/[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 1042 - (hide annotations)
Tue Jan 24 12:40:24 2006 UTC (18 years, 3 months ago) by astrand
File MIME type: text/plain
File size: 33346 byte(s)
Applied patch #1390148 from Ilya Konstantinov: Refactoring of color depth code.

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

  ViewVC Help
Powered by ViewVC 1.1.26