/[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 624 - (show annotations)
Thu Mar 4 08:11:40 2004 UTC (20 years, 3 months ago) by n-ki
File MIME type: text/plain
File size: 23571 byte(s)
get real ip address, or lp if not avail - volker milde, also part of rdp compression within ifdef 0 from uni patches

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

  ViewVC Help
Powered by ViewVC 1.1.26