diff options
Diffstat (limited to 'rdp/rdp_orders.c')
-rw-r--r-- | rdp/rdp_orders.c | 1017 |
1 files changed, 1017 insertions, 0 deletions
diff --git a/rdp/rdp_orders.c b/rdp/rdp_orders.c new file mode 100644 index 00000000..a22faa27 --- /dev/null +++ b/rdp/rdp_orders.c @@ -0,0 +1,1017 @@ +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + xrdp: A Remote Desktop Protocol server. + Copyright (C) Jay Sorg 2005 + + librdp orders + +*/ + +#include "rdp.h" + +/*****************************************************************************/ +struct rdp_orders* APP_CC +rdp_orders_create(struct rdp_rdp* owner) +{ + struct rdp_orders* self; + + self = (struct rdp_orders*)g_malloc(sizeof(struct rdp_orders), 1); + self->rdp_layer = owner; + return self; +} + +/*****************************************************************************/ +void APP_CC +rdp_orders_delete(struct rdp_orders* self) +{ + int i; + int j; + + for (i = 0; i < 6; i++) + { + g_free(self->cache_colormap[i]); + } + for (i = 0; i < 3; i++) + { + for (j = 0; j < 600; j++) + { + if (self->cache_bitmap[i][j] != 0) + { + g_free(self->cache_bitmap[i][j]->data); + } + g_free(self->cache_bitmap[i][j]); + } + } + g_free(self); +} + +/*****************************************************************************/ +void APP_CC +rdp_orders_reset_state(struct rdp_orders* self) +{ + g_memset(&self->state, 0, sizeof(self->state)); +} + +/*****************************************************************************/ +/* Read field indicating which parameters are present */ +static void APP_CC +rdp_orders_in_present(struct stream* s, int* present, + int flags, int size) +{ + int bits; + int i; + + if (flags & RDP_ORDER_SMALL) + { + size--; + } + if (flags & RDP_ORDER_TINY) + { + if (size < 2) + { + size = 0; + } + else + { + size -= 2; + } + } + *present = 0; + for (i = 0; i < size; i++) + { + in_uint8(s, bits); + *present |= bits << (i * 8); + } +} + +/*****************************************************************************/ +/* Read a co-ordinate (16-bit, or 8-bit delta) */ +static void APP_CC +rdp_orders_in_coord(struct stream* s, int* coord, int delta) +{ + char change; + + if (delta) + { + in_uint8(s, change); + *coord += change; + } + else + { + in_sint16_le(s, *coord); + } +} + +/*****************************************************************************/ +/* Parse bounds information */ +static void APP_CC +rdp_orders_parse_bounds(struct rdp_orders* self, struct stream* s) +{ + int present; + + in_uint8(s, present); + if (present & 1) + { + rdp_orders_in_coord(s, &self->state.clip_left, 0); + } + else if (present & 16) + { + rdp_orders_in_coord(s, &self->state.clip_left, 1); + } + if (present & 2) + { + rdp_orders_in_coord(s, &self->state.clip_top, 0); + } + else if (present & 32) + { + rdp_orders_in_coord(s, &self->state.clip_top, 1); + } + if (present & 4) + { + rdp_orders_in_coord(s, &self->state.clip_right, 0); + } + else if (present & 64) + { + rdp_orders_in_coord(s, &self->state.clip_right, 1); + } + if (present & 8) + { + rdp_orders_in_coord(s, &self->state.clip_bottom, 0); + } + else if (present & 128) + { + rdp_orders_in_coord(s, &self->state.clip_bottom, 1); + } +} + +/*****************************************************************************/ +/* Process a colormap cache order */ +static void APP_CC +rdp_orders_process_colcache(struct rdp_orders* self, struct stream* s, + int flags) +{ + struct rdp_colormap* colormap; + int cache_id; + int i; + + colormap = (struct rdp_colormap*)g_malloc(sizeof(struct rdp_colormap), 1); + in_uint8(s, cache_id); + in_uint16_le(s, colormap->ncolors); + for (i = 0; i < colormap->ncolors; i++) + { + in_uint32_le(s, colormap->colors[i]); + } + g_free(self->cache_colormap[cache_id]); + self->cache_colormap[cache_id] = colormap; +} + +/*****************************************************************************/ +/* Process a raw bitmap cache order */ +static void APP_CC +rdp_orders_process_raw_bmpcache(struct rdp_orders* self, struct stream* s, + int flags) +{ + int cache_idx; + int bufsize; + int cache_id; + int width; + int height; + int bpp; + int Bpp; + int y; + char* data; + char* inverted; + char* src; + char* dst; + struct rdp_bitmap* bitmap; + + in_uint8(s, cache_id); + in_uint8s(s, 1); + in_uint8(s, width); + in_uint8(s, height); + in_uint8(s, bpp); + Bpp = (bpp + 7) / 8; + in_uint16_le(s, bufsize); + in_uint16_le(s, cache_idx); + in_uint8p(s, data, bufsize); + inverted = (char*)g_malloc(width * height * Bpp, 0); + for (y = 0; y < height; y++) + { + src = data + (y * (width * Bpp)); + dst = inverted + (((height - y) - 1) * (width * Bpp)); + g_memcpy(dst, src, width * Bpp); + } + bitmap = (struct rdp_bitmap*)g_malloc(sizeof(struct rdp_bitmap), 0); + bitmap->width = width; + bitmap->height = height; + bitmap->bpp = bpp; + bitmap->data = inverted; + if (self->cache_bitmap[cache_id][cache_idx] != 0) + { + g_free(self->cache_bitmap[cache_id][cache_idx]->data); + } + g_free(self->cache_bitmap[cache_id][cache_idx]); + self->cache_bitmap[cache_id][cache_idx] = bitmap; +} + +/*****************************************************************************/ +/* Process a bitmap cache order */ +static void APP_CC +rdp_orders_process_bmpcache(struct rdp_orders* self, struct stream* s, + int flags) +{ + char* data; + char* bmpdata; + int cache_idx; + int size; + int cache_id; + int width; + int height; + int bpp; + int Bpp; + int bufsize; + int pad1; + int pad2; + int row_size; + int final_size; + struct rdp_bitmap* bitmap; + + in_uint8(s, cache_id); + in_uint8(s, pad1); + in_uint8(s, width); + in_uint8(s, height); + in_uint8(s, bpp); + Bpp = (bpp + 7) / 8; + in_uint16_le(s, bufsize); + in_uint16_le(s, cache_idx); + if (flags & 1024) + { + size = bufsize; + } + else + { + in_uint16_le(s, pad2); + in_uint16_le(s, size); + in_uint16_le(s, row_size); + in_uint16_le(s, final_size); + } + in_uint8p(s, data, size); + bmpdata = (char*)g_malloc(width * height * Bpp, 0); + if (rdp_bitmap_decompress(bmpdata, width, height, data, size, Bpp)) + { + } + else + { + /* error */ + } + bitmap = (struct rdp_bitmap*)g_malloc(sizeof(struct rdp_bitmap), 0); + bitmap->width = width; + bitmap->height = height; + bitmap->bpp = bpp; + bitmap->data = bmpdata; + if (self->cache_bitmap[cache_id][cache_idx] != 0) + { + g_free(self->cache_bitmap[cache_id][cache_idx]->data); + } + g_free(self->cache_bitmap[cache_id][cache_idx]); + self->cache_bitmap[cache_id][cache_idx] = bitmap; +} + +/*****************************************************************************/ +/* Process a font cache order */ +static void APP_CC +rdp_orders_process_fontcache(struct rdp_orders* self, struct stream* s, + int flags) +{ + int font; + int nglyphs; + int character; + int offset; + int baseline; + int width; + int height; + int i; + int datasize; + char* data; + + in_uint8(s, font); + in_uint8(s, nglyphs); + for (i = 0; i < nglyphs; i++) + { + in_uint16_le(s, character); + in_uint16_le(s, offset); + in_uint16_le(s, baseline); + in_uint16_le(s, width); + in_uint16_le(s, height); + datasize = (height * ((width + 7) / 8) + 3) & ~3; + in_uint8p(s, data, datasize); + self->rdp_layer->mod->server_add_char(self->rdp_layer->mod, font, + character, offset, baseline, + width, height, data); + } +} + +/*****************************************************************************/ +/* Process a secondary order */ +static int APP_CC +rdp_orders_process_secondary_order(struct rdp_orders* self, struct stream* s) +{ + short length; + int flags; + int type; + char* next_order; + + in_uint16_le(s, length); + in_uint16_le(s, flags); + in_uint8(s, type); + next_order = s->p + length + 7; + switch (type) + { + case RDP_ORDER_COLCACHE: + rdp_orders_process_colcache(self, s, flags); + break; + case RDP_ORDER_RAW_BMPCACHE: + rdp_orders_process_raw_bmpcache(self, s, flags); + break; + case RDP_ORDER_BMPCACHE: + rdp_orders_process_bmpcache(self, s, flags); + break; + case RDP_ORDER_FONTCACHE: + rdp_orders_process_fontcache(self, s, flags); + break; + default: + /* error, unknown order */ + break; + } + s->p = next_order; + return 0; +} + +/*****************************************************************************/ +/* Read a color entry */ +static void APP_CC +rdp_orders_in_color(struct stream* s, int* color) +{ + int i; + + in_uint8(s, i); + *color = i; + in_uint8(s, i); + *color |= i << 8; + in_uint8(s, i); + *color |= i << 16; +} + +/*****************************************************************************/ +/* Parse a brush */ +static void APP_CC +rdp_orders_parse_brush(struct stream* s, struct rdp_brush* brush, int present) +{ + if (present & 1) + { + in_uint8(s, brush->xorigin); + } + if (present & 2) + { + in_uint8(s, brush->yorigin); + } + if (present & 4) + { + in_uint8(s, brush->style); + } + if (present & 8) + { + in_uint8(s, brush->pattern[0]); + } + if (present & 16) + { + in_uint8a(s, brush->pattern + 1, 7); + } +} + +/*****************************************************************************/ +/* Parse a pen */ +static void APP_CC +rdp_orders_parse_pen(struct stream* s, struct rdp_pen* pen, int present) +{ + if (present & 1) + { + in_uint8(s, pen->style); + } + if (present & 2) + { + in_uint8(s, pen->width); + } + if (present & 4) + { + rdp_orders_in_color(s, &pen->color); + } +} + +/*****************************************************************************/ +/* Process a text order */ +static void APP_CC +rdp_orders_process_text2(struct rdp_orders* self, struct stream* s, + int present, int delta) +{ + if (present & 0x000001) + { + in_uint8(s, self->state.text_font); + } + if (present & 0x000002) + { + in_uint8(s, self->state.text_flags); + } + if (present & 0x000004) + { + in_uint8(s, self->state.text_opcode); + } + if (present & 0x000008) + { + in_uint8(s, self->state.text_mixmode); + } + if (present & 0x000010) + { + rdp_orders_in_color(s, &self->state.text_fgcolor); + } + if (present & 0x000020) + { + rdp_orders_in_color(s, &self->state.text_bgcolor); + } + if (present & 0x000040) + { + in_sint16_le(s, self->state.text_clipleft); + } + if (present & 0x000080) + { + in_sint16_le(s, self->state.text_cliptop); + } + if (present & 0x000100) + { + in_sint16_le(s, self->state.text_clipright); + } + if (present & 0x000200) + { + in_sint16_le(s, self->state.text_clipbottom); + } + if (present & 0x000400) + { + in_sint16_le(s, self->state.text_boxleft); + } + if (present & 0x000800) + { + in_sint16_le(s, self->state.text_boxtop); + } + if (present & 0x001000) + { + in_sint16_le(s, self->state.text_boxright); + } + if (present & 0x002000) + { + in_sint16_le(s, self->state.text_boxbottom); + } + rdp_orders_parse_brush(s, &self->state.text_brush, present >> 14); + if (present & 0x080000) + { + in_sint16_le(s, self->state.text_x); + } + if (present & 0x100000) + { + in_sint16_le(s, self->state.text_y); + } + if (present & 0x200000) + { + in_uint8(s, self->state.text_length); + in_uint8a(s, self->state.text_text, self->state.text_length); + } + self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, + self->state.text_opcode); + self->rdp_layer->mod->server_set_fgcolor(self->rdp_layer->mod, + self->state.text_fgcolor); + self->rdp_layer->mod->server_set_bgcolor(self->rdp_layer->mod, + self->state.text_bgcolor); + self->rdp_layer->mod->server_draw_text(self->rdp_layer->mod, + self->state.text_font, + self->state.text_flags, + self->state.text_mixmode, + self->state.text_clipleft, + self->state.text_cliptop, + self->state.text_clipright, + self->state.text_clipbottom, + self->state.text_boxleft, + self->state.text_boxtop, + self->state.text_boxright, + self->state.text_boxbottom, + self->state.text_x, + self->state.text_y, + self->state.text_text, + self->state.text_length); + self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, 0xcc); +} + +/*****************************************************************************/ +/* Process a destination blt order */ +static void APP_CC +rdp_orders_process_destblt(struct rdp_orders* self, struct stream* s, + int present, int delta) +{ + if (present & 0x01) + { + rdp_orders_in_coord(s, &self->state.dest_x, delta); + } + if (present & 0x02) + { + rdp_orders_in_coord(s, &self->state.dest_y, delta); + } + if (present & 0x04) + { + rdp_orders_in_coord(s, &self->state.dest_cx, delta); + } + if (present & 0x08) + { + rdp_orders_in_coord(s, &self->state.dest_cy, delta); + } + if (present & 0x10) + { + in_uint8(s, self->state.dest_opcode); + } + self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, + self->state.dest_opcode); + self->rdp_layer->mod->server_fill_rect(self->rdp_layer->mod, + self->state.dest_x, + self->state.dest_y, + self->state.dest_cx, + self->state.dest_cy); + self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, 0xcc); +} + +/*****************************************************************************/ +/* Process a pattern blt order */ +static void APP_CC +rdp_orders_process_patblt(struct rdp_orders* self, struct stream* s, + int present, int delta) +{ + if (present & 0x0001) + { + rdp_orders_in_coord(s, &self->state.pat_x, delta); + } + if (present & 0x0002) + { + rdp_orders_in_coord(s, &self->state.pat_y, delta); + } + if (present & 0x0004) + { + rdp_orders_in_coord(s, &self->state.pat_cx, delta); + } + if (present & 0x0008) + { + rdp_orders_in_coord(s, &self->state.pat_cy, delta); + } + if (present & 0x0010) + { + in_uint8(s, self->state.pat_opcode); + } + if (present & 0x0020) + { + rdp_orders_in_color(s, &self->state.pat_bgcolor); + } + if (present & 0x0040) + { + rdp_orders_in_color(s, &self->state.pat_fgcolor); + } + rdp_orders_parse_brush(s, &self->state.pat_brush, present >> 7); + self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, + self->state.pat_opcode); + self->rdp_layer->mod->server_set_mixmode(self->rdp_layer->mod, 1); + self->rdp_layer->mod->server_set_fgcolor(self->rdp_layer->mod, + self->state.pat_fgcolor); + self->rdp_layer->mod->server_set_bgcolor(self->rdp_layer->mod, + self->state.pat_bgcolor); + self->rdp_layer->mod->server_set_brush(self->rdp_layer->mod, + self->state.pat_brush.xorigin, + self->state.pat_brush.yorigin, + self->state.pat_brush.style, + self->state.pat_brush.pattern); + self->rdp_layer->mod->server_fill_rect(self->rdp_layer->mod, + self->state.pat_x, + self->state.pat_y, + self->state.pat_cx, + self->state.pat_cy); + self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, 0xcc); + self->rdp_layer->mod->server_set_mixmode(self->rdp_layer->mod, 0); +} + +/*****************************************************************************/ +/* Process a screen blt order */ +static void APP_CC +rdp_orders_process_screenblt(struct rdp_orders* self, struct stream* s, + int present, int delta) +{ + if (present & 0x0001) + { + rdp_orders_in_coord(s, &self->state.screenblt_x, delta); + } + if (present & 0x0002) + { + rdp_orders_in_coord(s, &self->state.screenblt_y, delta); + } + if (present & 0x0004) + { + rdp_orders_in_coord(s, &self->state.screenblt_cx, delta); + } + if (present & 0x0008) + { + rdp_orders_in_coord(s, &self->state.screenblt_cy, delta); + } + if (present & 0x0010) + { + in_uint8(s, self->state.screenblt_opcode); + } + if (present & 0x0020) + { + rdp_orders_in_coord(s, &self->state.screenblt_srcx, delta); + } + if (present & 0x0040) + { + rdp_orders_in_coord(s, &self->state.screenblt_srcy, delta); + } + self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, + self->state.screenblt_opcode); + self->rdp_layer->mod->server_screen_blt(self->rdp_layer->mod, + self->state.screenblt_x, + self->state.screenblt_y, + self->state.screenblt_cx, + self->state.screenblt_cy, + self->state.screenblt_srcx, + self->state.screenblt_srcy); + self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, 0xcc); +} + +/*****************************************************************************/ +/* Process a line order */ +static void APP_CC +rdp_orders_process_line(struct rdp_orders* self, struct stream* s, + int present, int delta) +{ + if (present & 0x0001) + { + in_uint16_le(s, self->state.line_mixmode); + } + if (present & 0x0002) + { + rdp_orders_in_coord(s, &self->state.line_startx, delta); + } + if (present & 0x0004) + { + rdp_orders_in_coord(s, &self->state.line_starty, delta); + } + if (present & 0x0008) + { + rdp_orders_in_coord(s, &self->state.line_endx, delta); + } + if (present & 0x0010) + { + rdp_orders_in_coord(s, &self->state.line_endy, delta); + } + if (present & 0x0020) + { + rdp_orders_in_color(s, &self->state.line_bgcolor); + } + if (present & 0x0040) + { + in_uint8(s, self->state.line_opcode); + } + rdp_orders_parse_pen(s, &self->state.line_pen, present >> 7); + self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, + self->state.line_opcode); + self->rdp_layer->mod->server_set_fgcolor(self->rdp_layer->mod, + self->state.line_pen.color); + self->rdp_layer->mod->server_set_pen(self->rdp_layer->mod, + self->state.line_pen.style, + self->state.line_pen.width); + self->rdp_layer->mod->server_draw_line(self->rdp_layer->mod, + self->state.line_startx, + self->state.line_starty, + self->state.line_endx, + self->state.line_endy); + self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, 0xcc); +} + +/*****************************************************************************/ +/* Process an opaque rectangle order */ +static void APP_CC +rdp_orders_process_rect(struct rdp_orders* self, struct stream* s, + int present, int delta) +{ + int i; + + if (present & 0x01) + { + rdp_orders_in_coord(s, &self->state.rect_x, delta); + } + if (present & 0x02) + { + rdp_orders_in_coord(s, &self->state.rect_y, delta); + } + if (present & 0x04) + { + rdp_orders_in_coord(s, &self->state.rect_cx, delta); + } + if (present & 0x08) + { + rdp_orders_in_coord(s, &self->state.rect_cy, delta); + } + if (present & 0x10) + { + in_uint8(s, i); + self->state.rect_color = (self->state.rect_color & 0xffffff00) | i; + } + if (present & 0x20) + { + in_uint8(s, i); + self->state.rect_color = (self->state.rect_color & 0xffff00ff) | (i << 8); + } + if (present & 0x40) + { + in_uint8(s, i); + self->state.rect_color = (self->state.rect_color & 0xff00ffff) | (i << 16); + } + self->rdp_layer->mod->server_set_fgcolor(self->rdp_layer->mod, + self->state.rect_color); + self->rdp_layer->mod->server_fill_rect(self->rdp_layer->mod, + self->state.rect_x, + self->state.rect_y, + self->state.rect_cx, + self->state.rect_cy); +} + +/*****************************************************************************/ +/* Process a desktop save order */ +static void APP_CC +rdp_orders_process_desksave(struct rdp_orders* self, struct stream* s, + int present, int delta) +{ + int width; + int height; + + if (present & 0x01) + { + in_uint32_le(s, self->state.desksave_offset); + } + if (present & 0x02) + { + rdp_orders_in_coord(s, &self->state.desksave_left, delta); + } + if (present & 0x04) + { + rdp_orders_in_coord(s, &self->state.desksave_top, delta); + } + if (present & 0x08) + { + rdp_orders_in_coord(s, &self->state.desksave_right, delta); + } + if (present & 0x10) + { + rdp_orders_in_coord(s, &self->state.desksave_bottom, delta); + } + if (present & 0x20) + { + in_uint8(s, self->state.desksave_action); + } + width = (self->state.desksave_right - self->state.desksave_left) + 1; + height = (self->state.desksave_bottom - self->state.desksave_top) + 1; + if (self->state.desksave_action == 0) + { +// ui_desktop_save(os->offset, os->left, os->top, width, height); + } + else + { +// ui_desktop_restore(os->offset, os->left, os->top, width, height); + } +} + +/*****************************************************************************/ +/* Process a memory blt order */ +static void APP_CC +rdp_orders_process_memblt(struct rdp_orders* self, struct stream* s, + int present, int delta) +{ + struct rdp_bitmap* bitmap; + + if (present & 0x0001) + { + in_uint8(s, self->state.memblt_cache_id); + in_uint8(s, self->state.memblt_color_table); + } + if (present & 0x0002) + { + rdp_orders_in_coord(s, &self->state.memblt_x, delta); + } + if (present & 0x0004) + { + rdp_orders_in_coord(s, &self->state.memblt_y, delta); + } + if (present & 0x0008) + { + rdp_orders_in_coord(s, &self->state.memblt_cx, delta); + } + if (present & 0x0010) + { + rdp_orders_in_coord(s, &self->state.memblt_cy, delta); + } + if (present & 0x0020) + { + in_uint8(s, self->state.memblt_opcode); + } + if (present & 0x0040) + { + rdp_orders_in_coord(s, &self->state.memblt_srcx, delta); + } + if (present & 0x0080) + { + rdp_orders_in_coord(s, &self->state.memblt_srcy, delta); + } + if (present & 0x0100) + { + in_uint16_le(s, self->state.memblt_cache_idx); + } + bitmap = self->cache_bitmap[self->state.memblt_cache_id] + [self->state.memblt_cache_idx]; + if (bitmap != 0) + { + self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, + self->state.memblt_opcode); + self->rdp_layer->mod->server_paint_rect(self->rdp_layer->mod, + self->state.memblt_x, + self->state.memblt_y, + self->state.memblt_cx, + self->state.memblt_cy, + bitmap->data, + bitmap->width, + bitmap->height, + self->state.memblt_srcx, + self->state.memblt_srcy); + self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, 0xcc); + } +} + +/*****************************************************************************/ +/* Process a 3-way blt order */ +static void APP_CC +rdp_orders_process_triblt(struct rdp_orders* self, struct stream* s, + int present, int delta) +{ + /* not used */ +} + +/*****************************************************************************/ +/* Process a polyline order */ +static void APP_CC +rdp_orders_process_polyline(struct rdp_orders* self, struct stream* s, + int present, int delta) +{ + if (present & 0x01) + { + rdp_orders_in_coord(s, &self->state.polyline_x, delta); + } + if (present & 0x02) + { + rdp_orders_in_coord(s, &self->state.polyline_y, delta); + } + if (present & 0x04) + { + in_uint8(s, self->state.polyline_opcode); + } + if (present & 0x10) + { + rdp_orders_in_color(s, &self->state.polyline_fgcolor); + } + if (present & 0x20) + { + in_uint8(s, self->state.polyline_lines); + } + if (present & 0x40) + { + in_uint8(s, self->state.polyline_datasize); + in_uint8a(s, self->state.polyline_data, self->state.polyline_datasize); + } + /* todo */ +} + +/*****************************************************************************/ +int APP_CC +rdp_orders_process_orders(struct rdp_orders* self, struct stream* s, + int num_orders) +{ + int processed; + int order_flags; + int size; + int present; + int delta; + + processed = 0; + while (processed < num_orders) + { + in_uint8(s, order_flags); + if (!(order_flags & RDP_ORDER_STANDARD)) + { + /* error, this should always be set */ + break; + } + if (order_flags & RDP_ORDER_SECONDARY) + { + rdp_orders_process_secondary_order(self, s); + } + else + { + if (order_flags & RDP_ORDER_CHANGE) + { + in_uint8(s, self->state.order_type); + } + switch (self->state.order_type) + { + case RDP_ORDER_TRIBLT: + case RDP_ORDER_TEXT2: + size = 3; + break; + case RDP_ORDER_PATBLT: + case RDP_ORDER_MEMBLT: + case RDP_ORDER_LINE: + size = 2; + break; + default: + size = 1; + break; + } + rdp_orders_in_present(s, &present, order_flags, size); + if (order_flags & RDP_ORDER_BOUNDS) + { + if (!(order_flags & RDP_ORDER_LASTBOUNDS)) + { + rdp_orders_parse_bounds(self, s); + } + self->rdp_layer->mod->server_set_clip(self->rdp_layer->mod, + self->state.clip_left, + self->state.clip_top, + (self->state.clip_right - self->state.clip_left) + 1, + (self->state.clip_bottom - self->state.clip_top) + 1); + } + delta = order_flags & RDP_ORDER_DELTA; + switch (self->state.order_type) + { + case RDP_ORDER_TEXT2: + rdp_orders_process_text2(self, s, present, delta); + break; + case RDP_ORDER_DESTBLT: + rdp_orders_process_destblt(self, s, present, delta); + break; + case RDP_ORDER_PATBLT: + rdp_orders_process_patblt(self, s, present, delta); + break; + case RDP_ORDER_SCREENBLT: + rdp_orders_process_screenblt(self, s, present, delta); + break; + case RDP_ORDER_LINE: + rdp_orders_process_line(self, s, present, delta); + break; + case RDP_ORDER_RECT: + rdp_orders_process_rect(self, s, present, delta); + break; + case RDP_ORDER_DESKSAVE: + rdp_orders_process_desksave(self, s, present, delta); + break; + case RDP_ORDER_MEMBLT: + rdp_orders_process_memblt(self, s, present, delta); + break; + case RDP_ORDER_TRIBLT: + rdp_orders_process_triblt(self, s, present, delta); + break; + case RDP_ORDER_POLYLINE: + rdp_orders_process_polyline(self, s, present, delta); + break; + default: + /* error unknown order */ + break; + } + if (order_flags & RDP_ORDER_BOUNDS) + { + self->rdp_layer->mod->server_reset_clip(self->rdp_layer->mod); + } + } + processed++; + } + return 0; +} |