/[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 1308 - (hide annotations)
Wed Nov 1 18:38:40 2006 UTC (17 years, 6 months ago) by stargo
File MIME type: text/plain
File size: 33654 byte(s)
64bit fix from Jennings Jared <jared.jennings.ctr@eglin.af.mil>

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

  ViewVC Help
Powered by ViewVC 1.1.26