/[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 889 - (show annotations)
Sun Apr 17 23:14:20 2005 UTC (19 years ago) by jdmeijer
File MIME type: text/plain
File size: 30698 byte(s)
Add alternative mppc decompression code with 64kB history buffer from Vahur Sinijärv, and reenable rdp5 (persistent) bitmap cache 2 (64x64)

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

  ViewVC Help
Powered by ViewVC 1.1.26