VirtualBox

source: vbox/trunk/src/VBox/RDP/client/rdp.c@ 34346

Last change on this file since 34346 was 33656, checked in by vboxsync, 14 years ago

*: rebrand Sun (L)GPL disclaimers

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 34.2 KB
Line 
1/* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Protocol services - RDP layer
4 Copyright (C) Matthew Chapman 1999-2007
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/*
22 * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
23 * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
24 * the General Public License version 2 (GPLv2) at this time for any software where
25 * a choice of GPL license versions is made available with the language indicating
26 * that GPLv2 or any later version may be used, or where a choice of which version
27 * of the GPL is applied is otherwise unspecified.
28 */
29
30#include <time.h>
31#ifndef _WIN32
32#include <errno.h>
33#include <unistd.h>
34#endif
35#include "rdesktop.h"
36
37#ifdef HAVE_ICONV
38#ifdef HAVE_ICONV_H
39#include <iconv.h>
40#endif
41
42#ifndef ICONV_CONST
43#define ICONV_CONST ""
44#endif
45#endif
46
47extern uint16 g_mcs_userid;
48extern char g_username[64];
49extern char g_codepage[16];
50extern RD_BOOL g_bitmap_compression;
51extern RD_BOOL g_orders;
52extern RD_BOOL g_encryption;
53extern RD_BOOL g_desktop_save;
54extern RD_BOOL g_polygon_ellipse_orders;
55extern RD_BOOL g_use_rdp5;
56extern uint16 g_server_rdp_version;
57extern uint32 g_rdp5_performanceflags;
58extern int g_server_depth;
59extern int g_width;
60extern int g_height;
61extern RD_BOOL g_bitmap_cache;
62extern RD_BOOL g_bitmap_cache_persist_enable;
63extern RD_BOOL g_numlock_sync;
64
65uint8 *g_next_packet;
66uint32 g_rdp_shareid;
67
68extern RDPCOMP g_mppc_dict;
69
70/* Session Directory support */
71extern RD_BOOL g_redirect;
72extern char g_redirect_server[64];
73extern char g_redirect_domain[16];
74extern char g_redirect_password[64];
75extern char g_redirect_username[64];
76extern char g_redirect_cookie[128];
77extern uint32 g_redirect_flags;
78/* END Session Directory support */
79
80#if WITH_DEBUG
81static uint32 g_packetno;
82#endif
83
84#ifdef HAVE_ICONV
85static RD_BOOL g_iconv_works = True;
86#endif
87
88/* Receive an RDP packet */
89static STREAM
90rdp_recv(uint8 * type)
91{
92 static STREAM rdp_s;
93 uint16 length, pdu_type;
94 uint8 rdpver;
95
96 if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end) || (g_next_packet == NULL))
97 {
98 rdp_s = sec_recv(&rdpver);
99 if (rdp_s == NULL)
100 return NULL;
101 if (rdpver == 0xff)
102 {
103 g_next_packet = rdp_s->end;
104 *type = 0;
105 return rdp_s;
106 }
107 else if (rdpver != 3)
108 {
109 /* rdp5_process should move g_next_packet ok */
110 rdp5_process(rdp_s);
111 *type = 0;
112 return rdp_s;
113 }
114
115 g_next_packet = rdp_s->p;
116 }
117 else
118 {
119 rdp_s->p = g_next_packet;
120 }
121
122 in_uint16_le(rdp_s, length);
123 /* 32k packets are really 8, keepalive fix */
124 if (length == 0x8000)
125 {
126 g_next_packet += 8;
127 *type = 0;
128 return rdp_s;
129 }
130 in_uint16_le(rdp_s, pdu_type);
131 in_uint8s(rdp_s, 2); /* userid */
132 *type = pdu_type & 0xf;
133
134#if WITH_DEBUG
135 DEBUG(("RDP packet #%d, (type %x)\n", ++g_packetno, *type));
136 hexdump(g_next_packet, length);
137#endif /* */
138
139 g_next_packet += length;
140 return rdp_s;
141}
142
143/* Initialise an RDP data packet */
144static STREAM
145rdp_init_data(int maxlen)
146{
147 STREAM s;
148
149 s = sec_init(g_encryption ? SEC_ENCRYPT : 0, maxlen + 18);
150 s_push_layer(s, rdp_hdr, 18);
151
152 return s;
153}
154
155/* Send an RDP data packet */
156static void
157rdp_send_data(STREAM s, uint8 data_pdu_type)
158{
159 uint16 length;
160
161 s_pop_layer(s, rdp_hdr);
162 length = s->end - s->p;
163
164 out_uint16_le(s, length);
165 out_uint16_le(s, (RDP_PDU_DATA | 0x10));
166 out_uint16_le(s, (g_mcs_userid + 1001));
167
168 out_uint32_le(s, g_rdp_shareid);
169 out_uint8(s, 0); /* pad */
170 out_uint8(s, 1); /* streamid */
171 out_uint16_le(s, (length - 14));
172 out_uint8(s, data_pdu_type);
173 out_uint8(s, 0); /* compress_type */
174 out_uint16(s, 0); /* compress_len */
175
176 sec_send(s, g_encryption ? SEC_ENCRYPT : 0);
177}
178
179/* Output a string in Unicode */
180void
181rdp_out_unistr(STREAM s, char *string, int len)
182{
183#ifdef HAVE_ICONV
184 size_t ibl = strlen(string), obl = len + 2;
185 static iconv_t iconv_h = (iconv_t) - 1;
186 char *pin = string, *pout = (char *) s->p;
187
188 memset(pout, 0, len + 4);
189
190 if (g_iconv_works)
191 {
192 if (iconv_h == (iconv_t) - 1)
193 {
194 size_t i = 1, o = 4;
195 if ((iconv_h = iconv_open(WINDOWS_CODEPAGE, g_codepage)) == (iconv_t) - 1)
196 {
197 warning("rdp_out_unistr: iconv_open[%s -> %s] fail %p\n",
198 g_codepage, WINDOWS_CODEPAGE, iconv_h);
199
200 g_iconv_works = False;
201 rdp_out_unistr(s, string, len);
202 return;
203 }
204 if (iconv(iconv_h, (ICONV_CONST char **) &pin, &i, &pout, &o) ==
205 (size_t) - 1)
206 {
207 iconv_close(iconv_h);
208 iconv_h = (iconv_t) - 1;
209 warning("rdp_out_unistr: iconv(1) fail, errno %d\n", errno);
210
211 g_iconv_works = False;
212 rdp_out_unistr(s, string, len);
213 return;
214 }
215 pin = string;
216 pout = (char *) s->p;
217 }
218
219 if (iconv(iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
220 {
221 iconv_close(iconv_h);
222 iconv_h = (iconv_t) - 1;
223 warning("rdp_out_unistr: iconv(2) fail, errno %d\n", errno);
224
225 g_iconv_works = False;
226 rdp_out_unistr(s, string, len);
227 return;
228 }
229
230 s->p += len + 2;
231
232 }
233 else
234#endif
235 {
236 int i = 0, j = 0;
237
238 len += 2;
239
240 while (i < len)
241 {
242 s->p[i++] = string[j++];
243 s->p[i++] = 0;
244 }
245
246 s->p += len;
247 }
248}
249
250/* Input a string in Unicode
251 *
252 * Returns str_len of string
253 */
254int
255rdp_in_unistr(STREAM s, char *string, int str_size, int in_len)
256{
257#ifdef HAVE_ICONV
258 size_t ibl = in_len, obl = str_size - 1;
259 char *pin = (char *) s->p, *pout = string;
260 static iconv_t iconv_h = (iconv_t) - 1;
261
262 if (g_iconv_works)
263 {
264 if (iconv_h == (iconv_t) - 1)
265 {
266 if ((iconv_h = iconv_open(g_codepage, WINDOWS_CODEPAGE)) == (iconv_t) - 1)
267 {
268 warning("rdp_in_unistr: iconv_open[%s -> %s] fail %p\n",
269 WINDOWS_CODEPAGE, g_codepage, iconv_h);
270
271 g_iconv_works = False;
272 return rdp_in_unistr(s, string, str_size, in_len);
273 }
274 }
275
276 if (iconv(iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
277 {
278 if (errno == E2BIG)
279 {
280 warning("server sent an unexpectedly long string, truncating\n");
281 }
282 else
283 {
284 iconv_close(iconv_h);
285 iconv_h = (iconv_t) - 1;
286 warning("rdp_in_unistr: iconv fail, errno %d\n", errno);
287
288 g_iconv_works = False;
289 return rdp_in_unistr(s, string, str_size, in_len);
290 }
291 }
292
293 /* we must update the location of the current STREAM for future reads of s->p */
294 s->p += in_len;
295
296 *pout = 0;
297 return pout - string;
298 }
299 else
300#endif
301 {
302 int i = 0;
303 int len = in_len / 2;
304 int rem = 0;
305
306 if (len > str_size - 1)
307 {
308 warning("server sent an unexpectedly long string, truncating\n");
309 len = str_size - 1;
310 rem = in_len - 2 * len;
311 }
312
313 while (i < len)
314 {
315 in_uint8a(s, &string[i++], 1);
316 in_uint8s(s, 1);
317 }
318
319 in_uint8s(s, rem);
320 string[len] = 0;
321 return len;
322 }
323}
324
325
326/* Parse a logon info packet */
327static void
328rdp_send_logon_info(uint32 flags, char *domain, char *user,
329 char *password, char *program, char *directory)
330{
331 char *ipaddr = tcp_get_address();
332 int len_domain = 2 * strlen(domain);
333 int len_user = 2 * strlen(user);
334 int len_password = 2 * strlen(password);
335 int len_program = 2 * strlen(program);
336 int len_directory = 2 * strlen(directory);
337 int len_ip = 2 * strlen(ipaddr);
338 int len_dll = 2 * strlen("C:\\WINNT\\System32\\mstscax.dll");
339 int packetlen = 0;
340 uint32 sec_flags = g_encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO;
341 STREAM s;
342 time_t t = time(NULL);
343 time_t tzone;
344
345 if (!g_use_rdp5 || 1 == g_server_rdp_version)
346 {
347 DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));
348
349 s = sec_init(sec_flags, 18 + len_domain + len_user + len_password
350 + len_program + len_directory + 10);
351
352 out_uint32(s, 0);
353 out_uint32_le(s, flags);
354 out_uint16_le(s, len_domain);
355 out_uint16_le(s, len_user);
356 out_uint16_le(s, len_password);
357 out_uint16_le(s, len_program);
358 out_uint16_le(s, len_directory);
359 rdp_out_unistr(s, domain, len_domain);
360 rdp_out_unistr(s, user, len_user);
361 rdp_out_unistr(s, password, len_password);
362 rdp_out_unistr(s, program, len_program);
363 rdp_out_unistr(s, directory, len_directory);
364 }
365 else
366 {
367
368 flags |= RDP_LOGON_BLOB;
369 DEBUG_RDP5(("Sending RDP5-style Logon packet\n"));
370 packetlen = 4 + /* Unknown uint32 */
371 4 + /* flags */
372 2 + /* len_domain */
373 2 + /* len_user */
374 (flags & RDP_LOGON_AUTO ? 2 : 0) + /* len_password */
375 (flags & RDP_LOGON_BLOB ? 2 : 0) + /* Length of BLOB */
376 2 + /* len_program */
377 2 + /* len_directory */
378 (0 < len_domain ? len_domain : 2) + /* domain */
379 len_user + (flags & RDP_LOGON_AUTO ? len_password : 0) + 0 + /* We have no 512 byte BLOB. Perhaps we must? */
380 (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO) ? 2 : 0) + /* After the BLOB is a unknown int16. If there is a BLOB, that is. */
381 (0 < len_program ? len_program : 2) + (0 < len_directory ? len_directory : 2) + 2 + /* Unknown (2) */
382 2 + /* Client ip length */
383 len_ip + /* Client ip */
384 2 + /* DLL string length */
385 len_dll + /* DLL string */
386 2 + /* Unknown */
387 2 + /* Unknown */
388 64 + /* Time zone #0 */
389 2 + /* Unknown */
390 64 + /* Time zone #1 */
391 32; /* Unknown */
392
393 s = sec_init(sec_flags, packetlen);
394 DEBUG_RDP5(("Called sec_init with packetlen %d\n", packetlen));
395
396 out_uint32(s, 0); /* Unknown */
397 out_uint32_le(s, flags);
398 out_uint16_le(s, len_domain);
399 out_uint16_le(s, len_user);
400 if (flags & RDP_LOGON_AUTO)
401 {
402 out_uint16_le(s, len_password);
403
404 }
405 if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
406 {
407 out_uint16_le(s, 0);
408 }
409 out_uint16_le(s, len_program);
410 out_uint16_le(s, len_directory);
411 if (0 < len_domain)
412 rdp_out_unistr(s, domain, len_domain);
413 else
414 out_uint16_le(s, 0);
415 rdp_out_unistr(s, user, len_user);
416 if (flags & RDP_LOGON_AUTO)
417 {
418 rdp_out_unistr(s, password, len_password);
419 }
420 if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
421 {
422 out_uint16_le(s, 0);
423 }
424 if (0 < len_program)
425 {
426 rdp_out_unistr(s, program, len_program);
427
428 }
429 else
430 {
431 out_uint16_le(s, 0);
432 }
433 if (0 < len_directory)
434 {
435 rdp_out_unistr(s, directory, len_directory);
436 }
437 else
438 {
439 out_uint16_le(s, 0);
440 }
441 out_uint16_le(s, 2);
442 out_uint16_le(s, len_ip + 2); /* Length of client ip */
443 rdp_out_unistr(s, ipaddr, len_ip);
444 out_uint16_le(s, len_dll + 2);
445 rdp_out_unistr(s, "C:\\WINNT\\System32\\mstscax.dll", len_dll);
446
447 tzone = (mktime(gmtime(&t)) - mktime(localtime(&t))) / 60;
448 out_uint32_le(s, tzone);
449
450 rdp_out_unistr(s, "GTB, normaltid", 2 * strlen("GTB, normaltid"));
451 out_uint8s(s, 62 - 2 * strlen("GTB, normaltid"));
452
453 out_uint32_le(s, 0x0a0000);
454 out_uint32_le(s, 0x050000);
455 out_uint32_le(s, 3);
456 out_uint32_le(s, 0);
457 out_uint32_le(s, 0);
458
459 rdp_out_unistr(s, "GTB, sommartid", 2 * strlen("GTB, sommartid"));
460 out_uint8s(s, 62 - 2 * strlen("GTB, sommartid"));
461
462 out_uint32_le(s, 0x30000);
463 out_uint32_le(s, 0x050000);
464 out_uint32_le(s, 2);
465 out_uint32(s, 0);
466 out_uint32_le(s, 0xffffffc4);
467 out_uint32_le(s, 0xfffffffe);
468 out_uint32_le(s, g_rdp5_performanceflags);
469 out_uint16(s, 0);
470
471
472 }
473 s_mark_end(s);
474 sec_send(s, sec_flags);
475}
476
477/* Send a control PDU */
478static void
479rdp_send_control(uint16 action)
480{
481 STREAM s;
482
483 s = rdp_init_data(8);
484
485 out_uint16_le(s, action);
486 out_uint16(s, 0); /* userid */
487 out_uint32(s, 0); /* control id */
488
489 s_mark_end(s);
490 rdp_send_data(s, RDP_DATA_PDU_CONTROL);
491}
492
493/* Send a synchronisation PDU */
494static void
495rdp_send_synchronise(void)
496{
497 STREAM s;
498
499 s = rdp_init_data(4);
500
501 out_uint16_le(s, 1); /* type */
502 out_uint16_le(s, 1002);
503
504 s_mark_end(s);
505 rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
506}
507
508/* Send a single input event */
509void
510rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2)
511{
512 STREAM s;
513
514 s = rdp_init_data(16);
515
516 out_uint16_le(s, 1); /* number of events */
517 out_uint16(s, 0); /* pad */
518
519 out_uint32_le(s, time);
520 out_uint16_le(s, message_type);
521 out_uint16_le(s, device_flags);
522 out_uint16_le(s, param1);
523 out_uint16_le(s, param2);
524
525 s_mark_end(s);
526 rdp_send_data(s, RDP_DATA_PDU_INPUT);
527}
528
529/* Send a client window information PDU */
530void
531rdp_send_client_window_status(int status)
532{
533 STREAM s;
534 static int current_status = 1;
535
536 if (current_status == status)
537 return;
538
539 s = rdp_init_data(12);
540
541 out_uint32_le(s, status);
542
543 switch (status)
544 {
545 case 0: /* shut the server up */
546 break;
547
548 case 1: /* receive data again */
549 out_uint32_le(s, 0); /* unknown */
550 out_uint16_le(s, g_width);
551 out_uint16_le(s, g_height);
552 break;
553 }
554
555 s_mark_end(s);
556 rdp_send_data(s, RDP_DATA_PDU_CLIENT_WINDOW_STATUS);
557 current_status = status;
558}
559
560/* Send persistent bitmap cache enumeration PDU's */
561static void
562rdp_enum_bmpcache2(void)
563{
564 STREAM s;
565 HASH_KEY keylist[BMPCACHE2_NUM_PSTCELLS];
566 uint32 num_keys, offset, count, flags;
567
568 offset = 0;
569 num_keys = pstcache_enumerate(2, keylist);
570
571 while (offset < num_keys)
572 {
573 count = MIN(num_keys - offset, 169);
574
575 s = rdp_init_data(24 + count * sizeof(HASH_KEY));
576
577 flags = 0;
578 if (offset == 0)
579 flags |= PDU_FLAG_FIRST;
580 if (num_keys - offset <= 169)
581 flags |= PDU_FLAG_LAST;
582
583 /* header */
584 out_uint32_le(s, 0);
585 out_uint16_le(s, count);
586 out_uint16_le(s, 0);
587 out_uint16_le(s, 0);
588 out_uint16_le(s, 0);
589 out_uint16_le(s, 0);
590 out_uint16_le(s, num_keys);
591 out_uint32_le(s, 0);
592 out_uint32_le(s, flags);
593
594 /* list */
595 out_uint8a(s, keylist[offset], count * sizeof(HASH_KEY));
596
597 s_mark_end(s);
598 rdp_send_data(s, 0x2b);
599
600 offset += 169;
601 }
602}
603
604/* Send an (empty) font information PDU */
605static void
606rdp_send_fonts(uint16 seq)
607{
608 STREAM s;
609
610 s = rdp_init_data(8);
611
612 out_uint16(s, 0); /* number of fonts */
613 out_uint16_le(s, 0); /* pad? */
614 out_uint16_le(s, seq); /* unknown */
615 out_uint16_le(s, 0x32); /* entry size */
616
617 s_mark_end(s);
618 rdp_send_data(s, RDP_DATA_PDU_FONT2);
619}
620
621/* Output general capability set */
622static void
623rdp_out_general_caps(STREAM s)
624{
625 out_uint16_le(s, RDP_CAPSET_GENERAL);
626 out_uint16_le(s, RDP_CAPLEN_GENERAL);
627
628 out_uint16_le(s, 1); /* OS major type */
629 out_uint16_le(s, 3); /* OS minor type */
630 out_uint16_le(s, 0x200); /* Protocol version */
631 out_uint16(s, 0); /* Pad */
632 out_uint16(s, 0); /* Compression types */
633 out_uint16_le(s, g_use_rdp5 ? 0x40d : 0);
634 /* Pad, according to T.128. 0x40d seems to
635 trigger
636 the server to start sending RDP5 packets.
637 However, the value is 0x1d04 with W2KTSK and
638 NT4MS. Hmm.. Anyway, thankyou, Microsoft,
639 for sending such information in a padding
640 field.. */
641 out_uint16(s, 0); /* Update capability */
642 out_uint16(s, 0); /* Remote unshare capability */
643 out_uint16(s, 0); /* Compression level */
644 out_uint16(s, 0); /* Pad */
645}
646
647/* Output bitmap capability set */
648static void
649rdp_out_bitmap_caps(STREAM s)
650{
651 out_uint16_le(s, RDP_CAPSET_BITMAP);
652 out_uint16_le(s, RDP_CAPLEN_BITMAP);
653
654 out_uint16_le(s, g_server_depth); /* Preferred colour depth */
655 out_uint16_le(s, 1); /* Receive 1 BPP */
656 out_uint16_le(s, 1); /* Receive 4 BPP */
657 out_uint16_le(s, 1); /* Receive 8 BPP */
658 out_uint16_le(s, 800); /* Desktop width */
659 out_uint16_le(s, 600); /* Desktop height */
660 out_uint16(s, 0); /* Pad */
661 out_uint16(s, 1); /* Allow resize */
662 out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */
663 out_uint16(s, 0); /* Unknown */
664 out_uint16_le(s, 1); /* Unknown */
665 out_uint16(s, 0); /* Pad */
666}
667
668/* Output order capability set */
669static void
670rdp_out_order_caps(STREAM s)
671{
672 uint8 order_caps[32];
673
674 memset(order_caps, 0, 32);
675 order_caps[0] = 1; /* dest blt */
676 order_caps[1] = 1; /* pat blt */
677 order_caps[2] = 1; /* screen blt */
678 order_caps[3] = (g_bitmap_cache ? 1 : 0); /* memblt */
679 order_caps[4] = 0; /* triblt */
680 order_caps[8] = 1; /* line */
681 order_caps[9] = 1; /* line */
682 order_caps[10] = 1; /* rect */
683 order_caps[11] = (g_desktop_save ? 1 : 0); /* desksave */
684 order_caps[13] = 1; /* memblt */
685 order_caps[14] = 1; /* triblt */
686 order_caps[20] = (g_polygon_ellipse_orders ? 1 : 0); /* polygon */
687 order_caps[21] = (g_polygon_ellipse_orders ? 1 : 0); /* polygon2 */
688 order_caps[22] = 1; /* polyline */
689 order_caps[25] = (g_polygon_ellipse_orders ? 1 : 0); /* ellipse */
690 order_caps[26] = (g_polygon_ellipse_orders ? 1 : 0); /* ellipse2 */
691 order_caps[27] = 1; /* text2 */
692 out_uint16_le(s, RDP_CAPSET_ORDER);
693 out_uint16_le(s, RDP_CAPLEN_ORDER);
694
695 out_uint8s(s, 20); /* Terminal desc, pad */
696 out_uint16_le(s, 1); /* Cache X granularity */
697 out_uint16_le(s, 20); /* Cache Y granularity */
698 out_uint16(s, 0); /* Pad */
699 out_uint16_le(s, 1); /* Max order level */
700 out_uint16_le(s, 0x147); /* Number of fonts */
701 out_uint16_le(s, 0x2a); /* Capability flags */
702 out_uint8p(s, order_caps, 32); /* Orders supported */
703 out_uint16_le(s, 0x6a1); /* Text capability flags */
704 out_uint8s(s, 6); /* Pad */
705 out_uint32_le(s, g_desktop_save == False ? 0 : 0x38400); /* Desktop cache size */
706 out_uint32(s, 0); /* Unknown */
707 out_uint32_le(s, 0x4e4); /* Unknown */
708}
709
710/* Output bitmap cache capability set */
711static void
712rdp_out_bmpcache_caps(STREAM s)
713{
714 int Bpp;
715 out_uint16_le(s, RDP_CAPSET_BMPCACHE);
716 out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
717
718 Bpp = (g_server_depth + 7) / 8; /* bytes per pixel */
719 out_uint8s(s, 24); /* unused */
720 out_uint16_le(s, 0x258); /* entries */
721 out_uint16_le(s, 0x100 * Bpp); /* max cell size */
722 out_uint16_le(s, 0x12c); /* entries */
723 out_uint16_le(s, 0x400 * Bpp); /* max cell size */
724 out_uint16_le(s, 0x106); /* entries */
725 out_uint16_le(s, 0x1000 * Bpp); /* max cell size */
726}
727
728/* Output bitmap cache v2 capability set */
729static void
730rdp_out_bmpcache2_caps(STREAM s)
731{
732 out_uint16_le(s, RDP_CAPSET_BMPCACHE2);
733 out_uint16_le(s, RDP_CAPLEN_BMPCACHE2);
734
735 out_uint16_le(s, g_bitmap_cache_persist_enable ? 2 : 0); /* version */
736
737 out_uint16_be(s, 3); /* number of caches in this set */
738
739 /* max cell size for cache 0 is 16x16, 1 = 32x32, 2 = 64x64, etc */
740 out_uint32_le(s, BMPCACHE2_C0_CELLS);
741 out_uint32_le(s, BMPCACHE2_C1_CELLS);
742 if (pstcache_init(2))
743 {
744 out_uint32_le(s, BMPCACHE2_NUM_PSTCELLS | BMPCACHE2_FLAG_PERSIST);
745 }
746 else
747 {
748 out_uint32_le(s, BMPCACHE2_C2_CELLS);
749 }
750 out_uint8s(s, 20); /* other bitmap caches not used */
751}
752
753/* Output control capability set */
754static void
755rdp_out_control_caps(STREAM s)
756{
757 out_uint16_le(s, RDP_CAPSET_CONTROL);
758 out_uint16_le(s, RDP_CAPLEN_CONTROL);
759
760 out_uint16(s, 0); /* Control capabilities */
761 out_uint16(s, 0); /* Remote detach */
762 out_uint16_le(s, 2); /* Control interest */
763 out_uint16_le(s, 2); /* Detach interest */
764}
765
766/* Output activation capability set */
767static void
768rdp_out_activate_caps(STREAM s)
769{
770 out_uint16_le(s, RDP_CAPSET_ACTIVATE);
771 out_uint16_le(s, RDP_CAPLEN_ACTIVATE);
772
773 out_uint16(s, 0); /* Help key */
774 out_uint16(s, 0); /* Help index key */
775 out_uint16(s, 0); /* Extended help key */
776 out_uint16(s, 0); /* Window activate */
777}
778
779/* Output pointer capability set */
780static void
781rdp_out_pointer_caps(STREAM s)
782{
783 out_uint16_le(s, RDP_CAPSET_POINTER);
784 out_uint16_le(s, RDP_CAPLEN_POINTER);
785
786 out_uint16(s, 0); /* Colour pointer */
787 out_uint16_le(s, 20); /* Cache size */
788}
789
790/* Output share capability set */
791static void
792rdp_out_share_caps(STREAM s)
793{
794 out_uint16_le(s, RDP_CAPSET_SHARE);
795 out_uint16_le(s, RDP_CAPLEN_SHARE);
796
797 out_uint16(s, 0); /* userid */
798 out_uint16(s, 0); /* pad */
799}
800
801/* Output colour cache capability set */
802static void
803rdp_out_colcache_caps(STREAM s)
804{
805 out_uint16_le(s, RDP_CAPSET_COLCACHE);
806 out_uint16_le(s, RDP_CAPLEN_COLCACHE);
807
808 out_uint16_le(s, 6); /* cache size */
809 out_uint16(s, 0); /* pad */
810}
811
812static uint8 caps_0x0d[] = {
813 0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00,
814 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
815 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
816 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
817 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
818 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
819 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
820 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
821 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
822 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
823 0x00, 0x00, 0x00, 0x00
824};
825
826static uint8 caps_0x0c[] = { 0x01, 0x00, 0x00, 0x00 };
827
828static uint8 caps_0x0e[] = { 0x01, 0x00, 0x00, 0x00 };
829
830static uint8 caps_0x10[] = {
831 0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00,
832 0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00,
833 0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00,
834 0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00,
835 0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08,
836 0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00
837};
838
839/* Output unknown capability sets */
840static void
841rdp_out_unknown_caps(STREAM s, uint16 id, uint16 length, uint8 * caps)
842{
843 out_uint16_le(s, id);
844 out_uint16_le(s, length);
845
846 out_uint8p(s, caps, length - 4);
847}
848
849#define RDP5_FLAG 0x0030
850/* Send a confirm active PDU */
851static void
852rdp_send_confirm_active(void)
853{
854 STREAM s;
855 uint32 sec_flags = g_encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG;
856 uint16 caplen =
857 RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
858 RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
859 RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
860 RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE +
861 0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */ +
862 4 /* w2k fix, why? */ ;
863
864 s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
865
866 out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE));
867 out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10)); /* Version 1 */
868 out_uint16_le(s, (g_mcs_userid + 1001));
869
870 out_uint32_le(s, g_rdp_shareid);
871 out_uint16_le(s, 0x3ea); /* userid */
872 out_uint16_le(s, sizeof(RDP_SOURCE));
873 out_uint16_le(s, caplen);
874
875 out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));
876 out_uint16_le(s, 0xd); /* num_caps */
877 out_uint8s(s, 2); /* pad */
878
879 rdp_out_general_caps(s);
880 rdp_out_bitmap_caps(s);
881 rdp_out_order_caps(s);
882 g_use_rdp5 ? rdp_out_bmpcache2_caps(s) : rdp_out_bmpcache_caps(s);
883 rdp_out_colcache_caps(s);
884 rdp_out_activate_caps(s);
885 rdp_out_control_caps(s);
886 rdp_out_pointer_caps(s);
887 rdp_out_share_caps(s);
888
889 rdp_out_unknown_caps(s, 0x0d, 0x58, caps_0x0d); /* international? */
890 rdp_out_unknown_caps(s, 0x0c, 0x08, caps_0x0c);
891 rdp_out_unknown_caps(s, 0x0e, 0x08, caps_0x0e);
892 rdp_out_unknown_caps(s, 0x10, 0x34, caps_0x10); /* glyph cache? */
893
894 s_mark_end(s);
895 sec_send(s, sec_flags);
896}
897
898/* Process a general capability set */
899static void
900rdp_process_general_caps(STREAM s)
901{
902 uint16 pad2octetsB; /* rdp5 flags? */
903
904 in_uint8s(s, 10);
905 in_uint16_le(s, pad2octetsB);
906
907 if (!pad2octetsB)
908 g_use_rdp5 = False;
909}
910
911/* Process a bitmap capability set */
912static void
913rdp_process_bitmap_caps(STREAM s)
914{
915 uint16 width, height, depth;
916
917 in_uint16_le(s, depth);
918 in_uint8s(s, 6);
919
920 in_uint16_le(s, width);
921 in_uint16_le(s, height);
922
923 DEBUG(("setting desktop size and depth to: %dx%dx%d\n", width, height, depth));
924
925 /*
926 * The server may limit depth and change the size of the desktop (for
927 * example when shadowing another session).
928 */
929 if (g_server_depth != depth)
930 {
931 warning("Remote desktop does not support colour depth %d; falling back to %d\n",
932 g_server_depth, depth);
933 g_server_depth = depth;
934 }
935 if (g_width != width || g_height != height)
936 {
937 warning("Remote desktop changed from %dx%d to %dx%d.\n", g_width, g_height,
938 width, height);
939 g_width = width;
940 g_height = height;
941 ui_resize_window();
942 }
943}
944
945/* Process server capabilities */
946static void
947rdp_process_server_caps(STREAM s, uint16 length)
948{
949 int n;
950 uint8 *next, *start;
951 uint16 ncapsets, capset_type, capset_length;
952
953 start = s->p;
954
955 in_uint16_le(s, ncapsets);
956 in_uint8s(s, 2); /* pad */
957
958 for (n = 0; n < ncapsets; n++)
959 {
960 if (s->p > start + length)
961 return;
962
963 in_uint16_le(s, capset_type);
964 in_uint16_le(s, capset_length);
965
966 next = s->p + capset_length - 4;
967
968 switch (capset_type)
969 {
970 case RDP_CAPSET_GENERAL:
971 rdp_process_general_caps(s);
972 break;
973
974 case RDP_CAPSET_BITMAP:
975 rdp_process_bitmap_caps(s);
976 break;
977 }
978
979 s->p = next;
980 }
981}
982
983/* Respond to a demand active PDU */
984static void
985process_demand_active(STREAM s)
986{
987 uint8 type;
988 uint16 len_src_descriptor, len_combined_caps;
989
990 in_uint32_le(s, g_rdp_shareid);
991 in_uint16_le(s, len_src_descriptor);
992 in_uint16_le(s, len_combined_caps);
993 in_uint8s(s, len_src_descriptor);
994
995 DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
996 rdp_process_server_caps(s, len_combined_caps);
997
998 rdp_send_confirm_active();
999 rdp_send_synchronise();
1000 rdp_send_control(RDP_CTL_COOPERATE);
1001 rdp_send_control(RDP_CTL_REQUEST_CONTROL);
1002 rdp_recv(&type); /* RDP_PDU_SYNCHRONIZE */
1003 rdp_recv(&type); /* RDP_CTL_COOPERATE */
1004 rdp_recv(&type); /* RDP_CTL_GRANT_CONTROL */
1005 rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0,
1006 g_numlock_sync ? ui_get_numlock_state(read_keyboard_state()) : 0, 0);
1007
1008 if (g_use_rdp5)
1009 {
1010 rdp_enum_bmpcache2();
1011 rdp_send_fonts(3);
1012 }
1013 else
1014 {
1015 rdp_send_fonts(1);
1016 rdp_send_fonts(2);
1017 }
1018
1019 rdp_recv(&type); /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */
1020 reset_order_state();
1021}
1022
1023/* Process a colour pointer PDU */
1024void
1025process_colour_pointer_pdu(STREAM s)
1026{
1027 uint16 x, y, width, height, cache_idx, masklen, datalen;
1028 uint8 *mask, *data;
1029 RD_HCURSOR cursor;
1030
1031 in_uint16_le(s, cache_idx);
1032 in_uint16_le(s, x);
1033 in_uint16_le(s, y);
1034 in_uint16_le(s, width);
1035 in_uint16_le(s, height);
1036 in_uint16_le(s, masklen);
1037 in_uint16_le(s, datalen);
1038 in_uint8p(s, data, datalen);
1039 in_uint8p(s, mask, masklen);
1040 cursor = ui_create_cursor(x, y, width, height, mask, data);
1041 ui_set_cursor(cursor);
1042 cache_put_cursor(cache_idx, cursor);
1043}
1044
1045/* Process a cached pointer PDU */
1046void
1047process_cached_pointer_pdu(STREAM s)
1048{
1049 uint16 cache_idx;
1050
1051 in_uint16_le(s, cache_idx);
1052 ui_set_cursor(cache_get_cursor(cache_idx));
1053}
1054
1055/* Process a system pointer PDU */
1056void
1057process_system_pointer_pdu(STREAM s)
1058{
1059 uint16 system_pointer_type;
1060
1061 in_uint16_le(s, system_pointer_type);
1062 switch (system_pointer_type)
1063 {
1064 case RDP_NULL_POINTER:
1065 ui_set_null_cursor();
1066 break;
1067
1068 default:
1069 unimpl("System pointer message 0x%x\n", system_pointer_type);
1070 }
1071}
1072
1073/* Process a pointer PDU */
1074static void
1075process_pointer_pdu(STREAM s)
1076{
1077 uint16 message_type;
1078 uint16 x, y;
1079
1080 in_uint16_le(s, message_type);
1081 in_uint8s(s, 2); /* pad */
1082
1083 switch (message_type)
1084 {
1085 case RDP_POINTER_MOVE:
1086 in_uint16_le(s, x);
1087 in_uint16_le(s, y);
1088 if (s_check(s))
1089 ui_move_pointer(x, y);
1090 break;
1091
1092 case RDP_POINTER_COLOR:
1093 process_colour_pointer_pdu(s);
1094 break;
1095
1096 case RDP_POINTER_CACHED:
1097 process_cached_pointer_pdu(s);
1098 break;
1099
1100 case RDP_POINTER_SYSTEM:
1101 process_system_pointer_pdu(s);
1102 break;
1103
1104 default:
1105 unimpl("Pointer message 0x%x\n", message_type);
1106 }
1107}
1108
1109/* Process bitmap updates */
1110void
1111process_bitmap_updates(STREAM s)
1112{
1113 uint16 num_updates;
1114 uint16 left, top, right, bottom, width, height;
1115 uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
1116 uint8 *data, *bmpdata;
1117 int i;
1118
1119 in_uint16_le(s, num_updates);
1120
1121 for (i = 0; i < num_updates; i++)
1122 {
1123 in_uint16_le(s, left);
1124 in_uint16_le(s, top);
1125 in_uint16_le(s, right);
1126 in_uint16_le(s, bottom);
1127 in_uint16_le(s, width);
1128 in_uint16_le(s, height);
1129 in_uint16_le(s, bpp);
1130 Bpp = (bpp + 7) / 8;
1131 in_uint16_le(s, compress);
1132 in_uint16_le(s, bufsize);
1133
1134 cx = right - left + 1;
1135 cy = bottom - top + 1;
1136
1137 DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",
1138 left, top, right, bottom, width, height, Bpp, compress));
1139
1140 if (!compress)
1141 {
1142 int y;
1143 bmpdata = (uint8 *) xmalloc(width * height * Bpp);
1144 for (y = 0; y < height; y++)
1145 {
1146 in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
1147 width * Bpp);
1148 }
1149 ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
1150 xfree(bmpdata);
1151 continue;
1152 }
1153
1154
1155 if (compress & 0x400)
1156 {
1157 size = bufsize;
1158 }
1159 else
1160 {
1161 in_uint8s(s, 2); /* pad */
1162 in_uint16_le(s, size);
1163 in_uint8s(s, 4); /* line_size, final_size */
1164 }
1165 in_uint8p(s, data, size);
1166 bmpdata = (uint8 *) xmalloc(width * height * Bpp);
1167 if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
1168 {
1169 ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
1170 }
1171 else
1172 {
1173 DEBUG_RDP5(("Failed to decompress data\n"));
1174 }
1175
1176 xfree(bmpdata);
1177 }
1178}
1179
1180/* Process a palette update */
1181void
1182process_palette(STREAM s)
1183{
1184 COLOURENTRY *entry;
1185 COLOURMAP map;
1186 RD_HCOLOURMAP hmap;
1187 int i;
1188
1189 in_uint8s(s, 2); /* pad */
1190 in_uint16_le(s, map.ncolours);
1191 in_uint8s(s, 2); /* pad */
1192
1193 map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
1194
1195 DEBUG(("PALETTE(c=%d)\n", map.ncolours));
1196
1197 for (i = 0; i < map.ncolours; i++)
1198 {
1199 entry = &map.colours[i];
1200 in_uint8(s, entry->red);
1201 in_uint8(s, entry->green);
1202 in_uint8(s, entry->blue);
1203 }
1204
1205 hmap = ui_create_colourmap(&map);
1206 ui_set_colourmap(hmap);
1207
1208 xfree(map.colours);
1209}
1210
1211/* Process an update PDU */
1212static void
1213process_update_pdu(STREAM s)
1214{
1215 uint16 update_type, count;
1216
1217 in_uint16_le(s, update_type);
1218
1219 ui_begin_update();
1220 switch (update_type)
1221 {
1222 case RDP_UPDATE_ORDERS:
1223 in_uint8s(s, 2); /* pad */
1224 in_uint16_le(s, count);
1225 in_uint8s(s, 2); /* pad */
1226 process_orders(s, count);
1227 break;
1228
1229 case RDP_UPDATE_BITMAP:
1230 process_bitmap_updates(s);
1231 break;
1232
1233 case RDP_UPDATE_PALETTE:
1234 process_palette(s);
1235 break;
1236
1237 case RDP_UPDATE_SYNCHRONIZE:
1238 break;
1239
1240 default:
1241 unimpl("update %d\n", update_type);
1242 }
1243 ui_end_update();
1244}
1245
1246/* Process a disconnect PDU */
1247void
1248process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason)
1249{
1250 in_uint32_le(s, *ext_disc_reason);
1251
1252 DEBUG(("Received disconnect PDU\n"));
1253}
1254
1255/* Process data PDU */
1256static RD_BOOL
1257process_data_pdu(STREAM s, uint32 * ext_disc_reason)
1258{
1259 uint8 data_pdu_type;
1260 uint8 ctype;
1261 uint16 clen;
1262 uint32 len;
1263
1264 uint32 roff, rlen;
1265
1266 struct stream *ns = &(g_mppc_dict.ns);
1267
1268 in_uint8s(s, 6); /* shareid, pad, streamid */
1269 in_uint16_le(s, len);
1270 in_uint8(s, data_pdu_type);
1271 in_uint8(s, ctype);
1272 in_uint16_le(s, clen);
1273 clen -= 18;
1274
1275 if (ctype & RDP_MPPC_COMPRESSED)
1276 {
1277 if (len > RDP_MPPC_DICT_SIZE)
1278 error("error decompressed packet size exceeds max\n");
1279 if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)
1280 error("error while decompressing packet\n");
1281
1282 /* len -= 18; */
1283
1284 /* allocate memory and copy the uncompressed data into the temporary stream */
1285 ns->data = (uint8 *) xrealloc(ns->data, rlen);
1286
1287 memcpy((ns->data), (unsigned char *) (g_mppc_dict.hist + roff), rlen);
1288
1289 ns->size = rlen;
1290 ns->end = (ns->data + ns->size);
1291 ns->p = ns->data;
1292 ns->rdp_hdr = ns->p;
1293
1294 s = ns;
1295 }
1296
1297 switch (data_pdu_type)
1298 {
1299 case RDP_DATA_PDU_UPDATE:
1300 process_update_pdu(s);
1301 break;
1302
1303 case RDP_DATA_PDU_CONTROL:
1304 DEBUG(("Received Control PDU\n"));
1305 break;
1306
1307 case RDP_DATA_PDU_SYNCHRONISE:
1308 DEBUG(("Received Sync PDU\n"));
1309 break;
1310
1311 case RDP_DATA_PDU_POINTER:
1312 process_pointer_pdu(s);
1313 break;
1314
1315 case RDP_DATA_PDU_BELL:
1316 ui_bell();
1317 break;
1318
1319 case RDP_DATA_PDU_LOGON:
1320 DEBUG(("Received Logon PDU\n"));
1321 /* User logged on */
1322 break;
1323
1324 case RDP_DATA_PDU_DISCONNECT:
1325 process_disconnect_pdu(s, ext_disc_reason);
1326
1327 /* We used to return true and disconnect immediately here, but
1328 * Windows Vista sends a disconnect PDU with reason 0 when
1329 * reconnecting to a disconnected session, and MSTSC doesn't
1330 * drop the connection. I think we should just save the status.
1331 */
1332 break;
1333
1334 default:
1335 unimpl("data PDU %d\n", data_pdu_type);
1336 }
1337 return False;
1338}
1339
1340/* Process redirect PDU from Session Directory */
1341static RD_BOOL
1342process_redirect_pdu(STREAM s /*, uint32 * ext_disc_reason */ )
1343{
1344 uint32 len;
1345
1346 /* these 2 bytes are unknown, seem to be zeros */
1347 in_uint8s(s, 2);
1348
1349 /* read connection flags */
1350 in_uint32_le(s, g_redirect_flags);
1351
1352 /* read length of ip string */
1353 in_uint32_le(s, len);
1354
1355 /* read ip string */
1356 rdp_in_unistr(s, g_redirect_server, sizeof(g_redirect_server), len);
1357
1358 /* read length of cookie string */
1359 in_uint32_le(s, len);
1360
1361 /* read cookie string (plain ASCII) */
1362 if (len > sizeof(g_redirect_cookie) - 1)
1363 {
1364 uint32 rem = len - (sizeof(g_redirect_cookie) - 1);
1365 len = sizeof(g_redirect_cookie) - 1;
1366
1367 warning("Unexpectedly large redirection cookie\n");
1368 in_uint8a(s, g_redirect_cookie, len);
1369 in_uint8s(s, rem);
1370 }
1371 else
1372 {
1373 in_uint8a(s, g_redirect_cookie, len);
1374 }
1375 g_redirect_cookie[len] = 0;
1376
1377 /* read length of username string */
1378 in_uint32_le(s, len);
1379
1380 /* read username string */
1381 rdp_in_unistr(s, g_redirect_username, sizeof(g_redirect_username), len);
1382
1383 /* read length of domain string */
1384 in_uint32_le(s, len);
1385
1386 /* read domain string */
1387 rdp_in_unistr(s, g_redirect_domain, sizeof(g_redirect_domain), len);
1388
1389 /* read length of password string */
1390 in_uint32_le(s, len);
1391
1392 /* read password string */
1393 rdp_in_unistr(s, g_redirect_password, sizeof(g_redirect_password), len);
1394
1395 g_redirect = True;
1396
1397 return True;
1398}
1399
1400/* Process incoming packets */
1401/* nevers gets out of here till app is done */
1402void
1403rdp_main_loop(RD_BOOL * deactivated, uint32 * ext_disc_reason)
1404{
1405 while (rdp_loop(deactivated, ext_disc_reason))
1406 ;
1407}
1408
1409/* used in uiports and rdp_main_loop, processes the rdp packets waiting */
1410RD_BOOL
1411rdp_loop(RD_BOOL * deactivated, uint32 * ext_disc_reason)
1412{
1413 uint8 type;
1414 RD_BOOL disc = False; /* True when a disconnect PDU was received */
1415 RD_BOOL cont = True;
1416 STREAM s;
1417
1418 while (cont)
1419 {
1420 s = rdp_recv(&type);
1421 if (s == NULL)
1422 return False;
1423 switch (type)
1424 {
1425 case RDP_PDU_DEMAND_ACTIVE:
1426 process_demand_active(s);
1427 *deactivated = False;
1428 break;
1429 case RDP_PDU_DEACTIVATE:
1430 DEBUG(("RDP_PDU_DEACTIVATE\n"));
1431 *deactivated = True;
1432 break;
1433 case RDP_PDU_REDIRECT:
1434 return process_redirect_pdu(s);
1435 break;
1436 case RDP_PDU_DATA:
1437 disc = process_data_pdu(s, ext_disc_reason);
1438 break;
1439 case 0:
1440 break;
1441 default:
1442 unimpl("PDU %d\n", type);
1443 }
1444 if (disc)
1445 return False;
1446 cont = g_next_packet < s->end;
1447 }
1448 return True;
1449}
1450
1451/* Establish a connection up to the RDP layer */
1452RD_BOOL
1453rdp_connect(char *server, uint32 flags, char *domain, char *password,
1454 char *command, char *directory)
1455{
1456 if (!sec_connect(server, g_username))
1457 return False;
1458
1459 rdp_send_logon_info(flags, domain, g_username, password, command, directory);
1460 return True;
1461}
1462
1463/* Establish a reconnection up to the RDP layer */
1464RD_BOOL
1465rdp_reconnect(char *server, uint32 flags, char *domain, char *password,
1466 char *command, char *directory, char *cookie)
1467{
1468 if (!sec_reconnect(server))
1469 return False;
1470
1471 rdp_send_logon_info(flags, domain, g_username, password, command, directory);
1472 return True;
1473}
1474
1475/* Called during redirection to reset the state to support redirection */
1476void
1477rdp_reset_state(void)
1478{
1479 g_next_packet = NULL; /* reset the packet information */
1480 g_rdp_shareid = 0;
1481 sec_reset_state();
1482}
1483
1484/* Disconnect from the RDP layer */
1485void
1486rdp_disconnect(void)
1487{
1488 sec_disconnect();
1489}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette