added persistant bitmap chaching from Jeroen Meijer, slightly modified
git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@724 423420c4-83ab-492f-b58f-81f9feb106b5
This commit is contained in:
parent
4004b21d48
commit
7f836f0384
2
Makefile
2
Makefile
@ -15,7 +15,7 @@ datadir = $(prefix)/share/rdesktop
|
||||
VERSION = 1.3.1
|
||||
KEYMAP_PATH = $(datadir)/keymaps/
|
||||
|
||||
RDPOBJ = tcp.o iso.o mcs.o secure.o licence.o rdp.o orders.o bitmap.o cache.o rdp5.o channels.o rdpdr.o serial.o printer.o disk.o parallel.o printercache.o mppc.o
|
||||
RDPOBJ = tcp.o iso.o mcs.o secure.o licence.o rdp.o orders.o bitmap.o cache.o rdp5.o channels.o rdpdr.o serial.o printer.o disk.o parallel.o printercache.o mppc.o pstcache.o
|
||||
X11OBJ = rdesktop.o xwin.o xkeymap.o ewmhints.o xclip.o cliprdr.o
|
||||
VNCOBJ = vnc/rdp2vnc.o vnc/vnc.o vnc/xkeymap.o vnc/x11stubs.o
|
||||
CRYPTOBJ = crypto/rc4_enc.o crypto/rc4_skey.o crypto/md5_dgst.o crypto/sha1dgst.o crypto/bn_exp.o crypto/bn_mul.o crypto/bn_div.o crypto/bn_sqr.o crypto/bn_add.o crypto/bn_shift.o crypto/bn_asm.o crypto/bn_ctx.o crypto/bn_lib.o
|
||||
|
73
cache.c
73
cache.c
@ -21,22 +21,59 @@
|
||||
#include "rdesktop.h"
|
||||
|
||||
#define NUM_ELEMENTS(array) (sizeof(array) / sizeof(array[0]))
|
||||
#define TOUCH(id, idx) (g_bmpcache[id][idx].usage = ++g_stamp)
|
||||
#define IS_PERSISTENT(id) (g_pstcache_fd[id] > 0)
|
||||
|
||||
extern int g_pstcache_fd[];
|
||||
|
||||
uint32 g_stamp;
|
||||
int g_num_bitmaps_in_memory[3];
|
||||
|
||||
|
||||
/* BITMAP CACHE */
|
||||
static HBITMAP g_bmpcache[3][600];
|
||||
static BMPCACHEENTRY g_bmpcache[3][0xa00];
|
||||
|
||||
/* Remove the least-recently used bitmap from the cache */
|
||||
void
|
||||
cache_remove_lru_bitmap(uint8 cache_id)
|
||||
{
|
||||
int i;
|
||||
uint16 cache_idx = 0;
|
||||
uint32 m = -1;
|
||||
BMPCACHEENTRY *pbce;
|
||||
|
||||
for (i = 0; i < NUM_ELEMENTS(g_bmpcache[cache_id]); i++)
|
||||
{
|
||||
if (g_bmpcache[cache_id][i].bitmap && g_bmpcache[cache_id][i].usage < m)
|
||||
{
|
||||
cache_idx = i;
|
||||
m = g_bmpcache[cache_id][i].usage;
|
||||
}
|
||||
}
|
||||
|
||||
pbce = &g_bmpcache[cache_id][cache_idx];
|
||||
ui_destroy_bitmap(pbce->bitmap);
|
||||
--g_num_bitmaps_in_memory[cache_id];
|
||||
pbce->bitmap = 0;
|
||||
pbce->usage = 0;
|
||||
}
|
||||
|
||||
/* Retrieve a bitmap from the cache */
|
||||
HBITMAP
|
||||
cache_get_bitmap(uint8 cache_id, uint16 cache_idx)
|
||||
{
|
||||
HBITMAP bitmap;
|
||||
HBITMAP *pbitmap;
|
||||
|
||||
if ((cache_id < NUM_ELEMENTS(g_bmpcache)) && (cache_idx < NUM_ELEMENTS(g_bmpcache[0])))
|
||||
{
|
||||
bitmap = g_bmpcache[cache_id][cache_idx];
|
||||
if (bitmap != NULL)
|
||||
return bitmap;
|
||||
pbitmap = &g_bmpcache[cache_id][cache_idx].bitmap;
|
||||
if ((*pbitmap != 0) || pstcache_load_bitmap(cache_id, cache_idx))
|
||||
{
|
||||
if (IS_PERSISTENT(cache_id))
|
||||
TOUCH(cache_id, cache_idx);
|
||||
|
||||
return *pbitmap;
|
||||
}
|
||||
}
|
||||
|
||||
error("get bitmap %d:%d\n", cache_id, cache_idx);
|
||||
@ -45,17 +82,25 @@ cache_get_bitmap(uint8 cache_id, uint16 cache_idx)
|
||||
|
||||
/* Store a bitmap in the cache */
|
||||
void
|
||||
cache_put_bitmap(uint8 cache_id, uint16 cache_idx, HBITMAP bitmap)
|
||||
cache_put_bitmap(uint8 cache_id, uint16 cache_idx, HBITMAP bitmap, uint32 stamp)
|
||||
{
|
||||
HBITMAP old;
|
||||
|
||||
if ((cache_id < NUM_ELEMENTS(g_bmpcache)) && (cache_idx < NUM_ELEMENTS(g_bmpcache[0])))
|
||||
{
|
||||
old = g_bmpcache[cache_id][cache_idx];
|
||||
old = g_bmpcache[cache_id][cache_idx].bitmap;
|
||||
if (old != NULL)
|
||||
{
|
||||
ui_destroy_bitmap(old);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (++g_num_bitmaps_in_memory[cache_id] > BMPCACHE2_C2_CELLS)
|
||||
cache_remove_lru_bitmap(cache_id);
|
||||
}
|
||||
|
||||
g_bmpcache[cache_id][cache_idx] = bitmap;
|
||||
g_bmpcache[cache_id][cache_idx].bitmap = bitmap;
|
||||
g_bmpcache[cache_id][cache_idx].usage = stamp;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -63,6 +108,18 @@ cache_put_bitmap(uint8 cache_id, uint16 cache_idx, HBITMAP bitmap)
|
||||
}
|
||||
}
|
||||
|
||||
/* Updates the persistent bitmap cache MRU information on exit */
|
||||
void
|
||||
cache_save_state(void)
|
||||
{
|
||||
int id, idx;
|
||||
|
||||
for (id = 0; id < NUM_ELEMENTS(g_bmpcache); id++)
|
||||
if (IS_PERSISTENT(id))
|
||||
for (idx = 0; idx < NUM_ELEMENTS(g_bmpcache[id]); idx++)
|
||||
pstcache_touch_bitmap(id, idx, g_bmpcache[id][idx].usage);
|
||||
}
|
||||
|
||||
|
||||
/* FONT CACHE */
|
||||
static FONTGLYPH g_fontcache[12][256];
|
||||
|
14
constants.h
14
constants.h
@ -199,6 +199,15 @@ enum RDP_INPUT_DEVICE
|
||||
#define TEXT2_VERTICAL 0x04
|
||||
#define TEXT2_IMPLICIT_X 0x20
|
||||
|
||||
/* RDP bitmap cache (version 2) constants */
|
||||
#define BMPCACHE2_C0_CELLS 0x78
|
||||
#define BMPCACHE2_C1_CELLS 0x78
|
||||
#define BMPCACHE2_C2_CELLS 0x150
|
||||
#define BMPCACHE2_NUM_PSTCELLS 0x9f6
|
||||
|
||||
#define PDU_FLAG_FIRST 0x01
|
||||
#define PDU_FLAG_LAST 0x02
|
||||
|
||||
/* RDP capabilities */
|
||||
#define RDP_CAPSET_GENERAL 1 /* Maps to generalCapabilitySet in T.128 page 138 */
|
||||
#define RDP_CAPLEN_GENERAL 0x18
|
||||
@ -231,8 +240,9 @@ enum RDP_INPUT_DEVICE
|
||||
#define RDP_CAPSET_COLCACHE 10
|
||||
#define RDP_CAPLEN_COLCACHE 0x08
|
||||
|
||||
#define RDP_CAPSET_UNKNOWN 13
|
||||
#define RDP_CAPLEN_UNKNOWN 0x9C
|
||||
#define RDP_CAPSET_BMPCACHE2 19
|
||||
#define RDP_CAPLEN_BMPCACHE2 0x28
|
||||
#define BMPCACHE2_FLAG_PERSIST (1<<31)
|
||||
|
||||
#define RDP_SOURCE "MSTSC"
|
||||
|
||||
|
@ -108,14 +108,21 @@ More than 8 bpp are only supported when connecting to Windows XP
|
||||
limited by the server configuration.
|
||||
.TP
|
||||
.BR "-x <experience>"
|
||||
Alters default bandwith performance behaviour for RDP5. By default only
|
||||
Changes default bandwidth performance behaviour for RDP5. By default only
|
||||
theming is enabled, and all other options are disabled (corresponding
|
||||
to modem (56 Kbps)). Setting experience to b[roadband] enables menu
|
||||
animations and full window dragging. Setting experience to l[an] will
|
||||
also enable the desktop wallpaper. Setting experience to m[odem]
|
||||
disables all (including theming). Experience can also be a hexidecimal
|
||||
disables all (including themes). Experience can also be a hexidecimal
|
||||
number containing the flags.
|
||||
.TP
|
||||
.BR "-P"
|
||||
Enable caching of bitmaps to disk (persistent bitmap caching). This generally
|
||||
improves performance (especially on low bandwidth connections) and reduces
|
||||
network traffic at the cost of slightly longer startup and some disk space.
|
||||
(10MB for 8-bit colour, 20MB for 15/16-bit colour and 30MB for 24-bit colour
|
||||
sessions)
|
||||
.TP
|
||||
.BR "-r <device>"
|
||||
Enable redirection of the specified device on the client, such
|
||||
that it appears on the server. Note that the allowed
|
||||
|
112
orders.c
112
orders.c
@ -670,7 +670,7 @@ process_raw_bmpcache(STREAM s)
|
||||
|
||||
bitmap = ui_create_bitmap(width, height, inverted);
|
||||
xfree(inverted);
|
||||
cache_put_bitmap(cache_id, cache_idx, bitmap);
|
||||
cache_put_bitmap(cache_id, cache_idx, bitmap, 0);
|
||||
}
|
||||
|
||||
/* Process a bitmap cache order */
|
||||
@ -695,7 +695,11 @@ process_bmpcache(STREAM s)
|
||||
in_uint16_le(s, bufsize); /* bufsize */
|
||||
in_uint16_le(s, cache_idx);
|
||||
|
||||
if (!g_use_rdp5)
|
||||
if (g_use_rdp5)
|
||||
{
|
||||
size = bufsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Begin compressedBitmapData */
|
||||
@ -706,10 +710,6 @@ process_bmpcache(STREAM s)
|
||||
in_uint16_le(s, final_size);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
size = bufsize;
|
||||
}
|
||||
in_uint8p(s, data, size);
|
||||
|
||||
DEBUG(("BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d,bpp=%d,size=%d,pad1=%d,bufsize=%d,pad2=%d,rs=%d,fs=%d)\n", width, height, cache_id, cache_idx, bpp, size, pad1, bufsize, pad2, row_size, final_size));
|
||||
@ -719,7 +719,7 @@ process_bmpcache(STREAM s)
|
||||
if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
|
||||
{
|
||||
bitmap = ui_create_bitmap(width, height, bmpdata);
|
||||
cache_put_bitmap(cache_id, cache_idx, bitmap);
|
||||
cache_put_bitmap(cache_id, cache_idx, bitmap, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -729,6 +729,86 @@ process_bmpcache(STREAM s)
|
||||
xfree(bmpdata);
|
||||
}
|
||||
|
||||
/* Process a bitmap cache v2 order */
|
||||
static void
|
||||
process_bmpcache2(STREAM s, uint16 flags, BOOL compressed)
|
||||
{
|
||||
HBITMAP bitmap;
|
||||
int y;
|
||||
uint8 cache_id, cache_idx_low, width, height, Bpp;
|
||||
uint16 cache_idx, bufsize;
|
||||
uint8 *data, *bmpdata, *bitmap_id;
|
||||
|
||||
bitmap_id = NULL; /* prevent compiler warning */
|
||||
cache_id = flags & ID_MASK;
|
||||
Bpp = ((flags & MODE_MASK) >> MODE_SHIFT) - 2;
|
||||
|
||||
if (flags & PERSIST)
|
||||
{
|
||||
in_uint8p(s, bitmap_id, 8);
|
||||
}
|
||||
|
||||
if (flags & SQUARE)
|
||||
{
|
||||
in_uint8(s, width);
|
||||
height = width;
|
||||
}
|
||||
else
|
||||
{
|
||||
in_uint8(s, width);
|
||||
in_uint8(s, height);
|
||||
}
|
||||
|
||||
in_uint16_be(s, bufsize);
|
||||
bufsize &= BUFSIZE_MASK;
|
||||
in_uint8(s, cache_idx);
|
||||
|
||||
if (cache_idx & LONG_FORMAT)
|
||||
{
|
||||
in_uint8(s, cache_idx_low);
|
||||
cache_idx = ((cache_idx ^ LONG_FORMAT) << 8) + cache_idx_low;
|
||||
}
|
||||
|
||||
in_uint8p(s, data, bufsize);
|
||||
|
||||
DEBUG(("BMPCACHE2(compr=%d,flags=%x,cx=%d,cy=%d,id=%d,idx=%d,Bpp=%d,bs=%d)\n",
|
||||
compressed, flags, width, height, cache_id, cache_idx, Bpp, bufsize));
|
||||
|
||||
bmpdata = (uint8 *) xmalloc(width * height * Bpp);
|
||||
|
||||
if (compressed)
|
||||
{
|
||||
if (!bitmap_decompress(bmpdata, width, height, data, bufsize, Bpp))
|
||||
{
|
||||
DEBUG(("Failed to decompress bitmap data\n"));
|
||||
xfree(bmpdata);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (y = 0; y < height; y++)
|
||||
memcpy(&bmpdata[(height - y - 1) * (width * Bpp)],
|
||||
&data[y * (width * Bpp)], width * Bpp);
|
||||
}
|
||||
|
||||
bitmap = ui_create_bitmap(width, height, bmpdata);
|
||||
|
||||
if (bitmap)
|
||||
{
|
||||
cache_put_bitmap(cache_id, cache_idx, bitmap, 0);
|
||||
if (flags & PERSIST)
|
||||
pstcache_put_bitmap(cache_id, cache_idx, bitmap_id, width, height,
|
||||
width * height * Bpp, bmpdata);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG(("process_bmpcache2: ui_create_bitmap failed\n"));
|
||||
}
|
||||
|
||||
xfree(bmpdata);
|
||||
}
|
||||
|
||||
/* Process a colourmap cache order */
|
||||
static void
|
||||
process_colcache(STREAM s)
|
||||
@ -796,12 +876,16 @@ process_fontcache(STREAM s)
|
||||
static void
|
||||
process_secondary_order(STREAM s)
|
||||
{
|
||||
uint16 length;
|
||||
/* The length isn't calculated correctly by the server.
|
||||
* For very compact orders the length becomes negative
|
||||
* so a signed integer must be used. */
|
||||
sint16 length;
|
||||
uint16 flags;
|
||||
uint8 type;
|
||||
uint8 *next_order;
|
||||
|
||||
in_uint16_le(s, length);
|
||||
in_uint8s(s, 2); /* flags */
|
||||
in_uint16_le(s, (uint16) length);
|
||||
in_uint16_le(s, flags); /* used by bmpcache2 */
|
||||
in_uint8(s, type);
|
||||
|
||||
next_order = s->p + length + 7;
|
||||
@ -824,6 +908,14 @@ process_secondary_order(STREAM s)
|
||||
process_fontcache(s);
|
||||
break;
|
||||
|
||||
case RDP_ORDER_RAW_BMPCACHE2:
|
||||
process_bmpcache2(s, flags, False); /* uncompressed */
|
||||
break;
|
||||
|
||||
case RDP_ORDER_BMPCACHE2:
|
||||
process_bmpcache2(s, flags, True); /* compressed */
|
||||
break;
|
||||
|
||||
default:
|
||||
unimpl("secondary order %d\n", type);
|
||||
}
|
||||
|
16
orders.h
16
orders.h
@ -46,7 +46,9 @@ enum RDP_SECONDARY_ORDER_TYPE
|
||||
RDP_ORDER_RAW_BMPCACHE = 0,
|
||||
RDP_ORDER_COLCACHE = 1,
|
||||
RDP_ORDER_BMPCACHE = 2,
|
||||
RDP_ORDER_FONTCACHE = 3
|
||||
RDP_ORDER_FONTCACHE = 3,
|
||||
RDP_ORDER_RAW_BMPCACHE2 = 4,
|
||||
RDP_ORDER_BMPCACHE2 = 5
|
||||
};
|
||||
|
||||
typedef struct _DESTBLT_ORDER
|
||||
@ -252,6 +254,18 @@ typedef struct _RDP_BMPCACHE_ORDER
|
||||
}
|
||||
RDP_BMPCACHE_ORDER;
|
||||
|
||||
/* RDP_BMPCACHE2_ORDER */
|
||||
#define ID_MASK 0x0007
|
||||
#define MODE_MASK 0x0038
|
||||
#define SQUARE 0x0080
|
||||
#define PERSIST 0x0100
|
||||
#define FLAG_51_UNKNOWN 0x0800
|
||||
|
||||
#define MODE_SHIFT 3
|
||||
|
||||
#define LONG_FORMAT 0x80
|
||||
#define BUFSIZE_MASK 0x3FFF /* or 0x1FFF? */
|
||||
|
||||
#define MAX_GLYPH 32
|
||||
|
||||
typedef struct _RDP_FONT_GLYPH
|
||||
|
17
proto.h
17
proto.h
@ -2,7 +2,8 @@
|
||||
BOOL bitmap_decompress(uint8 * output, int width, int height, uint8 * input, int size, int Bpp);
|
||||
/* cache.c */
|
||||
HBITMAP cache_get_bitmap(uint8 cache_id, uint16 cache_idx);
|
||||
void cache_put_bitmap(uint8 cache_id, uint16 cache_idx, HBITMAP bitmap);
|
||||
void cache_put_bitmap(uint8 cache_id, uint16 cache_idx, HBITMAP bitmap, uint32 stamp);
|
||||
void cache_save_state(void);
|
||||
FONTGLYPH *cache_get_font(uint8 font, uint16 character);
|
||||
void cache_put_font(uint8 font, uint16 character, uint16 offset, uint16 baseline, uint16 width,
|
||||
uint16 height, HGLYPH pixmap);
|
||||
@ -60,6 +61,13 @@ int printer_enum_devices(uint32 * id, char *optarg);
|
||||
/* printercache.c */
|
||||
int printercache_load_blob(char *printer_name, uint8 ** data);
|
||||
void printercache_process(STREAM s);
|
||||
/* pstcache.c */
|
||||
void pstcache_touch_bitmap(uint8 id, uint16 idx, uint32 stamp);
|
||||
BOOL pstcache_load_bitmap(uint8 id, uint16 idx);
|
||||
BOOL pstcache_put_bitmap(uint8 id, uint16 idx, uint8 *bmp_id, uint16 wd,
|
||||
uint16 ht, uint16 len, uint8 *data);
|
||||
int pstcache_enumerate(uint8 id, uint8 *list);
|
||||
BOOL pstcache_init(uint8 id);
|
||||
/* rdesktop.c */
|
||||
int main(int argc, char *argv[]);
|
||||
void generate_random(uint8 * random);
|
||||
@ -75,6 +83,13 @@ void toupper_str(char *p);
|
||||
char *l_to_a(long N, int base);
|
||||
int load_licence(unsigned char **data);
|
||||
void save_licence(unsigned char *data, int length);
|
||||
BOOL rd_pstcache_mkdir(void);
|
||||
int rd_open_file(char *filename);
|
||||
void rd_close_file(int fd);
|
||||
int rd_read_file(int fd, void *ptr, int len);
|
||||
int rd_write_file(int fd, void* ptr, int len);
|
||||
int rd_lseek_file(int fd, int offset);
|
||||
BOOL rd_lock_file(int fd, int start, int len);
|
||||
/* rdp5.c */
|
||||
void rdp5_process(STREAM s, BOOL encryption);
|
||||
/* rdp.c */
|
||||
|
194
pstcache.c
Normal file
194
pstcache.c
Normal file
@ -0,0 +1,194 @@
|
||||
/*
|
||||
rdesktop: A Remote Desktop Protocol client.
|
||||
Persistent Bitmap Cache routines
|
||||
Copyright (C) Jeroen Meijer 2004
|
||||
|
||||
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 "rdesktop.h"
|
||||
|
||||
#define MAX_CELL_SIZE 0x1000 /* pixels */
|
||||
|
||||
#define IS_PERSISTENT(id) (g_pstcache_fd[id] > 0)
|
||||
|
||||
extern int g_server_bpp;
|
||||
extern uint32 g_stamp;
|
||||
extern BOOL g_bitmap_cache;
|
||||
extern BOOL g_bitmap_cache_persist_enable;
|
||||
extern BOOL g_bitmap_cache_precache;
|
||||
|
||||
int g_pstcache_fd[8];
|
||||
int g_pstcache_Bpp;
|
||||
BOOL g_pstcache_enumerated = False;
|
||||
uint8 zero_id[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
|
||||
/* Update usage info for a bitmap */
|
||||
void
|
||||
pstcache_touch_bitmap(uint8 cache_id, uint16 cache_idx, uint32 stamp)
|
||||
{
|
||||
int fd;
|
||||
|
||||
if (!IS_PERSISTENT(cache_id))
|
||||
return;
|
||||
|
||||
fd = g_pstcache_fd[cache_id];
|
||||
rd_lseek_file(fd, 12 + cache_idx * (g_pstcache_Bpp * MAX_CELL_SIZE + sizeof(CELLHEADER)));
|
||||
rd_write_file(fd, &stamp, sizeof(stamp));
|
||||
}
|
||||
|
||||
/* Load a bitmap from the persistent cache */
|
||||
BOOL
|
||||
pstcache_load_bitmap(uint8 cache_id, uint16 cache_idx)
|
||||
{
|
||||
uint8 *celldata;
|
||||
int fd;
|
||||
CELLHEADER cellhdr;
|
||||
HBITMAP bitmap;
|
||||
|
||||
if (!(g_bitmap_cache_persist_enable && IS_PERSISTENT(cache_id)))
|
||||
return False;
|
||||
|
||||
fd = g_pstcache_fd[cache_id];
|
||||
rd_lseek_file(fd, cache_idx * (g_pstcache_Bpp * MAX_CELL_SIZE + sizeof(CELLHEADER)));
|
||||
rd_read_file(fd, &cellhdr, sizeof(CELLHEADER));
|
||||
celldata = (uint8 *)xmalloc(cellhdr.length);
|
||||
rd_read_file(fd, celldata, cellhdr.length);
|
||||
|
||||
DEBUG(("Loading bitmap from disk (%d:%d)\n", cache_id, cache_idx));
|
||||
|
||||
bitmap = ui_create_bitmap(cellhdr.width, cellhdr.height, celldata);
|
||||
cache_put_bitmap(cache_id, cache_idx, bitmap, cellhdr.stamp);
|
||||
|
||||
xfree(celldata);
|
||||
return True;
|
||||
}
|
||||
|
||||
/* Store a bitmap in the persistent cache */
|
||||
BOOL
|
||||
pstcache_put_bitmap(uint8 cache_id, uint16 cache_idx, uint8 *bitmap_id,
|
||||
uint16 width, uint16 height, uint16 length, uint8 *data)
|
||||
{
|
||||
int fd;
|
||||
CELLHEADER cellhdr;
|
||||
|
||||
if (!IS_PERSISTENT(cache_id))
|
||||
return False;
|
||||
|
||||
memcpy(cellhdr.bitmap_id, bitmap_id, sizeof(BITMAP_ID));
|
||||
cellhdr.width = width;
|
||||
cellhdr.height = height;
|
||||
cellhdr.length = length;
|
||||
cellhdr.stamp = 0;
|
||||
|
||||
fd = g_pstcache_fd[cache_id];
|
||||
rd_lseek_file(fd, cache_idx * (g_pstcache_Bpp * MAX_CELL_SIZE + sizeof(CELLHEADER)));
|
||||
rd_write_file(fd, &cellhdr, sizeof(CELLHEADER));
|
||||
rd_write_file(fd, data, length);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/* list the bitmaps from the persistent cache file */
|
||||
int
|
||||
pstcache_enumerate(uint8 cache_id, uint8 *idlist)
|
||||
{
|
||||
int fd, n, c = 0;
|
||||
CELLHEADER cellhdr;
|
||||
|
||||
if (!(g_bitmap_cache && g_bitmap_cache_persist_enable && IS_PERSISTENT(cache_id)))
|
||||
return 0;
|
||||
|
||||
/* The server disconnects if the bitmap cache content is sent more than once */
|
||||
if (g_pstcache_enumerated)
|
||||
return 0;
|
||||
|
||||
DEBUG(("pstcache enumeration... "));
|
||||
for (n = 0; n < BMPCACHE2_NUM_PSTCELLS; n++)
|
||||
{
|
||||
fd = g_pstcache_fd[cache_id];
|
||||
rd_lseek_file(fd, n * (g_pstcache_Bpp * MAX_CELL_SIZE + sizeof(CELLHEADER)));
|
||||
if (rd_read_file(fd, &cellhdr, sizeof(CELLHEADER)) <= 0)
|
||||
break;
|
||||
|
||||
if (memcmp(cellhdr.bitmap_id, zero_id, sizeof(BITMAP_ID)) != 0)
|
||||
{
|
||||
memcpy(idlist + n * sizeof(BITMAP_ID), cellhdr.bitmap_id,
|
||||
sizeof(BITMAP_ID));
|
||||
|
||||
if (cellhdr.stamp)
|
||||
{
|
||||
/* Pre-caching is not possible with 8bpp because a colourmap
|
||||
* is needed to load them */
|
||||
if (g_bitmap_cache_precache && (g_server_bpp > 8))
|
||||
{
|
||||
if (pstcache_load_bitmap(cache_id, n))
|
||||
c++;
|
||||
}
|
||||
|
||||
g_stamp = MAX(g_stamp, cellhdr.stamp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG(("%d bitmaps in persistent cache, %d bitmaps loaded in memory\n", n, c));
|
||||
g_pstcache_enumerated = True;
|
||||
return n;
|
||||
}
|
||||
|
||||
/* initialise the persistent bitmap cache */
|
||||
BOOL
|
||||
pstcache_init(uint8 cache_id)
|
||||
{
|
||||
int fd;
|
||||
char filename[256];
|
||||
|
||||
if (g_pstcache_enumerated)
|
||||
return True;
|
||||
|
||||
g_pstcache_fd[cache_id] = 0;
|
||||
|
||||
if (!(g_bitmap_cache && g_bitmap_cache_persist_enable))
|
||||
return False;
|
||||
|
||||
if (!rd_pstcache_mkdir())
|
||||
{
|
||||
DEBUG(("failed to get/make cache directory!\n"));
|
||||
return False;
|
||||
}
|
||||
|
||||
g_pstcache_Bpp = (g_server_bpp + 7) / 8;
|
||||
sprintf(filename, "cache/pstcache_%d_%d", cache_id, g_pstcache_Bpp);
|
||||
DEBUG(("persistent bitmap cache file: %s\n", filename));
|
||||
|
||||
fd = rd_open_file(filename);
|
||||
if (fd == -1)
|
||||
return False;
|
||||
|
||||
if (!rd_lock_file(fd, 0, 0))
|
||||
{
|
||||
warning("Persistent bitmap caching is disabled. (The file is already in use)\n");
|
||||
rd_close_file(fd);
|
||||
return False;
|
||||
}
|
||||
|
||||
g_pstcache_fd[cache_id] = fd;
|
||||
return True;
|
||||
}
|
106
rdesktop.c
106
rdesktop.c
@ -59,6 +59,8 @@ int g_win_button_size = 0; /* If zero, disable single app mode */
|
||||
BOOL g_bitmap_compression = True;
|
||||
BOOL g_sendmotion = True;
|
||||
BOOL g_bitmap_cache = True;
|
||||
BOOL g_bitmap_cache_persist_enable = False;
|
||||
BOOL g_bitmap_cache_precache = True;
|
||||
BOOL g_encryption = True;
|
||||
BOOL packet_encryption = True;
|
||||
BOOL g_desktop_save = True;
|
||||
@ -124,8 +126,8 @@ usage(char *program)
|
||||
fprintf(stderr, " -N: enable numlock syncronization\n");
|
||||
fprintf(stderr, " -X: embed into another window with a given id.\n");
|
||||
fprintf(stderr, " -a: connection colour depth\n");
|
||||
fprintf(stderr,
|
||||
" -x: RDP5 experience (m[odem 28.8], b[roadband], l[an] or hex number)\n");
|
||||
fprintf(stderr, " -x: RDP5 experience (m[odem 28.8], b[roadband], l[an] or hex nr.)\n");
|
||||
fprintf(stderr, " -P: use persistent bitmap caching\n");
|
||||
fprintf(stderr, " -r: enable specified device redirection (this flag can be repeated)\n");
|
||||
fprintf(stderr,
|
||||
" '-r comport:COM1=/dev/ttyS0': enable serial redirection of /dev/ttyS0 to COM1\n");
|
||||
@ -364,7 +366,8 @@ main(int argc, char *argv[])
|
||||
#define VNCOPT
|
||||
#endif
|
||||
|
||||
while ((c = getopt(argc, argv, VNCOPT "u:d:s:c:p:n:k:g:fbBeEmCDKS:T:NX:a:x:r:045h?")) != -1)
|
||||
while ((c = getopt(argc, argv,
|
||||
VNCOPT "u:d:s:c:p:n:k:g:fbBeEmCDKS:T:NX:a:x:Pr:045h?")) != -1)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
@ -547,6 +550,10 @@ main(int argc, char *argv[])
|
||||
}
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
g_bitmap_cache_persist_enable = True;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
|
||||
if (strncmp("sound", optarg, 5) == 0)
|
||||
@ -713,6 +720,7 @@ main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
DEBUG(("Disconnecting...\n"));
|
||||
cache_save_state();
|
||||
rdp_disconnect();
|
||||
ui_deinit();
|
||||
|
||||
@ -1121,3 +1129,95 @@ save_licence(unsigned char *data, int length)
|
||||
xfree(tmppath);
|
||||
xfree(path);
|
||||
}
|
||||
|
||||
/* Create the bitmap cache directory */
|
||||
BOOL
|
||||
rd_pstcache_mkdir(void)
|
||||
{
|
||||
char *home;
|
||||
char bmpcache_dir[256];
|
||||
|
||||
home = getenv("HOME");
|
||||
|
||||
if (home == NULL)
|
||||
return False;
|
||||
|
||||
sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop");
|
||||
|
||||
if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
|
||||
{
|
||||
perror(bmpcache_dir);
|
||||
return False;
|
||||
}
|
||||
|
||||
sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop/cache");
|
||||
|
||||
if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
|
||||
{
|
||||
perror(bmpcache_dir);
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/* open a file in the .rdesktop directory */
|
||||
int
|
||||
rd_open_file(char *filename)
|
||||
{
|
||||
char *home;
|
||||
char fn[256];
|
||||
int fd;
|
||||
|
||||
home = getenv("HOME");
|
||||
if (home == NULL)
|
||||
return -1;
|
||||
sprintf(fn, "%s/.rdesktop/%s", home, filename);
|
||||
fd = open(fn, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
|
||||
if (fd == -1)
|
||||
perror(fn);
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* close file */
|
||||
void
|
||||
rd_close_file(int fd)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/* read from file*/
|
||||
int
|
||||
rd_read_file(int fd, void *ptr, int len)
|
||||
{
|
||||
return read(fd, ptr, len);
|
||||
}
|
||||
|
||||
/* write to file */
|
||||
int
|
||||
rd_write_file(int fd, void* ptr, int len)
|
||||
{
|
||||
return write(fd, ptr, len);
|
||||
}
|
||||
|
||||
/* move file pointer */
|
||||
int
|
||||
rd_lseek_file(int fd, int offset)
|
||||
{
|
||||
return lseek(fd, offset, SEEK_SET);
|
||||
}
|
||||
|
||||
/* do a write lock on a file */
|
||||
BOOL
|
||||
rd_lock_file(int fd, int start, int len)
|
||||
{
|
||||
struct flock lock;
|
||||
|
||||
lock.l_type = F_WRLCK;
|
||||
lock.l_whence = SEEK_SET;
|
||||
lock.l_start = start;
|
||||
lock.l_len = len;
|
||||
if (fcntl(fd, F_SETLK, &lock) == -1)
|
||||
return False;
|
||||
return True;
|
||||
}
|
||||
|
182
rdp.c
182
rdp.c
@ -34,6 +34,7 @@ extern int g_server_bpp;
|
||||
extern int g_width;
|
||||
extern int g_height;
|
||||
extern BOOL g_bitmap_cache;
|
||||
extern BOOL g_bitmap_cache_persist_enable;
|
||||
|
||||
uint8 *g_next_packet;
|
||||
uint32 g_rdp_shareid;
|
||||
@ -366,6 +367,51 @@ rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 par
|
||||
rdp_send_data(s, RDP_DATA_PDU_INPUT);
|
||||
}
|
||||
|
||||
/* Inform the server on the contents of the persistent bitmap cache */
|
||||
static void
|
||||
rdp_enum_bmpcache2(void)
|
||||
{
|
||||
STREAM s;
|
||||
uint8 idlist[BMPCACHE2_NUM_PSTCELLS * sizeof(BITMAP_ID)];
|
||||
uint32 nids, offset, count, flags;
|
||||
|
||||
offset = 0;
|
||||
nids = pstcache_enumerate(2, idlist);
|
||||
|
||||
while (offset < nids)
|
||||
{
|
||||
count = MIN(nids - offset, 169);
|
||||
|
||||
s = rdp_init_data(24 + count * sizeof(BITMAP_ID));
|
||||
|
||||
flags = 0;
|
||||
if (offset == 0)
|
||||
flags |= PDU_FLAG_FIRST;
|
||||
if (nids - offset <= 169)
|
||||
flags |= PDU_FLAG_LAST;
|
||||
|
||||
/* header */
|
||||
out_uint32_le(s, 0);
|
||||
out_uint16_le(s, count);
|
||||
out_uint16_le(s, 0);
|
||||
out_uint16_le(s, 0);
|
||||
out_uint16_le(s, 0);
|
||||
out_uint16_le(s, 0);
|
||||
out_uint16_le(s, nids);
|
||||
out_uint32_le(s, 0);
|
||||
out_uint32_le(s, flags);
|
||||
|
||||
/* list */
|
||||
out_uint8a(s, idlist + offset * sizeof(BITMAP_ID),
|
||||
count * sizeof(BITMAP_ID));
|
||||
|
||||
s_mark_end(s);
|
||||
rdp_send_data(s, 0x2b);
|
||||
|
||||
offset += 169;
|
||||
}
|
||||
}
|
||||
|
||||
/* Send an (empty) font information PDU */
|
||||
static void
|
||||
rdp_send_fonts(uint16 seq)
|
||||
@ -486,6 +532,30 @@ rdp_out_bmpcache_caps(STREAM s)
|
||||
out_uint16_le(s, 0x1000 * Bpp); /* max cell size */
|
||||
}
|
||||
|
||||
/* Output bitmap cache v2 capability set */
|
||||
static void
|
||||
rdp_out_bmpcache2_caps(STREAM s)
|
||||
{
|
||||
out_uint16_le(s, RDP_CAPSET_BMPCACHE2);
|
||||
out_uint16_le(s, RDP_CAPLEN_BMPCACHE2);
|
||||
|
||||
out_uint16_le(s, g_bitmap_cache_persist_enable ? 1 : 0); /* version */
|
||||
|
||||
out_uint16_le(s, 0x0300); /* flags? number of caches? */
|
||||
|
||||
out_uint32_le(s, BMPCACHE2_C0_CELLS);
|
||||
out_uint32_le(s, BMPCACHE2_C1_CELLS);
|
||||
if (pstcache_init(2))
|
||||
{
|
||||
out_uint32_le(s, BMPCACHE2_NUM_PSTCELLS | BMPCACHE2_FLAG_PERSIST);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_uint32_le(s, BMPCACHE2_C2_CELLS);
|
||||
}
|
||||
out_uint8s(s, 20); /* other bitmap caches not used */
|
||||
}
|
||||
|
||||
/* Output control capability set */
|
||||
static void
|
||||
rdp_out_control_caps(STREAM s)
|
||||
@ -545,36 +615,41 @@ rdp_out_colcache_caps(STREAM s)
|
||||
out_uint16(s, 0); /* pad */
|
||||
}
|
||||
|
||||
static uint8 canned_caps[] = {
|
||||
0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 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,
|
||||
0x0C, 0x00, 0x08, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x0E, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x10, 0x00, 0x34, 0x00, 0xFE,
|
||||
0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x08, 0x00,
|
||||
0xFE, 0x00, 0x08, 0x00, 0xFE,
|
||||
0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00, 0xFE, 0x00, 0x40, 0x00,
|
||||
0xFE, 0x00, 0x80, 0x00, 0xFE,
|
||||
0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01,
|
||||
0x02, 0x00, 0x00, 0x00
|
||||
static uint8 caps_0x0d[] = {
|
||||
0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 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
|
||||
};
|
||||
|
||||
/* Output unknown capability sets (number 13, 12, 14 and 16) */
|
||||
static void
|
||||
rdp_out_unknown_caps(STREAM s)
|
||||
{
|
||||
out_uint16_le(s, RDP_CAPSET_UNKNOWN);
|
||||
out_uint16_le(s, 0x58);
|
||||
static uint8 caps_0x0c[] = { 0x01, 0x00, 0x00, 0x00 };
|
||||
|
||||
out_uint8p(s, canned_caps, RDP_CAPLEN_UNKNOWN - 4);
|
||||
static uint8 caps_0x0e[] = { 0x01, 0x00, 0x00, 0x00 };
|
||||
|
||||
static uint8 caps_0x10[] = {
|
||||
0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00,
|
||||
0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00,
|
||||
0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00,
|
||||
0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00,
|
||||
0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08,
|
||||
0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
/* Output unknown capability sets */
|
||||
static void
|
||||
rdp_out_unknown_caps(STREAM s, uint16 id, uint16 length, uint8 *caps)
|
||||
{
|
||||
out_uint16_le(s, id);
|
||||
out_uint16_le(s, length);
|
||||
|
||||
out_uint8p(s, caps, length - 4);
|
||||
}
|
||||
|
||||
#define RDP5_FLAG 0x0030
|
||||
@ -588,7 +663,9 @@ rdp_send_confirm_active(void)
|
||||
RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
|
||||
RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
|
||||
RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
|
||||
RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE + RDP_CAPLEN_UNKNOWN + 4 /* w2k fix, why? */ ;
|
||||
RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE +
|
||||
0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */ +
|
||||
4 /* w2k fix, why? */ ;
|
||||
|
||||
s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
|
||||
|
||||
@ -608,13 +685,17 @@ rdp_send_confirm_active(void)
|
||||
rdp_out_general_caps(s);
|
||||
rdp_out_bitmap_caps(s);
|
||||
rdp_out_order_caps(s);
|
||||
rdp_out_bmpcache_caps(s);
|
||||
g_use_rdp5 ? rdp_out_bmpcache2_caps(s) : rdp_out_bmpcache_caps(s);
|
||||
rdp_out_colcache_caps(s);
|
||||
rdp_out_activate_caps(s);
|
||||
rdp_out_control_caps(s);
|
||||
rdp_out_pointer_caps(s);
|
||||
rdp_out_share_caps(s);
|
||||
rdp_out_unknown_caps(s);
|
||||
|
||||
rdp_out_unknown_caps(s, 0x0d, 0x58, caps_0x0d); /* international? */
|
||||
rdp_out_unknown_caps(s, 0x0c, 0x08, caps_0x0c);
|
||||
rdp_out_unknown_caps(s, 0x0e, 0x08, caps_0x0e);
|
||||
rdp_out_unknown_caps(s, 0x10, 0x34, caps_0x10); /* glyph cache? */
|
||||
|
||||
s_mark_end(s);
|
||||
sec_send(s, sec_flags);
|
||||
@ -666,26 +747,24 @@ rdp_process_bitmap_caps(STREAM s)
|
||||
}
|
||||
}
|
||||
|
||||
/* Respond to a demand active PDU */
|
||||
static void
|
||||
process_demand_active(STREAM s)
|
||||
/* Process server capabilities */
|
||||
void
|
||||
rdp_process_server_caps(STREAM s, uint16 length)
|
||||
{
|
||||
int n;
|
||||
uint8 type, *next;
|
||||
uint16 len_src_descriptor, len_combined_caps, num_capsets, capset_type, capset_length;
|
||||
uint8 *next, *start;
|
||||
uint16 ncapsets, capset_type, capset_length;
|
||||
|
||||
in_uint32_le(s, g_rdp_shareid);
|
||||
in_uint16_le(s, len_src_descriptor);
|
||||
in_uint16_le(s, len_combined_caps);
|
||||
in_uint8s(s, len_src_descriptor);
|
||||
start = s->p;
|
||||
|
||||
in_uint16_le(s, num_capsets);
|
||||
in_uint16_le(s, ncapsets);
|
||||
in_uint8s(s, 2); /* pad */
|
||||
|
||||
DEBUG(("DEMAND_ACTIVE(id=0x%x,num_caps=%d)\n", g_rdp_shareid, num_capsets));
|
||||
|
||||
for (n = 0; n < num_capsets; n++)
|
||||
for (n = 0; n < ncapsets; n++)
|
||||
{
|
||||
if (s->p > start + length)
|
||||
return;
|
||||
|
||||
in_uint16_le(s, capset_type);
|
||||
in_uint16_le(s, capset_length);
|
||||
|
||||
@ -704,6 +783,22 @@ process_demand_active(STREAM s)
|
||||
|
||||
s->p = next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Respond to a demand active PDU */
|
||||
static void
|
||||
process_demand_active(STREAM s)
|
||||
{
|
||||
uint8 type;
|
||||
uint16 len_src_descriptor, len_combined_caps;
|
||||
|
||||
in_uint32_le(s, g_rdp_shareid);
|
||||
in_uint16_le(s, len_src_descriptor);
|
||||
in_uint16_le(s, len_combined_caps);
|
||||
in_uint8s(s, len_src_descriptor);
|
||||
|
||||
DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
|
||||
rdp_process_server_caps(s, len_combined_caps);
|
||||
|
||||
rdp_send_confirm_active();
|
||||
rdp_send_synchronise();
|
||||
@ -716,6 +811,7 @@ process_demand_active(STREAM s)
|
||||
|
||||
if (g_use_rdp5)
|
||||
{
|
||||
rdp_enum_bmpcache2();
|
||||
rdp_send_fonts(3);
|
||||
}
|
||||
else
|
||||
|
22
types.h
22
types.h
@ -119,6 +119,28 @@ typedef struct _VCHANNEL
|
||||
}
|
||||
VCHANNEL;
|
||||
|
||||
typedef struct _BMPCACHEENTRY
|
||||
{
|
||||
HBITMAP bitmap;
|
||||
uint32 usage;
|
||||
|
||||
}
|
||||
BMPCACHEENTRY;
|
||||
|
||||
/* PSTCACHE */
|
||||
|
||||
typedef uint8 BITMAP_ID[8];
|
||||
|
||||
/* Header for an entry in the persistent bitmap cache file */
|
||||
typedef struct _PSTCACHE_CELLHEADER
|
||||
{
|
||||
BITMAP_ID bitmap_id;
|
||||
uint8 width, height;
|
||||
uint16 length;
|
||||
uint32 stamp;
|
||||
}
|
||||
CELLHEADER;
|
||||
|
||||
#define MAX_CBSIZE 256
|
||||
|
||||
/* RDPSND */
|
||||
|
14
xwin.c
14
xwin.c
@ -47,6 +47,8 @@ extern uint32 g_embed_wnd;
|
||||
BOOL g_enable_compose = False;
|
||||
BOOL g_Unobscured; /* used for screenblt */
|
||||
static GC g_gc = NULL;
|
||||
static GC g_create_bitmap_gc = NULL;
|
||||
static GC g_create_glyph_gc = NULL;
|
||||
static Visual *g_visual;
|
||||
static int g_depth;
|
||||
static int g_bpp;
|
||||
@ -969,6 +971,9 @@ ui_create_window(void)
|
||||
if (g_gc == NULL)
|
||||
g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
|
||||
|
||||
if (g_create_bitmap_gc == NULL)
|
||||
g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
|
||||
|
||||
if ((g_ownbackstore) && (g_backstore == 0))
|
||||
{
|
||||
g_backstore = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
|
||||
@ -1481,7 +1486,7 @@ ui_create_bitmap(int width, int height, uint8 * data)
|
||||
image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
|
||||
(char *) tdata, width, height, bitmap_pad, 0);
|
||||
|
||||
XPutImage(g_display, bitmap, g_gc, image, 0, 0, 0, 0, width, height);
|
||||
XPutImage(g_display, bitmap, g_create_bitmap_gc, image, 0, 0, 0, 0, width, height);
|
||||
|
||||
XFree(image);
|
||||
if (tdata != data)
|
||||
@ -1539,12 +1544,12 @@ ui_create_glyph(int width, int height, uint8 * data)
|
||||
XImage *image;
|
||||
Pixmap bitmap;
|
||||
int scanline;
|
||||
GC gc;
|
||||
|
||||
scanline = (width + 7) / 8;
|
||||
|
||||
bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
|
||||
gc = XCreateGC(g_display, bitmap, 0, NULL);
|
||||
if (g_create_glyph_gc == 0)
|
||||
g_create_glyph_gc = XCreateGC(g_display, bitmap, 0, NULL);
|
||||
|
||||
image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
|
||||
width, height, 8, scanline);
|
||||
@ -1552,10 +1557,9 @@ ui_create_glyph(int width, int height, uint8 * data)
|
||||
image->bitmap_bit_order = MSBFirst;
|
||||
XInitImage(image);
|
||||
|
||||
XPutImage(g_display, bitmap, gc, image, 0, 0, 0, 0, width, height);
|
||||
XPutImage(g_display, bitmap, g_create_glyph_gc, image, 0, 0, 0, 0, width, height);
|
||||
|
||||
XFree(image);
|
||||
XFreeGC(g_display, gc);
|
||||
return (HGLYPH) bitmap;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user