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:
parent
a608d31345
commit
e11a571f14
7
Makefile
7
Makefile
@ -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
|
||||
|
58
bitmap.c
58
bitmap.c
@ -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
131
cache.c
Normal 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);
|
||||
}
|
||||
}
|
6
client.c
6
client.c
@ -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);
|
||||
|
@ -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
6
iso.c
@ -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
65
mcs.c
@ -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
2
misc.c
@ -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
72
misc.h
@ -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
10
parse.c
@ -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;
|
||||
}
|
||||
|
||||
|
6
parse.h
6
parse.h
@ -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
569
process.c
Normal 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
264
proto.h
@ -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);
|
||||
|
225
rdp.h
225
rdp.h
@ -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;
|
||||
|
||||
|
33
tcp.c
33
tcp.c
@ -100,24 +100,39 @@ 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);
|
||||
|
||||
if (rcvd <= 0)
|
||||
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)
|
||||
{
|
||||
fprintf(stderr, "read: %s\n", strerror(errno));
|
||||
return False;
|
||||
}
|
||||
rcvd = read(conn->tcp_socket, conn->in.data
|
||||
+ conn->in.end, length);
|
||||
|
||||
conn->in.end += rcvd;
|
||||
length -= rcvd;
|
||||
if (rcvd <= 0)
|
||||
{
|
||||
fprintf(stderr, "read: %s\n",
|
||||
strerror(errno));
|
||||
return False;
|
||||
}
|
||||
|
||||
conn->in.end += rcvd;
|
||||
length -= rcvd;
|
||||
}
|
||||
}
|
||||
|
||||
return True;
|
||||
|
436
xwin.c
436
xwin.c
@ -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);
|
||||
|
||||
return (HBITMAP)image;
|
||||
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)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
9
xwin.h
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user