VirtualBox

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

最後變更 在這個檔案從9902是 9902,由 vboxsync 提交於 16 年 前

Added rdesktop 1.6.0.

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

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