/[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 559 - (show annotations)
Thu Dec 11 12:25:38 2003 UTC (20 years, 5 months ago) by stargo
File MIME type: text/plain
File size: 22591 byte(s)
Removed timezone stuff, due to too much portability problems...
Will solve this later
Portability "fix" for rdpsnd_sun.c on openbsd

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

  ViewVC Help
Powered by ViewVC 1.1.26