/[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 678 - (show annotations)
Mon Apr 26 22:31:22 2004 UTC (20 years ago) by jsorg71
File MIME type: text/plain
File size: 25116 byte(s)
fix the -b switch

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

  ViewVC Help
Powered by ViewVC 1.1.26