/[rdesktop]/sourceforge.net/trunk/rdesktop/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 /sourceforge.net/trunk/rdesktop/rdp.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1474 - (hide annotations)
Fri Jul 11 03:35:24 2008 UTC (15 years, 10 months ago) by jsorg71
File MIME type: text/plain
File size: 34796 byte(s)
added brush cache

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

  ViewVC Help
Powered by ViewVC 1.1.26