/[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 654 - (show annotations)
Thu Apr 15 22:03:24 2004 UTC (20 years, 1 month ago) by jsorg71
File MIME type: text/plain
File size: 23935 byte(s)
move color fallback from process_bitmap_updates to process_demand_active

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

  ViewVC Help
Powered by ViewVC 1.1.26