Merge pull request #953 from awakecoding/master
Messaging + GDI Improvements
This commit is contained in:
commit
5533d51c58
@ -288,8 +288,7 @@ Pixmap xf_glyph_new(xfInfo* xfi, int width, int height, BYTE* data)
|
|||||||
void xf_gdi_palette_update(rdpContext* context, PALETTE_UPDATE* palette)
|
void xf_gdi_palette_update(rdpContext* context, PALETTE_UPDATE* palette)
|
||||||
{
|
{
|
||||||
xfInfo* xfi = ((xfContext*) context)->xfi;
|
xfInfo* xfi = ((xfContext*) context)->xfi;
|
||||||
xfi->clrconv->palette->count = palette->number;
|
CopyMemory(xfi->clrconv->palette, palette, sizeof(rdpPalette));
|
||||||
xfi->clrconv->palette->entries = palette->entries;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void xf_gdi_set_bounds(rdpContext* context, rdpBounds* bounds)
|
void xf_gdi_set_bounds(rdpContext* context, rdpBounds* bounds)
|
||||||
|
@ -69,25 +69,26 @@
|
|||||||
#define GDI_DPa 0x00A000C9 /* D = D & P */
|
#define GDI_DPa 0x00A000C9 /* D = D & P */
|
||||||
#define GDI_PDxn 0x00A50065 /* D = D ^ ~P */
|
#define GDI_PDxn 0x00A50065 /* D = D ^ ~P */
|
||||||
|
|
||||||
#define GDI_DSxn 0x00990066
|
#define GDI_DSxn 0x00990066 /* D = ~(D ^ S) */
|
||||||
#define GDI_PSDnox 0x002D060A
|
#define GDI_PSDnox 0x002D060A /* D = P ^ (S | ~D) */
|
||||||
#define GDI_PDSona 0x00100C85
|
#define GDI_PDSona 0x00100C85 /* D = P & ~(D | S) */
|
||||||
#define GDI_DSPDxox 0x00740646
|
#define GDI_DSPDxox 0x00740646 /* D = D ^ (S | ( P ^ D)) */
|
||||||
#define GDI_DPSDonox 0x005B18A9
|
#define GDI_DPSDonox 0x005B18A9 /* D = D ^ (P | ~(S | D)) */
|
||||||
|
#define GDI_SPDSxax 0x00AC0744 /* D = S ^ (P & (D ^ S)) */
|
||||||
|
|
||||||
#define GDI_DPon 0x000500A9
|
#define GDI_DPon 0x000500A9 /* D = ~(D | P) */
|
||||||
#define GDI_DPna 0x000A0329
|
#define GDI_DPna 0x000A0329 /* D = D & ~P */
|
||||||
#define GDI_Pn 0x000F0001
|
#define GDI_Pn 0x000F0001 /* D = ~P */
|
||||||
#define GDI_PDna 0x00500325
|
#define GDI_PDna 0x00500325 /* D = P &~D */
|
||||||
#define GDI_DPan 0x005F00E9
|
#define GDI_DPan 0x005F00E9 /* D = ~(D & P) */
|
||||||
#define GDI_DSan 0x007700E6
|
#define GDI_DSan 0x007700E6 /* D = ~(D & S) */
|
||||||
#define GDI_DSxn 0x00990066
|
#define GDI_DSxn 0x00990066 /* D = ~(D ^ S) */
|
||||||
#define GDI_DPa 0x00A000C9
|
#define GDI_DPa 0x00A000C9 /* D = D & P */
|
||||||
#define GDI_D 0x00AA0029
|
#define GDI_D 0x00AA0029 /* D = D */
|
||||||
#define GDI_DPno 0x00AF0229
|
#define GDI_DPno 0x00AF0229 /* D = D | ~P */
|
||||||
#define GDI_SDno 0x00DD0228
|
#define GDI_SDno 0x00DD0228 /* D = S | ~D */
|
||||||
#define GDI_PDno 0x00F50225
|
#define GDI_PDno 0x00F50225 /* D = P | ~D */
|
||||||
#define GDI_DPo 0x00FA0089
|
#define GDI_DPo 0x00FA0089 /* D = D | P */
|
||||||
|
|
||||||
/* Brush Styles */
|
/* Brush Styles */
|
||||||
#define GDI_BS_SOLID 0x00
|
#define GDI_BS_SOLID 0x00
|
||||||
|
@ -58,7 +58,7 @@ typedef struct rdp_input rdpInput;
|
|||||||
#define RDP_CLIENT_INPUT_PDU_HEADER_LENGTH 4
|
#define RDP_CLIENT_INPUT_PDU_HEADER_LENGTH 4
|
||||||
|
|
||||||
/* defined inside libfreerdp-core */
|
/* defined inside libfreerdp-core */
|
||||||
typedef struct rdp_event rdpEvent;
|
typedef struct rdp_input_proxy rdpInputProxy;
|
||||||
|
|
||||||
/* Input Interface */
|
/* Input Interface */
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ struct rdp_input
|
|||||||
/* Internal */
|
/* Internal */
|
||||||
|
|
||||||
BOOL asynchronous;
|
BOOL asynchronous;
|
||||||
rdpEvent* event;
|
rdpInputProxy* proxy;
|
||||||
wMessageQueue* queue;
|
wMessageQueue* queue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -22,6 +22,30 @@
|
|||||||
|
|
||||||
#include <freerdp/types.h>
|
#include <freerdp/types.h>
|
||||||
|
|
||||||
|
struct _GLYPH_DATA
|
||||||
|
{
|
||||||
|
UINT32 cacheIndex;
|
||||||
|
INT32 x;
|
||||||
|
INT32 y;
|
||||||
|
UINT32 cx;
|
||||||
|
UINT32 cy;
|
||||||
|
UINT32 cb;
|
||||||
|
BYTE* aj;
|
||||||
|
};
|
||||||
|
typedef struct _GLYPH_DATA GLYPH_DATA;
|
||||||
|
|
||||||
|
struct _GLYPH_DATA_V2
|
||||||
|
{
|
||||||
|
UINT32 cacheIndex;
|
||||||
|
INT32 x;
|
||||||
|
INT32 y;
|
||||||
|
UINT32 cx;
|
||||||
|
UINT32 cy;
|
||||||
|
UINT32 cb;
|
||||||
|
BYTE* aj;
|
||||||
|
};
|
||||||
|
typedef struct _GLYPH_DATA_V2 GLYPH_DATA_V2;
|
||||||
|
|
||||||
#define BACKMODE_TRANSPARENT 0x0001
|
#define BACKMODE_TRANSPARENT 0x0001
|
||||||
#define BACKMODE_OPAQUE 0x0002
|
#define BACKMODE_OPAQUE 0x0002
|
||||||
|
|
||||||
@ -357,7 +381,7 @@ struct _FAST_GLYPH_ORDER
|
|||||||
INT32 y;
|
INT32 y;
|
||||||
UINT32 cbData;
|
UINT32 cbData;
|
||||||
BYTE data[256];
|
BYTE data[256];
|
||||||
void* glyph_data;
|
GLYPH_DATA_V2 glyphData;
|
||||||
};
|
};
|
||||||
typedef struct _FAST_GLYPH_ORDER FAST_GLYPH_ORDER;
|
typedef struct _FAST_GLYPH_ORDER FAST_GLYPH_ORDER;
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#define FREERDP_UPDATE_SECONDARY_H
|
#define FREERDP_UPDATE_SECONDARY_H
|
||||||
|
|
||||||
#include <freerdp/types.h>
|
#include <freerdp/types.h>
|
||||||
|
#include <freerdp/primary.h>
|
||||||
|
|
||||||
#define GLYPH_FRAGMENT_NOP 0x00
|
#define GLYPH_FRAGMENT_NOP 0x00
|
||||||
#define GLYPH_FRAGMENT_USE 0xFE
|
#define GLYPH_FRAGMENT_USE 0xFE
|
||||||
@ -127,49 +128,25 @@ struct _CACHE_COLOR_TABLE_ORDER
|
|||||||
{
|
{
|
||||||
UINT32 cacheIndex;
|
UINT32 cacheIndex;
|
||||||
UINT32 numberColors;
|
UINT32 numberColors;
|
||||||
UINT32* colorTable;
|
UINT32 colorTable[256];
|
||||||
};
|
};
|
||||||
typedef struct _CACHE_COLOR_TABLE_ORDER CACHE_COLOR_TABLE_ORDER;
|
typedef struct _CACHE_COLOR_TABLE_ORDER CACHE_COLOR_TABLE_ORDER;
|
||||||
|
|
||||||
struct _GLYPH_DATA
|
|
||||||
{
|
|
||||||
UINT32 cacheIndex;
|
|
||||||
INT32 x;
|
|
||||||
INT32 y;
|
|
||||||
UINT32 cx;
|
|
||||||
UINT32 cy;
|
|
||||||
UINT32 cb;
|
|
||||||
BYTE* aj;
|
|
||||||
};
|
|
||||||
typedef struct _GLYPH_DATA GLYPH_DATA;
|
|
||||||
|
|
||||||
struct _CACHE_GLYPH_ORDER
|
struct _CACHE_GLYPH_ORDER
|
||||||
{
|
{
|
||||||
UINT32 cacheId;
|
UINT32 cacheId;
|
||||||
UINT32 cGlyphs;
|
UINT32 cGlyphs;
|
||||||
GLYPH_DATA glyphData[255];
|
GLYPH_DATA glyphData[256];
|
||||||
BYTE* unicodeCharacters;
|
BYTE* unicodeCharacters;
|
||||||
};
|
};
|
||||||
typedef struct _CACHE_GLYPH_ORDER CACHE_GLYPH_ORDER;
|
typedef struct _CACHE_GLYPH_ORDER CACHE_GLYPH_ORDER;
|
||||||
|
|
||||||
struct _GLYPH_DATA_V2
|
|
||||||
{
|
|
||||||
UINT32 cacheIndex;
|
|
||||||
INT32 x;
|
|
||||||
INT32 y;
|
|
||||||
UINT32 cx;
|
|
||||||
UINT32 cy;
|
|
||||||
UINT32 cb;
|
|
||||||
BYTE* aj;
|
|
||||||
};
|
|
||||||
typedef struct _GLYPH_DATA_V2 GLYPH_DATA_V2;
|
|
||||||
|
|
||||||
struct _CACHE_GLYPH_V2_ORDER
|
struct _CACHE_GLYPH_V2_ORDER
|
||||||
{
|
{
|
||||||
UINT32 cacheId;
|
UINT32 cacheId;
|
||||||
UINT32 flags;
|
UINT32 flags;
|
||||||
UINT32 cGlyphs;
|
UINT32 cGlyphs;
|
||||||
GLYPH_DATA_V2 glyphData[255];
|
GLYPH_DATA_V2 glyphData[256];
|
||||||
BYTE* unicodeCharacters;
|
BYTE* unicodeCharacters;
|
||||||
};
|
};
|
||||||
typedef struct _CACHE_GLYPH_V2_ORDER CACHE_GLYPH_V2_ORDER;
|
typedef struct _CACHE_GLYPH_V2_ORDER CACHE_GLYPH_V2_ORDER;
|
||||||
|
@ -90,7 +90,7 @@ typedef struct _PALETTE_UPDATE PALETTE_UPDATE;
|
|||||||
struct rdp_palette
|
struct rdp_palette
|
||||||
{
|
{
|
||||||
UINT32 count;
|
UINT32 count;
|
||||||
PALETTE_ENTRY* entries;
|
PALETTE_ENTRY entries[256];
|
||||||
};
|
};
|
||||||
typedef struct rdp_palette rdpPalette;
|
typedef struct rdp_palette rdpPalette;
|
||||||
|
|
||||||
@ -135,7 +135,7 @@ enum SURFCMD_FRAMEACTION
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* defined inside libfreerdp-core */
|
/* defined inside libfreerdp-core */
|
||||||
typedef struct rdp_message rdpMessage;
|
typedef struct rdp_update_proxy rdpUpdateProxy;
|
||||||
|
|
||||||
/* Update Interface */
|
/* Update Interface */
|
||||||
|
|
||||||
@ -204,7 +204,7 @@ struct rdp_update
|
|||||||
SURFACE_FRAME_MARKER surface_frame_marker;
|
SURFACE_FRAME_MARKER surface_frame_marker;
|
||||||
|
|
||||||
BOOL asynchronous;
|
BOOL asynchronous;
|
||||||
rdpMessage* message;
|
rdpUpdateProxy* proxy;
|
||||||
wMessageQueue* queue;
|
wMessageQueue* queue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
25
libfreerdp/cache/glyph.c
vendored
25
libfreerdp/cache/glyph.c
vendored
@ -173,6 +173,7 @@ void update_gdi_glyph_index(rdpContext* context, GLYPH_INDEX_ORDER* glyph_index)
|
|||||||
rdpGlyphCache* glyph_cache;
|
rdpGlyphCache* glyph_cache;
|
||||||
|
|
||||||
glyph_cache = context->cache->glyph;
|
glyph_cache = context->cache->glyph;
|
||||||
|
|
||||||
update_process_glyph_fragments(context, glyph_index->data, glyph_index->cbData,
|
update_process_glyph_fragments(context, glyph_index->data, glyph_index->cbData,
|
||||||
glyph_index->cacheId, glyph_index->ulCharInc, glyph_index->flAccel,
|
glyph_index->cacheId, glyph_index->ulCharInc, glyph_index->flAccel,
|
||||||
glyph_index->backColor, glyph_index->foreColor, glyph_index->x, glyph_index->y,
|
glyph_index->backColor, glyph_index->foreColor, glyph_index->x, glyph_index->y,
|
||||||
@ -184,8 +185,9 @@ void update_gdi_glyph_index(rdpContext* context, GLYPH_INDEX_ORDER* glyph_index)
|
|||||||
|
|
||||||
void update_gdi_fast_index(rdpContext* context, FAST_INDEX_ORDER* fast_index)
|
void update_gdi_fast_index(rdpContext* context, FAST_INDEX_ORDER* fast_index)
|
||||||
{
|
{
|
||||||
INT32 opLeft, opTop, opRight, opBottom;
|
|
||||||
INT32 x, y;
|
INT32 x, y;
|
||||||
|
INT32 opLeft, opTop;
|
||||||
|
INT32 opRight, opBottom;
|
||||||
rdpGlyphCache* glyph_cache;
|
rdpGlyphCache* glyph_cache;
|
||||||
|
|
||||||
glyph_cache = context->cache->glyph;
|
glyph_cache = context->cache->glyph;
|
||||||
@ -234,12 +236,13 @@ void update_gdi_fast_index(rdpContext* context, FAST_INDEX_ORDER* fast_index)
|
|||||||
|
|
||||||
void update_gdi_fast_glyph(rdpContext* context, FAST_GLYPH_ORDER* fast_glyph)
|
void update_gdi_fast_glyph(rdpContext* context, FAST_GLYPH_ORDER* fast_glyph)
|
||||||
{
|
{
|
||||||
INT32 opLeft, opTop, opRight, opBottom;
|
|
||||||
INT32 x, y;
|
INT32 x, y;
|
||||||
GLYPH_DATA_V2* glyph_data;
|
|
||||||
rdpGlyph* glyph;
|
rdpGlyph* glyph;
|
||||||
rdpCache* cache = context->cache;
|
|
||||||
BYTE text_data[2];
|
BYTE text_data[2];
|
||||||
|
INT32 opLeft, opTop;
|
||||||
|
INT32 opRight, opBottom;
|
||||||
|
GLYPH_DATA_V2* glyph_data;
|
||||||
|
rdpCache* cache = context->cache;
|
||||||
|
|
||||||
opLeft = fast_glyph->opLeft;
|
opLeft = fast_glyph->opLeft;
|
||||||
opTop = fast_glyph->opTop;
|
opTop = fast_glyph->opTop;
|
||||||
@ -274,21 +277,21 @@ void update_gdi_fast_glyph(rdpContext* context, FAST_GLYPH_ORDER* fast_glyph)
|
|||||||
if (y == -32768)
|
if (y == -32768)
|
||||||
y = fast_glyph->bkTop;
|
y = fast_glyph->bkTop;
|
||||||
|
|
||||||
if (fast_glyph->glyph_data != NULL)
|
if (fast_glyph->cbData > 1)
|
||||||
{
|
{
|
||||||
/* got option font that needs to go into cache */
|
/* got option font that needs to go into cache */
|
||||||
glyph_data = (GLYPH_DATA_V2*) (fast_glyph->glyph_data);
|
glyph_data = &fast_glyph->glyphData;
|
||||||
|
|
||||||
glyph = Glyph_Alloc(context);
|
glyph = Glyph_Alloc(context);
|
||||||
glyph->x = glyph_data->x;
|
glyph->x = glyph_data->x;
|
||||||
glyph->y = glyph_data->y;
|
glyph->y = glyph_data->y;
|
||||||
glyph->cx = glyph_data->cx;
|
glyph->cx = glyph_data->cx;
|
||||||
glyph->cy = glyph_data->cy;
|
glyph->cy = glyph_data->cy;
|
||||||
glyph->aj = glyph_data->aj;
|
|
||||||
glyph->cb = glyph_data->cb;
|
glyph->cb = glyph_data->cb;
|
||||||
|
glyph->aj = glyph_data->aj;
|
||||||
Glyph_New(context, glyph);
|
Glyph_New(context, glyph);
|
||||||
|
|
||||||
glyph_cache_put(cache->glyph, fast_glyph->cacheId, fast_glyph->data[0], glyph);
|
glyph_cache_put(cache->glyph, fast_glyph->cacheId, fast_glyph->data[0], glyph);
|
||||||
free(fast_glyph->glyph_data);
|
|
||||||
fast_glyph->glyph_data = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
text_data[0] = fast_glyph->data[0];
|
text_data[0] = fast_glyph->data[0];
|
||||||
@ -320,8 +323,8 @@ void update_gdi_cache_glyph(rdpContext* context, CACHE_GLYPH_ORDER* cache_glyph)
|
|||||||
glyph->y = glyph_data->y;
|
glyph->y = glyph_data->y;
|
||||||
glyph->cx = glyph_data->cx;
|
glyph->cx = glyph_data->cx;
|
||||||
glyph->cy = glyph_data->cy;
|
glyph->cy = glyph_data->cy;
|
||||||
glyph->aj = glyph_data->aj;
|
|
||||||
glyph->cb = glyph_data->cb;
|
glyph->cb = glyph_data->cb;
|
||||||
|
glyph->aj = glyph_data->aj;
|
||||||
Glyph_New(context, glyph);
|
Glyph_New(context, glyph);
|
||||||
|
|
||||||
glyph_cache_put(cache->glyph, cache_glyph->cacheId, glyph_data->cacheIndex, glyph);
|
glyph_cache_put(cache->glyph, cache_glyph->cacheId, glyph_data->cacheIndex, glyph);
|
||||||
@ -345,8 +348,8 @@ void update_gdi_cache_glyph_v2(rdpContext* context, CACHE_GLYPH_V2_ORDER* cache_
|
|||||||
glyph->y = glyph_data->y;
|
glyph->y = glyph_data->y;
|
||||||
glyph->cx = glyph_data->cx;
|
glyph->cx = glyph_data->cx;
|
||||||
glyph->cy = glyph_data->cy;
|
glyph->cy = glyph_data->cy;
|
||||||
glyph->aj = glyph_data->aj;
|
|
||||||
glyph->cb = glyph_data->cb;
|
glyph->cb = glyph_data->cb;
|
||||||
|
glyph->aj = glyph_data->aj;
|
||||||
Glyph_New(context, glyph);
|
Glyph_New(context, glyph);
|
||||||
|
|
||||||
glyph_cache_put(cache->glyph, cache_glyph_v2->cacheId, glyph_data->cacheIndex, glyph);
|
glyph_cache_put(cache->glyph, cache_glyph_v2->cacheId, glyph_data->cacheIndex, glyph);
|
||||||
|
10
libfreerdp/cache/palette.c
vendored
10
libfreerdp/cache/palette.c
vendored
@ -25,14 +25,17 @@
|
|||||||
|
|
||||||
#include <winpr/crt.h>
|
#include <winpr/crt.h>
|
||||||
|
|
||||||
#include <freerdp/utils/stream.h>
|
|
||||||
|
|
||||||
#include <freerdp/cache/palette.h>
|
#include <freerdp/cache/palette.h>
|
||||||
|
|
||||||
void update_gdi_cache_color_table(rdpContext* context, CACHE_COLOR_TABLE_ORDER* cache_color_table)
|
void update_gdi_cache_color_table(rdpContext* context, CACHE_COLOR_TABLE_ORDER* cache_color_table)
|
||||||
{
|
{
|
||||||
|
UINT32* colorTable;
|
||||||
rdpCache* cache = context->cache;
|
rdpCache* cache = context->cache;
|
||||||
palette_cache_put(cache->palette, cache_color_table->cacheIndex, (void*) cache_color_table->colorTable);
|
|
||||||
|
colorTable = (UINT32*) malloc(sizeof(UINT32) * 256);
|
||||||
|
CopyMemory(colorTable, cache_color_table->colorTable, sizeof(UINT32) * 256);
|
||||||
|
|
||||||
|
palette_cache_put(cache->palette, cache_color_table->cacheIndex, (void*) colorTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* palette_cache_get(rdpPaletteCache* palette_cache, UINT32 index)
|
void* palette_cache_get(rdpPaletteCache* palette_cache, UINT32 index)
|
||||||
@ -98,4 +101,3 @@ void palette_cache_free(rdpPaletteCache* palette_cache)
|
|||||||
free(palette_cache);
|
free(palette_cache);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,6 +342,17 @@ UINT32 freerdp_color_convert_var(UINT32 srcColor, int srcBpp, int dstBpp, HCLRCO
|
|||||||
|
|
||||||
UINT32 freerdp_color_convert_var_rgb(UINT32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv)
|
UINT32 freerdp_color_convert_var_rgb(UINT32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv)
|
||||||
{
|
{
|
||||||
|
if (srcBpp == 8)
|
||||||
|
{
|
||||||
|
BYTE alpha = 0xFF;
|
||||||
|
UINT32 dstColor = 0;
|
||||||
|
PALETTE_ENTRY* entry = &clrconv->palette->entries[srcColor & 0xFF];
|
||||||
|
|
||||||
|
freerdp_color_make_bgr(&dstColor, dstBpp, &entry->red, &entry->green, &entry->blue, &alpha, clrconv);
|
||||||
|
|
||||||
|
return dstColor;
|
||||||
|
}
|
||||||
|
|
||||||
if (srcBpp > 16)
|
if (srcBpp > 16)
|
||||||
return freerdp_color_convert_bgr_rgb(srcColor, srcBpp, dstBpp, clrconv);
|
return freerdp_color_convert_bgr_rgb(srcColor, srcBpp, dstBpp, clrconv);
|
||||||
else
|
else
|
||||||
@ -350,6 +361,17 @@ UINT32 freerdp_color_convert_var_rgb(UINT32 srcColor, int srcBpp, int dstBpp, HC
|
|||||||
|
|
||||||
UINT32 freerdp_color_convert_var_bgr(UINT32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv)
|
UINT32 freerdp_color_convert_var_bgr(UINT32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv)
|
||||||
{
|
{
|
||||||
|
if (srcBpp == 8)
|
||||||
|
{
|
||||||
|
BYTE alpha = 0xFF;
|
||||||
|
UINT32 dstColor = 0;
|
||||||
|
PALETTE_ENTRY* entry = &clrconv->palette->entries[srcColor & 0xFF];
|
||||||
|
|
||||||
|
freerdp_color_make_rgb(&dstColor, dstBpp, &entry->red, &entry->green, &entry->blue, &alpha, clrconv);
|
||||||
|
|
||||||
|
return dstColor;
|
||||||
|
}
|
||||||
|
|
||||||
if (srcBpp > 16)
|
if (srcBpp > 16)
|
||||||
return freerdp_color_convert_bgr(srcColor, srcBpp, dstBpp, clrconv);
|
return freerdp_color_convert_bgr(srcColor, srcBpp, dstBpp, clrconv);
|
||||||
else
|
else
|
||||||
|
@ -64,8 +64,6 @@ set(${MODULE_PREFIX}_SRCS
|
|||||||
info.h
|
info.h
|
||||||
input.c
|
input.c
|
||||||
input.h
|
input.h
|
||||||
event.c
|
|
||||||
event.h
|
|
||||||
license.c
|
license.c
|
||||||
license.h
|
license.h
|
||||||
errinfo.c
|
errinfo.c
|
||||||
|
@ -1,212 +0,0 @@
|
|||||||
/**
|
|
||||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
|
||||||
* Asynchronous Event Queue
|
|
||||||
*
|
|
||||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "event.h"
|
|
||||||
|
|
||||||
#include <winpr/crt.h>
|
|
||||||
#include <winpr/collections.h>
|
|
||||||
|
|
||||||
/* Input */
|
|
||||||
|
|
||||||
static void event_SynchronizeEvent(rdpInput* input, UINT32 flags)
|
|
||||||
{
|
|
||||||
MessageQueue_Post(input->queue, (void*) input,
|
|
||||||
MakeMessageId(Input, SynchronizeEvent), (void*) (size_t) flags, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void event_KeyboardEvent(rdpInput* input, UINT16 flags, UINT16 code)
|
|
||||||
{
|
|
||||||
MessageQueue_Post(input->queue, (void*) input,
|
|
||||||
MakeMessageId(Input, KeyboardEvent), (void*) (size_t) flags, (void*) (size_t) code);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void event_UnicodeKeyboardEvent(rdpInput* input, UINT16 flags, UINT16 code)
|
|
||||||
{
|
|
||||||
MessageQueue_Post(input->queue, (void*) input,
|
|
||||||
MakeMessageId(Input, UnicodeKeyboardEvent), (void*) (size_t) flags, (void*) (size_t) code);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void event_MouseEvent(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
|
|
||||||
{
|
|
||||||
UINT32 pos = (x << 16) | y;
|
|
||||||
|
|
||||||
MessageQueue_Post(input->queue, (void*) input,
|
|
||||||
MakeMessageId(Input, MouseEvent), (void*) (size_t) flags, (void*) (size_t) pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void event_ExtendedMouseEvent(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
|
|
||||||
{
|
|
||||||
UINT32 pos = (x << 16) | y;
|
|
||||||
|
|
||||||
MessageQueue_Post(input->queue, (void*) input,
|
|
||||||
MakeMessageId(Input, ExtendedMouseEvent), (void*) (size_t) flags, (void*) (size_t) pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Event Queue */
|
|
||||||
|
|
||||||
int event_process_input_class(rdpEvent* event, wMessage* msg, int type)
|
|
||||||
{
|
|
||||||
int status = 0;
|
|
||||||
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case Input_SynchronizeEvent:
|
|
||||||
IFCALL(event->SynchronizeEvent, msg->context, (UINT32) (size_t) msg->wParam);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Input_KeyboardEvent:
|
|
||||||
IFCALL(event->KeyboardEvent, msg->context, (UINT16) (size_t) msg->wParam, (UINT16) (size_t) msg->lParam);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Input_UnicodeKeyboardEvent:
|
|
||||||
IFCALL(event->UnicodeKeyboardEvent, msg->context, (UINT16) (size_t) msg->wParam, (UINT16) (size_t) msg->lParam);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Input_MouseEvent:
|
|
||||||
{
|
|
||||||
UINT32 pos;
|
|
||||||
UINT16 x, y;
|
|
||||||
|
|
||||||
pos = (UINT32) (size_t) msg->lParam;
|
|
||||||
x = ((pos & 0xFFFF0000) >> 16);
|
|
||||||
y = (pos & 0x0000FFFF);
|
|
||||||
|
|
||||||
IFCALL(event->MouseEvent, msg->context, (UINT16) (size_t) msg->wParam, x, y);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Input_ExtendedMouseEvent:
|
|
||||||
{
|
|
||||||
UINT32 pos;
|
|
||||||
UINT16 x, y;
|
|
||||||
|
|
||||||
pos = (UINT32) (size_t) msg->lParam;
|
|
||||||
x = ((pos & 0xFFFF0000) >> 16);
|
|
||||||
y = (pos & 0x0000FFFF);
|
|
||||||
|
|
||||||
IFCALL(event->ExtendedMouseEvent, msg->context, (UINT16) (size_t) msg->wParam, x, y);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
status = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int event_process_class(rdpEvent* event, wMessage* msg, int msgClass, int msgType)
|
|
||||||
{
|
|
||||||
int status = 0;
|
|
||||||
|
|
||||||
switch (msgClass)
|
|
||||||
{
|
|
||||||
case Input_Class:
|
|
||||||
status = event_process_input_class(event, msg, msgType);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
status = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status < 0)
|
|
||||||
printf("Unknown event: class: %d type: %d\n", msgClass, msgType);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
int event_process_pending_input(rdpInput* input)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
int msgClass;
|
|
||||||
int msgType;
|
|
||||||
wMessage message;
|
|
||||||
wMessageQueue* queue;
|
|
||||||
|
|
||||||
queue = input->queue;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
status = MessageQueue_Peek(queue, &message, TRUE);
|
|
||||||
|
|
||||||
if (!status)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (message.type == WMQ_QUIT)
|
|
||||||
break;
|
|
||||||
|
|
||||||
msgClass = GetMessageClass(message.type);
|
|
||||||
msgType = GetMessageType(message.type);
|
|
||||||
|
|
||||||
status = event_process_class(input->event, &message, msgClass, msgType);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void event_register_input(rdpEvent* event, rdpInput* input)
|
|
||||||
{
|
|
||||||
/* Input */
|
|
||||||
|
|
||||||
event->SynchronizeEvent = input->SynchronizeEvent;
|
|
||||||
event->KeyboardEvent = input->KeyboardEvent;
|
|
||||||
event->UnicodeKeyboardEvent = input->UnicodeKeyboardEvent;
|
|
||||||
event->MouseEvent = input->MouseEvent;
|
|
||||||
event->ExtendedMouseEvent = input->ExtendedMouseEvent;
|
|
||||||
|
|
||||||
input->SynchronizeEvent = event_SynchronizeEvent;
|
|
||||||
input->KeyboardEvent = event_KeyboardEvent;
|
|
||||||
input->UnicodeKeyboardEvent = event_UnicodeKeyboardEvent;
|
|
||||||
input->MouseEvent = event_MouseEvent;
|
|
||||||
input->ExtendedMouseEvent = event_ExtendedMouseEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
rdpEvent* event_new(rdpInput* input)
|
|
||||||
{
|
|
||||||
rdpEvent* event;
|
|
||||||
|
|
||||||
event = (rdpEvent*) malloc(sizeof(rdpEvent));
|
|
||||||
|
|
||||||
if (event)
|
|
||||||
{
|
|
||||||
ZeroMemory(event, sizeof(rdpEvent));
|
|
||||||
|
|
||||||
event->input = input;
|
|
||||||
input->queue = MessageQueue_New();
|
|
||||||
event_register_input(event, input);
|
|
||||||
}
|
|
||||||
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
void event_free(rdpEvent* event)
|
|
||||||
{
|
|
||||||
if (event)
|
|
||||||
{
|
|
||||||
MessageQueue_Free(event->input->queue);
|
|
||||||
free(event);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
/**
|
|
||||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
|
||||||
* Asynchronous Event Queue
|
|
||||||
*
|
|
||||||
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FREERDP_CORE_EVENT_PRIVATE_H
|
|
||||||
#define FREERDP_CORE_EVENT_PRIVATE_H
|
|
||||||
|
|
||||||
#include "message.h"
|
|
||||||
|
|
||||||
#include <freerdp/freerdp.h>
|
|
||||||
|
|
||||||
/* Input */
|
|
||||||
|
|
||||||
#define Input_Class 1
|
|
||||||
|
|
||||||
#define Input_SynchronizeEvent 1
|
|
||||||
#define Input_KeyboardEvent 2
|
|
||||||
#define Input_UnicodeKeyboardEvent 3
|
|
||||||
#define Input_MouseEvent 4
|
|
||||||
#define Input_ExtendedMouseEvent 5
|
|
||||||
|
|
||||||
/* Event Queue */
|
|
||||||
|
|
||||||
struct rdp_event
|
|
||||||
{
|
|
||||||
/* Input */
|
|
||||||
|
|
||||||
pSynchronizeEvent SynchronizeEvent;
|
|
||||||
pKeyboardEvent KeyboardEvent;
|
|
||||||
pUnicodeKeyboardEvent UnicodeKeyboardEvent;
|
|
||||||
pMouseEvent MouseEvent;
|
|
||||||
pExtendedMouseEvent ExtendedMouseEvent;
|
|
||||||
|
|
||||||
/* Internal */
|
|
||||||
|
|
||||||
rdpInput* input;
|
|
||||||
};
|
|
||||||
|
|
||||||
int event_process_pending_input(rdpInput* input);
|
|
||||||
|
|
||||||
rdpEvent* event_new(rdpInput* input);
|
|
||||||
void event_free(rdpEvent* event);
|
|
||||||
|
|
||||||
#endif /* FREERDP_CORE_EVENT_PRIVATE_H */
|
|
||||||
|
|
@ -157,11 +157,27 @@ const RPC_FAULT_CODE RPC_FAULT_CODES[] =
|
|||||||
|
|
||||||
const RPC_FAULT_CODE RPC_TSG_FAULT_CODES[] =
|
const RPC_FAULT_CODE RPC_TSG_FAULT_CODES[] =
|
||||||
{
|
{
|
||||||
DEFINE_RPC_FAULT_CODE(ERROR_SUCCESS)
|
DEFINE_RPC_FAULT_CODE(RPC_S_OK)
|
||||||
DEFINE_RPC_FAULT_CODE(ERROR_ACCESS_DENIED)
|
DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_ARG)
|
||||||
DEFINE_RPC_FAULT_CODE(ERROR_INVALID_HANDLE)
|
DEFINE_RPC_FAULT_CODE(RPC_S_OUT_OF_MEMORY)
|
||||||
|
DEFINE_RPC_FAULT_CODE(RPC_S_OUT_OF_THREADS)
|
||||||
|
DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_LEVEL)
|
||||||
|
DEFINE_RPC_FAULT_CODE(RPC_S_BUFFER_TOO_SMALL)
|
||||||
|
DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_SECURITY_DESC)
|
||||||
|
DEFINE_RPC_FAULT_CODE(RPC_S_ACCESS_DENIED)
|
||||||
|
DEFINE_RPC_FAULT_CODE(RPC_S_SERVER_OUT_OF_MEMORY)
|
||||||
|
DEFINE_RPC_FAULT_CODE(RPC_S_ASYNC_CALL_PENDING)
|
||||||
|
DEFINE_RPC_FAULT_CODE(RPC_S_UNKNOWN_PRINCIPAL)
|
||||||
|
DEFINE_RPC_FAULT_CODE(RPC_S_TIMEOUT)
|
||||||
|
DEFINE_RPC_FAULT_CODE(RPC_X_NO_MEMORY)
|
||||||
|
DEFINE_RPC_FAULT_CODE(RPC_X_INVALID_BOUND)
|
||||||
|
DEFINE_RPC_FAULT_CODE(RPC_X_INVALID_TAG)
|
||||||
|
DEFINE_RPC_FAULT_CODE(RPC_X_ENUM_VALUE_TOO_LARGE)
|
||||||
|
DEFINE_RPC_FAULT_CODE(RPC_X_SS_CONTEXT_MISMATCH)
|
||||||
|
DEFINE_RPC_FAULT_CODE(RPC_X_INVALID_BUFFER)
|
||||||
|
DEFINE_RPC_FAULT_CODE(RPC_X_PIPE_APP_MEMORY)
|
||||||
|
DEFINE_RPC_FAULT_CODE(RPC_X_INVALID_PIPE_OPERATION)
|
||||||
DEFINE_RPC_FAULT_CODE(ERROR_ONLY_IF_CONNECTED)
|
DEFINE_RPC_FAULT_CODE(ERROR_ONLY_IF_CONNECTED)
|
||||||
DEFINE_RPC_FAULT_CODE(ERROR_INVALID_PARAMETER)
|
|
||||||
DEFINE_RPC_FAULT_CODE(ERROR_GRACEFUL_DISCONNECT)
|
DEFINE_RPC_FAULT_CODE(ERROR_GRACEFUL_DISCONNECT)
|
||||||
DEFINE_RPC_FAULT_CODE(ERROR_OPERATION_ABORTED)
|
DEFINE_RPC_FAULT_CODE(ERROR_OPERATION_ABORTED)
|
||||||
DEFINE_RPC_FAULT_CODE(ERROR_BAD_ARGUMENTS)
|
DEFINE_RPC_FAULT_CODE(ERROR_BAD_ARGUMENTS)
|
||||||
|
@ -320,8 +320,7 @@ BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg)
|
|||||||
SwitchValue = *((UINT32*) &buffer[offset + 4]); /* SwitchValue */
|
SwitchValue = *((UINT32*) &buffer[offset + 4]); /* SwitchValue */
|
||||||
offset += 8;
|
offset += 8;
|
||||||
|
|
||||||
if ((SwitchValue != TSG_CAPABILITY_TYPE_NAP) ||
|
if ((SwitchValue != TSG_CAPABILITY_TYPE_NAP) || (tsgCaps->capabilityType != TSG_CAPABILITY_TYPE_NAP))
|
||||||
(tsgCaps->capabilityType != TSG_CAPABILITY_TYPE_NAP))
|
|
||||||
{
|
{
|
||||||
printf("Unexpected CapabilityType: 0x%08X, Expected TSG_CAPABILITY_TYPE_NAP\n",
|
printf("Unexpected CapabilityType: 0x%08X, Expected TSG_CAPABILITY_TYPE_NAP\n",
|
||||||
tsgCaps->capabilityType);
|
tsgCaps->capabilityType);
|
||||||
@ -573,8 +572,7 @@ BOOL TsProxyAuthorizeTunnelReadResponse(rdpTsg* tsg)
|
|||||||
packet->packetId = *((UINT32*) &buffer[offset]); /* PacketId */
|
packet->packetId = *((UINT32*) &buffer[offset]); /* PacketId */
|
||||||
SwitchValue = *((UINT32*) &buffer[offset + 4]); /* SwitchValue */
|
SwitchValue = *((UINT32*) &buffer[offset + 4]); /* SwitchValue */
|
||||||
|
|
||||||
if ((packet->packetId != TSG_PACKET_TYPE_RESPONSE) ||
|
if ((packet->packetId != TSG_PACKET_TYPE_RESPONSE) || (SwitchValue != TSG_PACKET_TYPE_RESPONSE))
|
||||||
(SwitchValue != TSG_PACKET_TYPE_RESPONSE))
|
|
||||||
{
|
{
|
||||||
printf("Unexpected PacketId: 0x%08X, Expected TSG_PACKET_TYPE_RESPONSE\n", packet->packetId);
|
printf("Unexpected PacketId: 0x%08X, Expected TSG_PACKET_TYPE_RESPONSE\n", packet->packetId);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -696,7 +694,114 @@ BOOL TsProxyMakeTunnelCallWriteRequest(rdpTsg* tsg, PTUNNEL_CONTEXT_HANDLE_NOSER
|
|||||||
|
|
||||||
BOOL TsProxyMakeTunnelCallReadResponse(rdpTsg* tsg)
|
BOOL TsProxyMakeTunnelCallReadResponse(rdpTsg* tsg)
|
||||||
{
|
{
|
||||||
/* ??? */
|
RPC_PDU* pdu;
|
||||||
|
BYTE* buffer;
|
||||||
|
UINT32 length;
|
||||||
|
UINT32 offset;
|
||||||
|
UINT32 Pointer;
|
||||||
|
UINT32 MaxCount;
|
||||||
|
UINT32 ActualCount;
|
||||||
|
UINT32 SwitchValue;
|
||||||
|
PTSG_PACKET packet;
|
||||||
|
rdpRpc* rpc = tsg->rpc;
|
||||||
|
PTSG_PACKET_MSG_RESPONSE packetMsgResponse;
|
||||||
|
PTSG_PACKET_STRING_MESSAGE packetStringMessage = NULL;
|
||||||
|
PTSG_PACKET_REAUTH_MESSAGE packetReauthMessage = NULL;
|
||||||
|
|
||||||
|
/* This is an asynchronous response */
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
pdu = rpc_recv_dequeue_pdu(rpc);
|
||||||
|
|
||||||
|
if (!pdu)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
length = Stream_Length(pdu->s);
|
||||||
|
buffer = Stream_Buffer(pdu->s);
|
||||||
|
|
||||||
|
if (!(pdu->Flags & RPC_PDU_FLAG_STUB))
|
||||||
|
buffer = &buffer[24];
|
||||||
|
|
||||||
|
packet = (PTSG_PACKET) malloc(sizeof(TSG_PACKET));
|
||||||
|
ZeroMemory(packet, sizeof(TSG_PACKET));
|
||||||
|
|
||||||
|
offset = 4;
|
||||||
|
packet->packetId = *((UINT32*) &buffer[offset]); /* PacketId */
|
||||||
|
SwitchValue = *((UINT32*) &buffer[offset + 4]); /* SwitchValue */
|
||||||
|
|
||||||
|
if ((packet->packetId != TSG_PACKET_TYPE_MESSAGE_PACKET) || (SwitchValue != TSG_PACKET_TYPE_MESSAGE_PACKET))
|
||||||
|
{
|
||||||
|
printf("Unexpected PacketId: 0x%08X, Expected TSG_PACKET_TYPE_MESSAGE_PACKET\n", packet->packetId);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
packetMsgResponse = (PTSG_PACKET_MSG_RESPONSE) malloc(sizeof(TSG_PACKET_MSG_RESPONSE));
|
||||||
|
ZeroMemory(packetMsgResponse, sizeof(TSG_PACKET_MSG_RESPONSE));
|
||||||
|
packet->tsgPacket.packetMsgResponse = packetMsgResponse;
|
||||||
|
|
||||||
|
Pointer = *((UINT32*) &buffer[offset + 8]); /* PacketMsgResponsePtr */
|
||||||
|
packetMsgResponse->msgID = *((UINT32*) &buffer[offset + 12]); /* MsgId */
|
||||||
|
packetMsgResponse->msgType = *((UINT32*) &buffer[offset + 16]); /* MsgType */
|
||||||
|
packetMsgResponse->isMsgPresent = *((INT32*) &buffer[offset + 20]); /* IsMsgPresent */
|
||||||
|
|
||||||
|
SwitchValue = *((UINT32*) &buffer[offset + 24]); /* SwitchValue */
|
||||||
|
|
||||||
|
switch (SwitchValue)
|
||||||
|
{
|
||||||
|
case TSG_ASYNC_MESSAGE_CONSENT_MESSAGE:
|
||||||
|
packetStringMessage = (PTSG_PACKET_STRING_MESSAGE) malloc(sizeof(TSG_PACKET_STRING_MESSAGE));
|
||||||
|
ZeroMemory(packetStringMessage, sizeof(TSG_PACKET_STRING_MESSAGE));
|
||||||
|
packetMsgResponse->messagePacket.consentMessage = packetStringMessage;
|
||||||
|
|
||||||
|
Pointer = *((UINT32*) &buffer[offset + 28]); /* ConsentMessagePtr */
|
||||||
|
packetStringMessage->isDisplayMandatory = *((INT32*) &buffer[offset + 32]); /* IsDisplayMandatory */
|
||||||
|
packetStringMessage->isConsentMandatory = *((INT32*) &buffer[offset + 36]); /* IsConsentMandatory */
|
||||||
|
packetStringMessage->msgBytes = *((UINT32*) &buffer[offset + 40]); /* MsgBytes */
|
||||||
|
|
||||||
|
Pointer = *((UINT32*) &buffer[offset + 44]); /* MsgPtr */
|
||||||
|
MaxCount = *((UINT32*) &buffer[offset + 48]); /* MaxCount */
|
||||||
|
/* Offset */
|
||||||
|
ActualCount = *((UINT32*) &buffer[offset + 56]); /* ActualCount */
|
||||||
|
|
||||||
|
winpr_HexDump(&buffer[offset + 60], ActualCount * 2);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TSG_ASYNC_MESSAGE_SERVICE_MESSAGE:
|
||||||
|
packetStringMessage = (PTSG_PACKET_STRING_MESSAGE) malloc(sizeof(TSG_PACKET_STRING_MESSAGE));
|
||||||
|
ZeroMemory(packetStringMessage, sizeof(TSG_PACKET_STRING_MESSAGE));
|
||||||
|
packetMsgResponse->messagePacket.serviceMessage = packetStringMessage;
|
||||||
|
|
||||||
|
Pointer = *((UINT32*) &buffer[offset + 28]); /* ServiceMessagePtr */
|
||||||
|
packetStringMessage->isDisplayMandatory = *((INT32*) &buffer[offset + 32]); /* IsDisplayMandatory */
|
||||||
|
packetStringMessage->isConsentMandatory = *((INT32*) &buffer[offset + 36]); /* IsConsentMandatory */
|
||||||
|
packetStringMessage->msgBytes = *((UINT32*) &buffer[offset + 40]); /* MsgBytes */
|
||||||
|
|
||||||
|
Pointer = *((UINT32*) &buffer[offset + 44]); /* MsgPtr */
|
||||||
|
MaxCount = *((UINT32*) &buffer[offset + 48]); /* MaxCount */
|
||||||
|
/* Offset */
|
||||||
|
ActualCount = *((UINT32*) &buffer[offset + 56]); /* ActualCount */
|
||||||
|
|
||||||
|
winpr_HexDump(&buffer[offset + 60], ActualCount * 2);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TSG_ASYNC_MESSAGE_REAUTH:
|
||||||
|
packetReauthMessage = (PTSG_PACKET_REAUTH_MESSAGE) malloc(sizeof(TSG_PACKET_REAUTH_MESSAGE));
|
||||||
|
ZeroMemory(packetReauthMessage, sizeof(TSG_PACKET_REAUTH_MESSAGE));
|
||||||
|
packetMsgResponse->messagePacket.reauthMessage = packetReauthMessage;
|
||||||
|
|
||||||
|
Pointer = *((UINT32*) &buffer[offset + 28]); /* ReauthMessagePtr */
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("TsProxyMakeTunnelCallReadResponse: unexpected message type: %d\n", SwitchValue);
|
||||||
|
return FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -112,6 +112,7 @@ typedef struct _tsendpointinfo
|
|||||||
#define TSG_ASYNC_MESSAGE_CONSENT_MESSAGE 0x00000001
|
#define TSG_ASYNC_MESSAGE_CONSENT_MESSAGE 0x00000001
|
||||||
#define TSG_ASYNC_MESSAGE_SERVICE_MESSAGE 0x00000002
|
#define TSG_ASYNC_MESSAGE_SERVICE_MESSAGE 0x00000002
|
||||||
#define TSG_ASYNC_MESSAGE_REAUTH 0x00000003
|
#define TSG_ASYNC_MESSAGE_REAUTH 0x00000003
|
||||||
|
|
||||||
#define TSG_TUNNEL_CALL_ASYNC_MSG_REQUEST 0x00000001
|
#define TSG_TUNNEL_CALL_ASYNC_MSG_REQUEST 0x00000001
|
||||||
#define TSG_TUNNEL_CANCEL_ASYNC_MSG_REQUEST 0x00000002
|
#define TSG_TUNNEL_CANCEL_ASYNC_MSG_REQUEST 0x00000002
|
||||||
|
|
||||||
|
@ -25,8 +25,9 @@
|
|||||||
|
|
||||||
#include <freerdp/input.h>
|
#include <freerdp/input.h>
|
||||||
|
|
||||||
|
#include "message.h"
|
||||||
|
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "event.h"
|
|
||||||
|
|
||||||
void rdp_write_client_input_pdu_header(STREAM* s, UINT16 number)
|
void rdp_write_client_input_pdu_header(STREAM* s, UINT16 number)
|
||||||
{
|
{
|
||||||
@ -392,7 +393,7 @@ void input_register_client_callbacks(rdpInput* input)
|
|||||||
|
|
||||||
if (input->asynchronous)
|
if (input->asynchronous)
|
||||||
{
|
{
|
||||||
input->event = event_new(input);
|
input->proxy = input_message_proxy_new(input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -431,7 +432,7 @@ void freerdp_input_send_extended_mouse_event(rdpInput* input, UINT16 flags, UINT
|
|||||||
|
|
||||||
int input_process_events(rdpInput* input)
|
int input_process_events(rdpInput* input)
|
||||||
{
|
{
|
||||||
return event_process_pending_input(input);
|
return input_message_process_pending_input(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
rdpInput* input_new(rdpRdp* rdp)
|
rdpInput* input_new(rdpRdp* rdp)
|
||||||
@ -453,7 +454,7 @@ void input_free(rdpInput* input)
|
|||||||
if (input != NULL)
|
if (input != NULL)
|
||||||
{
|
{
|
||||||
if (input->asynchronous)
|
if (input->asynchronous)
|
||||||
event_free(input->event);
|
input_message_proxy_free(input->proxy);
|
||||||
|
|
||||||
free(input);
|
free(input);
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include "rdp.h"
|
#include "rdp.h"
|
||||||
#include "fastpath.h"
|
#include "fastpath.h"
|
||||||
#include "event.h"
|
#include "message.h"
|
||||||
|
|
||||||
#include <freerdp/input.h>
|
#include <freerdp/input.h>
|
||||||
#include <freerdp/freerdp.h>
|
#include <freerdp/freerdp.h>
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -22,11 +22,15 @@
|
|||||||
|
|
||||||
#include <freerdp/freerdp.h>
|
#include <freerdp/freerdp.h>
|
||||||
|
|
||||||
#define GetMessageType(_id) (_id & 0xF)
|
#define GetMessageType(_id) (_id & 0xFF)
|
||||||
#define GetMessageClass(_id) ((_id >> 8) & 0xF)
|
#define GetMessageClass(_id) ((_id >> 16) & 0xFF)
|
||||||
|
|
||||||
#define MakeMessageId(_class, _type) \
|
#define MakeMessageId(_class, _type) \
|
||||||
(((_class ##_Class) << 8) | (_class ## _ ## _type))
|
(((_class ##_Class) << 16) | (_class ## _ ## _type))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update Message Queue
|
||||||
|
*/
|
||||||
|
|
||||||
/* Update */
|
/* Update */
|
||||||
|
|
||||||
@ -128,10 +132,12 @@
|
|||||||
#define PointerUpdate_PointerNew 4
|
#define PointerUpdate_PointerNew 4
|
||||||
#define PointerUpdate_PointerCached 5
|
#define PointerUpdate_PointerCached 5
|
||||||
|
|
||||||
/* Message Queue */
|
/* Update Proxy Interface */
|
||||||
|
|
||||||
struct rdp_message
|
struct rdp_update_proxy
|
||||||
{
|
{
|
||||||
|
rdpUpdate* update;
|
||||||
|
|
||||||
/* Update */
|
/* Update */
|
||||||
|
|
||||||
pBeginPaint BeginPaint;
|
pBeginPaint BeginPaint;
|
||||||
@ -219,15 +225,45 @@ struct rdp_message
|
|||||||
pPointerColor PointerColor;
|
pPointerColor PointerColor;
|
||||||
pPointerNew PointerNew;
|
pPointerNew PointerNew;
|
||||||
pPointerCached PointerCached;
|
pPointerCached PointerCached;
|
||||||
|
|
||||||
/* Internal */
|
|
||||||
|
|
||||||
rdpUpdate* update;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int message_process_pending_updates(rdpUpdate* update);
|
int update_message_process_pending_updates(rdpUpdate* update);
|
||||||
|
|
||||||
rdpMessage* message_new(rdpUpdate* update);
|
rdpUpdateProxy* update_message_proxy_new(rdpUpdate* update);
|
||||||
void message_free(rdpMessage* message);
|
void update_message_proxy_free(rdpUpdateProxy* message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input Message Queue
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Input */
|
||||||
|
|
||||||
|
#define Input_Class 1
|
||||||
|
|
||||||
|
#define Input_SynchronizeEvent 1
|
||||||
|
#define Input_KeyboardEvent 2
|
||||||
|
#define Input_UnicodeKeyboardEvent 3
|
||||||
|
#define Input_MouseEvent 4
|
||||||
|
#define Input_ExtendedMouseEvent 5
|
||||||
|
|
||||||
|
/* Input Proxy Interface */
|
||||||
|
|
||||||
|
struct rdp_input_proxy
|
||||||
|
{
|
||||||
|
rdpInput* input;
|
||||||
|
|
||||||
|
/* Input */
|
||||||
|
|
||||||
|
pSynchronizeEvent SynchronizeEvent;
|
||||||
|
pKeyboardEvent KeyboardEvent;
|
||||||
|
pUnicodeKeyboardEvent UnicodeKeyboardEvent;
|
||||||
|
pMouseEvent MouseEvent;
|
||||||
|
pExtendedMouseEvent ExtendedMouseEvent;
|
||||||
|
};
|
||||||
|
|
||||||
|
int input_message_process_pending_input(rdpInput* input);
|
||||||
|
|
||||||
|
rdpInputProxy* input_message_proxy_new(rdpInput* input);
|
||||||
|
void input_message_proxy_free(rdpInputProxy* proxy);
|
||||||
|
|
||||||
#endif /* FREERDP_CORE_MESSAGE_PRIVATE_H */
|
#endif /* FREERDP_CORE_MESSAGE_PRIVATE_H */
|
||||||
|
@ -909,8 +909,6 @@ BOOL update_read_glyph_index_order(STREAM* s, ORDER_INFO* orderInfo, GLYPH_INDEX
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BOOL update_read_fast_index_order(STREAM* s, ORDER_INFO* orderInfo, FAST_INDEX_ORDER* fast_index)
|
BOOL update_read_fast_index_order(STREAM* s, ORDER_INFO* orderInfo, FAST_INDEX_ORDER* fast_index)
|
||||||
{
|
{
|
||||||
ORDER_FIELD_BYTE(1, fast_index->cacheId);
|
ORDER_FIELD_BYTE(1, fast_index->cacheId);
|
||||||
@ -942,12 +940,10 @@ BOOL update_read_fast_index_order(STREAM* s, ORDER_INFO* orderInfo, FAST_INDEX_O
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BOOL update_read_fast_glyph_order(STREAM* s, ORDER_INFO* orderInfo, FAST_GLYPH_ORDER* fast_glyph)
|
BOOL update_read_fast_glyph_order(STREAM* s, ORDER_INFO* orderInfo, FAST_GLYPH_ORDER* fast_glyph)
|
||||||
{
|
{
|
||||||
GLYPH_DATA_V2* glyph;
|
|
||||||
BYTE* phold;
|
BYTE* phold;
|
||||||
|
GLYPH_DATA_V2* glyph;
|
||||||
|
|
||||||
ORDER_FIELD_BYTE(1, fast_glyph->cacheId);
|
ORDER_FIELD_BYTE(1, fast_glyph->cacheId);
|
||||||
ORDER_FIELD_2BYTE(2, fast_glyph->ulCharInc, fast_glyph->flAccel);
|
ORDER_FIELD_2BYTE(2, fast_glyph->ulCharInc, fast_glyph->flAccel);
|
||||||
@ -968,32 +964,40 @@ BOOL update_read_fast_glyph_order(STREAM* s, ORDER_INFO* orderInfo, FAST_GLYPH_O
|
|||||||
{
|
{
|
||||||
if (stream_get_left(s) < 1)
|
if (stream_get_left(s) < 1)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
stream_read_BYTE(s, fast_glyph->cbData);
|
stream_read_BYTE(s, fast_glyph->cbData);
|
||||||
|
|
||||||
if (stream_get_left(s) < fast_glyph->cbData)
|
if (stream_get_left(s) < fast_glyph->cbData)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
memcpy(fast_glyph->data, s->p, fast_glyph->cbData);
|
memcpy(fast_glyph->data, s->p, fast_glyph->cbData);
|
||||||
phold = s->p;
|
phold = s->p;
|
||||||
|
|
||||||
if (!stream_skip(s, 1))
|
if (!stream_skip(s, 1))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
if ((fast_glyph->cbData > 1) && (fast_glyph->glyph_data == NULL))
|
|
||||||
|
if (fast_glyph->cbData > 1)
|
||||||
{
|
{
|
||||||
/* parse optional glyph data */
|
/* parse optional glyph data */
|
||||||
glyph = (GLYPH_DATA_V2*) malloc(sizeof(GLYPH_DATA_V2));
|
glyph = &fast_glyph->glyphData;
|
||||||
glyph->cacheIndex = fast_glyph->data[0];
|
glyph->cacheIndex = fast_glyph->data[0];
|
||||||
|
|
||||||
if (!update_read_2byte_signed(s, &glyph->x) ||
|
if (!update_read_2byte_signed(s, &glyph->x) ||
|
||||||
!update_read_2byte_signed(s, &glyph->y) ||
|
!update_read_2byte_signed(s, &glyph->y) ||
|
||||||
!update_read_2byte_unsigned(s, &glyph->cx) ||
|
!update_read_2byte_unsigned(s, &glyph->cx) ||
|
||||||
!update_read_2byte_unsigned(s, &glyph->cy))
|
!update_read_2byte_unsigned(s, &glyph->cy))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
glyph->cb = ((glyph->cx + 7) / 8) * glyph->cy;
|
glyph->cb = ((glyph->cx + 7) / 8) * glyph->cy;
|
||||||
glyph->cb += ((glyph->cb % 4) > 0) ? 4 - (glyph->cb % 4) : 0;
|
glyph->cb += ((glyph->cb % 4) > 0) ? 4 - (glyph->cb % 4) : 0;
|
||||||
|
|
||||||
if (stream_get_left(s) < glyph->cb)
|
if (stream_get_left(s) < glyph->cb)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
glyph->aj = (BYTE*) malloc(glyph->cb);
|
glyph->aj = (BYTE*) malloc(glyph->cb);
|
||||||
stream_read(s, glyph->aj, glyph->cb);
|
stream_read(s, glyph->aj, glyph->cb);
|
||||||
fast_glyph->glyph_data = glyph;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s->p = phold + fast_glyph->cbData;
|
s->p = phold + fast_glyph->cbData;
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -1239,25 +1243,26 @@ BOOL update_read_cache_color_table_order(STREAM* s, CACHE_COLOR_TABLE_ORDER* cac
|
|||||||
|
|
||||||
if (stream_get_left(s) < 3)
|
if (stream_get_left(s) < 3)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
stream_read_BYTE(s, cache_color_table_order->cacheIndex); /* cacheIndex (1 byte) */
|
stream_read_BYTE(s, cache_color_table_order->cacheIndex); /* cacheIndex (1 byte) */
|
||||||
stream_read_UINT16(s, cache_color_table_order->numberColors); /* numberColors (2 bytes) */
|
stream_read_UINT16(s, cache_color_table_order->numberColors); /* numberColors (2 bytes) */
|
||||||
|
|
||||||
|
if (cache_color_table_order->numberColors != 256)
|
||||||
|
{
|
||||||
|
/* This field MUST be set to 256 */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (stream_get_left(s) < cache_color_table_order->numberColors * 4)
|
if (stream_get_left(s) < cache_color_table_order->numberColors * 4)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
colorTable = cache_color_table_order->colorTable;
|
colorTable = (UINT32*) &cache_color_table_order->colorTable;
|
||||||
|
|
||||||
if (colorTable == NULL)
|
|
||||||
colorTable = (UINT32*) malloc(cache_color_table_order->numberColors * 4);
|
|
||||||
else
|
|
||||||
colorTable = (UINT32*) realloc(colorTable, cache_color_table_order->numberColors * 4);
|
|
||||||
|
|
||||||
for (i = 0; i < (int) cache_color_table_order->numberColors; i++)
|
for (i = 0; i < (int) cache_color_table_order->numberColors; i++)
|
||||||
{
|
{
|
||||||
update_read_color_quad(s, &colorTable[i]);
|
update_read_color_quad(s, &colorTable[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
cache_color_table_order->colorTable = colorTable;
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,7 +429,7 @@ void update_post_connect(rdpUpdate* update)
|
|||||||
update->asynchronous = update->context->settings->AsyncUpdate;
|
update->asynchronous = update->context->settings->AsyncUpdate;
|
||||||
|
|
||||||
if (update->asynchronous)
|
if (update->asynchronous)
|
||||||
update->message = message_new(update);
|
update->proxy = update_message_proxy_new(update);
|
||||||
|
|
||||||
update->altsec->switch_surface.bitmapId = SCREEN_BITMAP_SURFACE;
|
update->altsec->switch_surface.bitmapId = SCREEN_BITMAP_SURFACE;
|
||||||
IFCALL(update->altsec->SwitchSurface, update->context, &(update->altsec->switch_surface));
|
IFCALL(update->altsec->SwitchSurface, update->context, &(update->altsec->switch_surface));
|
||||||
@ -735,7 +735,7 @@ void update_register_client_callbacks(rdpUpdate* update)
|
|||||||
|
|
||||||
int update_process_messages(rdpUpdate* update)
|
int update_process_messages(rdpUpdate* update)
|
||||||
{
|
{
|
||||||
return message_process_pending_updates(update);
|
return update_message_process_pending_updates(update);
|
||||||
}
|
}
|
||||||
|
|
||||||
rdpUpdate* update_new(rdpRdp* rdp)
|
rdpUpdate* update_new(rdpRdp* rdp)
|
||||||
@ -808,7 +808,7 @@ void update_free(rdpUpdate* update)
|
|||||||
free(update->window);
|
free(update->window);
|
||||||
|
|
||||||
if (update->asynchronous)
|
if (update->asynchronous)
|
||||||
message_free(update->message);
|
update_message_proxy_free(update->proxy);
|
||||||
|
|
||||||
free(update);
|
free(update);
|
||||||
}
|
}
|
||||||
|
@ -104,6 +104,7 @@ static void* base64_decode(BYTE* s, int length, int* data_len)
|
|||||||
if (length % 4)
|
if (length % 4)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
n[0] = n[1] = n[2] = n[3] = 0;
|
||||||
q = data = (BYTE*) malloc(length / 4 * 3);
|
q = data = (BYTE*) malloc(length / 4 * 3);
|
||||||
|
|
||||||
for (p = (char*) s; *p; )
|
for (p = (char*) s; *p; )
|
||||||
|
@ -506,6 +506,60 @@ static int BitBlt_PSDPxax_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWi
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int BitBlt_SPDSxax_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
UINT32* srcp;
|
||||||
|
UINT32* dstp;
|
||||||
|
UINT32* patp;
|
||||||
|
UINT32 color32;
|
||||||
|
|
||||||
|
/* D = S ^ (P & (D ^ S)) */
|
||||||
|
|
||||||
|
if (hdcDest->brush->style == GDI_BS_SOLID)
|
||||||
|
{
|
||||||
|
color32 = gdi_get_color_32bpp(hdcDest, hdcDest->brush->color);
|
||||||
|
patp = (UINT32*) &color32;
|
||||||
|
|
||||||
|
for (y = 0; y < nHeight; y++)
|
||||||
|
{
|
||||||
|
srcp = (UINT32*) gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y);
|
||||||
|
dstp = (UINT32*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y);
|
||||||
|
|
||||||
|
if (dstp != 0)
|
||||||
|
{
|
||||||
|
for (x = 0; x < nWidth; x++)
|
||||||
|
{
|
||||||
|
*dstp = *srcp ^ (*patp & (*dstp ^ *srcp));
|
||||||
|
srcp++;
|
||||||
|
dstp++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (y = 0; y < nHeight; y++)
|
||||||
|
{
|
||||||
|
srcp = (UINT32*) gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y);
|
||||||
|
dstp = (UINT32*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y);
|
||||||
|
|
||||||
|
if (dstp != 0)
|
||||||
|
{
|
||||||
|
for (x = 0; x < nWidth; x++)
|
||||||
|
{
|
||||||
|
patp = (UINT32*) gdi_get_brush_pointer(hdcDest, x, y);
|
||||||
|
*dstp = *srcp ^ (*patp & (*dstp ^ *srcp));
|
||||||
|
srcp++;
|
||||||
|
dstp++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int BitBlt_SPna_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc)
|
static int BitBlt_SPna_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc)
|
||||||
{
|
{
|
||||||
int x, y;
|
int x, y;
|
||||||
@ -839,6 +893,10 @@ int BitBlt_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeigh
|
|||||||
return BitBlt_PSDPxax_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc);
|
return BitBlt_PSDPxax_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GDI_SPDSxax:
|
||||||
|
return BitBlt_SPDSxax_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc);
|
||||||
|
break;
|
||||||
|
|
||||||
case GDI_NOTSRCCOPY:
|
case GDI_NOTSRCCOPY:
|
||||||
return BitBlt_NOTSRCCOPY_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc);
|
return BitBlt_NOTSRCCOPY_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc);
|
||||||
break;
|
break;
|
||||||
|
@ -58,3 +58,8 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/libfreerdp")
|
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/libfreerdp")
|
||||||
|
|
||||||
|
if(BUILD_TESTING)
|
||||||
|
add_subdirectory(test)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
@ -449,8 +449,7 @@ void gdi_bitmap_free_ex(gdiBitmap* bitmap)
|
|||||||
void gdi_palette_update(rdpContext* context, PALETTE_UPDATE* palette)
|
void gdi_palette_update(rdpContext* context, PALETTE_UPDATE* palette)
|
||||||
{
|
{
|
||||||
rdpGdi* gdi = context->gdi;
|
rdpGdi* gdi = context->gdi;
|
||||||
gdi->clrconv->palette->count = palette->number;
|
CopyMemory(gdi->clrconv->palette, palette, sizeof(rdpPalette));
|
||||||
gdi->clrconv->palette->entries = palette->entries;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gdi_set_bounds(rdpContext* context, rdpBounds* bounds)
|
void gdi_set_bounds(rdpContext* context, rdpBounds* bounds)
|
||||||
@ -662,6 +661,7 @@ void gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt)
|
|||||||
|
|
||||||
void gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt)
|
void gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt)
|
||||||
{
|
{
|
||||||
|
BYTE* data;
|
||||||
rdpBrush* brush;
|
rdpBrush* brush;
|
||||||
UINT32 foreColor;
|
UINT32 foreColor;
|
||||||
UINT32 backColor;
|
UINT32 backColor;
|
||||||
@ -687,6 +687,32 @@ void gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt)
|
|||||||
gdi_DeleteObject((HGDIOBJECT) gdi->drawing->hdc->brush);
|
gdi_DeleteObject((HGDIOBJECT) gdi->drawing->hdc->brush);
|
||||||
gdi->drawing->hdc->brush = originalBrush;
|
gdi->drawing->hdc->brush = originalBrush;
|
||||||
}
|
}
|
||||||
|
else if (brush->style == GDI_BS_PATTERN)
|
||||||
|
{
|
||||||
|
HGDI_BITMAP hBmp;
|
||||||
|
|
||||||
|
if (brush->bpp > 1)
|
||||||
|
{
|
||||||
|
data = freerdp_image_convert(brush->data, NULL, 8, 8, gdi->srcBpp, gdi->dstBpp, gdi->clrconv);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data = freerdp_mono_image_convert(brush->data, 8, 8, gdi->srcBpp, gdi->dstBpp,
|
||||||
|
mem3blt->backColor, mem3blt->foreColor, gdi->clrconv);
|
||||||
|
}
|
||||||
|
|
||||||
|
hBmp = gdi_CreateBitmap(8, 8, gdi->drawing->hdc->bitsPerPixel, data);
|
||||||
|
|
||||||
|
originalBrush = gdi->drawing->hdc->brush;
|
||||||
|
gdi->drawing->hdc->brush = gdi_CreatePatternBrush(hBmp);
|
||||||
|
|
||||||
|
gdi_BitBlt(gdi->drawing->hdc, mem3blt->nLeftRect, mem3blt->nTopRect,
|
||||||
|
mem3blt->nWidth, mem3blt->nHeight, bitmap->hdc,
|
||||||
|
mem3blt->nXSrc, mem3blt->nYSrc, gdi_rop3_code(mem3blt->bRop));
|
||||||
|
|
||||||
|
gdi_DeleteObject((HGDIOBJECT) gdi->drawing->hdc->brush);
|
||||||
|
gdi->drawing->hdc->brush = originalBrush;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("Mem3Blt unimplemented brush style:%d\n", brush->style);
|
printf("Mem3Blt unimplemented brush style:%d\n", brush->style);
|
||||||
|
2
libfreerdp/gdi/test/.gitignore
vendored
Normal file
2
libfreerdp/gdi/test/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
TestGdi
|
||||||
|
TestGdi.c
|
40
libfreerdp/gdi/test/CMakeLists.txt
Normal file
40
libfreerdp/gdi/test/CMakeLists.txt
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
|
||||||
|
set(MODULE_NAME "TestGdi")
|
||||||
|
set(MODULE_PREFIX "TEST_GDI")
|
||||||
|
|
||||||
|
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
|
||||||
|
|
||||||
|
set(${MODULE_PREFIX}_TESTS
|
||||||
|
TestGdiRop3.c)
|
||||||
|
|
||||||
|
create_test_sourcelist(${MODULE_PREFIX}_SRCS
|
||||||
|
${${MODULE_PREFIX}_DRIVER}
|
||||||
|
${${MODULE_PREFIX}_TESTS})
|
||||||
|
|
||||||
|
include_directories(..)
|
||||||
|
|
||||||
|
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||||
|
|
||||||
|
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${CMOCKERY_LIBRARIES})
|
||||||
|
|
||||||
|
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||||
|
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||||
|
MODULE freerdp
|
||||||
|
MODULES freerdp-gdi)
|
||||||
|
|
||||||
|
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||||
|
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||||
|
MODULE winpr
|
||||||
|
MODULES winpr-crt winpr-utils)
|
||||||
|
|
||||||
|
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||||
|
|
||||||
|
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
|
||||||
|
|
||||||
|
foreach(test ${${MODULE_PREFIX}_TESTS})
|
||||||
|
get_filename_component(TestName ${test} NAME_WE)
|
||||||
|
add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Test")
|
||||||
|
|
238
libfreerdp/gdi/test/TestGdiRop3.c
Normal file
238
libfreerdp/gdi/test/TestGdiRop3.c
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
|
||||||
|
#include <winpr/crt.h>
|
||||||
|
#include <winpr/winpr.h>
|
||||||
|
#include <winpr/collections.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ternary Raster Operations:
|
||||||
|
* See "Windows Graphics Programming: Win32 GDI and DirectDraw", chapter 11. Advanced Bitmap Graphics
|
||||||
|
*
|
||||||
|
* Operators:
|
||||||
|
*
|
||||||
|
* AND & a
|
||||||
|
* OR | o
|
||||||
|
* NOT ~ n
|
||||||
|
* XOR ^ x
|
||||||
|
*
|
||||||
|
* Operands:
|
||||||
|
*
|
||||||
|
* Pen/Brush P
|
||||||
|
* Destination D
|
||||||
|
* Source S
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* Raster operation which returns P if S is 1 or D otherwise:
|
||||||
|
* (rop_S & rop_P) | (~rop_S & rop_D); -> 0xE2 (0x00E20746)
|
||||||
|
*
|
||||||
|
* Postfix notation: DSPDxax
|
||||||
|
* Infix notation: D^(S&(P^D))), (S&P)|(~S&D)
|
||||||
|
*
|
||||||
|
* DSPDxax using D^(S&(P^D)):
|
||||||
|
*
|
||||||
|
* mov eax, P // P
|
||||||
|
* xor eax, D // P^D
|
||||||
|
* and eax, S // S&(P^D)
|
||||||
|
* xor eax, D // D^(S&(P^D))
|
||||||
|
* mov D, eax // write result
|
||||||
|
*
|
||||||
|
* DSPDxax using (S&P)|(~S&D):
|
||||||
|
*
|
||||||
|
* mov eax, S // S
|
||||||
|
* and eax, P // S&P
|
||||||
|
* mov ebx, S // S
|
||||||
|
* not ebx // ~S
|
||||||
|
* and ebx, D // ~D&D
|
||||||
|
* or eax, ebx // (S&P)|(~S&D)
|
||||||
|
* mov D, eax // write result
|
||||||
|
*
|
||||||
|
* Raster operation lower word encoding:
|
||||||
|
*
|
||||||
|
* _______________________________________________________________________________
|
||||||
|
* | | | | | | | | | | | | | | | | |
|
||||||
|
* | Op5 | Op4 | Op3 | Op2 | Op1 | Not| Parse String | Offset |
|
||||||
|
* |____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|
|
||||||
|
* 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||||
|
*
|
||||||
|
* Operator:
|
||||||
|
* 0: NOT
|
||||||
|
* 1: XOR
|
||||||
|
* 2: OR
|
||||||
|
* 3: AND
|
||||||
|
*
|
||||||
|
* Parse String:
|
||||||
|
* 0: SPDDDDDD
|
||||||
|
* 1: SPDSPDSP
|
||||||
|
* 2: SDPSDPSD
|
||||||
|
* 3: DDDDDDDD
|
||||||
|
* 4: DDDDDDDD
|
||||||
|
* 5: S+SP-DSS
|
||||||
|
* 6: S+SP-PDS
|
||||||
|
* 7: S+SD-PDS
|
||||||
|
*
|
||||||
|
* The lower word for 0x00E20746 is 0x0746 (00000111 01000110)
|
||||||
|
*
|
||||||
|
* 00 Op5 (NOT, n)
|
||||||
|
* 00 Op4 (NOT, n)
|
||||||
|
* 01 Op3 (XOR, x)
|
||||||
|
* 11 Op2 (AND, a)
|
||||||
|
* 01 Op1 (XOR, x)
|
||||||
|
* 0 Not (unused)
|
||||||
|
* 001 String (SPDSPDSP)
|
||||||
|
* 10 Offset (2)
|
||||||
|
*
|
||||||
|
* We shift SPDSPDSP to the left by 2: DSPDSPSP
|
||||||
|
*
|
||||||
|
* We have 5 operators: 3 binary operators and the last two are unary operators,
|
||||||
|
* so only four operands are needed. The parse string is truncated to reflect
|
||||||
|
* the number of operands we need: DSPD
|
||||||
|
*
|
||||||
|
* The operator string (from Op1 to Op5) is xaxnn, which can be simplified to xax
|
||||||
|
*
|
||||||
|
* The complete string representing the operation is DSPDxax
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
const BYTE rop_P = 0xF0; /* 11110000 */
|
||||||
|
const BYTE rop_S = 0xCC; /* 11001100 */
|
||||||
|
const BYTE rop_D = 0xAA; /* 10101010 */
|
||||||
|
|
||||||
|
char* gdi_convert_postfix_to_infix(char* postfix)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int length;
|
||||||
|
BOOL unary;
|
||||||
|
wStack* stack;
|
||||||
|
int al, bl, cl, dl;
|
||||||
|
char *a, *b, *c, *d;
|
||||||
|
|
||||||
|
stack = Stack_New(FALSE);
|
||||||
|
|
||||||
|
length = strlen(postfix);
|
||||||
|
|
||||||
|
for (i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
if ((postfix[i] == 'P') || (postfix[i] == 'D') || (postfix[i] == 'S'))
|
||||||
|
{
|
||||||
|
/* token is an operand, push on the stack */
|
||||||
|
|
||||||
|
a = malloc(2);
|
||||||
|
a[0] = postfix[i];
|
||||||
|
a[1] = '\0';
|
||||||
|
|
||||||
|
//printf("Operand: %s\n", a);
|
||||||
|
|
||||||
|
Stack_Push(stack, a);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* token is an operator */
|
||||||
|
|
||||||
|
unary = FALSE;
|
||||||
|
|
||||||
|
c = malloc(2);
|
||||||
|
c[0] = postfix[i];
|
||||||
|
c[1] = '\0';
|
||||||
|
|
||||||
|
if (c[0] == 'a')
|
||||||
|
{
|
||||||
|
c[0] = '&';
|
||||||
|
}
|
||||||
|
else if (c[0] == 'o')
|
||||||
|
{
|
||||||
|
c[0] = '|';
|
||||||
|
}
|
||||||
|
else if (c[0] == 'n')
|
||||||
|
{
|
||||||
|
c[0] = '~';
|
||||||
|
unary = TRUE;
|
||||||
|
}
|
||||||
|
else if (c[0] == 'x')
|
||||||
|
{
|
||||||
|
c[0] = '^';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("invalid operator: %s\n", c[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//printf("Operator: %s\n", c);
|
||||||
|
|
||||||
|
a = (char*) Stack_Pop(stack);
|
||||||
|
|
||||||
|
if (unary)
|
||||||
|
b = NULL;
|
||||||
|
else
|
||||||
|
b = (char*) Stack_Pop(stack);
|
||||||
|
|
||||||
|
al = strlen(a);
|
||||||
|
|
||||||
|
if (b)
|
||||||
|
bl = strlen(b);
|
||||||
|
|
||||||
|
cl = 1;
|
||||||
|
|
||||||
|
dl = al + bl + cl + 3;
|
||||||
|
|
||||||
|
d = malloc(cl + 1);
|
||||||
|
sprintf_s(d, dl, "(%s%s%s)", b ? b : "", c, a);
|
||||||
|
|
||||||
|
Stack_Push(stack, d);
|
||||||
|
|
||||||
|
free(a);
|
||||||
|
free(b);
|
||||||
|
free(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
d = (char*) Stack_Pop(stack);
|
||||||
|
Stack_Free(stack);
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char* test_ROP3[] =
|
||||||
|
{
|
||||||
|
"DSPDxax",
|
||||||
|
"PSDPxax",
|
||||||
|
"SPna",
|
||||||
|
"DSna",
|
||||||
|
"DPa",
|
||||||
|
"PDxn",
|
||||||
|
"DSxn",
|
||||||
|
"PSDnox",
|
||||||
|
"PDSona",
|
||||||
|
"DSPDxox",
|
||||||
|
"DPSDonox",
|
||||||
|
"SPDSxax",
|
||||||
|
"DPon",
|
||||||
|
"DPna",
|
||||||
|
"Pn",
|
||||||
|
"PDna",
|
||||||
|
"DPan",
|
||||||
|
"DSan",
|
||||||
|
"DSxn",
|
||||||
|
"DPa",
|
||||||
|
"D",
|
||||||
|
"DPno",
|
||||||
|
"SDno",
|
||||||
|
"PDno",
|
||||||
|
"DPo"
|
||||||
|
};
|
||||||
|
|
||||||
|
int TestGdiRop3(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
char* infix;
|
||||||
|
char* postfix;
|
||||||
|
|
||||||
|
for (index = 0; index < sizeof(test_ROP3) / sizeof(test_ROP3[0]); index++)
|
||||||
|
{
|
||||||
|
postfix = test_ROP3[index];
|
||||||
|
infix = gdi_convert_postfix_to_infix(postfix);
|
||||||
|
printf("%s\t\t%s\n", postfix, infix);
|
||||||
|
free(infix);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -714,13 +714,12 @@ PRIM_STATIC pstatus_t neon_yCbCrToRGB_16s16s_P3P3(
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
void primitives_init_colors(
|
void primitives_init_colors(const primitives_hints_t* hints, primitives_t* prims)
|
||||||
const primitives_hints_t *hints,
|
|
||||||
primitives_t *prims)
|
|
||||||
{
|
{
|
||||||
prims->RGBToRGB_16s8u_P3AC4R = general_RGBToRGB_16s8u_P3AC4R;
|
prims->RGBToRGB_16s8u_P3AC4R = general_RGBToRGB_16s8u_P3AC4R;
|
||||||
prims->yCbCrToRGB_16s16s_P3P3 = general_yCbCrToRGB_16s16s_P3P3;
|
prims->yCbCrToRGB_16s16s_P3P3 = general_yCbCrToRGB_16s16s_P3P3;
|
||||||
prims->RGBToYCbCr_16s16s_P3P3 = general_RGBToYCbCr_16s16s_P3P3;
|
prims->RGBToYCbCr_16s16s_P3P3 = general_RGBToYCbCr_16s16s_P3P3;
|
||||||
|
|
||||||
#if defined(WITH_SSE2)
|
#if defined(WITH_SSE2)
|
||||||
if (hints->x86_flags & PRIM_X86_SSE2_AVAILABLE)
|
if (hints->x86_flags & PRIM_X86_SSE2_AVAILABLE)
|
||||||
{
|
{
|
||||||
@ -737,8 +736,7 @@ void primitives_init_colors(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
void primitives_deinit_colors(
|
void primitives_deinit_colors(primitives_t* prims)
|
||||||
primitives_t *prims)
|
|
||||||
{
|
{
|
||||||
/* Nothing to do. */
|
/* Nothing to do. */
|
||||||
}
|
}
|
||||||
|
@ -81,6 +81,10 @@ WINPR_API void Queue_Free(wQueue* queue);
|
|||||||
|
|
||||||
struct _wStack
|
struct _wStack
|
||||||
{
|
{
|
||||||
|
int size;
|
||||||
|
int capacity;
|
||||||
|
void** array;
|
||||||
|
HANDLE mutex;
|
||||||
BOOL synchronized;
|
BOOL synchronized;
|
||||||
wObject object;
|
wObject object;
|
||||||
};
|
};
|
||||||
|
@ -65,10 +65,7 @@ BOOL Stack_IsSynchronized(wStack* stack)
|
|||||||
|
|
||||||
void Stack_Clear(wStack* stack)
|
void Stack_Clear(wStack* stack)
|
||||||
{
|
{
|
||||||
if (stack->synchronized)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -77,11 +74,6 @@ void Stack_Clear(wStack* stack)
|
|||||||
|
|
||||||
BOOL Stack_Contains(wStack* stack, void* obj)
|
BOOL Stack_Contains(wStack* stack, void* obj)
|
||||||
{
|
{
|
||||||
if (stack->synchronized)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,9 +84,18 @@ BOOL Stack_Contains(wStack* stack, void* obj)
|
|||||||
void Stack_Push(wStack* stack, void* obj)
|
void Stack_Push(wStack* stack, void* obj)
|
||||||
{
|
{
|
||||||
if (stack->synchronized)
|
if (stack->synchronized)
|
||||||
{
|
WaitForSingleObject(stack->mutex, INFINITE);
|
||||||
|
|
||||||
|
if ((stack->size + 1) >= stack->capacity)
|
||||||
|
{
|
||||||
|
stack->capacity *= 2;
|
||||||
|
stack->array = (void**) realloc(stack->array, sizeof(void*) * stack->capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stack->array[(stack->size)++] = obj;
|
||||||
|
|
||||||
|
if (stack->synchronized)
|
||||||
|
ReleaseMutex(stack->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -103,12 +104,18 @@ void Stack_Push(wStack* stack, void* obj)
|
|||||||
|
|
||||||
void* Stack_Pop(wStack* stack)
|
void* Stack_Pop(wStack* stack)
|
||||||
{
|
{
|
||||||
|
void* obj = NULL;
|
||||||
|
|
||||||
if (stack->synchronized)
|
if (stack->synchronized)
|
||||||
{
|
WaitForSingleObject(stack->mutex, INFINITE);
|
||||||
|
|
||||||
}
|
if (stack->size > 0)
|
||||||
|
obj = stack->array[--(stack->size)];
|
||||||
|
|
||||||
return NULL;
|
if (stack->synchronized)
|
||||||
|
ReleaseMutex(stack->mutex);
|
||||||
|
|
||||||
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -117,19 +124,25 @@ void* Stack_Pop(wStack* stack)
|
|||||||
|
|
||||||
void* Stack_Peek(wStack* stack)
|
void* Stack_Peek(wStack* stack)
|
||||||
{
|
{
|
||||||
|
void* obj = NULL;
|
||||||
|
|
||||||
if (stack->synchronized)
|
if (stack->synchronized)
|
||||||
{
|
WaitForSingleObject(stack->mutex, INFINITE);
|
||||||
|
|
||||||
}
|
if (stack->size > 0)
|
||||||
|
obj = stack->array[stack->size];
|
||||||
|
|
||||||
return NULL;
|
if (stack->synchronized)
|
||||||
|
ReleaseMutex(stack->mutex);
|
||||||
|
|
||||||
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construction, Destruction
|
* Construction, Destruction
|
||||||
*/
|
*/
|
||||||
|
|
||||||
wStack* Stack_New(BOOL bSynchronized)
|
wStack* Stack_New(BOOL synchronized)
|
||||||
{
|
{
|
||||||
wStack* stack = NULL;
|
wStack* stack = NULL;
|
||||||
|
|
||||||
@ -137,7 +150,14 @@ wStack* Stack_New(BOOL bSynchronized)
|
|||||||
|
|
||||||
if (stack)
|
if (stack)
|
||||||
{
|
{
|
||||||
stack->synchronized = bSynchronized;
|
stack->synchronized = synchronized;
|
||||||
|
|
||||||
|
if (stack->synchronized)
|
||||||
|
stack->mutex = CreateMutex(NULL, FALSE, NULL);
|
||||||
|
|
||||||
|
stack->size = 0;
|
||||||
|
stack->capacity = 32;
|
||||||
|
stack->array = (void**) malloc(sizeof(void*) * stack->capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
return stack;
|
return stack;
|
||||||
@ -145,5 +165,13 @@ wStack* Stack_New(BOOL bSynchronized)
|
|||||||
|
|
||||||
void Stack_Free(wStack* stack)
|
void Stack_Free(wStack* stack)
|
||||||
{
|
{
|
||||||
|
if (stack)
|
||||||
|
{
|
||||||
|
if (stack->synchronized)
|
||||||
|
CloseHandle(stack->mutex);
|
||||||
|
|
||||||
|
free(stack->array);
|
||||||
|
|
||||||
free(stack);
|
free(stack);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user