summaryrefslogtreecommitdiff
path: root/src/rdp/rdp_io.c
diff options
context:
space:
mode:
authorsss <sss@dark-alexandr.net>2023-01-17 00:38:19 +0300
committersss <sss@dark-alexandr.net>2023-01-17 00:38:19 +0300
commitcc3f33db7a8d3c4ad373e646b199808e01bc5d9b (patch)
treeec09d690c7656ab5f2cc72607e05fb359c24d8b2 /src/rdp/rdp_io.c
added webrdp public code
Diffstat (limited to 'src/rdp/rdp_io.c')
-rw-r--r--src/rdp/rdp_io.c1492
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;
+}