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