/[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 668 - (show annotations)
Sat Apr 17 07:37:07 2004 UTC (20 years, 1 month ago) by astrand
File MIME type: text/plain
File size: 23960 byte(s)
Variables for uncommented code now uncommented as well. Fixes
"unused variable" warnings from GCC.

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, g_server_bpp); /* 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 uint16 i;
622 uint16 p_bpp;
623
624 in_uint32_le(s, g_rdp_shareid);
625
626 /* scan for prefered bpp */
627 while (s_check_rem(s, 6))
628 {
629 in_uint16_le(s, i);
630 if (i == RDP_CAPSET_BITMAP)
631 {
632 in_uint16_le(s, i);
633 if (i == RDP_CAPLEN_BITMAP)
634 {
635 in_uint16_le(s, p_bpp);
636 if (p_bpp == 8 || p_bpp == 15 || p_bpp == 16 || p_bpp == 24)
637 {
638 if (p_bpp < g_server_bpp)
639 {
640 warning("Server limited colour depth to %d bits\n",
641 p_bpp);
642 g_server_bpp = p_bpp;
643 }
644 break;
645 }
646 }
647 }
648 }
649
650
651 DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
652
653 rdp_send_confirm_active();
654 rdp_send_synchronise();
655 rdp_send_control(RDP_CTL_COOPERATE);
656 rdp_send_control(RDP_CTL_REQUEST_CONTROL);
657 rdp_recv(&type); /* RDP_PDU_SYNCHRONIZE */
658 rdp_recv(&type); /* RDP_CTL_COOPERATE */
659 rdp_recv(&type); /* RDP_CTL_GRANT_CONTROL */
660 rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(read_keyboard_state()), 0);
661 rdp_send_fonts(1);
662 rdp_send_fonts(2);
663 rdp_recv(&type); /* RDP_PDU_UNKNOWN 0x28 */
664 reset_order_state();
665 }
666
667 /* Process a colour pointer PDU */
668 void
669 process_colour_pointer_pdu(STREAM s)
670 {
671 uint16 x, y, width, height, cache_idx, masklen, datalen;
672 uint8 *mask, *data;
673 HCURSOR cursor;
674
675 in_uint16_le(s, cache_idx);
676 in_uint16_le(s, x);
677 in_uint16_le(s, y);
678 in_uint16_le(s, width);
679 in_uint16_le(s, height);
680 in_uint16_le(s, masklen);
681 in_uint16_le(s, datalen);
682 in_uint8p(s, data, datalen);
683 in_uint8p(s, mask, masklen);
684 cursor = ui_create_cursor(x, y, width, height, mask, data);
685 ui_set_cursor(cursor);
686 cache_put_cursor(cache_idx, cursor);
687 }
688
689 /* Process a cached pointer PDU */
690 void
691 process_cached_pointer_pdu(STREAM s)
692 {
693 uint16 cache_idx;
694
695 in_uint16_le(s, cache_idx);
696 ui_set_cursor(cache_get_cursor(cache_idx));
697 }
698
699 /* Process a system pointer PDU */
700 void
701 process_system_pointer_pdu(STREAM s)
702 {
703 uint16 system_pointer_type;
704
705 in_uint16(s, system_pointer_type);
706 switch (system_pointer_type)
707 {
708 case RDP_NULL_POINTER:
709 ui_set_null_cursor();
710 break;
711
712 default:
713 unimpl("System pointer message 0x%x\n", system_pointer_type);
714 }
715 }
716
717 /* Process a pointer PDU */
718 static void
719 process_pointer_pdu(STREAM s)
720 {
721 uint16 message_type;
722 uint16 x, y;
723
724 in_uint16_le(s, message_type);
725 in_uint8s(s, 2); /* pad */
726
727 switch (message_type)
728 {
729 case RDP_POINTER_MOVE:
730 in_uint16_le(s, x);
731 in_uint16_le(s, y);
732 if (s_check(s))
733 ui_move_pointer(x, y);
734 break;
735
736 case RDP_POINTER_COLOR:
737 process_colour_pointer_pdu(s);
738 break;
739
740 case RDP_POINTER_CACHED:
741 process_cached_pointer_pdu(s);
742 break;
743
744 case RDP_POINTER_SYSTEM:
745 process_system_pointer_pdu(s);
746 break;
747
748 default:
749 unimpl("Pointer message 0x%x\n", message_type);
750 }
751 }
752
753 /* Process bitmap updates */
754 void
755 process_bitmap_updates(STREAM s)
756 {
757 uint16 num_updates;
758 uint16 left, top, right, bottom, width, height;
759 uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
760 uint8 *data, *bmpdata;
761 int i;
762
763 in_uint16_le(s, num_updates);
764
765 for (i = 0; i < num_updates; i++)
766 {
767 in_uint16_le(s, left);
768 in_uint16_le(s, top);
769 in_uint16_le(s, right);
770 in_uint16_le(s, bottom);
771 in_uint16_le(s, width);
772 in_uint16_le(s, height);
773 in_uint16_le(s, bpp);
774 Bpp = (bpp + 7) / 8;
775 in_uint16_le(s, compress);
776 in_uint16_le(s, bufsize);
777
778 cx = right - left + 1;
779 cy = bottom - top + 1;
780
781 DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",
782 left, top, right, bottom, width, height, Bpp, compress));
783
784 if (!compress)
785 {
786 int y;
787 bmpdata = (uint8 *) xmalloc(width * height * Bpp);
788 for (y = 0; y < height; y++)
789 {
790 in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
791 width * Bpp);
792 }
793 ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
794 xfree(bmpdata);
795 continue;
796 }
797
798
799 if (compress & 0x400)
800 {
801 size = bufsize;
802 }
803 else
804 {
805 in_uint8s(s, 2); /* pad */
806 in_uint16_le(s, size);
807 in_uint8s(s, 4); /* line_size, final_size */
808 }
809 in_uint8p(s, data, size);
810 bmpdata = (uint8 *) xmalloc(width * height * Bpp);
811 if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
812 {
813 ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
814 }
815 else
816 {
817 DEBUG_RDP5(("Failed to decompress data\n"));
818 }
819
820 xfree(bmpdata);
821 }
822 }
823
824 /* Process a palette update */
825 void
826 process_palette(STREAM s)
827 {
828 COLOURENTRY *entry;
829 COLOURMAP map;
830 HCOLOURMAP hmap;
831 int i;
832
833 in_uint8s(s, 2); /* pad */
834 in_uint16_le(s, map.ncolours);
835 in_uint8s(s, 2); /* pad */
836
837 map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
838
839 DEBUG(("PALETTE(c=%d)\n", map.ncolours));
840
841 for (i = 0; i < map.ncolours; i++)
842 {
843 entry = &map.colours[i];
844 in_uint8(s, entry->red);
845 in_uint8(s, entry->green);
846 in_uint8(s, entry->blue);
847 }
848
849 hmap = ui_create_colourmap(&map);
850 ui_set_colourmap(hmap);
851
852 xfree(map.colours);
853 }
854
855 /* Process an update PDU */
856 static void
857 process_update_pdu(STREAM s)
858 {
859 uint16 update_type, count;
860
861 in_uint16_le(s, update_type);
862
863 switch (update_type)
864 {
865 case RDP_UPDATE_ORDERS:
866 in_uint8s(s, 2); /* pad */
867 in_uint16_le(s, count);
868 in_uint8s(s, 2); /* pad */
869 process_orders(s, count);
870 break;
871
872 case RDP_UPDATE_BITMAP:
873 process_bitmap_updates(s);
874 break;
875
876 case RDP_UPDATE_PALETTE:
877 process_palette(s);
878 break;
879
880 case RDP_UPDATE_SYNCHRONIZE:
881 break;
882
883 default:
884 unimpl("update %d\n", update_type);
885 }
886
887 }
888
889 /* Process data PDU */
890 static void
891 process_data_pdu(STREAM s)
892 {
893 uint8 data_pdu_type;
894 uint8 ctype;
895 uint16 clen;
896 int len;
897 #if 0
898 int roff, rlen, ret;
899 static struct stream ns;
900 static signed char *dict = 0;
901 #endif
902
903 in_uint8s(s, 6); /* shareid, pad, streamid */
904 in_uint16(s, len);
905 in_uint8(s, data_pdu_type);
906 in_uint8(s, ctype);
907 in_uint16(s, clen);
908 clen -= 18;
909
910 #if 0
911 if (ctype & 0x20)
912 {
913 if (!dict)
914 {
915 dict = (signed char *) malloc(8200 * sizeof(signed char));
916 dict = (signed char *) memset(dict, 0, 8200 * sizeof(signed char));
917 }
918
919 ret = decompress(s->p, clen, ctype, (signed char *) dict, &roff, &rlen);
920
921 len -= 18;
922
923 ns.data = xrealloc(ns.data, len);
924
925 ns.data = (unsigned char *) memcpy(ns.data, (unsigned char *) (dict + roff), len);
926
927 ns.size = len;
928 ns.end = ns.data + ns.size;
929 ns.p = ns.data;
930 ns.rdp_hdr = ns.p;
931
932 s = &ns;
933 }
934 #endif
935
936 switch (data_pdu_type)
937 {
938 case RDP_DATA_PDU_UPDATE:
939 process_update_pdu(s);
940 break;
941
942 case RDP_DATA_PDU_POINTER:
943 process_pointer_pdu(s);
944 break;
945
946 case RDP_DATA_PDU_BELL:
947 ui_bell();
948 break;
949
950 case RDP_DATA_PDU_LOGON:
951 DEBUG(("Received Logon PDU\n"));
952 /* User logged on */
953 break;
954
955 case RDP_DATA_PDU_DISCONNECT:
956 /* Normally received when user logs out or disconnects from a
957 console session on Windows XP and 2003 Server */
958 DEBUG(("Received disconnect PDU\n"));
959 break;
960
961 default:
962 unimpl("data PDU %d\n", data_pdu_type);
963 }
964 }
965
966 /* Process incoming packets */
967 BOOL
968 rdp_main_loop(void)
969 {
970 uint8 type;
971 STREAM s;
972
973 while ((s = rdp_recv(&type)) != NULL)
974 {
975 switch (type)
976 {
977 case RDP_PDU_DEMAND_ACTIVE:
978 process_demand_active(s);
979 break;
980
981 case RDP_PDU_DEACTIVATE:
982 DEBUG(("RDP_PDU_DEACTIVATE\n"));
983 /* We thought we could detect a clean
984 shutdown of the session by this
985 packet, but it seems Windows 2003
986 is sending us one of these when we
987 reconnect to a disconnected session
988 return True; */
989 break;
990
991 case RDP_PDU_DATA:
992 process_data_pdu(s);
993 break;
994
995 case 0:
996 break;
997
998 default:
999 unimpl("PDU %d\n", type);
1000 }
1001 }
1002 return True;
1003 /* We want to detect if we got a clean shutdown, but we
1004 can't. Se above.
1005 return False; */
1006 }
1007
1008 /* Establish a connection up to the RDP layer */
1009 BOOL
1010 rdp_connect(char *server, uint32 flags, char *domain, char *password,
1011 char *command, char *directory)
1012 {
1013 if (!sec_connect(server, g_username))
1014 return False;
1015
1016 rdp_send_logon_info(flags, domain, g_username, password, command, directory);
1017 return True;
1018 }
1019
1020 /* Disconnect from the RDP layer */
1021 void
1022 rdp_disconnect(void)
1023 {
1024 sec_disconnect();
1025 }

  ViewVC Help
Powered by ViewVC 1.1.26