/[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 676 - (show annotations)
Tue Apr 20 07:01:21 2004 UTC (20 years ago) by astrand
File MIME type: text/plain
File size: 24065 byte(s)
Applied disconnect handling patch from Jeroen Meijer

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

  ViewVC Help
Powered by ViewVC 1.1.26