/[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 562 - (show annotations)
Thu Dec 11 17:20:01 2003 UTC (20 years, 5 months ago) by stargo
File MIME type: text/plain
File size: 22637 byte(s)
Hopefully portable timezone implementation by Johan Larsson

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

  ViewVC Help
Powered by ViewVC 1.1.26