diff options
author | sss <sss@dark-alexandr.net> | 2023-01-17 00:38:19 +0300 |
---|---|---|
committer | sss <sss@dark-alexandr.net> | 2023-01-17 00:38:19 +0300 |
commit | cc3f33db7a8d3c4ad373e646b199808e01bc5d9b (patch) | |
tree | ec09d690c7656ab5f2cc72607e05fb359c24d8b2 /src/rdp/rdp_io.c |
added webrdp public code
Diffstat (limited to 'src/rdp/rdp_io.c')
-rw-r--r-- | src/rdp/rdp_io.c | 1492 |
1 files changed, 1492 insertions, 0 deletions
diff --git a/src/rdp/rdp_io.c b/src/rdp/rdp_io.c new file mode 100644 index 0000000..5754997 --- /dev/null +++ b/src/rdp/rdp_io.c @@ -0,0 +1,1492 @@ +#include <freerdp/client/channels.h> +#include <freerdp/client/cliprdr.h> +#include <freerdp/client/cmdline.h> +#include <freerdp/client/file.h> +#include <freerdp/constants.h> +#include <freerdp/freerdp.h> +#include <freerdp/gdi/gdi.h> +#include <freerdp/log.h> +#include <winpr/crt.h> +#include <winpr/synch.h> + +#include <webrdp_core_api.h> +#include <webrdp_module_api.h> + +#include "rdp_backend_api.h" +#include "rdp_impl.h" +#include "rdp_png.h" + +const UINT32 ASCII_TO_SCANCODE[256] = { + 0, /* 0 */ + 0, /* 1 */ + 0, /* 2 */ + 0, /* 3 */ + 0, /* 4 */ + 0, /* 5 */ + 0, /* 6 */ + 0, /* 7 */ + RDP_SCANCODE_BACKSPACE, /* 8 */ + RDP_SCANCODE_TAB, /* 9 */ + VK_KEY_D, /* 10 */ + VK_KEY_F, /* 11 */ + VK_KEY_H, /* 12 */ + RDP_SCANCODE_RETURN, /* 13 */ + RDP_SCANCODE_BACKSPACE, /* 14 */ + VK_KEY_X, /* 15 */ + RDP_SCANCODE_LSHIFT, /* 16 */ + RDP_SCANCODE_LCONTROL, /* 17 */ + RDP_SCANCODE_LMENU, /* 18 */ + RDP_SCANCODE_PAUSE, /* 19 */ + RDP_SCANCODE_CAPSLOCK, /* 20 */ + VK_KEY_W, /* 21 */ + VK_KEY_E, /* 22 */ + VK_KEY_R, /* 23 */ + VK_KEY_Y, /* 24 */ + VK_KEY_A, /* 25 */ + VK_KEY_1, /* 26 */ + RDP_SCANCODE_ESCAPE, /* 27 */ + VK_KEY_3, /* 28 */ + VK_KEY_4, /* 29 */ + VK_KEY_6, /* 30 */ + VK_KEY_5, /* 31 */ + RDP_SCANCODE_SPACE, /* 32 */ + RDP_SCANCODE_PRIOR, /* 33 */ + RDP_SCANCODE_NEXT, /* 34 */ + RDP_SCANCODE_END, /* 35 */ + RDP_SCANCODE_HOME, /* 36 */ + RDP_SCANCODE_LEFT, /* 37 */ + RDP_SCANCODE_UP, /* 38 */ + RDP_SCANCODE_RIGHT, /* 39 */ + RDP_SCANCODE_DOWN, /* 40 */ + RDP_SCANCODE_KEY_0, /* 41 */ + RDP_SCANCODE_MULTIPLY, /* 42 */ + RDP_SCANCODE_ADD, /* 43 */ + RDP_SCANCODE_PRINTSCREEN, /* 44 */ + RDP_SCANCODE_INSERT, /* 45 */ + RDP_SCANCODE_DELETE, /* 46 */ + RDP_SCANCODE_DIVIDE, /* 47 */ + RDP_SCANCODE_KEY_0, /* 48 */ + RDP_SCANCODE_KEY_1, /* 49 */ + RDP_SCANCODE_KEY_2, /* 50 */ + RDP_SCANCODE_KEY_3, /* 51 */ + RDP_SCANCODE_KEY_4, /* 52 */ + RDP_SCANCODE_KEY_5, /* 53 */ + RDP_SCANCODE_KEY_6, /* 54 */ + RDP_SCANCODE_KEY_7, /* 55 */ + RDP_SCANCODE_KEY_8, /* 56 */ + RDP_SCANCODE_KEY_9, /* 57 */ + RDP_SCANCODE_OEM_1, /* 58 */ + RDP_SCANCODE_OEM_1, /* 59 */ + RDP_SCANCODE_OEM_COMMA, /* 60 */ + RDP_SCANCODE_OEM_PLUS, /* 61 */ + RDP_SCANCODE_OEM_PERIOD, /* 62 */ + RDP_SCANCODE_DIVIDE, /* 63 */ + RDP_SCANCODE_KEY_2, /* 64 */ + RDP_SCANCODE_KEY_A, /* 65 */ + RDP_SCANCODE_KEY_B, /* 66 */ + RDP_SCANCODE_KEY_C, /* 67 */ + RDP_SCANCODE_KEY_D, /* 68 */ + RDP_SCANCODE_KEY_E, /* 69 */ + RDP_SCANCODE_KEY_F, /* 70 */ + RDP_SCANCODE_KEY_G, /* 71 */ + RDP_SCANCODE_KEY_H, /* 72 */ + RDP_SCANCODE_KEY_I, /* 73 */ + RDP_SCANCODE_KEY_J, /* 74 */ + RDP_SCANCODE_KEY_K, /* 75 */ + RDP_SCANCODE_KEY_L, /* 76 */ + RDP_SCANCODE_KEY_M, /* 77 */ + RDP_SCANCODE_KEY_N, /* 78 */ + RDP_SCANCODE_KEY_O, /* 79 */ + RDP_SCANCODE_KEY_P, /* 80 */ + RDP_SCANCODE_KEY_Q, /* 81 */ + RDP_SCANCODE_KEY_R, /* 82 */ + RDP_SCANCODE_KEY_S, /* 83 */ + RDP_SCANCODE_KEY_T, /* 84 */ + RDP_SCANCODE_KEY_U, /* 85 */ + RDP_SCANCODE_KEY_V, /* 86 */ + RDP_SCANCODE_KEY_W, /* 87 */ + RDP_SCANCODE_KEY_X, /* 88 */ + RDP_SCANCODE_KEY_Y, /* 89 */ + RDP_SCANCODE_KEY_Z, /* 90 */ + RDP_SCANCODE_LWIN, /* 91 */ + RDP_SCANCODE_RWIN, /* 92 */ + RDP_SCANCODE_APPS, /* 93 */ + RDP_SCANCODE_KEY_6, /* 94 */ + RDP_SCANCODE_OEM_MINUS, /* 95 */ + RDP_SCANCODE_NUMPAD0, /* 96 */ + RDP_SCANCODE_NUMPAD1, /* 97 */ + RDP_SCANCODE_NUMPAD2, /* 98 */ + RDP_SCANCODE_NUMPAD3, /* 99 */ + RDP_SCANCODE_NUMPAD4, /* 100 */ + RDP_SCANCODE_NUMPAD5, /* 101 */ + RDP_SCANCODE_NUMPAD6, /* 102 */ + RDP_SCANCODE_NUMPAD7, /* 103 */ + RDP_SCANCODE_NUMPAD8, /* 104 */ + RDP_SCANCODE_NUMPAD9, /* 105 */ + RDP_SCANCODE_MULTIPLY, /* 106 */ + RDP_SCANCODE_ADD, /* 107 */ + 0, /* 108 */ + RDP_SCANCODE_SUBTRACT, /* 109 */ + RDP_SCANCODE_DELETE, /* 110 */ + RDP_SCANCODE_DIVIDE, /* 111 */ + RDP_SCANCODE_F1, /* 112 */ + RDP_SCANCODE_F2, /* 113 */ + RDP_SCANCODE_F3, /* 114 */ + RDP_SCANCODE_F4, /* 115 */ + RDP_SCANCODE_F5, /* 116 */ + RDP_SCANCODE_F6, /* 117 */ + RDP_SCANCODE_F7, /* 118 */ + RDP_SCANCODE_F8, /* 119 */ + RDP_SCANCODE_F9, /* 120 */ + RDP_SCANCODE_F10, /* 121 */ + RDP_SCANCODE_F11, /* 122 */ + RDP_SCANCODE_F12, /* 123 */ + RDP_SCANCODE_OEM_5, /* 124 */ + RDP_SCANCODE_OEM_6, /* 125 */ + VK_F4, /* 126 */ + VK_END, /* 127 */ + VK_F2, /* 128 */ + VK_NEXT, /* 129 */ + VK_F1, /* 130 */ + VK_LEFT, /* 131 */ + VK_RIGHT, /* 132 */ + VK_DOWN, /* 133 */ + VK_UP, /* 134 */ + 0, /* 135 */ + 0, /* 136 */ + 0, /* 137 */ + 0, /* 138 */ + 0, /* 139 */ + 0, /* 140 */ + 0, /* 141 */ + 0, /* 142 */ + 0, /* 143 */ + RDP_SCANCODE_NUMLOCK, /* 144 */ + RDP_SCANCODE_SCROLLLOCK, /* 145 */ + 0, /* 146 */ + 0, /* 147 */ + 0, /* 148 */ + 0, /* 149 */ + 0, /* 150 */ + 0, /* 151 */ + 0, /* 152 */ + 0, /* 153 */ + 0, /* 154 */ + 0, /* 155 */ + 0, /* 156 */ + 0, /* 157 */ + 0, /* 158 */ + 0, /* 159 */ + 0, /* 160 */ + 0, /* 161 */ + 0, /* 162 */ + 0, /* 163 */ + 0, /* 164 */ + 0, /* 165 */ + 0, /* 166 */ + 0, /* 167 */ + 0, /* 168 */ + 0, /* 169 */ + 0, /* 170 */ + 0, /* 171 */ + 0, /* 172 */ + RDP_SCANCODE_OEM_MINUS, /* 173 */ + 0, /* 174 */ + 0, /* 175 */ + 0, /* 176 */ + 0, /* 177 */ + 0, /* 178 */ + 0, /* 179 */ + 0, /* 180 */ + 0, /* 181 */ + 0, /* 182 */ + 0, /* 183 */ + 0, /* 184 */ + 0, /* 185 */ + RDP_SCANCODE_OEM_1, /* 186 */ + RDP_SCANCODE_OEM_PLUS, /* 187 */ + RDP_SCANCODE_OEM_COMMA, /* 188 */ + RDP_SCANCODE_OEM_MINUS, /* 189 */ + RDP_SCANCODE_OEM_PERIOD, /* 190 */ + RDP_SCANCODE_OEM_2, /* 191 */ + RDP_SCANCODE_OEM_3, /* 192 */ + 0, /* 193 */ + 0, /* 194 */ + 0, /* 195 */ + 0, /* 196 */ + 0, /* 197 */ + 0, /* 198 */ + 0, /* 199 */ + 0, /* 200 */ + 0, /* 201 */ + 0, /* 202 */ + 0, /* 203 */ + 0, /* 204 */ + 0, /* 205 */ + 0, /* 206 */ + 0, /* 207 */ + 0, /* 208 */ + 0, /* 209 */ + 0, /* 210 */ + 0, /* 211 */ + 0, /* 212 */ + 0, /* 213 */ + 0, /* 214 */ + 0, /* 215 */ + 0, /* 216 */ + 0, /* 217 */ + 0, /* 218 */ + RDP_SCANCODE_OEM_4, /* 219 */ + RDP_SCANCODE_OEM_5, /* 220 */ + RDP_SCANCODE_OEM_6, /* 221 */ + RDP_SCANCODE_OEM_7, /* 222 */ + 0, /* 223 */ + 0, /* 224 */ + 0, /* 225 */ + 0, /* 226 */ + 0, /* 227 */ + 0, /* 228 */ + 0, /* 229 */ + 0, /* 230 */ + 0, /* 231 */ + 0, /* 232 */ + 0, /* 233 */ + 0, /* 234 */ + 0, /* 235 */ + 0, /* 236 */ + 0, /* 237 */ + 0, /* 238 */ + 0, /* 239 */ + 0, /* 240 */ + 0, /* 241 */ + 0, /* 242 */ + 0, /* 243 */ + 0, /* 244 */ + 0, /* 245 */ + 0, /* 246 */ + 0, /* 247 */ + 0, /* 248 */ + 0, /* 249 */ + 0, /* 250 */ + 0, /* 251 */ + 0, /* 252 */ + 0, /* 253 */ + 0, /* 254 */ + 0 /* 255 */ +}; + +#define RGB_555_888(_r, _g, _b) \ + _r = (_r << 3 & ~0x7) | (_r >> 2); \ + _g = (_g << 3 & ~0x7) | (_g >> 2); \ + _b = (_b << 3 & ~0x7) | (_b >> 2); +#define RGB_565_888(_r, _g, _b) \ + _r = (_r << 3 & ~0x7) | (_r >> 2); \ + _g = (_g << 2 & ~0x3) | (_g >> 4); \ + _b = (_b << 3 & ~0x7) | (_b >> 2); +#define GetRGB_555(_r, _g, _b, _p) \ + _r = (_p & 0x7C00) >> 10; \ + _g = (_p & 0x3E0) >> 5; \ + _b = (_p & 0x1F); +#define GetRGB_565(_r, _g, _b, _p) \ + _r = (_p & 0xF800) >> 11; \ + _g = (_p & 0x7E0) >> 5; \ + _b = (_p & 0x1F); +#define GetRGB15(_r, _g, _b, _p) \ + GetRGB_555(_r, _g, _b, _p); \ + RGB_555_888(_r, _g, _b); +#define GetRGB16(_r, _g, _b, _p) \ + GetRGB_565(_r, _g, _b, _p); \ + RGB_565_888(_r, _g, _b); +#define RGB24(_r, _g, _b) ((_r << 16) | (_g << 8) | _b) +#define GetRGB24(_r, _g, _b, _p) \ + _r = (_p & 0xFF0000) >> 16; \ + _g = (_p & 0xFF00) >> 8; \ + _b = (_p & 0xFF); +#define GetRGB32(_r, _g, _b, _p) \ + _r = (_p & 0xFF0000) >> 16; \ + _g = (_p & 0xFF00) >> 8; \ + _b = (_p & 0xFF); +#define ARGB32(_a, _r, _g, _b) (_a << 24) | (_r << 16) | (_g << 8) | _b +#define RGB16(_r, _g, _b) \ + (((_r >> 3) & 0x1F) << 11) | (((_g >> 2) & 0x3F) << 5) \ + | ((_b >> 3) & 0x1F) +#define RGB15(_r, _g, _b) \ + (((_r >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) \ + | ((_b >> 3) & 0x1F) +#define GetARGB32(_a, _r, _g, _b, _p) \ + _a = (_p & 0xFF000000) >> 24; \ + _r = (_p & 0xFF0000) >> 16; \ + _g = (_p & 0xFF00) >> 8; \ + _b = (_p & 0xFF); + +static HCLRCONV +freerdp_clrconv_new(UINT32 flags) +{ + HCLRCONV clrconv; + + clrconv = (CLRCONV *)calloc(1, sizeof(CLRCONV)); + + if (!clrconv) + return NULL; + + clrconv->alpha = (flags & CLRCONV_ALPHA) ? TRUE : FALSE; + clrconv->invert = (flags & CLRCONV_INVERT) ? TRUE : FALSE; + clrconv->rgb555 = (flags & CLRCONV_RGB555) ? TRUE : FALSE; + + clrconv->palette = (rdpPalette *)calloc(1, sizeof(rdpPalette)); + + if (!clrconv->palette) + { + free(clrconv); + return NULL; + } + + return clrconv; +} + +static void +freerdp_clrconv_free(HCLRCONV clrconv) +{ + if (clrconv) + { + free(clrconv->palette); + free(clrconv); + } +} + +static int +freerdp_get_pixel(BYTE *data, int x, int y, int width, int height, int bpp) +{ + int start; + int shift; + UINT16 *src16; + UINT32 *src32; + int red, green, blue; + + switch (bpp) + { + case 1: + width = (width + 7) / 8; + start = (y * width) + x / 8; + shift = x % 8; + return (data[start] & (0x80 >> shift)) != 0; + case 8: + return data[y * width + x]; + case 15: + case 16: + src16 = (UINT16 *)data; + return src16[y * width + x]; + case 24: + data += y * width * 3; + data += x * 3; + red = data[0]; + green = data[1]; + blue = data[2]; + return RGB24(red, green, blue); + case 32: + src32 = (UINT32 *)data; + return src32[y * width + x]; + default: + break; + } + + return 0; +} + +static void +freerdp_set_pixel( + BYTE *data, int x, int y, int width, int height, int bpp, int pixel) +{ + int start; + int shift; + int *dst32; + + if (bpp == 1) + { + width = (width + 7) / 8; + start = (y * width) + x / 8; + shift = x % 8; + if (pixel) + data[start] = data[start] | (0x80 >> shift); + else + data[start] = data[start] & ~(0x80 >> shift); + } + else if (bpp == 32) + { + dst32 = (int *)data; + dst32[y * width + x] = pixel; + } +} + +static void +freerdp_color_split_rgb(UINT32 *color, int bpp, BYTE *red, BYTE *green, + BYTE *blue, BYTE *alpha, HCLRCONV clrconv) +{ + *red = *green = *blue = 0; + *alpha = (clrconv->alpha) ? 0xFF : 0x00; + + switch (bpp) + { + case 32: + if (clrconv->alpha) + { + GetARGB32(*alpha, *red, *green, *blue, *color); + } + else + { + GetRGB32(*red, *green, *blue, *color); + } + break; + + case 24: + GetRGB24(*red, *green, *blue, *color); + break; + + case 16: + GetRGB16(*red, *green, *blue, *color); + break; + + case 15: + GetRGB15(*red, *green, *blue, *color); + break; + + case 8: + *color &= 0xFF; + *red = clrconv->palette->entries[*color].red; + *green = clrconv->palette->entries[*color].green; + *blue = clrconv->palette->entries[*color].blue; + break; + + case 1: + if (*color != 0) + { + *red = 0xFF; + *green = 0xFF; + *blue = 0xFF; + } + break; + + default: + break; + } +} + +static void +freerdp_color_make_rgb(UINT32 *color, int bpp, BYTE *red, BYTE *green, + BYTE *blue, BYTE *alpha, HCLRCONV clrconv) +{ + switch (bpp) + { + case 32: + *color = ARGB32(*alpha, *red, *green, *blue); + break; + + case 24: + *color = RGB24(*red, *green, *blue); + break; + + case 16: + if (clrconv->rgb555) + { + *color = RGB15(*red, *green, *blue); + } + else + { + *color = RGB16(*red, *green, *blue); + } + break; + + case 15: + *color = RGB15(*red, *green, *blue); + break; + + case 8: + *color = RGB24(*red, *green, *blue); + break; + + case 1: + if ((*red != 0) || (*green != 0) || (*blue != 0)) + *color = 1; + break; + + default: + break; + } +} + +static UINT32 +freerdp_color_convert_rgb( + UINT32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv) +{ + BYTE red = 0; + BYTE green = 0; + BYTE blue = 0; + BYTE alpha = 0xFF; + UINT32 dstColor = 0; + + freerdp_color_split_rgb( + &srcColor, srcBpp, &red, &green, &blue, &alpha, clrconv); + freerdp_color_make_rgb( + &dstColor, dstBpp, &red, &green, &blue, &alpha, clrconv); + + return dstColor; +} + +static void +freerdp_alpha_cursor_convert(BYTE *alphaData, BYTE *xorMask, BYTE *andMask, + int width, int height, int bpp, HCLRCONV clrconv) +{ + UINT32 xorPixel; + UINT32 andPixel; + UINT32 x, y, jj; + + for (y = 0; y < height; y++) + { + jj = (bpp == 1) ? y : (height - 1) - y; + + for (x = 0; x < width; x++) + { + xorPixel = freerdp_get_pixel( + xorMask, x, jj, width, height, bpp); + xorPixel = freerdp_color_convert_rgb( + xorPixel, bpp, 32, clrconv); + andPixel = freerdp_get_pixel( + andMask, x, jj, width, height, 1); + + if (andPixel) + { + if ((xorPixel & 0xFFFFFF) == 0xFFFFFF) + { + /* use pattern (not solid black) for xor + * area */ + xorPixel = (x & 1) == (y & 1); + xorPixel = xorPixel ? 0xFFFFFF : 0; + xorPixel |= 0xFF000000; + } + else if (xorPixel == 0xFF000000) + { + xorPixel = 0; + } + } + + freerdp_set_pixel( + alphaData, x, y, width, height, 32, xorPixel); + } + } +} + +static void +freerdp_bitmap_flip(BYTE *src, BYTE *dst, int scanLineSz, int height) +{ + int i; + + BYTE *bottomLine = dst + (scanLineSz * (height - 1)); + BYTE *topLine = src; + + /* Special processing if called for flip-in-place. */ + if (src == dst) + { + /* Allocate a scanline buffer. + * (FIXME: malloc / xfree below should be replaced by "get/put + * scanline buffer from a pool/Q of fixed buffers" to reuse + * fixed size buffers (of max scanline size (or adaptative?) ) + * -- would be much faster). + */ + BYTE *tmpBfr = (BYTE *)_aligned_malloc(scanLineSz, 16); + int half = height / 2; + /* Flip buffer in place by line permutations through the temp + * scan line buffer. + * Note that if height has an odd number of line, we don't need + * to move the center scanline anyway. + * Also note that in place flipping takes three memcpy() calls + * to process two scanlines while src to distinct dest would + * only requires two memcpy() calls for two scanlines. + */ + height--; + for (i = 0; i < half; i++) + { + CopyMemory(tmpBfr, topLine, scanLineSz); + CopyMemory(topLine, bottomLine, scanLineSz); + CopyMemory(bottomLine, tmpBfr, scanLineSz); + topLine += scanLineSz; + bottomLine -= scanLineSz; + height--; + } + _aligned_free(tmpBfr); + } + /* Flip from source buffer to destination buffer. */ + else + { + + for (i = 0; i < height; i++) + { + CopyMemory(bottomLine, topLine, scanLineSz); + topLine += scanLineSz; + bottomLine -= scanLineSz; + } + } +} + +static BYTE * +freerdp_image_flip(BYTE *srcData, BYTE *dstData, int width, int height, int bpp) +{ + int scanline; + + scanline = width * ((bpp + 7) / 8); + + if (!dstData) + dstData = (BYTE *)_aligned_malloc( + width * height * ((bpp + 7) / 8), 16); + + if (!dstData) + { + return NULL; + } + + freerdp_bitmap_flip(srcData, dstData, scanline, height); + + return dstData; +} + +/* outgoing rdp protocol to client implementation */ + +static BOOL +Pointer_New(rdpContext *context, rdpPointer *pointer) +{ + my_rdp_context *c = (my_rdp_context *)context; + HCLRCONV hclrconv = c->my_internals->clrconv; + size_t psize = pointer->width * pointer->height * 4; + + my_rdp_pointer *p = (my_rdp_pointer *)pointer; + p->id = c->my_internals->m_ptrId++; + uint8_t *pixels = malloc(sizeof(uint8_t) * psize); + memset(pixels, 0, psize); + if ((pointer->andMaskData != 0) && (pointer->xorMaskData != 0)) + { + //XXX + freerdp_alpha_cursor_convert(pixels, pointer->xorMaskData, + pointer->andMaskData, pointer->width, pointer->height, + pointer->xorBpp, hclrconv); + } + + //check if the cursor is fully transparent + bool transparent = TRUE; + for (int y = 0; y < pointer->height; y++) + { + for (int x = 0; x < pointer->width; x++) + { + if (pixels[0 + x * 4 + y * 4 * pointer->width] != 0) + { + transparent = FALSE; + } + } + } + if (transparent) + { + pixels[3] = 1; + } + + rdp_png_buf png_buf; + memset(&png_buf, 0, sizeof(png_buf)); + png_buf.buf_size + = (pointer->width * pointer->height * sizeof(uint32_t)) + + 8 /* allocating fullsize 32but argb pixels + png header */; + png_buf.buf = malloc(png_buf.buf_size); + png_generate_from_argb( + pointer->width, pointer->height, pixels, &png_buf); + + struct + { + unsigned char resL; //2 bytes reserved must always be 0 + unsigned char resH; + unsigned char imgTypeL; //2 bytes image type. 1 = ICO, 2 = CUR + unsigned char imgTypeH; + unsigned char nbImgL; //2 bytes number of images + unsigned char nbImgH; + unsigned char width; //1 byte image width in pixels + unsigned char height; //1 byte image height in pixels + unsigned char nbColors; //1 bytenumber of colors. 0 if not using + //a color pallete + unsigned char res; //1 byte reserved, should be 0 + unsigned char xPosL; //2 bytes of hot spot x (for ICO, color + //planes, 0 or 1) + unsigned char xPosH; + unsigned char + yPosL; //2 bytes of hot spot y (for ICO bits per pixel) + unsigned char yPosH; + unsigned char sizeLL; //4 bytes of image size + unsigned char sizeLH; + unsigned char sizeHL; + unsigned char sizeHH; + unsigned char offsetLL; //4 bytes of offset of the data + unsigned char offsetLH; + unsigned char offsetHL; + unsigned char offsetHH; + } curHeader = {0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + (unsigned char)pointer->width, (unsigned char)pointer->height, 0x00, + 0x00, (unsigned char)pointer->xPos, + (unsigned char)(pointer->xPos >> 8), (unsigned char)pointer->yPos, + (unsigned char)(pointer->yPos >> 8), (unsigned char)png_buf.written, + (unsigned char)(png_buf.written >> 8), + (unsigned char)(png_buf.written >> 16), + (unsigned char)(png_buf.written >> 24), 0x16, 0x00, 0x00, 0x00}; + + size_t cursor_buf_size = png_buf.written + sizeof(curHeader); + uint8_t *cursor_buf = malloc(cursor_buf_size); + + memcpy(cursor_buf, &curHeader, sizeof(curHeader)); + memcpy(cursor_buf + sizeof(curHeader), png_buf.buf, png_buf.written); + free(png_buf.buf); + + /* rdp_cursor_add (p->id, cursor_buf, cursor_buf_size, + * c->my_internals); */ + + free(pixels); + struct + { + uint32_t id; + uint32_t hx; + uint32_t hy; + } tmp = {p->id, pointer->xPos, pointer->yPos}; + size_t send_buf_size = sizeof(tmp) + cursor_buf_size; + uint8_t *send_buf = malloc(send_buf_size); + memcpy(send_buf, &tmp, sizeof(tmp)); + memcpy(send_buf + sizeof(tmp), cursor_buf, cursor_buf_size); + free(cursor_buf); + c->my_internals->core->send_ptr_new( + send_buf, send_buf_size, c->my_internals->task_info); + return TRUE; +} + +static void +Pointer_Free(rdpContext *context, rdpPointer *pointer) +{ + my_rdp_pointer *p = (my_rdp_pointer *)pointer; + my_rdp_context *c = (my_rdp_context *)context; + if (p->id) + { + /* rdp_cursor_erase (p->id, c->my_internals); */ + c->my_internals->core->send_ptr_free((uint8_t *)&(p->id), + sizeof(uint32_t), c->my_internals->task_info); + } +} + +static BOOL +Pointer_Set(rdpContext *context, const rdpPointer *pointer) +{ + my_rdp_pointer *p = (my_rdp_pointer *)pointer; + my_rdp_context *c = (my_rdp_context *)context; + c->my_internals->core->send_ptr_set( + (uint8_t *)&(p->id), sizeof(uint32_t), c->my_internals->task_info); + return TRUE; +} + +static BOOL +Pointer_SetNull(rdpContext *context) +{ + my_rdp_context *c = (my_rdp_context *)context; + c->my_internals->core->send_ptr_set_null(c->my_internals->task_info); + return TRUE; +} + +static BOOL +Pointer_SetDefault(rdpContext *context) +{ + my_rdp_context *c = (my_rdp_context *)context; + c->my_internals->core->send_ptr_set_default(c->my_internals->task_info); + return TRUE; +} + +void +register_pointer(rdpPointer *p) +{ + p->New = Pointer_New; + p->Free = Pointer_Free; + p->Set = Pointer_Set; + p->SetNull = Pointer_SetNull; + p->SetDefault = Pointer_SetDefault; +} + +static BOOL +rdp_context_new(freerdp *instance, rdpContext *context) +{ + return TRUE; +} + +static void +rdp_context_free(freerdp *instance, rdpContext *context) +{ + my_rdp_context *c = (my_rdp_context *)context; + if (context->cache) + { + cache_free(context->cache); + context->cache = NULL; + } + if (c->my_internals->clrconv) + { + freerdp_clrconv_free(c->my_internals->clrconv); + c->my_internals->clrconv = NULL; + } +} + +static BOOL +BeginPaint(rdpContext *context) +{ + my_rdp_context *c = (my_rdp_context *)context; + c->my_internals->core->send_begin_paint(c->my_internals->task_info); + return TRUE; +} + +static BOOL +EndPaint(rdpContext *context) +{ + my_rdp_context *c = (my_rdp_context *)context; + c->my_internals->core->send_end_paint(c->my_internals->task_info); + return TRUE; +} + +static BOOL +SetBounds(rdpContext *context, const rdpBounds *bounds) +{ + my_rdp_context *c = (my_rdp_context *)context; + rdpBounds lB; + if (bounds) + { + memcpy(&lB, bounds, sizeof(rdpBounds)); + lB.right++; + lB.bottom++; + } + else + { + memset(&lB, 0, sizeof(rdpBounds)); + } + c->my_internals->core->send_set_bounds( + (uint8_t *)&lB, sizeof(lB), c->my_internals->task_info); + return TRUE; +} + +static BOOL +Synchronize(rdpContext *context) +{ + return TRUE; +} + +static BOOL +DesktopResize(rdpContext *context) +{ + my_rdp_context *c = (my_rdp_context *)context; + char buf[64]; + snprintf(buf, 63, "R:%dx%d", context->settings->DesktopWidth, + context->settings->DesktopHeight); + c->my_internals->core->send_text_msg(buf, c->my_internals->task_info); + return TRUE; +} + +static BOOL +BitmapUpdate(rdpContext *context, const BITMAP_UPDATE *bitmap) +{ + my_rdp_context *c = (my_rdp_context *)context; + int i; + BITMAP_DATA *bmd; + for (i = 0; i < (int)bitmap->number; i++) + { + bmd = &bitmap->rectangles[i]; + struct + { + uint32_t x; + uint32_t y; + uint32_t w; + uint32_t h; + uint32_t dw; + uint32_t dh; + uint32_t bpp; + uint32_t cf; + uint32_t sz; + } wxbm = {bmd->destLeft, bmd->destTop, bmd->width, bmd->height, + bmd->destRight - bmd->destLeft + 1, + bmd->destBottom - bmd->destTop + 1, bmd->bitsPerPixel, + (uint32_t)bmd->compressed, bmd->bitmapLength}; + if (!bmd->compressed) + { + freerdp_image_flip(bmd->bitmapDataStream, + bmd->bitmapDataStream, bmd->width, bmd->height, + bmd->bitsPerPixel); + } + size_t buf_size = sizeof(wxbm) + bmd->bitmapLength; + uint8_t *buf = malloc(buf_size); + memcpy(buf, &wxbm, sizeof(wxbm)); + memcpy(buf + sizeof(wxbm), bmd->bitmapDataStream, + bmd->bitmapLength); + c->my_internals->core->send_bitmap( + buf, buf_size, c->my_internals->task_info); + free(buf); + } + return TRUE; +} + +static BOOL +Palette(rdpContext *c, const PALETTE_UPDATE *p) +{ + return TRUE; +} + +static BOOL +PlaySound(rdpContext *c, const PLAY_SOUND_UPDATE *s) +{ + return TRUE; +} + +static BOOL +RefreshRect(rdpContext *c, UINT8 hz, const RECTANGLE_16 *r) +{ + return TRUE; +} + +static BOOL +SuppressOutput(rdpContext *c, UINT8 hz, const RECTANGLE_16 *r) +{ + return TRUE; +} + +/*static BOOL +SurfaceCommand(rdpContext* c, wStream* s) +{ + return TRUE; +}*/ + +static BOOL +SurfaceBits(rdpContext *c, const SURFACE_BITS_COMMAND *sbc) +{ + return TRUE; +} + +/*static BOOL +SurfaceFrameMarker(rdpContext* c, SURFACE_FRAME_MARKER* sfm) +{ + return TRUE; +} */ + +void +RegisterUpdate(freerdp *rdp) +{ + rdp->update->BeginPaint = BeginPaint; + rdp->update->EndPaint = EndPaint; + rdp->update->SetBounds = SetBounds; + rdp->update->Synchronize = Synchronize; + rdp->update->DesktopResize = DesktopResize; + rdp->update->BitmapUpdate = BitmapUpdate; + rdp->update->Palette = Palette; + rdp->update->PlaySound = PlaySound; + rdp->update->SurfaceBits = SurfaceBits; + + rdp->update->RefreshRect = RefreshRect; + rdp->update->SuppressOutput = SuppressOutput; +} + +static BOOL +DstBlt(rdpContext *c, const DSTBLT_ORDER *_do) +{ + return TRUE; +} + +static BOOL +PatBlt(rdpContext *ctx, PATBLT_ORDER *po) +{ + my_rdp_context *c = (my_rdp_context *)ctx; + uint32_t rop3 = gdi_rop3_code(po->bRop); + if (GDI_BS_SOLID == po->brush.style) + { + struct + { + int32_t x; + int32_t y; + int32_t w; + int32_t h; + uint32_t fg; + uint32_t rop; + } tmp = {po->nLeftRect, po->nTopRect, po->nWidth, po->nHeight, + ConvertColor(po->foreColor, PIXEL_FORMAT_BGR16, + PIXEL_FORMAT_ABGR32, + NULL), //XXX + rop3}; + c->my_internals->core->send_pat_blt( + (uint8_t *)&tmp, sizeof(tmp), c->my_internals->task_info); + } + return TRUE; +} + +static BOOL +ScrBlt(rdpContext *ctx, const SCRBLT_ORDER *sbo) +{ + my_rdp_context *c = (my_rdp_context *)ctx; + uint32_t rop3 = gdi_rop3_code(sbo->bRop); + struct + { + uint32_t rop; + int32_t x; + int32_t y; + int32_t w; + int32_t h; + int32_t sx; + int32_t sy; + } tmp = {rop3, sbo->nLeftRect, sbo->nTopRect, sbo->nWidth, sbo->nHeight, + sbo->nXSrc, sbo->nYSrc}; + c->my_internals->core->send_scr_blt( + (uint8_t *)&tmp, sizeof(tmp), c->my_internals->task_info); + return TRUE; +} + +static BOOL +OpaqueRect(rdpContext *context, const OPAQUE_RECT_ORDER *oro) +{ + my_rdp_context *c = (my_rdp_context *)context; + OPAQUE_RECT_ORDER oro2 = *oro; + oro2.color = ConvertColor( + oro2.color, PIXEL_FORMAT_BGR16, PIXEL_FORMAT_ABGR32, NULL); + c->my_internals->core->send_opaque_rect_order((uint8_t *)&oro2, + sizeof(OPAQUE_RECT_ORDER), c->my_internals->task_info); + return TRUE; +} + +static BOOL +DrawNineGrid(rdpContext *c, const DRAW_NINE_GRID_ORDER *dngo) +{ + return TRUE; +} + +static BOOL +MultiDstBlt(rdpContext *c, const MULTI_DSTBLT_ORDER *mdo) +{ + return TRUE; +} + +static BOOL +MultiPatBlt(rdpContext *c, const MULTI_PATBLT_ORDER *mpo) +{ + return TRUE; +} + +static BOOL +MultiScrBlt(rdpContext *c, const MULTI_SCRBLT_ORDER *mso) +{ + return TRUE; +} + +static BOOL +MultiOpaqueRect(rdpContext *context, const MULTI_OPAQUE_RECT_ORDER *moro) +{ + my_rdp_context *c = (my_rdp_context *)context; + uint32_t color = ConvertColor( + moro->color, PIXEL_FORMAT_BGR16, PIXEL_FORMAT_ABGR32, NULL); + uint32_t nr = moro->numRectangles; + size_t buf_size + = (sizeof(color) + sizeof(nr)) + (sizeof(DELTA_RECT) * nr); + uint8_t *buf = malloc(buf_size); + memcpy(buf, (uint8_t *)&color, sizeof(color)); + memcpy(buf + sizeof(color), (uint8_t *)&nr, sizeof(nr)); + memcpy(buf + (sizeof(color) + sizeof(color)), + (uint8_t *)&moro->rectangles[1], sizeof(DELTA_RECT) * nr); + c->my_internals->core->send_multi_opaque_rect( + buf, buf_size, c->my_internals->task_info); + free(buf); + return TRUE; +} + +static BOOL +MultiDrawNineGrid(rdpContext *c, const MULTI_DRAW_NINE_GRID_ORDER *mdngo) +{ + return TRUE; +} + +static BOOL +LineTo(rdpContext *c, const LINE_TO_ORDER *lto) +{ + return TRUE; +} + +static BOOL +Polyline(rdpContext *c, const POLYLINE_ORDER *po) +{ + return TRUE; +} + +static BOOL +MemBlt(rdpContext *c, MEMBLT_ORDER *mo) +{ + return TRUE; +} + +static BOOL +Mem3Blt(rdpContext *c, MEM3BLT_ORDER *mo) +{ + return TRUE; +} + +static BOOL +SaveBitmap(rdpContext *c, const SAVE_BITMAP_ORDER *sbo) +{ + return TRUE; +} + +static BOOL +GlyphIndex(rdpContext *c, GLYPH_INDEX_ORDER *gio) +{ + return TRUE; +} + +static BOOL +FastIndex(rdpContext *c, const FAST_INDEX_ORDER *fio) +{ + return TRUE; +} + +static BOOL +FastGlyph(rdpContext *c, const FAST_GLYPH_ORDER *fgo) +{ + return TRUE; +} + +static BOOL +PolygonSC(rdpContext *c, const POLYGON_SC_ORDER *pso) +{ + return TRUE; +} + +static BOOL +PolygonCB(rdpContext *c, POLYGON_CB_ORDER *pco) +{ + return TRUE; +} + +static BOOL +EllipseSC(rdpContext *c, const ELLIPSE_SC_ORDER *eso) +{ + return TRUE; +} + +static BOOL +EllipseCB(rdpContext *c, const ELLIPSE_CB_ORDER *eco) +{ + return TRUE; +} +void +RegisterPrimary(freerdp *rdp) +{ + rdp->update->primary->DstBlt = DstBlt; + rdp->update->primary->PatBlt = PatBlt; + rdp->update->primary->ScrBlt = ScrBlt; + rdp->update->primary->OpaqueRect = OpaqueRect; + rdp->update->primary->DrawNineGrid = DrawNineGrid; + rdp->update->primary->MultiDstBlt = MultiDstBlt; + rdp->update->primary->MultiPatBlt = MultiPatBlt; + rdp->update->primary->MultiScrBlt = MultiScrBlt; + rdp->update->primary->MultiOpaqueRect = MultiOpaqueRect; + rdp->update->primary->MultiDrawNineGrid = MultiDrawNineGrid; + rdp->update->primary->LineTo = LineTo; + rdp->update->primary->Polyline = Polyline; + rdp->update->primary->MemBlt = MemBlt; + rdp->update->primary->Mem3Blt = Mem3Blt; + rdp->update->primary->SaveBitmap = SaveBitmap; + rdp->update->primary->GlyphIndex = GlyphIndex; + rdp->update->primary->FastIndex = FastIndex; + rdp->update->primary->FastGlyph = FastGlyph; + rdp->update->primary->PolygonSC = PolygonSC; + rdp->update->primary->PolygonCB = PolygonCB; + rdp->update->primary->EllipseSC = EllipseSC; + rdp->update->primary->EllipseCB = EllipseCB; +} + +/* incomming input from client handlers */ + +static bool +rdp_backend_handle_input_mouse(ws_input_mouse input, void *internals) +{ + rdp_internals *_i = internals; + rdpInput *inp = _i->instance->input; + _i->core->reset_idle(_i->task_info); + inp->MouseEvent(inp, input.flags, input.x, input.y); + return true; +} + +static bool +rdp_backend_handle_input_kupdown(ws_input_kupdown input, void *internals) +{ + rdp_internals *_i = internals; + rdpInput *inp = _i->instance->input; + if (0 < input.code) + { + _i->core->reset_idle(_i->task_info); + /*log::info << "257 >> tcode: " << input.code << "\n"; */ + /* make byte */ + input.code = RDP_SCANCODE_CODE(input.code); + /* apply extended */ + input.code = ASCII_TO_SCANCODE[input.code]; + /* extract extended sepparatelly in tflag */ + uint32_t tflag = RDP_SCANCODE_EXTENDED(input.code) ? + KBD_FLAGS_EXTENDED : + 0; + /* now make the call */ + freerdp_input_send_keyboard_event(inp, + (input.down ? KBD_FLAGS_DOWN : KBD_FLAGS_RELEASE) | tflag, + input.code); + } + return true; +} + +static bool +rdp_backend_handle_input_kpress(ws_input_kpress input, void *internals) +{ + rdp_internals *_i = internals; + rdpInput *inp = _i->instance->input; + _i->core->reset_idle(_i->task_info); + if (0x20 < input.code) + { + if (input.shiftstate & 6) + { + //Control and or Alt: Must use scan-codes since + //unicode-event can't handle these + if (((64 < input.code) && (91 > input.code)) + || ((96 < input.code) && (123 > input.code))) + { + input.code -= (input.shiftstate & 1) ? 0 : 32; + input.code + = GetVirtualScanCodeFromVirtualKeyCode( + input.code, 4); + if (0 < input.code) + { + freerdp_input_send_unicode_keyboard_event( + inp, KBD_FLAGS_DOWN, + ASCII_TO_SCANCODE[input.code]); + freerdp_input_send_unicode_keyboard_event( + inp, KBD_FLAGS_RELEASE, + ASCII_TO_SCANCODE[input.code]); + } + } + } + else + { + if (0 < input.code) + { + if (input.code == 96) + { + freerdp_input_send_keyboard_event(inp, + KBD_FLAGS_DOWN, + RDP_SCANCODE_LCONTROL); + freerdp_input_send_keyboard_event(inp, + KBD_FLAGS_DOWN, RDP_SCANCODE_LMENU); + freerdp_input_send_keyboard_event(inp, + KBD_FLAGS_DOWN, + RDP_SCANCODE_DELETE); + freerdp_input_send_keyboard_event(inp, + KBD_FLAGS_RELEASE, + RDP_SCANCODE_LCONTROL); + freerdp_input_send_keyboard_event(inp, + KBD_FLAGS_RELEASE, + RDP_SCANCODE_LMENU); + freerdp_input_send_keyboard_event(inp, + KBD_FLAGS_RELEASE, + RDP_SCANCODE_DELETE); + } + + freerdp_input_send_keyboard_event(inp, + KBD_FLAGS_DOWN, + ASCII_TO_SCANCODE[input.code]); + freerdp_input_send_keyboard_event(inp, + KBD_FLAGS_RELEASE, + ASCII_TO_SCANCODE[input.code]); + } + } + } + else + { + if (0 < input.code) + { + input.code = RDP_SCANCODE_CODE(input.code); + freerdp_input_send_keyboard_event( + inp, KBD_FLAGS_DOWN, ASCII_TO_SCANCODE[input.code]); + freerdp_input_send_keyboard_event(inp, + KBD_FLAGS_RELEASE, ASCII_TO_SCANCODE[input.code]); + } + } + return true; +} + +static bool +rdp_backend_handle_input_kcomb(ws_input_keycomb input, void *internals) +{ + rdp_internals *_i = internals; + rdpInput *inp = _i->instance->input; + _i->core->reset_idle(_i->task_info); + switch (input) + { + case ws_keycomb_ctrlaltdel_press: + { + freerdp_input_send_keyboard_event( + inp, KBD_FLAGS_DOWN, RDP_SCANCODE_LCONTROL); + freerdp_input_send_keyboard_event( + inp, KBD_FLAGS_DOWN, RDP_SCANCODE_LMENU); + freerdp_input_send_keyboard_event( + inp, KBD_FLAGS_DOWN, RDP_SCANCODE_DELETE); + freerdp_input_send_keyboard_event( + inp, KBD_FLAGS_RELEASE, RDP_SCANCODE_LCONTROL); + freerdp_input_send_keyboard_event( + inp, KBD_FLAGS_RELEASE, RDP_SCANCODE_LMENU); + freerdp_input_send_keyboard_event( + inp, KBD_FLAGS_RELEASE, RDP_SCANCODE_DELETE); + } + break; + case ws_keycomb_alttab_press: + { + freerdp_input_send_keyboard_event( + inp, KBD_FLAGS_DOWN, RDP_SCANCODE_LMENU); + freerdp_input_send_keyboard_event( + inp, KBD_FLAGS_DOWN, RDP_SCANCODE_TAB); + freerdp_input_send_keyboard_event( + inp, KBD_FLAGS_RELEASE, RDP_SCANCODE_TAB); + } + break; + case ws_keycomb_alttab_release: + { + freerdp_input_send_keyboard_event( + inp, KBD_FLAGS_RELEASE, RDP_SCANCODE_LMENU); + } + break; + default: + break; + } + return true; +} + +static bool +rdp_backend_handle_input_unicode(ws_input_unicode input, void *internals) +{ + rdp_internals *_i = internals; + rdpInput *inp = _i->instance->input; + int i; + _i->core->reset_idle(_i->task_info); + for (i = 0; i < input.length; ++i) + { + freerdp_input_send_unicode_keyboard_event( + inp, KBD_FLAGS_DOWN, (UINT16)input.input[i]); + freerdp_input_send_unicode_keyboard_event( + inp, KBD_FLAGS_RELEASE, (UINT16)input.input[i]); + } + return true; +} + +void +register_input(wrdp_backend_module *backend) +{ + backend->backend_handle_input_kcomb = rdp_backend_handle_input_kcomb; + backend->backend_handle_input_kupdown + = rdp_backend_handle_input_kupdown; + backend->backend_handle_input_kpress = rdp_backend_handle_input_kpress; + backend->backend_handle_input_mouse = rdp_backend_handle_input_mouse; + backend->backend_handle_input_unicode + = rdp_backend_handle_input_unicode; +} + +static BOOL +rdp_pre_connect(freerdp *instance) +{ + rdpSettings *settings = instance->settings; + my_rdp_context *c = (my_rdp_context *)instance->context; + + RegisterUpdate(instance); + RegisterPrimary(instance); + + /* looks like this settings reducing artifacts level */ + settings->OrderSupport[NEG_PATBLT_INDEX] = FALSE; + settings->OrderSupport[NEG_SCRBLT_INDEX] = FALSE; + + /* causing random disconnects */ + settings->OrderSupport[NEG_ATEXTOUT_INDEX] = FALSE; + settings->OrderSupport[NEG_DRAWNINEGRID_INDEX] = FALSE; + settings->NoBitmapCompressionHeader = TRUE; + settings->BitmapCompressionDisabled = TRUE; + settings->FastPathOutput = FALSE; + settings->BitmapCacheEnabled = FALSE; + settings->BrushSupportLevel = 0; + + /* causing connection failure on recent versions of freerdp */ + settings->OffscreenSupportLevel = 0; + settings->OffscreenCacheSize = 0; + + /* following required at least on windows 7 */ + settings->OrderSupport[NEG_MEMBLT_INDEX] = FALSE; + settings->OrderSupport[NEG_MEM3BLT_INDEX] = FALSE; + + instance->context->cache = cache_new(settings); + + c->my_internals->clrconv + = freerdp_clrconv_new(CLRCONV_ALPHA | CLRCONV_INVERT); + + if (!instance->context->cache) + { + return FALSE; + } + return TRUE; +} + +static BOOL +rdp_post_connect(freerdp *instance) +{ + my_rdp_context *c = (my_rdp_context *)instance->context; + c->my_internals->conn_state = rdp_conn_state_connected; + rdpPointer p; + memset(&p, 0, sizeof(p)); + p.size = sizeof(my_rdp_pointer); + register_pointer(&p); + graphics_register_pointer(instance->context->graphics, &p); + pointer_cache_register_callbacks(instance->update); + + c->my_internals->core->send_text_msg( + "C:RDP session connection started.", c->my_internals->task_info); + + instance->update->DesktopResize(instance->context); + + return TRUE; +} + +static DWORD +rdp_verify_certificate(freerdp *instance, const char *common_name, + const char *subject, const char *issuer, const char *fingerprint, + BOOL host_mismatch) +{ + WLog_INFO(TAG, "Certificate details:"); + WLog_INFO(TAG, "\tSubject: %s", subject); + WLog_INFO(TAG, "\tIssuer: %s", issuer); + WLog_INFO(TAG, "\tThumbprint: %s", fingerprint); + WLog_INFO(TAG, + "The above X.509 certificate could not be verified, possibly " + "because you do not have " + "the CA certificate in your certificate store, or the " + "certificate has expired. " + "Please look at the OpenSSL documentation on how to add a " + "private CA to the store."); + + return TRUE; /* ?? */ +} + +/*static int +rdp_receive_channel_data (freerdp* instance, + UINT16 channelId, + BYTE* data, + int size, + int flags, + int total_size) +{ + return freerdp_channels_data ( + instance, channelId, data, size, flags, total_size); +}*/ + +void +rdp_register_base(freerdp *r) +{ + r->PreConnect = rdp_pre_connect; + r->PostConnect = rdp_post_connect; + r->VerifyCertificate = rdp_verify_certificate; + // r->ReceiveChannelData = rdp_receive_channel_data; + r->ContextNew = rdp_context_new; + r->ContextFree = rdp_context_free; +} |