/[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 683 - (show annotations)
Tue Apr 27 12:55:33 2004 UTC (20 years ago) by n-ki
File MIME type: text/plain
File size: 25294 byte(s)
mppc like decompression for the rdp protocol. code not activated. rdp5 gets some extra opcodes, and the decompression seems to work fine. :\

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

  ViewVC Help
Powered by ViewVC 1.1.26