/[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 1364 - (hide annotations)
Thu Jan 4 04:55:56 2007 UTC (17 years, 4 months ago) by jsorg71
File MIME type: text/plain
File size: 33682 byte(s)
RD_ prefix and win32 compatibility for core files

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

  ViewVC Help
Powered by ViewVC 1.1.26