Diffstat (limited to 'noncore/net/opierdesktop/rdp.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | noncore/net/opierdesktop/rdp.cpp | 748 |
1 files changed, 748 insertions, 0 deletions
diff --git a/noncore/net/opierdesktop/rdp.cpp b/noncore/net/opierdesktop/rdp.cpp new file mode 100644 index 0000000..bab8568 --- a/dev/null +++ b/noncore/net/opierdesktop/rdp.cpp | |||
@@ -0,0 +1,748 @@ | |||
1 | /* | ||
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 "rdesktop.h" | ||
22 | |||
23 | extern uint16 mcs_userid; | ||
24 | extern char username[16]; | ||
25 | extern BOOL bitmap_compression; | ||
26 | extern BOOL orders; | ||
27 | extern BOOL encryption; | ||
28 | extern BOOL desktop_save; | ||
29 | |||
30 | uint8 *next_packet; | ||
31 | uint32 rdp_shareid; | ||
32 | |||
33 | /* Initialise an RDP packet */ | ||
34 | static STREAM | ||
35 | rdp_init(int maxlen) | ||
36 | { | ||
37 | STREAM s; | ||
38 | |||
39 | s = sec_init(encryption ? SEC_ENCRYPT : 0, maxlen + 6); | ||
40 | s_push_layer(s, rdp_hdr, 6); | ||
41 | |||
42 | return s; | ||
43 | } | ||
44 | |||
45 | /* Send an RDP packet */ | ||
46 | static void | ||
47 | rdp_send(STREAM s, uint8 pdu_type) | ||
48 | { | ||
49 | uint16 length; | ||
50 | |||
51 | s_pop_layer(s, rdp_hdr); | ||
52 | length = s->end - s->p; | ||
53 | |||
54 | out_uint16_le(s, length); | ||
55 | out_uint16_le(s, (pdu_type | 0x10));/* Version 1 */ | ||
56 | out_uint16_le(s, (mcs_userid + 1001)); | ||
57 | |||
58 | sec_send(s, encryption ? SEC_ENCRYPT : 0); | ||
59 | } | ||
60 | |||
61 | /* Receive an RDP packet */ | ||
62 | STREAM | ||
63 | rdp_recv(uint8 * type) | ||
64 | { | ||
65 | static STREAM rdp_s; | ||
66 | uint16 length, pdu_type; | ||
67 | |||
68 | if ((rdp_s == NULL) || (next_packet >= rdp_s->end)) | ||
69 | { | ||
70 | rdp_s = sec_recv(); | ||
71 | if (rdp_s == NULL) | ||
72 | return NULL; | ||
73 | |||
74 | next_packet = rdp_s->p; | ||
75 | } | ||
76 | else | ||
77 | { | ||
78 | rdp_s->p = next_packet; | ||
79 | } | ||
80 | |||
81 | in_uint16_le(rdp_s, length); | ||
82 | /* 32k packets are really 8, keepalive fix */ | ||
83 | if (length == 0x8000) | ||
84 | { | ||
85 | next_packet += 8; | ||
86 | *type = 0; | ||
87 | return rdp_s; | ||
88 | } | ||
89 | in_uint16_le(rdp_s, pdu_type); | ||
90 | in_uint8s(rdp_s, 2);/* userid */ | ||
91 | *type = pdu_type & 0xf; | ||
92 | |||
93 | #if WITH_DEBUG | ||
94 | DEBUG(("RDP packet (type %x):\n", *type)); | ||
95 | hexdump(next_packet, length); | ||
96 | #endif /* */ | ||
97 | |||
98 | next_packet += length; | ||
99 | return rdp_s; | ||
100 | } | ||
101 | |||
102 | /* Initialise an RDP data packet */ | ||
103 | static STREAM | ||
104 | rdp_init_data(int maxlen) | ||
105 | { | ||
106 | STREAM s; | ||
107 | |||
108 | s = sec_init(encryption ? SEC_ENCRYPT : 0, maxlen + 18); | ||
109 | s_push_layer(s, rdp_hdr, 18); | ||
110 | |||
111 | return s; | ||
112 | } | ||
113 | |||
114 | /* Send an RDP data packet */ | ||
115 | static void | ||
116 | rdp_send_data(STREAM s, uint8 data_pdu_type) | ||
117 | { | ||
118 | uint16 length; | ||
119 | |||
120 | s_pop_layer(s, rdp_hdr); | ||
121 | length = s->end - s->p; | ||
122 | |||
123 | out_uint16_le(s, length); | ||
124 | out_uint16_le(s, (RDP_PDU_DATA | 0x10)); | ||
125 | out_uint16_le(s, (mcs_userid + 1001)); | ||
126 | |||
127 | out_uint32_le(s, rdp_shareid); | ||
128 | out_uint8(s, 0);/* pad */ | ||
129 | out_uint8(s, 1);/* streamid */ | ||
130 | out_uint16_le(s, (length - 14)); | ||
131 | out_uint8(s, data_pdu_type); | ||
132 | out_uint8(s, 0);/* compress_type */ | ||
133 | out_uint16(s, 0);/* compress_len */ | ||
134 | |||
135 | sec_send(s, encryption ? SEC_ENCRYPT : 0); | ||
136 | } | ||
137 | |||
138 | /* Output a string in Unicode */ | ||
139 | void | ||
140 | rdp_out_unistr(STREAM s, char *string, int len) | ||
141 | { | ||
142 | int i = 0, j = 0; | ||
143 | |||
144 | len += 2; | ||
145 | |||
146 | while (i < len) | ||
147 | { | ||
148 | s->p[i++] = string[j++]; | ||
149 | s->p[i++] = 0; | ||
150 | } | ||
151 | |||
152 | s->p += len; | ||
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 | int len_domain = 2 * strlen(domain); | ||
161 | int len_user = 2 * strlen(user); | ||
162 | int len_password = 2 * strlen(password); | ||
163 | int len_program = 2 * strlen(program); | ||
164 | int len_directory = 2 * strlen(directory); | ||
165 | uint32 sec_flags = encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO; | ||
166 | STREAM s; | ||
167 | |||
168 | s = sec_init(sec_flags, 18 + len_domain + len_user + len_password | ||
169 | + len_program + len_directory + 10); | ||
170 | |||
171 | out_uint32(s, 0); | ||
172 | out_uint32_le(s, flags); | ||
173 | out_uint16_le(s, len_domain); | ||
174 | out_uint16_le(s, len_user); | ||
175 | out_uint16_le(s, len_password); | ||
176 | out_uint16_le(s, len_program); | ||
177 | out_uint16_le(s, len_directory); | ||
178 | rdp_out_unistr(s, domain, len_domain); | ||
179 | rdp_out_unistr(s, user, len_user); | ||
180 | rdp_out_unistr(s, password, len_password); | ||
181 | rdp_out_unistr(s, program, len_program); | ||
182 | rdp_out_unistr(s, directory, len_directory); | ||
183 | |||
184 | s_mark_end(s); | ||
185 | sec_send(s, sec_flags); | ||
186 | } | ||
187 | |||
188 | /* Send a control PDU */ | ||
189 | static void | ||
190 | rdp_send_control(uint16 action) | ||
191 | { | ||
192 | STREAM s; | ||
193 | |||
194 | s = rdp_init_data(8); | ||
195 | |||
196 | out_uint16_le(s, action); | ||
197 | out_uint16(s, 0);/* userid */ | ||
198 | out_uint32(s, 0);/* control id */ | ||
199 | |||
200 | s_mark_end(s); | ||
201 | rdp_send_data(s, RDP_DATA_PDU_CONTROL); | ||
202 | } | ||
203 | |||
204 | /* Send a synchronisation PDU */ | ||
205 | static void | ||
206 | rdp_send_synchronise(void) | ||
207 | { | ||
208 | STREAM s; | ||
209 | |||
210 | s = rdp_init_data(4); | ||
211 | |||
212 | out_uint16_le(s, 1);/* type */ | ||
213 | out_uint16_le(s, 1002); | ||
214 | |||
215 | s_mark_end(s); | ||
216 | rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE); | ||
217 | } | ||
218 | |||
219 | /* Send a single input event */ | ||
220 | void | ||
221 | rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2) | ||
222 | { | ||
223 | STREAM s; | ||
224 | |||
225 | s = rdp_init_data(16); | ||
226 | |||
227 | out_uint16_le(s, 1);/* number of events */ | ||
228 | out_uint16(s, 0);/* pad */ | ||
229 | |||
230 | out_uint32_le(s, time); | ||
231 | out_uint16_le(s, message_type); | ||
232 | out_uint16_le(s, device_flags); | ||
233 | out_uint16_le(s, param1); | ||
234 | out_uint16_le(s, param2); | ||
235 | |||
236 | s_mark_end(s); | ||
237 | rdp_send_data(s, RDP_DATA_PDU_INPUT); | ||
238 | } | ||
239 | |||
240 | /* Send an (empty) font information PDU */ | ||
241 | static void | ||
242 | rdp_send_fonts(uint16 seq) | ||
243 | { | ||
244 | STREAM s; | ||
245 | |||
246 | s = rdp_init_data(8); | ||
247 | |||
248 | out_uint16(s, 0);/* number of fonts */ | ||
249 | out_uint16_le(s, 0x3e);/* unknown */ | ||
250 | out_uint16_le(s, seq);/* unknown */ | ||
251 | out_uint16_le(s, 0x32);/* entry size */ | ||
252 | |||
253 | s_mark_end(s); | ||
254 | rdp_send_data(s, RDP_DATA_PDU_FONT2); | ||
255 | } | ||
256 | |||
257 | /* Output general capability set */ | ||
258 | static void | ||
259 | rdp_out_general_caps(STREAM s) | ||
260 | { | ||
261 | out_uint16_le(s, RDP_CAPSET_GENERAL); | ||
262 | out_uint16_le(s, RDP_CAPLEN_GENERAL); | ||
263 | |||
264 | out_uint16_le(s, 1);/* OS major type */ | ||
265 | out_uint16_le(s, 3);/* OS minor type */ | ||
266 | out_uint16_le(s, 0x200);/* Protocol version */ | ||
267 | out_uint16(s, 0);/* Pad */ | ||
268 | out_uint16(s, 0);/* Compression types */ | ||
269 | out_uint16(s, 0);/* Pad */ | ||
270 | out_uint16(s, 0);/* Update capability */ | ||
271 | out_uint16(s, 0);/* Remote unshare capability */ | ||
272 | out_uint16(s, 0);/* Compression level */ | ||
273 | out_uint16(s, 0);/* Pad */ | ||
274 | } | ||
275 | |||
276 | /* Output bitmap capability set */ | ||
277 | static void | ||
278 | rdp_out_bitmap_caps(STREAM s) | ||
279 | { | ||
280 | out_uint16_le(s, RDP_CAPSET_BITMAP); | ||
281 | out_uint16_le(s, RDP_CAPLEN_BITMAP); | ||
282 | |||
283 | out_uint16_le(s, 8);/* Preferred BPP */ | ||
284 | out_uint16_le(s, 1);/* Receive 1 BPP */ | ||
285 | out_uint16_le(s, 1);/* Receive 4 BPP */ | ||
286 | out_uint16_le(s, 1);/* Receive 8 BPP */ | ||
287 | out_uint16_le(s, 800);/* Desktop width */ | ||
288 | out_uint16_le(s, 600);/* Desktop height */ | ||
289 | out_uint16(s, 0);/* Pad */ | ||
290 | out_uint16(s, 0);/* Allow resize */ | ||
291 | out_uint16_le(s, bitmap_compression ? 1 : 0);/* Support compression */ | ||
292 | out_uint16(s, 0);/* Unknown */ | ||
293 | out_uint16_le(s, 1);/* Unknown */ | ||
294 | out_uint16(s, 0);/* Pad */ | ||
295 | } | ||
296 | |||
297 | /* Output order capability set */ | ||
298 | static void | ||
299 | rdp_out_order_caps(STREAM s) | ||
300 | { | ||
301 | uint8 order_caps[32]; | ||
302 | |||
303 | |||
304 | memset(order_caps, 0, 32); | ||
305 | order_caps[0] = 1;/* dest blt */ | ||
306 | order_caps[1] = 1;/* pat blt */ | ||
307 | order_caps[2] = 1;/* screen blt */ | ||
308 | // order_caps[3] = 1;/* required for memblt? */ | ||
309 | order_caps[8] = 1;/* line */ | ||
310 | order_caps[9] = 1;/* line */ | ||
311 | order_caps[10] = 1;/* rect */ | ||
312 | order_caps[11] = (desktop_save == False ? 0 : 1);/* desksave */ | ||
313 | order_caps[13] = 1;/* memblt */ | ||
314 | order_caps[14] = 1;/* triblt */ | ||
315 | order_caps[22] = 1;/* polyline */ | ||
316 | order_caps[27] = 1;/* text2 */ | ||
317 | out_uint16_le(s, RDP_CAPSET_ORDER); | ||
318 | out_uint16_le(s, RDP_CAPLEN_ORDER); | ||
319 | |||
320 | out_uint8s(s, 20);/* Terminal desc, pad */ | ||
321 | out_uint16_le(s, 1);/* Cache X granularity */ | ||
322 | out_uint16_le(s, 20);/* Cache Y granularity */ | ||
323 | out_uint16(s, 0);/* Pad */ | ||
324 | out_uint16_le(s, 1);/* Max order level */ | ||
325 | out_uint16_le(s, 0x147);/* Number of fonts */ | ||
326 | out_uint16_le(s, 0x2a);/* Capability flags */ | ||
327 | out_uint8p(s, order_caps, 32);/* Orders supported */ | ||
328 | out_uint16_le(s, 0x6a1);/* Text capability flags */ | ||
329 | out_uint8s(s, 6);/* Pad */ | ||
330 | out_uint32_le(s, desktop_save == False ? 0 : 0x38400);/* Desktop cache size */ | ||
331 | //out_uint32_le(s, 0); // desktop cache set to 0 | ||
332 | out_uint32(s, 0);/* Unknown */ | ||
333 | out_uint32_le(s, 0x4e4);/* Unknown */ | ||
334 | } | ||
335 | |||
336 | /* Output bitmap cache capability set */ | ||
337 | static void | ||
338 | rdp_out_bmpcache_caps(STREAM s) | ||
339 | { | ||
340 | out_uint16_le(s, RDP_CAPSET_BMPCACHE); | ||
341 | out_uint16_le(s, RDP_CAPLEN_BMPCACHE); | ||
342 | |||
343 | out_uint8s(s, 24);/* unused */ | ||
344 | out_uint16_le(s, 0x258);/* entries */ | ||
345 | out_uint16_le(s, 0x100);/* max cell size */ | ||
346 | out_uint16_le(s, 0x12c);/* entries */ | ||
347 | out_uint16_le(s, 0x400);/* max cell size */ | ||
348 | out_uint16_le(s, 0x106);/* entries */ | ||
349 | out_uint16_le(s, 0x1000);/* max cell size */ | ||
350 | } | ||
351 | |||
352 | /* Output control capability set */ | ||
353 | static void | ||
354 | rdp_out_control_caps(STREAM s) | ||
355 | { | ||
356 | out_uint16_le(s, RDP_CAPSET_CONTROL); | ||
357 | out_uint16_le(s, RDP_CAPLEN_CONTROL); | ||
358 | |||
359 | out_uint16(s, 0);/* Control capabilities */ | ||
360 | out_uint16(s, 0);/* Remote detach */ | ||
361 | out_uint16_le(s, 2);/* Control interest */ | ||
362 | out_uint16_le(s, 2);/* Detach interest */ | ||
363 | } | ||
364 | |||
365 | /* Output activation capability set */ | ||
366 | static void | ||
367 | rdp_out_activate_caps(STREAM s) | ||
368 | { | ||
369 | out_uint16_le(s, RDP_CAPSET_ACTIVATE); | ||
370 | out_uint16_le(s, RDP_CAPLEN_ACTIVATE); | ||
371 | |||
372 | out_uint16(s, 0);/* Help key */ | ||
373 | out_uint16(s, 0);/* Help index key */ | ||
374 | out_uint16(s, 0);/* Extended help key */ | ||
375 | out_uint16(s, 0);/* Window activate */ | ||
376 | } | ||
377 | |||
378 | /* Output pointer capability set */ | ||
379 | static void | ||
380 | rdp_out_pointer_caps(STREAM s) | ||
381 | { | ||
382 | out_uint16_le(s, RDP_CAPSET_POINTER); | ||
383 | out_uint16_le(s, RDP_CAPLEN_POINTER); | ||
384 | |||
385 | out_uint16(s, 0);/* Colour pointer */ | ||
386 | out_uint16_le(s, 20);/* Cache size */ | ||
387 | } | ||
388 | |||
389 | /* Output share capability set */ | ||
390 | static void | ||
391 | rdp_out_share_caps(STREAM s) | ||
392 | { | ||
393 | out_uint16_le(s, RDP_CAPSET_SHARE); | ||
394 | out_uint16_le(s, RDP_CAPLEN_SHARE); | ||
395 | |||
396 | out_uint16(s, 0);/* userid */ | ||
397 | out_uint16(s, 0);/* pad */ | ||
398 | } | ||
399 | |||
400 | /* Output colour cache capability set */ | ||
401 | static void | ||
402 | rdp_out_colcache_caps(STREAM s) | ||
403 | { | ||
404 | out_uint16_le(s, RDP_CAPSET_COLCACHE); | ||
405 | out_uint16_le(s, RDP_CAPLEN_COLCACHE); | ||
406 | |||
407 | out_uint16_le(s, 6);/* cache size */ | ||
408 | out_uint16(s, 0);/* pad */ | ||
409 | } | ||
410 | |||
411 | static uint8 canned_caps[] = { | ||
412 | 0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x04, | ||
413 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, | ||
414 | 0x00, 0x00, 0x00, 0x00, 0x00, | ||
415 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
416 | 0x00, 0x00, 0x00, 0x00, 0x00, | ||
417 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
418 | 0x00, 0x00, 0x00, 0x00, 0x00, | ||
419 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
420 | 0x00, 0x00, 0x00, 0x00, 0x00, | ||
421 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
422 | 0x0C, 0x00, 0x08, 0x00, 0x01, | ||
423 | 0x00, 0x00, 0x00, 0x0E, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, | ||
424 | 0x10, 0x00, 0x34, 0x00, 0xFE, | ||
425 | 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x08, 0x00, | ||
426 | 0xFE, 0x00, 0x08, 0x00, 0xFE, | ||
427 | 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00, 0xFE, 0x00, 0x40, 0x00, | ||
428 | 0xFE, 0x00, 0x80, 0x00, 0xFE, | ||
429 | 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, | ||
430 | 0x02, 0x00, 0x00, 0x00 | ||
431 | }; | ||
432 | |||
433 | /* Output unknown capability set */ | ||
434 | static void | ||
435 | rdp_out_unknown_caps(STREAM s) | ||
436 | { | ||
437 | out_uint16_le(s, RDP_CAPSET_UNKNOWN); | ||
438 | out_uint16_le(s, 0x58); | ||
439 | |||
440 | out_uint8p(s, canned_caps, RDP_CAPLEN_UNKNOWN - 4); | ||
441 | } | ||
442 | |||
443 | /* Send a confirm active PDU */ | ||
444 | static void | ||
445 | rdp_send_confirm_active(void) | ||
446 | { | ||
447 | STREAM s; | ||
448 | uint16 caplen = | ||
449 | RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER + | ||
450 | RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE + | ||
451 | RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL + | ||
452 | RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE + RDP_CAPLEN_UNKNOWN + 4 /* w2k fix, why? */ ; | ||
453 | |||
454 | s = rdp_init(14 + caplen + sizeof(RDP_SOURCE)); | ||
455 | |||
456 | out_uint32_le(s, rdp_shareid); | ||
457 | out_uint16_le(s, 0x3ea);/* userid */ | ||
458 | out_uint16_le(s, sizeof(RDP_SOURCE)); | ||
459 | out_uint16_le(s, caplen); | ||
460 | |||
461 | out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE)); | ||
462 | out_uint16_le(s, 0xd);/* num_caps */ | ||
463 | out_uint8s(s, 2);/* pad */ | ||
464 | |||
465 | rdp_out_general_caps(s); | ||
466 | rdp_out_bitmap_caps(s); | ||
467 | rdp_out_order_caps(s); | ||
468 | rdp_out_bmpcache_caps(s); | ||
469 | rdp_out_colcache_caps(s); | ||
470 | rdp_out_activate_caps(s); | ||
471 | rdp_out_control_caps(s); | ||
472 | rdp_out_pointer_caps(s); | ||
473 | rdp_out_share_caps(s); | ||
474 | rdp_out_unknown_caps(s); | ||
475 | |||
476 | s_mark_end(s); | ||
477 | rdp_send(s, RDP_PDU_CONFIRM_ACTIVE); | ||
478 | } | ||
479 | |||
480 | /* Respond to a demand active PDU */ | ||
481 | void | ||
482 | process_demand_active(STREAM s) | ||
483 | { | ||
484 | uint8 type; | ||
485 | |||
486 | in_uint32_le(s, rdp_shareid); | ||
487 | |||
488 | DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", rdp_shareid)); | ||
489 | |||
490 | rdp_send_confirm_active(); | ||
491 | rdp_send_synchronise(); | ||
492 | rdp_send_control(RDP_CTL_COOPERATE); | ||
493 | rdp_send_control(RDP_CTL_REQUEST_CONTROL); | ||
494 | rdp_recv(&type);/* RDP_PDU_SYNCHRONIZE */ | ||
495 | rdp_recv(&type);/* RDP_CTL_COOPERATE */ | ||
496 | rdp_recv(&type);/* RDP_CTL_GRANT_CONTROL */ | ||
497 | rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, 0, 0); | ||
498 | rdp_send_fonts(1); | ||
499 | rdp_send_fonts(2); | ||
500 | rdp_recv(&type);/* RDP_PDU_UNKNOWN 0x28 */ | ||
501 | reset_order_state(); | ||
502 | } | ||
503 | |||
504 | /* Process a pointer PDU */ | ||
505 | static void | ||
506 | process_pointer_pdu(STREAM s) | ||
507 | { | ||
508 | uint16 message_type; | ||
509 | uint16 x, y, width, height, cache_idx, masklen, datalen; | ||
510 | uint8 *mask, *data; | ||
511 | HCURSOR cursor; | ||
512 | |||
513 | in_uint16_le(s, message_type); | ||
514 | in_uint8s(s, 2);/* pad */ | ||
515 | |||
516 | switch (message_type) | ||
517 | { | ||
518 | case RDP_POINTER_MOVE: | ||
519 | in_uint16_le(s, x); | ||
520 | in_uint16_le(s, y); | ||
521 | if (s_check(s)) | ||
522 | ui_move_pointer(x, y); | ||
523 | break; | ||
524 | |||
525 | case RDP_POINTER_COLOR: | ||
526 | in_uint16_le(s, cache_idx); | ||
527 | in_uint16_le(s, x); | ||
528 | in_uint16_le(s, y); | ||
529 | in_uint16_le(s, width); | ||
530 | in_uint16_le(s, height); | ||
531 | in_uint16_le(s, masklen); | ||
532 | in_uint16_le(s, datalen); | ||
533 | in_uint8p(s, data, datalen); | ||
534 | in_uint8p(s, mask, masklen); | ||
535 | cursor = ui_create_cursor(x, y, width, height, mask, data); | ||
536 | ui_set_cursor(cursor); | ||
537 | cache_put_cursor(cache_idx, cursor); | ||
538 | break; | ||
539 | |||
540 | case RDP_POINTER_CACHED: | ||
541 | in_uint16_le(s, cache_idx); | ||
542 | ui_set_cursor(cache_get_cursor(cache_idx)); | ||
543 | break; | ||
544 | |||
545 | default: | ||
546 | DEBUG(("Pointer message 0x%x\n", message_type)); | ||
547 | } | ||
548 | } | ||
549 | |||
550 | /* Process bitmap updates */ | ||
551 | static void | ||
552 | process_bitmap_updates(STREAM s) | ||
553 | { | ||
554 | uint16 num_updates; | ||
555 | uint16 left, top, right, bottom, width, height; | ||
556 | uint16 cx, cy, bpp, Bpp, compress, bufsize, size; | ||
557 | uint8 *data, *bmpdata; | ||
558 | int i; | ||
559 | |||
560 | in_uint16_le(s, num_updates); | ||
561 | |||
562 | for (i = 0; i < num_updates; i++) | ||
563 | { | ||
564 | in_uint16_le(s, left); | ||
565 | in_uint16_le(s, top); | ||
566 | in_uint16_le(s, right); | ||
567 | in_uint16_le(s, bottom); | ||
568 | in_uint16_le(s, width); | ||
569 | in_uint16_le(s, height); | ||
570 | in_uint16_le(s, bpp); | ||
571 | Bpp = (bpp + 7) / 8; | ||
572 | in_uint16_le(s, compress); | ||
573 | in_uint16_le(s, bufsize); | ||
574 | |||
575 | cx = right - left + 1; | ||
576 | cy = bottom - top + 1; | ||
577 | |||
578 | DEBUG(("UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,cmp=%d)\n", | ||
579 | left, top, right, bottom, width, height, compress)); | ||
580 | |||
581 | if (!compress) | ||
582 | { | ||
583 | int y; | ||
584 | bmpdata = (uint8*)xmalloc(width * height * Bpp); | ||
585 | for (y = 0; y < height; y++) | ||
586 | { | ||
587 | in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)], | ||
588 | width * Bpp); | ||
589 | } | ||
590 | ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata); | ||
591 | xfree(bmpdata); | ||
592 | continue; | ||
593 | } | ||
594 | |||
595 | in_uint8s(s, 2);/* pad */ | ||
596 | in_uint16_le(s, size); | ||
597 | in_uint8s(s, 4);/* line_size, final_size */ | ||
598 | in_uint8p(s, data, size); | ||
599 | bmpdata = (uint8*)xmalloc(width * height * Bpp); | ||
600 | if (bitmap_decompress(bmpdata, width, height, data, size, Bpp)) | ||
601 | { | ||
602 | ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata); | ||
603 | } | ||
604 | xfree(bmpdata); | ||
605 | } | ||
606 | } | ||
607 | |||
608 | /* Process a palette update */ | ||
609 | static void | ||
610 | process_palette(STREAM s) | ||
611 | { | ||
612 | COLOURENTRY *entry; | ||
613 | COLOURMAP map; | ||
614 | HCOLOURMAP hmap; | ||
615 | int i; | ||
616 | uint8 data[1536]; | ||
617 | |||
618 | in_uint8s(s, 2);/* pad */ | ||
619 | in_uint16_le(s, map.ncolours); | ||
620 | in_uint8s(s, 2);/* pad */ | ||
621 | |||
622 | map.colours = (COLOURENTRY*)data; | ||
623 | |||
624 | for (i = 0; i < map.ncolours; i++) | ||
625 | { | ||
626 | entry = &map.colours[i]; | ||
627 | in_uint8(s, entry->red); | ||
628 | in_uint8(s, entry->green); | ||
629 | in_uint8(s, entry->blue); | ||
630 | } | ||
631 | hmap = ui_create_colourmap(&map); | ||
632 | ui_set_colourmap(hmap); | ||
633 | } | ||
634 | |||
635 | /* Process an update PDU */ | ||
636 | static void | ||
637 | process_update_pdu(STREAM s) | ||
638 | { | ||
639 | uint16 update_type; | ||
640 | |||
641 | in_uint16_le(s, update_type); | ||
642 | ui_begin_update(); | ||
643 | switch (update_type) | ||
644 | { | ||
645 | case RDP_UPDATE_ORDERS: | ||
646 | process_orders(s); | ||
647 | break; | ||
648 | |||
649 | case RDP_UPDATE_BITMAP: | ||
650 | process_bitmap_updates(s); | ||
651 | break; | ||
652 | |||
653 | case RDP_UPDATE_PALETTE: | ||
654 | process_palette(s); | ||
655 | break; | ||
656 | |||
657 | case RDP_UPDATE_SYNCHRONIZE: | ||
658 | break; | ||
659 | |||
660 | default: | ||
661 | unimpl("update %d\n", update_type); | ||
662 | } | ||
663 | ui_end_update(); | ||
664 | } | ||
665 | |||
666 | /* Process data PDU */ | ||
667 | void | ||
668 | process_data_pdu(STREAM s) | ||
669 | { | ||
670 | uint8 data_pdu_type; | ||
671 | |||
672 | in_uint8s(s, 8);/* shareid, pad, streamid, length */ | ||
673 | in_uint8(s, data_pdu_type); | ||
674 | in_uint8s(s, 3);/* compress_type, compress_len */ | ||
675 | |||
676 | switch (data_pdu_type) | ||
677 | { | ||
678 | case RDP_DATA_PDU_UPDATE: | ||
679 | process_update_pdu(s); | ||
680 | break; | ||
681 | |||
682 | case RDP_DATA_PDU_POINTER: | ||
683 | process_pointer_pdu(s); | ||
684 | break; | ||
685 | |||
686 | case RDP_DATA_PDU_BELL: | ||
687 | ui_bell(); | ||
688 | break; | ||
689 | |||
690 | case RDP_DATA_PDU_LOGON: | ||
691 | /* User logged on */ | ||
692 | break; | ||
693 | |||
694 | default: | ||
695 | unimpl("data PDU %d\n", data_pdu_type); | ||
696 | } | ||
697 | } | ||
698 | |||
699 | /* Process incoming packets */ | ||
700 | BOOL | ||
701 | rdp_main_loop(void) | ||
702 | { | ||
703 | uint8 type; | ||
704 | STREAM s; | ||
705 | BOOL cont = True; | ||
706 | while (cont) | ||
707 | { | ||
708 | s = rdp_recv(&type); | ||
709 | if (s == NULL) | ||
710 | return False; | ||
711 | switch (type) | ||
712 | { | ||
713 | case RDP_PDU_DEMAND_ACTIVE: | ||
714 | process_demand_active(s); | ||
715 | break; | ||
716 | case RDP_PDU_DEACTIVATE: | ||
717 | break; | ||
718 | case RDP_PDU_DATA: | ||
719 | process_data_pdu(s); | ||
720 | break; | ||
721 | case 0: | ||
722 | break; | ||
723 | default: | ||
724 | unimpl("PDU %d\n", type); | ||
725 | } | ||
726 | cont = next_packet < s->end; | ||
727 | } | ||
728 | return True; | ||
729 | } | ||
730 | |||
731 | /* Establish a connection up to the RDP layer */ | ||
732 | BOOL | ||
733 | rdp_connect(char *server, uint32 flags, char *domain, char *password, | ||
734 | char *command, char *directory) | ||
735 | { | ||
736 | if (!sec_connect(server)) | ||
737 | return False; | ||
738 | |||
739 | rdp_send_logon_info(flags, domain, username, password, command, directory); | ||
740 | return True; | ||
741 | } | ||
742 | |||
743 | /* Disconnect from the RDP layer */ | ||
744 | void | ||
745 | rdp_disconnect(void) | ||
746 | { | ||
747 | sec_disconnect(); | ||
748 | } | ||