/[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 381 - (show annotations)
Fri May 30 21:59:56 2003 UTC (20 years, 11 months ago) by jsorg71
File MIME type: text/plain
File size: 21364 byte(s)
adding g_ prefix to global vars, mcs.c done

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

  ViewVC Help
Powered by ViewVC 1.1.26