Merge pull request #2124 from awakecoding/shadow

Shadow Improvements, Server-Side Fixes
This commit is contained in:
Marc-André Moreau 2014-09-25 11:03:18 -04:00
commit ff07469386
52 changed files with 2228 additions and 1132 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 */

View File

@ -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)

View File

@ -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;

View File

@ -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))

View File

@ -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;
}

View File

@ -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;

View File

@ -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 */

View File

@ -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;

View File

@ -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);

View File

@ -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");

View File

@ -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;

View File

@ -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];

View File

@ -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 */

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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)

View File

@ -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")

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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;
}

82
server/shadow/shadow.c Normal file
View File

@ -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;
}

View File

@ -28,6 +28,7 @@
#include "shadow_encoder.h"
#include "shadow_capture.h"
#include "shadow_channels.h"
#include "shadow_subsystem.h"
#ifdef __cplusplus
extern "C" {

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 */

View File

@ -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";
}

View File

@ -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)

View File

@ -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);
}

View File

@ -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);
}
}