/[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 540 - (show annotations)
Fri Oct 31 20:34:26 2003 UTC (20 years, 6 months ago) by astrand
File MIME type: text/plain
File size: 22476 byte(s)
Replaced C++ comments with C-style

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

  ViewVC Help
Powered by ViewVC 1.1.26