/[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 677 - (show annotations)
Mon Apr 26 13:48:39 2004 UTC (20 years, 1 month ago) by n-ki
File MIME type: text/plain
File size: 25079 byte(s)
new: ui_resize_window() and related, which is used when resizing while shadowing. And fallback for color when connecting to a session with fewer colors than you have set in your session. Jeroen Meijer jeroen@oldambt7.com

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

  ViewVC Help
Powered by ViewVC 1.1.26