/[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 554 - (show annotations)
Tue Dec 9 09:57:44 2003 UTC (20 years, 5 months ago) by stargo
File MIME type: text/plain
File size: 22575 byte(s)
Timezone patch by Mark Roach

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

  ViewVC Help
Powered by ViewVC 1.1.26