mirror of https://github.com/FreeRDP/FreeRDP
Merge pull request #2124 from awakecoding/shadow
Shadow Improvements, Server-Side Fixes
This commit is contained in:
commit
ff07469386
|
@ -868,6 +868,7 @@ int freerdp_parse_hostname(char* hostname, char** host, int* port)
|
|||
int freerdp_set_connection_type(rdpSettings* settings, int type)
|
||||
{
|
||||
settings->ConnectionType = type;
|
||||
|
||||
if (type == CONNECTION_TYPE_MODEM)
|
||||
{
|
||||
settings->DisableWallpaper = TRUE;
|
||||
|
@ -1595,8 +1596,12 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
|
|||
type = CONNECTION_TYPE_WAN;
|
||||
else if (_stricmp(arg->Value, "lan") == 0)
|
||||
type = CONNECTION_TYPE_LAN;
|
||||
else if (_stricmp(arg->Value, "auto") == 0)
|
||||
else if ((_stricmp(arg->Value, "autodetect") == 0) ||
|
||||
(_stricmp(arg->Value, "auto") == 0) ||
|
||||
(_stricmp(arg->Value, "detect") == 0))
|
||||
{
|
||||
type = CONNECTION_TYPE_AUTODETECT;
|
||||
}
|
||||
}
|
||||
|
||||
freerdp_set_connection_type(settings, type);
|
||||
|
|
|
@ -34,11 +34,16 @@ struct _BITMAP_INTERLEAVED_CONTEXT
|
|||
|
||||
UINT32 TempSize;
|
||||
BYTE* TempBuffer;
|
||||
|
||||
wStream* bts;
|
||||
};
|
||||
|
||||
FREERDP_API int interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* interleaved, BYTE* pSrcData, UINT32 SrcSize, int bpp,
|
||||
BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, BYTE* palette);
|
||||
|
||||
FREERDP_API int interleaved_compress(BITMAP_INTERLEAVED_CONTEXT* interleaved, BYTE* pDstData, UINT32* pDstSize,
|
||||
int nWidth, int nHeight, BYTE* pSrcData, DWORD SrcFormat, int nSrcStep, int nXSrc, int nYSrc, BYTE* palette, int bpp);
|
||||
|
||||
FREERDP_API int bitmap_interleaved_context_reset(BITMAP_INTERLEAVED_CONTEXT* interleaved);
|
||||
|
||||
FREERDP_API BITMAP_INTERLEAVED_CONTEXT* bitmap_interleaved_context_new(BOOL Compressor);
|
||||
|
|
|
@ -31,17 +31,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* NSCODEC_BITMAP_STREAM */
|
||||
struct _NSC_STREAM
|
||||
{
|
||||
UINT32 PlaneByteCount[4];
|
||||
BYTE ColorLossLevel;
|
||||
BYTE ChromaSubSamplingLevel;
|
||||
UINT16 Reserved;
|
||||
BYTE* Planes;
|
||||
};
|
||||
typedef struct _NSC_STREAM NSC_STREAM;
|
||||
|
||||
struct _NSC_MESSAGE
|
||||
{
|
||||
int x;
|
||||
|
@ -54,7 +43,13 @@ struct _NSC_MESSAGE
|
|||
UINT32 MaxPlaneSize;
|
||||
BYTE* PlaneBuffers[5];
|
||||
UINT32 OrgByteCount[4];
|
||||
UINT32 PlaneByteCount[4];
|
||||
|
||||
UINT32 LumaPlaneByteCount;
|
||||
UINT32 OrangeChromaPlaneByteCount;
|
||||
UINT32 GreenChromaPlaneByteCount;
|
||||
UINT32 AlphaPlaneByteCount;
|
||||
UINT32 ColorLossLevel;
|
||||
UINT32 ChromaSubsamplingLevel;
|
||||
};
|
||||
typedef struct _NSC_MESSAGE NSC_MESSAGE;
|
||||
|
||||
|
@ -64,15 +59,20 @@ typedef struct _NSC_CONTEXT NSC_CONTEXT;
|
|||
|
||||
struct _NSC_CONTEXT
|
||||
{
|
||||
UINT32 OrgByteCount[4]; /* original byte length of luma, chroma orange, chroma green, alpha variable in order */
|
||||
NSC_STREAM nsc_stream;
|
||||
UINT32 OrgByteCount[4];
|
||||
UINT16 bpp;
|
||||
UINT16 width;
|
||||
UINT16 height;
|
||||
BYTE* BitmapData; /* final argb values in little endian order */
|
||||
UINT32 BitmapDataLength; /* the maximum length of the buffer that bmpdata points to */
|
||||
BYTE* BitmapData;
|
||||
UINT32 BitmapDataLength;
|
||||
RDP_PIXEL_FORMAT pixel_format;
|
||||
|
||||
BYTE* Planes;
|
||||
UINT32 PlaneByteCount[4];
|
||||
UINT32 ColorLossLevel;
|
||||
UINT32 ChromaSubsamplingLevel;
|
||||
BOOL DynamicColorFidelity;
|
||||
|
||||
/* color palette allocated by the application */
|
||||
const BYTE* palette;
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ FREERDP_API BYTE* freerdp_bitmap_planar_delta_encode_plane(BYTE* inPlane, int wi
|
|||
FREERDP_API int freerdp_bitmap_planar_delta_encode_planes(BYTE* inPlanes[4], int width, int height, BYTE* outPlanes[4]);
|
||||
|
||||
FREERDP_API BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* context, BYTE* data, UINT32 format,
|
||||
int width, int height, int scanline, BYTE* dstData, int* dstSize);
|
||||
int width, int height, int scanline, BYTE* dstData, int* pDstSize);
|
||||
|
||||
FREERDP_API int freerdp_bitmap_planar_context_reset(BITMAP_PLANAR_CONTEXT* context);
|
||||
|
||||
|
|
|
@ -43,6 +43,13 @@ struct _REGION16 {
|
|||
};
|
||||
typedef struct _REGION16 REGION16;
|
||||
|
||||
/** computes if two rectangles are equal
|
||||
* @param r1 first rectangle
|
||||
* @param r2 second rectangle
|
||||
* @return if the two rectangles are equal
|
||||
*/
|
||||
FREERDP_API BOOL rectangles_equal(const RECTANGLE_16 *r1, const RECTANGLE_16 *r2);
|
||||
|
||||
/** computes if two rectangles intersect
|
||||
* @param r1 first rectangle
|
||||
* @param r2 second rectangle
|
||||
|
|
|
@ -313,7 +313,6 @@ FREERDP_API UINT32 gdi_rop3_code(BYTE code);
|
|||
FREERDP_API UINT32 gdi_get_pixel_format(UINT32 bitsPerPixel, BOOL vFlip);
|
||||
FREERDP_API BYTE* gdi_get_bitmap_pointer(HGDI_DC hdcBmp, int x, int y);
|
||||
FREERDP_API BYTE* gdi_get_brush_pointer(HGDI_DC hdcBrush, int x, int y);
|
||||
FREERDP_API int gdi_is_mono_pixel_set(BYTE* data, int x, int y, int width);
|
||||
FREERDP_API void gdi_resize(rdpGdi* gdi, int width, int height);
|
||||
|
||||
FREERDP_API int gdi_init(freerdp* instance, UINT32 flags, BYTE* buffer);
|
||||
|
|
|
@ -47,16 +47,19 @@ typedef struct rdp_shadow_encoder rdpShadowEncoder;
|
|||
typedef struct rdp_shadow_capture rdpShadowCapture;
|
||||
typedef struct rdp_shadow_subsystem rdpShadowSubsystem;
|
||||
|
||||
typedef rdpShadowSubsystem* (*pfnShadowCreateSubsystem)(rdpShadowServer* server);
|
||||
typedef struct _RDP_SHADOW_ENTRY_POINTS RDP_SHADOW_ENTRY_POINTS;
|
||||
typedef int (*pfnShadowSubsystemEntry)(RDP_SHADOW_ENTRY_POINTS* pEntryPoints);
|
||||
|
||||
typedef rdpShadowSubsystem* (*pfnShadowSubsystemNew)(void);
|
||||
typedef void (*pfnShadowSubsystemFree)(rdpShadowSubsystem* subsystem);
|
||||
|
||||
typedef int (*pfnShadowSubsystemInit)(rdpShadowSubsystem* subsystem);
|
||||
typedef int (*pfnShadowSubsystemUninit)(rdpShadowSubsystem* subsystem);
|
||||
|
||||
typedef int (*pfnShadowSubsystemStart)(rdpShadowSubsystem* subsystem);
|
||||
typedef int (*pfnShadowSubsystemStop)(rdpShadowSubsystem* subsystem);
|
||||
typedef void (*pfnShadowSubsystemFree)(rdpShadowSubsystem* subsystem);
|
||||
|
||||
typedef int (*pfnShadowSurfaceCopy)(rdpShadowSubsystem* subsystem);
|
||||
typedef int (*pfnShadowSurfaceUpdate)(rdpShadowSubsystem* subsystem, REGION16* subRect);
|
||||
typedef int (*pfnShadowEnumMonitors)(MONITOR_DEF* monitors, int maxMonitors);
|
||||
|
||||
typedef int (*pfnShadowSynchronizeEvent)(rdpShadowSubsystem* subsystem, UINT32 flags);
|
||||
typedef int (*pfnShadowKeyboardEvent)(rdpShadowSubsystem* subsystem, UINT16 flags, UINT16 code);
|
||||
|
@ -79,6 +82,7 @@ struct rdp_shadow_client
|
|||
rdpShadowServer* server;
|
||||
rdpShadowSurface* lobby;
|
||||
rdpShadowEncoder* encoder;
|
||||
rdpShadowSubsystem* subsystem;
|
||||
|
||||
HANDLE vcm;
|
||||
EncomspServerContext* encomsp;
|
||||
|
@ -100,6 +104,7 @@ struct rdp_shadow_server
|
|||
BOOL mayView;
|
||||
BOOL mayInteract;
|
||||
BOOL shareSubRect;
|
||||
int selectedMonitor;
|
||||
RECTANGLE_16 subRect;
|
||||
char* ipcSocket;
|
||||
char* ConfigPath;
|
||||
|
@ -107,28 +112,36 @@ struct rdp_shadow_server
|
|||
char* PrivateKeyFile;
|
||||
CRITICAL_SECTION lock;
|
||||
freerdp_listener* listener;
|
||||
pfnShadowCreateSubsystem CreateSubsystem;
|
||||
};
|
||||
|
||||
struct _RDP_SHADOW_ENTRY_POINTS
|
||||
{
|
||||
pfnShadowSubsystemNew New;
|
||||
pfnShadowSubsystemFree Free;
|
||||
|
||||
pfnShadowSubsystemInit Init;
|
||||
pfnShadowSubsystemUninit Uninit;
|
||||
|
||||
pfnShadowSubsystemStart Start;
|
||||
pfnShadowSubsystemStop Stop;
|
||||
|
||||
pfnShadowEnumMonitors EnumMonitors;
|
||||
};
|
||||
|
||||
#define RDP_SHADOW_SUBSYSTEM_COMMON() \
|
||||
RDP_SHADOW_ENTRY_POINTS ep; \
|
||||
HANDLE event; \
|
||||
int monitorCount; \
|
||||
int numMonitors; \
|
||||
int captureFrameRate; \
|
||||
int selectedMonitor; \
|
||||
MONITOR_DEF monitors[16]; \
|
||||
MONITOR_DEF virtualScreen; \
|
||||
HANDLE updateEvent; \
|
||||
BOOL suppressOutput; \
|
||||
REGION16 invalidRegion; \
|
||||
wMessagePipe* MsgPipe; \
|
||||
SYNCHRONIZATION_BARRIER barrier; \
|
||||
\
|
||||
pfnShadowSubsystemInit Init; \
|
||||
pfnShadowSubsystemUninit Uninit; \
|
||||
pfnShadowSubsystemStart Start; \
|
||||
pfnShadowSubsystemStop Stop; \
|
||||
pfnShadowSubsystemFree Free; \
|
||||
\
|
||||
pfnShadowSurfaceCopy SurfaceCopy; \
|
||||
pfnShadowSurfaceUpdate SurfaceUpdate; \
|
||||
\
|
||||
pfnShadowSynchronizeEvent SynchronizeEvent; \
|
||||
pfnShadowKeyboardEvent KeyboardEvent; \
|
||||
pfnShadowUnicodeKeyboardEvent UnicodeKeyboardEvent; \
|
||||
|
@ -142,5 +155,27 @@ struct rdp_shadow_subsystem
|
|||
RDP_SHADOW_SUBSYSTEM_COMMON();
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
FREERDP_API int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** argv);
|
||||
FREERDP_API int shadow_server_command_line_status_print(rdpShadowServer* server, int argc, char** argv, int status);
|
||||
|
||||
FREERDP_API int shadow_server_start(rdpShadowServer* server);
|
||||
FREERDP_API int shadow_server_stop(rdpShadowServer* server);
|
||||
|
||||
FREERDP_API int shadow_server_init(rdpShadowServer* server);
|
||||
FREERDP_API int shadow_server_uninit(rdpShadowServer* server);
|
||||
|
||||
FREERDP_API int shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors, const char* name);
|
||||
|
||||
FREERDP_API rdpShadowServer* shadow_server_new();
|
||||
FREERDP_API void shadow_server_free(rdpShadowServer* server);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_SERVER_SHADOW_H */
|
||||
|
||||
|
|
|
@ -760,6 +760,9 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
|
|||
#define FreeRDP_NSCodec 3712
|
||||
#define FreeRDP_NSCodecId 3713
|
||||
#define FreeRDP_FrameAcknowledge 3714
|
||||
#define FreeRDP_NSCodecColorLossLevel 3715
|
||||
#define FreeRDP_NSCodecAllowSubsampling 3716
|
||||
#define FreeRDP_NSCodecAllowDynamicColorFidelity 3717
|
||||
#define FreeRDP_JpegCodec 3776
|
||||
#define FreeRDP_JpegCodecId 3777
|
||||
#define FreeRDP_JpegQuality 3778
|
||||
|
@ -1272,7 +1275,10 @@ struct rdp_settings
|
|||
ALIGN64 BOOL NSCodec; /* 3712 */
|
||||
ALIGN64 UINT32 NSCodecId; /* 3713 */
|
||||
ALIGN64 UINT32 FrameAcknowledge; /* 3714 */
|
||||
UINT64 padding3776[3776 - 3715]; /* 3715 */
|
||||
ALIGN64 UINT32 NSCodecColorLossLevel; /* 3715 */
|
||||
ALIGN64 BOOL NSCodecAllowSubsampling; /* 3716 */
|
||||
ALIGN64 BOOL NSCodecAllowDynamicColorFidelity; /* 3717 */
|
||||
UINT64 padding3776[3776 - 3718]; /* 3718 */
|
||||
|
||||
/* JPEG */
|
||||
ALIGN64 BOOL JpegCodec; /* 3776 */
|
||||
|
|
|
@ -147,8 +147,9 @@ typedef void (*pRefreshRect)(rdpContext* context, BYTE count, RECTANGLE_16* area
|
|||
typedef void (*pSuppressOutput)(rdpContext* context, BYTE allow, RECTANGLE_16* area);
|
||||
|
||||
typedef void (*pSurfaceCommand)(rdpContext* context, wStream* s);
|
||||
typedef void (*pSurfaceBits)(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_command);
|
||||
typedef void (*pSurfaceFrameMarker)(rdpContext* context, SURFACE_FRAME_MARKER* surface_frame_marker);
|
||||
typedef void (*pSurfaceBits)(rdpContext* context, SURFACE_BITS_COMMAND* surfaceBitsCommand);
|
||||
typedef void (*pSurfaceFrameMarker)(rdpContext* context, SURFACE_FRAME_MARKER* surfaceFrameMarker);
|
||||
typedef void (*pSurfaceFrameBits)(rdpContext* context, SURFACE_BITS_COMMAND* cmd, BOOL first, BOOL last, UINT32 frameId);
|
||||
typedef void (*pSurfaceFrameAcknowledge)(rdpContext* context, UINT32 frameId);
|
||||
|
||||
struct rdp_update
|
||||
|
@ -180,8 +181,9 @@ struct rdp_update
|
|||
pSurfaceCommand SurfaceCommand; /* 64 */
|
||||
pSurfaceBits SurfaceBits; /* 65 */
|
||||
pSurfaceFrameMarker SurfaceFrameMarker; /* 66 */
|
||||
pSurfaceFrameAcknowledge SurfaceFrameAcknowledge; /* 67 */
|
||||
UINT32 paddingE[80 - 68]; /* 68 */
|
||||
pSurfaceFrameBits SurfaceFrameBits; /* 67 */
|
||||
pSurfaceFrameAcknowledge SurfaceFrameAcknowledge; /* 68 */
|
||||
UINT32 paddingE[80 - 69]; /* 69 */
|
||||
|
||||
/* internal */
|
||||
|
||||
|
|
|
@ -347,6 +347,57 @@ int interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* interleaved, BYTE* pSrcDa
|
|||
return 1;
|
||||
}
|
||||
|
||||
int interleaved_compress(BITMAP_INTERLEAVED_CONTEXT* interleaved, BYTE* pDstData, UINT32* pDstSize,
|
||||
int nWidth, int nHeight, BYTE* pSrcData, DWORD SrcFormat, int nSrcStep, int nXSrc, int nYSrc, BYTE* palette, int bpp)
|
||||
{
|
||||
int status;
|
||||
wStream* s;
|
||||
UINT32 DstFormat = 0;
|
||||
int maxSize = 64 * 64 * 4;
|
||||
|
||||
if (nWidth % 4)
|
||||
{
|
||||
fprintf(stderr, "interleaved_compress: width is not a multiple of 4\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((nWidth > 64) || (nHeight > 64))
|
||||
{
|
||||
fprintf(stderr, "interleaved_compress: width (%d) or height (%d) is greater than 64\n", nWidth, nHeight);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bpp == 24)
|
||||
DstFormat = PIXEL_FORMAT_XRGB32;
|
||||
else if (bpp == 16)
|
||||
DstFormat = PIXEL_FORMAT_RGB16;
|
||||
else if (bpp == 15)
|
||||
DstFormat = PIXEL_FORMAT_RGB15;
|
||||
else if (bpp == 8)
|
||||
DstFormat = PIXEL_FORMAT_RGB8;
|
||||
|
||||
if (!DstFormat)
|
||||
return -1;
|
||||
|
||||
status = freerdp_image_copy(interleaved->TempBuffer, DstFormat, -1, 0, 0, nWidth, nHeight,
|
||||
pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc, palette);
|
||||
|
||||
s = Stream_New(pDstData, maxSize);
|
||||
|
||||
if (!s)
|
||||
return -1;
|
||||
|
||||
status = freerdp_bitmap_compress((char*) interleaved->TempBuffer, nWidth, nHeight,
|
||||
s, bpp, maxSize, nHeight - 1, interleaved->bts, 0);
|
||||
|
||||
Stream_SealLength(s);
|
||||
*pDstSize = (UINT32) Stream_Length(s);
|
||||
|
||||
Stream_Free(s, FALSE);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int bitmap_interleaved_context_reset(BITMAP_INTERLEAVED_CONTEXT* interleaved)
|
||||
{
|
||||
return 1;
|
||||
|
@ -360,8 +411,9 @@ BITMAP_INTERLEAVED_CONTEXT* bitmap_interleaved_context_new(BOOL Compressor)
|
|||
|
||||
if (interleaved)
|
||||
{
|
||||
interleaved->TempSize = 64 * 64 * 3;
|
||||
interleaved->TempSize = 64 * 64 * 4;
|
||||
interleaved->TempBuffer = _aligned_malloc(interleaved->TempSize, 16);
|
||||
interleaved->bts = Stream_New(NULL, interleaved->TempSize);
|
||||
}
|
||||
|
||||
return interleaved;
|
||||
|
@ -373,6 +425,7 @@ void bitmap_interleaved_context_free(BITMAP_INTERLEAVED_CONTEXT* interleaved)
|
|||
return;
|
||||
|
||||
_aligned_free(interleaved->TempBuffer);
|
||||
Stream_Free(interleaved->bts, TRUE);
|
||||
|
||||
free(interleaved);
|
||||
}
|
||||
|
|
|
@ -63,14 +63,14 @@ static void nsc_decode(NSC_CONTEXT* context)
|
|||
|
||||
bmpdata = context->BitmapData;
|
||||
rw = ROUND_UP_TO(context->width, 8);
|
||||
shift = context->nsc_stream.ColorLossLevel - 1; /* colorloss recovery + YCoCg shift */
|
||||
shift = context->ColorLossLevel - 1; /* colorloss recovery + YCoCg shift */
|
||||
|
||||
WLog_Print(context->priv->log, WLOG_DEBUG, "NscDecode: width: %d height: %d ChromaSubSamplingLevel: %d",
|
||||
context->width, context->height, context->nsc_stream.ChromaSubSamplingLevel);
|
||||
WLog_Print(context->priv->log, WLOG_DEBUG, "NscDecode: width: %d height: %d ChromaSubsamplingLevel: %d",
|
||||
context->width, context->height, context->ChromaSubsamplingLevel);
|
||||
|
||||
for (y = 0; y < context->height; y++)
|
||||
{
|
||||
if (context->nsc_stream.ChromaSubSamplingLevel > 0)
|
||||
if (context->ChromaSubsamplingLevel)
|
||||
{
|
||||
yplane = context->priv->PlaneBuffers[0] + y * rw; /* Y */
|
||||
coplane = context->priv->PlaneBuffers[1] + (y >> 1) * (rw >> 1); /* Co, supersampled */
|
||||
|
@ -98,8 +98,8 @@ static void nsc_decode(NSC_CONTEXT* context)
|
|||
*bmpdata++ = MINMAX(r_val, 0, 0xFF);
|
||||
*bmpdata++ = *aplane;
|
||||
yplane++;
|
||||
coplane += (context->nsc_stream.ChromaSubSamplingLevel > 0 ? x % 2 : 1);
|
||||
cgplane += (context->nsc_stream.ChromaSubSamplingLevel > 0 ? x % 2 : 1);
|
||||
coplane += (context->ChromaSubsamplingLevel ? x % 2 : 1);
|
||||
cgplane += (context->ChromaSubsamplingLevel ? x % 2 : 1);
|
||||
aplane++;
|
||||
}
|
||||
}
|
||||
|
@ -159,12 +159,12 @@ static void nsc_rle_decompress_data(NSC_CONTEXT* context)
|
|||
UINT32 planeSize;
|
||||
UINT32 originalSize;
|
||||
|
||||
rle = context->nsc_stream.Planes;
|
||||
rle = context->Planes;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
originalSize = context->OrgByteCount[i];
|
||||
planeSize = context->nsc_stream.PlaneByteCount[i];
|
||||
planeSize = context->PlaneByteCount[i];
|
||||
|
||||
if (planeSize == 0)
|
||||
FillMemory(context->priv->PlaneBuffers[i], originalSize, 0xFF);
|
||||
|
@ -182,13 +182,13 @@ static void nsc_stream_initialize(NSC_CONTEXT* context, wStream* s)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
Stream_Read_UINT32(s, context->nsc_stream.PlaneByteCount[i]);
|
||||
Stream_Read_UINT32(s, context->PlaneByteCount[i]);
|
||||
|
||||
Stream_Read_UINT8(s, context->nsc_stream.ColorLossLevel);
|
||||
Stream_Read_UINT8(s, context->nsc_stream.ChromaSubSamplingLevel);
|
||||
Stream_Seek(s, 2);
|
||||
Stream_Read_UINT8(s, context->ColorLossLevel); /* ColorLossLevel (1 byte) */
|
||||
Stream_Read_UINT8(s, context->ChromaSubsamplingLevel); /* ChromaSubsamplingLevel (1 byte) */
|
||||
Stream_Seek(s, 2); /* Reserved (2 bytes) */
|
||||
|
||||
context->nsc_stream.Planes = Stream_Pointer(s);
|
||||
context->Planes = Stream_Pointer(s);
|
||||
}
|
||||
|
||||
static void nsc_context_initialize(NSC_CONTEXT* context, wStream* s)
|
||||
|
@ -232,7 +232,7 @@ static void nsc_context_initialize(NSC_CONTEXT* context, wStream* s)
|
|||
context->OrgByteCount[i] = context->width * context->height;
|
||||
}
|
||||
|
||||
if (context->nsc_stream.ChromaSubSamplingLevel > 0) /* [MS-RDPNSC] 2.2 */
|
||||
if (context->ChromaSubsamplingLevel)
|
||||
{
|
||||
context->OrgByteCount[0] = tempWidth * context->height;
|
||||
context->OrgByteCount[1] = (tempWidth >> 1) * (tempHeight >> 1);
|
||||
|
@ -288,8 +288,8 @@ NSC_CONTEXT* nsc_context_new(void)
|
|||
PROFILER_CREATE(context->priv->prof_nsc_encode, "nsc_encode");
|
||||
|
||||
/* Default encoding parameters */
|
||||
context->nsc_stream.ColorLossLevel = 3;
|
||||
context->nsc_stream.ChromaSubSamplingLevel = 1;
|
||||
context->ColorLossLevel = 3;
|
||||
context->ChromaSubsamplingLevel = 1;
|
||||
|
||||
/* init optimized methods */
|
||||
NSC_INIT_SIMD(context);
|
||||
|
|
|
@ -57,7 +57,7 @@ static void nsc_context_initialize_encode(NSC_CONTEXT* context)
|
|||
context->priv->PlaneBuffersLength = length;
|
||||
}
|
||||
|
||||
if (context->nsc_stream.ChromaSubSamplingLevel > 0)
|
||||
if (context->ChromaSubsamplingLevel)
|
||||
{
|
||||
context->OrgByteCount[0] = tempWidth * context->height;
|
||||
context->OrgByteCount[1] = tempWidth * tempHeight / 4;
|
||||
|
@ -93,8 +93,8 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* data, int scan
|
|||
|
||||
tempWidth = ROUND_UP_TO(context->width, 8);
|
||||
tempHeight = ROUND_UP_TO(context->height, 2);
|
||||
rw = (context->nsc_stream.ChromaSubSamplingLevel > 0 ? tempWidth : context->width);
|
||||
ccl = context->nsc_stream.ColorLossLevel;
|
||||
rw = (context->ChromaSubsamplingLevel ? tempWidth : context->width);
|
||||
ccl = context->ColorLossLevel;
|
||||
yplane = context->priv->PlaneBuffers[0];
|
||||
coplane = context->priv->PlaneBuffers[1];
|
||||
cgplane = context->priv->PlaneBuffers[2];
|
||||
|
@ -201,7 +201,7 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* data, int scan
|
|||
*aplane++ = a_val;
|
||||
}
|
||||
|
||||
if (context->nsc_stream.ChromaSubSamplingLevel > 0 && (x % 2) == 1)
|
||||
if (context->ChromaSubsamplingLevel && (x % 2) == 1)
|
||||
{
|
||||
*yplane = *(yplane - 1);
|
||||
*coplane = *(coplane - 1);
|
||||
|
@ -209,7 +209,7 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* data, int scan
|
|||
}
|
||||
}
|
||||
|
||||
if (context->nsc_stream.ChromaSubSamplingLevel > 0 && (y % 2) == 1)
|
||||
if (context->ChromaSubsamplingLevel && (y % 2) == 1)
|
||||
{
|
||||
CopyMemory(yplane + rw, yplane, rw);
|
||||
CopyMemory(coplane + rw, coplane, rw);
|
||||
|
@ -260,7 +260,7 @@ void nsc_encode(NSC_CONTEXT* context, BYTE* bmpdata, int rowstride)
|
|||
{
|
||||
nsc_encode_argb_to_aycocg(context, bmpdata, rowstride);
|
||||
|
||||
if (context->nsc_stream.ChromaSubSamplingLevel > 0)
|
||||
if (context->ChromaSubsamplingLevel)
|
||||
{
|
||||
nsc_encode_subsampling(context);
|
||||
}
|
||||
|
@ -344,7 +344,7 @@ static void nsc_rle_compress_data(NSC_CONTEXT* context)
|
|||
planeSize = originalSize;
|
||||
}
|
||||
|
||||
context->nsc_stream.PlaneByteCount[i] = planeSize;
|
||||
context->PlaneByteCount[i] = planeSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -359,7 +359,7 @@ UINT32 nsc_compute_byte_count(NSC_CONTEXT* context, UINT32* ByteCount, UINT32 wi
|
|||
|
||||
maxPlaneSize = tempWidth * tempHeight + 16;
|
||||
|
||||
if (context->nsc_stream.ChromaSubSamplingLevel > 0)
|
||||
if (context->ChromaSubsamplingLevel)
|
||||
{
|
||||
ByteCount[0] = tempWidth * height;
|
||||
ByteCount[1] = tempWidth * tempHeight / 4;
|
||||
|
@ -406,8 +406,10 @@ NSC_MESSAGE* nsc_encode_messages(NSC_CONTEXT* context, BYTE* data, int x, int y,
|
|||
|
||||
maxDataSize -= 1024; /* reserve enough space for headers */
|
||||
|
||||
messages = (NSC_MESSAGE*) malloc(sizeof(NSC_MESSAGE) * (*numMessages));
|
||||
ZeroMemory(messages, sizeof(NSC_MESSAGE) * (*numMessages));
|
||||
messages = (NSC_MESSAGE*) calloc(*numMessages, sizeof(NSC_MESSAGE));
|
||||
|
||||
if (!messages)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < rows; i++)
|
||||
{
|
||||
|
@ -467,10 +469,12 @@ NSC_MESSAGE* nsc_encode_messages(NSC_CONTEXT* context, BYTE* data, int x, int y,
|
|||
nsc_rle_compress_data(context);
|
||||
PROFILER_EXIT(context->priv->prof_nsc_rle_compress_data);
|
||||
|
||||
messages[i].PlaneByteCount[0] = context->nsc_stream.PlaneByteCount[0];
|
||||
messages[i].PlaneByteCount[1] = context->nsc_stream.PlaneByteCount[1];
|
||||
messages[i].PlaneByteCount[2] = context->nsc_stream.PlaneByteCount[2];
|
||||
messages[i].PlaneByteCount[3] = context->nsc_stream.PlaneByteCount[3];
|
||||
messages[i].LumaPlaneByteCount = context->PlaneByteCount[0];
|
||||
messages[i].OrangeChromaPlaneByteCount = context->PlaneByteCount[1];
|
||||
messages[i].GreenChromaPlaneByteCount = context->PlaneByteCount[2];
|
||||
messages[i].AlphaPlaneByteCount = context->PlaneByteCount[3];
|
||||
messages[i].ColorLossLevel = context->ColorLossLevel;
|
||||
messages[i].ChromaSubsamplingLevel = context->ChromaSubsamplingLevel;
|
||||
}
|
||||
|
||||
context->priv->PlaneBuffers[0] = NULL;
|
||||
|
@ -484,25 +488,31 @@ NSC_MESSAGE* nsc_encode_messages(NSC_CONTEXT* context, BYTE* data, int x, int y,
|
|||
|
||||
int nsc_write_message(NSC_CONTEXT* context, wStream* s, NSC_MESSAGE* message)
|
||||
{
|
||||
int i;
|
||||
UINT32 totalPlaneByteCount;
|
||||
|
||||
Stream_EnsureRemainingCapacity(s, 20);
|
||||
Stream_Write_UINT32(s, message->PlaneByteCount[0]); /* LumaPlaneByteCount (4 bytes) */
|
||||
Stream_Write_UINT32(s, message->PlaneByteCount[1]); /* OrangeChromaPlaneByteCount (4 bytes) */
|
||||
Stream_Write_UINT32(s, message->PlaneByteCount[2]); /* GreenChromaPlaneByteCount (4 bytes) */
|
||||
Stream_Write_UINT32(s, message->PlaneByteCount[3]); /* AlphaPlaneByteCount (4 bytes) */
|
||||
Stream_Write_UINT8(s, context->nsc_stream.ColorLossLevel); /* ColorLossLevel (1 byte) */
|
||||
Stream_Write_UINT8(s, context->nsc_stream.ChromaSubSamplingLevel); /* ChromaSubsamplingLevel (1 byte) */
|
||||
totalPlaneByteCount = message->LumaPlaneByteCount + message->OrangeChromaPlaneByteCount +
|
||||
message->GreenChromaPlaneByteCount + message->AlphaPlaneByteCount;
|
||||
|
||||
Stream_EnsureRemainingCapacity(s, 20 + totalPlaneByteCount);
|
||||
Stream_Write_UINT32(s, message->LumaPlaneByteCount); /* LumaPlaneByteCount (4 bytes) */
|
||||
Stream_Write_UINT32(s, message->OrangeChromaPlaneByteCount); /* OrangeChromaPlaneByteCount (4 bytes) */
|
||||
Stream_Write_UINT32(s, message->GreenChromaPlaneByteCount); /* GreenChromaPlaneByteCount (4 bytes) */
|
||||
Stream_Write_UINT32(s, message->AlphaPlaneByteCount); /* AlphaPlaneByteCount (4 bytes) */
|
||||
Stream_Write_UINT8(s, message->ColorLossLevel); /* ColorLossLevel (1 byte) */
|
||||
Stream_Write_UINT8(s, message->ChromaSubsamplingLevel); /* ChromaSubsamplingLevel (1 byte) */
|
||||
Stream_Write_UINT16(s, 0); /* Reserved (2 bytes) */
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (message->PlaneByteCount[i] > 0)
|
||||
{
|
||||
Stream_EnsureRemainingCapacity(s, (int) message->PlaneByteCount[i]);
|
||||
Stream_Write(s, message->PlaneBuffers[i], message->PlaneByteCount[i]);
|
||||
}
|
||||
}
|
||||
if (message->LumaPlaneByteCount)
|
||||
Stream_Write(s, message->PlaneBuffers[0], message->LumaPlaneByteCount); /* LumaPlane */
|
||||
|
||||
if (message->OrangeChromaPlaneByteCount)
|
||||
Stream_Write(s, message->PlaneBuffers[1], message->OrangeChromaPlaneByteCount); /* OrangeChromaPlane */
|
||||
|
||||
if (message->GreenChromaPlaneByteCount)
|
||||
Stream_Write(s, message->PlaneBuffers[2], message->GreenChromaPlaneByteCount); /* GreenChromaPlane */
|
||||
|
||||
if (message->AlphaPlaneByteCount)
|
||||
Stream_Write(s, message->PlaneBuffers[3], message->AlphaPlaneByteCount); /* AlphaPlane */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -515,7 +525,8 @@ int nsc_message_free(NSC_CONTEXT* context, NSC_MESSAGE* message)
|
|||
|
||||
void nsc_compose_message(NSC_CONTEXT* context, wStream* s, BYTE* data, int width, int height, int scanline)
|
||||
{
|
||||
int i;
|
||||
NSC_MESSAGE s_message = { 0 };
|
||||
NSC_MESSAGE* message = &s_message;
|
||||
|
||||
context->width = width;
|
||||
context->height = height;
|
||||
|
@ -531,22 +542,17 @@ void nsc_compose_message(NSC_CONTEXT* context, wStream* s, BYTE* data, int width
|
|||
nsc_rle_compress_data(context);
|
||||
PROFILER_EXIT(context->priv->prof_nsc_rle_compress_data);
|
||||
|
||||
/* Assemble the NSCodec message into stream */
|
||||
Stream_EnsureRemainingCapacity(s, 20);
|
||||
Stream_Write_UINT32(s, context->nsc_stream.PlaneByteCount[0]); /* LumaPlaneByteCount (4 bytes) */
|
||||
Stream_Write_UINT32(s, context->nsc_stream.PlaneByteCount[1]); /* OrangeChromaPlaneByteCount (4 bytes) */
|
||||
Stream_Write_UINT32(s, context->nsc_stream.PlaneByteCount[2]); /* GreenChromaPlaneByteCount (4 bytes) */
|
||||
Stream_Write_UINT32(s, context->nsc_stream.PlaneByteCount[3]); /* AlphaPlaneByteCount (4 bytes) */
|
||||
Stream_Write_UINT8(s, context->nsc_stream.ColorLossLevel); /* ColorLossLevel (1 byte) */
|
||||
Stream_Write_UINT8(s, context->nsc_stream.ChromaSubSamplingLevel); /* ChromaSubsamplingLevel (1 byte) */
|
||||
Stream_Write_UINT16(s, 0); /* Reserved (2 bytes) */
|
||||
message->PlaneBuffers[0] = context->priv->PlaneBuffers[0];
|
||||
message->PlaneBuffers[1] = context->priv->PlaneBuffers[1];
|
||||
message->PlaneBuffers[2] = context->priv->PlaneBuffers[2];
|
||||
message->PlaneBuffers[3] = context->priv->PlaneBuffers[3];
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (context->nsc_stream.PlaneByteCount[i] > 0)
|
||||
{
|
||||
Stream_EnsureRemainingCapacity(s, (int) context->nsc_stream.PlaneByteCount[i]);
|
||||
Stream_Write(s, context->priv->PlaneBuffers[i], context->nsc_stream.PlaneByteCount[i]);
|
||||
}
|
||||
}
|
||||
message->LumaPlaneByteCount = context->PlaneByteCount[0];
|
||||
message->OrangeChromaPlaneByteCount = context->PlaneByteCount[1];
|
||||
message->GreenChromaPlaneByteCount = context->PlaneByteCount[2];
|
||||
message->AlphaPlaneByteCount = context->PlaneByteCount[3];
|
||||
message->ColorLossLevel = context->ColorLossLevel;
|
||||
message->ChromaSubsamplingLevel = context->ChromaSubsamplingLevel;
|
||||
|
||||
nsc_write_message(context, s, message);
|
||||
}
|
||||
|
|
|
@ -56,8 +56,8 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* data, int
|
|||
|
||||
tempWidth = ROUND_UP_TO(context->width, 8);
|
||||
tempHeight = ROUND_UP_TO(context->height, 2);
|
||||
rw = (context->nsc_stream.ChromaSubSamplingLevel > 0 ? tempWidth : context->width);
|
||||
ccl = context->nsc_stream.ColorLossLevel;
|
||||
rw = (context->ChromaSubsamplingLevel > 0 ? tempWidth : context->width);
|
||||
ccl = context->ColorLossLevel;
|
||||
yplane = context->priv->PlaneBuffers[0];
|
||||
coplane = context->priv->PlaneBuffers[1];
|
||||
cgplane = context->priv->PlaneBuffers[2];
|
||||
|
@ -278,7 +278,7 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* data, int
|
|||
aplane += 8;
|
||||
}
|
||||
|
||||
if (context->nsc_stream.ChromaSubSamplingLevel > 0 && (context->width % 2) == 1)
|
||||
if (context->ChromaSubsamplingLevel > 0 && (context->width % 2) == 1)
|
||||
{
|
||||
context->priv->PlaneBuffers[0][y * rw + context->width] = context->priv->PlaneBuffers[0][y * rw + context->width - 1];
|
||||
context->priv->PlaneBuffers[1][y * rw + context->width] = context->priv->PlaneBuffers[1][y * rw + context->width - 1];
|
||||
|
@ -286,7 +286,7 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* data, int
|
|||
}
|
||||
}
|
||||
|
||||
if (context->nsc_stream.ChromaSubSamplingLevel > 0 && (y % 2) == 1)
|
||||
if (context->ChromaSubsamplingLevel > 0 && (y % 2) == 1)
|
||||
{
|
||||
CopyMemory(yplane + rw, yplane, rw);
|
||||
CopyMemory(coplane + rw, coplane, rw);
|
||||
|
@ -351,7 +351,7 @@ static void nsc_encode_sse2(NSC_CONTEXT* context, BYTE* data, int scanline)
|
|||
{
|
||||
nsc_encode_argb_to_aycocg_sse2(context, data, scanline);
|
||||
|
||||
if (context->nsc_stream.ChromaSubSamplingLevel > 0)
|
||||
if (context->ChromaSubsamplingLevel > 0)
|
||||
{
|
||||
nsc_encode_subsampling_sse2(context);
|
||||
}
|
||||
|
|
|
@ -1001,7 +1001,7 @@ int freerdp_bitmap_planar_delta_encode_planes(BYTE* inPlanes[4], int width, int
|
|||
}
|
||||
|
||||
BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* context, BYTE* data, UINT32 format,
|
||||
int width, int height, int scanline, BYTE* dstData, int* dstSize)
|
||||
int width, int height, int scanline, BYTE* dstData, int* pDstSize)
|
||||
{
|
||||
int size;
|
||||
BYTE* dstp;
|
||||
|
@ -1064,7 +1064,7 @@ BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* context, BYTE* data,
|
|||
size++;
|
||||
|
||||
dstData = malloc(size);
|
||||
*dstSize = size;
|
||||
*pDstSize = size;
|
||||
}
|
||||
|
||||
dstp = dstData;
|
||||
|
@ -1136,7 +1136,7 @@ BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* context, BYTE* data,
|
|||
}
|
||||
|
||||
size = (dstp - dstData);
|
||||
*dstSize = size;
|
||||
*pDstSize = size;
|
||||
|
||||
return dstData;
|
||||
}
|
||||
|
|
|
@ -143,6 +143,12 @@ BOOL region16_is_empty(const REGION16 *region)
|
|||
return (region->data->nbRects == 0);
|
||||
}
|
||||
|
||||
BOOL rectangles_equal(const RECTANGLE_16 *r1, const RECTANGLE_16 *r2)
|
||||
{
|
||||
return ((r1->left == r2->left) && (r1->top == r2->top) &&
|
||||
(r1->right == r2->right) && (r1->bottom == r2->bottom)) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
BOOL rectangles_intersects(const RECTANGLE_16 *r1, const RECTANGLE_16 *r2)
|
||||
{
|
||||
RECTANGLE_16 tmp;
|
||||
|
|
|
@ -976,8 +976,11 @@ BOOL freerdp_get_param_bool(rdpSettings* settings, int id)
|
|||
case FreeRDP_NSCodec:
|
||||
return settings->NSCodec;
|
||||
|
||||
case FreeRDP_FrameAcknowledge:
|
||||
return settings->FrameAcknowledge;
|
||||
case FreeRDP_NSCodecAllowSubsampling:
|
||||
return settings->NSCodecAllowSubsampling;
|
||||
|
||||
case FreeRDP_NSCodecAllowDynamicColorFidelity:
|
||||
return settings->NSCodecAllowDynamicColorFidelity;
|
||||
|
||||
case FreeRDP_JpegCodec:
|
||||
return settings->JpegCodec;
|
||||
|
@ -1464,8 +1467,12 @@ int freerdp_set_param_bool(rdpSettings* settings, int id, BOOL param)
|
|||
settings->NSCodec = param;
|
||||
break;
|
||||
|
||||
case FreeRDP_FrameAcknowledge:
|
||||
settings->FrameAcknowledge = param;
|
||||
case FreeRDP_NSCodecAllowSubsampling:
|
||||
settings->NSCodecAllowSubsampling = param;
|
||||
break;
|
||||
|
||||
case FreeRDP_NSCodecAllowDynamicColorFidelity:
|
||||
settings->NSCodecAllowDynamicColorFidelity = param;
|
||||
break;
|
||||
|
||||
case FreeRDP_JpegCodec:
|
||||
|
@ -1788,6 +1795,12 @@ UINT32 freerdp_get_param_uint32(rdpSettings* settings, int id)
|
|||
case FreeRDP_NSCodecId:
|
||||
return settings->NSCodecId;
|
||||
|
||||
case FreeRDP_FrameAcknowledge:
|
||||
return settings->FrameAcknowledge;
|
||||
|
||||
case FreeRDP_NSCodecColorLossLevel:
|
||||
return settings->NSCodecColorLossLevel;
|
||||
|
||||
case FreeRDP_JpegCodecId:
|
||||
return settings->JpegCodecId;
|
||||
|
||||
|
@ -2095,6 +2108,14 @@ int freerdp_set_param_uint32(rdpSettings* settings, int id, UINT32 param)
|
|||
settings->NSCodecId = param;
|
||||
break;
|
||||
|
||||
case FreeRDP_FrameAcknowledge:
|
||||
settings->FrameAcknowledge = param;
|
||||
break;
|
||||
|
||||
case FreeRDP_NSCodecColorLossLevel:
|
||||
settings->NSCodecColorLossLevel = param;
|
||||
break;
|
||||
|
||||
case FreeRDP_JpegCodecId:
|
||||
settings->JpegCodecId = param;
|
||||
break;
|
||||
|
|
|
@ -41,10 +41,10 @@ static BOOL autodetect_send_rtt_measure_response(rdpRdp* rdp, UINT16 sequenceNum
|
|||
|
||||
s = rdp_message_channel_pdu_init(rdp);
|
||||
|
||||
if (s == NULL)
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
DEBUG_AUTODETECT("sending RTT Measure Response PDU");
|
||||
WLog_DBG(AUTODETECT_TAG, "sending RTT Measure Response PDU");
|
||||
|
||||
Stream_Write_UINT8(s, 0x06); /* headerLength (1 byte) */
|
||||
Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_RESPONSE); /* headerTypeId (1 byte) */
|
||||
|
@ -56,8 +56,8 @@ static BOOL autodetect_send_rtt_measure_response(rdpRdp* rdp, UINT16 sequenceNum
|
|||
|
||||
static BOOL autodetect_send_bandwidth_measure_results(rdpRdp* rdp, UINT16 responseType, UINT16 sequenceNumber)
|
||||
{
|
||||
UINT32 timeDelta;
|
||||
wStream* s;
|
||||
UINT32 timeDelta;
|
||||
|
||||
/* Compute the total time */
|
||||
timeDelta = GetTickCount() - rdp->autodetect->bandwidthMeasureStartTime;
|
||||
|
@ -66,10 +66,10 @@ static BOOL autodetect_send_bandwidth_measure_results(rdpRdp* rdp, UINT16 respon
|
|||
|
||||
s = rdp_message_channel_pdu_init(rdp);
|
||||
|
||||
if (s == NULL)
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
DEBUG_AUTODETECT("sending Bandwidth Measure Results PDU -> timeDelta=%u, byteCount=%u", timeDelta, rdp->autodetect->bandwidthMeasureByteCount);
|
||||
WLog_DBG(AUTODETECT_TAG, "sending Bandwidth Measure Results PDU -> timeDelta=%u, byteCount=%u", timeDelta, rdp->autodetect->bandwidthMeasureByteCount);
|
||||
|
||||
Stream_Write_UINT8(s, 0x0E); /* headerLength (1 byte) */
|
||||
Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_RESPONSE); /* headerTypeId (1 byte) */
|
||||
|
@ -89,10 +89,10 @@ BOOL autodetect_send_netchar_sync(rdpRdp* rdp, UINT16 sequenceNumber)
|
|||
|
||||
s = rdp_message_channel_pdu_init(rdp);
|
||||
|
||||
if (s == NULL)
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
DEBUG_AUTODETECT("sending Network Characteristics Sync PDU -> bandwidth=%u, rtt=%u", rdp->autodetect->netCharBandwidth, rdp->autodetect->netCharAverageRTT);
|
||||
WLog_DBG(AUTODETECT_TAG, "sending Network Characteristics Sync PDU -> bandwidth=%u, rtt=%u", rdp->autodetect->netCharBandwidth, rdp->autodetect->netCharAverageRTT);
|
||||
|
||||
Stream_Write_UINT8(s, 0x0E); /* headerLength (1 byte) */
|
||||
Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_RESPONSE); /* headerTypeId (1 byte) */
|
||||
|
@ -109,7 +109,7 @@ static BOOL autodetect_recv_rtt_measure_request(rdpRdp* rdp, wStream* s, AUTODET
|
|||
if (autodetectReqPdu->headerLength != 0x06)
|
||||
return FALSE;
|
||||
|
||||
DEBUG_AUTODETECT("received RTT Measure Request PDU");
|
||||
WLog_DBG(AUTODETECT_TAG, "received RTT Measure Request PDU");
|
||||
|
||||
/* Send a response to the server */
|
||||
return autodetect_send_rtt_measure_response(rdp, autodetectReqPdu->sequenceNumber);
|
||||
|
@ -120,7 +120,7 @@ static BOOL autodetect_recv_bandwidth_measure_start(rdpRdp* rdp, wStream* s, AUT
|
|||
if (autodetectReqPdu->headerLength != 0x06)
|
||||
return FALSE;
|
||||
|
||||
DEBUG_AUTODETECT("received Bandwidth Measure Start PDU - time=%lu", GetTickCount());
|
||||
WLog_DBG(AUTODETECT_TAG, "received Bandwidth Measure Start PDU - time=%lu", GetTickCount());
|
||||
|
||||
/* Initialize bandwidth measurement parameters */
|
||||
rdp->autodetect->bandwidthMeasureStartTime = GetTickCount();
|
||||
|
@ -141,7 +141,7 @@ static BOOL autodetect_recv_bandwidth_measure_payload(rdpRdp* rdp, wStream* s, A
|
|||
|
||||
Stream_Read_UINT16(s, payloadLength); /* payloadLength (2 bytes) */
|
||||
|
||||
DEBUG_AUTODETECT("received Bandwidth Measure Payload PDU -> payloadLength=%u", payloadLength);
|
||||
WLog_DBG(AUTODETECT_TAG, "received Bandwidth Measure Payload PDU -> payloadLength=%u", payloadLength);
|
||||
|
||||
/* Add the payload length to the bandwidth measurement parameters */
|
||||
rdp->autodetect->bandwidthMeasureByteCount += payloadLength;
|
||||
|
@ -172,7 +172,7 @@ static BOOL autodetect_recv_bandwidth_measure_stop(rdpRdp* rdp, wStream* s, AUTO
|
|||
payloadLength = 0;
|
||||
}
|
||||
|
||||
DEBUG_AUTODETECT("received Bandwidth Measure Stop PDU -> payloadLength=%u", payloadLength);
|
||||
WLog_DBG(AUTODETECT_TAG, "received Bandwidth Measure Stop PDU -> payloadLength=%u", payloadLength);
|
||||
|
||||
/* Add the payload length to the bandwidth measurement parameters */
|
||||
rdp->autodetect->bandwidthMeasureByteCount += payloadLength;
|
||||
|
@ -213,7 +213,7 @@ static BOOL autodetect_recv_netchar_result(rdpRdp* rdp, wStream* s, AUTODETECT_R
|
|||
break;
|
||||
}
|
||||
|
||||
DEBUG_AUTODETECT("received Network Characteristics Result PDU -> baseRTT=%u, bandwidth=%u, averageRTT=%u", rdp->autodetect->netCharBaseRTT, rdp->autodetect->netCharBandwidth, rdp->autodetect->netCharAverageRTT);
|
||||
WLog_DBG(AUTODETECT_TAG, "received Network Characteristics Result PDU -> baseRTT=%u, bandwidth=%u, averageRTT=%u", rdp->autodetect->netCharBaseRTT, rdp->autodetect->netCharBandwidth, rdp->autodetect->netCharAverageRTT);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -231,7 +231,7 @@ int rdp_recv_autodetect_packet(rdpRdp* rdp, wStream* s)
|
|||
Stream_Read_UINT16(s, autodetectReqPdu.sequenceNumber); /* sequenceNumber (2 bytes) */
|
||||
Stream_Read_UINT16(s, autodetectReqPdu.requestType); /* requestType (2 bytes) */
|
||||
|
||||
DEBUG_AUTODETECT(
|
||||
WLog_DBG(AUTODETECT_TAG,
|
||||
"rdp_recv_autodetect_packet: headerLength=%u, headerTypeId=%u, sequenceNumber=%u, requestType=%04x",
|
||||
autodetectReqPdu.headerLength, autodetectReqPdu.headerTypeId,
|
||||
autodetectReqPdu.sequenceNumber, autodetectReqPdu.requestType);
|
||||
|
@ -282,11 +282,11 @@ int rdp_recv_autodetect_packet(rdpRdp* rdp, wStream* s)
|
|||
|
||||
rdpAutoDetect* autodetect_new(void)
|
||||
{
|
||||
rdpAutoDetect* autoDetect = (rdpAutoDetect*) malloc(sizeof(rdpAutoDetect));
|
||||
rdpAutoDetect* autoDetect = (rdpAutoDetect*) calloc(1, sizeof(rdpAutoDetect));
|
||||
|
||||
if (autoDetect)
|
||||
{
|
||||
ZeroMemory(autoDetect, sizeof(rdpAutoDetect));
|
||||
|
||||
}
|
||||
|
||||
return autoDetect;
|
||||
|
|
|
@ -51,10 +51,5 @@ rdpAutoDetect* autodetect_new(void);
|
|||
void autodetect_free(rdpAutoDetect* autodetect);
|
||||
|
||||
#define AUTODETECT_TAG FREERDP_TAG("core.autodetect")
|
||||
#ifdef WITH_DEBUG_AUTODETECT
|
||||
#define DEBUG_AUTODETECT(fmt, ...) WLog_DBG(AUTODETECT_TAG, fmt, ## __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_AUTODETECT(fmt, ...) do { } while (0)
|
||||
#endif
|
||||
|
||||
#endif /* __AUTODETECT_H */
|
||||
|
|
|
@ -195,6 +195,9 @@ BOOL rdp_read_general_capability_set(wStream* s, UINT16 length, rdpSettings* set
|
|||
if (!(extraFlags & FASTPATH_OUTPUT_SUPPORTED))
|
||||
settings->FastPathOutput = FALSE;
|
||||
|
||||
if (!(extraFlags & ENC_SALTED_CHECKSUM))
|
||||
settings->SaltedChecksum = FALSE;
|
||||
|
||||
if (refreshRectSupport == FALSE)
|
||||
settings->RefreshRect = FALSE;
|
||||
|
||||
|
@ -341,6 +344,15 @@ BOOL rdp_read_bitmap_capability_set(wStream* s, UINT16 length, rdpSettings* sett
|
|||
settings->DesktopHeight = desktopHeight;
|
||||
}
|
||||
|
||||
if (settings->DrawAllowSkipAlpha)
|
||||
settings->DrawAllowSkipAlpha = (drawingFlags & DRAW_ALLOW_SKIP_ALPHA) ? TRUE : FALSE;
|
||||
|
||||
if (settings->DrawAllowDynamicColorFidelity)
|
||||
settings->DrawAllowDynamicColorFidelity = (drawingFlags & DRAW_ALLOW_DYNAMIC_COLOR_FIDELITY) ? TRUE : FALSE;
|
||||
|
||||
if (settings->DrawAllowColorSubsampling)
|
||||
settings->DrawAllowColorSubsampling = (drawingFlags & DRAW_ALLOW_COLOR_SUBSAMPLING) ? TRUE : FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -365,10 +377,10 @@ void rdp_write_bitmap_capability_set(wStream* s, rdpSettings* settings)
|
|||
if (settings->DrawAllowSkipAlpha)
|
||||
drawingFlags |= DRAW_ALLOW_SKIP_ALPHA;
|
||||
|
||||
if (settings->DrawAllowColorSubsampling)
|
||||
if (settings->DrawAllowDynamicColorFidelity)
|
||||
drawingFlags |= DRAW_ALLOW_DYNAMIC_COLOR_FIDELITY;
|
||||
|
||||
if (settings->DrawAllowDynamicColorFidelity)
|
||||
if (settings->DrawAllowColorSubsampling)
|
||||
drawingFlags |= DRAW_ALLOW_COLOR_SUBSAMPLING; /* currently unimplemented */
|
||||
|
||||
/* While bitmap_decode.c now implements YCoCg, in turning it
|
||||
|
@ -2408,6 +2420,7 @@ BOOL rdp_print_large_pointer_capability_set(wStream* s, UINT16 length)
|
|||
BOOL rdp_read_surface_commands_capability_set(wStream* s, UINT16 length, rdpSettings* settings)
|
||||
{
|
||||
UINT32 cmdFlags;
|
||||
|
||||
if (length < 12)
|
||||
return FALSE;
|
||||
|
||||
|
@ -2436,8 +2449,8 @@ void rdp_write_surface_commands_capability_set(wStream* s, rdpSettings* settings
|
|||
|
||||
header = rdp_capability_set_start(s);
|
||||
|
||||
cmdFlags = SURFCMDS_SET_SURFACE_BITS |
|
||||
SURFCMDS_STREAM_SURFACE_BITS;
|
||||
cmdFlags = SURFCMDS_SET_SURFACE_BITS | SURFCMDS_STREAM_SURFACE_BITS;
|
||||
|
||||
if (settings->SurfaceFrameMarkerEnabled)
|
||||
cmdFlags |= SURFCMDS_FRAME_MARKER;
|
||||
|
||||
|
@ -2463,6 +2476,33 @@ BOOL rdp_print_surface_commands_capability_set(wStream* s, UINT16 length)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
void rdp_print_bitmap_codec_guid(GUID* guid)
|
||||
{
|
||||
WLog_INFO(TAG, "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||
guid->Data1, guid->Data2, guid->Data3,
|
||||
guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
|
||||
guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
|
||||
}
|
||||
|
||||
char* rdp_get_bitmap_codec_guid_name(GUID* guid)
|
||||
{
|
||||
RPC_STATUS rpc_status;
|
||||
|
||||
if (UuidEqual(guid, &CODEC_GUID_REMOTEFX, &rpc_status))
|
||||
return "CODEC_GUID_REMOTEFX";
|
||||
else if (UuidEqual(guid, &CODEC_GUID_NSCODEC, &rpc_status))
|
||||
return "CODEC_GUID_NSCODEC";
|
||||
else if (UuidEqual(guid, &CODEC_GUID_IGNORE, &rpc_status))
|
||||
return "CODEC_GUID_IGNORE";
|
||||
else if (UuidEqual(guid, &CODEC_GUID_IMAGE_REMOTEFX, &rpc_status))
|
||||
return "CODEC_GUID_IMAGE_REMOTEFX";
|
||||
else if (UuidEqual(guid, &CODEC_GUID_JPEG, &rpc_status))
|
||||
return "CODEC_GUID_JPEG";
|
||||
|
||||
return "CODEC_GUID_UNKNOWN";
|
||||
}
|
||||
|
||||
|
||||
void rdp_read_bitmap_codec_guid(wStream* s, GUID* guid)
|
||||
{
|
||||
BYTE g[16];
|
||||
|
@ -2506,32 +2546,6 @@ void rdp_write_bitmap_codec_guid(wStream* s, GUID* guid)
|
|||
Stream_Write(s, g, 16);
|
||||
}
|
||||
|
||||
void rdp_print_bitmap_codec_guid(GUID* guid)
|
||||
{
|
||||
WLog_INFO(TAG, "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||
guid->Data1, guid->Data2, guid->Data3,
|
||||
guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
|
||||
guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
|
||||
}
|
||||
|
||||
char* rdp_get_bitmap_codec_guid_name(GUID* guid)
|
||||
{
|
||||
RPC_STATUS rpc_status;
|
||||
|
||||
if (UuidEqual(guid, &CODEC_GUID_REMOTEFX, &rpc_status))
|
||||
return "CODEC_GUID_REMOTEFX";
|
||||
else if (UuidEqual(guid, &CODEC_GUID_NSCODEC, &rpc_status))
|
||||
return "CODEC_GUID_NSCODEC";
|
||||
else if (UuidEqual(guid, &CODEC_GUID_IGNORE, &rpc_status))
|
||||
return "CODEC_GUID_IGNORE";
|
||||
else if (UuidEqual(guid, &CODEC_GUID_IMAGE_REMOTEFX, &rpc_status))
|
||||
return "CODEC_GUID_IMAGE_REMOTEFX";
|
||||
else if (UuidEqual(guid, &CODEC_GUID_JPEG, &rpc_status))
|
||||
return "CODEC_GUID_JPEG";
|
||||
|
||||
return "CODEC_GUID_UNKNOWN";
|
||||
}
|
||||
|
||||
/**
|
||||
* Read bitmap codecs capability set.\n
|
||||
* @msdn{dd891377}
|
||||
|
@ -2542,13 +2556,15 @@ char* rdp_get_bitmap_codec_guid_name(GUID* guid)
|
|||
|
||||
BOOL rdp_read_bitmap_codecs_capability_set(wStream* s, UINT16 length, rdpSettings* settings)
|
||||
{
|
||||
BYTE codecId;
|
||||
GUID codecGuid;
|
||||
RPC_STATUS rpc_status;
|
||||
BYTE bitmapCodecCount;
|
||||
UINT16 codecPropertiesLength;
|
||||
UINT16 remainingLength;
|
||||
BOOL receivedRemoteFxCodec = FALSE;
|
||||
BOOL receivedNSCodec = FALSE;
|
||||
BOOL guidNSCodec = FALSE;
|
||||
BOOL guidRemoteFx = FALSE;
|
||||
BOOL guidRemoteFxImage = FALSE;
|
||||
|
||||
if (length < 5)
|
||||
return FALSE;
|
||||
|
@ -2563,28 +2579,7 @@ BOOL rdp_read_bitmap_codecs_capability_set(wStream* s, UINT16 length, rdpSetting
|
|||
|
||||
rdp_read_bitmap_codec_guid(s, &codecGuid); /* codecGuid (16 bytes) */
|
||||
|
||||
if (settings->ServerMode)
|
||||
{
|
||||
if (UuidEqual(&codecGuid, &CODEC_GUID_REMOTEFX, &rpc_status))
|
||||
{
|
||||
Stream_Read_UINT8(s, settings->RemoteFxCodecId);
|
||||
receivedRemoteFxCodec = TRUE;
|
||||
}
|
||||
else if (UuidEqual(&codecGuid, &CODEC_GUID_NSCODEC, &rpc_status))
|
||||
{
|
||||
Stream_Read_UINT8(s, settings->NSCodecId);
|
||||
receivedNSCodec = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Stream_Seek_UINT8(s); /* codecID (1 byte) */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Stream_Seek_UINT8(s); /* codecID (1 byte) */
|
||||
}
|
||||
|
||||
Stream_Read_UINT8(s, codecId); /* codecId (1 byte) */
|
||||
Stream_Read_UINT16(s, codecPropertiesLength); /* codecPropertiesLength (2 bytes) */
|
||||
remainingLength -= 19;
|
||||
|
||||
|
@ -2593,21 +2588,156 @@ BOOL rdp_read_bitmap_codecs_capability_set(wStream* s, UINT16 length, rdpSetting
|
|||
|
||||
if (settings->ServerMode)
|
||||
{
|
||||
UINT32 beg;
|
||||
UINT32 end;
|
||||
|
||||
beg = (UINT32) Stream_GetPosition(s);
|
||||
end = beg + codecPropertiesLength;
|
||||
|
||||
if (UuidEqual(&codecGuid, &CODEC_GUID_REMOTEFX, &rpc_status))
|
||||
{
|
||||
Stream_Seek_UINT32(s); /* length */
|
||||
Stream_Read_UINT32(s, settings->RemoteFxCaptureFlags); /* captureFlags */
|
||||
Stream_Rewind(s, 8);
|
||||
UINT32 rfxCapsLength;
|
||||
UINT32 rfxPropsLength;
|
||||
UINT32 captureFlags;
|
||||
|
||||
if (settings->RemoteFxCaptureFlags & CARDP_CAPS_CAPTURE_NON_CAC)
|
||||
guidRemoteFx = TRUE;
|
||||
settings->RemoteFxCodecId = codecId;
|
||||
|
||||
Stream_Read_UINT32(s, rfxPropsLength); /* length (4 bytes) */
|
||||
Stream_Read_UINT32(s, captureFlags); /* captureFlags (4 bytes) */
|
||||
Stream_Read_UINT32(s, rfxCapsLength); /* capsLength (4 bytes) */
|
||||
|
||||
settings->RemoteFxCaptureFlags = captureFlags;
|
||||
settings->RemoteFxOnly = (captureFlags & CARDP_CAPS_CAPTURE_NON_CAC) ? TRUE : FALSE;
|
||||
|
||||
if (rfxCapsLength)
|
||||
{
|
||||
settings->RemoteFxOnly = TRUE;
|
||||
UINT16 blockType;
|
||||
UINT32 blockLen;
|
||||
UINT16 numCapsets;
|
||||
BYTE rfxCodecId;
|
||||
UINT16 capsetType;
|
||||
UINT16 numIcaps;
|
||||
UINT16 icapLen;
|
||||
|
||||
/* TS_RFX_CAPS */
|
||||
|
||||
Stream_Read_UINT16(s, blockType); /* blockType (2 bytes) */
|
||||
Stream_Read_UINT32(s, blockLen); /* blockLen (4 bytes) */
|
||||
Stream_Read_UINT16(s, numCapsets); /* numCapsets (2 bytes) */
|
||||
|
||||
if (blockType != 0xCBC0)
|
||||
return FALSE;
|
||||
|
||||
if (blockLen != 8)
|
||||
return FALSE;
|
||||
|
||||
if (numCapsets != 1)
|
||||
return FALSE;
|
||||
|
||||
/* TS_RFX_CAPSET */
|
||||
|
||||
Stream_Read_UINT16(s, blockType); /* blockType (2 bytes) */
|
||||
Stream_Read_UINT32(s, blockLen); /* blockLen (4 bytes) */
|
||||
Stream_Read_UINT8(s, rfxCodecId); /* codecId (1 byte) */
|
||||
Stream_Read_UINT16(s, capsetType); /* capsetType (2 bytes) */
|
||||
Stream_Read_UINT16(s, numIcaps); /* numIcaps (2 bytes) */
|
||||
Stream_Read_UINT16(s, icapLen); /* icapLen (2 bytes) */
|
||||
|
||||
if (blockType != 0xCBC1)
|
||||
return FALSE;
|
||||
|
||||
if (rfxCodecId != 1)
|
||||
return FALSE;
|
||||
|
||||
if (capsetType != 0xCFC0)
|
||||
return FALSE;
|
||||
|
||||
while (numIcaps--)
|
||||
{
|
||||
UINT16 version;
|
||||
UINT16 tileSize;
|
||||
BYTE codecFlags;
|
||||
BYTE colConvBits;
|
||||
BYTE transformBits;
|
||||
BYTE entropyBits;
|
||||
|
||||
/* TS_RFX_ICAP */
|
||||
|
||||
Stream_Read_UINT16(s, version); /* version (2 bytes) */
|
||||
Stream_Read_UINT16(s, tileSize); /* tileSize (2 bytes) */
|
||||
Stream_Read_UINT8(s, codecFlags); /* flags (1 byte) */
|
||||
Stream_Read_UINT8(s, colConvBits); /* colConvBits (1 byte) */
|
||||
Stream_Read_UINT8(s, transformBits); /* transformBits (1 byte) */
|
||||
Stream_Read_UINT8(s, entropyBits); /* entropyBits (1 byte) */
|
||||
|
||||
if (version != 0x0100)
|
||||
return FALSE;
|
||||
|
||||
if (tileSize != 0x0040)
|
||||
return FALSE;
|
||||
|
||||
if (colConvBits != 1)
|
||||
return FALSE;
|
||||
|
||||
if (transformBits != 1)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (UuidEqual(&codecGuid, &CODEC_GUID_IMAGE_REMOTEFX, &rpc_status))
|
||||
{
|
||||
/* Microsoft RDP servers ignore CODEC_GUID_IMAGE_REMOTEFX codec properties */
|
||||
|
||||
Stream_Seek(s, codecPropertiesLength); /* codecProperties */
|
||||
remainingLength -= codecPropertiesLength;
|
||||
guidRemoteFxImage = TRUE;
|
||||
Stream_Seek(s, codecPropertiesLength); /* codecProperties */
|
||||
}
|
||||
else if (UuidEqual(&codecGuid, &CODEC_GUID_NSCODEC, &rpc_status))
|
||||
{
|
||||
BYTE colorLossLevel;
|
||||
BYTE fAllowSubsampling;
|
||||
BYTE fAllowDynamicFidelity;
|
||||
|
||||
guidNSCodec = TRUE;
|
||||
settings->NSCodecId = codecId;
|
||||
|
||||
Stream_Read_UINT8(s, fAllowDynamicFidelity); /* fAllowDynamicFidelity (1 byte) */
|
||||
Stream_Read_UINT8(s, fAllowSubsampling); /* fAllowSubsampling (1 byte) */
|
||||
Stream_Read_UINT8(s, colorLossLevel); /* colorLossLevel (1 byte) */
|
||||
|
||||
if (colorLossLevel < 1)
|
||||
colorLossLevel = 1;
|
||||
|
||||
if (colorLossLevel > 7)
|
||||
colorLossLevel = 7;
|
||||
|
||||
settings->NSCodecAllowDynamicColorFidelity = fAllowDynamicFidelity;
|
||||
settings->NSCodecAllowSubsampling = fAllowSubsampling;
|
||||
settings->NSCodecColorLossLevel = colorLossLevel;
|
||||
}
|
||||
else if (UuidEqual(&codecGuid, &CODEC_GUID_IGNORE, &rpc_status))
|
||||
{
|
||||
Stream_Seek(s, codecPropertiesLength); /* codecProperties */
|
||||
}
|
||||
else
|
||||
{
|
||||
Stream_Seek(s, codecPropertiesLength); /* codecProperties */
|
||||
}
|
||||
|
||||
if (Stream_GetPosition(s) != end)
|
||||
{
|
||||
fprintf(stderr, "error while reading codec properties: actual offset: %d expected offset: %d\n",
|
||||
(int) Stream_GetPosition(s), end);
|
||||
Stream_SetPosition(s, end);
|
||||
}
|
||||
|
||||
remainingLength -= codecPropertiesLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
Stream_Seek(s, codecPropertiesLength); /* codecProperties */
|
||||
remainingLength -= codecPropertiesLength;
|
||||
}
|
||||
|
||||
bitmapCodecCount--;
|
||||
}
|
||||
|
@ -2615,8 +2745,9 @@ BOOL rdp_read_bitmap_codecs_capability_set(wStream* s, UINT16 length, rdpSetting
|
|||
if (settings->ServerMode)
|
||||
{
|
||||
/* only enable a codec if we've announced/enabled it before */
|
||||
settings->RemoteFxCodec = settings->RemoteFxCodec && receivedRemoteFxCodec;
|
||||
settings->NSCodec = settings->NSCodec && receivedNSCodec;
|
||||
settings->RemoteFxCodec = settings->RemoteFxCodec && guidRemoteFx;
|
||||
settings->RemoteFxImageCodec = settings->RemoteFxImageCodec && guidRemoteFxImage;
|
||||
settings->NSCodec = settings->NSCodec && guidNSCodec;
|
||||
settings->JpegCodec = FALSE;
|
||||
}
|
||||
|
||||
|
@ -2687,9 +2818,9 @@ void rdp_write_nsc_client_capability_container(wStream* s, rdpSettings* settings
|
|||
Stream_Write_UINT16(s, 3); /* codecPropertiesLength */
|
||||
|
||||
/* TS_NSCODEC_CAPABILITYSET */
|
||||
Stream_Write_UINT8(s, 1); /* fAllowDynamicFidelity */
|
||||
Stream_Write_UINT8(s, 1); /* fAllowSubsampling */
|
||||
Stream_Write_UINT8(s, 3); /* colorLossLevel */
|
||||
Stream_Write_UINT8(s, settings->NSCodecAllowDynamicColorFidelity); /* fAllowDynamicFidelity */
|
||||
Stream_Write_UINT8(s, settings->NSCodecAllowSubsampling); /* fAllowSubsampling */
|
||||
Stream_Write_UINT8(s, settings->NSCodecColorLossLevel); /* colorLossLevel */
|
||||
}
|
||||
|
||||
void rdp_write_jpeg_client_capability_container(wStream* s, rdpSettings* settings)
|
||||
|
@ -2752,9 +2883,6 @@ void rdp_write_bitmap_codecs_capability_set(wStream* s, rdpSettings* settings)
|
|||
|
||||
bitmapCodecCount = 0;
|
||||
|
||||
if (settings->RemoteFxCodec)
|
||||
settings->RemoteFxImageCodec = TRUE;
|
||||
|
||||
if (settings->RemoteFxCodec)
|
||||
bitmapCodecCount++;
|
||||
if (settings->NSCodec)
|
||||
|
|
|
@ -162,6 +162,7 @@ BOOL certificate_read_x509_certificate(rdpCertBlob* cert, rdpCertInfo* info)
|
|||
int modulus_length;
|
||||
int exponent_length;
|
||||
int error = 0;
|
||||
|
||||
s = Stream_New(cert->data, cert->length);
|
||||
|
||||
if (!s)
|
||||
|
@ -312,13 +313,14 @@ error1:
|
|||
rdpX509CertChain* certificate_new_x509_certificate_chain(UINT32 count)
|
||||
{
|
||||
rdpX509CertChain* x509_cert_chain;
|
||||
x509_cert_chain = (rdpX509CertChain*)malloc(sizeof(rdpX509CertChain));
|
||||
|
||||
x509_cert_chain = (rdpX509CertChain*) malloc(sizeof(rdpX509CertChain));
|
||||
|
||||
if (!x509_cert_chain)
|
||||
return NULL;
|
||||
|
||||
x509_cert_chain->count = count;
|
||||
x509_cert_chain->array = (rdpCertBlob*)calloc(count, sizeof(rdpCertBlob));
|
||||
x509_cert_chain->array = (rdpCertBlob*) calloc(count, sizeof(rdpCertBlob));
|
||||
|
||||
if (!x509_cert_chain->array)
|
||||
{
|
||||
|
@ -386,8 +388,8 @@ static BOOL certificate_process_server_public_key(rdpCertificate* certificate, w
|
|||
return FALSE;
|
||||
|
||||
Stream_Read(s, certificate->cert_info.Modulus, certificate->cert_info.ModulusLength);
|
||||
/* 8 bytes of zero padding */
|
||||
Stream_Seek(s, 8);
|
||||
Stream_Seek(s, 8); /* 8 bytes of zero padding */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -399,6 +401,7 @@ static BOOL certificate_process_server_public_signature(rdpCertificate* certific
|
|||
BYTE sig[TSSK_KEY_LENGTH];
|
||||
BYTE encsig[TSSK_KEY_LENGTH + 8];
|
||||
BYTE md5hash[CRYPTO_MD5_DIGEST_LENGTH];
|
||||
|
||||
md5ctx = crypto_md5_init();
|
||||
|
||||
if (!md5ctx)
|
||||
|
@ -474,7 +477,7 @@ BOOL certificate_read_server_proprietary_certificate(rdpCertificate* certificate
|
|||
Stream_Read_UINT32(s, dwSigAlgId);
|
||||
Stream_Read_UINT32(s, dwKeyAlgId);
|
||||
|
||||
if (!(dwSigAlgId == SIGNATURE_ALG_RSA && dwKeyAlgId == KEY_EXCHANGE_ALG_RSA))
|
||||
if (!((dwSigAlgId == SIGNATURE_ALG_RSA) && (dwKeyAlgId == KEY_EXCHANGE_ALG_RSA)))
|
||||
{
|
||||
WLog_ERR(TAG, "unsupported signature or key algorithm, dwSigAlgId=%d dwKeyAlgId=%d",
|
||||
dwSigAlgId, dwKeyAlgId);
|
||||
|
@ -544,9 +547,10 @@ BOOL certificate_read_server_proprietary_certificate(rdpCertificate* certificate
|
|||
BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* certificate, wStream* s)
|
||||
{
|
||||
int i;
|
||||
BOOL ret;
|
||||
UINT32 certLength;
|
||||
UINT32 numCertBlobs;
|
||||
BOOL ret;
|
||||
|
||||
DEBUG_CERTIFICATE("Server X.509 Certificate Chain");
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 4)
|
||||
|
@ -577,11 +581,14 @@ BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* certificate,
|
|||
Stream_Read(s, certificate->x509_cert_chain->array[i].data, certLength);
|
||||
certificate->x509_cert_chain->array[i].length = certLength;
|
||||
|
||||
if (numCertBlobs - i == 2)
|
||||
if ((numCertBlobs - i) == 2)
|
||||
{
|
||||
rdpCertInfo cert_info;
|
||||
|
||||
DEBUG_CERTIFICATE("License Server Certificate");
|
||||
|
||||
ret = certificate_read_x509_certificate(&certificate->x509_cert_chain->array[i], &cert_info);
|
||||
|
||||
DEBUG_LICENSE("modulus length:%d", (int) cert_info.ModulusLength);
|
||||
|
||||
if (cert_info.Modulus)
|
||||
|
@ -617,9 +624,9 @@ BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* certificate,
|
|||
|
||||
BOOL certificate_read_server_certificate(rdpCertificate* certificate, BYTE* server_cert, int length)
|
||||
{
|
||||
BOOL ret;
|
||||
wStream* s;
|
||||
UINT32 dwVersion;
|
||||
BOOL ret;
|
||||
|
||||
if (length < 4) /* NULL certificate is not an error see #1795 */
|
||||
return TRUE;
|
||||
|
@ -644,39 +651,60 @@ BOOL certificate_read_server_certificate(rdpCertificate* certificate, BYTE* serv
|
|||
}
|
||||
|
||||
Stream_Free(s, FALSE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
rdpRsaKey* key_new(const char* keyfile)
|
||||
{
|
||||
BIO* bio;
|
||||
FILE* fp;
|
||||
RSA* rsa;
|
||||
int length;
|
||||
BYTE* buffer;
|
||||
rdpRsaKey* key;
|
||||
key = (rdpRsaKey*)calloc(1, sizeof(rdpRsaKey));
|
||||
|
||||
key = (rdpRsaKey*) calloc(1, sizeof(rdpRsaKey));
|
||||
|
||||
if (!key)
|
||||
return NULL;
|
||||
|
||||
fp = fopen(keyfile, "r");
|
||||
fp = fopen(keyfile, "r+b");
|
||||
|
||||
if (fp == NULL)
|
||||
if (!fp)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to open RSA key file %s: %s.", keyfile, strerror(errno));
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
|
||||
fseek(fp, 0, SEEK_END);
|
||||
length = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
if (rsa == NULL)
|
||||
buffer = (BYTE*) malloc(length);
|
||||
|
||||
if (!buffer)
|
||||
goto out_free;
|
||||
|
||||
fread((void*) buffer, length, 1, fp);
|
||||
fclose(fp);
|
||||
|
||||
bio = BIO_new_mem_buf((void*) buffer, length);
|
||||
|
||||
if (!bio)
|
||||
goto out_free;
|
||||
|
||||
rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
|
||||
|
||||
BIO_free(bio);
|
||||
free(buffer);
|
||||
|
||||
if (!rsa)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to load RSA key from %s: %s.", keyfile, strerror(errno));
|
||||
ERR_print_errors_fp(stderr);
|
||||
fclose(fp);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
switch (RSA_check_key(rsa))
|
||||
{
|
||||
case 0:
|
||||
|
@ -689,7 +717,6 @@ rdpRsaKey* key_new(const char* keyfile)
|
|||
|
||||
default:
|
||||
WLog_ERR(TAG, "unexpected error when checking RSA key from %s: %s.", keyfile, strerror(errno));
|
||||
ERR_print_errors_fp(stderr);
|
||||
goto out_free_rsa;
|
||||
}
|
||||
|
||||
|
@ -700,7 +727,7 @@ rdpRsaKey* key_new(const char* keyfile)
|
|||
}
|
||||
|
||||
key->ModulusLength = BN_num_bytes(rsa->n);
|
||||
key->Modulus = (BYTE*)malloc(key->ModulusLength);
|
||||
key->Modulus = (BYTE*) malloc(key->ModulusLength);
|
||||
|
||||
if (!key->Modulus)
|
||||
goto out_free_rsa;
|
||||
|
@ -708,7 +735,7 @@ rdpRsaKey* key_new(const char* keyfile)
|
|||
BN_bn2bin(rsa->n, key->Modulus);
|
||||
crypto_reverse(key->Modulus, key->ModulusLength);
|
||||
key->PrivateExponentLength = BN_num_bytes(rsa->d);
|
||||
key->PrivateExponent = (BYTE*)malloc(key->PrivateExponentLength);
|
||||
key->PrivateExponent = (BYTE*) malloc(key->PrivateExponentLength);
|
||||
|
||||
if (!key->PrivateExponent)
|
||||
goto out_free_modulus;
|
||||
|
|
|
@ -537,6 +537,8 @@ BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
rdp->do_crypt_license = (sec_flags & SEC_LICENSE_ENCRYPT_SC) != 0 ? TRUE : FALSE;
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 4)
|
||||
return FALSE;
|
||||
|
||||
|
@ -574,9 +576,6 @@ BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s)
|
|||
|
||||
rdp->do_crypt = TRUE;
|
||||
|
||||
if (rdp->settings->SaltedChecksum)
|
||||
rdp->do_secure_checksum = TRUE;
|
||||
|
||||
if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
|
||||
{
|
||||
rdp->fips_encrypt = crypto_des3_encrypt_init(rdp->fips_encrypt_key, fips_ivec);
|
||||
|
@ -1117,6 +1116,9 @@ BOOL rdp_server_accept_confirm_active(rdpRdp* rdp, wStream* s)
|
|||
if (!rdp_recv_confirm_active(rdp, s))
|
||||
return FALSE;
|
||||
|
||||
if (rdp->settings->SaltedChecksum)
|
||||
rdp->do_secure_checksum = TRUE;
|
||||
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION);
|
||||
|
||||
if (!rdp_send_server_synchronize_pdu(rdp))
|
||||
|
|
|
@ -388,7 +388,7 @@ BOOL gcc_read_client_data_blocks(wStream* s, rdpMcs* mcs, int length)
|
|||
if (endPos != (begPos + blockLength))
|
||||
{
|
||||
WLog_ERR(TAG, "Error parsing GCC client data block 0x%04X: Actual Offset: %d Expected Offset: %d",
|
||||
type, endPos, begPos + blockLength);
|
||||
type, endPos, begPos + blockLength);
|
||||
}
|
||||
|
||||
length -= blockLength;
|
||||
|
@ -558,7 +558,8 @@ BOOL gcc_read_client_core_data(wStream* s, rdpMcs* mcs, UINT16 blockLength)
|
|||
{
|
||||
char* str = NULL;
|
||||
UINT32 version;
|
||||
UINT32 color_depth;
|
||||
BYTE connectionType = 0;
|
||||
UINT32 clientColorDepth;
|
||||
UINT16 colorDepth = 0;
|
||||
UINT16 postBeta2ColorDepth = 0;
|
||||
UINT16 highColorDepth = 0;
|
||||
|
@ -569,6 +570,7 @@ BOOL gcc_read_client_core_data(wStream* s, rdpMcs* mcs, UINT16 blockLength)
|
|||
UINT16 desktopOrientation = 0;
|
||||
UINT32 desktopScaleFactor = 0;
|
||||
UINT32 deviceScaleFactor = 0;
|
||||
UINT16 earlyCapabilityFlags = 0;
|
||||
rdpSettings* settings = mcs->settings;
|
||||
|
||||
/* Length of all required fields, until imeFileName */
|
||||
|
@ -637,7 +639,8 @@ BOOL gcc_read_client_core_data(wStream* s, rdpMcs* mcs, UINT16 blockLength)
|
|||
|
||||
if (blockLength < 2)
|
||||
break;
|
||||
Stream_Read_UINT16(s, settings->EarlyCapabilityFlags); /* earlyCapabilityFlags (2 bytes) */
|
||||
Stream_Read_UINT16(s, earlyCapabilityFlags); /* earlyCapabilityFlags (2 bytes) */
|
||||
settings->EarlyCapabilityFlags = (UINT32) earlyCapabilityFlags;
|
||||
blockLength -= 2;
|
||||
|
||||
if (blockLength < 64)
|
||||
|
@ -651,7 +654,7 @@ BOOL gcc_read_client_core_data(wStream* s, rdpMcs* mcs, UINT16 blockLength)
|
|||
|
||||
if (blockLength < 1)
|
||||
break;
|
||||
Stream_Read_UINT8(s, settings->PerformanceFlags); /* connectionType (1 byte) */
|
||||
Stream_Read_UINT8(s, connectionType); /* connectionType (1 byte) */
|
||||
blockLength -= 1;
|
||||
|
||||
if (blockLength < 1)
|
||||
|
@ -695,29 +698,29 @@ BOOL gcc_read_client_core_data(wStream* s, rdpMcs* mcs, UINT16 blockLength)
|
|||
|
||||
if (highColorDepth > 0)
|
||||
{
|
||||
if (settings->EarlyCapabilityFlags & RNS_UD_CS_WANT_32BPP_SESSION)
|
||||
color_depth = 32;
|
||||
if (earlyCapabilityFlags & RNS_UD_CS_WANT_32BPP_SESSION)
|
||||
clientColorDepth = 32;
|
||||
else
|
||||
color_depth = highColorDepth;
|
||||
clientColorDepth = highColorDepth;
|
||||
}
|
||||
else if (postBeta2ColorDepth > 0)
|
||||
{
|
||||
switch (postBeta2ColorDepth)
|
||||
{
|
||||
case RNS_UD_COLOR_4BPP:
|
||||
color_depth = 4;
|
||||
clientColorDepth = 4;
|
||||
break;
|
||||
case RNS_UD_COLOR_8BPP:
|
||||
color_depth = 8;
|
||||
clientColorDepth = 8;
|
||||
break;
|
||||
case RNS_UD_COLOR_16BPP_555:
|
||||
color_depth = 15;
|
||||
clientColorDepth = 15;
|
||||
break;
|
||||
case RNS_UD_COLOR_16BPP_565:
|
||||
color_depth = 16;
|
||||
clientColorDepth = 16;
|
||||
break;
|
||||
case RNS_UD_COLOR_24BPP:
|
||||
color_depth = 24;
|
||||
clientColorDepth = 24;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
|
@ -728,10 +731,10 @@ BOOL gcc_read_client_core_data(wStream* s, rdpMcs* mcs, UINT16 blockLength)
|
|||
switch (colorDepth)
|
||||
{
|
||||
case RNS_UD_COLOR_4BPP:
|
||||
color_depth = 4;
|
||||
clientColorDepth = 4;
|
||||
break;
|
||||
case RNS_UD_COLOR_8BPP:
|
||||
color_depth = 8;
|
||||
clientColorDepth = 8;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
|
@ -742,8 +745,25 @@ BOOL gcc_read_client_core_data(wStream* s, rdpMcs* mcs, UINT16 blockLength)
|
|||
* If we are in server mode, accept client's color depth only if
|
||||
* it is smaller than ours. This is what Windows server does.
|
||||
*/
|
||||
if ((color_depth < settings->ColorDepth) || !settings->ServerMode)
|
||||
settings->ColorDepth = color_depth;
|
||||
if ((clientColorDepth < settings->ColorDepth) || !settings->ServerMode)
|
||||
settings->ColorDepth = clientColorDepth;
|
||||
|
||||
if (settings->NetworkAutoDetect)
|
||||
settings->NetworkAutoDetect = (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_NETWORK_AUTODETECT) ? TRUE : FALSE;
|
||||
|
||||
if (settings->SupportHeartbeatPdu)
|
||||
settings->SupportHeartbeatPdu = (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_HEARTBEAT_PDU) ? TRUE : FALSE;
|
||||
|
||||
if (settings->SupportGraphicsPipeline)
|
||||
settings->SupportGraphicsPipeline = (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL) ? TRUE : FALSE;
|
||||
|
||||
if (settings->SupportDynamicTimeZone)
|
||||
settings->SupportDynamicTimeZone = (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE) ? TRUE : FALSE;
|
||||
|
||||
if (!(earlyCapabilityFlags & RNS_UD_CS_VALID_CONNECTION_TYPE))
|
||||
connectionType = 0;
|
||||
|
||||
settings->ConnectionType = connectionType;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -788,7 +808,7 @@ void gcc_write_client_core_data(wStream* s, rdpMcs* mcs)
|
|||
if (clientNameLength >= 16)
|
||||
{
|
||||
clientNameLength = 16;
|
||||
clientName[clientNameLength-1] = 0;
|
||||
clientName[clientNameLength - 1] = 0;
|
||||
}
|
||||
|
||||
Stream_Write(s, clientName, (clientNameLength * 2));
|
||||
|
@ -812,13 +832,17 @@ void gcc_write_client_core_data(wStream* s, rdpMcs* mcs)
|
|||
RNS_UD_16BPP_SUPPORT |
|
||||
RNS_UD_15BPP_SUPPORT;
|
||||
|
||||
connectionType = settings->ConnectionType;
|
||||
earlyCapabilityFlags = RNS_UD_CS_SUPPORT_ERRINFO_PDU;
|
||||
|
||||
if (settings->RemoteFxCodec)
|
||||
connectionType = CONNECTION_TYPE_LAN;
|
||||
if (settings->NetworkAutoDetect)
|
||||
settings->ConnectionType = CONNECTION_TYPE_AUTODETECT;
|
||||
|
||||
if (connectionType != 0)
|
||||
if (settings->RemoteFxCodec && !settings->NetworkAutoDetect)
|
||||
settings->ConnectionType = CONNECTION_TYPE_LAN;
|
||||
|
||||
connectionType = settings->ConnectionType;
|
||||
|
||||
if (connectionType)
|
||||
earlyCapabilityFlags |= RNS_UD_CS_VALID_CONNECTION_TYPE;
|
||||
|
||||
if (settings->ColorDepth == 32)
|
||||
|
@ -848,7 +872,7 @@ void gcc_write_client_core_data(wStream* s, rdpMcs* mcs)
|
|||
if (clientDigProductIdLength >= 32)
|
||||
{
|
||||
clientDigProductIdLength = 32;
|
||||
clientDigProductId[clientDigProductIdLength-1] = 0;
|
||||
clientDigProductId[clientDigProductIdLength - 1] = 0;
|
||||
}
|
||||
Stream_Write(s, clientDigProductId, (clientDigProductIdLength * 2) );
|
||||
Stream_Zero(s, 64 - (clientDigProductIdLength * 2) );
|
||||
|
@ -892,13 +916,20 @@ BOOL gcc_read_server_core_data(wStream* s, rdpMcs* mcs)
|
|||
|
||||
void gcc_write_server_core_data(wStream* s, rdpMcs* mcs)
|
||||
{
|
||||
UINT32 version;
|
||||
UINT32 earlyCapabilityFlags = 0;
|
||||
rdpSettings* settings = mcs->settings;
|
||||
|
||||
gcc_write_user_data_header(s, SC_CORE, 16);
|
||||
|
||||
Stream_Write_UINT32(s, settings->RdpVersion == 4 ? RDP_VERSION_4 : RDP_VERSION_5_PLUS);
|
||||
Stream_Write_UINT32(s, settings->RequestedProtocols); /* clientRequestedProtocols */
|
||||
Stream_Write_UINT32(s, settings->EarlyCapabilityFlags); /* earlyCapabilityFlags */
|
||||
version = settings->RdpVersion == 4 ? RDP_VERSION_4 : RDP_VERSION_5_PLUS;
|
||||
|
||||
if (settings->SupportDynamicTimeZone)
|
||||
earlyCapabilityFlags |= RNS_UD_SC_DYNAMIC_DST_SUPPORTED;
|
||||
|
||||
Stream_Write_UINT32(s, version); /* version (4 bytes) */
|
||||
Stream_Write_UINT32(s, settings->RequestedProtocols); /* clientRequestedProtocols (4 bytes) */
|
||||
Stream_Write_UINT32(s, earlyCapabilityFlags); /* earlyCapabilityFlags (4 bytes) */
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1337,6 +1368,15 @@ BOOL gcc_read_client_cluster_data(wStream* s, rdpMcs* mcs, UINT16 blockLength)
|
|||
if (flags & REDIRECTED_SESSIONID_FIELD_VALID)
|
||||
settings->RedirectedSessionId = redirectedSessionId;
|
||||
|
||||
if (blockLength != 8)
|
||||
{
|
||||
if (Stream_GetRemainingLength(s) >= (blockLength - 8))
|
||||
{
|
||||
/* The old Microsoft Mac RDP client can send a pad here */
|
||||
Stream_Seek(s, (blockLength - 8));
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,17 +40,18 @@ int rdp_recv_heartbeat_packet(rdpRdp* rdp, wStream* s)
|
|||
Stream_Read_UINT8(s, count1); /* count1 (1 byte) */
|
||||
Stream_Read_UINT8(s, count2); /* count2 (1 byte) */
|
||||
|
||||
DEBUG_HEARTBEAT("received Heartbeat PDU -> period=%u, count1=%u, count2=%u", period, count1, count2);
|
||||
WLog_DBG(HEARTBEAT_TAG, "received Heartbeat PDU -> period=%u, count1=%u, count2=%u", period, count1, count2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
rdpHeartbeat* heartbeat_new(void)
|
||||
{
|
||||
rdpHeartbeat* heartbeat = (rdpHeartbeat*)malloc(sizeof(rdpHeartbeat));
|
||||
rdpHeartbeat* heartbeat = (rdpHeartbeat*) calloc(1, sizeof(rdpHeartbeat));
|
||||
|
||||
if (heartbeat)
|
||||
{
|
||||
ZeroMemory(heartbeat, sizeof(rdpHeartbeat));
|
||||
|
||||
}
|
||||
|
||||
return heartbeat;
|
||||
|
|
|
@ -40,10 +40,5 @@ rdpHeartbeat* heartbeat_new(void);
|
|||
void heartbeat_free(rdpHeartbeat* heartbeat);
|
||||
|
||||
#define HEARTBEAT_TAG FREERDP_TAG("core.heartbeat")
|
||||
#ifdef WITH_DEBUG_HEARTBEAT
|
||||
#define DEBUG_HEARTBEAT(fmt, ...) WLog_DBG(HEARTBEAT_TAG, fmt, ## __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_HEARTBEAT(fmt, ...) do { } while (0)
|
||||
#endif
|
||||
|
||||
#endif /* __HEARTBEAT_H */
|
||||
|
|
|
@ -167,6 +167,10 @@ wStream* license_send_stream_init(rdpLicense* license)
|
|||
|
||||
s = transport_send_stream_init(license->rdp->transport, 4096);
|
||||
rdp_init_stream(license->rdp, s);
|
||||
|
||||
if (!license->rdp->do_crypt_license)
|
||||
license->rdp->sec_flags &= ~SEC_ENCRYPT;
|
||||
|
||||
license->PacketHeaderLength = Stream_GetPosition(s);
|
||||
Stream_Seek(s, LICENSE_PREAMBLE_LENGTH);
|
||||
return s;
|
||||
|
|
|
@ -79,16 +79,16 @@ static const char* inet_ntop(int af, const void* src, char* dst, size_t cnt)
|
|||
|
||||
static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_address, UINT16 port)
|
||||
{
|
||||
rdpListener* listener = (rdpListener*) instance->listener;
|
||||
int status;
|
||||
int sockfd;
|
||||
char servname[10];
|
||||
struct addrinfo hints = { 0 };
|
||||
struct addrinfo* res;
|
||||
struct addrinfo* ai;
|
||||
int option_value;
|
||||
char addr[64];
|
||||
void* sin_addr;
|
||||
char buf[50];
|
||||
int option_value;
|
||||
char servname[16];
|
||||
struct addrinfo* ai;
|
||||
struct addrinfo* res;
|
||||
struct addrinfo hints = { 0 };
|
||||
rdpListener* listener = (rdpListener*) instance->listener;
|
||||
#ifdef _WIN32
|
||||
u_long arg;
|
||||
#endif
|
||||
|
@ -96,7 +96,7 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a
|
|||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
if (bind_address == NULL)
|
||||
if (!bind_address)
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
|
||||
sprintf_s(servname, sizeof(servname), "%d", port);
|
||||
|
@ -112,9 +112,9 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
for (ai = res; ai && listener->num_sockfds < 5; ai = ai->ai_next)
|
||||
for (ai = res; ai && (listener->num_sockfds < 5); ai = ai->ai_next)
|
||||
{
|
||||
if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
|
||||
if ((ai->ai_family != AF_INET) && (ai->ai_family != AF_INET6))
|
||||
continue;
|
||||
|
||||
sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
||||
|
@ -125,6 +125,16 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a
|
|||
continue;
|
||||
}
|
||||
|
||||
if (ai->ai_family == AF_INET)
|
||||
sin_addr = &(((struct sockaddr_in*) ai->ai_addr)->sin_addr);
|
||||
else
|
||||
sin_addr = &(((struct sockaddr_in6*) ai->ai_addr)->sin6_addr);
|
||||
|
||||
inet_ntop(ai->ai_family, sin_addr, addr, sizeof(addr));
|
||||
|
||||
if (strcmp(addr, "::") == 0)
|
||||
continue;
|
||||
|
||||
option_value = 1;
|
||||
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*) &option_value, sizeof(option_value)) == -1)
|
||||
|
@ -166,12 +176,7 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a
|
|||
listener->events[listener->num_sockfds] = CreateFileDescriptorEvent(NULL, FALSE, FALSE, sockfd);
|
||||
listener->num_sockfds++;
|
||||
|
||||
if (ai->ai_family == AF_INET)
|
||||
sin_addr = &(((struct sockaddr_in*) ai->ai_addr)->sin_addr);
|
||||
else
|
||||
sin_addr = &(((struct sockaddr_in6*) ai->ai_addr)->sin6_addr);
|
||||
|
||||
WLog_ERR(TAG, "Listening on %s port %s.\n", inet_ntop(ai->ai_family, sin_addr, buf, sizeof(buf)), servname);
|
||||
WLog_INFO(TAG, "Listening on %s:%s", addr, servname);
|
||||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
|
|
|
@ -72,6 +72,8 @@ BOOL nego_security_connect(rdpNego* nego);
|
|||
|
||||
BOOL nego_connect(rdpNego* nego)
|
||||
{
|
||||
rdpSettings* settings = nego->transport->settings;
|
||||
|
||||
if (nego->state == NEGO_STATE_INITIAL)
|
||||
{
|
||||
if (nego->enabled_protocols[PROTOCOL_EXT])
|
||||
|
@ -156,15 +158,15 @@ BOOL nego_connect(rdpNego* nego)
|
|||
DEBUG_NEGO("Negotiated %s security", PROTOCOL_SECURITY_STRINGS[nego->selected_protocol]);
|
||||
|
||||
/* update settings with negotiated protocol security */
|
||||
nego->transport->settings->RequestedProtocols = nego->requested_protocols;
|
||||
nego->transport->settings->SelectedProtocol = nego->selected_protocol;
|
||||
nego->transport->settings->NegotiationFlags = nego->flags;
|
||||
settings->RequestedProtocols = nego->requested_protocols;
|
||||
settings->SelectedProtocol = nego->selected_protocol;
|
||||
settings->NegotiationFlags = nego->flags;
|
||||
|
||||
if (nego->selected_protocol == PROTOCOL_RDP)
|
||||
{
|
||||
nego->transport->settings->DisableEncryption = TRUE;
|
||||
nego->transport->settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_56BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS;
|
||||
nego->transport->settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
|
||||
settings->DisableEncryption = TRUE;
|
||||
settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_56BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS;
|
||||
settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
|
||||
}
|
||||
|
||||
/* finally connect security layer (if not already done) */
|
||||
|
@ -174,6 +176,9 @@ BOOL nego_connect(rdpNego* nego)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (!(nego->flags & DYNVC_GFX_PROTOCOL_SUPPORTED))
|
||||
settings->NetworkAutoDetect = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -506,10 +511,12 @@ BOOL nego_recv_response(rdpNego* nego)
|
|||
wStream* s;
|
||||
|
||||
s = Stream_New(NULL, 1024);
|
||||
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
status = transport_read_pdu(nego->transport, s);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
Stream_Free(s, TRUE);
|
||||
|
@ -958,17 +965,11 @@ BOOL nego_send_negotiation_response(rdpNego* nego)
|
|||
|
||||
if (!settings->LocalConnection)
|
||||
{
|
||||
settings->DisableEncryption = FALSE;
|
||||
settings->DisableEncryption = TRUE;
|
||||
settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_56BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS;
|
||||
settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
|
||||
}
|
||||
|
||||
if (settings->DisableEncryption)
|
||||
{
|
||||
WLog_WARN(TAG, "Encryption is disabled.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!settings->RdpServerRsaKey && !settings->RdpKeyFile)
|
||||
{
|
||||
WLog_ERR(TAG, "Missing server certificate");
|
||||
|
|
|
@ -275,18 +275,45 @@ wStream* rdp_message_channel_pdu_init(rdpRdp* rdp)
|
|||
|
||||
BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId)
|
||||
{
|
||||
BYTE li;
|
||||
BYTE byte;
|
||||
BYTE code;
|
||||
BYTE choice;
|
||||
UINT16 initiator;
|
||||
enum DomainMCSPDU MCSPDU;
|
||||
enum DomainMCSPDU domainMCSPDU;
|
||||
|
||||
MCSPDU = (rdp->settings->ServerMode) ? DomainMCSPDU_SendDataRequest : DomainMCSPDU_SendDataIndication;
|
||||
|
||||
if (!mcs_read_domain_mcspdu_header(s, &MCSPDU, length))
|
||||
*length = tpkt_read_header(s);
|
||||
|
||||
if (!tpdu_read_header(s, &code, &li))
|
||||
return FALSE;
|
||||
|
||||
if (code != X224_TPDU_DATA)
|
||||
{
|
||||
if (MCSPDU != DomainMCSPDU_DisconnectProviderUltimatum)
|
||||
if (code == X224_TPDU_DISCONNECT_REQUEST)
|
||||
{
|
||||
rdp->disconnect = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!per_read_choice(s, &choice))
|
||||
return FALSE;
|
||||
|
||||
domainMCSPDU = (enum DomainMCSPDU) (choice >> 2);
|
||||
|
||||
if (domainMCSPDU != MCSPDU)
|
||||
{
|
||||
if (domainMCSPDU != DomainMCSPDU_DisconnectProviderUltimatum)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
MCSPDU = domainMCSPDU;
|
||||
|
||||
if ((size_t) (*length - 8) > Stream_GetRemainingLength(s))
|
||||
return FALSE;
|
||||
|
||||
|
@ -299,7 +326,7 @@ BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId)
|
|||
if (!mcs_recv_disconnect_provider_ultimatum(rdp->mcs, s, &reason))
|
||||
return FALSE;
|
||||
|
||||
if (rdp->instance == NULL)
|
||||
if (!rdp->instance)
|
||||
{
|
||||
rdp->disconnect = TRUE;
|
||||
return FALSE;
|
||||
|
|
|
@ -151,6 +151,7 @@ struct rdp_rdp
|
|||
struct crypto_hmac_struct* fips_hmac;
|
||||
UINT32 sec_flags;
|
||||
BOOL do_crypt;
|
||||
BOOL do_crypt_license;
|
||||
BOOL do_secure_checksum;
|
||||
BYTE sign_key[16];
|
||||
BYTE decrypt_key[16];
|
||||
|
|
|
@ -402,6 +402,10 @@ rdpSettings* freerdp_settings_new(DWORD flags)
|
|||
settings->FrameAcknowledge = 2;
|
||||
settings->MouseMotion = TRUE;
|
||||
|
||||
settings->NSCodecColorLossLevel = 3;
|
||||
settings->NSCodecAllowSubsampling = TRUE;
|
||||
settings->NSCodecAllowDynamicColorFidelity = TRUE;
|
||||
|
||||
settings->AutoReconnectionEnabled = FALSE;
|
||||
settings->AutoReconnectMaxRetries = 20;
|
||||
|
||||
|
@ -584,6 +588,7 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings)
|
|||
_settings->RemoteFxCaptureFlags = settings->RemoteFxCaptureFlags; /* 3653 */
|
||||
_settings->NSCodecId = settings->NSCodecId; /* 3713 */
|
||||
_settings->FrameAcknowledge = settings->FrameAcknowledge; /* 3714 */
|
||||
_settings->NSCodecColorLossLevel = settings->NSCodecColorLossLevel; /* 3715 */
|
||||
_settings->JpegCodecId = settings->JpegCodecId; /* 3777 */
|
||||
_settings->JpegQuality = settings->JpegQuality; /* 3778 */
|
||||
_settings->BitmapCacheV3CodecId = settings->BitmapCacheV3CodecId; /* 3904 */
|
||||
|
@ -708,6 +713,8 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings)
|
|||
_settings->RemoteFxCodec = settings->RemoteFxCodec; /* 3649 */
|
||||
_settings->RemoteFxImageCodec = settings->RemoteFxImageCodec; /* 3652 */
|
||||
_settings->NSCodec = settings->NSCodec; /* 3712 */
|
||||
_settings->NSCodecAllowSubsampling = settings->NSCodecAllowSubsampling; /* 3716 */
|
||||
_settings->NSCodecAllowDynamicColorFidelity = settings->NSCodecAllowDynamicColorFidelity; /* 3717 */
|
||||
_settings->JpegCodec = settings->JpegCodec; /* 3776 */
|
||||
_settings->GfxThinClient = settings->GfxThinClient; /* 3840 */
|
||||
_settings->GfxSmallCache = settings->GfxSmallCache; /* 3841 */
|
||||
|
|
|
@ -867,7 +867,7 @@ static void update_send_surface_command(rdpContext* context, wStream* s)
|
|||
Stream_Release(update);
|
||||
}
|
||||
|
||||
static void update_send_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_command)
|
||||
static void update_send_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surfaceBitsCommand)
|
||||
{
|
||||
wStream* s;
|
||||
rdpRdp* rdp = context->rdp;
|
||||
|
@ -875,9 +875,9 @@ static void update_send_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND*
|
|||
update_force_flush(context);
|
||||
|
||||
s = fastpath_update_pdu_init(rdp->fastpath);
|
||||
Stream_EnsureRemainingCapacity(s, SURFCMD_SURFACE_BITS_HEADER_LENGTH + (int) surface_bits_command->bitmapDataLength);
|
||||
update_write_surfcmd_surface_bits_header(s, surface_bits_command);
|
||||
Stream_Write(s, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength);
|
||||
Stream_EnsureRemainingCapacity(s, SURFCMD_SURFACE_BITS_HEADER_LENGTH + (int) surfaceBitsCommand->bitmapDataLength);
|
||||
update_write_surfcmd_surface_bits_header(s, surfaceBitsCommand);
|
||||
Stream_Write(s, surfaceBitsCommand->bitmapData, surfaceBitsCommand->bitmapDataLength);
|
||||
fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s);
|
||||
|
||||
update_force_flush(context);
|
||||
|
@ -885,7 +885,7 @@ static void update_send_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND*
|
|||
Stream_Release(s);
|
||||
}
|
||||
|
||||
static void update_send_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surface_frame_marker)
|
||||
static void update_send_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surfaceFrameMarker)
|
||||
{
|
||||
wStream* s;
|
||||
rdpRdp* rdp = context->rdp;
|
||||
|
@ -893,7 +893,34 @@ static void update_send_surface_frame_marker(rdpContext* context, SURFACE_FRAME_
|
|||
update_force_flush(context);
|
||||
|
||||
s = fastpath_update_pdu_init(rdp->fastpath);
|
||||
update_write_surfcmd_frame_marker(s, surface_frame_marker->frameAction, surface_frame_marker->frameId);
|
||||
update_write_surfcmd_frame_marker(s, surfaceFrameMarker->frameAction, surfaceFrameMarker->frameId);
|
||||
fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s);
|
||||
|
||||
update_force_flush(context);
|
||||
|
||||
Stream_Release(s);
|
||||
}
|
||||
|
||||
static void update_send_surface_frame_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd, BOOL first, BOOL last, UINT32 frameId)
|
||||
{
|
||||
wStream* s;
|
||||
rdpRdp* rdp = context->rdp;
|
||||
|
||||
update_force_flush(context);
|
||||
|
||||
s = fastpath_update_pdu_init(rdp->fastpath);
|
||||
Stream_EnsureRemainingCapacity(s, SURFCMD_SURFACE_BITS_HEADER_LENGTH + (int) cmd->bitmapDataLength + 16);
|
||||
|
||||
if (first)
|
||||
update_write_surfcmd_frame_marker(s, SURFACECMD_FRAMEACTION_BEGIN, frameId);
|
||||
|
||||
update_write_surfcmd_surface_bits_header(s, cmd);
|
||||
Stream_Write(s, cmd->bitmapData, cmd->bitmapDataLength);
|
||||
|
||||
|
||||
if (last)
|
||||
update_write_surfcmd_frame_marker(s, SURFACECMD_FRAMEACTION_END, frameId);
|
||||
|
||||
fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s);
|
||||
|
||||
update_force_flush(context);
|
||||
|
@ -1596,6 +1623,7 @@ void update_register_server_callbacks(rdpUpdate* update)
|
|||
update->SurfaceBits = update_send_surface_bits;
|
||||
update->SurfaceFrameMarker = update_send_surface_frame_marker;
|
||||
update->SurfaceCommand = update_send_surface_command;
|
||||
update->SurfaceFrameBits = update_send_surface_frame_bits;
|
||||
update->PlaySound = update_send_play_sound;
|
||||
update->primary->DstBlt = update_send_dstblt;
|
||||
update->primary->PatBlt = update_send_patblt;
|
||||
|
|
|
@ -198,7 +198,9 @@ BOOL per_read_integer(wStream* s, UINT32* integer)
|
|||
if (Stream_GetRemainingLength(s) < length)
|
||||
return FALSE;
|
||||
|
||||
if (length == 1)
|
||||
if (length == 0)
|
||||
*integer = 0;
|
||||
else if (length == 1)
|
||||
Stream_Read_UINT8(s, *integer);
|
||||
else if (length == 2)
|
||||
Stream_Read_UINT16_BE(s, *integer);
|
||||
|
|
|
@ -405,54 +405,6 @@ INLINE BYTE* gdi_get_brush_pointer(HGDI_DC hdcBrush, int x, int y)
|
|||
return p;
|
||||
}
|
||||
|
||||
INLINE int gdi_is_mono_pixel_set(BYTE* data, int x, int y, int width)
|
||||
{
|
||||
int byte;
|
||||
int shift;
|
||||
|
||||
width = (width + 7) / 8;
|
||||
byte = (y * width) + (x / 8);
|
||||
shift = x % 8;
|
||||
|
||||
return (data[byte] & (0x80 >> shift)) != 0;
|
||||
}
|
||||
|
||||
static gdiBitmap* gdi_glyph_new(rdpGdi* gdi, GLYPH_DATA* glyph)
|
||||
{
|
||||
BYTE* extra;
|
||||
gdiBitmap* gdi_bmp;
|
||||
|
||||
gdi_bmp = (gdiBitmap*) malloc(sizeof(gdiBitmap));
|
||||
|
||||
if (!gdi_bmp)
|
||||
return NULL;
|
||||
|
||||
gdi_bmp->hdc = gdi_GetDC();
|
||||
gdi_bmp->hdc->bytesPerPixel = 1;
|
||||
gdi_bmp->hdc->bitsPerPixel = 1;
|
||||
|
||||
extra = freerdp_glyph_convert(glyph->cx, glyph->cy, glyph->aj);
|
||||
gdi_bmp->bitmap = gdi_CreateBitmap(glyph->cx, glyph->cy, 1, extra);
|
||||
gdi_bmp->bitmap->bytesPerPixel = 1;
|
||||
gdi_bmp->bitmap->bitsPerPixel = 1;
|
||||
|
||||
gdi_SelectObject(gdi_bmp->hdc, (HGDIOBJECT) gdi_bmp->bitmap);
|
||||
gdi_bmp->org_bitmap = NULL;
|
||||
|
||||
return gdi_bmp;
|
||||
}
|
||||
|
||||
static void gdi_glyph_free(gdiBitmap* gdi_bmp)
|
||||
{
|
||||
if (gdi_bmp)
|
||||
{
|
||||
gdi_SelectObject(gdi_bmp->hdc, (HGDIOBJECT) gdi_bmp->org_bitmap);
|
||||
gdi_DeleteObject((HGDIOBJECT) gdi_bmp->bitmap);
|
||||
gdi_DeleteDC(gdi_bmp->hdc);
|
||||
free(gdi_bmp);
|
||||
}
|
||||
}
|
||||
|
||||
gdiBitmap* gdi_bitmap_new_ex(rdpGdi* gdi, int width, int height, int bpp, BYTE* data)
|
||||
{
|
||||
gdiBitmap* bitmap;
|
||||
|
@ -911,26 +863,25 @@ static void gdi_ellipse_cb(rdpContext* context, ELLIPSE_CB_ORDER* ellipse_cb)
|
|||
|
||||
static void gdi_frame_marker(rdpContext* context, FRAME_MARKER_ORDER* frameMarker)
|
||||
{
|
||||
WLog_VRB(TAG, "not implemented");
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void gdi_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surface_frame_marker)
|
||||
void gdi_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surfaceFrameMarker)
|
||||
{
|
||||
DEBUG_GDI("frameId %d frameAction %d",
|
||||
surface_frame_marker->frameId,
|
||||
surface_frame_marker->frameAction);
|
||||
surfaceFrameMarker->frameId,
|
||||
surfaceFrameMarker->frameAction);
|
||||
|
||||
/* TODO: Implement frame marker completely */
|
||||
|
||||
switch (surface_frame_marker->frameAction)
|
||||
switch (surfaceFrameMarker->frameAction)
|
||||
{
|
||||
case SURFACECMD_FRAMEACTION_BEGIN:
|
||||
break;
|
||||
|
||||
case SURFACECMD_FRAMEACTION_END:
|
||||
if (context->instance->settings->FrameAcknowledge > 0)
|
||||
if (context->settings->FrameAcknowledge > 0)
|
||||
{
|
||||
IFCALL(context->instance->update->SurfaceFrameAcknowledge, context, surface_frame_marker->frameId);
|
||||
IFCALL(context->update->SurfaceFrameAcknowledge, context, surfaceFrameMarker->frameId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ if(FREERDP_VENDOR)
|
|||
|
||||
if(NOT WIN32)
|
||||
if(APPLE AND (NOT IOS))
|
||||
add_subdirectory(Mac)
|
||||
#add_subdirectory(Mac)
|
||||
endif()
|
||||
else()
|
||||
#add_subdirectory(Windows)
|
||||
|
|
|
@ -151,6 +151,8 @@ set(${MODULE_PREFIX}_SRCS
|
|||
shadow_encomsp.h
|
||||
shadow_remdesk.c
|
||||
shadow_remdesk.h
|
||||
shadow_subsystem.c
|
||||
shadow_subsystem.h
|
||||
shadow_server.c
|
||||
shadow.h)
|
||||
|
||||
|
@ -186,9 +188,7 @@ elseif(WITH_SHADOW_MAC)
|
|||
list(APPEND ${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_MAC_LIBS})
|
||||
endif()
|
||||
|
||||
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "freerdp-shadow")
|
||||
add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
list(APPEND ${MODULE_PREFIX}_LIBS freerdp)
|
||||
list(APPEND ${MODULE_PREFIX}_LIBS freerdp-server)
|
||||
|
@ -199,7 +199,25 @@ list(APPEND ${MODULE_PREFIX}_LIBS winpr-makecert-tool)
|
|||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT server)
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT server)
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Server/shadow")
|
||||
|
||||
# command-line executable
|
||||
|
||||
set(MODULE_NAME "freerdp-shadow-cli")
|
||||
set(MODULE_PREFIX "FREERDP_SERVER_SHADOW_CLI")
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
shadow.c)
|
||||
|
||||
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "freerdp-shadow")
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-shadow)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
install(TARGETS ${MODULE_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT server)
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Server/shadow")
|
||||
|
|
|
@ -25,7 +25,11 @@
|
|||
#include <freerdp/codec/region.h>
|
||||
|
||||
#include "../shadow_screen.h"
|
||||
#include "../shadow_client.h"
|
||||
#include "../shadow_surface.h"
|
||||
#include "../shadow_capture.h"
|
||||
#include "../shadow_encoder.h"
|
||||
#include "../shadow_subsystem.h"
|
||||
|
||||
#include "mac_shadow.h"
|
||||
|
||||
|
@ -54,27 +58,29 @@ void mac_shadow_input_keyboard_event(macShadowSubsystem* subsystem, UINT16 flags
|
|||
if (extended)
|
||||
vkcode |= KBDEXT;
|
||||
|
||||
keycode = GetKeycodeFromVirtualKeyCode(vkcode, KEYCODE_TYPE_APPLE) - 8;
|
||||
keycode = GetKeycodeFromVirtualKeyCode(vkcode, KEYCODE_TYPE_APPLE);
|
||||
|
||||
if (keycode)
|
||||
if (keycode < 8)
|
||||
return;
|
||||
|
||||
keycode -= 8;
|
||||
|
||||
source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
||||
|
||||
if (flags & KBD_FLAGS_DOWN)
|
||||
{
|
||||
source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
||||
|
||||
if (flags & KBD_FLAGS_DOWN)
|
||||
{
|
||||
kbdEvent = CGEventCreateKeyboardEvent(source, (CGKeyCode) keycode, TRUE);
|
||||
CGEventPost(kCGHIDEventTap, kbdEvent);
|
||||
CFRelease(kbdEvent);
|
||||
}
|
||||
else if (flags & KBD_FLAGS_RELEASE)
|
||||
{
|
||||
kbdEvent = CGEventCreateKeyboardEvent(source, (CGKeyCode) keycode, FALSE);
|
||||
CGEventPost(kCGHIDEventTap, kbdEvent);
|
||||
CFRelease(kbdEvent);
|
||||
}
|
||||
|
||||
CFRelease(source);
|
||||
kbdEvent = CGEventCreateKeyboardEvent(source, (CGKeyCode) keycode, TRUE);
|
||||
CGEventPost(kCGHIDEventTap, kbdEvent);
|
||||
CFRelease(kbdEvent);
|
||||
}
|
||||
else if (flags & KBD_FLAGS_RELEASE)
|
||||
{
|
||||
kbdEvent = CGEventCreateKeyboardEvent(source, (CGKeyCode) keycode, FALSE);
|
||||
CGEventPost(kCGHIDEventTap, kbdEvent);
|
||||
CFRelease(kbdEvent);
|
||||
}
|
||||
|
||||
CFRelease(source);
|
||||
}
|
||||
|
||||
void mac_shadow_input_unicode_keyboard_event(macShadowSubsystem* subsystem, UINT16 flags, UINT16 code)
|
||||
|
@ -222,7 +228,7 @@ int mac_shadow_detect_monitors(macShadowSubsystem* subsystem)
|
|||
subsystem->height = subsystem->pixelHeight;
|
||||
}
|
||||
|
||||
subsystem->monitorCount = 1;
|
||||
subsystem->numMonitors = 1;
|
||||
|
||||
monitor = &(subsystem->monitors[0]);
|
||||
|
||||
|
@ -259,7 +265,7 @@ int mac_shadow_capture_stop(macShadowSubsystem* subsystem)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int mac_shadow_capture_peek_dirty_region(macShadowSubsystem* subsystem)
|
||||
int mac_shadow_capture_get_dirty_region(macShadowSubsystem* subsystem)
|
||||
{
|
||||
size_t index;
|
||||
size_t numRects;
|
||||
|
@ -293,46 +299,6 @@ int mac_shadow_capture_peek_dirty_region(macShadowSubsystem* subsystem)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int mac_shadow_capture_get_dirty_region(macShadowSubsystem* subsystem)
|
||||
{
|
||||
dispatch_semaphore_wait(subsystem->regionSemaphore, DISPATCH_TIME_FOREVER);
|
||||
|
||||
if (subsystem->lastUpdate)
|
||||
{
|
||||
mac_shadow_capture_peek_dirty_region(subsystem);
|
||||
}
|
||||
|
||||
dispatch_semaphore_signal(subsystem->regionSemaphore);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mac_shadow_capture_clear_dirty_region(macShadowSubsystem* subsystem)
|
||||
{
|
||||
dispatch_semaphore_wait(subsystem->regionSemaphore, DISPATCH_TIME_FOREVER);
|
||||
|
||||
CFRelease(subsystem->lastUpdate);
|
||||
subsystem->lastUpdate = NULL;
|
||||
|
||||
dispatch_semaphore_signal(subsystem->regionSemaphore);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mac_shadow_capture_surface_copy(macShadowSubsystem* subsystem)
|
||||
{
|
||||
dispatch_semaphore_wait(subsystem->regionSemaphore, DISPATCH_TIME_FOREVER);
|
||||
subsystem->updateReady = TRUE;
|
||||
|
||||
dispatch_semaphore_wait(subsystem->dataSemaphore, DISPATCH_TIME_FOREVER);
|
||||
dispatch_semaphore_signal(subsystem->regionSemaphore);
|
||||
|
||||
dispatch_semaphore_wait(subsystem->dataSemaphore, DISPATCH_TIME_FOREVER);
|
||||
dispatch_semaphore_signal(subsystem->dataSemaphore);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void (^mac_capture_stream_handler)(CGDisplayStreamFrameStatus, uint64_t, IOSurfaceRef, CGDisplayStreamUpdateRef) =
|
||||
^(CGDisplayStreamFrameStatus status, uint64_t displayTime, IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef)
|
||||
{
|
||||
|
@ -348,78 +314,80 @@ void (^mac_capture_stream_handler)(CGDisplayStreamFrameStatus, uint64_t, IOSurfa
|
|||
rdpShadowServer* server = subsystem->server;
|
||||
rdpShadowSurface* surface = server->surface;
|
||||
|
||||
if (ArrayList_Count(server->clients) < 1)
|
||||
{
|
||||
region16_clear(&(subsystem->invalidRegion));
|
||||
count = ArrayList_Count(server->clients);
|
||||
|
||||
if (count < 1)
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch_semaphore_wait(subsystem->regionSemaphore, DISPATCH_TIME_FOREVER);
|
||||
|
||||
if (!subsystem->updateReady)
|
||||
{
|
||||
dispatch_semaphore_signal(subsystem->regionSemaphore);
|
||||
if ((count == 1) && subsystem->suppressOutput)
|
||||
return;
|
||||
}
|
||||
|
||||
mac_shadow_capture_peek_dirty_region(subsystem);
|
||||
mac_shadow_capture_get_dirty_region(subsystem);
|
||||
|
||||
surfaceRect.left = surface->x;
|
||||
surfaceRect.top = surface->y;
|
||||
surfaceRect.right = surface->x + surface->width;
|
||||
surfaceRect.bottom = surface->y + surface->height;
|
||||
surfaceRect.left = 0;
|
||||
surfaceRect.top = 0;
|
||||
surfaceRect.right = surface->width;
|
||||
surfaceRect.bottom = surface->height;
|
||||
|
||||
region16_intersect_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &surfaceRect);
|
||||
|
||||
if (region16_is_empty(&(subsystem->invalidRegion)))
|
||||
|
||||
if (!region16_is_empty(&(subsystem->invalidRegion)))
|
||||
{
|
||||
extents = region16_extents(&(subsystem->invalidRegion));
|
||||
|
||||
}
|
||||
x = extents->left;
|
||||
y = extents->top;
|
||||
width = extents->right - extents->left;
|
||||
height = extents->bottom - extents->top;
|
||||
|
||||
extents = region16_extents(&(subsystem->invalidRegion));
|
||||
IOSurfaceLock(frameSurface, kIOSurfaceLockReadOnly, NULL);
|
||||
|
||||
pSrcData = (BYTE*) IOSurfaceGetBaseAddress(frameSurface);
|
||||
nSrcStep = (int) IOSurfaceGetBytesPerRow(frameSurface);
|
||||
|
||||
x = extents->left;
|
||||
y = extents->top;
|
||||
width = extents->right - extents->left;
|
||||
height = extents->bottom - extents->top;
|
||||
if (subsystem->retina)
|
||||
{
|
||||
freerdp_image_copy_from_retina(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
|
||||
x, y, width, height, pSrcData, nSrcStep, x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
|
||||
x, y, width, height, pSrcData, PIXEL_FORMAT_XRGB32, nSrcStep, x, y, NULL);
|
||||
}
|
||||
|
||||
IOSurfaceLock(frameSurface, kIOSurfaceLockReadOnly, NULL);
|
||||
|
||||
pSrcData = (BYTE*) IOSurfaceGetBaseAddress(frameSurface);
|
||||
nSrcStep = (int) IOSurfaceGetBytesPerRow(frameSurface);
|
||||
|
||||
if (subsystem->retina)
|
||||
{
|
||||
freerdp_image_copy_from_retina(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
|
||||
x, y, width, height, pSrcData, nSrcStep, x, y);
|
||||
IOSurfaceUnlock(frameSurface, kIOSurfaceLockReadOnly, NULL);
|
||||
|
||||
ArrayList_Lock(server->clients);
|
||||
|
||||
count = ArrayList_Count(server->clients);
|
||||
|
||||
InitializeSynchronizationBarrier(&(subsystem->barrier), count + 1, -1);
|
||||
|
||||
SetEvent(subsystem->updateEvent);
|
||||
|
||||
EnterSynchronizationBarrier(&(subsystem->barrier), 0);
|
||||
|
||||
DeleteSynchronizationBarrier(&(subsystem->barrier));
|
||||
|
||||
if (count == 1)
|
||||
{
|
||||
rdpShadowClient* client;
|
||||
|
||||
client = (rdpShadowClient*) ArrayList_GetItem(server->clients, 0);
|
||||
|
||||
if (client)
|
||||
{
|
||||
subsystem->captureFrameRate = client->encoder->fps;
|
||||
}
|
||||
}
|
||||
|
||||
ResetEvent(subsystem->updateEvent);
|
||||
|
||||
ArrayList_Unlock(server->clients);
|
||||
|
||||
region16_clear(&(subsystem->invalidRegion));
|
||||
}
|
||||
else
|
||||
{
|
||||
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
|
||||
x, y, width, height, pSrcData, PIXEL_FORMAT_XRGB32, nSrcStep, x, y, NULL);
|
||||
}
|
||||
|
||||
IOSurfaceUnlock(frameSurface, kIOSurfaceLockReadOnly, NULL);
|
||||
|
||||
subsystem->updateReady = FALSE;
|
||||
dispatch_semaphore_signal(subsystem->dataSemaphore);
|
||||
|
||||
ArrayList_Lock(server->clients);
|
||||
|
||||
count = ArrayList_Count(server->clients);
|
||||
|
||||
InitializeSynchronizationBarrier(&(subsystem->barrier), count + 1, -1);
|
||||
|
||||
SetEvent(subsystem->updateEvent);
|
||||
|
||||
EnterSynchronizationBarrier(&(subsystem->barrier), 0);
|
||||
ResetEvent(subsystem->updateEvent);
|
||||
|
||||
DeleteSynchronizationBarrier(&(subsystem->barrier));
|
||||
|
||||
ArrayList_Unlock(server->clients);
|
||||
|
||||
region16_clear(&(subsystem->invalidRegion));
|
||||
|
||||
if (status != kCGDisplayStreamFrameStatusFrameComplete)
|
||||
{
|
||||
|
@ -449,8 +417,6 @@ void (^mac_capture_stream_handler)(CGDisplayStreamFrameStatus, uint64_t, IOSurfa
|
|||
subsystem->lastUpdate = CGDisplayStreamUpdateCreateMergedUpdate(tmpRef, updateRef);
|
||||
CFRelease(tmpRef);
|
||||
}
|
||||
|
||||
dispatch_semaphore_signal(subsystem->regionSemaphore);
|
||||
};
|
||||
|
||||
int mac_shadow_capture_init(macShadowSubsystem* subsystem)
|
||||
|
@ -462,11 +428,11 @@ int mac_shadow_capture_init(macShadowSubsystem* subsystem)
|
|||
|
||||
displayId = CGMainDisplayID();
|
||||
|
||||
subsystem->regionSemaphore = dispatch_semaphore_create(1);
|
||||
subsystem->dataSemaphore = dispatch_semaphore_create(1);
|
||||
|
||||
subsystem->updateBuffer = (BYTE*) malloc(subsystem->pixelWidth * subsystem->pixelHeight * 4);
|
||||
|
||||
if (!subsystem->updateBuffer)
|
||||
return -1;
|
||||
|
||||
subsystem->captureQueue = dispatch_queue_create("mac.shadow.capture", NULL);
|
||||
|
||||
keys[0] = (void*) kCGDisplayStreamShowCursor;
|
||||
|
@ -484,15 +450,58 @@ int mac_shadow_capture_init(macShadowSubsystem* subsystem)
|
|||
|
||||
int mac_shadow_screen_grab(macShadowSubsystem* subsystem)
|
||||
{
|
||||
mac_shadow_capture_get_dirty_region(subsystem);
|
||||
mac_shadow_capture_surface_copy(subsystem);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mac_shadow_subsystem_process_message(macShadowSubsystem* subsystem, wMessage* message)
|
||||
{
|
||||
if (message->id == SHADOW_MSG_IN_REFRESH_OUTPUT_ID)
|
||||
{
|
||||
UINT32 index;
|
||||
SHADOW_MSG_IN_REFRESH_OUTPUT* msg = (SHADOW_MSG_IN_REFRESH_OUTPUT*) message->wParam;
|
||||
|
||||
if (msg->numRects)
|
||||
{
|
||||
for (index = 0; index < msg->numRects; index++)
|
||||
{
|
||||
region16_union_rect(&(subsystem->invalidRegion),
|
||||
&(subsystem->invalidRegion), &msg->rects[index]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RECTANGLE_16 refreshRect;
|
||||
|
||||
refreshRect.left = 0;
|
||||
refreshRect.top = 0;
|
||||
refreshRect.right = subsystem->width;
|
||||
refreshRect.bottom = subsystem->height;
|
||||
|
||||
region16_union_rect(&(subsystem->invalidRegion),
|
||||
&(subsystem->invalidRegion), &refreshRect);
|
||||
}
|
||||
}
|
||||
else if (message->id == SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID)
|
||||
{
|
||||
SHADOW_MSG_IN_SUPPRESS_OUTPUT* msg = (SHADOW_MSG_IN_SUPPRESS_OUTPUT*) message->wParam;
|
||||
|
||||
subsystem->suppressOutput = (msg->allow) ? FALSE : TRUE;
|
||||
|
||||
if (msg->allow)
|
||||
{
|
||||
region16_union_rect(&(subsystem->invalidRegion),
|
||||
&(subsystem->invalidRegion), &(msg->rect));
|
||||
}
|
||||
}
|
||||
|
||||
if (message->Free)
|
||||
message->Free(message);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void* mac_shadow_subsystem_thread(macShadowSubsystem* subsystem)
|
||||
{
|
||||
int fps;
|
||||
DWORD status;
|
||||
DWORD nCount;
|
||||
UINT64 cTime;
|
||||
|
@ -500,15 +509,16 @@ void* mac_shadow_subsystem_thread(macShadowSubsystem* subsystem)
|
|||
DWORD dwInterval;
|
||||
UINT64 frameTime;
|
||||
HANDLE events[32];
|
||||
HANDLE StopEvent;
|
||||
wMessage message;
|
||||
wMessagePipe* MsgPipe;
|
||||
|
||||
StopEvent = subsystem->server->StopEvent;
|
||||
MsgPipe = subsystem->MsgPipe;
|
||||
|
||||
nCount = 0;
|
||||
events[nCount++] = StopEvent;
|
||||
events[nCount++] = MessageQueue_Event(MsgPipe->In);
|
||||
|
||||
fps = 16;
|
||||
dwInterval = 1000 / fps;
|
||||
subsystem->captureFrameRate = 16;
|
||||
dwInterval = 1000 / subsystem->captureFrameRate;
|
||||
frameTime = GetTickCount64() + dwInterval;
|
||||
|
||||
while (1)
|
||||
|
@ -518,16 +528,22 @@ void* mac_shadow_subsystem_thread(macShadowSubsystem* subsystem)
|
|||
|
||||
status = WaitForMultipleObjects(nCount, events, FALSE, dwTimeout);
|
||||
|
||||
if (WaitForSingleObject(StopEvent, 0) == WAIT_OBJECT_0)
|
||||
if (WaitForSingleObject(MessageQueue_Event(MsgPipe->In), 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
break;
|
||||
if (MessageQueue_Peek(MsgPipe->In, &message, TRUE))
|
||||
{
|
||||
if (message.id == WMQ_QUIT)
|
||||
break;
|
||||
|
||||
mac_shadow_subsystem_process_message(subsystem, &message);
|
||||
}
|
||||
}
|
||||
|
||||
if ((status == WAIT_TIMEOUT) || (GetTickCount64() > frameTime))
|
||||
{
|
||||
mac_shadow_screen_grab(subsystem);
|
||||
|
||||
dwInterval = 1000 / fps;
|
||||
dwInterval = 1000 / subsystem->captureFrameRate;
|
||||
frameTime += dwInterval;
|
||||
}
|
||||
}
|
||||
|
@ -536,6 +552,36 @@ void* mac_shadow_subsystem_thread(macShadowSubsystem* subsystem)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int mac_shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors)
|
||||
{
|
||||
int index;
|
||||
size_t wide, high;
|
||||
int numMonitors = 0;
|
||||
MONITOR_DEF* monitor;
|
||||
CGDirectDisplayID displayId;
|
||||
|
||||
displayId = CGMainDisplayID();
|
||||
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayId);
|
||||
|
||||
wide = CGDisplayPixelsWide(displayId);
|
||||
high = CGDisplayPixelsHigh(displayId);
|
||||
|
||||
CGDisplayModeRelease(mode);
|
||||
|
||||
index = 0;
|
||||
numMonitors = 1;
|
||||
|
||||
monitor = &monitors[index];
|
||||
|
||||
monitor->left = 0;
|
||||
monitor->top = 0;
|
||||
monitor->right = (int) wide;
|
||||
monitor->bottom = (int) high;
|
||||
monitor->flags = 1;
|
||||
|
||||
return numMonitors;
|
||||
}
|
||||
|
||||
int mac_shadow_subsystem_init(macShadowSubsystem* subsystem)
|
||||
{
|
||||
g_Subsystem = subsystem;
|
||||
|
@ -551,6 +597,12 @@ int mac_shadow_subsystem_uninit(macShadowSubsystem* subsystem)
|
|||
{
|
||||
if (!subsystem)
|
||||
return -1;
|
||||
|
||||
if (subsystem->lastUpdate)
|
||||
{
|
||||
CFRelease(subsystem->lastUpdate);
|
||||
subsystem->lastUpdate = NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -589,7 +641,7 @@ void mac_shadow_subsystem_free(macShadowSubsystem* subsystem)
|
|||
free(subsystem);
|
||||
}
|
||||
|
||||
macShadowSubsystem* mac_shadow_subsystem_new(rdpShadowServer* server)
|
||||
macShadowSubsystem* mac_shadow_subsystem_new()
|
||||
{
|
||||
macShadowSubsystem* subsystem;
|
||||
|
||||
|
@ -598,18 +650,6 @@ macShadowSubsystem* mac_shadow_subsystem_new(rdpShadowServer* server)
|
|||
if (!subsystem)
|
||||
return NULL;
|
||||
|
||||
subsystem->server = server;
|
||||
|
||||
subsystem->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
region16_init(&(subsystem->invalidRegion));
|
||||
|
||||
subsystem->Init = (pfnShadowSubsystemInit) mac_shadow_subsystem_init;
|
||||
subsystem->Uninit = (pfnShadowSubsystemInit) mac_shadow_subsystem_uninit;
|
||||
subsystem->Start = (pfnShadowSubsystemStart) mac_shadow_subsystem_start;
|
||||
subsystem->Stop = (pfnShadowSubsystemStop) mac_shadow_subsystem_stop;
|
||||
subsystem->Free = (pfnShadowSubsystemFree) mac_shadow_subsystem_free;
|
||||
|
||||
subsystem->SynchronizeEvent = (pfnShadowSynchronizeEvent) mac_shadow_input_synchronize_event;
|
||||
subsystem->KeyboardEvent = (pfnShadowKeyboardEvent) mac_shadow_input_keyboard_event;
|
||||
subsystem->UnicodeKeyboardEvent = (pfnShadowUnicodeKeyboardEvent) mac_shadow_input_unicode_keyboard_event;
|
||||
|
@ -619,7 +659,18 @@ macShadowSubsystem* mac_shadow_subsystem_new(rdpShadowServer* server)
|
|||
return subsystem;
|
||||
}
|
||||
|
||||
rdpShadowSubsystem* Mac_ShadowCreateSubsystem(rdpShadowServer* server)
|
||||
int Mac_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints)
|
||||
{
|
||||
return (rdpShadowSubsystem*) mac_shadow_subsystem_new(server);
|
||||
pEntryPoints->New = (pfnShadowSubsystemNew) mac_shadow_subsystem_new;
|
||||
pEntryPoints->Free = (pfnShadowSubsystemFree) mac_shadow_subsystem_free;
|
||||
|
||||
pEntryPoints->Init = (pfnShadowSubsystemInit) mac_shadow_subsystem_init;
|
||||
pEntryPoints->Uninit = (pfnShadowSubsystemInit) mac_shadow_subsystem_uninit;
|
||||
|
||||
pEntryPoints->Start = (pfnShadowSubsystemStart) mac_shadow_subsystem_start;
|
||||
pEntryPoints->Stop = (pfnShadowSubsystemStop) mac_shadow_subsystem_stop;
|
||||
|
||||
pEntryPoints->EnumMonitors = (pfnShadowEnumMonitors) mac_shadow_enum_monitors;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -47,12 +47,9 @@ struct mac_shadow_subsystem
|
|||
BOOL mouseDownLeft;
|
||||
BOOL mouseDownRight;
|
||||
BOOL mouseDownOther;
|
||||
BOOL updateReady;
|
||||
BYTE* updateBuffer;
|
||||
CGDisplayStreamRef stream;
|
||||
dispatch_queue_t captureQueue;
|
||||
dispatch_semaphore_t dataSemaphore;
|
||||
dispatch_semaphore_t regionSemaphore;
|
||||
CGDisplayStreamUpdateRef lastUpdate;
|
||||
};
|
||||
|
||||
|
|
|
@ -20,13 +20,14 @@
|
|||
#include <winpr/synch.h>
|
||||
#include <winpr/sysinfo.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/codec/region.h>
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#include "../shadow_screen.h"
|
||||
#include "../shadow_surface.h"
|
||||
#include "../shadow_capture.h"
|
||||
#include "../shadow_subsystem.h"
|
||||
|
||||
#include "win_shadow.h"
|
||||
|
||||
|
@ -398,27 +399,51 @@ void* win_shadow_subsystem_thread(winShadowSubsystem* subsystem)
|
|||
|
||||
#endif
|
||||
|
||||
int win_shadow_subsystem_init(winShadowSubsystem* subsystem)
|
||||
int win_shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors)
|
||||
{
|
||||
HDC hdc;
|
||||
int status;
|
||||
int index;
|
||||
int desktopWidth;
|
||||
int desktopHeight;
|
||||
DWORD iDevNum = 0;
|
||||
int numMonitors = 0;
|
||||
MONITOR_DEF* monitor;
|
||||
MONITOR_DEF* virtualScreen;
|
||||
DISPLAY_DEVICE DisplayDevice;
|
||||
DISPLAY_DEVICE displayDevice;
|
||||
|
||||
ZeroMemory(&DisplayDevice, sizeof(DISPLAY_DEVICE));
|
||||
DisplayDevice.cb = sizeof(DISPLAY_DEVICE);
|
||||
ZeroMemory(&displayDevice, sizeof(DISPLAY_DEVICE));
|
||||
displayDevice.cb = sizeof(DISPLAY_DEVICE);
|
||||
|
||||
if (!EnumDisplayDevices(NULL, iDevNum, &DisplayDevice, 0))
|
||||
return -1;
|
||||
if (EnumDisplayDevices(NULL, iDevNum, &displayDevice, 0))
|
||||
{
|
||||
hdc = CreateDC(displayDevice.DeviceName, NULL, NULL, NULL);
|
||||
|
||||
hdc = CreateDC(DisplayDevice.DeviceName, NULL, NULL, NULL);
|
||||
desktopWidth = GetDeviceCaps(hdc, HORZRES);
|
||||
desktopHeight = GetDeviceCaps(hdc, VERTRES);
|
||||
|
||||
subsystem->width = GetDeviceCaps(hdc, HORZRES);
|
||||
subsystem->height = GetDeviceCaps(hdc, VERTRES);
|
||||
subsystem->bpp = GetDeviceCaps(hdc, BITSPIXEL);
|
||||
index = 0;
|
||||
numMonitors = 1;
|
||||
|
||||
DeleteDC(hdc);
|
||||
monitor = &monitors[index];
|
||||
|
||||
monitor->left = 0;
|
||||
monitor->top = 0;
|
||||
monitor->right = desktopWidth;
|
||||
monitor->bottom = desktopHeight;
|
||||
monitor->flags = 1;
|
||||
|
||||
DeleteDC(hdc);
|
||||
}
|
||||
|
||||
return numMonitors;
|
||||
}
|
||||
|
||||
int win_shadow_subsystem_init(winShadowSubsystem* subsystem)
|
||||
{
|
||||
int status;
|
||||
MONITOR_DEF* virtualScreen;
|
||||
|
||||
subsystem->numMonitors = win_shadow_enum_monitors(subsystem->monitors, 16);
|
||||
|
||||
#if defined(WITH_WDS_API)
|
||||
status = win_shadow_wds_init(subsystem);
|
||||
|
@ -434,16 +459,6 @@ int win_shadow_subsystem_init(winShadowSubsystem* subsystem)
|
|||
virtualScreen->bottom = subsystem->height;
|
||||
virtualScreen->flags = 1;
|
||||
|
||||
if (subsystem->monitorCount < 1)
|
||||
{
|
||||
subsystem->monitorCount = 1;
|
||||
subsystem->monitors[0].left = virtualScreen->left;
|
||||
subsystem->monitors[0].top = virtualScreen->top;
|
||||
subsystem->monitors[0].right = virtualScreen->right;
|
||||
subsystem->monitors[0].bottom = virtualScreen->bottom;
|
||||
subsystem->monitors[0].flags = 1;
|
||||
}
|
||||
|
||||
WLog_INFO(TAG, "width: %d height: %d", subsystem->width, subsystem->height);
|
||||
|
||||
return 1;
|
||||
|
@ -492,14 +507,10 @@ void win_shadow_subsystem_free(winShadowSubsystem* subsystem)
|
|||
|
||||
win_shadow_subsystem_uninit(subsystem);
|
||||
|
||||
region16_uninit(&(subsystem->invalidRegion));
|
||||
|
||||
CloseHandle(subsystem->updateEvent);
|
||||
|
||||
free(subsystem);
|
||||
}
|
||||
|
||||
winShadowSubsystem* win_shadow_subsystem_new(rdpShadowServer* server)
|
||||
winShadowSubsystem* win_shadow_subsystem_new()
|
||||
{
|
||||
winShadowSubsystem* subsystem;
|
||||
|
||||
|
@ -508,20 +519,6 @@ winShadowSubsystem* win_shadow_subsystem_new(rdpShadowServer* server)
|
|||
if (!subsystem)
|
||||
return NULL;
|
||||
|
||||
subsystem->server = server;
|
||||
|
||||
subsystem->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
region16_init(&(subsystem->invalidRegion));
|
||||
|
||||
subsystem->Init = (pfnShadowSubsystemInit) win_shadow_subsystem_init;
|
||||
subsystem->Uninit = (pfnShadowSubsystemInit) win_shadow_subsystem_uninit;
|
||||
subsystem->Start = (pfnShadowSubsystemStart) win_shadow_subsystem_start;
|
||||
subsystem->Stop = (pfnShadowSubsystemStop) win_shadow_subsystem_stop;
|
||||
subsystem->Free = (pfnShadowSubsystemFree) win_shadow_subsystem_free;
|
||||
|
||||
subsystem->SurfaceCopy = (pfnShadowSurfaceCopy) win_shadow_surface_copy;
|
||||
|
||||
subsystem->SynchronizeEvent = (pfnShadowSynchronizeEvent) win_shadow_input_synchronize_event;
|
||||
subsystem->KeyboardEvent = (pfnShadowKeyboardEvent) win_shadow_input_keyboard_event;
|
||||
subsystem->UnicodeKeyboardEvent = (pfnShadowUnicodeKeyboardEvent) win_shadow_input_unicode_keyboard_event;
|
||||
|
@ -531,7 +528,18 @@ winShadowSubsystem* win_shadow_subsystem_new(rdpShadowServer* server)
|
|||
return subsystem;
|
||||
}
|
||||
|
||||
rdpShadowSubsystem* Win_ShadowCreateSubsystem(rdpShadowServer* server)
|
||||
int Win_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints)
|
||||
{
|
||||
return (rdpShadowSubsystem*) win_shadow_subsystem_new(server);
|
||||
pEntryPoints->New = (pfnShadowSubsystemNew) win_shadow_subsystem_new;
|
||||
pEntryPoints->Free = (pfnShadowSubsystemFree) win_shadow_subsystem_free;
|
||||
|
||||
pEntryPoints->Init = (pfnShadowSubsystemInit) win_shadow_subsystem_init;
|
||||
pEntryPoints->Uninit = (pfnShadowSubsystemInit) win_shadow_subsystem_uninit;
|
||||
|
||||
pEntryPoints->Start = (pfnShadowSubsystemStart) win_shadow_subsystem_start;
|
||||
pEntryPoints->Stop = (pfnShadowSubsystemStop) win_shadow_subsystem_stop;
|
||||
|
||||
pEntryPoints->EnumMonitors = (pfnShadowEnumMonitors) win_shadow_enum_monitors;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -35,13 +35,16 @@
|
|||
#include <winpr/image.h>
|
||||
#include <winpr/sysinfo.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/codec/region.h>
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#include "../shadow_screen.h"
|
||||
#include "../shadow_client.h"
|
||||
#include "../shadow_encoder.h"
|
||||
#include "../shadow_capture.h"
|
||||
#include "../shadow_surface.h"
|
||||
#include "../shadow_subsystem.h"
|
||||
|
||||
#include "x11_shadow.h"
|
||||
|
||||
|
@ -136,7 +139,7 @@ void x11_shadow_input_mouse_event(x11ShadowSubsystem* subsystem, UINT16 flags, U
|
|||
if (flags & PTR_FLAGS_DOWN)
|
||||
down = TRUE;
|
||||
|
||||
if (button != 0)
|
||||
if (button)
|
||||
XTestFakeButtonEvent(subsystem->display, button, down, 0);
|
||||
}
|
||||
|
||||
|
@ -165,6 +168,7 @@ void x11_shadow_input_extended_mouse_event(x11ShadowSubsystem* subsystem, UINT16
|
|||
}
|
||||
|
||||
XTestGrabControl(subsystem->display, True);
|
||||
|
||||
XTestFakeMotionEvent(subsystem->display, 0, x, y, CurrentTime);
|
||||
|
||||
if (flags & PTR_XFLAGS_BUTTON1)
|
||||
|
@ -175,7 +179,7 @@ void x11_shadow_input_extended_mouse_event(x11ShadowSubsystem* subsystem, UINT16
|
|||
if (flags & PTR_XFLAGS_DOWN)
|
||||
down = TRUE;
|
||||
|
||||
if (button != 0)
|
||||
if (button)
|
||||
XTestFakeButtonEvent(subsystem->display, button, down, 0);
|
||||
|
||||
XTestGrabControl(subsystem->display, False);
|
||||
|
@ -286,23 +290,6 @@ void x11_shadow_validate_region(x11ShadowSubsystem* subsystem, int x, int y, int
|
|||
#endif
|
||||
}
|
||||
|
||||
int x11_shadow_invalidate_region(x11ShadowSubsystem* subsystem, int x, int y, int width, int height)
|
||||
{
|
||||
rdpShadowServer* server;
|
||||
RECTANGLE_16 invalidRect;
|
||||
|
||||
server = subsystem->server;
|
||||
|
||||
invalidRect.left = x;
|
||||
invalidRect.top = y;
|
||||
invalidRect.right = x + width;
|
||||
invalidRect.bottom = y + height;
|
||||
|
||||
region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x11_shadow_blend_cursor(x11ShadowSubsystem* subsystem)
|
||||
{
|
||||
int x, y;
|
||||
|
@ -429,6 +416,8 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
|
|||
rdpShadowServer* server;
|
||||
rdpShadowSurface* surface;
|
||||
RECTANGLE_16 invalidRect;
|
||||
RECTANGLE_16 surfaceRect;
|
||||
const RECTANGLE_16 *extents;
|
||||
|
||||
server = subsystem->server;
|
||||
surface = server->surface;
|
||||
|
@ -439,105 +428,140 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
|
|||
if (count < 1)
|
||||
return 1;
|
||||
|
||||
if ((count == 1) && subsystem->suppressOutput)
|
||||
return 1;
|
||||
|
||||
surfaceRect.left = 0;
|
||||
surfaceRect.top = 0;
|
||||
surfaceRect.right = surface->width;
|
||||
surfaceRect.bottom = surface->height;
|
||||
|
||||
XLockDisplay(subsystem->display);
|
||||
|
||||
if (subsystem->use_xshm)
|
||||
{
|
||||
XLockDisplay(subsystem->display);
|
||||
image = subsystem->fb_image;
|
||||
|
||||
XCopyArea(subsystem->display, subsystem->root_window, subsystem->fb_pixmap,
|
||||
subsystem->xshm_gc, 0, 0, subsystem->width, subsystem->height, 0, 0);
|
||||
|
||||
XSync(subsystem->display, False);
|
||||
|
||||
XUnlockDisplay(subsystem->display);
|
||||
|
||||
image = subsystem->fb_image;
|
||||
|
||||
status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height,
|
||||
(BYTE*) &(image->data[surface->width * 4]), image->bytes_per_line, &invalidRect);
|
||||
|
||||
if (status > 0)
|
||||
{
|
||||
x = invalidRect.left;
|
||||
y = invalidRect.top;
|
||||
width = invalidRect.right - invalidRect.left;
|
||||
height = invalidRect.bottom - invalidRect.top;
|
||||
|
||||
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32,
|
||||
surface->scanline, x - surface->x, y - surface->y, width, height,
|
||||
(BYTE*) image->data, PIXEL_FORMAT_XRGB32,
|
||||
image->bytes_per_line, x, y, NULL);
|
||||
|
||||
region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect);
|
||||
|
||||
x11_shadow_blend_cursor(subsystem);
|
||||
|
||||
count = ArrayList_Count(server->clients);
|
||||
|
||||
InitializeSynchronizationBarrier(&(subsystem->barrier), count + 1, -1);
|
||||
|
||||
SetEvent(subsystem->updateEvent);
|
||||
|
||||
EnterSynchronizationBarrier(&(subsystem->barrier), 0);
|
||||
|
||||
DeleteSynchronizationBarrier(&(subsystem->barrier));
|
||||
|
||||
ResetEvent(subsystem->updateEvent);
|
||||
|
||||
region16_clear(&(subsystem->invalidRegion));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
XLockDisplay(subsystem->display);
|
||||
|
||||
image = XGetImage(subsystem->display, subsystem->root_window,
|
||||
surface->x, surface->y, surface->width, surface->height, AllPlanes, ZPixmap);
|
||||
|
||||
XUnlockDisplay(subsystem->display);
|
||||
surface->x, surface->y, surface->width, surface->height, AllPlanes, ZPixmap);
|
||||
|
||||
status = shadow_capture_compare(surface->data, surface->scanline, surface->width, surface->height,
|
||||
(BYTE*) image->data, image->bytes_per_line, &invalidRect);
|
||||
}
|
||||
|
||||
if (status > 0)
|
||||
XSync(subsystem->display, False);
|
||||
|
||||
XUnlockDisplay(subsystem->display);
|
||||
|
||||
region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect);
|
||||
region16_intersect_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &surfaceRect);
|
||||
|
||||
if (!region16_is_empty(&(subsystem->invalidRegion)))
|
||||
{
|
||||
extents = region16_extents(&(subsystem->invalidRegion));
|
||||
|
||||
x = extents->left;
|
||||
y = extents->top;
|
||||
width = extents->right - extents->left;
|
||||
height = extents->bottom - extents->top;
|
||||
|
||||
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32,
|
||||
surface->scanline, x, y, width, height,
|
||||
(BYTE*) image->data, PIXEL_FORMAT_XRGB32,
|
||||
image->bytes_per_line, x, y, NULL);
|
||||
|
||||
x11_shadow_blend_cursor(subsystem);
|
||||
|
||||
count = ArrayList_Count(server->clients);
|
||||
|
||||
InitializeSynchronizationBarrier(&(subsystem->barrier), count + 1, -1);
|
||||
|
||||
SetEvent(subsystem->updateEvent);
|
||||
|
||||
EnterSynchronizationBarrier(&(subsystem->barrier), 0);
|
||||
|
||||
DeleteSynchronizationBarrier(&(subsystem->barrier));
|
||||
|
||||
if (count == 1)
|
||||
{
|
||||
x = invalidRect.left;
|
||||
y = invalidRect.top;
|
||||
width = invalidRect.right - invalidRect.left;
|
||||
height = invalidRect.bottom - invalidRect.top;
|
||||
rdpShadowClient* client;
|
||||
|
||||
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32,
|
||||
surface->scanline, x, y, width, height,
|
||||
(BYTE*) image->data, PIXEL_FORMAT_XRGB32,
|
||||
image->bytes_per_line, x, y, NULL);
|
||||
client = (rdpShadowClient*) ArrayList_GetItem(server->clients, 0);
|
||||
|
||||
region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect);
|
||||
|
||||
x11_shadow_blend_cursor(subsystem);
|
||||
|
||||
count = ArrayList_Count(server->clients);
|
||||
|
||||
InitializeSynchronizationBarrier(&(subsystem->barrier), count + 1, -1);
|
||||
|
||||
SetEvent(subsystem->updateEvent);
|
||||
|
||||
EnterSynchronizationBarrier(&(subsystem->barrier), 0);
|
||||
|
||||
DeleteSynchronizationBarrier(&(subsystem->barrier));
|
||||
|
||||
ResetEvent(subsystem->updateEvent);
|
||||
|
||||
region16_clear(&(subsystem->invalidRegion));
|
||||
if (client)
|
||||
{
|
||||
subsystem->captureFrameRate = client->encoder->fps;
|
||||
}
|
||||
}
|
||||
|
||||
XDestroyImage(image);
|
||||
ResetEvent(subsystem->updateEvent);
|
||||
|
||||
region16_clear(&(subsystem->invalidRegion));
|
||||
}
|
||||
|
||||
if (!subsystem->use_xshm)
|
||||
XDestroyImage(image);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x11_shadow_subsystem_process_message(x11ShadowSubsystem* subsystem, wMessage* message)
|
||||
{
|
||||
if (message->id == SHADOW_MSG_IN_REFRESH_OUTPUT_ID)
|
||||
{
|
||||
UINT32 index;
|
||||
SHADOW_MSG_IN_REFRESH_OUTPUT* msg = (SHADOW_MSG_IN_REFRESH_OUTPUT*) message->wParam;
|
||||
|
||||
if (msg->numRects)
|
||||
{
|
||||
for (index = 0; index < msg->numRects; index++)
|
||||
{
|
||||
region16_union_rect(&(subsystem->invalidRegion),
|
||||
&(subsystem->invalidRegion), &msg->rects[index]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RECTANGLE_16 refreshRect;
|
||||
|
||||
refreshRect.left = 0;
|
||||
refreshRect.top = 0;
|
||||
refreshRect.right = subsystem->width;
|
||||
refreshRect.bottom = subsystem->height;
|
||||
|
||||
region16_union_rect(&(subsystem->invalidRegion),
|
||||
&(subsystem->invalidRegion), &refreshRect);
|
||||
}
|
||||
}
|
||||
else if (message->id == SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID)
|
||||
{
|
||||
SHADOW_MSG_IN_SUPPRESS_OUTPUT* msg = (SHADOW_MSG_IN_SUPPRESS_OUTPUT*) message->wParam;
|
||||
|
||||
subsystem->suppressOutput = (msg->allow) ? FALSE : TRUE;
|
||||
|
||||
if (msg->allow)
|
||||
{
|
||||
region16_union_rect(&(subsystem->invalidRegion),
|
||||
&(subsystem->invalidRegion), &(msg->rect));
|
||||
}
|
||||
}
|
||||
|
||||
if (message->Free)
|
||||
message->Free(message);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem)
|
||||
{
|
||||
int fps;
|
||||
XEvent xevent;
|
||||
DWORD status;
|
||||
DWORD nCount;
|
||||
|
@ -546,16 +570,17 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem)
|
|||
DWORD dwInterval;
|
||||
UINT64 frameTime;
|
||||
HANDLE events[32];
|
||||
HANDLE StopEvent;
|
||||
wMessage message;
|
||||
wMessagePipe* MsgPipe;
|
||||
|
||||
StopEvent = subsystem->server->StopEvent;
|
||||
MsgPipe = subsystem->MsgPipe;
|
||||
|
||||
nCount = 0;
|
||||
events[nCount++] = StopEvent;
|
||||
events[nCount++] = subsystem->event;
|
||||
events[nCount++] = MessageQueue_Event(MsgPipe->In);
|
||||
|
||||
fps = 16;
|
||||
dwInterval = 1000 / fps;
|
||||
subsystem->captureFrameRate = 16;
|
||||
dwInterval = 1000 / subsystem->captureFrameRate;
|
||||
frameTime = GetTickCount64() + dwInterval;
|
||||
|
||||
while (1)
|
||||
|
@ -565,15 +590,24 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem)
|
|||
|
||||
status = WaitForMultipleObjects(nCount, events, FALSE, dwTimeout);
|
||||
|
||||
if (WaitForSingleObject(StopEvent, 0) == WAIT_OBJECT_0)
|
||||
if (WaitForSingleObject(MessageQueue_Event(MsgPipe->In), 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
break;
|
||||
if (MessageQueue_Peek(MsgPipe->In, &message, TRUE))
|
||||
{
|
||||
if (message.id == WMQ_QUIT)
|
||||
break;
|
||||
|
||||
x11_shadow_subsystem_process_message(subsystem, &message);
|
||||
}
|
||||
}
|
||||
|
||||
if (WaitForSingleObject(subsystem->event, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
XNextEvent(subsystem->display, &xevent);
|
||||
x11_shadow_handle_xevent(subsystem, &xevent);
|
||||
if (XEventsQueued(subsystem->display, QueuedAlready))
|
||||
{
|
||||
XNextEvent(subsystem->display, &xevent);
|
||||
x11_shadow_handle_xevent(subsystem, &xevent);
|
||||
}
|
||||
}
|
||||
|
||||
if ((status == WAIT_TIMEOUT) || (GetTickCount64() > frameTime))
|
||||
|
@ -581,7 +615,7 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem)
|
|||
x11_shadow_query_cursor(subsystem, FALSE);
|
||||
x11_shadow_screen_grab(subsystem);
|
||||
|
||||
dwInterval = 1000 / fps;
|
||||
dwInterval = 1000 / subsystem->captureFrameRate;
|
||||
frameTime += dwInterval;
|
||||
}
|
||||
}
|
||||
|
@ -590,6 +624,36 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int x11_shadow_subsystem_base_init(x11ShadowSubsystem* subsystem)
|
||||
{
|
||||
if (subsystem->display)
|
||||
return 1; /* initialize once */
|
||||
|
||||
if (!getenv("DISPLAY"))
|
||||
setenv("DISPLAY", ":0", 1);
|
||||
|
||||
if (!XInitThreads())
|
||||
return -1;
|
||||
|
||||
subsystem->display = XOpenDisplay(NULL);
|
||||
|
||||
if (!subsystem->display)
|
||||
{
|
||||
WLog_ERR(TAG, "failed to open display: %s", XDisplayName(NULL));
|
||||
return -1;
|
||||
}
|
||||
|
||||
subsystem->xfds = ConnectionNumber(subsystem->display);
|
||||
subsystem->number = DefaultScreen(subsystem->display);
|
||||
subsystem->screen = ScreenOfDisplay(subsystem->display, subsystem->number);
|
||||
subsystem->depth = DefaultDepthOfScreen(subsystem->screen);
|
||||
subsystem->width = WidthOfScreen(subsystem->screen);
|
||||
subsystem->height = HeightOfScreen(subsystem->screen);
|
||||
subsystem->root_window = DefaultRootWindow(subsystem->display);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x11_shadow_xfixes_init(x11ShadowSubsystem* subsystem)
|
||||
{
|
||||
#ifdef WITH_XFIXES
|
||||
|
@ -616,14 +680,11 @@ int x11_shadow_xfixes_init(x11ShadowSubsystem* subsystem)
|
|||
int x11_shadow_xinerama_init(x11ShadowSubsystem* subsystem)
|
||||
{
|
||||
#ifdef WITH_XINERAMA
|
||||
int index;
|
||||
int numMonitors;
|
||||
int major, minor;
|
||||
int xinerama_event;
|
||||
int xinerama_error;
|
||||
MONITOR_DEF* monitor;
|
||||
XineramaScreenInfo* screen;
|
||||
XineramaScreenInfo* screens;
|
||||
|
||||
x11_shadow_subsystem_base_init(subsystem);
|
||||
|
||||
if (!XineramaQueryExtension(subsystem->display, &xinerama_event, &xinerama_error))
|
||||
return -1;
|
||||
|
@ -634,32 +695,10 @@ int x11_shadow_xinerama_init(x11ShadowSubsystem* subsystem)
|
|||
if (!XineramaIsActive(subsystem->display))
|
||||
return -1;
|
||||
|
||||
screens = XineramaQueryScreens(subsystem->display, &numMonitors);
|
||||
|
||||
if (numMonitors > 16)
|
||||
numMonitors = 16;
|
||||
|
||||
if (!screens || (numMonitors < 1))
|
||||
return -1;
|
||||
|
||||
subsystem->monitorCount = numMonitors;
|
||||
|
||||
for (index = 0; index < numMonitors; index++)
|
||||
{
|
||||
screen = &screens[index];
|
||||
monitor = &(subsystem->monitors[index]);
|
||||
|
||||
monitor->left = screen->x_org;
|
||||
monitor->top = screen->y_org;
|
||||
monitor->right = monitor->left + screen->width;
|
||||
monitor->bottom = monitor->top + screen->height;
|
||||
monitor->flags = (index == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
XFree(screens);
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int x11_shadow_xdamage_init(x11ShadowSubsystem* subsystem)
|
||||
|
@ -774,6 +813,82 @@ int x11_shadow_xshm_init(x11ShadowSubsystem* subsystem)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int x11_shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors)
|
||||
{
|
||||
int index;
|
||||
Display* display;
|
||||
int displayWidth;
|
||||
int displayHeight;
|
||||
int numMonitors = 0;
|
||||
MONITOR_DEF* monitor;
|
||||
|
||||
if (!getenv("DISPLAY"))
|
||||
setenv("DISPLAY", ":0", 1);
|
||||
|
||||
display = XOpenDisplay(NULL);
|
||||
|
||||
if (!display)
|
||||
{
|
||||
WLog_ERR(TAG, "failed to open display: %s", XDisplayName(NULL));
|
||||
return -1;
|
||||
}
|
||||
|
||||
displayWidth = WidthOfScreen(DefaultScreenOfDisplay(display));
|
||||
displayHeight = HeightOfScreen(DefaultScreenOfDisplay(display));
|
||||
|
||||
#ifdef WITH_XINERAMA
|
||||
{
|
||||
int major, minor;
|
||||
int xinerama_event;
|
||||
int xinerama_error;
|
||||
XineramaScreenInfo* screen;
|
||||
XineramaScreenInfo* screens;
|
||||
|
||||
if (XineramaQueryExtension(display, &xinerama_event, &xinerama_error) &&
|
||||
XDamageQueryVersion(display, &major, &minor) && XineramaIsActive(display))
|
||||
{
|
||||
screens = XineramaQueryScreens(display, &numMonitors);
|
||||
|
||||
if (numMonitors > maxMonitors)
|
||||
numMonitors = maxMonitors;
|
||||
|
||||
if (screens && (numMonitors > 0))
|
||||
{
|
||||
for (index = 0; index < numMonitors; index++)
|
||||
{
|
||||
screen = &screens[index];
|
||||
monitor = &monitors[index];
|
||||
|
||||
monitor->left = screen->x_org;
|
||||
monitor->top = screen->y_org;
|
||||
monitor->right = monitor->left + screen->width;
|
||||
monitor->bottom = monitor->top + screen->height;
|
||||
monitor->flags = (index == 0) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
XFree(screens);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (numMonitors < 1)
|
||||
{
|
||||
index = 0;
|
||||
numMonitors = 1;
|
||||
|
||||
monitor = &monitors[index];
|
||||
|
||||
monitor->left = 0;
|
||||
monitor->top = 0;
|
||||
monitor->right = displayWidth;
|
||||
monitor->bottom = displayHeight;
|
||||
monitor->flags = 1;
|
||||
}
|
||||
|
||||
return numMonitors;
|
||||
}
|
||||
|
||||
int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem)
|
||||
{
|
||||
int i;
|
||||
|
@ -788,25 +903,13 @@ int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem)
|
|||
XPixmapFormatValues* pfs;
|
||||
MONITOR_DEF* virtualScreen;
|
||||
|
||||
/**
|
||||
* To see if your X11 server supports shared pixmaps, use:
|
||||
* xdpyinfo -ext MIT-SHM | grep "shared pixmaps"
|
||||
*/
|
||||
subsystem->numMonitors = x11_shadow_enum_monitors(subsystem->monitors, 16);
|
||||
|
||||
if (!getenv("DISPLAY"))
|
||||
x11_shadow_subsystem_base_init(subsystem);
|
||||
|
||||
if ((subsystem->depth != 24) && (subsystem->depth != 32))
|
||||
{
|
||||
/* Set DISPLAY variable if not already set */
|
||||
setenv("DISPLAY", ":0", 1);
|
||||
}
|
||||
|
||||
if (!XInitThreads())
|
||||
return -1;
|
||||
|
||||
subsystem->display = XOpenDisplay(NULL);
|
||||
|
||||
if (!subsystem->display)
|
||||
{
|
||||
WLog_ERR(TAG, "failed to open display: %s", XDisplayName(NULL));
|
||||
fprintf(stderr, "x11_shadow_subsystem_init: unsupported X11 server color depth: %d\n", subsystem->depth);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -826,14 +929,6 @@ int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem)
|
|||
if (subsystem->composite)
|
||||
subsystem->use_xdamage = FALSE;
|
||||
|
||||
subsystem->xfds = ConnectionNumber(subsystem->display);
|
||||
subsystem->number = DefaultScreen(subsystem->display);
|
||||
subsystem->screen = ScreenOfDisplay(subsystem->display, subsystem->number);
|
||||
subsystem->depth = DefaultDepthOfScreen(subsystem->screen);
|
||||
subsystem->width = WidthOfScreen(subsystem->screen);
|
||||
subsystem->height = HeightOfScreen(subsystem->screen);
|
||||
subsystem->root_window = DefaultRootWindow(subsystem->display);
|
||||
|
||||
pfs = XListPixmapFormats(subsystem->display, &pf_count);
|
||||
|
||||
if (!pfs)
|
||||
|
@ -924,16 +1019,6 @@ int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem)
|
|||
virtualScreen->bottom = subsystem->height;
|
||||
virtualScreen->flags = 1;
|
||||
|
||||
if (subsystem->monitorCount < 1)
|
||||
{
|
||||
subsystem->monitorCount = 1;
|
||||
subsystem->monitors[0].left = virtualScreen->left;
|
||||
subsystem->monitors[0].top = virtualScreen->top;
|
||||
subsystem->monitors[0].right = virtualScreen->right;
|
||||
subsystem->monitors[0].bottom = virtualScreen->bottom;
|
||||
subsystem->monitors[0].flags = 1;
|
||||
}
|
||||
|
||||
WLog_INFO(TAG, "X11 Extensions: XFixes: %d Xinerama: %d XDamage: %d XShm: %d",
|
||||
subsystem->use_xfixes, subsystem->use_xinerama, subsystem->use_xdamage, subsystem->use_xshm);
|
||||
|
||||
|
@ -968,12 +1053,10 @@ int x11_shadow_subsystem_uninit(x11ShadowSubsystem* subsystem)
|
|||
|
||||
int x11_shadow_subsystem_start(x11ShadowSubsystem* subsystem)
|
||||
{
|
||||
HANDLE thread;
|
||||
|
||||
if (!subsystem)
|
||||
return -1;
|
||||
|
||||
thread = CreateThread(NULL, 0,
|
||||
subsystem->thread = CreateThread(NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE) x11_shadow_subsystem_thread,
|
||||
(void*) subsystem, 0, NULL);
|
||||
|
||||
|
@ -985,24 +1068,18 @@ int x11_shadow_subsystem_stop(x11ShadowSubsystem* subsystem)
|
|||
if (!subsystem)
|
||||
return -1;
|
||||
|
||||
if (subsystem->thread)
|
||||
{
|
||||
MessageQueue_PostQuit(subsystem->MsgPipe->In, 0);
|
||||
WaitForSingleObject(subsystem->thread, INFINITE);
|
||||
CloseHandle(subsystem->thread);
|
||||
subsystem->thread = NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void x11_shadow_subsystem_free(x11ShadowSubsystem* subsystem)
|
||||
{
|
||||
if (!subsystem)
|
||||
return;
|
||||
|
||||
x11_shadow_subsystem_uninit(subsystem);
|
||||
|
||||
region16_uninit(&(subsystem->invalidRegion));
|
||||
|
||||
CloseHandle(subsystem->updateEvent);
|
||||
|
||||
free(subsystem);
|
||||
}
|
||||
|
||||
x11ShadowSubsystem* x11_shadow_subsystem_new(rdpShadowServer* server)
|
||||
x11ShadowSubsystem* x11_shadow_subsystem_new()
|
||||
{
|
||||
x11ShadowSubsystem* subsystem;
|
||||
|
||||
|
@ -1011,18 +1088,6 @@ x11ShadowSubsystem* x11_shadow_subsystem_new(rdpShadowServer* server)
|
|||
if (!subsystem)
|
||||
return NULL;
|
||||
|
||||
subsystem->server = server;
|
||||
|
||||
subsystem->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
region16_init(&(subsystem->invalidRegion));
|
||||
|
||||
subsystem->Init = (pfnShadowSubsystemInit) x11_shadow_subsystem_init;
|
||||
subsystem->Uninit = (pfnShadowSubsystemInit) x11_shadow_subsystem_uninit;
|
||||
subsystem->Start = (pfnShadowSubsystemStart) x11_shadow_subsystem_start;
|
||||
subsystem->Stop = (pfnShadowSubsystemStop) x11_shadow_subsystem_stop;
|
||||
subsystem->Free = (pfnShadowSubsystemFree) x11_shadow_subsystem_free;
|
||||
|
||||
subsystem->SynchronizeEvent = (pfnShadowSynchronizeEvent) x11_shadow_input_synchronize_event;
|
||||
subsystem->KeyboardEvent = (pfnShadowKeyboardEvent) x11_shadow_input_keyboard_event;
|
||||
subsystem->UnicodeKeyboardEvent = (pfnShadowUnicodeKeyboardEvent) x11_shadow_input_unicode_keyboard_event;
|
||||
|
@ -1038,7 +1103,28 @@ x11ShadowSubsystem* x11_shadow_subsystem_new(rdpShadowServer* server)
|
|||
return subsystem;
|
||||
}
|
||||
|
||||
rdpShadowSubsystem* X11_ShadowCreateSubsystem(rdpShadowServer* server)
|
||||
void x11_shadow_subsystem_free(x11ShadowSubsystem* subsystem)
|
||||
{
|
||||
return (rdpShadowSubsystem*) x11_shadow_subsystem_new(server);
|
||||
if (!subsystem)
|
||||
return;
|
||||
|
||||
x11_shadow_subsystem_uninit(subsystem);
|
||||
|
||||
free(subsystem);
|
||||
}
|
||||
|
||||
int X11_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints)
|
||||
{
|
||||
pEntryPoints->New = (pfnShadowSubsystemNew) x11_shadow_subsystem_new;
|
||||
pEntryPoints->Free = (pfnShadowSubsystemFree) x11_shadow_subsystem_free;
|
||||
|
||||
pEntryPoints->Init = (pfnShadowSubsystemInit) x11_shadow_subsystem_init;
|
||||
pEntryPoints->Uninit = (pfnShadowSubsystemInit) x11_shadow_subsystem_uninit;
|
||||
|
||||
pEntryPoints->Start = (pfnShadowSubsystemStart) x11_shadow_subsystem_start;
|
||||
pEntryPoints->Stop = (pfnShadowSubsystemStop) x11_shadow_subsystem_stop;
|
||||
|
||||
pEntryPoints->EnumMonitors = (pfnShadowEnumMonitors) x11_shadow_enum_monitors;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
*
|
||||
* Copyright 2014 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 <winpr/crt.h>
|
||||
#include <winpr/ssl.h>
|
||||
#include <winpr/wnd.h>
|
||||
#include <winpr/path.h>
|
||||
#include <winpr/cmdline.h>
|
||||
#include <winpr/winsock.h>
|
||||
|
||||
#include <winpr/tools/makecert.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
static BOOL g_MessagePump = TRUE;
|
||||
#else
|
||||
static BOOL g_MessagePump = FALSE;
|
||||
#endif
|
||||
|
||||
#include <freerdp/server/shadow.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
MSG msg;
|
||||
int status;
|
||||
DWORD dwExitCode;
|
||||
rdpShadowServer* server;
|
||||
|
||||
server = shadow_server_new();
|
||||
|
||||
if (!server)
|
||||
return 0;
|
||||
|
||||
status = shadow_server_parse_command_line(server, argc, argv);
|
||||
|
||||
status = shadow_server_command_line_status_print(server, argc, argv, status);
|
||||
|
||||
if (status < 0)
|
||||
return 0;
|
||||
|
||||
if (shadow_server_init(server) < 0)
|
||||
return 0;
|
||||
|
||||
if (shadow_server_start(server) < 0)
|
||||
return 0;
|
||||
|
||||
if (g_MessagePump)
|
||||
{
|
||||
while (GetMessage(&msg, 0, 0, 0))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
WaitForSingleObject(server->thread, INFINITE);
|
||||
|
||||
GetExitCodeThread(server->thread, &dwExitCode);
|
||||
|
||||
shadow_server_free(server);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -28,6 +28,7 @@
|
|||
#include "shadow_encoder.h"
|
||||
#include "shadow_capture.h"
|
||||
#include "shadow_channels.h"
|
||||
#include "shadow_subsystem.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
|
@ -40,6 +40,7 @@ void shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client)
|
|||
|
||||
server = (rdpShadowServer*) peer->ContextExtra;
|
||||
client->server = server;
|
||||
client->subsystem = server->subsystem;
|
||||
|
||||
settings = peer->settings;
|
||||
|
||||
|
@ -49,6 +50,11 @@ void shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client)
|
|||
settings->BitmapCacheV3Enabled = TRUE;
|
||||
settings->FrameMarkerCommandEnabled = TRUE;
|
||||
settings->SurfaceFrameMarkerEnabled = TRUE;
|
||||
settings->SupportGraphicsPipeline = FALSE;
|
||||
|
||||
settings->DrawAllowSkipAlpha = TRUE;
|
||||
settings->DrawAllowColorSubsampling = TRUE;
|
||||
settings->DrawAllowDynamicColorFidelity = TRUE;
|
||||
|
||||
settings->RdpSecurity = TRUE;
|
||||
settings->TlsSecurity = TRUE;
|
||||
|
@ -71,7 +77,7 @@ void shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client)
|
|||
|
||||
client->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
client->encoder = shadow_encoder_new(server);
|
||||
client->encoder = shadow_encoder_new(client);
|
||||
|
||||
ArrayList_Add(server->clients, (void*) client);
|
||||
}
|
||||
|
@ -103,6 +109,22 @@ void shadow_client_context_free(freerdp_peer* peer, rdpShadowClient* client)
|
|||
}
|
||||
}
|
||||
|
||||
void shadow_client_message_free(wMessage* message)
|
||||
{
|
||||
if (message->id == SHADOW_MSG_IN_REFRESH_OUTPUT_ID)
|
||||
{
|
||||
SHADOW_MSG_IN_REFRESH_OUTPUT* wParam = (SHADOW_MSG_IN_REFRESH_OUTPUT*) message->wParam;
|
||||
|
||||
free(wParam->rects);
|
||||
free(wParam);
|
||||
}
|
||||
else if (message->id == SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID)
|
||||
{
|
||||
SHADOW_MSG_IN_SUPPRESS_OUTPUT* wParam = (SHADOW_MSG_IN_SUPPRESS_OUTPUT*) message->wParam;
|
||||
free(wParam);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL shadow_client_capabilities(freerdp_peer* peer)
|
||||
{
|
||||
return TRUE;
|
||||
|
@ -165,17 +187,87 @@ BOOL shadow_client_post_connect(freerdp_peer* peer)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
void shadow_client_refresh_rect(rdpShadowClient* client, BYTE count, RECTANGLE_16* areas)
|
||||
{
|
||||
wMessage message = { 0 };
|
||||
SHADOW_MSG_IN_REFRESH_OUTPUT* wParam;
|
||||
wMessagePipe* MsgPipe = client->subsystem->MsgPipe;
|
||||
|
||||
wParam = (SHADOW_MSG_IN_REFRESH_OUTPUT*) calloc(1, sizeof(SHADOW_MSG_IN_REFRESH_OUTPUT));
|
||||
|
||||
if (!wParam)
|
||||
return;
|
||||
|
||||
wParam->numRects = (UINT32) count;
|
||||
|
||||
if (wParam->numRects)
|
||||
{
|
||||
wParam->rects = (RECTANGLE_16*) calloc(wParam->numRects, sizeof(RECTANGLE_16));
|
||||
|
||||
if (!wParam->rects)
|
||||
return;
|
||||
}
|
||||
|
||||
CopyMemory(wParam->rects, areas, wParam->numRects * sizeof(RECTANGLE_16));
|
||||
|
||||
message.id = SHADOW_MSG_IN_REFRESH_OUTPUT_ID;
|
||||
message.wParam = (void*) wParam;
|
||||
message.lParam = NULL;
|
||||
message.context = (void*) client;
|
||||
message.Free = shadow_client_message_free;
|
||||
|
||||
MessageQueue_Dispatch(MsgPipe->In, &message);
|
||||
}
|
||||
|
||||
void shadow_client_suppress_output(rdpShadowClient* client, BYTE allow, RECTANGLE_16* area)
|
||||
{
|
||||
wMessage message = { 0 };
|
||||
SHADOW_MSG_IN_SUPPRESS_OUTPUT* wParam;
|
||||
wMessagePipe* MsgPipe = client->subsystem->MsgPipe;
|
||||
|
||||
wParam = (SHADOW_MSG_IN_SUPPRESS_OUTPUT*) calloc(1, sizeof(SHADOW_MSG_IN_SUPPRESS_OUTPUT));
|
||||
|
||||
if (!wParam)
|
||||
return;
|
||||
|
||||
wParam->allow = (UINT32) allow;
|
||||
|
||||
if (area)
|
||||
CopyMemory(&(wParam->rect), area, sizeof(RECTANGLE_16));
|
||||
|
||||
message.id = SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID;
|
||||
message.wParam = (void*) wParam;
|
||||
message.lParam = NULL;
|
||||
message.context = (void*) client;
|
||||
message.Free = shadow_client_message_free;
|
||||
|
||||
MessageQueue_Dispatch(MsgPipe->In, &message);
|
||||
}
|
||||
|
||||
BOOL shadow_client_activate(freerdp_peer* peer)
|
||||
{
|
||||
rdpShadowClient* client;
|
||||
rdpSettings* settings = peer->settings;
|
||||
rdpShadowClient* client = (rdpShadowClient*) peer->context;
|
||||
|
||||
client = (rdpShadowClient*) peer->context;
|
||||
if (strcmp(settings->ClientDir, "librdp") == 0)
|
||||
{
|
||||
/* Hack for Mac/iOS/Android Microsoft RDP clients */
|
||||
|
||||
settings->RemoteFxCodec = FALSE;
|
||||
|
||||
settings->NSCodec = FALSE;
|
||||
settings->NSCodecAllowSubsampling = FALSE;
|
||||
|
||||
settings->SurfaceFrameMarkerEnabled = FALSE;
|
||||
}
|
||||
|
||||
client->activated = TRUE;
|
||||
client->inLobby = client->mayView ? FALSE : TRUE;
|
||||
|
||||
shadow_encoder_reset(client->encoder);
|
||||
|
||||
shadow_client_refresh_rect(client, 0, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -194,11 +286,6 @@ void shadow_client_surface_frame_acknowledge(rdpShadowClient* client, UINT32 fra
|
|||
}
|
||||
}
|
||||
|
||||
void shadow_client_suppress_output(rdpShadowClient* client, BYTE allow, RECTANGLE_16* area)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int shadow_client_send_surface_frame_marker(rdpShadowClient* client, UINT32 action, UINT32 id)
|
||||
{
|
||||
SURFACE_FRAME_MARKER surfaceFrameMarker;
|
||||
|
@ -216,6 +303,8 @@ int shadow_client_send_surface_frame_marker(rdpShadowClient* client, UINT32 acti
|
|||
int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* surface, int nXSrc, int nYSrc, int nWidth, int nHeight)
|
||||
{
|
||||
int i;
|
||||
BOOL first;
|
||||
BOOL last;
|
||||
wStream* s;
|
||||
int nSrcStep;
|
||||
BYTE* pSrcData;
|
||||
|
@ -254,16 +343,15 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s
|
|||
}
|
||||
|
||||
if (encoder->frameAck)
|
||||
{
|
||||
frameId = (UINT32) shadow_encoder_create_frame_id(encoder);
|
||||
shadow_client_send_surface_frame_marker(client, SURFACECMD_FRAMEACTION_BEGIN, frameId);
|
||||
}
|
||||
|
||||
if (settings->RemoteFxCodec)
|
||||
{
|
||||
RFX_RECT rect;
|
||||
RFX_MESSAGE* messages;
|
||||
|
||||
shadow_encoder_prepare(encoder, FREERDP_CODEC_REMOTEFX);
|
||||
|
||||
s = encoder->bs;
|
||||
|
||||
rect.x = nXSrc;
|
||||
|
@ -295,50 +383,47 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s
|
|||
cmd.bitmapDataLength = Stream_GetPosition(s);
|
||||
cmd.bitmapData = Stream_Buffer(s);
|
||||
|
||||
IFCALL(update->SurfaceBits, update->context, &cmd);
|
||||
first = (i == 0) ? TRUE : FALSE;
|
||||
last = ((i + 1) == numMessages) ? TRUE : FALSE;
|
||||
|
||||
if (!encoder->frameAck)
|
||||
IFCALL(update->SurfaceBits, update->context, &cmd);
|
||||
else
|
||||
IFCALL(update->SurfaceFrameBits, update->context, &cmd, first, last, frameId);
|
||||
}
|
||||
|
||||
free(messages);
|
||||
}
|
||||
else if (settings->NSCodec)
|
||||
{
|
||||
NSC_MESSAGE* messages;
|
||||
shadow_encoder_prepare(encoder, FREERDP_CODEC_NSCODEC);
|
||||
|
||||
s = encoder->bs;
|
||||
Stream_SetPosition(s, 0);
|
||||
|
||||
messages = nsc_encode_messages(encoder->nsc, pSrcData,
|
||||
nXSrc, nYSrc, nWidth, nHeight, nSrcStep,
|
||||
&numMessages, settings->MultifragMaxRequestSize);
|
||||
pSrcData = &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 4)];
|
||||
|
||||
nsc_compose_message(encoder->nsc, s, pSrcData, nWidth, nHeight, nSrcStep);
|
||||
|
||||
cmd.bpp = 32;
|
||||
cmd.codecID = settings->NSCodecId;
|
||||
cmd.destLeft = nXSrc;
|
||||
cmd.destTop = nYSrc;
|
||||
cmd.destRight = cmd.destLeft + nWidth;
|
||||
cmd.destBottom = cmd.destTop + nHeight;
|
||||
cmd.width = nWidth;
|
||||
cmd.height = nHeight;
|
||||
|
||||
for (i = 0; i < numMessages; i++)
|
||||
{
|
||||
Stream_SetPosition(s, 0);
|
||||
cmd.bitmapDataLength = Stream_GetPosition(s);
|
||||
cmd.bitmapData = Stream_Buffer(s);
|
||||
|
||||
nsc_write_message(encoder->nsc, s, &messages[i]);
|
||||
nsc_message_free(encoder->nsc, &messages[i]);
|
||||
|
||||
cmd.destLeft = messages[i].x;
|
||||
cmd.destTop = messages[i].y;
|
||||
cmd.destRight = messages[i].x + messages[i].width;
|
||||
cmd.destBottom = messages[i].y + messages[i].height;
|
||||
cmd.width = messages[i].width;
|
||||
cmd.height = messages[i].height;
|
||||
|
||||
cmd.bitmapDataLength = Stream_GetPosition(s);
|
||||
cmd.bitmapData = Stream_Buffer(s);
|
||||
first = TRUE;
|
||||
last = TRUE;
|
||||
|
||||
if (!encoder->frameAck)
|
||||
IFCALL(update->SurfaceBits, update->context, &cmd);
|
||||
}
|
||||
|
||||
free(messages);
|
||||
}
|
||||
|
||||
if (encoder->frameAck)
|
||||
{
|
||||
shadow_client_send_surface_frame_marker(client, SURFACECMD_FRAMEACTION_END, frameId);
|
||||
else
|
||||
IFCALL(update->SurfaceFrameBits, update->context, &cmd, first, last, frameId);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -348,18 +433,19 @@ int shadow_client_send_bitmap_update(rdpShadowClient* client, rdpShadowSurface*
|
|||
{
|
||||
BYTE* data;
|
||||
BYTE* buffer;
|
||||
int i, j, k;
|
||||
wStream* s;
|
||||
wStream* ts;
|
||||
int e, lines;
|
||||
int yIdx, xIdx, k;
|
||||
int rows, cols;
|
||||
int nSrcStep;
|
||||
BYTE* pSrcData;
|
||||
UINT32 DstSize;
|
||||
UINT32 SrcFormat;
|
||||
BITMAP_DATA* bitmap;
|
||||
rdpUpdate* update;
|
||||
rdpContext* context;
|
||||
rdpSettings* settings;
|
||||
int MaxRegionWidth;
|
||||
int MaxRegionHeight;
|
||||
UINT32 maxUpdateSize;
|
||||
UINT32 totalBitmapSize;
|
||||
UINT32 updateSizeEstimate;
|
||||
BITMAP_DATA* bitmapData;
|
||||
BITMAP_UPDATE bitmapUpdate;
|
||||
rdpShadowServer* server;
|
||||
|
@ -372,11 +458,16 @@ int shadow_client_send_bitmap_update(rdpShadowClient* client, rdpShadowSurface*
|
|||
server = client->server;
|
||||
encoder = client->encoder;
|
||||
|
||||
maxUpdateSize = settings->MultifragMaxRequestSize;
|
||||
|
||||
if (settings->ColorDepth < 32)
|
||||
shadow_encoder_prepare(encoder, FREERDP_CODEC_INTERLEAVED);
|
||||
else
|
||||
shadow_encoder_prepare(encoder, FREERDP_CODEC_PLANAR);
|
||||
|
||||
pSrcData = surface->data;
|
||||
nSrcStep = surface->scanline;
|
||||
|
||||
MaxRegionWidth = 64 * 4;
|
||||
MaxRegionHeight = 64 * 1;
|
||||
SrcFormat = PIXEL_FORMAT_RGB32;
|
||||
|
||||
if ((nXSrc % 4) != 0)
|
||||
{
|
||||
|
@ -390,39 +481,12 @@ int shadow_client_send_bitmap_update(rdpShadowClient* client, rdpShadowSurface*
|
|||
nYSrc -= (nYSrc % 4);
|
||||
}
|
||||
|
||||
if ((nWidth * nHeight) > (MaxRegionWidth * MaxRegionHeight))
|
||||
{
|
||||
int nXSrcSub;
|
||||
int nYSrcSub;
|
||||
int nWidthSub;
|
||||
int nHeightSub;
|
||||
rows = (nWidth + (MaxRegionWidth - (nWidth % MaxRegionWidth))) / MaxRegionWidth;
|
||||
cols = (nHeight + (MaxRegionHeight - (nHeight % MaxRegionHeight))) / MaxRegionHeight;
|
||||
|
||||
for (i = 0; i < rows; i++)
|
||||
{
|
||||
for (j = 0; j < cols; j++)
|
||||
{
|
||||
nXSrcSub = nXSrc + (i * MaxRegionWidth);
|
||||
nYSrcSub = nYSrc + (j * MaxRegionHeight);
|
||||
|
||||
nWidthSub = (i < (rows - 1)) ? MaxRegionWidth : nWidth - (i * MaxRegionWidth);
|
||||
nHeightSub = (j < (cols - 1)) ? MaxRegionHeight : nHeight - (j * MaxRegionHeight);
|
||||
|
||||
if ((nWidthSub * nHeightSub) > 0)
|
||||
{
|
||||
shadow_client_send_bitmap_update(client, surface, nXSrcSub, nYSrcSub, nWidthSub, nHeightSub);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
rows = (nWidth + (64 - (nWidth % 64))) / 64;
|
||||
cols = (nHeight + (64 - (nHeight % 64))) / 64;
|
||||
rows = (nHeight / 64) + ((nHeight % 64) ? 1 : 0);
|
||||
cols = (nWidth / 64) + ((nWidth % 64) ? 1 : 0);
|
||||
|
||||
k = 0;
|
||||
totalBitmapSize = 0;
|
||||
|
||||
bitmapUpdate.count = bitmapUpdate.number = rows * cols;
|
||||
bitmapData = (BITMAP_DATA*) malloc(sizeof(BITMAP_DATA) * bitmapUpdate.number);
|
||||
bitmapUpdate.rectangles = bitmapData;
|
||||
|
@ -442,107 +506,81 @@ int shadow_client_send_bitmap_update(rdpShadowClient* client, rdpShadowSurface*
|
|||
nHeight += (nHeight % 4);
|
||||
}
|
||||
|
||||
for (i = 0; i < rows; i++)
|
||||
for (yIdx = 0; yIdx < rows; yIdx++)
|
||||
{
|
||||
for (j = 0; j < cols; j++)
|
||||
for (xIdx = 0; xIdx < cols; xIdx++)
|
||||
{
|
||||
nWidth = (i < (rows - 1)) ? 64 : nWidth - (i * 64);
|
||||
nHeight = (j < (cols - 1)) ? 64 : nHeight - (j * 64);
|
||||
bitmap = &bitmapData[k];
|
||||
|
||||
bitmapData[k].bitsPerPixel = 16;
|
||||
bitmapData[k].width = nWidth;
|
||||
bitmapData[k].height = nHeight;
|
||||
bitmapData[k].destLeft = nXSrc + (i * 64);
|
||||
bitmapData[k].destTop = nYSrc + (j * 64);
|
||||
bitmapData[k].destRight = bitmapData[k].destLeft + nWidth - 1;
|
||||
bitmapData[k].destBottom = bitmapData[k].destTop + nHeight - 1;
|
||||
bitmapData[k].compressed = TRUE;
|
||||
bitmap->width = 64;
|
||||
bitmap->height = 64;
|
||||
bitmap->destLeft = nXSrc + (xIdx * 64);
|
||||
bitmap->destTop = nYSrc + (yIdx * 64);
|
||||
|
||||
if (((nWidth * nHeight) > 0) && (nWidth >= 4) && (nHeight >= 4))
|
||||
if ((bitmap->destLeft + bitmap->width) > (nXSrc + nWidth))
|
||||
bitmap->width = (nXSrc + nWidth) - bitmap->destLeft;
|
||||
|
||||
if ((bitmap->destTop + bitmap->height) > (nYSrc + nHeight))
|
||||
bitmap->height = (nYSrc + nHeight) - bitmap->destTop;
|
||||
|
||||
bitmap->destRight = bitmap->destLeft + bitmap->width - 1;
|
||||
bitmap->destBottom = bitmap->destTop + bitmap->height - 1;
|
||||
bitmap->compressed = TRUE;
|
||||
|
||||
if ((bitmap->width < 4) || (bitmap->height < 4))
|
||||
continue;
|
||||
|
||||
if (settings->ColorDepth < 32)
|
||||
{
|
||||
UINT32 srcFormat = PIXEL_FORMAT_RGB32;
|
||||
int bitsPerPixel = settings->ColorDepth;
|
||||
int bytesPerPixel = (bitsPerPixel + 7) / 8;
|
||||
|
||||
e = nWidth % 4;
|
||||
DstSize = 64 * 64 * 4;
|
||||
buffer = encoder->grid[k];
|
||||
|
||||
if (e != 0)
|
||||
e = 4 - e;
|
||||
interleaved_compress(encoder->interleaved, buffer, &DstSize, bitmap->width, bitmap->height,
|
||||
pSrcData, SrcFormat, nSrcStep, bitmap->destLeft, bitmap->destTop, NULL, bitsPerPixel);
|
||||
|
||||
s = encoder->bs;
|
||||
ts = encoder->bts;
|
||||
|
||||
Stream_SetPosition(s, 0);
|
||||
Stream_SetPosition(ts, 0);
|
||||
|
||||
data = surface->data;
|
||||
data = &data[(bitmapData[k].destTop * nSrcStep) +
|
||||
(bitmapData[k].destLeft * 4)];
|
||||
|
||||
srcFormat = PIXEL_FORMAT_RGB32;
|
||||
|
||||
if (settings->ColorDepth > 24)
|
||||
{
|
||||
int dstSize;
|
||||
|
||||
buffer = encoder->grid[k];
|
||||
|
||||
buffer = freerdp_bitmap_compress_planar(encoder->planar,
|
||||
data, srcFormat, nWidth, nHeight, nSrcStep, buffer, &dstSize);
|
||||
|
||||
bitmapData[k].bitmapDataStream = buffer;
|
||||
bitmapData[k].bitmapLength = dstSize;
|
||||
|
||||
bitmapData[k].bitsPerPixel = 32;
|
||||
bitmapData[k].cbScanWidth = nWidth * 4;
|
||||
bitmapData[k].cbUncompressedSize = nWidth * nHeight * 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
int bytesPerPixel = 2;
|
||||
UINT32 dstFormat = PIXEL_FORMAT_RGB16;
|
||||
|
||||
if (settings->ColorDepth == 15)
|
||||
{
|
||||
bytesPerPixel = 2;
|
||||
dstFormat = PIXEL_FORMAT_RGB15;
|
||||
}
|
||||
else if (settings->ColorDepth == 24)
|
||||
{
|
||||
bytesPerPixel = 3;
|
||||
dstFormat = PIXEL_FORMAT_XRGB32;
|
||||
}
|
||||
|
||||
buffer = encoder->grid[k];
|
||||
|
||||
freerdp_image_copy(buffer, dstFormat, -1, 0, 0, nWidth, nHeight,
|
||||
data, srcFormat, nSrcStep, 0, 0, NULL);
|
||||
|
||||
lines = freerdp_bitmap_compress((char*) buffer, nWidth, nHeight, s,
|
||||
settings->ColorDepth, 64 * 64 * 4, nHeight - 1, ts, e);
|
||||
|
||||
Stream_SealLength(s);
|
||||
|
||||
bitmapData[k].bitmapDataStream = Stream_Buffer(s);
|
||||
bitmapData[k].bitmapLength = Stream_Length(s);
|
||||
|
||||
buffer = encoder->grid[k];
|
||||
CopyMemory(buffer, bitmapData[k].bitmapDataStream, bitmapData[k].bitmapLength);
|
||||
bitmapData[k].bitmapDataStream = buffer;
|
||||
|
||||
bitmapData[k].bitsPerPixel = settings->ColorDepth;
|
||||
bitmapData[k].cbScanWidth = nWidth * bytesPerPixel;
|
||||
bitmapData[k].cbUncompressedSize = nWidth * nHeight * bytesPerPixel;
|
||||
}
|
||||
|
||||
bitmapData[k].cbCompFirstRowSize = 0;
|
||||
bitmapData[k].cbCompMainBodySize = bitmapData[k].bitmapLength;
|
||||
|
||||
k++;
|
||||
bitmap->bitmapDataStream = buffer;
|
||||
bitmap->bitmapLength = DstSize;
|
||||
bitmap->bitsPerPixel = bitsPerPixel;
|
||||
bitmap->cbScanWidth = bitmap->width * bytesPerPixel;
|
||||
bitmap->cbUncompressedSize = bitmap->width * bitmap->height * bytesPerPixel;
|
||||
}
|
||||
else
|
||||
{
|
||||
int dstSize;
|
||||
|
||||
buffer = encoder->grid[k];
|
||||
data = &pSrcData[(bitmap->destTop * nSrcStep) + (bitmap->destLeft * 4)];
|
||||
|
||||
buffer = freerdp_bitmap_compress_planar(encoder->planar, data, SrcFormat,
|
||||
bitmap->width, bitmap->height, nSrcStep, buffer, &dstSize);
|
||||
|
||||
bitmap->bitmapDataStream = buffer;
|
||||
bitmap->bitmapLength = dstSize;
|
||||
bitmap->bitsPerPixel = 32;
|
||||
bitmap->cbScanWidth = bitmap->width * 4;
|
||||
bitmap->cbUncompressedSize = bitmap->width * bitmap->height * 4;
|
||||
}
|
||||
|
||||
bitmap->cbCompFirstRowSize = 0;
|
||||
bitmap->cbCompMainBodySize = bitmap->bitmapLength;
|
||||
|
||||
totalBitmapSize += bitmap->bitmapLength;
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
bitmapUpdate.count = bitmapUpdate.number = k;
|
||||
|
||||
updateSizeEstimate = totalBitmapSize + (k * bitmapUpdate.count) + 16;
|
||||
|
||||
if (updateSizeEstimate > maxUpdateSize)
|
||||
{
|
||||
fprintf(stderr, "update size estimate larger than maximum update size\n");
|
||||
}
|
||||
|
||||
IFCALL(update->BitmapUpdate, context, &bitmapUpdate);
|
||||
|
||||
free(bitmapData);
|
||||
|
@ -609,17 +647,10 @@ int shadow_client_send_surface_update(rdpShadowClient* client)
|
|||
|
||||
if (settings->RemoteFxCodec || settings->NSCodec)
|
||||
{
|
||||
if (settings->RemoteFxCodec)
|
||||
shadow_encoder_prepare(encoder, SHADOW_CODEC_REMOTEFX);
|
||||
else if (settings->NSCodec)
|
||||
shadow_encoder_prepare(encoder, SHADOW_CODEC_NSCODEC);
|
||||
|
||||
status = shadow_client_send_surface_bits(client, surface, nXSrc, nYSrc, nWidth, nHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
shadow_encoder_prepare(encoder, SHADOW_CODEC_BITMAP);
|
||||
|
||||
status = shadow_client_send_bitmap_update(client, surface, nXSrc, nYSrc, nWidth, nHeight);
|
||||
}
|
||||
|
||||
|
@ -658,6 +689,7 @@ void* shadow_client_thread(rdpShadowClient* client)
|
|||
HANDLE ChannelEvent;
|
||||
HANDLE UpdateEvent;
|
||||
freerdp_peer* peer;
|
||||
rdpContext* context;
|
||||
rdpSettings* settings;
|
||||
rdpShadowServer* server;
|
||||
rdpShadowScreen* screen;
|
||||
|
@ -669,7 +701,8 @@ void* shadow_client_thread(rdpShadowClient* client)
|
|||
encoder = client->encoder;
|
||||
subsystem = server->subsystem;
|
||||
|
||||
peer = ((rdpContext*) client)->peer;
|
||||
context = (rdpContext*) client;
|
||||
peer = context->peer;
|
||||
settings = peer->settings;
|
||||
|
||||
peer->Capabilities = shadow_client_capabilities;
|
||||
|
@ -680,9 +713,9 @@ void* shadow_client_thread(rdpShadowClient* client)
|
|||
|
||||
peer->Initialize(peer);
|
||||
|
||||
peer->update->SurfaceFrameAcknowledge = (pSurfaceFrameAcknowledge)
|
||||
shadow_client_surface_frame_acknowledge;
|
||||
peer->update->RefreshRect = (pRefreshRect) shadow_client_refresh_rect;
|
||||
peer->update->SuppressOutput = (pSuppressOutput) shadow_client_suppress_output;
|
||||
peer->update->SurfaceFrameAcknowledge = (pSurfaceFrameAcknowledge) shadow_client_surface_frame_acknowledge;
|
||||
|
||||
StopEvent = client->StopEvent;
|
||||
UpdateEvent = subsystem->updateEvent;
|
||||
|
|
|
@ -114,6 +114,9 @@ int shadow_encoder_uninit_grid(rdpShadowEncoder* encoder)
|
|||
|
||||
int shadow_encoder_init_rfx(rdpShadowEncoder* encoder)
|
||||
{
|
||||
rdpContext* context = (rdpContext*) encoder->client;
|
||||
rdpSettings* settings = context->settings;
|
||||
|
||||
if (!encoder->rfx)
|
||||
encoder->rfx = rfx_context_new(TRUE);
|
||||
|
||||
|
@ -131,17 +134,20 @@ int shadow_encoder_init_rfx(rdpShadowEncoder* encoder)
|
|||
encoder->fps = 16;
|
||||
encoder->maxFps = 32;
|
||||
encoder->frameId = 0;
|
||||
encoder->frameAck = TRUE;
|
||||
encoder->frameList = ListDictionary_New(TRUE);
|
||||
encoder->frameAck = settings->SurfaceFrameMarkerEnabled;
|
||||
}
|
||||
|
||||
encoder->codecs |= SHADOW_CODEC_REMOTEFX;
|
||||
encoder->codecs |= FREERDP_CODEC_REMOTEFX;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int shadow_encoder_init_nsc(rdpShadowEncoder* encoder)
|
||||
{
|
||||
rdpContext* context = (rdpContext*) encoder->client;
|
||||
rdpSettings* settings = context->settings;
|
||||
|
||||
if (!encoder->nsc)
|
||||
encoder->nsc = nsc_context_new();
|
||||
|
||||
|
@ -155,20 +161,28 @@ int shadow_encoder_init_nsc(rdpShadowEncoder* encoder)
|
|||
encoder->fps = 16;
|
||||
encoder->maxFps = 32;
|
||||
encoder->frameId = 0;
|
||||
encoder->frameAck = TRUE;
|
||||
encoder->frameList = ListDictionary_New(TRUE);
|
||||
encoder->frameAck = settings->SurfaceFrameMarkerEnabled;
|
||||
}
|
||||
|
||||
encoder->codecs |= SHADOW_CODEC_NSCODEC;
|
||||
encoder->nsc->ColorLossLevel = settings->NSCodecColorLossLevel;
|
||||
encoder->nsc->ChromaSubsamplingLevel = settings->NSCodecAllowSubsampling ? 1 : 0;
|
||||
encoder->nsc->DynamicColorFidelity = settings->NSCodecAllowDynamicColorFidelity;
|
||||
|
||||
encoder->codecs |= FREERDP_CODEC_NSCODEC;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int shadow_encoder_init_bitmap(rdpShadowEncoder* encoder)
|
||||
int shadow_encoder_init_planar(rdpShadowEncoder* encoder)
|
||||
{
|
||||
DWORD planarFlags;
|
||||
DWORD planarFlags = 0;
|
||||
rdpContext* context = (rdpContext*) encoder->client;
|
||||
rdpSettings* settings = context->settings;
|
||||
|
||||
if (settings->DrawAllowSkipAlpha)
|
||||
planarFlags |= PLANAR_FORMAT_HEADER_NA;
|
||||
|
||||
planarFlags = PLANAR_FORMAT_HEADER_NA;
|
||||
planarFlags |= PLANAR_FORMAT_HEADER_RLE;
|
||||
|
||||
if (!encoder->planar)
|
||||
|
@ -180,13 +194,20 @@ int shadow_encoder_init_bitmap(rdpShadowEncoder* encoder)
|
|||
if (!encoder->planar)
|
||||
return -1;
|
||||
|
||||
if (!encoder->bts)
|
||||
encoder->bts = Stream_New(NULL, encoder->maxTileWidth * encoder->maxTileHeight * 4);
|
||||
encoder->codecs |= FREERDP_CODEC_PLANAR;
|
||||
|
||||
if (!encoder->bts)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int shadow_encoder_init_interleaved(rdpShadowEncoder* encoder)
|
||||
{
|
||||
if (!encoder->interleaved)
|
||||
encoder->interleaved = bitmap_interleaved_context_new(TRUE);
|
||||
|
||||
if (!encoder->interleaved)
|
||||
return -1;
|
||||
|
||||
encoder->codecs |= SHADOW_CODEC_BITMAP;
|
||||
encoder->codecs |= FREERDP_CODEC_INTERLEAVED;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -221,7 +242,7 @@ int shadow_encoder_uninit_rfx(rdpShadowEncoder* encoder)
|
|||
encoder->frameList = NULL;
|
||||
}
|
||||
|
||||
encoder->codecs &= ~SHADOW_CODEC_REMOTEFX;
|
||||
encoder->codecs &= ~FREERDP_CODEC_REMOTEFX;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -240,12 +261,12 @@ int shadow_encoder_uninit_nsc(rdpShadowEncoder* encoder)
|
|||
encoder->frameList = NULL;
|
||||
}
|
||||
|
||||
encoder->codecs &= ~SHADOW_CODEC_NSCODEC;
|
||||
encoder->codecs &= ~FREERDP_CODEC_NSCODEC;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int shadow_encoder_uninit_bitmap(rdpShadowEncoder* encoder)
|
||||
int shadow_encoder_uninit_planar(rdpShadowEncoder* encoder)
|
||||
{
|
||||
if (encoder->planar)
|
||||
{
|
||||
|
@ -253,13 +274,20 @@ int shadow_encoder_uninit_bitmap(rdpShadowEncoder* encoder)
|
|||
encoder->planar = NULL;
|
||||
}
|
||||
|
||||
if (encoder->bts)
|
||||
encoder->codecs &= ~FREERDP_CODEC_PLANAR;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int shadow_encoder_uninit_interleaved(rdpShadowEncoder* encoder)
|
||||
{
|
||||
if (encoder->interleaved)
|
||||
{
|
||||
Stream_Free(encoder->bts, TRUE);
|
||||
encoder->bts = NULL;
|
||||
bitmap_interleaved_context_free(encoder->interleaved);
|
||||
encoder->interleaved = NULL;
|
||||
}
|
||||
|
||||
encoder->codecs &= ~SHADOW_CODEC_BITMAP;
|
||||
encoder->codecs &= ~FREERDP_CODEC_INTERLEAVED;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -274,19 +302,24 @@ int shadow_encoder_uninit(rdpShadowEncoder* encoder)
|
|||
encoder->bs = NULL;
|
||||
}
|
||||
|
||||
if (encoder->codecs & SHADOW_CODEC_REMOTEFX)
|
||||
if (encoder->codecs & FREERDP_CODEC_REMOTEFX)
|
||||
{
|
||||
shadow_encoder_uninit_rfx(encoder);
|
||||
}
|
||||
|
||||
if (encoder->codecs & SHADOW_CODEC_NSCODEC)
|
||||
if (encoder->codecs & FREERDP_CODEC_NSCODEC)
|
||||
{
|
||||
shadow_encoder_uninit_nsc(encoder);
|
||||
}
|
||||
|
||||
if (encoder->codecs & SHADOW_CODEC_BITMAP)
|
||||
if (encoder->codecs & FREERDP_CODEC_PLANAR)
|
||||
{
|
||||
shadow_encoder_uninit_bitmap(encoder);
|
||||
shadow_encoder_uninit_planar(encoder);
|
||||
}
|
||||
|
||||
if (encoder->codecs & FREERDP_CODEC_INTERLEAVED)
|
||||
{
|
||||
shadow_encoder_uninit_interleaved(encoder);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -319,7 +352,7 @@ int shadow_encoder_prepare(rdpShadowEncoder* encoder, UINT32 codecs)
|
|||
{
|
||||
int status;
|
||||
|
||||
if ((codecs & SHADOW_CODEC_REMOTEFX) && !(encoder->codecs & SHADOW_CODEC_REMOTEFX))
|
||||
if ((codecs & FREERDP_CODEC_REMOTEFX) && !(encoder->codecs & FREERDP_CODEC_REMOTEFX))
|
||||
{
|
||||
status = shadow_encoder_init_rfx(encoder);
|
||||
|
||||
|
@ -327,7 +360,7 @@ int shadow_encoder_prepare(rdpShadowEncoder* encoder, UINT32 codecs)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if ((codecs & SHADOW_CODEC_NSCODEC) && !(encoder->codecs & SHADOW_CODEC_NSCODEC))
|
||||
if ((codecs & FREERDP_CODEC_NSCODEC) && !(encoder->codecs & FREERDP_CODEC_NSCODEC))
|
||||
{
|
||||
status = shadow_encoder_init_nsc(encoder);
|
||||
|
||||
|
@ -335,9 +368,17 @@ int shadow_encoder_prepare(rdpShadowEncoder* encoder, UINT32 codecs)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if ((codecs & SHADOW_CODEC_BITMAP) && !(encoder->codecs & SHADOW_CODEC_BITMAP))
|
||||
if ((codecs & FREERDP_CODEC_PLANAR) && !(encoder->codecs & FREERDP_CODEC_PLANAR))
|
||||
{
|
||||
status = shadow_encoder_init_bitmap(encoder);
|
||||
status = shadow_encoder_init_planar(encoder);
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((codecs & FREERDP_CODEC_INTERLEAVED) && !(encoder->codecs & FREERDP_CODEC_INTERLEAVED))
|
||||
{
|
||||
status = shadow_encoder_init_interleaved(encoder);
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
@ -346,15 +387,17 @@ int shadow_encoder_prepare(rdpShadowEncoder* encoder, UINT32 codecs)
|
|||
return 1;
|
||||
}
|
||||
|
||||
rdpShadowEncoder* shadow_encoder_new(rdpShadowServer* server)
|
||||
rdpShadowEncoder* shadow_encoder_new(rdpShadowClient* client)
|
||||
{
|
||||
rdpShadowEncoder* encoder;
|
||||
rdpShadowServer* server = client->server;
|
||||
|
||||
encoder = (rdpShadowEncoder*) calloc(1, sizeof(rdpShadowEncoder));
|
||||
|
||||
if (!encoder)
|
||||
return NULL;
|
||||
|
||||
encoder->client = client;
|
||||
encoder->server = server;
|
||||
|
||||
encoder->fps = 16;
|
||||
|
|
|
@ -23,18 +23,13 @@
|
|||
#include <winpr/stream.h>
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/codec/rfx.h>
|
||||
#include <freerdp/codec/nsc.h>
|
||||
#include <freerdp/codec/bitmap.h>
|
||||
#include <freerdp/codecs.h>
|
||||
|
||||
#include <freerdp/server/shadow.h>
|
||||
|
||||
#define SHADOW_CODEC_REMOTEFX 1
|
||||
#define SHADOW_CODEC_NSCODEC 2
|
||||
#define SHADOW_CODEC_BITMAP 4
|
||||
|
||||
struct rdp_shadow_encoder
|
||||
{
|
||||
rdpShadowClient* client;
|
||||
rdpShadowServer* server;
|
||||
|
||||
int width;
|
||||
|
@ -49,11 +44,11 @@ struct rdp_shadow_encoder
|
|||
int maxTileHeight;
|
||||
|
||||
wStream* bs;
|
||||
wStream* bts;
|
||||
|
||||
RFX_CONTEXT* rfx;
|
||||
NSC_CONTEXT* nsc;
|
||||
BITMAP_PLANAR_CONTEXT* planar;
|
||||
BITMAP_INTERLEAVED_CONTEXT* interleaved;
|
||||
|
||||
int fps;
|
||||
int maxFps;
|
||||
|
@ -70,7 +65,7 @@ int shadow_encoder_reset(rdpShadowEncoder* encoder);
|
|||
int shadow_encoder_prepare(rdpShadowEncoder* encoder, UINT32 codecs);
|
||||
int shadow_encoder_create_frame_id(rdpShadowEncoder* encoder);
|
||||
|
||||
rdpShadowEncoder* shadow_encoder_new(rdpShadowServer* server);
|
||||
rdpShadowEncoder* shadow_encoder_new(rdpShadowClient* client);
|
||||
void shadow_encoder_free(rdpShadowEncoder* encoder);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -43,7 +43,7 @@ void shadow_input_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
|
|||
|
||||
if (!client->mayInteract)
|
||||
return;
|
||||
|
||||
|
||||
if (subsystem->KeyboardEvent)
|
||||
{
|
||||
subsystem->KeyboardEvent(subsystem, flags, code);
|
||||
|
|
|
@ -27,15 +27,11 @@
|
|||
#include <winpr/cmdline.h>
|
||||
#include <winpr/winsock.h>
|
||||
|
||||
#include <freerdp/version.h>
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/version.h>
|
||||
|
||||
#include <winpr/tools/makecert.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <openssl/applink.c>
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/select.h>
|
||||
#include <sys/signal.h>
|
||||
|
@ -45,24 +41,6 @@
|
|||
|
||||
#define TAG SERVER_TAG("shadow")
|
||||
|
||||
#ifdef _WIN32
|
||||
static BOOL g_MessagePump = TRUE;
|
||||
#else
|
||||
static BOOL g_MessagePump = FALSE;
|
||||
#endif
|
||||
|
||||
#ifdef WITH_SHADOW_X11
|
||||
extern rdpShadowSubsystem* X11_ShadowCreateSubsystem(rdpShadowServer* server);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_SHADOW_MAC
|
||||
extern rdpShadowSubsystem* Mac_ShadowCreateSubsystem(rdpShadowServer* server);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_SHADOW_WIN
|
||||
extern rdpShadowSubsystem* Win_ShadowCreateSubsystem(rdpShadowServer* server);
|
||||
#endif
|
||||
|
||||
static COMMAND_LINE_ARGUMENT_A shadow_args[] =
|
||||
{
|
||||
{ "port", COMMAND_LINE_VALUE_REQUIRED, "<number>", NULL, NULL, -1, NULL, "Server port" },
|
||||
|
@ -268,7 +246,10 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a
|
|||
if (arg && (arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT))
|
||||
{
|
||||
int index;
|
||||
rdpShadowSubsystem* subsystem = server->subsystem;
|
||||
int numMonitors;
|
||||
MONITOR_DEF monitors[16];
|
||||
|
||||
numMonitors = shadow_enum_monitors(monitors, 16, 0);
|
||||
|
||||
if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
|
||||
{
|
||||
|
@ -279,10 +260,10 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a
|
|||
if (index < 0)
|
||||
index = 0;
|
||||
|
||||
if (index >= subsystem->monitorCount)
|
||||
if (index >= numMonitors)
|
||||
index = 0;
|
||||
|
||||
subsystem->selectedMonitor = index;
|
||||
server->selectedMonitor = index;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -291,9 +272,9 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a
|
|||
|
||||
/* List monitors */
|
||||
|
||||
for (index = 0; index < subsystem->monitorCount; index++)
|
||||
for (index = 0; index < numMonitors; index++)
|
||||
{
|
||||
monitor = &(subsystem->monitors[index]);
|
||||
monitor = &monitors[index];
|
||||
|
||||
width = monitor->right - monitor->left;
|
||||
height = monitor->bottom - monitor->top;
|
||||
|
@ -310,32 +291,6 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a
|
|||
return status;
|
||||
}
|
||||
|
||||
int shadow_server_surface_update(rdpShadowSubsystem* subsystem, REGION16* region)
|
||||
{
|
||||
int index;
|
||||
int count;
|
||||
wArrayList* clients;
|
||||
rdpShadowServer* server;
|
||||
rdpShadowClient* client;
|
||||
|
||||
server = subsystem->server;
|
||||
clients = server->clients;
|
||||
|
||||
ArrayList_Lock(clients);
|
||||
|
||||
count = ArrayList_Count(clients);
|
||||
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
client = ArrayList_GetItem(clients, index);
|
||||
shadow_client_surface_update(client, region);
|
||||
}
|
||||
|
||||
ArrayList_Unlock(clients);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void* shadow_server_thread(rdpShadowServer* server)
|
||||
{
|
||||
DWORD status;
|
||||
|
@ -349,10 +304,7 @@ void* shadow_server_thread(rdpShadowServer* server)
|
|||
StopEvent = server->StopEvent;
|
||||
subsystem = server->subsystem;
|
||||
|
||||
if (subsystem->Start)
|
||||
{
|
||||
subsystem->Start(subsystem);
|
||||
}
|
||||
shadow_subsystem_start(server->subsystem);
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
@ -386,10 +338,7 @@ void* shadow_server_thread(rdpShadowServer* server)
|
|||
|
||||
listener->Close(listener);
|
||||
|
||||
if (subsystem->Stop)
|
||||
{
|
||||
subsystem->Stop(subsystem);
|
||||
}
|
||||
shadow_subsystem_stop(server->subsystem);
|
||||
|
||||
ExitThread(0);
|
||||
|
||||
|
@ -459,6 +408,67 @@ int shadow_server_stop(rdpShadowServer* server)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int shadow_server_init_config_path(rdpShadowServer* server)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (!server->ConfigPath)
|
||||
{
|
||||
server->ConfigPath = GetEnvironmentSubPath("LOCALAPPDATA", "freerdp");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (!server->ConfigPath)
|
||||
{
|
||||
char* userLibraryPath;
|
||||
char* userApplicationSupportPath;
|
||||
|
||||
userLibraryPath = GetKnownSubPath(KNOWN_PATH_HOME, "Library");
|
||||
|
||||
if (userLibraryPath)
|
||||
{
|
||||
if (!PathFileExistsA(userLibraryPath))
|
||||
CreateDirectoryA(userLibraryPath, 0);
|
||||
|
||||
userApplicationSupportPath = GetCombinedPath(userLibraryPath, "Application Support");
|
||||
|
||||
if (userApplicationSupportPath)
|
||||
{
|
||||
if (!PathFileExistsA(userApplicationSupportPath))
|
||||
CreateDirectoryA(userApplicationSupportPath, 0);
|
||||
|
||||
server->ConfigPath = GetCombinedPath(userApplicationSupportPath, "freerdp");
|
||||
}
|
||||
|
||||
free(userLibraryPath);
|
||||
free(userApplicationSupportPath);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!server->ConfigPath)
|
||||
{
|
||||
char* configHome;
|
||||
|
||||
configHome = GetKnownPath(KNOWN_PATH_XDG_CONFIG_HOME);
|
||||
|
||||
if (configHome)
|
||||
{
|
||||
if (!PathFileExistsA(configHome))
|
||||
CreateDirectoryA(configHome, 0);
|
||||
|
||||
server->ConfigPath = GetKnownSubPath(KNOWN_PATH_XDG_CONFIG_HOME, "freerdp");
|
||||
|
||||
free(configHome);
|
||||
}
|
||||
}
|
||||
|
||||
if (!server->ConfigPath)
|
||||
return -1; /* no usable config path */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int shadow_server_init_certificate(rdpShadowServer* server)
|
||||
{
|
||||
char* filepath;
|
||||
|
@ -520,8 +530,17 @@ int shadow_server_init(rdpShadowServer* server)
|
|||
|
||||
WTSRegisterWtsApiFunctionTable(FreeRDP_InitWtsApi());
|
||||
|
||||
server->clients = ArrayList_New(TRUE);
|
||||
|
||||
server->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
InitializeCriticalSectionAndSpinCount(&(server->lock), 4000);
|
||||
|
||||
status = shadow_server_init_config_path(server);
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
status = shadow_server_init_certificate(server);
|
||||
|
||||
if (status < 0)
|
||||
|
@ -535,35 +554,14 @@ int shadow_server_init(rdpShadowServer* server)
|
|||
server->listener->info = (void*) server;
|
||||
server->listener->PeerAccepted = shadow_client_accepted;
|
||||
|
||||
#ifdef WITH_SHADOW_X11
|
||||
server->CreateSubsystem = X11_ShadowCreateSubsystem;
|
||||
#endif
|
||||
|
||||
#ifdef WITH_SHADOW_MAC
|
||||
server->CreateSubsystem = Mac_ShadowCreateSubsystem;
|
||||
#endif
|
||||
|
||||
#ifdef WITH_SHADOW_WIN
|
||||
server->CreateSubsystem = Win_ShadowCreateSubsystem;
|
||||
#endif
|
||||
|
||||
if (server->CreateSubsystem)
|
||||
server->subsystem = server->CreateSubsystem(server);
|
||||
server->subsystem = shadow_subsystem_new(NULL);
|
||||
|
||||
if (!server->subsystem)
|
||||
return -1;
|
||||
|
||||
server->subsystem->SurfaceUpdate = shadow_server_surface_update;
|
||||
status = shadow_subsystem_init(server->subsystem, server);
|
||||
|
||||
if (server->subsystem->Init)
|
||||
{
|
||||
status = server->subsystem->Init(server->subsystem);
|
||||
|
||||
if (status < 0)
|
||||
WLog_ERR(TAG, "subsystem init failure: %d", status);
|
||||
}
|
||||
|
||||
return 1;
|
||||
return status;
|
||||
}
|
||||
|
||||
int shadow_server_uninit(rdpShadowServer* server)
|
||||
|
@ -576,12 +574,6 @@ int shadow_server_uninit(rdpShadowServer* server)
|
|||
server->listener = NULL;
|
||||
}
|
||||
|
||||
if (server->subsystem)
|
||||
{
|
||||
server->subsystem->Free(server->subsystem);
|
||||
server->subsystem = NULL;
|
||||
}
|
||||
|
||||
if (server->CertificateFile)
|
||||
{
|
||||
free(server->CertificateFile);
|
||||
|
@ -600,6 +592,8 @@ int shadow_server_uninit(rdpShadowServer* server)
|
|||
server->ipcSocket = NULL;
|
||||
}
|
||||
|
||||
shadow_subsystem_uninit(server->subsystem);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -616,17 +610,6 @@ rdpShadowServer* shadow_server_new()
|
|||
server->mayView = TRUE;
|
||||
server->mayInteract = TRUE;
|
||||
|
||||
#ifdef _WIN32
|
||||
server->ConfigPath = GetEnvironmentSubPath("LOCALAPPDATA", "freerdp");
|
||||
#endif
|
||||
|
||||
if (!server->ConfigPath)
|
||||
server->ConfigPath = GetKnownSubPath(KNOWN_PATH_XDG_CONFIG_HOME, "freerdp");
|
||||
|
||||
InitializeCriticalSectionAndSpinCount(&(server->lock), 4000);
|
||||
|
||||
server->clients = ArrayList_New(TRUE);
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
|
@ -643,50 +626,8 @@ void shadow_server_free(rdpShadowServer* server)
|
|||
server->clients = NULL;
|
||||
}
|
||||
|
||||
shadow_server_uninit(server);
|
||||
shadow_subsystem_free(server->subsystem);
|
||||
|
||||
free(server);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
MSG msg;
|
||||
int status;
|
||||
DWORD dwExitCode;
|
||||
rdpShadowServer* server;
|
||||
|
||||
server = shadow_server_new();
|
||||
|
||||
if (!server)
|
||||
return 0;
|
||||
|
||||
if (shadow_server_init(server) < 0)
|
||||
return 0;
|
||||
|
||||
status = shadow_server_parse_command_line(server, argc, argv);
|
||||
|
||||
status = shadow_server_command_line_status_print(server, argc, argv, status);
|
||||
|
||||
if (status < 0)
|
||||
return 0;
|
||||
|
||||
if (shadow_server_start(server) < 0)
|
||||
return 0;
|
||||
|
||||
if (g_MessagePump)
|
||||
{
|
||||
while (GetMessage(&msg, 0, 0, 0))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
WaitForSingleObject(server->thread, INFINITE);
|
||||
|
||||
GetExitCodeThread(server->thread, &dwExitCode);
|
||||
|
||||
shadow_server_free(server);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,209 @@
|
|||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
*
|
||||
* Copyright 2014 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 "shadow.h"
|
||||
|
||||
#include "shadow_subsystem.h"
|
||||
|
||||
struct _RDP_SHADOW_SUBSYSTEM
|
||||
{
|
||||
const char* name;
|
||||
pfnShadowSubsystemEntry entry;
|
||||
};
|
||||
typedef struct _RDP_SHADOW_SUBSYSTEM RDP_SHADOW_SUBSYSTEM;
|
||||
|
||||
|
||||
#ifdef WITH_SHADOW_X11
|
||||
extern int X11_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_SHADOW_MAC
|
||||
extern int Mac_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_SHADOW_WIN
|
||||
extern int Win_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints);
|
||||
#endif
|
||||
|
||||
|
||||
static RDP_SHADOW_SUBSYSTEM g_Subsystems[] =
|
||||
{
|
||||
|
||||
#ifdef WITH_SHADOW_X11
|
||||
{ "X11", X11_ShadowSubsystemEntry },
|
||||
#endif
|
||||
|
||||
#ifdef WITH_SHADOW_MAC
|
||||
{ "Mac", Mac_ShadowSubsystemEntry },
|
||||
#endif
|
||||
|
||||
#ifdef WITH_SHADOW_WIN
|
||||
{ "Win", Win_ShadowSubsystemEntry },
|
||||
#endif
|
||||
|
||||
{ "", NULL }
|
||||
};
|
||||
|
||||
static int g_SubsystemCount = (sizeof(g_Subsystems) / sizeof(g_Subsystems[0]));
|
||||
|
||||
pfnShadowSubsystemEntry shadow_subsystem_load_static_entry(const char* name)
|
||||
{
|
||||
int index;
|
||||
|
||||
if (!name)
|
||||
{
|
||||
for (index = 0; index < g_SubsystemCount; index++)
|
||||
{
|
||||
if (g_Subsystems[index].name)
|
||||
return g_Subsystems[index].entry;
|
||||
}
|
||||
}
|
||||
|
||||
for (index = 0; index < g_SubsystemCount; index++)
|
||||
{
|
||||
if (strcmp(name, g_Subsystems[index].name) == 0)
|
||||
return g_Subsystems[index].entry;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int shadow_subsystem_load_entry_points(RDP_SHADOW_ENTRY_POINTS* pEntryPoints, const char* name)
|
||||
{
|
||||
pfnShadowSubsystemEntry entry;
|
||||
|
||||
entry = shadow_subsystem_load_static_entry(name);
|
||||
|
||||
if (!entry)
|
||||
return -1;
|
||||
|
||||
ZeroMemory(pEntryPoints, sizeof(RDP_SHADOW_ENTRY_POINTS));
|
||||
|
||||
if (entry(pEntryPoints) < 0)
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
rdpShadowSubsystem* shadow_subsystem_new(const char* name)
|
||||
{
|
||||
RDP_SHADOW_ENTRY_POINTS ep;
|
||||
rdpShadowSubsystem* subsystem = NULL;
|
||||
|
||||
shadow_subsystem_load_entry_points(&ep, name);
|
||||
|
||||
if (!ep.New)
|
||||
return NULL;
|
||||
|
||||
subsystem = ep.New();
|
||||
|
||||
if (!subsystem)
|
||||
return NULL;
|
||||
|
||||
CopyMemory(&(subsystem->ep), &ep, sizeof(RDP_SHADOW_ENTRY_POINTS));
|
||||
|
||||
return subsystem;
|
||||
}
|
||||
|
||||
void shadow_subsystem_free(rdpShadowSubsystem* subsystem)
|
||||
{
|
||||
if (subsystem->ep.Free)
|
||||
subsystem->ep.Free(subsystem);
|
||||
}
|
||||
|
||||
int shadow_subsystem_init(rdpShadowSubsystem* subsystem, rdpShadowServer* server)
|
||||
{
|
||||
int status;
|
||||
|
||||
subsystem->server = server;
|
||||
subsystem->selectedMonitor = server->selectedMonitor;
|
||||
|
||||
subsystem->MsgPipe = MessagePipe_New();
|
||||
subsystem->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
region16_init(&(subsystem->invalidRegion));
|
||||
|
||||
if (!subsystem->ep.Init)
|
||||
return -1;
|
||||
|
||||
status = subsystem->ep.Init(subsystem);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void shadow_subsystem_uninit(rdpShadowSubsystem* subsystem)
|
||||
{
|
||||
if (subsystem->ep.Uninit)
|
||||
subsystem->ep.Uninit(subsystem);
|
||||
|
||||
if (subsystem->MsgPipe)
|
||||
{
|
||||
MessagePipe_Free(subsystem->MsgPipe);
|
||||
subsystem->MsgPipe = NULL;
|
||||
}
|
||||
|
||||
if (subsystem->updateEvent)
|
||||
{
|
||||
CloseHandle(subsystem->updateEvent);
|
||||
subsystem->updateEvent = NULL;
|
||||
}
|
||||
|
||||
if (subsystem->invalidRegion.data)
|
||||
region16_uninit(&(subsystem->invalidRegion));
|
||||
}
|
||||
|
||||
int shadow_subsystem_start(rdpShadowSubsystem* subsystem)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (!subsystem->ep.Start)
|
||||
return -1;
|
||||
|
||||
status = subsystem->ep.Start(subsystem);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int shadow_subsystem_stop(rdpShadowSubsystem* subsystem)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (!subsystem->ep.Stop)
|
||||
return -1;
|
||||
|
||||
status = subsystem->ep.Stop(subsystem);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors, const char* name)
|
||||
{
|
||||
int numMonitors = 0;
|
||||
RDP_SHADOW_ENTRY_POINTS ep;
|
||||
|
||||
if (shadow_subsystem_load_entry_points(&ep, name) < 0)
|
||||
return -1;
|
||||
|
||||
numMonitors = ep.EnumMonitors(monitors, maxMonitors);
|
||||
|
||||
return numMonitors;
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
*
|
||||
* Copyright 2014 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_SHADOW_SERVER_SUBSYSTEM_H
|
||||
#define FREERDP_SHADOW_SERVER_SUBSYSTEM_H
|
||||
|
||||
#include <freerdp/server/shadow.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
|
||||
#define SHADOW_MSG_IN_REFRESH_OUTPUT_ID 1001
|
||||
#define SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID 1002
|
||||
|
||||
struct _SHADOW_MSG_IN_REFRESH_OUTPUT
|
||||
{
|
||||
UINT32 numRects;
|
||||
RECTANGLE_16* rects;
|
||||
};
|
||||
typedef struct _SHADOW_MSG_IN_REFRESH_OUTPUT SHADOW_MSG_IN_REFRESH_OUTPUT;
|
||||
|
||||
struct _SHADOW_MSG_IN_SUPPRESS_OUTPUT
|
||||
{
|
||||
BOOL allow;
|
||||
RECTANGLE_16 rect;
|
||||
};
|
||||
typedef struct _SHADOW_MSG_IN_SUPPRESS_OUTPUT SHADOW_MSG_IN_SUPPRESS_OUTPUT;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
rdpShadowSubsystem* shadow_subsystem_new(const char* name);
|
||||
void shadow_subsystem_free(rdpShadowSubsystem* subsystem);
|
||||
|
||||
int shadow_subsystem_init(rdpShadowSubsystem* subsystem, rdpShadowServer* server);
|
||||
void shadow_subsystem_uninit(rdpShadowSubsystem* subsystem);
|
||||
|
||||
int shadow_subsystem_start(rdpShadowSubsystem* subsystem);
|
||||
int shadow_subsystem_stop(rdpShadowSubsystem* subsystem);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_SHADOW_SERVER_SUBSYSTEM_H */
|
||||
|
|
@ -48,7 +48,6 @@ char* openssl_get_ssl_error_string(int ssl_error)
|
|||
return "SSL_ERROR_SYSCALL";
|
||||
|
||||
case SSL_ERROR_SSL:
|
||||
ERR_print_errors_fp(stdout);
|
||||
return "SSL_ERROR_SSL";
|
||||
}
|
||||
|
||||
|
|
|
@ -300,6 +300,7 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
|
|||
int status;
|
||||
WINPR_EVENT* event;
|
||||
event = (WINPR_EVENT*) Object;
|
||||
|
||||
status = waitOnFd(event->pipe_fd[0], dwMilliseconds);
|
||||
|
||||
if (status < 0)
|
||||
|
|
|
@ -111,6 +111,7 @@ void MessageQueue_Post(wMessageQueue* queue, void* context, UINT32 type, void* w
|
|||
message.id = type;
|
||||
message.wParam = wParam;
|
||||
message.lParam = lParam;
|
||||
message.Free = NULL;
|
||||
|
||||
MessageQueue_Dispatch(queue, &message);
|
||||
}
|
||||
|
|
|
@ -40,7 +40,6 @@ struct _MAKECERT_CONTEXT
|
|||
int argc;
|
||||
char** argv;
|
||||
|
||||
BIO* bio;
|
||||
RSA* rsa;
|
||||
X509* x509;
|
||||
EVP_PKEY* pkey;
|
||||
|
@ -454,7 +453,9 @@ int makecert_context_set_output_file_name(MAKECERT_CONTEXT* context, char* name)
|
|||
int makecert_context_output_certificate_file(MAKECERT_CONTEXT* context, char* path)
|
||||
{
|
||||
FILE* fp;
|
||||
int status;
|
||||
int length;
|
||||
int offset;
|
||||
char* filename;
|
||||
char* fullpath;
|
||||
|
||||
|
@ -485,6 +486,9 @@ int makecert_context_output_certificate_file(MAKECERT_CONTEXT* context, char* pa
|
|||
|
||||
if (fp)
|
||||
{
|
||||
BIO* bio;
|
||||
BYTE* x509_str;
|
||||
|
||||
if (context->pfxFormat)
|
||||
{
|
||||
if (!context->password)
|
||||
|
@ -497,17 +501,136 @@ int makecert_context_output_certificate_file(MAKECERT_CONTEXT* context, char* pa
|
|||
OpenSSL_add_all_ciphers();
|
||||
OpenSSL_add_all_digests();
|
||||
|
||||
context->pkcs12 = PKCS12_create(context->password, context->default_name, context->pkey,
|
||||
context->x509, NULL, 0, 0, 0, 0, 0);
|
||||
context->pkcs12 = PKCS12_create(context->password, context->default_name,
|
||||
context->pkey, context->x509, NULL, 0, 0, 0, 0, 0);
|
||||
|
||||
i2d_PKCS12_fp(fp, context->pkcs12);
|
||||
bio = BIO_new(BIO_s_mem());
|
||||
|
||||
if (!bio)
|
||||
return -1;
|
||||
|
||||
status = i2d_PKCS12_bio(bio, context->pkcs12);
|
||||
|
||||
offset = 0;
|
||||
length = 2048;
|
||||
x509_str = (BYTE*) malloc(length);
|
||||
|
||||
status = BIO_read(bio, x509_str, length);
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
offset += status;
|
||||
|
||||
while (offset >= length)
|
||||
{
|
||||
length *= 2;
|
||||
x509_str = (BYTE*) realloc(x509_str, length);
|
||||
|
||||
status = BIO_read(bio, &x509_str[offset], length);
|
||||
|
||||
if (status < 0)
|
||||
break;
|
||||
|
||||
offset += status;
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
length = offset;
|
||||
|
||||
fwrite((void*) x509_str, length, 1, fp);
|
||||
|
||||
free(x509_str);
|
||||
BIO_free(bio);
|
||||
}
|
||||
else
|
||||
{
|
||||
PEM_write_X509(fp, context->x509);
|
||||
bio = BIO_new(BIO_s_mem());
|
||||
|
||||
if (!bio)
|
||||
return -1;
|
||||
|
||||
status = PEM_write_bio_X509(bio, context->x509);
|
||||
|
||||
offset = 0;
|
||||
length = 2048;
|
||||
x509_str = (BYTE*) malloc(length);
|
||||
|
||||
status = BIO_read(bio, x509_str, length);
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
offset += status;
|
||||
|
||||
while (offset >= length)
|
||||
{
|
||||
length *= 2;
|
||||
x509_str = (BYTE*) realloc(x509_str, length);
|
||||
|
||||
status = BIO_read(bio, &x509_str[offset], length);
|
||||
|
||||
if (status < 0)
|
||||
break;
|
||||
|
||||
offset += status;
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
length = offset;
|
||||
|
||||
fwrite((void*) x509_str, length, 1, fp);
|
||||
|
||||
free(x509_str);
|
||||
BIO_free(bio);
|
||||
|
||||
if (context->pemFormat)
|
||||
PEM_write_PrivateKey(fp, context->pkey, NULL, NULL, 0, NULL, NULL);
|
||||
{
|
||||
bio = BIO_new(BIO_s_mem());
|
||||
|
||||
if (!bio)
|
||||
return -1;
|
||||
|
||||
status = PEM_write_bio_PrivateKey(bio, context->pkey, NULL, NULL, 0, NULL, NULL);
|
||||
|
||||
offset = 0;
|
||||
length = 2048;
|
||||
x509_str = (BYTE*) malloc(length);
|
||||
|
||||
status = BIO_read(bio, x509_str, length);
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
offset += status;
|
||||
|
||||
while (offset >= length)
|
||||
{
|
||||
length *= 2;
|
||||
x509_str = (BYTE*) realloc(x509_str, length);
|
||||
|
||||
status = BIO_read(bio, &x509_str[offset], length);
|
||||
|
||||
if (status < 0)
|
||||
break;
|
||||
|
||||
offset += status;
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
length = offset;
|
||||
|
||||
fwrite((void*) x509_str, length, 1, fp);
|
||||
|
||||
free(x509_str);
|
||||
BIO_free(bio);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
@ -522,7 +645,9 @@ int makecert_context_output_certificate_file(MAKECERT_CONTEXT* context, char* pa
|
|||
int makecert_context_output_private_key_file(MAKECERT_CONTEXT* context, char* path)
|
||||
{
|
||||
FILE* fp;
|
||||
int status;
|
||||
int length;
|
||||
int offset;
|
||||
char* filename;
|
||||
char* fullpath;
|
||||
|
||||
|
@ -551,7 +676,50 @@ int makecert_context_output_private_key_file(MAKECERT_CONTEXT* context, char* pa
|
|||
|
||||
if (fp)
|
||||
{
|
||||
PEM_write_PrivateKey(fp, context->pkey, NULL, NULL, 0, NULL, NULL);
|
||||
BIO* bio;
|
||||
BYTE* x509_str;
|
||||
|
||||
bio = BIO_new(BIO_s_mem());
|
||||
|
||||
if (!bio)
|
||||
return -1;
|
||||
|
||||
status = PEM_write_bio_PrivateKey(bio, context->pkey, NULL, NULL, 0, NULL, NULL);
|
||||
|
||||
offset = 0;
|
||||
length = 2048;
|
||||
x509_str = (BYTE*) malloc(length);
|
||||
|
||||
status = BIO_read(bio, x509_str, length);
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
offset += status;
|
||||
|
||||
while (offset >= length)
|
||||
{
|
||||
length *= 2;
|
||||
x509_str = (BYTE*) realloc(x509_str, length);
|
||||
|
||||
status = BIO_read(bio, &x509_str[offset], length);
|
||||
|
||||
if (status < 0)
|
||||
break;
|
||||
|
||||
offset += status;
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
length = offset;
|
||||
|
||||
fwrite((void*) x509_str, length, 1, fp);
|
||||
|
||||
free(x509_str);
|
||||
BIO_free(bio);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
|
@ -582,9 +750,6 @@ int makecert_context_process(MAKECERT_CONTEXT* context, int argc, char** argv)
|
|||
if (!context->common_name)
|
||||
context->common_name = _strdup(context->default_name);
|
||||
|
||||
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
|
||||
context->bio = BIO_new_fp(stderr, BIO_NOCLOSE);
|
||||
|
||||
if (!context->pkey)
|
||||
context->pkey = EVP_PKEY_new();
|
||||
|
||||
|
@ -712,7 +877,55 @@ int makecert_context_process(MAKECERT_CONTEXT* context, int argc, char** argv)
|
|||
*/
|
||||
|
||||
if (!context->silent)
|
||||
X509_print_fp(stdout, context->x509);
|
||||
{
|
||||
BIO* bio;
|
||||
int status;
|
||||
int length;
|
||||
int offset;
|
||||
BYTE* x509_str;
|
||||
|
||||
bio = BIO_new(BIO_s_mem());
|
||||
|
||||
if (!bio)
|
||||
return -1;
|
||||
|
||||
status = X509_print(bio, context->x509);
|
||||
|
||||
offset = 0;
|
||||
length = 2048;
|
||||
x509_str = (BYTE*) malloc(length + 1);
|
||||
|
||||
status = BIO_read(bio, x509_str, length);
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
offset += status;
|
||||
|
||||
while (offset >= length)
|
||||
{
|
||||
length *= 2;
|
||||
x509_str = (BYTE*) realloc(x509_str, length + 1);
|
||||
|
||||
status = BIO_read(bio, &x509_str[offset], length);
|
||||
|
||||
if (status < 0)
|
||||
break;
|
||||
|
||||
offset += status;
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
length = offset;
|
||||
x509_str[length] = '\0';
|
||||
|
||||
printf("%s", x509_str);
|
||||
|
||||
free(x509_str);
|
||||
BIO_free(bio);
|
||||
}
|
||||
|
||||
/**
|
||||
* Output certificate and private key to files
|
||||
|
@ -757,9 +970,6 @@ void makecert_context_free(MAKECERT_CONTEXT* context)
|
|||
|
||||
CRYPTO_cleanup_all_ex_data();
|
||||
|
||||
CRYPTO_mem_leaks(context->bio);
|
||||
BIO_free(context->bio);
|
||||
|
||||
free(context);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue