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:
parent
72da43c808
commit
26d316fec0
4
Makefile
4
Makefile
@ -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)
|
||||||
|
362
bitmap.c
362
bitmap.c
@ -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;
|
||||||
|
|
||||||
|
/* Handle different opcode forms */
|
||||||
|
switch (opcode)
|
||||||
{
|
{
|
||||||
case 0x00: // Fill
|
case 0xc:
|
||||||
n = RCVAL() + 32;
|
case 0xd:
|
||||||
FILL();
|
case 0xe:
|
||||||
|
opcode -= 6;
|
||||||
|
count = code & 0xf;
|
||||||
|
offset = 16;
|
||||||
break;
|
break;
|
||||||
case 0xF0: // Fill
|
|
||||||
n = RSVAL();
|
case 0xf:
|
||||||
FILL();
|
opcode = code & 0xf;
|
||||||
break;
|
count = (opcode < 13) ? SVAL(input) : 1;
|
||||||
case 0x20: // Mix
|
offset = 0;
|
||||||
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;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
n = code & 31;
|
opcode >>= 1;
|
||||||
|
count = code & 0x1f;
|
||||||
|
offset = 32;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (n == 0)
|
/* Handle strange cases for counts */
|
||||||
|
if (offset != 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Undefined escape 0x%X\n", code);
|
isfillormix = ((opcode == 2) || (opcode == 7));
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ((code >> 5) & 7)
|
if (count == 0)
|
||||||
{
|
{
|
||||||
case 0: // Fill
|
if (isfillormix)
|
||||||
FILL();
|
count = CVAL(input) + 1;
|
||||||
break;
|
else
|
||||||
case 1: // Mix
|
count = CVAL(input) + offset;
|
||||||
MIX();
|
}
|
||||||
break;
|
else if (isfillormix)
|
||||||
case 2: // FillOrMix
|
|
||||||
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 0xC:
|
count <<= 3;
|
||||||
fprintf(stderr, "SetMix_Mix 3\n");
|
|
||||||
SETMIX_MIX();
|
|
||||||
break;
|
|
||||||
case 0xD:
|
|
||||||
fprintf(stderr, "SetMix_FillOrMix unsupported\n");
|
|
||||||
n *= 8;
|
|
||||||
savedn = n;
|
|
||||||
SETMIX_MIX();
|
|
||||||
input += (savedn+7)/8;
|
|
||||||
break;
|
|
||||||
case 0xE:
|
|
||||||
fprintf(stderr, "Bicolor 3\n");
|
|
||||||
BICOLOR();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "Undefined escape 0x%X\n", code);
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Uncompressed size: %d\n", output - start);
|
/* Read preliminary data */
|
||||||
#if BITMAP_DEBUG
|
maskpix = 0;
|
||||||
|
switch (opcode)
|
||||||
{
|
{
|
||||||
static int bmpno = 1;
|
case 3: /* Color */
|
||||||
char filename[64];
|
color1 = CVAL(input);
|
||||||
|
case 8: /* Bicolor */
|
||||||
snprintf(filename, sizeof(filename)-1, "in%d.raw", bmpno);
|
color2 = CVAL(input);
|
||||||
hexdump(filename, savedinput, size);
|
break;
|
||||||
|
case 6: /* SetMix/Mix */
|
||||||
snprintf(filename, sizeof(filename)-1, "out%d.raw", bmpno);
|
case 7: /* SetMix/FillOrMix */
|
||||||
hexdump(filename, start, output-start);
|
mix = CVAL(input);
|
||||||
|
opcode -= 5;
|
||||||
bmpno++;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Output body */
|
||||||
|
while (count > 0)
|
||||||
|
{
|
||||||
|
if (x >= width)
|
||||||
|
{
|
||||||
|
if (height <= 0)
|
||||||
|
return True;
|
||||||
|
|
||||||
|
x = 0;
|
||||||
|
height--;
|
||||||
|
|
||||||
|
prevline = line;
|
||||||
|
line = output + height * width;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (opcode)
|
||||||
|
{
|
||||||
|
case 0: /* Fill */
|
||||||
|
fprintf(stderr, "Fill %d\n", count);
|
||||||
|
if (prevline == NULL)
|
||||||
|
REPEAT(line[x] = 0)
|
||||||
|
else
|
||||||
|
REPEAT(line[x] = prevline[x])
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: /* Mix */
|
||||||
|
fprintf(stderr, "Mix %d\n", count);
|
||||||
|
if (prevline == NULL)
|
||||||
|
REPEAT(line[x] = mix)
|
||||||
|
else
|
||||||
|
REPEAT(line[x] = prevline[x] ^ mix)
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
case 2: /* Fill or Mix */
|
||||||
|
REPEAT(line[x] = 0);
|
||||||
|
break;
|
||||||
|
if (prevline == NULL)
|
||||||
|
REPEAT(
|
||||||
|
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;
|
||||||
#endif
|
#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:
|
||||||
|
fprintf(stderr, "Unknown bitmap opcode 0x%x\n", opcode);
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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
|
|
||||||
|
21
client.c
21
client.c
@ -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;
|
|
||||||
}
|
|
||||||
|
@ -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"
|
||||||
|
37
mcs.c
37
mcs.c
@ -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;
|
||||||
|
|
||||||
|
if (s->marshall)
|
||||||
|
{
|
||||||
res = res ? msb_io_uint16(s, &dt->length) : False;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1
parse.h
1
parse.h
@ -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
21
proto.h
@ -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);
|
||||||
|
|
||||||
|
247
rdp.c
247
rdp.c
@ -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)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Received orders\n");
|
|
||||||
process_orders(conn, &os);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case RDP_DATA_PDU_POINTER:
|
||||||
|
process_pointer(conn);
|
||||||
|
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)
|
if (order_flags & RDP_ORDER_CHANGE)
|
||||||
prs_io_uint8(&conn->in, &os->order_type);
|
prs_io_uint8(&conn->in, &os->order_type);
|
||||||
|
|
||||||
|
delta = order_flags & RDP_ORDER_DELTA;
|
||||||
|
|
||||||
switch (os->order_type)
|
switch (os->order_type)
|
||||||
{
|
{
|
||||||
case RDP_ORDER_OPAQUE_RECT:
|
case RDP_ORDER_OPAQUE_RECT:
|
||||||
process_opaque_rect(conn, os, order_flags & RDP_ORDER_DELTA);
|
process_opaque_rect(conn, os, delta);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case RDP_ORDER_MEMBLT:
|
||||||
|
process_memblt(conn, os, delta);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Unknown order %d\n", os->order_type);
|
fprintf(stderr, "Unknown order %d\n", os->order_type);
|
||||||
return;
|
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;
|
||||||
|
}
|
||||||
|
29
rdp.h
29
rdp.h
@ -307,6 +307,7 @@ typedef struct _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
60
xwin.c
@ -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);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user