mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-15 00:44:19 +09:00
libfreerdp-core: improve order parsing
This commit is contained in:
@@ -77,114 +77,141 @@ uint8 ALTSEC_DRAWING_ORDER_STRINGS[][32] =
|
||||
"Frame Marker"
|
||||
};
|
||||
|
||||
uint8 PRIMARY_DRAWING_ORDER_FIELD_BYTES[] =
|
||||
{
|
||||
DSTBLT_ORDER_FIELD_BYTES,
|
||||
PATBLT_ORDER_FIELD_BYTES,
|
||||
SCRBLT_ORDER_FIELD_BYTES,
|
||||
0, 0, 0, 0,
|
||||
DRAW_NINE_GRID_ORDER_FIELD_BYTES,
|
||||
MULTI_DRAW_NINE_GRID_ORDER_FIELD_BYTES,
|
||||
LINE_TO_ORDER_FIELD_BYTES,
|
||||
OPAQUE_RECT_ORDER_FIELD_BYTES,
|
||||
SAVE_BITMAP_ORDER_FIELD_BYTES,
|
||||
MEMBLT_ORDER_FIELD_BYTES,
|
||||
MEM3BLT_ORDER_FIELD_BYTES,
|
||||
MULTI_DSTBLT_ORDER_FIELD_BYTES,
|
||||
MULTI_PATBLT_ORDER_FIELD_BYTES,
|
||||
MULTI_SCRBLT_ORDER_FIELD_BYTES,
|
||||
MULTI_OPAQUE_RECT_ORDER_FIELD_BYTES,
|
||||
FAST_INDEX_ORDER_FIELD_BYTES,
|
||||
POLYGON_SC_ORDER_FIELD_BYTES,
|
||||
POLYGON_CB_ORDER_FIELD_BYTES,
|
||||
POLYLINE_ORDER_FIELD_BYTES,
|
||||
FAST_GLYPH_ORDER_FIELD_BYTES,
|
||||
ELLIPSE_SC_ORDER_FIELD_BYTES,
|
||||
ELLIPSE_CB_ORDER_FIELD_BYTES,
|
||||
GLYPH_INDEX_ORDER_FIELD_BYTES
|
||||
};
|
||||
|
||||
/* Primary Drawing Orders */
|
||||
|
||||
void rdp_recv_dstblt_order(rdpRdp* rdp, STREAM* s)
|
||||
void rdp_recv_dstblt_order(rdpRdp* rdp, STREAM* s, ORDER_INFO* orderInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void rdp_recv_patblt_order(rdpRdp* rdp, STREAM* s)
|
||||
void rdp_recv_patblt_order(rdpRdp* rdp, STREAM* s, ORDER_INFO* orderInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void rdp_recv_scrblt_order(rdpRdp* rdp, STREAM* s)
|
||||
void rdp_recv_scrblt_order(rdpRdp* rdp, STREAM* s, ORDER_INFO* orderInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void rdp_recv_draw_nine_grid_order(rdpRdp* rdp, STREAM* s)
|
||||
void rdp_recv_draw_nine_grid_order(rdpRdp* rdp, STREAM* s, ORDER_INFO* orderInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void rdp_recv_multi_draw_nine_grid_order(rdpRdp* rdp, STREAM* s)
|
||||
void rdp_recv_multi_draw_nine_grid_order(rdpRdp* rdp, STREAM* s, ORDER_INFO* orderInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void rdp_recv_line_to_order(rdpRdp* rdp, STREAM* s)
|
||||
void rdp_recv_line_to_order(rdpRdp* rdp, STREAM* s, ORDER_INFO* orderInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void rdp_recv_opaque_rect_order(rdpRdp* rdp, STREAM* s)
|
||||
void rdp_recv_opaque_rect_order(rdpRdp* rdp, STREAM* s, ORDER_INFO* orderInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void rdp_recv_save_bitmap_order(rdpRdp* rdp, STREAM* s)
|
||||
void rdp_recv_save_bitmap_order(rdpRdp* rdp, STREAM* s, ORDER_INFO* orderInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void rdp_recv_memblt_order(rdpRdp* rdp, STREAM* s)
|
||||
void rdp_recv_memblt_order(rdpRdp* rdp, STREAM* s, ORDER_INFO* orderInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void rdp_recv_mem3blt_order(rdpRdp* rdp, STREAM* s)
|
||||
void rdp_recv_mem3blt_order(rdpRdp* rdp, STREAM* s, ORDER_INFO* orderInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void rdp_recv_multi_dstblt_order(rdpRdp* rdp, STREAM* s)
|
||||
void rdp_recv_multi_dstblt_order(rdpRdp* rdp, STREAM* s, ORDER_INFO* orderInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void rdp_recv_multi_patblt_order(rdpRdp* rdp, STREAM* s)
|
||||
void rdp_recv_multi_patblt_order(rdpRdp* rdp, STREAM* s, ORDER_INFO* orderInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void rdp_recv_multi_scrblt_order(rdpRdp* rdp, STREAM* s)
|
||||
void rdp_recv_multi_scrblt_order(rdpRdp* rdp, STREAM* s, ORDER_INFO* orderInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void rdp_recv_multi_opaque_rect_order(rdpRdp* rdp, STREAM* s)
|
||||
void rdp_recv_multi_opaque_rect_order(rdpRdp* rdp, STREAM* s, ORDER_INFO* orderInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void rdp_recv_fast_index_order(rdpRdp* rdp, STREAM* s)
|
||||
void rdp_recv_fast_index_order(rdpRdp* rdp, STREAM* s, ORDER_INFO* orderInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void rdp_recv_polygon_sc_order(rdpRdp* rdp, STREAM* s)
|
||||
void rdp_recv_polygon_sc_order(rdpRdp* rdp, STREAM* s, ORDER_INFO* orderInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void rdp_recv_polygon_cb_order(rdpRdp* rdp, STREAM* s)
|
||||
void rdp_recv_polygon_cb_order(rdpRdp* rdp, STREAM* s, ORDER_INFO* orderInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void rdp_recv_polyline_order(rdpRdp* rdp, STREAM* s)
|
||||
void rdp_recv_polyline_order(rdpRdp* rdp, STREAM* s, ORDER_INFO* orderInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void rdp_recv_fast_glyph_order(rdpRdp* rdp, STREAM* s)
|
||||
void rdp_recv_fast_glyph_order(rdpRdp* rdp, STREAM* s, ORDER_INFO* orderInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void rdp_recv_ellipse_sc_order(rdpRdp* rdp, STREAM* s)
|
||||
void rdp_recv_ellipse_sc_order(rdpRdp* rdp, STREAM* s, ORDER_INFO* orderInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void rdp_recv_ellipse_cb_order(rdpRdp* rdp, STREAM* s)
|
||||
void rdp_recv_ellipse_cb_order(rdpRdp* rdp, STREAM* s, ORDER_INFO* orderInfo)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void rdp_recv_glyph_index_order(rdpRdp* rdp, STREAM* s)
|
||||
void rdp_recv_glyph_index_order(rdpRdp* rdp, STREAM* s, ORDER_INFO* orderInfo)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -303,102 +330,167 @@ void rdp_recv_frame_marker_order(rdpRdp* rdp, STREAM* s)
|
||||
|
||||
}
|
||||
|
||||
void rdp_read_field_flags(STREAM* s, uint32* fieldFlags, uint8 flags, uint8 fieldBytes)
|
||||
{
|
||||
int i;
|
||||
uint8 byte;
|
||||
|
||||
if (flags & ORDER_ZERO_FIELD_BYTE_BIT0)
|
||||
fieldBytes--;
|
||||
|
||||
if (flags & ORDER_ZERO_FIELD_BYTE_BIT1)
|
||||
{
|
||||
if (fieldBytes < 2)
|
||||
fieldBytes = 0;
|
||||
else
|
||||
fieldBytes -= 2;
|
||||
}
|
||||
|
||||
*fieldFlags = 0;
|
||||
for (i = 0; i < fieldBytes; i++)
|
||||
{
|
||||
stream_read_uint8(s, byte);
|
||||
*fieldFlags |= byte << (i * 8);
|
||||
}
|
||||
}
|
||||
|
||||
void rdp_read_bounds(STREAM* s, ORDER_INFO* orderInfo)
|
||||
{
|
||||
uint8 flags;
|
||||
|
||||
stream_read_uint8(s, flags); /* field flags */
|
||||
|
||||
if (flags & BOUND_DELTA_LEFT)
|
||||
stream_read_uint8(s, orderInfo->deltaBoundLeft);
|
||||
else if (flags & BOUND_LEFT)
|
||||
stream_read_uint16(s, orderInfo->boundLeft);
|
||||
|
||||
if (flags & BOUND_DELTA_TOP)
|
||||
stream_read_uint8(s, orderInfo->deltaBoundTop);
|
||||
else if (flags & BOUND_TOP)
|
||||
stream_read_uint16(s, orderInfo->boundTop);
|
||||
|
||||
if (flags & BOUND_DELTA_RIGHT)
|
||||
stream_read_uint8(s, orderInfo->deltaBoundRight);
|
||||
else if (flags & BOUND_RIGHT)
|
||||
stream_read_uint16(s, orderInfo->boundRight);
|
||||
|
||||
if (flags & BOUND_DELTA_BOTTOM)
|
||||
stream_read_uint8(s, orderInfo->deltaBoundBottom);
|
||||
else if (flags & BOUND_BOTTOM)
|
||||
stream_read_uint16(s, orderInfo->boundBottom);
|
||||
}
|
||||
|
||||
void rdp_recv_primary_order(rdpRdp* rdp, STREAM* s, uint8 flags)
|
||||
{
|
||||
uint8 orderType;
|
||||
ORDER_INFO* orderInfo = &(rdp->order_info);
|
||||
|
||||
stream_read_uint8(s, orderType); /* orderType (1 byte) */
|
||||
if (flags & ORDER_TYPE_CHANGE)
|
||||
stream_read_uint8(s, orderInfo->orderType); /* orderType (1 byte) */
|
||||
|
||||
printf("%s Primary Drawing Order\n", PRIMARY_DRAWING_ORDER_STRINGS[orderType]);
|
||||
rdp_read_field_flags(s, &(orderInfo->fieldFlags), flags,
|
||||
PRIMARY_DRAWING_ORDER_FIELD_BYTES[orderInfo->orderType]);
|
||||
|
||||
switch (orderType)
|
||||
if (flags & ORDER_BOUNDS)
|
||||
{
|
||||
if (!(flags & ORDER_ZERO_BOUNDS_DELTAS))
|
||||
{
|
||||
rdp_read_bounds(s, orderInfo);
|
||||
}
|
||||
}
|
||||
|
||||
orderInfo->deltaCoordinates = (flags & ORDER_DELTA_COORDINATES) ? True : False;
|
||||
|
||||
printf("%s Primary Drawing Order\n", PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType]);
|
||||
|
||||
switch (orderInfo->orderType)
|
||||
{
|
||||
case ORDER_TYPE_DSTBLT:
|
||||
rdp_recv_dstblt_order(rdp, s);
|
||||
rdp_recv_dstblt_order(rdp, s, orderInfo);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_PATBLT:
|
||||
rdp_recv_patblt_order(rdp, s);
|
||||
rdp_recv_patblt_order(rdp, s, orderInfo);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_SCRBLT:
|
||||
rdp_recv_scrblt_order(rdp, s);
|
||||
rdp_recv_scrblt_order(rdp, s, orderInfo);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_DRAW_NINE_GRID:
|
||||
rdp_recv_draw_nine_grid_order(rdp, s);
|
||||
rdp_recv_draw_nine_grid_order(rdp, s, orderInfo);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_MULTI_DRAW_NINE_GRID:
|
||||
rdp_recv_multi_draw_nine_grid_order(rdp, s);
|
||||
rdp_recv_multi_draw_nine_grid_order(rdp, s, orderInfo);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_LINE_TO:
|
||||
rdp_recv_line_to_order(rdp, s);
|
||||
rdp_recv_line_to_order(rdp, s, orderInfo);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_OPAQUE_RECT:
|
||||
rdp_recv_opaque_rect_order(rdp, s);
|
||||
rdp_recv_opaque_rect_order(rdp, s, orderInfo);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_SAVE_BITMAP:
|
||||
rdp_recv_save_bitmap_order(rdp, s);
|
||||
rdp_recv_save_bitmap_order(rdp, s, orderInfo);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_MEMBLT:
|
||||
rdp_recv_memblt_order(rdp, s);
|
||||
rdp_recv_memblt_order(rdp, s, orderInfo);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_MEM3BLT:
|
||||
rdp_recv_mem3blt_order(rdp, s);
|
||||
rdp_recv_mem3blt_order(rdp, s, orderInfo);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_MULTI_DSTBLT:
|
||||
rdp_recv_multi_dstblt_order(rdp, s);
|
||||
rdp_recv_multi_dstblt_order(rdp, s, orderInfo);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_MULTI_PATBLT:
|
||||
rdp_recv_multi_patblt_order(rdp, s);
|
||||
rdp_recv_multi_patblt_order(rdp, s, orderInfo);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_MULTI_SCRBLT:
|
||||
rdp_recv_multi_scrblt_order(rdp, s);
|
||||
rdp_recv_multi_scrblt_order(rdp, s, orderInfo);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_MULTI_OPAQUE_RECT:
|
||||
rdp_recv_multi_opaque_rect_order(rdp, s);
|
||||
rdp_recv_multi_opaque_rect_order(rdp, s, orderInfo);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_FAST_INDEX:
|
||||
rdp_recv_fast_index_order(rdp, s);
|
||||
rdp_recv_fast_index_order(rdp, s, orderInfo);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_POLYGON_SC:
|
||||
rdp_recv_polygon_sc_order(rdp, s);
|
||||
rdp_recv_polygon_sc_order(rdp, s, orderInfo);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_POLYGON_CB:
|
||||
rdp_recv_polygon_cb_order(rdp, s);
|
||||
rdp_recv_polygon_cb_order(rdp, s, orderInfo);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_POLYLINE:
|
||||
rdp_recv_polyline_order(rdp, s);
|
||||
rdp_recv_polyline_order(rdp, s, orderInfo);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_FAST_GLYPH:
|
||||
rdp_recv_fast_glyph_order(rdp, s);
|
||||
rdp_recv_fast_glyph_order(rdp, s, orderInfo);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_ELLIPSE_SC:
|
||||
rdp_recv_ellipse_sc_order(rdp, s);
|
||||
rdp_recv_ellipse_sc_order(rdp, s, orderInfo);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_ELLIPSE_CB:
|
||||
rdp_recv_ellipse_cb_order(rdp, s);
|
||||
rdp_recv_ellipse_cb_order(rdp, s, orderInfo);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_GLYPH_INDEX:
|
||||
rdp_recv_glyph_index_order(rdp, s);
|
||||
rdp_recv_glyph_index_order(rdp, s, orderInfo);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -408,10 +500,19 @@ void rdp_recv_primary_order(rdpRdp* rdp, STREAM* s, uint8 flags)
|
||||
|
||||
void rdp_recv_secondary_order(rdpRdp* rdp, STREAM* s, uint8 flags)
|
||||
{
|
||||
uint8* next;
|
||||
uint8 orderType;
|
||||
uint16 extraFlags;
|
||||
uint16 orderLength;
|
||||
|
||||
stream_get_mark(s, next);
|
||||
stream_read_uint16(s, orderLength); /* orderLength (2 bytes) */
|
||||
stream_read_uint16(s, extraFlags); /* extraFlags (2 bytes) */
|
||||
stream_read_uint8(s, orderType); /* orderType (1 byte) */
|
||||
|
||||
orderLength += 13; /* adjust length (13 bytes less than actual length) */
|
||||
next += orderLength;
|
||||
|
||||
printf("%s Secondary Drawing Order\n", SECONDARY_DRAWING_ORDER_STRINGS[orderType]);
|
||||
|
||||
switch (orderType)
|
||||
@@ -451,13 +552,15 @@ void rdp_recv_secondary_order(rdpRdp* rdp, STREAM* s, uint8 flags)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
stream_set_mark(s, next);
|
||||
}
|
||||
|
||||
void rdp_recv_altsec_order(rdpRdp* rdp, STREAM* s, uint8 flags)
|
||||
{
|
||||
uint8 orderType;
|
||||
|
||||
stream_read_uint8(s, orderType); /* orderType (1 byte) */
|
||||
orderType = flags >>= 2; /* orderType is in higher 6 bits of flags field */
|
||||
|
||||
printf("%s Alternate Secondary Drawing Order\n", ALTSEC_DRAWING_ORDER_STRINGS[orderType]);
|
||||
|
||||
|
||||
@@ -20,10 +20,26 @@
|
||||
#ifndef __ORDERS_H
|
||||
#define __ORDERS_H
|
||||
|
||||
#include "rdp.h"
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8 orderType;
|
||||
uint32 fieldFlags;
|
||||
uint16 boundLeft;
|
||||
uint16 boundTop;
|
||||
uint16 boundRight;
|
||||
uint16 boundBottom;
|
||||
sint8 deltaBoundLeft;
|
||||
sint8 deltaBoundTop;
|
||||
sint8 deltaBoundRight;
|
||||
sint8 deltaBoundBottom;
|
||||
boolean deltaCoordinates;
|
||||
} ORDER_INFO;
|
||||
|
||||
#include "rdp.h"
|
||||
|
||||
/* Order Control Flags */
|
||||
#define ORDER_STANDARD 0x01
|
||||
#define ORDER_SECONDARY 0x02
|
||||
@@ -34,6 +50,16 @@
|
||||
#define ORDER_ZERO_FIELD_BYTE_BIT0 0x40
|
||||
#define ORDER_ZERO_FIELD_BYTE_BIT1 0x80
|
||||
|
||||
/* Bound Field Flags */
|
||||
#define BOUND_LEFT 0x01
|
||||
#define BOUND_TOP 0x02
|
||||
#define BOUND_RIGHT 0x04
|
||||
#define BOUND_BOTTOM 0x08
|
||||
#define BOUND_DELTA_LEFT 0x10
|
||||
#define BOUND_DELTA_TOP 0x20
|
||||
#define BOUND_DELTA_RIGHT 0x40
|
||||
#define BOUND_DELTA_BOTTOM 0x80
|
||||
|
||||
/* Order Classes */
|
||||
#define ORDER_PRIMARY_CLASS 0x01
|
||||
#define ORDER_SECONDARY_CLASS 0x03
|
||||
@@ -88,6 +114,30 @@
|
||||
#define ELLIPSE_CB_ORDER_FIELDS 13
|
||||
#define GLYPH_INDEX_ORDER_FIELDS 22
|
||||
|
||||
/* Primary Drawing Orders Field Bytes */
|
||||
#define DSTBLT_ORDER_FIELD_BYTES 1
|
||||
#define PATBLT_ORDER_FIELD_BYTES 2
|
||||
#define SCRBLT_ORDER_FIELD_BYTES 1
|
||||
#define DRAW_NINE_GRID_ORDER_FIELD_BYTES 1
|
||||
#define MULTI_DRAW_NINE_GRID_ORDER_FIELD_BYTES 1
|
||||
#define LINE_TO_ORDER_FIELD_BYTES 2
|
||||
#define OPAQUE_RECT_ORDER_FIELD_BYTES 1
|
||||
#define SAVE_BITMAP_ORDER_FIELD_BYTES 1
|
||||
#define MEMBLT_ORDER_FIELD_BYTES 2
|
||||
#define MEM3BLT_ORDER_FIELD_BYTES 3
|
||||
#define MULTI_DSTBLT_ORDER_FIELD_BYTES 1
|
||||
#define MULTI_PATBLT_ORDER_FIELD_BYTES 2
|
||||
#define MULTI_SCRBLT_ORDER_FIELD_BYTES 2
|
||||
#define MULTI_OPAQUE_RECT_ORDER_FIELD_BYTES 2
|
||||
#define FAST_INDEX_ORDER_FIELD_BYTES 2
|
||||
#define POLYGON_SC_ORDER_FIELD_BYTES 1
|
||||
#define POLYGON_CB_ORDER_FIELD_BYTES 2
|
||||
#define POLYLINE_ORDER_FIELD_BYTES 1
|
||||
#define FAST_GLYPH_ORDER_FIELD_BYTES 2
|
||||
#define ELLIPSE_SC_ORDER_FIELD_BYTES 1
|
||||
#define ELLIPSE_CB_ORDER_FIELD_BYTES 2
|
||||
#define GLYPH_INDEX_ORDER_FIELD_BYTES 3
|
||||
|
||||
/* Secondary Drawing Orders */
|
||||
#define ORDER_TYPE_BITMAP_UNCOMPRESSED 0x00
|
||||
#define ORDER_TYPE_CACHE_COLOR_TABLE 0x01
|
||||
|
||||
@@ -27,6 +27,7 @@ typedef struct rdp_rdp rdpRdp;
|
||||
#include "tpdu.h"
|
||||
#include "nego.h"
|
||||
#include "update.h"
|
||||
#include "orders.h"
|
||||
#include "license.h"
|
||||
#include "security.h"
|
||||
#include "registry.h"
|
||||
@@ -204,6 +205,7 @@ struct rdp_rdp
|
||||
{
|
||||
boolean licensed;
|
||||
boolean activated;
|
||||
ORDER_INFO order_info;
|
||||
struct rdp_mcs* mcs;
|
||||
struct rdp_nego* nego;
|
||||
struct rdp_license* license;
|
||||
|
||||
Reference in New Issue
Block a user