orders.c revision 6e9aa255e3376b2da5824c09c4c62bc233463bfe
/* -*- c-basic-offset: 8 -*-
rdesktop: A Remote Desktop Protocol client.
RDP order processing
Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
*/
/*
* Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
* other than GPL or LGPL is available it will apply instead, Oracle elects to use only
* the General Public License version 2 (GPLv2) at this time for any software where
* a choice of GPL license versions is made available with the language indicating
* that GPLv2 or any later version may be used, or where a choice of which version
* of the GPL is applied is otherwise unspecified.
*/
#include "rdesktop.h"
#include "orders.h"
extern uint8 *g_next_packet;
static RDP_ORDER_STATE g_order_state;
extern RDP_VERSION g_rdp_version;
/* Read field indicating which parameters are present */
static void
{
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++)
{
}
}
/* Read a co-ordinate (16-bit, or 8-bit delta) */
static void
{
if (delta)
{
}
else
{
in_uint16_le(s, *coord);
}
}
static int
{
value |= ~0x3f;
else
value &= 0x3f;
if (two_byte)
return value;
}
/* Read a colour entry */
static void
{
uint32 i;
in_uint8(s, i);
*colour = i;
in_uint8(s, i);
*colour |= i << 8;
in_uint8(s, i);
*colour |= i << 16;
}
/* Parse bounds information */
static RD_BOOL
{
if (present & 1)
else if (present & 16)
if (present & 2)
else if (present & 32)
if (present & 4)
else if (present & 64)
if (present & 8)
else if (present & 128)
return s_check(s);
}
/* Parse a pen */
static RD_BOOL
{
if (present & 1)
if (present & 2)
if (present & 4)
return s_check(s);
}
static void
{
{
{
}
else
{
}
}
}
/* Parse a brush */
static RD_BOOL
{
if (present & 1)
if (present & 2)
if (present & 4)
if (present & 8)
if (present & 16)
return s_check(s);
}
/* Process a destination blt order */
static void
{
if (present & 0x01)
if (present & 0x02)
if (present & 0x04)
if (present & 0x08)
if (present & 0x10)
DEBUG(("DESTBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d)\n",
}
/* Process a pattern blt order */
static void
{
if (present & 0x0001)
if (present & 0x0002)
if (present & 0x0004)
if (present & 0x0008)
if (present & 0x0010)
if (present & 0x0020)
if (present & 0x0040)
}
/* Process a screen blt order */
static void
{
if (present & 0x0001)
if (present & 0x0002)
if (present & 0x0004)
if (present & 0x0008)
if (present & 0x0010)
if (present & 0x0020)
if (present & 0x0040)
DEBUG(("SCREENBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,srcx=%d,srcy=%d)\n",
}
/* Process a line order */
static void
{
if (present & 0x0001)
if (present & 0x0002)
if (present & 0x0004)
if (present & 0x0008)
if (present & 0x0010)
if (present & 0x0020)
if (present & 0x0040)
DEBUG(("LINE(op=0x%x,sx=%d,sy=%d,dx=%d,dy=%d,fg=0x%x)\n",
{
return;
}
}
/* Process an opaque rectangle order */
static void
{
uint32 i;
if (present & 0x01)
if (present & 0x02)
if (present & 0x04)
if (present & 0x08)
if (present & 0x10)
{
in_uint8(s, i);
}
if (present & 0x20)
{
in_uint8(s, i);
}
if (present & 0x40)
{
in_uint8(s, i);
}
}
/* Process a desktop save order */
static void
{
if (present & 0x01)
if (present & 0x02)
if (present & 0x04)
if (present & 0x08)
if (present & 0x10)
if (present & 0x20)
DEBUG(("DESKSAVE(l=%d,t=%d,r=%d,b=%d,off=%d,op=%d)\n",
else
}
/* Process a memory blt order */
static void
{
if (present & 0x0001)
{
}
if (present & 0x0002)
if (present & 0x0004)
if (present & 0x0008)
if (present & 0x0010)
if (present & 0x0020)
if (present & 0x0040)
if (present & 0x0080)
if (present & 0x0100)
DEBUG(("MEMBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,id=%d,idx=%d)\n",
return;
}
/* Process a 3-way blt order */
static void
{
if (present & 0x000001)
{
}
if (present & 0x000002)
if (present & 0x000004)
if (present & 0x000008)
if (present & 0x000010)
if (present & 0x000020)
if (present & 0x000040)
if (present & 0x000080)
if (present & 0x000100)
if (present & 0x000200)
if (present & 0x008000)
if (present & 0x010000)
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",
return;
}
/* Process a polygon order */
static void
{
if (present & 0x01)
if (present & 0x02)
if (present & 0x04)
if (present & 0x08)
if (present & 0x10)
if (present & 0x20)
if (present & 0x40)
{
}
DEBUG(("POLYGON(x=%d,y=%d,op=0x%x,fm=%d,fg=0x%x,n=%d,sz=%d)\n",
DEBUG(("Data: "));
DEBUG(("\n"));
{
return;
}
index = 0;
{
if (~flags & 0x80)
if (~flags & 0x40)
flags <<= 2;
}
else
error("polygon parse error\n");
}
/* Process a polygon2 order */
static void
{
if (present & 0x0001)
if (present & 0x0002)
if (present & 0x0004)
if (present & 0x0008)
if (present & 0x0010)
if (present & 0x0020)
if (present & 0x0800)
if (present & 0x1000)
{
}
DEBUG(("POLYGON2(x=%d,y=%d,op=0x%x,fm=%d,bs=%d,bg=0x%x,fg=0x%x,n=%d,sz=%d)\n",
DEBUG(("Data: "));
DEBUG(("\n"));
{
return;
}
index = 0;
{
if (~flags & 0x80)
if (~flags & 0x40)
flags <<= 2;
}
else
error("polygon2 parse error\n");
}
/* Process a polyline order */
static void
{
if (present & 0x01)
if (present & 0x02)
if (present & 0x04)
if (present & 0x10)
if (present & 0x20)
if (present & 0x40)
{
}
DEBUG(("POLYLINE(x=%d,y=%d,op=0x%x,fg=0x%x,n=%d,sz=%d)\n",
DEBUG(("Data: "));
DEBUG(("\n"));
{
return;
}
index = 0;
{
if (~flags & 0x80)
if (~flags & 0x40)
flags <<= 2;
}
else
error("polyline parse error\n");
}
/* Process an ellipse order */
static void
{
if (present & 0x01)
if (present & 0x02)
if (present & 0x04)
if (present & 0x08)
if (present & 0x10)
if (present & 0x20)
if (present & 0x40)
}
/* Process an ellipse2 order */
static void
{
if (present & 0x0001)
if (present & 0x0002)
if (present & 0x0004)
if (present & 0x0008)
if (present & 0x0010)
if (present & 0x0020)
if (present & 0x0040)
if (present & 0x0080)
DEBUG(("ELLIPSE2(l=%d,t=%d,r=%d,b=%d,op=0x%x,fm=%d,bs=%d,bg=0x%x,fg=0x%x)\n",
}
/* Process a text order */
static void
{
int i;
if (present & 0x000001)
if (present & 0x000002)
if (present & 0x000004)
if (present & 0x000008)
if (present & 0x000010)
if (present & 0x000020)
if (present & 0x000040)
if (present & 0x000080)
if (present & 0x000100)
if (present & 0x000200)
if (present & 0x000400)
if (present & 0x000800)
if (present & 0x001000)
if (present & 0x002000)
if (present & 0x080000)
in_uint16_le(s, os->x);
if (present & 0x100000)
in_uint16_le(s, os->y);
if (present & 0x200000)
{
}
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));
DEBUG(("Text: "));
DEBUG(("\n"));
}
/* Process a raw bitmap cache order */
static void
{
int y;
in_uint16_le(s, bufsize);
in_uint16_le(s, cache_idx);
for (y = 0; y < height; y++)
{
}
}
/* Process a bitmap cache order */
static void
{
in_uint16_le(s, cache_idx);
if (g_rdp_version >= RDP_V5)
{
}
else
{
/* Begin compressedBitmapData */
in_uint16_le(s, size);
/* in_uint8s(s, 4); *//* row_size, final_size */
in_uint16_le(s, row_size);
in_uint16_le(s, final_size);
}
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));
{
}
else
{
DEBUG(("Failed to decompress bitmap data\n"));
}
}
/* Process a bitmap cache v2 order */
static void
{
int y;
{
}
{
}
else
{
}
in_uint16_be(s, bufsize);
bufsize &= BUFSIZE_MASK;
if (cache_idx & LONG_FORMAT)
{
in_uint8(s, cache_idx_low);
}
DEBUG(("BMPCACHE2(compr=%d,flags=%x,cx=%d,cy=%d,id=%d,idx=%d,Bpp=%d,bs=%d)\n",
if (compressed)
{
{
DEBUG(("Failed to decompress bitmap data\n"));
return;
}
}
else
{
for (y = 0; y < height; y++)
}
if (bitmap)
{
}
else
{
DEBUG(("process_bmpcache2: ui_create_bitmap failed\n"));
}
}
/* Process a colourmap cache order */
static void
{
int i;
{
}
if (cache_id)
}
/* Process a font cache order */
static void
{
int i, datasize;
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);
}
}
static void
{
in_index = 0;
/* read it bottom up */
for (y = 7; y >= 0; y--)
{
/* 2 bytes per row */
x = 0;
{
/* 4 pixels per byte */
shift = 6;
while (shift >= 0)
{
/* size of palette entries depends on Bpp */
for (i = 0; i < Bpp; i++)
{
}
x++;
shift -= 2;
}
in_index++;
}
}
}
/* Process a brush cache order */
static void
{
int index;
int Bpp;
in_uint8(s, colour_code);
{
if (colour_code == 1)
{
if (size == 8)
{
/* read it bottom up */
{
}
}
else
{
size);
}
}
{
{
}
else
{
}
}
else
{
}
}
else
{
}
}
/* Process a secondary order */
static void
{
/* The length isn't calculated correctly by the server.
* For very compact orders the length becomes negative
* so a signed integer must be used. */
in_uint16_le(s, length);
switch (type)
{
case RDP_ORDER_RAW_BMPCACHE:
break;
case RDP_ORDER_COLCACHE:
process_colcache(s);
break;
case RDP_ORDER_BMPCACHE:
process_bmpcache(s);
break;
case RDP_ORDER_FONTCACHE:
break;
case RDP_ORDER_RAW_BMPCACHE2:
break;
case RDP_ORDER_BMPCACHE2:
break;
case RDP_ORDER_BRUSHCACHE:
process_brushcache(s, flags);
break;
default:
}
s->p = next_order;
}
/* Process an order PDU */
void
{
while (processed < num_orders)
{
in_uint8(s, order_flags);
if (!(order_flags & RDP_ORDER_STANDARD))
{
error("order parsing failed\n");
break;
}
if (order_flags & RDP_ORDER_SECONDARY)
{
}
else
{
if (order_flags & RDP_ORDER_CHANGE)
{
}
switch (os->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:
case RDP_ORDER_POLYGON2:
case RDP_ORDER_ELLIPSE2:
size = 2;
break;
default:
size = 1;
}
if (order_flags & RDP_ORDER_BOUNDS)
{
if (!(order_flags & RDP_ORDER_LASTBOUNDS))
}
switch (os->order_type)
{
case RDP_ORDER_DESTBLT:
break;
case RDP_ORDER_PATBLT:
break;
case RDP_ORDER_SCREENBLT:
break;
case RDP_ORDER_LINE:
break;
case RDP_ORDER_RECT:
break;
case RDP_ORDER_DESKSAVE:
break;
case RDP_ORDER_MEMBLT:
break;
case RDP_ORDER_TRIBLT:
break;
case RDP_ORDER_POLYGON:
break;
case RDP_ORDER_POLYGON2:
break;
case RDP_ORDER_POLYLINE:
break;
case RDP_ORDER_ELLIPSE:
break;
case RDP_ORDER_ELLIPSE2:
break;
case RDP_ORDER_TEXT2:
break;
default:
return;
}
if (order_flags & RDP_ORDER_BOUNDS)
}
processed++;
}
#if 0
/* not true when RDP_COMPRESSION is set */
if (s->p != g_next_packet)
#endif
}
/* Reset order state */
void
reset_order_state(void)
{
}