1 /* -*- c-basic-offset: 8 -*- 2 rdesktop: A Remote Desktop Protocol client. 3 RDP order processing 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 "rdesktop.h" 22 #include "orders.h" 23 24 /* Read field indicating which parameters are present */ 25 static void 26 rdp_in_present(STREAM s, uint32 * present, uint8 flags, int size) 27 { 28 uint8 bits; 29 int i; 30 31 if (flags & RDP_ORDER_SMALL) 32 { 33 size--; 34 } 35 36 if (flags & RDP_ORDER_TINY) 37 { 38 if (size < 2) 39 size = 0; 40 else 41 size -= 2; 42 } 43 44 *present = 0; 45 for (i = 0; i < size; i++) 46 { 47 in_uint8(s, bits); 48 *present |= bits << (i * 8); 49 } 50 } 51 52 /* Read a co-ordinate (16-bit, or 8-bit delta) */ 53 static void 54 rdp_in_coord(STREAM s, sint16 * coord, BOOL delta) 55 { 56 sint8 change; 57 58 if (delta) 59 { 60 in_uint8(s, change); 61 *coord += change; 62 } 63 else 64 { 65 in_uint16_le(s, *coord); 66 } 67 } 68 69 /* Parse a delta co-ordinate in polyline/polygon order form */ 70 static int 71 parse_delta(uint8 * buffer, int *offset) 72 { 73 int value = buffer[(*offset)++]; 74 int two_byte = value & 0x80; 75 76 if (value & 0x40) /* sign bit */ 77 value |= ~0x3f; 78 else 79 value &= 0x3f; 80 81 if (two_byte) 82 value = (value << 8) | buffer[(*offset)++]; 83 84 return value; 85 } 86 87 /* Read a colour entry */ 88 static void 89 rdp_in_colour(STREAM s, uint32 * colour) 90 { 91 uint32 i; 92 in_uint8(s, i); 93 *colour = i; 94 in_uint8(s, i); 95 *colour |= i << 8; 96 in_uint8(s, i); 97 *colour |= i << 16; 98 } 99 100 /* Parse bounds information */ 101 static BOOL 102 rdp_parse_bounds(STREAM s, BOUNDS * bounds) 103 { 104 uint8 present; 105 106 in_uint8(s, present); 107 108 if (present & 1) 109 rdp_in_coord(s, &bounds->left, False); 110 else if (present & 16) 111 rdp_in_coord(s, &bounds->left, True); 112 113 if (present & 2) 114 rdp_in_coord(s, &bounds->top, False); 115 else if (present & 32) 116 rdp_in_coord(s, &bounds->top, True); 117 118 if (present & 4) 119 rdp_in_coord(s, &bounds->right, False); 120 else if (present & 64) 121 rdp_in_coord(s, &bounds->right, True); 122 123 if (present & 8) 124 rdp_in_coord(s, &bounds->bottom, False); 125 else if (present & 128) 126 rdp_in_coord(s, &bounds->bottom, True); 127 128 return s_check(s); 129 } 130 131 /* Parse a pen */ 132 static BOOL 133 rdp_parse_pen(STREAM s, PEN * pen, uint32 present) 134 { 135 if (present & 1) 136 in_uint8(s, pen->style); 137 138 if (present & 2) 139 in_uint8(s, pen->width); 140 141 if (present & 4) 142 rdp_in_colour(s, &pen->colour); 143 144 return s_check(s); 145 } 146 147 /* Parse a brush */ 148 static BOOL 149 rdp_parse_brush(STREAM s, BRUSH * brush, uint32 present) 150 { 151 if (present & 1) 152 in_uint8(s, brush->xorigin); 153 154 if (present & 2) 155 in_uint8(s, brush->yorigin); 156 157 if (present & 4) 158 in_uint8(s, brush->style); 159 160 if (present & 8) 161 in_uint8(s, brush->pattern[0]); 162 163 if (present & 16) 164 in_uint8a(s, &brush->pattern[1], 7); 165 166 return s_check(s); 167 } 168 169 /* Process a destination blt order */ 170 static void 171 process_destblt(RDPCLIENT * This, STREAM s, DESTBLT_ORDER * os, uint32 present, BOOL delta) 172 { 173 if (present & 0x01) 174 rdp_in_coord(s, &os->x, delta); 175 176 if (present & 0x02) 177 rdp_in_coord(s, &os->y, delta); 178 179 if (present & 0x04) 180 rdp_in_coord(s, &os->cx, delta); 181 182 if (present & 0x08) 183 rdp_in_coord(s, &os->cy, delta); 184 185 if (present & 0x10) 186 in_uint8(s, os->opcode); 187 188 DEBUG(("DESTBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d)\n", 189 os->opcode, os->x, os->y, os->cx, os->cy)); 190 191 #if 0 192 ui_destblt(This, ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy); 193 #else 194 ui_destblt(This, os->opcode, os->x, os->y, os->cx, os->cy); 195 #endif 196 } 197 198 /* Process a pattern blt order */ 199 static void 200 process_patblt(RDPCLIENT * This, STREAM s, PATBLT_ORDER * os, uint32 present, BOOL delta) 201 { 202 if (present & 0x0001) 203 rdp_in_coord(s, &os->x, delta); 204 205 if (present & 0x0002) 206 rdp_in_coord(s, &os->y, delta); 207 208 if (present & 0x0004) 209 rdp_in_coord(s, &os->cx, delta); 210 211 if (present & 0x0008) 212 rdp_in_coord(s, &os->cy, delta); 213 214 if (present & 0x0010) 215 in_uint8(s, os->opcode); 216 217 if (present & 0x0020) 218 rdp_in_colour(s, &os->bgcolour); 219 220 if (present & 0x0040) 221 rdp_in_colour(s, &os->fgcolour); 222 223 rdp_parse_brush(s, &os->brush, present >> 7); 224 225 DEBUG(("PATBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,bs=%d,bg=0x%x,fg=0x%x)\n", os->opcode, os->x, 226 os->y, os->cx, os->cy, os->brush.style, os->bgcolour, os->fgcolour)); 227 228 #if 0 229 ui_patblt(This, ROP2_P(os->opcode), os->x, os->y, os->cx, os->cy, 230 &os->brush, os->bgcolour, os->fgcolour); 231 #else 232 ui_patblt(This, os->opcode, os->x, os->y, os->cx, os->cy, 233 &os->brush, os->bgcolour, os->fgcolour); 234 #endif 235 } 236 237 /* Process a screen blt order */ 238 static void 239 process_screenblt(RDPCLIENT * This, STREAM s, SCREENBLT_ORDER * os, uint32 present, BOOL delta) 240 { 241 if (present & 0x0001) 242 rdp_in_coord(s, &os->x, delta); 243 244 if (present & 0x0002) 245 rdp_in_coord(s, &os->y, delta); 246 247 if (present & 0x0004) 248 rdp_in_coord(s, &os->cx, delta); 249 250 if (present & 0x0008) 251 rdp_in_coord(s, &os->cy, delta); 252 253 if (present & 0x0010) 254 in_uint8(s, os->opcode); 255 256 if (present & 0x0020) 257 rdp_in_coord(s, &os->srcx, delta); 258 259 if (present & 0x0040) 260 rdp_in_coord(s, &os->srcy, delta); 261 262 DEBUG(("SCREENBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,srcx=%d,srcy=%d)\n", 263 os->opcode, os->x, os->y, os->cx, os->cy, os->srcx, os->srcy)); 264 265 #if 0 266 ui_screenblt(This, ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy, os->srcx, os->srcy); 267 #else 268 ui_screenblt(This, os->opcode, os->x, os->y, os->cx, os->cy, os->srcx, os->srcy); 269 #endif 270 } 271 272 /* Process a line order */ 273 static void 274 process_line(RDPCLIENT * This, STREAM s, LINE_ORDER * os, uint32 present, BOOL delta) 275 { 276 if (present & 0x0001) 277 in_uint16_le(s, os->mixmode); 278 279 if (present & 0x0002) 280 rdp_in_coord(s, &os->startx, delta); 281 282 if (present & 0x0004) 283 rdp_in_coord(s, &os->starty, delta); 284 285 if (present & 0x0008) 286 rdp_in_coord(s, &os->endx, delta); 287 288 if (present & 0x0010) 289 rdp_in_coord(s, &os->endy, delta); 290 291 if (present & 0x0020) 292 rdp_in_colour(s, &os->bgcolour); 293 294 if (present & 0x0040) 295 in_uint8(s, os->opcode); 296 297 rdp_parse_pen(s, &os->pen, present >> 7); 298 299 DEBUG(("LINE(op=0x%x,sx=%d,sy=%d,dx=%d,dy=%d,fg=0x%x)\n", 300 os->opcode, os->startx, os->starty, os->endx, os->endy, os->pen.colour)); 301 302 if (os->opcode < 0x01 || os->opcode > 0x10) 303 { 304 error("bad ROP2 0x%x\n", os->opcode); 305 return; 306 } 307 308 #if 0 309 ui_line(This, os->opcode - 1, os->startx, os->starty, os->endx, os->endy, &os->pen); 310 #else 311 ui_line(This, os->opcode, os->startx, os->starty, os->endx, os->endy, &os->pen); 312 #endif 313 } 314 315 /* Process an opaque rectangle order */ 316 static void 317 process_rect(RDPCLIENT * This, STREAM s, RECT_ORDER * os, uint32 present, BOOL delta) 318 { 319 uint32 i; 320 if (present & 0x01) 321 rdp_in_coord(s, &os->x, delta); 322 323 if (present & 0x02) 324 rdp_in_coord(s, &os->y, delta); 325 326 if (present & 0x04) 327 rdp_in_coord(s, &os->cx, delta); 328 329 if (present & 0x08) 330 rdp_in_coord(s, &os->cy, delta); 331 332 if (present & 0x10) 333 { 334 in_uint8(s, i); 335 os->colour = (os->colour & 0xffffff00) | i; 336 } 337 338 if (present & 0x20) 339 { 340 in_uint8(s, i); 341 os->colour = (os->colour & 0xffff00ff) | (i << 8); 342 } 343 344 if (present & 0x40) 345 { 346 in_uint8(s, i); 347 os->colour = (os->colour & 0xff00ffff) | (i << 16); 348 } 349 350 DEBUG(("RECT(x=%d,y=%d,cx=%d,cy=%d,fg=0x%x)\n", os->x, os->y, os->cx, os->cy, os->colour)); 351 352 ui_rect(This, os->x, os->y, os->cx, os->cy, os->colour); 353 } 354 355 /* Process a desktop save order */ 356 static void 357 process_desksave(RDPCLIENT * This, STREAM s, DESKSAVE_ORDER * os, uint32 present, BOOL delta) 358 { 359 int width, height; 360 361 if (present & 0x01) 362 in_uint32_le(s, os->offset); 363 364 if (present & 0x02) 365 rdp_in_coord(s, &os->left, delta); 366 367 if (present & 0x04) 368 rdp_in_coord(s, &os->top, delta); 369 370 if (present & 0x08) 371 rdp_in_coord(s, &os->right, delta); 372 373 if (present & 0x10) 374 rdp_in_coord(s, &os->bottom, delta); 375 376 if (present & 0x20) 377 in_uint8(s, os->action); 378 379 DEBUG(("DESKSAVE(l=%d,t=%d,r=%d,b=%d,off=%d,op=%d)\n", 380 os->left, os->top, os->right, os->bottom, os->offset, os->action)); 381 382 width = os->right - os->left + 1; 383 height = os->bottom - os->top + 1; 384 385 if (os->action == 0) 386 ui_desktop_save(This, os->offset, os->left, os->top, width, height); 387 else 388 ui_desktop_restore(This, os->offset, os->left, os->top, width, height); 389 } 390 391 /* Process a memory blt order */ 392 static void 393 process_memblt(RDPCLIENT * This, STREAM s, MEMBLT_ORDER * os, uint32 present, BOOL delta) 394 { 395 HBITMAP bitmap; 396 397 if (present & 0x0001) 398 { 399 in_uint8(s, os->cache_id); 400 in_uint8(s, os->colour_table); 401 } 402 403 if (present & 0x0002) 404 rdp_in_coord(s, &os->x, delta); 405 406 if (present & 0x0004) 407 rdp_in_coord(s, &os->y, delta); 408 409 if (present & 0x0008) 410 rdp_in_coord(s, &os->cx, delta); 411 412 if (present & 0x0010) 413 rdp_in_coord(s, &os->cy, delta); 414 415 if (present & 0x0020) 416 in_uint8(s, os->opcode); 417 418 if (present & 0x0040) 419 rdp_in_coord(s, &os->srcx, delta); 420 421 if (present & 0x0080) 422 rdp_in_coord(s, &os->srcy, delta); 423 424 if (present & 0x0100) 425 in_uint16_le(s, os->cache_idx); 426 427 DEBUG(("MEMBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,id=%d,idx=%d)\n", 428 os->opcode, os->x, os->y, os->cx, os->cy, os->cache_id, os->cache_idx)); 429 430 bitmap = cache_get_bitmap(This, os->cache_id, os->cache_idx); 431 if (bitmap == NULL) 432 return; 433 434 #if 0 435 ui_memblt(This, ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy, bitmap, os->srcx, os->srcy); 436 #else 437 ui_memblt(This, os->opcode, os->x, os->y, os->cx, os->cy, bitmap, os->srcx, os->srcy); 438 #endif 439 } 440 441 /* Process a 3-way blt order */ 442 static void 443 process_triblt(RDPCLIENT * This, STREAM s, TRIBLT_ORDER * os, uint32 present, BOOL delta) 444 { 445 HBITMAP bitmap; 446 447 if (present & 0x000001) 448 { 449 in_uint8(s, os->cache_id); 450 in_uint8(s, os->colour_table); 451 } 452 453 if (present & 0x000002) 454 rdp_in_coord(s, &os->x, delta); 455 456 if (present & 0x000004) 457 rdp_in_coord(s, &os->y, delta); 458 459 if (present & 0x000008) 460 rdp_in_coord(s, &os->cx, delta); 461 462 if (present & 0x000010) 463 rdp_in_coord(s, &os->cy, delta); 464 465 if (present & 0x000020) 466 in_uint8(s, os->opcode); 467 468 if (present & 0x000040) 469 rdp_in_coord(s, &os->srcx, delta); 470 471 if (present & 0x000080) 472 rdp_in_coord(s, &os->srcy, delta); 473 474 if (present & 0x000100) 475 rdp_in_colour(s, &os->bgcolour); 476 477 if (present & 0x000200) 478 rdp_in_colour(s, &os->fgcolour); 479 480 rdp_parse_brush(s, &os->brush, present >> 10); 481 482 if (present & 0x008000) 483 in_uint16_le(s, os->cache_idx); 484 485 if (present & 0x010000) 486 in_uint16_le(s, os->unknown); 487 488 DEBUG(("TRIBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,id=%d,idx=%d,bs=%d,bg=0x%x,fg=0x%x)\n", 489 os->opcode, os->x, os->y, os->cx, os->cy, os->cache_id, os->cache_idx, 490 os->brush.style, os->bgcolour, os->fgcolour)); 491 492 bitmap = cache_get_bitmap(This, os->cache_id, os->cache_idx); 493 if (bitmap == NULL) 494 return; 495 496 ui_triblt(This, os->opcode, os->x, os->y, os->cx, os->cy, 497 bitmap, os->srcx, os->srcy, &os->brush, os->bgcolour, os->fgcolour); 498 } 499 500 /* Process a polygon order */ 501 static void 502 process_polygon(RDPCLIENT * This, STREAM s, POLYGON_ORDER * os, uint32 present, BOOL delta) 503 { 504 int index, data, next; 505 uint8 flags = 0; 506 POINT *points; 507 508 if (present & 0x01) 509 rdp_in_coord(s, &os->x, delta); 510 511 if (present & 0x02) 512 rdp_in_coord(s, &os->y, delta); 513 514 if (present & 0x04) 515 in_uint8(s, os->opcode); 516 517 if (present & 0x08) 518 in_uint8(s, os->fillmode); 519 520 if (present & 0x10) 521 rdp_in_colour(s, &os->fgcolour); 522 523 if (present & 0x20) 524 in_uint8(s, os->npoints); 525 526 if (present & 0x40) 527 { 528 in_uint8(s, os->datasize); 529 in_uint8a(s, os->data, os->datasize); 530 } 531 532 DEBUG(("POLYGON(x=%d,y=%d,op=0x%x,fm=%d,fg=0x%x,n=%d,sz=%d)\n", 533 os->x, os->y, os->opcode, os->fillmode, os->fgcolour, os->npoints, os->datasize)); 534 535 DEBUG(("Data: ")); 536 537 for (index = 0; index < os->datasize; index++) 538 DEBUG(("%02x ", os->data[index])); 539 540 DEBUG(("\n")); 541 542 if (os->opcode < 0x01 || os->opcode > 0x10) 543 { 544 error("bad ROP2 0x%x\n", os->opcode); 545 return; 546 } 547 548 points = (POINT *) malloc((os->npoints + 1) * sizeof(POINT)); 549 550 if(points == NULL) 551 return; 552 553 memset(points, 0, (os->npoints + 1) * sizeof(POINT)); 554 555 points[0].x = os->x; 556 points[0].y = os->y; 557 558 index = 0; 559 data = ((os->npoints - 1) / 4) + 1; 560 for (next = 1; (next <= os->npoints) && (next < 256) && (data < os->datasize); next++) 561 { 562 if ((next - 1) % 4 == 0) 563 flags = os->data[index++]; 564 565 if (~flags & 0x80) 566 points[next].x = parse_delta(os->data, &data); 567 568 if (~flags & 0x40) 569 points[next].y = parse_delta(os->data, &data); 570 571 flags <<= 2; 572 } 573 574 if (next - 1 == os->npoints) 575 #if 0 576 ui_polygon(This, os->opcode - 1, os->fillmode, points, os->npoints + 1, NULL, 0, 577 os->fgcolour); 578 #else 579 ui_polygon(This, os->opcode, os->fillmode, points, os->npoints + 1, NULL, 0, 580 os->fgcolour); 581 #endif 582 else 583 error("polygon parse error\n"); 584 585 free(points); 586 } 587 588 /* Process a polygon2 order */ 589 static void 590 process_polygon2(RDPCLIENT * This, STREAM s, POLYGON2_ORDER * os, uint32 present, BOOL delta) 591 { 592 int index, data, next; 593 uint8 flags = 0; 594 POINT *points; 595 596 if (present & 0x0001) 597 rdp_in_coord(s, &os->x, delta); 598 599 if (present & 0x0002) 600 rdp_in_coord(s, &os->y, delta); 601 602 if (present & 0x0004) 603 in_uint8(s, os->opcode); 604 605 if (present & 0x0008) 606 in_uint8(s, os->fillmode); 607 608 if (present & 0x0010) 609 rdp_in_colour(s, &os->bgcolour); 610 611 if (present & 0x0020) 612 rdp_in_colour(s, &os->fgcolour); 613 614 rdp_parse_brush(s, &os->brush, present >> 6); 615 616 if (present & 0x0800) 617 in_uint8(s, os->npoints); 618 619 if (present & 0x1000) 620 { 621 in_uint8(s, os->datasize); 622 in_uint8a(s, os->data, os->datasize); 623 } 624 625 DEBUG(("POLYGON2(x=%d,y=%d,op=0x%x,fm=%d,bs=%d,bg=0x%x,fg=0x%x,n=%d,sz=%d)\n", 626 os->x, os->y, os->opcode, os->fillmode, os->brush.style, os->bgcolour, os->fgcolour, 627 os->npoints, os->datasize)); 628 629 DEBUG(("Data: ")); 630 631 for (index = 0; index < os->datasize; index++) 632 DEBUG(("%02x ", os->data[index])); 633 634 DEBUG(("\n")); 635 636 if (os->opcode < 0x01 || os->opcode > 0x10) 637 { 638 error("bad ROP2 0x%x\n", os->opcode); 639 return; 640 } 641 642 points = (POINT *) malloc((os->npoints + 1) * sizeof(POINT)); 643 644 if(points == NULL) 645 return; 646 647 memset(points, 0, (os->npoints + 1) * sizeof(POINT)); 648 649 points[0].x = os->x; 650 points[0].y = os->y; 651 652 index = 0; 653 data = ((os->npoints - 1) / 4) + 1; 654 for (next = 1; (next <= os->npoints) && (next < 256) && (data < os->datasize); next++) 655 { 656 if ((next - 1) % 4 == 0) 657 flags = os->data[index++]; 658 659 if (~flags & 0x80) 660 points[next].x = parse_delta(os->data, &data); 661 662 if (~flags & 0x40) 663 points[next].y = parse_delta(os->data, &data); 664 665 flags <<= 2; 666 } 667 668 if (next - 1 == os->npoints) 669 #if 0 670 ui_polygon(This, os->opcode - 1, os->fillmode, points, os->npoints + 1, 671 &os->brush, os->bgcolour, os->fgcolour); 672 #else 673 ui_polygon(This, os->opcode, os->fillmode, points, os->npoints + 1, 674 &os->brush, os->bgcolour, os->fgcolour); 675 #endif 676 else 677 error("polygon2 parse error\n"); 678 679 free(points); 680 } 681 682 /* Process a polyline order */ 683 static void 684 process_polyline(RDPCLIENT * This, STREAM s, POLYLINE_ORDER * os, uint32 present, BOOL delta) 685 { 686 int index, next, data; 687 uint8 flags = 0; 688 PEN pen; 689 POINT *points; 690 691 if (present & 0x01) 692 rdp_in_coord(s, &os->x, delta); 693 694 if (present & 0x02) 695 rdp_in_coord(s, &os->y, delta); 696 697 if (present & 0x04) 698 in_uint8(s, os->opcode); 699 700 if (present & 0x10) 701 rdp_in_colour(s, &os->fgcolour); 702 703 if (present & 0x20) 704 in_uint8(s, os->lines); 705 706 if (present & 0x40) 707 { 708 in_uint8(s, os->datasize); 709 in_uint8a(s, os->data, os->datasize); 710 } 711 712 DEBUG(("POLYLINE(x=%d,y=%d,op=0x%x,fg=0x%x,n=%d,sz=%d)\n", 713 os->x, os->y, os->opcode, os->fgcolour, os->lines, os->datasize)); 714 715 DEBUG(("Data: ")); 716 717 for (index = 0; index < os->datasize; index++) 718 DEBUG(("%02x ", os->data[index])); 719 720 DEBUG(("\n")); 721 722 if (os->opcode < 0x01 || os->opcode > 0x10) 723 { 724 error("bad ROP2 0x%x\n", os->opcode); 725 return; 726 } 727 728 points = (POINT *) malloc((os->lines + 1) * sizeof(POINT)); 729 730 if(points == NULL) 731 return; 732 733 memset(points, 0, (os->lines + 1) * sizeof(POINT)); 734 735 points[0].x = os->x; 736 points[0].y = os->y; 737 pen.style = pen.width = 0; 738 pen.colour = os->fgcolour; 739 740 index = 0; 741 data = ((os->lines - 1) / 4) + 1; 742 for (next = 1; (next <= os->lines) && (data < os->datasize); next++) 743 { 744 if ((next - 1) % 4 == 0) 745 flags = os->data[index++]; 746 747 if (~flags & 0x80) 748 points[next].x = parse_delta(os->data, &data); 749 750 if (~flags & 0x40) 751 points[next].y = parse_delta(os->data, &data); 752 753 flags <<= 2; 754 } 755 756 if (next - 1 == os->lines) 757 #if 0 758 ui_polyline(This, os->opcode - 1, points, os->lines + 1, &pen); 759 #else 760 ui_polyline(This, os->opcode, points, os->lines + 1, &pen); 761 #endif 762 else 763 error("polyline parse error\n"); 764 765 free(points); 766 } 767 768 /* Process an ellipse order */ 769 static void 770 process_ellipse(RDPCLIENT * This, STREAM s, ELLIPSE_ORDER * os, uint32 present, BOOL delta) 771 { 772 if (present & 0x01) 773 rdp_in_coord(s, &os->left, delta); 774 775 if (present & 0x02) 776 rdp_in_coord(s, &os->top, delta); 777 778 if (present & 0x04) 779 rdp_in_coord(s, &os->right, delta); 780 781 if (present & 0x08) 782 rdp_in_coord(s, &os->bottom, delta); 783 784 if (present & 0x10) 785 in_uint8(s, os->opcode); 786 787 if (present & 0x20) 788 in_uint8(s, os->fillmode); 789 790 if (present & 0x40) 791 rdp_in_colour(s, &os->fgcolour); 792 793 DEBUG(("ELLIPSE(l=%d,t=%d,r=%d,b=%d,op=0x%x,fm=%d,fg=0x%x)\n", os->left, os->top, 794 os->right, os->bottom, os->opcode, os->fillmode, os->fgcolour)); 795 796 #if 0 797 ui_ellipse(This, os->opcode - 1, os->fillmode, os->left, os->top, os->right - os->left, 798 os->bottom - os->top, NULL, 0, os->fgcolour); 799 #else 800 ui_ellipse(This, os->opcode, os->fillmode, os->left, os->top, os->right - os->left, 801 os->bottom - os->top, NULL, 0, os->fgcolour); 802 #endif 803 } 804 805 /* Process an ellipse2 order */ 806 static void 807 process_ellipse2(RDPCLIENT * This, STREAM s, ELLIPSE2_ORDER * os, uint32 present, BOOL delta) 808 { 809 if (present & 0x0001) 810 rdp_in_coord(s, &os->left, delta); 811 812 if (present & 0x0002) 813 rdp_in_coord(s, &os->top, delta); 814 815 if (present & 0x0004) 816 rdp_in_coord(s, &os->right, delta); 817 818 if (present & 0x0008) 819 rdp_in_coord(s, &os->bottom, delta); 820 821 if (present & 0x0010) 822 in_uint8(s, os->opcode); 823 824 if (present & 0x0020) 825 in_uint8(s, os->fillmode); 826 827 if (present & 0x0040) 828 rdp_in_colour(s, &os->bgcolour); 829 830 if (present & 0x0080) 831 rdp_in_colour(s, &os->fgcolour); 832 833 rdp_parse_brush(s, &os->brush, present >> 8); 834 835 DEBUG(("ELLIPSE2(l=%d,t=%d,r=%d,b=%d,op=0x%x,fm=%d,bs=%d,bg=0x%x,fg=0x%x)\n", 836 os->left, os->top, os->right, os->bottom, os->opcode, os->fillmode, os->brush.style, 837 os->bgcolour, os->fgcolour)); 838 839 #if 0 840 ui_ellipse(This, os->opcode - 1, os->fillmode, os->left, os->top, os->right - os->left, 841 os->bottom - os->top, &os->brush, os->bgcolour, os->fgcolour); 842 #else 843 ui_ellipse(This, os->opcode, os->fillmode, os->left, os->top, os->right - os->left, 844 os->bottom - os->top, &os->brush, os->bgcolour, os->fgcolour); 845 #endif 846 } 847 848 /* Process a text order */ 849 static void 850 process_text2(RDPCLIENT * This, STREAM s, TEXT2_ORDER * os, uint32 present, BOOL delta) 851 { 852 int i; 853 854 if (present & 0x000001) 855 in_uint8(s, os->font); 856 857 if (present & 0x000002) 858 in_uint8(s, os->flags); 859 860 if (present & 0x000004) 861 in_uint8(s, os->opcode); 862 863 if (present & 0x000008) 864 in_uint8(s, os->mixmode); 865 866 if (present & 0x000010) 867 rdp_in_colour(s, &os->fgcolour); 868 869 if (present & 0x000020) 870 rdp_in_colour(s, &os->bgcolour); 871 872 if (present & 0x000040) 873 in_uint16_le(s, os->clipleft); 874 875 if (present & 0x000080) 876 in_uint16_le(s, os->cliptop); 877 878 if (present & 0x000100) 879 in_uint16_le(s, os->clipright); 880 881 if (present & 0x000200) 882 in_uint16_le(s, os->clipbottom); 883 884 if (present & 0x000400) 885 in_uint16_le(s, os->boxleft); 886 887 if (present & 0x000800) 888 in_uint16_le(s, os->boxtop); 889 890 if (present & 0x001000) 891 in_uint16_le(s, os->boxright); 892 893 if (present & 0x002000) 894 in_uint16_le(s, os->boxbottom); 895 896 rdp_parse_brush(s, &os->brush, present >> 14); 897 898 if (present & 0x080000) 899 in_uint16_le(s, os->x); 900 901 if (present & 0x100000) 902 in_uint16_le(s, os->y); 903 904 if (present & 0x200000) 905 { 906 in_uint8(s, os->length); 907 in_uint8a(s, os->text, os->length); 908 } 909 910 DEBUG(("TEXT2(x=%d,y=%d,cl=%d,ct=%d,cr=%d,cb=%d,bl=%d,bt=%d,br=%d,bb=%d,bs=%d,bg=0x%x,fg=0x%x,font=%d,fl=0x%x,op=0x%x,mix=%d,n=%d)\n", os->x, os->y, os->clipleft, os->cliptop, os->clipright, os->clipbottom, os->boxleft, os->boxtop, os->boxright, os->boxbottom, os->brush.style, os->bgcolour, os->fgcolour, os->font, os->flags, os->opcode, os->mixmode, os->length)); 911 912 DEBUG(("Text: ")); 913 914 for (i = 0; i < os->length; i++) 915 DEBUG(("%02x ", os->text[i])); 916 917 DEBUG(("\n")); 918 919 #if 0 920 ui_draw_text(This, os->font, os->flags, os->opcode - 1, os->mixmode, os->x, os->y, 921 os->clipleft, os->cliptop, os->clipright - os->clipleft, 922 os->clipbottom - os->cliptop, os->boxleft, os->boxtop, 923 os->boxright - os->boxleft, os->boxbottom - os->boxtop, 924 &os->brush, os->bgcolour, os->fgcolour, os->text, os->length); 925 #else 926 ui_draw_text(This, os->font, os->flags, os->opcode, os->mixmode, os->x, os->y, 927 os->clipleft, os->cliptop, os->clipright - os->clipleft, 928 os->clipbottom - os->cliptop, os->boxleft, os->boxtop, 929 os->boxright - os->boxleft, os->boxbottom - os->boxtop, 930 &os->brush, os->bgcolour, os->fgcolour, os->text, os->length); 931 #endif 932 } 933 934 /* Process a raw bitmap cache order */ 935 static void 936 process_raw_bmpcache(RDPCLIENT * This, STREAM s) 937 { 938 HBITMAP bitmap; 939 uint16 cache_idx, bufsize; 940 uint8 cache_id, width, height, bpp, Bpp; 941 uint8 *data; 942 943 in_uint8(s, cache_id); 944 in_uint8s(s, 1); /* pad */ 945 in_uint8(s, width); 946 in_uint8(s, height); 947 in_uint8(s, bpp); 948 Bpp = (bpp + 7) / 8; 949 in_uint16_le(s, bufsize); 950 in_uint16_le(s, cache_idx); 951 in_uint8p(s, data, bufsize); 952 953 DEBUG(("RAW_BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d)\n", width, height, cache_id, cache_idx)); 954 #if 0 955 inverted = (uint8 *) xmalloc(width * height * Bpp); 956 for (y = 0; y < height; y++) 957 { 958 memcpy(&inverted[(height - y - 1) * (width * Bpp)], &data[y * (width * Bpp)], 959 width * Bpp); 960 } 961 #endif 962 963 #if 0 964 bitmap = ui_create_bitmap(This, width, height, inverted); 965 xfree(inverted); 966 #else 967 bitmap = ui_create_bitmap(This, width, height, data); 968 #endif 969 970 cache_put_bitmap(This, cache_id, cache_idx, bitmap); 971 } 972 973 /* Process a bitmap cache order */ 974 static void 975 process_bmpcache(RDPCLIENT * This, STREAM s) 976 { 977 HBITMAP bitmap; 978 uint16 cache_idx, size; 979 uint8 cache_id, width, height, bpp, Bpp; 980 uint8 *data, *bmpdata; 981 uint16 bufsize, pad2, row_size, final_size; 982 uint8 pad1; 983 984 pad2 = row_size = final_size = 0xffff; /* Shut the compiler up */ 985 986 in_uint8(s, cache_id); 987 in_uint8(s, pad1); /* pad */ 988 in_uint8(s, width); 989 in_uint8(s, height); 990 in_uint8(s, bpp); 991 Bpp = (bpp + 7) / 8; 992 in_uint16_le(s, bufsize); /* bufsize */ 993 in_uint16_le(s, cache_idx); 994 995 if (This->use_rdp5) 996 { 997 size = bufsize; 998 } 999 else 1000 { 1001 1002 /* Begin compressedBitmapData */ 1003 in_uint16_le(s, pad2); /* pad */ 1004 in_uint16_le(s, size); 1005 /* in_uint8s(s, 4); *//* row_size, final_size */ 1006 in_uint16_le(s, row_size); 1007 in_uint16_le(s, final_size); 1008 1009 } 1010 in_uint8p(s, data, size); 1011 1012 DEBUG(("BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d,bpp=%d,size=%d,pad1=%d,bufsize=%d,pad2=%d,rs=%d,fs=%d)\n", width, height, cache_id, cache_idx, bpp, size, pad1, bufsize, pad2, row_size, final_size)); 1013 1014 bmpdata = (uint8 *) malloc(width * height * Bpp); 1015 1016 if(bmpdata == NULL) 1017 return; 1018 1019 if (bitmap_decompress(bmpdata, width, height, data, size, Bpp)) 1020 { 1021 bitmap = ui_create_bitmap(This, width, height, bmpdata); 1022 cache_put_bitmap(This, cache_id, cache_idx, bitmap); 1023 } 1024 else 1025 { 1026 DEBUG(("Failed to decompress bitmap data\n")); 1027 } 1028 1029 free(bmpdata); 1030 } 1031 1032 /* Process a bitmap cache v2 order */ 1033 static void 1034 process_bmpcache2(RDPCLIENT * This, STREAM s, uint16 flags, BOOL compressed) 1035 { 1036 HBITMAP bitmap; 1037 uint8 cache_id, cache_idx_low, width, height, Bpp; 1038 uint16 cache_idx, bufsize; 1039 uint8 *data, *bmpdata, *bitmap_id; 1040 1041 bitmap_id = NULL; /* prevent compiler warning */ 1042 cache_id = flags & ID_MASK; 1043 Bpp = ((flags & MODE_MASK) >> MODE_SHIFT) - 2; 1044 1045 if (flags & PERSIST) 1046 { 1047 in_uint8p(s, bitmap_id, 8); 1048 } 1049 1050 if (flags & SQUARE) 1051 { 1052 in_uint8(s, width); 1053 height = width; 1054 } 1055 else 1056 { 1057 in_uint8(s, width); 1058 in_uint8(s, height); 1059 } 1060 1061 in_uint16_be(s, bufsize); 1062 bufsize &= BUFSIZE_MASK; 1063 in_uint8(s, cache_idx); 1064 1065 if (cache_idx & LONG_FORMAT) 1066 { 1067 in_uint8(s, cache_idx_low); 1068 cache_idx = ((cache_idx ^ LONG_FORMAT) << 8) + cache_idx_low; 1069 } 1070 1071 in_uint8p(s, data, bufsize); 1072 1073 DEBUG(("BMPCACHE2(compr=%d,flags=%x,cx=%d,cy=%d,id=%d,idx=%d,Bpp=%d,bs=%d)\n", 1074 compressed, flags, width, height, cache_id, cache_idx, Bpp, bufsize)); 1075 1076 if (compressed) 1077 { 1078 bmpdata = (uint8 *) malloc(width * height * Bpp); 1079 1080 if(bmpdata == NULL) 1081 return; 1082 1083 if (!bitmap_decompress(bmpdata, width, height, data, bufsize, Bpp)) 1084 { 1085 DEBUG(("Failed to decompress bitmap data\n")); 1086 free(bmpdata); 1087 return; 1088 } 1089 } 1090 else 1091 { 1092 #if 0 1093 for (y = 0; y < height; y++) 1094 memcpy(&bmpdata[(height - y - 1) * (width * Bpp)], 1095 &data[y * (width * Bpp)], width * Bpp); 1096 #else 1097 bmpdata = data; 1098 #endif 1099 } 1100 1101 bitmap = ui_create_bitmap(This, width, height, bmpdata); 1102 1103 if (bitmap) 1104 { 1105 cache_put_bitmap(This, cache_id, cache_idx, bitmap); 1106 if (flags & PERSIST) 1107 pstcache_save_bitmap(This, cache_id, cache_idx, bitmap_id, width, height, 1108 width * height * Bpp, bmpdata); 1109 } 1110 else 1111 { 1112 DEBUG(("process_bmpcache2: ui_create_bitmap failed\n")); 1113 } 1114 1115 if (compressed) 1116 free(bmpdata); 1117 } 1118 1119 /* Process a colourmap cache order */ 1120 static void 1121 process_colcache(RDPCLIENT * This, STREAM s) 1122 { 1123 COLOURENTRY *entry; 1124 COLOURMAP map; 1125 HCOLOURMAP hmap; 1126 uint8 cache_id; 1127 int i; 1128 1129 in_uint8(s, cache_id); 1130 in_uint16_le(s, map.ncolours); 1131 1132 map.colours = (COLOURENTRY *) malloc(sizeof(COLOURENTRY) * map.ncolours); 1133 1134 if(map.colours == NULL) 1135 { 1136 in_uint8s(s, map.ncolours * 4); 1137 return; 1138 } 1139 1140 for (i = 0; i < map.ncolours; i++) 1141 { 1142 entry = &map.colours[i]; 1143 in_uint8(s, entry->blue); 1144 in_uint8(s, entry->green); 1145 in_uint8(s, entry->red); 1146 in_uint8s(s, 1); /* pad */ 1147 } 1148 1149 DEBUG(("COLCACHE(id=%d,n=%d)\n", cache_id, map.ncolours)); 1150 1151 hmap = ui_create_colourmap(This, &map); 1152 1153 if (cache_id) 1154 ui_set_colourmap(This, hmap); 1155 1156 free(map.colours); 1157 } 1158 1159 /* Process a font cache order */ 1160 static void 1161 process_fontcache(RDPCLIENT * This, STREAM s) 1162 { 1163 HGLYPH bitmap; 1164 uint8 font, nglyphs; 1165 uint16 character, offset, baseline, width, height; 1166 int i, datasize; 1167 uint8 *data; 1168 1169 in_uint8(s, font); 1170 in_uint8(s, nglyphs); 1171 1172 DEBUG(("FONTCACHE(font=%d,n=%d)\n", font, nglyphs)); 1173 1174 for (i = 0; i < nglyphs; i++) 1175 { 1176 in_uint16_le(s, character); 1177 in_uint16_le(s, offset); 1178 in_uint16_le(s, baseline); 1179 in_uint16_le(s, width); 1180 in_uint16_le(s, height); 1181 1182 datasize = (height * ((width + 7) / 8) + 3) & ~3; 1183 in_uint8p(s, data, datasize); 1184 1185 bitmap = ui_create_glyph(This, width, height, data); 1186 cache_put_font(This, font, character, offset, baseline, width, height, bitmap); 1187 } 1188 } 1189 1190 /* Process a secondary order */ 1191 static void 1192 process_secondary_order(RDPCLIENT * This, STREAM s) 1193 { 1194 /* The length isn't calculated correctly by the server. 1195 * For very compact orders the length becomes negative 1196 * so a signed integer must be used. */ 1197 uint16 length; 1198 uint16 flags; 1199 uint8 type; 1200 uint8 *next_order; 1201 1202 in_uint16_le(s, length); 1203 in_uint16_le(s, flags); /* used by bmpcache2 */ 1204 in_uint8(s, type); 1205 1206 next_order = s->p + (sint16) length + 7; 1207 1208 switch (type) 1209 { 1210 case RDP_ORDER_RAW_BMPCACHE: 1211 process_raw_bmpcache(This, s); 1212 break; 1213 1214 case RDP_ORDER_COLCACHE: 1215 process_colcache(This, s); 1216 break; 1217 1218 case RDP_ORDER_BMPCACHE: 1219 process_bmpcache(This, s); 1220 break; 1221 1222 case RDP_ORDER_FONTCACHE: 1223 process_fontcache(This, s); 1224 break; 1225 1226 case RDP_ORDER_RAW_BMPCACHE2: 1227 process_bmpcache2(This, s, flags, False); /* uncompressed */ 1228 break; 1229 1230 case RDP_ORDER_BMPCACHE2: 1231 process_bmpcache2(This, s, flags, True); /* compressed */ 1232 break; 1233 1234 default: 1235 unimpl("secondary order %d\n", type); 1236 } 1237 1238 s->p = next_order; 1239 } 1240 1241 /* Process an order PDU */ 1242 void 1243 process_orders(RDPCLIENT * This, STREAM s, uint16 num_orders) 1244 { 1245 RDP_ORDER_STATE *os = &This->orders.order_state; 1246 uint32 present; 1247 uint8 order_flags; 1248 int size, processed = 0; 1249 BOOL delta; 1250 1251 while (processed < num_orders) 1252 { 1253 in_uint8(s, order_flags); 1254 1255 if (!(order_flags & RDP_ORDER_STANDARD)) 1256 { 1257 error("order parsing failed\n"); 1258 break; 1259 } 1260 1261 if (order_flags & RDP_ORDER_SECONDARY) 1262 { 1263 process_secondary_order(This, s); 1264 } 1265 else 1266 { 1267 if (order_flags & RDP_ORDER_CHANGE) 1268 { 1269 in_uint8(s, os->order_type); 1270 } 1271 1272 switch (os->order_type) 1273 { 1274 case RDP_ORDER_TRIBLT: 1275 case RDP_ORDER_TEXT2: 1276 size = 3; 1277 break; 1278 1279 case RDP_ORDER_PATBLT: 1280 case RDP_ORDER_MEMBLT: 1281 case RDP_ORDER_LINE: 1282 case RDP_ORDER_POLYGON2: 1283 case RDP_ORDER_ELLIPSE2: 1284 size = 2; 1285 break; 1286 1287 default: 1288 size = 1; 1289 } 1290 1291 rdp_in_present(s, &present, order_flags, size); 1292 1293 if (order_flags & RDP_ORDER_BOUNDS) 1294 { 1295 if (!(order_flags & RDP_ORDER_LASTBOUNDS)) 1296 rdp_parse_bounds(s, &os->bounds); 1297 1298 ui_set_clip(This, os->bounds.left, 1299 os->bounds.top, 1300 os->bounds.right - 1301 os->bounds.left + 1, 1302 os->bounds.bottom - os->bounds.top + 1); 1303 } 1304 1305 delta = order_flags & RDP_ORDER_DELTA; 1306 1307 switch (os->order_type) 1308 { 1309 case RDP_ORDER_DESTBLT: 1310 process_destblt(This, s, &os->destblt, present, delta); 1311 break; 1312 1313 case RDP_ORDER_PATBLT: 1314 process_patblt(This, s, &os->patblt, present, delta); 1315 break; 1316 1317 case RDP_ORDER_SCREENBLT: 1318 process_screenblt(This, s, &os->screenblt, present, delta); 1319 break; 1320 1321 case RDP_ORDER_LINE: 1322 process_line(This, s, &os->line, present, delta); 1323 break; 1324 1325 case RDP_ORDER_RECT: 1326 process_rect(This, s, &os->rect, present, delta); 1327 break; 1328 1329 case RDP_ORDER_DESKSAVE: 1330 process_desksave(This, s, &os->desksave, present, delta); 1331 break; 1332 1333 case RDP_ORDER_MEMBLT: 1334 process_memblt(This, s, &os->memblt, present, delta); 1335 break; 1336 1337 case RDP_ORDER_TRIBLT: 1338 process_triblt(This, s, &os->triblt, present, delta); 1339 break; 1340 1341 case RDP_ORDER_POLYGON: 1342 process_polygon(This, s, &os->polygon, present, delta); 1343 break; 1344 1345 case RDP_ORDER_POLYGON2: 1346 process_polygon2(This, s, &os->polygon2, present, delta); 1347 break; 1348 1349 case RDP_ORDER_POLYLINE: 1350 process_polyline(This, s, &os->polyline, present, delta); 1351 break; 1352 1353 case RDP_ORDER_ELLIPSE: 1354 process_ellipse(This, s, &os->ellipse, present, delta); 1355 break; 1356 1357 case RDP_ORDER_ELLIPSE2: 1358 process_ellipse2(This, s, &os->ellipse2, present, delta); 1359 break; 1360 1361 case RDP_ORDER_TEXT2: 1362 process_text2(This, s, &os->text2, present, delta); 1363 break; 1364 1365 default: 1366 unimpl("order %d\n", os->order_type); 1367 return; 1368 } 1369 1370 if (order_flags & RDP_ORDER_BOUNDS) 1371 ui_reset_clip(This); 1372 } 1373 1374 processed++; 1375 } 1376 #if 0 1377 /* not true when RDP_COMPRESSION is set */ 1378 if (s->p != This->next_packet) 1379 error("%d bytes remaining\n", (int) (This->next_packet - s->p)); 1380 #endif 1381 1382 } 1383 1384 /* Reset order state */ 1385 void 1386 reset_order_state(RDPCLIENT * This) 1387 { 1388 memset(&This->orders.order_state, 0, sizeof(This->orders.order_state)); 1389 This->orders.order_state.order_type = RDP_ORDER_PATBLT; 1390 } 1391