/[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 518 - (show annotations)
Tue Oct 28 03:37:44 2003 UTC (20 years, 6 months ago) by matthewc
File MIME type: text/plain
File size: 22198 byte(s)
Hack to detect server-limited colour depth
(from neoware)

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 warning("Server limited colour depth to %d bits\n", bpp);
730 g_server_bpp = bpp;
731 }
732
733 if (!compress)
734 {
735 int y;
736 bmpdata = (uint8 *) xmalloc(width * height * Bpp);
737 for (y = 0; y < height; y++)
738 {
739 in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
740 width * Bpp);
741 }
742 ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
743 xfree(bmpdata);
744 continue;
745 }
746
747
748 if (compress & 0x400)
749 {
750 size = bufsize;
751 }
752 else
753 {
754 in_uint8s(s, 2); /* pad */
755 in_uint16_le(s, size);
756 in_uint8s(s, 4); /* line_size, final_size */
757 }
758 in_uint8p(s, data, size);
759 bmpdata = (uint8 *) xmalloc(width * height * Bpp);
760 if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
761 {
762 ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
763 }
764 else
765 {
766 DEBUG_RDP5(("Failed to decompress data\n"));
767 }
768
769 xfree(bmpdata);
770 }
771 }
772
773 /* Process a palette update */
774 void
775 process_palette(STREAM s)
776 {
777 COLOURENTRY *entry;
778 COLOURMAP map;
779 HCOLOURMAP hmap;
780 int i;
781
782 in_uint8s(s, 2); /* pad */
783 in_uint16_le(s, map.ncolours);
784 in_uint8s(s, 2); /* pad */
785
786 map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
787
788 DEBUG(("PALETTE(c=%d)\n", map.ncolours));
789
790 for (i = 0; i < map.ncolours; i++)
791 {
792 entry = &map.colours[i];
793 in_uint8(s, entry->red);
794 in_uint8(s, entry->green);
795 in_uint8(s, entry->blue);
796 }
797
798 hmap = ui_create_colourmap(&map);
799 ui_set_colourmap(hmap);
800
801 xfree(map.colours);
802 }
803
804 /* Process an update PDU */
805 static void
806 process_update_pdu(STREAM s)
807 {
808 uint16 update_type, count;
809
810 in_uint16_le(s, update_type);
811
812 switch (update_type)
813 {
814 case RDP_UPDATE_ORDERS:
815 in_uint8s(s, 2); /* pad */
816 in_uint16_le(s, count);
817 in_uint8s(s, 2); /* pad */
818 process_orders(s, count);
819 break;
820
821 case RDP_UPDATE_BITMAP:
822 process_bitmap_updates(s);
823 break;
824
825 case RDP_UPDATE_PALETTE:
826 process_palette(s);
827 break;
828
829 case RDP_UPDATE_SYNCHRONIZE:
830 break;
831
832 default:
833 unimpl("update %d\n", update_type);
834 }
835
836 }
837
838 /* Process data PDU */
839 static void
840 process_data_pdu(STREAM s)
841 {
842 uint8 data_pdu_type;
843
844 in_uint8s(s, 8); /* shareid, pad, streamid, length */
845 in_uint8(s, data_pdu_type);
846 in_uint8s(s, 3); /* compress_type, compress_len */
847
848 switch (data_pdu_type)
849 {
850 case RDP_DATA_PDU_UPDATE:
851 process_update_pdu(s);
852 break;
853
854 case RDP_DATA_PDU_POINTER:
855 process_pointer_pdu(s);
856 break;
857
858 case RDP_DATA_PDU_BELL:
859 ui_bell();
860 break;
861
862 case RDP_DATA_PDU_LOGON:
863 DEBUG(("Received Logon PDU\n"));
864 /* User logged on */
865 break;
866
867 default:
868 unimpl("data PDU %d\n", data_pdu_type);
869 }
870 }
871
872 /* Process incoming packets */
873 BOOL
874 rdp_main_loop(void)
875 {
876 uint8 type;
877 STREAM s;
878
879 while ((s = rdp_recv(&type)) != NULL)
880 {
881 switch (type)
882 {
883 case RDP_PDU_DEMAND_ACTIVE:
884 process_demand_active(s);
885 break;
886
887 case RDP_PDU_DEACTIVATE:
888 DEBUG(("RDP_PDU_DEACTIVATE\n"));
889 /* We thought we could detect a clean
890 shutdown of the session by this
891 packet, but it seems Windows 2003
892 is sending us one of these when we
893 reconnect to a disconnected session
894 return True; */
895 break;
896
897 case RDP_PDU_DATA:
898 process_data_pdu(s);
899 break;
900
901 case 0:
902 break;
903
904 default:
905 unimpl("PDU %d\n", type);
906 }
907 }
908 return True;
909 /* We want to detect if we got a clean shutdown, but we
910 can't. Se above.
911 return False; */
912 }
913
914 /* Establish a connection up to the RDP layer */
915 BOOL
916 rdp_connect(char *server, uint32 flags, char *domain, char *password,
917 char *command, char *directory)
918 {
919 if (!sec_connect(server, g_username))
920 return False;
921
922 rdp_send_logon_info(flags, domain, g_username, password, command, directory);
923 return True;
924 }
925
926 /* Disconnect from the RDP layer */
927 void
928 rdp_disconnect(void)
929 {
930 sec_disconnect();
931 }

  ViewVC Help
Powered by ViewVC 1.1.26