/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1429 - (hide annotations)
Thu Jan 24 08:06:02 2008 UTC (16 years, 4 months ago) by astrand
Original Path: sourceforge.net/trunk/rdesktop/rdp.c
File MIME type: text/plain
File size: 34529 byte(s)
Indent fixes

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

  ViewVC Help
Powered by ViewVC 1.1.26