You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
977 lines
28 KiB
977 lines
28 KiB
|
|
/*
|
|
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.
|
|
|
|
Copyright (C) Jay Sorg 2004
|
|
|
|
orders
|
|
|
|
*/
|
|
|
|
#include "xrdp.h"
|
|
|
|
/*****************************************************************************/
|
|
struct xrdp_orders* xrdp_orders_create(struct xrdp_process* owner)
|
|
{
|
|
struct xrdp_orders* self;
|
|
|
|
self = (struct xrdp_orders*)g_malloc(sizeof(struct xrdp_orders), 1);
|
|
self->pro_layer = owner;
|
|
self->rdp_layer = owner->rdp_layer;
|
|
self->out_s = &owner->out_s;
|
|
return self;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
void xrdp_orders_delete(struct xrdp_orders* self)
|
|
{
|
|
g_free(self);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* returns error */
|
|
int xrdp_orders_init(struct xrdp_orders* self)
|
|
{
|
|
self->order_level++;
|
|
if (self->order_level == 1)
|
|
{
|
|
self->order_count = 0;
|
|
if (xrdp_rdp_init_data(self->rdp_layer, 8192) != 0) /* is this big enough */
|
|
return 1;
|
|
out_uint16_le(self->out_s, RDP_UPDATE_ORDERS);
|
|
out_uint8s(self->out_s, 2); /* pad */
|
|
self->order_count_ptr = self->out_s->p;
|
|
out_uint8s(self->out_s, 2); /* number of orders, set later */
|
|
out_uint8s(self->out_s, 2); /* pad */
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* returns error */
|
|
int xrdp_orders_send(struct xrdp_orders* self)
|
|
{
|
|
int rv;
|
|
|
|
rv = 0;
|
|
if (self->order_level > 0)
|
|
{
|
|
self->order_level--;
|
|
if (self->order_level == 0)
|
|
{
|
|
s_mark_end(self->out_s);
|
|
*((short*)self->order_count_ptr) = self->order_count;
|
|
if (xrdp_rdp_send_data(self->rdp_layer, RDP_DATA_PDU_UPDATE) != 0)
|
|
rv = 1;
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* returns error */
|
|
int xrdp_orders_force_send(struct xrdp_orders* self)
|
|
{
|
|
if (self->order_count > 0)
|
|
{
|
|
s_mark_end(self->out_s);
|
|
*((short*)self->order_count_ptr) = self->order_count;
|
|
if (xrdp_rdp_send_data(self->rdp_layer, RDP_DATA_PDU_UPDATE) != 0)
|
|
return 1;
|
|
}
|
|
self->order_count = 0;
|
|
self->order_level = 0;
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
int xrdp_orders_check(struct xrdp_orders* self, int max_size)
|
|
{
|
|
int size;
|
|
|
|
if (self->order_level < 1)
|
|
{
|
|
if (max_size > 8000)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
size = self->out_s->p - self->order_count_ptr;
|
|
if (size < 0 || size > 8192)
|
|
return 1;
|
|
if (size + max_size + 100 > 8000)
|
|
{
|
|
xrdp_orders_force_send(self);
|
|
xrdp_orders_init(self);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* returns boolean */
|
|
int xrdp_orders_last_bounds(struct xrdp_orders* self,
|
|
struct xrdp_rect* rect)
|
|
{
|
|
if (rect == 0)
|
|
return 0;
|
|
if (rect->left == self->clip_left && rect->top == self->clip_top &&
|
|
rect->right == self->clip_right && rect->bottom == self->clip_bottom)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* returns boolean */
|
|
int xrdp_orders_send_delta(struct xrdp_orders* self, int* vals, int count)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < count; i += 2)
|
|
if (g_abs(vals[i] - vals[i + 1]) >= 128)
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* returns error */
|
|
int xrdp_orders_out_bounds(struct xrdp_orders* self, struct xrdp_rect* rect)
|
|
{
|
|
char* bounds_flags_ptr;
|
|
int bounds_flags;
|
|
|
|
bounds_flags = 0;
|
|
bounds_flags_ptr = self->out_s->p;
|
|
out_uint8s(self->out_s, 1);
|
|
/* left */
|
|
if (rect->left == self->clip_left) ;
|
|
else if (g_abs(rect->left - self->clip_left) < 128)
|
|
bounds_flags |= 0x10;
|
|
else
|
|
bounds_flags |= 0x01;
|
|
/* top */
|
|
if (rect->top == self->clip_top) ;
|
|
else if (g_abs(rect->top - self->clip_top) < 128)
|
|
bounds_flags |= 0x20;
|
|
else
|
|
bounds_flags |= 0x02;
|
|
/* right */
|
|
if (rect->right == self->clip_right) ;
|
|
else if (g_abs(rect->right - self->clip_right) < 128)
|
|
bounds_flags |= 0x40;
|
|
else
|
|
bounds_flags |= 0x04;
|
|
/* bottom */
|
|
if (rect->bottom == self->clip_bottom) ;
|
|
else if (g_abs(rect->bottom - self->clip_bottom) < 128)
|
|
bounds_flags |= 0x80;
|
|
else
|
|
bounds_flags |= 0x08;
|
|
/* left */
|
|
if (bounds_flags & 0x01)
|
|
out_uint16_le(self->out_s, rect->left)
|
|
else if (bounds_flags & 0x10)
|
|
out_uint8(self->out_s, rect->left - self->clip_left)
|
|
self->clip_left = rect->left;
|
|
/* top */
|
|
if (bounds_flags & 0x02)
|
|
out_uint16_le(self->out_s, rect->top)
|
|
else if (bounds_flags & 0x20)
|
|
out_uint8(self->out_s, rect->top - self->clip_top)
|
|
self->clip_top = rect->top;
|
|
/* right */
|
|
if (bounds_flags & 0x04)
|
|
out_uint16_le(self->out_s, rect->right)
|
|
else if (bounds_flags & 0x40)
|
|
out_uint8(self->out_s, rect->right - self->clip_right)
|
|
self->clip_right = rect->right;
|
|
/* bottom */
|
|
if (bounds_flags & 0x08)
|
|
out_uint16_le(self->out_s, rect->bottom)
|
|
else if (bounds_flags & 0x80)
|
|
out_uint8(self->out_s, rect->bottom - self->clip_bottom)
|
|
self->clip_bottom = rect->bottom;
|
|
/* set flags */
|
|
*bounds_flags_ptr = bounds_flags;
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* returns error */
|
|
/* send a solid rect to client */
|
|
/* max size 23 */
|
|
int xrdp_orders_rect(struct xrdp_orders* self, int x, int y, int cx, int cy,
|
|
int color, struct xrdp_rect* rect)
|
|
{
|
|
int order_flags;
|
|
int vals[8];
|
|
int present;
|
|
char* present_ptr;
|
|
|
|
xrdp_orders_check(self, 23);
|
|
self->order_count++;
|
|
order_flags = RDP_ORDER_STANDARD;
|
|
if (self->last_order != RDP_ORDER_RECT)
|
|
order_flags |= RDP_ORDER_CHANGE;
|
|
self->last_order = RDP_ORDER_RECT;
|
|
if (rect != 0)
|
|
{
|
|
order_flags |= RDP_ORDER_BOUNDS;
|
|
if (xrdp_orders_last_bounds(self, rect))
|
|
order_flags |= RDP_ORDER_LASTBOUNDS;
|
|
}
|
|
vals[0] = x; vals[1] = self->rect_x;
|
|
vals[2] = y; vals[3] = self->rect_y;
|
|
vals[4] = cx; vals[5] = self->rect_cx;
|
|
vals[6] = cy; vals[7] = self->rect_cy;
|
|
if (xrdp_orders_send_delta(self, vals, 8))
|
|
order_flags |= RDP_ORDER_DELTA;
|
|
out_uint8(self->out_s, order_flags)
|
|
if (order_flags & RDP_ORDER_CHANGE)
|
|
out_uint8(self->out_s, self->last_order)
|
|
present = 0;
|
|
present_ptr = self->out_s->p; /* hold 1 byte present pointer */
|
|
out_uint8s(self->out_s, 1)
|
|
if ((order_flags & RDP_ORDER_BOUNDS) &&
|
|
!(order_flags & RDP_ORDER_LASTBOUNDS))
|
|
xrdp_orders_out_bounds(self, rect);
|
|
if (x != self->rect_x)
|
|
{
|
|
present |= 0x01;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, x - self->rect_x)
|
|
else
|
|
out_uint16_le(self->out_s, x)
|
|
self->rect_x = x;
|
|
}
|
|
if (y != self->rect_y)
|
|
{
|
|
present |= 0x02;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, y - self->rect_y)
|
|
else
|
|
out_uint16_le(self->out_s, y)
|
|
self->rect_y = y;
|
|
}
|
|
if (cx != self->rect_cx)
|
|
{
|
|
present |= 0x04;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, cx - self->rect_cx)
|
|
else
|
|
out_uint16_le(self->out_s, cx)
|
|
self->rect_cx = cx;
|
|
}
|
|
if (cy != self->rect_cy)
|
|
{
|
|
present |= 0x08;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, cy - self->rect_cy)
|
|
else
|
|
out_uint16_le(self->out_s, cy)
|
|
self->rect_cy = cy;
|
|
}
|
|
if ((color & 0xff) != (self->rect_color & 0xff))
|
|
{
|
|
present |= 0x10;
|
|
self->rect_color = (self->rect_color & 0xffff00) | (color & 0xff);
|
|
out_uint8(self->out_s, color);
|
|
}
|
|
if ((color & 0xff00) != (self->rect_color & 0xff00))
|
|
{
|
|
present |= 0x20;
|
|
self->rect_color = (self->rect_color & 0xff00ff) | (color & 0xff00);
|
|
out_uint8(self->out_s, color >> 8);
|
|
}
|
|
if ((color & 0xff0000) != (self->rect_color & 0xff0000))
|
|
{
|
|
present |= 0x40;
|
|
self->rect_color = (self->rect_color & 0x00ffff) | (color & 0xff0000);
|
|
out_uint8(self->out_s, color >> 16);
|
|
}
|
|
*present_ptr = present;
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* returns error */
|
|
/* send a screen blt order */
|
|
/* max size 25 */
|
|
int xrdp_orders_screen_blt(struct xrdp_orders* self, int x, int y,
|
|
int cx, int cy, int srcx, int srcy,
|
|
int rop, struct xrdp_rect* rect)
|
|
{
|
|
int order_flags;
|
|
int vals[12];
|
|
int present;
|
|
char* present_ptr;
|
|
|
|
xrdp_orders_check(self, 25);
|
|
self->order_count++;
|
|
order_flags = RDP_ORDER_STANDARD;
|
|
if (self->last_order != RDP_ORDER_SCREENBLT)
|
|
order_flags |= RDP_ORDER_CHANGE;
|
|
self->last_order = RDP_ORDER_SCREENBLT;
|
|
if (rect != 0)
|
|
{
|
|
order_flags |= RDP_ORDER_BOUNDS;
|
|
if (xrdp_orders_last_bounds(self, rect))
|
|
order_flags |= RDP_ORDER_LASTBOUNDS;
|
|
}
|
|
vals[0] = x; vals[1] = self->scr_blt_x;
|
|
vals[2] = y; vals[3] = self->scr_blt_y;
|
|
vals[4] = cx; vals[5] = self->scr_blt_cx;
|
|
vals[6] = cy; vals[7] = self->scr_blt_cy;
|
|
vals[8] = srcx; vals[9] = self->scr_blt_srcx;
|
|
vals[10] = srcy; vals[11] = self->scr_blt_srcy;
|
|
if (xrdp_orders_send_delta(self, vals, 12))
|
|
order_flags |= RDP_ORDER_DELTA;
|
|
out_uint8(self->out_s, order_flags);
|
|
if (order_flags & RDP_ORDER_CHANGE)
|
|
out_uint8(self->out_s, self->last_order)
|
|
present = 0;
|
|
present_ptr = self->out_s->p; /* hold 1 byte present pointer */
|
|
out_uint8s(self->out_s, 1)
|
|
if ((order_flags & RDP_ORDER_BOUNDS) &&
|
|
!(order_flags & RDP_ORDER_LASTBOUNDS))
|
|
xrdp_orders_out_bounds(self, rect);
|
|
if (x != self->scr_blt_x)
|
|
{
|
|
present |= 0x01;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, x - self->scr_blt_x)
|
|
else
|
|
out_uint16_le(self->out_s, x)
|
|
self->scr_blt_x = x;
|
|
}
|
|
if (y != self->scr_blt_y)
|
|
{
|
|
present |= 0x02;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, y - self->scr_blt_y)
|
|
else
|
|
out_uint16_le(self->out_s, y)
|
|
self->scr_blt_y = y;
|
|
}
|
|
if (cx != self->scr_blt_cx)
|
|
{
|
|
present |= 0x04;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, cx - self->scr_blt_cx)
|
|
else
|
|
out_uint16_le(self->out_s, cx)
|
|
self->scr_blt_cx = cx;
|
|
}
|
|
if (cy != self->scr_blt_cy)
|
|
{
|
|
present |= 0x08;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, cy - self->scr_blt_cy)
|
|
else
|
|
out_uint16_le(self->out_s, cy)
|
|
self->scr_blt_cy = cy;
|
|
}
|
|
if (rop != self->scr_blt_rop)
|
|
{
|
|
present |= 0x10;
|
|
out_uint8(self->out_s, rop);
|
|
self->scr_blt_rop = rop;
|
|
}
|
|
if (srcx != self->scr_blt_srcx)
|
|
{
|
|
present |= 0x20;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, srcx - self->scr_blt_srcx)
|
|
else
|
|
out_uint16_le(self->out_s, srcx)
|
|
self->scr_blt_srcx = srcx;
|
|
}
|
|
if (srcy != self->scr_blt_srcy)
|
|
{
|
|
present |= 0x40;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, srcy - self->scr_blt_srcy)
|
|
else
|
|
out_uint16_le(self->out_s, srcy)
|
|
self->scr_blt_srcy = srcy;
|
|
}
|
|
*present_ptr = present;
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* returns error */
|
|
/* send a pat blt order */
|
|
/* max size 39 */
|
|
int xrdp_orders_pat_blt(struct xrdp_orders* self, int x, int y,
|
|
int cx, int cy, int rop, int bg_color,
|
|
int fg_color, struct xrdp_brush* brush,
|
|
struct xrdp_rect* rect)
|
|
{
|
|
int order_flags;
|
|
int vals[8];
|
|
int present;
|
|
char* present_ptr;
|
|
struct xrdp_brush blank_brush;
|
|
|
|
xrdp_orders_check(self, 39);
|
|
self->order_count++;
|
|
order_flags = RDP_ORDER_STANDARD;
|
|
if (self->last_order != RDP_ORDER_PATBLT)
|
|
order_flags |= RDP_ORDER_CHANGE;
|
|
self->last_order = RDP_ORDER_PATBLT;
|
|
if (rect != 0)
|
|
{
|
|
order_flags |= RDP_ORDER_BOUNDS;
|
|
if (xrdp_orders_last_bounds(self, rect))
|
|
order_flags |= RDP_ORDER_LASTBOUNDS;
|
|
}
|
|
vals[0] = x; vals[1] = self->pat_blt_x;
|
|
vals[2] = y; vals[3] = self->pat_blt_y;
|
|
vals[4] = cx; vals[5] = self->pat_blt_cx;
|
|
vals[6] = cy; vals[7] = self->pat_blt_cy;
|
|
if (xrdp_orders_send_delta(self, vals, 8))
|
|
order_flags |= RDP_ORDER_DELTA;
|
|
out_uint8(self->out_s, order_flags);
|
|
if (order_flags & RDP_ORDER_CHANGE)
|
|
out_uint8(self->out_s, self->last_order)
|
|
present = 0;
|
|
present_ptr = self->out_s->p; /* hold 2 byte present pointer, todo */
|
|
out_uint8s(self->out_s, 2) /* this can be smaller, */
|
|
/* see RDP_ORDER_SMALL and RDP_ORDER_TINY */
|
|
if ((order_flags & RDP_ORDER_BOUNDS) &&
|
|
!(order_flags & RDP_ORDER_LASTBOUNDS))
|
|
xrdp_orders_out_bounds(self, rect);
|
|
if (x != self->pat_blt_x)
|
|
{
|
|
present |= 0x0001;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, x - self->pat_blt_x)
|
|
else
|
|
out_uint16_le(self->out_s, x)
|
|
self->pat_blt_x = x;
|
|
}
|
|
if (y != self->pat_blt_y)
|
|
{
|
|
present |= 0x0002;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, y - self->pat_blt_y)
|
|
else
|
|
out_uint16_le(self->out_s, y)
|
|
self->pat_blt_y = y;
|
|
}
|
|
if (cx != self->pat_blt_cx)
|
|
{
|
|
present |= 0x0004;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, cx - self->pat_blt_cx)
|
|
else
|
|
out_uint16_le(self->out_s, cx)
|
|
self->pat_blt_cx = cx;
|
|
}
|
|
if (cy != self->pat_blt_cy)
|
|
{
|
|
present |= 0x0008;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, cy - self->pat_blt_cy)
|
|
else
|
|
out_uint16_le(self->out_s, cy)
|
|
self->pat_blt_cy = cy;
|
|
}
|
|
if (rop != self->pat_blt_rop)
|
|
{
|
|
present |= 0x0010;
|
|
/* PATCOPY PATPAINT PATINVERT DSTINVERT BLACKNESS WHITENESS */
|
|
out_uint8(self->out_s, rop);
|
|
self->pat_blt_rop = rop;
|
|
}
|
|
if (bg_color != self->pat_blt_bg_color)
|
|
{
|
|
present |= 0x0020;
|
|
out_uint8(self->out_s, bg_color);
|
|
out_uint8(self->out_s, bg_color >> 8);
|
|
out_uint8(self->out_s, bg_color >> 16);
|
|
self->pat_blt_bg_color = bg_color;
|
|
}
|
|
if (fg_color != self->pat_blt_fg_color)
|
|
{
|
|
present |= 0x0040;
|
|
out_uint8(self->out_s, fg_color);
|
|
out_uint8(self->out_s, fg_color >> 8);
|
|
out_uint8(self->out_s, fg_color >> 16);
|
|
self->pat_blt_fg_color = fg_color;
|
|
}
|
|
if (brush == 0) /* if nil use blank one */
|
|
{ /* todo can we just set style to zero */
|
|
g_memset(&blank_brush, 0, sizeof(struct xrdp_brush));
|
|
brush = &blank_brush;
|
|
}
|
|
if (brush->x_orgin != self->pat_blt_brush.x_orgin)
|
|
{
|
|
present |= 0x0080;
|
|
out_uint8(self->out_s, brush->x_orgin);
|
|
self->pat_blt_brush.x_orgin = brush->x_orgin;
|
|
}
|
|
if (brush->y_orgin != self->pat_blt_brush.y_orgin)
|
|
{
|
|
present |= 0x0100;
|
|
out_uint8(self->out_s, brush->y_orgin);
|
|
self->pat_blt_brush.y_orgin = brush->y_orgin;
|
|
}
|
|
if (brush->style != self->pat_blt_brush.style)
|
|
{
|
|
present |= 0x0200;
|
|
out_uint8(self->out_s, brush->style);
|
|
self->pat_blt_brush.style = brush->style;
|
|
}
|
|
if (brush->pattern[0] != self->pat_blt_brush.pattern[0])
|
|
{
|
|
present |= 0x0400;
|
|
out_uint8(self->out_s, brush->pattern[0]);
|
|
self->pat_blt_brush.pattern[0] = brush->pattern[0];
|
|
}
|
|
if (g_memcmp(brush->pattern + 1, self->pat_blt_brush.pattern + 1, 7) != 0)
|
|
{
|
|
present |= 0x0800;
|
|
out_uint8a(self->out_s, brush->pattern + 1, 7);
|
|
g_memcpy(self->pat_blt_brush.pattern + 1, brush->pattern + 1, 7);
|
|
}
|
|
*((short*)present_ptr) = present;
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* returns error */
|
|
/* send a dest blt order */
|
|
/* max size 21 */
|
|
int xrdp_orders_dest_blt(struct xrdp_orders* self, int x, int y,
|
|
int cx, int cy, int rop,
|
|
struct xrdp_rect* rect)
|
|
{
|
|
int order_flags;
|
|
int vals[8];
|
|
int present;
|
|
char* present_ptr;
|
|
|
|
xrdp_orders_check(self, 21);
|
|
self->order_count++;
|
|
order_flags = RDP_ORDER_STANDARD;
|
|
if (self->last_order != RDP_ORDER_DESTBLT)
|
|
order_flags |= RDP_ORDER_CHANGE;
|
|
self->last_order = RDP_ORDER_DESTBLT;
|
|
if (rect != 0)
|
|
{
|
|
order_flags |= RDP_ORDER_BOUNDS;
|
|
if (xrdp_orders_last_bounds(self, rect))
|
|
order_flags |= RDP_ORDER_LASTBOUNDS;
|
|
}
|
|
vals[0] = x; vals[1] = self->dest_blt_x;
|
|
vals[2] = y; vals[3] = self->dest_blt_y;
|
|
vals[4] = cx; vals[5] = self->dest_blt_cx;
|
|
vals[6] = cy; vals[7] = self->dest_blt_cy;
|
|
if (xrdp_orders_send_delta(self, vals, 8))
|
|
order_flags |= RDP_ORDER_DELTA;
|
|
out_uint8(self->out_s, order_flags);
|
|
if (order_flags & RDP_ORDER_CHANGE)
|
|
out_uint8(self->out_s, self->last_order)
|
|
present = 0;
|
|
present_ptr = self->out_s->p; /* hold 1 byte present pointer */
|
|
out_uint8s(self->out_s, 1)
|
|
if ((order_flags & RDP_ORDER_BOUNDS) &&
|
|
!(order_flags & RDP_ORDER_LASTBOUNDS))
|
|
xrdp_orders_out_bounds(self, rect);
|
|
if (x != self->dest_blt_x)
|
|
{
|
|
present |= 0x01;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, x - self->dest_blt_x)
|
|
else
|
|
out_uint16_le(self->out_s, x)
|
|
self->dest_blt_x = x;
|
|
}
|
|
if (y != self->dest_blt_y)
|
|
{
|
|
present |= 0x02;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, y - self->dest_blt_y)
|
|
else
|
|
out_uint16_le(self->out_s, y)
|
|
self->dest_blt_y = y;
|
|
}
|
|
if (cx != self->dest_blt_cx)
|
|
{
|
|
present |= 0x04;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, cx - self->dest_blt_cx)
|
|
else
|
|
out_uint16_le(self->out_s, cx)
|
|
self->dest_blt_cx = cx;
|
|
}
|
|
if (cy != self->dest_blt_cy)
|
|
{
|
|
present |= 0x08;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, cy - self->dest_blt_cy)
|
|
else
|
|
out_uint16_le(self->out_s, cy)
|
|
self->dest_blt_cy = cy;
|
|
}
|
|
if (rop != self->dest_blt_rop)
|
|
{
|
|
present |= 0x0010;
|
|
out_uint8(self->out_s, rop);
|
|
self->dest_blt_rop = rop;
|
|
}
|
|
*present_ptr = present;
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* returns error */
|
|
/* send a line order */
|
|
/* max size 32 */
|
|
int xrdp_orders_line(struct xrdp_orders* self, int mix_mode,
|
|
int startx, int starty,
|
|
int endx, int endy, int rop, int bg_color,
|
|
struct xrdp_pen* pen,
|
|
struct xrdp_rect* rect)
|
|
{
|
|
int order_flags;
|
|
int vals[8];
|
|
int present;
|
|
char* present_ptr;
|
|
struct xrdp_pen blank_pen;
|
|
|
|
xrdp_orders_check(self, 32);
|
|
self->order_count++;
|
|
order_flags = RDP_ORDER_STANDARD;
|
|
if (self->last_order != RDP_ORDER_LINE)
|
|
order_flags |= RDP_ORDER_CHANGE;
|
|
self->last_order = RDP_ORDER_LINE;
|
|
if (rect != 0)
|
|
{
|
|
order_flags |= RDP_ORDER_BOUNDS;
|
|
if (xrdp_orders_last_bounds(self, rect))
|
|
order_flags |= RDP_ORDER_LASTBOUNDS;
|
|
}
|
|
vals[0] = startx; vals[1] = self->line_startx;
|
|
vals[2] = starty; vals[3] = self->line_starty;
|
|
vals[4] = endx; vals[5] = self->line_endx;
|
|
vals[6] = endy; vals[7] = self->line_endy;
|
|
if (xrdp_orders_send_delta(self, vals, 8))
|
|
order_flags |= RDP_ORDER_DELTA;
|
|
out_uint8(self->out_s, order_flags);
|
|
if (order_flags & RDP_ORDER_CHANGE)
|
|
out_uint8(self->out_s, self->last_order)
|
|
present = 0;
|
|
present_ptr = self->out_s->p; /* hold 2 byte present pointer */
|
|
out_uint8s(self->out_s, 2)
|
|
if ((order_flags & RDP_ORDER_BOUNDS) &&
|
|
!(order_flags & RDP_ORDER_LASTBOUNDS))
|
|
xrdp_orders_out_bounds(self, rect);
|
|
if (mix_mode != self->line_mix_mode)
|
|
{
|
|
present |= 0x0001;
|
|
out_uint16_le(self->out_s, mix_mode)
|
|
self->line_mix_mode = mix_mode;
|
|
}
|
|
if (startx != self->line_startx)
|
|
{
|
|
present |= 0x0002;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, startx - self->line_startx)
|
|
else
|
|
out_uint16_le(self->out_s, startx)
|
|
self->line_startx = startx;
|
|
}
|
|
if (starty != self->line_starty)
|
|
{
|
|
present |= 0x0004;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, starty - self->line_starty)
|
|
else
|
|
out_uint16_le(self->out_s, starty)
|
|
self->line_starty = starty;
|
|
}
|
|
if (endx != self->line_endx)
|
|
{
|
|
present |= 0x0008;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, endx - self->line_endx)
|
|
else
|
|
out_uint16_le(self->out_s, endx)
|
|
self->line_endx = endx;
|
|
}
|
|
if (endy != self->line_endy)
|
|
{
|
|
present |= 0x0010;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, endy - self->line_endy)
|
|
else
|
|
out_uint16_le(self->out_s, endy)
|
|
self->line_endy = endy;
|
|
}
|
|
if (bg_color != self->line_bg_color)
|
|
{
|
|
present |= 0x0020;
|
|
out_uint8(self->out_s, bg_color)
|
|
out_uint8(self->out_s, bg_color >> 8)
|
|
out_uint8(self->out_s, bg_color >> 16)
|
|
self->line_bg_color = bg_color;
|
|
}
|
|
if (rop != self->line_rop)
|
|
{
|
|
present |= 0x0040;
|
|
out_uint8(self->out_s, rop)
|
|
self->line_rop = rop;
|
|
}
|
|
if (pen == 0)
|
|
{
|
|
g_memset(&blank_pen, 0, sizeof(struct xrdp_pen));
|
|
pen = &blank_pen;
|
|
}
|
|
if (pen->style != self->line_pen.style)
|
|
{
|
|
present |= 0x0080;
|
|
out_uint8(self->out_s, pen->style)
|
|
self->line_pen.style = pen->style;
|
|
}
|
|
if (pen->width != self->line_pen.width)
|
|
{
|
|
present |= 0x0100;
|
|
out_uint8(self->out_s, pen->width)
|
|
self->line_pen.width = pen->width;
|
|
}
|
|
if (pen->color != self->line_pen.color)
|
|
{
|
|
present |= 0x0200;
|
|
out_uint8(self->out_s, pen->color)
|
|
out_uint8(self->out_s, pen->color >> 8)
|
|
out_uint8(self->out_s, pen->color >> 16)
|
|
self->line_pen.color = pen->color;
|
|
}
|
|
*((short*)present_ptr) = present;
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* returns error */
|
|
/* send a mem blt order */
|
|
/* max size 30 */
|
|
int xrdp_orders_mem_blt(struct xrdp_orders* self, int cache_id,
|
|
int color_table, int x, int y, int cx, int cy,
|
|
int rop, int srcx, int srcy,
|
|
int cache_idx, struct xrdp_rect* rect)
|
|
{
|
|
int order_flags;
|
|
int vals[12];
|
|
int present;
|
|
char* present_ptr;
|
|
|
|
xrdp_orders_check(self, 30);
|
|
self->order_count++;
|
|
order_flags = RDP_ORDER_STANDARD;
|
|
if (self->last_order != RDP_ORDER_MEMBLT)
|
|
order_flags |= RDP_ORDER_CHANGE;
|
|
self->last_order = RDP_ORDER_MEMBLT;
|
|
if (rect != 0)
|
|
{
|
|
order_flags |= RDP_ORDER_BOUNDS;
|
|
if (xrdp_orders_last_bounds(self, rect))
|
|
order_flags |= RDP_ORDER_LASTBOUNDS;
|
|
}
|
|
vals[0] = x; vals[1] = self->mem_blt_x;
|
|
vals[2] = y; vals[3] = self->mem_blt_y;
|
|
vals[4] = cx; vals[5] = self->mem_blt_cx;
|
|
vals[6] = cy; vals[7] = self->mem_blt_cy;
|
|
vals[8] = srcx; vals[9] = self->mem_blt_srcx;
|
|
vals[10] = srcy; vals[11] = self->mem_blt_srcy;
|
|
if (xrdp_orders_send_delta(self, vals, 12))
|
|
order_flags |= RDP_ORDER_DELTA;
|
|
out_uint8(self->out_s, order_flags);
|
|
if (order_flags & RDP_ORDER_CHANGE)
|
|
out_uint8(self->out_s, self->last_order)
|
|
present = 0;
|
|
present_ptr = self->out_s->p; /* hold 2 byte present pointer, todo */
|
|
out_uint8s(self->out_s, 2) /* this can be smaller, */
|
|
/* see RDP_ORDER_SMALL and RDP_ORDER_TINY */
|
|
if ((order_flags & RDP_ORDER_BOUNDS) &&
|
|
!(order_flags & RDP_ORDER_LASTBOUNDS))
|
|
xrdp_orders_out_bounds(self, rect);
|
|
if (cache_id != self->mem_blt_cache_id ||
|
|
color_table != self->mem_blt_color_table)
|
|
{
|
|
present |= 0x0001;
|
|
out_uint8(self->out_s, cache_id);
|
|
out_uint8(self->out_s, color_table);
|
|
self->mem_blt_cache_id = cache_id;
|
|
self->mem_blt_color_table = color_table;
|
|
}
|
|
if (x != self->mem_blt_x)
|
|
{
|
|
present |= 0x0002;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, x - self->mem_blt_x)
|
|
else
|
|
out_uint16_le(self->out_s, x)
|
|
self->mem_blt_x = x;
|
|
}
|
|
if (y != self->mem_blt_y)
|
|
{
|
|
present |= 0x0004;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, y - self->mem_blt_y)
|
|
else
|
|
out_uint16_le(self->out_s, y)
|
|
self->mem_blt_y = y;
|
|
}
|
|
if (cx != self->mem_blt_cx)
|
|
{
|
|
present |= 0x0008;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, cx - self->mem_blt_cx)
|
|
else
|
|
out_uint16_le(self->out_s, cx)
|
|
self->mem_blt_cx = cx;
|
|
}
|
|
if (cy != self->mem_blt_cy)
|
|
{
|
|
present |= 0x0010;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, cy - self->mem_blt_cy)
|
|
else
|
|
out_uint16_le(self->out_s, cy)
|
|
self->mem_blt_cy = cy;
|
|
}
|
|
if (rop != self->mem_blt_rop)
|
|
{
|
|
present |= 0x0020;
|
|
out_uint8(self->out_s, rop);
|
|
self->mem_blt_rop = rop;
|
|
}
|
|
if (srcx != self->mem_blt_srcx)
|
|
{
|
|
present |= 0x0040;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, srcx - self->mem_blt_srcx)
|
|
else
|
|
out_uint16_le(self->out_s, srcx)
|
|
self->mem_blt_srcx = srcx;
|
|
}
|
|
if (srcy != self->mem_blt_srcy)
|
|
{
|
|
present |= 0x0080;
|
|
if (order_flags & RDP_ORDER_DELTA)
|
|
out_uint8(self->out_s, srcy - self->mem_blt_srcy)
|
|
else
|
|
out_uint16_le(self->out_s, srcy)
|
|
self->mem_blt_srcy = srcy;
|
|
}
|
|
if (cache_idx != self->mem_blt_cache_idx)
|
|
{
|
|
present |= 0x0100;
|
|
out_uint16_le(self->out_s, cache_idx);
|
|
self->mem_blt_cache_idx = cache_idx;
|
|
}
|
|
*((short*)present_ptr) = present;
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* returns error */
|
|
/* when a palette gets sent, send the main palette too */
|
|
/* don't need max size here */
|
|
int xrdp_orders_send_palette(struct xrdp_orders* self, int* palette,
|
|
int cache_id)
|
|
{
|
|
int order_flags;
|
|
int len;
|
|
int i;
|
|
|
|
/* gota clear any build up orders and send the main palette */
|
|
xrdp_orders_force_send(self);
|
|
xrdp_wm_send_palette(self->pro_layer->wm);
|
|
xrdp_orders_init(self);
|
|
self->order_count++;
|
|
order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY;
|
|
out_uint8(self->out_s, order_flags);
|
|
len = 1027 - 7; /* length after type minus 7 */
|
|
out_uint16_le(self->out_s, len);
|
|
out_uint16_le(self->out_s, 0); /* flags */
|
|
out_uint8(self->out_s, RDP_ORDER_COLCACHE); /* type */
|
|
out_uint8(self->out_s, cache_id);
|
|
out_uint16_le(self->out_s, 256); /* num colors */
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
out_uint8(self->out_s, palette[i]);
|
|
out_uint8(self->out_s, palette[i] >> 8);
|
|
out_uint8(self->out_s, palette[i] >> 16);
|
|
out_uint8(self->out_s, 0);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* returns error */
|
|
/* max size width * height * Bpp + 16 */
|
|
int xrdp_orders_send_raw_bitmap(struct xrdp_orders* self,
|
|
struct xrdp_bitmap* bitmap,
|
|
int cache_id, int cache_idx)
|
|
{
|
|
int order_flags;
|
|
int len;
|
|
int bufsize;
|
|
int Bpp;
|
|
int i;
|
|
int j;
|
|
int pixel;
|
|
|
|
Bpp = (bitmap->bpp + 7) / 8;
|
|
bufsize = bitmap->width * bitmap->height * Bpp;
|
|
xrdp_orders_check(self, bufsize + 16);
|
|
self->order_count++;
|
|
order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY;
|
|
out_uint8(self->out_s, order_flags);
|
|
len = (bufsize + 9) - 7;
|
|
out_uint16_le(self->out_s, len);
|
|
out_uint16_le(self->out_s, 8); /* flags */
|
|
out_uint8(self->out_s, RDP_ORDER_RAW_BMPCACHE); /* type */
|
|
out_uint8(self->out_s, cache_id);
|
|
out_uint8s(self->out_s, 1); /* pad */
|
|
out_uint8(self->out_s, bitmap->width);
|
|
out_uint8(self->out_s, bitmap->height);
|
|
out_uint8(self->out_s, bitmap->bpp);
|
|
out_uint16_le(self->out_s, bufsize);
|
|
out_uint16_le(self->out_s, cache_idx);
|
|
for (i = bitmap->height - 1; i >= 0; i--)
|
|
for (j = 0; j < bitmap->width; j++)
|
|
{
|
|
pixel = xrdp_bitmap_get_pixel(bitmap, j, i);
|
|
if (Bpp == 3)
|
|
{
|
|
out_uint8(self->out_s, pixel >> 16);
|
|
out_uint8(self->out_s, pixel >> 8);
|
|
out_uint8(self->out_s, pixel);
|
|
}
|
|
else if (Bpp == 2)
|
|
{
|
|
out_uint8(self->out_s, pixel);
|
|
out_uint8(self->out_s, pixel >> 8);
|
|
}
|
|
else if (Bpp == 1)
|
|
out_uint8(self->out_s, pixel);
|
|
}
|
|
return 0;
|
|
}
|