/[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 848 - (show annotations)
Sun Mar 13 03:29:19 2005 UTC (19 years, 2 months ago) by jsorg71
File MIME type: text/plain
File size: 28435 byte(s)
added var for new polygon and ellipse orders

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

  ViewVC Help
Powered by ViewVC 1.1.26