📄 rdp.c
字号:
in_uint16_le(s, masklen);
in_uint16_le(s, datalen);
in_uint8p(s, data, datalen);
in_uint8p(s, mask, masklen);
cursor = ui_create_cursor(This, x, y, width, height, mask, data);
ui_set_cursor(This, cursor);
cache_put_cursor(This, cache_idx, cursor);
}
/* Process a cached pointer PDU */
void
process_cached_pointer_pdu(RDPCLIENT * This, STREAM s)
{
uint16 cache_idx;
in_uint16_le(s, cache_idx);
ui_set_cursor(This, cache_get_cursor(This, cache_idx));
}
/* Process a system pointer PDU */
void
process_system_pointer_pdu(RDPCLIENT * This, STREAM s)
{
uint16 system_pointer_type;
in_uint16(s, system_pointer_type);
switch (system_pointer_type)
{
case RDP_NULL_POINTER:
ui_set_null_cursor(This);
break;
default:
unimpl("System pointer message 0x%x\n", system_pointer_type);
}
}
/* Process a pointer PDU */
static void
process_pointer_pdu(RDPCLIENT * This, STREAM s)
{
uint16 message_type;
uint16 x, y;
in_uint16_le(s, message_type);
in_uint8s(s, 2); /* pad */
switch (message_type)
{
case RDP_POINTER_MOVE:
in_uint16_le(s, x);
in_uint16_le(s, y);
if (s_check(s))
ui_move_pointer(This, x, y);
break;
case RDP_POINTER_COLOR:
process_colour_pointer_pdu(This, s);
break;
case RDP_POINTER_CACHED:
process_cached_pointer_pdu(This, s);
break;
case RDP_POINTER_SYSTEM:
process_system_pointer_pdu(This, s);
break;
default:
unimpl("Pointer message 0x%x\n", message_type);
}
}
/* Process bitmap updates */
void
process_bitmap_updates(RDPCLIENT * This, STREAM s)
{
uint16 num_updates;
uint16 left, top, right, bottom, width, height;
uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
uint8 *data, *bmpdata;
int i;
in_uint16_le(s, num_updates);
for (i = 0; i < num_updates; i++)
{
in_uint16_le(s, left);
in_uint16_le(s, top);
in_uint16_le(s, right);
in_uint16_le(s, bottom);
in_uint16_le(s, width);
in_uint16_le(s, height);
in_uint16_le(s, bpp);
Bpp = (bpp + 7) / 8;
in_uint16_le(s, compress);
in_uint16_le(s, bufsize);
cx = right - left + 1;
cy = bottom - top + 1;
DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",
left, top, right, bottom, width, height, Bpp, compress));
if (!compress)
{
#if 0
int y;
bmpdata = (uint8 *) xmalloc(width * height * Bpp);
for (y = 0; y < height; y++)
{
in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
width * Bpp);
}
ui_paint_bitmap(This, left, top, cx, cy, width, height, bmpdata);
xfree(bmpdata);
#else
in_uint8p(s, bmpdata, width * height * Bpp);
ui_paint_bitmap(This, left, top, cx, cy, width, height, bmpdata);
#endif
continue;
}
if (compress & 0x400)
{
size = bufsize;
}
else
{
in_uint8s(s, 2); /* pad */
in_uint16_le(s, size);
in_uint8s(s, 4); /* line_size, final_size */
}
in_uint8p(s, data, size);
bmpdata = (uint8 *) malloc(width * height * Bpp);
if(bmpdata == NULL)
return;
if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
{
ui_paint_bitmap(This, left, top, cx, cy, width, height, bmpdata);
}
else
{
DEBUG_RDP5(("Failed to decompress data\n"));
}
free(bmpdata);
}
}
/* Process a palette update */
void
process_palette(RDPCLIENT * This, STREAM s)
{
COLOURENTRY *entry;
COLOURMAP map;
HCOLOURMAP hmap;
int i;
in_uint8s(s, 2); /* pad */
in_uint16_le(s, map.ncolours);
in_uint8s(s, 2); /* pad */
map.colours = (COLOURENTRY *) malloc(sizeof(COLOURENTRY) * map.ncolours);
if(map.colours == NULL)
{
in_uint8s(s, sizeof(*entry) * map.ncolours);
return;
}
DEBUG(("PALETTE(c=%d)\n", map.ncolours));
for (i = 0; i < map.ncolours; i++)
{
entry = &map.colours[i];
in_uint8(s, entry->red);
in_uint8(s, entry->green);
in_uint8(s, entry->blue);
}
hmap = ui_create_colourmap(This, &map);
ui_set_colourmap(This, hmap);
free(map.colours);
}
/* Process an update PDU */
static void
process_update_pdu(RDPCLIENT * This, STREAM s)
{
uint16 update_type, count;
in_uint16_le(s, update_type);
ui_begin_update(This);
switch (update_type)
{
case RDP_UPDATE_ORDERS:
in_uint8s(s, 2); /* pad */
in_uint16_le(s, count);
in_uint8s(s, 2); /* pad */
process_orders(This, s, count);
break;
case RDP_UPDATE_BITMAP:
process_bitmap_updates(This, s);
break;
case RDP_UPDATE_PALETTE:
process_palette(This, s);
break;
case RDP_UPDATE_SYNCHRONIZE:
break;
default:
unimpl("update %d\n", update_type);
}
ui_end_update(This);
}
/* Process a disconnect PDU */
void
process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason)
{
in_uint32_le(s, *ext_disc_reason);
DEBUG(("Received disconnect PDU\n"));
}
/* Process data PDU */
static BOOL
process_data_pdu(RDPCLIENT * This, STREAM s, uint32 * ext_disc_reason)
{
uint8 data_pdu_type;
uint8 ctype;
uint16 clen;
uint32 len;
uint32 roff, rlen;
struct stream *ns = &(This->mppc_dict.ns);
in_uint8s(s, 6); /* shareid, pad, streamid */
in_uint16(s, len);
in_uint8(s, data_pdu_type);
in_uint8(s, ctype);
in_uint16(s, clen);
clen -= 18;
if (ctype & RDP_MPPC_COMPRESSED)
{
void * p;
if (len > RDP_MPPC_DICT_SIZE)
error("error decompressed packet size exceeds max\n");
if (mppc_expand(This, s->p, clen, ctype, &roff, &rlen) == -1)
error("error while decompressing packet\n");
/* len -= 18; */
/* allocate memory and copy the uncompressed data into the temporary stream */
p = realloc(ns->data, rlen);
if(p == NULL)
{
This->disconnect_reason = 262;
return True;
}
ns->data = (uint8 *) p;
memcpy((ns->data), (unsigned char *) (This->mppc_dict.hist + roff), rlen);
ns->size = rlen;
ns->end = (ns->data + ns->size);
ns->p = ns->data;
ns->rdp_hdr = ns->p;
s = ns;
}
switch (data_pdu_type)
{
case RDP_DATA_PDU_UPDATE:
process_update_pdu(This, s);
break;
case RDP_DATA_PDU_CONTROL:
DEBUG(("Received Control PDU\n"));
break;
case RDP_DATA_PDU_SYNCHRONISE:
DEBUG(("Received Sync PDU\n"));
break;
case RDP_DATA_PDU_POINTER:
process_pointer_pdu(This, s);
break;
case RDP_DATA_PDU_BELL:
ui_bell(This);
break;
case RDP_DATA_PDU_LOGON:
DEBUG(("Received Logon PDU\n"));
event_logon(This);
/* User logged on */
break;
case RDP_DATA_PDU_DISCONNECT:
process_disconnect_pdu(s, ext_disc_reason);
/* We used to return true and disconnect immediately here, but
* Windows Vista sends a disconnect PDU with reason 0 when
* reconnecting to a disconnected session, and MSTSC doesn't
* drop the connection. I think we should just save the status.
*/
break;
default:
unimpl("data PDU %d\n", data_pdu_type);
}
return False;
}
/* Process redirect PDU from Session Directory */
static BOOL
process_redirect_pdu(RDPCLIENT * This, STREAM s /*, uint32 * ext_disc_reason */ )
{
uint32 flags;
uint32 server_len;
wchar_t * server;
uint32 cookie_len;
char * cookie;
uint32 username_len;
wchar_t * username;
uint32 domain_len;
wchar_t * domain;
uint32 password_len;
wchar_t * password;
/* these 2 bytes are unknown, seem to be zeros */
in_uint8s(s, 2);
/* read connection flags */
in_uint32_le(s, flags);
/* read length of ip string */
in_uint32_le(s, server_len);
/* read ip string */
server = (wchar_t *)s->p;
in_uint8s(s, server_len);
/* read length of cookie string */
in_uint32_le(s, cookie_len);
/* read cookie string (plain ASCII) */
cookie = (char *)s->p;
in_uint8s(s, cookie_len);
/* read length of username string */
in_uint32_le(s, username_len);
/* read username string */
username = (wchar_t *)s->p;
in_uint8s(s, username_len);
/* read length of domain string */
in_uint32_le(s, domain_len);
/* read domain string */
domain = (wchar_t *)s->p;
in_uint8s(s, domain_len);
/* read length of password string */
in_uint32_le(s, password_len);
/* read password string */
password = (wchar_t *)s->p;
in_uint8s(s, password_len);
This->redirect = True;
return event_redirect
(
This,
flags,
server_len,
server,
cookie_len,
cookie,
username_len,
username,
domain_len,
domain,
password_len,
password
);
}
/* Process incoming packets */
/* nevers gets out of here till app is done */
void
rdp_main_loop(RDPCLIENT * This, BOOL * deactivated, uint32 * ext_disc_reason)
{
while (rdp_loop(This, deactivated, ext_disc_reason))
;
}
/* used in uiports and rdp_main_loop, processes the rdp packets waiting */
BOOL
rdp_loop(RDPCLIENT * This, BOOL * deactivated, uint32 * ext_disc_reason)
{
uint8 type;
BOOL disc = False; /* True when a disconnect PDU was received */
BOOL cont = True;
STREAM s;
while (cont)
{
s = rdp_recv(This, &type);
if (s == NULL)
return False;
switch (type)
{
case RDP_PDU_DEMAND_ACTIVE:
if(!process_demand_active(This, s))
return False;
*deactivated = False;
break;
case RDP_PDU_DEACTIVATE:
DEBUG(("RDP_PDU_DEACTIVATE\n"));
*deactivated = True;
break;
case RDP_PDU_REDIRECT:
return process_redirect_pdu(This, s);
break;
case RDP_PDU_DATA:
disc = process_data_pdu(This, s, ext_disc_reason);
break;
case 0:
break;
default:
unimpl("PDU %d\n", type);
}
if (disc)
return False;
cont = This->next_packet < s->end;
}
return True;
}
/* Establish a connection up to the RDP layer */
BOOL
rdp_connect(RDPCLIENT * This, char *server, uint32 flags, wchar_t *username, wchar_t *domain, wchar_t *password,
wchar_t *command, wchar_t *directory, wchar_t *hostname, char *cookie)
{
if (!sec_connect(This, server, hostname, cookie))
return False;
rdp_send_logon_info(This, flags, domain, username, password, command, directory);
return True;
}
/* Establish a reconnection up to the RDP layer */
BOOL
rdp_reconnect(RDPCLIENT * This, char *server, uint32 flags, wchar_t *username, wchar_t *domain, wchar_t *password,
wchar_t *command, wchar_t *directory, wchar_t *hostname, char *cookie)
{
if (!sec_reconnect(This, server, hostname, cookie))
return False;
rdp_send_logon_info(This, flags, domain, username, password, command, directory);
return True;
}
/* Called during redirection to reset the state to support redirection */
void
rdp_reset_state(RDPCLIENT * This)
{
This->next_packet = NULL; /* reset the packet information */
This->rdp_shareid = 0;
sec_reset_state(This);
}
/* Disconnect from the RDP layer */
void
rdp_disconnect(RDPCLIENT * This)
{
sec_disconnect(This);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -