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

Contents of /sourceforge.net/trunk/rdesktop/rdp.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 604 - (show annotations)
Sat Feb 14 19:30:01 2004 UTC (20 years, 3 months ago) by stargo
File MIME type: text/plain
File size: 22847 byte(s)
Timezone patch from Mark Roach/Stephen Sprunk

1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Protocol services - RDP layer
4 Copyright (C) Matthew Chapman 1999-2002
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
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 #include <time.h>
22 #include "rdesktop.h"
23
24 extern uint16 g_mcs_userid;
25 extern char g_username[16];
26 extern BOOL g_bitmap_compression;
27 extern BOOL g_orders;
28 extern BOOL g_encryption;
29 extern BOOL g_desktop_save;
30 extern BOOL g_use_rdp5;
31 extern uint16 g_server_rdp_version;
32 extern int g_server_bpp;
33
34 uint8 *g_next_packet;
35 uint32 g_rdp_shareid;
36
37 #if WITH_DEBUG
38 static uint32 g_packetno;
39 #endif
40
41 /* Receive an RDP packet */
42 static STREAM
43 rdp_recv(uint8 * type)
44 {
45 static STREAM rdp_s;
46 uint16 length, pdu_type;
47
48 if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end))
49 {
50 rdp_s = sec_recv();
51 if (rdp_s == NULL)
52 return NULL;
53
54 g_next_packet = rdp_s->p;
55 }
56 else
57 {
58 rdp_s->p = g_next_packet;
59 }
60
61 in_uint16_le(rdp_s, length);
62 /* 32k packets are really 8, keepalive fix */
63 if (length == 0x8000)
64 {
65 g_next_packet += 8;
66 *type = 0;
67 return rdp_s;
68 }
69 in_uint16_le(rdp_s, pdu_type);
70 in_uint8s(rdp_s, 2); /* userid */
71 *type = pdu_type & 0xf;
72
73 #if WITH_DEBUG
74 DEBUG(("RDP packet #%d, (type %x)\n", ++g_packetno, *type));
75 hexdump(g_next_packet, length);
76 #endif /* */
77
78 g_next_packet += length;
79 return rdp_s;
80 }
81
82 /* Initialise an RDP data packet */
83 static STREAM
84 rdp_init_data(int maxlen)
85 {
86 STREAM s;
87
88 s = sec_init(g_encryption ? SEC_ENCRYPT : 0, maxlen + 18);
89 s_push_layer(s, rdp_hdr, 18);
90
91 return s;
92 }
93
94 /* Send an RDP data packet */
95 static void
96 rdp_send_data(STREAM s, uint8 data_pdu_type)
97 {
98 uint16 length;
99
100 s_pop_layer(s, rdp_hdr);
101 length = s->end - s->p;
102
103 out_uint16_le(s, length);
104 out_uint16_le(s, (RDP_PDU_DATA | 0x10));
105 out_uint16_le(s, (g_mcs_userid + 1001));
106
107 out_uint32_le(s, g_rdp_shareid);
108 out_uint8(s, 0); /* pad */
109 out_uint8(s, 1); /* streamid */
110 out_uint16_le(s, (length - 14));
111 out_uint8(s, data_pdu_type);
112 out_uint8(s, 0); /* compress_type */
113 out_uint16(s, 0); /* compress_len */
114
115 sec_send(s, g_encryption ? SEC_ENCRYPT : 0);
116 }
117
118 /* Output a string in Unicode */
119 void
120 rdp_out_unistr(STREAM s, char *string, int len)
121 {
122 int i = 0, j = 0;
123
124 len += 2;
125
126 while (i < len)
127 {
128 s->p[i++] = string[j++];
129 s->p[i++] = 0;
130 }
131
132 s->p += len;
133 }
134
135 /* Input a string in Unicode
136 *
137 * Returns str_len of string
138 */
139 int
140 rdp_in_unistr(STREAM s, char *string, int uni_len)
141 {
142 int i = 0;
143
144 while (i < uni_len / 2)
145 {
146 in_uint8a(s, &string[i++], 1);
147 in_uint8s(s, 1);
148 }
149
150 return i - 1;
151 }
152
153
154 /* Parse a logon info packet */
155 static void
156 rdp_send_logon_info(uint32 flags, char *domain, char *user,
157 char *password, char *program, char *directory)
158 {
159 int len_domain = 2 * strlen(domain);
160 int len_user = 2 * strlen(user);
161 int len_password = 2 * strlen(password);
162 int len_program = 2 * strlen(program);
163 int len_directory = 2 * strlen(directory);
164 int len_ip = 2 * strlen("127.0.0.1");
165 int len_dll = 2 * strlen("C:\\WINNT\\System32\\mstscax.dll");
166 int packetlen = 0;
167 uint32 sec_flags = g_encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO;
168 STREAM s;
169 time_t t = time(NULL);
170 time_t tzone;
171
172 if (!g_use_rdp5 || 1 == g_server_rdp_version)
173 {
174 DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));
175
176 s = sec_init(sec_flags, 18 + len_domain + len_user + len_password
177 + len_program + len_directory + 10);
178
179 out_uint32(s, 0);
180 out_uint32_le(s, flags);
181 out_uint16_le(s, len_domain);
182 out_uint16_le(s, len_user);
183 out_uint16_le(s, len_password);
184 out_uint16_le(s, len_program);
185 out_uint16_le(s, len_directory);
186 rdp_out_unistr(s, domain, len_domain);
187 rdp_out_unistr(s, user, len_user);
188 rdp_out_unistr(s, password, len_password);
189 rdp_out_unistr(s, program, len_program);
190 rdp_out_unistr(s, directory, len_directory);
191 }
192 else
193 {
194 flags |= RDP_LOGON_BLOB;
195 DEBUG_RDP5(("Sending RDP5-style Logon packet\n"));
196 packetlen = 4 + /* Unknown uint32 */
197 4 + /* flags */
198 2 + /* len_domain */
199 2 + /* len_user */
200 (flags & RDP_LOGON_AUTO ? 2 : 0) + /* len_password */
201 (flags & RDP_LOGON_BLOB ? 2 : 0) + /* Length of BLOB */
202 2 + /* len_program */
203 2 + /* len_directory */
204 (0 < len_domain ? len_domain : 2) + /* domain */
205 len_user + (flags & RDP_LOGON_AUTO ? len_password : 0) + 0 + /* We have no 512 byte BLOB. Perhaps we must? */
206 (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO) ? 2 : 0) + /* After the BLOB is a unknown int16. If there is a BLOB, that is. */
207 (0 < len_program ? len_program : 2) + (0 < len_directory ? len_directory : 2) + 2 + /* Unknown (2) */
208 2 + /* Client ip length */
209 len_ip + /* Client ip */
210 2 + /* DLL string length */
211 len_dll + /* DLL string */
212 2 + /* Unknown */
213 2 + /* Unknown */
214 64 + /* Time zone #0 */
215 2 + /* Unknown */
216 64 + /* Time zone #1 */
217 32; /* Unknown */
218
219 s = sec_init(sec_flags, packetlen);
220 DEBUG_RDP5(("Called sec_init with packetlen %d\n", packetlen));
221
222 out_uint32(s, 0); /* Unknown */
223 out_uint32_le(s, flags);
224 out_uint16_le(s, len_domain);
225 out_uint16_le(s, len_user);
226 if (flags & RDP_LOGON_AUTO)
227 {
228 out_uint16_le(s, len_password);
229
230 }
231 if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
232 {
233 out_uint16_le(s, 0);
234 }
235 out_uint16_le(s, len_program);
236 out_uint16_le(s, len_directory);
237 if (0 < len_domain)
238 rdp_out_unistr(s, domain, len_domain);
239 else
240 out_uint16_le(s, 0);
241 rdp_out_unistr(s, user, len_user);
242 if (flags & RDP_LOGON_AUTO)
243 {
244 rdp_out_unistr(s, password, len_password);
245 }
246 if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
247 {
248 out_uint16_le(s, 0);
249 }
250 if (0 < len_program)
251 {
252 rdp_out_unistr(s, program, len_program);
253
254 }
255 else
256 {
257 out_uint16_le(s, 0);
258 }
259 if (0 < len_directory)
260 {
261 rdp_out_unistr(s, directory, len_directory);
262 }
263 else
264 {
265 out_uint16_le(s, 0);
266 }
267 out_uint16_le(s, 2);
268 out_uint16_le(s, len_ip + 2); /* Length of client ip */
269 rdp_out_unistr(s, "127.0.0.1", len_ip);
270 out_uint16_le(s, len_dll + 2);
271 rdp_out_unistr(s, "C:\\WINNT\\System32\\mstscax.dll", len_dll);
272
273 tzone = (mktime(gmtime(&t)) - mktime(localtime(&t))) / 60;
274 out_uint32_le(s, tzone);
275
276 rdp_out_unistr(s, "GTB, normaltid", 2 * strlen("GTB, normaltid"));
277 out_uint8s(s, 62 - 2 * strlen("GTB, normaltid"));
278
279
280 out_uint32_le(s, 0x0a0000);
281 out_uint32_le(s, 0x050000);
282 out_uint32_le(s, 3);
283 out_uint32_le(s, 0);
284 out_uint32_le(s, 0);
285
286 rdp_out_unistr(s, "GTB, sommartid", 2 * strlen("GTB, sommartid"));
287 out_uint8s(s, 62 - 2 * strlen("GTB, sommartid"));
288
289 out_uint32_le(s, 0x30000);
290 out_uint32_le(s, 0x050000);
291 out_uint32_le(s, 2);
292 out_uint32(s, 0);
293 out_uint32_le(s, 0xffffffc4);
294 out_uint32_le(s, 0xfffffffe);
295 out_uint32_le(s, 0x0f);
296 out_uint32(s, 0);
297
298
299 }
300 s_mark_end(s);
301 sec_send(s, sec_flags);
302 }
303
304 /* Send a control PDU */
305 static void
306 rdp_send_control(uint16 action)
307 {
308 STREAM s;
309
310 s = rdp_init_data(8);
311
312 out_uint16_le(s, action);
313 out_uint16(s, 0); /* userid */
314 out_uint32(s, 0); /* control id */
315
316 s_mark_end(s);
317 rdp_send_data(s, RDP_DATA_PDU_CONTROL);
318 }
319
320 /* Send a synchronisation PDU */
321 static void
322 rdp_send_synchronise(void)
323 {
324 STREAM s;
325
326 s = rdp_init_data(4);
327
328 out_uint16_le(s, 1); /* type */
329 out_uint16_le(s, 1002);
330
331 s_mark_end(s);
332 rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
333 }
334
335 /* Send a single input event */
336 void
337 rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2)
338 {
339 STREAM s;
340
341 s = rdp_init_data(16);
342
343 out_uint16_le(s, 1); /* number of events */
344 out_uint16(s, 0); /* pad */
345
346 out_uint32_le(s, time);
347 out_uint16_le(s, message_type);
348 out_uint16_le(s, device_flags);
349 out_uint16_le(s, param1);
350 out_uint16_le(s, param2);
351
352 s_mark_end(s);
353 rdp_send_data(s, RDP_DATA_PDU_INPUT);
354 }
355
356 /* Send an (empty) font information PDU */
357 static void
358 rdp_send_fonts(uint16 seq)
359 {
360 STREAM s;
361
362 s = rdp_init_data(8);
363
364 out_uint16(s, 0); /* number of fonts */
365 out_uint16_le(s, 0x3e); /* unknown */
366 out_uint16_le(s, seq); /* unknown */
367 out_uint16_le(s, 0x32); /* entry size */
368
369 s_mark_end(s);
370 rdp_send_data(s, RDP_DATA_PDU_FONT2);
371 }
372
373 /* Output general capability set */
374 static void
375 rdp_out_general_caps(STREAM s)
376 {
377 out_uint16_le(s, RDP_CAPSET_GENERAL);
378 out_uint16_le(s, RDP_CAPLEN_GENERAL);
379
380 out_uint16_le(s, 1); /* OS major type */
381 out_uint16_le(s, 3); /* OS minor type */
382 out_uint16_le(s, 0x200); /* Protocol version */
383 out_uint16(s, 0); /* Pad */
384 out_uint16(s, 0); /* Compression types */
385 out_uint16_le(s, g_use_rdp5 ? 0x40d : 0);
386 /* Pad, according to T.128. 0x40d seems to
387 trigger
388 the server to start sending RDP5 packets.
389 However, the value is 0x1d04 with W2KTSK and
390 NT4MS. Hmm.. Anyway, thankyou, Microsoft,
391 for sending such information in a padding
392 field.. */
393 out_uint16(s, 0); /* Update capability */
394 out_uint16(s, 0); /* Remote unshare capability */
395 out_uint16(s, 0); /* Compression level */
396 out_uint16(s, 0); /* Pad */
397 }
398
399 /* Output bitmap capability set */
400 static void
401 rdp_out_bitmap_caps(STREAM s)
402 {
403 out_uint16_le(s, RDP_CAPSET_BITMAP);
404 out_uint16_le(s, RDP_CAPLEN_BITMAP);
405
406 out_uint16_le(s, 8); /* Preferred BPP */
407 out_uint16_le(s, 1); /* Receive 1 BPP */
408 out_uint16_le(s, 1); /* Receive 4 BPP */
409 out_uint16_le(s, 1); /* Receive 8 BPP */
410 out_uint16_le(s, 800); /* Desktop width */
411 out_uint16_le(s, 600); /* Desktop height */
412 out_uint16(s, 0); /* Pad */
413 out_uint16(s, 0); /* Allow resize */
414 out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */
415 out_uint16(s, 0); /* Unknown */
416 out_uint16_le(s, 1); /* Unknown */
417 out_uint16(s, 0); /* Pad */
418 }
419
420 /* Output order capability set */
421 static void
422 rdp_out_order_caps(STREAM s)
423 {
424 uint8 order_caps[32];
425
426
427 memset(order_caps, 0, 32);
428 order_caps[0] = 1; /* dest blt */
429 order_caps[1] = 1; /* pat blt */
430 order_caps[2] = 1; /* screen blt */
431 order_caps[3] = 1; /* required for memblt? */
432 order_caps[8] = 1; /* line */
433 order_caps[9] = 1; /* line */
434 order_caps[10] = 1; /* rect */
435 order_caps[11] = (g_desktop_save == False ? 0 : 1); /* desksave */
436 order_caps[13] = 1; /* memblt */
437 order_caps[14] = 1; /* triblt */
438 order_caps[22] = 1; /* polyline */
439 order_caps[27] = 1; /* text2 */
440 out_uint16_le(s, RDP_CAPSET_ORDER);
441 out_uint16_le(s, RDP_CAPLEN_ORDER);
442
443 out_uint8s(s, 20); /* Terminal desc, pad */
444 out_uint16_le(s, 1); /* Cache X granularity */
445 out_uint16_le(s, 20); /* Cache Y granularity */
446 out_uint16(s, 0); /* Pad */
447 out_uint16_le(s, 1); /* Max order level */
448 out_uint16_le(s, 0x147); /* Number of fonts */
449 out_uint16_le(s, 0x2a); /* Capability flags */
450 out_uint8p(s, order_caps, 32); /* Orders supported */
451 out_uint16_le(s, 0x6a1); /* Text capability flags */
452 out_uint8s(s, 6); /* Pad */
453 out_uint32_le(s, g_desktop_save == False ? 0 : 0x38400); /* Desktop cache size */
454 out_uint32(s, 0); /* Unknown */
455 out_uint32_le(s, 0x4e4); /* Unknown */
456 }
457
458 /* Output bitmap cache capability set */
459 static void
460 rdp_out_bmpcache_caps(STREAM s)
461 {
462 int Bpp;
463 out_uint16_le(s, RDP_CAPSET_BMPCACHE);
464 out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
465
466 Bpp = (g_server_bpp + 7) / 8;
467 out_uint8s(s, 24); /* unused */
468 out_uint16_le(s, 0x258); /* entries */
469 out_uint16_le(s, 0x100 * Bpp); /* max cell size */
470 out_uint16_le(s, 0x12c); /* entries */
471 out_uint16_le(s, 0x400 * Bpp); /* max cell size */
472 out_uint16_le(s, 0x106); /* entries */
473 out_uint16_le(s, 0x1000 * Bpp); /* max cell size */
474 }
475
476 /* Output control capability set */
477 static void
478 rdp_out_control_caps(STREAM s)
479 {
480 out_uint16_le(s, RDP_CAPSET_CONTROL);
481 out_uint16_le(s, RDP_CAPLEN_CONTROL);
482
483 out_uint16(s, 0); /* Control capabilities */
484 out_uint16(s, 0); /* Remote detach */
485 out_uint16_le(s, 2); /* Control interest */
486 out_uint16_le(s, 2); /* Detach interest */
487 }
488
489 /* Output activation capability set */
490 static void
491 rdp_out_activate_caps(STREAM s)
492 {
493 out_uint16_le(s, RDP_CAPSET_ACTIVATE);
494 out_uint16_le(s, RDP_CAPLEN_ACTIVATE);
495
496 out_uint16(s, 0); /* Help key */
497 out_uint16(s, 0); /* Help index key */
498 out_uint16(s, 0); /* Extended help key */
499 out_uint16(s, 0); /* Window activate */
500 }
501
502 /* Output pointer capability set */
503 static void
504 rdp_out_pointer_caps(STREAM s)
505 {
506 out_uint16_le(s, RDP_CAPSET_POINTER);
507 out_uint16_le(s, RDP_CAPLEN_POINTER);
508
509 out_uint16(s, 0); /* Colour pointer */
510 out_uint16_le(s, 20); /* Cache size */
511 }
512
513 /* Output share capability set */
514 static void
515 rdp_out_share_caps(STREAM s)
516 {
517 out_uint16_le(s, RDP_CAPSET_SHARE);
518 out_uint16_le(s, RDP_CAPLEN_SHARE);
519
520 out_uint16(s, 0); /* userid */
521 out_uint16(s, 0); /* pad */
522 }
523
524 /* Output colour cache capability set */
525 static void
526 rdp_out_colcache_caps(STREAM s)
527 {
528 out_uint16_le(s, RDP_CAPSET_COLCACHE);
529 out_uint16_le(s, RDP_CAPLEN_COLCACHE);
530
531 out_uint16_le(s, 6); /* cache size */
532 out_uint16(s, 0); /* pad */
533 }
534
535 static uint8 canned_caps[] = {
536 0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x04,
537 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
538 0x00, 0x00, 0x00, 0x00, 0x00,
539 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
540 0x00, 0x00, 0x00, 0x00, 0x00,
541 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
542 0x00, 0x00, 0x00, 0x00, 0x00,
543 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
544 0x00, 0x00, 0x00, 0x00, 0x00,
545 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
546 0x0C, 0x00, 0x08, 0x00, 0x01,
547 0x00, 0x00, 0x00, 0x0E, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00,
548 0x10, 0x00, 0x34, 0x00, 0xFE,
549 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x08, 0x00,
550 0xFE, 0x00, 0x08, 0x00, 0xFE,
551 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00, 0xFE, 0x00, 0x40, 0x00,
552 0xFE, 0x00, 0x80, 0x00, 0xFE,
553 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01,
554 0x02, 0x00, 0x00, 0x00
555 };
556
557 /* Output unknown capability sets (number 13, 12, 14 and 16) */
558 static void
559 rdp_out_unknown_caps(STREAM s)
560 {
561 out_uint16_le(s, RDP_CAPSET_UNKNOWN);
562 out_uint16_le(s, 0x58);
563
564 out_uint8p(s, canned_caps, RDP_CAPLEN_UNKNOWN - 4);
565 }
566
567 #define RDP5_FLAG 0x0030
568 /* Send a confirm active PDU */
569 static void
570 rdp_send_confirm_active(void)
571 {
572 STREAM s;
573 uint32 sec_flags = g_encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG;
574 uint16 caplen =
575 RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
576 RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
577 RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
578 RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE + RDP_CAPLEN_UNKNOWN + 4 /* w2k fix, why? */ ;
579
580 s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
581
582 out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE));
583 out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10)); /* Version 1 */
584 out_uint16_le(s, (g_mcs_userid + 1001));
585
586 out_uint32_le(s, g_rdp_shareid);
587 out_uint16_le(s, 0x3ea); /* userid */
588 out_uint16_le(s, sizeof(RDP_SOURCE));
589 out_uint16_le(s, caplen);
590
591 out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));
592 out_uint16_le(s, 0xd); /* num_caps */
593 out_uint8s(s, 2); /* pad */
594
595 rdp_out_general_caps(s);
596 rdp_out_bitmap_caps(s);
597 rdp_out_order_caps(s);
598 rdp_out_bmpcache_caps(s);
599 rdp_out_colcache_caps(s);
600 rdp_out_activate_caps(s);
601 rdp_out_control_caps(s);
602 rdp_out_pointer_caps(s);
603 rdp_out_share_caps(s);
604 rdp_out_unknown_caps(s);
605
606 s_mark_end(s);
607 sec_send(s, sec_flags);
608 }
609
610 /* Respond to a demand active PDU */
611 static void
612 process_demand_active(STREAM s)
613 {
614 uint8 type;
615
616 in_uint32_le(s, g_rdp_shareid);
617
618 DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
619
620 rdp_send_confirm_active();
621 rdp_send_synchronise();
622 rdp_send_control(RDP_CTL_COOPERATE);
623 rdp_send_control(RDP_CTL_REQUEST_CONTROL);
624 rdp_recv(&type); /* RDP_PDU_SYNCHRONIZE */
625 rdp_recv(&type); /* RDP_CTL_COOPERATE */
626 rdp_recv(&type); /* RDP_CTL_GRANT_CONTROL */
627 rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(read_keyboard_state()), 0);
628 rdp_send_fonts(1);
629 rdp_send_fonts(2);
630 rdp_recv(&type); /* RDP_PDU_UNKNOWN 0x28 */
631 reset_order_state();
632 }
633
634 /* Process a colour pointer PDU */
635 void
636 process_colour_pointer_pdu(STREAM s)
637 {
638 uint16 x, y, width, height, cache_idx, masklen, datalen;
639 uint8 *mask, *data;
640 HCURSOR cursor;
641
642 in_uint16_le(s, cache_idx);
643 in_uint16_le(s, x);
644 in_uint16_le(s, y);
645 in_uint16_le(s, width);
646 in_uint16_le(s, height);
647 in_uint16_le(s, masklen);
648 in_uint16_le(s, datalen);
649 in_uint8p(s, data, datalen);
650 in_uint8p(s, mask, masklen);
651 cursor = ui_create_cursor(x, y, width, height, mask, data);
652 ui_set_cursor(cursor);
653 cache_put_cursor(cache_idx, cursor);
654 }
655
656 /* Process a cached pointer PDU */
657 void
658 process_cached_pointer_pdu(STREAM s)
659 {
660 uint16 cache_idx;
661
662 in_uint16_le(s, cache_idx);
663 ui_set_cursor(cache_get_cursor(cache_idx));
664 }
665
666 /* Process a system pointer PDU */
667 void
668 process_system_pointer_pdu(STREAM s)
669 {
670 uint16 system_pointer_type;
671
672 in_uint16(s, system_pointer_type);
673 switch (system_pointer_type)
674 {
675 case RDP_NULL_POINTER:
676 ui_set_null_cursor();
677 break;
678
679 default:
680 unimpl("System pointer message 0x%x\n", system_pointer_type);
681 }
682 }
683
684 /* Process a pointer PDU */
685 static void
686 process_pointer_pdu(STREAM s)
687 {
688 uint16 message_type;
689 uint16 x, y;
690
691 in_uint16_le(s, message_type);
692 in_uint8s(s, 2); /* pad */
693
694 switch (message_type)
695 {
696 case RDP_POINTER_MOVE:
697 in_uint16_le(s, x);
698 in_uint16_le(s, y);
699 if (s_check(s))
700 ui_move_pointer(x, y);
701 break;
702
703 case RDP_POINTER_COLOR:
704 process_colour_pointer_pdu(s);
705 break;
706
707 case RDP_POINTER_CACHED:
708 process_cached_pointer_pdu(s);
709 break;
710
711 case RDP_POINTER_SYSTEM:
712 process_system_pointer_pdu(s);
713 break;
714
715 default:
716 unimpl("Pointer message 0x%x\n", message_type);
717 }
718 }
719
720 /* Process bitmap updates */
721 void
722 process_bitmap_updates(STREAM s)
723 {
724 uint16 num_updates;
725 uint16 left, top, right, bottom, width, height;
726 uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
727 uint8 *data, *bmpdata;
728 int i;
729
730 in_uint16_le(s, num_updates);
731
732 for (i = 0; i < num_updates; i++)
733 {
734 in_uint16_le(s, left);
735 in_uint16_le(s, top);
736 in_uint16_le(s, right);
737 in_uint16_le(s, bottom);
738 in_uint16_le(s, width);
739 in_uint16_le(s, height);
740 in_uint16_le(s, bpp);
741 Bpp = (bpp + 7) / 8;
742 in_uint16_le(s, compress);
743 in_uint16_le(s, bufsize);
744
745 cx = right - left + 1;
746 cy = bottom - top + 1;
747
748 DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",
749 left, top, right, bottom, width, height, Bpp, compress));
750
751 /* Server may limit bpp - this is how we find out */
752 if (g_server_bpp != bpp)
753 {
754 warning("Server limited colour depth to %d bits\n", bpp);
755 g_server_bpp = bpp;
756 }
757
758 if (!compress)
759 {
760 int y;
761 bmpdata = (uint8 *) xmalloc(width * height * Bpp);
762 for (y = 0; y < height; y++)
763 {
764 in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
765 width * Bpp);
766 }
767 ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
768 xfree(bmpdata);
769 continue;
770 }
771
772
773 if (compress & 0x400)
774 {
775 size = bufsize;
776 }
777 else
778 {
779 in_uint8s(s, 2); /* pad */
780 in_uint16_le(s, size);
781 in_uint8s(s, 4); /* line_size, final_size */
782 }
783 in_uint8p(s, data, size);
784 bmpdata = (uint8 *) xmalloc(width * height * Bpp);
785 if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
786 {
787 ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
788 }
789 else
790 {
791 DEBUG_RDP5(("Failed to decompress data\n"));
792 }
793
794 xfree(bmpdata);
795 }
796 }
797
798 /* Process a palette update */
799 void
800 process_palette(STREAM s)
801 {
802 COLOURENTRY *entry;
803 COLOURMAP map;
804 HCOLOURMAP hmap;
805 int i;
806
807 in_uint8s(s, 2); /* pad */
808 in_uint16_le(s, map.ncolours);
809 in_uint8s(s, 2); /* pad */
810
811 map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
812
813 DEBUG(("PALETTE(c=%d)\n", map.ncolours));
814
815 for (i = 0; i < map.ncolours; i++)
816 {
817 entry = &map.colours[i];
818 in_uint8(s, entry->red);
819 in_uint8(s, entry->green);
820 in_uint8(s, entry->blue);
821 }
822
823 hmap = ui_create_colourmap(&map);
824 ui_set_colourmap(hmap);
825
826 xfree(map.colours);
827 }
828
829 /* Process an update PDU */
830 static void
831 process_update_pdu(STREAM s)
832 {
833 uint16 update_type, count;
834
835 in_uint16_le(s, update_type);
836
837 switch (update_type)
838 {
839 case RDP_UPDATE_ORDERS:
840 in_uint8s(s, 2); /* pad */
841 in_uint16_le(s, count);
842 in_uint8s(s, 2); /* pad */
843 process_orders(s, count);
844 break;
845
846 case RDP_UPDATE_BITMAP:
847 process_bitmap_updates(s);
848 break;
849
850 case RDP_UPDATE_PALETTE:
851 process_palette(s);
852 break;
853
854 case RDP_UPDATE_SYNCHRONIZE:
855 break;
856
857 default:
858 unimpl("update %d\n", update_type);
859 }
860
861 }
862
863 /* Process data PDU */
864 static void
865 process_data_pdu(STREAM s)
866 {
867 uint8 data_pdu_type;
868
869 in_uint8s(s, 8); /* shareid, pad, streamid, length */
870 in_uint8(s, data_pdu_type);
871 in_uint8s(s, 3); /* compress_type, compress_len */
872
873 switch (data_pdu_type)
874 {
875 case RDP_DATA_PDU_UPDATE:
876 process_update_pdu(s);
877 break;
878
879 case RDP_DATA_PDU_POINTER:
880 process_pointer_pdu(s);
881 break;
882
883 case RDP_DATA_PDU_BELL:
884 ui_bell();
885 break;
886
887 case RDP_DATA_PDU_LOGON:
888 DEBUG(("Received Logon PDU\n"));
889 /* User logged on */
890 break;
891
892 case RDP_DATA_PDU_DISCONNECT:
893 /* Normally received when user logs out or disconnects from a
894 console session on Windows XP and 2003 Server */
895 DEBUG(("Received disconnect PDU\n"));
896 break;
897
898 default:
899 unimpl("data PDU %d\n", data_pdu_type);
900 }
901 }
902
903 /* Process incoming packets */
904 BOOL
905 rdp_main_loop(void)
906 {
907 uint8 type;
908 STREAM s;
909
910 while ((s = rdp_recv(&type)) != NULL)
911 {
912 switch (type)
913 {
914 case RDP_PDU_DEMAND_ACTIVE:
915 process_demand_active(s);
916 break;
917
918 case RDP_PDU_DEACTIVATE:
919 DEBUG(("RDP_PDU_DEACTIVATE\n"));
920 /* We thought we could detect a clean
921 shutdown of the session by this
922 packet, but it seems Windows 2003
923 is sending us one of these when we
924 reconnect to a disconnected session
925 return True; */
926 break;
927
928 case RDP_PDU_DATA:
929 process_data_pdu(s);
930 break;
931
932 case 0:
933 break;
934
935 default:
936 unimpl("PDU %d\n", type);
937 }
938 }
939 return True;
940 /* We want to detect if we got a clean shutdown, but we
941 can't. Se above.
942 return False; */
943 }
944
945 /* Establish a connection up to the RDP layer */
946 BOOL
947 rdp_connect(char *server, uint32 flags, char *domain, char *password,
948 char *command, char *directory)
949 {
950 if (!sec_connect(server, g_username))
951 return False;
952
953 rdp_send_logon_info(flags, domain, g_username, password, command, directory);
954 return True;
955 }
956
957 /* Disconnect from the RDP layer */
958 void
959 rdp_disconnect(void)
960 {
961 sec_disconnect();
962 }

  ViewVC Help
Powered by ViewVC 1.1.26