diff options
-rw-r--r-- | uirdesktop/bitmap.c | 2506 | ||||
-rwxr-xr-x | uirdesktop/bsops.c | 1644 | ||||
-rwxr-xr-x | uirdesktop/bsops.h | 98 | ||||
-rwxr-xr-x | uirdesktop/constants.h | 12 | ||||
-rwxr-xr-x | uirdesktop/example-winrdesktop.ini | 16 | ||||
-rwxr-xr-x | uirdesktop/licence.c | 66 | ||||
-rwxr-xr-x | uirdesktop/makefile_win32 | 38 | ||||
-rw-r--r-- | uirdesktop/pstcache.c | 2 | ||||
-rw-r--r-- | uirdesktop/rdesktop.h | 20 | ||||
-rw-r--r-- | uirdesktop/rdp.c | 2914 | ||||
-rw-r--r-- | uirdesktop/secure.c | 228 | ||||
-rwxr-xr-x | uirdesktop/ssl_calls.c | 46 | ||||
-rw-r--r-- | uirdesktop/tcp.c | 32 | ||||
-rw-r--r-- | uirdesktop/types.h | 4 | ||||
-rwxr-xr-x | uirdesktop/uimain.c | 2252 | ||||
-rwxr-xr-x | uirdesktop/uimain.h | 168 | ||||
-rwxr-xr-x | uirdesktop/win32.c | 3466 |
17 files changed, 6759 insertions, 6753 deletions
diff --git a/uirdesktop/bitmap.c b/uirdesktop/bitmap.c index e9e4ed3a..1dc384e7 100644 --- a/uirdesktop/bitmap.c +++ b/uirdesktop/bitmap.c @@ -1,1253 +1,1253 @@ -/* -*- c-basic-offset: 8 -*-
- rdesktop: A Remote Desktop Protocol client.
- Bitmap decompression routines
- Copyright (C) Matthew Chapman 1999-2005
-
- 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.
-*/
-
-/* three seperate function for speed when decompressing the bitmaps */
-/* when modifing one function make the change in the others */
-/* comment out #define BITMAP_SPEED_OVER_SIZE below for one slower function */
-/* j@american-data.com */
-
-/* indent is confused by this file */
-/* *INDENT-OFF* */
-
-#include "rdesktop.h"
-#include "uimain.h"
-
-#define CVAL(p) (*(p++))
-#ifdef NEED_ALIGN
-#ifdef L_ENDIAN
-#define CVAL2(p, v) { v = (*(p++)); v |= (*(p++)) << 8; }
-#else
-#define CVAL2(p, v) { v = (*(p++)) << 8; v |= (*(p++)); }
-#endif /* L_ENDIAN */
-#else
-#define CVAL2(p, v) { v = (*((uint16*)p)); p += 2; }
-#endif /* NEED_ALIGN */
-
-#define UNROLL8(exp) { exp exp exp exp exp exp exp exp }
-
-#define REPEAT(statement) \
-{ \
- while((count & ~0x7) && ((x+8) < width)) \
- UNROLL8( statement; count--; x++; ); \
- \
- while((count > 0) && (x < width)) \
- { \
- statement; \
- count--; \
- x++; \
- } \
-}
-
-#define MASK_UPDATE() \
-{ \
- mixmask <<= 1; \
- if (mixmask == 0) \
- { \
- mask = fom_mask ? fom_mask : CVAL(input); \
- mixmask = 1; \
- } \
-}
-
-/* 1 byte bitmap decompress */
-static BOOL
-bitmap_decompress1(uint8 * output, int width, int height, uint8 * input, int size)
-{
- uint8 *end = input + size;
- uint8 *prevline = NULL, *line = NULL;
- int opcode, count, offset, isfillormix, x = width;
- int lastopcode = -1, insertmix = False, bicolour = False;
- uint8 code;
- uint8 colour1 = 0, colour2 = 0;
- uint8 mixmask, mask = 0;
- uint8 mix = 0xff;
- int fom_mask;
-
- while (input < end)
- {
- fom_mask = 0;
- code = CVAL(input);
- opcode = code >> 4;
- /* Handle different opcode forms */
- switch (opcode)
- {
- case 0xc:
- case 0xd:
- case 0xe:
- opcode -= 6;
- count = code & 0xf;
- offset = 16;
- break;
- case 0xf:
- opcode = code & 0xf;
- if (opcode < 9)
- {
- count = CVAL(input);
- count |= CVAL(input) << 8;
- }
- else
- {
- count = (opcode < 0xb) ? 8 : 1;
- }
- offset = 0;
- break;
- default:
- opcode >>= 1;
- count = code & 0x1f;
- offset = 32;
- break;
- }
- /* Handle strange cases for counts */
- if (offset != 0)
- {
- isfillormix = ((opcode == 2) || (opcode == 7));
- if (count == 0)
- {
- if (isfillormix)
- count = CVAL(input) + 1;
- else
- count = CVAL(input) + offset;
- }
- else if (isfillormix)
- {
- count <<= 3;
- }
- }
- /* Read preliminary data */
- switch (opcode)
- {
- case 0: /* Fill */
- if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
- insertmix = True;
- break;
- case 8: /* Bicolour */
- colour1 = CVAL(input);
- case 3: /* Colour */
- colour2 = CVAL(input);
- break;
- case 6: /* SetMix/Mix */
- case 7: /* SetMix/FillOrMix */
- mix = CVAL(input);
- opcode -= 5;
- break;
- case 9: /* FillOrMix_1 */
- mask = 0x03;
- opcode = 0x02;
- fom_mask = 3;
- break;
- case 0x0a: /* FillOrMix_2 */
- mask = 0x05;
- opcode = 0x02;
- fom_mask = 5;
- break;
- }
- lastopcode = opcode;
- mixmask = 0;
- /* Output body */
- while (count > 0)
- {
- if (x >= width)
- {
- if (height <= 0)
- return False;
- x = 0;
- height--;
- prevline = line;
- line = output + height * width;
- }
- switch (opcode)
- {
- case 0: /* Fill */
- 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
- {
- REPEAT(line[x] = prevline[x])
- }
- break;
- case 1: /* Mix */
- if (prevline == NULL)
- {
- REPEAT(line[x] = mix)
- }
- else
- {
- REPEAT(line[x] = prevline[x] ^ mix)
- }
- break;
- case 2: /* Fill or Mix */
- if (prevline == NULL)
- {
- REPEAT
- (
- MASK_UPDATE();
- if (mask & mixmask)
- line[x] = mix;
- else
- line[x] = 0;
- )
- }
- else
- {
- REPEAT
- (
- MASK_UPDATE();
- if (mask & mixmask)
- line[x] = prevline[x] ^ mix;
- else
- line[x] = prevline[x];
- )
- }
- break;
- case 3: /* Colour */
- REPEAT(line[x] = colour2)
- break;
- case 4: /* Copy */
- REPEAT(line[x] = CVAL(input))
- break;
- case 8: /* Bicolour */
- REPEAT
- (
- if (bicolour)
- {
- line[x] = colour2;
- bicolour = False;
- }
- else
- {
- line[x] = colour1;
- bicolour = True; count++;
- }
- )
- break;
- case 0xd: /* White */
- REPEAT(line[x] = 0xff)
- break;
- case 0xe: /* Black */
- REPEAT(line[x] = 0)
- break;
- default:
- unimpl("bitmap opcode 0x%x\n", opcode);
- return False;
- }
- }
- }
- return True;
-}
-
-/* 2 byte bitmap decompress */
-static BOOL
-bitmap_decompress2(uint8 * output, int width, int height, uint8 * input, int size)
-{
- uint8 *end = input + size;
- uint16 *prevline = NULL, *line = NULL;
- int opcode, count, offset, isfillormix, x = width;
- int lastopcode = -1, insertmix = False, bicolour = False;
- uint8 code;
- uint16 colour1 = 0, colour2 = 0;
- uint8 mixmask, mask = 0;
- uint16 mix = 0xffff;
- int fom_mask;
-
- while (input < end)
- {
- fom_mask = 0;
- code = CVAL(input);
- opcode = code >> 4;
- /* Handle different opcode forms */
- switch (opcode)
- {
- case 0xc:
- case 0xd:
- case 0xe:
- opcode -= 6;
- count = code & 0xf;
- offset = 16;
- break;
- case 0xf:
- opcode = code & 0xf;
- if (opcode < 9)
- {
- count = CVAL(input);
- count |= CVAL(input) << 8;
- }
- else
- {
- count = (opcode < 0xb) ? 8 : 1;
- }
- offset = 0;
- break;
- default:
- opcode >>= 1;
- count = code & 0x1f;
- offset = 32;
- break;
- }
- /* Handle strange cases for counts */
- if (offset != 0)
- {
- isfillormix = ((opcode == 2) || (opcode == 7));
- if (count == 0)
- {
- if (isfillormix)
- count = CVAL(input) + 1;
- else
- count = CVAL(input) + offset;
- }
- else if (isfillormix)
- {
- count <<= 3;
- }
- }
- /* Read preliminary data */
- switch (opcode)
- {
- case 0: /* Fill */
- if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
- insertmix = True;
- break;
- case 8: /* Bicolour */
- CVAL2(input, colour1);
- case 3: /* Colour */
- CVAL2(input, colour2);
- break;
- case 6: /* SetMix/Mix */
- case 7: /* SetMix/FillOrMix */
- CVAL2(input, mix);
- opcode -= 5;
- break;
- case 9: /* FillOrMix_1 */
- mask = 0x03;
- opcode = 0x02;
- fom_mask = 3;
- break;
- case 0x0a: /* FillOrMix_2 */
- mask = 0x05;
- opcode = 0x02;
- fom_mask = 5;
- break;
- }
- lastopcode = opcode;
- mixmask = 0;
- /* Output body */
- while (count > 0)
- {
- if (x >= width)
- {
- if (height <= 0)
- return False;
- x = 0;
- height--;
- prevline = line;
- line = ((uint16 *) output) + height * width;
- }
- switch (opcode)
- {
- case 0: /* Fill */
- 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
- {
- REPEAT(line[x] = prevline[x])
- }
- break;
- case 1: /* Mix */
- if (prevline == NULL)
- {
- REPEAT(line[x] = mix)
- }
- else
- {
- REPEAT(line[x] = prevline[x] ^ mix)
- }
- break;
- case 2: /* Fill or Mix */
- if (prevline == NULL)
- {
- REPEAT
- (
- MASK_UPDATE();
- if (mask & mixmask)
- line[x] = mix;
- else
- line[x] = 0;
- )
- }
- else
- {
- REPEAT
- (
- MASK_UPDATE();
- if (mask & mixmask)
- line[x] = prevline[x] ^ mix;
- else
- line[x] = prevline[x];
- )
- }
- break;
- case 3: /* Colour */
- REPEAT(line[x] = colour2)
- break;
- case 4: /* Copy */
- REPEAT(CVAL2(input, line[x]))
- break;
- case 8: /* Bicolour */
- REPEAT
- (
- if (bicolour)
- {
- line[x] = colour2;
- bicolour = False;
- }
- else
- {
- line[x] = colour1;
- bicolour = True;
- count++;
- }
- )
- break;
- case 0xd: /* White */
- REPEAT(line[x] = 0xffff)
- break;
- case 0xe: /* Black */
- REPEAT(line[x] = 0)
- break;
- default:
- unimpl("bitmap opcode 0x%x\n", opcode);
- return False;
- }
- }
- }
- return True;
-}
-
-/* 3 byte bitmap decompress */
-static BOOL
-bitmap_decompress3(uint8 * output, int width, int height, uint8 * input, int size)
-{
- uint8 *end = input + size;
- uint8 *prevline = NULL, *line = NULL;
- int opcode, count, offset, isfillormix, x = width;
- int lastopcode = -1, insertmix = False, bicolour = False;
- uint8 code;
- uint8 colour1[3] = {0, 0, 0}, colour2[3] = {0, 0, 0};
- uint8 mixmask, mask = 0;
- uint8 mix[3] = {0xff, 0xff, 0xff};
- int fom_mask;
-
- while (input < end)
- {
- fom_mask = 0;
- code = CVAL(input);
- opcode = code >> 4;
- /* Handle different opcode forms */
- switch (opcode)
- {
- case 0xc:
- case 0xd:
- case 0xe:
- opcode -= 6;
- count = code & 0xf;
- offset = 16;
- break;
- case 0xf:
- opcode = code & 0xf;
- if (opcode < 9)
- {
- count = CVAL(input);
- count |= CVAL(input) << 8;
- }
- else
- {
- count = (opcode <
- 0xb) ? 8 : 1;
- }
- offset = 0;
- break;
- default:
- opcode >>= 1;
- count = code & 0x1f;
- offset = 32;
- break;
- }
- /* Handle strange cases for counts */
- if (offset != 0)
- {
- isfillormix = ((opcode == 2) || (opcode == 7));
- if (count == 0)
- {
- if (isfillormix)
- count = CVAL(input) + 1;
- else
- count = CVAL(input) + offset;
- }
- else if (isfillormix)
- {
- count <<= 3;
- }
- }
- /* Read preliminary data */
- switch (opcode)
- {
- case 0: /* Fill */
- if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
- insertmix = True;
- break;
- case 8: /* Bicolour */
- colour1[0] = CVAL(input);
- colour1[1] = CVAL(input);
- colour1[2] = CVAL(input);
- case 3: /* Colour */
- colour2[0] = CVAL(input);
- colour2[1] = CVAL(input);
- colour2[2] = CVAL(input);
- break;
- case 6: /* SetMix/Mix */
- case 7: /* SetMix/FillOrMix */
- mix[0] = CVAL(input);
- mix[1] = CVAL(input);
- mix[2] = CVAL(input);
- opcode -= 5;
- break;
- case 9: /* FillOrMix_1 */
- mask = 0x03;
- opcode = 0x02;
- fom_mask = 3;
- break;
- case 0x0a: /* FillOrMix_2 */
- mask = 0x05;
- opcode = 0x02;
- fom_mask = 5;
- break;
- }
- lastopcode = opcode;
- mixmask = 0;
- /* Output body */
- while (count > 0)
- {
- if (x >= width)
- {
- if (height <= 0)
- return False;
- x = 0;
- height--;
- prevline = line;
- line = output + height * (width * 3);
- }
- switch (opcode)
- {
- case 0: /* Fill */
- if (insertmix)
- {
- if (prevline == NULL)
- {
- line[x * 3] = mix[0];
- line[x * 3 + 1] = mix[1];
- line[x * 3 + 2] = mix[2];
- }
- else
- {
- line[x * 3] =
- prevline[x * 3] ^ mix[0];
- line[x * 3 + 1] =
- prevline[x * 3 + 1] ^ mix[1];
- line[x * 3 + 2] =
- prevline[x * 3 + 2] ^ mix[2];
- }
- insertmix = False;
- count--;
- x++;
- }
- if (prevline == NULL)
- {
- REPEAT
- (
- line[x * 3] = 0;
- line[x * 3 + 1] = 0;
- line[x * 3 + 2] = 0;
- )
- }
- else
- {
- REPEAT
- (
- line[x * 3] = prevline[x * 3];
- line[x * 3 + 1] = prevline[x * 3 + 1];
- line[x * 3 + 2] = prevline[x * 3 + 2];
- )
- }
- break;
- case 1: /* Mix */
- if (prevline == NULL)
- {
- REPEAT
- (
- line[x * 3] = mix[0];
- line[x * 3 + 1] = mix[1];
- line[x * 3 + 2] = mix[2];
- )
- }
- else
- {
- REPEAT
- (
- line[x * 3] =
- prevline[x * 3] ^ mix[0];
- line[x * 3 + 1] =
- prevline[x * 3 + 1] ^ mix[1];
- line[x * 3 + 2] =
- prevline[x * 3 + 2] ^ mix[2];
- )
- }
- break;
- case 2: /* Fill or Mix */
- if (prevline == NULL)
- {
- REPEAT
- (
- MASK_UPDATE();
- if (mask & mixmask)
- {
- line[x * 3] = mix[0];
- line[x * 3 + 1] = mix[1];
- line[x * 3 + 2] = mix[2];
- }
- else
- {
- line[x * 3] = 0;
- line[x * 3 + 1] = 0;
- line[x * 3 + 2] = 0;
- }
- )
- }
- else
- {
- REPEAT
- (
- MASK_UPDATE();
- if (mask & mixmask)
- {
- line[x * 3] =
- prevline[x * 3] ^ mix [0];
- line[x * 3 + 1] =
- prevline[x * 3 + 1] ^ mix [1];
- line[x * 3 + 2] =
- prevline[x * 3 + 2] ^ mix [2];
- }
- else
- {
- line[x * 3] =
- prevline[x * 3];
- line[x * 3 + 1] =
- prevline[x * 3 + 1];
- line[x * 3 + 2] =
- prevline[x * 3 + 2];
- }
- )
- }
- break;
- case 3: /* Colour */
- REPEAT
- (
- line[x * 3] = colour2 [0];
- line[x * 3 + 1] = colour2 [1];
- line[x * 3 + 2] = colour2 [2];
- )
- break;
- case 4: /* Copy */
- REPEAT
- (
- line[x * 3] = CVAL(input);
- line[x * 3 + 1] = CVAL(input);
- line[x * 3 + 2] = CVAL(input);
- )
- break;
- case 8: /* Bicolour */
- REPEAT
- (
- if (bicolour)
- {
- line[x * 3] = colour2[0];
- line[x * 3 + 1] = colour2[1];
- line[x * 3 + 2] = colour2[2];
- bicolour = False;
- }
- else
- {
- line[x * 3] = colour1[0];
- line[x * 3 + 1] = colour1[1];
- line[x * 3 + 2] = colour1[2];
- bicolour = True;
- count++;
- }
- )
- break;
- case 0xd: /* White */
- REPEAT
- (
- line[x * 3] = 0xff;
- line[x * 3 + 1] = 0xff;
- line[x * 3 + 2] = 0xff;
- )
- break;
- case 0xe: /* Black */
- REPEAT
- (
- line[x * 3] = 0;
- line[x * 3 + 1] = 0;
- line[x * 3 + 2] = 0;
- )
- break;
- default:
- unimpl("bitmap opcode 0x%x\n", opcode);
- return False;
- }
- }
- }
- return True;
-}
-
-/* main decompress function */
-BOOL
-bitmap_decompress(uint8 * output, int width, int height, uint8 * input, int size, int Bpp)
-{
- BOOL rv = False;
- switch (Bpp)
- {
- case 1:
- rv = bitmap_decompress1(output, width, height, input, size);
- break;
- case 2:
- rv = bitmap_decompress2(output, width, height, input, size);
- break;
- case 3:
- rv = bitmap_decompress3(output, width, height, input, size);
- break;
- }
- return rv;
-}
-
-/* 2 byte bitmap decompress */
-static BOOL
-bitmap_decompress_ex_16_to_32(uint8 * output, int width, int height, uint8 * input, int size)
-{
- uint8 * end = input + size;
- int * prevline = NULL, * line = NULL;
- int opcode, count, offset, isfillormix, x = width;
- int lastopcode = -1, insertmix = False, bicolour = False;
- uint8 code;
- int colour1 = 0, colour2 = 0;
- uint8 mixmask, mask = 0;
- int mix = 0xffffff;
- int fom_mask;
- int p, r, g, b;
-
- while (input < end)
- {
- fom_mask = 0;
- code = CVAL(input);
- opcode = code >> 4;
- /* Handle different opcode forms */
- switch (opcode)
- {
- case 0xc:
- case 0xd:
- case 0xe:
- opcode -= 6;
- count = code & 0xf;
- offset = 16;
- break;
- case 0xf:
- opcode = code & 0xf;
- if (opcode < 9)
- {
- count = CVAL(input);
- count |= CVAL(input) << 8;
- }
- else
- {
- count = (opcode < 0xb) ? 8 : 1;
- }
- offset = 0;
- break;
- default:
- opcode >>= 1;
- count = code & 0x1f;
- offset = 32;
- break;
- }
- /* Handle strange cases for counts */
- if (offset != 0)
- {
- isfillormix = ((opcode == 2) || (opcode == 7));
- if (count == 0)
- {
- if (isfillormix)
- {
- count = CVAL(input) + 1;
- }
- else
- {
- count = CVAL(input) + offset;
- }
- }
- else if (isfillormix)
- {
- count <<= 3;
- }
- }
- /* Read preliminary data */
- switch (opcode)
- {
- case 0: /* Fill */
- if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
- {
- insertmix = True;
- }
- break;
- case 8: /* Bicolour */
- CVAL2(input, p);
- SPLIT_COLOUR16(p, r, g, b);
- MAKE_COLOUR32(p, r, g, b);
- colour1 = p;
- case 3: /* Colour */
- CVAL2(input, p);
- SPLIT_COLOUR16(p, r, g, b);
- MAKE_COLOUR32(p, r, g, b);
- colour2 = p;
- break;
- case 6: /* SetMix/Mix */
- case 7: /* SetMix/FillOrMix */
- CVAL2(input, p);
- SPLIT_COLOUR16(p, r, g, b);
- MAKE_COLOUR32(p, r, g, b);
- mix = p;
- opcode -= 5;
- break;
- case 9: /* FillOrMix_1 */
- mask = 0x03;
- opcode = 0x02;
- fom_mask = 3;
- break;
- case 0x0a: /* FillOrMix_2 */
- mask = 0x05;
- opcode = 0x02;
- fom_mask = 5;
- break;
- }
- lastopcode = opcode;
- mixmask = 0;
- /* Output body */
- while (count > 0)
- {
- if (x >= width)
- {
- if (height <= 0)
- {
- return False;
- }
- x = 0;
- height--;
- prevline = line;
- line = ((int *) output) + height * width;
- }
- switch (opcode)
- {
- case 0: /* Fill */
- 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
- {
- REPEAT(line[x] = prevline[x])
- }
- break;
- case 1: /* Mix */
- if (prevline == NULL)
- {
- REPEAT(line[x] = mix)
- }
- else
- {
- REPEAT(line[x] = prevline[x] ^ mix)
- }
- break;
- case 2: /* Fill or Mix */
- if (prevline == NULL)
- {
- REPEAT
- (
- MASK_UPDATE();
- if (mask & mixmask)
- {
- line[x] = mix;
- }
- else
- {
- line[x] = 0;
- }
- )
- }
- else
- {
- REPEAT
- (
- MASK_UPDATE();
- if (mask & mixmask)
- {
- line[x] = prevline[x] ^ mix;
- }
- else
- {
- line[x] = prevline[x];
- }
- )
- }
- break;
- case 3: /* Colour */
- REPEAT(line[x] = colour2)
- break;
- case 4: /* Copy */
- REPEAT
- (
- CVAL2(input, p);
- SPLIT_COLOUR16(p, r, g, b);
- MAKE_COLOUR32(p, r, g, b);
- line[x] = p;
- )
- break;
- case 8: /* Bicolour */
- REPEAT
- (
- if (bicolour)
- {
- line[x] = colour2;
- bicolour = False;
- }
- else
- {
- line[x] = colour1;
- bicolour = True;
- count++;
- }
- )
- break;
- case 0xd: /* White */
- REPEAT(line[x] = 0xffffff)
- break;
- case 0xe: /* Black */
- REPEAT(line[x] = 0)
- break;
- default:
- unimpl("bitmap opcode 0x%x\n", opcode);
- return False;
- }
- }
- }
- return True;
-}
-
-/* 3 byte bitmap decompress */
-static BOOL
-bitmap_decompress_ex_24_to_32(uint8 * output, int width, int height, uint8 * input, int size)
-{
- uint8 * end = input + size;
- int * prevline = NULL, * line = NULL;
- int opcode, count, offset, isfillormix, x = width;
- int lastopcode = -1, insertmix = False, bicolour = False;
- uint8 code;
- int colour1 = 0, colour2 = 0;
- uint8 mixmask, mask = 0;
- int mix = 0xffffff;
- int fom_mask;
- int p, r, g, b;
-
- while (input < end)
- {
- fom_mask = 0;
- code = CVAL(input);
- opcode = code >> 4;
- /* Handle different opcode forms */
- switch (opcode)
- {
- case 0xc:
- case 0xd:
- case 0xe:
- opcode -= 6;
- count = code & 0xf;
- offset = 16;
- break;
- case 0xf:
- opcode = code & 0xf;
- if (opcode < 9)
- {
- count = CVAL(input);
- count |= CVAL(input) << 8;
- }
- else
- {
- count = (opcode <
- 0xb) ? 8 : 1;
- }
- offset = 0;
- break;
- default:
- opcode >>= 1;
- count = code & 0x1f;
- offset = 32;
- break;
- }
- /* Handle strange cases for counts */
- if (offset != 0)
- {
- isfillormix = ((opcode == 2) || (opcode == 7));
- if (count == 0)
- {
- if (isfillormix)
- count = CVAL(input) + 1;
- else
- count = CVAL(input) + offset;
- }
- else if (isfillormix)
- {
- count <<= 3;
- }
- }
- /* Read preliminary data */
- switch (opcode)
- {
- case 0: /* Fill */
- if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
- insertmix = True;
- break;
- case 8: /* Bicolour */
- b = CVAL(input);
- g = CVAL(input);
- r = CVAL(input);
- MAKE_COLOUR32(p, r, g, b);
- colour1 = p;
- case 3: /* Colour */
- b = CVAL(input);
- g = CVAL(input);
- r = CVAL(input);
- MAKE_COLOUR32(p, r, g, b);
- colour2 = p;
- break;
- case 6: /* SetMix/Mix */
- case 7: /* SetMix/FillOrMix */
- b = CVAL(input);
- g = CVAL(input);
- r = CVAL(input);
- MAKE_COLOUR32(p, r, g, b);
- mix = p;
- opcode -= 5;
- break;
- case 9: /* FillOrMix_1 */
- mask = 0x03;
- opcode = 0x02;
- fom_mask = 3;
- break;
- case 0x0a: /* FillOrMix_2 */
- mask = 0x05;
- opcode = 0x02;
- fom_mask = 5;
- break;
- }
- lastopcode = opcode;
- mixmask = 0;
- /* Output body */
- while (count > 0)
- {
- if (x >= width)
- {
- if (height <= 0)
- return False;
- x = 0;
- height--;
- prevline = line;
- line = ((int *) output) + height * width;
- }
- switch (opcode)
- {
- case 0: /* Fill */
- 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
- {
- REPEAT(line[x] = prevline[x])
- }
- break;
- case 1: /* Mix */
- if (prevline == NULL)
- {
- REPEAT(line[x] = mix)
- }
- else
- {
- REPEAT(line[x] = prevline[x] ^ mix)
- }
- break;
- case 2: /* Fill or Mix */
- if (prevline == NULL)
- {
- REPEAT
- (
- MASK_UPDATE();
- if (mask & mixmask)
- {
- line[x] = mix;
- }
- else
- {
- line[x] = 0;
- }
- )
- }
- else
- {
- REPEAT
- (
- MASK_UPDATE();
- if (mask & mixmask)
- {
- line[x] = prevline[x] ^ mix;
- }
- else
- {
- line[x] = prevline[x];
- }
- )
- }
- break;
- case 3: /* Colour */
- REPEAT(line[x] = colour2)
- break;
- case 4: /* Copy */
- REPEAT
- (
- b = CVAL(input);
- g = CVAL(input);
- r = CVAL(input);
- MAKE_COLOUR32(p, r, g, b);
- line[x] = p;
- )
- break;
- case 8: /* Bicolour */
- REPEAT
- (
- if (bicolour)
- {
- line[x] = colour2;
- bicolour = False;
- }
- else
- {
- line[x] = colour1;
- bicolour = True;
- count++;
- }
- )
- break;
- case 0xd: /* White */
- REPEAT(line[x] = 0xffffff);
- break;
- case 0xe: /* Black */
- REPEAT(line[x] = 0);
- break;
- default:
- unimpl("bitmap opcode 0x%x\n", opcode);
- return False;
- }
- }
- }
- return True;
-}
-
-BOOL
-bitmap_decompress_ex(uint8 * output, int width, int height, uint8 * input, int size,
- int in_bpp, int out_bpp)
-{
- if (in_bpp == 16 && out_bpp == 32)
- {
- return bitmap_decompress_ex_16_to_32(output, width, height, input, size);
- }
- else if (in_bpp == 24 && out_bpp == 32)
- {
- return bitmap_decompress_ex_24_to_32(output, width, height, input, size);
- }
- return False;
-}
-
-/* *INDENT-ON* */
+/* -*- c-basic-offset: 8 -*- + rdesktop: A Remote Desktop Protocol client. + Bitmap decompression routines + Copyright (C) Matthew Chapman 1999-2005 + + 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. +*/ + +/* three seperate function for speed when decompressing the bitmaps */ +/* when modifing one function make the change in the others */ +/* comment out #define BITMAP_SPEED_OVER_SIZE below for one slower function */ +/* j@american-data.com */ + +/* indent is confused by this file */ +/* *INDENT-OFF* */ + +#include "rdesktop.h" +#include "uimain.h" + +#define CVAL(p) (*(p++)) +#ifdef NEED_ALIGN +#ifdef L_ENDIAN +#define CVAL2(p, v) { v = (*(p++)); v |= (*(p++)) << 8; } +#else +#define CVAL2(p, v) { v = (*(p++)) << 8; v |= (*(p++)); } +#endif /* L_ENDIAN */ +#else +#define CVAL2(p, v) { v = (*((uint16*)p)); p += 2; } +#endif /* NEED_ALIGN */ + +#define UNROLL8(exp) { exp exp exp exp exp exp exp exp } + +#define REPEAT(statement) \ +{ \ + while((count & ~0x7) && ((x+8) < width)) \ + UNROLL8( statement; count--; x++; ); \ + \ + while((count > 0) && (x < width)) \ + { \ + statement; \ + count--; \ + x++; \ + } \ +} + +#define MASK_UPDATE() \ +{ \ + mixmask <<= 1; \ + if (mixmask == 0) \ + { \ + mask = fom_mask ? fom_mask : CVAL(input); \ + mixmask = 1; \ + } \ +} + +/* 1 byte bitmap decompress */ +static BOOL +bitmap_decompress1(uint8 * output, int width, int height, uint8 * input, int size) +{ + uint8 *end = input + size; + uint8 *prevline = NULL, *line = NULL; + int opcode, count, offset, isfillormix, x = width; + int lastopcode = -1, insertmix = False, bicolour = False; + uint8 code; + uint8 colour1 = 0, colour2 = 0; + uint8 mixmask, mask = 0; + uint8 mix = 0xff; + int fom_mask; + + while (input < end) + { + fom_mask = 0; + code = CVAL(input); + opcode = code >> 4; + /* Handle different opcode forms */ + switch (opcode) + { + case 0xc: + case 0xd: + case 0xe: + opcode -= 6; + count = code & 0xf; + offset = 16; + break; + case 0xf: + opcode = code & 0xf; + if (opcode < 9) + { + count = CVAL(input); + count |= CVAL(input) << 8; + } + else + { + count = (opcode < 0xb) ? 8 : 1; + } + offset = 0; + break; + default: + opcode >>= 1; + count = code & 0x1f; + offset = 32; + break; + } + /* Handle strange cases for counts */ + if (offset != 0) + { + isfillormix = ((opcode == 2) || (opcode == 7)); + if (count == 0) + { + if (isfillormix) + count = CVAL(input) + 1; + else + count = CVAL(input) + offset; + } + else if (isfillormix) + { + count <<= 3; + } + } + /* Read preliminary data */ + switch (opcode) + { + case 0: /* Fill */ + if ((lastopcode == opcode) && !((x == width) && (prevline == NULL))) + insertmix = True; + break; + case 8: /* Bicolour */ + colour1 = CVAL(input); + case 3: /* Colour */ + colour2 = CVAL(input); + break; + case 6: /* SetMix/Mix */ + case 7: /* SetMix/FillOrMix */ + mix = CVAL(input); + opcode -= 5; + break; + case 9: /* FillOrMix_1 */ + mask = 0x03; + opcode = 0x02; + fom_mask = 3; + break; + case 0x0a: /* FillOrMix_2 */ + mask = 0x05; + opcode = 0x02; + fom_mask = 5; + break; + } + lastopcode = opcode; + mixmask = 0; + /* Output body */ + while (count > 0) + { + if (x >= width) + { + if (height <= 0) + return False; + x = 0; + height--; + prevline = line; + line = output + height * width; + } + switch (opcode) + { + case 0: /* Fill */ + 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 + { + REPEAT(line[x] = prevline[x]) + } + break; + case 1: /* Mix */ + if (prevline == NULL) + { + REPEAT(line[x] = mix) + } + else + { + REPEAT(line[x] = prevline[x] ^ mix) + } + break; + case 2: /* Fill or Mix */ + if (prevline == NULL) + { + REPEAT + ( + MASK_UPDATE(); + if (mask & mixmask) + line[x] = mix; + else + line[x] = 0; + ) + } + else + { + REPEAT + ( + MASK_UPDATE(); + if (mask & mixmask) + line[x] = prevline[x] ^ mix; + else + line[x] = prevline[x]; + ) + } + break; + case 3: /* Colour */ + REPEAT(line[x] = colour2) + break; + case 4: /* Copy */ + REPEAT(line[x] = CVAL(input)) + break; + case 8: /* Bicolour */ + REPEAT + ( + if (bicolour) + { + line[x] = colour2; + bicolour = False; + } + else + { + line[x] = colour1; + bicolour = True; count++; + } + ) + break; + case 0xd: /* White */ + REPEAT(line[x] = 0xff) + break; + case 0xe: /* Black */ + REPEAT(line[x] = 0) + break; + default: + unimpl("bitmap opcode 0x%x\n", opcode); + return False; + } + } + } + return True; +} + +/* 2 byte bitmap decompress */ +static BOOL +bitmap_decompress2(uint8 * output, int width, int height, uint8 * input, int size) +{ + uint8 *end = input + size; + uint16 *prevline = NULL, *line = NULL; + int opcode, count, offset, isfillormix, x = width; + int lastopcode = -1, insertmix = False, bicolour = False; + uint8 code; + uint16 colour1 = 0, colour2 = 0; + uint8 mixmask, mask = 0; + uint16 mix = 0xffff; + int fom_mask; + + while (input < end) + { + fom_mask = 0; + code = CVAL(input); + opcode = code >> 4; + /* Handle different opcode forms */ + switch (opcode) + { + case 0xc: + case 0xd: + case 0xe: + opcode -= 6; + count = code & 0xf; + offset = 16; + break; + case 0xf: + opcode = code & 0xf; + if (opcode < 9) + { + count = CVAL(input); + count |= CVAL(input) << 8; + } + else + { + count = (opcode < 0xb) ? 8 : 1; + } + offset = 0; + break; + default: + opcode >>= 1; + count = code & 0x1f; + offset = 32; + break; + } + /* Handle strange cases for counts */ + if (offset != 0) + { + isfillormix = ((opcode == 2) || (opcode == 7)); + if (count == 0) + { + if (isfillormix) + count = CVAL(input) + 1; + else + count = CVAL(input) + offset; + } + else if (isfillormix) + { + count <<= 3; + } + } + /* Read preliminary data */ + switch (opcode) + { + case 0: /* Fill */ + if ((lastopcode == opcode) && !((x == width) && (prevline == NULL))) + insertmix = True; + break; + case 8: /* Bicolour */ + CVAL2(input, colour1); + case 3: /* Colour */ + CVAL2(input, colour2); + break; + case 6: /* SetMix/Mix */ + case 7: /* SetMix/FillOrMix */ + CVAL2(input, mix); + opcode -= 5; + break; + case 9: /* FillOrMix_1 */ + mask = 0x03; + opcode = 0x02; + fom_mask = 3; + break; + case 0x0a: /* FillOrMix_2 */ + mask = 0x05; + opcode = 0x02; + fom_mask = 5; + break; + } + lastopcode = opcode; + mixmask = 0; + /* Output body */ + while (count > 0) + { + if (x >= width) + { + if (height <= 0) + return False; + x = 0; + height--; + prevline = line; + line = ((uint16 *) output) + height * width; + } + switch (opcode) + { + case 0: /* Fill */ + 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 + { + REPEAT(line[x] = prevline[x]) + } + break; + case 1: /* Mix */ + if (prevline == NULL) + { + REPEAT(line[x] = mix) + } + else + { + REPEAT(line[x] = prevline[x] ^ mix) + } + break; + case 2: /* Fill or Mix */ + if (prevline == NULL) + { + REPEAT + ( + MASK_UPDATE(); + if (mask & mixmask) + line[x] = mix; + else + line[x] = 0; + ) + } + else + { + REPEAT + ( + MASK_UPDATE(); + if (mask & mixmask) + line[x] = prevline[x] ^ mix; + else + line[x] = prevline[x]; + ) + } + break; + case 3: /* Colour */ + REPEAT(line[x] = colour2) + break; + case 4: /* Copy */ + REPEAT(CVAL2(input, line[x])) + break; + case 8: /* Bicolour */ + REPEAT + ( + if (bicolour) + { + line[x] = colour2; + bicolour = False; + } + else + { + line[x] = colour1; + bicolour = True; + count++; + } + ) + break; + case 0xd: /* White */ + REPEAT(line[x] = 0xffff) + break; + case 0xe: /* Black */ + REPEAT(line[x] = 0) + break; + default: + unimpl("bitmap opcode 0x%x\n", opcode); + return False; + } + } + } + return True; +} + +/* 3 byte bitmap decompress */ +static BOOL +bitmap_decompress3(uint8 * output, int width, int height, uint8 * input, int size) +{ + uint8 *end = input + size; + uint8 *prevline = NULL, *line = NULL; + int opcode, count, offset, isfillormix, x = width; + int lastopcode = -1, insertmix = False, bicolour = False; + uint8 code; + uint8 colour1[3] = {0, 0, 0}, colour2[3] = {0, 0, 0}; + uint8 mixmask, mask = 0; + uint8 mix[3] = {0xff, 0xff, 0xff}; + int fom_mask; + + while (input < end) + { + fom_mask = 0; + code = CVAL(input); + opcode = code >> 4; + /* Handle different opcode forms */ + switch (opcode) + { + case 0xc: + case 0xd: + case 0xe: + opcode -= 6; + count = code & 0xf; + offset = 16; + break; + case 0xf: + opcode = code & 0xf; + if (opcode < 9) + { + count = CVAL(input); + count |= CVAL(input) << 8; + } + else + { + count = (opcode < + 0xb) ? 8 : 1; + } + offset = 0; + break; + default: + opcode >>= 1; + count = code & 0x1f; + offset = 32; + break; + } + /* Handle strange cases for counts */ + if (offset != 0) + { + isfillormix = ((opcode == 2) || (opcode == 7)); + if (count == 0) + { + if (isfillormix) + count = CVAL(input) + 1; + else + count = CVAL(input) + offset; + } + else if (isfillormix) + { + count <<= 3; + } + } + /* Read preliminary data */ + switch (opcode) + { + case 0: /* Fill */ + if ((lastopcode == opcode) && !((x == width) && (prevline == NULL))) + insertmix = True; + break; + case 8: /* Bicolour */ + colour1[0] = CVAL(input); + colour1[1] = CVAL(input); + colour1[2] = CVAL(input); + case 3: /* Colour */ + colour2[0] = CVAL(input); + colour2[1] = CVAL(input); + colour2[2] = CVAL(input); + break; + case 6: /* SetMix/Mix */ + case 7: /* SetMix/FillOrMix */ + mix[0] = CVAL(input); + mix[1] = CVAL(input); + mix[2] = CVAL(input); + opcode -= 5; + break; + case 9: /* FillOrMix_1 */ + mask = 0x03; + opcode = 0x02; + fom_mask = 3; + break; + case 0x0a: /* FillOrMix_2 */ + mask = 0x05; + opcode = 0x02; + fom_mask = 5; + break; + } + lastopcode = opcode; + mixmask = 0; + /* Output body */ + while (count > 0) + { + if (x >= width) + { + if (height <= 0) + return False; + x = 0; + height--; + prevline = line; + line = output + height * (width * 3); + } + switch (opcode) + { + case 0: /* Fill */ + if (insertmix) + { + if (prevline == NULL) + { + line[x * 3] = mix[0]; + line[x * 3 + 1] = mix[1]; + line[x * 3 + 2] = mix[2]; + } + else + { + line[x * 3] = + prevline[x * 3] ^ mix[0]; + line[x * 3 + 1] = + prevline[x * 3 + 1] ^ mix[1]; + line[x * 3 + 2] = + prevline[x * 3 + 2] ^ mix[2]; + } + insertmix = False; + count--; + x++; + } + if (prevline == NULL) + { + REPEAT + ( + line[x * 3] = 0; + line[x * 3 + 1] = 0; + line[x * 3 + 2] = 0; + ) + } + else + { + REPEAT + ( + line[x * 3] = prevline[x * 3]; + line[x * 3 + 1] = prevline[x * 3 + 1]; + line[x * 3 + 2] = prevline[x * 3 + 2]; + ) + } + break; + case 1: /* Mix */ + if (prevline == NULL) + { + REPEAT + ( + line[x * 3] = mix[0]; + line[x * 3 + 1] = mix[1]; + line[x * 3 + 2] = mix[2]; + ) + } + else + { + REPEAT + ( + line[x * 3] = + prevline[x * 3] ^ mix[0]; + line[x * 3 + 1] = + prevline[x * 3 + 1] ^ mix[1]; + line[x * 3 + 2] = + prevline[x * 3 + 2] ^ mix[2]; + ) + } + break; + case 2: /* Fill or Mix */ + if (prevline == NULL) + { + REPEAT + ( + MASK_UPDATE(); + if (mask & mixmask) + { + line[x * 3] = mix[0]; + line[x * 3 + 1] = mix[1]; + line[x * 3 + 2] = mix[2]; + } + else + { + line[x * 3] = 0; + line[x * 3 + 1] = 0; + line[x * 3 + 2] = 0; + } + ) + } + else + { + REPEAT + ( + MASK_UPDATE(); + if (mask & mixmask) + { + line[x * 3] = + prevline[x * 3] ^ mix [0]; + line[x * 3 + 1] = + prevline[x * 3 + 1] ^ mix [1]; + line[x * 3 + 2] = + prevline[x * 3 + 2] ^ mix [2]; + } + else + { + line[x * 3] = + prevline[x * 3]; + line[x * 3 + 1] = + prevline[x * 3 + 1]; + line[x * 3 + 2] = + prevline[x * 3 + 2]; + } + ) + } + break; + case 3: /* Colour */ + REPEAT + ( + line[x * 3] = colour2 [0]; + line[x * 3 + 1] = colour2 [1]; + line[x * 3 + 2] = colour2 [2]; + ) + break; + case 4: /* Copy */ + REPEAT + ( + line[x * 3] = CVAL(input); + line[x * 3 + 1] = CVAL(input); + line[x * 3 + 2] = CVAL(input); + ) + break; + case 8: /* Bicolour */ + REPEAT + ( + if (bicolour) + { + line[x * 3] = colour2[0]; + line[x * 3 + 1] = colour2[1]; + line[x * 3 + 2] = colour2[2]; + bicolour = False; + } + else + { + line[x * 3] = colour1[0]; + line[x * 3 + 1] = colour1[1]; + line[x * 3 + 2] = colour1[2]; + bicolour = True; + count++; + } + ) + break; + case 0xd: /* White */ + REPEAT + ( + line[x * 3] = 0xff; + line[x * 3 + 1] = 0xff; + line[x * 3 + 2] = 0xff; + ) + break; + case 0xe: /* Black */ + REPEAT + ( + line[x * 3] = 0; + line[x * 3 + 1] = 0; + line[x * 3 + 2] = 0; + ) + break; + default: + unimpl("bitmap opcode 0x%x\n", opcode); + return False; + } + } + } + return True; +} + +/* main decompress function */ +BOOL +bitmap_decompress(uint8 * output, int width, int height, uint8 * input, int size, int Bpp) +{ + BOOL rv = False; + switch (Bpp) + { + case 1: + rv = bitmap_decompress1(output, width, height, input, size); + break; + case 2: + rv = bitmap_decompress2(output, width, height, input, size); + break; + case 3: + rv = bitmap_decompress3(output, width, height, input, size); + break; + } + return rv; +} + +/* 2 byte bitmap decompress */ +static BOOL +bitmap_decompress_ex_16_to_32(uint8 * output, int width, int height, uint8 * input, int size) +{ + uint8 * end = input + size; + int * prevline = NULL, * line = NULL; + int opcode, count, offset, isfillormix, x = width; + int lastopcode = -1, insertmix = False, bicolour = False; + uint8 code; + int colour1 = 0, colour2 = 0; + uint8 mixmask, mask = 0; + int mix = 0xffffff; + int fom_mask; + int p, r, g, b; + + while (input < end) + { + fom_mask = 0; + code = CVAL(input); + opcode = code >> 4; + /* Handle different opcode forms */ + switch (opcode) + { + case 0xc: + case 0xd: + case 0xe: + opcode -= 6; + count = code & 0xf; + offset = 16; + break; + case 0xf: + opcode = code & 0xf; + if (opcode < 9) + { + count = CVAL(input); + count |= CVAL(input) << 8; + } + else + { + count = (opcode < 0xb) ? 8 : 1; + } + offset = 0; + break; + default: + opcode >>= 1; + count = code & 0x1f; + offset = 32; + break; + } + /* Handle strange cases for counts */ + if (offset != 0) + { + isfillormix = ((opcode == 2) || (opcode == 7)); + if (count == 0) + { + if (isfillormix) + { + count = CVAL(input) + 1; + } + else + { + count = CVAL(input) + offset; + } + } + else if (isfillormix) + { + count <<= 3; + } + } + /* Read preliminary data */ + switch (opcode) + { + case 0: /* Fill */ + if ((lastopcode == opcode) && !((x == width) && (prevline == NULL))) + { + insertmix = True; + } + break; + case 8: /* Bicolour */ + CVAL2(input, p); + SPLIT_COLOUR16(p, r, g, b); + MAKE_COLOUR32(p, r, g, b); + colour1 = p; + case 3: /* Colour */ + CVAL2(input, p); + SPLIT_COLOUR16(p, r, g, b); + MAKE_COLOUR32(p, r, g, b); + colour2 = p; + break; + case 6: /* SetMix/Mix */ + case 7: /* SetMix/FillOrMix */ + CVAL2(input, p); + SPLIT_COLOUR16(p, r, g, b); + MAKE_COLOUR32(p, r, g, b); + mix = p; + opcode -= 5; + break; + case 9: /* FillOrMix_1 */ + mask = 0x03; + opcode = 0x02; + fom_mask = 3; + break; + case 0x0a: /* FillOrMix_2 */ + mask = 0x05; + opcode = 0x02; + fom_mask = 5; + break; + } + lastopcode = opcode; + mixmask = 0; + /* Output body */ + while (count > 0) + { + if (x >= width) + { + if (height <= 0) + { + return False; + } + x = 0; + height--; + prevline = line; + line = ((int *) output) + height * width; + } + switch (opcode) + { + case 0: /* Fill */ + 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 + { + REPEAT(line[x] = prevline[x]) + } + break; + case 1: /* Mix */ + if (prevline == NULL) + { + REPEAT(line[x] = mix) + } + else + { + REPEAT(line[x] = prevline[x] ^ mix) + } + break; + case 2: /* Fill or Mix */ + if (prevline == NULL) + { + REPEAT + ( + MASK_UPDATE(); + if (mask & mixmask) + { + line[x] = mix; + } + else + { + line[x] = 0; + } + ) + } + else + { + REPEAT + ( + MASK_UPDATE(); + if (mask & mixmask) + { + line[x] = prevline[x] ^ mix; + } + else + { + line[x] = prevline[x]; + } + ) + } + break; + case 3: /* Colour */ + REPEAT(line[x] = colour2) + break; + case 4: /* Copy */ + REPEAT + ( + CVAL2(input, p); + SPLIT_COLOUR16(p, r, g, b); + MAKE_COLOUR32(p, r, g, b); + line[x] = p; + ) + break; + case 8: /* Bicolour */ + REPEAT + ( + if (bicolour) + { + line[x] = colour2; + bicolour = False; + } + else + { + line[x] = colour1; + bicolour = True; + count++; + } + ) + break; + case 0xd: /* White */ + REPEAT(line[x] = 0xffffff) + break; + case 0xe: /* Black */ + REPEAT(line[x] = 0) + break; + default: + unimpl("bitmap opcode 0x%x\n", opcode); + return False; + } + } + } + return True; +} + +/* 3 byte bitmap decompress */ +static BOOL +bitmap_decompress_ex_24_to_32(uint8 * output, int width, int height, uint8 * input, int size) +{ + uint8 * end = input + size; + int * prevline = NULL, * line = NULL; + int opcode, count, offset, isfillormix, x = width; + int lastopcode = -1, insertmix = False, bicolour = False; + uint8 code; + int colour1 = 0, colour2 = 0; + uint8 mixmask, mask = 0; + int mix = 0xffffff; + int fom_mask; + int p, r, g, b; + + while (input < end) + { + fom_mask = 0; + code = CVAL(input); + opcode = code >> 4; + /* Handle different opcode forms */ + switch (opcode) + { + case 0xc: + case 0xd: + case 0xe: + opcode -= 6; + count = code & 0xf; + offset = 16; + break; + case 0xf: + opcode = code & 0xf; + if (opcode < 9) + { + count = CVAL(input); + count |= CVAL(input) << 8; + } + else + { + count = (opcode < + 0xb) ? 8 : 1; + } + offset = 0; + break; + default: + opcode >>= 1; + count = code & 0x1f; + offset = 32; + break; + } + /* Handle strange cases for counts */ + if (offset != 0) + { + isfillormix = ((opcode == 2) || (opcode == 7)); + if (count == 0) + { + if (isfillormix) + count = CVAL(input) + 1; + else + count = CVAL(input) + offset; + } + else if (isfillormix) + { + count <<= 3; + } + } + /* Read preliminary data */ + switch (opcode) + { + case 0: /* Fill */ + if ((lastopcode == opcode) && !((x == width) && (prevline == NULL))) + insertmix = True; + break; + case 8: /* Bicolour */ + b = CVAL(input); + g = CVAL(input); + r = CVAL(input); + MAKE_COLOUR32(p, r, g, b); + colour1 = p; + case 3: /* Colour */ + b = CVAL(input); + g = CVAL(input); + r = CVAL(input); + MAKE_COLOUR32(p, r, g, b); + colour2 = p; + break; + case 6: /* SetMix/Mix */ + case 7: /* SetMix/FillOrMix */ + b = CVAL(input); + g = CVAL(input); + r = CVAL(input); + MAKE_COLOUR32(p, r, g, b); + mix = p; + opcode -= 5; + break; + case 9: /* FillOrMix_1 */ + mask = 0x03; + opcode = 0x02; + fom_mask = 3; + break; + case 0x0a: /* FillOrMix_2 */ + mask = 0x05; + opcode = 0x02; + fom_mask = 5; + break; + } + lastopcode = opcode; + mixmask = 0; + /* Output body */ + while (count > 0) + { + if (x >= width) + { + if (height <= 0) + return False; + x = 0; + height--; + prevline = line; + line = ((int *) output) + height * width; + } + switch (opcode) + { + case 0: /* Fill */ + 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 + { + REPEAT(line[x] = prevline[x]) + } + break; + case 1: /* Mix */ + if (prevline == NULL) + { + REPEAT(line[x] = mix) + } + else + { + REPEAT(line[x] = prevline[x] ^ mix) + } + break; + case 2: /* Fill or Mix */ + if (prevline == NULL) + { + REPEAT + ( + MASK_UPDATE(); + if (mask & mixmask) + { + line[x] = mix; + } + else + { + line[x] = 0; + } + ) + } + else + { + REPEAT + ( + MASK_UPDATE(); + if (mask & mixmask) + { + line[x] = prevline[x] ^ mix; + } + else + { + line[x] = prevline[x]; + } + ) + } + break; + case 3: /* Colour */ + REPEAT(line[x] = colour2) + break; + case 4: /* Copy */ + REPEAT + ( + b = CVAL(input); + g = CVAL(input); + r = CVAL(input); + MAKE_COLOUR32(p, r, g, b); + line[x] = p; + ) + break; + case 8: /* Bicolour */ + REPEAT + ( + if (bicolour) + { + line[x] = colour2; + bicolour = False; + } + else + { + line[x] = colour1; + bicolour = True; + count++; + } + ) + break; + case 0xd: /* White */ + REPEAT(line[x] = 0xffffff); + break; + case 0xe: /* Black */ + REPEAT(line[x] = 0); + break; + default: + unimpl("bitmap opcode 0x%x\n", opcode); + return False; + } + } + } + return True; +} + +BOOL +bitmap_decompress_ex(uint8 * output, int width, int height, uint8 * input, int size, + int in_bpp, int out_bpp) +{ + if (in_bpp == 16 && out_bpp == 32) + { + return bitmap_decompress_ex_16_to_32(output, width, height, input, size); + } + else if (in_bpp == 24 && out_bpp == 32) + { + return bitmap_decompress_ex_24_to_32(output, width, height, input, size); + } + return False; +} + +/* *INDENT-ON* */ diff --git a/uirdesktop/bsops.c b/uirdesktop/bsops.c index d70ef9c3..620e6002 100755 --- a/uirdesktop/bsops.c +++ b/uirdesktop/bsops.c @@ -1,822 +1,822 @@ -/* -*- c-basic-offset: 8 -*-
- rdesktop: A Remote Desktop Protocol client.
- Generics backingstore operations
- Copyright (C) Jay Sorg 2005-2006
-
- 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 <stdlib.h>
-#include <string.h>
-#include "bsops.h"
-
-/* externals */
-extern int g_width;
-extern int g_height;
-extern int g_bs_bpp;
-extern int g_bs_Bpp;
-extern char * g_bs;
-
-/* globals */
-static int g_clip_left = 0;
-static int g_clip_top = 0;
-static int g_clip_right = 800;
-static int g_clip_bottom = 600;
-
-/* for bs_patblt */
-static unsigned char g_hatch_patterns[] =
-{
- 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
- 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
- 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
- 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
- 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
- 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 /* 5 - bsDiagCross */
-};
-
-
-/*****************************************************************************/
-/* do a raster op */
-int
-bs_do_rop(int rop, int src, int dst)
-{
- switch (rop)
- {
- case 0x0: return 0;
- case 0x1: return ~(src | dst);
- case 0x2: return (~src) & dst;
- case 0x3: return ~src;
- case 0x4: return src & (~dst);
- case 0x5: return ~(dst);
- case 0x6: return src ^ dst;
- case 0x7: return ~(src & dst);
- case 0x8: return src & dst;
- case 0x9: return ~(src) ^ dst;
- case 0xa: return dst;
- case 0xb: return (~src) | dst;
- case 0xc: return src;
- case 0xd: return src | (~dst);
- case 0xe: return src | dst;
- case 0xf: return ~0;
- }
- return dst;
-}
-
-/*****************************************************************************/
-/* get a pixel from the in memory copy of whats on the screen */
-int
-bs_get_pixel(int x, int y)
-{
- char * p;
-
- if (x >= 0 && x < g_width && y >= 0 && y < g_height)
- {
- p = g_bs + (y * g_width * g_bs_Bpp) + (x * g_bs_Bpp);
- if (g_bs_Bpp == 1)
- {
- return *((unsigned char *) p);
- }
- else if (g_bs_Bpp == 2)
- {
- return *((unsigned short *) p);
- }
- else
- {
- return *((unsigned int *) p);
- }
- }
- else
- {
- return 0;
- }
-}
-
-/*****************************************************************************/
-/* set a pixel on the screen using the clip */
-void
-bs_set_pixel(int x, int y, int pixel, int rop, int use_clip)
-{
- char * p;
-
- if (!use_clip ||
- (x >= g_clip_left && x < g_clip_right &&
- y >= g_clip_top && y < g_clip_bottom))
- {
- if (x >= 0 && x < g_width && y >= 0 && y < g_height)
- {
- p = g_bs + (y * g_width * g_bs_Bpp) + (x * g_bs_Bpp);
- if (rop != 12)
- {
- pixel = bs_do_rop(rop, pixel, bs_get_pixel(x, y));
- }
- if (g_bs_Bpp == 1)
- {
- *((unsigned char *) p) = pixel;
- }
- else if (g_bs_Bpp == 2)
- {
- *((unsigned short *) p) = pixel;
- }
- else
- {
- *((unsigned int *) p) = pixel;
- }
- }
- }
-}
-
-/*****************************************************************************/
-static char *
-get_bs_ptr(int x, int y)
-{
- char * p;
-
- if (x >= 0 && x < g_width && y >= 0 && y < g_height)
- {
- p = g_bs + (y * g_width * g_bs_Bpp) + (x * g_bs_Bpp);
- return p;
- }
- else
- {
- return 0;
- }
-}
-
-/*****************************************************************************/
-void
-bs_init(void)
-{
- g_clip_left = 0;
- g_clip_top = 0;
- g_clip_right = g_width;
- g_clip_bottom = g_height;
-}
-
-/*****************************************************************************/
-void
-bs_exit(void)
-{
-}
-
-/*****************************************************************************/
-void
-bs_set_clip(int x, int y, int cx, int cy)
-{
- g_clip_left = x;
- g_clip_top = y;
- g_clip_right = x + cx;
- g_clip_bottom = y + cy;
-}
-
-/*****************************************************************************/
-void
-bs_reset_clip(void)
-{
- g_clip_left = 0;
- g_clip_top = 0;
- g_clip_right = g_width;
- g_clip_bottom = g_height;
-}
-
-/*****************************************************************************/
-/* check if a certain pixel is set in a bitmap */
-int
-bs_is_pixel_on(char * data, int x, int y, int width, int bpp)
-{
- int start;
- int shift;
-
- if (bpp == 1)
- {
- width = (width + 7) / 8;
- start = (y * width) + x / 8;
- shift = x % 8;
- return (data[start] & (0x80 >> shift)) != 0;
- }
- else if (bpp == 8)
- {
- return data[y * width + x] != 0;
- }
- else if (bpp == 24)
- {
- return data[(y * 3) * width + (x * 3)] != 0 &&
- data[(y * 3) * width + (x * 3) + 1] != 0 &&
- data[(y * 3) * width + (x * 3) + 2] != 0;
- }
- else
- {
- return 0;
- }
-}
-
-/*****************************************************************************/
-void
-bs_set_pixel_on(char * data, int x, int y, int width, int bpp,
- int pixel)
-{
- int start;
- int shift;
-
- if (bpp == 1)
- {
- width = (width + 7) / 8;
- start = (y * width) + x / 8;
- shift = x % 8;
- if (pixel != 0)
- {
- data[start] = data[start] | (0x80 >> shift);
- }
- else
- {
- data[start] = data[start] & ~(0x80 >> shift);
- }
- }
- else if (bpp == 8)
- {
- data[y * width + x] = pixel;
- }
- else if (bpp == 15 || bpp == 16)
- {
- ((unsigned short *) data)[y * width + x] = pixel;
- }
-}
-
-/*****************************************************************************/
-void
-bs_copy_mem(char * d, char * s, int n)
-{
- while (n & (~7))
- {
- *(d++) = *(s++);
- *(d++) = *(s++);
- *(d++) = *(s++);
- *(d++) = *(s++);
- *(d++) = *(s++);
- *(d++) = *(s++);
- *(d++) = *(s++);
- *(d++) = *(s++);
- n = n - 8;
- }
- while (n > 0)
- {
- *(d++) = *(s++);
- n--;
- }
-}
-
-/*****************************************************************************/
-void
-bs_copy_memb(char * d, char * s, int n)
-{
- d = (d + n) - 1;
- s = (s + n) - 1;
- while (n & (~7))
- {
- *(d--) = *(s--);
- *(d--) = *(s--);
- *(d--) = *(s--);
- *(d--) = *(s--);
- *(d--) = *(s--);
- *(d--) = *(s--);
- *(d--) = *(s--);
- *(d--) = *(s--);
- n = n - 8;
- }
- while (n > 0)
- {
- *(d--) = *(s--);
- n--;
- }
-}
-
-/*****************************************************************************/
-/* return true is the is something to draw */
-int
-bs_warp_coords(int * x, int * y, int * cx, int * cy,
- int * srcx, int * srcy)
-{
- int dx;
- int dy;
-
- if (g_clip_left > *x)
- {
- dx = g_clip_left - *x;
- }
- else
- {
- dx = 0;
- }
- if (g_clip_top > *y)
- {
- dy = g_clip_top - *y;
- }
- else
- {
- dy = 0;
- }
- if (*x + *cx > g_clip_right)
- {
- *cx = (*cx - ((*x + *cx) - g_clip_right));
- }
- if (*y + *cy > g_clip_bottom)
- {
- *cy = (*cy - ((*y + *cy) - g_clip_bottom));
- }
- *cx = *cx - dx;
- *cy = *cy - dy;
- if (*cx <= 0)
- {
- return 0;
- }
- if (*cy <= 0)
- {
- return 0;
- }
- *x = *x + dx;
- *y = *y + dy;
- if (srcx != 0)
- {
- *srcx = *srcx + dx;
- }
- if (srcy != 0)
- {
- *srcy = *srcy + dy;
- }
- return 1;
-}
-
-/*****************************************************************************/
-void
-bs_rect(int x, int y, int cx, int cy, int colour, int rop)
-{
- int i;
- int j;
- unsigned char * p8;
- unsigned short * p16;
- unsigned int * p32;
-
- if (bs_warp_coords(&x, &y, &cx, &cy, 0, 0))
- {
- if (rop == 0) /* black */
- {
- rop = 12;
- colour = 0;
- }
- else if (rop == 15) /* white */
- {
- rop = 12;
- colour = 0xffffff;
- }
- if (rop == 12) /* copy */
- {
- if (g_bs_Bpp == 1)
- {
- for (i = 0; i < cy; i++)
- {
- p8 = (unsigned char *) get_bs_ptr(x, y + i);
- if (p8 != 0)
- {
- for (j = 0; j < cx; j++)
- {
- *p8 = colour;
- p8++;
- }
- }
- }
- }
- else if (g_bs_Bpp == 2)
- {
- for (i = 0; i < cy; i++)
- {
- p16 = (unsigned short *) get_bs_ptr(x, y + i);
- if (p16 != 0)
- {
- for (j = 0; j < cx; j++)
- {
- *p16 = colour;
- p16++;
- }
- }
- }
- }
- else
- {
- for (i = 0; i < cy; i++)
- {
- p32 = (unsigned int *) get_bs_ptr(x, y + i);
- if (p32 != 0)
- {
- for (j = 0; j < cx; j++)
- {
- *p32 = colour;
- p32++;
- }
- }
- }
- }
- }
- else /* slow */
- {
- for (i = 0; i < cy; i++)
- {
- for (j = 0; j < cx; j++)
- {
- bs_set_pixel(j + x, i + y, colour, rop, 0);
- }
- }
- }
- }
-}
-
-/*****************************************************************************/
-void
-bs_screenblt(int rop, int x, int y, int cx, int cy,
- int srcx, int srcy)
-{
- int p;
- int i;
- int j;
- char * src;
- char * dst;
-
- if (bs_warp_coords(&x, &y, &cx, &cy, &srcx, &srcy))
- {
- if (rop == 12) /* copy */
- {
- if (srcy < y) /* copy down - bottom to top */
- {
- for (i = cy - 1; i >= 0; i--)
- {
- src = get_bs_ptr(srcx, srcy + i);
- dst = get_bs_ptr(x, y + i);
- if (src != 0 && dst != 0)
- {
- bs_copy_mem(dst, src, cx * g_bs_Bpp);
- }
- }
- }
- else if (srcy > y || srcx > x) /* copy up or left - top to bottom */
- {
- for (i = 0; i < cy; i++)
- {
- src = get_bs_ptr(srcx, srcy + i);
- dst = get_bs_ptr(x, y + i);
- if (src != 0 && dst != 0)
- {
- bs_copy_mem(dst, src, cx * g_bs_Bpp);
- }
- }
- }
- else /* copy straight right */
- {
- for (i = 0; i < cy; i++)
- {
- src = get_bs_ptr(srcx, srcy + i);
- dst = get_bs_ptr(x, y + i);
- if (src != 0 && dst != 0)
- {
- bs_copy_memb(dst, src, cx * g_bs_Bpp);
- }
- }
- }
- }
- else /* slow */
- {
- if (srcy < y) /* copy down - bottom to top */
- {
- for (i = cy - 1; i >= 0; i--)
- {
- for (j = 0; j < cx; j++)
- {
- p = bs_get_pixel(srcx + j, srcy + i);
- bs_set_pixel(x + j, y + i, p, rop, 0);
- }
- }
- }
- else if (srcy > y || srcx > x) /* copy up or left - top to bottom */
- {
- for (i = 0; i < cy; i++)
- {
- for (j = 0; j < cx; j++)
- {
- p = bs_get_pixel(srcx + j, srcy + i);
- bs_set_pixel(x + j, y + i, p, rop, 0);
- }
- }
- }
- else /* copy straight right */
- {
- for (i = 0; i < cy; i++)
- {
- for (j = cx - 1; j >= 0; j--)
- {
- p = bs_get_pixel(srcx + j, srcy + i);
- bs_set_pixel(x + j, y + i, p, rop, 0);
- }
- }
- }
- }
- }
-}
-
-/*****************************************************************************/
-void
-bs_memblt(int opcode, int x, int y, int cx, int cy,
- void * srcdata, int srcwidth, int srcheight,
- int srcx, int srcy)
-{
- int i;
- int j;
- int p;
- char * dst;
- char * src;
-
- if (bs_warp_coords(&x, &y, &cx, &cy, &srcx, &srcy))
- {
- if (opcode == 12) /* copy */
- {
- if (g_bs_Bpp == 1)
- {
- src = (char *) (((unsigned char *) srcdata) + srcy * srcwidth + srcx);
- }
- else if (g_bs_Bpp == 2)
- {
- src = (char *) (((unsigned short *) srcdata) + srcy * srcwidth + srcx);
- }
- else
- {
- src = (char *) (((unsigned int *) srcdata) + srcy * srcwidth + srcx);
- }
- for (i = 0; i < cy; i++)
- {
- dst = get_bs_ptr(x, y + i);
- if (dst != 0)
- {
- bs_copy_mem(dst, src, cx * g_bs_Bpp);
- src += srcwidth * g_bs_Bpp;
- }
- }
- }
- else /* slow */
- {
- if (g_bs_Bpp == 1)
- {
- for (i = 0; i < cy; i++)
- {
- for (j = 0; j < cx; j++)
- {
- p = *(((unsigned char *) srcdata) +
- ((i + srcy) * srcwidth + (j + srcx)));
- bs_set_pixel(x + j, y + i, p, opcode, 0);
- }
- }
- }
- else if (g_bs_Bpp == 2)
- {
- for (i = 0; i < cy; i++)
- {
- for (j = 0; j < cx; j++)
- {
- p = *(((unsigned short *) srcdata) +
- ((i + srcy) * srcwidth + (j + srcx)));
- bs_set_pixel(x + j, y + i, p, opcode, 0);
- }
- }
- }
- else
- {
- for (i = 0; i < cy; i++)
- {
- for (j = 0; j < cx; j++)
- {
- p = *(((unsigned int *) srcdata) +
- ((i + srcy) * srcwidth + (j + srcx)));
- bs_set_pixel(x + j, y + i, p, opcode, 0);
- }
- }
- }
- }
- }
-}
-
-/*****************************************************************************/
-void
-bs_draw_glyph(int x, int y, char * glyph_data, int glyph_width,
- int glyph_height, int fgcolour)
-{
- int i;
- int j;
-
- for (i = 0; i < glyph_height; i++)
- {
- for (j = 0; j < glyph_width; j++)
- {
- if (bs_is_pixel_on(glyph_data, j, i, glyph_width, 8))
- {
- bs_set_pixel(x + j, y + i, fgcolour, 12, 1);
- }
- }
- }
-}
-
-/*****************************************************************************/
-/* Bresenham's line drawing algorithm */
-void
-bs_line(int opcode, int startx, int starty, int endx, int endy,
- int pen_width, int pen_style, int pen_colour)
-{
- int dx;
- int dy;
- int incx;
- int incy;
- int dpr;
- int dpru;
- int p;
-
- if (startx > endx)
- {
- dx = startx - endx;
- incx = -1;
- }
- else
- {
- dx = endx - startx;
- incx = 1;
- }
- if (starty > endy)
- {
- dy = starty - endy;
- incy = -1;
- }
- else
- {
- dy = endy - starty;
- incy = 1;
- }
- if (dx >= dy)
- {
- dpr = dy << 1;
- dpru = dpr - (dx << 1);
- p = dpr - dx;
- for (; dx >= 0; dx--)
- {
- if (startx != endx || starty != endy)
- {
- bs_set_pixel(startx, starty, pen_colour, opcode, 1);
- }
- if (p > 0)
- {
- startx += incx;
- starty += incy;
- p += dpru;
- }
- else
- {
- startx += incx;
- p += dpr;
- }
- }
- }
- else
- {
- dpr = dx << 1;
- dpru = dpr - (dy << 1);
- p = dpr - dy;
- for (; dy >= 0; dy--)
- {
- if (startx != endx || starty != endy)
- {
- bs_set_pixel(startx, starty, pen_colour, opcode, 1);
- }
- if (p > 0)
- {
- startx += incx;
- starty += incy;
- p += dpru;
- }
- else
- {
- starty += incy;
- p += dpr;
- }
- }
- }
-}
-
-/*****************************************************************************/
-void
-bs_patblt(int opcode, int x, int y, int cx, int cy,
- int brush_style, char * brush_pattern,
- int brush_x_org, int brush_y_org,
- int bgcolour, int fgcolour)
-{
- int i;
- int j;
- char ipattern[8];
- char * b;
-
- b = 0;
- switch (brush_style)
- {
- case 0:
- bs_rect(x, y, cx, cy, fgcolour, opcode);
- break;
- case 2: /* Hatch */
- b = g_hatch_patterns + brush_pattern[0] * 8;
- break;
- case 3:
- for (i = 0; i < 8; i++)
- {
- ipattern[i] = ~brush_pattern[7 - i];
- }
- b = ipattern;
- break;
- }
- if (b != 0)
- {
- for (i = 0; i < cy; i++)
- {
- for (j = 0; j < cx; j++)
- {
- if (bs_is_pixel_on(b, (x + j + brush_x_org) % 8,
- (y + i + brush_y_org) % 8, 8, 1))
- {
- bs_set_pixel(x + j, y + i, fgcolour, opcode, 1);
- }
- else
- {
- bs_set_pixel(x + j, y + i, bgcolour, opcode, 1);
- }
- }
- }
- }
-}
-
-/*****************************************************************************/
-void
-bs_copy_box(char * dst, int x, int y, int cx, int cy, int line_size)
-{
- char * src;
- int i;
-
- /* shouldn't happen */
- if (cx < 1 || cy < 1)
- {
- return;
- }
- /* nothing to draw, memset and leave */
- if (x + cx < 0 || y + cy < 0 || x >= g_width || y >= g_height)
- {
- memset(dst, 0, cx * cy * g_bs_Bpp);
- return;
- }
- /* check if it goes over an edge */
- if (x < 0 || y < 0 || x + cx > g_width || y + cy > g_height)
- {
- memset(dst, 0, cx * cy * g_bs_Bpp);
- if (x < 0)
- {
- cx += x;
- dst += -x * g_bs_Bpp;
- x = 0;
- }
- if (x + cx > g_width)
- {
- cx = g_width - x;
- }
- for (i = 0; i < cy; i++)
- {
- src = get_bs_ptr(x, y + i);
- if (src != 0)
- {
- bs_copy_mem(dst, src, cx * g_bs_Bpp);
- }
- dst += line_size;
- }
- }
- else /* whole box is within */
- {
- for (i = 0; i < cy; i++)
- {
- src = get_bs_ptr(x, y + i);
- if (src != 0)
- {
- bs_copy_mem(dst, src, cx * g_bs_Bpp);
- }
- dst += line_size;
- }
- }
-}
-
+/* -*- c-basic-offset: 8 -*- + rdesktop: A Remote Desktop Protocol client. + Generics backingstore operations + Copyright (C) Jay Sorg 2005-2006 + + 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 <stdlib.h> +#include <string.h> +#include "bsops.h" + +/* externals */ +extern int g_width; +extern int g_height; +extern int g_bs_bpp; +extern int g_bs_Bpp; +extern char * g_bs; + +/* globals */ +static int g_clip_left = 0; +static int g_clip_top = 0; +static int g_clip_right = 800; +static int g_clip_bottom = 600; + +/* for bs_patblt */ +static unsigned char g_hatch_patterns[] = +{ + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */ + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */ + 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */ + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */ + 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */ + 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 /* 5 - bsDiagCross */ +}; + + +/*****************************************************************************/ +/* do a raster op */ +int +bs_do_rop(int rop, int src, int dst) +{ + switch (rop) + { + case 0x0: return 0; + case 0x1: return ~(src | dst); + case 0x2: return (~src) & dst; + case 0x3: return ~src; + case 0x4: return src & (~dst); + case 0x5: return ~(dst); + case 0x6: return src ^ dst; + case 0x7: return ~(src & dst); + case 0x8: return src & dst; + case 0x9: return ~(src) ^ dst; + case 0xa: return dst; + case 0xb: return (~src) | dst; + case 0xc: return src; + case 0xd: return src | (~dst); + case 0xe: return src | dst; + case 0xf: return ~0; + } + return dst; +} + +/*****************************************************************************/ +/* get a pixel from the in memory copy of whats on the screen */ +int +bs_get_pixel(int x, int y) +{ + char * p; + + if (x >= 0 && x < g_width && y >= 0 && y < g_height) + { + p = g_bs + (y * g_width * g_bs_Bpp) + (x * g_bs_Bpp); + if (g_bs_Bpp == 1) + { + return *((unsigned char *) p); + } + else if (g_bs_Bpp == 2) + { + return *((unsigned short *) p); + } + else + { + return *((unsigned int *) p); + } + } + else + { + return 0; + } +} + +/*****************************************************************************/ +/* set a pixel on the screen using the clip */ +void +bs_set_pixel(int x, int y, int pixel, int rop, int use_clip) +{ + char * p; + + if (!use_clip || + (x >= g_clip_left && x < g_clip_right && + y >= g_clip_top && y < g_clip_bottom)) + { + if (x >= 0 && x < g_width && y >= 0 && y < g_height) + { + p = g_bs + (y * g_width * g_bs_Bpp) + (x * g_bs_Bpp); + if (rop != 12) + { + pixel = bs_do_rop(rop, pixel, bs_get_pixel(x, y)); + } + if (g_bs_Bpp == 1) + { + *((unsigned char *) p) = pixel; + } + else if (g_bs_Bpp == 2) + { + *((unsigned short *) p) = pixel; + } + else + { + *((unsigned int *) p) = pixel; + } + } + } +} + +/*****************************************************************************/ +static char * +get_bs_ptr(int x, int y) +{ + char * p; + + if (x >= 0 && x < g_width && y >= 0 && y < g_height) + { + p = g_bs + (y * g_width * g_bs_Bpp) + (x * g_bs_Bpp); + return p; + } + else + { + return 0; + } +} + +/*****************************************************************************/ +void +bs_init(void) +{ + g_clip_left = 0; + g_clip_top = 0; + g_clip_right = g_width; + g_clip_bottom = g_height; +} + +/*****************************************************************************/ +void +bs_exit(void) +{ +} + +/*****************************************************************************/ +void +bs_set_clip(int x, int y, int cx, int cy) +{ + g_clip_left = x; + g_clip_top = y; + g_clip_right = x + cx; + g_clip_bottom = y + cy; +} + +/*****************************************************************************/ +void +bs_reset_clip(void) +{ + g_clip_left = 0; + g_clip_top = 0; + g_clip_right = g_width; + g_clip_bottom = g_height; +} + +/*****************************************************************************/ +/* check if a certain pixel is set in a bitmap */ +int +bs_is_pixel_on(char * data, int x, int y, int width, int bpp) +{ + int start; + int shift; + + if (bpp == 1) + { + width = (width + 7) / 8; + start = (y * width) + x / 8; + shift = x % 8; + return (data[start] & (0x80 >> shift)) != 0; + } + else if (bpp == 8) + { + return data[y * width + x] != 0; + } + else if (bpp == 24) + { + return data[(y * 3) * width + (x * 3)] != 0 && + data[(y * 3) * width + (x * 3) + 1] != 0 && + data[(y * 3) * width + (x * 3) + 2] != 0; + } + else + { + return 0; + } +} + +/*****************************************************************************/ +void +bs_set_pixel_on(char * data, int x, int y, int width, int bpp, + int pixel) +{ + int start; + int shift; + + if (bpp == 1) + { + width = (width + 7) / 8; + start = (y * width) + x / 8; + shift = x % 8; + if (pixel != 0) + { + data[start] = data[start] | (0x80 >> shift); + } + else + { + data[start] = data[start] & ~(0x80 >> shift); + } + } + else if (bpp == 8) + { + data[y * width + x] = pixel; + } + else if (bpp == 15 || bpp == 16) + { + ((unsigned short *) data)[y * width + x] = pixel; + } +} + +/*****************************************************************************/ +void +bs_copy_mem(char * d, char * s, int n) +{ + while (n & (~7)) + { + *(d++) = *(s++); + *(d++) = *(s++); + *(d++) = *(s++); + *(d++) = *(s++); + *(d++) = *(s++); + *(d++) = *(s++); + *(d++) = *(s++); + *(d++) = *(s++); + n = n - 8; + } + while (n > 0) + { + *(d++) = *(s++); + n--; + } +} + +/*****************************************************************************/ +void +bs_copy_memb(char * d, char * s, int n) +{ + d = (d + n) - 1; + s = (s + n) - 1; + while (n & (~7)) + { + *(d--) = *(s--); + *(d--) = *(s--); + *(d--) = *(s--); + *(d--) = *(s--); + *(d--) = *(s--); + *(d--) = *(s--); + *(d--) = *(s--); + *(d--) = *(s--); + n = n - 8; + } + while (n > 0) + { + *(d--) = *(s--); + n--; + } +} + +/*****************************************************************************/ +/* return true is the is something to draw */ +int +bs_warp_coords(int * x, int * y, int * cx, int * cy, + int * srcx, int * srcy) +{ + int dx; + int dy; + + if (g_clip_left > *x) + { + dx = g_clip_left - *x; + } + else + { + dx = 0; + } + if (g_clip_top > *y) + { + dy = g_clip_top - *y; + } + else + { + dy = 0; + } + if (*x + *cx > g_clip_right) + { + *cx = (*cx - ((*x + *cx) - g_clip_right)); + } + if (*y + *cy > g_clip_bottom) + { + *cy = (*cy - ((*y + *cy) - g_clip_bottom)); + } + *cx = *cx - dx; + *cy = *cy - dy; + if (*cx <= 0) + { + return 0; + } + if (*cy <= 0) + { + return 0; + } + *x = *x + dx; + *y = *y + dy; + if (srcx != 0) + { + *srcx = *srcx + dx; + } + if (srcy != 0) + { + *srcy = *srcy + dy; + } + return 1; +} + +/*****************************************************************************/ +void +bs_rect(int x, int y, int cx, int cy, int colour, int rop) +{ + int i; + int j; + unsigned char * p8; + unsigned short * p16; + unsigned int * p32; + + if (bs_warp_coords(&x, &y, &cx, &cy, 0, 0)) + { + if (rop == 0) /* black */ + { + rop = 12; + colour = 0; + } + else if (rop == 15) /* white */ + { + rop = 12; + colour = 0xffffff; + } + if (rop == 12) /* copy */ + { + if (g_bs_Bpp == 1) + { + for (i = 0; i < cy; i++) + { + p8 = (unsigned char *) get_bs_ptr(x, y + i); + if (p8 != 0) + { + for (j = 0; j < cx; j++) + { + *p8 = colour; + p8++; + } + } + } + } + else if (g_bs_Bpp == 2) + { + for (i = 0; i < cy; i++) + { + p16 = (unsigned short *) get_bs_ptr(x, y + i); + if (p16 != 0) + { + for (j = 0; j < cx; j++) + { + *p16 = colour; + p16++; + } + } + } + } + else + { + for (i = 0; i < cy; i++) + { + p32 = (unsigned int *) get_bs_ptr(x, y + i); + if (p32 != 0) + { + for (j = 0; j < cx; j++) + { + *p32 = colour; + p32++; + } + } + } + } + } + else /* slow */ + { + for (i = 0; i < cy; i++) + { + for (j = 0; j < cx; j++) + { + bs_set_pixel(j + x, i + y, colour, rop, 0); + } + } + } + } +} + +/*****************************************************************************/ +void +bs_screenblt(int rop, int x, int y, int cx, int cy, + int srcx, int srcy) +{ + int p; + int i; + int j; + char * src; + char * dst; + + if (bs_warp_coords(&x, &y, &cx, &cy, &srcx, &srcy)) + { + if (rop == 12) /* copy */ + { + if (srcy < y) /* copy down - bottom to top */ + { + for (i = cy - 1; i >= 0; i--) + { + src = get_bs_ptr(srcx, srcy + i); + dst = get_bs_ptr(x, y + i); + if (src != 0 && dst != 0) + { + bs_copy_mem(dst, src, cx * g_bs_Bpp); + } + } + } + else if (srcy > y || srcx > x) /* copy up or left - top to bottom */ + { + for (i = 0; i < cy; i++) + { + src = get_bs_ptr(srcx, srcy + i); + dst = get_bs_ptr(x, y + i); + if (src != 0 && dst != 0) + { + bs_copy_mem(dst, src, cx * g_bs_Bpp); + } + } + } + else /* copy straight right */ + { + for (i = 0; i < cy; i++) + { + src = get_bs_ptr(srcx, srcy + i); + dst = get_bs_ptr(x, y + i); + if (src != 0 && dst != 0) + { + bs_copy_memb(dst, src, cx * g_bs_Bpp); + } + } + } + } + else /* slow */ + { + if (srcy < y) /* copy down - bottom to top */ + { + for (i = cy - 1; i >= 0; i--) + { + for (j = 0; j < cx; j++) + { + p = bs_get_pixel(srcx + j, srcy + i); + bs_set_pixel(x + j, y + i, p, rop, 0); + } + } + } + else if (srcy > y || srcx > x) /* copy up or left - top to bottom */ + { + for (i = 0; i < cy; i++) + { + for (j = 0; j < cx; j++) + { + p = bs_get_pixel(srcx + j, srcy + i); + bs_set_pixel(x + j, y + i, p, rop, 0); + } + } + } + else /* copy straight right */ + { + for (i = 0; i < cy; i++) + { + for (j = cx - 1; j >= 0; j--) + { + p = bs_get_pixel(srcx + j, srcy + i); + bs_set_pixel(x + j, y + i, p, rop, 0); + } + } + } + } + } +} + +/*****************************************************************************/ +void +bs_memblt(int opcode, int x, int y, int cx, int cy, + void * srcdata, int srcwidth, int srcheight, + int srcx, int srcy) +{ + int i; + int j; + int p; + char * dst; + char * src; + + if (bs_warp_coords(&x, &y, &cx, &cy, &srcx, &srcy)) + { + if (opcode == 12) /* copy */ + { + if (g_bs_Bpp == 1) + { + src = (char *) (((unsigned char *) srcdata) + srcy * srcwidth + srcx); + } + else if (g_bs_Bpp == 2) + { + src = (char *) (((unsigned short *) srcdata) + srcy * srcwidth + srcx); + } + else + { + src = (char *) (((unsigned int *) srcdata) + srcy * srcwidth + srcx); + } + for (i = 0; i < cy; i++) + { + dst = get_bs_ptr(x, y + i); + if (dst != 0) + { + bs_copy_mem(dst, src, cx * g_bs_Bpp); + src += srcwidth * g_bs_Bpp; + } + } + } + else /* slow */ + { + if (g_bs_Bpp == 1) + { + for (i = 0; i < cy; i++) + { + for (j = 0; j < cx; j++) + { + p = *(((unsigned char *) srcdata) + + ((i + srcy) * srcwidth + (j + srcx))); + bs_set_pixel(x + j, y + i, p, opcode, 0); + } + } + } + else if (g_bs_Bpp == 2) + { + for (i = 0; i < cy; i++) + { + for (j = 0; j < cx; j++) + { + p = *(((unsigned short *) srcdata) + + ((i + srcy) * srcwidth + (j + srcx))); + bs_set_pixel(x + j, y + i, p, opcode, 0); + } + } + } + else + { + for (i = 0; i < cy; i++) + { + for (j = 0; j < cx; j++) + { + p = *(((unsigned int *) srcdata) + + ((i + srcy) * srcwidth + (j + srcx))); + bs_set_pixel(x + j, y + i, p, opcode, 0); + } + } + } + } + } +} + +/*****************************************************************************/ +void +bs_draw_glyph(int x, int y, char * glyph_data, int glyph_width, + int glyph_height, int fgcolour) +{ + int i; + int j; + + for (i = 0; i < glyph_height; i++) + { + for (j = 0; j < glyph_width; j++) + { + if (bs_is_pixel_on(glyph_data, j, i, glyph_width, 8)) + { + bs_set_pixel(x + j, y + i, fgcolour, 12, 1); + } + } + } +} + +/*****************************************************************************/ +/* Bresenham's line drawing algorithm */ +void +bs_line(int opcode, int startx, int starty, int endx, int endy, + int pen_width, int pen_style, int pen_colour) +{ + int dx; + int dy; + int incx; + int incy; + int dpr; + int dpru; + int p; + + if (startx > endx) + { + dx = startx - endx; + incx = -1; + } + else + { + dx = endx - startx; + incx = 1; + } + if (starty > endy) + { + dy = starty - endy; + incy = -1; + } + else + { + dy = endy - starty; + incy = 1; + } + if (dx >= dy) + { + dpr = dy << 1; + dpru = dpr - (dx << 1); + p = dpr - dx; + for (; dx >= 0; dx--) + { + if (startx != endx || starty != endy) + { + bs_set_pixel(startx, starty, pen_colour, opcode, 1); + } + if (p > 0) + { + startx += incx; + starty += incy; + p += dpru; + } + else + { + startx += incx; + p += dpr; + } + } + } + else + { + dpr = dx << 1; + dpru = dpr - (dy << 1); + p = dpr - dy; + for (; dy >= 0; dy--) + { + if (startx != endx || starty != endy) + { + bs_set_pixel(startx, starty, pen_colour, opcode, 1); + } + if (p > 0) + { + startx += incx; + starty += incy; + p += dpru; + } + else + { + starty += incy; + p += dpr; + } + } + } +} + +/*****************************************************************************/ +void +bs_patblt(int opcode, int x, int y, int cx, int cy, + int brush_style, char * brush_pattern, + int brush_x_org, int brush_y_org, + int bgcolour, int fgcolour) +{ + int i; + int j; + char ipattern[8]; + char * b; + + b = 0; + switch (brush_style) + { + case 0: + bs_rect(x, y, cx, cy, fgcolour, opcode); + break; + case 2: /* Hatch */ + b = g_hatch_patterns + brush_pattern[0] * 8; + break; + case 3: + for (i = 0; i < 8; i++) + { + ipattern[i] = ~brush_pattern[7 - i]; + } + b = ipattern; + break; + } + if (b != 0) + { + for (i = 0; i < cy; i++) + { + for (j = 0; j < cx; j++) + { + if (bs_is_pixel_on(b, (x + j + brush_x_org) % 8, + (y + i + brush_y_org) % 8, 8, 1)) + { + bs_set_pixel(x + j, y + i, fgcolour, opcode, 1); + } + else + { + bs_set_pixel(x + j, y + i, bgcolour, opcode, 1); + } + } + } + } +} + +/*****************************************************************************/ +void +bs_copy_box(char * dst, int x, int y, int cx, int cy, int line_size) +{ + char * src; + int i; + + /* shouldn't happen */ + if (cx < 1 || cy < 1) + { + return; + } + /* nothing to draw, memset and leave */ + if (x + cx < 0 || y + cy < 0 || x >= g_width || y >= g_height) + { + memset(dst, 0, cx * cy * g_bs_Bpp); + return; + } + /* check if it goes over an edge */ + if (x < 0 || y < 0 || x + cx > g_width || y + cy > g_height) + { + memset(dst, 0, cx * cy * g_bs_Bpp); + if (x < 0) + { + cx += x; + dst += -x * g_bs_Bpp; + x = 0; + } + if (x + cx > g_width) + { + cx = g_width - x; + } + for (i = 0; i < cy; i++) + { + src = get_bs_ptr(x, y + i); + if (src != 0) + { + bs_copy_mem(dst, src, cx * g_bs_Bpp); + } + dst += line_size; + } + } + else /* whole box is within */ + { + for (i = 0; i < cy; i++) + { + src = get_bs_ptr(x, y + i); + if (src != 0) + { + bs_copy_mem(dst, src, cx * g_bs_Bpp); + } + dst += line_size; + } + } +} + diff --git a/uirdesktop/bsops.h b/uirdesktop/bsops.h index 25df2208..017bcd55 100755 --- a/uirdesktop/bsops.h +++ b/uirdesktop/bsops.h @@ -1,49 +1,49 @@ -/* -*- c-basic-offset: 8 -*-
- rdesktop: A Remote Desktop Protocol client.
- Generics backingstore operations
- Copyright (C) Jay Sorg 2005-2006
-
- 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.
-*/
-
-int bs_get_pixel(int x, int y);
-void bs_set_pixel(int x, int y, int pixel, int rop, int use_clip);
-int bs_do_rop(int rop, int src, int dst);
-void bs_init(void);
-void bs_exit(void);
-void bs_set_clip(int x, int y, int cx, int cy);
-void bs_reset_clip(void);
-void bs_set_pixel_on(char * data, int x, int y, int width, int bpp,
- int pixel);
-int bs_is_pixel_on(char * data, int x, int y, int width, int bpp);
-void bs_copy_mem(char * d, char * s, int n);
-void bs_copy_memb(char * d, char * s, int n);
-int bs_warp_coords(int * x, int * y, int * cx, int * cy,
- int * srcx, int * srcy);
-void bs_rect(int x, int y, int cx, int cy, int colour, int rop);
-void bs_screenblt(int opcode, int x, int y, int cx, int cy,
- int srcx, int srcy);
-void bs_memblt(int opcode, int x, int y, int cx, int cy,
- void * srcdata, int srcwidth, int srcheight,
- int srcx, int srcy);
-void bs_copy_box(char * dst, int x, int y, int cx, int cy, int line_size);
-void bs_draw_glyph(int x, int y, char * glyph_data, int glyph_width,
- int glyph_height, int fgcolour);
-void bs_line(int opcode, int startx, int starty, int endx, int endy,
- int pen_width, int pen_style, int pen_colour);
-void bs_patblt(int opcode, int x, int y, int cx, int cy,
- int brush_style, char * brush_pattern,
- int brush_x_org, int brush_y_org,
- int bgcolour, int fgcolour);
+/* -*- c-basic-offset: 8 -*- + rdesktop: A Remote Desktop Protocol client. + Generics backingstore operations + Copyright (C) Jay Sorg 2005-2006 + + 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. +*/ + +int bs_get_pixel(int x, int y); +void bs_set_pixel(int x, int y, int pixel, int rop, int use_clip); +int bs_do_rop(int rop, int src, int dst); +void bs_init(void); +void bs_exit(void); +void bs_set_clip(int x, int y, int cx, int cy); +void bs_reset_clip(void); +void bs_set_pixel_on(char * data, int x, int y, int width, int bpp, + int pixel); +int bs_is_pixel_on(char * data, int x, int y, int width, int bpp); +void bs_copy_mem(char * d, char * s, int n); +void bs_copy_memb(char * d, char * s, int n); +int bs_warp_coords(int * x, int * y, int * cx, int * cy, + int * srcx, int * srcy); +void bs_rect(int x, int y, int cx, int cy, int colour, int rop); +void bs_screenblt(int opcode, int x, int y, int cx, int cy, + int srcx, int srcy); +void bs_memblt(int opcode, int x, int y, int cx, int cy, + void * srcdata, int srcwidth, int srcheight, + int srcx, int srcy); +void bs_copy_box(char * dst, int x, int y, int cx, int cy, int line_size); +void bs_draw_glyph(int x, int y, char * glyph_data, int glyph_width, + int glyph_height, int fgcolour); +void bs_line(int opcode, int startx, int starty, int endx, int endy, + int pen_width, int pen_style, int pen_colour); +void bs_patblt(int opcode, int x, int y, int cx, int cy, + int brush_style, char * brush_pattern, + int brush_x_org, int brush_y_org, + int bgcolour, int fgcolour); diff --git a/uirdesktop/constants.h b/uirdesktop/constants.h index a2349a09..32db85a7 100755 --- a/uirdesktop/constants.h +++ b/uirdesktop/constants.h @@ -192,7 +192,7 @@ enum RDP_INPUT_DEVICE /* Raster operation masks */ #define ROP2_S(rop3) ((uint8) (rop3 & 0xf)) -#define ROP2_P(rop3) ((uint8) ((rop3 & 0x3) | ((rop3 & 0x30) >> 2)))
+#define ROP2_P(rop3) ((uint8) ((rop3 & 0x3) | ((rop3 & 0x30) >> 2))) #define ROP_MINUS_1(rop) ((uint8) (rop - 1)) #define ROP2_COPY 0xc @@ -355,21 +355,21 @@ enum RDP_INPUT_DEVICE #define CHANNEL_OPTION_COMPRESS_RDP 0x00800000 #define CHANNEL_OPTION_SHOW_PROTOCOL 0x00200000 -/* NT status codes for RDPDR */
+/* NT status codes for RDPDR */ #undef STATUS_SUCCESS -#define STATUS_SUCCESS 0x00000000
+#define STATUS_SUCCESS 0x00000000 #undef STATUS_NOT_IMPLEMENTED #define STATUS_NOT_IMPLEMENTED 0x00000001 -#undef STATUS_PENDING
+#undef STATUS_PENDING #define STATUS_PENDING 0x00000103 -#ifndef STATUS_NO_MORE_FILES
+#ifndef STATUS_NO_MORE_FILES #define STATUS_NO_MORE_FILES 0x80000006 #define STATUS_DEVICE_PAPER_EMPTY 0x8000000e #define STATUS_DEVICE_POWERED_OFF 0x8000000f #define STATUS_DEVICE_OFF_LINE 0x80000010 #define STATUS_DEVICE_BUSY 0x80000011 -#endif
+#endif #ifndef STATUS_INVALID_HANDLE #define STATUS_INVALID_HANDLE 0xc0000008 diff --git a/uirdesktop/example-winrdesktop.ini b/uirdesktop/example-winrdesktop.ini index cbb88b64..22deab46 100755 --- a/uirdesktop/example-winrdesktop.ini +++ b/uirdesktop/example-winrdesktop.ini @@ -1,8 +1,8 @@ -[main]
-server=192.168.1.1
-port=3389
-username=user1
-password=password1
-bpp=16
-#geometry=300x400
-fullscreen
+[main] +server=192.168.1.1 +port=3389 +username=user1 +password=password1 +bpp=16 +#geometry=300x400 +fullscreen diff --git a/uirdesktop/licence.c b/uirdesktop/licence.c index 32918011..09cb4548 100755 --- a/uirdesktop/licence.c +++ b/uirdesktop/licence.c @@ -20,19 +20,19 @@ #include "rdesktop.h" //#include <openssl/rc4.h> -
-void *
-ssl_rc4_info_create(void);
-void
-ssl_rc4_info_delete(void * rc4_info);
-void
-ssl_rc4_set_key(void * rc4_info, char * key, int len);
-void
-ssl_rc4_crypt(void * rc4_info, char * in_data, char * out_data, int len);
-int
-ssl_mod_exp(char* out, int out_len, char* in, int in_len,
- char* mod, int mod_len, char* exp, int exp_len);
-
+ +void * +ssl_rc4_info_create(void); +void +ssl_rc4_info_delete(void * rc4_info); +void +ssl_rc4_set_key(void * rc4_info, char * key, int len); +void +ssl_rc4_crypt(void * rc4_info, char * in_data, char * out_data, int len); +int +ssl_mod_exp(char* out, int out_len, char* in, int in_len, + char* mod, int mod_len, char* exp, int exp_len); + extern char g_username[64]; extern char g_hostname[16]; @@ -172,11 +172,11 @@ licence_process_demand(STREAM s) licence_generate_hwid(hwid); sec_sign(signature, 16, g_licence_sign_key, 16, hwid, sizeof(hwid)); - /* Now encrypt the HWID */
- crypt_key = ssl_rc4_info_create();
- ssl_rc4_set_key(crypt_key, g_licence_key, 16);
- ssl_rc4_crypt(crypt_key, hwid, hwid, sizeof(hwid));
- ssl_rc4_info_delete(crypt_key);
+ /* Now encrypt the HWID */ + crypt_key = ssl_rc4_info_create(); + ssl_rc4_set_key(crypt_key, g_licence_key, 16); + ssl_rc4_crypt(crypt_key, hwid, hwid, sizeof(hwid)); + ssl_rc4_info_delete(crypt_key); licence_present(null_data, null_data, licence_data, licence_size, hwid, signature); xfree(licence_data); @@ -251,11 +251,11 @@ licence_process_authreq(STREAM s) memcpy(out_token, in_token, LICENCE_TOKEN_SIZE); /* Decrypt the token. It should read TEST in Unicode. */ - crypt_key = ssl_rc4_info_create();
- ssl_rc4_set_key(crypt_key, g_licence_key, 16);
- ssl_rc4_crypt(crypt_key, in_token, decrypt_token, LICENCE_TOKEN_SIZE);
- ssl_rc4_info_delete(crypt_key);
-
+ crypt_key = ssl_rc4_info_create(); + ssl_rc4_set_key(crypt_key, g_licence_key, 16); + ssl_rc4_crypt(crypt_key, in_token, decrypt_token, LICENCE_TOKEN_SIZE); + ssl_rc4_info_delete(crypt_key); + /* Generate a signature for a buffer of token and HWID */ licence_generate_hwid(hwid); memcpy(sealed_buffer, decrypt_token, LICENCE_TOKEN_SIZE); @@ -263,11 +263,11 @@ licence_process_authreq(STREAM s) sec_sign(out_sig, 16, g_licence_sign_key, 16, sealed_buffer, sizeof(sealed_buffer)); /* Now encrypt the HWID */ - crypt_key = ssl_rc4_info_create();
- ssl_rc4_set_key(crypt_key, g_licence_key, 16);
- ssl_rc4_crypt(crypt_key, hwid, crypt_hwid, LICENCE_HWID_SIZE);
- ssl_rc4_info_delete(crypt_key);
-
+ crypt_key = ssl_rc4_info_create(); + ssl_rc4_set_key(crypt_key, g_licence_key, 16); + ssl_rc4_crypt(crypt_key, hwid, crypt_hwid, LICENCE_HWID_SIZE); + ssl_rc4_info_delete(crypt_key); + licence_send_authresp(out_token, crypt_hwid, out_sig); } @@ -285,11 +285,11 @@ licence_process_issue(STREAM s) if (!s_check_rem(s, length)) return; - crypt_key = ssl_rc4_info_create();
- ssl_rc4_set_key(crypt_key, g_licence_key, 16);
- ssl_rc4_crypt(crypt_key, s->p, s->p, length);
- ssl_rc4_info_delete(crypt_key);
-
+ crypt_key = ssl_rc4_info_create(); + ssl_rc4_set_key(crypt_key, g_licence_key, 16); + ssl_rc4_crypt(crypt_key, s->p, s->p, length); + ssl_rc4_info_delete(crypt_key); + in_uint16(s, check); if (check != 0) return; diff --git a/uirdesktop/makefile_win32 b/uirdesktop/makefile_win32 index 96a7c8ff..e171bb25 100755 --- a/uirdesktop/makefile_win32 +++ b/uirdesktop/makefile_win32 @@ -1,19 +1,19 @@ -# makefile
-
-OBJS = tcp.obj iso.obj mcs.obj secure.obj rdp.obj rdp5.obj orders.obj \
-bitmap.obj cache.obj mppc.obj pstcache.obj channels.obj licence.obj \
-ssl_calls.obj
-
-UIOBJS = uimain.obj bsops.obj win32.obj
-
-#-w-aus -w-rch
-CFLAGS = -O2 -w-par -I.. -Ic:\borland\bcc55\include
-LDFLAGS = -W -Lc:\borland\bcc55\lib
-
-all: rd
-
-rd: $(OBJS) $(UIOBJS)
- $(CC) -ewinrdesktop.exe $(LDFLAGS) $(OBJS) $(UIOBJS)
-
-clean:
- del /q $(OBJS) $(UIOBJS) winrdesktop.exe *.tds
+# makefile + +OBJS = tcp.obj iso.obj mcs.obj secure.obj rdp.obj rdp5.obj orders.obj \ +bitmap.obj cache.obj mppc.obj pstcache.obj channels.obj licence.obj \ +ssl_calls.obj + +UIOBJS = uimain.obj bsops.obj win32.obj + +#-w-aus -w-rch +CFLAGS = -O2 -w-par -I.. -Ic:\borland\bcc55\include +LDFLAGS = -W -Lc:\borland\bcc55\lib + +all: rd + +rd: $(OBJS) $(UIOBJS) + $(CC) -ewinrdesktop.exe $(LDFLAGS) $(OBJS) $(UIOBJS) + +clean: + del /q $(OBJS) $(UIOBJS) winrdesktop.exe *.tds diff --git a/uirdesktop/pstcache.c b/uirdesktop/pstcache.c index 7704d943..9e6432bd 100644 --- a/uirdesktop/pstcache.c +++ b/uirdesktop/pstcache.c @@ -107,7 +107,7 @@ pstcache_save_bitmap(uint8 cache_id, uint16 cache_idx, uint8 * key, int pstcache_enumerate(uint8 id, HASH_KEY * keylist) { - int fd, n;
+ int fd, n; uint16 idx; sint16 mru_idx[0xa00]; uint32 mru_stamp[0xa00]; diff --git a/uirdesktop/rdesktop.h b/uirdesktop/rdesktop.h index e835231e..0f39b6e3 100644 --- a/uirdesktop/rdesktop.h +++ b/uirdesktop/rdesktop.h @@ -20,22 +20,22 @@ #include <stdlib.h> #include <stdio.h> -#include <string.h>
-#ifdef _WIN32
-#include <winsock2.h> /* winsock2.h first */
-#include <windows.h>
-#include <time.h>
-#else /* WIN32 */
-#include <dirent.h>
-#include <sys/types.h>
-#include <sys/time.h>
+#include <string.h> +#ifdef _WIN32 +#include <winsock2.h> /* winsock2.h first */ +#include <windows.h> +#include <time.h> +#else /* WIN32 */ +#include <dirent.h> +#include <sys/types.h> +#include <sys/time.h> #ifdef HAVE_SYS_SELECT_H #include <sys/select.h> #else /* HAVE_SYS_SELECT_H */ #include <sys/types.h> #include <unistd.h> #endif /* HAVE_SYS_SELECT_H */ -#endif /* WIN32 */
+#endif /* WIN32 */ #include <limits.h> /* PATH_MAX */ #define VERSION "1.4.1" diff --git a/uirdesktop/rdp.c b/uirdesktop/rdp.c index d9810371..481a0005 100644 --- a/uirdesktop/rdp.c +++ b/uirdesktop/rdp.c @@ -1,1457 +1,1457 @@ -/* -*- c-basic-offset: 8 -*-
- rdesktop: A Remote Desktop Protocol client.
- Protocol services - RDP layer
- Copyright (C) Matthew Chapman 1999-2005
-
- 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 <time.h>
-#ifndef _WIN32
-#include <errno.h>
-#include <unistd.h>
-#endif
-#include "rdesktop.h"
-
-#ifdef HAVE_ICONV
-#ifdef HAVE_ICONV_H
-#include <iconv.h>
-#endif
-
-#ifndef ICONV_CONST
-#define ICONV_CONST ""
-#endif
-#endif
-
-extern uint16 g_mcs_userid;
-extern char g_username[64];
-extern char g_codepage[16];
-extern BOOL g_bitmap_compression;
-extern BOOL g_orders;
-extern BOOL g_encryption;
-extern BOOL g_desktop_save;
-extern BOOL g_polygon_ellipse_orders;
-extern BOOL g_use_rdp5;
-extern uint16 g_server_rdp_version;
-extern uint32 g_rdp5_performanceflags;
-extern int g_server_depth;
-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;
-
-extern RDPCOMP g_mppc_dict;
-
-/* Session Directory support */
-extern BOOL g_redirect;
-extern char g_redirect_server[64];
-extern char g_redirect_domain[16];
-extern char g_redirect_password[64];
-extern char g_redirect_username[64];
-extern char g_redirect_cookie[128];
-extern uint32 g_redirect_flags;
-/* END Session Directory support */
-
-#ifdef WITH_DEBUG
-static uint32 g_packetno;
-#endif
-
-#ifdef HAVE_ICONV
-static BOOL g_iconv_works = True;
-#endif
-
-/* Receive an RDP packet */
-static STREAM
-rdp_recv(uint8 * type)
-{
- static STREAM rdp_s;
- uint16 length, pdu_type;
- uint8 rdpver;
-
- if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end) || (g_next_packet == NULL))
- {
- rdp_s = sec_recv(&rdpver);
- if (rdp_s == NULL)
- return NULL;
- if (rdpver == 0xff)
- {
- g_next_packet = rdp_s->end;
- *type = 0;
- return rdp_s;
- }
- else if (rdpver != 3)
- {
- /* rdp5_process should move g_next_packet ok */
- rdp5_process(rdp_s);
- *type = 0;
- return rdp_s;
- }
-
- g_next_packet = rdp_s->p;
- }
- else
- {
- rdp_s->p = g_next_packet;
- }
-
- in_uint16_le(rdp_s, length);
- /* 32k packets are really 8, keepalive fix */
- if (length == 0x8000)
- {
- g_next_packet += 8;
- *type = 0;
- return rdp_s;
- }
- in_uint16_le(rdp_s, pdu_type);
- in_uint8s(rdp_s, 2); /* userid */
- *type = pdu_type & 0xf;
-
-#ifdef WITH_DEBUG
- DEBUG(("RDP packet #%d, (type %x)\n", ++g_packetno, *type));
- hexdump(g_next_packet, length);
-#endif /* */
-
- g_next_packet += length;
- return rdp_s;
-}
-
-/* Initialise an RDP data packet */
-static STREAM
-rdp_init_data(int maxlen)
-{
- STREAM s;
-
- s = sec_init(g_encryption ? SEC_ENCRYPT : 0, maxlen + 18);
- s_push_layer(s, rdp_hdr, 18);
-
- return s;
-}
-
-/* Send an RDP data packet */
-static void
-rdp_send_data(STREAM s, uint8 data_pdu_type)
-{
- uint16 length;
-
- s_pop_layer(s, rdp_hdr);
- length = s->end - s->p;
-
- out_uint16_le(s, length);
- out_uint16_le(s, (RDP_PDU_DATA | 0x10));
- out_uint16_le(s, (g_mcs_userid + 1001));
-
- out_uint32_le(s, g_rdp_shareid);
- out_uint8(s, 0); /* pad */
- out_uint8(s, 1); /* streamid */
- out_uint16_le(s, (length - 14));
- out_uint8(s, data_pdu_type);
- out_uint8(s, 0); /* compress_type */
- out_uint16(s, 0); /* compress_len */
-
- sec_send(s, g_encryption ? SEC_ENCRYPT : 0);
-}
-
-/* Output a string in Unicode */
-void
-rdp_out_unistr(STREAM s, char *string, int len)
-{
-#ifdef HAVE_ICONV
- size_t ibl = strlen(string), obl = len + 2;
- static iconv_t iconv_h = (iconv_t) - 1;
- char *pin = string, *pout = (char *) s->p;
-
- memset(pout, 0, len + 4);
-
- if (g_iconv_works)
- {
- if (iconv_h == (iconv_t) - 1)
- {
- size_t i = 1, o = 4;
- if ((iconv_h = iconv_open(WINDOWS_CODEPAGE, g_codepage)) == (iconv_t) - 1)
- {
- warning("rdp_out_unistr: iconv_open[%s -> %s] fail %d\n",
- g_codepage, WINDOWS_CODEPAGE, (int) iconv_h);
-
- g_iconv_works = False;
- rdp_out_unistr(s, string, len);
- return;
- }
- if (iconv(iconv_h, (ICONV_CONST char **) &pin, &i, &pout, &o) ==
- (size_t) - 1)
- {
- iconv_close(iconv_h);
- iconv_h = (iconv_t) - 1;
- warning("rdp_out_unistr: iconv(1) fail, errno %d\n", errno);
-
- g_iconv_works = False;
- rdp_out_unistr(s, string, len);
- return;
- }
- pin = string;
- pout = (char *) s->p;
- }
-
- if (iconv(iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
- {
- iconv_close(iconv_h);
- iconv_h = (iconv_t) - 1;
- warning("rdp_out_unistr: iconv(2) fail, errno %d\n", errno);
-
- g_iconv_works = False;
- rdp_out_unistr(s, string, len);
- return;
- }
-
- s->p += len + 2;
-
- }
- else
-#endif
- {
- int i = 0, j = 0;
-
- len += 2;
-
- while (i < len)
- {
- s->p[i++] = string[j++];
- s->p[i++] = 0;
- }
-
- s->p += len;
- }
-}
-
-/* Input a string in Unicode
- *
- * Returns str_len of string
- */
-int
-rdp_in_unistr(STREAM s, char *string, int uni_len)
-{
-#ifdef HAVE_ICONV
- size_t ibl = uni_len, obl = uni_len;
- char *pin = (char *) s->p, *pout = string;
- static iconv_t iconv_h = (iconv_t) - 1;
-
- if (g_iconv_works)
- {
- if (iconv_h == (iconv_t) - 1)
- {
- if ((iconv_h = iconv_open(g_codepage, WINDOWS_CODEPAGE)) == (iconv_t) - 1)
- {
- warning("rdp_in_unistr: iconv_open[%s -> %s] fail %d\n",
- WINDOWS_CODEPAGE, g_codepage, (int) iconv_h);
-
- g_iconv_works = False;
- return rdp_in_unistr(s, string, uni_len);
- }
- }
-
- if (iconv(iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
- {
- iconv_close(iconv_h);
- iconv_h = (iconv_t) - 1;
- warning("rdp_in_unistr: iconv fail, errno %d\n", errno);
-
- g_iconv_works = False;
- return rdp_in_unistr(s, string, uni_len);
- }
-
- /* we must update the location of the current STREAM for future reads of s->p */
- s->p += uni_len;
-
- return pout - string;
- }
- else
-#endif
- {
- int i = 0;
-
- while (i < uni_len / 2)
- {
- in_uint8a(s, &string[i++], 1);
- in_uint8s(s, 1);
- }
-
- return i - 1;
- }
-}
-
-
-/* Parse a logon info packet */
-static void
-rdp_send_logon_info(uint32 flags, char *domain, char *user,
- char *password, char *program, char *directory)
-{
- char *ipaddr = tcp_get_address();
- int len_domain = 2 * strlen(domain);
- int len_user = 2 * strlen(user);
- int len_password = 2 * strlen(password);
- int len_program = 2 * strlen(program);
- int len_directory = 2 * strlen(directory);
- int len_ip = 2 * strlen(ipaddr);
- int len_dll = 2 * strlen("C:\\WINNT\\System32\\mstscax.dll");
- int packetlen = 0;
- uint32 sec_flags = g_encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO;
- STREAM s;
- //time_t t = time(NULL);
- //time_t tzone;
-
- if (!g_use_rdp5 || 1 == g_server_rdp_version)
- {
- DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));
-
- s = sec_init(sec_flags, 18 + len_domain + len_user + len_password
- + len_program + len_directory + 10);
-
- out_uint32(s, 0);
- out_uint32_le(s, flags);
- out_uint16_le(s, len_domain);
- out_uint16_le(s, len_user);
- out_uint16_le(s, len_password);
- out_uint16_le(s, len_program);
- out_uint16_le(s, len_directory);
- rdp_out_unistr(s, domain, len_domain);
- rdp_out_unistr(s, user, len_user);
- rdp_out_unistr(s, password, len_password);
- rdp_out_unistr(s, program, len_program);
- rdp_out_unistr(s, directory, len_directory);
- }
- else
- {
-#if 0
- flags |= RDP_LOGON_BLOB;
- DEBUG_RDP5(("Sending RDP5-style Logon packet\n"));
- packetlen = 4 + /* Unknown uint32 */
- 4 + /* flags */
- 2 + /* len_domain */
- 2 + /* len_user */
- (flags & RDP_LOGON_AUTO ? 2 : 0) + /* len_password */
- (flags & RDP_LOGON_BLOB ? 2 : 0) + /* Length of BLOB */
- 2 + /* len_program */
- 2 + /* len_directory */
- (0 < len_domain ? len_domain : 2) + /* domain */
- len_user + (flags & RDP_LOGON_AUTO ? len_password : 0) + 0 + /* We have no 512 byte BLOB. Perhaps we must? */
- (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO) ? 2 : 0) + /* After the BLOB is a unknown int16. If there is a BLOB, that is. */
- (0 < len_program ? len_program : 2) + (0 < len_directory ? len_directory : 2) + 2 + /* Unknown (2) */
- 2 + /* Client ip length */
- len_ip + /* Client ip */
- 2 + /* DLL string length */
- len_dll + /* DLL string */
- 2 + /* Unknown */
- 2 + /* Unknown */
- 64 + /* Time zone #0 */
- 2 + /* Unknown */
- 64 + /* Time zone #1 */
- 32; /* Unknown */
-
- s = sec_init(sec_flags, packetlen);
- DEBUG_RDP5(("Called sec_init with packetlen %d\n", packetlen));
-
- out_uint32(s, 0); /* Unknown */
- out_uint32_le(s, flags);
- out_uint16_le(s, len_domain);
- out_uint16_le(s, len_user);
- if (flags & RDP_LOGON_AUTO)
- {
- out_uint16_le(s, len_password);
-
- }
- if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
- {
- out_uint16_le(s, 0);
- }
- out_uint16_le(s, len_program);
- out_uint16_le(s, len_directory);
- if (0 < len_domain)
- rdp_out_unistr(s, domain, len_domain);
- else
- out_uint16_le(s, 0);
- rdp_out_unistr(s, user, len_user);
- if (flags & RDP_LOGON_AUTO)
- {
- rdp_out_unistr(s, password, len_password);
- }
- if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
- {
- out_uint16_le(s, 0);
- }
- if (0 < len_program)
- {
- rdp_out_unistr(s, program, len_program);
-
- }
- else
- {
- out_uint16_le(s, 0);
- }
- if (0 < len_directory)
- {
- rdp_out_unistr(s, directory, len_directory);
- }
- else
- {
- out_uint16_le(s, 0);
- }
- out_uint16_le(s, 2);
- out_uint16_le(s, len_ip + 2); /* Length of client ip */
- rdp_out_unistr(s, ipaddr, len_ip);
- out_uint16_le(s, len_dll + 2);
- rdp_out_unistr(s, "C:\\WINNT\\System32\\mstscax.dll", len_dll);
-
- tzone = (mktime(gmtime(&t)) - mktime(localtime(&t))) / 60;
- out_uint32_le(s, tzone);
-
- rdp_out_unistr(s, "GTB, normaltid", 2 * strlen("GTB, normaltid"));
- out_uint8s(s, 62 - 2 * strlen("GTB, normaltid"));
-
- out_uint32_le(s, 0x0a0000);
- out_uint32_le(s, 0x050000);
- out_uint32_le(s, 3);
- out_uint32_le(s, 0);
- out_uint32_le(s, 0);
-
- rdp_out_unistr(s, "GTB, sommartid", 2 * strlen("GTB, sommartid"));
- out_uint8s(s, 62 - 2 * strlen("GTB, sommartid"));
-
- out_uint32_le(s, 0x30000);
- out_uint32_le(s, 0x050000);
- out_uint32_le(s, 2);
- out_uint32(s, 0);
- out_uint32_le(s, 0xffffffc4);
- out_uint32_le(s, 0xfffffffe);
- out_uint32_le(s, g_rdp5_performanceflags);
- out_uint32(s, 0);
-
-#endif
- }
- s_mark_end(s);
- sec_send(s, sec_flags);
-}
-
-/* Send a control PDU */
-static void
-rdp_send_control(uint16 action)
-{
- STREAM s;
-
- s = rdp_init_data(8);
-
- out_uint16_le(s, action);
- out_uint16(s, 0); /* userid */
- out_uint32(s, 0); /* control id */
-
- s_mark_end(s);
- rdp_send_data(s, RDP_DATA_PDU_CONTROL);
-}
-
-/* Send a synchronisation PDU */
-static void
-rdp_send_synchronise(void)
-{
- STREAM s;
-
- s = rdp_init_data(4);
-
- out_uint16_le(s, 1); /* type */
- out_uint16_le(s, 1002);
-
- s_mark_end(s);
- rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
-}
-
-/* Send a single input event */
-void
-rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2)
-{
- STREAM s;
-
- s = rdp_init_data(16);
-
- out_uint16_le(s, 1); /* number of events */
- out_uint16(s, 0); /* pad */
-
- out_uint32_le(s, time);
- out_uint16_le(s, message_type);
- out_uint16_le(s, device_flags);
- out_uint16_le(s, param1);
- out_uint16_le(s, param2);
-
- s_mark_end(s);
- rdp_send_data(s, RDP_DATA_PDU_INPUT);
-}
-
-/* Send a client window information PDU */
-void
-rdp_send_client_window_status(int status)
-{
- STREAM s;
- static int current_status = 1;
-
- if (current_status == status)
- return;
-
- s = rdp_init_data(12);
-
- out_uint32_le(s, status);
-
- switch (status)
- {
- case 0: /* shut the server up */
- break;
-
- case 1: /* receive data again */
- out_uint32_le(s, 0); /* unknown */
- out_uint16_le(s, g_width);
- out_uint16_le(s, g_height);
- break;
- }
-
- s_mark_end(s);
- rdp_send_data(s, RDP_DATA_PDU_CLIENT_WINDOW_STATUS);
- current_status = status;
-}
-
-/* Send persistent bitmap cache enumeration PDU's */
-static void
-rdp_enum_bmpcache2(void)
-{
- STREAM s;
- HASH_KEY keylist[BMPCACHE2_NUM_PSTCELLS];
- uint32 num_keys, offset, count, flags;
-
- offset = 0;
- num_keys = pstcache_enumerate(2, keylist);
-
- while (offset < num_keys)
- {
- count = MIN(num_keys - offset, 169);
-
- s = rdp_init_data(24 + count * sizeof(HASH_KEY));
-
- flags = 0;
- if (offset == 0)
- flags |= PDU_FLAG_FIRST;
- if (num_keys - 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, num_keys);
- out_uint32_le(s, 0);
- out_uint32_le(s, flags);
-
- /* list */
- out_uint8a(s, keylist[offset], count * sizeof(HASH_KEY));
-
- s_mark_end(s);
- rdp_send_data(s, 0x2b);
-
- offset += 169;
- }
-}
-
-/* Send an (empty) font information PDU */
-static void
-rdp_send_fonts(uint16 seq)
-{
- STREAM s;
-
- s = rdp_init_data(8);
-
- out_uint16(s, 0); /* number of fonts */
- out_uint16_le(s, 0); /* pad? */
- out_uint16_le(s, seq); /* unknown */
- out_uint16_le(s, 0x32); /* entry size */
-
- s_mark_end(s);
- rdp_send_data(s, RDP_DATA_PDU_FONT2);
-}
-
-/* Output general capability set */
-static void
-rdp_out_general_caps(STREAM s)
-{
- out_uint16_le(s, RDP_CAPSET_GENERAL);
- out_uint16_le(s, RDP_CAPLEN_GENERAL);
-
- out_uint16_le(s, 1); /* OS major type */
- out_uint16_le(s, 3); /* OS minor type */
- out_uint16_le(s, 0x200); /* Protocol version */
- out_uint16(s, 0); /* Pad */
- out_uint16(s, 0); /* Compression types */
- out_uint16_le(s, g_use_rdp5 ? 0x40d : 0);
- /* Pad, according to T.128. 0x40d seems to
- trigger
- the server to start sending RDP5 packets.
- However, the value is 0x1d04 with W2KTSK and
- NT4MS. Hmm.. Anyway, thankyou, Microsoft,
- for sending such information in a padding
- field.. */
- out_uint16(s, 0); /* Update capability */
- out_uint16(s, 0); /* Remote unshare capability */
- out_uint16(s, 0); /* Compression level */
- out_uint16(s, 0); /* Pad */
-}
-
-/* Output bitmap capability set */
-static void
-rdp_out_bitmap_caps(STREAM s)
-{
- out_uint16_le(s, RDP_CAPSET_BITMAP);
- out_uint16_le(s, RDP_CAPLEN_BITMAP);
-
- out_uint16_le(s, g_server_depth); /* Preferred colour depth */
- out_uint16_le(s, 1); /* Receive 1 BPP */
- out_uint16_le(s, 1); /* Receive 4 BPP */
- out_uint16_le(s, 1); /* Receive 8 BPP */
- out_uint16_le(s, 800); /* Desktop width */
- out_uint16_le(s, 600); /* Desktop height */
- out_uint16(s, 0); /* Pad */
- out_uint16(s, 1); /* Allow resize */
- out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */
- out_uint16(s, 0); /* Unknown */
- out_uint16_le(s, 1); /* Unknown */
- out_uint16(s, 0); /* Pad */
-}
-
-/* Output order capability set */
-static void
-rdp_out_order_caps(STREAM s)
-{
- uint8 order_caps[32];
-
- memset(order_caps, 0, 32);
- order_caps[0] = 1; /* dest blt */
- order_caps[1] = 1; /* pat blt */
- order_caps[2] = 1; /* screen blt */
- order_caps[3] = (g_bitmap_cache ? 1 : 0); /* memblt */
- order_caps[4] = 0; /* triblt */
- order_caps[8] = 1; /* line */
- order_caps[9] = 1; /* line */
- order_caps[10] = 1; /* rect */
- order_caps[11] = (g_desktop_save ? 1 : 0); /* desksave */
- order_caps[13] = 1; /* memblt */
- order_caps[14] = 1; /* triblt */
- order_caps[20] = (g_polygon_ellipse_orders ? 1 : 0); /* polygon */
- order_caps[21] = (g_polygon_ellipse_orders ? 1 : 0); /* polygon2 */
- order_caps[22] = 1; /* polyline */
- order_caps[25] = (g_polygon_ellipse_orders ? 1 : 0); /* ellipse */
- order_caps[26] = (g_polygon_ellipse_orders ? 1 : 0); /* ellipse2 */
- order_caps[27] = 1; /* text2 */
- out_uint16_le(s, RDP_CAPSET_ORDER);
- out_uint16_le(s, RDP_CAPLEN_ORDER);
-
- out_uint8s(s, 20); /* Terminal desc, pad */
- out_uint16_le(s, 1); /* Cache X granularity */
- out_uint16_le(s, 20); /* Cache Y granularity */
- out_uint16(s, 0); /* Pad */
- out_uint16_le(s, 1); /* Max order level */
- out_uint16_le(s, 0x147); /* Number of fonts */
- out_uint16_le(s, 0x2a); /* Capability flags */
- out_uint8p(s, order_caps, 32); /* Orders supported */
- out_uint16_le(s, 0x6a1); /* Text capability flags */
- out_uint8s(s, 6); /* Pad */
- out_uint32_le(s, g_desktop_save == False ? 0 : 0x38400); /* Desktop cache size */
- out_uint32(s, 0); /* Unknown */
- out_uint32_le(s, 0x4e4); /* Unknown */
-}
-
-/* Output bitmap cache capability set */
-static void
-rdp_out_bmpcache_caps(STREAM s)
-{
- int Bpp;
- out_uint16_le(s, RDP_CAPSET_BMPCACHE);
- out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
-
- Bpp = (g_server_depth + 7) / 8; /* bytes per pixel */
- out_uint8s(s, 24); /* unused */
- out_uint16_le(s, 0x258); /* entries */
- out_uint16_le(s, 0x100 * Bpp); /* max cell size */
- out_uint16_le(s, 0x12c); /* entries */
- out_uint16_le(s, 0x400 * Bpp); /* max cell size */
- out_uint16_le(s, 0x106); /* entries */
- 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 ? 2 : 0); /* version */
-
- out_uint16_be(s, 3); /* number of caches in this set */
-
- /* max cell size for cache 0 is 16x16, 1 = 32x32, 2 = 64x64, etc */
- 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)
-{
- out_uint16_le(s, RDP_CAPSET_CONTROL);
- out_uint16_le(s, RDP_CAPLEN_CONTROL);
-
- out_uint16(s, 0); /* Control capabilities */
- out_uint16(s, 0); /* Remote detach */
- out_uint16_le(s, 2); /* Control interest */
- out_uint16_le(s, 2); /* Detach interest */
-}
-
-/* Output activation capability set */
-static void
-rdp_out_activate_caps(STREAM s)
-{
- out_uint16_le(s, RDP_CAPSET_ACTIVATE);
- out_uint16_le(s, RDP_CAPLEN_ACTIVATE);
-
- out_uint16(s, 0); /* Help key */
- out_uint16(s, 0); /* Help index key */
- out_uint16(s, 0); /* Extended help key */
- out_uint16(s, 0); /* Window activate */
-}
-
-/* Output pointer capability set */
-static void
-rdp_out_pointer_caps(STREAM s)
-{
- out_uint16_le(s, RDP_CAPSET_POINTER);
- out_uint16_le(s, RDP_CAPLEN_POINTER);
-
- out_uint16(s, 0); /* Colour pointer */
- out_uint16_le(s, 20); /* Cache size */
-}
-
-/* Output share capability set */
-static void
-rdp_out_share_caps(STREAM s)
-{
- out_uint16_le(s, RDP_CAPSET_SHARE);
- out_uint16_le(s, RDP_CAPLEN_SHARE);
-
- out_uint16(s, 0); /* userid */
- out_uint16(s, 0); /* pad */
-}
-
-/* Output colour cache capability set */
-static void
-rdp_out_colcache_caps(STREAM s)
-{
- out_uint16_le(s, RDP_CAPSET_COLCACHE);
- out_uint16_le(s, RDP_CAPLEN_COLCACHE);
-
- out_uint16_le(s, 6); /* cache size */
- out_uint16(s, 0); /* pad */
-}
-
-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
-};
-
-static uint8 caps_0x0c[] = { 0x01, 0x00, 0x00, 0x00 };
-
-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
-/* Send a confirm active PDU */
-static void
-rdp_send_confirm_active(void)
-{
- STREAM s;
- uint32 sec_flags = g_encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG;
- uint16 caplen =
- 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 +
- 0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */ +
- 4 /* w2k fix, why? */ ;
-
- s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
-
- out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE));
- out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10)); /* Version 1 */
- out_uint16_le(s, (g_mcs_userid + 1001));
-
- out_uint32_le(s, g_rdp_shareid);
- out_uint16_le(s, 0x3ea); /* userid */
- out_uint16_le(s, sizeof(RDP_SOURCE));
- out_uint16_le(s, caplen);
-
- out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));
- out_uint16_le(s, 0xd); /* num_caps */
- out_uint8s(s, 2); /* pad */
-
- rdp_out_general_caps(s);
- rdp_out_bitmap_caps(s);
- rdp_out_order_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, 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);
-}
-
-/* Process a general capability set */
-static void
-rdp_process_general_caps(STREAM s)
-{
- uint16 pad2octetsB; /* rdp5 flags? */
-
- in_uint8s(s, 10);
- in_uint16_le(s, pad2octetsB);
-
- if (!pad2octetsB)
- g_use_rdp5 = False;
-}
-
-/* Process a bitmap capability set */
-static void
-rdp_process_bitmap_caps(STREAM s)
-{
- uint16 width, height, depth;
-
- in_uint16_le(s, depth);
- in_uint8s(s, 6);
-
- in_uint16_le(s, width);
- in_uint16_le(s, height);
-
- DEBUG(("setting desktop size and depth to: %dx%dx%d\n", width, height, depth));
-
- /*
- * The server may limit depth and change the size of the desktop (for
- * example when shadowing another session).
- */
- if (g_server_depth != depth)
- {
- warning("Remote desktop does not support colour depth %d; falling back to %d\n",
- g_server_depth, depth);
- g_server_depth = depth;
- }
- if (g_width != width || g_height != height)
- {
- warning("Remote desktop changed from %dx%d to %dx%d.\n", g_width, g_height,
- width, height);
- g_width = width;
- g_height = height;
- ui_resize_window();
- }
-}
-
-/* Process server capabilities */
-static void
-rdp_process_server_caps(STREAM s, uint16 length)
-{
- int n;
- uint8 *next, *start;
- uint16 ncapsets, capset_type, capset_length;
-
- start = s->p;
-
- in_uint16_le(s, ncapsets);
- in_uint8s(s, 2); /* pad */
-
- for (n = 0; n < ncapsets; n++)
- {
- if (s->p > start + length)
- return;
-
- in_uint16_le(s, capset_type);
- in_uint16_le(s, capset_length);
-
- next = s->p + capset_length - 4;
-
- switch (capset_type)
- {
- case RDP_CAPSET_GENERAL:
- rdp_process_general_caps(s);
- break;
-
- case RDP_CAPSET_BITMAP:
- rdp_process_bitmap_caps(s);
- break;
- }
-
- 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();
- rdp_send_control(RDP_CTL_COOPERATE);
- rdp_send_control(RDP_CTL_REQUEST_CONTROL);
- rdp_recv(&type); /* RDP_PDU_SYNCHRONIZE */
- rdp_recv(&type); /* RDP_CTL_COOPERATE */
- rdp_recv(&type); /* RDP_CTL_GRANT_CONTROL */
- rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(read_keyboard_state()), 0);
-
- if (g_use_rdp5)
- {
- rdp_enum_bmpcache2();
- rdp_send_fonts(3);
- }
- else
- {
- rdp_send_fonts(1);
- rdp_send_fonts(2);
- }
-
- rdp_recv(&type); /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */
- reset_order_state();
-}
-
-/* Process a colour pointer PDU */
-void
-process_colour_pointer_pdu(STREAM s)
-{
- uint16 x, y, width, height, cache_idx, masklen, datalen;
- uint8 *mask, *data;
- HCURSOR cursor;
-
- in_uint16_le(s, cache_idx);
- in_uint16_le(s, x);
- in_uint16_le(s, y);
- in_uint16_le(s, width);
- in_uint16_le(s, height);
- in_uint16_le(s, masklen);
- in_uint16_le(s, datalen);
- in_uint8p(s, data, datalen);
- in_uint8p(s, mask, masklen);
- cursor = ui_create_cursor(x, y, width, height, mask, data);
- ui_set_cursor(cursor);
- cache_put_cursor(cache_idx, cursor);
-}
-
-/* Process a cached pointer PDU */
-void
-process_cached_pointer_pdu(STREAM s)
-{
- uint16 cache_idx;
-
- in_uint16_le(s, cache_idx);
- ui_set_cursor(cache_get_cursor(cache_idx));
-}
-
-/* Process a system pointer PDU */
-void
-process_system_pointer_pdu(STREAM s)
-{
- uint16 system_pointer_type;
-
- in_uint16(s, system_pointer_type);
- switch (system_pointer_type)
- {
- case RDP_NULL_POINTER:
- ui_set_null_cursor();
- break;
-
- default:
- unimpl("System pointer message 0x%x\n", system_pointer_type);
- }
-}
-
-/* Process a pointer PDU */
-static void
-process_pointer_pdu(STREAM s)
-{
- uint16 message_type;
- uint16 x, y;
-
- in_uint16_le(s, message_type);
- in_uint8s(s, 2); /* pad */
-
- switch (message_type)
- {
- case RDP_POINTER_MOVE:
- in_uint16_le(s, x);
- in_uint16_le(s, y);
- if (s_check(s))
- ui_move_pointer(x, y);
- break;
-
- case RDP_POINTER_COLOR:
- process_colour_pointer_pdu(s);
- break;
-
- case RDP_POINTER_CACHED:
- process_cached_pointer_pdu(s);
- break;
-
- case RDP_POINTER_SYSTEM:
- process_system_pointer_pdu(s);
- break;
-
- default:
- unimpl("Pointer message 0x%x\n", message_type);
- }
-}
-
-/* Process bitmap updates */
-void
-process_bitmap_updates(STREAM s)
-{
- uint16 num_updates;
- uint16 left, top, right, bottom, width, height;
- uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
- uint8 *data, *bmpdata;
- int i;
-
- in_uint16_le(s, num_updates);
-
- for (i = 0; i < num_updates; i++)
- {
- in_uint16_le(s, left);
- in_uint16_le(s, top);
- in_uint16_le(s, right);
- in_uint16_le(s, bottom);
- in_uint16_le(s, width);
- in_uint16_le(s, height);
- in_uint16_le(s, bpp);
- Bpp = (bpp + 7) / 8;
- in_uint16_le(s, compress);
- in_uint16_le(s, bufsize);
-
- cx = right - left + 1;
- cy = bottom - top + 1;
-
- DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",
- left, top, right, bottom, width, height, Bpp, compress));
- if (!compress)
- {
- size = width * height * Bpp; /* same as bufsize */
- }
- else if (compress & 0x400)
- {
- size = bufsize;
- }
- else
- {
- in_uint8s(s, 2); /* pad */
- in_uint16_le(s, size);
- in_uint8s(s, 4);
- }
- in_uint8p(s, data, size);
- ui_paint_bitmap_ex(left, top, cx, cy, width, height, data, size, compress);
-#if 0
- if (!compress)
- {
- int y;
- bmpdata = (uint8 *) xmalloc(width * height * Bpp);
- for (y = 0; y < height; y++)
- {
- in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
- width * Bpp);
- }
- ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
- xfree(bmpdata);
- continue;
- }
-
-
- if (compress & 0x400)
- {
- size = bufsize;
- }
- else
- {
- in_uint8s(s, 2); /* pad */
- in_uint16_le(s, size);
- in_uint8s(s, 4); /* line_size, final_size */
- }
- in_uint8p(s, data, size);
- bmpdata = (uint8 *) xmalloc(width * height * Bpp);
- if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
- {
- ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
- }
- else
- {
- DEBUG_RDP5(("Failed to decompress data\n"));
- }
- xfree(bmpdata);
-#endif
- }
-}
-
-/* Process a palette update */
-void
-process_palette(STREAM s)
-{
- COLOURENTRY *entry;
- COLOURMAP map;
- RD_HCOLOURMAP hmap;
- int i;
-
- in_uint8s(s, 2); /* pad */
- in_uint16_le(s, map.ncolours);
- in_uint8s(s, 2); /* pad */
-
- map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
-
- DEBUG(("PALETTE(c=%d)\n", map.ncolours));
-
- for (i = 0; i < map.ncolours; i++)
- {
- entry = &map.colours[i];
- in_uint8(s, entry->red);
- in_uint8(s, entry->green);
- in_uint8(s, entry->blue);
- }
-
- hmap = ui_create_colourmap(&map);
- ui_set_colourmap(hmap);
-
- xfree(map.colours);
-}
-
-/* Process an update PDU */
-static void
-process_update_pdu(STREAM s)
-{
- uint16 update_type, count;
-
- in_uint16_le(s, update_type);
-
- ui_begin_update();
- switch (update_type)
- {
- case RDP_UPDATE_ORDERS:
- in_uint8s(s, 2); /* pad */
- in_uint16_le(s, count);
- in_uint8s(s, 2); /* pad */
- process_orders(s, count);
- break;
-
- case RDP_UPDATE_BITMAP:
- process_bitmap_updates(s);
- break;
-
- case RDP_UPDATE_PALETTE:
- process_palette(s);
- break;
-
- case RDP_UPDATE_SYNCHRONIZE:
- break;
-
- default:
- unimpl("update %d\n", update_type);
- }
- ui_end_update();
-}
-
-/* Process a disconnect PDU */
-void
-process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason)
-{
- in_uint32_le(s, *ext_disc_reason);
-
- DEBUG(("Received disconnect PDU\n"));
-}
-
-/* Process data PDU */
-static BOOL
-process_data_pdu(STREAM s, uint32 * ext_disc_reason)
-{
- uint8 data_pdu_type;
- uint8 ctype;
- uint16 clen;
- uint32 len;
-
- uint32 roff, rlen;
-
- struct stream *ns = &(g_mppc_dict.ns);
-
- in_uint8s(s, 6); /* shareid, pad, streamid */
- in_uint16(s, len);
- in_uint8(s, data_pdu_type);
- in_uint8(s, ctype);
- in_uint16(s, clen);
- clen -= 18;
-
- if (ctype & RDP_MPPC_COMPRESSED)
- {
- if (len > RDP_MPPC_DICT_SIZE)
- error("error decompressed packet size exceeds max\n");
- if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)
- error("error while decompressing packet\n");
-
- /* len -= 18; */
-
- /* allocate memory and copy the uncompressed data into the temporary stream */
- ns->data = (uint8 *) xrealloc(ns->data, rlen);
-
- memcpy((ns->data), (unsigned char *) (g_mppc_dict.hist + roff), rlen);
-
- ns->size = rlen;
- ns->end = (ns->data + ns->size);
- ns->p = ns->data;
- ns->rdp_hdr = ns->p;
-
- s = ns;
- }
-
- switch (data_pdu_type)
- {
- case RDP_DATA_PDU_UPDATE:
- process_update_pdu(s);
- break;
-
- case RDP_DATA_PDU_CONTROL:
- DEBUG(("Received Control PDU\n"));
- break;
-
- case RDP_DATA_PDU_SYNCHRONISE:
- DEBUG(("Received Sync PDU\n"));
- break;
-
- case RDP_DATA_PDU_POINTER:
- process_pointer_pdu(s);
- break;
-
- case RDP_DATA_PDU_BELL:
- ui_bell();
- break;
-
- case RDP_DATA_PDU_LOGON:
- DEBUG(("Received Logon PDU\n"));
- /* User logged on */
- break;
-
- case RDP_DATA_PDU_DISCONNECT:
- process_disconnect_pdu(s, ext_disc_reason);
- return True;
-
- default:
- unimpl("data PDU %d\n", data_pdu_type);
- }
- return False;
-}
-
-/* Process redirect PDU from Session Directory */
-static BOOL
-process_redirect_pdu(STREAM s /*, uint32 * ext_disc_reason */ )
-{
- uint32 len;
-
- /* these 2 bytes are unknown, seem to be zeros */
- in_uint8s(s, 2);
-
- /* read connection flags */
- in_uint32_le(s, g_redirect_flags);
-
- /* read length of ip string */
- in_uint32_le(s, len);
-
- /* read ip string */
- rdp_in_unistr(s, g_redirect_server, len);
-
- /* read length of cookie string */
- in_uint32_le(s, len);
-
- /* read cookie string (plain ASCII) */
- in_uint8a(s, g_redirect_cookie, len);
- g_redirect_cookie[len] = 0;
-
- /* read length of username string */
- in_uint32_le(s, len);
-
- /* read username string */
- rdp_in_unistr(s, g_redirect_username, len);
-
- /* read length of domain string */
- in_uint32_le(s, len);
-
- /* read domain string */
- rdp_in_unistr(s, g_redirect_domain, len);
-
- /* read length of password string */
- in_uint32_le(s, len);
-
- /* read password string */
- rdp_in_unistr(s, g_redirect_password, len);
-
- g_redirect = True;
-
- return True;
-}
-
-/* Process incoming packets */
-/* nevers gets out of here till app is done */
-void
-rdp_main_loop(BOOL * deactivated, uint32 * ext_disc_reason)
-{
- while (rdp_loop(deactivated, ext_disc_reason))
- ;
-}
-
-/* used in uiports and rdp_main_loop, processes the rdp packets waiting */
-BOOL
-rdp_loop(BOOL * deactivated, uint32 * ext_disc_reason)
-{
- uint8 type;
- BOOL disc = False; /* True when a disconnect PDU was received */
- BOOL cont = True;
- STREAM s;
-
- while (cont)
- {
- s = rdp_recv(&type);
- if (s == NULL)
- return False;
- switch (type)
- {
- case RDP_PDU_DEMAND_ACTIVE:
- process_demand_active(s);
- *deactivated = False;
- break;
- case RDP_PDU_DEACTIVATE:
- DEBUG(("RDP_PDU_DEACTIVATE\n"));
- *deactivated = True;
- break;
- case RDP_PDU_REDIRECT:
- return process_redirect_pdu(s);
- break;
- case RDP_PDU_DATA:
- disc = process_data_pdu(s, ext_disc_reason);
- break;
- case 0:
- break;
- default:
- unimpl("PDU %d\n", type);
- }
- if (disc)
- return False;
- cont = g_next_packet < s->end;
- }
- return True;
-}
-
-/* Establish a connection up to the RDP layer */
-BOOL
-rdp_connect(char *server, uint32 flags, char *domain, char *password,
- char *command, char *directory)
-{
- if (!sec_connect(server, g_username))
- return False;
-
- rdp_send_logon_info(flags, domain, g_username, password, command, directory);
- return True;
-}
-
-/* Establish a reconnection up to the RDP layer */
-BOOL
-rdp_reconnect(char *server, uint32 flags, char *domain, char *password,
- char *command, char *directory, char *cookie)
-{
- if (!sec_reconnect(server))
- return False;
-
- rdp_send_logon_info(flags, domain, g_username, password, command, directory);
- return True;
-}
-
-/* Called during redirection to reset the state to support redirection */
-void
-rdp_reset_state(void)
-{
- g_next_packet = NULL; /* reset the packet information */
- g_rdp_shareid = 0;
- sec_reset_state();
-}
-
-/* Disconnect from the RDP layer */
-void
-rdp_disconnect(void)
-{
- sec_disconnect();
-}
+/* -*- c-basic-offset: 8 -*- + rdesktop: A Remote Desktop Protocol client. + Protocol services - RDP layer + Copyright (C) Matthew Chapman 1999-2005 + + 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 <time.h> +#ifndef _WIN32 +#include <errno.h> +#include <unistd.h> +#endif +#include "rdesktop.h" + +#ifdef HAVE_ICONV +#ifdef HAVE_ICONV_H +#include <iconv.h> +#endif + +#ifndef ICONV_CONST +#define ICONV_CONST "" +#endif +#endif + +extern uint16 g_mcs_userid; +extern char g_username[64]; +extern char g_codepage[16]; +extern BOOL g_bitmap_compression; +extern BOOL g_orders; +extern BOOL g_encryption; +extern BOOL g_desktop_save; +extern BOOL g_polygon_ellipse_orders; +extern BOOL g_use_rdp5; +extern uint16 g_server_rdp_version; +extern uint32 g_rdp5_performanceflags; +extern int g_server_depth; +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; + +extern RDPCOMP g_mppc_dict; + +/* Session Directory support */ +extern BOOL g_redirect; +extern char g_redirect_server[64]; +extern char g_redirect_domain[16]; +extern char g_redirect_password[64]; +extern char g_redirect_username[64]; +extern char g_redirect_cookie[128]; +extern uint32 g_redirect_flags; +/* END Session Directory support */ + +#ifdef WITH_DEBUG +static uint32 g_packetno; +#endif + +#ifdef HAVE_ICONV +static BOOL g_iconv_works = True; +#endif + +/* Receive an RDP packet */ +static STREAM +rdp_recv(uint8 * type) +{ + static STREAM rdp_s; + uint16 length, pdu_type; + uint8 rdpver; + + if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end) || (g_next_packet == NULL)) + { + rdp_s = sec_recv(&rdpver); + if (rdp_s == NULL) + return NULL; + if (rdpver == 0xff) + { + g_next_packet = rdp_s->end; + *type = 0; + return rdp_s; + } + else if (rdpver != 3) + { + /* rdp5_process should move g_next_packet ok */ + rdp5_process(rdp_s); + *type = 0; + return rdp_s; + } + + g_next_packet = rdp_s->p; + } + else + { + rdp_s->p = g_next_packet; + } + + in_uint16_le(rdp_s, length); + /* 32k packets are really 8, keepalive fix */ + if (length == 0x8000) + { + g_next_packet += 8; + *type = 0; + return rdp_s; + } + in_uint16_le(rdp_s, pdu_type); + in_uint8s(rdp_s, 2); /* userid */ + *type = pdu_type & 0xf; + +#ifdef WITH_DEBUG + DEBUG(("RDP packet #%d, (type %x)\n", ++g_packetno, *type)); + hexdump(g_next_packet, length); +#endif /* */ + + g_next_packet += length; + return rdp_s; +} + +/* Initialise an RDP data packet */ +static STREAM +rdp_init_data(int maxlen) +{ + STREAM s; + + s = sec_init(g_encryption ? SEC_ENCRYPT : 0, maxlen + 18); + s_push_layer(s, rdp_hdr, 18); + + return s; +} + +/* Send an RDP data packet */ +static void +rdp_send_data(STREAM s, uint8 data_pdu_type) +{ + uint16 length; + + s_pop_layer(s, rdp_hdr); + length = s->end - s->p; + + out_uint16_le(s, length); + out_uint16_le(s, (RDP_PDU_DATA | 0x10)); + out_uint16_le(s, (g_mcs_userid + 1001)); + + out_uint32_le(s, g_rdp_shareid); + out_uint8(s, 0); /* pad */ + out_uint8(s, 1); /* streamid */ + out_uint16_le(s, (length - 14)); + out_uint8(s, data_pdu_type); + out_uint8(s, 0); /* compress_type */ + out_uint16(s, 0); /* compress_len */ + + sec_send(s, g_encryption ? SEC_ENCRYPT : 0); +} + +/* Output a string in Unicode */ +void +rdp_out_unistr(STREAM s, char *string, int len) +{ +#ifdef HAVE_ICONV + size_t ibl = strlen(string), obl = len + 2; + static iconv_t iconv_h = (iconv_t) - 1; + char *pin = string, *pout = (char *) s->p; + + memset(pout, 0, len + 4); + + if (g_iconv_works) + { + if (iconv_h == (iconv_t) - 1) + { + size_t i = 1, o = 4; + if ((iconv_h = iconv_open(WINDOWS_CODEPAGE, g_codepage)) == (iconv_t) - 1) + { + warning("rdp_out_unistr: iconv_open[%s -> %s] fail %d\n", + g_codepage, WINDOWS_CODEPAGE, (int) iconv_h); + + g_iconv_works = False; + rdp_out_unistr(s, string, len); + return; + } + if (iconv(iconv_h, (ICONV_CONST char **) &pin, &i, &pout, &o) == + (size_t) - 1) + { + iconv_close(iconv_h); + iconv_h = (iconv_t) - 1; + warning("rdp_out_unistr: iconv(1) fail, errno %d\n", errno); + + g_iconv_works = False; + rdp_out_unistr(s, string, len); + return; + } + pin = string; + pout = (char *) s->p; + } + + if (iconv(iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1) + { + iconv_close(iconv_h); + iconv_h = (iconv_t) - 1; + warning("rdp_out_unistr: iconv(2) fail, errno %d\n", errno); + + g_iconv_works = False; + rdp_out_unistr(s, string, len); + return; + } + + s->p += len + 2; + + } + else +#endif + { + int i = 0, j = 0; + + len += 2; + + while (i < len) + { + s->p[i++] = string[j++]; + s->p[i++] = 0; + } + + s->p += len; + } +} + +/* Input a string in Unicode + * + * Returns str_len of string + */ +int +rdp_in_unistr(STREAM s, char *string, int uni_len) +{ +#ifdef HAVE_ICONV + size_t ibl = uni_len, obl = uni_len; + char *pin = (char *) s->p, *pout = string; + static iconv_t iconv_h = (iconv_t) - 1; + + if (g_iconv_works) + { + if (iconv_h == (iconv_t) - 1) + { + if ((iconv_h = iconv_open(g_codepage, WINDOWS_CODEPAGE)) == (iconv_t) - 1) + { + warning("rdp_in_unistr: iconv_open[%s -> %s] fail %d\n", + WINDOWS_CODEPAGE, g_codepage, (int) iconv_h); + + g_iconv_works = False; + return rdp_in_unistr(s, string, uni_len); + } + } + + if (iconv(iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1) + { + iconv_close(iconv_h); + iconv_h = (iconv_t) - 1; + warning("rdp_in_unistr: iconv fail, errno %d\n", errno); + + g_iconv_works = False; + return rdp_in_unistr(s, string, uni_len); + } + + /* we must update the location of the current STREAM for future reads of s->p */ + s->p += uni_len; + + return pout - string; + } + else +#endif + { + int i = 0; + + while (i < uni_len / 2) + { + in_uint8a(s, &string[i++], 1); + in_uint8s(s, 1); + } + + return i - 1; + } +} + + +/* Parse a logon info packet */ +static void +rdp_send_logon_info(uint32 flags, char *domain, char *user, + char *password, char *program, char *directory) +{ + char *ipaddr = tcp_get_address(); + int len_domain = 2 * strlen(domain); + int len_user = 2 * strlen(user); + int len_password = 2 * strlen(password); + int len_program = 2 * strlen(program); + int len_directory = 2 * strlen(directory); + int len_ip = 2 * strlen(ipaddr); + int len_dll = 2 * strlen("C:\\WINNT\\System32\\mstscax.dll"); + int packetlen = 0; + uint32 sec_flags = g_encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO; + STREAM s; + //time_t t = time(NULL); + //time_t tzone; + + if (!g_use_rdp5 || 1 == g_server_rdp_version) + { + DEBUG_RDP5(("Sending RDP4-style Logon packet\n")); + + s = sec_init(sec_flags, 18 + len_domain + len_user + len_password + + len_program + len_directory + 10); + + out_uint32(s, 0); + out_uint32_le(s, flags); + out_uint16_le(s, len_domain); + out_uint16_le(s, len_user); + out_uint16_le(s, len_password); + out_uint16_le(s, len_program); + out_uint16_le(s, len_directory); + rdp_out_unistr(s, domain, len_domain); + rdp_out_unistr(s, user, len_user); + rdp_out_unistr(s, password, len_password); + rdp_out_unistr(s, program, len_program); + rdp_out_unistr(s, directory, len_directory); + } + else + { +#if 0 + flags |= RDP_LOGON_BLOB; + DEBUG_RDP5(("Sending RDP5-style Logon packet\n")); + packetlen = 4 + /* Unknown uint32 */ + 4 + /* flags */ + 2 + /* len_domain */ + 2 + /* len_user */ + (flags & RDP_LOGON_AUTO ? 2 : 0) + /* len_password */ + (flags & RDP_LOGON_BLOB ? 2 : 0) + /* Length of BLOB */ + 2 + /* len_program */ + 2 + /* len_directory */ + (0 < len_domain ? len_domain : 2) + /* domain */ + len_user + (flags & RDP_LOGON_AUTO ? len_password : 0) + 0 + /* We have no 512 byte BLOB. Perhaps we must? */ + (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO) ? 2 : 0) + /* After the BLOB is a unknown int16. If there is a BLOB, that is. */ + (0 < len_program ? len_program : 2) + (0 < len_directory ? len_directory : 2) + 2 + /* Unknown (2) */ + 2 + /* Client ip length */ + len_ip + /* Client ip */ + 2 + /* DLL string length */ + len_dll + /* DLL string */ + 2 + /* Unknown */ + 2 + /* Unknown */ + 64 + /* Time zone #0 */ + 2 + /* Unknown */ + 64 + /* Time zone #1 */ + 32; /* Unknown */ + + s = sec_init(sec_flags, packetlen); + DEBUG_RDP5(("Called sec_init with packetlen %d\n", packetlen)); + + out_uint32(s, 0); /* Unknown */ + out_uint32_le(s, flags); + out_uint16_le(s, len_domain); + out_uint16_le(s, len_user); + if (flags & RDP_LOGON_AUTO) + { + out_uint16_le(s, len_password); + + } + if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO)) + { + out_uint16_le(s, 0); + } + out_uint16_le(s, len_program); + out_uint16_le(s, len_directory); + if (0 < len_domain) + rdp_out_unistr(s, domain, len_domain); + else + out_uint16_le(s, 0); + rdp_out_unistr(s, user, len_user); + if (flags & RDP_LOGON_AUTO) + { + rdp_out_unistr(s, password, len_password); + } + if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO)) + { + out_uint16_le(s, 0); + } + if (0 < len_program) + { + rdp_out_unistr(s, program, len_program); + + } + else + { + out_uint16_le(s, 0); + } + if (0 < len_directory) + { + rdp_out_unistr(s, directory, len_directory); + } + else + { + out_uint16_le(s, 0); + } + out_uint16_le(s, 2); + out_uint16_le(s, len_ip + 2); /* Length of client ip */ + rdp_out_unistr(s, ipaddr, len_ip); + out_uint16_le(s, len_dll + 2); + rdp_out_unistr(s, "C:\\WINNT\\System32\\mstscax.dll", len_dll); + + tzone = (mktime(gmtime(&t)) - mktime(localtime(&t))) / 60; + out_uint32_le(s, tzone); + + rdp_out_unistr(s, "GTB, normaltid", 2 * strlen("GTB, normaltid")); + out_uint8s(s, 62 - 2 * strlen("GTB, normaltid")); + + out_uint32_le(s, 0x0a0000); + out_uint32_le(s, 0x050000); + out_uint32_le(s, 3); + out_uint32_le(s, 0); + out_uint32_le(s, 0); + + rdp_out_unistr(s, "GTB, sommartid", 2 * strlen("GTB, sommartid")); + out_uint8s(s, 62 - 2 * strlen("GTB, sommartid")); + + out_uint32_le(s, 0x30000); + out_uint32_le(s, 0x050000); + out_uint32_le(s, 2); + out_uint32(s, 0); + out_uint32_le(s, 0xffffffc4); + out_uint32_le(s, 0xfffffffe); + out_uint32_le(s, g_rdp5_performanceflags); + out_uint32(s, 0); + +#endif + } + s_mark_end(s); + sec_send(s, sec_flags); +} + +/* Send a control PDU */ +static void +rdp_send_control(uint16 action) +{ + STREAM s; + + s = rdp_init_data(8); + + out_uint16_le(s, action); + out_uint16(s, 0); /* userid */ + out_uint32(s, 0); /* control id */ + + s_mark_end(s); + rdp_send_data(s, RDP_DATA_PDU_CONTROL); +} + +/* Send a synchronisation PDU */ +static void +rdp_send_synchronise(void) +{ + STREAM s; + + s = rdp_init_data(4); + + out_uint16_le(s, 1); /* type */ + out_uint16_le(s, 1002); + + s_mark_end(s); + rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE); +} + +/* Send a single input event */ +void +rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2) +{ + STREAM s; + + s = rdp_init_data(16); + + out_uint16_le(s, 1); /* number of events */ + out_uint16(s, 0); /* pad */ + + out_uint32_le(s, time); + out_uint16_le(s, message_type); + out_uint16_le(s, device_flags); + out_uint16_le(s, param1); + out_uint16_le(s, param2); + + s_mark_end(s); + rdp_send_data(s, RDP_DATA_PDU_INPUT); +} + +/* Send a client window information PDU */ +void +rdp_send_client_window_status(int status) +{ + STREAM s; + static int current_status = 1; + + if (current_status == status) + return; + + s = rdp_init_data(12); + + out_uint32_le(s, status); + + switch (status) + { + case 0: /* shut the server up */ + break; + + case 1: /* receive data again */ + out_uint32_le(s, 0); /* unknown */ + out_uint16_le(s, g_width); + out_uint16_le(s, g_height); + break; + } + + s_mark_end(s); + rdp_send_data(s, RDP_DATA_PDU_CLIENT_WINDOW_STATUS); + current_status = status; +} + +/* Send persistent bitmap cache enumeration PDU's */ +static void +rdp_enum_bmpcache2(void) +{ + STREAM s; + HASH_KEY keylist[BMPCACHE2_NUM_PSTCELLS]; + uint32 num_keys, offset, count, flags; + + offset = 0; + num_keys = pstcache_enumerate(2, keylist); + + while (offset < num_keys) + { + count = MIN(num_keys - offset, 169); + + s = rdp_init_data(24 + count * sizeof(HASH_KEY)); + + flags = 0; + if (offset == 0) + flags |= PDU_FLAG_FIRST; + if (num_keys - 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, num_keys); + out_uint32_le(s, 0); + out_uint32_le(s, flags); + + /* list */ + out_uint8a(s, keylist[offset], count * sizeof(HASH_KEY)); + + s_mark_end(s); + rdp_send_data(s, 0x2b); + + offset += 169; + } +} + +/* Send an (empty) font information PDU */ +static void +rdp_send_fonts(uint16 seq) +{ + STREAM s; + + s = rdp_init_data(8); + + out_uint16(s, 0); /* number of fonts */ + out_uint16_le(s, 0); /* pad? */ + out_uint16_le(s, seq); /* unknown */ + out_uint16_le(s, 0x32); /* entry size */ + + s_mark_end(s); + rdp_send_data(s, RDP_DATA_PDU_FONT2); +} + +/* Output general capability set */ +static void +rdp_out_general_caps(STREAM s) +{ + out_uint16_le(s, RDP_CAPSET_GENERAL); + out_uint16_le(s, RDP_CAPLEN_GENERAL); + + out_uint16_le(s, 1); /* OS major type */ + out_uint16_le(s, 3); /* OS minor type */ + out_uint16_le(s, 0x200); /* Protocol version */ + out_uint16(s, 0); /* Pad */ + out_uint16(s, 0); /* Compression types */ + out_uint16_le(s, g_use_rdp5 ? 0x40d : 0); + /* Pad, according to T.128. 0x40d seems to + trigger + the server to start sending RDP5 packets. + However, the value is 0x1d04 with W2KTSK and + NT4MS. Hmm.. Anyway, thankyou, Microsoft, + for sending such information in a padding + field.. */ + out_uint16(s, 0); /* Update capability */ + out_uint16(s, 0); /* Remote unshare capability */ + out_uint16(s, 0); /* Compression level */ + out_uint16(s, 0); /* Pad */ +} + +/* Output bitmap capability set */ +static void +rdp_out_bitmap_caps(STREAM s) +{ + out_uint16_le(s, RDP_CAPSET_BITMAP); + out_uint16_le(s, RDP_CAPLEN_BITMAP); + + out_uint16_le(s, g_server_depth); /* Preferred colour depth */ + out_uint16_le(s, 1); /* Receive 1 BPP */ + out_uint16_le(s, 1); /* Receive 4 BPP */ + out_uint16_le(s, 1); /* Receive 8 BPP */ + out_uint16_le(s, 800); /* Desktop width */ + out_uint16_le(s, 600); /* Desktop height */ + out_uint16(s, 0); /* Pad */ + out_uint16(s, 1); /* Allow resize */ + out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */ + out_uint16(s, 0); /* Unknown */ + out_uint16_le(s, 1); /* Unknown */ + out_uint16(s, 0); /* Pad */ +} + +/* Output order capability set */ +static void +rdp_out_order_caps(STREAM s) +{ + uint8 order_caps[32]; + + memset(order_caps, 0, 32); + order_caps[0] = 1; /* dest blt */ + order_caps[1] = 1; /* pat blt */ + order_caps[2] = 1; /* screen blt */ + order_caps[3] = (g_bitmap_cache ? 1 : 0); /* memblt */ + order_caps[4] = 0; /* triblt */ + order_caps[8] = 1; /* line */ + order_caps[9] = 1; /* line */ + order_caps[10] = 1; /* rect */ + order_caps[11] = (g_desktop_save ? 1 : 0); /* desksave */ + order_caps[13] = 1; /* memblt */ + order_caps[14] = 1; /* triblt */ + order_caps[20] = (g_polygon_ellipse_orders ? 1 : 0); /* polygon */ + order_caps[21] = (g_polygon_ellipse_orders ? 1 : 0); /* polygon2 */ + order_caps[22] = 1; /* polyline */ + order_caps[25] = (g_polygon_ellipse_orders ? 1 : 0); /* ellipse */ + order_caps[26] = (g_polygon_ellipse_orders ? 1 : 0); /* ellipse2 */ + order_caps[27] = 1; /* text2 */ + out_uint16_le(s, RDP_CAPSET_ORDER); + out_uint16_le(s, RDP_CAPLEN_ORDER); + + out_uint8s(s, 20); /* Terminal desc, pad */ + out_uint16_le(s, 1); /* Cache X granularity */ + out_uint16_le(s, 20); /* Cache Y granularity */ + out_uint16(s, 0); /* Pad */ + out_uint16_le(s, 1); /* Max order level */ + out_uint16_le(s, 0x147); /* Number of fonts */ + out_uint16_le(s, 0x2a); /* Capability flags */ + out_uint8p(s, order_caps, 32); /* Orders supported */ + out_uint16_le(s, 0x6a1); /* Text capability flags */ + out_uint8s(s, 6); /* Pad */ + out_uint32_le(s, g_desktop_save == False ? 0 : 0x38400); /* Desktop cache size */ + out_uint32(s, 0); /* Unknown */ + out_uint32_le(s, 0x4e4); /* Unknown */ +} + +/* Output bitmap cache capability set */ +static void +rdp_out_bmpcache_caps(STREAM s) +{ + int Bpp; + out_uint16_le(s, RDP_CAPSET_BMPCACHE); + out_uint16_le(s, RDP_CAPLEN_BMPCACHE); + + Bpp = (g_server_depth + 7) / 8; /* bytes per pixel */ + out_uint8s(s, 24); /* unused */ + out_uint16_le(s, 0x258); /* entries */ + out_uint16_le(s, 0x100 * Bpp); /* max cell size */ + out_uint16_le(s, 0x12c); /* entries */ + out_uint16_le(s, 0x400 * Bpp); /* max cell size */ + out_uint16_le(s, 0x106); /* entries */ + 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 ? 2 : 0); /* version */ + + out_uint16_be(s, 3); /* number of caches in this set */ + + /* max cell size for cache 0 is 16x16, 1 = 32x32, 2 = 64x64, etc */ + 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) +{ + out_uint16_le(s, RDP_CAPSET_CONTROL); + out_uint16_le(s, RDP_CAPLEN_CONTROL); + + out_uint16(s, 0); /* Control capabilities */ + out_uint16(s, 0); /* Remote detach */ + out_uint16_le(s, 2); /* Control interest */ + out_uint16_le(s, 2); /* Detach interest */ +} + +/* Output activation capability set */ +static void +rdp_out_activate_caps(STREAM s) +{ + out_uint16_le(s, RDP_CAPSET_ACTIVATE); + out_uint16_le(s, RDP_CAPLEN_ACTIVATE); + + out_uint16(s, 0); /* Help key */ + out_uint16(s, 0); /* Help index key */ + out_uint16(s, 0); /* Extended help key */ + out_uint16(s, 0); /* Window activate */ +} + +/* Output pointer capability set */ +static void +rdp_out_pointer_caps(STREAM s) +{ + out_uint16_le(s, RDP_CAPSET_POINTER); + out_uint16_le(s, RDP_CAPLEN_POINTER); + + out_uint16(s, 0); /* Colour pointer */ + out_uint16_le(s, 20); /* Cache size */ +} + +/* Output share capability set */ +static void +rdp_out_share_caps(STREAM s) +{ + out_uint16_le(s, RDP_CAPSET_SHARE); + out_uint16_le(s, RDP_CAPLEN_SHARE); + + out_uint16(s, 0); /* userid */ + out_uint16(s, 0); /* pad */ +} + +/* Output colour cache capability set */ +static void +rdp_out_colcache_caps(STREAM s) +{ + out_uint16_le(s, RDP_CAPSET_COLCACHE); + out_uint16_le(s, RDP_CAPLEN_COLCACHE); + + out_uint16_le(s, 6); /* cache size */ + out_uint16(s, 0); /* pad */ +} + +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 +}; + +static uint8 caps_0x0c[] = { 0x01, 0x00, 0x00, 0x00 }; + +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 +/* Send a confirm active PDU */ +static void +rdp_send_confirm_active(void) +{ + STREAM s; + uint32 sec_flags = g_encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG; + uint16 caplen = + 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 + + 0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */ + + 4 /* w2k fix, why? */ ; + + s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE)); + + out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE)); + out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10)); /* Version 1 */ + out_uint16_le(s, (g_mcs_userid + 1001)); + + out_uint32_le(s, g_rdp_shareid); + out_uint16_le(s, 0x3ea); /* userid */ + out_uint16_le(s, sizeof(RDP_SOURCE)); + out_uint16_le(s, caplen); + + out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE)); + out_uint16_le(s, 0xd); /* num_caps */ + out_uint8s(s, 2); /* pad */ + + rdp_out_general_caps(s); + rdp_out_bitmap_caps(s); + rdp_out_order_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, 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); +} + +/* Process a general capability set */ +static void +rdp_process_general_caps(STREAM s) +{ + uint16 pad2octetsB; /* rdp5 flags? */ + + in_uint8s(s, 10); + in_uint16_le(s, pad2octetsB); + + if (!pad2octetsB) + g_use_rdp5 = False; +} + +/* Process a bitmap capability set */ +static void +rdp_process_bitmap_caps(STREAM s) +{ + uint16 width, height, depth; + + in_uint16_le(s, depth); + in_uint8s(s, 6); + + in_uint16_le(s, width); + in_uint16_le(s, height); + + DEBUG(("setting desktop size and depth to: %dx%dx%d\n", width, height, depth)); + + /* + * The server may limit depth and change the size of the desktop (for + * example when shadowing another session). + */ + if (g_server_depth != depth) + { + warning("Remote desktop does not support colour depth %d; falling back to %d\n", + g_server_depth, depth); + g_server_depth = depth; + } + if (g_width != width || g_height != height) + { + warning("Remote desktop changed from %dx%d to %dx%d.\n", g_width, g_height, + width, height); + g_width = width; + g_height = height; + ui_resize_window(); + } +} + +/* Process server capabilities */ +static void +rdp_process_server_caps(STREAM s, uint16 length) +{ + int n; + uint8 *next, *start; + uint16 ncapsets, capset_type, capset_length; + + start = s->p; + + in_uint16_le(s, ncapsets); + in_uint8s(s, 2); /* pad */ + + for (n = 0; n < ncapsets; n++) + { + if (s->p > start + length) + return; + + in_uint16_le(s, capset_type); + in_uint16_le(s, capset_length); + + next = s->p + capset_length - 4; + + switch (capset_type) + { + case RDP_CAPSET_GENERAL: + rdp_process_general_caps(s); + break; + + case RDP_CAPSET_BITMAP: + rdp_process_bitmap_caps(s); + break; + } + + 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(); + rdp_send_control(RDP_CTL_COOPERATE); + rdp_send_control(RDP_CTL_REQUEST_CONTROL); + rdp_recv(&type); /* RDP_PDU_SYNCHRONIZE */ + rdp_recv(&type); /* RDP_CTL_COOPERATE */ + rdp_recv(&type); /* RDP_CTL_GRANT_CONTROL */ + rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(read_keyboard_state()), 0); + + if (g_use_rdp5) + { + rdp_enum_bmpcache2(); + rdp_send_fonts(3); + } + else + { + rdp_send_fonts(1); + rdp_send_fonts(2); + } + + rdp_recv(&type); /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */ + reset_order_state(); +} + +/* Process a colour pointer PDU */ +void +process_colour_pointer_pdu(STREAM s) +{ + uint16 x, y, width, height, cache_idx, masklen, datalen; + uint8 *mask, *data; + HCURSOR cursor; + + in_uint16_le(s, cache_idx); + in_uint16_le(s, x); + in_uint16_le(s, y); + in_uint16_le(s, width); + in_uint16_le(s, height); + in_uint16_le(s, masklen); + in_uint16_le(s, datalen); + in_uint8p(s, data, datalen); + in_uint8p(s, mask, masklen); + cursor = ui_create_cursor(x, y, width, height, mask, data); + ui_set_cursor(cursor); + cache_put_cursor(cache_idx, cursor); +} + +/* Process a cached pointer PDU */ +void +process_cached_pointer_pdu(STREAM s) +{ + uint16 cache_idx; + + in_uint16_le(s, cache_idx); + ui_set_cursor(cache_get_cursor(cache_idx)); +} + +/* Process a system pointer PDU */ +void +process_system_pointer_pdu(STREAM s) +{ + uint16 system_pointer_type; + + in_uint16(s, system_pointer_type); + switch (system_pointer_type) + { + case RDP_NULL_POINTER: + ui_set_null_cursor(); + break; + + default: + unimpl("System pointer message 0x%x\n", system_pointer_type); + } +} + +/* Process a pointer PDU */ +static void +process_pointer_pdu(STREAM s) +{ + uint16 message_type; + uint16 x, y; + + in_uint16_le(s, message_type); + in_uint8s(s, 2); /* pad */ + + switch (message_type) + { + case RDP_POINTER_MOVE: + in_uint16_le(s, x); + in_uint16_le(s, y); + if (s_check(s)) + ui_move_pointer(x, y); + break; + + case RDP_POINTER_COLOR: + process_colour_pointer_pdu(s); + break; + + case RDP_POINTER_CACHED: + process_cached_pointer_pdu(s); + break; + + case RDP_POINTER_SYSTEM: + process_system_pointer_pdu(s); + break; + + default: + unimpl("Pointer message 0x%x\n", message_type); + } +} + +/* Process bitmap updates */ +void +process_bitmap_updates(STREAM s) +{ + uint16 num_updates; + uint16 left, top, right, bottom, width, height; + uint16 cx, cy, bpp, Bpp, compress, bufsize, size; + uint8 *data, *bmpdata; + int i; + + in_uint16_le(s, num_updates); + + for (i = 0; i < num_updates; i++) + { + in_uint16_le(s, left); + in_uint16_le(s, top); + in_uint16_le(s, right); + in_uint16_le(s, bottom); + in_uint16_le(s, width); + in_uint16_le(s, height); + in_uint16_le(s, bpp); + Bpp = (bpp + 7) / 8; + in_uint16_le(s, compress); + in_uint16_le(s, bufsize); + + cx = right - left + 1; + cy = bottom - top + 1; + + DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n", + left, top, right, bottom, width, height, Bpp, compress)); + if (!compress) + { + size = width * height * Bpp; /* same as bufsize */ + } + else if (compress & 0x400) + { + size = bufsize; + } + else + { + in_uint8s(s, 2); /* pad */ + in_uint16_le(s, size); + in_uint8s(s, 4); + } + in_uint8p(s, data, size); + ui_paint_bitmap_ex(left, top, cx, cy, width, height, data, size, compress); +#if 0 + if (!compress) + { + int y; + bmpdata = (uint8 *) xmalloc(width * height * Bpp); + for (y = 0; y < height; y++) + { + in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)], + width * Bpp); + } + ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata); + xfree(bmpdata); + continue; + } + + + if (compress & 0x400) + { + size = bufsize; + } + else + { + in_uint8s(s, 2); /* pad */ + in_uint16_le(s, size); + in_uint8s(s, 4); /* line_size, final_size */ + } + in_uint8p(s, data, size); + bmpdata = (uint8 *) xmalloc(width * height * Bpp); + if (bitmap_decompress(bmpdata, width, height, data, size, Bpp)) + { + ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata); + } + else + { + DEBUG_RDP5(("Failed to decompress data\n")); + } + xfree(bmpdata); +#endif + } +} + +/* Process a palette update */ +void +process_palette(STREAM s) +{ + COLOURENTRY *entry; + COLOURMAP map; + RD_HCOLOURMAP hmap; + int i; + + in_uint8s(s, 2); /* pad */ + in_uint16_le(s, map.ncolours); + in_uint8s(s, 2); /* pad */ + + map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours); + + DEBUG(("PALETTE(c=%d)\n", map.ncolours)); + + for (i = 0; i < map.ncolours; i++) + { + entry = &map.colours[i]; + in_uint8(s, entry->red); + in_uint8(s, entry->green); + in_uint8(s, entry->blue); + } + + hmap = ui_create_colourmap(&map); + ui_set_colourmap(hmap); + + xfree(map.colours); +} + +/* Process an update PDU */ +static void +process_update_pdu(STREAM s) +{ + uint16 update_type, count; + + in_uint16_le(s, update_type); + + ui_begin_update(); + switch (update_type) + { + case RDP_UPDATE_ORDERS: + in_uint8s(s, 2); /* pad */ + in_uint16_le(s, count); + in_uint8s(s, 2); /* pad */ + process_orders(s, count); + break; + + case RDP_UPDATE_BITMAP: + process_bitmap_updates(s); + break; + + case RDP_UPDATE_PALETTE: + process_palette(s); + break; + + case RDP_UPDATE_SYNCHRONIZE: + break; + + default: + unimpl("update %d\n", update_type); + } + ui_end_update(); +} + +/* Process a disconnect PDU */ +void +process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason) +{ + in_uint32_le(s, *ext_disc_reason); + + DEBUG(("Received disconnect PDU\n")); +} + +/* Process data PDU */ +static BOOL +process_data_pdu(STREAM s, uint32 * ext_disc_reason) +{ + uint8 data_pdu_type; + uint8 ctype; + uint16 clen; + uint32 len; + + uint32 roff, rlen; + + struct stream *ns = &(g_mppc_dict.ns); + + in_uint8s(s, 6); /* shareid, pad, streamid */ + in_uint16(s, len); + in_uint8(s, data_pdu_type); + in_uint8(s, ctype); + in_uint16(s, clen); + clen -= 18; + + if (ctype & RDP_MPPC_COMPRESSED) + { + if (len > RDP_MPPC_DICT_SIZE) + error("error decompressed packet size exceeds max\n"); + if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1) + error("error while decompressing packet\n"); + + /* len -= 18; */ + + /* allocate memory and copy the uncompressed data into the temporary stream */ + ns->data = (uint8 *) xrealloc(ns->data, rlen); + + memcpy((ns->data), (unsigned char *) (g_mppc_dict.hist + roff), rlen); + + ns->size = rlen; + ns->end = (ns->data + ns->size); + ns->p = ns->data; + ns->rdp_hdr = ns->p; + + s = ns; + } + + switch (data_pdu_type) + { + case RDP_DATA_PDU_UPDATE: + process_update_pdu(s); + break; + + case RDP_DATA_PDU_CONTROL: + DEBUG(("Received Control PDU\n")); + break; + + case RDP_DATA_PDU_SYNCHRONISE: + DEBUG(("Received Sync PDU\n")); + break; + + case RDP_DATA_PDU_POINTER: + process_pointer_pdu(s); + break; + + case RDP_DATA_PDU_BELL: + ui_bell(); + break; + + case RDP_DATA_PDU_LOGON: + DEBUG(("Received Logon PDU\n")); + /* User logged on */ + break; + + case RDP_DATA_PDU_DISCONNECT: + process_disconnect_pdu(s, ext_disc_reason); + return True; + + default: + unimpl("data PDU %d\n", data_pdu_type); + } + return False; +} + +/* Process redirect PDU from Session Directory */ +static BOOL +process_redirect_pdu(STREAM s /*, uint32 * ext_disc_reason */ ) +{ + uint32 len; + + /* these 2 bytes are unknown, seem to be zeros */ + in_uint8s(s, 2); + + /* read connection flags */ + in_uint32_le(s, g_redirect_flags); + + /* read length of ip string */ + in_uint32_le(s, len); + + /* read ip string */ + rdp_in_unistr(s, g_redirect_server, len); + + /* read length of cookie string */ + in_uint32_le(s, len); + + /* read cookie string (plain ASCII) */ + in_uint8a(s, g_redirect_cookie, len); + g_redirect_cookie[len] = 0; + + /* read length of username string */ + in_uint32_le(s, len); + + /* read username string */ + rdp_in_unistr(s, g_redirect_username, len); + + /* read length of domain string */ + in_uint32_le(s, len); + + /* read domain string */ + rdp_in_unistr(s, g_redirect_domain, len); + + /* read length of password string */ + in_uint32_le(s, len); + + /* read password string */ + rdp_in_unistr(s, g_redirect_password, len); + + g_redirect = True; + + return True; +} + +/* Process incoming packets */ +/* nevers gets out of here till app is done */ +void +rdp_main_loop(BOOL * deactivated, uint32 * ext_disc_reason) +{ + while (rdp_loop(deactivated, ext_disc_reason)) + ; +} + +/* used in uiports and rdp_main_loop, processes the rdp packets waiting */ +BOOL +rdp_loop(BOOL * deactivated, uint32 * ext_disc_reason) +{ + uint8 type; + BOOL disc = False; /* True when a disconnect PDU was received */ + BOOL cont = True; + STREAM s; + + while (cont) + { + s = rdp_recv(&type); + if (s == NULL) + return False; + switch (type) + { + case RDP_PDU_DEMAND_ACTIVE: + process_demand_active(s); + *deactivated = False; + break; + case RDP_PDU_DEACTIVATE: + DEBUG(("RDP_PDU_DEACTIVATE\n")); + *deactivated = True; + break; + case RDP_PDU_REDIRECT: + return process_redirect_pdu(s); + break; + case RDP_PDU_DATA: + disc = process_data_pdu(s, ext_disc_reason); + break; + case 0: + break; + default: + unimpl("PDU %d\n", type); + } + if (disc) + return False; + cont = g_next_packet < s->end; + } + return True; +} + +/* Establish a connection up to the RDP layer */ +BOOL +rdp_connect(char *server, uint32 flags, char *domain, char *password, + char *command, char *directory) +{ + if (!sec_connect(server, g_username)) + return False; + + rdp_send_logon_info(flags, domain, g_username, password, command, directory); + return True; +} + +/* Establish a reconnection up to the RDP layer */ +BOOL +rdp_reconnect(char *server, uint32 flags, char *domain, char *password, + char *command, char *directory, char *cookie) +{ + if (!sec_reconnect(server)) + return False; + + rdp_send_logon_info(flags, domain, g_username, password, command, directory); + return True; +} + +/* Called during redirection to reset the state to support redirection */ +void +rdp_reset_state(void) +{ + g_next_packet = NULL; /* reset the packet information */ + g_rdp_shareid = 0; + sec_reset_state(); +} + +/* Disconnect from the RDP layer */ +void +rdp_disconnect(void) +{ + sec_disconnect(); +} diff --git a/uirdesktop/secure.c b/uirdesktop/secure.c index 90b8eedb..5dba480e 100644 --- a/uirdesktop/secure.c +++ b/uirdesktop/secure.c @@ -24,44 +24,44 @@ //#include <openssl/md5.h> //#include <openssl/sha.h> //#include <openssl/bn.h> -//#include <openssl/x509v3.h>
-
-void *
-ssl_sha1_info_create(void);
-void
-ssl_sha1_info_delete(void * sha1_info);
-void
-ssl_sha1_clear(void * sha1_info);
-void
-ssl_sha1_transform(void * sha1_info, char * data, int len);
-void
-ssl_sha1_complete(void * sha1_info, char * data);
-void *
-ssl_md5_info_create(void);
-void
-ssl_md5_info_delete(void * md5_info);
-void *
-ssl_md5_info_create(void);
-void
-ssl_md5_info_delete(void * md5_info);
-void
-ssl_md5_clear(void * md5_info);
-void
-ssl_md5_transform(void * md5_info, char * data, int len);
-void
-ssl_md5_complete(void * md5_info, char * data);
-void *
-ssl_rc4_info_create(void);
-void
-ssl_rc4_info_delete(void * rc4_info);
-void
-ssl_rc4_set_key(void * rc4_info, char * key, int len);
-void
-ssl_rc4_crypt(void * rc4_info, char * in_data, char * out_data, int len);
-int
-ssl_mod_exp(char* out, int out_len, char* in, int in_len,
- char* mod, int mod_len, char* exp, int exp_len);
-
+//#include <openssl/x509v3.h> + +void * +ssl_sha1_info_create(void); +void +ssl_sha1_info_delete(void * sha1_info); +void +ssl_sha1_clear(void * sha1_info); +void +ssl_sha1_transform(void * sha1_info, char * data, int len); +void +ssl_sha1_complete(void * sha1_info, char * data); +void * +ssl_md5_info_create(void); +void +ssl_md5_info_delete(void * md5_info); +void * +ssl_md5_info_create(void); +void +ssl_md5_info_delete(void * md5_info); +void +ssl_md5_clear(void * md5_info); +void +ssl_md5_transform(void * md5_info, char * data, int len); +void +ssl_md5_complete(void * md5_info, char * data); +void * +ssl_rc4_info_create(void); +void +ssl_rc4_info_delete(void * rc4_info); +void +ssl_rc4_set_key(void * rc4_info, char * key, int len); +void +ssl_rc4_crypt(void * rc4_info, char * in_data, char * out_data, int len); +int +ssl_mod_exp(char* out, int out_len, char* in, int in_len, + char* mod, int mod_len, char* exp, int exp_len); + extern char g_hostname[16]; extern int g_width; extern int g_height; @@ -82,7 +82,7 @@ static int rc4_key_len; static void * rc4_decrypt_key = 0; static void * rc4_encrypt_key = 0; //static RSA *server_public_key; -static void * server_public_key;
+static void * server_public_key; static uint8 sec_sign_key[16]; static uint8 sec_decrypt_key[16]; @@ -123,19 +123,19 @@ sec_hash_48(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2, uint8 salt) for (i = 0; i < 3; i++) { memset(pad, salt + i, i + 1); - sha = ssl_sha1_info_create();
- ssl_sha1_clear(sha);
- ssl_sha1_transform(sha, pad, i + 1);
- ssl_sha1_transform(sha, in, 48);
- ssl_sha1_transform(sha, salt1, 32);
- ssl_sha1_transform(sha, salt2, 32);
- ssl_sha1_complete(sha, shasig);
- ssl_sha1_info_delete(sha);
- md5 = ssl_md5_info_create();
- ssl_md5_clear(md5);
- ssl_md5_transform(md5, in, 48);
- ssl_md5_transform(md5, shasig, 20);
- ssl_md5_complete(md5, out + i * 16);
+ sha = ssl_sha1_info_create(); + ssl_sha1_clear(sha); + ssl_sha1_transform(sha, pad, i + 1); + ssl_sha1_transform(sha, in, 48); + ssl_sha1_transform(sha, salt1, 32); + ssl_sha1_transform(sha, salt2, 32); + ssl_sha1_complete(sha, shasig); + ssl_sha1_info_delete(sha); + md5 = ssl_md5_info_create(); + ssl_md5_clear(md5); + ssl_md5_transform(md5, in, 48); + ssl_md5_transform(md5, shasig, 20); + ssl_md5_complete(md5, out + i * 16); ssl_md5_info_delete(md5); } } @@ -147,13 +147,13 @@ void sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2) { void * md5; -
- md5 = ssl_md5_info_create();
- ssl_md5_clear(md5);
+ + md5 = ssl_md5_info_create(); + ssl_md5_clear(md5); ssl_md5_transform(md5, in, 16); ssl_md5_transform(md5, salt1, 32); - ssl_md5_transform(md5, salt2, 32);
- ssl_md5_complete(md5, out);
+ ssl_md5_transform(md5, salt2, 32); + ssl_md5_complete(md5, out); ssl_md5_info_delete(md5); } @@ -207,15 +207,15 @@ sec_generate_keys(uint8 * client_random, uint8 * server_random, int rc4_key_size memcpy(sec_decrypt_update_key, sec_decrypt_key, 16); memcpy(sec_encrypt_update_key, sec_encrypt_key, 16); - /* Initialise RC4 state arrays */
-
- ssl_rc4_info_delete(rc4_decrypt_key);
- rc4_decrypt_key = ssl_rc4_info_create();
- ssl_rc4_set_key(rc4_decrypt_key, sec_decrypt_key, rc4_key_len);
+ /* Initialise RC4 state arrays */ + + ssl_rc4_info_delete(rc4_decrypt_key); + rc4_decrypt_key = ssl_rc4_info_create(); + ssl_rc4_set_key(rc4_decrypt_key, sec_decrypt_key, rc4_key_len); - ssl_rc4_info_delete(rc4_encrypt_key);
- rc4_encrypt_key = ssl_rc4_info_create();
- ssl_rc4_set_key(rc4_encrypt_key, sec_encrypt_key, rc4_key_len);
+ ssl_rc4_info_delete(rc4_encrypt_key); + rc4_encrypt_key = ssl_rc4_info_create(); + ssl_rc4_set_key(rc4_encrypt_key, sec_encrypt_key, rc4_key_len); } static uint8 pad_54[40] = { @@ -254,23 +254,23 @@ sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * buf_out_uint32(lenhdr, datalen); - sha = ssl_sha1_info_create();
- ssl_sha1_clear(sha);
- ssl_sha1_transform(sha, session_key, keylen);
- ssl_sha1_transform(sha, pad_54, 40);
- ssl_sha1_transform(sha, lenhdr, 4);
- ssl_sha1_transform(sha, data, datalen);
- ssl_sha1_complete(sha, shasig);
- ssl_sha1_info_delete(sha);
-
- md5 = ssl_md5_info_create();
- ssl_md5_clear(md5);
- ssl_md5_transform(md5, session_key, keylen);
- ssl_md5_transform(md5, pad_92, 48);
- ssl_md5_transform(md5, shasig, 20);
- ssl_md5_complete(md5, md5sig);
- ssl_md5_info_delete(md5);
-
+ sha = ssl_sha1_info_create(); + ssl_sha1_clear(sha); + ssl_sha1_transform(sha, session_key, keylen); + ssl_sha1_transform(sha, pad_54, 40); + ssl_sha1_transform(sha, lenhdr, 4); + ssl_sha1_transform(sha, data, datalen); + ssl_sha1_complete(sha, shasig); + ssl_sha1_info_delete(sha); + + md5 = ssl_md5_info_create(); + ssl_md5_clear(md5); + ssl_md5_transform(md5, session_key, keylen); + ssl_md5_transform(md5, pad_92, 48); + ssl_md5_transform(md5, shasig, 20); + ssl_md5_complete(md5, md5sig); + ssl_md5_info_delete(md5); + memcpy(signature, md5sig, siglen); } @@ -282,29 +282,29 @@ sec_update(uint8 * key, uint8 * update_key) void * sha; void * md5; void * update; -
- sha = ssl_sha1_info_create();
- ssl_sha1_clear(sha);
- ssl_sha1_transform(sha, update_key, rc4_key_len);
- ssl_sha1_transform(sha, pad_54, 40);
- ssl_sha1_transform(sha, key, rc4_key_len);
- ssl_sha1_complete(sha, shasig);
- ssl_sha1_info_delete(sha);
- - md5 = ssl_md5_info_create();
- ssl_md5_clear(md5);
- ssl_md5_transform(md5, update_key, rc4_key_len);
- ssl_md5_transform(md5, pad_92, 48);
- ssl_md5_transform(md5, shasig, 20);
- ssl_md5_complete(md5, key);
- ssl_md5_info_delete(md5);
- -
- update = ssl_rc4_info_create();
- ssl_rc4_set_key(update, key, rc4_key_len);
- ssl_rc4_crypt(update, key, key, rc4_key_len);
- ssl_rc4_info_delete(update);
-
+ + sha = ssl_sha1_info_create(); + ssl_sha1_clear(sha); + ssl_sha1_transform(sha, update_key, rc4_key_len); + ssl_sha1_transform(sha, pad_54, 40); + ssl_sha1_transform(sha, key, rc4_key_len); + ssl_sha1_complete(sha, shasig); + ssl_sha1_info_delete(sha); + + md5 = ssl_md5_info_create(); + ssl_md5_clear(md5); + ssl_md5_transform(md5, update_key, rc4_key_len); + ssl_md5_transform(md5, pad_92, 48); + ssl_md5_transform(md5, shasig, 20); + ssl_md5_complete(md5, key); + ssl_md5_info_delete(md5); + + + update = ssl_rc4_info_create(); + ssl_rc4_set_key(update, key, rc4_key_len); + ssl_rc4_crypt(update, key, key, rc4_key_len); + ssl_rc4_info_delete(update); + if (rc4_key_len == 8) sec_make_40bit(key); } @@ -315,7 +315,7 @@ sec_encrypt(uint8 * data, int length) { if (sec_encrypt_use_count == 4096) { - sec_update(sec_encrypt_key, sec_encrypt_update_key);
+ sec_update(sec_encrypt_key, sec_encrypt_update_key); ssl_rc4_set_key(rc4_encrypt_key, sec_encrypt_key, rc4_key_len); sec_encrypt_use_count = 0; } @@ -330,10 +330,10 @@ sec_decrypt(uint8 * data, int length) if (sec_decrypt_use_count == 4096) { sec_update(sec_decrypt_key, sec_decrypt_update_key); - ssl_rc4_set_key(rc4_decrypt_key, sec_decrypt_key, rc4_key_len);
+ ssl_rc4_set_key(rc4_decrypt_key, sec_decrypt_key, rc4_key_len); sec_decrypt_use_count = 0; } - ssl_rc4_crypt(rc4_decrypt_key, data, data, length);
+ ssl_rc4_crypt(rc4_decrypt_key, data, data, length); sec_decrypt_use_count++; } @@ -354,8 +354,8 @@ reverse(uint8 * p, int len) /* Perform an RSA public key encryption operation */ static void sec_rsa_encrypt(uint8 * out, uint8 * in, int len, uint8 * modulus, uint8 * exponent) -{
- ssl_mod_exp(out, 64, in, 32, modulus, 64, exponent, 4);
+{ + ssl_mod_exp(out, 64, in, 32, modulus, 64, exponent, 4); /* BN_CTX *ctx; BIGNUM mod, exp, x, y; @@ -578,7 +578,7 @@ sec_parse_public_key(STREAM s, uint8 ** modulus, uint8 ** exponent) return s_check(s); } -
+ /* Parse a crypto information structure */ static BOOL sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size, @@ -647,7 +647,7 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size, } } else - {
+ { #if 0 uint32 certcount; @@ -737,7 +737,7 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size, } X509_free(server_cert); return True; /* There's some garbage here we don't care about */ -#endif
+#endif } return s_check_end(s); } @@ -783,7 +783,7 @@ sec_process_crypt_info(STREAM s) reverse(sec_crypted_random, SEC_MODULUS_SIZE); RSA_free(server_public_key); - server_public_key = NULL;
+ server_public_key = NULL; #endif } else diff --git a/uirdesktop/ssl_calls.c b/uirdesktop/ssl_calls.c index da05b135..37642185 100755 --- a/uirdesktop/ssl_calls.c +++ b/uirdesktop/ssl_calls.c @@ -18,30 +18,30 @@ ssl calls -*/
-
+*/ + #include "rdesktop.h" -
-#define APP_CC
-
-/*****************************************************************************/
-static void * g_malloc(int size, int zero)
-{
- void * p;
-
- p = xmalloc(size);
- if (zero)
- {
- memset(p, 0, size);
- }
- return p;
-}
-
-/*****************************************************************************/
-static void g_free(void * in)
-{
- xfree(in);
-}
+ +#define APP_CC + +/*****************************************************************************/ +static void * g_malloc(int size, int zero) +{ + void * p; + + p = xmalloc(size); + if (zero) + { + memset(p, 0, size); + } + return p; +} + +/*****************************************************************************/ +static void g_free(void * in) +{ + xfree(in); +} /*****************************************************************************/ /*****************************************************************************/ diff --git a/uirdesktop/tcp.c b/uirdesktop/tcp.c index 35097263..597bacd1 100644 --- a/uirdesktop/tcp.c +++ b/uirdesktop/tcp.c @@ -28,22 +28,22 @@ #include <arpa/inet.h> /* inet_addr */ #include <errno.h> /* errno */ #endif /* _WIN32 */ -
-#include "rdesktop.h"
- -#ifdef _WIN32
-#define socklen_t int
-#define TCP_CLOSE(_sck) closesocket(_sck)
-#define TCP_STRERROR "tcp error"
-#define TCP_SLEEP(_n) Sleep(_n)
-#define TCP_BLOCKS (WSAGetLastError() == WSAEWOULDBLOCK)
-#else /* _WIN32 */
-#define TCP_CLOSE(_sck) close(_sck)
-#define TCP_STRERROR strerror(errno)
-#define TCP_SLEEP(_n) sleep(_n)
-#define TCP_BLOCKS (errno == EWOULDBLOCK)
-#endif /* _WIN32 */
-
+ +#include "rdesktop.h" + +#ifdef _WIN32 +#define socklen_t int +#define TCP_CLOSE(_sck) closesocket(_sck) +#define TCP_STRERROR "tcp error" +#define TCP_SLEEP(_n) Sleep(_n) +#define TCP_BLOCKS (WSAGetLastError() == WSAEWOULDBLOCK) +#else /* _WIN32 */ +#define TCP_CLOSE(_sck) close(_sck) +#define TCP_STRERROR strerror(errno) +#define TCP_SLEEP(_n) sleep(_n) +#define TCP_BLOCKS (errno == EWOULDBLOCK) +#endif /* _WIN32 */ + #ifndef INADDR_NONE #define INADDR_NONE ((unsigned long) -1) #endif diff --git a/uirdesktop/types.h b/uirdesktop/types.h index 2dc230dc..f8b62821 100644 --- a/uirdesktop/types.h +++ b/uirdesktop/types.h @@ -251,7 +251,7 @@ NOTIFY; #ifndef PATH_MAX #define PATH_MAX 256 #endif -
+ #ifndef _WIN32 typedef struct fileinfo { @@ -264,7 +264,7 @@ typedef struct fileinfo NOTIFY notify; uint32 info_class; } -FILEINFO;
+FILEINFO; #endif typedef BOOL(*str_handle_lines_t) (const char *line, void *data); diff --git a/uirdesktop/uimain.c b/uirdesktop/uimain.c index 9f9bcac7..70da51d7 100755 --- a/uirdesktop/uimain.c +++ b/uirdesktop/uimain.c @@ -1,1124 +1,1128 @@ -/* -*- c-basic-offset: 8 -*-
- rdesktop: A Remote Desktop Protocol client.
- Main ui file
- Copyright (C) Jay Sorg 2006
-
- 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"
-#include "bsops.h"
-#include "uimain.h"
-
-char g_username[256] = "";
-char g_hostname[256] = "";
-char g_servername[256] = "";
-char g_password[256] = "";
-char g_shell[256] = "";
-char g_directory[256] = "";
-char g_domain[256] = "";
-char * g_bs = 0; /* created in hardware file, used in bsops.c */
-int g_bs_Bpp = 4;
-int g_bs_bpp = 32;
-BOOL g_desktop_save = False; /* desktop save order */
-BOOL g_polygon_ellipse_orders = False; /* polygon / ellipse orders */
-BOOL g_bitmap_compression = True;
-uint32 g_rdp5_performanceflags =
- RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS;
-BOOL g_bitmap_cache_persist_enable = False;
-BOOL g_bitmap_cache_precache = True;
-BOOL g_bitmap_cache = True;
-BOOL g_encryption = True;
-int g_server_depth = 8;
-BOOL g_use_rdp5 = False;
-int g_width = 800;
-int g_height = 600;
-uint32 g_keylayout = 0x409; /* Defaults to US keyboard layout */
-int g_keyboard_type = 0x4; /* Defaults to US keyboard layout */
-int g_keyboard_subtype = 0x0; /* Defaults to US keyboard layout */
-int g_keyboard_functionkeys = 0xc; /* Defaults to US keyboard layout */
-BOOL g_console_session = False;
-
-/* can't be static, hardware file or bsops need these */
-int g_tcp_sck = 0;
-int pal_entries[256];
-
-/* Session Directory redirection */
-BOOL g_redirect = False;
-char g_redirect_server[64];
-char g_redirect_domain[16];
-char g_redirect_password[64];
-char g_redirect_username[64];
-char g_redirect_cookie[128];
-uint32 g_redirect_flags = 0;
-
-extern int g_tcp_port_rdp;
-
-static int g_deactivated = 0;
-static uint32 g_ext_disc_reason = 0;
-
-struct bitmap
-{
- uint8 * data;
- uint32 width;
- uint32 height;
-};
-
-/* in ui specific file eg win32.c, qt.c, dfb.c, ... */
-int
-mi_create_window(void);
-void
-mi_invalidate(int x, int y, int cx, int cy);
-int
-mi_create_bs(void);
-int
-mi_main_loop(void);
-void
-mi_error(char * msg);
-void
-mi_warning(char * msg);
-void
-ui_invalidate(int x, int y, int cx, int cy);
-void
-mi_paint_rect(char * data, int width, int height, int x, int y, int cx, int cy);
-void
-mi_begin_update(void);
-void
-mi_end_update(void);
-void
-mi_fill_rect(int x, int y, int cx, int cy, int colour);
-void
-mi_screen_copy(int x, int y, int cx, int cy, int srcx, int srcy);
-void
-mi_set_clip(int x, int y, int cx, int cy);
-void
-mi_reset_clip(void);
-void
-mi_line(int x1, int y1, int x2, int y2, int colour);
-mi_create_cursor(unsigned int x, unsigned int y,
- int width, int height,
- unsigned char * andmask, unsigned char * xormask);
-void
-mi_destroy_cursor(void * cursor);
-void
-mi_set_cursor(void * cursor);
-void
-mi_set_null_cursor(void);
-int
-mi_read_keyboard_state(void);
-
-/*****************************************************************************/
-/* put part of the screen from the backing store to the display */
-void
-ui_invalidate(int x, int y, int cx, int cy)
-{
- if (cx < 1 || cy < 1 || g_bs == 0)
- {
- return;
- }
- if (bs_warp_coords(&x, &y, &cx, &cy, 0, 0))
- {
- mi_invalidate(x, y, cx, cy);
- }
-/*
- if (bs_warp_coords(&x, &y, &cx, &cy, 0, 0))
- {
- cx = (cx + 3) & ~3;
- data = (char *) xmalloc(cx * cy * 4);
- bs_copy_box(data, x, y, cx, cy, cx * ((g_server_depth + 7) / 8));
- mi_paint_rect(data, cx, cy, x, y, cx, cy);
- xfree(data);
- }
-*/
-}
-
-/*****************************************************************************/
-static int
-convert_colour(int in_colour)
-{
- int r;
- int g;
- int b;
-
- if (g_server_depth == 8)
- {
- r = (pal_entries[in_colour & 0xff] & 0xff0000) >> 16;
- g = (pal_entries[in_colour & 0xff] & 0xff00) >> 8;
- b = pal_entries[in_colour & 0xff] & 0xff;
- }
- else if (g_server_depth == 15)
- {
- SPLIT_COLOUR15(in_colour, r, g, b);
- }
- else if (g_server_depth == 16)
- {
- SPLIT_COLOUR16(in_colour, r, g, b);
- }
- else if (g_server_depth == 24)
- {
- SPLIT_COLOUR32(in_colour, r, g, b);
- }
- if (g_bs_bpp == 32)
- {
- MAKE_COLOUR32(in_colour, r, g, b);
- }
- return in_colour;
-}
-
-/*****************************************************************************/
-void
-ui_bell(void)
-{
-}
-
-/*****************************************************************************/
-int
-ui_select(int in)
-{
- if (g_tcp_sck == 0)
- {
- g_tcp_sck = in;
- }
- return 1;
-}
-
-/*****************************************************************************/
-void *
-ui_create_cursor(uint32 x, uint32 y,
- int width, int height,
- uint8 * andmask, uint8 * xormask)
-{
- int i;
- int j;
- char am[32 * 4];
- char xm[32 * 4];
-
- if (width != 32 || height != 32)
- {
- return 0;
- }
- memset(am, 0, 32 * 4);
- memset(xm, 0, 32 * 4);
- for (i = 0; i < 32; i++)
- {
- for (j = 0; j < 32; j++)
- {
- if (bs_is_pixel_on(andmask, j, i, 32, 1))
- {
- bs_set_pixel_on(am, j, 31 - i, 32, 1, 1);
- }
- if (bs_is_pixel_on(xormask, j, i, 32, 24))
- {
- bs_set_pixel_on(xm, j, 31 - i, 32, 1, 1);
- }
- }
- }
- return (void *) mi_create_cursor(x, y, width, height, am, xm);
-}
-
-/*****************************************************************************/
-void
-ui_destroy_cursor(void * cursor)
-{
- mi_destroy_cursor(cursor);
-}
-
-/*****************************************************************************/
-void
-ui_set_cursor(void * cursor)
-{
- mi_set_cursor(cursor);
-}
-
-/*****************************************************************************/
-void
-ui_set_null_cursor(void)
-{
- mi_set_null_cursor();
-}
-
-/*****************************************************************************/
-void *
-ui_create_glyph(int width, int height, uint8 * data)
-{
- int i;
- int j;
- char * glyph_data;
- struct bitmap * the_glyph;
-
- glyph_data = (char *) xmalloc(width * height);
- memset(glyph_data, 0, width * height);
- the_glyph = (struct bitmap *) xmalloc(sizeof(struct bitmap));
- memset(the_glyph, 0, sizeof(struct bitmap));
- the_glyph->width = width;
- the_glyph->height = height;
- the_glyph->data = glyph_data;
- for (i = 0; i < height; i++)
- {
- for (j = 0; j < width; j++)
- {
- if (bs_is_pixel_on(data, j, i, width, 1))
- {
- bs_set_pixel_on(glyph_data, j, i, width, 8, 255);
- }
- }
- }
- return the_glyph;
-}
-
-/*****************************************************************************/
-void
-ui_destroy_glyph(void * glyph)
-{
- struct bitmap * the_glyph;
-
- the_glyph = glyph;
- if (the_glyph != 0)
- {
- xfree(the_glyph->data);
- }
- xfree(the_glyph);
-}
-
-/*****************************************************************************/
-void *
-ui_create_bitmap(int width, int height, uint8 * data)
-{
-#if 0
- struct bitmap * b;
- int size;
-
- size = width * height * ((g_server_depth + 7) / 8);
- b = (struct bitmap *) xmalloc(sizeof(struct bitmap));
- b->data = (uint8 *) xmalloc(size);
- memcpy(b->data, data, size);
- b->width = width;
- b->height = height;
- return b;
-#endif
- return 0;
-}
-
-/*****************************************************************************/
-void *
-ui_create_bitmap_ex(int width, int height, uint8 * data, int data_size,
- int compressed)
-{
- struct bitmap * b;
- int size;
- int i;
- int j;
- int pixel;
- int red;
- int green;
- int blue;
- unsigned short * s16;
- unsigned char * s8;
- unsigned int * d32;
-
- size = width * height * 4;
- b = (struct bitmap *) xmalloc(sizeof(struct bitmap));
- b->data = (uint8 *) xmalloc(size);
- if (compressed)
- {
- bitmap_decompress_ex(b->data, width, height, data, data_size,
- g_server_depth, 32);
- }
- else
- {
- if (g_server_depth == 16 && g_bs_bpp == 32)
- {
- for (i = 0; i < height; i++)
- {
- s16 = ((unsigned short *) data) + (i * width);
- d32 = ((unsigned int *) b->data) + (height - i - 1) * width;
- for (j = 0; j < width; j++)
- {
- pixel = *s16;
- s16++;
- SPLIT_COLOUR16(pixel, red, green, blue);
- MAKE_COLOUR32(pixel, red, green, blue);
- *d32 = pixel;
- d32++;
- }
- }
- }
- else if (g_server_depth == 24 && g_bs_bpp == 32)
- {
- for (i = 0; i < height; i++)
- {
- s8 = ((unsigned char *) data) + (i * width * 3);
- d32 = ((unsigned int *) b->data) + (height - i - 1) * width;
- for (j = 0; j < width; j++)
- {
- blue = *s8;
- s8++;
- green = *s8;
- s8++;
- red = *s8;
- s8++;
- MAKE_COLOUR32(pixel, red, green, blue);
- *d32 = pixel;
- d32++;
- }
- }
- }
- }
- b->width = width;
- b->height = height;
- return b;
-}
-
-/*****************************************************************************/
-void
-ui_destroy_bitmap(void * bmp)
-{
- struct bitmap * b;
-
- b = (struct bitmap *) bmp;
- if (b != 0)
- {
- xfree(b->data);
- }
- xfree(b);
-}
-
-/*****************************************************************************/
-void
-ui_paint_bitmap(int x, int y, int cx, int cy,
- int width, int height, uint8 * data)
-{
-/* struct bitmap b;
-
- b.width = width;
- b.height = height;
- b.data = data;
- ui_memblt(12, x, y, cx, cy, &b, 0, 0); */
-}
-
-/*****************************************************************************/
-void
-ui_paint_bitmap_ex(int x, int y, int cx, int cy,
- int width, int height, uint8 * data, int data_size,
- int compressed)
-{
- struct bitmap * b;
-
- b = ui_create_bitmap_ex(width, height, data, data_size, compressed);
- ui_memblt(12, x, y, cx, cy, b, 0, 0);
- ui_destroy_bitmap(b);
-}
-
-/*****************************************************************************/
-void
-ui_set_clip(int x, int y, int cx, int cy)
-{
- bs_set_clip(x, y, cx, cy);
- mi_set_clip(x, y, cx, cy);
-}
-
-/*****************************************************************************/
-void
-ui_reset_clip(void)
-{
- bs_reset_clip();
- mi_reset_clip();
-}
-
-/*****************************************************************************/
-void *
-ui_create_colourmap(COLOURMAP * colours)
-{
- int i;
- int n;
-
- n = MIN(256, colours->ncolours);
- memset(pal_entries, 0, sizeof(pal_entries));
- for (i = 0; i < n; i++)
- {
- pal_entries[i] = (colours->colours[i].red << 16) |
- (colours->colours[i].green << 8) |
- colours->colours[i].blue;
- }
- return 0;
-}
-
-/*****************************************************************************/
-void
-ui_set_colourmap(void * map)
-{
-}
-
-/*****************************************************************************/
-/* don't convert colour here */
-static void
-draw_glyph(int x, int y, void * glyph, int fgcolor)
-{
- struct bitmap * b;
-
- b = glyph;
- bs_draw_glyph(x, y, b->data, b->width, b->height, fgcolor);
-}
-
-/*****************************************************************************/
-#define DO_GLYPH(ttext,idx) \
-{ \
- glyph = cache_get_font(font, ttext[idx]); \
- if (!(flags & TEXT2_IMPLICIT_X)) \
- { \
- xyoffset = ttext[++idx]; \
- if (xyoffset & 0x80) \
- { \
- if (flags & TEXT2_VERTICAL) \
- { \
- y += ttext[idx + 1] | (ttext[idx + 2] << 8); \
- } \
- else \
- { \
- x += ttext[idx + 1] | (ttext[idx + 2] << 8); \
- } \
- idx += 2; \
- } \
- else \
- { \
- if (flags & TEXT2_VERTICAL) \
- { \
- y += xyoffset; \
- } \
- else \
- { \
- x += xyoffset; \
- } \
- } \
- } \
- if (glyph != NULL) \
- { \
- draw_glyph(x + glyph->offset, y + glyph->baseline, glyph->pixmap, \
- fgcolour); \
- if (flags & TEXT2_IMPLICIT_X) \
- { \
- x += glyph->width; \
- } \
- } \
-}
-
-/*****************************************************************************/
-void
-ui_draw_text(uint8 font, uint8 flags, uint8 opcode, int mixmode,
- int x, int y,
- int clipx, int clipy, int clipcx, int clipcy,
- int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush,
- int bgcolour, int fgcolour, uint8 * text, uint8 length)
-{
- int i;
- int j;
- int xyoffset;
- DATABLOB * entry;
- FONTGLYPH * glyph;
-
- fgcolour = convert_colour(fgcolour);
- bgcolour = convert_colour(bgcolour);
- if (boxx + boxcx > g_width)
- {
- boxcx = g_width - boxx;
- }
- if (boxcx > 1)
- {
- bs_rect(boxx, boxy, boxcx, boxcy, bgcolour, 0xc);
- }
- else
- {
- if (mixmode == MIX_OPAQUE)
- {
- bs_rect(clipx, clipy, clipcx, clipcy, bgcolour, 0xc);
- }
- }
- /* Paint text, character by character */
- for (i = 0; i < length;)
- {
- switch (text[i])
- {
- case 0xff:
- if (i + 2 < length)
- {
- cache_put_text(text[i + 1], text, text[i + 2]);
- }
- else
- {
- error("this shouldn't be happening\n");
- exit(1);
- }
- /* this will move pointer from start to first character after */
- /* FF command */
- length -= i + 3;
- text = &(text[i + 3]);
- i = 0;
- break;
- case 0xfe:
- entry = cache_get_text(text[i + 1]);
- if (entry != NULL)
- {
- if ((((uint8 *) (entry->data))[1] == 0) &&
- (!(flags & TEXT2_IMPLICIT_X)))
- {
- if (flags & TEXT2_VERTICAL)
- {
- y += text[i + 2];
- }
- else
- {
- x += text[i + 2];
- }
- }
- for (j = 0; j < entry->size; j++)
- {
- DO_GLYPH(((uint8 *) (entry->data)), j);
- }
- }
- if (i + 2 < length)
- {
- i += 3;
- }
- else
- {
- i += 2;
- }
- length -= i;
- /* this will move pointer from start to first character after */
- /* FE command */
- text = &(text[i]);
- i = 0;
- break;
- default:
- DO_GLYPH(text, i);
- i++;
- break;
- }
- }
- if (boxcx > 1)
- {
- ui_invalidate(boxx, boxy, boxcx, boxcy);
- }
- else
- {
- ui_invalidate(clipx, clipy, clipcx, clipcy);
- }
-}
-
-/*****************************************************************************/
-void
-ui_line(uint8 opcode, int startx, int starty, int endx, int endy,
- PEN * pen)
-{
- int x;
- int y;
- int cx;
- int cy;
- int colour;
-
- colour = convert_colour(pen->colour);
-
- bs_line(opcode, startx, starty, endx, endy, pen->width, pen->style,
- colour);
- if (pen->style == 0 && pen->width < 2 && opcode == 12)
- {
- mi_line(startx, starty, endx, endy, colour);
- }
- else
- {
- x = MIN(startx, endx);
- y = MIN(starty, endy);
- cx = (MAX(startx, endx) + 1) - x;
- cy = (MAX(starty, endy) + 1) - y;
- ui_invalidate(x, y, cx, cy);
- }
-}
-
-/*****************************************************************************/
-void
-ui_triblt(uint8 opcode, int x, int y, int cx, int cy,
- void * src, int srcx, int srcy,
- BRUSH* brush, int bgcolour, int fgcolour)
-{
- /* not used */
-}
-
-/*****************************************************************************/
-void
-ui_memblt(uint8 opcode, int x, int y, int cx, int cy,
- void * src, int srcx, int srcy)
-{
- struct bitmap* b;
-
- b = (struct bitmap *) src;
- bs_memblt(opcode, x, y, cx, cy, b->data, b->width, b->height,
- srcx, srcy);
- ui_invalidate(x, y, cx, cy);
-}
-
-/*****************************************************************************/
-void
-ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
-{
-}
-
-/*****************************************************************************/
-void
-ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
-{
-}
-
-/*****************************************************************************/
-void
-ui_rect(int x, int y, int cx, int cy, int colour)
-{
- colour = convert_colour(colour);
- bs_rect(x, y, cx, cy, colour, 12);
- mi_fill_rect(x, y, cx, cy, colour);
-}
-
-/*****************************************************************************/
-void
-ui_screenblt(uint8 opcode, int x, int y, int cx, int cy,
- int srcx, int srcy)
-{
- bs_screenblt(opcode, x, y, cx, cy, srcx, srcy);
- if (opcode == 12)
- {
- mi_screen_copy(x, y, cx, cy, srcx, srcy);
- }
- else
- {
- ui_invalidate(x, y, cx, cy);
- }
-}
-
-/*****************************************************************************/
-void
-ui_patblt(uint8 opcode, int x, int y, int cx, int cy,
- BRUSH * brush, int bgcolour, int fgcolour)
-{
- bgcolour = convert_colour(bgcolour);
- fgcolour = convert_colour(fgcolour);
- bs_patblt(opcode, x, y, cx, cy, brush->style, brush->pattern,
- brush->xorigin, brush->yorigin, bgcolour, fgcolour);
- ui_invalidate(x, y, cx, cy);
-}
-
-/*****************************************************************************/
-void
-ui_destblt(uint8 opcode, int x, int y, int cx, int cy)
-{
- bs_rect(x, y, cx, cy, 0, opcode);
- ui_invalidate(x, y, cx, cy);
- /* todo */
-}
-
-/*****************************************************************************/
-void
-ui_move_pointer(int x, int y)
-{
-}
-
-/*****************************************************************************/
-uint16
-ui_get_numlock_state(uint32 state)
-{
- return (uint16) state;
-}
-
-/*****************************************************************************/
-/* get the num, caps, and scroll lock state */
-/* scroll lock is 1, num lock is 2 and caps lock is 4 */
-/* just returning 0, the hardware specific file is responsable for this */
-uint32
-read_keyboard_state(void)
-{
- return (uint32) mi_read_keyboard_state();
-}
-
-/*****************************************************************************/
-void
-ui_set_modifier_state(int code)
-
{
-
//error("%8.8x", code);
-
rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, (uint16) code, 0);
-
}
-
-/*****************************************************************************/
-void
-ui_resize_window(void)
-{
-}
-
-/*****************************************************************************/
-void
-ui_begin_update(void)
-{
- mi_begin_update();
-}
-
-/*****************************************************************************/
-void
-ui_end_update(void)
-{
- mi_end_update();
-}
-
-/*****************************************************************************/
-void
-ui_polygon(uint8 opcode, uint8 fillmode, POINT * point, int npoints,
- BRUSH * brush, int bgcolour, int fgcolour)
-{
- /* not used */
-}
-
-/*****************************************************************************/
-void
-ui_polyline(uint8 opcode, POINT * points, int npoints, PEN * pen)
-{
- int i, x, y, dx, dy;
- if (npoints > 0)
- {
- x = points[0].x;
- y = points[0].y;
- for (i = 1; i < npoints; i++)
- {
- dx = points[i].x;
- dy = points[i].y;
- ui_line(opcode, x, y, x + dx, y + dy, pen);
- x = x + dx;
- y = y + dy;
- }
- }
-}
-
-/*****************************************************************************/
-void
-ui_ellipse(uint8 opcode, uint8 fillmode,
- int x, int y, int cx, int cy,
- BRUSH * brush, int bgcolour, int fgcolour)
-{
- /* not used */
-}
-
-/*****************************************************************************/
-/* get a 32 byte random */
-void
-generate_random(uint8 * random)
-{
- int i;
-
- rand();
- rand();
- for (i = 0; i < 32; i++)
- {
- random[i] = rand() >> 16; /* higher bits are more random */
- }
-}
-
-/*****************************************************************************/
-void
-save_licence(uint8 * data, int length)
-{
-}
-
-/*****************************************************************************/
-int
-load_licence(uint8 ** data)
-{
- return 0;
-}
-
-/*****************************************************************************/
-void *
-xrealloc(void * in, int size)
-{
- if (size < 1)
- {
- size = 1;
- }
- return realloc(in, size);
-}
-
-/*****************************************************************************/
-void *
-xmalloc(int size)
-{
- if (size < 1)
- {
- size = 1;
- }
- return malloc(size);
-}
-
-/*****************************************************************************/
-void
-xfree(void * in)
-{
- if (in != 0)
- {
- free(in);
- }
-}
-
-/*****************************************************************************/
-char *
-xstrdup(const char * s)
-{
- int len;
- char * p;
-
- if (s == 0)
- {
- return 0;
- }
- len = strlen(s);
- p = (char *) xmalloc(len + 1);
- strcpy(p, s);
- return p;
-}
-
-/*****************************************************************************/
-void
-warning(char * format, ...)
-{
- va_list ap;
- char text[512];
- char text1[512];
-
- sprintf(text1, "WARNING: ");
- va_start(ap, format);
- vsprintf(text, format, ap);
- va_end(ap);
- strcat(text1, text);
- mi_warning(text1);
-}
-
-/*****************************************************************************/
-void
-unimpl(char * format, ...)
-{
- va_list ap;
- char text[512];
- char text1[512];
-
- sprintf(text1, "UNIMPL: ");
- va_start(ap, format);
- vsprintf(text, format, ap);
- va_end(ap);
- strcat(text1, text);
- mi_warning(text1);
-}
-
-/*****************************************************************************/
-void
-error(char * format, ...)
-{
- va_list ap;
- char text[512];
- char text1[512];
-
- sprintf(text1, "ERROR: ");
- va_start(ap, format);
- vsprintf(text, format, ap);
- va_end(ap);
- strcat(text1, text);
- mi_error(text1);
-}
-
-/*****************************************************************************/
-BOOL
-rd_pstcache_mkdir(void)
-{
- return 0;
-}
-
-/*****************************************************************************/
-int
-rd_open_file(char * filename)
-{
- return 0;
-}
-
-/*****************************************************************************/
-void
-rd_close_file(int fd)
-{
- return;
-}
-
-/*****************************************************************************/
-int
-rd_read_file(int fd, void * ptr, int len)
-{
- return 0;
-}
-
-/*****************************************************************************/
-int
-rd_write_file(int fd, void * ptr, int len)
-{
- return 0;
-}
-
-/*****************************************************************************/
-int
-rd_lseek_file(int fd, int offset)
-{
- return 0;
-}
-
-/*****************************************************************************/
-BOOL
-rd_lock_file(int fd, int start, int len)
-{
- return False;
-}
-
-
-/*****************************************************************************/
-void
-ui_mouse_move(int x, int y)
-{
- rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE, (uint16) x, (uint16) y);
-}
-
-
-/*****************************************************************************/
-void
-ui_mouse_button(int button, int x, int y, int down)
-{
- uint16 flags;
-
- flags = 0;
- if (down)
- {
- flags |= MOUSE_FLAG_DOWN;
- }
- switch (button)
- {
- case 1:
- flags |= MOUSE_FLAG_BUTTON1;
- break;
- case 2:
- flags |= MOUSE_FLAG_BUTTON2;
- break;
- case 3:
- flags |= MOUSE_FLAG_BUTTON3;
- break;
- case 4:
- flags |= MOUSE_FLAG_BUTTON4;
- break;
- case 5:
- flags |= MOUSE_FLAG_BUTTON5;
- break;
- }
- rdp_send_input(0, RDP_INPUT_MOUSE, flags, (uint16) x, (uint16) y);
-}
-
-
-/*****************************************************************************/
-void
-ui_key_down(int key, int ext)
-
-{
- rdp_send_input(0, RDP_INPUT_SCANCODE, (uint16) (RDP_KEYPRESS | ext),
- (uint16) key, 0);
-}
-
-/*****************************************************************************/
-void
-ui_key_up(int key, int ext)
-{
- rdp_send_input(0, RDP_INPUT_SCANCODE, (uint16) (RDP_KEYRELEASE | ext),
- (uint16) key, 0);
-}
-
-/*****************************************************************************/
-/* returns boolean, non zero is good */
-int
-ui_read_wire(void)
-{
- return rdp_loop(&g_deactivated, &g_ext_disc_reason);
-}
-
-/*****************************************************************************/
-/* called after the command line parameters are processed */
-/* returns boolean, non zero is ok */
-int
-ui_main(void)
-{
- uint32 flags;
-
- /* try to connect */
- flags = RDP_LOGON_NORMAL;
- if (g_password[0] != 0)
- {
- flags |= RDP_LOGON_AUTO;
- }
- if (!rdp_connect(g_servername, flags, g_domain, g_password,
- g_shell, g_directory))
- {
- return 0;
- }
- /* create the window */
- if (!mi_create_window())
- {
- error("mi_create_window failed\r\n");
- return 0;
- }
- /* create backingstore stuff for use in bsops.c */
- if (!mi_create_bs())
- {
- error("mi_create_bs failed\r\n");
- return 0;
- }
- /* init backingstore */
- bs_init();
- /* if all ok, enter main loop */
- return mi_main_loop();
-}
-
-/*****************************************************************************/
-/* produce a hex dump */
-void
-hexdump(uint8 * p, uint32 len)
-{
- uint8 * line = p;
- int i, thisline, offset = 0;
-
- while (offset < (int)len)
- {
- printf("%04x ", offset);
- thisline = len - offset;
- if (thisline > 16)
- thisline = 16;
-
- for (i = 0; i < thisline; i++)
- printf("%02x ", line[i]);
-
- for (; i < 16; i++)
- printf(" ");
-
- for (i = 0; i < thisline; i++)
- printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
-
- printf("\n");
- offset += thisline;
- line += thisline;
- }
-}
-
+/* -*- c-basic-offset: 8 -*- + rdesktop: A Remote Desktop Protocol client. + Main ui file + Copyright (C) Jay Sorg 2006 + + 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" +#include "bsops.h" +#include "uimain.h" + +char g_username[256] = ""; +char g_hostname[256] = ""; +char g_servername[256] = ""; +char g_password[256] = ""; +char g_shell[256] = ""; +char g_directory[256] = ""; +char g_domain[256] = ""; +char * g_bs = 0; /* created in hardware file, used in bsops.c */ +int g_bs_Bpp = 4; +int g_bs_bpp = 32; +BOOL g_desktop_save = False; /* desktop save order */ +BOOL g_polygon_ellipse_orders = False; /* polygon / ellipse orders */ +BOOL g_bitmap_compression = True; +uint32 g_rdp5_performanceflags = + RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS; +BOOL g_bitmap_cache_persist_enable = False; +BOOL g_bitmap_cache_precache = True; +BOOL g_bitmap_cache = True; +BOOL g_encryption = True; +int g_server_depth = 8; +BOOL g_use_rdp5 = False; +int g_width = 800; +int g_height = 600; +uint32 g_keylayout = 0x409; /* Defaults to US keyboard layout */ +int g_keyboard_type = 0x4; /* Defaults to US keyboard layout */ +int g_keyboard_subtype = 0x0; /* Defaults to US keyboard layout */ +int g_keyboard_functionkeys = 0xc; /* Defaults to US keyboard layout */ +BOOL g_console_session = False; + +/* can't be static, hardware file or bsops need these */ +int g_tcp_sck = 0; +int pal_entries[256]; + +/* Session Directory redirection */ +BOOL g_redirect = False; +char g_redirect_server[64]; +char g_redirect_domain[16]; +char g_redirect_password[64]; +char g_redirect_username[64]; +char g_redirect_cookie[128]; +uint32 g_redirect_flags = 0; + +extern int g_tcp_port_rdp; + +static int g_deactivated = 0; +static uint32 g_ext_disc_reason = 0; + +struct bitmap +{ + uint8 * data; + uint32 width; + uint32 height; +}; + +/* in ui specific file eg win32.c, qt.c, dfb.c, ... */ +int +mi_create_window(void); +void +mi_invalidate(int x, int y, int cx, int cy); +int +mi_create_bs(void); +int +mi_main_loop(void); +void +mi_error(char * msg); +void +mi_warning(char * msg); +void +ui_invalidate(int x, int y, int cx, int cy); +void +mi_paint_rect(char * data, int width, int height, int x, int y, int cx, int cy); +void +mi_begin_update(void); +void +mi_end_update(void); +void +mi_fill_rect(int x, int y, int cx, int cy, int colour); +void +mi_screen_copy(int x, int y, int cx, int cy, int srcx, int srcy); +void +mi_set_clip(int x, int y, int cx, int cy); +void +mi_reset_clip(void); +void +mi_line(int x1, int y1, int x2, int y2, int colour); +mi_create_cursor(unsigned int x, unsigned int y, + int width, int height, + unsigned char * andmask, unsigned char * xormask); +void +mi_destroy_cursor(void * cursor); +void +mi_set_cursor(void * cursor); +void +mi_set_null_cursor(void); +int +mi_read_keyboard_state(void); + +/*****************************************************************************/ +/* put part of the screen from the backing store to the display */ +void +ui_invalidate(int x, int y, int cx, int cy) +{ + if (cx < 1 || cy < 1 || g_bs == 0) + { + return; + } + if (bs_warp_coords(&x, &y, &cx, &cy, 0, 0)) + { + mi_invalidate(x, y, cx, cy); + } +/* + if (bs_warp_coords(&x, &y, &cx, &cy, 0, 0)) + { + cx = (cx + 3) & ~3; + data = (char *) xmalloc(cx * cy * 4); + bs_copy_box(data, x, y, cx, cy, cx * ((g_server_depth + 7) / 8)); + mi_paint_rect(data, cx, cy, x, y, cx, cy); + xfree(data); + } +*/ +} + +/*****************************************************************************/ +static int +convert_colour(int in_colour) +{ + int r; + int g; + int b; + + if (g_server_depth == 8) + { + r = (pal_entries[in_colour & 0xff] & 0xff0000) >> 16; + g = (pal_entries[in_colour & 0xff] & 0xff00) >> 8; + b = pal_entries[in_colour & 0xff] & 0xff; + } + else if (g_server_depth == 15) + { + SPLIT_COLOUR15(in_colour, r, g, b); + } + else if (g_server_depth == 16) + { + SPLIT_COLOUR16(in_colour, r, g, b); + } + else if (g_server_depth == 24) + { + SPLIT_COLOUR32(in_colour, r, g, b); + } + if (g_bs_bpp == 32) + { + MAKE_COLOUR32(in_colour, r, g, b); + } + return in_colour; +} + +/*****************************************************************************/ +void +ui_bell(void) +{ +} + +/*****************************************************************************/ +int +ui_select(int in) +{ + if (g_tcp_sck == 0) + { + g_tcp_sck = in; + } + return 1; +} + +/*****************************************************************************/ +void * +ui_create_cursor(uint32 x, uint32 y, + int width, int height, + uint8 * andmask, uint8 * xormask) +{ + int i; + int j; + char am[32 * 4]; + char xm[32 * 4]; + + if (width != 32 || height != 32) + { + return 0; + } + memset(am, 0, 32 * 4); + memset(xm, 0, 32 * 4); + for (i = 0; i < 32; i++) + { + for (j = 0; j < 32; j++) + { + if (bs_is_pixel_on(andmask, j, i, 32, 1)) + { + bs_set_pixel_on(am, j, 31 - i, 32, 1, 1); + } + if (bs_is_pixel_on(xormask, j, i, 32, 24)) + { + bs_set_pixel_on(xm, j, 31 - i, 32, 1, 1); + } + } + } + return (void *) mi_create_cursor(x, y, width, height, am, xm); +} + +/*****************************************************************************/ +void +ui_destroy_cursor(void * cursor) +{ + mi_destroy_cursor(cursor); +} + +/*****************************************************************************/ +void +ui_set_cursor(void * cursor) +{ + mi_set_cursor(cursor); +} + +/*****************************************************************************/ +void +ui_set_null_cursor(void) +{ + mi_set_null_cursor(); +} + +/*****************************************************************************/ +void * +ui_create_glyph(int width, int height, uint8 * data) +{ + int i; + int j; + char * glyph_data; + struct bitmap * the_glyph; + + glyph_data = (char *) xmalloc(width * height); + memset(glyph_data, 0, width * height); + the_glyph = (struct bitmap *) xmalloc(sizeof(struct bitmap)); + memset(the_glyph, 0, sizeof(struct bitmap)); + the_glyph->width = width; + the_glyph->height = height; + the_glyph->data = glyph_data; + for (i = 0; i < height; i++) + { + for (j = 0; j < width; j++) + { + if (bs_is_pixel_on(data, j, i, width, 1)) + { + bs_set_pixel_on(glyph_data, j, i, width, 8, 255); + } + } + } + return the_glyph; +} + +/*****************************************************************************/ +void +ui_destroy_glyph(void * glyph) +{ + struct bitmap * the_glyph; + + the_glyph = glyph; + if (the_glyph != 0) + { + xfree(the_glyph->data); + } + xfree(the_glyph); +} + +/*****************************************************************************/ +void * +ui_create_bitmap(int width, int height, uint8 * data) +{ +#if 0 + struct bitmap * b; + int size; + + size = width * height * ((g_server_depth + 7) / 8); + b = (struct bitmap *) xmalloc(sizeof(struct bitmap)); + b->data = (uint8 *) xmalloc(size); + memcpy(b->data, data, size); + b->width = width; + b->height = height; + return b; +#endif + return 0; +} + +/*****************************************************************************/ +void * +ui_create_bitmap_ex(int width, int height, uint8 * data, int data_size, + int compressed) +{ + struct bitmap * b; + int size; + int i; + int j; + int pixel; + int red; + int green; + int blue; + unsigned short * s16; + unsigned char * s8; + unsigned int * d32; + + size = width * height * 4; + b = (struct bitmap *) xmalloc(sizeof(struct bitmap)); + b->data = (uint8 *) xmalloc(size); + if (compressed) + { + bitmap_decompress_ex(b->data, width, height, data, data_size, + g_server_depth, 32); + } + else + { + if (g_server_depth == 16 && g_bs_bpp == 32) + { + for (i = 0; i < height; i++) + { + s16 = ((unsigned short *) data) + (i * width); + d32 = ((unsigned int *) b->data) + (height - i - 1) * width; + for (j = 0; j < width; j++) + { + pixel = *s16; + s16++; + SPLIT_COLOUR16(pixel, red, green, blue); + MAKE_COLOUR32(pixel, red, green, blue); + *d32 = pixel; + d32++; + } + } + } + else if (g_server_depth == 24 && g_bs_bpp == 32) + { + for (i = 0; i < height; i++) + { + s8 = ((unsigned char *) data) + (i * width * 3); + d32 = ((unsigned int *) b->data) + (height - i - 1) * width; + for (j = 0; j < width; j++) + { + blue = *s8; + s8++; + green = *s8; + s8++; + red = *s8; + s8++; + MAKE_COLOUR32(pixel, red, green, blue); + *d32 = pixel; + d32++; + } + } + } + } + b->width = width; + b->height = height; + return b; +} + +/*****************************************************************************/ +void +ui_destroy_bitmap(void * bmp) +{ + struct bitmap * b; + + b = (struct bitmap *) bmp; + if (b != 0) + { + xfree(b->data); + } + xfree(b); +} + +/*****************************************************************************/ +void +ui_paint_bitmap(int x, int y, int cx, int cy, + int width, int height, uint8 * data) +{ +/* struct bitmap b; + + b.width = width; + b.height = height; + b.data = data; + ui_memblt(12, x, y, cx, cy, &b, 0, 0); */ +} + +/*****************************************************************************/ +void +ui_paint_bitmap_ex(int x, int y, int cx, int cy, + int width, int height, uint8 * data, int data_size, + int compressed) +{ + struct bitmap * b; + + b = ui_create_bitmap_ex(width, height, data, data_size, compressed); + ui_memblt(12, x, y, cx, cy, b, 0, 0); + ui_destroy_bitmap(b); +} + +/*****************************************************************************/ +void +ui_set_clip(int x, int y, int cx, int cy) +{ + bs_set_clip(x, y, cx, cy); + mi_set_clip(x, y, cx, cy); +} + +/*****************************************************************************/ +void +ui_reset_clip(void) +{ + bs_reset_clip(); + mi_reset_clip(); +} + +/*****************************************************************************/ +void * +ui_create_colourmap(COLOURMAP * colours) +{ + int i; + int n; + + n = MIN(256, colours->ncolours); + memset(pal_entries, 0, sizeof(pal_entries)); + for (i = 0; i < n; i++) + { + pal_entries[i] = (colours->colours[i].red << 16) | + (colours->colours[i].green << 8) | + colours->colours[i].blue; + } + return 0; +} + +/*****************************************************************************/ +void +ui_set_colourmap(void * map) +{ +} + +/*****************************************************************************/ +/* don't convert colour here */ +static void +draw_glyph(int x, int y, void * glyph, int fgcolor) +{ + struct bitmap * b; + + b = glyph; + bs_draw_glyph(x, y, b->data, b->width, b->height, fgcolor); +} + +/*****************************************************************************/ +#define DO_GLYPH(ttext,idx) \ +{ \ + glyph = cache_get_font(font, ttext[idx]); \ + if (!(flags & TEXT2_IMPLICIT_X)) \ + { \ + xyoffset = ttext[++idx]; \ + if (xyoffset & 0x80) \ + { \ + if (flags & TEXT2_VERTICAL) \ + { \ + y += ttext[idx + 1] | (ttext[idx + 2] << 8); \ + } \ + else \ + { \ + x += ttext[idx + 1] | (ttext[idx + 2] << 8); \ + } \ + idx += 2; \ + } \ + else \ + { \ + if (flags & TEXT2_VERTICAL) \ + { \ + y += xyoffset; \ + } \ + else \ + { \ + x += xyoffset; \ + } \ + } \ + } \ + if (glyph != NULL) \ + { \ + draw_glyph(x + glyph->offset, y + glyph->baseline, glyph->pixmap, \ + fgcolour); \ + if (flags & TEXT2_IMPLICIT_X) \ + { \ + x += glyph->width; \ + } \ + } \ +} + +/*****************************************************************************/ +void +ui_draw_text(uint8 font, uint8 flags, uint8 opcode, int mixmode, + int x, int y, + int clipx, int clipy, int clipcx, int clipcy, + int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush, + int bgcolour, int fgcolour, uint8 * text, uint8 length) +{ + int i; + int j; + int xyoffset; + DATABLOB * entry; + FONTGLYPH * glyph; + + fgcolour = convert_colour(fgcolour); + bgcolour = convert_colour(bgcolour); + if (boxx + boxcx > g_width) + { + boxcx = g_width - boxx; + } + if (boxcx > 1) + { + bs_rect(boxx, boxy, boxcx, boxcy, bgcolour, 0xc); + } + else + { + if (mixmode == MIX_OPAQUE) + { + bs_rect(clipx, clipy, clipcx, clipcy, bgcolour, 0xc); + } + } + /* Paint text, character by character */ + for (i = 0; i < length;) + { + switch (text[i]) + { + case 0xff: + if (i + 2 < length) + { + cache_put_text(text[i + 1], text, text[i + 2]); + } + else + { + error("this shouldn't be happening\n"); + exit(1); + } + /* this will move pointer from start to first character after */ + /* FF command */ + length -= i + 3; + text = &(text[i + 3]); + i = 0; + break; + case 0xfe: + entry = cache_get_text(text[i + 1]); + if (entry != NULL) + { + if ((((uint8 *) (entry->data))[1] == 0) && + (!(flags & TEXT2_IMPLICIT_X))) + { + if (flags & TEXT2_VERTICAL) + { + y += text[i + 2]; + } + else + { + x += text[i + 2]; + } + } + for (j = 0; j < entry->size; j++) + { + DO_GLYPH(((uint8 *) (entry->data)), j); + } + } + if (i + 2 < length) + { + i += 3; + } + else + { + i += 2; + } + length -= i; + /* this will move pointer from start to first character after */ + /* FE command */ + text = &(text[i]); + i = 0; + break; + default: + DO_GLYPH(text, i); + i++; + break; + } + } + if (boxcx > 1) + { + ui_invalidate(boxx, boxy, boxcx, boxcy); + } + else + { + ui_invalidate(clipx, clipy, clipcx, clipcy); + } +} + +/*****************************************************************************/ +void +ui_line(uint8 opcode, int startx, int starty, int endx, int endy, + PEN * pen) +{ + int x; + int y; + int cx; + int cy; + int colour; + + colour = convert_colour(pen->colour); + + bs_line(opcode, startx, starty, endx, endy, pen->width, pen->style, + colour); + if (pen->style == 0 && pen->width < 2 && opcode == 12) + { + mi_line(startx, starty, endx, endy, colour); + } + else + { + x = MIN(startx, endx); + y = MIN(starty, endy); + cx = (MAX(startx, endx) + 1) - x; + cy = (MAX(starty, endy) + 1) - y; + ui_invalidate(x, y, cx, cy); + } +} + +/*****************************************************************************/ +void +ui_triblt(uint8 opcode, int x, int y, int cx, int cy, + void * src, int srcx, int srcy, + BRUSH* brush, int bgcolour, int fgcolour) +{ + /* not used */ +} + +/*****************************************************************************/ +void +ui_memblt(uint8 opcode, int x, int y, int cx, int cy, + void * src, int srcx, int srcy) +{ + struct bitmap* b; + + b = (struct bitmap *) src; + bs_memblt(opcode, x, y, cx, cy, b->data, b->width, b->height, + srcx, srcy); + ui_invalidate(x, y, cx, cy); +} + +/*****************************************************************************/ +void +ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy) +{ +} + +/*****************************************************************************/ +void +ui_desktop_save(uint32 offset, int x, int y, int cx, int cy) +{ +} + +/*****************************************************************************/ +void +ui_rect(int x, int y, int cx, int cy, int colour) +{ + colour = convert_colour(colour); + bs_rect(x, y, cx, cy, colour, 12); + mi_fill_rect(x, y, cx, cy, colour); +} + +/*****************************************************************************/ +void +ui_screenblt(uint8 opcode, int x, int y, int cx, int cy, + int srcx, int srcy) +{ + bs_screenblt(opcode, x, y, cx, cy, srcx, srcy); + if (opcode == 12) + { + mi_screen_copy(x, y, cx, cy, srcx, srcy); + } + else + { + ui_invalidate(x, y, cx, cy); + } +} + +/*****************************************************************************/ +void +ui_patblt(uint8 opcode, int x, int y, int cx, int cy, + BRUSH * brush, int bgcolour, int fgcolour) +{ + bgcolour = convert_colour(bgcolour); + fgcolour = convert_colour(fgcolour); + bs_patblt(opcode, x, y, cx, cy, brush->style, brush->pattern, + brush->xorigin, brush->yorigin, bgcolour, fgcolour); + ui_invalidate(x, y, cx, cy); +} + +/*****************************************************************************/ +void +ui_destblt(uint8 opcode, int x, int y, int cx, int cy) +{ + bs_rect(x, y, cx, cy, 0, opcode); + ui_invalidate(x, y, cx, cy); + /* todo */ +} + +/*****************************************************************************/ +void +ui_move_pointer(int x, int y) +{ +} + +/*****************************************************************************/ +uint16 +ui_get_numlock_state(uint32 state) +{ + return (uint16) state; +} + +/*****************************************************************************/ +/* get the num, caps, and scroll lock state */ +/* scroll lock is 1, num lock is 2 and caps lock is 4 */ +/* just returning 0, the hardware specific file is responsable for this */ +uint32 +read_keyboard_state(void) +{ + return (uint32) mi_read_keyboard_state(); +} + +/*****************************************************************************/ +void +ui_set_modifier_state(int code) + +{ + + //error("%8.8x", code); + + rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, (uint16) code, 0); + +} + +/*****************************************************************************/ +void +ui_resize_window(void) +{ +} + +/*****************************************************************************/ +void +ui_begin_update(void) +{ + mi_begin_update(); +} + +/*****************************************************************************/ +void +ui_end_update(void) +{ + mi_end_update(); +} + +/*****************************************************************************/ +void +ui_polygon(uint8 opcode, uint8 fillmode, POINT * point, int npoints, + BRUSH * brush, int bgcolour, int fgcolour) +{ + /* not used */ +} + +/*****************************************************************************/ +void +ui_polyline(uint8 opcode, POINT * points, int npoints, PEN * pen) +{ + int i, x, y, dx, dy; + if (npoints > 0) + { + x = points[0].x; + y = points[0].y; + for (i = 1; i < npoints; i++) + { + dx = points[i].x; + dy = points[i].y; + ui_line(opcode, x, y, x + dx, y + dy, pen); + x = x + dx; + y = y + dy; + } + } +} + +/*****************************************************************************/ +void +ui_ellipse(uint8 opcode, uint8 fillmode, + int x, int y, int cx, int cy, + BRUSH * brush, int bgcolour, int fgcolour) +{ + /* not used */ +} + +/*****************************************************************************/ +/* get a 32 byte random */ +void +generate_random(uint8 * random) +{ + int i; + + rand(); + rand(); + for (i = 0; i < 32; i++) + { + random[i] = rand() >> 16; /* higher bits are more random */ + } +} + +/*****************************************************************************/ +void +save_licence(uint8 * data, int length) +{ +} + +/*****************************************************************************/ +int +load_licence(uint8 ** data) +{ + return 0; +} + +/*****************************************************************************/ +void * +xrealloc(void * in, int size) +{ + if (size < 1) + { + size = 1; + } + return realloc(in, size); +} + +/*****************************************************************************/ +void * +xmalloc(int size) +{ + if (size < 1) + { + size = 1; + } + return malloc(size); +} + +/*****************************************************************************/ +void +xfree(void * in) +{ + if (in != 0) + { + free(in); + } +} + +/*****************************************************************************/ +char * +xstrdup(const char * s) +{ + int len; + char * p; + + if (s == 0) + { + return 0; + } + len = strlen(s); + p = (char *) xmalloc(len + 1); + strcpy(p, s); + return p; +} + +/*****************************************************************************/ +void +warning(char * format, ...) +{ + va_list ap; + char text[512]; + char text1[512]; + + sprintf(text1, "WARNING: "); + va_start(ap, format); + vsprintf(text, format, ap); + va_end(ap); + strcat(text1, text); + mi_warning(text1); +} + +/*****************************************************************************/ +void +unimpl(char * format, ...) +{ + va_list ap; + char text[512]; + char text1[512]; + + sprintf(text1, "UNIMPL: "); + va_start(ap, format); + vsprintf(text, format, ap); + va_end(ap); + strcat(text1, text); + mi_warning(text1); +} + +/*****************************************************************************/ +void +error(char * format, ...) +{ + va_list ap; + char text[512]; + char text1[512]; + + sprintf(text1, "ERROR: "); + va_start(ap, format); + vsprintf(text, format, ap); + va_end(ap); + strcat(text1, text); + mi_error(text1); +} + +/*****************************************************************************/ +BOOL +rd_pstcache_mkdir(void) +{ + return 0; +} + +/*****************************************************************************/ +int +rd_open_file(char * filename) +{ + return 0; +} + +/*****************************************************************************/ +void +rd_close_file(int fd) +{ + return; +} + +/*****************************************************************************/ +int +rd_read_file(int fd, void * ptr, int len) +{ + return 0; +} + +/*****************************************************************************/ +int +rd_write_file(int fd, void * ptr, int len) +{ + return 0; +} + +/*****************************************************************************/ +int +rd_lseek_file(int fd, int offset) +{ + return 0; +} + +/*****************************************************************************/ +BOOL +rd_lock_file(int fd, int start, int len) +{ + return False; +} + + +/*****************************************************************************/ +void +ui_mouse_move(int x, int y) +{ + rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE, (uint16) x, (uint16) y); +} + + +/*****************************************************************************/ +void +ui_mouse_button(int button, int x, int y, int down) +{ + uint16 flags; + + flags = 0; + if (down) + { + flags |= MOUSE_FLAG_DOWN; + } + switch (button) + { + case 1: + flags |= MOUSE_FLAG_BUTTON1; + break; + case 2: + flags |= MOUSE_FLAG_BUTTON2; + break; + case 3: + flags |= MOUSE_FLAG_BUTTON3; + break; + case 4: + flags |= MOUSE_FLAG_BUTTON4; + break; + case 5: + flags |= MOUSE_FLAG_BUTTON5; + break; + } + rdp_send_input(0, RDP_INPUT_MOUSE, flags, (uint16) x, (uint16) y); +} + + +/*****************************************************************************/ +void +ui_key_down(int key, int ext) + +{ + rdp_send_input(0, RDP_INPUT_SCANCODE, (uint16) (RDP_KEYPRESS | ext), + (uint16) key, 0); +} + +/*****************************************************************************/ +void +ui_key_up(int key, int ext) +{ + rdp_send_input(0, RDP_INPUT_SCANCODE, (uint16) (RDP_KEYRELEASE | ext), + (uint16) key, 0); +} + +/*****************************************************************************/ +/* returns boolean, non zero is good */ +int +ui_read_wire(void) +{ + return rdp_loop(&g_deactivated, &g_ext_disc_reason); +} + +/*****************************************************************************/ +/* called after the command line parameters are processed */ +/* returns boolean, non zero is ok */ +int +ui_main(void) +{ + uint32 flags; + + /* try to connect */ + flags = RDP_LOGON_NORMAL; + if (g_password[0] != 0) + { + flags |= RDP_LOGON_AUTO; + } + if (!rdp_connect(g_servername, flags, g_domain, g_password, + g_shell, g_directory)) + { + return 0; + } + /* create the window */ + if (!mi_create_window()) + { + error("mi_create_window failed\r\n"); + return 0; + } + /* create backingstore stuff for use in bsops.c */ + if (!mi_create_bs()) + { + error("mi_create_bs failed\r\n"); + return 0; + } + /* init backingstore */ + bs_init(); + /* if all ok, enter main loop */ + return mi_main_loop(); +} + +/*****************************************************************************/ +/* produce a hex dump */ +void +hexdump(uint8 * p, uint32 len) +{ + uint8 * line = p; + int i, thisline, offset = 0; + + while (offset < (int)len) + { + printf("%04x ", offset); + thisline = len - offset; + if (thisline > 16) + thisline = 16; + + for (i = 0; i < thisline; i++) + printf("%02x ", line[i]); + + for (; i < 16; i++) + printf(" "); + + for (i = 0; i < thisline; i++) + printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.'); + + printf("\n"); + offset += thisline; + line += thisline; + } +} + diff --git a/uirdesktop/uimain.h b/uirdesktop/uimain.h index a9d55c47..4f2f46c0 100755 --- a/uirdesktop/uimain.h +++ b/uirdesktop/uimain.h @@ -1,83 +1,85 @@ -/* -*- c-basic-offset: 8 -*-
- rdesktop: A Remote Desktop Protocol client.
- main ui header
- Copyright (C) Jay Sorg 2005-2006
-
- 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.
-*/
-
-/* in uimain.c */
-int
-ui_main(void);
-void
-ui_invalidate(int x, int y, int cx, int cy);
-int
-ui_read_wire(void);
-void
-ui_mouse_move(int x, int y);
-void
-ui_mouse_button(int button, int x, int y, int down);
-void
-ui_key_down(int key, int ext);
-void
-ui_key_up(int key, int ext);
-
void
-
ui_set_modifier_state(int code);
-
-#define SPLIT_COLOUR15(c, r, g, b) \
-{ \
- r = ((c >> 7) & 0xf8) | ((c >> 12) & 0x7); \
- g = ((c >> 2) & 0xf8) | ((c >> 8) & 0x7); \
- b = ((c << 3) & 0xf8) | ((c >> 2) & 0x7); \
-}
-
-#define SPLIT_COLOUR16(c, r, g, b) \
-{ \
- r = ((c >> 8) & 0xf8) | ((c >> 13) & 0x7); \
- g = ((c >> 3) & 0xfc) | ((c >> 9) & 0x3); \
- b = ((c << 3) & 0xf8) | ((c >> 2) & 0x7); \
-}
-
-#define SPLIT_COLOUR32(c, r, g, b) \
-{ \
- r = ((c >> 0) & 0xff); \
- g = ((c >> 8) & 0xff); \
- b = ((c >> 16) & 0xff); \
-}
-
-#define MAKE_COLOUR15(c, r, g, b) \
-{ \
- c = ( \
- (((r & 0xff) >> 3) << 10) | \
- (((g & 0xff) >> 3) << 5) | \
- (((b & 0xff) >> 3) << 0) \
- ); \
-}
-
-#define MAKE_COLOUR32(c, r, g, b) \
-{ \
- c = ( \
- ((r & 0xff) << 16) | \
- ((g & 0xff) << 8) | \
- ((b & 0xff) << 0) \
- ); \
-}
-
-#undef UI_MAX
-#define UI_MAX(a, b) (((a) > (b)) ? (a) : (b))
-#undef UI_MIN
-#define UI_MIN(a, b) (((a) < (b)) ? (a) : (b))
-
-
+/* -*- c-basic-offset: 8 -*- + rdesktop: A Remote Desktop Protocol client. + main ui header + Copyright (C) Jay Sorg 2005-2006 + + 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. +*/ + +/* in uimain.c */ +int +ui_main(void); +void +ui_invalidate(int x, int y, int cx, int cy); +int +ui_read_wire(void); +void +ui_mouse_move(int x, int y); +void +ui_mouse_button(int button, int x, int y, int down); +void +ui_key_down(int key, int ext); +void +ui_key_up(int key, int ext); + +void + +ui_set_modifier_state(int code); + +#define SPLIT_COLOUR15(c, r, g, b) \ +{ \ + r = ((c >> 7) & 0xf8) | ((c >> 12) & 0x7); \ + g = ((c >> 2) & 0xf8) | ((c >> 8) & 0x7); \ + b = ((c << 3) & 0xf8) | ((c >> 2) & 0x7); \ +} + +#define SPLIT_COLOUR16(c, r, g, b) \ +{ \ + r = ((c >> 8) & 0xf8) | ((c >> 13) & 0x7); \ + g = ((c >> 3) & 0xfc) | ((c >> 9) & 0x3); \ + b = ((c << 3) & 0xf8) | ((c >> 2) & 0x7); \ +} + +#define SPLIT_COLOUR32(c, r, g, b) \ +{ \ + r = ((c >> 0) & 0xff); \ + g = ((c >> 8) & 0xff); \ + b = ((c >> 16) & 0xff); \ +} + +#define MAKE_COLOUR15(c, r, g, b) \ +{ \ + c = ( \ + (((r & 0xff) >> 3) << 10) | \ + (((g & 0xff) >> 3) << 5) | \ + (((b & 0xff) >> 3) << 0) \ + ); \ +} + +#define MAKE_COLOUR32(c, r, g, b) \ +{ \ + c = ( \ + ((r & 0xff) << 16) | \ + ((g & 0xff) << 8) | \ + ((b & 0xff) << 0) \ + ); \ +} + +#undef UI_MAX +#define UI_MAX(a, b) (((a) > (b)) ? (a) : (b)) +#undef UI_MIN +#define UI_MIN(a, b) (((a) < (b)) ? (a) : (b)) + + diff --git a/uirdesktop/win32.c b/uirdesktop/win32.c index 75862216..ca72c5ae 100755 --- a/uirdesktop/win32.c +++ b/uirdesktop/win32.c @@ -1,1733 +1,1733 @@ -/* -*- c-basic-offset: 8 -*-
- rdesktop: A Remote Desktop Protocol client.
- win32 calls
- Copyright (C) Jay Sorg 2006
-
- 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.
-*/
-
-#ifdef _WIN32_WCE
-#define MYWINCE
-#endif
-
-#include <winsock2.h> /* winsock2.h first */
-#include <windows.h>
-#ifdef MYWINCE
-#include <aygshell.h> /* aygshell.lib */
-#endif /* MYWINCE */
-#include <winuser.h>
-#include <stdio.h>
-#include "uimain.h"
-
-extern char g_username[];
-extern char g_hostname[];
-extern char g_servername[];
-extern char g_password[];
-extern char g_shell[];
-extern char g_directory[];
-extern char g_domain[];
-extern int g_width;
-extern int g_height;
-extern int g_tcp_sck;
-extern int g_server_depth;
-extern int g_tcp_port_rdp; /* in tcp.c */
-extern int pal_entries[];
-extern char * g_bs;
-extern int g_bs_bpp;
-extern int g_bs_Bpp;
-
-static HWND g_Wnd = 0;
-static HINSTANCE g_Instance = 0;
-static HCURSOR g_cursor = 0;
-static HBITMAP g_bs_bitmap = 0;
-static int g_block = 0;
-static int g_xoff = 0; /* offset from window to client coords */
-static int g_yoff = 0;
-static int g_xscroll = 0; /* current scroll position */
-static int g_yscroll = 0;
-static int g_screen_width = 0;
-static int g_screen_height = 0;
-static int g_wnd_cwidth = 0; /* set from WM_SIZE */
-static int g_wnd_cheight = 0;
-static int g_fullscreen = 0;
-static int g_workarea = 0;
-static int g_mousex = 0; /* in client coords */
-static int g_mousey = 0;
-static int g_width_height_set = 0;
-
-static int g_clip_left = 0;
-static int g_clip_top = 0;
-static int g_clip_right = 800;
-static int g_clip_bottom = 600;
-static RECT g_wnd_clip; /* this client area of whats actually visable */
- /* set from WM_SIZE */
-#ifdef MYWINCE
-static int g_sip_up = 0;
-#endif
-
-/*****************************************************************************/
-static void
-str_to_uni(TCHAR * sizex, char * size1)
-{
- int len;
- int i;
-
- len = strlen(size1);
- for (i = 0; i < len; i++)
- {
- sizex[i] = size1[i];
- }
- sizex[len] = 0;
-}
-
-/*****************************************************************************/
-/* returns non zero if it processed something */
-static int
-check_sck(void)
-{
- fd_set rfds;
- struct timeval tm;
- int count;
- int rv;
-
- rv = 0;
- if (g_block == 0)
- {
- g_block = 1;
- /* see if there really is data */
- FD_ZERO(&rfds);
- FD_SET((unsigned int)g_tcp_sck, &rfds);
- ZeroMemory(&tm, sizeof(tm));
- count = select(g_tcp_sck + 1, &rfds, 0, 0, &tm);
- if (count > 0)
- {
- if (ui_read_wire())
- {
- rv = 1;
- }
- else
- {
- PostQuitMessage(0);
- }
- }
- g_block = 0;
- }
- return rv;
-}
-
-/*****************************************************************************/
-void
-mi_error(char * msg)
-{
-#ifdef WITH_DEBUG
- printf(msg);
-#else /* WITH_DEBUG */
- TCHAR lmsg[512];
- TCHAR ltitle[512];
-
- str_to_uni(lmsg, msg);
- str_to_uni(ltitle, "Error");
- MessageBox(g_Wnd, lmsg, ltitle, MB_OK);
-#endif /* WITH_DEBUG */
-}
-
-/*****************************************************************************/
-static int
-get_scan_code_from_ascii(int code)
-{
- int rv;
-
- rv = 0;
- switch (code & 0xff)
- {
- case 0x30: rv = 0x0b; break; // 0
- case 0x31: rv = 0x02; break; // 1
- case 0x32: rv = 0x03; break; // 2
- case 0x33: rv = 0x04; break; // 3
- case 0x34: rv = 0x05; break; // 4
- case 0x35: rv = 0x06; break; // 5
- case 0x36: rv = 0x07; break; // 6
- case 0x37: rv = 0x08; break; // 7
- case 0x38: rv = 0x09; break; // 8
- case 0x39: rv = 0x0a; break; // 9
-
- case 0xbd: rv = 0x0c; break; // -
- case 0xbb: rv = 0x0d; break; // =
- case 0x08: rv = 0x0e; break; // backspace
- case 0x09: rv = 0x0f; break; // tab
- case 0xdb: rv = 0x1b; break; // ]
- case 0xdd: rv = 0x1a; break; // [
- case 0x14: rv = 0x3a; break; // capslock
- case 0xba: rv = 0x27; break; // ;
- case 0xde: rv = 0x28; break; // '
- case 0x10: rv = 0x2a; break; // shift
- case 0xbc: rv = 0x33; break; // ,
- case 0xbe: rv = 0x34; break; // .
- case 0xbf: rv = 0x35; break; // /
- case 0x0d: rv = 0x1c; break; // enter
- case 0x27: rv = 0x4d; break; // arrow right
- case 0x25: rv = 0x4b; break; // arrow left
- case 0x26: rv = 0x48; break; // arrow up
- case 0x28: rv = 0x50; break; // arrow down
- case 0x20: rv = 0x39; break; // space
- case 0xdc: rv = 0x2b; break; // backslash
- case 0xc0: rv = 0x29; break; // `
- case 0x11: rv = 0x1d; break; // ctl
-
- case 0x41: rv = 0x1e; break; // a
- case 0x42: rv = 0x30; break; // b
- case 0x43: rv = 0x2e; break; // c
- case 0x44: rv = 0x20; break; // d
- case 0x45: rv = 0x12; break; // e
- case 0x46: rv = 0x21; break; // f
- case 0x47: rv = 0x22; break; // g
- case 0x48: rv = 0x23; break; // h
- case 0x49: rv = 0x17; break; // i
- case 0x4a: rv = 0x24; break; // j
- case 0x4b: rv = 0x25; break; // k
- case 0x4c: rv = 0x26; break; // l
- case 0x4d: rv = 0x32; break; // m
- case 0x4e: rv = 0x31; break; // n
- case 0x4f: rv = 0x18; break; // o
- case 0x50: rv = 0x19; break; // p
- case 0x51: rv = 0x10; break; // q
- case 0x52: rv = 0x13; break; // r
- case 0x53: rv = 0x1f; break; // s
- case 0x54: rv = 0x14; break; // t
- case 0x55: rv = 0x16; break; // u
- case 0x56: rv = 0x2f; break; // v
- case 0x57: rv = 0x11; break; // w
- case 0x58: rv = 0x2d; break; // x
- case 0x59: rv = 0x15; break; // y
- case 0x5a: rv = 0x2c; break; // z
- }
- return rv;
-}
-
-/*****************************************************************************/
-static void
-mi_scroll(int dx, int dy)
-{
- HRGN rgn;
-
- rgn = CreateRectRgn(0, 0, 0, 0);
- ScrollWindowEx(g_Wnd, dx, dy, 0, 0, rgn, 0, SW_ERASE);
- InvalidateRgn(g_Wnd, rgn, 0);
- DeleteObject(rgn);
-}
-
-/*****************************************************************************/
-int
-mi_read_keyboard_state(void)
-{
- short keydata;
- int code;
-
- code = 0;
- keydata = GetKeyState(VK_SCROLL);
- if (keydata & 0x0001)
- {
- code |= 1;
- }
- keydata = GetKeyState(VK_NUMLOCK);
- if (keydata & 0x0001)
- {
- code |= 2;
- }
- keydata = GetKeyState(VK_CAPITAL);
- if (keydata & 0x0001)
- {
- code |= 4;
- }
- return code;
-}
-
-/*****************************************************************************/
-static void
-mi_check_modifier(void)
-{
- int code;
-
- code = mi_read_keyboard_state();
- ui_set_modifier_state(code);
-}
-
-/*****************************************************************************/
-static LRESULT
-handle_WM_SETCURSOR(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- if (g_mousex >= g_wnd_clip.left &&
- g_mousey >= g_wnd_clip.top &&
- g_mousex < g_wnd_clip.right &&
- g_mousey < g_wnd_clip.bottom)
- {
- SetCursor(g_cursor);
- }
- /* need default behavoir here */
- return DefWindowProc(hWnd, message, wParam, lParam);
-}
-
-/*****************************************************************************/
-static LRESULT
-handle_WM_NCHITTEST(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- POINT pt;
-
- pt.x = LOWORD(lParam);
- pt.y = HIWORD(lParam);
- if (ScreenToClient(g_Wnd, &pt))
- {
- g_mousex = pt.x;
- g_mousey = pt.y;
- }
- return DefWindowProc(hWnd, message, wParam, lParam);
-}
-
-/*****************************************************************************/
-static LRESULT
-handle_WM_MOUSEMOVE(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- g_mousex = LOWORD(lParam);
- g_mousey = HIWORD(lParam);
- ui_mouse_move(g_mousex + g_xscroll, g_mousey + g_yscroll);
- return 0;
-}
-
-/*****************************************************************************/
-static LRESULT
-handle_WM_LBUTTONDOWN(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- g_mousex = LOWORD(lParam);
- g_mousey = HIWORD(lParam);
- ui_mouse_button(1, g_mousex + g_xscroll, g_mousey + g_yscroll, 1);
- return 0;
-}
-
-/*****************************************************************************/
-static LRESULT
-handle_WM_LBUTTONUP(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- g_mousex = LOWORD(lParam);
- g_mousey = HIWORD(lParam);
- ui_mouse_button(1, g_mousex + g_xscroll, g_mousey + g_yscroll, 0);
- return 0;
-}
-
-/*****************************************************************************/
-static LRESULT
-handle_WM_RBUTTONDOWN(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- g_mousex = LOWORD(lParam);
- g_mousey = HIWORD(lParam);
- ui_mouse_button(2, g_mousex + g_xscroll, g_mousey + g_yscroll, 1);
- return 0;
-}
-
-/*****************************************************************************/
-static LRESULT
-handle_WM_RBUTTONUP(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- g_mousex = LOWORD(lParam);
- g_mousey = HIWORD(lParam);
- ui_mouse_button(2, g_mousex + g_xscroll, g_mousey + g_yscroll, 0);
- return 0;
-}
-
-/*****************************************************************************/
-static LRESULT
-handle_WM_MBUTTONDOWN(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- g_mousex = LOWORD(lParam);
- g_mousey = HIWORD(lParam);
- ui_mouse_button(3, g_mousex + g_xscroll, g_mousey + g_yscroll, 1);
- return 0;
-}
-
-/*****************************************************************************/
-static LRESULT
-handle_WM_MBUTTONUP(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- g_mousex = LOWORD(lParam);
- g_mousey = HIWORD(lParam);
- ui_mouse_button(3, g_mousex + g_xscroll, g_mousey + g_yscroll, 0);
- return 0;
-}
-
-/*****************************************************************************/
-static LRESULT
-handle_WM_MOUSEWHEEL(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- int delta;
-
- delta = ((signed short)HIWORD(wParam)); /* GET_WHEEL_DELTA_WPARAM(wParam); */
- if (delta > 0)
- {
- ui_mouse_button(4, 0, 0, 1);
- ui_mouse_button(4, 0, 0, 0);
- }
- else
- {
- ui_mouse_button(5, 0, 0, 1);
- ui_mouse_button(5, 0, 0, 0);
- }
- return 0;
-}
-
-/*****************************************************************************/
-static LRESULT
-handle_WM_KEY(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- int scancode;
- int ext;
- int down;
-
- ext = HIWORD(lParam);
- scancode = ext;
- down = !(ext & 0x8000);
- scancode &= 0xff;
- if (scancode == 0)
- {
- scancode = get_scan_code_from_ascii(wParam);
- }
- ext &= 0x0100;
- if (scancode == 0x0045) /* num lock */
- {
- ext &= ~0x0100;
- }
- if (down)
- {
- ui_key_down(scancode, ext);
- }
- else
- {
- ui_key_up(scancode, ext);
- }
- return 0;
-}
-
-/*****************************************************************************/
-static LRESULT
-handle_WM_PAINT(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- PAINTSTRUCT ps;
- RECT rect;
- HBRUSH brush;
-
- BeginPaint(hWnd, &ps);
- /* paint the area outside the rdp screen with one colour */
- rect = ps.rcPaint;
- rect.left = UI_MAX(rect.left, g_width);
- if (!IsRectEmpty(&rect))
- {
- brush = CreateSolidBrush(RGB(0, 0, 255));
- FillRect(ps.hdc, &rect, brush);
- DeleteObject(brush);
- }
- rect = ps.rcPaint;
- rect.top = UI_MAX(rect.top, g_height);
- if (!IsRectEmpty(&rect))
- {
- brush = CreateSolidBrush(RGB(0, 0, 255));
- FillRect(ps.hdc, &rect, brush);
- DeleteObject(brush);
- }
- rect = ps.rcPaint;
- EndPaint(hWnd, &ps);
- ui_invalidate(rect.left + g_xscroll,
- rect.top + g_yscroll,
- (rect.right - rect.left) + 1,
- (rect.bottom - rect.top) + 1);
- return 0;
-}
-
-/*****************************************************************************/
-static LRESULT
-handle_WM_SIZE(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- int oldxscroll;
- int oldyscroll;
-
- if (wParam == SIZE_MINIMIZED)
- {
- return DefWindowProc(hWnd, message, wParam, lParam);
- }
- g_wnd_cwidth = LOWORD(lParam); /* client width / height */
- g_wnd_cheight = HIWORD(lParam);
- g_wnd_clip.left = 0;
- g_wnd_clip.top = 0;
- g_wnd_clip.right = g_wnd_clip.left + g_wnd_cwidth;
- g_wnd_clip.bottom = g_wnd_clip.top + g_wnd_cheight;
- if (g_wnd_cwidth < g_width || g_wnd_cheight < g_height)
- {
- SetScrollRange(g_Wnd, SB_HORZ, 0, g_width - g_wnd_cwidth, 1);
- SetScrollRange(g_Wnd, SB_VERT, 0, g_height - g_wnd_cheight, 1);
- }
- oldxscroll = g_xscroll;
- oldyscroll = g_yscroll;
- if (g_wnd_cwidth >= g_width)
- {
- g_xscroll = 0;
- }
- else
- {
- g_xscroll = UI_MIN(g_xscroll, g_width - g_wnd_cwidth);
- }
- if (g_wnd_cheight >= g_height)
- {
- g_yscroll = 0;
- }
- else
- {
- g_yscroll = UI_MIN(g_yscroll, g_height - g_wnd_cheight);
- }
- mi_scroll(oldxscroll - g_xscroll, oldyscroll - g_yscroll);
- if (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED)
- {
- /* check the caps, num, and scroll lock here */
- mi_check_modifier();
- }
- return 0;
-}
-
-/*****************************************************************************/
-static LRESULT
-handle_WM_SIZING(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- LPRECT prect;
- int width;
- int height;
- int style;
-
- prect = (LPRECT) lParam; /* total window rect */
- width = (prect->right - prect->left) - (g_xoff * 2);
- height = (prect->bottom - prect->top) - (g_yoff + g_xoff);
- if (height < g_height || width < g_width)
- {
- style = GetWindowLong(g_Wnd, GWL_STYLE);
- if (!(style & WS_HSCROLL))
- {
- style |= WS_HSCROLL | WS_VSCROLL;
- SetWindowLong(g_Wnd, GWL_STYLE, style);
- g_xscroll = 0;
- g_yscroll = 0;
- SetScrollPos(g_Wnd, SB_HORZ, g_xscroll, 1);
- SetScrollPos(g_Wnd, SB_VERT, g_yscroll, 1);
- }
- }
- else if (height >= g_height && width >= g_width)
- {
- style = GetWindowLong(g_Wnd, GWL_STYLE);
- if (style & WS_HSCROLL)
- {
- style &= ~WS_HSCROLL;
- style &= ~WS_VSCROLL;
- SetWindowLong(g_Wnd, GWL_STYLE, style);
- g_xscroll = 0;
- g_yscroll = 0;
- }
- }
- return 0;
-}
-
-/*****************************************************************************/
-static LRESULT
-handle_WM_HSCROLL(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- int code;
- int oldxscroll;
-
- code = (int) LOWORD(wParam); /* scroll bar value */
- if (code == SB_LINELEFT)
- {
- oldxscroll = g_xscroll;
- g_xscroll--;
- g_xscroll = UI_MAX(g_xscroll, 0);
- SetScrollPos(g_Wnd, SB_HORZ, g_xscroll, 1);
- mi_scroll(oldxscroll - g_xscroll, 0);
- }
- else if (code == SB_LINERIGHT)
- {
- oldxscroll = g_xscroll;
- g_xscroll++;
- g_xscroll = UI_MIN(g_xscroll, g_width - g_wnd_cwidth);
- SetScrollPos(g_Wnd, SB_HORZ, g_xscroll, 1);
- mi_scroll(oldxscroll - g_xscroll, 0);
- }
- else if (code == SB_PAGELEFT)
- {
- oldxscroll = g_xscroll;
- g_xscroll -= g_wnd_cwidth / 2;
- g_xscroll = UI_MAX(g_xscroll, 0);
- SetScrollPos(g_Wnd, SB_HORZ, g_xscroll, 1);
- mi_scroll(oldxscroll - g_xscroll, 0);
- }
- else if (code == SB_PAGERIGHT)
- {
- oldxscroll = g_xscroll;
- g_xscroll += g_wnd_cwidth / 2;
- g_xscroll = UI_MIN(g_xscroll, g_width - g_wnd_cwidth);
- SetScrollPos(g_Wnd, SB_HORZ, g_xscroll, 1);
- mi_scroll(oldxscroll - g_xscroll, 0);
- }
- else if (code == SB_BOTTOM)
- {
- oldxscroll = g_xscroll;
- g_xscroll = g_width - g_wnd_cwidth;
- SetScrollPos(g_Wnd, SB_HORZ, g_xscroll, 1);
- mi_scroll(oldxscroll - g_xscroll, 0);
- }
- else if (code == SB_TOP)
- {
- oldxscroll = g_xscroll;
- g_xscroll = 0;
- SetScrollPos(g_Wnd, SB_HORZ, g_xscroll, 1);
- mi_scroll(oldxscroll - g_xscroll, 0);
- }
- else if (code == SB_THUMBPOSITION)
- {
- oldxscroll = g_xscroll;
- g_xscroll = (signed short) HIWORD(wParam);
- SetScrollPos(g_Wnd, SB_HORZ, g_xscroll, 1);
- mi_scroll(oldxscroll - g_xscroll, 0);
- }
- return 0;
-}
-
-/*****************************************************************************/
-static LRESULT
-handle_WM_VSCROLL(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- int code;
- int oldyscroll;
-
- code = (int) LOWORD(wParam); /* scroll bar value */
- if (code == SB_LINELEFT)
- {
- oldyscroll = g_yscroll;
- g_yscroll--;
- g_yscroll = UI_MAX(g_yscroll, 0);
- SetScrollPos(g_Wnd, SB_VERT, g_yscroll, 1);
- mi_scroll(0, oldyscroll - g_yscroll);
- }
- else if (code == SB_LINERIGHT)
- {
- oldyscroll = g_yscroll;
- g_yscroll++;
- g_yscroll = UI_MIN(g_yscroll, g_height - g_wnd_cheight);
- SetScrollPos(g_Wnd, SB_VERT, g_yscroll, 1);
- mi_scroll(0, oldyscroll - g_yscroll);
- }
- else if (code == SB_PAGELEFT)
- {
- oldyscroll = g_yscroll;
- g_yscroll -= g_wnd_cheight / 2;
- g_yscroll = UI_MAX(g_yscroll, 0);
- SetScrollPos(g_Wnd, SB_VERT, g_yscroll, 1);
- mi_scroll(0, oldyscroll - g_yscroll);
- }
- else if (code == SB_PAGERIGHT)
- {
- oldyscroll = g_yscroll;
- g_yscroll += g_wnd_cheight / 2;
- g_yscroll = UI_MIN(g_yscroll, g_height - g_wnd_cheight);
- SetScrollPos(g_Wnd, SB_VERT, g_yscroll, 1);
- mi_scroll(0, oldyscroll - g_yscroll);
- }
- else if (code == SB_BOTTOM)
- {
- oldyscroll = g_yscroll;
- g_yscroll = g_height - g_wnd_cheight;
- SetScrollPos(g_Wnd, SB_VERT, g_yscroll, 1);
- mi_scroll(0, oldyscroll - g_yscroll);
- }
- else if (code == SB_TOP)
- {
- oldyscroll = g_yscroll;
- g_yscroll = 0;
- SetScrollPos(g_Wnd, SB_VERT, g_yscroll, 1);
- mi_scroll(0, oldyscroll - g_yscroll);
- }
- else if (code == SB_THUMBPOSITION)
- {
- oldyscroll = g_yscroll;
- g_yscroll = (signed short) HIWORD(wParam);
- SetScrollPos(g_Wnd, SB_VERT, g_yscroll, 1);
- mi_scroll(0, oldyscroll - g_yscroll);
- }
- return 0;
-}
-
-#ifdef MYWINCE
-/*****************************************************************************/
-static LRESULT
-handle_WM_SETTINGCHANGE(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- SIPINFO si;
- SHMENUBARINFO mb;
- int x;
- int y;
- int w;
- int h;
- int style;
-
- ZeroMemory(&si, sizeof(SIPINFO));
- si.cbSize = sizeof(SIPINFO);
- SHSipInfo(SPI_GETSIPINFO, lParam, &si, 0);
- x = si.rcVisibleDesktop.left;
- y = si.rcVisibleDesktop.top;
- w = si.rcVisibleDesktop.right - x;
- h = si.rcVisibleDesktop.bottom - y;
- /* get rid of menu */
- DestroyWindow(SHFindMenuBar(g_Wnd));
- if (si.fdwFlags & SIPF_ON)
- {
- g_sip_up = 1; /* used for WM_SETFOCUS */
- ZeroMemory(&mb, sizeof(SHMENUBARINFO));
- mb.cbSize = sizeof(SHMENUBARINFO);
- mb.hwndParent = g_Wnd;
- mb.dwFlags = SHCMBF_EMPTYBAR;
- SHCreateMenuBar(&mb);
- MoveWindow(g_Wnd, x, y, w, h, FALSE);
- SHFullScreen(g_Wnd, SHFS_SHOWTASKBAR | SHFS_SHOWSIPBUTTON |
- SHFS_SHOWSTARTICON);
- }
- else
- {
- g_sip_up = 0;
- if (g_fullscreen)
- {
- MoveWindow(g_Wnd, 0, 0, g_screen_width, g_screen_height, FALSE);
- }
- else
- {
- MoveWindow(g_Wnd, x, y, w, h, FALSE);
- }
- if ((g_fullscreen && g_width <= g_screen_width &&
- g_height <= g_screen_height) ||
- (!g_fullscreen && g_width <= w && g_height <= h))
- {
- style = GetWindowLong(g_Wnd, GWL_STYLE);
- if (style & WS_HSCROLL)
- {
- style &= ~WS_HSCROLL;
- style &= ~WS_VSCROLL;
- SetWindowLong(g_Wnd, GWL_STYLE, style);
- g_xscroll = 0;
- g_yscroll = 0;
- }
- }
- if (g_fullscreen)
- {
- SHFullScreen(g_Wnd, SHFS_HIDETASKBAR | SHFS_SHOWSIPBUTTON |
- SHFS_SHOWSTARTICON);
- }
- else
- {
- SHFullScreen(g_Wnd, SHFS_SHOWTASKBAR | SHFS_SHOWSIPBUTTON |
- SHFS_SHOWSTARTICON);
- }
- }
- return 0;
-}
-#endif /* MYWINCE */
-
-/*****************************************************************************/
-LRESULT CALLBACK
-WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- switch (message)
- {
- case WM_SETCURSOR:
- return handle_WM_SETCURSOR(hWnd, message, wParam, lParam);
- case 0x0084: /* WinCE don't have this WM_NCHITTEST: */
- return handle_WM_NCHITTEST(hWnd, message, wParam, lParam);
- case WM_MOUSEMOVE:
- return handle_WM_MOUSEMOVE(hWnd, message, wParam, lParam);
- case WM_LBUTTONDOWN:
- return handle_WM_LBUTTONDOWN(hWnd, message, wParam, lParam);
- case WM_LBUTTONUP:
- return handle_WM_LBUTTONUP(hWnd, message, wParam, lParam);
- case WM_RBUTTONDOWN:
- return handle_WM_RBUTTONDOWN(hWnd, message, wParam, lParam);
- case WM_RBUTTONUP:
- return handle_WM_RBUTTONUP(hWnd, message, wParam, lParam);
- case WM_MBUTTONDOWN:
- return handle_WM_MBUTTONDOWN(hWnd, message, wParam, lParam);
- case WM_MBUTTONUP:
- return handle_WM_MBUTTONUP(hWnd, message, wParam, lParam);
- /* some windows compilers don't have these defined like vc6 */
- case 0x020a: /* WM_MOUSEWHEEL: */
- return handle_WM_MOUSEWHEEL(hWnd, message, wParam, lParam);
- case WM_KEYDOWN:
- case WM_KEYUP:
- case WM_SYSKEYDOWN:
- case WM_SYSKEYUP:
- return handle_WM_KEY(hWnd, message, wParam, lParam);
- case WM_CHAR:
- case WM_DEADCHAR:
- case WM_SYSCHAR:
- case WM_SYSDEADCHAR:
- break;
- case WM_PAINT:
- return handle_WM_PAINT(hWnd, message, wParam, lParam);
- case WM_DESTROY:
- PostQuitMessage(0);
- break;
- case WM_APP + 1:
- case WM_TIMER:
- check_sck();
- break;
- case WM_SIZE:
- return handle_WM_SIZE(hWnd, message, wParam, lParam);
- case 532: /* not defined in wince WM_SIZING: */
- return handle_WM_SIZING(hWnd, message, wParam, lParam);
- case WM_HSCROLL:
- return handle_WM_HSCROLL(hWnd, message, wParam, lParam);
- case WM_VSCROLL:
- return handle_WM_VSCROLL(hWnd, message, wParam, lParam);
-#ifdef MYWINCE
- case WM_SETTINGCHANGE:
- return handle_WM_SETTINGCHANGE(hWnd, message, wParam, lParam);
-#endif /* MYWINCE */
- case WM_SETFOCUS:
- mi_check_modifier();
-#ifdef MYWINCE
- if (g_sip_up)
- {
- SHSipPreference(hWnd, SIP_UP);
- }
-#endif
- return DefWindowProc(hWnd, message, wParam, lParam);
- default:
- return DefWindowProc(hWnd, message, wParam, lParam);
- }
- return 0;
-}
-
-/*****************************************************************************/
-static HRGN
-mi_clip(HDC dc)
-{
- HRGN rgn;
-
- rgn = CreateRectRgn(g_clip_left + g_xoff - g_xscroll,
- g_clip_top + g_yoff - g_yscroll,
- g_clip_right + g_xoff - g_xscroll,
- g_clip_bottom + g_yoff - g_yscroll);
- SelectClipRgn(dc, rgn);
- IntersectClipRect(dc, g_wnd_clip.left + g_xoff, g_wnd_clip.top + g_yoff,
- g_wnd_clip.right + g_xoff, g_wnd_clip.bottom + g_yoff);
- return rgn;
-}
-
-/*****************************************************************************/
-static void
-mi_show_error(char * caption)
-{
- LPVOID lpMsgBuf;
- TCHAR lcaption[512];
-
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &lpMsgBuf, 0, NULL);
-#ifdef WITH_DEBUG
- printf(lpMsgBuf);
-#else /* WITH_DEBUG */
- str_to_uni(lcaption, caption);
- MessageBox(g_Wnd, (LPTSTR) lpMsgBuf, lcaption,
- MB_OK | MB_ICONINFORMATION);
-#endif /* WITH_DEBUG */
- LocalFree(lpMsgBuf);
-}
-
-/*****************************************************************************/
-void
-mi_invalidate(int x, int y, int cx, int cy)
-{
- HDC dc;
- HDC maindc;
- HGDIOBJ save;
- HRGN rgn;
- int dstx;
- int dsty;
-
- maindc = GetWindowDC(g_Wnd);
- dc = CreateCompatibleDC(maindc);
- if (dc == 0)
- {
- mi_show_error("CreateCompatibleDC failed in mi_invalidate");
- }
- save = SelectObject(dc, g_bs_bitmap);
- dstx = (x + g_xoff) - g_xscroll;
- dsty = (y + g_yoff) - g_yscroll;
- rgn = mi_clip(maindc);
- BitBlt(maindc, dstx, dsty, cx, cy, dc, x, y, SRCCOPY);
- SelectObject(dc, save);
- DeleteDC(dc);
- ReleaseDC(g_Wnd, maindc);
- DeleteObject(rgn);
-}
-
-/*****************************************************************************/
-int
-mi_create_bs(void)
-{
- HBITMAP bitmap;
- BITMAPINFO bi;
- HDC maindc;
-
- ZeroMemory(&bi, sizeof(bi));
- bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
- bi.bmiHeader.biWidth = g_width;
- bi.bmiHeader.biHeight = -g_height;
- bi.bmiHeader.biPlanes = 1;
- bi.bmiHeader.biBitCount = 32;
- bi.bmiHeader.biCompression = BI_RGB;
- maindc = GetWindowDC(g_Wnd);
- g_bs_bitmap = CreateDIBSection(maindc, &bi, DIB_RGB_COLORS, (void **) &g_bs, 0, 0);
- ReleaseDC(g_Wnd, maindc);
- g_bs_bpp = 32;
- g_bs_Bpp = 4;
- if (g_bs_bitmap != 0)
- {
- //FillMemory(g_bs, g_width * g_height * 4, 0xff);
- ZeroMemory(g_bs, g_width * g_height * 4);
- UpdateWindow(g_Wnd);
- return 1;
- }
- return 0;
-}
-
-/*****************************************************************************/
-/* returns non zero if ok */
-int
-mi_create_window(void)
-{
- RECT rc;
- WNDCLASS wc;
- TCHAR classname[512];
- TCHAR caption[512];
- DWORD style;
- int x;
- int y;
- int w;
- int h;
-
- if (g_Wnd != 0 || g_Instance != 0)
- {
- return 0;
- }
- g_Instance = GetModuleHandle(NULL);
- ZeroMemory(&wc, sizeof(wc));
- wc.lpfnWndProc = WndProc; /* points to window procedure */
- /* name of window class */
- str_to_uni(classname, "rdesktop");
- wc.lpszClassName = classname;
- str_to_uni(caption, "WinRDesktop");
- /* Register the window class. */
- if (!RegisterClass(&wc))
- {
- return 0; /* Failed to register window class */
- }
- rc.left = 0;
- rc.right = rc.left + UI_MIN(g_width, g_screen_width);
- rc.top = 0;
- rc.bottom = rc.top + UI_MIN(g_height, g_screen_height);
-#ifdef MYWINCE
- SHInitExtraControls();
- x = CW_USEDEFAULT;
- y = CW_USEDEFAULT;
- w = CW_USEDEFAULT;
- h = CW_USEDEFAULT;
- style = WS_VISIBLE;
- if (g_fullscreen)
- {
- x = 0;
- y = 0;
- w = g_screen_width;
- h = g_screen_height;
- }
-#else /* MYWINCE */
- if (g_fullscreen)
- {
- style = WS_POPUP;
- }
- else
- {
- style = WS_OVERLAPPED | WS_CAPTION | WS_POPUP | WS_MINIMIZEBOX |
- WS_SYSMENU | WS_SIZEBOX | WS_MAXIMIZEBOX;
- }
- if (g_screen_width < g_width || g_screen_height < g_height)
- {
- style |= WS_HSCROLL | WS_VSCROLL;
- }
- AdjustWindowRectEx(&rc, style, 0, 0);
- x = CW_USEDEFAULT;
- y = CW_USEDEFAULT;
- w = rc.right - rc.left;
- h = rc.bottom - rc.top;
-#endif /* MYWINCE */
- g_Wnd = CreateWindow(wc.lpszClassName, caption,
- style, x, y, w, h,
- (HWND) NULL, (HMENU) NULL, g_Instance,
- (LPVOID) NULL);
- g_clip_left = 0;
- g_clip_top = 0;
- g_clip_right = g_clip_left + g_width;
- g_clip_bottom = g_clip_top + g_height;
- if (g_workarea)
- {
- ShowWindow(g_Wnd, SW_SHOWMAXIMIZED);
- }
- else
- {
- ShowWindow(g_Wnd, SW_SHOWNORMAL);
- }
-
-#ifdef MYWINCE
- if (g_fullscreen)
- {
- SHFullScreen(g_Wnd, SHFS_HIDETASKBAR | SHFS_SHOWSIPBUTTON |
- SHFS_SHOWSTARTICON);
- }
- else
- {
- SHFullScreen(g_Wnd, SHFS_SHOWTASKBAR | SHFS_SHOWSIPBUTTON |
- SHFS_SHOWSTARTICON);
- }
-#endif /* MYWINCE */
-
- /* WinCE doesn't have WSAAsyncSelect */
-#ifdef MYWINCE
- SetTimer(g_Wnd, 1, 1000 / 60, 0); /* 60 per second */
-#else /* MYWINCE */
- WSAAsyncSelect(g_tcp_sck, g_Wnd, WM_APP + 1, FD_READ);
- SetTimer(g_Wnd, 1, 333, 0);
-#endif /* MYWINCE */
- return 1;
-}
-
-/*****************************************************************************/
-int
-mi_main_loop(void)
-{
- MSG msg;
-
- while (GetMessage(&msg, NULL, 0, 0))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- return msg.wParam;
-}
-
-/*****************************************************************************/
-void
-mi_warning(char * msg)
-{
-}
-
-/*****************************************************************************/
-void
-mi_paint_rect(char * data, int width, int height, int x, int y, int cx, int cy)
-{
- HBITMAP bitmap;
- BITMAPINFO bi;
- HDC dc;
- HDC maindc;
- HGDIOBJ save;
- HRGN rgn;
- void * bits;
- int i;
- int j;
- int colour;
- int red;
- int green;
- int blue;
-
- ZeroMemory(&bi, sizeof(bi));
- bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
- bi.bmiHeader.biWidth = width;
- bi.bmiHeader.biHeight = -height;
- bi.bmiHeader.biPlanes = 1;
- bi.bmiHeader.biBitCount = 32;
- bi.bmiHeader.biCompression = BI_RGB;
- maindc = GetWindowDC(g_Wnd);
- bitmap = CreateDIBSection(maindc, &bi, DIB_RGB_COLORS, (void **) &bits, 0, 0);
- if (bitmap == 0)
- {
- mi_show_error("CreateDIBSection failed");
- }
-
- if (g_server_depth == 8)
- {
- for (i = cy - 1; i >= 0; i--)
- {
- for (j = cx - 1; j >= 0; j--)
- {
- colour = ((unsigned char*)data)[i * cx + j];
- red = (pal_entries[colour & 0xff] & 0xff0000) >> 16;
- green = (pal_entries[colour & 0xff] & 0xff00) >> 8;
- blue = pal_entries[colour & 0xff] & 0xff;
- MAKE_COLOUR32(colour, red, green, blue);
- ((unsigned int*)bits)[i * cx + j] = colour;
- }
- }
- }
- else if (g_server_depth == 15)
- {
- for (i = cy - 1; i >= 0; i--)
- {
- for (j = cx - 1; j >= 0; j--)
- {
- colour = ((unsigned short*)data)[i * cx + j];
- SPLIT_COLOUR15(colour, red, green, blue);
- MAKE_COLOUR32(colour, red, green, blue);
- ((unsigned int*)bits)[i * cx + j] = colour;
- }
- }
- }
- else if (g_server_depth == 16)
- {
- for (i = cy - 1; i >= 0; i--)
- {
- for (j = cx - 1; j >= 0; j--)
- {
- colour = ((unsigned short*)data)[i * cx + j];
- SPLIT_COLOUR16(colour, red, green, blue);
- MAKE_COLOUR32(colour, red, green, blue);
- ((unsigned int*)bits)[i * cx + j] = colour;
- }
- }
- }
- dc = CreateCompatibleDC(maindc);
- if (dc == 0)
- {
- mi_show_error("CreateCompatibleDC failed");
- }
- save = SelectObject(dc, bitmap);
- rgn = mi_clip(maindc);
- BitBlt(maindc, x + g_xoff - g_xscroll, y + g_yoff - g_yscroll, cx, cy, dc,
- 0, 0, SRCCOPY);
- SelectObject(dc, save);
- DeleteObject(bitmap);
- DeleteDC(dc);
- ReleaseDC(g_Wnd, maindc);
- DeleteObject(rgn);
-
-}
-
-/*****************************************************************************/
-static int
-mi_process_a_param(char * param1, int state)
-{
- char * p;
-
- if (state == 0)
- {
- if (strcmp(param1, "-g") == 0 || strcmp(param1, "geometry") == 0)
- {
- state = 1;
- }
- if (strcmp(param1, "-t") == 0 || strcmp(param1, "port") == 0)
- {
- state = 2;
- }
- if (strcmp(param1, "-a") == 0 || strcmp(param1, "bpp") == 0)
- {
- state = 3;
- }
- if (strcmp(param1, "-f") == 0 || strcmp(param1, "fullscreen") == 0)
- {
- g_fullscreen = 1;
- }
- if (strcmp(param1, "-u") == 0 || strcmp(param1, "username") == 0)
- {
- state = 5;
- }
- if (strcmp(param1, "-p") == 0 || strcmp(param1, "password") == 0)
- {
- state = 6;
- }
- if (strcmp(param1, "-d") == 0 || strcmp(param1, "domain") == 0)
- {
- state = 7;
- }
- if (strcmp(param1, "-s") == 0 || strcmp(param1, "shell") == 0)
- {
- state = 8;
- }
- if (strcmp(param1, "-c") == 0 || strcmp(param1, "directory") == 0)
- {
- state = 9;
- }
- if (strcmp(param1, "-n") == 0 || strcmp(param1, "hostname") == 0)
- {
- state = 10;
- }
- }
- else
- {
- if (state == 1) /* -g */
- {
- state = 0;
- if (strcmp(param1, "workarea") == 0)
- {
- g_workarea = 1;
- return state;
- }
- g_width = strtol(param1, &p, 10);
- if (g_width <= 0)
- {
- mi_error("invalid geometry\r\n");
- }
- if (*p == 'x')
- {
- g_height = strtol(p + 1, &p, 10);
- }
- if (g_height <= 0)
- {
- mi_error("invalid geometry\r\n");
- }
- g_width_height_set = 1;
- }
- if (state == 2) /* -t */
- {
- state = 0;
- g_tcp_port_rdp = atol(param1);
- }
- if (state == 3) /* -a */
- {
- state = 0;
- g_server_depth = atol(param1);
- if (g_server_depth != 8 && g_server_depth != 15 &&
- g_server_depth != 16 && g_server_depth != 24)
- {
- mi_error("invalid server bpp\r\n");
- }
- }
- if (state == 5) /* -u */
- {
- state = 0;
- strcpy(g_username, param1);
- }
- if (state == 6) /* -p */
- {
- state = 0;
- strcpy(g_password, param1);
- }
- if (state == 7) /* -d */
- {
- state = 0;
- strcpy(g_domain, param1);
- }
- if (state == 8) /* -s */
- {
- state = 0;
- strcpy(g_shell, param1);
- }
- if (state == 9) /* -c */
- {
- state = 0;
- strcpy(g_directory, param1);
- }
- if (state == 10) /* -n */
- {
- state = 0;
- strcpy(g_hostname, param1);
- }
- }
- return state;
-}
-
-/*****************************************************************************/
-static int
-mi_post_param(void)
-{
- /* after parameters */
- if (g_fullscreen)
- {
- g_xoff = 0;
- g_yoff = 0;
- if (!g_width_height_set)
- {
- g_width = g_screen_width;
- g_height = g_screen_height;
- }
- }
- else if (g_workarea)
- {
-#ifdef MYWINCE
- g_xoff = 0;
- g_yoff = 0;
- g_width = g_screen_width;
- g_height = g_screen_height - 26; /* start menu size is 26 */
-#else /* MYWINCE */
- g_xoff = GetSystemMetrics(SM_CXEDGE) * 2;
- g_yoff = GetSystemMetrics(SM_CYCAPTION) +
- GetSystemMetrics(SM_CYEDGE) * 2;
- g_width = g_screen_width;
- g_height = g_screen_height;
- g_height = (g_height - g_yoff) - g_xoff - 20; /* todo */
-#endif /* MYWINCE */
- g_width_height_set = 1;
- }
- else
- {
-#ifdef MYWINCE
- g_xoff = 0;
- g_yoff = 0;
-#else /* MYWINCE */
- g_xoff = GetSystemMetrics(SM_CXEDGE) * 2;
- g_yoff = GetSystemMetrics(SM_CYCAPTION) +
- GetSystemMetrics(SM_CYEDGE) * 2;
-#endif /* MYWINCE */
- }
- g_width = g_width & (~3);
- return 1;
-}
-
-/*****************************************************************************/
-static int
-mi_check_config_file(void)
-{
- HANDLE fd;
- DWORD count;
- TCHAR filename[256];
- char buffer[256];
- char vname[256];
- char value[256];
- int index;
- int mode;
- int vnameindex;
- int valueindex;
- int state;
- int rv;
-
- rv = 0;
- mode = 0;
- vnameindex = 0;
- valueindex = 0;
- vname[vnameindex] = 0;
- value[valueindex] = 0;
-#ifdef MYWINCE
- str_to_uni(filename, "\\My Documents\\winrdesktop.ini");
-#else /* MYWINCE */
- str_to_uni(filename, ".\\winrdesktop.ini");
-#endif /* MYWINCE */
- fd = CreateFile(filename, GENERIC_READ,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- count = 255;
- while (ReadFile(fd, buffer, count, &count, NULL))
- {
- if (count == 0)
- {
- break;
- }
- buffer[count] = 0;
- index = 0;
- while (index < (int) count)
- {
- if (buffer[index] == '=')
- {
- mode = 1;
- }
- else if (buffer[index] == 10 || buffer[index] == 13)
- {
- mode = 0;
- vname[vnameindex] = 0;
- value[valueindex] = 0;
- if (strlen(vname) > 0 || strlen(value) > 0)
- {
- if (strcmp(vname, "server") == 0)
- {
- strcpy(g_servername, value);
- rv = 1;
- }
- else
- {
- state = mi_process_a_param(vname, 0);
- mi_process_a_param(value, state);
- }
- }
- vnameindex = 0;
- valueindex = 0;
- }
- else if (mode == 0)
- {
- vname[vnameindex] = buffer[index];
- vnameindex++;
- }
- else
- {
- value[valueindex] = buffer[index];
- valueindex++;
- }
- index++;
- }
- count = 255;
- }
- CloseHandle(fd);
- if (rv)
- {
- mi_post_param();
- }
- return rv;
-}
-
-/*****************************************************************************/
-/* process the command line parameters */
-/* returns boolean, non zero is ok */
-static int
-mi_process_cl(LPTSTR lpCmdLine)
-{
- char param[256];
- char param1[256];
-#ifndef MYWINCE
- TCHAR l_username[256];
-#endif
- DWORD size;
- int len;
- int i;
- int i1;
- int state;
-
- strcpy(g_hostname, "test");
- strcpy(g_username, "pda");
- /* get username and convert it from unicode */
- size = 255;
-#ifndef MYWINCE
- /* WinCE doesn't have GetUserName */
- if (GetUserName(l_username, &size))
- {
- for (i = size; i >= 0; i--)
- {
- g_username[i] = (char) l_username[i];
- }
- g_username[size] = 0;
- }
- else
- {
- mi_show_error("GetUserName");
- }
-#endif /* MYWINCE */
- /* get computer name */
- if (gethostname(g_hostname, 255) != 0)
- {
- mi_show_error("gethostname");
- }
- /* defaults */
- strcpy(g_servername, "127.0.0.1");
- g_server_depth = 8;
- g_screen_width = GetSystemMetrics(SM_CXSCREEN);
- g_screen_height = GetSystemMetrics(SM_CYSCREEN);
- /* process parameters */
- i1 = 0;
- state = 0;
- len = lstrlen(lpCmdLine);
- if (len == 0)
- {
- return mi_check_config_file();
- }
- for (i = 0; i < len; i++)
- {
- if (lpCmdLine[i] != 32 && lpCmdLine[i] != 9) /* space or tab */
- {
- param[i1] = (char) lpCmdLine[i];
- i1++;
- }
- else
- {
- param[i1] = 0;
- i1 = 0;
- strcpy(param1, param);
- state = mi_process_a_param(param1, state);
- strcpy(g_servername, param1);
- }
- }
- if (i1 > 0)
- {
- param[i1] = 0;
- strcpy(param1, param);
- state = mi_process_a_param(param1, state);
- strcpy(g_servername, param1);
- }
- if (state == 0)
- {
- mi_post_param();
- }
- return (state == 0);
-}
-
-/*****************************************************************************/
-/* display the command line options available */
-static void
-mi_show_params(void)
-{
- char text1[512 * 4];
- TCHAR textx[512 * 4];
- TCHAR lcaption[64];
-
- strcpy(text1, "");
- strcat(text1, "WinRDesktop - an RDP client based on rdesktop\r\n");
- strcat(text1, "You can't run this application without " );
- strcat(text1, "correct parameters\r\n");
- strcat(text1, "\r\n");
- strcat(text1, "command line options\r\n");
- strcat(text1, "\r\n");
- strcat(text1, "WinRDesktop [-g widthxheight] [-t port] [-a bpp]\r\n");
- strcat(text1, " [-f] [-u username] [-p password] [-d domain]\r\n");
- strcat(text1, " [-s shell] [-c working directory] [-n host name]\r\n");
- strcat(text1, " server-name-or-ip\r\n");
- strcat(text1, "\r\n");
- strcat(text1, "You can use a config file in the current directory\r\n");
- strcat(text1, "called WinRDesktop.ini\r\n");
- strcat(text1, "The file should look like this...\r\n");
- strcat(text1, "[main]\r\n");
- strcat(text1, "server=192.168.1.1\r\n");
- strcat(text1, "port=3389\r\n");
- strcat(text1, "username=user1\r\n");
- strcat(text1, "password=password1\r\n");
- strcat(text1, "bpp=16\r\n");
- strcat(text1, "geometry=800x600\r\n");
-#ifdef WITH_DEBUG
- printf(text1);
-#else /* WITH_DEBUG */
- str_to_uni(lcaption, "WinRDesktop");
- str_to_uni(textx, text1);
- MessageBox(g_Wnd, textx, lcaption, MB_OK);
-#endif /* WITH_DEBUG */
-}
-
-#ifdef WITH_DEBUG
-/*****************************************************************************/
-int
-main(int argc, char ** argv)
-{
- WSADATA d;
-
- WSAStartup(MAKEWORD(2, 0), &d);
- if (!mi_process_cl(argv[0]))
- {
- mi_show_params();
- WSACleanup();
- return 0;
- }
- return ui_main();
-}
-#else /* WITH_DEBUG */
-/*****************************************************************************/
-int WINAPI
-WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
- LPTSTR lpCmdLine, int nCmdShow)
-{
- WSADATA d;
-
- WSAStartup(MAKEWORD(2, 0), &d);
- if (!mi_process_cl(lpCmdLine))
- {
- mi_show_params();
- WSACleanup();
- return 0;
- }
- return ui_main();
-}
-#endif /* WITH_DEBUG */
-
-/*****************************************************************************/
-void
-mi_begin_update(void)
-{
-}
-
-/*****************************************************************************/
-void
-mi_end_update(void)
-{
-}
-
-/*****************************************************************************/
-void
-mi_fill_rect(int x, int y, int cx, int cy, int colour)
-{
- HBRUSH brush;
- RECT rect;
- HDC maindc;
- HRGN rgn;
- int red;
- int green;
- int blue;
-
- red = (colour & 0xff0000) >> 16;
- green = (colour & 0xff00) >> 8;
- blue = colour & 0xff;
- maindc = GetWindowDC(g_Wnd);
- rgn = mi_clip(maindc);
- brush = CreateSolidBrush(RGB(red, green, blue));
- rect.left = x + g_xoff - g_xscroll;
- rect.top = y + g_yoff - g_yscroll;
- rect.right = rect.left + cx;
- rect.bottom = rect.top + cy;
- FillRect(maindc, &rect, brush);
- DeleteObject(brush);
- ReleaseDC(g_Wnd, maindc);
- DeleteObject(rgn);
-}
-
-/*****************************************************************************/
-void
-mi_line(int x1, int y1, int x2, int y2, int colour)
-{
- HPEN pen;
- HDC maindc;
- HGDIOBJ save;
- HRGN rgn;
- int red;
- int green;
- int blue;
-
- red = (colour & 0xff0000) >> 16;
- green = (colour & 0xff00) >> 8;
- blue = colour & 0xff;
- maindc = GetWindowDC(g_Wnd);
- rgn = mi_clip(maindc);
- pen = CreatePen(PS_SOLID, 0, RGB(red, green, blue));
- save = SelectObject(maindc, pen);
- MoveToEx(maindc, x1 + g_xoff - g_xscroll, y1 + g_yoff - g_yscroll, 0);
- LineTo(maindc, x2 + g_xoff - g_xscroll, y2 + g_yoff - g_yscroll);
- SelectObject(maindc, save);
- DeleteObject(pen);
- ReleaseDC(g_Wnd, maindc);
- DeleteObject(rgn);
-}
-
-/*****************************************************************************/
-void
-mi_screen_copy(int x, int y, int cx, int cy, int srcx, int srcy)
-{
- RECT rect;
- RECT clip_rect;
- RECT draw_rect;
- HRGN rgn;
- int ok_to_ScrollWindowEx;
-
- /* WinCE can't scroll in 2 directions at once */
-#ifdef MYWINCE
- ok_to_ScrollWindowEx = cx == 0 || cy == 0;
-#else /* MYWINCE */
- ok_to_ScrollWindowEx = 1;
-#endif /* MYWINCE */
- if (!ok_to_ScrollWindowEx)
- {
- rgn = CreateRectRgn(x - g_xscroll, y - g_yscroll,
- (x - g_xscroll) + cx,
- (y - g_yscroll) + cy);
- InvalidateRgn(g_Wnd, rgn, 0);
- DeleteObject(rgn);
- }
- else
- {
- /* this is all in client coords */
- rect.left = srcx - g_xscroll;
- rect.top = srcy - g_yscroll;
- rect.right = rect.left + cx;
- rect.bottom = rect.top + cy;
- clip_rect.left = g_clip_left - g_xscroll;
- clip_rect.top = g_clip_top - g_yscroll;
- clip_rect.right = g_clip_right - g_xscroll;
- clip_rect.bottom = g_clip_bottom - g_yscroll;
- if (IntersectRect(&draw_rect, &clip_rect, &g_wnd_clip))
- {
- rgn = CreateRectRgn(0, 0, 0, 0);
- ScrollWindowEx(g_Wnd, x - srcx, y - srcy, &rect, &draw_rect,
- rgn, 0, SW_ERASE);
- InvalidateRgn(g_Wnd, rgn, 0);
- DeleteObject(rgn);
- }
- }
-}
-
-/*****************************************************************************/
-void
-mi_set_clip(int x, int y, int cx, int cy)
-{
- g_clip_left = x;
- g_clip_top = y;
- g_clip_right = g_clip_left + cx;
- g_clip_bottom = g_clip_top + cy;
-}
-
-/*****************************************************************************/
-void
-mi_reset_clip(void)
-{
- g_clip_left = 0;
- g_clip_top = 0;
- g_clip_right = g_clip_left + g_width;
- g_clip_bottom = g_clip_top + g_height;
-}
-
-/*****************************************************************************/
-void *
-mi_create_cursor(unsigned int x, unsigned int y,
- int width, int height,
- unsigned char * andmask, unsigned char * xormask)
-{
-#ifdef MYWINCE
- return (void *) 1;
-#else /* MYWINCE */
- HCURSOR hCur;
-
- hCur = CreateCursor(g_Instance, x, y, width, height, andmask, xormask);
- if (hCur == 0)
- {
- hCur = LoadCursor(NULL, IDC_ARROW);
- }
- return hCur;
-#endif /* MYWINCE */
-}
-
-/*****************************************************************************/
-void
-mi_destroy_cursor(void * cursor)
-{
-#ifdef MYWINCE
-#else /* MYWINCE */
- if (g_cursor == cursor)
- {
- g_cursor = 0;
- }
- DestroyCursor(cursor);
-#endif /* MYWINCE */
-}
-
-/*****************************************************************************/
-void
-mi_set_cursor(void * cursor)
-{
-#ifdef MYWINCE
-#else /* MYWINCE */
- g_cursor = cursor;
- SetCursor(g_cursor);
-#endif /* MYWINCE */
-}
-
-/*****************************************************************************/
-void
-mi_set_null_cursor(void)
-{
-}
-
+/* -*- c-basic-offset: 8 -*- + rdesktop: A Remote Desktop Protocol client. + win32 calls + Copyright (C) Jay Sorg 2006 + + 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. +*/ + +#ifdef _WIN32_WCE +#define MYWINCE +#endif + +#include <winsock2.h> /* winsock2.h first */ +#include <windows.h> +#ifdef MYWINCE +#include <aygshell.h> /* aygshell.lib */ +#endif /* MYWINCE */ +#include <winuser.h> +#include <stdio.h> +#include "uimain.h" + +extern char g_username[]; +extern char g_hostname[]; +extern char g_servername[]; +extern char g_password[]; +extern char g_shell[]; +extern char g_directory[]; +extern char g_domain[]; +extern int g_width; +extern int g_height; +extern int g_tcp_sck; +extern int g_server_depth; +extern int g_tcp_port_rdp; /* in tcp.c */ +extern int pal_entries[]; +extern char * g_bs; +extern int g_bs_bpp; +extern int g_bs_Bpp; + +static HWND g_Wnd = 0; +static HINSTANCE g_Instance = 0; +static HCURSOR g_cursor = 0; +static HBITMAP g_bs_bitmap = 0; +static int g_block = 0; +static int g_xoff = 0; /* offset from window to client coords */ +static int g_yoff = 0; +static int g_xscroll = 0; /* current scroll position */ +static int g_yscroll = 0; +static int g_screen_width = 0; +static int g_screen_height = 0; +static int g_wnd_cwidth = 0; /* set from WM_SIZE */ +static int g_wnd_cheight = 0; +static int g_fullscreen = 0; +static int g_workarea = 0; +static int g_mousex = 0; /* in client coords */ +static int g_mousey = 0; +static int g_width_height_set = 0; + +static int g_clip_left = 0; +static int g_clip_top = 0; +static int g_clip_right = 800; +static int g_clip_bottom = 600; +static RECT g_wnd_clip; /* this client area of whats actually visable */ + /* set from WM_SIZE */ +#ifdef MYWINCE +static int g_sip_up = 0; +#endif + +/*****************************************************************************/ +static void +str_to_uni(TCHAR * sizex, char * size1) +{ + int len; + int i; + + len = strlen(size1); + for (i = 0; i < len; i++) + { + sizex[i] = size1[i]; + } + sizex[len] = 0; +} + +/*****************************************************************************/ +/* returns non zero if it processed something */ +static int +check_sck(void) +{ + fd_set rfds; + struct timeval tm; + int count; + int rv; + + rv = 0; + if (g_block == 0) + { + g_block = 1; + /* see if there really is data */ + FD_ZERO(&rfds); + FD_SET((unsigned int)g_tcp_sck, &rfds); + ZeroMemory(&tm, sizeof(tm)); + count = select(g_tcp_sck + 1, &rfds, 0, 0, &tm); + if (count > 0) + { + if (ui_read_wire()) + { + rv = 1; + } + else + { + PostQuitMessage(0); + } + } + g_block = 0; + } + return rv; +} + +/*****************************************************************************/ +void +mi_error(char * msg) +{ +#ifdef WITH_DEBUG + printf(msg); +#else /* WITH_DEBUG */ + TCHAR lmsg[512]; + TCHAR ltitle[512]; + + str_to_uni(lmsg, msg); + str_to_uni(ltitle, "Error"); + MessageBox(g_Wnd, lmsg, ltitle, MB_OK); +#endif /* WITH_DEBUG */ +} + +/*****************************************************************************/ +static int +get_scan_code_from_ascii(int code) +{ + int rv; + + rv = 0; + switch (code & 0xff) + { + case 0x30: rv = 0x0b; break; // 0 + case 0x31: rv = 0x02; break; // 1 + case 0x32: rv = 0x03; break; // 2 + case 0x33: rv = 0x04; break; // 3 + case 0x34: rv = 0x05; break; // 4 + case 0x35: rv = 0x06; break; // 5 + case 0x36: rv = 0x07; break; // 6 + case 0x37: rv = 0x08; break; // 7 + case 0x38: rv = 0x09; break; // 8 + case 0x39: rv = 0x0a; break; // 9 + + case 0xbd: rv = 0x0c; break; // - + case 0xbb: rv = 0x0d; break; // = + case 0x08: rv = 0x0e; break; // backspace + case 0x09: rv = 0x0f; break; // tab + case 0xdb: rv = 0x1b; break; // ] + case 0xdd: rv = 0x1a; break; // [ + case 0x14: rv = 0x3a; break; // capslock + case 0xba: rv = 0x27; break; // ; + case 0xde: rv = 0x28; break; // ' + case 0x10: rv = 0x2a; break; // shift + case 0xbc: rv = 0x33; break; // , + case 0xbe: rv = 0x34; break; // . + case 0xbf: rv = 0x35; break; // / + case 0x0d: rv = 0x1c; break; // enter + case 0x27: rv = 0x4d; break; // arrow right + case 0x25: rv = 0x4b; break; // arrow left + case 0x26: rv = 0x48; break; // arrow up + case 0x28: rv = 0x50; break; // arrow down + case 0x20: rv = 0x39; break; // space + case 0xdc: rv = 0x2b; break; // backslash + case 0xc0: rv = 0x29; break; // ` + case 0x11: rv = 0x1d; break; // ctl + + case 0x41: rv = 0x1e; break; // a + case 0x42: rv = 0x30; break; // b + case 0x43: rv = 0x2e; break; // c + case 0x44: rv = 0x20; break; // d + case 0x45: rv = 0x12; break; // e + case 0x46: rv = 0x21; break; // f + case 0x47: rv = 0x22; break; // g + case 0x48: rv = 0x23; break; // h + case 0x49: rv = 0x17; break; // i + case 0x4a: rv = 0x24; break; // j + case 0x4b: rv = 0x25; break; // k + case 0x4c: rv = 0x26; break; // l + case 0x4d: rv = 0x32; break; // m + case 0x4e: rv = 0x31; break; // n + case 0x4f: rv = 0x18; break; // o + case 0x50: rv = 0x19; break; // p + case 0x51: rv = 0x10; break; // q + case 0x52: rv = 0x13; break; // r + case 0x53: rv = 0x1f; break; // s + case 0x54: rv = 0x14; break; // t + case 0x55: rv = 0x16; break; // u + case 0x56: rv = 0x2f; break; // v + case 0x57: rv = 0x11; break; // w + case 0x58: rv = 0x2d; break; // x + case 0x59: rv = 0x15; break; // y + case 0x5a: rv = 0x2c; break; // z + } + return rv; +} + +/*****************************************************************************/ +static void +mi_scroll(int dx, int dy) +{ + HRGN rgn; + + rgn = CreateRectRgn(0, 0, 0, 0); + ScrollWindowEx(g_Wnd, dx, dy, 0, 0, rgn, 0, SW_ERASE); + InvalidateRgn(g_Wnd, rgn, 0); + DeleteObject(rgn); +} + +/*****************************************************************************/ +int +mi_read_keyboard_state(void) +{ + short keydata; + int code; + + code = 0; + keydata = GetKeyState(VK_SCROLL); + if (keydata & 0x0001) + { + code |= 1; + } + keydata = GetKeyState(VK_NUMLOCK); + if (keydata & 0x0001) + { + code |= 2; + } + keydata = GetKeyState(VK_CAPITAL); + if (keydata & 0x0001) + { + code |= 4; + } + return code; +} + +/*****************************************************************************/ +static void +mi_check_modifier(void) +{ + int code; + + code = mi_read_keyboard_state(); + ui_set_modifier_state(code); +} + +/*****************************************************************************/ +static LRESULT +handle_WM_SETCURSOR(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + if (g_mousex >= g_wnd_clip.left && + g_mousey >= g_wnd_clip.top && + g_mousex < g_wnd_clip.right && + g_mousey < g_wnd_clip.bottom) + { + SetCursor(g_cursor); + } + /* need default behavoir here */ + return DefWindowProc(hWnd, message, wParam, lParam); +} + +/*****************************************************************************/ +static LRESULT +handle_WM_NCHITTEST(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + POINT pt; + + pt.x = LOWORD(lParam); + pt.y = HIWORD(lParam); + if (ScreenToClient(g_Wnd, &pt)) + { + g_mousex = pt.x; + g_mousey = pt.y; + } + return DefWindowProc(hWnd, message, wParam, lParam); +} + +/*****************************************************************************/ +static LRESULT +handle_WM_MOUSEMOVE(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + g_mousex = LOWORD(lParam); + g_mousey = HIWORD(lParam); + ui_mouse_move(g_mousex + g_xscroll, g_mousey + g_yscroll); + return 0; +} + +/*****************************************************************************/ +static LRESULT +handle_WM_LBUTTONDOWN(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + g_mousex = LOWORD(lParam); + g_mousey = HIWORD(lParam); + ui_mouse_button(1, g_mousex + g_xscroll, g_mousey + g_yscroll, 1); + return 0; +} + +/*****************************************************************************/ +static LRESULT +handle_WM_LBUTTONUP(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + g_mousex = LOWORD(lParam); + g_mousey = HIWORD(lParam); + ui_mouse_button(1, g_mousex + g_xscroll, g_mousey + g_yscroll, 0); + return 0; +} + +/*****************************************************************************/ +static LRESULT +handle_WM_RBUTTONDOWN(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + g_mousex = LOWORD(lParam); + g_mousey = HIWORD(lParam); + ui_mouse_button(2, g_mousex + g_xscroll, g_mousey + g_yscroll, 1); + return 0; +} + +/*****************************************************************************/ +static LRESULT +handle_WM_RBUTTONUP(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + g_mousex = LOWORD(lParam); + g_mousey = HIWORD(lParam); + ui_mouse_button(2, g_mousex + g_xscroll, g_mousey + g_yscroll, 0); + return 0; +} + +/*****************************************************************************/ +static LRESULT +handle_WM_MBUTTONDOWN(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + g_mousex = LOWORD(lParam); + g_mousey = HIWORD(lParam); + ui_mouse_button(3, g_mousex + g_xscroll, g_mousey + g_yscroll, 1); + return 0; +} + +/*****************************************************************************/ +static LRESULT +handle_WM_MBUTTONUP(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + g_mousex = LOWORD(lParam); + g_mousey = HIWORD(lParam); + ui_mouse_button(3, g_mousex + g_xscroll, g_mousey + g_yscroll, 0); + return 0; +} + +/*****************************************************************************/ +static LRESULT +handle_WM_MOUSEWHEEL(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + int delta; + + delta = ((signed short)HIWORD(wParam)); /* GET_WHEEL_DELTA_WPARAM(wParam); */ + if (delta > 0) + { + ui_mouse_button(4, 0, 0, 1); + ui_mouse_button(4, 0, 0, 0); + } + else + { + ui_mouse_button(5, 0, 0, 1); + ui_mouse_button(5, 0, 0, 0); + } + return 0; +} + +/*****************************************************************************/ +static LRESULT +handle_WM_KEY(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + int scancode; + int ext; + int down; + + ext = HIWORD(lParam); + scancode = ext; + down = !(ext & 0x8000); + scancode &= 0xff; + if (scancode == 0) + { + scancode = get_scan_code_from_ascii(wParam); + } + ext &= 0x0100; + if (scancode == 0x0045) /* num lock */ + { + ext &= ~0x0100; + } + if (down) + { + ui_key_down(scancode, ext); + } + else + { + ui_key_up(scancode, ext); + } + return 0; +} + +/*****************************************************************************/ +static LRESULT +handle_WM_PAINT(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + PAINTSTRUCT ps; + RECT rect; + HBRUSH brush; + + BeginPaint(hWnd, &ps); + /* paint the area outside the rdp screen with one colour */ + rect = ps.rcPaint; + rect.left = UI_MAX(rect.left, g_width); + if (!IsRectEmpty(&rect)) + { + brush = CreateSolidBrush(RGB(0, 0, 255)); + FillRect(ps.hdc, &rect, brush); + DeleteObject(brush); + } + rect = ps.rcPaint; + rect.top = UI_MAX(rect.top, g_height); + if (!IsRectEmpty(&rect)) + { + brush = CreateSolidBrush(RGB(0, 0, 255)); + FillRect(ps.hdc, &rect, brush); + DeleteObject(brush); + } + rect = ps.rcPaint; + EndPaint(hWnd, &ps); + ui_invalidate(rect.left + g_xscroll, + rect.top + g_yscroll, + (rect.right - rect.left) + 1, + (rect.bottom - rect.top) + 1); + return 0; +} + +/*****************************************************************************/ +static LRESULT +handle_WM_SIZE(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + int oldxscroll; + int oldyscroll; + + if (wParam == SIZE_MINIMIZED) + { + return DefWindowProc(hWnd, message, wParam, lParam); + } + g_wnd_cwidth = LOWORD(lParam); /* client width / height */ + g_wnd_cheight = HIWORD(lParam); + g_wnd_clip.left = 0; + g_wnd_clip.top = 0; + g_wnd_clip.right = g_wnd_clip.left + g_wnd_cwidth; + g_wnd_clip.bottom = g_wnd_clip.top + g_wnd_cheight; + if (g_wnd_cwidth < g_width || g_wnd_cheight < g_height) + { + SetScrollRange(g_Wnd, SB_HORZ, 0, g_width - g_wnd_cwidth, 1); + SetScrollRange(g_Wnd, SB_VERT, 0, g_height - g_wnd_cheight, 1); + } + oldxscroll = g_xscroll; + oldyscroll = g_yscroll; + if (g_wnd_cwidth >= g_width) + { + g_xscroll = 0; + } + else + { + g_xscroll = UI_MIN(g_xscroll, g_width - g_wnd_cwidth); + } + if (g_wnd_cheight >= g_height) + { + g_yscroll = 0; + } + else + { + g_yscroll = UI_MIN(g_yscroll, g_height - g_wnd_cheight); + } + mi_scroll(oldxscroll - g_xscroll, oldyscroll - g_yscroll); + if (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED) + { + /* check the caps, num, and scroll lock here */ + mi_check_modifier(); + } + return 0; +} + +/*****************************************************************************/ +static LRESULT +handle_WM_SIZING(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + LPRECT prect; + int width; + int height; + int style; + + prect = (LPRECT) lParam; /* total window rect */ + width = (prect->right - prect->left) - (g_xoff * 2); + height = (prect->bottom - prect->top) - (g_yoff + g_xoff); + if (height < g_height || width < g_width) + { + style = GetWindowLong(g_Wnd, GWL_STYLE); + if (!(style & WS_HSCROLL)) + { + style |= WS_HSCROLL | WS_VSCROLL; + SetWindowLong(g_Wnd, GWL_STYLE, style); + g_xscroll = 0; + g_yscroll = 0; + SetScrollPos(g_Wnd, SB_HORZ, g_xscroll, 1); + SetScrollPos(g_Wnd, SB_VERT, g_yscroll, 1); + } + } + else if (height >= g_height && width >= g_width) + { + style = GetWindowLong(g_Wnd, GWL_STYLE); + if (style & WS_HSCROLL) + { + style &= ~WS_HSCROLL; + style &= ~WS_VSCROLL; + SetWindowLong(g_Wnd, GWL_STYLE, style); + g_xscroll = 0; + g_yscroll = 0; + } + } + return 0; +} + +/*****************************************************************************/ +static LRESULT +handle_WM_HSCROLL(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + int code; + int oldxscroll; + + code = (int) LOWORD(wParam); /* scroll bar value */ + if (code == SB_LINELEFT) + { + oldxscroll = g_xscroll; + g_xscroll--; + g_xscroll = UI_MAX(g_xscroll, 0); + SetScrollPos(g_Wnd, SB_HORZ, g_xscroll, 1); + mi_scroll(oldxscroll - g_xscroll, 0); + } + else if (code == SB_LINERIGHT) + { + oldxscroll = g_xscroll; + g_xscroll++; + g_xscroll = UI_MIN(g_xscroll, g_width - g_wnd_cwidth); + SetScrollPos(g_Wnd, SB_HORZ, g_xscroll, 1); + mi_scroll(oldxscroll - g_xscroll, 0); + } + else if (code == SB_PAGELEFT) + { + oldxscroll = g_xscroll; + g_xscroll -= g_wnd_cwidth / 2; + g_xscroll = UI_MAX(g_xscroll, 0); + SetScrollPos(g_Wnd, SB_HORZ, g_xscroll, 1); + mi_scroll(oldxscroll - g_xscroll, 0); + } + else if (code == SB_PAGERIGHT) + { + oldxscroll = g_xscroll; + g_xscroll += g_wnd_cwidth / 2; + g_xscroll = UI_MIN(g_xscroll, g_width - g_wnd_cwidth); + SetScrollPos(g_Wnd, SB_HORZ, g_xscroll, 1); + mi_scroll(oldxscroll - g_xscroll, 0); + } + else if (code == SB_BOTTOM) + { + oldxscroll = g_xscroll; + g_xscroll = g_width - g_wnd_cwidth; + SetScrollPos(g_Wnd, SB_HORZ, g_xscroll, 1); + mi_scroll(oldxscroll - g_xscroll, 0); + } + else if (code == SB_TOP) + { + oldxscroll = g_xscroll; + g_xscroll = 0; + SetScrollPos(g_Wnd, SB_HORZ, g_xscroll, 1); + mi_scroll(oldxscroll - g_xscroll, 0); + } + else if (code == SB_THUMBPOSITION) + { + oldxscroll = g_xscroll; + g_xscroll = (signed short) HIWORD(wParam); + SetScrollPos(g_Wnd, SB_HORZ, g_xscroll, 1); + mi_scroll(oldxscroll - g_xscroll, 0); + } + return 0; +} + +/*****************************************************************************/ +static LRESULT +handle_WM_VSCROLL(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + int code; + int oldyscroll; + + code = (int) LOWORD(wParam); /* scroll bar value */ + if (code == SB_LINELEFT) + { + oldyscroll = g_yscroll; + g_yscroll--; + g_yscroll = UI_MAX(g_yscroll, 0); + SetScrollPos(g_Wnd, SB_VERT, g_yscroll, 1); + mi_scroll(0, oldyscroll - g_yscroll); + } + else if (code == SB_LINERIGHT) + { + oldyscroll = g_yscroll; + g_yscroll++; + g_yscroll = UI_MIN(g_yscroll, g_height - g_wnd_cheight); + SetScrollPos(g_Wnd, SB_VERT, g_yscroll, 1); + mi_scroll(0, oldyscroll - g_yscroll); + } + else if (code == SB_PAGELEFT) + { + oldyscroll = g_yscroll; + g_yscroll -= g_wnd_cheight / 2; + g_yscroll = UI_MAX(g_yscroll, 0); + SetScrollPos(g_Wnd, SB_VERT, g_yscroll, 1); + mi_scroll(0, oldyscroll - g_yscroll); + } + else if (code == SB_PAGERIGHT) + { + oldyscroll = g_yscroll; + g_yscroll += g_wnd_cheight / 2; + g_yscroll = UI_MIN(g_yscroll, g_height - g_wnd_cheight); + SetScrollPos(g_Wnd, SB_VERT, g_yscroll, 1); + mi_scroll(0, oldyscroll - g_yscroll); + } + else if (code == SB_BOTTOM) + { + oldyscroll = g_yscroll; + g_yscroll = g_height - g_wnd_cheight; + SetScrollPos(g_Wnd, SB_VERT, g_yscroll, 1); + mi_scroll(0, oldyscroll - g_yscroll); + } + else if (code == SB_TOP) + { + oldyscroll = g_yscroll; + g_yscroll = 0; + SetScrollPos(g_Wnd, SB_VERT, g_yscroll, 1); + mi_scroll(0, oldyscroll - g_yscroll); + } + else if (code == SB_THUMBPOSITION) + { + oldyscroll = g_yscroll; + g_yscroll = (signed short) HIWORD(wParam); + SetScrollPos(g_Wnd, SB_VERT, g_yscroll, 1); + mi_scroll(0, oldyscroll - g_yscroll); + } + return 0; +} + +#ifdef MYWINCE +/*****************************************************************************/ +static LRESULT +handle_WM_SETTINGCHANGE(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + SIPINFO si; + SHMENUBARINFO mb; + int x; + int y; + int w; + int h; + int style; + + ZeroMemory(&si, sizeof(SIPINFO)); + si.cbSize = sizeof(SIPINFO); + SHSipInfo(SPI_GETSIPINFO, lParam, &si, 0); + x = si.rcVisibleDesktop.left; + y = si.rcVisibleDesktop.top; + w = si.rcVisibleDesktop.right - x; + h = si.rcVisibleDesktop.bottom - y; + /* get rid of menu */ + DestroyWindow(SHFindMenuBar(g_Wnd)); + if (si.fdwFlags & SIPF_ON) + { + g_sip_up = 1; /* used for WM_SETFOCUS */ + ZeroMemory(&mb, sizeof(SHMENUBARINFO)); + mb.cbSize = sizeof(SHMENUBARINFO); + mb.hwndParent = g_Wnd; + mb.dwFlags = SHCMBF_EMPTYBAR; + SHCreateMenuBar(&mb); + MoveWindow(g_Wnd, x, y, w, h, FALSE); + SHFullScreen(g_Wnd, SHFS_SHOWTASKBAR | SHFS_SHOWSIPBUTTON | + SHFS_SHOWSTARTICON); + } + else + { + g_sip_up = 0; + if (g_fullscreen) + { + MoveWindow(g_Wnd, 0, 0, g_screen_width, g_screen_height, FALSE); + } + else + { + MoveWindow(g_Wnd, x, y, w, h, FALSE); + } + if ((g_fullscreen && g_width <= g_screen_width && + g_height <= g_screen_height) || + (!g_fullscreen && g_width <= w && g_height <= h)) + { + style = GetWindowLong(g_Wnd, GWL_STYLE); + if (style & WS_HSCROLL) + { + style &= ~WS_HSCROLL; + style &= ~WS_VSCROLL; + SetWindowLong(g_Wnd, GWL_STYLE, style); + g_xscroll = 0; + g_yscroll = 0; + } + } + if (g_fullscreen) + { + SHFullScreen(g_Wnd, SHFS_HIDETASKBAR | SHFS_SHOWSIPBUTTON | + SHFS_SHOWSTARTICON); + } + else + { + SHFullScreen(g_Wnd, SHFS_SHOWTASKBAR | SHFS_SHOWSIPBUTTON | + SHFS_SHOWSTARTICON); + } + } + return 0; +} +#endif /* MYWINCE */ + +/*****************************************************************************/ +LRESULT CALLBACK +WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_SETCURSOR: + return handle_WM_SETCURSOR(hWnd, message, wParam, lParam); + case 0x0084: /* WinCE don't have this WM_NCHITTEST: */ + return handle_WM_NCHITTEST(hWnd, message, wParam, lParam); + case WM_MOUSEMOVE: + return handle_WM_MOUSEMOVE(hWnd, message, wParam, lParam); + case WM_LBUTTONDOWN: + return handle_WM_LBUTTONDOWN(hWnd, message, wParam, lParam); + case WM_LBUTTONUP: + return handle_WM_LBUTTONUP(hWnd, message, wParam, lParam); + case WM_RBUTTONDOWN: + return handle_WM_RBUTTONDOWN(hWnd, message, wParam, lParam); + case WM_RBUTTONUP: + return handle_WM_RBUTTONUP(hWnd, message, wParam, lParam); + case WM_MBUTTONDOWN: + return handle_WM_MBUTTONDOWN(hWnd, message, wParam, lParam); + case WM_MBUTTONUP: + return handle_WM_MBUTTONUP(hWnd, message, wParam, lParam); + /* some windows compilers don't have these defined like vc6 */ + case 0x020a: /* WM_MOUSEWHEEL: */ + return handle_WM_MOUSEWHEEL(hWnd, message, wParam, lParam); + case WM_KEYDOWN: + case WM_KEYUP: + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + return handle_WM_KEY(hWnd, message, wParam, lParam); + case WM_CHAR: + case WM_DEADCHAR: + case WM_SYSCHAR: + case WM_SYSDEADCHAR: + break; + case WM_PAINT: + return handle_WM_PAINT(hWnd, message, wParam, lParam); + case WM_DESTROY: + PostQuitMessage(0); + break; + case WM_APP + 1: + case WM_TIMER: + check_sck(); + break; + case WM_SIZE: + return handle_WM_SIZE(hWnd, message, wParam, lParam); + case 532: /* not defined in wince WM_SIZING: */ + return handle_WM_SIZING(hWnd, message, wParam, lParam); + case WM_HSCROLL: + return handle_WM_HSCROLL(hWnd, message, wParam, lParam); + case WM_VSCROLL: + return handle_WM_VSCROLL(hWnd, message, wParam, lParam); +#ifdef MYWINCE + case WM_SETTINGCHANGE: + return handle_WM_SETTINGCHANGE(hWnd, message, wParam, lParam); +#endif /* MYWINCE */ + case WM_SETFOCUS: + mi_check_modifier(); +#ifdef MYWINCE + if (g_sip_up) + { + SHSipPreference(hWnd, SIP_UP); + } +#endif + return DefWindowProc(hWnd, message, wParam, lParam); + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + return 0; +} + +/*****************************************************************************/ +static HRGN +mi_clip(HDC dc) +{ + HRGN rgn; + + rgn = CreateRectRgn(g_clip_left + g_xoff - g_xscroll, + g_clip_top + g_yoff - g_yscroll, + g_clip_right + g_xoff - g_xscroll, + g_clip_bottom + g_yoff - g_yscroll); + SelectClipRgn(dc, rgn); + IntersectClipRect(dc, g_wnd_clip.left + g_xoff, g_wnd_clip.top + g_yoff, + g_wnd_clip.right + g_xoff, g_wnd_clip.bottom + g_yoff); + return rgn; +} + +/*****************************************************************************/ +static void +mi_show_error(char * caption) +{ + LPVOID lpMsgBuf; + TCHAR lcaption[512]; + + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, 0, NULL); +#ifdef WITH_DEBUG + printf(lpMsgBuf); +#else /* WITH_DEBUG */ + str_to_uni(lcaption, caption); + MessageBox(g_Wnd, (LPTSTR) lpMsgBuf, lcaption, + MB_OK | MB_ICONINFORMATION); +#endif /* WITH_DEBUG */ + LocalFree(lpMsgBuf); +} + +/*****************************************************************************/ +void +mi_invalidate(int x, int y, int cx, int cy) +{ + HDC dc; + HDC maindc; + HGDIOBJ save; + HRGN rgn; + int dstx; + int dsty; + + maindc = GetWindowDC(g_Wnd); + dc = CreateCompatibleDC(maindc); + if (dc == 0) + { + mi_show_error("CreateCompatibleDC failed in mi_invalidate"); + } + save = SelectObject(dc, g_bs_bitmap); + dstx = (x + g_xoff) - g_xscroll; + dsty = (y + g_yoff) - g_yscroll; + rgn = mi_clip(maindc); + BitBlt(maindc, dstx, dsty, cx, cy, dc, x, y, SRCCOPY); + SelectObject(dc, save); + DeleteDC(dc); + ReleaseDC(g_Wnd, maindc); + DeleteObject(rgn); +} + +/*****************************************************************************/ +int +mi_create_bs(void) +{ + HBITMAP bitmap; + BITMAPINFO bi; + HDC maindc; + + ZeroMemory(&bi, sizeof(bi)); + bi.bmiHeader.biSize = sizeof(bi.bmiHeader); + bi.bmiHeader.biWidth = g_width; + bi.bmiHeader.biHeight = -g_height; + bi.bmiHeader.biPlanes = 1; + bi.bmiHeader.biBitCount = 32; + bi.bmiHeader.biCompression = BI_RGB; + maindc = GetWindowDC(g_Wnd); + g_bs_bitmap = CreateDIBSection(maindc, &bi, DIB_RGB_COLORS, (void **) &g_bs, 0, 0); + ReleaseDC(g_Wnd, maindc); + g_bs_bpp = 32; + g_bs_Bpp = 4; + if (g_bs_bitmap != 0) + { + //FillMemory(g_bs, g_width * g_height * 4, 0xff); + ZeroMemory(g_bs, g_width * g_height * 4); + UpdateWindow(g_Wnd); + return 1; + } + return 0; +} + +/*****************************************************************************/ +/* returns non zero if ok */ +int +mi_create_window(void) +{ + RECT rc; + WNDCLASS wc; + TCHAR classname[512]; + TCHAR caption[512]; + DWORD style; + int x; + int y; + int w; + int h; + + if (g_Wnd != 0 || g_Instance != 0) + { + return 0; + } + g_Instance = GetModuleHandle(NULL); + ZeroMemory(&wc, sizeof(wc)); + wc.lpfnWndProc = WndProc; /* points to window procedure */ + /* name of window class */ + str_to_uni(classname, "rdesktop"); + wc.lpszClassName = classname; + str_to_uni(caption, "WinRDesktop"); + /* Register the window class. */ + if (!RegisterClass(&wc)) + { + return 0; /* Failed to register window class */ + } + rc.left = 0; + rc.right = rc.left + UI_MIN(g_width, g_screen_width); + rc.top = 0; + rc.bottom = rc.top + UI_MIN(g_height, g_screen_height); +#ifdef MYWINCE + SHInitExtraControls(); + x = CW_USEDEFAULT; + y = CW_USEDEFAULT; + w = CW_USEDEFAULT; + h = CW_USEDEFAULT; + style = WS_VISIBLE; + if (g_fullscreen) + { + x = 0; + y = 0; + w = g_screen_width; + h = g_screen_height; + } +#else /* MYWINCE */ + if (g_fullscreen) + { + style = WS_POPUP; + } + else + { + style = WS_OVERLAPPED | WS_CAPTION | WS_POPUP | WS_MINIMIZEBOX | + WS_SYSMENU | WS_SIZEBOX | WS_MAXIMIZEBOX; + } + if (g_screen_width < g_width || g_screen_height < g_height) + { + style |= WS_HSCROLL | WS_VSCROLL; + } + AdjustWindowRectEx(&rc, style, 0, 0); + x = CW_USEDEFAULT; + y = CW_USEDEFAULT; + w = rc.right - rc.left; + h = rc.bottom - rc.top; +#endif /* MYWINCE */ + g_Wnd = CreateWindow(wc.lpszClassName, caption, + style, x, y, w, h, + (HWND) NULL, (HMENU) NULL, g_Instance, + (LPVOID) NULL); + g_clip_left = 0; + g_clip_top = 0; + g_clip_right = g_clip_left + g_width; + g_clip_bottom = g_clip_top + g_height; + if (g_workarea) + { + ShowWindow(g_Wnd, SW_SHOWMAXIMIZED); + } + else + { + ShowWindow(g_Wnd, SW_SHOWNORMAL); + } + +#ifdef MYWINCE + if (g_fullscreen) + { + SHFullScreen(g_Wnd, SHFS_HIDETASKBAR | SHFS_SHOWSIPBUTTON | + SHFS_SHOWSTARTICON); + } + else + { + SHFullScreen(g_Wnd, SHFS_SHOWTASKBAR | SHFS_SHOWSIPBUTTON | + SHFS_SHOWSTARTICON); + } +#endif /* MYWINCE */ + + /* WinCE doesn't have WSAAsyncSelect */ +#ifdef MYWINCE + SetTimer(g_Wnd, 1, 1000 / 60, 0); /* 60 per second */ +#else /* MYWINCE */ + WSAAsyncSelect(g_tcp_sck, g_Wnd, WM_APP + 1, FD_READ); + SetTimer(g_Wnd, 1, 333, 0); +#endif /* MYWINCE */ + return 1; +} + +/*****************************************************************************/ +int +mi_main_loop(void) +{ + MSG msg; + + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + return msg.wParam; +} + +/*****************************************************************************/ +void +mi_warning(char * msg) +{ +} + +/*****************************************************************************/ +void +mi_paint_rect(char * data, int width, int height, int x, int y, int cx, int cy) +{ + HBITMAP bitmap; + BITMAPINFO bi; + HDC dc; + HDC maindc; + HGDIOBJ save; + HRGN rgn; + void * bits; + int i; + int j; + int colour; + int red; + int green; + int blue; + + ZeroMemory(&bi, sizeof(bi)); + bi.bmiHeader.biSize = sizeof(bi.bmiHeader); + bi.bmiHeader.biWidth = width; + bi.bmiHeader.biHeight = -height; + bi.bmiHeader.biPlanes = 1; + bi.bmiHeader.biBitCount = 32; + bi.bmiHeader.biCompression = BI_RGB; + maindc = GetWindowDC(g_Wnd); + bitmap = CreateDIBSection(maindc, &bi, DIB_RGB_COLORS, (void **) &bits, 0, 0); + if (bitmap == 0) + { + mi_show_error("CreateDIBSection failed"); + } + + if (g_server_depth == 8) + { + for (i = cy - 1; i >= 0; i--) + { + for (j = cx - 1; j >= 0; j--) + { + colour = ((unsigned char*)data)[i * cx + j]; + red = (pal_entries[colour & 0xff] & 0xff0000) >> 16; + green = (pal_entries[colour & 0xff] & 0xff00) >> 8; + blue = pal_entries[colour & 0xff] & 0xff; + MAKE_COLOUR32(colour, red, green, blue); + ((unsigned int*)bits)[i * cx + j] = colour; + } + } + } + else if (g_server_depth == 15) + { + for (i = cy - 1; i >= 0; i--) + { + for (j = cx - 1; j >= 0; j--) + { + colour = ((unsigned short*)data)[i * cx + j]; + SPLIT_COLOUR15(colour, red, green, blue); + MAKE_COLOUR32(colour, red, green, blue); + ((unsigned int*)bits)[i * cx + j] = colour; + } + } + } + else if (g_server_depth == 16) + { + for (i = cy - 1; i >= 0; i--) + { + for (j = cx - 1; j >= 0; j--) + { + colour = ((unsigned short*)data)[i * cx + j]; + SPLIT_COLOUR16(colour, red, green, blue); + MAKE_COLOUR32(colour, red, green, blue); + ((unsigned int*)bits)[i * cx + j] = colour; + } + } + } + dc = CreateCompatibleDC(maindc); + if (dc == 0) + { + mi_show_error("CreateCompatibleDC failed"); + } + save = SelectObject(dc, bitmap); + rgn = mi_clip(maindc); + BitBlt(maindc, x + g_xoff - g_xscroll, y + g_yoff - g_yscroll, cx, cy, dc, + 0, 0, SRCCOPY); + SelectObject(dc, save); + DeleteObject(bitmap); + DeleteDC(dc); + ReleaseDC(g_Wnd, maindc); + DeleteObject(rgn); + +} + +/*****************************************************************************/ +static int +mi_process_a_param(char * param1, int state) +{ + char * p; + + if (state == 0) + { + if (strcmp(param1, "-g") == 0 || strcmp(param1, "geometry") == 0) + { + state = 1; + } + if (strcmp(param1, "-t") == 0 || strcmp(param1, "port") == 0) + { + state = 2; + } + if (strcmp(param1, "-a") == 0 || strcmp(param1, "bpp") == 0) + { + state = 3; + } + if (strcmp(param1, "-f") == 0 || strcmp(param1, "fullscreen") == 0) + { + g_fullscreen = 1; + } + if (strcmp(param1, "-u") == 0 || strcmp(param1, "username") == 0) + { + state = 5; + } + if (strcmp(param1, "-p") == 0 || strcmp(param1, "password") == 0) + { + state = 6; + } + if (strcmp(param1, "-d") == 0 || strcmp(param1, "domain") == 0) + { + state = 7; + } + if (strcmp(param1, "-s") == 0 || strcmp(param1, "shell") == 0) + { + state = 8; + } + if (strcmp(param1, "-c") == 0 || strcmp(param1, "directory") == 0) + { + state = 9; + } + if (strcmp(param1, "-n") == 0 || strcmp(param1, "hostname") == 0) + { + state = 10; + } + } + else + { + if (state == 1) /* -g */ + { + state = 0; + if (strcmp(param1, "workarea") == 0) + { + g_workarea = 1; + return state; + } + g_width = strtol(param1, &p, 10); + if (g_width <= 0) + { + mi_error("invalid geometry\r\n"); + } + if (*p == 'x') + { + g_height = strtol(p + 1, &p, 10); + } + if (g_height <= 0) + { + mi_error("invalid geometry\r\n"); + } + g_width_height_set = 1; + } + if (state == 2) /* -t */ + { + state = 0; + g_tcp_port_rdp = atol(param1); + } + if (state == 3) /* -a */ + { + state = 0; + g_server_depth = atol(param1); + if (g_server_depth != 8 && g_server_depth != 15 && + g_server_depth != 16 && g_server_depth != 24) + { + mi_error("invalid server bpp\r\n"); + } + } + if (state == 5) /* -u */ + { + state = 0; + strcpy(g_username, param1); + } + if (state == 6) /* -p */ + { + state = 0; + strcpy(g_password, param1); + } + if (state == 7) /* -d */ + { + state = 0; + strcpy(g_domain, param1); + } + if (state == 8) /* -s */ + { + state = 0; + strcpy(g_shell, param1); + } + if (state == 9) /* -c */ + { + state = 0; + strcpy(g_directory, param1); + } + if (state == 10) /* -n */ + { + state = 0; + strcpy(g_hostname, param1); + } + } + return state; +} + +/*****************************************************************************/ +static int +mi_post_param(void) +{ + /* after parameters */ + if (g_fullscreen) + { + g_xoff = 0; + g_yoff = 0; + if (!g_width_height_set) + { + g_width = g_screen_width; + g_height = g_screen_height; + } + } + else if (g_workarea) + { +#ifdef MYWINCE + g_xoff = 0; + g_yoff = 0; + g_width = g_screen_width; + g_height = g_screen_height - 26; /* start menu size is 26 */ +#else /* MYWINCE */ + g_xoff = GetSystemMetrics(SM_CXEDGE) * 2; + g_yoff = GetSystemMetrics(SM_CYCAPTION) + + GetSystemMetrics(SM_CYEDGE) * 2; + g_width = g_screen_width; + g_height = g_screen_height; + g_height = (g_height - g_yoff) - g_xoff - 20; /* todo */ +#endif /* MYWINCE */ + g_width_height_set = 1; + } + else + { +#ifdef MYWINCE + g_xoff = 0; + g_yoff = 0; +#else /* MYWINCE */ + g_xoff = GetSystemMetrics(SM_CXEDGE) * 2; + g_yoff = GetSystemMetrics(SM_CYCAPTION) + + GetSystemMetrics(SM_CYEDGE) * 2; +#endif /* MYWINCE */ + } + g_width = g_width & (~3); + return 1; +} + +/*****************************************************************************/ +static int +mi_check_config_file(void) +{ + HANDLE fd; + DWORD count; + TCHAR filename[256]; + char buffer[256]; + char vname[256]; + char value[256]; + int index; + int mode; + int vnameindex; + int valueindex; + int state; + int rv; + + rv = 0; + mode = 0; + vnameindex = 0; + valueindex = 0; + vname[vnameindex] = 0; + value[valueindex] = 0; +#ifdef MYWINCE + str_to_uni(filename, "\\My Documents\\winrdesktop.ini"); +#else /* MYWINCE */ + str_to_uni(filename, ".\\winrdesktop.ini"); +#endif /* MYWINCE */ + fd = CreateFile(filename, GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + count = 255; + while (ReadFile(fd, buffer, count, &count, NULL)) + { + if (count == 0) + { + break; + } + buffer[count] = 0; + index = 0; + while (index < (int) count) + { + if (buffer[index] == '=') + { + mode = 1; + } + else if (buffer[index] == 10 || buffer[index] == 13) + { + mode = 0; + vname[vnameindex] = 0; + value[valueindex] = 0; + if (strlen(vname) > 0 || strlen(value) > 0) + { + if (strcmp(vname, "server") == 0) + { + strcpy(g_servername, value); + rv = 1; + } + else + { + state = mi_process_a_param(vname, 0); + mi_process_a_param(value, state); + } + } + vnameindex = 0; + valueindex = 0; + } + else if (mode == 0) + { + vname[vnameindex] = buffer[index]; + vnameindex++; + } + else + { + value[valueindex] = buffer[index]; + valueindex++; + } + index++; + } + count = 255; + } + CloseHandle(fd); + if (rv) + { + mi_post_param(); + } + return rv; +} + +/*****************************************************************************/ +/* process the command line parameters */ +/* returns boolean, non zero is ok */ +static int +mi_process_cl(LPTSTR lpCmdLine) +{ + char param[256]; + char param1[256]; +#ifndef MYWINCE + TCHAR l_username[256]; +#endif + DWORD size; + int len; + int i; + int i1; + int state; + + strcpy(g_hostname, "test"); + strcpy(g_username, "pda"); + /* get username and convert it from unicode */ + size = 255; +#ifndef MYWINCE + /* WinCE doesn't have GetUserName */ + if (GetUserName(l_username, &size)) + { + for (i = size; i >= 0; i--) + { + g_username[i] = (char) l_username[i]; + } + g_username[size] = 0; + } + else + { + mi_show_error("GetUserName"); + } +#endif /* MYWINCE */ + /* get computer name */ + if (gethostname(g_hostname, 255) != 0) + { + mi_show_error("gethostname"); + } + /* defaults */ + strcpy(g_servername, "127.0.0.1"); + g_server_depth = 8; + g_screen_width = GetSystemMetrics(SM_CXSCREEN); + g_screen_height = GetSystemMetrics(SM_CYSCREEN); + /* process parameters */ + i1 = 0; + state = 0; + len = lstrlen(lpCmdLine); + if (len == 0) + { + return mi_check_config_file(); + } + for (i = 0; i < len; i++) + { + if (lpCmdLine[i] != 32 && lpCmdLine[i] != 9) /* space or tab */ + { + param[i1] = (char) lpCmdLine[i]; + i1++; + } + else + { + param[i1] = 0; + i1 = 0; + strcpy(param1, param); + state = mi_process_a_param(param1, state); + strcpy(g_servername, param1); + } + } + if (i1 > 0) + { + param[i1] = 0; + strcpy(param1, param); + state = mi_process_a_param(param1, state); + strcpy(g_servername, param1); + } + if (state == 0) + { + mi_post_param(); + } + return (state == 0); +} + +/*****************************************************************************/ +/* display the command line options available */ +static void +mi_show_params(void) +{ + char text1[512 * 4]; + TCHAR textx[512 * 4]; + TCHAR lcaption[64]; + + strcpy(text1, ""); + strcat(text1, "WinRDesktop - an RDP client based on rdesktop\r\n"); + strcat(text1, "You can't run this application without " ); + strcat(text1, "correct parameters\r\n"); + strcat(text1, "\r\n"); + strcat(text1, "command line options\r\n"); + strcat(text1, "\r\n"); + strcat(text1, "WinRDesktop [-g widthxheight] [-t port] [-a bpp]\r\n"); + strcat(text1, " [-f] [-u username] [-p password] [-d domain]\r\n"); + strcat(text1, " [-s shell] [-c working directory] [-n host name]\r\n"); + strcat(text1, " server-name-or-ip\r\n"); + strcat(text1, "\r\n"); + strcat(text1, "You can use a config file in the current directory\r\n"); + strcat(text1, "called WinRDesktop.ini\r\n"); + strcat(text1, "The file should look like this...\r\n"); + strcat(text1, "[main]\r\n"); + strcat(text1, "server=192.168.1.1\r\n"); + strcat(text1, "port=3389\r\n"); + strcat(text1, "username=user1\r\n"); + strcat(text1, "password=password1\r\n"); + strcat(text1, "bpp=16\r\n"); + strcat(text1, "geometry=800x600\r\n"); +#ifdef WITH_DEBUG + printf(text1); +#else /* WITH_DEBUG */ + str_to_uni(lcaption, "WinRDesktop"); + str_to_uni(textx, text1); + MessageBox(g_Wnd, textx, lcaption, MB_OK); +#endif /* WITH_DEBUG */ +} + +#ifdef WITH_DEBUG +/*****************************************************************************/ +int +main(int argc, char ** argv) +{ + WSADATA d; + + WSAStartup(MAKEWORD(2, 0), &d); + if (!mi_process_cl(argv[0])) + { + mi_show_params(); + WSACleanup(); + return 0; + } + return ui_main(); +} +#else /* WITH_DEBUG */ +/*****************************************************************************/ +int WINAPI +WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, + LPTSTR lpCmdLine, int nCmdShow) +{ + WSADATA d; + + WSAStartup(MAKEWORD(2, 0), &d); + if (!mi_process_cl(lpCmdLine)) + { + mi_show_params(); + WSACleanup(); + return 0; + } + return ui_main(); +} +#endif /* WITH_DEBUG */ + +/*****************************************************************************/ +void +mi_begin_update(void) +{ +} + +/*****************************************************************************/ +void +mi_end_update(void) +{ +} + +/*****************************************************************************/ +void +mi_fill_rect(int x, int y, int cx, int cy, int colour) +{ + HBRUSH brush; + RECT rect; + HDC maindc; + HRGN rgn; + int red; + int green; + int blue; + + red = (colour & 0xff0000) >> 16; + green = (colour & 0xff00) >> 8; + blue = colour & 0xff; + maindc = GetWindowDC(g_Wnd); + rgn = mi_clip(maindc); + brush = CreateSolidBrush(RGB(red, green, blue)); + rect.left = x + g_xoff - g_xscroll; + rect.top = y + g_yoff - g_yscroll; + rect.right = rect.left + cx; + rect.bottom = rect.top + cy; + FillRect(maindc, &rect, brush); + DeleteObject(brush); + ReleaseDC(g_Wnd, maindc); + DeleteObject(rgn); +} + +/*****************************************************************************/ +void +mi_line(int x1, int y1, int x2, int y2, int colour) +{ + HPEN pen; + HDC maindc; + HGDIOBJ save; + HRGN rgn; + int red; + int green; + int blue; + + red = (colour & 0xff0000) >> 16; + green = (colour & 0xff00) >> 8; + blue = colour & 0xff; + maindc = GetWindowDC(g_Wnd); + rgn = mi_clip(maindc); + pen = CreatePen(PS_SOLID, 0, RGB(red, green, blue)); + save = SelectObject(maindc, pen); + MoveToEx(maindc, x1 + g_xoff - g_xscroll, y1 + g_yoff - g_yscroll, 0); + LineTo(maindc, x2 + g_xoff - g_xscroll, y2 + g_yoff - g_yscroll); + SelectObject(maindc, save); + DeleteObject(pen); + ReleaseDC(g_Wnd, maindc); + DeleteObject(rgn); +} + +/*****************************************************************************/ +void +mi_screen_copy(int x, int y, int cx, int cy, int srcx, int srcy) +{ + RECT rect; + RECT clip_rect; + RECT draw_rect; + HRGN rgn; + int ok_to_ScrollWindowEx; + + /* WinCE can't scroll in 2 directions at once */ +#ifdef MYWINCE + ok_to_ScrollWindowEx = cx == 0 || cy == 0; +#else /* MYWINCE */ + ok_to_ScrollWindowEx = 1; +#endif /* MYWINCE */ + if (!ok_to_ScrollWindowEx) + { + rgn = CreateRectRgn(x - g_xscroll, y - g_yscroll, + (x - g_xscroll) + cx, + (y - g_yscroll) + cy); + InvalidateRgn(g_Wnd, rgn, 0); + DeleteObject(rgn); + } + else + { + /* this is all in client coords */ + rect.left = srcx - g_xscroll; + rect.top = srcy - g_yscroll; + rect.right = rect.left + cx; + rect.bottom = rect.top + cy; + clip_rect.left = g_clip_left - g_xscroll; + clip_rect.top = g_clip_top - g_yscroll; + clip_rect.right = g_clip_right - g_xscroll; + clip_rect.bottom = g_clip_bottom - g_yscroll; + if (IntersectRect(&draw_rect, &clip_rect, &g_wnd_clip)) + { + rgn = CreateRectRgn(0, 0, 0, 0); + ScrollWindowEx(g_Wnd, x - srcx, y - srcy, &rect, &draw_rect, + rgn, 0, SW_ERASE); + InvalidateRgn(g_Wnd, rgn, 0); + DeleteObject(rgn); + } + } +} + +/*****************************************************************************/ +void +mi_set_clip(int x, int y, int cx, int cy) +{ + g_clip_left = x; + g_clip_top = y; + g_clip_right = g_clip_left + cx; + g_clip_bottom = g_clip_top + cy; +} + +/*****************************************************************************/ +void +mi_reset_clip(void) +{ + g_clip_left = 0; + g_clip_top = 0; + g_clip_right = g_clip_left + g_width; + g_clip_bottom = g_clip_top + g_height; +} + +/*****************************************************************************/ +void * +mi_create_cursor(unsigned int x, unsigned int y, + int width, int height, + unsigned char * andmask, unsigned char * xormask) +{ +#ifdef MYWINCE + return (void *) 1; +#else /* MYWINCE */ + HCURSOR hCur; + + hCur = CreateCursor(g_Instance, x, y, width, height, andmask, xormask); + if (hCur == 0) + { + hCur = LoadCursor(NULL, IDC_ARROW); + } + return hCur; +#endif /* MYWINCE */ +} + +/*****************************************************************************/ +void +mi_destroy_cursor(void * cursor) +{ +#ifdef MYWINCE +#else /* MYWINCE */ + if (g_cursor == cursor) + { + g_cursor = 0; + } + DestroyCursor(cursor); +#endif /* MYWINCE */ +} + +/*****************************************************************************/ +void +mi_set_cursor(void * cursor) +{ +#ifdef MYWINCE +#else /* MYWINCE */ + g_cursor = cursor; + SetCursor(g_cursor); +#endif /* MYWINCE */ +} + +/*****************************************************************************/ +void +mi_set_null_cursor(void) +{ +} + |