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