/[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 637 - (show annotations)
Mon Mar 15 14:49:12 2004 UTC (20 years, 2 months ago) by stargo
File MIME type: text/plain
File size: 23629 byte(s)
RDP5 Experience patch by Jeroen Meijer <jeroen@oldambt7.com>

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

  ViewVC Help
Powered by ViewVC 1.1.26