Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

orders.cpp

Go to the documentation of this file.
00001 /*
00002    rdesktop: A Remote Desktop Protocol client.
00003    RDP order processing
00004    Copyright (C) Matthew Chapman 1999-2002
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010 
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 */
00020 
00021 #include "rdesktop.h"
00022 #include "orders.h"
00023 
00024 extern uint8 *next_packet;
00025 static RDP_ORDER_STATE order_state;
00026 
00027 /* Read field indicating which parameters are present */
00028 static void
00029 rdp_in_present(STREAM s, uint32 * present, uint8 flags, int size)
00030 {
00031         uint8 bits;
00032         int i;
00033 
00034         if (flags & RDP_ORDER_SMALL)
00035         {
00036                 size--;
00037         }
00038 
00039         if (flags & RDP_ORDER_TINY)
00040         {
00041                 if (size < 2)
00042                         size = 0;
00043                 else
00044                         size -= 2;
00045         }
00046 
00047         *present = 0;
00048         for (i = 0; i < size; i++)
00049         {
00050                 in_uint8(s, bits);
00051                 *present |= bits << (i * 8);
00052         }
00053 }
00054 
00055 /* Read a co-ordinate (16-bit, or 8-bit delta) */
00056 static void
00057 rdp_in_coord(STREAM s, sint16 * coord, BOOL delta)
00058 {
00059         sint8 change;
00060 
00061         if (delta)
00062         {
00063                 in_uint8(s, change);
00064                 *coord += change;
00065         }
00066         else
00067         {
00068                 in_uint16_le(s, *coord);
00069         }
00070 }
00071 
00072 /* Read a colour entry */
00073 static void
00074 rdp_in_colour(STREAM s, uint32 * colour)
00075 {
00076         uint32 i;
00077         in_uint8(s, i);
00078         *colour = i;
00079         in_uint8(s, i);
00080         *colour |= i << 8;
00081         in_uint8(s, i);
00082         *colour |= i << 16;
00083 }
00084 
00085 /* Parse bounds information */
00086 static BOOL
00087 rdp_parse_bounds(STREAM s, BOUNDS * bounds)
00088 {
00089         uint8 present;
00090 
00091         in_uint8(s, present);
00092 
00093         if (present & 1)
00094                 rdp_in_coord(s, &bounds->left, False);
00095         else if (present & 16)
00096                 rdp_in_coord(s, &bounds->left, True);
00097 
00098         if (present & 2)
00099                 rdp_in_coord(s, &bounds->top, False);
00100         else if (present & 32)
00101                 rdp_in_coord(s, &bounds->top, True);
00102 
00103         if (present & 4)
00104                 rdp_in_coord(s, &bounds->right, False);
00105         else if (present & 64)
00106                 rdp_in_coord(s, &bounds->right, True);
00107 
00108         if (present & 8)
00109                 rdp_in_coord(s, &bounds->bottom, False);
00110         else if (present & 128)
00111                 rdp_in_coord(s, &bounds->bottom, True);
00112 
00113         return s_check(s);
00114 }
00115 
00116 /* Parse a pen */
00117 static BOOL
00118 rdp_parse_pen(STREAM s, PEN * pen, uint32 present)
00119 {
00120         if (present & 1)
00121                 in_uint8(s, pen->style);
00122 
00123         if (present & 2)
00124                 in_uint8(s, pen->width);
00125 
00126         if (present & 4)
00127                 rdp_in_colour(s, &pen->colour);
00128 
00129         return s_check(s);
00130 }
00131 
00132 /* Parse a brush */
00133 static BOOL
00134 rdp_parse_brush(STREAM s, BRUSH * brush, uint32 present)
00135 {
00136         if (present & 1)
00137                 in_uint8(s, brush->xorigin);
00138 
00139         if (present & 2)
00140                 in_uint8(s, brush->yorigin);
00141 
00142         if (present & 4)
00143                 in_uint8(s, brush->style);
00144 
00145         if (present & 8)
00146                 in_uint8(s, brush->pattern[0]);
00147 
00148         if (present & 16)
00149                 in_uint8a(s, &brush->pattern[1], 7);
00150 
00151         return s_check(s);
00152 }
00153 
00154 /* Process a destination blt order */
00155 static void
00156 process_destblt(STREAM s, DESTBLT_ORDER * os, uint32 present, BOOL delta)
00157 {
00158         if (present & 0x01)
00159                 rdp_in_coord(s, &os->x, delta);
00160 
00161         if (present & 0x02)
00162                 rdp_in_coord(s, &os->y, delta);
00163 
00164         if (present & 0x04)
00165                 rdp_in_coord(s, &os->cx, delta);
00166 
00167         if (present & 0x08)
00168                 rdp_in_coord(s, &os->cy, delta);
00169 
00170         if (present & 0x10)
00171                 in_uint8(s, os->opcode);
00172 
00173         DEBUG(("DESTBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d)\n",
00174                os->opcode, os->x, os->y, os->cx, os->cy));
00175 
00176         ui_destblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy);
00177 }
00178 
00179 /* Process a pattern blt order */
00180 static void
00181 process_patblt(STREAM s, PATBLT_ORDER * os, uint32 present, BOOL delta)
00182 {
00183         if (present & 0x0001)
00184                 rdp_in_coord(s, &os->x, delta);
00185 
00186         if (present & 0x0002)
00187                 rdp_in_coord(s, &os->y, delta);
00188 
00189         if (present & 0x0004)
00190                 rdp_in_coord(s, &os->cx, delta);
00191 
00192         if (present & 0x0008)
00193                 rdp_in_coord(s, &os->cy, delta);
00194 
00195         if (present & 0x0010)
00196                 in_uint8(s, os->opcode);
00197 
00198         if (present & 0x0020)
00199                 rdp_in_colour(s, &os->bgcolour);
00200 
00201         if (present & 0x0040)
00202                 rdp_in_colour(s, &os->fgcolour);
00203 
00204         rdp_parse_brush(s, &os->brush, present >> 7);
00205 
00206         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,
00207                os->y, os->cx, os->cy, os->brush.style, os->bgcolour, os->fgcolour));
00208 
00209         ui_patblt(ROP2_P(os->opcode), os->x, os->y, os->cx, os->cy,
00210                   &os->brush, os->bgcolour, os->fgcolour);
00211 }
00212 
00213 /* Process a screen blt order */
00214 static void
00215 process_screenblt(STREAM s, SCREENBLT_ORDER * os, uint32 present, BOOL delta)
00216 {
00217         if (present & 0x0001)
00218                 rdp_in_coord(s, &os->x, delta);
00219 
00220         if (present & 0x0002)
00221                 rdp_in_coord(s, &os->y, delta);
00222 
00223         if (present & 0x0004)
00224                 rdp_in_coord(s, &os->cx, delta);
00225 
00226         if (present & 0x0008)
00227                 rdp_in_coord(s, &os->cy, delta);
00228 
00229         if (present & 0x0010)
00230                 in_uint8(s, os->opcode);
00231 
00232         if (present & 0x0020)
00233                 rdp_in_coord(s, &os->srcx, delta);
00234 
00235         if (present & 0x0040)
00236                 rdp_in_coord(s, &os->srcy, delta);
00237 
00238         DEBUG(("SCREENBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,srcx=%d,srcy=%d)\n",
00239                os->opcode, os->x, os->y, os->cx, os->cy, os->srcx, os->srcy));
00240 
00241         ui_screenblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy, os->srcx, os->srcy);
00242 }
00243 
00244 /* Process a line order */
00245 static void
00246 process_line(STREAM s, LINE_ORDER * os, uint32 present, BOOL delta)
00247 {
00248         if (present & 0x0001)
00249                 in_uint16_le(s, os->mixmode);
00250 
00251         if (present & 0x0002)
00252                 rdp_in_coord(s, &os->startx, delta);
00253 
00254         if (present & 0x0004)
00255                 rdp_in_coord(s, &os->starty, delta);
00256 
00257         if (present & 0x0008)
00258                 rdp_in_coord(s, &os->endx, delta);
00259 
00260         if (present & 0x0010)
00261                 rdp_in_coord(s, &os->endy, delta);
00262 
00263         if (present & 0x0020)
00264                 rdp_in_colour(s, &os->bgcolour);
00265 
00266         if (present & 0x0040)
00267                 in_uint8(s, os->opcode);
00268 
00269         rdp_parse_pen(s, &os->pen, present >> 7);
00270 
00271         DEBUG(("LINE(op=0x%x,sx=%d,sy=%d,dx=%d,dx=%d,fg=0x%x)\n",
00272                os->opcode, os->startx, os->starty, os->endx, os->endy, os->pen.colour));
00273 
00274         if (os->opcode < 0x01 || os->opcode > 0x10)
00275         {
00276                 error("bad ROP2 0x%x\n", os->opcode);
00277                 return;
00278         }
00279 
00280         ui_line(os->opcode - 1, os->startx, os->starty, os->endx, os->endy, &os->pen);
00281 }
00282 
00283 /* Process an opaque rectangle order */
00284 static void
00285 process_rect(STREAM s, RECT_ORDER * os, uint32 present, BOOL delta)
00286 {
00287         uint32 i;
00288         if (present & 0x01)
00289                 rdp_in_coord(s, &os->x, delta);
00290 
00291         if (present & 0x02)
00292                 rdp_in_coord(s, &os->y, delta);
00293 
00294         if (present & 0x04)
00295                 rdp_in_coord(s, &os->cx, delta);
00296 
00297         if (present & 0x08)
00298                 rdp_in_coord(s, &os->cy, delta);
00299 
00300         if (present & 0x10)
00301         {
00302                 in_uint8(s, i);
00303                 os->colour = (os->colour & 0xffffff00) | i;
00304         }
00305 
00306         if (present & 0x20)
00307         {
00308                 in_uint8(s, i);
00309                 os->colour = (os->colour & 0xffff00ff) | (i << 8);
00310         }
00311 
00312         if (present & 0x40)
00313         {
00314                 in_uint8(s, i);
00315                 os->colour = (os->colour & 0xff00ffff) | (i << 16);
00316         }
00317 
00318         DEBUG(("RECT(x=%d,y=%d,cx=%d,cy=%d,fg=0x%x)\n", os->x, os->y, os->cx, os->cy, os->colour));
00319 
00320         ui_rect(os->x, os->y, os->cx, os->cy, os->colour);
00321 }
00322 
00323 /* Process a desktop save order */
00324 static void
00325 process_desksave(STREAM s, DESKSAVE_ORDER * os, uint32 present, BOOL delta)
00326 {
00327         int width, height;
00328 
00329         if (present & 0x01)
00330                 in_uint32_le(s, os->offset);
00331 
00332         if (present & 0x02)
00333                 rdp_in_coord(s, &os->left, delta);
00334 
00335         if (present & 0x04)
00336                 rdp_in_coord(s, &os->top, delta);
00337 
00338         if (present & 0x08)
00339                 rdp_in_coord(s, &os->right, delta);
00340 
00341         if (present & 0x10)
00342                 rdp_in_coord(s, &os->bottom, delta);
00343 
00344         if (present & 0x20)
00345                 in_uint8(s, os->action);
00346 
00347         DEBUG(("DESKSAVE(l=%d,t=%d,r=%d,b=%d,off=%d,op=%d)\n",
00348                os->left, os->top, os->right, os->bottom, os->offset, os->action));
00349 
00350         width = os->right - os->left + 1;
00351         height = os->bottom - os->top + 1;
00352 
00353         if (os->action == 0)
00354                 ui_desktop_save(os->offset, os->left, os->top, width, height);
00355         else
00356                 ui_desktop_restore(os->offset, os->left, os->top, width, height);
00357 }
00358 
00359 /* Process a memory blt order */
00360 static void
00361 process_memblt(STREAM s, MEMBLT_ORDER * os, uint32 present, BOOL delta)
00362 {
00363         HBITMAP bitmap;
00364 
00365         if (present & 0x0001)
00366         {
00367                 in_uint8(s, os->cache_id);
00368                 in_uint8(s, os->colour_table);
00369         }
00370 
00371         if (present & 0x0002)
00372                 rdp_in_coord(s, &os->x, delta);
00373 
00374         if (present & 0x0004)
00375                 rdp_in_coord(s, &os->y, delta);
00376 
00377         if (present & 0x0008)
00378                 rdp_in_coord(s, &os->cx, delta);
00379 
00380         if (present & 0x0010)
00381                 rdp_in_coord(s, &os->cy, delta);
00382 
00383         if (present & 0x0020)
00384                 in_uint8(s, os->opcode);
00385 
00386         if (present & 0x0040)
00387                 rdp_in_coord(s, &os->srcx, delta);
00388 
00389         if (present & 0x0080)
00390                 rdp_in_coord(s, &os->srcy, delta);
00391 
00392         if (present & 0x0100)
00393                 in_uint16_le(s, os->cache_idx);
00394 
00395         DEBUG(("MEMBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,id=%d,idx=%d)\n",
00396                os->opcode, os->x, os->y, os->cx, os->cy, os->cache_id, os->cache_idx));
00397 
00398         bitmap = cache_get_bitmap(os->cache_id, os->cache_idx);
00399         if (bitmap == NULL)
00400                 return;
00401 
00402         ui_memblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy, bitmap, os->srcx, os->srcy);
00403 }
00404 
00405 /* Process a 3-way blt order */
00406 static void
00407 process_triblt(STREAM s, TRIBLT_ORDER * os, uint32 present, BOOL delta)
00408 {
00409         HBITMAP bitmap;
00410 
00411         if (present & 0x000001)
00412         {
00413                 in_uint8(s, os->cache_id);
00414                 in_uint8(s, os->colour_table);
00415         }
00416 
00417         if (present & 0x000002)
00418                 rdp_in_coord(s, &os->x, delta);
00419 
00420         if (present & 0x000004)
00421                 rdp_in_coord(s, &os->y, delta);
00422 
00423         if (present & 0x000008)
00424                 rdp_in_coord(s, &os->cx, delta);
00425 
00426         if (present & 0x000010)
00427                 rdp_in_coord(s, &os->cy, delta);
00428 
00429         if (present & 0x000020)
00430                 in_uint8(s, os->opcode);
00431 
00432         if (present & 0x000040)
00433                 rdp_in_coord(s, &os->srcx, delta);
00434 
00435         if (present & 0x000080)
00436                 rdp_in_coord(s, &os->srcy, delta);
00437 
00438         if (present & 0x000100)
00439                 rdp_in_colour(s, &os->bgcolour);
00440 
00441         if (present & 0x000200)
00442                 rdp_in_colour(s, &os->fgcolour);
00443 
00444         rdp_parse_brush(s, &os->brush, present >> 10);
00445 
00446         if (present & 0x008000)
00447                 in_uint16_le(s, os->cache_idx);
00448 
00449         if (present & 0x010000)
00450                 in_uint16_le(s, os->unknown);
00451 
00452         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",
00453                os->opcode, os->x, os->y, os->cx, os->cy, os->cache_id, os->cache_idx,
00454                os->brush.style, os->bgcolour, os->fgcolour));
00455 
00456         bitmap = cache_get_bitmap(os->cache_id, os->cache_idx);
00457         if (bitmap == NULL)
00458                 return;
00459 
00460         ui_triblt(os->opcode, os->x, os->y, os->cx, os->cy,
00461                   bitmap, os->srcx, os->srcy, &os->brush, os->bgcolour, os->fgcolour);
00462 }
00463 
00464 /* Parse a delta co-ordinate in polyline order form */
00465 static int
00466 parse_delta(uint8 * buffer, int *offset)
00467 {
00468         int value = buffer[(*offset)++];
00469         int two_byte = value & 0x80;
00470 
00471         if (value & 0x40)       /* sign bit */
00472                 value |= ~0x3f;
00473         else
00474                 value &= 0x3f;
00475 
00476         if (two_byte)
00477                 value = (value << 8) | buffer[(*offset)++];
00478 
00479         return value;
00480 }
00481 
00482 /* Process a polyline order */
00483 static void
00484 process_polyline(STREAM s, POLYLINE_ORDER * os, uint32 present, BOOL delta)
00485 {
00486         int index, line, data;
00487         int x, y, xfrom, yfrom;
00488         uint8 flags = 0;
00489         PEN pen;
00490         uint8 opcode;
00491 
00492         if (present & 0x01)
00493                 rdp_in_coord(s, &os->x, delta);
00494 
00495         if (present & 0x02)
00496                 rdp_in_coord(s, &os->y, delta);
00497 
00498         if (present & 0x04)
00499                 in_uint8(s, os->opcode);
00500 
00501         if (present & 0x10)
00502                 rdp_in_colour(s, &os->fgcolour);
00503 
00504         if (present & 0x20)
00505                 in_uint8(s, os->lines);
00506 
00507         if (present & 0x40)
00508         {
00509                 in_uint8(s, os->datasize);
00510                 in_uint8a(s, os->data, os->datasize);
00511         }
00512 
00513         DEBUG(("POLYLINE(x=%d,y=%d,op=0x%x,fg=0x%x,n=%d,sz=%d)\n",
00514                os->x, os->y, os->opcode, os->fgcolour, os->lines, os->datasize));
00515 
00516         DEBUG(("Data: "));
00517 
00518         for (index = 0; index < os->datasize; index++)
00519                 DEBUG(("%02x ", os->data[index]));
00520 
00521         DEBUG(("\n"));
00522 
00523         if (os->opcode < 0x01 || os->opcode > 0x10)
00524         {
00525                 error("bad ROP2 0x%x\n", os->opcode);
00526                 return;
00527         }
00528 
00529         opcode = os->opcode - 1;
00530         x = os->x;
00531         y = os->y;
00532         pen.style = pen.width = 0;
00533         pen.colour = os->fgcolour;
00534 
00535         index = 0;
00536         data = ((os->lines - 1) / 4) + 1;
00537         for (line = 0; (line < os->lines) && (data < os->datasize); line++)
00538         {
00539                 xfrom = x;
00540                 yfrom = y;
00541 
00542                 if (line % 4 == 0)
00543                         flags = os->data[index++];
00544 
00545                 if ((flags & 0xc0) == 0)
00546                         flags |= 0xc0;  /* none = both */
00547 
00548                 if (flags & 0x40)
00549                         x += parse_delta(os->data, &data);
00550 
00551                 if (flags & 0x80)
00552                         y += parse_delta(os->data, &data);
00553 
00554                 ui_line(opcode, xfrom, yfrom, x, y, &pen);
00555 
00556                 flags <<= 2;
00557         }
00558 }
00559 
00560 /* Process a text order */
00561 static void
00562 process_text2(STREAM s, TEXT2_ORDER * os, uint32 present, BOOL delta)
00563 {
00564         int i;
00565 
00566         if (present & 0x000001)
00567                 in_uint8(s, os->font);
00568 
00569         if (present & 0x000002)
00570                 in_uint8(s, os->flags);
00571 
00572         if (present & 0x000004)
00573                 in_uint8(s, os->unknown);
00574 
00575         if (present & 0x000008)
00576                 in_uint8(s, os->mixmode);
00577 
00578         if (present & 0x000010)
00579                 rdp_in_colour(s, &os->fgcolour);
00580 
00581         if (present & 0x000020)
00582                 rdp_in_colour(s, &os->bgcolour);
00583 
00584         if (present & 0x000040)
00585                 in_uint16_le(s, os->clipleft);
00586 
00587         if (present & 0x000080)
00588                 in_uint16_le(s, os->cliptop);
00589 
00590         if (present & 0x000100)
00591                 in_uint16_le(s, os->clipright);
00592 
00593         if (present & 0x000200)
00594                 in_uint16_le(s, os->clipbottom);
00595 
00596         if (present & 0x000400)
00597                 in_uint16_le(s, os->boxleft);
00598 
00599         if (present & 0x000800)
00600                 in_uint16_le(s, os->boxtop);
00601 
00602         if (present & 0x001000)
00603                 in_uint16_le(s, os->boxright);
00604 
00605         if (present & 0x002000)
00606                 in_uint16_le(s, os->boxbottom);
00607 
00608         if (present & 0x004000) /* fix for connecting to a server that */
00609                 in_uint8s(s, 10);    /* was disconnected with mstsc.exe */
00610                 /* 0x008000, 0x020000, and 0x040000 are present too ??? */
00611 
00612         if (present & 0x080000)
00613                 in_uint16_le(s, os->x);
00614 
00615         if (present & 0x100000)
00616                 in_uint16_le(s, os->y);
00617 
00618         if (present & 0x200000)
00619         {
00620                 in_uint8(s, os->length);
00621                 in_uint8a(s, os->text, os->length);
00622         }
00623 
00624         DEBUG(("TEXT2(x=%d,y=%d,cl=%d,ct=%d,cr=%d,cb=%d,bl=%d,bt=%d,bb=%d,br=%d,fg=0x%x,bg=0x%x,font=%d,fl=0x%x,mix=%d,unk=0x%x,n=%d)\n", os->x, os->y, os->clipleft, os->cliptop, os->clipright, os->clipbottom, os->boxleft, os->boxtop, os->boxright, os->boxbottom, os->fgcolour, os->bgcolour, os->font, os->flags, os->mixmode, os->unknown, os->length));
00625 
00626         DEBUG(("Text: "));
00627 
00628         for (i = 0; i < os->length; i++)
00629                 DEBUG(("%02x ", os->text[i]));
00630 
00631         DEBUG(("\n"));
00632 
00633         ui_draw_text(os->font, os->flags, os->mixmode, os->x, os->y,
00634                      os->clipleft, os->cliptop,
00635                      os->clipright - os->clipleft,
00636                      os->clipbottom - os->cliptop,
00637                      os->boxleft, os->boxtop,
00638                      os->boxright - os->boxleft,
00639                      os->boxbottom - os->boxtop, os->bgcolour, os->fgcolour, os->text, os->length);
00640 }
00641 
00642 /* Process a raw bitmap cache order */
00643 static void
00644 process_raw_bmpcache(STREAM s)
00645 {
00646         HBITMAP bitmap;
00647         uint16 cache_idx, bufsize;
00648         uint8 cache_id, width, height, bpp, Bpp;
00649         uint8 *data, *inverted;
00650         int y;
00651 
00652         in_uint8(s, cache_id);
00653         in_uint8s(s, 1);        /* pad */
00654         in_uint8(s, width);
00655         in_uint8(s, height);
00656         in_uint8(s, bpp);
00657         Bpp = (bpp + 7) / 8;
00658         in_uint16_le(s, bufsize);
00659         in_uint16_le(s, cache_idx);
00660         in_uint8p(s, data, bufsize);
00661 
00662         DEBUG(("RAW_BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d)\n", width, height, cache_id, cache_idx));
00663         inverted = (uint8*)xmalloc(width * height * Bpp);
00664         for (y = 0; y < height; y++)
00665         {
00666                 memcpy(&inverted[(height - y - 1) * (width * Bpp)], &data[y * (width * Bpp)],
00667                        width * Bpp);
00668         }
00669 
00670         bitmap = ui_create_bitmap(width, height, inverted);
00671         xfree(inverted);
00672         cache_put_bitmap(cache_id, cache_idx, bitmap);
00673 }
00674 
00675 /* Process a bitmap cache order */
00676 static void
00677 process_bmpcache(STREAM s)
00678 {
00679         HBITMAP bitmap;
00680         uint16 cache_idx, size;
00681         uint8 cache_id, width, height, bpp, Bpp;
00682         uint8 *data, *bmpdata;
00683 
00684         in_uint8(s, cache_id);
00685         in_uint8s(s, 1);        /* pad */
00686         in_uint8(s, width);
00687         in_uint8(s, height);
00688         in_uint8(s, bpp);
00689         Bpp = (bpp + 7) / 8;
00690         in_uint8s(s, 2);        /* bufsize */
00691         in_uint16_le(s, cache_idx);
00692         in_uint8s(s, 2);        /* pad */
00693         in_uint16_le(s, size);
00694         in_uint8s(s, 4);        /* row_size, final_size */
00695         in_uint8p(s, data, size);
00696         DEBUG(("BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d)\n", width, height, cache_id, cache_idx));
00697         bmpdata = (uint8*)xmalloc(width * height * Bpp);
00698         if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
00699         {
00700                 bitmap = ui_create_bitmap(width, height, bmpdata);
00701                 cache_put_bitmap(cache_id, cache_idx, bitmap);
00702         }
00703         xfree(bmpdata);
00704 }
00705 
00706 /* Process a colourmap cache order */
00707 static void
00708 process_colcache(STREAM s)
00709 {
00710         COLOURENTRY *entry;
00711         COLOURMAP map;
00712         HCOLOURMAP hmap;
00713         uint8 cache_id;
00714         int i;
00715         in_uint8(s, cache_id);
00716         in_uint16_le(s, map.ncolours);
00717 
00718         map.colours = (COLOURENTRY*)xmalloc(3 * map.ncolours);
00719 
00720         for (i = 0; i < map.ncolours; i++)
00721         {
00722                 entry = &map.colours[i];
00723                 in_uint8(s, entry->blue);
00724                 in_uint8(s, entry->green);
00725                 in_uint8(s, entry->red);
00726                 in_uint8s(s, 1);        /* pad */
00727         }
00728 
00729         DEBUG(("COLCACHE(id=%d,n=%d)\n", cache_id, map.ncolours));
00730 
00731         hmap = ui_create_colourmap(&map);
00732         ui_set_colourmap(hmap);
00733 
00734         xfree(map.colours);
00735 }
00736 
00737 /* Process a font cache order */
00738 static void
00739 process_fontcache(STREAM s)
00740 {
00741         HGLYPH bitmap;
00742         uint8 font, nglyphs;
00743         uint16 character, offset, baseline, width, height;
00744         int i, datasize;
00745         uint8 *data;
00746 
00747         in_uint8(s, font);
00748         in_uint8(s, nglyphs);
00749 
00750         DEBUG(("FONTCACHE(font=%d,n=%d)\n", font, nglyphs));
00751 
00752         for (i = 0; i < nglyphs; i++)
00753         {
00754                 in_uint16_le(s, character);
00755                 in_uint16_le(s, offset);
00756                 in_uint16_le(s, baseline);
00757                 in_uint16_le(s, width);
00758                 in_uint16_le(s, height);
00759 
00760                 datasize = (height * ((width + 7) / 8) + 3) & ~3;
00761                 in_uint8p(s, data, datasize);
00762 
00763                 bitmap = ui_create_glyph(width, height, data);
00764                 cache_put_font(font, character, offset, baseline, width, height, bitmap);
00765         }
00766 }
00767 
00768 /* Process a secondary order */
00769 static void
00770 process_secondary_order(STREAM s)
00771 {
00772         uint16 length;
00773         uint8 type;
00774         uint8 *next_order;
00775 
00776         in_uint16_le(s, length);
00777         in_uint8s(s, 2);        /* flags */
00778         in_uint8(s, type);
00779 
00780         next_order = s->p + length + 7;
00781 
00782         switch (type)
00783         {
00784                 case RDP_ORDER_RAW_BMPCACHE:
00785                         process_raw_bmpcache(s);
00786                         break;
00787 
00788                 case RDP_ORDER_COLCACHE:
00789                         process_colcache(s);
00790                         break;
00791 
00792                 case RDP_ORDER_BMPCACHE:
00793                         process_bmpcache(s);
00794                         break;
00795 
00796                 case RDP_ORDER_FONTCACHE:
00797                         process_fontcache(s);
00798                         break;
00799 
00800                 default:
00801                         unimpl("secondary order %d\n", type);
00802         }
00803 
00804         s->p = next_order;
00805 }
00806 
00807 /* Process an order PDU */
00808 void
00809 process_orders(STREAM s)
00810 {
00811         RDP_ORDER_STATE *os = &order_state;
00812         uint32 present;
00813         uint16 num_orders;
00814         uint8 order_flags;
00815         int size, processed = 0;
00816         BOOL delta;
00817 
00818         in_uint8s(s, 2);        /* pad */
00819         in_uint16_le(s, num_orders);
00820         in_uint8s(s, 2);        /* pad */
00821 
00822         while (processed < num_orders)
00823         {
00824                 in_uint8(s, order_flags);
00825 
00826                 if (!(order_flags & RDP_ORDER_STANDARD))
00827                 {
00828                         error("order parsing failed\n");
00829                         break;
00830                 }
00831 
00832                 if (order_flags & RDP_ORDER_SECONDARY)
00833                 {
00834                         process_secondary_order(s);
00835                 }
00836                 else
00837                 {
00838                         if (order_flags & RDP_ORDER_CHANGE)
00839                         {
00840                                 in_uint8(s, os->order_type);
00841                         }
00842 
00843                         switch (os->order_type)
00844                         {
00845                                 case RDP_ORDER_TRIBLT:
00846                                 case RDP_ORDER_TEXT2:
00847                                         size = 3;
00848                                         break;
00849 
00850                                 case RDP_ORDER_PATBLT:
00851                                 case RDP_ORDER_MEMBLT:
00852                                 case RDP_ORDER_LINE:
00853                                         size = 2;
00854                                         break;
00855 
00856                                 default:
00857                                         size = 1;
00858                         }
00859 
00860                         rdp_in_present(s, &present, order_flags, size);
00861 
00862                         if (order_flags & RDP_ORDER_BOUNDS)
00863                         {
00864                                 if (!(order_flags & RDP_ORDER_LASTBOUNDS))
00865                                         rdp_parse_bounds(s, &os->bounds);
00866 
00867                                 ui_set_clip(os->bounds.left,
00868                                             os->bounds.top,
00869                                             os->bounds.right -
00870                                             os->bounds.left + 1,
00871                                             os->bounds.bottom - os->bounds.top + 1);
00872                         }
00873 
00874                         delta = order_flags & RDP_ORDER_DELTA;
00875 
00876                         switch (os->order_type)
00877                         {
00878                                 case RDP_ORDER_DESTBLT:
00879                                         process_destblt(s, &os->destblt, present, delta);
00880                                         break;
00881 
00882                                 case RDP_ORDER_PATBLT:
00883                                         process_patblt(s, &os->patblt, present, delta);
00884                                         break;
00885 
00886                                 case RDP_ORDER_SCREENBLT:
00887                                         process_screenblt(s, &os->screenblt, present, delta);
00888                                         break;
00889 
00890                                 case RDP_ORDER_LINE:
00891                                         process_line(s, &os->line, present, delta);
00892                                         break;
00893 
00894                                 case RDP_ORDER_RECT:
00895                                         process_rect(s, &os->rect, present, delta);
00896                                         break;
00897 
00898                                 case RDP_ORDER_DESKSAVE:
00899                                         process_desksave(s, &os->desksave, present, delta);
00900                                         break;
00901 
00902                                 case RDP_ORDER_MEMBLT:
00903                                         process_memblt(s, &os->memblt, present, delta);
00904                                         break;
00905 
00906                                 case RDP_ORDER_TRIBLT:
00907                                         process_triblt(s, &os->triblt, present, delta);
00908                                         break;
00909 
00910                                 case RDP_ORDER_POLYLINE:
00911                                         process_polyline(s, &os->polyline, present, delta);
00912                                         break;
00913 
00914                                 case RDP_ORDER_TEXT2:
00915                                         process_text2(s, &os->text2, present, delta);
00916                                         break;
00917 
00918                                 default:
00919                                         unimpl("order %d\n", os->order_type);
00920                                         return;
00921                         }
00922 
00923                         if (order_flags & RDP_ORDER_BOUNDS)
00924                                 ui_reset_clip();
00925                 }
00926 
00927                 processed++;
00928         }
00929 
00930         if (s->p != next_packet)
00931                 error("%d bytes remaining\n", (int) (next_packet - s->p));
00932 }
00933 
00934 /* Reset order state */
00935 void
00936 reset_order_state(void)
00937 {
00938         memset(&order_state, 0, sizeof(order_state));
00939         order_state.order_type = RDP_ORDER_PATBLT;
00940 }

Generated on Sat Nov 5 16:17:41 2005 for OPIE by  doxygen 1.4.2