VirtualBox

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

最後變更 在這個檔案從8497是 7826,由 vboxsync 提交於 17 年 前

Export modified rdesktop version including USB support to OSE. It's GPL anyway.

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

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