/[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 351 - (show annotations)
Thu Mar 27 13:22:29 2003 UTC (21 years, 2 months ago) by forsberg
File MIME type: text/plain
File size: 20299 byte(s)
Send different logon packets based on if we try to support RDP5 or not. The
order of the data is slightly different in RDP5.

Moved pointer PDU handling to their own functions, since RDP5 no longer
encapsulates ColorPointer and CachedPointer in a PDU with a type field.

Made debug output when doing Bitmap updates clearer. Also added debug
printout when bitmap compression failed.

Added code that checks for a new way of sending the size of the compressed
bitmaps. Code imported from Matt's RDP5 adventures :).

Debug output when doing Palette updates in order to make it easier to follow
packets.

Fetch the number of orders here instead of in process_orders and send it
along to that function as an argument.

Send the username to sec_connect.

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

  ViewVC Help
Powered by ViewVC 1.1.26