/[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 717 - (show annotations)
Thu Jun 17 09:42:58 2004 UTC (19 years, 11 months ago) by astrand
File MIME type: text/plain
File size: 26178 byte(s)
Indent fixes

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

  ViewVC Help
Powered by ViewVC 1.1.26