/[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 569 - (show annotations)
Wed Jan 21 14:40:40 2004 UTC (20 years, 4 months ago) by n-ki
File MIME type: text/plain
File size: 22875 byte(s)
redirection of disk, lptport, printer, comport.

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

  ViewVC Help
Powered by ViewVC 1.1.26