/[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 435 - (show annotations)
Wed Jul 9 09:18:20 2003 UTC (20 years, 9 months ago) by astrand
File MIME type: text/plain
File size: 21794 byte(s)
Indent fixes

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 extern int server_bpp;
32
33 uint8 *next_packet;
34 uint32 rdp_shareid;
35
36 #if WITH_DEBUG
37 static uint32 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) || (next_packet >= rdp_s->end))
48 {
49 rdp_s = sec_recv();
50 if (rdp_s == NULL)
51 return NULL;
52
53 next_packet = rdp_s->p;
54 }
55 else
56 {
57 rdp_s->p = 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 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", ++packetno, *type));
74 // hexdump(next_packet, length);
75 #endif /* */
76
77 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(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, 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, 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 = encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO;
148 STREAM s;
149
150 if (!use_rdp5 || 1 == 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, 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, 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] = (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, 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 = (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 = 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, 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, rdp_shareid);
593
594 DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", 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 null system pointer PDU */
611 void
612 process_null_system_pointer_pdu(STREAM s)
613 {
614 // FIXME: We should probably set another cursor here,
615 // like the X window system base cursor or something.
616 ui_set_cursor(cache_get_cursor(0));
617 }
618
619 /* Process a colour pointer PDU */
620 void
621 process_colour_pointer_pdu(STREAM s)
622 {
623 uint16 x, y, width, height, cache_idx, masklen, datalen;
624 uint8 *mask, *data;
625 HCURSOR cursor;
626
627 in_uint16_le(s, cache_idx);
628 in_uint16_le(s, x);
629 in_uint16_le(s, y);
630 in_uint16_le(s, width);
631 in_uint16_le(s, height);
632 in_uint16_le(s, masklen);
633 in_uint16_le(s, datalen);
634 in_uint8p(s, data, datalen);
635 in_uint8p(s, mask, masklen);
636 cursor = ui_create_cursor(x, y, width, height, mask, data);
637 ui_set_cursor(cursor);
638 cache_put_cursor(cache_idx, cursor);
639 }
640
641 /* Process a cached pointer PDU */
642 void
643 process_cached_pointer_pdu(STREAM s)
644 {
645 uint16 cache_idx;
646
647 in_uint16_le(s, cache_idx);
648 ui_set_cursor(cache_get_cursor(cache_idx));
649 }
650
651
652 /* Process a pointer PDU */
653 static void
654 process_pointer_pdu(STREAM s)
655 {
656 uint16 message_type;
657 uint16 x, y;
658
659 in_uint16_le(s, message_type);
660 in_uint8s(s, 2); /* pad */
661
662 switch (message_type)
663 {
664 case RDP_POINTER_MOVE:
665 in_uint16_le(s, x);
666 in_uint16_le(s, y);
667 if (s_check(s))
668 ui_move_pointer(x, y);
669 break;
670
671 case RDP_POINTER_COLOR:
672 process_colour_pointer_pdu(s);
673 break;
674
675 case RDP_POINTER_CACHED:
676 process_cached_pointer_pdu(s);
677 break;
678
679 default:
680 DEBUG(("Pointer message 0x%x\n", message_type));
681 }
682 }
683
684 /* Process bitmap updates */
685 void
686 process_bitmap_updates(STREAM s)
687 {
688 uint16 num_updates;
689 uint16 left, top, right, bottom, width, height;
690 uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
691 uint8 *data, *bmpdata;
692 int i;
693
694 in_uint16_le(s, num_updates);
695
696 for (i = 0; i < num_updates; i++)
697 {
698 in_uint16_le(s, left);
699 in_uint16_le(s, top);
700 in_uint16_le(s, right);
701 in_uint16_le(s, bottom);
702 in_uint16_le(s, width);
703 in_uint16_le(s, height);
704 in_uint16_le(s, bpp);
705 Bpp = (bpp + 7) / 8;
706 in_uint16_le(s, compress);
707 in_uint16_le(s, bufsize);
708
709 cx = right - left + 1;
710 cy = bottom - top + 1;
711
712 DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",
713 left, top, right, bottom, width, height, Bpp, compress));
714
715 if (!compress)
716 {
717 int y;
718 bmpdata = (uint8 *) xmalloc(width * height * Bpp);
719 for (y = 0; y < height; y++)
720 {
721 in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
722 width * Bpp);
723 }
724 ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
725 xfree(bmpdata);
726 continue;
727 }
728
729
730 if (compress & 0x400)
731 {
732 size = bufsize;
733 }
734 else
735 {
736 in_uint8s(s, 2); /* pad */
737 in_uint16_le(s, size);
738 in_uint8s(s, 4); /* line_size, final_size */
739 }
740 in_uint8p(s, data, size);
741 bmpdata = (uint8 *) xmalloc(width * height * Bpp);
742 if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
743 {
744 ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
745 }
746 else
747 {
748 DEBUG_RDP5(("Failed to decompress data\n"));
749 }
750
751 xfree(bmpdata);
752 }
753 }
754
755 /* Process a palette update */
756 void
757 process_palette(STREAM s)
758 {
759 COLOURENTRY *entry;
760 COLOURMAP map;
761 HCOLOURMAP hmap;
762 int i;
763
764 in_uint8s(s, 2); /* pad */
765 in_uint16_le(s, map.ncolours);
766 in_uint8s(s, 2); /* pad */
767
768 map.colours = (COLOURENTRY *) xmalloc(3 * map.ncolours);
769
770 DEBUG(("PALETTE(c=%d)\n", map.ncolours));
771
772 for (i = 0; i < map.ncolours; i++)
773 {
774 entry = &map.colours[i];
775 in_uint8(s, entry->red);
776 in_uint8(s, entry->green);
777 in_uint8(s, entry->blue);
778 }
779
780 hmap = ui_create_colourmap(&map);
781 ui_set_colourmap(hmap);
782
783 xfree(map.colours);
784 }
785
786 /* Process an update PDU */
787 static void
788 process_update_pdu(STREAM s)
789 {
790 uint16 update_type, count;
791
792 in_uint16_le(s, update_type);
793
794 switch (update_type)
795 {
796 case RDP_UPDATE_ORDERS:
797 in_uint8s(s, 2); /* pad */
798 in_uint16_le(s, count);
799 in_uint8s(s, 2); /* pad */
800 process_orders(s, count);
801 break;
802
803 case RDP_UPDATE_BITMAP:
804 process_bitmap_updates(s);
805 break;
806
807 case RDP_UPDATE_PALETTE:
808 process_palette(s);
809 break;
810
811 case RDP_UPDATE_SYNCHRONIZE:
812 break;
813
814 default:
815 unimpl("update %d\n", update_type);
816 }
817
818 }
819
820 /* Process data PDU */
821 static void
822 process_data_pdu(STREAM s)
823 {
824 uint8 data_pdu_type;
825
826 in_uint8s(s, 8); /* shareid, pad, streamid, length */
827 in_uint8(s, data_pdu_type);
828 in_uint8s(s, 3); /* compress_type, compress_len */
829
830 switch (data_pdu_type)
831 {
832 case RDP_DATA_PDU_UPDATE:
833 process_update_pdu(s);
834 break;
835
836 case RDP_DATA_PDU_POINTER:
837 process_pointer_pdu(s);
838 break;
839
840 case RDP_DATA_PDU_BELL:
841 ui_bell();
842 break;
843
844 case RDP_DATA_PDU_LOGON:
845 DEBUG(("Received Logon PDU\n"));
846 /* User logged on */
847 break;
848
849 default:
850 unimpl("data PDU %d\n", data_pdu_type);
851 }
852 }
853
854 /* Process incoming packets */
855 BOOL
856 rdp_main_loop(void)
857 {
858 uint8 type;
859 STREAM s;
860
861 while ((s = rdp_recv(&type)) != NULL)
862 {
863 switch (type)
864 {
865 case RDP_PDU_DEMAND_ACTIVE:
866 process_demand_active(s);
867 break;
868
869 case RDP_PDU_DEACTIVATE:
870 DEBUG(("RDP_PDU_DEACTIVATE\n"));
871 /* We thought we could detect a clean
872 shutdown of the session by this
873 packet, but it seems Windows 2003
874 is sending us one of these when we
875 reconnect to a disconnected session
876 return True; */
877 break;
878
879 case RDP_PDU_DATA:
880 process_data_pdu(s);
881 break;
882
883 case 0:
884 break;
885
886 default:
887 unimpl("PDU %d\n", type);
888 }
889 }
890 return True;
891 /* We want to detect if we got a clean shutdown, but we
892 can't. Se above.
893 return False; */
894 }
895
896 /* Establish a connection up to the RDP layer */
897 BOOL
898 rdp_connect(char *server, uint32 flags, char *domain, char *password,
899 char *command, char *directory)
900 {
901 if (!sec_connect(server, username))
902 return False;
903
904 rdp_send_logon_info(flags, domain, username, password, command, directory);
905 return True;
906 }
907
908 /* Disconnect from the RDP layer */
909 void
910 rdp_disconnect(void)
911 {
912 sec_disconnect();
913 }

  ViewVC Help
Powered by ViewVC 1.1.26