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

  ViewVC Help
Powered by ViewVC 1.1.26