|
|
|
/*
|
|
|
|
Copyright 2005-2007 Jay Sorg
|
|
|
|
|
|
|
|
Permission to use, copy, modify, distribute, and sell this software and its
|
|
|
|
documentation for any purpose is hereby granted without fee, provided that
|
|
|
|
the above copyright notice appear in all copies and that both that
|
|
|
|
copyright notice and this permission notice appear in supporting
|
|
|
|
documentation.
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
|
|
|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "rdp.h"
|
|
|
|
/*#include "arch.h"*/
|
|
|
|
/*#include "parse.h"*/
|
|
|
|
/*#include "os_calls.h"*/
|
|
|
|
|
|
|
|
#define DEBUG_OUT_UP(arg)
|
|
|
|
/*#define DEBUG_OUT_UP(arg) ErrorF arg*/
|
|
|
|
|
|
|
|
static int g_listen_sck = 0;
|
|
|
|
static int g_sck = 0;
|
|
|
|
static int g_sck_closed = 0;
|
|
|
|
static int g_connected = 0;
|
|
|
|
static int g_begin = 0;
|
|
|
|
static struct stream* g_out_s = 0;
|
|
|
|
static struct stream* g_in_s = 0;
|
|
|
|
static int g_button_mask = 0;
|
|
|
|
static int g_cursor_x = 0;
|
|
|
|
static int g_cursor_y = 0;
|
|
|
|
static OsTimerPtr g_timer = 0;
|
|
|
|
static int g_scheduled = 0;
|
|
|
|
static int g_count = 0;
|
|
|
|
|
|
|
|
extern ScreenPtr g_pScreen; /* from rdpmain.c */
|
|
|
|
extern int g_Bpp; /* from rdpmain.c */
|
|
|
|
extern int g_Bpp_mask; /* from rdpmain.c */
|
|
|
|
extern rdpScreenInfo g_rdpScreen; /* from rdpmain.c */
|
|
|
|
|
|
|
|
extern char* display;
|
|
|
|
|
|
|
|
static void
|
|
|
|
rdpScheduleDeferredUpdate(void);
|
|
|
|
|
|
|
|
/*
|
|
|
|
0 GXclear, 0
|
|
|
|
1 GXnor, DPon
|
|
|
|
2 GXandInverted, DPna
|
|
|
|
3 GXcopyInverted, Pn
|
|
|
|
4 GXandReverse, PDna
|
|
|
|
5 GXinvert, Dn
|
|
|
|
6 GXxor, DPx
|
|
|
|
7 GXnand, DPan
|
|
|
|
8 GXand, DPa
|
|
|
|
9 GXequiv, DPxn
|
|
|
|
a GXnoop, D
|
|
|
|
b GXorInverted, DPno
|
|
|
|
c GXcopy, P
|
|
|
|
d GXorReverse, PDno
|
|
|
|
e GXor, DPo
|
|
|
|
f GXset 1
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int rdp_opcodes[16] =
|
|
|
|
{
|
|
|
|
0x00, /* GXclear 0x0 0 */
|
|
|
|
0x88, /* GXand 0x1 src AND dst */
|
|
|
|
0x44, /* GXandReverse 0x2 src AND NOT dst */
|
|
|
|
0xcc, /* GXcopy 0x3 src */
|
|
|
|
0x22, /* GXandInverted 0x4 NOT src AND dst */
|
|
|
|
0xaa, /* GXnoop 0x5 dst */
|
|
|
|
0x66, /* GXxor 0x6 src XOR dst */
|
|
|
|
0xee, /* GXor 0x7 src OR dst */
|
|
|
|
0x11, /* GXnor 0x8 NOT src AND NOT dst */
|
|
|
|
0x99, /* GXequiv 0x9 NOT src XOR dst */
|
|
|
|
0x55, /* GXinvert 0xa NOT dst */
|
|
|
|
0xdd, /* GXorReverse 0xb src OR NOT dst */
|
|
|
|
0x33, /* GXcopyInverted 0xc NOT src */
|
|
|
|
0xbb, /* GXorInverted 0xd NOT src OR dst */
|
|
|
|
0x77, /* GXnand 0xe NOT src OR NOT dst */
|
|
|
|
0xff /* GXset 0xf 1 */
|
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* returns error */
|
|
|
|
static int
|
|
|
|
rdpup_recv(char* data, int len)
|
|
|
|
{
|
|
|
|
int rcvd;
|
|
|
|
|
|
|
|
if (g_sck_closed)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
while (len > 0)
|
|
|
|
{
|
|
|
|
rcvd = g_tcp_recv(g_sck, data, len, 0);
|
|
|
|
if (rcvd == -1)
|
|
|
|
{
|
|
|
|
if (g_tcp_last_error_would_block(g_sck))
|
|
|
|
{
|
|
|
|
g_sleep(1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RemoveEnabledDevice(g_sck);
|
|
|
|
g_connected = 0;
|
|
|
|
g_tcp_close(g_sck);
|
|
|
|
g_sck = 0;
|
|
|
|
g_sck_closed = 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (rcvd == 0)
|
|
|
|
{
|
|
|
|
RemoveEnabledDevice(g_sck);
|
|
|
|
g_connected = 0;
|
|
|
|
g_tcp_close(g_sck);
|
|
|
|
g_sck = 0;
|
|
|
|
g_sck_closed = 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
data += rcvd;
|
|
|
|
len -= rcvd;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* returns error */
|
|
|
|
static int
|
|
|
|
rdpup_send(char* data, int len)
|
|
|
|
{
|
|
|
|
int sent;
|
|
|
|
|
|
|
|
DEBUG_OUT_UP(("rdpup_send - sending %d bytes\n", len));
|
|
|
|
if (g_sck_closed)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
while (len > 0)
|
|
|
|
{
|
|
|
|
sent = g_tcp_send(g_sck, data, len, 0);
|
|
|
|
if (sent == -1)
|
|
|
|
{
|
|
|
|
if (g_tcp_last_error_would_block(g_sck))
|
|
|
|
{
|
|
|
|
g_sleep(1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RemoveEnabledDevice(g_sck);
|
|
|
|
g_connected = 0;
|
|
|
|
g_tcp_close(g_sck);
|
|
|
|
g_sck = 0;
|
|
|
|
g_sck_closed = 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (sent == 0)
|
|
|
|
{
|
|
|
|
RemoveEnabledDevice(g_sck);
|
|
|
|
g_connected = 0;
|
|
|
|
g_tcp_close(g_sck);
|
|
|
|
g_sck = 0;
|
|
|
|
g_sck_closed = 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
data += sent;
|
|
|
|
len -= sent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
static int
|
|
|
|
rdpup_send_msg(struct stream* s)
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
rv = 1;
|
|
|
|
if (s != 0)
|
|
|
|
{
|
|
|
|
len = s->end - s->data;
|
|
|
|
if (len > s->size)
|
|
|
|
{
|
|
|
|
ErrorF("overrun error len %d count %d\n", len, g_count);
|
|
|
|
}
|
|
|
|
s_pop_layer(s, iso_hdr);
|
|
|
|
out_uint16_le(s, 1);
|
|
|
|
out_uint16_le(s, g_count);
|
|
|
|
out_uint32_le(s, len - 8);
|
|
|
|
rv = rdpup_send(s->data, len);
|
|
|
|
}
|
|
|
|
if (rv != 0)
|
|
|
|
{
|
|
|
|
ErrorF("error in rdpup_send_msg\n");
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
static int
|
|
|
|
rdpup_recv_msg(struct stream* s)
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
rv = 1;
|
|
|
|
if (s != 0)
|
|
|
|
{
|
|
|
|
init_stream(s, 4);
|
|
|
|
rv = rdpup_recv(s->data, 4);
|
|
|
|
if (rv == 0)
|
|
|
|
{
|
|
|
|
in_uint32_le(s, len);
|
|
|
|
if (len > 3)
|
|
|
|
{
|
|
|
|
init_stream(s, len);
|
|
|
|
rv = rdpup_recv(s->data, len - 4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (rv != 0)
|
|
|
|
{
|
|
|
|
ErrorF("error in rdpup_recv_msg\n");
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
static int
|
|
|
|
rdpup_process_msg(struct stream* s)
|
|
|
|
{
|
|
|
|
int msg_type;
|
|
|
|
int msg;
|
|
|
|
int param1;
|
|
|
|
int param2;
|
|
|
|
int param3;
|
|
|
|
int param4;
|
|
|
|
|
|
|
|
in_uint16_le(s, msg_type);
|
|
|
|
if (msg_type == 103)
|
|
|
|
{
|
|
|
|
in_uint32_le(s, msg);
|
|
|
|
in_uint32_le(s, param1);
|
|
|
|
in_uint32_le(s, param2);
|
|
|
|
in_uint32_le(s, param3);
|
|
|
|
in_uint32_le(s, param4);
|
|
|
|
DEBUG_OUT_UP(("rdpup_process_msg - msg %d param1 %d param2 %d param3 %d \
|
|
|
|
param4 %d\n", msg, param1, param2, param3, param4));
|
|
|
|
/*ErrorF("rdpup_process_msg - msg %d param1 %d param2 %d param3 %d \
|
|
|
|
param4 %d\n", msg, param1, param2, param3, param4);*/
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case 15: /* key down */
|
|
|
|
case 16: /* key up */
|
|
|
|
KbdAddEvent(msg == 15, param1, param2, param3, param4);
|
|
|
|
break;
|
|
|
|
case 17: /* from RDP_INPUT_SYNCHRONIZE */
|
|
|
|
#if 0
|
|
|
|
/* scroll lock */
|
|
|
|
if (param1 & 1)
|
|
|
|
{
|
|
|
|
KbdAddEvent(1, 70, 0, 70, 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
KbdAddEvent(0, 70, 49152, 70, 49152);
|
|
|
|
}
|
|
|
|
/* num lock */
|
|
|
|
if (param1 & 2)
|
|
|
|
{
|
|
|
|
KbdAddEvent(1, 69, 0, 69, 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
KbdAddEvent(0, 69, 49152, 69, 49152);
|
|
|
|
}
|
|
|
|
/* caps lock */
|
|
|
|
if (param1 & 4)
|
|
|
|
{
|
|
|
|
KbdAddEvent(1, 58, 0, 58, 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
KbdAddEvent(0, 58, 49152, 58, 49152);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
case 100:
|
|
|
|
g_cursor_x = param1;
|
|
|
|
g_cursor_y = param2;
|
|
|
|
PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
|
|
|
|
break;
|
|
|
|
case 101:
|
|
|
|
g_button_mask = g_button_mask & (~1);
|
|
|
|
PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
|
|
|
|
break;
|
|
|
|
case 102:
|
|
|
|
g_button_mask = g_button_mask | 1;
|
|
|
|
PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
|
|
|
|
break;
|
|
|
|
case 103:
|
|
|
|
g_button_mask = g_button_mask & (~4);
|
|
|
|
PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
|
|
|
|
break;
|
|
|
|
case 104:
|
|
|
|
g_button_mask = g_button_mask | 4;
|
|
|
|
PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
|
|
|
|
break;
|
|
|
|
case 105:
|
|
|
|
g_button_mask = g_button_mask & (~2);
|
|
|
|
PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
|
|
|
|
break;
|
|
|
|
case 106:
|
|
|
|
g_button_mask = g_button_mask | 2;
|
|
|
|
PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
|
|
|
|
break;
|
|
|
|
case 107:
|
|
|
|
g_button_mask = g_button_mask & (~8);
|
|
|
|
PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
|
|
|
|
break;
|
|
|
|
case 108:
|
|
|
|
g_button_mask = g_button_mask | 8;
|
|
|
|
PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
|
|
|
|
break;
|
|
|
|
case 109:
|
|
|
|
g_button_mask = g_button_mask & (~16);
|
|
|
|
PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
|
|
|
|
break;
|
|
|
|
case 110:
|
|
|
|
g_button_mask = g_button_mask | 16;
|
|
|
|
PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
|
|
|
|
break;
|
|
|
|
case 200:
|
|
|
|
rdpup_begin_update();
|
|
|
|
rdpup_send_area((param1 >> 16) & 0xffff, param1 & 0xffff,
|
|
|
|
(param2 >> 16) & 0xffff, param2 & 0xffff);
|
|
|
|
rdpup_end_update();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ErrorF("unknown message type in rdpup_process_msg\n");
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
int
|
|
|
|
rdpup_init(void)
|
|
|
|
{
|
|
|
|
char text[256];
|
|
|
|
int i;
|
|
|
|
|
|
|
|
i = atoi(display);
|
|
|
|
if (i < 1)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
g_sprintf(text, "62%2.2d", i);
|
|
|
|
if (g_in_s == 0)
|
|
|
|
{
|
|
|
|
make_stream(g_in_s);
|
|
|
|
init_stream(g_in_s, 8192);
|
|
|
|
}
|
|
|
|
if (g_out_s == 0)
|
|
|
|
{
|
|
|
|
make_stream(g_out_s);
|
|
|
|
init_stream(g_out_s, 8192 * g_Bpp + 100);
|
|
|
|
}
|
|
|
|
if (g_listen_sck == 0)
|
|
|
|
{
|
|
|
|
g_listen_sck = g_tcp_socket();
|
|
|
|
if (g_tcp_bind(g_listen_sck, text) != 0)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
g_tcp_listen(g_listen_sck);
|
|
|
|
AddEnabledDevice(g_listen_sck);
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
int
|
|
|
|
rdpup_check(void)
|
|
|
|
{
|
|
|
|
int sel;
|
|
|
|
|
|
|
|
sel = g_tcp_select(g_listen_sck, g_sck);
|
|
|
|
if (sel & 1)
|
|
|
|
{
|
|
|
|
if (g_sck == 0)
|
|
|
|
{
|
|
|
|
g_sck = g_tcp_accept(g_listen_sck);
|
|
|
|
if (g_sck == -1)
|
|
|
|
{
|
|
|
|
g_sck = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_tcp_set_non_blocking(g_sck);
|
|
|
|
g_tcp_set_no_delay(g_sck);
|
|
|
|
g_connected = 1;
|
|
|
|
g_sck_closed = 0;
|
|
|
|
AddEnabledDevice(g_sck);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ErrorF("rejecting connection\n");
|
|
|
|
g_sleep(10);
|
|
|
|
g_tcp_close(g_tcp_accept(g_listen_sck));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (sel & 2)
|
|
|
|
{
|
|
|
|
if (rdpup_recv_msg(g_in_s) == 0)
|
|
|
|
{
|
|
|
|
rdpup_process_msg(g_in_s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
int
|
|
|
|
rdpup_begin_update(void)
|
|
|
|
{
|
|
|
|
if (g_connected)
|
|
|
|
{
|
|
|
|
if (g_begin)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
init_stream(g_out_s, 0);
|
|
|
|
s_push_layer(g_out_s, iso_hdr, 8);
|
|
|
|
out_uint16_le(g_out_s, 1);
|
|
|
|
DEBUG_OUT_UP(("begin %d\n", g_count));
|
|
|
|
g_begin = 1;
|
|
|
|
g_count = 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
int
|
|
|
|
rdpup_end_update(void)
|
|
|
|
{
|
|
|
|
if (g_connected && g_begin)
|
|
|
|
{
|
|
|
|
rdpScheduleDeferredUpdate();
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
int
|
|
|
|
rdpup_pre_check(int in_size)
|
|
|
|
{
|
|
|
|
if (!g_begin)
|
|
|
|
{
|
|
|
|
rdpup_begin_update();
|
|
|
|
}
|
|
|
|
if ((g_out_s->p - g_out_s->data) > (g_out_s->size - (in_size + 20)))
|
|
|
|
{
|
|
|
|
/*ErrorF("%d %d\n", in_size, g_out_s->size);*/
|
|
|
|
s_mark_end(g_out_s);
|
|
|
|
rdpup_send_msg(g_out_s);
|
|
|
|
g_count = 0;
|
|
|
|
init_stream(g_out_s, 0);
|
|
|
|
s_push_layer(g_out_s, iso_hdr, 8);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
int
|
|
|
|
rdpup_fill_rect(short x, short y, int cx, int cy)
|
|
|
|
{
|
|
|
|
if (g_connected)
|
|
|
|
{
|
|
|
|
DEBUG_OUT_UP((" rdpup_fill_rect\n"));
|
|
|
|
rdpup_pre_check(10);
|
|
|
|
out_uint16_le(g_out_s, 3);
|
|
|
|
g_count++;
|
|
|
|
out_uint16_le(g_out_s, x);
|
|
|
|
out_uint16_le(g_out_s, y);
|
|
|
|
out_uint16_le(g_out_s, cx);
|
|
|
|
out_uint16_le(g_out_s, cy);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
int
|
|
|
|
rdpup_screen_blt(short x, short y, int cx, int cy, short srcx, short srcy)
|
|
|
|
{
|
|
|
|
if (g_connected)
|
|
|
|
{
|
|
|
|
DEBUG_OUT_UP((" rdpup_screen_blt\n"));
|
|
|
|
rdpup_pre_check(14);
|
|
|
|
out_uint16_le(g_out_s, 4);
|
|
|
|
g_count++;
|
|
|
|
out_uint16_le(g_out_s, x);
|
|
|
|
out_uint16_le(g_out_s, y);
|
|
|
|
out_uint16_le(g_out_s, cx);
|
|
|
|
out_uint16_le(g_out_s, cy);
|
|
|
|
out_uint16_le(g_out_s, srcx);
|
|
|
|
out_uint16_le(g_out_s, srcy);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
int
|
|
|
|
rdpup_set_clip(short x, short y, int cx, int cy)
|
|
|
|
{
|
|
|
|
if (g_connected)
|
|
|
|
{
|
|
|
|
DEBUG_OUT_UP((" rdpup_set_clip\n"));
|
|
|
|
rdpup_pre_check(10);
|
|
|
|
out_uint16_le(g_out_s, 10);
|
|
|
|
g_count++;
|
|
|
|
out_uint16_le(g_out_s, x);
|
|
|
|
out_uint16_le(g_out_s, y);
|
|
|
|
out_uint16_le(g_out_s, cx);
|
|
|
|
out_uint16_le(g_out_s, cy);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
int
|
|
|
|
rdpup_reset_clip(void)
|
|
|
|
{
|
|
|
|
if (g_connected)
|
|
|
|
{
|
|
|
|
DEBUG_OUT_UP((" rdpup_reset_clip\n"));
|
|
|
|
rdpup_pre_check(2);
|
|
|
|
out_uint16_le(g_out_s, 11);
|
|
|
|
g_count++;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
int
|
|
|
|
rdpup_set_fgcolor(int fgcolor)
|
|
|
|
{
|
|
|
|
if (g_connected)
|
|
|
|
{
|
|
|
|
DEBUG_OUT_UP((" rdpup_set_fgcolor\n"));
|
|
|
|
rdpup_pre_check(6);
|
|
|
|
out_uint16_le(g_out_s, 12);
|
|
|
|
g_count++;
|
|
|
|
fgcolor = fgcolor & g_Bpp_mask;
|
|
|
|
out_uint32_le(g_out_s, fgcolor);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
int
|
|
|
|
rdpup_set_bgcolor(int bgcolor)
|
|
|
|
{
|
|
|
|
if (g_connected)
|
|
|
|
{
|
|
|
|
DEBUG_OUT_UP((" rdpup_set_bgcolor\n"));
|
|
|
|
rdpup_pre_check(6);
|
|
|
|
out_uint16_le(g_out_s, 13);
|
|
|
|
g_count++;
|
|
|
|
bgcolor = bgcolor & g_Bpp_mask;
|
|
|
|
out_uint32_le(g_out_s, bgcolor);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
int
|
|
|
|
rdpup_set_opcode(int opcode)
|
|
|
|
{
|
|
|
|
if (g_connected)
|
|
|
|
{
|
|
|
|
DEBUG_OUT_UP((" rdpup_set_opcode\n"));
|
|
|
|
rdpup_pre_check(4);
|
|
|
|
out_uint16_le(g_out_s, 14);
|
|
|
|
g_count++;
|
|
|
|
out_uint16_le(g_out_s, rdp_opcodes[opcode & 0xf]);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
int
|
|
|
|
rdpup_set_pen(int style, int width)
|
|
|
|
{
|
|
|
|
if (g_connected)
|
|
|
|
{
|
|
|
|
DEBUG_OUT_UP((" rdpup_set_pen\n"));
|
|
|
|
rdpup_pre_check(6);
|
|
|
|
out_uint16_le(g_out_s, 17);
|
|
|
|
g_count++;
|
|
|
|
out_uint16_le(g_out_s, style);
|
|
|
|
out_uint16_le(g_out_s, width);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
int
|
|
|
|
rdpup_draw_line(short x1, short y1, short x2, short y2)
|
|
|
|
{
|
|
|
|
if (g_connected)
|
|
|
|
{
|
|
|
|
DEBUG_OUT_UP((" rdpup_draw_line\n"));
|
|
|
|
rdpup_pre_check(10);
|
|
|
|
out_uint16_le(g_out_s, 18);
|
|
|
|
g_count++;
|
|
|
|
out_uint16_le(g_out_s, x1);
|
|
|
|
out_uint16_le(g_out_s, y1);
|
|
|
|
out_uint16_le(g_out_s, x2);
|
|
|
|
out_uint16_le(g_out_s, y2);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
int
|
|
|
|
rdpup_set_cursor(short x, short y, char* cur_data, char* cur_mask)
|
|
|
|
{
|
|
|
|
if (g_connected)
|
|
|
|
{
|
|
|
|
DEBUG_OUT_UP((" rdpup_set_cursor\n"));
|
|
|
|
rdpup_pre_check(6 + 32 * (32 * 3) + 32 * (32 / 8));
|
|
|
|
out_uint16_le(g_out_s, 19);
|
|
|
|
g_count++;
|
|
|
|
out_uint16_le(g_out_s, x);
|
|
|
|
out_uint16_le(g_out_s, y);
|
|
|
|
out_uint8a(g_out_s, cur_data, 32 * (32 * 3));
|
|
|
|
out_uint8a(g_out_s, cur_mask, 32 * (32 / 8));
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
static int
|
|
|
|
get_single_color(int x, int y, int w, int h)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int i;
|
|
|
|
int j;
|
|
|
|
int p;
|
|
|
|
unsigned char* i8;
|
|
|
|
unsigned short* i16;
|
|
|
|
|
|
|
|
rv = -1;
|
|
|
|
if (g_Bpp == 1)
|
|
|
|
{
|
|
|
|
for (i = 0; i < h; i++)
|
|
|
|
{
|
|
|
|
i8 = (unsigned char*)(g_rdpScreen.pfbMemory +
|
|
|
|
((y + i) * g_rdpScreen.paddedWidthInBytes) + (x * g_Bpp));
|
|
|
|
if (i == 0)
|
|
|
|
{
|
|
|
|
p = *i8;
|
|
|
|
}
|
|
|
|
for (j = 0; j < w; j++)
|
|
|
|
{
|
|
|
|
if (i8[j] != p)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rv = p;
|
|
|
|
}
|
|
|
|
else if (g_Bpp == 2)
|
|
|
|
{
|
|
|
|
for (i = 0; i < h; i++)
|
|
|
|
{
|
|
|
|
i16 = (unsigned short*)(g_rdpScreen.pfbMemory +
|
|
|
|
((y + i) * g_rdpScreen.paddedWidthInBytes) + (x * g_Bpp));
|
|
|
|
if (i == 0)
|
|
|
|
{
|
|
|
|
p = *i16;
|
|
|
|
}
|
|
|
|
for (j = 0; j < w; j++)
|
|
|
|
{
|
|
|
|
if (i16[j] != p)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rv = p;
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* split the bitmap up into 64 x 64 pixel areas */
|
|
|
|
void
|
|
|
|
rdpup_send_area(int x, int y, int w, int h)
|
|
|
|
{
|
|
|
|
char* s;
|
|
|
|
int i;
|
|
|
|
int single_color;
|
|
|
|
int lx;
|
|
|
|
int ly;
|
|
|
|
int lh;
|
|
|
|
int lw;
|
|
|
|
|
|
|
|
if (x >= g_rdpScreen.width)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (y >= g_rdpScreen.height)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (x < 0)
|
|
|
|
{
|
|
|
|
w += x;
|
|
|
|
x = 0;
|
|
|
|
}
|
|
|
|
if (y < 0)
|
|
|
|
{
|
|
|
|
h += y;
|
|
|
|
y = 0;
|
|
|
|
}
|
|
|
|
if (w <= 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (h <= 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (x + w > g_rdpScreen.width)
|
|
|
|
{
|
|
|
|
w = g_rdpScreen.width - x;
|
|
|
|
}
|
|
|
|
if (y + h > g_rdpScreen.height)
|
|
|
|
{
|
|
|
|
h = g_rdpScreen.height - y;
|
|
|
|
}
|
|
|
|
/*ErrorF("%d\n", w * h);*/
|
|
|
|
if (g_connected && g_begin)
|
|
|
|
{
|
|
|
|
DEBUG_OUT_UP((" rdpup_send_area\n"));
|
|
|
|
ly = y;
|
|
|
|
while (ly < y + h)
|
|
|
|
{
|
|
|
|
lx = x;
|
|
|
|
while (lx < x + w)
|
|
|
|
{
|
|
|
|
lw = MIN(64, (x + w) - lx);
|
|
|
|
lh = MIN(64, (y + h) - ly);
|
|
|
|
single_color = get_single_color(lx, ly, lw, lh);
|
|
|
|
if (single_color != -1)
|
|
|
|
{
|
|
|
|
/*ErrorF("%d sending single color\n", g_count);*/
|
|
|
|
rdpup_set_fgcolor(single_color);
|
|
|
|
rdpup_fill_rect(lx, ly, lw, lh);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rdpup_pre_check(lw * lh * g_Bpp + 42);
|
|
|
|
out_uint16_le(g_out_s, 5);
|
|
|
|
g_count++;
|
|
|
|
out_uint16_le(g_out_s, lx);
|
|
|
|
out_uint16_le(g_out_s, ly);
|
|
|
|
out_uint16_le(g_out_s, lw);
|
|
|
|
out_uint16_le(g_out_s, lh);
|
|
|
|
out_uint32_le(g_out_s, lw * lh * g_Bpp);
|
|
|
|
for (i = 0; i < lh; i++)
|
|
|
|
{
|
|
|
|
s = (g_rdpScreen.pfbMemory +
|
|
|
|
((ly + i) * g_rdpScreen.paddedWidthInBytes) + (lx * g_Bpp));
|
|
|
|
out_uint8a(g_out_s, s, lw * g_Bpp);
|
|
|
|
}
|
|
|
|
out_uint16_le(g_out_s, lw);
|
|
|
|
out_uint16_le(g_out_s, lh);
|
|
|
|
out_uint16_le(g_out_s, 0);
|
|
|
|
out_uint16_le(g_out_s, 0);
|
|
|
|
}
|
|
|
|
lx += 64;
|
|
|
|
}
|
|
|
|
ly += 64;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
static CARD32
|
|
|
|
rdpDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg)
|
|
|
|
{
|
|
|
|
if (g_connected && g_begin)
|
|
|
|
{
|
|
|
|
DEBUG_OUT_UP(("end %d\n", g_count));
|
|
|
|
out_uint16_le(g_out_s, 2);
|
|
|
|
g_count++;
|
|
|
|
s_mark_end(g_out_s);
|
|
|
|
rdpup_send_msg(g_out_s);
|
|
|
|
}
|
|
|
|
g_count = 0;
|
|
|
|
g_begin = 0;
|
|
|
|
g_scheduled = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
static void
|
|
|
|
rdpScheduleDeferredUpdate(void)
|
|
|
|
{
|
|
|
|
if (!g_scheduled)
|
|
|
|
{
|
|
|
|
g_scheduled = 1;
|
|
|
|
g_timer = TimerSet(g_timer, 0, 40, rdpDeferredUpdateCallback, 0);
|
|
|
|
}
|
|
|
|
}
|