/[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 424 - (show annotations)
Thu Jun 19 07:29:53 2003 UTC (20 years, 11 months ago) by forsberg
File MIME type: text/plain
File size: 21445 byte(s)
Make rdesktop return 0 only if a RDP_PDU_DISCONNECT was received,
otherwise return 2 (except for usage errors, where it still returns
1).

Documented exit codes of rdesktop in doc/exit_codes.txt.

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

  ViewVC Help
Powered by ViewVC 1.1.26