/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 773 - (show annotations)
Sat Sep 11 22:57:42 2004 UTC (19 years, 8 months ago) by jsorg71
File MIME type: text/plain
File size: 28039 byte(s)
added option for rdp compression

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

  ViewVC Help
Powered by ViewVC 1.1.26