/[rdesktop]/sourceforge.net/trunk/rdesktop/rdp.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /sourceforge.net/trunk/rdesktop/rdp.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 907 - (hide annotations)
Tue May 31 18:49:05 2005 UTC (18 years, 11 months ago) by jdmeijer
File MIME type: text/plain
File size: 31193 byte(s)
Fix immediate disconnect when connecting to Windows XP RTM

1 forsberg 351 /* -*- c-basic-offset: 8 -*-
2 matty 3 rdesktop: A Remote Desktop Protocol client.
3     Protocol services - RDP layer
4 stargo 828 Copyright (C) Matthew Chapman 1999-2005
5 jsorg71 433
6 matty 3 This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 jsorg71 433
11 matty 3 This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     GNU General Public License for more details.
15 jsorg71 433
16 matty 3 You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19     */
20    
21 stargo 562 #include <time.h>
22 stargo 855 #include <errno.h>
23     #include <unistd.h>
24 matty 10 #include "rdesktop.h"
25 matty 3
26 stargo 857 #ifdef HAVE_ICONV
27 stargo 855 #ifdef HAVE_ICONV_H
28     #include <iconv.h>
29     #endif
30 stargo 858
31     #ifndef ICONV_CONST
32     #define ICONV_CONST ""
33 stargo 857 #endif
34 stargo 858 #endif
35 stargo 855
36 jsorg71 381 extern uint16 g_mcs_userid;
37 stargo 855 extern char g_username[64];
38     extern char g_codepage[16];
39 jsorg71 437 extern BOOL g_bitmap_compression;
40     extern BOOL g_orders;
41     extern BOOL g_encryption;
42 jsorg71 438 extern BOOL g_desktop_save;
43 jsorg71 848 extern BOOL g_polygon_ellipse_orders;
44 jsorg71 438 extern BOOL g_use_rdp5;
45     extern uint16 g_server_rdp_version;
46 stargo 637 extern uint32 g_rdp5_performanceflags;
47 jsorg71 438 extern int g_server_bpp;
48 n-ki 677 extern int g_width;
49     extern int g_height;
50 jsorg71 678 extern BOOL g_bitmap_cache;
51 jsorg71 725 extern BOOL g_bitmap_cache_persist_enable;
52 matty 3
53 jsorg71 438 uint8 *g_next_packet;
54     uint32 g_rdp_shareid;
55 matty 3
56 n-ki 687 extern RDPCOMP g_mppc_dict;
57 n-ki 683
58 forsberg 340 #if WITH_DEBUG
59 jsorg71 438 static uint32 g_packetno;
60 forsberg 351 #endif
61 forsberg 340
62 stargo 864 #ifdef HAVE_ICONV
63     static BOOL g_iconv_works = True;
64     #endif
65    
66 matty 10 /* Receive an RDP packet */
67 matty 25 static STREAM
68 astrand 64 rdp_recv(uint8 * type)
69 matty 3 {
70 matty 10 static STREAM rdp_s;
71     uint16 length, pdu_type;
72 jsorg71 733 uint8 rdpver;
73 matty 3
74 jsorg71 438 if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end))
75 matty 10 {
76 jsorg71 733 rdp_s = sec_recv(&rdpver);
77 matty 10 if (rdp_s == NULL)
78     return NULL;
79 jsorg71 779 if (rdpver == 0xff)
80 jsorg71 733 {
81 jsorg71 779 g_next_packet = rdp_s->end;
82     *type = 0;
83     return rdp_s;
84     }
85     else if (rdpver != 3)
86     {
87 jsorg71 733 /* rdp5_process should move g_next_packet ok */
88     rdp5_process(rdp_s);
89     *type = 0;
90     return rdp_s;
91     }
92 matty 3
93 jsorg71 438 g_next_packet = rdp_s->p;
94 matty 10 }
95     else
96 matty 7 {
97 jsorg71 438 rdp_s->p = g_next_packet;
98 matty 7 }
99    
100 matty 10 in_uint16_le(rdp_s, length);
101 jsorg71 283 /* 32k packets are really 8, keepalive fix */
102     if (length == 0x8000)
103     {
104 jsorg71 438 g_next_packet += 8;
105 jsorg71 283 *type = 0;
106     return rdp_s;
107     }
108 matty 10 in_uint16_le(rdp_s, pdu_type);
109 matty 24 in_uint8s(rdp_s, 2); /* userid */
110 matty 10 *type = pdu_type & 0xf;
111 matty 7
112 matty 30 #if WITH_DEBUG
113 jsorg71 438 DEBUG(("RDP packet #%d, (type %x)\n", ++g_packetno, *type));
114 matthewc 513 hexdump(g_next_packet, length);
115 matty 28 #endif /* */
116 matty 7
117 jsorg71 438 g_next_packet += length;
118 matty 10 return rdp_s;
119 matty 3 }
120    
121 matty 10 /* Initialise an RDP data packet */
122 matty 25 static STREAM
123     rdp_init_data(int maxlen)
124 matty 3 {
125 matty 10 STREAM s;
126 matty 3
127 jsorg71 437 s = sec_init(g_encryption ? SEC_ENCRYPT : 0, maxlen + 18);
128 matty 10 s_push_layer(s, rdp_hdr, 18);
129    
130     return s;
131 matty 3 }
132    
133 matty 10 /* Send an RDP data packet */
134 matty 25 static void
135     rdp_send_data(STREAM s, uint8 data_pdu_type)
136 matty 9 {
137 matty 10 uint16 length;
138 matty 9
139 matty 10 s_pop_layer(s, rdp_hdr);
140     length = s->end - s->p;
141 matty 9
142 matty 10 out_uint16_le(s, length);
143     out_uint16_le(s, (RDP_PDU_DATA | 0x10));
144 jsorg71 381 out_uint16_le(s, (g_mcs_userid + 1001));
145 matty 9
146 jsorg71 438 out_uint32_le(s, g_rdp_shareid);
147 matty 24 out_uint8(s, 0); /* pad */
148     out_uint8(s, 1); /* streamid */
149 n-ki 176 out_uint16_le(s, (length - 14));
150 matty 10 out_uint8(s, data_pdu_type);
151 matty 24 out_uint8(s, 0); /* compress_type */
152     out_uint16(s, 0); /* compress_len */
153 matty 3
154 jsorg71 437 sec_send(s, g_encryption ? SEC_ENCRYPT : 0);
155 matty 3 }
156    
157 matty 10 /* Output a string in Unicode */
158 matty 25 void
159     rdp_out_unistr(STREAM s, char *string, int len)
160 matty 3 {
161 stargo 857 #ifdef HAVE_ICONV
162 stargo 855 size_t ibl = strlen(string), obl = len + 2;
163 stargo 861 static iconv_t iconv_h = (iconv_t) - 1;
164 astrand 879 char *pin = string, *pout = (char *) s->p;
165 stargo 855
166     memset(pout, 0, len + 4);
167    
168 stargo 864 if (g_iconv_works)
169 stargo 855 {
170 stargo 864 if (iconv_h == (iconv_t) - 1)
171 stargo 855 {
172 stargo 864 size_t i = 1, o = 4;
173     if ((iconv_h = iconv_open(WINDOWS_CODEPAGE, g_codepage)) == (iconv_t) - 1)
174     {
175     warning("rdp_out_unistr: iconv_open[%s -> %s] fail %d\n",
176     g_codepage, WINDOWS_CODEPAGE, (int) iconv_h);
177    
178     g_iconv_works = False;
179 stargo 866 rdp_out_unistr(s, string, len);
180     return;
181 stargo 864 }
182     if (iconv(iconv_h, (ICONV_CONST char **) &pin, &i, &pout, &o) ==
183     (size_t) - 1)
184     {
185     iconv_close(iconv_h);
186     iconv_h = (iconv_t) - 1;
187     warning("rdp_out_unistr: iconv(1) fail, errno %d\n", errno);
188    
189     g_iconv_works = False;
190 stargo 866 rdp_out_unistr(s, string, len);
191     return;
192 stargo 864 }
193     pin = string;
194     pout = (char *) s->p;
195 stargo 855 }
196 stargo 864
197     if (iconv(iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
198 stargo 855 {
199     iconv_close(iconv_h);
200 stargo 861 iconv_h = (iconv_t) - 1;
201 stargo 864 warning("rdp_out_unistr: iconv(2) fail, errno %d\n", errno);
202    
203     g_iconv_works = False;
204 stargo 866 rdp_out_unistr(s, string, len);
205     return;
206 stargo 855 }
207 stargo 864
208     s->p += len + 2;
209    
210 stargo 855 }
211 stargo 864 else
212     #endif
213 stargo 855 {
214 stargo 864 int i = 0, j = 0;
215 stargo 855
216 stargo 864 len += 2;
217 stargo 855
218 stargo 864 while (i < len)
219     {
220     s->p[i++] = string[j++];
221     s->p[i++] = 0;
222     }
223 matty 9
224 stargo 864 s->p += len;
225 matty 9 }
226 matty 3 }
227    
228 n-ki 569 /* Input a string in Unicode
229     *
230     * Returns str_len of string
231     */
232     int
233     rdp_in_unistr(STREAM s, char *string, int uni_len)
234     {
235 stargo 857 #ifdef HAVE_ICONV
236 stargo 855 size_t ibl = uni_len, obl = uni_len;
237 astrand 879 char *pin = (char *) s->p, *pout = string;
238 stargo 861 static iconv_t iconv_h = (iconv_t) - 1;
239 stargo 855
240 stargo 864 if (g_iconv_works)
241 stargo 855 {
242 stargo 864 if (iconv_h == (iconv_t) - 1)
243 stargo 855 {
244 stargo 864 if ((iconv_h = iconv_open(g_codepage, WINDOWS_CODEPAGE)) == (iconv_t) - 1)
245     {
246     warning("rdp_in_unistr: iconv_open[%s -> %s] fail %d\n",
247     WINDOWS_CODEPAGE, g_codepage, (int) iconv_h);
248    
249     g_iconv_works = False;
250     return rdp_in_unistr(s, string, uni_len);
251     }
252 stargo 855 }
253 stargo 864
254     if (iconv(iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
255     {
256     iconv_close(iconv_h);
257     iconv_h = (iconv_t) - 1;
258     warning("rdp_in_unistr: iconv fail, errno %d\n", errno);
259    
260     g_iconv_works = False;
261     return rdp_in_unistr(s, string, uni_len);
262     }
263     return pout - string;
264 stargo 855 }
265 stargo 864 else
266     #endif
267 stargo 855 {
268 stargo 864 int i = 0;
269 n-ki 569
270 stargo 864 while (i < uni_len / 2)
271     {
272     in_uint8a(s, &string[i++], 1);
273     in_uint8s(s, 1);
274     }
275    
276     return i - 1;
277 n-ki 569 }
278     }
279    
280    
281 matty 10 /* Parse a logon info packet */
282 matty 25 static void
283     rdp_send_logon_info(uint32 flags, char *domain, char *user,
284     char *password, char *program, char *directory)
285 matty 3 {
286 n-ki 624 char *ipaddr = tcp_get_address();
287 matty 24 int len_domain = 2 * strlen(domain);
288     int len_user = 2 * strlen(user);
289     int len_password = 2 * strlen(password);
290     int len_program = 2 * strlen(program);
291 matty 10 int len_directory = 2 * strlen(directory);
292 n-ki 624 int len_ip = 2 * strlen(ipaddr);
293 forsberg 371 int len_dll = 2 * strlen("C:\\WINNT\\System32\\mstscax.dll");
294     int packetlen = 0;
295 jsorg71 437 uint32 sec_flags = g_encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO;
296 matty 10 STREAM s;
297 stargo 562 time_t t = time(NULL);
298     time_t tzone;
299 matty 3
300 jsorg71 438 if (!g_use_rdp5 || 1 == g_server_rdp_version)
301 forsberg 351 {
302     DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));
303 matty 3
304 forsberg 351 s = sec_init(sec_flags, 18 + len_domain + len_user + len_password
305     + len_program + len_directory + 10);
306 matty 3
307 forsberg 351 out_uint32(s, 0);
308     out_uint32_le(s, flags);
309     out_uint16_le(s, len_domain);
310     out_uint16_le(s, len_user);
311     out_uint16_le(s, len_password);
312     out_uint16_le(s, len_program);
313     out_uint16_le(s, len_directory);
314     rdp_out_unistr(s, domain, len_domain);
315     rdp_out_unistr(s, user, len_user);
316     rdp_out_unistr(s, password, len_password);
317     rdp_out_unistr(s, program, len_program);
318     rdp_out_unistr(s, directory, len_directory);
319     }
320     else
321     {
322 n-ki 683
323 forsberg 371 flags |= RDP_LOGON_BLOB;
324 forsberg 351 DEBUG_RDP5(("Sending RDP5-style Logon packet\n"));
325 astrand 540 packetlen = 4 + /* Unknown uint32 */
326     4 + /* flags */
327     2 + /* len_domain */
328     2 + /* len_user */
329     (flags & RDP_LOGON_AUTO ? 2 : 0) + /* len_password */
330     (flags & RDP_LOGON_BLOB ? 2 : 0) + /* Length of BLOB */
331     2 + /* len_program */
332     2 + /* len_directory */
333     (0 < len_domain ? len_domain : 2) + /* domain */
334     len_user + (flags & RDP_LOGON_AUTO ? len_password : 0) + 0 + /* We have no 512 byte BLOB. Perhaps we must? */
335     (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO) ? 2 : 0) + /* After the BLOB is a unknown int16. If there is a BLOB, that is. */
336     (0 < len_program ? len_program : 2) + (0 < len_directory ? len_directory : 2) + 2 + /* Unknown (2) */
337     2 + /* Client ip length */
338     len_ip + /* Client ip */
339     2 + /* DLL string length */
340     len_dll + /* DLL string */
341     2 + /* Unknown */
342     2 + /* Unknown */
343     64 + /* Time zone #0 */
344     2 + /* Unknown */
345     64 + /* Time zone #1 */
346     32; /* Unknown */
347 forsberg 410
348     s = sec_init(sec_flags, packetlen);
349 forsberg 371 DEBUG_RDP5(("Called sec_init with packetlen %d\n", packetlen));
350 forsberg 351
351 astrand 540 out_uint32(s, 0); /* Unknown */
352 forsberg 351 out_uint32_le(s, flags);
353     out_uint16_le(s, len_domain);
354     out_uint16_le(s, len_user);
355     if (flags & RDP_LOGON_AUTO)
356     {
357     out_uint16_le(s, len_password);
358 forsberg 371
359 forsberg 351 }
360 forsberg 410 if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
361     {
362 forsberg 371 out_uint16_le(s, 0);
363     }
364 forsberg 351 out_uint16_le(s, len_program);
365     out_uint16_le(s, len_directory);
366 forsberg 371 if (0 < len_domain)
367     rdp_out_unistr(s, domain, len_domain);
368 forsberg 410 else
369 forsberg 371 out_uint16_le(s, 0);
370     rdp_out_unistr(s, user, len_user);
371 forsberg 351 if (flags & RDP_LOGON_AUTO)
372     {
373     rdp_out_unistr(s, password, len_password);
374     }
375 forsberg 410 if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
376     {
377 forsberg 371 out_uint16_le(s, 0);
378     }
379 forsberg 410 if (0 < len_program)
380     {
381 forsberg 351 rdp_out_unistr(s, program, len_program);
382 forsberg 410
383     }
384     else
385     {
386 forsberg 371 out_uint16_le(s, 0);
387     }
388 forsberg 410 if (0 < len_directory)
389     {
390 forsberg 351 rdp_out_unistr(s, directory, len_directory);
391 forsberg 410 }
392     else
393     {
394 forsberg 371 out_uint16_le(s, 0);
395 jsorg71 376 }
396 forsberg 371 out_uint16_le(s, 2);
397 astrand 540 out_uint16_le(s, len_ip + 2); /* Length of client ip */
398 n-ki 624 rdp_out_unistr(s, ipaddr, len_ip);
399 forsberg 410 out_uint16_le(s, len_dll + 2);
400 forsberg 371 rdp_out_unistr(s, "C:\\WINNT\\System32\\mstscax.dll", len_dll);
401 stargo 562
402 stargo 604 tzone = (mktime(gmtime(&t)) - mktime(localtime(&t))) / 60;
403     out_uint32_le(s, tzone);
404 stargo 559
405 forsberg 410 rdp_out_unistr(s, "GTB, normaltid", 2 * strlen("GTB, normaltid"));
406     out_uint8s(s, 62 - 2 * strlen("GTB, normaltid"));
407 forsberg 351
408     out_uint32_le(s, 0x0a0000);
409     out_uint32_le(s, 0x050000);
410 forsberg 371 out_uint32_le(s, 3);
411     out_uint32_le(s, 0);
412     out_uint32_le(s, 0);
413 forsberg 351
414 forsberg 410 rdp_out_unistr(s, "GTB, sommartid", 2 * strlen("GTB, sommartid"));
415     out_uint8s(s, 62 - 2 * strlen("GTB, sommartid"));
416    
417 forsberg 371 out_uint32_le(s, 0x30000);
418 forsberg 351 out_uint32_le(s, 0x050000);
419     out_uint32_le(s, 2);
420 matthewc 365 out_uint32(s, 0);
421 forsberg 351 out_uint32_le(s, 0xffffffc4);
422     out_uint32_le(s, 0xfffffffe);
423 stargo 637 out_uint32_le(s, g_rdp5_performanceflags);
424 matthewc 365 out_uint32(s, 0);
425 forsberg 351
426 forsberg 371
427 forsberg 351 }
428 matty 10 s_mark_end(s);
429     sec_send(s, sec_flags);
430 matty 3 }
431    
432 matty 10 /* Send a control PDU */
433 matty 25 static void
434     rdp_send_control(uint16 action)
435 matty 3 {
436 matty 10 STREAM s;
437 matty 9
438 matty 10 s = rdp_init_data(8);
439 matty 9
440 matty 10 out_uint16_le(s, action);
441 matty 24 out_uint16(s, 0); /* userid */
442     out_uint32(s, 0); /* control id */
443 matty 9
444 matty 10 s_mark_end(s);
445     rdp_send_data(s, RDP_DATA_PDU_CONTROL);
446 matty 3 }
447    
448 matty 10 /* Send a synchronisation PDU */
449 matty 25 static void
450 matthewc 192 rdp_send_synchronise(void)
451 matty 3 {
452 matty 10 STREAM s;
453 matty 9
454 matty 10 s = rdp_init_data(4);
455 matty 9
456 matty 24 out_uint16_le(s, 1); /* type */
457 matty 10 out_uint16_le(s, 1002);
458 matty 9
459 matty 10 s_mark_end(s);
460     rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
461 matty 3 }
462    
463 matty 10 /* Send a single input event */
464 matty 25 void
465 astrand 82 rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2)
466 matty 3 {
467 matty 10 STREAM s;
468 matty 9
469 matty 10 s = rdp_init_data(16);
470 matty 9
471 matty 24 out_uint16_le(s, 1); /* number of events */
472     out_uint16(s, 0); /* pad */
473 matty 9
474 matty 10 out_uint32_le(s, time);
475     out_uint16_le(s, message_type);
476     out_uint16_le(s, device_flags);
477     out_uint16_le(s, param1);
478     out_uint16_le(s, param2);
479 matty 9
480 matty 10 s_mark_end(s);
481     rdp_send_data(s, RDP_DATA_PDU_INPUT);
482 matty 3 }
483    
484 jdmeijer 905 /* Send a client window information PDU */
485     void
486     rdp_send_client_window_status(int status)
487     {
488     STREAM s;
489 jdmeijer 907 static int current_status = 1;
490 jdmeijer 905
491 jdmeijer 907 if (current_status == status)
492     return;
493    
494 jdmeijer 905 s = rdp_init_data(12);
495    
496     out_uint32_le(s, status);
497    
498     switch (status)
499     {
500     case 0: /* shut the server up */
501     break;
502    
503     case 1: /* receive data again */
504     out_uint32_le(s, 0); /* unknown */
505     out_uint16_le(s, g_width);
506     out_uint16_le(s, g_height);
507     break;
508     }
509    
510     s_mark_end(s);
511     rdp_send_data(s, RDP_DATA_PDU_CLIENT_WINDOW_STATUS);
512 jdmeijer 907 current_status = status;
513 jdmeijer 905 }
514    
515     /* Send persistent bitmap cache enumeration PDU's */
516 jsorg71 725 static void
517     rdp_enum_bmpcache2(void)
518     {
519     STREAM s;
520 jdmeijer 830 HASH_KEY keylist[BMPCACHE2_NUM_PSTCELLS];
521     uint32 num_keys, offset, count, flags;
522 jsorg71 725
523     offset = 0;
524 jdmeijer 830 num_keys = pstcache_enumerate(2, keylist);
525 jsorg71 725
526 jdmeijer 830 while (offset < num_keys)
527 jsorg71 725 {
528 jdmeijer 830 count = MIN(num_keys - offset, 169);
529 jsorg71 725
530 jdmeijer 830 s = rdp_init_data(24 + count * sizeof(HASH_KEY));
531 jsorg71 725
532     flags = 0;
533     if (offset == 0)
534     flags |= PDU_FLAG_FIRST;
535 jdmeijer 830 if (num_keys - offset <= 169)
536 jsorg71 725 flags |= PDU_FLAG_LAST;
537    
538     /* header */
539     out_uint32_le(s, 0);
540     out_uint16_le(s, count);
541     out_uint16_le(s, 0);
542     out_uint16_le(s, 0);
543     out_uint16_le(s, 0);
544     out_uint16_le(s, 0);
545 jdmeijer 830 out_uint16_le(s, num_keys);
546 jsorg71 725 out_uint32_le(s, 0);
547     out_uint32_le(s, flags);
548    
549     /* list */
550 jdmeijer 830 out_uint8a(s, keylist[offset], count * sizeof(HASH_KEY));
551 jsorg71 725
552     s_mark_end(s);
553     rdp_send_data(s, 0x2b);
554    
555     offset += 169;
556     }
557     }
558    
559 matty 10 /* Send an (empty) font information PDU */
560 matty 25 static void
561     rdp_send_fonts(uint16 seq)
562 matty 3 {
563 matty 10 STREAM s;
564 matty 3
565 matty 10 s = rdp_init_data(8);
566 matty 9
567 matty 10 out_uint16(s, 0); /* number of fonts */
568 n-ki 677 out_uint16_le(s, 0); /* pad? */
569 matty 10 out_uint16_le(s, seq); /* unknown */
570     out_uint16_le(s, 0x32); /* entry size */
571 matty 9
572 matty 10 s_mark_end(s);
573     rdp_send_data(s, RDP_DATA_PDU_FONT2);
574 matty 3 }
575    
576 matty 10 /* Output general capability set */
577 matty 25 static void
578     rdp_out_general_caps(STREAM s)
579 matty 3 {
580 matty 10 out_uint16_le(s, RDP_CAPSET_GENERAL);
581     out_uint16_le(s, RDP_CAPLEN_GENERAL);
582 matty 3
583 matty 10 out_uint16_le(s, 1); /* OS major type */
584     out_uint16_le(s, 3); /* OS minor type */
585 matty 24 out_uint16_le(s, 0x200); /* Protocol version */
586 matty 10 out_uint16(s, 0); /* Pad */
587     out_uint16(s, 0); /* Compression types */
588 jsorg71 438 out_uint16_le(s, g_use_rdp5 ? 0x40d : 0);
589 forsberg 351 /* Pad, according to T.128. 0x40d seems to
590     trigger
591     the server to start sending RDP5 packets.
592     However, the value is 0x1d04 with W2KTSK and
593     NT4MS. Hmm.. Anyway, thankyou, Microsoft,
594     for sending such information in a padding
595     field.. */
596 matty 10 out_uint16(s, 0); /* Update capability */
597     out_uint16(s, 0); /* Remote unshare capability */
598     out_uint16(s, 0); /* Compression level */
599     out_uint16(s, 0); /* Pad */
600 matty 3 }
601    
602 matty 10 /* Output bitmap capability set */
603 matty 25 static void
604     rdp_out_bitmap_caps(STREAM s)
605 matty 9 {
606 matty 10 out_uint16_le(s, RDP_CAPSET_BITMAP);
607     out_uint16_le(s, RDP_CAPLEN_BITMAP);
608 matty 9
609 jsorg71 654 out_uint16_le(s, g_server_bpp); /* Preferred BPP */
610 n-ki 176 out_uint16_le(s, 1); /* Receive 1 BPP */
611     out_uint16_le(s, 1); /* Receive 4 BPP */
612 matty 10 out_uint16_le(s, 1); /* Receive 8 BPP */
613     out_uint16_le(s, 800); /* Desktop width */
614     out_uint16_le(s, 600); /* Desktop height */
615     out_uint16(s, 0); /* Pad */
616 n-ki 677 out_uint16(s, 1); /* Allow resize */
617 jsorg71 437 out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */
618 matty 10 out_uint16(s, 0); /* Unknown */
619     out_uint16_le(s, 1); /* Unknown */
620     out_uint16(s, 0); /* Pad */
621 matty 9 }
622    
623 matty 10 /* Output order capability set */
624 matty 25 static void
625     rdp_out_order_caps(STREAM s)
626 matty 3 {
627 matty 10 uint8 order_caps[32];
628 matty 3
629 matty 28 memset(order_caps, 0, 32);
630     order_caps[0] = 1; /* dest blt */
631     order_caps[1] = 1; /* pat blt */
632     order_caps[2] = 1; /* screen blt */
633 n-ki 683 order_caps[3] = (g_bitmap_cache ? 1 : 0); /* memblt */
634 jdmeijer 831 order_caps[4] = 0; /* triblt */
635 matty 28 order_caps[8] = 1; /* line */
636     order_caps[9] = 1; /* line */
637     order_caps[10] = 1; /* rect */
638 jsorg71 848 order_caps[11] = (g_desktop_save ? 1 : 0); /* desksave */
639 matty 28 order_caps[13] = 1; /* memblt */
640     order_caps[14] = 1; /* triblt */
641 jsorg71 848 order_caps[20] = (g_polygon_ellipse_orders ? 1 : 0); /* polygon */
642     order_caps[21] = (g_polygon_ellipse_orders ? 1 : 0); /* polygon2 */
643 matty 28 order_caps[22] = 1; /* polyline */
644 jsorg71 848 order_caps[25] = (g_polygon_ellipse_orders ? 1 : 0); /* ellipse */
645     order_caps[26] = (g_polygon_ellipse_orders ? 1 : 0); /* ellipse2 */
646 matty 28 order_caps[27] = 1; /* text2 */
647 matty 10 out_uint16_le(s, RDP_CAPSET_ORDER);
648     out_uint16_le(s, RDP_CAPLEN_ORDER);
649 matty 9
650 matty 10 out_uint8s(s, 20); /* Terminal desc, pad */
651     out_uint16_le(s, 1); /* Cache X granularity */
652     out_uint16_le(s, 20); /* Cache Y granularity */
653     out_uint16(s, 0); /* Pad */
654     out_uint16_le(s, 1); /* Max order level */
655     out_uint16_le(s, 0x147); /* Number of fonts */
656 matty 24 out_uint16_le(s, 0x2a); /* Capability flags */
657 matty 10 out_uint8p(s, order_caps, 32); /* Orders supported */
658     out_uint16_le(s, 0x6a1); /* Text capability flags */
659     out_uint8s(s, 6); /* Pad */
660 jsorg71 438 out_uint32_le(s, g_desktop_save == False ? 0 : 0x38400); /* Desktop cache size */
661 matty 10 out_uint32(s, 0); /* Unknown */
662 n-ki 176 out_uint32_le(s, 0x4e4); /* Unknown */
663 matty 9 }
664    
665 matty 10 /* Output bitmap cache capability set */
666 matty 25 static void
667     rdp_out_bmpcache_caps(STREAM s)
668 matty 9 {
669 jsorg71 433 int Bpp;
670 matty 10 out_uint16_le(s, RDP_CAPSET_BMPCACHE);
671     out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
672 matty 3
673 jsorg71 438 Bpp = (g_server_bpp + 7) / 8;
674 matty 24 out_uint8s(s, 24); /* unused */
675     out_uint16_le(s, 0x258); /* entries */
676 jsorg71 433 out_uint16_le(s, 0x100 * Bpp); /* max cell size */
677 matty 24 out_uint16_le(s, 0x12c); /* entries */
678 jsorg71 433 out_uint16_le(s, 0x400 * Bpp); /* max cell size */
679 matty 24 out_uint16_le(s, 0x106); /* entries */
680 jsorg71 433 out_uint16_le(s, 0x1000 * Bpp); /* max cell size */
681 matty 9 }
682    
683 jsorg71 725 /* Output bitmap cache v2 capability set */
684     static void
685     rdp_out_bmpcache2_caps(STREAM s)
686     {
687     out_uint16_le(s, RDP_CAPSET_BMPCACHE2);
688     out_uint16_le(s, RDP_CAPLEN_BMPCACHE2);
689    
690 jsorg71 730 out_uint16_le(s, g_bitmap_cache_persist_enable ? 2 : 0); /* version */
691 jsorg71 725
692 jdmeijer 889 out_uint16_be(s, 3); /* number of caches in this set */
693 jsorg71 725
694 jdmeijer 889 /* max cell size for cache 0 is 16x16, 1 = 32x32, 2 = 64x64, etc */
695 jsorg71 725 out_uint32_le(s, BMPCACHE2_C0_CELLS);
696     out_uint32_le(s, BMPCACHE2_C1_CELLS);
697     if (pstcache_init(2))
698     {
699     out_uint32_le(s, BMPCACHE2_NUM_PSTCELLS | BMPCACHE2_FLAG_PERSIST);
700     }
701     else
702     {
703     out_uint32_le(s, BMPCACHE2_C2_CELLS);
704     }
705 astrand 738 out_uint8s(s, 20); /* other bitmap caches not used */
706 jsorg71 725 }
707    
708 matty 10 /* Output control capability set */
709 matty 25 static void
710     rdp_out_control_caps(STREAM s)
711 matty 9 {
712 matty 10 out_uint16_le(s, RDP_CAPSET_CONTROL);
713     out_uint16_le(s, RDP_CAPLEN_CONTROL);
714 matty 9
715 matty 10 out_uint16(s, 0); /* Control capabilities */
716     out_uint16(s, 0); /* Remote detach */
717     out_uint16_le(s, 2); /* Control interest */
718     out_uint16_le(s, 2); /* Detach interest */
719 matty 9 }
720    
721 matty 10 /* Output activation capability set */
722 matty 25 static void
723     rdp_out_activate_caps(STREAM s)
724 matty 9 {
725 matty 10 out_uint16_le(s, RDP_CAPSET_ACTIVATE);
726     out_uint16_le(s, RDP_CAPLEN_ACTIVATE);
727 matty 9
728 matty 10 out_uint16(s, 0); /* Help key */
729     out_uint16(s, 0); /* Help index key */
730     out_uint16(s, 0); /* Extended help key */
731     out_uint16(s, 0); /* Window activate */
732 matty 9 }
733    
734 matty 10 /* Output pointer capability set */
735 matty 25 static void
736     rdp_out_pointer_caps(STREAM s)
737 matty 9 {
738 matty 10 out_uint16_le(s, RDP_CAPSET_POINTER);
739     out_uint16_le(s, RDP_CAPLEN_POINTER);
740 matty 9
741 matty 10 out_uint16(s, 0); /* Colour pointer */
742     out_uint16_le(s, 20); /* Cache size */
743 matty 9 }
744    
745 matty 10 /* Output share capability set */
746 matty 25 static void
747     rdp_out_share_caps(STREAM s)
748 matty 3 {
749 matty 10 out_uint16_le(s, RDP_CAPSET_SHARE);
750     out_uint16_le(s, RDP_CAPLEN_SHARE);
751 matty 3
752 matty 10 out_uint16(s, 0); /* userid */
753     out_uint16(s, 0); /* pad */
754 matty 9 }
755 matty 3
756 matty 10 /* Output colour cache capability set */
757 matty 25 static void
758     rdp_out_colcache_caps(STREAM s)
759 matty 9 {
760 matty 10 out_uint16_le(s, RDP_CAPSET_COLCACHE);
761     out_uint16_le(s, RDP_CAPLEN_COLCACHE);
762 matty 3
763 matty 10 out_uint16_le(s, 6); /* cache size */
764     out_uint16(s, 0); /* pad */
765 matty 3 }
766    
767 jsorg71 725 static uint8 caps_0x0d[] = {
768     0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00,
769     0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
770     0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
771     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
772     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
773     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
774     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
775     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
776     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
777     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
778     0x00, 0x00, 0x00, 0x00
779 matty 10 };
780 matty 3
781 jsorg71 725 static uint8 caps_0x0c[] = { 0x01, 0x00, 0x00, 0x00 };
782    
783     static uint8 caps_0x0e[] = { 0x01, 0x00, 0x00, 0x00 };
784    
785     static uint8 caps_0x10[] = {
786     0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00,
787     0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00,
788     0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00,
789     0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00,
790     0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08,
791     0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00
792     };
793    
794     /* Output unknown capability sets */
795 matty 25 static void
796 astrand 738 rdp_out_unknown_caps(STREAM s, uint16 id, uint16 length, uint8 * caps)
797 matty 3 {
798 jsorg71 725 out_uint16_le(s, id);
799     out_uint16_le(s, length);
800 matty 24
801 jsorg71 725 out_uint8p(s, caps, length - 4);
802 matty 3 }
803    
804 forsberg 351 #define RDP5_FLAG 0x0030
805 matty 10 /* Send a confirm active PDU */
806 matty 25 static void
807 matthewc 192 rdp_send_confirm_active(void)
808 matty 7 {
809 matty 10 STREAM s;
810 jsorg71 437 uint32 sec_flags = g_encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG;
811 matty 24 uint16 caplen =
812     RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
813     RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
814     RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
815 jsorg71 725 RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE +
816 astrand 738 0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */ +
817 jsorg71 725 4 /* w2k fix, why? */ ;
818 matty 7
819 forsberg 351 s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
820 matty 9
821 forsberg 351 out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE));
822     out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10)); /* Version 1 */
823 jsorg71 381 out_uint16_le(s, (g_mcs_userid + 1001));
824 forsberg 351
825 jsorg71 438 out_uint32_le(s, g_rdp_shareid);
826 matty 24 out_uint16_le(s, 0x3ea); /* userid */
827 matty 10 out_uint16_le(s, sizeof(RDP_SOURCE));
828     out_uint16_le(s, caplen);
829 matty 9
830 matty 10 out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));
831 matty 24 out_uint16_le(s, 0xd); /* num_caps */
832     out_uint8s(s, 2); /* pad */
833 matty 9
834 matty 10 rdp_out_general_caps(s);
835     rdp_out_bitmap_caps(s);
836     rdp_out_order_caps(s);
837 jsorg71 725 g_use_rdp5 ? rdp_out_bmpcache2_caps(s) : rdp_out_bmpcache_caps(s);
838 matty 10 rdp_out_colcache_caps(s);
839     rdp_out_activate_caps(s);
840     rdp_out_control_caps(s);
841     rdp_out_pointer_caps(s);
842     rdp_out_share_caps(s);
843 matty 9
844 astrand 738 rdp_out_unknown_caps(s, 0x0d, 0x58, caps_0x0d); /* international? */
845 jsorg71 725 rdp_out_unknown_caps(s, 0x0c, 0x08, caps_0x0c);
846     rdp_out_unknown_caps(s, 0x0e, 0x08, caps_0x0e);
847 astrand 738 rdp_out_unknown_caps(s, 0x10, 0x34, caps_0x10); /* glyph cache? */
848    
849 matty 10 s_mark_end(s);
850 forsberg 351 sec_send(s, sec_flags);
851 matty 9 }
852    
853 n-ki 677 /* Process a general capability set */
854     static void
855     rdp_process_general_caps(STREAM s)
856     {
857     uint16 pad2octetsB; /* rdp5 flags? */
858    
859     in_uint8s(s, 10);
860     in_uint16_le(s, pad2octetsB);
861    
862     if (!pad2octetsB)
863     g_use_rdp5 = False;
864     }
865    
866     /* Process a bitmap capability set */
867     static void
868     rdp_process_bitmap_caps(STREAM s)
869     {
870     uint16 width, height, bpp;
871    
872     in_uint16_le(s, bpp);
873     in_uint8s(s, 6);
874    
875     in_uint16_le(s, width);
876     in_uint16_le(s, height);
877    
878     DEBUG(("setting desktop size and bpp to: %dx%dx%d\n", width, height, bpp));
879    
880     /*
881     * The server may limit bpp and change the size of the desktop (for
882     * example when shadowing another session).
883     */
884 jsorg71 708 if (g_server_bpp != bpp)
885     {
886     warning("colour depth changed from %d to %d\n", g_server_bpp, bpp);
887     g_server_bpp = bpp;
888     }
889     if (g_width != width || g_height != height)
890     {
891     warning("screen size changed from %dx%d to %dx%d\n", g_width, g_height,
892 astrand 738 width, height);
893 jsorg71 708 g_width = width;
894     g_height = height;
895     ui_resize_window();
896     }
897 n-ki 677 }
898    
899 jsorg71 725 /* Process server capabilities */
900     void
901     rdp_process_server_caps(STREAM s, uint16 length)
902 matty 9 {
903 n-ki 677 int n;
904 jsorg71 725 uint8 *next, *start;
905     uint16 ncapsets, capset_type, capset_length;
906 matty 9
907 jsorg71 725 start = s->p;
908 matty 9
909 jsorg71 725 in_uint16_le(s, ncapsets);
910 n-ki 677 in_uint8s(s, 2); /* pad */
911    
912 jsorg71 725 for (n = 0; n < ncapsets; n++)
913     {
914     if (s->p > start + length)
915     return;
916 n-ki 677
917     in_uint16_le(s, capset_type);
918     in_uint16_le(s, capset_length);
919    
920     next = s->p + capset_length - 4;
921    
922     switch (capset_type)
923 jsorg71 654 {
924 n-ki 677 case RDP_CAPSET_GENERAL:
925     rdp_process_general_caps(s);
926     break;
927    
928     case RDP_CAPSET_BITMAP:
929     rdp_process_bitmap_caps(s);
930     break;
931 jsorg71 654 }
932 n-ki 677
933     s->p = next;
934 jsorg71 654 }
935 jsorg71 725 }
936 jsorg71 654
937 jsorg71 725 /* Respond to a demand active PDU */
938     static void
939     process_demand_active(STREAM s)
940     {
941     uint8 type;
942     uint16 len_src_descriptor, len_combined_caps;
943    
944     in_uint32_le(s, g_rdp_shareid);
945     in_uint16_le(s, len_src_descriptor);
946     in_uint16_le(s, len_combined_caps);
947     in_uint8s(s, len_src_descriptor);
948    
949     DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
950     rdp_process_server_caps(s, len_combined_caps);
951    
952 matty 10 rdp_send_confirm_active();
953     rdp_send_synchronise();
954     rdp_send_control(RDP_CTL_COOPERATE);
955     rdp_send_control(RDP_CTL_REQUEST_CONTROL);
956 matty 28 rdp_recv(&type); /* RDP_PDU_SYNCHRONIZE */
957     rdp_recv(&type); /* RDP_CTL_COOPERATE */
958     rdp_recv(&type); /* RDP_CTL_GRANT_CONTROL */
959 astrand 543 rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(read_keyboard_state()), 0);
960 n-ki 677
961     if (g_use_rdp5)
962     {
963 jsorg71 725 rdp_enum_bmpcache2();
964 n-ki 677 rdp_send_fonts(3);
965     }
966     else
967     {
968     rdp_send_fonts(1);
969     rdp_send_fonts(2);
970     }
971    
972     rdp_recv(&type); /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */
973 matty 10 reset_order_state();
974 matty 9 }
975    
976 forsberg 351 /* Process a colour pointer PDU */
977     void
978     process_colour_pointer_pdu(STREAM s)
979     {
980     uint16 x, y, width, height, cache_idx, masklen, datalen;
981     uint8 *mask, *data;
982     HCURSOR cursor;
983    
984     in_uint16_le(s, cache_idx);
985     in_uint16_le(s, x);
986     in_uint16_le(s, y);
987     in_uint16_le(s, width);
988     in_uint16_le(s, height);
989     in_uint16_le(s, masklen);
990     in_uint16_le(s, datalen);
991     in_uint8p(s, data, datalen);
992     in_uint8p(s, mask, masklen);
993     cursor = ui_create_cursor(x, y, width, height, mask, data);
994     ui_set_cursor(cursor);
995     cache_put_cursor(cache_idx, cursor);
996     }
997    
998     /* Process a cached pointer PDU */
999     void
1000     process_cached_pointer_pdu(STREAM s)
1001     {
1002     uint16 cache_idx;
1003    
1004     in_uint16_le(s, cache_idx);
1005     ui_set_cursor(cache_get_cursor(cache_idx));
1006     }
1007    
1008 astrand 508 /* Process a system pointer PDU */
1009     void
1010     process_system_pointer_pdu(STREAM s)
1011     {
1012     uint16 system_pointer_type;
1013 forsberg 351
1014 astrand 508 in_uint16(s, system_pointer_type);
1015     switch (system_pointer_type)
1016     {
1017     case RDP_NULL_POINTER:
1018     ui_set_null_cursor();
1019     break;
1020    
1021     default:
1022     unimpl("System pointer message 0x%x\n", system_pointer_type);
1023     }
1024     }
1025    
1026 matty 10 /* Process a pointer PDU */
1027 matty 25 static void
1028     process_pointer_pdu(STREAM s)
1029 matty 9 {
1030 matty 10 uint16 message_type;
1031 forsberg 351 uint16 x, y;
1032 matty 9
1033 matty 10 in_uint16_le(s, message_type);
1034 matty 24 in_uint8s(s, 2); /* pad */
1035 matty 9
1036 matty 10 switch (message_type)
1037 matty 7 {
1038 matty 10 case RDP_POINTER_MOVE:
1039     in_uint16_le(s, x);
1040     in_uint16_le(s, y);
1041     if (s_check(s))
1042     ui_move_pointer(x, y);
1043     break;
1044 matty 9
1045 matty 28 case RDP_POINTER_COLOR:
1046 forsberg 351 process_colour_pointer_pdu(s);
1047 matty 28 break;
1048    
1049     case RDP_POINTER_CACHED:
1050 forsberg 351 process_cached_pointer_pdu(s);
1051 matty 28 break;
1052    
1053 astrand 508 case RDP_POINTER_SYSTEM:
1054     process_system_pointer_pdu(s);
1055     break;
1056    
1057 matty 10 default:
1058 astrand 508 unimpl("Pointer message 0x%x\n", message_type);
1059 matty 7 }
1060 matty 9 }
1061    
1062 matty 10 /* Process bitmap updates */
1063 forsberg 351 void
1064 matty 25 process_bitmap_updates(STREAM s)
1065 matty 9 {
1066 matty 10 uint16 num_updates;
1067     uint16 left, top, right, bottom, width, height;
1068 jsorg71 314 uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
1069 matty 28 uint8 *data, *bmpdata;
1070 matty 9 int i;
1071    
1072 matty 10 in_uint16_le(s, num_updates);
1073 matty 9
1074 matty 10 for (i = 0; i < num_updates; i++)
1075 matty 9 {
1076 matty 10 in_uint16_le(s, left);
1077     in_uint16_le(s, top);
1078     in_uint16_le(s, right);
1079     in_uint16_le(s, bottom);
1080     in_uint16_le(s, width);
1081     in_uint16_le(s, height);
1082     in_uint16_le(s, bpp);
1083 jsorg71 314 Bpp = (bpp + 7) / 8;
1084 matty 10 in_uint16_le(s, compress);
1085     in_uint16_le(s, bufsize);
1086 matty 9
1087 matty 10 cx = right - left + 1;
1088     cy = bottom - top + 1;
1089 matty 7
1090 forsberg 351 DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",
1091     left, top, right, bottom, width, height, Bpp, compress));
1092 matty 9
1093 matty 10 if (!compress)
1094     {
1095 matty 28 int y;
1096 forsberg 410 bmpdata = (uint8 *) xmalloc(width * height * Bpp);
1097 matty 28 for (y = 0; y < height; y++)
1098     {
1099 astrand 318 in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
1100     width * Bpp);
1101 matty 28 }
1102 astrand 82 ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
1103 matty 28 xfree(bmpdata);
1104     continue;
1105 matty 10 }
1106 matty 9
1107 forsberg 351
1108     if (compress & 0x400)
1109     {
1110     size = bufsize;
1111     }
1112     else
1113     {
1114     in_uint8s(s, 2); /* pad */
1115     in_uint16_le(s, size);
1116     in_uint8s(s, 4); /* line_size, final_size */
1117     }
1118 matty 10 in_uint8p(s, data, size);
1119 forsberg 410 bmpdata = (uint8 *) xmalloc(width * height * Bpp);
1120 jsorg71 314 if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
1121 matty 9 {
1122 astrand 82 ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
1123 matty 9 }
1124 forsberg 351 else
1125     {
1126     DEBUG_RDP5(("Failed to decompress data\n"));
1127     }
1128    
1129 matty 28 xfree(bmpdata);
1130 matty 10 }
1131 matty 9 }
1132    
1133 matty 10 /* Process a palette update */
1134 forsberg 351 void
1135 matty 25 process_palette(STREAM s)
1136 matty 9 {
1137 matthewc 254 COLOURENTRY *entry;
1138     COLOURMAP map;
1139 matty 10 HCOLOURMAP hmap;
1140 matthewc 254 int i;
1141 matty 9
1142 matty 24 in_uint8s(s, 2); /* pad */
1143     in_uint16_le(s, map.ncolours);
1144     in_uint8s(s, 2); /* pad */
1145 matty 3
1146 jsorg71 436 map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
1147 matthewc 254
1148 forsberg 351 DEBUG(("PALETTE(c=%d)\n", map.ncolours));
1149    
1150 matthewc 254 for (i = 0; i < map.ncolours; i++)
1151     {
1152     entry = &map.colours[i];
1153     in_uint8(s, entry->red);
1154     in_uint8(s, entry->green);
1155     in_uint8(s, entry->blue);
1156 astrand 260 }
1157 matthewc 254
1158 matty 10 hmap = ui_create_colourmap(&map);
1159     ui_set_colourmap(hmap);
1160 matthewc 254
1161     xfree(map.colours);
1162 matty 3 }
1163    
1164 matty 10 /* Process an update PDU */
1165 matty 25 static void
1166     process_update_pdu(STREAM s)
1167 matty 9 {
1168 forsberg 351 uint16 update_type, count;
1169 matty 9
1170 matty 10 in_uint16_le(s, update_type);
1171 matty 3
1172 jsorg71 713 ui_begin_update();
1173 matty 10 switch (update_type)
1174 matty 3 {
1175 matty 10 case RDP_UPDATE_ORDERS:
1176 forsberg 351 in_uint8s(s, 2); /* pad */
1177     in_uint16_le(s, count);
1178     in_uint8s(s, 2); /* pad */
1179     process_orders(s, count);
1180 matty 10 break;
1181 matty 3
1182 matty 10 case RDP_UPDATE_BITMAP:
1183     process_bitmap_updates(s);
1184     break;
1185 matty 3
1186 matty 10 case RDP_UPDATE_PALETTE:
1187     process_palette(s);
1188     break;
1189 matty 3
1190 matty 10 case RDP_UPDATE_SYNCHRONIZE:
1191     break;
1192 matty 9
1193 matty 10 default:
1194 matty 30 unimpl("update %d\n", update_type);
1195 matty 3 }
1196 jsorg71 713 ui_end_update();
1197 matty 3 }
1198    
1199 astrand 676 /* Process a disconnect PDU */
1200     void
1201     process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason)
1202     {
1203     in_uint32_le(s, *ext_disc_reason);
1204    
1205     DEBUG(("Received disconnect PDU\n"));
1206     }
1207    
1208 matty 10 /* Process data PDU */
1209 astrand 676 static BOOL
1210     process_data_pdu(STREAM s, uint32 * ext_disc_reason)
1211 matty 9 {
1212 matty 10 uint8 data_pdu_type;
1213 n-ki 624 uint8 ctype;
1214     uint16 clen;
1215 n-ki 683 uint32 len;
1216 matty 9
1217 n-ki 683 uint32 roff, rlen;
1218    
1219 n-ki 687 struct stream *ns = &(g_mppc_dict.ns);
1220 n-ki 683
1221 n-ki 624 in_uint8s(s, 6); /* shareid, pad, streamid */
1222     in_uint16(s, len);
1223 matty 10 in_uint8(s, data_pdu_type);
1224 n-ki 624 in_uint8(s, ctype);
1225     in_uint16(s, clen);
1226     clen -= 18;
1227 matty 3
1228 n-ki 683 if (ctype & RDP_MPPC_COMPRESSED)
1229 n-ki 624 {
1230 jsorg71 773 if (len > RDP_MPPC_DICT_SIZE)
1231 astrand 782 error("error decompressed packet size exceeds max\n");
1232 n-ki 683 if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)
1233     error("error while decompressing packet\n");
1234 n-ki 624
1235 stargo 865 /* len -= 18; */
1236 n-ki 624
1237 n-ki 683 /* allocate memory and copy the uncompressed data into the temporary stream */
1238 jsorg71 711 ns->data = (uint8 *) xrealloc(ns->data, rlen);
1239 n-ki 624
1240 n-ki 687 memcpy((ns->data), (unsigned char *) (g_mppc_dict.hist + roff), rlen);
1241 n-ki 624
1242 n-ki 687 ns->size = rlen;
1243 n-ki 683 ns->end = (ns->data + ns->size);
1244     ns->p = ns->data;
1245     ns->rdp_hdr = ns->p;
1246    
1247     s = ns;
1248 n-ki 624 }
1249    
1250 matty 10 switch (data_pdu_type)
1251 matty 3 {
1252 matty 10 case RDP_DATA_PDU_UPDATE:
1253     process_update_pdu(s);
1254     break;
1255 matty 3
1256 astrand 676 case RDP_DATA_PDU_CONTROL:
1257     DEBUG(("Received Control PDU\n"));
1258     break;
1259    
1260     case RDP_DATA_PDU_SYNCHRONISE:
1261     DEBUG(("Received Sync PDU\n"));
1262     break;
1263    
1264 matty 10 case RDP_DATA_PDU_POINTER:
1265     process_pointer_pdu(s);
1266     break;
1267 matty 3
1268 matty 10 case RDP_DATA_PDU_BELL:
1269     ui_bell();
1270     break;
1271 matty 3
1272 matty 10 case RDP_DATA_PDU_LOGON:
1273 forsberg 351 DEBUG(("Received Logon PDU\n"));
1274 matty 10 /* User logged on */
1275     break;
1276 matty 3
1277 matthewc 522 case RDP_DATA_PDU_DISCONNECT:
1278 astrand 676 process_disconnect_pdu(s, ext_disc_reason);
1279     return True;
1280 matthewc 522
1281 matty 10 default:
1282 matty 30 unimpl("data PDU %d\n", data_pdu_type);
1283 matty 3 }
1284 astrand 676 return False;
1285 matty 3 }
1286    
1287 matty 10 /* Process incoming packets */
1288 jsorg71 733 /* nevers gets out of here till app is done */
1289 astrand 676 void
1290     rdp_main_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1291 matty 9 {
1292 jsorg71 733 while (rdp_loop(deactivated, ext_disc_reason))
1293     ;
1294 matty 3 }
1295    
1296 jsorg71 733 /* used in uiports and rdp_main_loop, processes the rdp packets waiting */
1297 jsorg71 713 BOOL
1298     rdp_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1299     {
1300     uint8 type;
1301     BOOL disc = False; /* True when a disconnect PDU was received */
1302     BOOL cont = True;
1303     STREAM s;
1304    
1305 astrand 717 while (cont)
1306 jsorg71 713 {
1307     s = rdp_recv(&type);
1308     if (s == NULL)
1309     return False;
1310     switch (type)
1311     {
1312     case RDP_PDU_DEMAND_ACTIVE:
1313     process_demand_active(s);
1314     *deactivated = False;
1315     break;
1316     case RDP_PDU_DEACTIVATE:
1317     DEBUG(("RDP_PDU_DEACTIVATE\n"));
1318     *deactivated = True;
1319     break;
1320     case RDP_PDU_DATA:
1321     disc = process_data_pdu(s, ext_disc_reason);
1322     break;
1323     case 0:
1324     break;
1325     default:
1326     unimpl("PDU %d\n", type);
1327     }
1328     if (disc)
1329     return False;
1330     cont = g_next_packet < s->end;
1331     }
1332     return True;
1333     }
1334    
1335 matty 10 /* Establish a connection up to the RDP layer */
1336 matty 25 BOOL
1337     rdp_connect(char *server, uint32 flags, char *domain, char *password,
1338     char *command, char *directory)
1339 matty 9 {
1340 jsorg71 437 if (!sec_connect(server, g_username))
1341 matty 3 return False;
1342    
1343 jsorg71 437 rdp_send_logon_info(flags, domain, g_username, password, command, directory);
1344 matty 10 return True;
1345 matty 3 }
1346    
1347 matty 10 /* Disconnect from the RDP layer */
1348 matty 25 void
1349 matthewc 192 rdp_disconnect(void)
1350 matty 9 {
1351 matty 10 sec_disconnect();
1352 matty 9 }

  ViewVC Help
Powered by ViewVC 1.1.26