summaryrefslogtreecommitdiff
path: root/src/rdp/rdp_display_output.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_display_output.c
added webrdp public code
Diffstat (limited to 'src/rdp/rdp_display_output.c')
-rw-r--r--src/rdp/rdp_display_output.c871
1 files changed, 871 insertions, 0 deletions
diff --git a/src/rdp/rdp_display_output.c b/src/rdp/rdp_display_output.c
new file mode 100644
index 0000000..16f3c5d
--- /dev/null
+++ b/src/rdp/rdp_display_output.c
@@ -0,0 +1,871 @@
+/* BSD-2-Clause license
+ *
+ * Copyright (c) 2018-2023 NST <www.newinfosec.ru>, sss <sss at dark-alexandr dot net>.
+ *
+ */
+
+#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"
+
+#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);
+
+HCLRCONV
+freerdp_clrconv_new(UINT32 flags)
+{
+ HCLRCONV clrconv;
+
+ clrconv = (CLRCONV *)calloc(1, sizeof(CLRCONV));
+
+ if (!clrconv)
+ {
+ perror("calloc");
+ return 0;
+ }
+
+ 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)
+ {
+ perror("calloc");
+ free(clrconv);
+ return 0;
+ }
+
+ return clrconv;
+}
+
+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 *)winpr_aligned_malloc(scanLineSz, 16);
+ if (!tmpBfr)
+ {
+ return;
+ }
+ 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--;
+ }
+ winpr_aligned_free(tmpBfr);
+ }
+ /* Flip from source buffer to destination buffer. */
+ else
+ {
+ for (i = 0; i < height; i++)
+ {
+ if (bottomLine && topLine && scanLineSz)
+ {
+ 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 *)winpr_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);
+ if (!pixels)
+ {
+ perror("malloc");
+ return FALSE;
+ }
+ 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);
+ if (!png_buf.buf)
+ {
+ free(pixels);
+ perror("malloc");
+ return FALSE;
+ }
+ png_generate_from_argb(
+ pointer->width, pointer->height, pixels, &png_buf);
+
+ wrdp_core_display_cursor cur = {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};
+
+ cur.data = png_buf.buf;
+ wrdp_core_display_cursor_info cursor_info
+ = {p->id, pointer->xPos, pointer->yPos, png_buf.written, &cur};
+
+ c->my_internals->core->api_paint->send_ptr_new(
+ &cursor_info, c->my_internals->task_info);
+ free(png_buf.buf);
+ free(pixels);
+ 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)
+ {
+ c->my_internals->core->api_paint->send_ptr_free(
+ p->id, c->my_internals->task_info);
+ }
+}
+
+static BOOL
+Pointer_Set(rdpContext *context, rdpPointer *pointer)
+{
+ my_rdp_pointer *p = (my_rdp_pointer *)pointer;
+ my_rdp_context *c = (my_rdp_context *)context;
+ c->my_internals->core->api_paint->send_ptr_set(
+ p->id, 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->api_paint->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->api_paint->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
+BeginPaint(rdpContext *context)
+{
+ my_rdp_context *c = (my_rdp_context *)context;
+ c->my_internals->core->api_paint->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->api_paint->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;
+ wrdp_core_display_bounds lB;
+ if (bounds)
+ {
+ lB.left = bounds->left;
+ lB.right = bounds->right + 1;
+ lB.top = bounds->top;
+ lB.bottom = bounds->bottom + 1;
+ }
+ else
+ {
+ memset(&lB, 0, sizeof(wrdp_core_display_bounds));
+ }
+ c->my_internals->core->api_paint->send_set_bounds(
+ &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->api_msgs->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];
+ wrdp_core_display_bmp bmp = {bmd->destLeft, bmd->destTop,
+ bmd->width, bmd->height, bmd->destRight - bmd->destLeft + 1,
+ bmd->destBottom - bmd->destTop + 1, bmd->bitsPerPixel,
+ bmd->compressed, bmd->bitmapLength};
+ if (!bmd->compressed)
+ {
+ freerdp_image_flip(bmd->bitmapDataStream,
+ bmd->bitmapDataStream, bmd->width, bmd->height,
+ bmd->bitsPerPixel);
+ }
+ c->my_internals->core->api_paint->send_bitmap(
+ &bmp, bmd->bitmapDataStream, c->my_internals->task_info);
+ }
+ 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)
+{
+ rdpUpdate *u = rdp->context->update;
+ u->BeginPaint = BeginPaint;
+ u->EndPaint = EndPaint;
+ u->SetBounds = SetBounds;
+ u->Synchronize = Synchronize;
+ u->DesktopResize = DesktopResize;
+ u->BitmapUpdate = BitmapUpdate;
+ u->Palette = Palette;
+ u->PlaySound = PlaySound;
+ u->SurfaceBits = SurfaceBits;
+
+ u->RefreshRect = RefreshRect;
+ u->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)
+ {
+ wrdp_core_display_patblt_order patblt
+ = {po->nLeftRect, po->nTopRect, po->nWidth, po->nHeight,
+ FreeRDPConvertColor(po->foreColor, PIXEL_FORMAT_BGR16,
+ PIXEL_FORMAT_ABGR32,
+ NULL), //XXX
+ rop3};
+ c->my_internals->core->api_paint->send_pat_blt(
+ &patblt, 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);
+ wrdp_core_display_scr_blt scr_blt = {rop3, sbo->nLeftRect,
+ sbo->nTopRect, sbo->nWidth, sbo->nHeight, sbo->nXSrc, sbo->nYSrc};
+ c->my_internals->core->api_paint->send_scr_blt(
+ &scr_blt, 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;
+ wrdp_core_display_opaque_rect_order oro2;
+ oro2.color = oro->color;
+ oro2.nHeight = oro->nHeight;
+ oro2.nLeftRect = oro->nLeftRect;
+ oro2.nTopRect = oro->nTopRect;
+ oro2.nWidth = oro->nWidth;
+ oro2.color = FreeRDPConvertColor(
+ oro2.color, PIXEL_FORMAT_BGR16, PIXEL_FORMAT_ABGR32, NULL);
+ c->my_internals->core->api_paint->send_opaque_rect_order(
+ &oro2, 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;
+ wrdp_core_display_m_opaque_rect mrect;
+ mrect.color = FreeRDPConvertColor(
+ moro->color, PIXEL_FORMAT_BGR16, PIXEL_FORMAT_ABGR32, NULL);
+ mrect.num_rect = moro->numRectangles;
+ mrect.rects = (wrdp_core_display_delta_rect *)(moro->rectangles);
+ c->my_internals->core->api_paint->send_multi_opaque_rect(
+ &mrect, c->my_internals->task_info);
+ 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)
+{
+ rdpPrimaryUpdate *p = rdp->context->update->primary;
+ p->DstBlt = DstBlt;
+ p->PatBlt = PatBlt;
+ p->ScrBlt = ScrBlt;
+ p->OpaqueRect = OpaqueRect;
+ p->DrawNineGrid = DrawNineGrid;
+ p->MultiDstBlt = MultiDstBlt;
+ p->MultiPatBlt = MultiPatBlt;
+ p->MultiScrBlt = MultiScrBlt;
+ p->MultiOpaqueRect = MultiOpaqueRect;
+ p->MultiDrawNineGrid = MultiDrawNineGrid;
+ p->LineTo = LineTo;
+ p->Polyline = Polyline;
+ p->MemBlt = MemBlt;
+ p->Mem3Blt = Mem3Blt;
+ p->SaveBitmap = SaveBitmap;
+ p->GlyphIndex = GlyphIndex;
+ p->FastIndex = FastIndex;
+ p->FastGlyph = FastGlyph;
+ p->PolygonSC = PolygonSC;
+ p->PolygonCB = PolygonCB;
+ p->EllipseSC = EllipseSC;
+ p->EllipseCB = EllipseCB;
+}