Committing some awesome progress I made while overseas - this commit

really embodies a huge number of changes. We are now able to talk quite
fluently to a French NT Terminal Server - in normal usage only minor
font issues remain (handling of TEXT2 order is not perfect).

The next major hurdle is encryption, and it will be quite a big hurdle
- there seems to be some quite nasty session key stuff.


git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@8 423420c4-83ab-492f-b58f-81f9feb106b5
This commit is contained in:
Matt Chapman 2000-07-25 12:34:29 +00:00
parent a608d31345
commit e11a571f14
18 changed files with 2623 additions and 978 deletions

View File

@ -5,12 +5,15 @@
##############################################
CC = gcc
CFLAGS = -g -Wall -DDEBUG
CFLAGS = -g -Wall -DDUMP
LIBS = -L/usr/X11R6/lib -lX11
OBJECTS = client.o parse.o tcp.o iso.o mcs.o rdp.o bitmap.o xwin.o misc.o
OBJECTS = client.o parse.o tcp.o iso.o mcs.o rdp.o process.o bitmap.o cache.o xwin.o misc.o
rdesktop: $(OBJECTS)
@$(CC) $(CFLAGS) -o rdesktop $(LIBS) $(OBJECTS)
proto:
@cproto -D MAKE_PROTO -o proto.h *.c
clean:
rm -f *.o

View File

@ -24,7 +24,7 @@
#define SVAL(p) ((*((p++) + 1) << 8) | CVAL(p))
#define REPEAT(statement) { while ((count > 0) && (x < width)) { statement; count--; x++; } }
#define MASK_UPDATE() { maskpix <<= 1; if (maskpix == 0) { mask = CVAL(input); maskpix = 1; } }
#define MASK_UPDATE() { mixmask <<= 1; if (mixmask == 0) { mask = CVAL(input); mixmask = 1; } }
BOOL bitmap_decompress(unsigned char *output, int width, int height,
unsigned char *input, int size)
@ -32,13 +32,12 @@ BOOL bitmap_decompress(unsigned char *output, int width, int height,
unsigned char *end = input + size;
unsigned char *prevline, *line = NULL;
int opcode, count, offset, isfillormix, x = width;
uint8 code, mask, maskpix, color1, color2;
int lastopcode = -1, insertmix = False;
uint8 code, colour1, colour2, mask, mixmask;
uint8 mix = 0xff;
dump_data(input, end-input);
while (input < end)
{
fprintf(stderr, "Offset %d from end\n", end-input);
code = CVAL(input);
opcode = code >> 4;
@ -85,13 +84,17 @@ BOOL bitmap_decompress(unsigned char *output, int width, int height,
}
/* Read preliminary data */
maskpix = 0;
mixmask = 0;
switch (opcode)
{
case 3: /* Color */
color1 = CVAL(input);
case 8: /* Bicolor */
color2 = CVAL(input);
case 0: /* Fill */
if ((lastopcode == opcode) && (x != width))
insertmix = True;
break;
case 8: /* Bicolour */
colour1 = CVAL(input);
case 3: /* Colour */
colour2 = CVAL(input);
break;
case 6: /* SetMix/Mix */
case 7: /* SetMix/FillOrMix */
@ -99,6 +102,7 @@ BOOL bitmap_decompress(unsigned char *output, int width, int height,
opcode -= 5;
break;
}
lastopcode = opcode;
/* Output body */
while (count > 0)
@ -106,7 +110,7 @@ BOOL bitmap_decompress(unsigned char *output, int width, int height,
if (x >= width)
{
if (height <= 0)
return True;
return False;
x = 0;
height--;
@ -118,7 +122,18 @@ BOOL bitmap_decompress(unsigned char *output, int width, int height,
switch (opcode)
{
case 0: /* Fill */
fprintf(stderr, "Fill %d\n", count);
if (insertmix)
{
if (prevline == NULL)
line[x] = mix;
else
line[x] = prevline[x] ^ mix;
insertmix = False;
count--;
x++;
}
if (prevline == NULL)
REPEAT(line[x] = 0)
else
@ -126,22 +141,18 @@ BOOL bitmap_decompress(unsigned char *output, int width, int height,
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)
if (mask & mixmask)
line[x] = mix;
else
line[x] = 0;
@ -150,27 +161,23 @@ BOOL bitmap_decompress(unsigned char *output, int width, int height,
REPEAT(
MASK_UPDATE();
if (mask & maskpix)
if (mask & mixmask)
line[x] = prevline[x] ^ mix;
else
line[x] = prevline[x];
)
break;
#endif
case 3: /* Colour */
fprintf(stderr, "Colour %d\n", count);
REPEAT(line[x] = color2)
REPEAT(line[x] = colour2)
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)
case 8: /* Bicolour */
REPEAT(line[x] = colour1; line[++x] = colour2)
break;
case 13: /* White */
@ -180,10 +187,9 @@ BOOL bitmap_decompress(unsigned char *output, int width, int height,
case 14: /* Black */
REPEAT(line[x] = 0x00)
break;
#endif
default:
fprintf(stderr, "Unknown bitmap opcode 0x%x\n", opcode);
NOTIMP("bitmap opcode 0x%x\n", opcode);
return False;
}
}

131
cache.c Normal file
View File

@ -0,0 +1,131 @@
/*
rdesktop: A Remote Desktop Protocol client.
Cache routines
Copyright (C) Matthew Chapman 1999-2000
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
HBITMAP cache_get_bitmap(HCONN conn, uint8 cache_id, uint16 cache_idx)
{
HBITMAP bitmap;
if ((cache_id < NUM_ELEMENTS(conn->bmpcache))
&& (cache_idx < NUM_ELEMENTS(conn->bmpcache[0])))
{
bitmap = conn->bmpcache[cache_id][cache_idx];
if (bitmap != NULL)
return bitmap;
}
ERROR("Bitmap %d:%d not found\n", cache_id, cache_idx);
return NULL;
}
void cache_put_bitmap(HCONN conn, uint8 cache_id, uint16 cache_idx, HBITMAP bitmap)
{
HBITMAP old;
if ((cache_id < NUM_ELEMENTS(conn->bmpcache))
&& (cache_idx < NUM_ELEMENTS(conn->bmpcache[0])))
{
old = conn->bmpcache[cache_id][cache_idx];
if (old != NULL)
ui_destroy_bitmap(conn->wnd, old);
conn->bmpcache[cache_id][cache_idx] = bitmap;
}
else
{
ERROR("Bitmap %d:%d past end of cache\n", cache_id, cache_idx);
}
}
FONT_GLYPH *cache_get_font(HCONN conn, uint8 font, uint16 character)
{
FONT_GLYPH *glyph;
if ((font < NUM_ELEMENTS(conn->fontcache))
&& (character < NUM_ELEMENTS(conn->fontcache[0])))
{
glyph = &conn->fontcache[font][character];
if (glyph->pixmap != NULL)
return glyph;
}
ERROR("Font %d character %d not found\n", font, character);
return NULL;
}
void cache_put_font(HCONN conn, uint8 font, uint32 character, uint16 baseline,
uint16 width, uint16 height, HGLYPH pixmap)
{
FONT_GLYPH *glyph;
if ((font < NUM_ELEMENTS(conn->fontcache))
&& (character < NUM_ELEMENTS(conn->fontcache[0])))
{
glyph = &conn->fontcache[font][character];
if (glyph->pixmap != NULL)
ui_destroy_glyph(conn->wnd, glyph->pixmap);
glyph->baseline = baseline;
glyph->width = width;
glyph->height = height;
glyph->pixmap = pixmap;
}
else
{
ERROR("Font %d character %d past end of cache\n",
font, character);
}
}
BLOB *cache_get_text(HCONN conn, uint8 cache_id)
{
BLOB *text;
if (cache_id < NUM_ELEMENTS(conn->textcache))
{
text = &conn->textcache[cache_id];
if (text->data != NULL)
return text;
}
ERROR("Text cache id %d not found\n", cache_id);
return NULL;
}
void cache_put_text(HCONN conn, uint8 cache_id, void *data, int length)
{
BLOB *text;
if (cache_id < NUM_ELEMENTS(conn->textcache))
{
text = &conn->textcache[cache_id];
if (text->data != NULL)
free(text->data);
text->data = malloc(length);
text->size = length;
memcpy(text->data, data, length);
}
else
{
ERROR("Text cache id %d past end of cache\n", cache_id);
}
}

View File

@ -23,6 +23,8 @@
int main(int argc, char *argv[])
{
HCONN conn;
int width = 640;
int height = 480;
fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
fprintf(stderr, "Version 0.9.0-prealpha. Copyright (C) 1999-2000 Matt Chapman.\n\n");
@ -33,12 +35,12 @@ int main(int argc, char *argv[])
return 1;
}
if ((conn = rdp_connect(argv[1])) == NULL)
if ((conn = rdp_connect(argv[1], width, height)) == NULL)
return 1;
fprintf(stderr, "Connection successful.\n");
conn->wnd = ui_create_window(640, 480);
conn->wnd = ui_create_window(conn, width, height);
rdp_main_loop(conn);
ui_destroy_window(conn->wnd);

View File

@ -30,6 +30,7 @@
#include <netinet/tcp.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/time.h>
#if 0
#define False (0)
@ -49,4 +50,6 @@ typedef unsigned int uint32;
#include "mcs.h"
#include "rdp.h"
#ifndef MAKE_PROTO
#include "proto.h"
#endif

6
iso.c
View File

@ -33,7 +33,7 @@ HCONN iso_connect(char *server)
if (!iso_recv_msg(conn, &code) || (code != ISO_PDU_CC))
{
fprintf(stderr, "ISO error, expected CC\n");
ERROR("ISO error, expected CC\n");
tcp_disconnect(conn);
return NULL;
}
@ -91,7 +91,7 @@ BOOL iso_recv(HCONN conn)
if (!iso_recv_msg(conn, &code) || (code != ISO_PDU_DT))
{
fprintf(stderr, "ISO error, expected DT\n");
ERROR("ISO error, expected DT\n");
return False;
}
@ -128,7 +128,7 @@ BOOL iso_io_tpkt(STREAM s, TPKT *tpkt)
if (tpkt->version != 3)
{
fprintf(stderr, "Wrong TPKT version %d\n", tpkt->version);
ERROR("Wrong TPKT version %d\n", tpkt->version);
return False;
}

65
mcs.c
View File

@ -33,15 +33,14 @@ HCONN mcs_connect(char *server)
mcs_send_connect_initial(conn);
if (!iso_recv(conn) || !mcs_io_connect_response(&conn->in, &mcr))
{
fprintf(stderr, "MCS error, expected Connect-Response\n");
ERROR("MCS error, expected Connect-Response\n");
iso_disconnect(conn);
return NULL;
}
if (mcr.result != 0)
{
fprintf(stderr, "MCS-Connect-Initial failed, result %d\n",
mcr.result);
ERROR("MCS-Connect-Initial failed, result %d\n", mcr.result);
iso_disconnect(conn);
return NULL;
}
@ -51,14 +50,14 @@ HCONN mcs_connect(char *server)
mcs_send_aurq(conn);
if (!iso_recv(conn) || !mcs_io_aucf(&conn->in, &aucf))
{
fprintf(stderr, "MCS error, expected AUcf\n");
ERROR("MCS error, expected AUcf\n");
mcs_disconnect(conn);
return NULL;
}
if (aucf.result != 0)
{
fprintf(stderr, "AUrq failed, result %d\n", mcr.result);
ERROR("AUrq failed, result %d\n", mcr.result);
mcs_disconnect(conn);
return NULL;
}
@ -82,13 +81,13 @@ BOOL mcs_join_channel(HCONN conn, uint16 chanid)
mcs_send_cjrq(conn, chanid);
if (!iso_recv(conn) || !mcs_io_cjcf(&conn->in, &cjcf))
{
fprintf(stderr, "MCS error, expected CJcf\n");
ERROR("MCS error, expected CJcf\n");
return False;
}
if (cjcf.result != 0)
{
fprintf(stderr, "CJrq failed, result %d\n", cjcf.result);
ERROR("CJrq failed, result %d\n", cjcf.result);
return False;
}
@ -179,11 +178,6 @@ BOOL mcs_recv(HCONN conn, BOOL 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;
}
@ -216,16 +210,34 @@ char precanned_connect_userdata[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x01,0xca,0x00,0x00,0x02,0xc0,0x08,0x00,0x00,0x00,0x00,0x00 };
0x00,0x01,0xca,0x00,0x00,0x02,0xc0,0x08,0x00,
/* encryption disabled */ 0x00,0x00,0x00,0x00 };
char precanned_connect_userdata_e[] = {
0x00,
0x05,0x00,0x14,0x7c,0x00,0x01,0x80,0x9e,0x00,0x08,0x00,0x10,0x00,0x01,0xc0,0x00,
0x44,0x75,0x63,0x61,0x80,0x90,0x01,0xc0,0x88,0x00,0x01,0x00,0x08,0x00,0x80,0x02,
0xe0,0x01,0x01,0xca,0x03,0xaa,0x09,0x04,0x00,0x00,0xa3,0x01,0x00,0x00,0x57,0x00,
0x49,0x00,0x4e,0x00,0x39,0x00,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xca,0x00,0x00,0x02,0xc0,
0x08,0x00,0x01,0x00,0x00,0x00
};
char domain_data[] = {0x01};
/* Initialise a MCS_CONNECT_INITIAL structure */
void mcs_make_connect_initial(MCS_CONNECT_INITIAL *mci)
{
mci->calling_domain.length = 0;
mci->calling_domain.data = NULL;
mci->calling_domain.length = 1;
mci->calling_domain.data = domain_data;
mci->called_domain.length = 0;
mci->called_domain.data = NULL;
mci->called_domain.length = 1;
mci->called_domain.data = domain_data;
mci->upward_flag = 0xff;
@ -267,7 +279,7 @@ BOOL ber_io_header(STREAM s, BOOL islong, int tagval, int *length)
if (!res || (tag != tagval))
{
fprintf(stderr, "Invalid ASN.1 tag\n");
ERROR("Invalid ASN.1 tag\n");
return False;
}
@ -374,7 +386,7 @@ BOOL ber_io_uint8(STREAM s, uint8 *i, int tagval)
if (length != 1)
{
fprintf(stderr, "Wrong length for simple type\n");
ERROR("Wrong length for simple type\n");
return False;
}
@ -441,7 +453,7 @@ BOOL mcs_io_edrq(STREAM s, MCS_EDRQ *edrq)
res = prs_io_uint8(s, &pkt_opcode);
if (pkt_opcode != opcode)
{
fprintf(stderr, "Expected EDrq, received %x\n", pkt_opcode);
ERROR("Expected EDrq, received %x\n", pkt_opcode);
return False;
}
@ -461,7 +473,7 @@ BOOL mcs_io_aurq(STREAM s, MCS_AURQ *aurq)
res = prs_io_uint8(s, &pkt_opcode);
if (pkt_opcode != opcode)
{
fprintf(stderr, "Expected AUrq, received %x\n", pkt_opcode);
ERROR("Expected AUrq, received %x\n", pkt_opcode);
return False;
}
@ -478,7 +490,7 @@ BOOL mcs_io_aucf(STREAM s, MCS_AUCF *aucf)
res = prs_io_uint8(s, &pkt_opcode);
if ((pkt_opcode & 0xfc) != opcode)
{
fprintf(stderr, "Expected AUcf, received %x\n", pkt_opcode);
ERROR("Expected AUcf, received %x\n", pkt_opcode);
return False;
}
@ -499,7 +511,7 @@ BOOL mcs_io_cjrq(STREAM s, MCS_CJRQ *cjrq)
res = prs_io_uint8(s, &pkt_opcode);
if (pkt_opcode != opcode)
{
fprintf(stderr, "Expected CJrq, received %x\n", pkt_opcode);
ERROR("Expected CJrq, received %x\n", pkt_opcode);
return False;
}
@ -519,7 +531,7 @@ BOOL mcs_io_cjcf(STREAM s, MCS_CJCF *cjcf)
res = prs_io_uint8(s, &pkt_opcode);
if ((pkt_opcode & 0xfc) != opcode)
{
fprintf(stderr, "Expected CJcf, received %x\n", pkt_opcode);
ERROR("Expected CJcf, received %x\n", pkt_opcode);
return False;
}
@ -543,18 +555,17 @@ BOOL mcs_io_data(STREAM s, MCS_DATA *dt, BOOL request)
res = prs_io_uint8(s, &pkt_opcode);
if (pkt_opcode != opcode)
{
fprintf(stderr, "Expected MCS data, received %x\n", pkt_opcode);
ERROR("Expected MCS data, received %x\n", pkt_opcode);
return False;
}
dt->length |= 0x8000;
res = res ? msb_io_uint16(s, &dt->userid) : False;
res = res ? msb_io_uint16(s, &dt->chanid) : False;
res = res ? prs_io_uint8 (s, &dt->flags ) : False;
if (s->marshall)
{
dt->length |= 0x8000;
res = res ? msb_io_uint16(s, &dt->length) : False;
}
else

2
misc.c
View File

@ -42,7 +42,6 @@ void *xrealloc(void *oldmem, int size)
return mem;
}
#if DEBUG
void dump_data(unsigned char *p, int len)
{
unsigned char *line = p;
@ -69,4 +68,3 @@ void dump_data(unsigned char *p, int len)
fputc('\n', stderr);
}
#endif

72
misc.h
View File

@ -19,20 +19,74 @@
*/
#define NUM_ELEMENTS(array) (sizeof(array) / sizeof(array[0]))
#define DEBUG(args...) fprintf(stderr, args);
#define ERROR(args...) fprintf(stderr, "ERROR: "args);
#define WARN(args...) fprintf(stderr, "WARNING: "args);
#define NOTIMP(args...) fprintf(stderr, "NOT IMPLEMENTED: "args);
#define MAX_COLORS 256
#define ROP2_S(rop3) (rop3 & 0xf)
#define ROP2_P(rop3) ((rop3 & 0x3) | ((rop3 & 0x30) >> 2))
typedef struct _colorentry
#define ROP2_COPY 0xc
#define ROP2_XOR 0x6
#define ROP2_AND 0x8
#define ROP2_OR 0xe
#define MAX_COLOURS 256
typedef struct _colourentry
{
uint8 red;
uint8 green;
uint8 blue;
uint8 green;
uint8 red;
} COLORENTRY;
} COLOURENTRY;
typedef struct _colormap
typedef struct _colourmap
{
uint16 ncolors;
COLORENTRY colors[MAX_COLORS];
uint16 ncolours;
COLOURENTRY colours[MAX_COLOURS];
} COLORMAP;
} COLOURMAP;
typedef struct _bounds
{
uint16 left;
uint16 top;
uint16 right;
uint16 bottom;
} BOUNDS;
typedef struct _pen
{
uint8 style;
uint8 width;
uint8 colour;
} PEN;
typedef struct _brush
{
uint8 xorigin;
uint8 yorigin;
uint8 style;
uint8 pattern[8];
} BRUSH;
typedef struct _font_glyph
{
uint16 baseline;
uint16 width;
uint16 height;
HBITMAP pixmap;
} FONT_GLYPH;
typedef struct _blob
{
void *data;
int size;
} BLOB;

10
parse.c
View File

@ -25,7 +25,7 @@ BOOL prs_io_uint8(STREAM s, uint8 *i)
{
if (s->offset + 1 > s->end)
{
fprintf(stderr, "Parse past end of buffer\n");
ERROR("Parse past end of buffer\n");
return False;
}
@ -43,7 +43,7 @@ BOOL prs_io_uint8s(STREAM s, uint8 *p, unsigned int length)
{
if (s->offset + length > s->end)
{
fprintf(stderr, "Parse past end of buffer\n");
ERROR("Parse past end of buffer\n");
return False;
}
@ -63,7 +63,7 @@ BOOL msb_io_uint16(STREAM s, uint16 *i)
if (offset + 2 > s->end)
{
fprintf(stderr, "Parse past end of buffer\n");
ERROR("Parse past end of buffer\n");
return False;
}
@ -85,7 +85,7 @@ BOOL lsb_io_uint16(STREAM s, uint16 *i)
if (offset + 2 > s->end)
{
fprintf(stderr, "Parse past end of buffer\n");
ERROR("Parse past end of buffer\n");
return False;
}
@ -107,7 +107,7 @@ BOOL lsb_io_uint32(STREAM s, uint32 *i)
if (offset + 4 > s->end)
{
fprintf(stderr, "Parse past end of buffer\n");
ERROR("Parse past end of buffer\n");
return False;
}

View File

@ -41,7 +41,10 @@ typedef struct connection
{
/* User interface */
HWINDOW wnd;
HBITMAP bmpcache[8];
HBITMAP bmpcache[3][600];
FONT_GLYPH fontcache[12][256];
BLOB textcache[256];
uint8 deskcache[0x38400];
/* Parsing layer */
struct stream in;
@ -61,3 +64,4 @@ typedef struct connection
#define PUSH_LAYER(s,v,l) { s.v = s.offset; s.offset += l; }
#define POP_LAYER(s,v) { s.offset = s.v; }
#define MARK_END(s) { s.end = s.offset; }
#define PRS_ERROR(s) (!(s)->error)

569
process.c Normal file
View File

@ -0,0 +1,569 @@
/*
rdesktop: A Remote Desktop Protocol client.
RDP message processing
Copyright (C) Matthew Chapman 1999-2000
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
/* Process incoming packets */
void rdp_main_loop(HCONN conn)
{
RDP_DATA_HEADER hdr;
RDP_ORDER_STATE os;
uint8 type;
memset(&os, 0, sizeof(os));
while (rdp_recv_pdu(conn, &type))
{
switch (type)
{
case RDP_PDU_DEMAND_ACTIVE:
process_demand_active(conn);
memset(&os, 0, sizeof(os));
break;
case RDP_PDU_DEACTIVATE:
break;
case RDP_PDU_DATA:
rdp_io_data_header(&conn->in, &hdr);
switch (hdr.data_pdu_type)
{
case RDP_DATA_PDU_UPDATE:
process_update_pdu(conn, &os);
break;
case RDP_DATA_PDU_POINTER:
process_pointer_pdu(conn);
break;
default:
NOTIMP("data PDU 0x%x\n",
hdr.data_pdu_type);
}
break;
default:
NOTIMP("PDU 0x%x\n", type);
}
}
}
/* Respond to a demand active PDU */
void process_demand_active(HCONN conn)
{
RDP_ACTIVE_PDU active;
uint8 type;
if (!rdp_io_active_pdu(&conn->in, &active, RDP_PDU_DEMAND_ACTIVE))
return;
DEBUG("DEMAND_ACTIVE(id=0x%x)\n", active.shareid);
rdp_send_confirm_active(conn, active.shareid, 640, 480);
rdp_send_synchronize(conn);
rdp_send_control(conn, RDP_CTL_COOPERATE);
rdp_send_control(conn, RDP_CTL_REQUEST_CONTROL);
rdp_recv_pdu(conn, &type); // RDP_PDU_SYNCHRONIZE
rdp_recv_pdu(conn, &type); // RDP_CTL_COOPERATE
rdp_recv_pdu(conn, &type); // RDP_CTL_GRANT_CONTROL
rdp_send_input(conn, RDP_INPUT_SYNCHRONIZE, 0, 0, 0);
rdp_send_fonts(conn, 1);
rdp_send_fonts(conn, 2);
rdp_recv_pdu(conn, &type); // RDP_PDU_UNKNOWN 0x28
}
/* Process a pointer PDU */
void process_pointer_pdu(HCONN conn)
{
RDP_POINTER_PDU pp;
if (!rdp_io_pointer_pdu(&conn->in, &pp))
return;
switch (pp.message)
{
case RDP_POINTER_MOVE:
ui_move_pointer(conn->wnd, pp.x, pp.y);
break;
default:
NOTIMP("pointer message 0x%x\n", pp.message);
}
}
/* Process an update PDU */
void process_update_pdu(HCONN conn, RDP_ORDER_STATE *os)
{
RDP_UPDATE_PDU update;
if (!rdp_io_update_pdu(&conn->in, &update))
return;
switch (update.update_type)
{
case RDP_UPDATE_ORDERS:
process_orders(conn, os);
break;
case RDP_UPDATE_PALETTE:
case RDP_UPDATE_SYNCHRONIZE:
break;
default:
NOTIMP("update 0x%x\n", update.update_type);
}
}
/* UPDATE PDUs */
/* Process an order */
void process_orders(HCONN conn, RDP_ORDER_STATE *os)
{
RDP_SECONDARY_ORDER rso;
uint32 present, num_orders;
uint8 order_flags;
int size, processed = 0;
BOOL delta;
lsb_io_uint32(&conn->in, &num_orders);
num_orders &= 0xffff; /* second word padding */
while (processed < num_orders)
{
if (!prs_io_uint8(&conn->in, &order_flags))
break;
if (!(order_flags & RDP_ORDER_STANDARD))
{
ERROR("Order parsing failed\n");
return;
}
if (order_flags & RDP_ORDER_SECONDARY)
{
if (!rdp_io_secondary_order(&conn->in, &rso))
break;
switch (rso.type)
{
case RDP_ORDER_RAW_BMPCACHE:
process_raw_bmpcache(conn);
break;
case RDP_ORDER_COLCACHE:
process_colcache(conn);
break;
case RDP_ORDER_BMPCACHE:
process_bmpcache(conn);
break;
case RDP_ORDER_FONTCACHE:
process_fontcache(conn);
break;
default:
NOTIMP("secondary order %d\n",
rso.type);
conn->in.offset += rso.length + 7;
}
}
else
{
if (order_flags & RDP_ORDER_CHANGE)
{
prs_io_uint8(&conn->in, &os->order_type);
}
switch (os->order_type)
{
case RDP_ORDER_TRIBLT:
case RDP_ORDER_TEXT2:
size = 3;
break;
case RDP_ORDER_PATBLT:
case RDP_ORDER_MEMBLT:
case RDP_ORDER_LINE:
size = 2;
break;
default:
size = 1;
}
rdp_io_present(&conn->in, &present, order_flags, size);
if (order_flags & RDP_ORDER_BOUNDS)
{
if (!(order_flags & RDP_ORDER_LASTBOUNDS))
rdp_io_bounds(&conn->in, &os->bounds);
ui_set_clip(conn->wnd, os->bounds.left,
os->bounds.top,
os->bounds.right - os->bounds.left + 1,
os->bounds.bottom - os->bounds.top + 1);
}
delta = order_flags & RDP_ORDER_DELTA;
switch (os->order_type)
{
case RDP_ORDER_DESTBLT:
process_destblt(conn, &os->destblt,
present, delta);
break;
case RDP_ORDER_PATBLT:
process_patblt(conn, &os->patblt,
present, delta);
break;
case RDP_ORDER_SCREENBLT:
process_screenblt(conn, &os->screenblt,
present, delta);
break;
case RDP_ORDER_LINE:
process_line(conn, &os->line,
present, delta);
break;
case RDP_ORDER_RECT:
process_rect(conn, &os->rect,
present, delta);
break;
case RDP_ORDER_DESKSAVE:
process_desksave(conn, &os->desksave,
present, delta);
break;
case RDP_ORDER_MEMBLT:
process_memblt(conn, &os->memblt,
present, delta);
break;
case RDP_ORDER_TRIBLT:
process_triblt(conn, &os->triblt,
present, delta);
break;
case RDP_ORDER_TEXT2:
process_text2(conn, &os->text2,
present, delta);
break;
default:
NOTIMP("order %d\n", os->order_type);
return;
}
if (order_flags & RDP_ORDER_BOUNDS)
ui_reset_clip(conn->wnd);
}
processed++;
}
if (conn->in.offset != conn->in.rdp_offset)
WARN("Order data remaining\n");
}
/* PRIMARY ORDERS */
/* Process a destination blt order */
void process_destblt(HCONN conn, DESTBLT_ORDER *os, uint32 present, BOOL delta)
{
if (!rdp_io_destblt_order(&conn->in, os, present, delta))
return;
DEBUG("DESTBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d)\n",
os->opcode, os->x, os->y, os->cx, os->cy);
ui_destblt(conn->wnd, ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy);
}
/* Process a pattern blt order */
void process_patblt(HCONN conn, PATBLT_ORDER *os, uint32 present, BOOL delta)
{
if (!rdp_io_patblt_order(&conn->in, os, present, delta))
return;
DEBUG("PATBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,bs=%d,bg=0x%x,fg=0x%x)\n",
os->opcode, os->x, os->y, os->cx, os->cy,
os->brush.style, os->bgcolour, os->fgcolour);
ui_patblt(conn->wnd, ROP2_P(os->opcode), os->x, os->y, os->cx, os->cy,
&os->brush, os->bgcolour, os->fgcolour);
}
/* Process a screen blt order */
void process_screenblt(HCONN conn, SCREENBLT_ORDER *os, uint32 present, BOOL delta)
{
if (!rdp_io_screenblt_order(&conn->in, os, present, delta))
return;
DEBUG("SCREENBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,srcx=%d,srcy=%d)\n",
os->opcode, os->x, os->y, os->cx, os->cy, os->srcx, os->srcy);
ui_screenblt(conn->wnd, ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy,
os->srcx, os->srcy);
}
/* Process a line order */
void process_line(HCONN conn, LINE_ORDER *os, uint32 present, BOOL delta)
{
if (!rdp_io_line_order(&conn->in, os, present, delta))
return;
DEBUG("LINE(op=0x%x,sx=%d,sy=%d,dx=%d,dx=%d,fg=0x%x)\n",
os->opcode, os->startx, os->starty, os->endx, os->endy,
os->pen.colour);
if (os->opcode < 0x01 || os->opcode > 0x10)
{
ERROR("Bad ROP2 opcode 0x%x\n", os->opcode);
return;
}
ui_line(conn->wnd, os->opcode-1, os->startx, os->starty,
os->endx, os->endy, &os->pen);
}
/* Process an opaque rectangle order */
void process_rect(HCONN conn, RECT_ORDER *os, uint32 present, BOOL delta)
{
if (!rdp_io_rect_order(&conn->in, os, present, delta))
return;
DEBUG("RECT(x=%d,y=%d,cx=%d,cy=%d,fg=0x%x)\n",
os->x, os->y, os->cx, os->cy, os->colour);
ui_rect(conn->wnd, os->x, os->y, os->cx, os->cy, os->colour);
}
/* Process a desktop save order */
void process_desksave(HCONN conn, DESKSAVE_ORDER *os, uint32 present, BOOL delta)
{
int width, height;
uint8 *data;
if (!rdp_io_desksave_order(&conn->in, os, present, delta))
return;
DEBUG("DESKSAVE(l=%d,t=%d,r=%d,b=%d,off=%d,op=%d)\n",
os->left, os->top, os->right, os->bottom, os->offset,
os->action);
data = conn->deskcache + os->offset;
width = os->right - os->left + 1;
height = os->bottom - os->top + 1;
if (os->action == 0)
{
ui_desktop_save(conn->wnd, data, os->left, os->top,
width, height);
}
else
{
ui_desktop_restore(conn->wnd, data, os->left, os->top,
width, height);
}
}
/* Process a memory blt order */
void process_memblt(HCONN conn, MEMBLT_ORDER *os, uint32 present, BOOL delta)
{
HBITMAP bitmap;
if (!rdp_io_memblt_order(&conn->in, os, present, delta))
return;
DEBUG("MEMBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,id=%d,idx=%d)\n",
os->opcode, os->x, os->y, os->cx, os->cy, os->cache_id,
os->cache_idx);
bitmap = cache_get_bitmap(conn, os->cache_id, os->cache_idx);
if (bitmap == NULL)
return;
ui_memblt(conn->wnd, ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy,
bitmap, os->srcx, os->srcy);
}
/* Process a 3-way blt order */
void process_triblt(HCONN conn, TRIBLT_ORDER *os, uint32 present, BOOL delta)
{
HBITMAP bitmap;
if (!rdp_io_triblt_order(&conn->in, os, present, delta))
return;
DEBUG("TRIBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,id=%d,idx=%d,bs=%d,bg=0x%x,fg=0x%x)\n",
os->opcode, os->x, os->y, os->cx, os->cy, os->cache_id,
os->cache_idx, os->brush.style, os->bgcolour, os->fgcolour);
bitmap = cache_get_bitmap(conn, os->cache_id, os->cache_idx);
if (bitmap == NULL)
return;
ui_triblt(conn->wnd, os->opcode, os->x, os->y, os->cx, os->cy,
bitmap, os->srcx, os->srcy,
&os->brush, os->bgcolour, os->fgcolour);
}
/* Process a text order */
void process_text2(HCONN conn, TEXT2_ORDER *os, uint32 present, BOOL delta)
{
BLOB *entry;
int i;
if (!rdp_io_text2_order(&conn->in, os, present, delta))
return;
DEBUG("TEXT2(x=%d,y=%d,cl=%d,ct=%d,cr=%d,cb=%d,bl=%d,bt=%d,bb=%d,br=%d,fg=0x%x,bg=0x%x,font=%d,fl=0x%x,mix=%d,unk=0x%x,n=%d)\n",
os->x, os->y, os->clipleft, os->cliptop, os->clipright,
os->clipbottom, os->boxleft, os->boxtop, os->boxright,
os->boxbottom, os->fgcolour, os->bgcolour, os->font,
os->flags, os->mixmode, os->unknown, os->length);
fprintf(stderr, "Text: ");
for (i = 0; i < os->length; i++)
fprintf(stderr, "%02x ", os->text[i]);
fprintf(stderr, "\n");
/* Process special cache strings */
if ((os->length == 2) && (os->text[0] == 0xfe))
{
entry = cache_get_text(conn, os->text[1]);
if (entry == NULL)
return;
memcpy(os->text, entry->data, entry->size);
os->length = entry->size;
}
else if ((os->length >= 3) && (os->text[os->length-3] == 0xff))
{
os->length -= 3;
cache_put_text(conn, os->text[os->length+1],
os->text, os->length);
}
ui_draw_text(conn->wnd, os->font, os->flags, os->mixmode,
os->x, os->y, os->boxleft, os->boxtop,
os->boxright - os->boxleft,
os->boxbottom - os->boxtop,
os->bgcolour, os->fgcolour, os->text, os->length);
}
/* SECONDARY ORDERS */
/* Process a raw bitmap cache order */
void process_raw_bmpcache(HCONN conn)
{
RDP_RAW_BMPCACHE_ORDER order;
HBITMAP bitmap;
if (!rdp_io_raw_bmpcache_order(&conn->in, &order))
return;
DEBUG("RAW_BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d)\n",
order.width, order.height, order.cache_id, order.cache_idx);
bitmap = ui_create_bitmap(conn->wnd, order.width, order.height,
order.data);
cache_put_bitmap(conn, order.cache_id, order.cache_idx, bitmap);
}
/* Process a bitmap cache order */
void process_bmpcache(HCONN conn)
{
RDP_BMPCACHE_ORDER order;
HBITMAP bitmap;
char *bmpdata;
if (!rdp_io_bmpcache_order(&conn->in, &order))
return;
DEBUG("BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d)\n",
order.width, order.height, order.cache_id, order.cache_idx);
bmpdata = malloc(order.width * order.height);
if (bitmap_decompress(bmpdata, order.width, order.height,
order.data, order.size))
{
bitmap = ui_create_bitmap(conn->wnd, order.width, order.height,
bmpdata);
cache_put_bitmap(conn, order.cache_id, order.cache_idx, bitmap);
}
free(bmpdata);
}
/* Process a colourmap cache order */
void process_colcache(HCONN conn)
{
RDP_COLCACHE_ORDER order;
HCOLOURMAP map;
if (!rdp_io_colcache_order(&conn->in, &order))
return;
DEBUG("COLCACHE(id=%d,n=%d)\n", order.cache_id, order.map.ncolours);
map = ui_create_colourmap(conn->wnd, &order.map);
ui_set_colourmap(conn->wnd, map);
}
/* Process a font cache order */
void process_fontcache(HCONN conn)
{
RDP_FONTCACHE_ORDER order;
RDP_FONT_GLYPH *glyph;
HGLYPH bitmap;
int i;
if (!rdp_io_fontcache_order(&conn->in, &order))
return;
DEBUG("FONTCACHE(font=%d,n=%d)\n", order.font, order.nglyphs);
for (i = 0; i < order.nglyphs; i++)
{
glyph = &order.glyphs[i];
bitmap = ui_create_glyph(conn->wnd, glyph->width,
glyph->height, glyph->data);
cache_put_font(conn, order.font, glyph->character,
glyph->baseline, glyph->width, glyph->height,
bitmap);
}
}

264
proto.h
View File

@ -1,50 +1,27 @@
/*
rdesktop: A Remote Desktop Protocol client.
Function prototypes
Copyright (C) Matthew Chapman 1999-2000
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Parsing layer */
BOOL prs_io_uint8(STREAM s, uint8 *i);
BOOL prs_io_uint8s(STREAM s, uint8 *p, unsigned int length);
BOOL msb_io_uint16(STREAM s, uint16 *i);
BOOL lsb_io_uint16(STREAM s, uint16 *i);
BOOL lsb_io_uint32(STREAM s, uint32 *i);
/* TCP layer */
HCONN tcp_connect(char *server);
void tcp_disconnect(HCONN conn);
BOOL tcp_send(HCONN conn);
BOOL tcp_recv(HCONN conn, int length);
/* ISO layer */
/* bitmap.c */
BOOL bitmap_decompress(unsigned char *output, int width, int height, unsigned char *input, int size);
/* cache.c */
HBITMAP cache_get_bitmap(HCONN conn, uint8 cache_id, uint16 cache_idx);
void cache_put_bitmap(HCONN conn, uint8 cache_id, uint16 cache_idx, HBITMAP bitmap);
FONT_GLYPH *cache_get_font(HCONN conn, uint8 font, uint16 character);
void cache_put_font(HCONN conn, uint8 font, uint32 character, uint16 baseline, uint16 width, uint16 height, HGLYPH pixmap);
BLOB *cache_get_text(HCONN conn, uint8 cache_id);
void cache_put_text(HCONN conn, uint8 cache_id, void *data, int length);
/* client.c */
int main(int argc, char *argv[]);
/* iso.c */
HCONN iso_connect(char *server);
void iso_disconnect(HCONN conn);
BOOL iso_send_msg(HCONN conn, uint8 code);
BOOL iso_recv_msg(HCONN conn, uint8 *code);
void iso_init(struct connection *conn);
BOOL iso_send(HCONN conn);
BOOL iso_recv(HCONN conn);
BOOL iso_send(HCONN conn);
void iso_make_tpkt(TPKT *tpkt, int length);
BOOL iso_io_tpkt(STREAM s, TPKT *tpkt);
void iso_make_tpdu(TPDU *tpdu, uint8 code);
BOOL iso_io_tpdu(STREAM s, TPDU *tpdu);
/* MCS layer */
/* mcs.c */
HCONN mcs_connect(char *server);
BOOL mcs_join_channel(HCONN conn, uint16 chanid);
void mcs_disconnect(HCONN conn);
@ -54,13 +31,12 @@ void mcs_send_aurq(HCONN conn);
void mcs_send_cjrq(HCONN conn, uint16 chanid);
void mcs_init_data(HCONN conn);
void mcs_send_data(HCONN conn, uint16 chanid, BOOL request);
int mcs_recv(HCONN conn, BOOL request);
void mcs_make_domain_params(DOMAIN_PARAMS *dp, uint16 max_channels,
uint16 max_users, uint16 max_tokens, uint16 max_pdusize);
BOOL mcs_recv(HCONN conn, BOOL request);
void mcs_make_domain_params(DOMAIN_PARAMS *dp, uint16 max_channels, uint16 max_users, uint16 max_tokens, uint16 max_pdusize);
void mcs_make_connect_initial(MCS_CONNECT_INITIAL *mci);
BOOL ber_io_header(STREAM s, BOOL islong, int tagval, int *length);
BOOL ber_io_octet_string(STREAM s, OCTET_STRING *os);
BOOL ber_io_integer(STREAM s, uint16 *i);
BOOL ber_io_integer(STREAM s, uint16 *word_int);
BOOL ber_io_uint8(STREAM s, uint8 *i, int tagval);
BOOL mcs_io_domain_params(STREAM s, DOMAIN_PARAMS *dp);
BOOL mcs_io_connect_initial(STREAM s, MCS_CONNECT_INITIAL *mci);
@ -71,86 +47,138 @@ BOOL mcs_io_aucf(STREAM s, MCS_AUCF *aucf);
BOOL mcs_io_cjrq(STREAM s, MCS_CJRQ *cjrq);
BOOL mcs_io_cjcf(STREAM s, MCS_CJCF *cjcf);
BOOL mcs_io_data(STREAM s, MCS_DATA *dt, BOOL request);
/* RDP layer */
HCONN rdp_connect(char *server);
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_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_send_cert(HCONN conn);
void rdp_send_confirm_active(HCONN conn);
void rdp_send_control(HCONN conn, uint16 action);
void rdp_send_synchronize(HCONN conn);
void rdp_send_fonts(HCONN conn, uint16 seqno);
void rdp_send_input(HCONN conn);
BOOL rdp_recv_pdu(HCONN conn, uint8 *type);
void rdp_disconnect(HCONN conn);
void rdp_make_header(RDP_HEADER *hdr, uint16 length, uint16 pdu_type,
uint16 userid);
void rdp_make_data_header(RDP_DATA_HEADER *hdr, uint32 shareid,
uint16 length, uint16 data_pdu_type);
void rdp_make_general_caps(RDP_GENERAL_CAPS *caps);
void rdp_make_bitmap_caps(RDP_BITMAP_CAPS *caps);
void rdp_make_order_caps(RDP_ORDER_CAPS *caps);
void rdp_make_bmpcache_caps(RDP_BMPCACHE_CAPS *caps);
void rdp_make_control_caps(RDP_CONTROL_CAPS *caps);
void rdp_make_activate_caps(RDP_ACTIVATE_CAPS *caps);
void rdp_make_pointer_caps(RDP_POINTER_CAPS *caps);
void rdp_make_share_caps(RDP_SHARE_CAPS *caps, uint16 userid);
void rdp_make_colcache_caps(RDP_COLCACHE_CAPS *caps);
void rdp_make_active_pdu(RDP_ACTIVE_PDU *pdu, uint32 shareid, uint16 userid);
void rdp_make_control_pdu(RDP_CONTROL_PDU *pdu, uint16 action);
void rdp_make_synchronize_pdu(RDP_SYNCHRONIZE_PDU *pdu, uint16 userid);
void rdp_make_font_pdu(RDP_FONT_PDU *pdu, uint16 seqno);
void rdp_make_input_pdu(RDP_INPUT_PDU *pdu);
BOOL rdp_io_header(STREAM s, RDP_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_bitmap_caps(STREAM s, RDP_BITMAP_CAPS *caps);
BOOL rdp_io_order_caps(STREAM s, RDP_ORDER_CAPS *caps);
BOOL rdp_io_bmpcache_info(STREAM s, RDP_BMPCACHE_INFO *info);
BOOL rdp_io_bmpcache_caps(STREAM s, RDP_BMPCACHE_CAPS *caps);
BOOL rdp_io_control_caps(STREAM s, RDP_CONTROL_CAPS *caps);
BOOL rdp_io_activate_caps(STREAM s, RDP_ACTIVATE_CAPS *caps);
BOOL rdp_io_pointer_caps(STREAM s, RDP_POINTER_CAPS *caps);
BOOL rdp_io_share_caps(STREAM s, RDP_SHARE_CAPS *caps);
BOOL rdp_io_colcache_caps(STREAM s, RDP_COLCACHE_CAPS *caps);
BOOL rdp_io_active_pdu(STREAM s, RDP_ACTIVE_PDU *pdu, int pdutype);
BOOL rdp_io_control_pdu(STREAM s, RDP_CONTROL_PDU *pdu);
BOOL rdp_io_synchronize_pdu(STREAM s, RDP_SYNCHRONIZE_PDU *pdu);
BOOL rdp_io_input_event(STREAM s, RDP_INPUT_EVENT *evt);
BOOL rdp_io_input_pdu(STREAM s, RDP_INPUT_PDU *pdu);
BOOL rdp_io_font_info(STREAM s, RDP_FONT_INFO *font);
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_secondary_order(STREAM s, RDP_SECONDARY_ORDER *rso);
BOOL rdp_io_bitmap_header(STREAM s, RDP_BITMAP_HEADER *rdh);
BOOL rdp_io_pointer(STREAM s, RDP_POINTER *ptr);
/* Utility routines */
/* misc.c */
void *xmalloc(int size);
void *xrealloc(void *oldmem, int size);
void dump_data(unsigned char *p, int len);
BOOL bitmap_decompress(unsigned char *output, int width, int height,
unsigned char *input, int size);
/* User interface routines */
HWINDOW ui_create_window(int width, int height);
/* parse.c */
BOOL prs_io_uint8(STREAM s, uint8 *i);
BOOL prs_io_uint8s(STREAM s, uint8 *p, unsigned int length);
BOOL msb_io_uint16(STREAM s, uint16 *i);
BOOL lsb_io_uint16(STREAM s, uint16 *i);
BOOL lsb_io_uint32(STREAM s, uint32 *i);
/* process.c */
void rdp_main_loop(HCONN conn);
void process_demand_active(HCONN conn);
void process_pointer_pdu(HCONN conn);
void process_update_pdu(HCONN conn, RDP_ORDER_STATE *os);
void process_orders(HCONN conn, RDP_ORDER_STATE *os);
void process_destblt(HCONN conn, DESTBLT_ORDER *os, uint32 present, BOOL delta);
void process_patblt(HCONN conn, PATBLT_ORDER *os, uint32 present, BOOL delta);
void process_screenblt(HCONN conn, SCREENBLT_ORDER *os, uint32 present, BOOL delta);
void process_line(HCONN conn, LINE_ORDER *os, uint32 present, BOOL delta);
void process_rect(HCONN conn, RECT_ORDER *os, uint32 present, BOOL delta);
void process_desksave(HCONN conn, DESKSAVE_ORDER *os, uint32 present, BOOL delta);
void process_memblt(HCONN conn, MEMBLT_ORDER *os, uint32 present, BOOL delta);
void process_triblt(HCONN conn, TRIBLT_ORDER *os, uint32 present, BOOL delta);
void process_text2(HCONN conn, TEXT2_ORDER *os, uint32 present, BOOL delta);
void process_raw_bmpcache(HCONN conn);
void process_bmpcache(HCONN conn);
void process_colcache(HCONN conn);
void process_fontcache(HCONN conn);
/* rdp.c */
HCONN rdp_connect(char *server, int width, int height);
void rdp_establish_key(HCONN conn);
void rdp_establish_key_e1(HCONN conn);
void rdp_establish_key_e2(HCONN conn);
void rdp_send_cert(HCONN conn);
void rdp_init(HCONN conn);
void rdp_send(HCONN conn, uint16 pdu_type);
void rdp_init_data(HCONN conn);
void rdp_send_data(HCONN conn, uint16 data_pdu_type);
void rdp_send_confirm_active(HCONN conn, uint32 shareid, int width, int height);
void rdp_send_synchronize(HCONN conn);
void rdp_send_control(HCONN conn, uint16 action);
void rdp_send_fonts(HCONN conn, uint16 seqno);
void rdp_send_input(HCONN conn, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2);
BOOL rdp_recv_pdu(HCONN conn, uint8 *type);
void rdp_disconnect(HCONN conn);
void rdp_make_header(RDP_HEADER *hdr, uint16 length, uint16 pdu_type, uint16 userid);
BOOL rdp_io_header(STREAM s, RDP_HEADER *hdr);
void rdp_make_data_header(RDP_DATA_HEADER *hdr, uint32 shareid, uint16 length, uint16 data_pdu_type);
BOOL rdp_io_data_header(STREAM s, RDP_DATA_HEADER *hdr);
BOOL rdp_io_present(STREAM s, uint32 *present, uint8 flags, int size);
BOOL rdp_io_coord(STREAM s, uint16 *coord, BOOL delta);
BOOL rdp_io_colour(STREAM s, uint8 *colour);
BOOL rdp_io_colourmap(STREAM s, COLOURMAP *colours);
BOOL rdp_io_bounds(STREAM s, BOUNDS *bounds);
BOOL rdp_io_pen(STREAM s, PEN *pen, uint32 present);
BOOL rdp_io_brush(STREAM s, BRUSH *brush, uint32 present);
void rdp_make_active_pdu(RDP_ACTIVE_PDU *pdu, uint32 shareid, uint16 userid, int width, int height);
BOOL rdp_io_active_pdu(STREAM s, RDP_ACTIVE_PDU *pdu, int pdutype);
void rdp_make_control_pdu(RDP_CONTROL_PDU *pdu, uint16 action);
BOOL rdp_io_control_pdu(STREAM s, RDP_CONTROL_PDU *pdu);
void rdp_make_synchronise_pdu(RDP_SYNCHRONISE_PDU *pdu, uint16 userid);
BOOL rdp_io_synchronise_pdu(STREAM s, RDP_SYNCHRONISE_PDU *pdu);
BOOL rdp_io_input_event(STREAM s, RDP_INPUT_EVENT *evt);
void rdp_make_input_pdu(RDP_INPUT_PDU *pdu, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2);
BOOL rdp_io_input_pdu(STREAM s, RDP_INPUT_PDU *pdu);
void rdp_make_font_pdu(RDP_FONT_PDU *pdu, uint16 seqno);
BOOL rdp_io_font_info(STREAM s, RDP_FONT_INFO *font);
BOOL rdp_io_font_pdu(STREAM s, RDP_FONT_PDU *pdu);
BOOL rdp_io_pointer_pdu(STREAM s, RDP_POINTER_PDU *ptr);
BOOL rdp_io_update_pdu(STREAM s, RDP_UPDATE_PDU *pdu);
BOOL rdp_io_destblt_order(STREAM s, DESTBLT_ORDER *os, uint32 present, BOOL delta);
BOOL rdp_io_patblt_order(STREAM s, PATBLT_ORDER *os, uint32 present, BOOL delta);
BOOL rdp_io_screenblt_order(STREAM s, SCREENBLT_ORDER *os, uint32 present, BOOL delta);
BOOL rdp_io_line_order(STREAM s, LINE_ORDER *os, uint32 present, BOOL delta);
BOOL rdp_io_rect_order(STREAM s, RECT_ORDER *os, uint32 present, BOOL delta);
BOOL rdp_io_desksave_order(STREAM s, DESKSAVE_ORDER *os, uint32 present, BOOL delta);
BOOL rdp_io_memblt_order(STREAM s, MEMBLT_ORDER *os, uint32 present, BOOL delta);
BOOL rdp_io_triblt_order(STREAM s, TRIBLT_ORDER *os, uint32 present, BOOL delta);
BOOL rdp_io_text2_order(STREAM s, TEXT2_ORDER *os, uint32 present, BOOL delta);
BOOL rdp_io_secondary_order(STREAM s, RDP_SECONDARY_ORDER *rso);
BOOL rdp_io_raw_bmpcache_order(STREAM s, RDP_RAW_BMPCACHE_ORDER *rbo);
BOOL rdp_io_bmpcache_order(STREAM s, RDP_BMPCACHE_ORDER *rbo);
BOOL rdp_io_colcache_order(STREAM s, RDP_COLCACHE_ORDER *colours);
BOOL rdp_io_fontcache_order(STREAM s, RDP_FONTCACHE_ORDER *font);
void rdp_make_general_caps(RDP_GENERAL_CAPS *caps);
BOOL rdp_io_general_caps(STREAM s, RDP_GENERAL_CAPS *caps);
void rdp_make_bitmap_caps(RDP_BITMAP_CAPS *caps, int width, int height);
BOOL rdp_io_bitmap_caps(STREAM s, RDP_BITMAP_CAPS *caps);
void rdp_make_order_caps(RDP_ORDER_CAPS *caps);
BOOL rdp_io_order_caps(STREAM s, RDP_ORDER_CAPS *caps);
void rdp_make_bmpcache_caps(RDP_BMPCACHE_CAPS *caps);
BOOL rdp_io_bmpcache_info(STREAM s, RDP_BMPCACHE_INFO *info);
BOOL rdp_io_bmpcache_caps(STREAM s, RDP_BMPCACHE_CAPS *caps);
void rdp_make_control_caps(RDP_CONTROL_CAPS *caps);
BOOL rdp_io_control_caps(STREAM s, RDP_CONTROL_CAPS *caps);
void rdp_make_activate_caps(RDP_ACTIVATE_CAPS *caps);
BOOL rdp_io_activate_caps(STREAM s, RDP_ACTIVATE_CAPS *caps);
void rdp_make_pointer_caps(RDP_POINTER_CAPS *caps);
BOOL rdp_io_pointer_caps(STREAM s, RDP_POINTER_CAPS *caps);
void rdp_make_share_caps(RDP_SHARE_CAPS *caps, uint16 userid);
BOOL rdp_io_share_caps(STREAM s, RDP_SHARE_CAPS *caps);
void rdp_make_colcache_caps(RDP_COLCACHE_CAPS *caps);
BOOL rdp_io_colcache_caps(STREAM s, RDP_COLCACHE_CAPS *caps);
BOOL rdp_io_unknown_caps(STREAM s, void *caps);
/* tcp.c */
HCONN tcp_connect(char *server);
void tcp_disconnect(HCONN conn);
BOOL tcp_send(HCONN conn);
BOOL tcp_recv(HCONN conn, int length);
/* xwin.c */
HWINDOW ui_create_window(HCONN conn, int width, int height);
void ui_destroy_window(HWINDOW wnd);
void ui_process_events(HWINDOW wnd, HCONN conn);
void ui_move_pointer(HWINDOW wnd, int x, int y);
HBITMAP ui_create_bitmap(HWINDOW wnd, int width, int height, uint8 *data);
void ui_destroy_bitmap(HWINDOW wnd, HBITMAP bmp);
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);
HGLYPH ui_create_glyph(HWINDOW wnd, int width, int height, uint8 *data);
void ui_destroy_glyph(HWINDOW wnd, HGLYPH glyph);
HCOLOURMAP ui_create_colourmap(HWINDOW wnd, COLOURMAP *colours);
void ui_destroy_colourmap(HWINDOW wnd, HCOLOURMAP map);
void ui_set_colourmap(HWINDOW wnd, HCOLOURMAP map);
void ui_set_clip(HWINDOW wnd, int x, int y, int cx, int cy);
void ui_reset_clip(HWINDOW wnd);
void ui_destblt(HWINDOW wnd, uint8 opcode, int x, int y, int cx, int cy);
void ui_patblt(HWINDOW wnd, uint8 opcode, int x, int y, int cx, int cy, BRUSH *brush, int bgcolour, int fgcolour);
void ui_screenblt(HWINDOW wnd, uint8 opcode, int x, int y, int cx, int cy, int srcx, int srcy);
void ui_memblt(HWINDOW wnd, uint8 opcode, int x, int y, int cx, int cy, HBITMAP src, int srcx, int srcy);
void ui_triblt(HWINDOW wnd, uint8 opcode, int x, int y, int cx, int cy, HBITMAP src, int srcx, int srcy, BRUSH *brush, int bgcolour, int fgcolour);
void ui_line(HWINDOW wnd, uint8 opcode, int startx, int starty, int endx, int endy, PEN *pen);
void ui_rect(HWINDOW wnd, int x, int y, int cx, int cy, int colour);
void ui_draw_glyph(HWINDOW wnd, int mixmode, int x, int y, int cx, int cy, HGLYPH glyph, int srcx, int srcy, int bgcolour, int fgcolour);
void ui_draw_text(HWINDOW wnd, uint8 font, uint8 flags, int mixmode, int x, int y, int boxx, int boxy, int boxcx, int boxcy, int bgcolour, int fgcolour, uint8 *text, uint8 length);
void ui_desktop_save(HWINDOW wnd, uint8 *data, int x, int y, int cx, int cy);
void ui_desktop_restore(HWINDOW wnd, uint8 *data, int x, int y, int cx, int cy);

1701
rdp.c

File diff suppressed because it is too large Load Diff

225
rdp.h
View File

@ -22,6 +22,7 @@ enum RDP_PDU_TYPE
{
RDP_PDU_DEMAND_ACTIVE = 1,
RDP_PDU_CONFIRM_ACTIVE = 3,
RDP_PDU_DEACTIVATE = 6,
RDP_PDU_DATA = 7
};
@ -218,12 +219,12 @@ typedef struct _RDP_ACTIVE_PDU
} RDP_ACTIVE_PDU;
typedef struct _RDP_SYNCHRONIZE_PDU
typedef struct _RDP_SYNCHRONISE_PDU
{
uint16 type; // 1
uint16 userid;
} RDP_SYNCHRONIZE_PDU;
} RDP_SYNCHRONISE_PDU;
#define RDP_CTL_REQUEST_CONTROL 1
#define RDP_CTL_GRANT_CONTROL 2
@ -241,13 +242,13 @@ typedef struct _RDP_CONTROL_PDU
#define RDP_INPUT_SYNCHRONIZE 0
#define RDP_INPUT_CODEPOINT 1
#define RDP_INPUT_VIRTKEY 2
#define RDP_INPUT_UNKNOWN 4
#define RDP_INPUT_SCANCODE 4
#define RDP_INPUT_MOUSE 0x8001
#define KBD_FLAG_RIGHT 0x0001
#define KBD_FLAG_QUIET 0x1000
#define KBD_FLAG_DOWN 0x4000
#define KBD_FLAG_RELEASE 0x8000
#define KBD_FLAG_UP 0x8000
#define MOUSE_FLAG_MOVE 0x0800
#define MOUSE_FLAG_BUTTON1 0x1000
@ -262,11 +263,8 @@ typedef struct _RDP_INPUT_EVENT
uint32 event_time;
uint16 message_type;
uint16 device_flags;
uint16 kbd_keycode;
uint16 mouse_x;
uint16 mouse_y;
uint16 param1;
uint16 param2;
} RDP_INPUT_EVENT;
@ -309,7 +307,55 @@ typedef struct _RDP_FONT_PDU
#define RDP_UPDATE_PALETTE 2
#define RDP_UPDATE_SYNCHRONIZE 3
typedef struct _OPAQUE_RECT_ORDER
typedef struct _DESTBLT_ORDER
{
uint16 x;
uint16 y;
uint16 cx;
uint16 cy;
uint8 opcode;
} DESTBLT_ORDER;
typedef struct _PATBLT_ORDER
{
uint16 x;
uint16 y;
uint16 cx;
uint16 cy;
uint8 opcode;
uint8 bgcolour;
uint8 fgcolour;
BRUSH brush;
} PATBLT_ORDER;
typedef struct _SCREENBLT_ORDER
{
uint16 x;
uint16 y;
uint16 cx;
uint16 cy;
uint8 opcode;
uint16 srcx;
uint16 srcy;
} SCREENBLT_ORDER;
typedef struct _LINE_ORDER
{
uint16 mixmode;
uint16 startx;
uint16 starty;
uint16 endx;
uint16 endy;
uint8 bgcolour;
uint8 opcode;
PEN pen;
} LINE_ORDER;
typedef struct _RECT_ORDER
{
uint16 x;
uint16 y;
@ -317,26 +363,97 @@ typedef struct _OPAQUE_RECT_ORDER
uint16 cy;
uint8 colour;
} OPAQUE_RECT_ORDER;
} RECT_ORDER;
typedef struct _MEMBLT_ORDER
typedef struct _DESKSAVE_ORDER
{
uint32 offset;
uint16 left;
uint16 top;
uint16 right;
uint16 bottom;
uint8 action;
} DESKSAVE_ORDER;
typedef struct _TRIBLT_ORDER
{
uint8 colour_table;
uint8 cache_id;
uint16 x;
uint16 y;
uint16 cx;
uint16 cy;
uint8 opcode;
uint16 srcx;
uint16 srcy;
uint8 bgcolour;
uint8 fgcolour;
BRUSH brush;
uint16 cache_idx;
uint16 unknown;
} TRIBLT_ORDER;
typedef struct _MEMBLT_ORDER
{
uint8 colour_table;
uint8 cache_id;
uint16 x;
uint16 y;
uint16 cx;
uint16 cy;
uint8 opcode;
uint16 srcx;
uint16 srcy;
uint16 cache_idx;
} MEMBLT_ORDER;
#define MAX_TEXT 256
#define MIX_TRANSPARENT 0
#define MIX_OPAQUE 1
#define TEXT2_IMPLICIT_X 0x20
typedef struct _TEXT2_ORDER
{
uint8 font;
uint8 flags;
uint8 mixmode;
uint8 unknown;
uint8 fgcolour;
uint8 bgcolour;
uint16 clipleft;
uint16 cliptop;
uint16 clipright;
uint16 clipbottom;
uint16 boxleft;
uint16 boxtop;
uint16 boxright;
uint16 boxbottom;
uint16 x;
uint16 y;
uint8 length;
uint8 text[MAX_TEXT];
} TEXT2_ORDER;
typedef struct _RDP_ORDER_STATE
{
uint8 order_type;
BOUNDS bounds;
OPAQUE_RECT_ORDER opaque_rect;
DESTBLT_ORDER destblt;
PATBLT_ORDER patblt;
SCREENBLT_ORDER screenblt;
LINE_ORDER line;
RECT_ORDER rect;
DESKSAVE_ORDER desksave;
MEMBLT_ORDER memblt;
TRIBLT_ORDER triblt;
TEXT2_ORDER text2;
} RDP_ORDER_STATE;
@ -347,22 +464,34 @@ typedef struct _RDP_UPDATE_PDU
} RDP_UPDATE_PDU;
#define RDP_ORDER_STANDARD 1
#define RDP_ORDER_SECONDARY 2
#define RDP_ORDER_BOUNDS 4
#define RDP_ORDER_CHANGE 8
#define RDP_ORDER_DELTA 16
#define RDP_ORDER_REPEAT 64
#define RDP_ORDER_STANDARD 0x01
#define RDP_ORDER_SECONDARY 0x02
#define RDP_ORDER_BOUNDS 0x04
#define RDP_ORDER_CHANGE 0x08
#define RDP_ORDER_DELTA 0x10
#define RDP_ORDER_LASTBOUNDS 0x20
#define RDP_ORDER_SMALL 0x40
#define RDP_ORDER_TINY 0x80
enum RDP_ORDER_TYPE
{
RDP_ORDER_OPAQUE_RECT = 10,
RDP_ORDER_MEMBLT = 13
RDP_ORDER_DESTBLT = 0,
RDP_ORDER_PATBLT = 1,
RDP_ORDER_SCREENBLT = 2,
RDP_ORDER_LINE = 9,
RDP_ORDER_RECT = 10,
RDP_ORDER_DESKSAVE = 11,
RDP_ORDER_MEMBLT = 13,
RDP_ORDER_TRIBLT = 14,
RDP_ORDER_TEXT2 = 27
};
enum RDP_SECONDARY_ORDER_TYPE
{
RDP_ORDER_BMPCACHE = 2
RDP_ORDER_RAW_BMPCACHE = 0,
RDP_ORDER_COLCACHE = 1,
RDP_ORDER_BMPCACHE = 2,
RDP_ORDER_FONTCACHE = 3
};
typedef struct _RDP_SECONDARY_ORDER
@ -373,7 +502,20 @@ typedef struct _RDP_SECONDARY_ORDER
} RDP_SECONDARY_ORDER;
typedef struct _RDP_BITMAP_HEADER
typedef struct _RDP_RAW_BMPCACHE_ORDER
{
uint8 cache_id;
uint8 pad1;
uint8 width;
uint8 height;
uint8 bpp;
uint16 bufsize;
uint16 cache_idx;
uint8 *data;
} RDP_RAW_BMPCACHE_ORDER;
typedef struct _RDP_BMPCACHE_ORDER
{
uint8 cache_id;
uint8 pad1;
@ -386,17 +528,48 @@ typedef struct _RDP_BITMAP_HEADER
uint16 size;
uint16 row_size;
uint16 final_size;
uint8 *data;
} RDP_BITMAP_HEADER;
} RDP_BMPCACHE_ORDER;
#define MAX_GLYPH 32
typedef struct _RDP_FONT_GLYPH
{
uint16 character;
uint16 unknown;
uint16 baseline;
uint16 width;
uint16 height;
uint8 data[MAX_GLYPH];
} RDP_FONT_GLYPH;
#define MAX_GLYPHS 256
typedef struct _RDP_FONTCACHE_ORDER
{
uint8 font;
uint8 nglyphs;
RDP_FONT_GLYPH glyphs[MAX_GLYPHS];
} RDP_FONTCACHE_ORDER;
typedef struct _RDP_COLCACHE_ORDER
{
uint8 cache_id;
COLOURMAP map;
} RDP_COLCACHE_ORDER;
#define RDP_POINTER_MOVE 3
typedef struct _RDP_POINTER
typedef struct _RDP_POINTER_PDU
{
uint16 message;
uint16 pad;
uint16 x;
uint16 y;
} RDP_POINTER;
} RDP_POINTER_PDU;

23
tcp.c
View File

@ -100,25 +100,40 @@ BOOL tcp_send(HCONN conn)
/* Receive a message on the TCP layer */
BOOL tcp_recv(HCONN conn, int length)
{
int rcvd;
int ret, rcvd = 0;
struct timeval tv;
fd_set rfds;
STREAM_SIZE(conn->in, length);
conn->in.end = conn->in.offset = 0;
while (length > 0)
{
rcvd = read(conn->tcp_socket, conn->in.data + conn->in.end,
length);
ui_process_events(conn->wnd, conn);
FD_ZERO(&rfds);
FD_SET(conn->tcp_socket, &rfds);
tv.tv_sec = 0;
tv.tv_usec = 100;
ret = select(conn->tcp_socket+1, &rfds, NULL, NULL, &tv);
if (ret)
{
rcvd = read(conn->tcp_socket, conn->in.data
+ conn->in.end, length);
if (rcvd <= 0)
{
fprintf(stderr, "read: %s\n", strerror(errno));
fprintf(stderr, "read: %s\n",
strerror(errno));
return False;
}
conn->in.end += rcvd;
length -= rcvd;
}
}
return True;
}

434
xwin.c
View File

@ -20,10 +20,12 @@
#include "includes.h"
HWINDOW ui_create_window(int width, int height)
HWINDOW ui_create_window(HCONN conn, int width, int height)
{
struct window *wnd;
XSetWindowAttributes attribs;
Display *display;
Visual *visual;
Window window;
int black;
GC gc;
@ -32,20 +34,30 @@ HWINDOW ui_create_window(int width, int height)
if (display == NULL)
return NULL;
visual = DefaultVisual(display, DefaultScreen(display));
black = BlackPixel(display, DefaultScreen(display));
window = XCreateSimpleWindow(display, DefaultRootWindow(display),
0, 0, width, height, 0, black, black);
attribs.background_pixel = black;
attribs.backing_store = Always;
window = XCreateWindow(display, DefaultRootWindow(display), 0, 0,
width, height, 0, 8, InputOutput, visual,
CWBackingStore | CWBackPixel, &attribs);
XStoreName(display, window, "rdesktop");
XMapWindow(display, window);
XSelectInput(display, window, KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);
XSync(display, True);
gc = XCreateGC(display, window, 0, NULL);
wnd = xmalloc(sizeof(struct window));
wnd->conn = conn;
wnd->width = width;
wnd->height = height;
wnd->display = display;
wnd->wnd = window;
wnd->gc = gc;
wnd->visual = DefaultVisual(wnd->display, DefaultScreen(wnd->display));
wnd->visual = visual;
return wnd;
}
@ -57,43 +69,168 @@ void ui_destroy_window(HWINDOW wnd)
XCloseDisplay(wnd->display);
}
static uint8 xwin_translate_key(unsigned long key)
{
DEBUG("KEY(code=0x%lx)\n", key);
if ((key > 8) && (key <= 0x60))
return (key - 8);
switch (key)
{
case 0x62: /* left arrow */
return 0x48;
case 0x64: /* up arrow */
return 0x4b;
case 0x66: /* down arrow */
return 0x4d;
case 0x68: /* right arrow */
return 0x50;
case 0x73: /* Windows key */
DEBUG("CHECKPOINT\n");
}
return 0;
}
static uint16 xwin_translate_mouse(unsigned long button)
{
switch (button)
{
case Button1: /* left */
return MOUSE_FLAG_BUTTON1;
case Button2: /* middle */
return MOUSE_FLAG_BUTTON3;
case Button3: /* right */
return MOUSE_FLAG_BUTTON2;
}
return 0;
}
void ui_process_events(HWINDOW wnd, HCONN conn)
{
XEvent event;
uint8 scancode;
uint16 button;
if (wnd == NULL)
return;
while (XCheckWindowEvent(wnd->display, wnd->wnd, 0xffffffff, &event))
{
switch (event.type)
{
case KeyPress:
scancode = xwin_translate_key(event.xkey.keycode);
if (scancode == 0)
break;
rdp_send_input(conn, RDP_INPUT_SCANCODE, 0,
scancode, 0);
break;
case KeyRelease:
scancode = xwin_translate_key(event.xkey.keycode);
if (scancode == 0)
break;
rdp_send_input(conn, RDP_INPUT_SCANCODE,
KBD_FLAG_DOWN | KBD_FLAG_UP,
scancode, 0);
break;
case ButtonPress:
button = xwin_translate_mouse(event.xbutton.button);
if (button == 0)
break;
rdp_send_input(conn, RDP_INPUT_MOUSE,
button | MOUSE_FLAG_DOWN,
event.xbutton.x,
event.xbutton.y);
break;
case ButtonRelease:
button = xwin_translate_mouse(event.xbutton.button);
if (button == 0)
break;
rdp_send_input(conn, RDP_INPUT_MOUSE,
button,
event.xbutton.x,
event.xbutton.y);
}
}
}
void ui_move_pointer(HWINDOW wnd, int x, int y)
{
XWarpPointer(wnd->display, wnd->wnd, wnd->wnd, 0, 0, 0, 0, x, y);
}
HBITMAP ui_create_bitmap(HWINDOW wnd, int width, int height, uint8 *data)
{
XImage *image;
Pixmap bitmap;
bitmap = XCreatePixmap(wnd->display, wnd->wnd, width, height, 8);
image = XCreateImage(wnd->display, wnd->visual, 8, ZPixmap, 0,
data, width, height, 32, width);
data, width, height, 8, width);
XSetFunction(wnd->display, wnd->gc, GXcopy);
XPutImage(wnd->display, bitmap, wnd->gc, image, 0, 0, 0, 0,
width, height);
XFree(image);
return (HBITMAP)image;
return (HBITMAP)bitmap;
}
void ui_destroy_bitmap(HWINDOW wnd, HBITMAP bmp)
{
XDestroyImage((XImage *)bmp);
XFreePixmap(wnd->display, (Pixmap)bmp);
}
void ui_paint_bitmap(HWINDOW wnd, HBITMAP bmp, int x, int y)
HGLYPH ui_create_glyph(HWINDOW wnd, int width, int height, uint8 *data)
{
XImage *image = (XImage *)bmp;
XImage *image;
Pixmap bitmap;
int scanline;
GC gc;
XPutImage(wnd->display, wnd->wnd, wnd->gc, image,
0, 0, x, y, image->width, image->height);
scanline = (width + 7) / 8;
XSync(wnd->display, True);
bitmap = XCreatePixmap(wnd->display, wnd->wnd, width, height, 1);
gc = XCreateGC(wnd->display, bitmap, 0, NULL);
image = XCreateImage(wnd->display, wnd->visual, 1, ZPixmap, 0,
data, width, height, 8, scanline);
XSetFunction(wnd->display, wnd->gc, GXcopy);
XPutImage(wnd->display, bitmap, gc, image, 0, 0, 0, 0, width, height);
XFree(image);
XFreeGC(wnd->display, gc);
return (HGLYPH)bitmap;
}
HCOLORMAP ui_create_colormap(HWINDOW wnd, COLORMAP *colors)
void ui_destroy_glyph(HWINDOW wnd, HGLYPH glyph)
{
COLORENTRY *entry;
XColor *xcolors, *xentry;
XFreePixmap(wnd->display, (Pixmap)glyph);
}
HCOLOURMAP ui_create_colourmap(HWINDOW wnd, COLOURMAP *colours)
{
COLOURENTRY *entry;
XColor *xcolours, *xentry;
Colormap map;
int i, ncolors = colors->ncolors;
int i, ncolours = colours->ncolours;
xcolors = malloc(sizeof(XColor) * ncolors);
for (i = 0; i < ncolors; i++)
xcolours = malloc(sizeof(XColor) * ncolours);
for (i = 0; i < ncolours; i++)
{
entry = &colors->colors[i];
xentry = &xcolors[i];
entry = &colours->colours[i];
xentry = &xcolours[i];
xentry->pixel = i;
xentry->red = entry->red << 8;
@ -103,33 +240,264 @@ HCOLORMAP ui_create_colormap(HWINDOW wnd, COLORMAP *colors)
}
map = XCreateColormap(wnd->display, wnd->wnd, wnd->visual, AllocAll);
XStoreColors(wnd->display, map, xcolors, ncolors);
XStoreColors(wnd->display, map, xcolours, ncolours);
free(xcolors);
return (HCOLORMAP)map;
free(xcolours);
return (HCOLOURMAP)map;
}
void ui_destroy_colormap(HWINDOW wnd, HCOLORMAP map)
void ui_destroy_colourmap(HWINDOW wnd, HCOLOURMAP map)
{
XFreeColormap(wnd->display, (Colormap)map);
}
void ui_set_colormap(HWINDOW wnd, HCOLORMAP map)
void ui_set_colourmap(HWINDOW wnd, HCOLOURMAP map)
{
XSetWindowColormap(wnd->display, wnd->wnd, (Colormap)map);
}
void ui_draw_rectangle(HWINDOW wnd, int x, int y, int width, int height)
void ui_set_clip(HWINDOW wnd, int x, int y, int cx, int cy)
{
static int white = 0;
XRectangle rect;
XSetForeground(wnd->display, wnd->gc, white);
XFillRectangle(wnd->display, wnd->wnd, wnd->gc, x, y, width, height);
white++;
rect.x = x;
rect.y = y;
rect.width = cx;
rect.height = cy;
XSetClipRectangles(wnd->display, wnd->gc, 0, 0, &rect, 1, YXBanded);
}
void ui_move_pointer(HWINDOW wnd, int x, int y)
void ui_reset_clip(HWINDOW wnd)
{
XWarpPointer(wnd->display, wnd->wnd, wnd->wnd, 0, 0, 0, 0, x, y);
XRectangle rect;
rect.x = 0;
rect.y = 0;
rect.width = wnd->width;
rect.height = wnd->height;
XSetClipRectangles(wnd->display, wnd->gc, 0, 0, &rect, 1, YXBanded);
}
static int rop2_map[] = {
GXclear, /* 0 */
GXnor, /* DPon */
GXandInverted, /* DPna */
GXcopyInverted, /* Pn */
GXandReverse, /* PDna */
GXinvert, /* Dn */
GXxor, /* DPx */
GXnand, /* DPan */
GXand, /* DPa */
GXequiv, /* DPxn */
GXnoop, /* D */
GXorInverted, /* DPno */
GXcopy, /* P */
GXorReverse, /* PDno */
GXor, /* DPo */
GXset /* 1 */
};
static void xwin_set_function(HWINDOW wnd, uint8 rop2)
{
XSetFunction(wnd->display, wnd->gc, rop2_map[rop2]);
}
void ui_destblt(HWINDOW wnd, uint8 opcode,
/* dest */ int x, int y, int cx, int cy)
{
xwin_set_function(wnd, opcode);
XFillRectangle(wnd->display, wnd->wnd, wnd->gc, x, y, cx, cy);
}
void ui_patblt(HWINDOW wnd, uint8 opcode,
/* dest */ int x, int y, int cx, int cy,
/* brush */ BRUSH *brush, int bgcolour, int fgcolour)
{
Display *dpy = wnd->display;
GC gc = wnd->gc;
Pixmap fill;
xwin_set_function(wnd, opcode);
switch (brush->style)
{
case 0: /* Solid */
XSetForeground(dpy, gc, fgcolour);
XFillRectangle(dpy, wnd->wnd, gc, x, y, cx, cy);
break;
case 3: /* Pattern */
fill = (Pixmap)ui_create_glyph(wnd, 8, 8, brush->pattern);
XSetForeground(dpy, gc, fgcolour);
XSetBackground(dpy, gc, bgcolour);
XSetFillStyle(dpy, gc, FillOpaqueStippled);
XSetStipple(dpy, gc, fill);
XFillRectangle(dpy, wnd->wnd, gc, x, y, cx, cy);
XSetFillStyle(dpy, gc, FillSolid);
ui_destroy_glyph(wnd, (HGLYPH)fill);
break;
default:
NOTIMP("brush style %d\n", brush->style);
}
}
void ui_screenblt(HWINDOW wnd, uint8 opcode,
/* dest */ int x, int y, int cx, int cy,
/* src */ int srcx, int srcy)
{
xwin_set_function(wnd, opcode);
XCopyArea(wnd->display, wnd->wnd, wnd->wnd, wnd->gc, srcx, srcy,
cx, cy, x, y);
}
void ui_memblt(HWINDOW wnd, uint8 opcode,
/* dest */ int x, int y, int cx, int cy,
/* src */ HBITMAP src, int srcx, int srcy)
{
xwin_set_function(wnd, opcode);
XCopyArea(wnd->display, (Pixmap)src, wnd->wnd, wnd->gc, srcx, srcy,
cx, cy, x, y);
}
void ui_triblt(HWINDOW wnd, uint8 opcode,
/* dest */ int x, int y, int cx, int cy,
/* src */ HBITMAP src, int srcx, int srcy,
/* brush */ BRUSH *brush, int bgcolour, int fgcolour)
{
/* This is potentially difficult to do in general. Until someone
comes up with an efficient way of doing that I am using cases. */
switch (opcode)
{
case 0xb8: /* PSDPxax */
ui_patblt(wnd, ROP2_XOR, x, y, cx, cy,
brush, bgcolour, fgcolour);
ui_memblt(wnd, ROP2_AND, x, y, cx, cy,
src, srcx, srcy);
ui_patblt(wnd, ROP2_XOR, x, y, cx, cy,
brush, bgcolour, fgcolour);
break;
default:
NOTIMP("triblt opcode 0x%x\n", opcode);
ui_memblt(wnd, ROP2_COPY, x, y, cx, cy,
brush, bgcolour, fgcolour);
}
}
void ui_line(HWINDOW wnd, uint8 opcode,
/* dest */ int startx, int starty, int endx, int endy,
/* pen */ PEN *pen)
{
xwin_set_function(wnd, opcode);
XSetForeground(wnd->display, wnd->gc, pen->colour);
XDrawLine(wnd->display, wnd->wnd, wnd->gc, startx, starty, endx, endy);
}
void ui_rect(HWINDOW wnd,
/* dest */ int x, int y, int cx, int cy,
/* brush */ int colour)
{
xwin_set_function(wnd, ROP2_COPY);
XSetForeground(wnd->display, wnd->gc, colour);
XFillRectangle(wnd->display, wnd->wnd, wnd->gc, x, y, cx, cy);
}
void ui_draw_glyph(HWINDOW wnd, int mixmode,
/* dest */ int x, int y, int cx, int cy,
/* src */ HGLYPH glyph, int srcx, int srcy, int bgcolour, int fgcolour)
{
Pixmap pixmap = (Pixmap)glyph;
xwin_set_function(wnd, ROP2_COPY);
XSetForeground(wnd->display, wnd->gc, fgcolour);
switch (mixmode)
{
case MIX_TRANSPARENT:
XSetStipple(wnd->display, wnd->gc, pixmap);
XSetFillStyle(wnd->display, wnd->gc, FillStippled);
XSetTSOrigin(wnd->display, wnd->gc, x, y);
XFillRectangle(wnd->display, wnd->wnd, wnd->gc,
x, y, cx, cy);
XSetFillStyle(wnd->display, wnd->gc, FillSolid);
break;
case MIX_OPAQUE:
XSetBackground(wnd->display, wnd->gc, bgcolour);
XCopyPlane(wnd->display, pixmap, wnd->wnd, wnd->gc,
srcx, srcy, cx, cy, x, y, 1);
break;
default:
NOTIMP("mix mode %d\n", mixmode);
}
}
void ui_draw_text(HWINDOW wnd, uint8 font, uint8 flags, int mixmode, int x,
int y, int boxx, int boxy, int boxcx, int boxcy,
int bgcolour, int fgcolour, uint8 *text, uint8 length)
{
FONT_GLYPH *glyph;
int i;
if (boxcx > 1)
{
ui_rect(wnd, boxx, boxy, boxcx, boxcy, bgcolour);
}
/* Paint text, character by character */
for (i = 0; i < length; i++)
{
glyph = cache_get_font(wnd->conn, font, text[i]);
if (glyph != NULL)
{
ui_draw_glyph(wnd, mixmode, x,
y + (short)glyph->baseline,
glyph->width, glyph->height,
glyph->pixmap, 0, 0,
bgcolour, fgcolour);
if (flags & TEXT2_IMPLICIT_X)
x += glyph->width;
else
x += text[++i];
}
}
}
void ui_desktop_save(HWINDOW wnd, uint8 *data, int x, int y, int cx, int cy)
{
XImage *image;
int scanline;
scanline = (cx + 3) & ~3;
image = XGetImage(wnd->display, wnd->wnd, x, y, cx, cy,
0xffffffff, ZPixmap);
memcpy(data, image->data, scanline*cy);
XDestroyImage(image);
}
void ui_desktop_restore(HWINDOW wnd, uint8 *data, int x, int y, int cx, int cy)
{
XImage *image;
int scanline;
scanline = (cx + 3) & ~3;
image = XCreateImage(wnd->display, wnd->visual, 8, ZPixmap, 0,
data, cx, cy, 32, scanline);
XSetFunction(wnd->display, wnd->gc, GXcopy);
XPutImage(wnd->display, wnd->wnd, wnd->gc, image, 0, 0, x, y, cx, cy);
XFree(image);
}

9
xwin.h
View File

@ -23,6 +23,10 @@
typedef struct window
{
struct connection *conn;
int width;
int height;
Display *display;
Window wnd;
GC gc;
@ -30,6 +34,7 @@ typedef struct window
} *HWINDOW;
typedef XImage *HBITMAP;
typedef Colormap HCOLORMAP;
typedef void *HBITMAP;
typedef void *HGLYPH;
typedef void *HCOLOURMAP;