Miscellaneous updates: implemented some more protocol features including

colour maps. Started on a new bitmap decompression engine which is not
completely working yet - however I am going back on the road so I am
committing now.


git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@6 423420c4-83ab-492f-b58f-81f9feb106b5
This commit is contained in:
Matt Chapman 2000-07-07 09:40:03 +00:00
parent 72da43c808
commit 26d316fec0
11 changed files with 514 additions and 302 deletions

View File

@ -5,9 +5,9 @@
############################################## ##############################################
CC = gcc CC = gcc
CFLAGS = -g -Wall CFLAGS = -g -Wall -DDEBUG
LIBS = -L/usr/X11R6/lib -lX11 LIBS = -L/usr/X11R6/lib -lX11
OBJECTS = client.o parse.o tcp.o iso.o mcs.o rdp.o bitmap.o xwin.o OBJECTS = client.o parse.o tcp.o iso.o mcs.o rdp.o bitmap.o xwin.o misc.o
rdesktop: $(OBJECTS) rdesktop: $(OBJECTS)
@$(CC) $(CFLAGS) -o rdesktop $(LIBS) $(OBJECTS) @$(CC) $(CFLAGS) -o rdesktop $(LIBS) $(OBJECTS)

364
bitmap.c
View File

@ -19,245 +19,175 @@
*/ */
#include "includes.h" #include "includes.h"
#include <fcntl.h>
#define BITMAP_DEBUG 1 #define CVAL(p) (*(p++))
#define SVAL(p) ((*((p++) + 1) << 8) | CVAL(p))
#if BITMAP_DEBUG #define REPEAT(statement) { while ((count > 0) && (x < width)) { statement; count--; x++; } }
void hexdump(char *filename, unsigned char *data, int length); #define MASK_UPDATE() { maskpix <<= 1; if (maskpix == 0) { mask = CVAL(input); maskpix = 1; } }
#endif
#define RCVAL() (*(input++)) BOOL bitmap_decompress(unsigned char *output, int width, int height,
#define RSVAL() ((*((input++) + 1) << 8) | RCVAL()) unsigned char *input, int size)
#define SCVAL(v) {*(output++) = (v);}
#define FILL() {while (n-- > 0) { if (output - start < width) { SCVAL(0) } else { SCVAL(*(output-width)); }}}
#define MIX() {while (n-- > 0) { if (output - start < width) { SCVAL(mix) } else { SCVAL(*(output-width) ^ mix); }}}
#define COPY() {while (n-- > 0) { SCVAL(RCVAL()); }}
#define COLOR() {int color = RCVAL(); \
while (n-- > 0) { SCVAL(color); }}
#define BICOLOR() {int color1 = RCVAL(); int color2 = RCVAL(); \
while (n-- > 0) { SCVAL(color1); SCVAL(color2); }}
#define SETMIX_MIX() {mix = RCVAL(); MIX();}
#define COPY_PACKED() {n++; n/=2; while (n-- > 0) \
{unsigned char c = RCVAL(); SCVAL((c & 0xF0) >> 4); \
SCVAL(c & 0x0F); }}
BOOL bitmap_decompress(unsigned char *input, int size,
unsigned char *output, int width)
{ {
unsigned char *savedinput = input;
unsigned char *start = output;
unsigned char *end = input + size; unsigned char *end = input + size;
unsigned char code; unsigned char *prevline, *line = NULL;
unsigned char mix = 0xFF; int opcode, count, offset, isfillormix, x = width;
int n, savedn; uint8 code, mask, maskpix, color1, color2;
uint8 mix = 0xff;
dump_data(input, end-input);
while (input < end) while (input < end)
{ {
code = RCVAL(); fprintf(stderr, "Offset %d from end\n", end-input);
switch (code) code = CVAL(input);
{ opcode = code >> 4;
case 0x00: // Fill
n = RCVAL() + 32;
FILL();
break;
case 0xF0: // Fill
n = RSVAL();
FILL();
break;
case 0x20: // Mix
n = RCVAL() + 32;
MIX();
break;
case 0xF1: // Mix
n = RSVAL();
MIX();
break;
case 0x40: // FillOrMix
fprintf(stderr, "FillOrMix unsupported\n");
savedn = n = RCVAL() + 1;
MIX();
input += (savedn+7)/8;
break;
case 0xF2:
fprintf(stderr, "FillOrMix unsupported\n");
savedn = n = RSVAL();
MIX();
input += (savedn+7)/8;
break;
case 0x60: // Color
n = RCVAL() + 32;
COLOR();
break;
case 0xF3:
n = RSVAL();
fprintf(stderr, "Color %d\n", n);
COLOR();
break;
case 0x80: // Copy
n = RCVAL() + 32;
COPY();
break;
case 0xF4:
n = RSVAL();
COPY();
break;
case 0xA0: // Copy Packed
fprintf(stderr, "CopyPacked 1\n");
n = RCVAL() + 32;
COPY_PACKED();
break;
case 0xF5:
fprintf(stderr, "CopyPacked 2\n");
n = RSVAL();
COPY_PACKED();
break;
case 0xC0: // SetMix_Mix
fprintf(stderr, "SetMix_Mix 1\n");
n = RCVAL() + 16;
SETMIX_MIX();
break;
case 0xF6:
fprintf(stderr, "SetMix_Mix 2\n");
n = RSVAL();
SETMIX_MIX();
break;
case 0xD0: // SetMix_FillOrMix
fprintf(stderr, "SetMix_FillOrMix unsupported\n");
savedn = n = RCVAL() + 1;
SETMIX_MIX();
input += (savedn+7)/8;
break;
case 0xF7:
fprintf(stderr, "SetMix_FillOrMix unsupported\n");
savedn = n = RSVAL();
SETMIX_MIX();
input += (savedn+7)/8;
break;
case 0xE0: // Bicolor
fprintf(stderr, "Bicolor 1\n");
n = RCVAL() + 16;
BICOLOR();
break;
case 0xF8:
fprintf(stderr, "Bicolor 2\n");
n = RSVAL();
BICOLOR();
break;
case 0xF9: // FillOrMix_1
fprintf(stderr, "FillOrMix_1 unsupported\n");
return False;
case 0xFA: // FillOrMix_2
fprintf(stderr, "FillOrMix_2 unsupported\n");
return False;
case 0xFD: // White
SCVAL(0xFF);
break;
case 0xFE: // Black
SCVAL(0);
break;
default:
n = code & 31;
if (n == 0) /* Handle different opcode forms */
switch (opcode)
{
case 0xc:
case 0xd:
case 0xe:
opcode -= 6;
count = code & 0xf;
offset = 16;
break;
case 0xf:
opcode = code & 0xf;
count = (opcode < 13) ? SVAL(input) : 1;
offset = 0;
break;
default:
opcode >>= 1;
count = code & 0x1f;
offset = 32;
break;
}
/* Handle strange cases for counts */
if (offset != 0)
{
isfillormix = ((opcode == 2) || (opcode == 7));
if (count == 0)
{ {
fprintf(stderr, "Undefined escape 0x%X\n", code); if (isfillormix)
return False; count = CVAL(input) + 1;
else
count = CVAL(input) + offset;
}
else if (isfillormix)
{
count <<= 3;
}
}
/* Read preliminary data */
maskpix = 0;
switch (opcode)
{
case 3: /* Color */
color1 = CVAL(input);
case 8: /* Bicolor */
color2 = CVAL(input);
break;
case 6: /* SetMix/Mix */
case 7: /* SetMix/FillOrMix */
mix = CVAL(input);
opcode -= 5;
break;
}
/* Output body */
while (count > 0)
{
if (x >= width)
{
if (height <= 0)
return True;
x = 0;
height--;
prevline = line;
line = output + height * width;
} }
switch ((code >> 5) & 7) switch (opcode)
{ {
case 0: // Fill case 0: /* Fill */
FILL(); fprintf(stderr, "Fill %d\n", count);
break; if (prevline == NULL)
case 1: // Mix REPEAT(line[x] = 0)
MIX(); else
break; REPEAT(line[x] = prevline[x])
case 2: // FillOrMix break;
fprintf(stderr, "FillOrMix unsupported\n");
n *= 8;
savedn = n;
MIX();
input += (savedn+7)/8;
break;
case 3: // Color
COLOR();
break;
case 4: // Copy
COPY();
break;
case 5: // Copy Packed
fprintf(stderr, "CopyPacked 3\n");
COPY_PACKED();
break;
case 6:
n = code & 15;
switch ((code >> 4) & 15) case 1: /* Mix */
{ fprintf(stderr, "Mix %d\n", count);
case 0xC: if (prevline == NULL)
fprintf(stderr, "SetMix_Mix 3\n"); REPEAT(line[x] = mix)
SETMIX_MIX(); else
REPEAT(line[x] = prevline[x] ^ mix)
break; break;
case 0xD:
fprintf(stderr, "SetMix_FillOrMix unsupported\n"); #if 0
n *= 8; case 2: /* Fill or Mix */
savedn = n; REPEAT(line[x] = 0);
SETMIX_MIX();
input += (savedn+7)/8;
break; break;
case 0xE: if (prevline == NULL)
fprintf(stderr, "Bicolor 3\n"); REPEAT(
BICOLOR(); MASK_UPDATE();
if (mask & maskpix)
line[x] = mix;
else
line[x] = 0;
)
else
REPEAT(
MASK_UPDATE();
if (mask & maskpix)
line[x] = prevline[x] ^ mix;
else
line[x] = prevline[x];
)
break; break;
#endif
case 3: /* Colour */
fprintf(stderr, "Colour %d\n", count);
REPEAT(line[x] = color2)
break;
case 4: /* Copy */
fprintf(stderr, "Copy %d\n", count);
REPEAT(line[x] = CVAL(input))
break;
#if 0
case 8: /* Bicolor */
REPEAT(line[x] = color1; line[++x] = color2)
break;
case 13: /* White */
REPEAT(line[x] = 0xff)
break;
case 14: /* Black */
REPEAT(line[x] = 0x00)
break;
#endif
default: default:
fprintf(stderr, "Undefined escape 0x%X\n", code); fprintf(stderr, "Unknown bitmap opcode 0x%x\n", opcode);
return False; return False;
}
} }
} }
} }
printf("Uncompressed size: %d\n", output - start);
#if BITMAP_DEBUG
{
static int bmpno = 1;
char filename[64];
snprintf(filename, sizeof(filename)-1, "in%d.raw", bmpno);
hexdump(filename, savedinput, size);
snprintf(filename, sizeof(filename)-1, "out%d.raw", bmpno);
hexdump(filename, start, output-start);
bmpno++;
}
#endif
return True; return True;
} }
#if BITMAP_DEBUG
void hexdump(char *filename, unsigned char *data, int length)
{
/*
int i;
for (i = 0; i < length; i++)
{
printf("%02X ", data[i]);
if (i % 16 == 15)
printf("\n");
}
*/
int fd;
fd = open(filename, O_WRONLY|O_CREAT, 0600);
write(fd, data, length);
close(fd);
}
#endif

View File

@ -19,7 +19,6 @@
*/ */
#include "includes.h" #include "includes.h"
#include "signal.h"
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
@ -47,23 +46,3 @@ int main(int argc, char *argv[])
return 0; return 0;
} }
void *xmalloc(int size)
{
void *mem = malloc(size);
if (mem == NULL) {
fprintf(stderr, "xmalloc: Out of memory.\n");
exit(1);
}
return mem;
}
void *xrealloc(void *oldmem, int size)
{
void *mem = realloc(oldmem, size);
if (mem == NULL) {
fprintf(stderr, "xrealloc: Out of memory.\n");
exit(1);
}
return mem;
}

View File

@ -42,6 +42,7 @@ typedef unsigned short uint16;
typedef unsigned int uint32; typedef unsigned int uint32;
#include "xwin.h" #include "xwin.h"
#include "misc.h"
#include "parse.h" #include "parse.h"
#include "tcp.h" #include "tcp.h"
#include "iso.h" #include "iso.h"

39
mcs.c
View File

@ -176,7 +176,16 @@ BOOL mcs_recv(HCONN conn, BOOL request)
{ {
MCS_DATA data; MCS_DATA data;
return (iso_recv(conn)) && mcs_io_data(&conn->in, &data, request); if (!iso_recv(conn) || !mcs_io_data(&conn->in, &data, request))
return False;
#ifdef MCS_DEBUG
fprintf(stderr, "MCS packet\n");
dump_data(conn->in.data+conn->in.offset, conn->in.end-conn->in.offset);
#endif
conn->in.rdp_offset = conn->in.offset;
return True;
} }
/* Initialise a DOMAIN_PARAMS structure */ /* Initialise a DOMAIN_PARAMS structure */
@ -243,17 +252,21 @@ BOOL ber_io_header(STREAM s, BOOL islong, int tagval, int *length)
BOOL res; BOOL res;
/* Read/write tag */ /* Read/write tag */
if (islong) { if (islong)
{
word_tag = tagval; word_tag = tagval;
res = msb_io_uint16(s, &word_tag); res = msb_io_uint16(s, &word_tag);
tag = word_tag; tag = word_tag;
} else { }
else
{
byte_tag = tagval; byte_tag = tagval;
res = prs_io_uint8(s, &byte_tag); res = prs_io_uint8(s, &byte_tag);
tag = byte_tag; tag = byte_tag;
} }
if (!res || (tag != tagval)) { if (!res || (tag != tagval))
{
fprintf(stderr, "Invalid ASN.1 tag\n"); fprintf(stderr, "Invalid ASN.1 tag\n");
return False; return False;
} }
@ -524,6 +537,7 @@ BOOL mcs_io_data(STREAM s, MCS_DATA *dt, BOOL request)
{ {
uint8 opcode = (request ? 25 : 26) << 2; uint8 opcode = (request ? 25 : 26) << 2;
uint8 pkt_opcode = opcode; uint8 pkt_opcode = opcode;
uint8 byte1, byte2;
BOOL res; BOOL res;
res = prs_io_uint8(s, &pkt_opcode); res = prs_io_uint8(s, &pkt_opcode);
@ -538,7 +552,22 @@ BOOL mcs_io_data(STREAM s, MCS_DATA *dt, BOOL request)
res = res ? msb_io_uint16(s, &dt->userid) : False; res = res ? msb_io_uint16(s, &dt->userid) : False;
res = res ? msb_io_uint16(s, &dt->chanid) : False; res = res ? msb_io_uint16(s, &dt->chanid) : False;
res = res ? prs_io_uint8 (s, &dt->flags ) : False; res = res ? prs_io_uint8 (s, &dt->flags ) : False;
res = res ? msb_io_uint16(s, &dt->length) : False;
if (s->marshall)
{
res = res ? msb_io_uint16(s, &dt->length) : False;
}
else
{
res = res ? prs_io_uint8(s, &byte1) : False;
if (byte1 & 0x80)
{
res = res ? prs_io_uint8(s, &byte2) : False;
dt->length = ((byte1 & ~0x80) << 8) + byte2;
}
else dt->length = byte1;
}
return res; return res;
} }

View File

@ -41,6 +41,7 @@ typedef struct connection
{ {
/* User interface */ /* User interface */
HWINDOW wnd; HWINDOW wnd;
HBITMAP bmpcache[8];
/* Parsing layer */ /* Parsing layer */
struct stream in; struct stream in;

21
proto.h
View File

@ -75,7 +75,12 @@ BOOL mcs_io_data(STREAM s, MCS_DATA *dt, BOOL request);
/* RDP layer */ /* RDP layer */
HCONN rdp_connect(char *server); HCONN rdp_connect(char *server);
void rdp_main_loop(HCONN conn); void rdp_main_loop(HCONN conn);
void process_opaque_rect(HCONN conn, RDP_ORDER_STATE *os, BOOL delta);
void process_bmpcache(HCONN conn);
void process_orders(HCONN conn, RDP_ORDER_STATE *os); void process_orders(HCONN conn, RDP_ORDER_STATE *os);
void process_palette(HCONN conn);
void process_update(HCONN conn, RDP_ORDER_STATE *os);
void process_pointer(HCONN conn);
void rdp_establish_key(HCONN conn); void rdp_establish_key(HCONN conn);
void rdp_send_cert(HCONN conn); void rdp_send_cert(HCONN conn);
void rdp_send_confirm_active(HCONN conn); void rdp_send_confirm_active(HCONN conn);
@ -105,6 +110,8 @@ void rdp_make_font_pdu(RDP_FONT_PDU *pdu, uint16 seqno);
void rdp_make_input_pdu(RDP_INPUT_PDU *pdu); void rdp_make_input_pdu(RDP_INPUT_PDU *pdu);
BOOL rdp_io_header(STREAM s, RDP_HEADER *hdr); BOOL rdp_io_header(STREAM s, RDP_HEADER *hdr);
BOOL rdp_io_data_header(STREAM s, RDP_DATA_HEADER *hdr); BOOL rdp_io_data_header(STREAM s, RDP_DATA_HEADER *hdr);
BOOL rdp_io_coord(STREAM s, uint16 *coord, BOOL delta);
BOOL rdp_io_colormap(STREAM s, COLORMAP *colors);
BOOL rdp_io_general_caps(STREAM s, RDP_GENERAL_CAPS *caps); BOOL rdp_io_general_caps(STREAM s, RDP_GENERAL_CAPS *caps);
BOOL rdp_io_bitmap_caps(STREAM s, RDP_BITMAP_CAPS *caps); BOOL rdp_io_bitmap_caps(STREAM s, RDP_BITMAP_CAPS *caps);
BOOL rdp_io_order_caps(STREAM s, RDP_ORDER_CAPS *caps); BOOL rdp_io_order_caps(STREAM s, RDP_ORDER_CAPS *caps);
@ -125,17 +132,25 @@ BOOL rdp_io_font_pdu(STREAM s, RDP_FONT_PDU *pdu);
BOOL rdp_io_update_pdu(STREAM s, RDP_UPDATE_PDU *pdu); BOOL rdp_io_update_pdu(STREAM s, RDP_UPDATE_PDU *pdu);
BOOL rdp_io_secondary_order(STREAM s, RDP_SECONDARY_ORDER *rso); BOOL rdp_io_secondary_order(STREAM s, RDP_SECONDARY_ORDER *rso);
BOOL rdp_io_bitmap_header(STREAM s, RDP_BITMAP_HEADER *rdh); BOOL rdp_io_bitmap_header(STREAM s, RDP_BITMAP_HEADER *rdh);
BOOL rdp_io_pointer(STREAM s, RDP_POINTER *ptr);
/* Utility routines */ /* Utility routines */
void *xmalloc(int size); void *xmalloc(int size);
void *xrealloc(void *oldmem, int size); void *xrealloc(void *oldmem, int size);
BOOL bitmap_decompress(unsigned char *input, int size, void dump_data(unsigned char *p, int len);
unsigned char *output, int width); BOOL bitmap_decompress(unsigned char *output, int width, int height,
unsigned char *input, int size);
/* User interface routines */ /* User interface routines */
HWINDOW ui_create_window(int width, int height); HWINDOW ui_create_window(int width, int height);
void ui_destroy_window(HWINDOW wnd); void ui_destroy_window(HWINDOW wnd);
HBITMAP ui_create_bitmap(HWINDOW wnd, int width, int height, uint8 *data); HBITMAP ui_create_bitmap(HWINDOW wnd, int width, int height, uint8 *data);
void ui_destroy_bitmap(HBITMAP bmp); void ui_destroy_bitmap(HWINDOW wnd, HBITMAP bmp);
void ui_paint_bitmap(HWINDOW wnd, HBITMAP bmp, int x, int y); void ui_paint_bitmap(HWINDOW wnd, HBITMAP bmp, int x, int y);
HCOLORMAP ui_create_colormap(HWINDOW wnd, COLORMAP *colors);
void ui_destroy_colormap(HWINDOW wnd, HCOLORMAP map);
void ui_set_colormap(HWINDOW wnd, HCOLORMAP map);
void ui_draw_rectangle(HWINDOW wnd, int x, int y, int width, int height);
void ui_move_pointer(HWINDOW wnd, int x, int y);

269
rdp.c
View File

@ -34,6 +34,7 @@ HCONN rdp_connect(char *server)
mcs_recv(conn, False); /* Server's licensing certificate */ mcs_recv(conn, False); /* Server's licensing certificate */
rdp_send_cert(conn); rdp_send_cert(conn);
mcs_recv(conn, False); mcs_recv(conn, False);
mcs_recv(conn, False); /* Demand active */
if (!rdp_recv_pdu(conn, &type) || (type != RDP_PDU_DEMAND_ACTIVE)) if (!rdp_recv_pdu(conn, &type) || (type != RDP_PDU_DEMAND_ACTIVE))
{ {
@ -61,7 +62,6 @@ HCONN rdp_connect(char *server)
void rdp_main_loop(HCONN conn) void rdp_main_loop(HCONN conn)
{ {
RDP_DATA_HEADER hdr; RDP_DATA_HEADER hdr;
RDP_UPDATE_PDU update;
RDP_ORDER_STATE os; RDP_ORDER_STATE os;
uint8 type; uint8 type;
@ -70,37 +70,75 @@ void rdp_main_loop(HCONN conn)
while (rdp_recv_pdu(conn, &type)) while (rdp_recv_pdu(conn, &type))
{ {
if (type != RDP_PDU_DATA) if (type != RDP_PDU_DATA)
{
fprintf(stderr, "Unknown PDU 0x%x\n", type);
continue; continue;
}
rdp_io_data_header(&conn->in, &hdr); rdp_io_data_header(&conn->in, &hdr);
switch (hdr.data_pdu_type) switch (hdr.data_pdu_type)
{ {
case RDP_DATA_PDU_UPDATE: case RDP_DATA_PDU_UPDATE:
rdp_io_update_pdu(&conn->in, &update); process_update(conn, &os);
if (update.update_type == RDP_UPDATE_ORDERS) break;
{
fprintf(stderr, "Received orders\n"); case RDP_DATA_PDU_POINTER:
process_orders(conn, &os); process_pointer(conn);
} break;
break;
default:
fprintf(stderr, "Unknown data PDU 0x%x\n",
hdr.data_pdu_type);
} }
} }
} }
void prs_io_coord(STREAM s, uint16 *coord, BOOL delta) void process_memblt(HCONN conn, RDP_ORDER_STATE *os, BOOL delta)
{ {
uint8 change; HBITMAP hbitmap;
uint16 present;
lsb_io_uint16(&conn->in, &present);
if (delta) if (present & 1)
prs_io_uint8(&conn->in, &os->memblt.cache_id);
if (present & 2)
rdp_io_coord(&conn->in, &os->memblt.x, delta);
if (present & 4)
rdp_io_coord(&conn->in, &os->memblt.y, delta);
if (present & 8)
rdp_io_coord(&conn->in, &os->memblt.cx, delta);
if (present & 16)
rdp_io_coord(&conn->in, &os->memblt.cy, delta);
if (present & 32)
prs_io_uint8(&conn->in, &os->memblt.opcode);
if (present & 256)
lsb_io_uint16(&conn->in, &os->memblt.cache_idx);
if (os->memblt.opcode != 0xcc) /* SRCCOPY */
{ {
prs_io_uint8(s, &change); fprintf(stderr, "Unsupported raster operation 0x%x\n",
*coord += change; os->memblt.opcode);
return;
} }
else
if ((os->memblt.cache_idx > NUM_ELEMENTS(conn->bmpcache))
|| ((hbitmap = conn->bmpcache[os->memblt.cache_idx]) == NULL))
{ {
lsb_io_uint16(s, coord); fprintf(stderr, "Bitmap %d not found\n", os->memblt.cache_idx);
return;
} }
fprintf(stderr, "MEMBLT %d:%dx%d\n", os->memblt.cache_idx,
os->memblt.x, os->memblt.y);
ui_paint_bitmap(conn->wnd, hbitmap, os->memblt.x, os->memblt.y);
} }
void process_opaque_rect(HCONN conn, RDP_ORDER_STATE *os, BOOL delta) void process_opaque_rect(HCONN conn, RDP_ORDER_STATE *os, BOOL delta)
@ -109,45 +147,60 @@ void process_opaque_rect(HCONN conn, RDP_ORDER_STATE *os, BOOL delta)
prs_io_uint8(&conn->in, &present); prs_io_uint8(&conn->in, &present);
if (present & 1) if (present & 1)
prs_io_coord(&conn->in, &os->opaque_rect.x, delta); rdp_io_coord(&conn->in, &os->opaque_rect.x, delta);
if (present & 2) if (present & 2)
prs_io_coord(&conn->in, &os->opaque_rect.y, delta); rdp_io_coord(&conn->in, &os->opaque_rect.y, delta);
if (present & 4) if (present & 4)
prs_io_coord(&conn->in, &os->opaque_rect.cx, delta); rdp_io_coord(&conn->in, &os->opaque_rect.cx, delta);
if (present & 8) if (present & 8)
prs_io_coord(&conn->in, &os->opaque_rect.cy, delta); rdp_io_coord(&conn->in, &os->opaque_rect.cy, delta);
if (present & 16) if (present & 16)
prs_io_uint8(&conn->in, &os->opaque_rect.colour); prs_io_uint8(&conn->in, &os->opaque_rect.colour);
fprintf(stderr, "Opaque rectangle at %d, %d\n", os->opaque_rect.x, os->opaque_rect.y); fprintf(stderr, "Opaque rectangle at %d, %d\n", os->opaque_rect.x, os->opaque_rect.y);
ui_draw_rectangle(conn->wnd, os->opaque_rect.x, os->opaque_rect.y,
os->opaque_rect.cx, os->opaque_rect.cy);
} }
void process_bmpcache(HCONN conn) void process_bmpcache(HCONN conn)
{ {
RDP_BITMAP_HEADER rbh; RDP_BITMAP_HEADER rbh;
char *bmpdata; HBITMAP *entry;
HBITMAP bmp; char *input, *bmpdata;
static int x = 0;
rdp_io_bitmap_header(&conn->in, &rbh); rdp_io_bitmap_header(&conn->in, &rbh);
fprintf(stderr, "Decompressing bitmap %d x %d, final size %d\n", rbh.width, rbh.height, rbh.final_size); fprintf(stderr, "BMPCACHE %d:%dx%d\n", rbh.cache_idx,
rbh.width, rbh.height);
input = conn->in.data + conn->in.offset;
conn->in.offset += rbh.size;
// dump_data(conn->in.data+conn->in.offset, conn->in.rdp_offset-conn->in.offset);
bmpdata = malloc(rbh.width * rbh.height); bmpdata = malloc(rbh.width * rbh.height);
bitmap_decompress(conn->in.data if (!bitmap_decompress(bmpdata, rbh.width, rbh.height, input, rbh.size))
+ conn->in.offset, rbh.size, {
bmpdata, rbh.width); fprintf(stderr, "Decompression failed\n");
conn->in.offset += rbh.size; free(bmpdata);
return;
}
bmp = ui_create_bitmap(conn->wnd, rbh.width, rbh.height, bmpdata); if (rbh.cache_idx > NUM_ELEMENTS(conn->bmpcache))
ui_paint_bitmap(conn->wnd, bmp, x, 0); {
ui_destroy_bitmap(bmp); fprintf(stderr, "Attempted store past end of cache");
return;
}
x += rbh.width; entry = &conn->bmpcache[rbh.cache_idx];
// if (*entry != NULL)
// ui_destroy_bitmap(conn->wnd, *entry);
*entry = ui_create_bitmap(conn->wnd, rbh.width, rbh.height, bmpdata);
// ui_paint_bitmap(conn->wnd, bmp, x, 0);
// ui_destroy_bitmap(conn->wnd, bmp);
} }
void process_orders(HCONN conn, RDP_ORDER_STATE *os) void process_orders(HCONN conn, RDP_ORDER_STATE *os)
@ -155,6 +208,7 @@ void process_orders(HCONN conn, RDP_ORDER_STATE *os)
uint16 num_orders; uint16 num_orders;
int processed = 0; int processed = 0;
BOOL res = True; BOOL res = True;
BOOL delta;
// unsigned char *p; // unsigned char *p;
lsb_io_uint16(&conn->in, &num_orders); lsb_io_uint16(&conn->in, &num_orders);
@ -169,6 +223,10 @@ void process_orders(HCONN conn, RDP_ORDER_STATE *os)
uint8 order_flags; uint8 order_flags;
prs_io_uint8(&conn->in, &order_flags); prs_io_uint8(&conn->in, &order_flags);
fprintf(stderr, "Order flags: 0x%x\n", order_flags);
if (order_flags == 0x51) /* ?? */
return;
if (!(order_flags & RDP_ORDER_STANDARD)) if (!(order_flags & RDP_ORDER_STANDARD))
return; return;
@ -188,27 +246,84 @@ void process_orders(HCONN conn, RDP_ORDER_STATE *os)
rso.type); rso.type);
return; return;
} }
} }
else
if (order_flags & RDP_ORDER_CHANGE)
prs_io_uint8(&conn->in, &os->order_type);
switch (os->order_type)
{ {
case RDP_ORDER_OPAQUE_RECT: if (order_flags & RDP_ORDER_CHANGE)
process_opaque_rect(conn, os, order_flags & RDP_ORDER_DELTA); prs_io_uint8(&conn->in, &os->order_type);
break;
default: delta = order_flags & RDP_ORDER_DELTA;
fprintf(stderr, "Unknown order %d\n", os->order_type);
return; switch (os->order_type)
{
case RDP_ORDER_OPAQUE_RECT:
process_opaque_rect(conn, os, delta);
break;
case RDP_ORDER_MEMBLT:
process_memblt(conn, os, delta);
break;
default:
fprintf(stderr, "Unknown order %d\n", os->order_type);
return;
}
} }
processed++; processed++;
} }
} }
void process_palette(HCONN conn)
{
HCOLORMAP map;
COLORMAP colors;
rdp_io_colormap(&conn->in, &colors);
map = ui_create_colormap(conn->wnd, &colors);
ui_set_colormap(conn->wnd, map);
// ui_destroy_colormap(map);
}
void process_update(HCONN conn, RDP_ORDER_STATE *os)
{
RDP_UPDATE_PDU update;
rdp_io_update_pdu(&conn->in, &update);
switch (update.update_type)
{
case RDP_UPDATE_ORDERS:
process_orders(conn, os);
break;
case RDP_UPDATE_PALETTE:
process_palette(conn);
break;
case RDP_UPDATE_SYNCHRONIZE:
break;
default:
fprintf(stderr, "Unknown update 0x%x\n",
update.update_type);
}
}
void process_pointer(HCONN conn)
{
RDP_POINTER ptr;
rdp_io_pointer(&conn->in, &ptr);
switch (ptr.message)
{
case RDP_POINTER_MOVE:
ui_move_pointer(conn->wnd, ptr.x, ptr.y);
break;
default:
fprintf(stderr, "Unknown pointer message 0x%x\n",
ptr.message);
}
}
/* Work this out later. This is useless anyway when encryption is off. */ /* Work this out later. This is useless anyway when encryption is off. */
uint8 precanned_key_packet[] = { uint8 precanned_key_packet[] = {
0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x00,0x00, 0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x00,0x00,
@ -420,10 +535,25 @@ BOOL rdp_recv_pdu(HCONN conn, uint8 *type)
{ {
RDP_HEADER hdr; RDP_HEADER hdr;
if (!mcs_recv(conn, False) || !rdp_io_header(&conn->in, &hdr)) conn->in.offset = conn->in.rdp_offset;
if (conn->in.offset >= conn->in.end)
{
if (!mcs_recv(conn, False))
return False;
}
if (!rdp_io_header(&conn->in, &hdr))
return False; return False;
conn->in.rdp_offset += hdr.length;
*type = hdr.pdu_type & 0xf; *type = hdr.pdu_type & 0xf;
#if DEBUG
fprintf(stderr, "RDP packet (type %x):\n", *type);
dump_data(conn->in.data+conn->in.offset, conn->in.rdp_offset-conn->in.offset);
#endif
return True; return True;
} }
@ -625,6 +755,39 @@ BOOL rdp_io_data_header(STREAM s, RDP_DATA_HEADER *hdr)
return res; return res;
} }
BOOL rdp_io_coord(STREAM s, uint16 *coord, BOOL delta)
{
uint8 change;
BOOL res;
if (delta)
{
res = prs_io_uint8(s, &change);
*coord += change;
}
else
{
res = lsb_io_uint16(s, coord);
}
return res;
}
BOOL rdp_io_colormap(STREAM s, COLORMAP *colors)
{
int datasize;
lsb_io_uint16(s, &colors->ncolors);
datasize = colors->ncolors * 3;
if (datasize > sizeof(colors->colors))
return False;
memcpy(colors->colors, s->data + s->offset, datasize);
s->offset += datasize;
return True;
}
BOOL rdp_io_general_caps(STREAM s, RDP_GENERAL_CAPS *caps) BOOL rdp_io_general_caps(STREAM s, RDP_GENERAL_CAPS *caps)
{ {
uint16 length = RDP_CAPLEN_GENERAL; uint16 length = RDP_CAPLEN_GENERAL;
@ -1153,3 +1316,15 @@ BOOL rdp_io_bitmap_header(STREAM s, RDP_BITMAP_HEADER *rdh)
return res; return res;
} }
BOOL rdp_io_pointer(STREAM s, RDP_POINTER *ptr)
{
BOOL res = True;
res = res ? lsb_io_uint16(s, &ptr->message) : False;
res = res ? lsb_io_uint16(s, &ptr->pad ) : False;
res = res ? lsb_io_uint16(s, &ptr->x ) : False;
res = res ? lsb_io_uint16(s, &ptr->y ) : False;
return res;
}

33
rdp.h
View File

@ -305,8 +305,9 @@ typedef struct _RDP_FONT_PDU
} RDP_FONT_PDU; } RDP_FONT_PDU;
#define RDP_UPDATE_ORDERS 0 #define RDP_UPDATE_ORDERS 0
#define RDP_UPDATE_PALETTE 2 #define RDP_UPDATE_PALETTE 2
#define RDP_UPDATE_SYNCHRONIZE 3
typedef struct _OPAQUE_RECT_ORDER typedef struct _OPAQUE_RECT_ORDER
{ {
@ -318,11 +319,24 @@ typedef struct _OPAQUE_RECT_ORDER
} OPAQUE_RECT_ORDER; } OPAQUE_RECT_ORDER;
typedef struct _MEMBLT_ORDER
{
uint8 cache_id;
uint16 x;
uint16 y;
uint16 cx;
uint16 cy;
uint8 opcode;
uint16 cache_idx;
} MEMBLT_ORDER;
typedef struct _RDP_ORDER_STATE typedef struct _RDP_ORDER_STATE
{ {
uint8 order_type; uint8 order_type;
OPAQUE_RECT_ORDER opaque_rect; OPAQUE_RECT_ORDER opaque_rect;
MEMBLT_ORDER memblt;
} RDP_ORDER_STATE; } RDP_ORDER_STATE;
@ -342,7 +356,8 @@ typedef struct _RDP_UPDATE_PDU
enum RDP_ORDER_TYPE enum RDP_ORDER_TYPE
{ {
RDP_ORDER_OPAQUE_RECT = 10 RDP_ORDER_OPAQUE_RECT = 10,
RDP_ORDER_MEMBLT = 13
}; };
enum RDP_SECONDARY_ORDER_TYPE enum RDP_SECONDARY_ORDER_TYPE
@ -373,3 +388,15 @@ typedef struct _RDP_BITMAP_HEADER
uint16 final_size; uint16 final_size;
} RDP_BITMAP_HEADER; } RDP_BITMAP_HEADER;
#define RDP_POINTER_MOVE 3
typedef struct _RDP_POINTER
{
uint16 message;
uint16 pad;
uint16 x;
uint16 y;
} RDP_POINTER;

60
xwin.c
View File

@ -45,6 +45,8 @@ HWINDOW ui_create_window(int width, int height)
wnd->display = display; wnd->display = display;
wnd->wnd = window; wnd->wnd = window;
wnd->gc = gc; wnd->gc = gc;
wnd->visual = DefaultVisual(wnd->display, DefaultScreen(wnd->display));
return wnd; return wnd;
} }
@ -58,16 +60,14 @@ void ui_destroy_window(HWINDOW wnd)
HBITMAP ui_create_bitmap(HWINDOW wnd, int width, int height, uint8 *data) HBITMAP ui_create_bitmap(HWINDOW wnd, int width, int height, uint8 *data)
{ {
XImage *image; XImage *image;
Visual *visual;
visual = DefaultVisual(wnd->display, DefaultScreen(wnd->display)); image = XCreateImage(wnd->display, wnd->visual, 8, ZPixmap, 0,
image = XCreateImage(wnd->display, visual, 8, ZPixmap, 0,
data, width, height, 32, width); data, width, height, 32, width);
return (HBITMAP)image; return (HBITMAP)image;
} }
void ui_destroy_bitmap(HBITMAP bmp) void ui_destroy_bitmap(HWINDOW wnd, HBITMAP bmp)
{ {
XDestroyImage((XImage *)bmp); XDestroyImage((XImage *)bmp);
} }
@ -81,3 +81,55 @@ void ui_paint_bitmap(HWINDOW wnd, HBITMAP bmp, int x, int y)
XSync(wnd->display, True); XSync(wnd->display, True);
} }
HCOLORMAP ui_create_colormap(HWINDOW wnd, COLORMAP *colors)
{
COLORENTRY *entry;
XColor *xcolors, *xentry;
Colormap map;
int i, ncolors = colors->ncolors;
xcolors = malloc(sizeof(XColor) * ncolors);
for (i = 0; i < ncolors; i++)
{
entry = &colors->colors[i];
xentry = &xcolors[i];
xentry->pixel = i;
xentry->red = entry->red << 8;
xentry->blue = entry->blue << 8;
xentry->green = entry->green << 8;
xentry->flags = DoRed | DoBlue | DoGreen;
}
map = XCreateColormap(wnd->display, wnd->wnd, wnd->visual, AllocAll);
XStoreColors(wnd->display, map, xcolors, ncolors);
free(xcolors);
return (HCOLORMAP)map;
}
void ui_destroy_colormap(HWINDOW wnd, HCOLORMAP map)
{
XFreeColormap(wnd->display, (Colormap)map);
}
void ui_set_colormap(HWINDOW wnd, HCOLORMAP map)
{
XSetWindowColormap(wnd->display, wnd->wnd, (Colormap)map);
}
void ui_draw_rectangle(HWINDOW wnd, int x, int y, int width, int height)
{
static int white = 0;
XSetForeground(wnd->display, wnd->gc, white);
XFillRectangle(wnd->display, wnd->wnd, wnd->gc, x, y, width, height);
white++;
}
void ui_move_pointer(HWINDOW wnd, int x, int y)
{
XWarpPointer(wnd->display, wnd->wnd, wnd->wnd, 0, 0, 0, 0, x, y);
}

3
xwin.h
View File

@ -26,7 +26,10 @@ typedef struct window
Display *display; Display *display;
Window wnd; Window wnd;
GC gc; GC gc;
Visual *visual;
} *HWINDOW; } *HWINDOW;
typedef XImage *HBITMAP; typedef XImage *HBITMAP;
typedef Colormap HCOLORMAP;