/[rdesktop]/jpeg/rdesktop/trunk/rdp.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /jpeg/rdesktop/trunk/rdp.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1483 - (show annotations)
Sat Nov 1 02:37:10 2008 UTC (15 years, 7 months ago) by jsorg71
Original Path: sourceforge.net/trunk/rdesktop/rdp.c
File MIME type: text/plain
File size: 34842 byte(s)
brush cache for > 2 color brushes

1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Protocol services - RDP layer
4 Copyright (C) Matthew Chapman 1999-2008
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
38 extern uint16 g_mcs_userid;
39 extern char *g_username;
40 extern char g_codepage[16];
41 extern RD_BOOL g_bitmap_compression;
42 extern RD_BOOL g_orders;
43 extern RD_BOOL g_encryption;
44 extern RD_BOOL g_desktop_save;
45 extern RD_BOOL g_polygon_ellipse_orders;
46 extern RD_BOOL g_use_rdp5;
47 extern uint16 g_server_rdp_version;
48 extern uint32 g_rdp5_performanceflags;
49 extern int g_server_depth;
50 extern int g_width;
51 extern int g_height;
52 extern RD_BOOL g_bitmap_cache;
53 extern RD_BOOL g_bitmap_cache_persist_enable;
54 extern RD_BOOL g_numlock_sync;
55
56 uint8 *g_next_packet;
57 uint32 g_rdp_shareid;
58
59 extern RDPCOMP g_mppc_dict;
60
61 /* Session Directory support */
62 extern RD_BOOL g_redirect;
63 extern char g_redirect_server[64];
64 extern char g_redirect_domain[16];
65 extern char g_redirect_password[64];
66 extern char *g_redirect_username;
67 extern char g_redirect_cookie[128];
68 extern uint32 g_redirect_flags;
69 /* END Session Directory support */
70
71 #if WITH_DEBUG
72 static uint32 g_packetno;
73 #endif
74
75 #ifdef HAVE_ICONV
76 static RD_BOOL g_iconv_works = True;
77 #endif
78
79 /* Receive an RDP packet */
80 static STREAM
81 rdp_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 */
135 static STREAM
136 rdp_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 */
147 static void
148 rdp_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 */
171 void
172 rdp_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 */
245 int
246 rdp_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 */
318 static void
319 rdp_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 */
469 static void
470 rdp_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 */
485 static void
486 rdp_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 */
500 void
501 rdp_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 */
521 void
522 rdp_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 */
552 static void
553 rdp_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 */
596 static void
597 rdp_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 */
613 static void
614 rdp_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 */
639 static void
640 rdp_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 */
660 static void
661 rdp_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 */
702 static void
703 rdp_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 */
720 static void
721 rdp_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 */
745 static void
746 rdp_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 */
758 static void
759 rdp_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 */
771 static void
772 rdp_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 */
782 static void
783 rdp_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 */
793 static void
794 rdp_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
803 /* Output brush cache capability set */
804 static void
805 rdp_out_brushcache_caps(STREAM s)
806 {
807 out_uint16_le(s, RDP_CAPSET_BRUSHCACHE);
808 out_uint16_le(s, RDP_CAPLEN_BRUSHCACHE);
809 out_uint32_le(s, 1); /* cache type */
810 }
811
812 static 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
826 static uint8 caps_0x0c[] = { 0x01, 0x00, 0x00, 0x00 };
827
828 static uint8 caps_0x0e[] = { 0x01, 0x00, 0x00, 0x00 };
829
830 static 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 */
840 static void
841 rdp_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 */
851 static void
852 rdp_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 RDP_CAPLEN_BRUSHCACHE +
862 0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */ +
863 4 /* w2k fix, why? */ ;
864
865 s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
866
867 out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE));
868 out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10)); /* Version 1 */
869 out_uint16_le(s, (g_mcs_userid + 1001));
870
871 out_uint32_le(s, g_rdp_shareid);
872 out_uint16_le(s, 0x3ea); /* userid */
873 out_uint16_le(s, sizeof(RDP_SOURCE));
874 out_uint16_le(s, caplen);
875
876 out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));
877 out_uint16_le(s, 0xd); /* num_caps */
878 out_uint8s(s, 2); /* pad */
879
880 rdp_out_general_caps(s);
881 rdp_out_bitmap_caps(s);
882 rdp_out_order_caps(s);
883 g_use_rdp5 ? rdp_out_bmpcache2_caps(s) : rdp_out_bmpcache_caps(s);
884 rdp_out_colcache_caps(s);
885 rdp_out_activate_caps(s);
886 rdp_out_control_caps(s);
887 rdp_out_pointer_caps(s);
888 rdp_out_share_caps(s);
889 rdp_out_brushcache_caps(s);
890
891 rdp_out_unknown_caps(s, 0x0d, 0x58, caps_0x0d); /* international? */
892 rdp_out_unknown_caps(s, 0x0c, 0x08, caps_0x0c);
893 rdp_out_unknown_caps(s, 0x0e, 0x08, caps_0x0e);
894 rdp_out_unknown_caps(s, 0x10, 0x34, caps_0x10); /* glyph cache? */
895
896 s_mark_end(s);
897 sec_send(s, sec_flags);
898 }
899
900 /* Process a general capability set */
901 static void
902 rdp_process_general_caps(STREAM s)
903 {
904 uint16 pad2octetsB; /* rdp5 flags? */
905
906 in_uint8s(s, 10);
907 in_uint16_le(s, pad2octetsB);
908
909 if (!pad2octetsB)
910 g_use_rdp5 = False;
911 }
912
913 /* Process a bitmap capability set */
914 static void
915 rdp_process_bitmap_caps(STREAM s)
916 {
917 uint16 width, height, depth;
918
919 in_uint16_le(s, depth);
920 in_uint8s(s, 6);
921
922 in_uint16_le(s, width);
923 in_uint16_le(s, height);
924
925 DEBUG(("setting desktop size and depth to: %dx%dx%d\n", width, height, depth));
926
927 /*
928 * The server may limit depth and change the size of the desktop (for
929 * example when shadowing another session).
930 */
931 if (g_server_depth != depth)
932 {
933 warning("Remote desktop does not support colour depth %d; falling back to %d\n",
934 g_server_depth, depth);
935 g_server_depth = depth;
936 }
937 if (g_width != width || g_height != height)
938 {
939 warning("Remote desktop changed from %dx%d to %dx%d.\n", g_width, g_height,
940 width, height);
941 g_width = width;
942 g_height = height;
943 ui_resize_window();
944 }
945 }
946
947 /* Process server capabilities */
948 static void
949 rdp_process_server_caps(STREAM s, uint16 length)
950 {
951 int n;
952 uint8 *next, *start;
953 uint16 ncapsets, capset_type, capset_length;
954
955 start = s->p;
956
957 in_uint16_le(s, ncapsets);
958 in_uint8s(s, 2); /* pad */
959
960 for (n = 0; n < ncapsets; n++)
961 {
962 if (s->p > start + length)
963 return;
964
965 in_uint16_le(s, capset_type);
966 in_uint16_le(s, capset_length);
967
968 next = s->p + capset_length - 4;
969
970 switch (capset_type)
971 {
972 case RDP_CAPSET_GENERAL:
973 rdp_process_general_caps(s);
974 break;
975
976 case RDP_CAPSET_BITMAP:
977 rdp_process_bitmap_caps(s);
978 break;
979 }
980
981 s->p = next;
982 }
983 }
984
985 /* Respond to a demand active PDU */
986 static void
987 process_demand_active(STREAM s)
988 {
989 uint8 type;
990 uint16 len_src_descriptor, len_combined_caps;
991
992 in_uint32_le(s, g_rdp_shareid);
993 in_uint16_le(s, len_src_descriptor);
994 in_uint16_le(s, len_combined_caps);
995 in_uint8s(s, len_src_descriptor);
996
997 DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
998 rdp_process_server_caps(s, len_combined_caps);
999
1000 rdp_send_confirm_active();
1001 rdp_send_synchronise();
1002 rdp_send_control(RDP_CTL_COOPERATE);
1003 rdp_send_control(RDP_CTL_REQUEST_CONTROL);
1004 rdp_recv(&type); /* RDP_PDU_SYNCHRONIZE */
1005 rdp_recv(&type); /* RDP_CTL_COOPERATE */
1006 rdp_recv(&type); /* RDP_CTL_GRANT_CONTROL */
1007 rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0,
1008 g_numlock_sync ? ui_get_numlock_state(read_keyboard_state()) : 0, 0);
1009
1010 if (g_use_rdp5)
1011 {
1012 rdp_enum_bmpcache2();
1013 rdp_send_fonts(3);
1014 }
1015 else
1016 {
1017 rdp_send_fonts(1);
1018 rdp_send_fonts(2);
1019 }
1020
1021 rdp_recv(&type); /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */
1022 reset_order_state();
1023 }
1024
1025 /* Process a colour pointer PDU */
1026 void
1027 process_colour_pointer_pdu(STREAM s)
1028 {
1029 uint16 x, y, width, height, cache_idx, masklen, datalen;
1030 uint8 *mask, *data;
1031 RD_HCURSOR cursor;
1032
1033 in_uint16_le(s, cache_idx);
1034 in_uint16_le(s, x);
1035 in_uint16_le(s, y);
1036 in_uint16_le(s, width);
1037 in_uint16_le(s, height);
1038 in_uint16_le(s, masklen);
1039 in_uint16_le(s, datalen);
1040 in_uint8p(s, data, datalen);
1041 in_uint8p(s, mask, masklen);
1042 cursor = ui_create_cursor(x, y, width, height, mask, data);
1043 ui_set_cursor(cursor);
1044 cache_put_cursor(cache_idx, cursor);
1045 }
1046
1047 /* Process a cached pointer PDU */
1048 void
1049 process_cached_pointer_pdu(STREAM s)
1050 {
1051 uint16 cache_idx;
1052
1053 in_uint16_le(s, cache_idx);
1054 ui_set_cursor(cache_get_cursor(cache_idx));
1055 }
1056
1057 /* Process a system pointer PDU */
1058 void
1059 process_system_pointer_pdu(STREAM s)
1060 {
1061 uint16 system_pointer_type;
1062
1063 in_uint16_le(s, system_pointer_type);
1064 switch (system_pointer_type)
1065 {
1066 case RDP_NULL_POINTER:
1067 ui_set_null_cursor();
1068 break;
1069
1070 default:
1071 unimpl("System pointer message 0x%x\n", system_pointer_type);
1072 }
1073 }
1074
1075 /* Process a pointer PDU */
1076 static void
1077 process_pointer_pdu(STREAM s)
1078 {
1079 uint16 message_type;
1080 uint16 x, y;
1081
1082 in_uint16_le(s, message_type);
1083 in_uint8s(s, 2); /* pad */
1084
1085 switch (message_type)
1086 {
1087 case RDP_POINTER_MOVE:
1088 in_uint16_le(s, x);
1089 in_uint16_le(s, y);
1090 if (s_check(s))
1091 ui_move_pointer(x, y);
1092 break;
1093
1094 case RDP_POINTER_COLOR:
1095 process_colour_pointer_pdu(s);
1096 break;
1097
1098 case RDP_POINTER_CACHED:
1099 process_cached_pointer_pdu(s);
1100 break;
1101
1102 case RDP_POINTER_SYSTEM:
1103 process_system_pointer_pdu(s);
1104 break;
1105
1106 default:
1107 unimpl("Pointer message 0x%x\n", message_type);
1108 }
1109 }
1110
1111 /* Process bitmap updates */
1112 void
1113 process_bitmap_updates(STREAM s)
1114 {
1115 uint16 num_updates;
1116 uint16 left, top, right, bottom, width, height;
1117 uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
1118 uint8 *data, *bmpdata;
1119 int i;
1120
1121 in_uint16_le(s, num_updates);
1122
1123 for (i = 0; i < num_updates; i++)
1124 {
1125 in_uint16_le(s, left);
1126 in_uint16_le(s, top);
1127 in_uint16_le(s, right);
1128 in_uint16_le(s, bottom);
1129 in_uint16_le(s, width);
1130 in_uint16_le(s, height);
1131 in_uint16_le(s, bpp);
1132 Bpp = (bpp + 7) / 8;
1133 in_uint16_le(s, compress);
1134 in_uint16_le(s, bufsize);
1135
1136 cx = right - left + 1;
1137 cy = bottom - top + 1;
1138
1139 DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",
1140 left, top, right, bottom, width, height, Bpp, compress));
1141
1142 if (!compress)
1143 {
1144 int y;
1145 bmpdata = (uint8 *) xmalloc(width * height * Bpp);
1146 for (y = 0; y < height; y++)
1147 {
1148 in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
1149 width * Bpp);
1150 }
1151 ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
1152 xfree(bmpdata);
1153 continue;
1154 }
1155
1156
1157 if (compress & 0x400)
1158 {
1159 size = bufsize;
1160 }
1161 else
1162 {
1163 in_uint8s(s, 2); /* pad */
1164 in_uint16_le(s, size);
1165 in_uint8s(s, 4); /* line_size, final_size */
1166 }
1167 in_uint8p(s, data, size);
1168 bmpdata = (uint8 *) xmalloc(width * height * Bpp);
1169 if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
1170 {
1171 ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
1172 }
1173 else
1174 {
1175 DEBUG_RDP5(("Failed to decompress data\n"));
1176 }
1177
1178 xfree(bmpdata);
1179 }
1180 }
1181
1182 /* Process a palette update */
1183 void
1184 process_palette(STREAM s)
1185 {
1186 COLOURENTRY *entry;
1187 COLOURMAP map;
1188 RD_HCOLOURMAP hmap;
1189 int i;
1190
1191 in_uint8s(s, 2); /* pad */
1192 in_uint16_le(s, map.ncolours);
1193 in_uint8s(s, 2); /* pad */
1194
1195 map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
1196
1197 DEBUG(("PALETTE(c=%d)\n", map.ncolours));
1198
1199 for (i = 0; i < map.ncolours; i++)
1200 {
1201 entry = &map.colours[i];
1202 in_uint8(s, entry->red);
1203 in_uint8(s, entry->green);
1204 in_uint8(s, entry->blue);
1205 }
1206
1207 hmap = ui_create_colourmap(&map);
1208 ui_set_colourmap(hmap);
1209
1210 xfree(map.colours);
1211 }
1212
1213 /* Process an update PDU */
1214 static void
1215 process_update_pdu(STREAM s)
1216 {
1217 uint16 update_type, count;
1218
1219 in_uint16_le(s, update_type);
1220
1221 ui_begin_update();
1222 switch (update_type)
1223 {
1224 case RDP_UPDATE_ORDERS:
1225 in_uint8s(s, 2); /* pad */
1226 in_uint16_le(s, count);
1227 in_uint8s(s, 2); /* pad */
1228 process_orders(s, count);
1229 break;
1230
1231 case RDP_UPDATE_BITMAP:
1232 process_bitmap_updates(s);
1233 break;
1234
1235 case RDP_UPDATE_PALETTE:
1236 process_palette(s);
1237 break;
1238
1239 case RDP_UPDATE_SYNCHRONIZE:
1240 break;
1241
1242 default:
1243 unimpl("update %d\n", update_type);
1244 }
1245 ui_end_update();
1246 }
1247
1248 /* Process a disconnect PDU */
1249 void
1250 process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason)
1251 {
1252 in_uint32_le(s, *ext_disc_reason);
1253
1254 DEBUG(("Received disconnect PDU\n"));
1255 }
1256
1257 /* Process data PDU */
1258 static RD_BOOL
1259 process_data_pdu(STREAM s, uint32 * ext_disc_reason)
1260 {
1261 uint8 data_pdu_type;
1262 uint8 ctype;
1263 uint16 clen;
1264 uint32 len;
1265
1266 uint32 roff, rlen;
1267
1268 struct stream *ns = &(g_mppc_dict.ns);
1269
1270 in_uint8s(s, 6); /* shareid, pad, streamid */
1271 in_uint16_le(s, len);
1272 in_uint8(s, data_pdu_type);
1273 in_uint8(s, ctype);
1274 in_uint16_le(s, clen);
1275 clen -= 18;
1276
1277 if (ctype & RDP_MPPC_COMPRESSED)
1278 {
1279 if (len > RDP_MPPC_DICT_SIZE)
1280 error("error decompressed packet size exceeds max\n");
1281 if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)
1282 error("error while decompressing packet\n");
1283
1284 /* len -= 18; */
1285
1286 /* allocate memory and copy the uncompressed data into the temporary stream */
1287 ns->data = (uint8 *) xrealloc(ns->data, rlen);
1288
1289 memcpy((ns->data), (unsigned char *) (g_mppc_dict.hist + roff), rlen);
1290
1291 ns->size = rlen;
1292 ns->end = (ns->data + ns->size);
1293 ns->p = ns->data;
1294 ns->rdp_hdr = ns->p;
1295
1296 s = ns;
1297 }
1298
1299 switch (data_pdu_type)
1300 {
1301 case RDP_DATA_PDU_UPDATE:
1302 process_update_pdu(s);
1303 break;
1304
1305 case RDP_DATA_PDU_CONTROL:
1306 DEBUG(("Received Control PDU\n"));
1307 break;
1308
1309 case RDP_DATA_PDU_SYNCHRONISE:
1310 DEBUG(("Received Sync PDU\n"));
1311 break;
1312
1313 case RDP_DATA_PDU_POINTER:
1314 process_pointer_pdu(s);
1315 break;
1316
1317 case RDP_DATA_PDU_BELL:
1318 ui_bell();
1319 break;
1320
1321 case RDP_DATA_PDU_LOGON:
1322 DEBUG(("Received Logon PDU\n"));
1323 /* User logged on */
1324 break;
1325
1326 case RDP_DATA_PDU_DISCONNECT:
1327 process_disconnect_pdu(s, ext_disc_reason);
1328
1329 /* We used to return true and disconnect immediately here, but
1330 * Windows Vista sends a disconnect PDU with reason 0 when
1331 * reconnecting to a disconnected session, and MSTSC doesn't
1332 * drop the connection. I think we should just save the status.
1333 */
1334 break;
1335
1336 default:
1337 unimpl("data PDU %d\n", data_pdu_type);
1338 }
1339 return False;
1340 }
1341
1342 /* Process redirect PDU from Session Directory */
1343 static RD_BOOL
1344 process_redirect_pdu(STREAM s /*, uint32 * ext_disc_reason */ )
1345 {
1346 uint32 len;
1347
1348 /* these 2 bytes are unknown, seem to be zeros */
1349 in_uint8s(s, 2);
1350
1351 /* read connection flags */
1352 in_uint32_le(s, g_redirect_flags);
1353
1354 /* read length of ip string */
1355 in_uint32_le(s, len);
1356
1357 /* read ip string */
1358 rdp_in_unistr(s, g_redirect_server, sizeof(g_redirect_server), len);
1359
1360 /* read length of cookie string */
1361 in_uint32_le(s, len);
1362
1363 /* read cookie string (plain ASCII) */
1364 if (len > sizeof(g_redirect_cookie) - 1)
1365 {
1366 uint32 rem = len - (sizeof(g_redirect_cookie) - 1);
1367 len = sizeof(g_redirect_cookie) - 1;
1368
1369 warning("Unexpectedly large redirection cookie\n");
1370 in_uint8a(s, g_redirect_cookie, len);
1371 in_uint8s(s, rem);
1372 }
1373 else
1374 {
1375 in_uint8a(s, g_redirect_cookie, len);
1376 }
1377 g_redirect_cookie[len] = 0;
1378
1379 /* read length of username string */
1380 in_uint32_le(s, len);
1381
1382 /* read username string */
1383 g_redirect_username = (char *) xmalloc(len + 1);
1384 rdp_in_unistr(s, g_redirect_username, strlen(g_redirect_username), len);
1385
1386 /* read length of domain string */
1387 in_uint32_le(s, len);
1388
1389 /* read domain string */
1390 rdp_in_unistr(s, g_redirect_domain, sizeof(g_redirect_domain), len);
1391
1392 /* read length of password string */
1393 in_uint32_le(s, len);
1394
1395 /* read password string */
1396 rdp_in_unistr(s, g_redirect_password, sizeof(g_redirect_password), len);
1397
1398 g_redirect = True;
1399
1400 return True;
1401 }
1402
1403 /* Process incoming packets */
1404 /* nevers gets out of here till app is done */
1405 void
1406 rdp_main_loop(RD_BOOL * deactivated, uint32 * ext_disc_reason)
1407 {
1408 while (rdp_loop(deactivated, ext_disc_reason))
1409 ;
1410 }
1411
1412 /* used in uiports and rdp_main_loop, processes the rdp packets waiting */
1413 RD_BOOL
1414 rdp_loop(RD_BOOL * deactivated, uint32 * ext_disc_reason)
1415 {
1416 uint8 type;
1417 RD_BOOL disc = False; /* True when a disconnect PDU was received */
1418 RD_BOOL cont = True;
1419 STREAM s;
1420
1421 while (cont)
1422 {
1423 s = rdp_recv(&type);
1424 if (s == NULL)
1425 return False;
1426 switch (type)
1427 {
1428 case RDP_PDU_DEMAND_ACTIVE:
1429 process_demand_active(s);
1430 *deactivated = False;
1431 break;
1432 case RDP_PDU_DEACTIVATE:
1433 DEBUG(("RDP_PDU_DEACTIVATE\n"));
1434 *deactivated = True;
1435 break;
1436 case RDP_PDU_REDIRECT:
1437 return process_redirect_pdu(s);
1438 break;
1439 case RDP_PDU_DATA:
1440 disc = process_data_pdu(s, ext_disc_reason);
1441 break;
1442 case 0:
1443 break;
1444 default:
1445 unimpl("PDU %d\n", type);
1446 }
1447 if (disc)
1448 return False;
1449 cont = g_next_packet < s->end;
1450 }
1451 return True;
1452 }
1453
1454 /* Establish a connection up to the RDP layer */
1455 RD_BOOL
1456 rdp_connect(char *server, uint32 flags, char *domain, char *password,
1457 char *command, char *directory)
1458 {
1459 if (!sec_connect(server, g_username))
1460 return False;
1461
1462 rdp_send_logon_info(flags, domain, g_username, password, command, directory);
1463 return True;
1464 }
1465
1466 /* Establish a reconnection up to the RDP layer */
1467 RD_BOOL
1468 rdp_reconnect(char *server, uint32 flags, char *domain, char *password,
1469 char *command, char *directory, char *cookie)
1470 {
1471 if (!sec_reconnect(server))
1472 return False;
1473
1474 rdp_send_logon_info(flags, domain, g_username, password, command, directory);
1475 return True;
1476 }
1477
1478 /* Called during redirection to reset the state to support redirection */
1479 void
1480 rdp_reset_state(void)
1481 {
1482 g_next_packet = NULL; /* reset the packet information */
1483 g_rdp_shareid = 0;
1484 sec_reset_state();
1485 }
1486
1487 /* Disconnect from the RDP layer */
1488 void
1489 rdp_disconnect(void)
1490 {
1491 sec_disconnect();
1492 }

  ViewVC Help
Powered by ViewVC 1.1.26