From c53841ac573585d6290ebedf28252a52b261c248 Mon Sep 17 00:00:00 2001 From: speyrefitte Date: Mon, 30 Jun 2014 18:04:51 +0200 Subject: [PATCH] code refactoring + integrate rdesktop code for bitmap decompression --- bin/rdpy-rdpclient | 2 +- bin/rdpy-vncclient | 2 +- lib/sip/rle.sip | 5 +- lib/src/rle/rle.c | 1372 ++++++++++++++++++++----------------- lib/src/rle/rle.h | 5 +- lib/src/rle/rle_m.h | 35 - rdpy/network/type.py | 242 ++++--- rdpy/protocol/rdp/gcc.py | 2 +- rdpy/protocol/rdp/mcs.py | 40 +- rdpy/protocol/rdp/pdu.py | 297 ++++---- rdpy/protocol/rdp/tpdu.py | 85 +-- rdpy/protocol/rdp/tpkt.py | 6 +- rdpy/ui/qt4.py | 13 +- 13 files changed, 1083 insertions(+), 1023 deletions(-) delete mode 100644 lib/src/rle/rle_m.h diff --git a/bin/rdpy-rdpclient b/bin/rdpy-rdpclient index ed55916..49fce47 100755 --- a/bin/rdpy-rdpclient +++ b/bin/rdpy-rdpclient @@ -53,7 +53,7 @@ class RDPClientQtFactory(rdp.ClientFactory): #create qt widget self._w = client.getWidget() self._w.resize(self._width, self._height) - self._w.setWindowTitle('rdpyclient-rdp') + self._w.setWindowTitle('rdpy-rdpclient') self._w.show() return client diff --git a/bin/rdpy-vncclient b/bin/rdpy-vncclient index bffd917..b20aef0 100755 --- a/bin/rdpy-vncclient +++ b/bin/rdpy-vncclient @@ -46,7 +46,7 @@ class RFBClientQtFactory(rfb.ClientFactory): #create qt widget self._w = client.getWidget() self._w.resize(1024, 800) - self._w.setWindowTitle('rdpyclient-vnc') + self._w.setWindowTitle('rdpy-vncclient') self._w.show() return client diff --git a/lib/sip/rle.sip b/lib/sip/rle.sip index 76a1398..e1bef84 100644 --- a/lib/sip/rle.sip +++ b/lib/sip/rle.sip @@ -4,6 +4,5 @@ #include "../../src/rle/rle.h" %End -int rle_decode_uint8(void* output, int width, int height, char* input, int size); -int rle_decode_uint16(void* output, int width, int height, char* input, int size); -int rle_decode_uint24(void* output, int width, int height, char* input, int size); +int bitmap_decompress(void * output, int width, int height, char * input, int size, int Bpp); + diff --git a/lib/src/rle/rle.c b/lib/src/rle/rle.c index 90bf3bc..913405d 100644 --- a/lib/src/rle/rle.c +++ b/lib/src/rle/rle.c @@ -1,38 +1,91 @@ -#include "rle_m.h" +/* -*- c-basic-offset: 8 -*- + rdesktop: A Remote Desktop Protocol client. + Bitmap decompression routines + Copyright (C) Matthew Chapman 1999-2008 -int rle_decode_uint8(char* output, int width, int height, char* input, int size) + 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 3 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, see . +*/ + +/* three seperate function for speed when decompressing the bitmaps + when modifing one function make the change in the others + jay.sorg@gmail.com */ + +/* indent is confused by this file */ +/* *INDENT-OFF* */ + +#include "rle.h" + +/* Specific rename for RDPY integration */ +#define uint8 unsigned char +#define uint16 unsigned short +#define NULL 0 +#define unimpl(str, code) + +#define RD_BOOL int +#define False 0 +#define True 1 +/* end specific rename */ + +#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 RD_BOOL +bitmap_decompress1(uint8 * output, int width, int height, uint8 * input, int size) { - char* prevline; - char* line; - char* end; - char color1; - char color2; - char mix; - int code; - int mixmask; - int mask; - int opcode; - int count; - int offset; - int isfillormix; - int x; - int lastopcode; - int insertmix; - int bicolor; - int fom_mask; - - end = input + size; - prevline = 0; - line = 0; - x = width; - lastopcode = -1; - insertmix = 0; - bicolor = 0; - color1 = 0; - color2 = 0; - mix = 0xff; - mask = 0; - fom_mask = 0; + 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 = 0; while (input < end) { @@ -42,31 +95,31 @@ int rle_decode_uint8(char* output, int width, int height, char* input, int size) /* 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; + 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) @@ -75,13 +128,9 @@ int rle_decode_uint8(char* output, int width, int height, char* input, int size) if (count == 0) { if (isfillormix) - { count = CVAL(input) + 1; - } else - { count = CVAL(input) + offset; - } } else if (isfillormix) { @@ -91,32 +140,30 @@ int rle_decode_uint8(char* output, int width, int height, char* input, int size) /* Read preliminary data */ switch (opcode) { - case 0: /* Fill */ - if ((lastopcode == opcode) && !((x == width) && (prevline == 0))) - { - insertmix = 1; - } - break; - case 8: /* Bicolor */ - color1 = CVAL(input); - case 3: /* Color */ - color2 = 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; + 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; @@ -126,9 +173,7 @@ int rle_decode_uint8(char* output, int width, int height, char* input, int size) if (x >= width) { if (height <= 0) - { - return 0; - } + return False; x = 0; height--; prevline = line; @@ -136,145 +181,109 @@ int rle_decode_uint8(char* output, int width, int height, char* input, int size) } switch (opcode) { - case 0: /* Fill */ - if (insertmix) - { - if (prevline == 0) - { - line[x] = mix; - } - else - { - line[x] = prevline[x] ^ mix; - } - insertmix = 0; - count--; - x++; - } - if (prevline == 0) - { - REPEAT(line[x] = 0) - } - else - { - REPEAT(line[x] = prevline[x]) - } - break; - case 1: /* Mix */ - if (prevline == 0) - { - REPEAT(line[x] = mix) - } - else - { - REPEAT(line[x] = prevline[x] ^ mix) - } - break; - case 2: /* Fill or Mix */ - if (prevline == 0) - { - REPEAT - ( - MASK_UPDATE; - if (mask & mixmask) + case 0: /* Fill */ + if (insertmix) { - line[x] = mix; + if (prevline == NULL) + line[x] = mix; + else + line[x] = prevline[x] ^ mix; + insertmix = False; + count--; + x++; + } + if (prevline == NULL) + { + REPEAT(line[x] = 0) } else { - line[x] = 0; + REPEAT(line[x] = prevline[x]) } - ) - } - else - { - REPEAT - ( - MASK_UPDATE; - if (mask & mixmask) + break; + case 1: /* Mix */ + if (prevline == NULL) { - line[x] = prevline[x] ^ mix; + REPEAT(line[x] = mix) } else { - line[x] = prevline[x]; + REPEAT(line[x] = prevline[x] ^ mix) } - ) - } - break; - case 3: /* Color */ - REPEAT(line[x] = color2) - break; - case 4: /* Copy */ - REPEAT(line[x] = CVAL(input)) - break; - case 8: /* Bicolor */ - REPEAT - ( - if (bicolor) + 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] = color2; - bicolor = 0; + line[x] = colour2; + bicolour = False; } else { - line[x] = color1; - bicolor = 1; - count++; + line[x] = colour1; + bicolour = True; count++; } - ) - break; - case 0xd: /* White */ - REPEAT(line[x] = 0xff) - break; - case 0xe: /* Black */ - REPEAT(line[x] = 0) - break; - default: - return 0; - break; + ) + 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 1; + return True; } -int rle_decode_uint16(char* output, int width, int height, char* input, int size) +/* 2 byte bitmap decompress */ +static RD_BOOL +bitmap_decompress2(uint8 * output, int width, int height, uint8 * input, int size) { - char* prevline; - char* line; - char* end; - char color1[2]; - char color2[2]; - char mix[2]; - int code; - int mixmask; - int mask; - int opcode; - int count; - int offset; - int isfillormix; - int x; - int lastopcode; - int insertmix; - int bicolor; - int fom_mask; - - end = input + size; - prevline = 0; - line = 0; - x = width; - lastopcode = -1; - insertmix = 0; - bicolor = 0; - color1[0] = 0; - color1[1] = 0; - color2[0] = 0; - color2[1] = 0; - mix[0] = 0xff; - mix[1] = 0xff; - mask = 0; - fom_mask = 0; + 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 = 0; while (input < end) { @@ -284,31 +293,31 @@ int rle_decode_uint16(char* output, int width, int height, char* input, int size /* 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; + 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) @@ -317,13 +326,9 @@ int rle_decode_uint16(char* output, int width, int height, char* input, int size if (count == 0) { if (isfillormix) - { count = CVAL(input) + 1; - } else - { count = CVAL(input) + offset; - } } else if (isfillormix) { @@ -333,35 +338,30 @@ int rle_decode_uint16(char* output, int width, int height, char* input, int size /* Read preliminary data */ switch (opcode) { - case 0: /* Fill */ - if ((lastopcode == opcode) && !((x == width) && (prevline == 0))) - { - insertmix = 1; - } - break; - case 8: /* Bicolor */ - color1[EIK0] = CVAL(input); - color1[EIK1] = CVAL(input); - case 3: /* Color */ - color2[EIK0] = CVAL(input); - color2[EIK1] = CVAL(input); - break; - case 6: /* SetMix/Mix */ - case 7: /* SetMix/FillOrMix */ - mix[EIK0] = CVAL(input); - mix[EIK1] = 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; + 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; @@ -371,198 +371,118 @@ int rle_decode_uint16(char* output, int width, int height, char* input, int size if (x >= width) { if (height <= 0) - { - return 0; - } + return False; x = 0; height--; prevline = line; - line = output + height * (width * 2); + line = ((uint16 *) output) + height * width; } switch (opcode) { - case 0: /* Fill */ - if (insertmix) - { - if (prevline == 0) - { - line[x * 2 + 0] = mix[0]; - line[x * 2 + 1] = mix[1]; - } - else - { - line[x * 2 + 0] = prevline[x * 2 + 0] ^ mix[0]; - line[x * 2 + 1] = prevline[x * 2 + 1] ^ mix[1]; - } - insertmix = 0; - count--; - x++; - } - if (prevline == 0) - { - REPEAT - ( - line[x * 2 + 0] = 0; - line[x * 2 + 1] = 0; - ) - } - else - { - REPEAT - ( - line[x * 2 + 0] = prevline[x * 2 + 0]; - line[x * 2 + 1] = prevline[x * 2 + 1]; - ) - } - break; - case 1: /* Mix */ - if (prevline == 0) - { - REPEAT - ( - line[x * 2 + 0] = mix[0]; - line[x * 2 + 1] = mix[1]; - ) - } - else - { - REPEAT - ( - line[x * 2 + 0] = prevline[x * 2 + 0] ^ mix[0]; - line[x * 2 + 1] = prevline[x * 2 + 1] ^ mix[1]; - ) - } - break; - case 2: /* Fill or Mix */ - if (prevline == 0) - { - REPEAT - ( - MASK_UPDATE; - if (mask & mixmask) + case 0: /* Fill */ + if (insertmix) { - line[x * 2 + 0] = mix[0]; - line[x * 2 + 1] = mix[1]; + if (prevline == NULL) + line[x] = mix; + else + line[x] = prevline[x] ^ mix; + insertmix = False; + count--; + x++; + } + if (prevline == NULL) + { + REPEAT(line[x] = 0) } else { - line[x * 2 + 0] = 0; - line[x * 2 + 1] = 0; + REPEAT(line[x] = prevline[x]) } - ) - } - else - { - REPEAT - ( - MASK_UPDATE; - if (mask & mixmask) + break; + case 1: /* Mix */ + if (prevline == NULL) { - line[x * 2 + 0] = prevline[x * 2 + 0] ^ mix[0]; - line[x * 2 + 1] = prevline[x * 2 + 1] ^ mix[1]; + REPEAT(line[x] = mix) } else { - line[x * 2 + 0] = prevline[x * 2 + 0]; - line[x * 2 + 1] = prevline[x * 2 + 1]; + REPEAT(line[x] = prevline[x] ^ mix) } - ) - } - break; - case 3: /* Color */ - REPEAT - ( - line[x * 2 + 0] = color2[0]; - line[x * 2 + 1] = color2[1]; - ) - break; - case 4: /* Copy */ - REPEAT - ( - line[x * 2 + EIK0] = CVAL(input); - line[x * 2 + EIK1] = CVAL(input); - ) - break; - case 8: /* Bicolor */ - REPEAT - ( - if (bicolor) + 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 * 2 + 0] = color2[0]; - line[x * 2 + 1] = color2[1]; - bicolor = 0; + line[x] = colour2; + bicolour = False; } else { - line[x * 2 + 0] = color1[0]; - line[x * 2 + 1] = color1[1]; - bicolor = 1; + line[x] = colour1; + bicolour = True; count++; } - ) - break; - case 0xd: /* White */ - REPEAT - ( - line[x * 2 + 0] = 0xff; - line[x * 2 + 1] = 0xff; - ) - break; - case 0xe: /* Black */ - REPEAT - ( - line[x * 2 + 0] = 0; - line[x * 2 + 1] = 0; - ) - break; - default: - return 0; - break; + ) + 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 1; + return True; } -int rle_decode_uint24(char* output, int width, int height, char* input, int size) +/* 3 byte bitmap decompress */ +static RD_BOOL +bitmap_decompress3(uint8 * output, int width, int height, uint8 * input, int size) { - char* prevline; - char* line; - char* end; - char color1[3]; - char color2[3]; - char mix[3]; - int code; - int mixmask; - int mask; - int opcode; - int count; - int offset; - int isfillormix; - int x; - int lastopcode; - int insertmix; - int bicolor; - int fom_mask; - - end = input + size; - prevline = 0; - line = 0; - x = width; - lastopcode = -1; - insertmix = 0; - bicolor = 0; - color1[0] = 0; - color1[1] = 0; - color1[2] = 0; - color2[0] = 0; - color2[1] = 0; - color2[2] = 0; - mix[0] = 0xff; - mix[1] = 0xff; - mix[2] = 0xff; - mask = 0; - fom_mask = 0; + 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 = 0; while (input < end) { @@ -572,31 +492,32 @@ int rle_decode_uint24(char* output, int width, int height, char* input, int size /* 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; + 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) @@ -605,13 +526,9 @@ int rle_decode_uint24(char* output, int width, int height, char* input, int size if (count == 0) { if (isfillormix) - { count = CVAL(input) + 1; - } else - { count = CVAL(input) + offset; - } } else if (isfillormix) { @@ -621,38 +538,36 @@ int rle_decode_uint24(char* output, int width, int height, char* input, int size /* Read preliminary data */ switch (opcode) { - case 0: /* Fill */ - if ((lastopcode == opcode) && !((x == width) && (prevline == 0))) - { - insertmix = 1; - } - break; - case 8: /* Bicolor */ - color1[0] = CVAL(input); - color1[1] = CVAL(input); - color1[2] = CVAL(input); - case 3: /* Color */ - color2[0] = CVAL(input); - color2[1] = CVAL(input); - color2[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; + 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; @@ -662,9 +577,7 @@ int rle_decode_uint24(char* output, int width, int height, char* input, int size if (x >= width) { if (height <= 0) - { - return 0; - } + return False; x = 0; height--; prevline = line; @@ -672,161 +585,336 @@ int rle_decode_uint24(char* output, int width, int height, char* input, int size } switch (opcode) { - case 0: /* Fill */ - if (insertmix) - { - if (prevline == 0) - { - line[x * 3 + 0] = mix[0]; - line[x * 3 + 1] = mix[1]; - line[x * 3 + 2] = mix[2]; - } - else - { - line[x * 3 + 0] = prevline[x * 3 + 0] ^ mix[0]; - line[x * 3 + 1] = prevline[x * 3 + 1] ^ mix[1]; - line[x * 3 + 2] = prevline[x * 3 + 2] ^ mix[2]; - } - insertmix = 0; - count--; - x++; - } - if (prevline == 0) - { - REPEAT - ( - line[x * 3 + 0] = 0; - line[x * 3 + 1] = 0; - line[x * 3 + 2] = 0; - ) - } - else - { - REPEAT - ( - line[x * 3 + 0] = prevline[x * 3 + 0]; - line[x * 3 + 1] = prevline[x * 3 + 1]; - line[x * 3 + 2] = prevline[x * 3 + 2]; - ) - } - break; - case 1: /* Mix */ - if (prevline == 0) - { - REPEAT - ( - line[x * 3 + 0] = mix[0]; - line[x * 3 + 1] = mix[1]; - line[x * 3 + 2] = mix[2]; - ) - } - else - { - REPEAT - ( - line[x * 3 + 0] = prevline[x * 3 + 0] ^ 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 == 0) - { - REPEAT - ( - MASK_UPDATE; - if (mask & mixmask) + case 0: /* Fill */ + if (insertmix) { - line[x * 3 + 0] = mix[0]; - line[x * 3 + 1] = mix[1]; - line[x * 3 + 2] = mix[2]; - } - else - { - line[x * 3 + 0] = 0; - line[x * 3 + 1] = 0; - line[x * 3 + 2] = 0; - } - ) - } - else - { - REPEAT - ( - MASK_UPDATE; - if (mask & mixmask) - { - line[x * 3 + 0] = prevline[x * 3 + 0] ^ 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 + 0] = prevline[x * 3 + 0]; - line[x * 3 + 1] = prevline[x * 3 + 1]; - line[x * 3 + 2] = prevline[x * 3 + 2]; - } - ) - } - break; - case 3: /* Color */ - REPEAT - ( - line[x * 3 + 0] = color2[0]; - line[x * 3 + 1] = color2[1]; - line[x * 3 + 2] = color2[2]; - ) - break; - case 4: /* Copy */ - REPEAT - ( - line[x * 3 + 0] = CVAL(input); - line[x * 3 + 1] = CVAL(input); - line[x * 3 + 2] = CVAL(input); - ) - break; - case 8: /* Bicolor */ - REPEAT - ( - if (bicolor) + if (prevline == NULL) { - line[x * 3 + 0] = color2[0]; - line[x * 3 + 1] = color2[1]; - line[x * 3 + 2] = color2[2]; - bicolor = 0; + line[x * 3] = mix[0]; + line[x * 3 + 1] = mix[1]; + line[x * 3 + 2] = mix[2]; } else { - line[x * 3 + 0] = color1[0]; - line[x * 3 + 1] = color1[1]; - line[x * 3 + 2] = color1[2]; - bicolor = 1; + 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 + 0] = 0xff; - line[x * 3 + 1] = 0xff; - line[x * 3 + 2] = 0xff; - ) - break; - case 0xe: /* Black */ - REPEAT - ( - line[x * 3 + 0] = 0; - line[x * 3 + 1] = 0; - line[x * 3 + 2] = 0; - ) - break; - default: - return 0; - break; + ) + 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 1; + return True; } + +/* decompress a colour plane */ +static int +process_plane(uint8 * in, int width, int height, uint8 * out, int size) +{ + int indexw; + int indexh; + int code; + int collen; + int replen; + int color; + int x; + int revcode; + uint8 * last_line; + uint8 * this_line; + uint8 * org_in; + uint8 * org_out; + + org_in = in; + org_out = out; + last_line = 0; + indexh = 0; + while (indexh < height) + { + out = (org_out + width * height * 4) - ((indexh + 1) * width * 4); + color = 0; + this_line = out; + indexw = 0; + if (last_line == 0) + { + while (indexw < width) + { + code = CVAL(in); + replen = code & 0xf; + collen = (code >> 4) & 0xf; + revcode = (replen << 4) | collen; + if ((revcode <= 47) && (revcode >= 16)) + { + replen = revcode; + collen = 0; + } + while (collen > 0) + { + color = CVAL(in); + *out = color; + out += 4; + indexw++; + collen--; + } + while (replen > 0) + { + *out = color; + out += 4; + indexw++; + replen--; + } + } + } + else + { + while (indexw < width) + { + code = CVAL(in); + replen = code & 0xf; + collen = (code >> 4) & 0xf; + revcode = (replen << 4) | collen; + if ((revcode <= 47) && (revcode >= 16)) + { + replen = revcode; + collen = 0; + } + while (collen > 0) + { + x = CVAL(in); + if (x & 1) + { + x = x >> 1; + x = x + 1; + color = -x; + } + else + { + x = x >> 1; + color = x; + } + x = last_line[indexw * 4] + color; + *out = x; + out += 4; + indexw++; + collen--; + } + while (replen > 0) + { + x = last_line[indexw * 4] + color; + *out = x; + out += 4; + indexw++; + replen--; + } + } + } + indexh++; + last_line = this_line; + } + return (int) (in - org_in); +} + +/* 4 byte bitmap decompress */ +static RD_BOOL +bitmap_decompress4(uint8 * output, int width, int height, uint8 * input, int size) +{ + int code; + int bytes_pro; + int total_pro; + + code = CVAL(input); + if (code != 0x10) + { + return False; + } + total_pro = 1; + bytes_pro = process_plane(input, width, height, output + 3, size - total_pro); + total_pro += bytes_pro; + input += bytes_pro; + bytes_pro = process_plane(input, width, height, output + 2, size - total_pro); + total_pro += bytes_pro; + input += bytes_pro; + bytes_pro = process_plane(input, width, height, output + 1, size - total_pro); + total_pro += bytes_pro; + input += bytes_pro; + bytes_pro = process_plane(input, width, height, output + 0, size - total_pro); + total_pro += bytes_pro; + return size == total_pro; +} + +/* main decompress function */ +int +bitmap_decompress(char * output, int width, int height, char * input, int size, int Bpp) +{ + RD_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; + case 4: + rv = bitmap_decompress4(output, width, height, input, size); + break; + default: + unimpl("Bpp %d\n", Bpp); + break; + } + return rv; +} + +/* *INDENT-ON* */ diff --git a/lib/src/rle/rle.h b/lib/src/rle/rle.h index 0b206bb..fea712e 100644 --- a/lib/src/rle/rle.h +++ b/lib/src/rle/rle.h @@ -1,9 +1,6 @@ #ifndef _RLE_H_ #define _RLE_H_ - -int rle_decode_uint8(char* output, int width, int height, char* input, int size); -int rle_decode_uint16(char* output, int width, int height, char* input, int size); -int rle_decode_uint24(char* output, int width, int height, char* input, int size); +int bitmap_decompress(char * output, int width, int height, char * input, int size, int Bpp); #endif diff --git a/lib/src/rle/rle_m.h b/lib/src/rle/rle_m.h deleted file mode 100644 index d1ef1a1..0000000 --- a/lib/src/rle/rle_m.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef _RLE_M_H_ -#define _RLE_M_H_ - -#include "rle.h" - -#define CVAL(p) ((unsigned char)(*(p++))) - -#if defined(B_ENDIAN) -#define EIK0 1 -#define EIK1 0 -#else -#define EIK0 0 -#define EIK1 1 -#endif - -#define REPEAT(statement) \ -{ \ - while ((count > 0) && (x < width)) \ - { \ - statement; \ - count--; \ - x++; \ - } \ -} - -#define MASK_UPDATE \ -{ \ - mixmask <<= 1; \ - if ((mixmask & 0xff) == 0) \ - { \ - mask = fom_mask ? fom_mask : CVAL(input); \ - mixmask = 1; \ - } \ -} -#endif diff --git a/rdpy/network/type.py b/rdpy/network/type.py index 5228365..eb69eda 100644 --- a/rdpy/network/type.py +++ b/rdpy/network/type.py @@ -28,17 +28,15 @@ import struct from copy import deepcopy from StringIO import StringIO from error import InvalidValue -from rdpy.network.error import InvalidExpectedDataException, InvalidSize +from rdpy.network.error import InvalidExpectedDataException, InvalidSize, CallPureVirtualFuntion def sizeof(element): - ''' - byte size of type - sum sizeof of tuple element - and count only element that condition - is true at sizeof call + """ + Byte size of type sum sizeof of tuple element + And count only element that condition is true at sizeof call @param element: Type or Tuple(Type | Tuple,) @return: size of element in byte - ''' + """ if isinstance(element, tuple) or isinstance(element, list): size = 0 for i in element: @@ -50,18 +48,16 @@ def sizeof(element): class Type(object): - ''' - root type object inheritance - record conditional optional of constant - mechanism - ''' + """ + Root type object inheritance + Record conditional optional of constant mechanism + """ def __init__(self, conditional = lambda:True, optional = False, constant = False): - ''' - constructor of any type object + """ @param conditional : function call before read or write type @param optional: boolean check before read if there is still data in stream - @param constant: if true check any changement of object during reading - ''' + @param constant: if true check any modification of object during reading + """ self._conditional = conditional self._optional = optional self._constant = constant @@ -73,22 +69,22 @@ class Type(object): self._is_writed = False def write(self, s): - ''' - write type into stream if conditional is true - and call private + """ + Write type into stream if conditional is true + Call virtual __write__ method @param s: Stream which will be written - ''' + """ self._is_writed = self._conditional() if not self._is_writed: return self.__write__(s) def read(self, s): - ''' - read type from stream s if conditional - is true and check constantness + """ + Read type from stream s if conditional is true + Check constantness @param s: Stream - ''' + """ self._is_readed = self._conditional() if not self._is_readed: return @@ -108,56 +104,54 @@ class Type(object): raise InvalidExpectedDataException("%s const value expected %s != %s"%(self.__class__, old.value, self.value)) def __read__(self, s): - ''' - interface definition of private read funtion + """ + Interface definition of private read function @param s: Stream - ''' - pass + """ + raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "__read__", "Type")) def __write__(self, s): - ''' - interface definition of private write funtion + """ + Interface definition of private write function @param s: Stream - ''' - pass + """ + raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "__write__", "Type")) def __sizeof__(self): - ''' - return size of type use for sizeof function + """ + Return size of type use for sizeof function @return: size in byte of type - ''' - pass + """ + raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "__sizeof__", "Type")) class CallableValue(object): - ''' - wrap access of callable value. + """ + Wrap access of callable value. When use getter value is call. - Constant value can also be wrap - and will be transformed into callable value(lambda function) - ''' + Constant value can also be wrap and will be transformed into callable value(lambda function) + """ def __init__(self, value): - ''' - construtor + """ @param value: value will be wrapped (constant | lambda | function) - ''' + """ self._value = None self.value = value def __getValue__(self): - ''' - can be overwritten to add specific check before + """ + Can be overwritten to add specific check before self.value is call - @return: result of callbale value - ''' + @return: result of callable value + """ return self._value() def __setValue__(self, value): - ''' - can be overwritten to add specific check before + """ + Can be overwritten to add specific check before self.value = value is call - check if value is callable and if not transform it + Check if value is callable and if not transform it @param value: new value wrapped if constant -> lambda function - ''' + """ value_callable = lambda:value if callable(value): value_callable = value @@ -166,37 +160,34 @@ class CallableValue(object): @property def value(self): - ''' - shortcut to access inner value - main getter of value + """ + Shortcut to access inner value main getter of value @return: result of callable value - ''' + """ return self.__getValue__() @value.setter def value(self, value): - ''' - setter of value after check it - main setter of value - @param value: new value encompass in valuetype object - ''' + """ + Setter of value after check it main setter of value + @param value: new value encompass in value type object + """ self.__setValue__(value) class SimpleType(Type, CallableValue): - ''' - simple type - ''' + """ + Simple type + """ def __init__(self, structFormat, typeSize, signed, value, conditional = lambda:True, optional = False, constant = False): - ''' - constructor of simple type + """ @param structFormat: letter that represent type in struct package @param typeSize: size in byte of type @param signed: true if type represent a signed type - @param value: value recorded in this object (can be callable value which be call when is acces usefull with closure) + @param value: value recorded in this object (can be callable value which be call when is access useful with closure) @param conditional : function call before read or write type @param optional: boolean check before read if there is still data in stream - @param constant: if true check any changement of object during reading - ''' + @param constant: if true check any modification of object during reading + """ self._signed = signed self._typeSize = typeSize self._structFormat = structFormat @@ -204,13 +195,12 @@ class SimpleType(Type, CallableValue): CallableValue.__init__(self, value) def __getValue__(self): - ''' - CallableValue overwrite - check mask type of value + """ + CallableValue overwrite check mask type of value use CallableValue access - @return: python value wrap into type + @return: Python value wrap into type @raise InvalidValue: if value doesn't respect type range - ''' + """ value = CallableValue.__getValue__(self) if not self.isInRange(value): raise InvalidValue("value is out of range for %s"%self.__class__) @@ -221,12 +211,12 @@ class SimpleType(Type, CallableValue): return value & self.mask() def __setValue__(self, value): - ''' + """ CallableValue overwrite - check mask type of value - @param value: new value encompass in object (respect python type | lambda | function) + Check mask type of value + @param value: new value encompass in object (respect Python type | lambda | function) @raise InvalidValue: if value doesn't respect type range - ''' + """ #check static value range if not callable(value) and not self.isInRange(value): raise InvalidValue("value is out of range for %s"%self.__class__) @@ -235,40 +225,40 @@ class SimpleType(Type, CallableValue): def __cmp__(self, other): - ''' - compare inner value - magic function of python use for any compare operators + """ + Compare inner value + Magic function of Python use for any compare operators @param other: SimpleType value which will be compared with self value or try to construct same type as self around other value - @return: python value compare - ''' + @return: Python value compare + """ if not isinstance(other, SimpleType): other = self.__class__(other) return self.value.__cmp__(other.value) def __write__(self, s): - ''' - write value in stream s - use struct package to pack value + """ + Write value in stream s + Use Struct package to pack value @param s: Stream which will be written - ''' + """ s.write(struct.pack(self._structFormat, self.value)) def __read__(self, s): - ''' - read inner value from stream - use struct package + """ + Read inner value from stream + Use struct package @param s: Stream - ''' + """ if s.dataLen() < self._typeSize: raise InvalidSize("Stream is too small to read expected data") self.value = struct.unpack(self._structFormat, s.read(self._typeSize))[0] def mask(self): - ''' - compute bit mask for type - because in python all numbers are int long or float - ''' + """ + Compute bit mask for type + Because in Python all numbers are Int long or float + """ if not self.__dict__.has_key("_mask"): mask = 0xff for i in range(1, self._typeSize): @@ -277,106 +267,106 @@ class SimpleType(Type, CallableValue): return self._mask def isInRange(self, value): - ''' - check if value is in mask range - @param value: python value + """ + Check if value is in mask range + @param value: Python value @return: true if value is in type range - ''' + """ if self._signed: return not (value < -(self.mask() >> 1) or value > (self.mask() >> 1)) else: return not (value < 0 or value > self.mask()) def __sizeof__(self): - ''' - return size of type + """ + Return size of type @return: typeSize pass in constructor - ''' + """ return self._typeSize def __invert__(self): - ''' - implement not operator + """ + Implement not operator @return: __class__ value - ''' + """ invert = ~self.value if not self._signed: invert &= self.mask() return self.__class__(invert) def __add__(self, other): - ''' - implement addition operator + """ + Implement addition operator @param other: SimpleType value or try to construct same type as self around other value @return: self.__class__ object with add result @raise InvalidValue: if new value is out of bound - ''' + """ if not isinstance(other, SimpleType): other = self.__class__(other) return self.__class__(self.value.__add__(other.value)) def __sub__(self, other): - ''' - implement sub operator + """ + Implement sub operator @param other: SimpleType value or try to construct same type as self around other value @return: self.__class__ object with sub result @raise InvalidValue: if new value is out of bound - ''' + """ if not isinstance(other, SimpleType): other = self.__class__(other) return self.__class__(self.value.__sub__(other.value)) def __and__(self, other): - ''' - implement bitwise and operator + """ + Implement bitwise and operator @param other: SimpleType value or try to construct same type as self around other value @return: self.__class__ object with and result - ''' + """ if not isinstance(other, SimpleType): other = self.__class__(other) return self.__class__(self.value.__and__(other.value)) def __or__(self, other): - ''' + """ implement bitwise or operator @param other: SimpleType value or try to construct same type as self around other value @return: self.__class__ object with or result - ''' + """ if not isinstance(other, SimpleType): other = self.__class__(other) return self.__class__(self.value.__or__(other.value)) def __xor__(self, other): - ''' - implement bitwise xor operator + """ + Implement bitwise xor operator @param other: SimpleType value or try to construct same type as self around other value @return: self.__class__ object with or result - ''' + """ if not isinstance(other, SimpleType): other = self.__class__(other) return self.__class__(self.value.__xor__(other.value)) def __lshift__(self, other): - ''' - left shift operator - @param other: python int + """ + Left shift operator + @param other: Python Int @return: self.__class__ object with or result - ''' + """ if not isinstance(other, SimpleType): other = self.__class__(other) return self.__class__(self.value.__lshift__(other.value)) def __rshift__(self, other): - ''' - left shift operator + """ + Left shift operator @param other: python int @return: self.__class__ object with or result - ''' + """ if not isinstance(other, SimpleType): other = self.__class__(other) return self.__class__(self.value.__rshift__(other.value)) diff --git a/rdpy/protocol/rdp/gcc.py b/rdpy/protocol/rdp/gcc.py index 6d4eaaa..580048d 100644 --- a/rdpy/protocol/rdp/gcc.py +++ b/rdpy/protocol/rdp/gcc.py @@ -1,7 +1,7 @@ ''' @author sylvain @summary gcc language -@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx +@see: http://msdn.microsoft.com/en-us/library/cc240508.aspx ''' from rdpy.network.const import ConstAttributes, TypeAttributes from rdpy.network.type import UInt8, UInt16Le, UInt32Le, CompositeType, String, UniString, Stream, sizeof diff --git a/rdpy/protocol/rdp/mcs.py b/rdpy/protocol/rdp/mcs.py index 37d1afe..1c95d36 100644 --- a/rdpy/protocol/rdp/mcs.py +++ b/rdpy/protocol/rdp/mcs.py @@ -18,14 +18,12 @@ # """ -Implement Multi Channel Service +Implement Multi-Channel Service Each channel have a particular role. The main channel is the graphical channel. It exist channel for file system order, audio channel, clipboard etc... """ - -from rdpy.network.const import ConstAttributes, TypeAttributes from rdpy.network.layer import LayerAutomata, LayerMode, StreamSender from rdpy.network.type import sizeof, Stream, UInt8, UInt16Be from rdpy.network.error import InvalidExpectedDataException, InvalidValue, InvalidSize @@ -33,8 +31,6 @@ from rdpy.protocol.rdp.ber import writeLength import ber, gcc, per -@ConstAttributes -@TypeAttributes(UInt8) class Message(object): """ Message type @@ -42,8 +38,6 @@ class Message(object): MCS_TYPE_CONNECT_INITIAL = 0x65 MCS_TYPE_CONNECT_RESPONSE = 0x66 -@ConstAttributes -@TypeAttributes(UInt8) class DomainMCSPDU: """ Domain MCS PDU header @@ -57,8 +51,6 @@ class DomainMCSPDU: SEND_DATA_REQUEST = 25 SEND_DATA_INDICATION = 26 -@ConstAttributes -@TypeAttributes(UInt16Be) class Channel: """ Channel id of main channels use in RDP @@ -126,7 +118,7 @@ class MCS(LayerAutomata): self._clientSettings = gcc.ClientSettings() self._serverSettings = gcc.ServerSettings() #default user Id - self._userId = UInt16Be(1) + self._userId = 1 #list of channel use in this layer and connection state self._channelIds = {Channel.MCS_GLOBAL_CHANNEL: presentation} #use to record already requested channel @@ -137,7 +129,7 @@ class MCS(LayerAutomata): Connection send for client mode a write connect initial packet """ - self._clientSettings.core.serverSelectedProtocol = self._transport._selectedProtocol + self._clientSettings.core.serverSelectedProtocol.value = self._transport._selectedProtocol self.sendConnectInitial() def connectNextChannel(self): @@ -173,7 +165,7 @@ class MCS(LayerAutomata): self.writeDomainParams(1, 1, 1, 0x420), self.writeDomainParams(0xffff, 0xfc17, 0xffff, 0xffff), ber.writeOctetstring(ccReqStream.getvalue())) - self._transport.send((ber.writeApplicationTag(Message.MCS_TYPE_CONNECT_INITIAL, sizeof(tmp)), tmp)) + self._transport.send((ber.writeApplicationTag(UInt8(Message.MCS_TYPE_CONNECT_INITIAL), sizeof(tmp)), tmp)) #we must receive a connect response self.setNextState(self.recvConnectResponse) @@ -181,26 +173,26 @@ class MCS(LayerAutomata): """ Send a formated erect domain request for RDP connection """ - self._transport.send((self.writeMCSPDUHeader(DomainMCSPDU.ERECT_DOMAIN_REQUEST), per.writeInteger(0), per.writeInteger(0))) + self._transport.send((self.writeMCSPDUHeader(UInt8(DomainMCSPDU.ERECT_DOMAIN_REQUEST)), per.writeInteger(0), per.writeInteger(0))) def sendAttachUserRequest(self): """ Send a formated attach user request for RDP connection """ - self._transport.send(self.writeMCSPDUHeader(DomainMCSPDU.ATTACH_USER_REQUEST)) + self._transport.send(self.writeMCSPDUHeader(UInt8(DomainMCSPDU.ATTACH_USER_REQUEST))) def sendChannelJoinRequest(self, channelId): """ Send a formated Channel join request from client to server """ - self._transport.send((self.writeMCSPDUHeader(DomainMCSPDU.CHANNEL_JOIN_REQUEST), self._userId, channelId)) + self._transport.send((self.writeMCSPDUHeader(UInt8(DomainMCSPDU.CHANNEL_JOIN_REQUEST)), UInt16Be(self._userId), UInt16Be(channelId))) def recvConnectResponse(self, data): """ receive MCS connect response from server @param data: Stream """ - ber.readApplicationTag(data, Message.MCS_TYPE_CONNECT_RESPONSE) + ber.readApplicationTag(data, UInt8(Message.MCS_TYPE_CONNECT_RESPONSE)) ber.readEnumerated(data) ber.readInteger(data) self.readDomainParams(data) @@ -225,13 +217,15 @@ class MCS(LayerAutomata): """ opcode = UInt8() confirm = UInt8() + userId = UInt16Be() data.readType((opcode, confirm)) - if not self.readMCSPDUHeader(opcode, DomainMCSPDU.ATTACH_USER_CONFIRM): + if not self.readMCSPDUHeader(opcode.value, DomainMCSPDU.ATTACH_USER_CONFIRM): raise InvalidExpectedDataException("invalid MCS PDU") if confirm != 0: raise Exception("server reject user") if opcode & UInt8(2) == UInt8(2): - data.readType(self._userId) + data.readType(userId) + self._userId = userId.value #build channel list because we have user id #add default channel + channels accepted by gcc connection sequence @@ -247,7 +241,7 @@ class MCS(LayerAutomata): opcode = UInt8() confirm = UInt8() data.readType((opcode, confirm)) - if not self.readMCSPDUHeader(opcode, DomainMCSPDU.CHANNEL_JOIN_CONFIRM): + if not self.readMCSPDUHeader(opcode.value, DomainMCSPDU.CHANNEL_JOIN_CONFIRM): raise InvalidExpectedDataException("invalid MCS PDU") userId = UInt16Be() channelId = UInt16Be() @@ -269,11 +263,11 @@ class MCS(LayerAutomata): opcode = UInt8() data.readType(opcode) - if self.readMCSPDUHeader(opcode, DomainMCSPDU.DISCONNECT_PROVIDER_ULTIMATUM): + if self.readMCSPDUHeader(opcode.value, DomainMCSPDU.DISCONNECT_PROVIDER_ULTIMATUM): print "receive DISCONNECT_PROVIDER_ULTIMATUM" self.close() - elif not self.readMCSPDUHeader(opcode, DomainMCSPDU.SEND_DATA_INDICATION): + elif not self.readMCSPDUHeader(opcode.value, DomainMCSPDU.SEND_DATA_INDICATION): raise InvalidExpectedDataException("invalid expected mcs opcode") userId = UInt16Be() @@ -306,7 +300,7 @@ class MCS(LayerAutomata): @param channelId: Channel use to send @param data: message to send """ - self._transport.send((self.writeMCSPDUHeader(DomainMCSPDU.SEND_DATA_REQUEST), self._userId, channelId, UInt8(0x70), UInt16Be(sizeof(data)) | UInt16Be(0x8000), data)) + self._transport.send((self.writeMCSPDUHeader(UInt8(DomainMCSPDU.SEND_DATA_REQUEST)), UInt16Be(self._userId), UInt16Be(channelId), UInt8(0x70), UInt16Be(sizeof(data)) | UInt16Be(0x8000), data)) def writeDomainParams(self, maxChannels, maxUsers, maxTokens, maxPduSize): @@ -336,7 +330,7 @@ class MCS(LayerAutomata): def readMCSPDUHeader(self, opcode, mcsPdu): """ Read mcsPdu header and return options parameter - @param opcode: UInt8 opcode + @param opcode: opcode @param mcsPdu: mcsPdu will be checked @return: true if opcode is correct """ diff --git a/rdpy/protocol/rdp/pdu.py b/rdpy/protocol/rdp/pdu.py index 60323df..cae96c3 100644 --- a/rdpy/protocol/rdp/pdu.py +++ b/rdpy/protocol/rdp/pdu.py @@ -1,6 +1,27 @@ -''' -@author: citronneur -''' +# +# Copyright (c) 2014 Sylvain Peyrefitte +# +# This file is part of rdpy. +# +# rdpy 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 3 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, see . +# + +""" +Implement the main graphic layer + +In this layer are managed all mains bitmap update orders end user inputs +""" from rdpy.network.layer import LayerAutomata from rdpy.network.type import CompositeType, UniString, String, UInt8, UInt16Le, UInt32Le, sizeof, ArrayType, FactoryType @@ -12,18 +33,18 @@ import gcc, lic, caps @ConstAttributes @TypeAttributes(UInt16Le) class SecurityFlag(object): - ''' - microsoft security flags - ''' + """ + Microsoft security flags + """ SEC_INFO_PKT = 0x0040 SEC_LICENSE_PKT = 0x0080 @ConstAttributes @TypeAttributes(UInt32Le) class InfoFlag(object): - ''' - client capabilities informations - ''' + """ + Client capabilities informations + """ INFO_MOUSE = 0x00000001 INFO_DISABLECTRLALTDEL = 0x00000002 INFO_AUTOLOGON = 0x00000008 @@ -47,9 +68,9 @@ class InfoFlag(object): @ConstAttributes @TypeAttributes(UInt32Le) class PerfFlag(object): - ''' - network performances flag - ''' + """ + Network performances flag + """ PERF_DISABLE_WALLPAPER = 0x00000001 PERF_DISABLE_FULLWINDOWDRAG = 0x00000002 PERF_DISABLE_MENUANIMATIONS = 0x00000004 @@ -62,16 +83,19 @@ class PerfFlag(object): @ConstAttributes @TypeAttributes(UInt16Le) class AfInet(object): + """ + IPv4 or IPv6 adress style + """ AF_INET = 0x00002 AF_INET6 = 0x0017 @ConstAttributes @TypeAttributes(UInt16Le) class PDUType(object): - ''' - data pdu type primary index + """ + Data PDU type primary index @see: http://msdn.microsoft.com/en-us/library/cc240576.aspx - ''' + """ PDUTYPE_DEMANDACTIVEPDU = 0x11 PDUTYPE_CONFIRMACTIVEPDU = 0x13 PDUTYPE_DEACTIVATEALLPDU = 0x16 @@ -81,10 +105,10 @@ class PDUType(object): @ConstAttributes @TypeAttributes(UInt8) class PDUType2(object): - ''' - data pdu type secondary index + """ + Data PDU type secondary index @see: http://msdn.microsoft.com/en-us/library/cc240577.aspx - ''' + """ PDUTYPE2_UPDATE = 0x02 PDUTYPE2_CONTROL = 0x14 PDUTYPE2_POINTER = 0x1B @@ -113,10 +137,10 @@ class PDUType2(object): @ConstAttributes @TypeAttributes(UInt8) class StreamId(object): - ''' - stream priority + """ + Stream priority @see: http://msdn.microsoft.com/en-us/library/cc240577.aspx - ''' + """ STREAM_UNDEFINED = 0x00 STREAM_LOW = 0x01 STREAM_MED = 0x02 @@ -125,10 +149,10 @@ class StreamId(object): @ConstAttributes @TypeAttributes(UInt8) class CompressionOrder(object): - ''' - pdu compression order + """ + PDU compression order @see: http://msdn.microsoft.com/en-us/library/cc240577.aspx - ''' + """ CompressionTypeMask = 0x0F PACKET_COMPRESSED = 0x20 PACKET_AT_FRONT = 0x40 @@ -137,10 +161,10 @@ class CompressionOrder(object): @ConstAttributes @TypeAttributes(UInt8) class CompressionType(object): - ''' - pdu compression type + """ + PDU compression type @see: http://msdn.microsoft.com/en-us/library/cc240577.aspx - ''' + """ PACKET_COMPR_TYPE_8K = 0x0 PACKET_COMPR_TYPE_64K = 0x1 PACKET_COMPR_TYPE_RDP6 = 0x2 @@ -149,10 +173,10 @@ class CompressionType(object): @ConstAttributes @TypeAttributes(UInt16Le) class Action(object): - ''' + """ Action flag use in Control PDU packet @see: http://msdn.microsoft.com/en-us/library/cc240492.aspx - ''' + """ CTRLACTION_REQUEST_CONTROL = 0x0001 CTRLACTION_GRANTED_CONTROL = 0x0002 CTRLACTION_DETACH = 0x0003 @@ -161,30 +185,30 @@ class Action(object): @ConstAttributes @TypeAttributes(UInt16Le) class PersistentKeyListFlag(object): - ''' - use to determine the number of persistent key packet + """ + Use to determine the number of persistent key packet @see: http://msdn.microsoft.com/en-us/library/cc240495.aspx - ''' + """ PERSIST_FIRST_PDU = 0x01 PERSIST_LAST_PDU = 0x02 @ConstAttributes @TypeAttributes(UInt16Le) class BitmapFlag(object): - ''' - use in bitmap update PDU + """ + Use in bitmap update PDU @see: http://msdn.microsoft.com/en-us/library/cc240612.aspx - ''' + """ BITMAP_COMPRESSION = 0x0001 NO_BITMAP_COMPRESSION_HDR = 0x0400 @ConstAttributes @TypeAttributes(UInt16Le) class UpdateType(object): - ''' - use in update pdu to determine which type of update + """ + Use in update PDU to determine which type of update @see: http://msdn.microsoft.com/en-us/library/cc240608.aspx - ''' + """ UPDATETYPE_ORDERS = 0x0000 UPDATETYPE_BITMAP = 0x0001 UPDATETYPE_PALETTE = 0x0002 @@ -193,10 +217,10 @@ class UpdateType(object): @ConstAttributes @TypeAttributes(UInt32Le) class ErrorInfo(object): - ''' - Error code use in Error info pdu + """ + Error code use in Error info PDU @see: http://msdn.microsoft.com/en-us/library/cc240544.aspx - ''' + """ ERRINFO_RPC_INITIATED_DISCONNECT = 0x00000001 ERRINFO_RPC_INITIATED_LOGOFF = 0x00000002 ERRINFO_IDLE_TIMEOUT = 0x00000003 @@ -404,11 +428,11 @@ class ErrorInfo(object): } class RDPInfo(CompositeType): - ''' - client informations - contains credentials (very important packet) + """ + Client informations + Contains credentials (very important packet) @see: http://msdn.microsoft.com/en-us/library/cc240475.aspx - ''' + """ def __init__(self, extendedInfoConditional): CompositeType.__init__(self) #code page @@ -431,10 +455,10 @@ class RDPInfo(CompositeType): self.extendedInfo = RDPExtendedInfo(conditional = extendedInfoConditional) class RDPExtendedInfo(CompositeType): - ''' - add more client informations - use for performance flag!!! - ''' + """ + Add more client informations + Use for performance flag!!! + """ def __init__(self, conditional): CompositeType.__init__(self, conditional = conditional) self.clientAddressFamily = AfInet.AF_INET @@ -446,10 +470,10 @@ class RDPExtendedInfo(CompositeType): #self.performanceFlags = PerfFlag.PERF_DISABLE_WALLPAPER | PerfFlag.PERF_DISABLE_MENUANIMATIONS | PerfFlag.PERF_DISABLE_CURSOR_SHADOW class ShareControlHeader(CompositeType): - ''' + """ PDU share control header @see: http://msdn.microsoft.com/en-us/library/cc240576.aspx - ''' + """ def __init__(self, totalLength, pduType, userId): ''' constructor @@ -462,10 +486,10 @@ class ShareControlHeader(CompositeType): self.PDUSource = UInt16Le(userId.value + 1001) class ShareDataHeader(CompositeType): - ''' + """ PDU share data header @see: http://msdn.microsoft.com/en-us/library/cc240577.aspx - ''' + """ def __init__(self, size, pduType2 = None, userId = UInt16Le(), shareId = UInt32Le()): CompositeType.__init__(self) self.shareControlHeader = ShareControlHeader(size, PDUType.PDUTYPE_DATAPDU, userId) @@ -478,10 +502,10 @@ class ShareDataHeader(CompositeType): self.compressedLength = UInt16Le() class DemandActivePDU(CompositeType): - ''' + """ @see: http://msdn.microsoft.com/en-us/library/cc240485.aspx - main use for capabilities exchange server -> client - ''' + Main use for capabilities exchange server -> client + """ def __init__(self, userId = UInt16Le()): CompositeType.__init__(self) self.shareControlHeader = ShareControlHeader(lambda:sizeof(self), PDUType.PDUTYPE_DEMANDACTIVEPDU, userId) @@ -495,10 +519,10 @@ class DemandActivePDU(CompositeType): self.sessionId = UInt32Le() class ConfirmActivePDU(CompositeType): - ''' + """ @see: http://msdn.microsoft.com/en-us/library/cc240488.aspx - main use for capabilities confirm client -> sever - ''' + Main use for capabilities confirm client -> sever + """ def __init__(self, userId = UInt16Le()): CompositeType.__init__(self) self.shareControlHeader = ShareControlHeader(lambda:sizeof(self), PDUType.PDUTYPE_CONFIRMACTIVEPDU, userId) @@ -512,21 +536,21 @@ class ConfirmActivePDU(CompositeType): self.capabilitySets = ArrayType(caps.Capability, readLen = self.numberCapabilities) class PersistentListEntry(CompositeType): - ''' - use to record persistent key in PersistentListPDU + """ + Use to record persistent key in PersistentListPDU @see: http://msdn.microsoft.com/en-us/library/cc240496.aspx - ''' + """ def __init__(self): CompositeType.__init__(self) self.key1 = UInt32Le() self.key2 = UInt32Le() class PersistentListPDU(CompositeType): - ''' + """ Use to indicate that bitmap cache was already - fill with some keys from previous session + Fill with some keys from previous session @see: http://msdn.microsoft.com/en-us/library/cc240495.aspx - ''' + """ def __init__(self, userId = UInt16Le(), shareId = UInt32Le()): CompositeType.__init__(self) self.shareDataHeader = ShareDataHeader(lambda:sizeof(self), PDUType2.PDUTYPE2_BITMAPCACHE_PERSISTENT_LIST, userId, shareId) @@ -546,9 +570,9 @@ class PersistentListPDU(CompositeType): self.entries = ArrayType(PersistentListEntry, readLen = UInt16Le(lambda:(self.numEntriesCache0 + self.numEntriesCache1 + self.numEntriesCache2 + self.numEntriesCache3 + self.numEntriesCache4))) class DataPDU(CompositeType): - ''' + """ Generic pdu packet use after connection sequence - ''' + """ def __init__(self, pduType = None, pduData = None, userId = UInt16Le(), shareId = UInt32Le()): CompositeType.__init__(self) self.shareDataHeader = ShareDataHeader(lambda:sizeof(self), pduType, userId, shareId) @@ -576,18 +600,18 @@ class DataPDU(CompositeType): self.pduData = FactoryType(pduData) class SynchronizeDataPDU(CompositeType): - ''' + """ @see http://msdn.microsoft.com/en-us/library/cc240490.aspx - ''' + """ def __init__(self, targetUser = UInt16Le()): CompositeType.__init__(self) self.messageType = UInt16Le(1, constant = True) self.targetUser = targetUser class ControlDataPDU(CompositeType): - ''' + """ @see http://msdn.microsoft.com/en-us/library/cc240492.aspx - ''' + """ def __init__(self, action = None): CompositeType.__init__(self) self.action = UInt16Le(action.value, constant = True) if not action is None else UInt16Le() @@ -595,21 +619,21 @@ class ControlDataPDU(CompositeType): self.controlId = UInt32Le() class ErrorInfoDataPDU(CompositeType): - ''' + """ Use to inform error in PDU layer @see: http://msdn.microsoft.com/en-us/library/cc240544.aspx - ''' + """ def __init__(self, errorInfo = UInt32Le()): CompositeType.__init__(self) #use to collect error info pdu self.errorInfo = errorInfo class FontListDataPDU(CompositeType): - ''' + """ Use to indicate list of font. Deprecated packet client -> server @see: http://msdn.microsoft.com/en-us/library/cc240498.aspx - ''' + """ def __init__(self): CompositeType.__init__(self) self.numberFonts = UInt16Le() @@ -618,11 +642,11 @@ class FontListDataPDU(CompositeType): self.entrySize = UInt16Le(0x0032) class FontMapDataPDU(CompositeType): - ''' + """ Use to indicate map of font. Deprecated packet (maybe the same as FontListDataPDU) server -> client @see: http://msdn.microsoft.com/en-us/library/cc240498.aspx - ''' + """ def __init__(self): CompositeType.__init__(self) self.numberEntries = UInt16Le() @@ -631,11 +655,11 @@ class FontMapDataPDU(CompositeType): self.entrySize = UInt16Le(0x0004) class UpdateDataPDU(CompositeType): - ''' - Update data pdu use by server to inform update img or palette + """ + Update data PDU use by server to inform update img or palette for example @see: http://msdn.microsoft.com/en-us/library/cc240608.aspx - ''' + """ def __init__(self, updateType = UInt16Le(), updateData = None): CompositeType.__init__(self) self.updateType = updateType @@ -652,20 +676,20 @@ class UpdateDataPDU(CompositeType): self.updateData = FactoryType(updateData, conditional = lambda:(self.updateType != UpdateType.UPDATETYPE_SYNCHRONIZE)) class BitmapUpdateDataPDU(CompositeType): - ''' + """ PDU use to send raw bitmap compressed or not @see: http://msdn.microsoft.com/en-us/library/dd306368.aspx - ''' + """ def __init__(self): CompositeType.__init__(self) self.numberRectangles = UInt16Le() self.rectangles = ArrayType(BitmapData, readLen = self.numberRectangles) class BitmapCompressedDataHeader(CompositeType): - ''' + """ Compressed header of bitmap @see: http://msdn.microsoft.com/en-us/library/cc240644.aspx - ''' + """ def __init__(self, conditional = lambda:True): CompositeType.__init__(self, conditional = conditional) self.cbCompFirstRowSize = UInt16Le(0x0000, constant = True) @@ -676,9 +700,9 @@ class BitmapCompressedDataHeader(CompositeType): self.cbUncompressedSize = UInt16Le() class BitmapData(CompositeType): - ''' + """ Bitmap data here the screen capture - ''' + """ def __init__(self): CompositeType.__init__(self) self.destLeft = UInt16Le() @@ -694,16 +718,15 @@ class BitmapData(CompositeType): self.bitmapDataStream = String(readLen = UInt16Le(lambda:(self.bitmapLength.value if (self.flags | BitmapFlag.NO_BITMAP_COMPRESSION_HDR) else self.bitmapComprHdr.cbCompMainBodySize.value))) class PDU(LayerAutomata): - ''' + """ Global channel for mcs that handle session identification user, licensing management, and capabilities exchange - ''' + """ def __init__(self, mode, controller): - ''' - Constructor + """ @param mode: LayerMode @param controller: controller use to inform orders - ''' + """ LayerAutomata.__init__(self, mode, None) #logon info send from client to server self._info = RDPInfo(extendedInfoConditional = lambda:self._transport.getGCCServerSettings().core.rdpVersion == gcc.Version.RDP_VERSION_5_PLUS) @@ -745,26 +768,32 @@ class PDU(LayerAutomata): self._controller = controller def connect(self): - ''' - connect event in client mode send logon info - next state recv licence pdu - ''' + """ + Connect event in client mode send logon info + Next state recv licence pdu + """ self.sendInfoPkt() #next state is licence info PDU self.setNextState(self.recvLicenceInfo) + def close(self): + """ + Send PDU close packet and call close method on transport method + """ + self._transport.send(ShareDataHeader(PDUType2.PDUTYPE2_SHUTDOWN_REQUEST, UInt16Le(self._transport.getUserId()), self._shareId)) + def sendInfoPkt(self): - ''' - send a logon info packet - ''' + """ + Send a logon info packet + """ #always send extended info because rdpy only accept rdp version 5 and more self._transport.send((SecurityFlag.SEC_INFO_PKT, UInt16Le(), self._info)) def recvLicenceInfo(self, data): - ''' - read license info packet and check if is a valid client info + """ + Read license info packet and check if is a valid client info @param data: Stream - ''' + """ securityFlag = UInt16Le() securityFlagHi = UInt16Le() data.readType((securityFlag, securityFlagHi)) @@ -784,11 +813,11 @@ class PDU(LayerAutomata): self.setNextState(self.recvDemandActivePDU) def readDataPDU(self, data): - ''' + """ Read a DataPdu struct. If is an error pdu log and close layer @param data: Stream from transport layer @return: - ''' + """ #maybe an error message dataPDU = DataPDU() data.readType(dataPDU) @@ -803,13 +832,13 @@ class PDU(LayerAutomata): def recvDemandActivePDU(self, data): - ''' - receive demand active PDU which contains - server capabilities. In this version of RDPY only - restricted group of capabilities are used. - send confirm active PDU + """ + Receive demand active PDU which contains + Server capabilities. In this version of RDPY only + Restricted group of capabilities are used. + Send confirm active PDU @param data: Stream - ''' + """ demandActivePDU = DemandActivePDU() data.readType(demandActivePDU) @@ -821,40 +850,40 @@ class PDU(LayerAutomata): self.sendConfirmActivePDU() def recvServerSynchronizePDU(self, data): - ''' - receive from server + """ + Receive from server @param data: Stream from transport layer - ''' + """ dataPDU = self.readDataPDU(data) if dataPDU.shareDataHeader.pduType2 != PDUType2.PDUTYPE2_SYNCHRONIZE: raise InvalidExpectedDataException("Error in PDU layer automata : expected synchronizePDU") self.setNextState(self.recvServerControlCooperatePDU) def recvServerControlCooperatePDU(self, data): - ''' - receive control cooperate pdu from server + """ + Receive control cooperate pdu from server @param data: Stream from transport layer - ''' + """ dataPDU = self.readDataPDU(data) if dataPDU.shareDataHeader.pduType2 != PDUType2.PDUTYPE2_CONTROL or dataPDU.pduData._value.action != Action.CTRLACTION_COOPERATE: raise InvalidExpectedDataException("Error in PDU layer automata : expected controlCooperatePDU") self.setNextState(self.recvServerControlGrantedPDU) def recvServerControlGrantedPDU(self, data): - ''' - receive last control pdu the granted control pdu + """ + Receive last control pdu the granted control pdu @param data: Stream from transport layer - ''' + """ dataPDU = self.readDataPDU(data) if dataPDU.shareDataHeader.pduType2 != PDUType2.PDUTYPE2_CONTROL or dataPDU.pduData._value.action != Action.CTRLACTION_GRANTED_CONTROL: raise InvalidExpectedDataException("Error in PDU layer automata : expected controlGrantedPDU") self.setNextState(self.recvServerFontMapPDU) def recvServerFontMapPDU(self, data): - ''' - last useless connection packet from server to client + """ + Last useless connection packet from server to client @param data: Stream from transport layer - ''' + """ dataPDU = self.readDataPDU(data) if dataPDU.shareDataHeader.pduType2 != PDUType2.PDUTYPE2_FONTMAP: raise InvalidExpectedDataException("Error in PDU layer automata : expected fontMapPDU") @@ -864,19 +893,19 @@ class PDU(LayerAutomata): self.setNextState(self.recvDataPDU) def recvDataPDU(self, data): - ''' - main receive function after connection sequence + """ + Main receive function after connection sequence @param data: Stream from transport layer - ''' + """ dataPDU = self.readDataPDU(data) if dataPDU.shareDataHeader.pduType2 == PDUType2.PDUTYPE2_UPDATE and dataPDU.pduData._value.updateType == UpdateType.UPDATETYPE_BITMAP: self._controller.recvBitmapUpdateDataPDU(dataPDU.pduData._value.updateData._value) def sendConfirmActivePDU(self): - ''' - send all client capabilities - ''' + """ + Send all client capabilities + """ #init general capability generalCapability = self._clientCapabilities[caps.CapsType.CAPSTYPE_GENERAL].capability._value generalCapability.osMajorType = caps.MajorType.OSMAJORTYPE_WINDOWS @@ -903,7 +932,7 @@ class PDU(LayerAutomata): inputCapability.imeFileName = self._transport.getGCCClientSettings().core.imeFileName #make active PDU packet - confirmActivePDU = ConfirmActivePDU(self._transport.getUserId()) + confirmActivePDU = ConfirmActivePDU(UInt16Le(self._transport.getUserId())) confirmActivePDU.shareId = self._shareId confirmActivePDU.capabilitySets._array = self._clientCapabilities.values() self._transport.send(confirmActivePDU) @@ -911,18 +940,18 @@ class PDU(LayerAutomata): self.sendClientFinalizeSynchronizePDU() def sendClientFinalizeSynchronizePDU(self): - ''' + """ send a synchronize PDU from client to server - ''' - synchronizePDU = DataPDU(PDUType2.PDUTYPE2_SYNCHRONIZE, SynchronizeDataPDU(UInt16Le(self._transport.getChannelId().value)), self._transport.getUserId(), self._shareId) + """ + synchronizePDU = DataPDU(PDUType2.PDUTYPE2_SYNCHRONIZE, SynchronizeDataPDU(UInt16Le(self._transport.getChannelId())), UInt16Le(self._transport.getUserId()), self._shareId) self._transport.send(synchronizePDU) #ask for cooperation - controlCooperatePDU = DataPDU(PDUType2.PDUTYPE2_CONTROL, ControlDataPDU(Action.CTRLACTION_COOPERATE), self._transport.getUserId(), self._shareId) + controlCooperatePDU = DataPDU(PDUType2.PDUTYPE2_CONTROL, ControlDataPDU(Action.CTRLACTION_COOPERATE), UInt16Le(self._transport.getUserId()), self._shareId) self._transport.send(controlCooperatePDU) #request control - controlRequestPDU = DataPDU(PDUType2.PDUTYPE2_CONTROL, ControlDataPDU(Action.CTRLACTION_REQUEST_CONTROL), self._transport.getUserId(), self._shareId) + controlRequestPDU = DataPDU(PDUType2.PDUTYPE2_CONTROL, ControlDataPDU(Action.CTRLACTION_REQUEST_CONTROL), UInt16Le(self._transport.getUserId()), self._shareId) self._transport.send(controlRequestPDU) #send persistent list pdu I don't know why this packet is rejected maybe beacause we made a 0 size bitmapcache capability @@ -931,7 +960,7 @@ class PDU(LayerAutomata): #self._transport.send(persistentListPDU) #deprecated font list pdu - fontListPDU = DataPDU(PDUType2.PDUTYPE2_FONTLIST, FontListDataPDU(), self._transport.getUserId(), self._shareId) + fontListPDU = DataPDU(PDUType2.PDUTYPE2_FONTLIST, FontListDataPDU(), UInt16Le(self._transport.getUserId()), self._shareId) self._transport.send(fontListPDU) self.setNextState(self.recvServerSynchronizePDU) diff --git a/rdpy/protocol/rdp/tpdu.py b/rdpy/protocol/rdp/tpdu.py index 31a3658..324f371 100644 --- a/rdpy/protocol/rdp/tpdu.py +++ b/rdpy/protocol/rdp/tpdu.py @@ -18,22 +18,19 @@ # """ -Implement transport pdu layer +Implement transport PDU layer -This layer have main goal to negociate ssl transport +This layer have main goal to negociate SSL transport RDP basic security is not supported by RDPY (because is not a true security layer...) """ from rdpy.network.layer import LayerAutomata, LayerMode, StreamSender from rdpy.network.type import UInt8, UInt16Le, UInt16Be, UInt32Le, CompositeType, sizeof from rdpy.network.error import InvalidExpectedDataException -from rdpy.network.const import ConstAttributes, TypeAttributes -@ConstAttributes -@TypeAttributes(UInt8) class MessageType(object): """ - message type + Message type """ X224_TPDU_CONNECTION_REQUEST = 0xE0 X224_TPDU_CONNECTION_CONFIRM = 0xD0 @@ -41,32 +38,26 @@ class MessageType(object): X224_TPDU_DATA = 0xF0 X224_TPDU_ERROR = 0x70 -@ConstAttributes -@TypeAttributes(UInt8) class NegociationType(object): """ - negotiation header + Negotiation header """ TYPE_RDP_NEG_REQ = 0x01 TYPE_RDP_NEG_RSP = 0x02 TYPE_RDP_NEG_FAILURE = 0x03 -@ConstAttributes -@TypeAttributes(UInt32Le) class Protocols(object): """ - protocols available for TPDU layer + Protocols available for TPDU layer """ PROTOCOL_RDP = 0x00000000 PROTOCOL_SSL = 0x00000001 PROTOCOL_HYBRID = 0x00000002 PROTOCOL_HYBRID_EX = 0x00000008 - -@ConstAttributes -@TypeAttributes(UInt32Le) + class NegotiationFailureCode(object): """ - protocol negotiation failure code + Protocol negotiation failure code """ SSL_REQUIRED_BY_SERVER = 0x00000001 SSL_NOT_ALLOWED_BY_SERVER = 0x00000002 @@ -77,7 +68,7 @@ class NegotiationFailureCode(object): class TPDUConnectMessage(CompositeType): """ - header of TPDU connection messages + Header of TPDU connection messages """ def __init__(self, code): """ @@ -85,24 +76,24 @@ class TPDUConnectMessage(CompositeType): """ CompositeType.__init__(self) self.len = UInt8(lambda:sizeof(self) - 1) - self.code = UInt8(code.value, constant = True) + self.code = UInt8(code, constant = True) self.padding = (UInt16Be(), UInt16Be(), UInt8()) #read if there is enough data self.protocolNeg = Negotiation(optional = True) class TPDUDataHeader(CompositeType): """ - header send when tpdu exchange application data + Header send when TPDU exchange application data """ def __init__(self): CompositeType.__init__(self) self.header = UInt8(2, constant = True) - self.messageType = UInt8(MessageType.X224_TPDU_DATA.value, constant = True) + self.messageType = UInt8(MessageType.X224_TPDU_DATA, constant = True) self.separator = UInt8(0x80, constant = True) class Negotiation(CompositeType): """ - negociate request message + Negociate request message @see: request -> http://msdn.microsoft.com/en-us/library/cc240500.aspx @see: response -> http://msdn.microsoft.com/en-us/library/cc240506.aspx @see: failure ->http://msdn.microsoft.com/en-us/library/cc240507.aspx @@ -113,8 +104,8 @@ class Negotiation(CompositeType): self.flag = UInt8(0) #always 8 self.len = UInt16Le(0x0008, constant = True) - self.selectedProtocol = UInt32Le(conditional = lambda: self.code == NegociationType.TYPE_RDP_NEG_RSP) - self.failureCode = UInt32Le(conditional = lambda: self.code == NegociationType.TYPE_RDP_NEG_FAILURE) + self.selectedProtocol = UInt32Le(conditional = lambda: (self.code.value != NegociationType.TYPE_RDP_NEG_FAILURE)) + self.failureCode = UInt32Le(conditional = lambda: (self.code.value == NegociationType.TYPE_RDP_NEG_FAILURE)) class TPDU(LayerAutomata, StreamSender): """ @@ -134,15 +125,15 @@ class TPDU(LayerAutomata, StreamSender): #server selected selectedProtocol self._selectedProtocol = Protocols.PROTOCOL_SSL - #Server mode informations for tls connexion + #Server mode informations for TLS connection self._serverPrivateKeyFileName = None self._serverCertificateFileName = None def initTLSServerInfos(self, privateKeyFileName, certificateFileName): """ - Init informations for ssl server connexion + Initialize informations for SSL server connection @param privateKeyFileName: file contain server private key - @param certficiateFileName: file that contain publi key + @param certficiateFileName: file that contain public key """ self._serverPrivateKeyFileName = privateKeyFileName self._serverCertificateFileName = certificateFileName @@ -176,7 +167,7 @@ class TPDU(LayerAutomata, StreamSender): if message.protocolNeg.failureCode._is_readed: raise InvalidExpectedDataException("negotiation failure code %x"%message.protocolNeg.failureCode.value) - self._selectedProtocol = message.protocolNeg.selectedProtocol + self._selectedProtocol = message.protocolNeg.selectedProtocol.value if self._selectedProtocol != Protocols.PROTOCOL_SSL: raise InvalidExpectedDataException("only ssl protocol is supported in RDPY version") @@ -190,8 +181,8 @@ class TPDU(LayerAutomata, StreamSender): def recvConnectionRequest(self, data): """ - read connection confirm packet - next state is send connection confirm + Read connection confirm packet + Next state is send connection confirm @param data: Stream @see : http://msdn.microsoft.com/en-us/library/cc240470.aspx """ @@ -199,16 +190,16 @@ class TPDU(LayerAutomata, StreamSender): data.readType(message) if not message.protocolNeg._is_readed or message.protocolNeg.failureCode._is_readed: - raise InvalidExpectedDataException("Too older rdp client") + raise InvalidExpectedDataException("Too older RDP client") - self._requestedProtocol = message.protocolNeg.selectedProtocol + self._requestedProtocol = message.protocolNeg.selectedProtocol.value if not self._requestedProtocol & Protocols.PROTOCOL_SSL: #send error message and quit message = TPDUConnectMessage() - message.code = MessageType.X224_TPDU_CONNECTION_CONFIRM - message.protocolNeg.code = NegociationType.TYPE_RDP_NEG_FAILURE - message.protocolNeg.failureCode = NegotiationFailureCode.SSL_REQUIRED_BY_SERVER + message.code.value = MessageType.X224_TPDU_CONNECTION_CONFIRM + message.protocolNeg.code.value = NegociationType.TYPE_RDP_NEG_FAILURE + message.protocolNeg.failureCode.value = NegotiationFailureCode.SSL_REQUIRED_BY_SERVER self._transport.send(message) raise InvalidExpectedDataException("rdpy needs ssl client compliant") @@ -217,8 +208,8 @@ class TPDU(LayerAutomata, StreamSender): def recvData(self, data): """ - read data header from packet - and pass to presentation layer + Read data header from packet + And pass to presentation layer @param data: Stream """ header = TPDUDataHeader() @@ -227,25 +218,25 @@ class TPDU(LayerAutomata, StreamSender): def sendConnectionRequest(self): """ - write connection request message - next state is recvConnectionConfirm + Write connection request message + Next state is recvConnectionConfirm @see: http://msdn.microsoft.com/en-us/library/cc240500.aspx """ message = TPDUConnectMessage(MessageType.X224_TPDU_CONNECTION_REQUEST) - message.protocolNeg.code = NegociationType.TYPE_RDP_NEG_REQ - message.protocolNeg.selectedProtocol = self._requestedProtocol + message.protocolNeg.code.value = NegociationType.TYPE_RDP_NEG_REQ + message.protocolNeg.selectedProtocol.value = self._requestedProtocol self._transport.send(message) self.setNextState(self.recvConnectionConfirm) def sendConnectionConfirm(self): """ - write connection confirm message - next state is recvData + Write connection confirm message + Next state is recvData @see : http://msdn.microsoft.com/en-us/library/cc240501.aspx """ message = TPDUConnectMessage(MessageType.X224_TPDU_CONNECTION_CONFIRM) - message.protocolNeg.code = NegociationType.TYPE_RDP_NEG_REQ - message.protocolNeg.selectedProtocol = self._selectedProtocol + message.protocolNeg.code.value = NegociationType.TYPE_RDP_NEG_REQ + message.protocolNeg.selectedProtocol.value = self._selectedProtocol self._transport.send(message) #_transport is TPKT and transport is TCP layer of twisted self._transport.transport.startTLS(ServerTLSContext(self._serverPrivateKeyFileName, self._serverCertificateFileName)) @@ -254,8 +245,8 @@ class TPDU(LayerAutomata, StreamSender): def send(self, message): """ - write message packet for TPDU layer - add TPDU header + Write message packet for TPDU layer + Add TPDU header @param message: network.Type message """ self._transport.send((TPDUDataHeader(), message)) @@ -294,7 +285,7 @@ class ClientTLSContext(ssl.ClientContextFactory): class ServerTLSContext(ssl.DefaultOpenSSLContextFactory): """ - server context factory for open ssl + Server context factory for open ssl @param privateKeyFileName: Name of a file containing a private key @param certificateFileName: Name of a file containing a certificate """ diff --git a/rdpy/protocol/rdp/tpkt.py b/rdpy/protocol/rdp/tpkt.py index f1c4330..1a3271c 100644 --- a/rdpy/protocol/rdp/tpkt.py +++ b/rdpy/protocol/rdp/tpkt.py @@ -32,7 +32,7 @@ class TPKT(RawLayer): and determine if is a fast path packet """ #first byte of classic tpkt header - TPKT_PACKET = UInt8(3) + TPKT_PACKET = 3 def __init__(self, presentation): """ @@ -64,7 +64,7 @@ class TPKT(RawLayer): #first read packet version data.readType(self._lastPacketVersion) #classic packet - if self._lastPacketVersion == TPKT.TPKT_PACKET: + if self._lastPacketVersion.value == TPKT.TPKT_PACKET: #padding data.readType(UInt8()) #read end header @@ -122,4 +122,4 @@ class TPKT(RawLayer): send encompassed data @param message: network.Type message to send """ - RawLayer.send(self, (TPKT.TPKT_PACKET, UInt8(0), UInt16Be(sizeof(message) + 4), message)) \ No newline at end of file + RawLayer.send(self, (UInt8(TPKT.TPKT_PACKET), UInt8(0), UInt16Be(sizeof(message) + 4), message)) \ No newline at end of file diff --git a/rdpy/ui/qt4.py b/rdpy/ui/qt4.py index 2f38374..1ec8148 100644 --- a/rdpy/ui/qt4.py +++ b/rdpy/ui/qt4.py @@ -153,16 +153,23 @@ class RDPClientQt(RDPClientObserver, QAdaptor): if bitsPerPixel == 16: if isCompress: image = QtGui.QImage(width, height, QtGui.QImage.Format_RGB16) - data = rle.rle_decode_uint16(image.bits(), width, height, data, len(data)) + data = rle.bitmap_decompress(image.bits(), width, height, data, len(data), 2) else: image = QtGui.QImage(data, width, height, QtGui.QImage.Format_RGB16) elif bitsPerPixel == 24: if isCompress: - image = QtGui.QImage(width, height, QtGui.QImage.Format_RGB888) - data = rle.rle_decode_uint24(image.bits(), width, height, data, len(data)) + image = QtGui.QImage(width, height, QtGui.QImage.Format_RGB24) + data = rle.bitmap_decompress(image.bits(), width, height, data, len(data), 3) else: image = QtGui.QImage(data, width, height, QtGui.QImage.Format_RGB24) + + elif bitsPerPixel == 32: + if isCompress: + image = QtGui.QImage(width, height, QtGui.QImage.Format_RGB32) + data = rle.bitmap_decompress(image.bits(), width, height, data, len(data), 4) + else: + image = QtGui.QImage(data, width, height, QtGui.QImage.Format_RGB32) else: print "Receive image in bad format" return