Fix unchecked CreateEvent calls and misc fixes

1)
Added missing checks for CreateEvent which also required the
following related changes:

- changed freerdp_context_new API to BOOL
- changed freerdp_peer_context_new API to BOOL
- changed pRdpClientNew callback to BOOL
- changed pContextNew callback to BOOL
- changed psPeerAccepted callback to BOOL
- changed psPeerContextNew callback to BOOL

2)
Fixed lots of missing alloc and error checks in the
changed code's neighbourhood.

3)
Check freerdp_client_codecs_prepare result to avoid segfaults
caused by using non-initialized codecs.

4)
Fixed deadlocks in x11 caused by missing xf_unlock_x11() calls
in some error handlers

5)
Some fixes in thread pool:
- DEFAULT_POOL assignment did not match TP_POOL definition
- don't free the pool pointer if it points to the static DEFAULT_POOL
- added error handling and cleanup in InitializeThreadpool
This commit is contained in:
Norbert Federa 2015-04-28 17:00:41 +02:00
parent 19dc7b7440
commit ef1fd12b15
54 changed files with 975 additions and 399 deletions

View File

@ -326,12 +326,23 @@ int android_cliprdr_server_file_contents_response(CliprdrClientContext* cliprdr,
int android_cliprdr_init(androidContext* afc, CliprdrClientContext* cliprdr)
{
cliprdr->custom = (void*) afc;
wClipboard* clipboard;
HANDLE hevent;
if (!(hevent = CreateEvent(NULL, TRUE, FALSE, NULL)))
return 0;
if (!(clipboard = ClipboardCreate()))
{
CloseHandle(hevent);
return 0;
}
afc->cliprdr = cliprdr;
afc->clipboard = clipboard;
afc->clipboardRequestEvent = hevent;
afc->clipboard = ClipboardCreate();
afc->clipboardRequestEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
cliprdr->custom = (void*) afc;
cliprdr->MonitorReady = android_cliprdr_monitor_ready;
cliprdr->ServerCapabilities = android_cliprdr_server_capabilities;
cliprdr->ServerFormatList = android_cliprdr_server_format_list;

View File

@ -48,17 +48,22 @@
#include "jni/prof.h"
#endif
int android_context_new(freerdp* instance, rdpContext* context)
BOOL android_context_new(freerdp* instance, rdpContext* context)
{
context->channels = freerdp_channels_new();
if (!(context->channels = freerdp_channels_new()))
return FALSE;
android_event_queue_init(instance);
return 0;
return TRUE;
}
void android_context_free(freerdp* instance, rdpContext* context)
{
freerdp_channels_close(instance->context->channels, instance);
freerdp_channels_free(context->channels);
if (context && context->channels)
{
freerdp_channels_close(context->channels, instance);
freerdp_channels_free(context->channels);
context->channels = NULL;
}
android_event_queue_uninit(instance);
}
@ -622,7 +627,8 @@ JNIEXPORT jint JNICALL jni_freerdp_new(JNIEnv *env, jclass cls)
#endif
// create instance
instance = freerdp_new();
if (!(instance = freerdp_new()))
return NULL;
instance->PreConnect = android_pre_connect;
instance->PostConnect = android_post_connect;
instance->PostDisconnect = android_post_disconnect;
@ -634,7 +640,12 @@ JNIEXPORT jint JNICALL jni_freerdp_new(JNIEnv *env, jclass cls)
instance->ContextSize = sizeof(androidContext);
instance->ContextNew = android_context_new;
instance->ContextFree = android_context_free;
freerdp_context_new(instance);
if (!freerdp_context_new(instance))
{
freerdp_free(instance);
instance = NULL;
}
return (jint) instance;
}

View File

@ -49,15 +49,22 @@ struct thread_data
freerdp* instance;
};
int df_context_new(freerdp* instance, rdpContext* context)
BOOL df_context_new(freerdp* instance, rdpContext* context)
{
context->channels = freerdp_channels_new();
return 0;
if (!(context->channels = freerdp_channels_new()))
return FALSE;
return TRUE;
}
void df_context_free(freerdp* instance, rdpContext* context)
{
if (context && context->channels)
{
freerdp_channels_close(context->channels, instance);
freerdp_channels_free(context->channels);
context->channels = NULL;
}
}
void df_begin_paint(rdpContext* context)
@ -458,7 +465,12 @@ int main(int argc, char* argv[])
instance->ContextSize = sizeof(dfContext);
instance->ContextNew = df_context_new;
instance->ContextFree = df_context_free;
freerdp_context_new(instance);
if (!freerdp_context_new(instance))
{
WLog_ERR(TAG, "Failed to create FreeRDP context");
exit(1);
}
context = (dfContext*) instance->context;
channels = instance->context->channels;

View File

@ -45,10 +45,12 @@ struct tf_context
};
typedef struct tf_context tfContext;
static int tf_context_new(freerdp* instance, rdpContext* context)
static BOOL tf_context_new(freerdp* instance, rdpContext* context)
{
context->channels = freerdp_channels_new();
return 0;
if (!(context->channels = freerdp_channels_new()))
return FALSE;
return TRUE;
}
static void tf_context_free(freerdp* instance, rdpContext* context)
@ -57,6 +59,7 @@ static void tf_context_free(freerdp* instance, rdpContext* context)
{
freerdp_channels_close(context->channels, instance);
freerdp_channels_free(context->channels);
context->channels = NULL;
}
}
@ -184,7 +187,8 @@ int main(int argc, char* argv[])
instance->ContextSize = sizeof(tfContext);
instance->ContextNew = tf_context_new;
instance->ContextFree = tf_context_free;
if (freerdp_context_new(instance) != 0)
if (!freerdp_context_new(instance))
{
WLog_ERR(TAG, "Couldn't create context");
exit(1);

View File

@ -26,11 +26,12 @@
#include "wlfreerdp.h"
static int wl_context_new(freerdp* instance, rdpContext* context)
static BOOL wl_context_new(freerdp* instance, rdpContext* context)
{
context->channels = freerdp_channels_new();
if (!(context->channels = freerdp_channels_new()))
return FALSE;
return 0;
return TRUE;
}
static void wl_context_free(freerdp* instance, rdpContext* context)
@ -39,6 +40,7 @@ static void wl_context_free(freerdp* instance, rdpContext* context)
{
freerdp_channels_close(context->channels, instance);
freerdp_channels_free(context->channels);
context->channels = NULL;
}
}

View File

@ -1012,11 +1012,15 @@ void wfreerdp_client_global_uninit(void)
WSACleanup();
}
int wfreerdp_client_new(freerdp* instance, rdpContext* context)
BOOL wfreerdp_client_new(freerdp* instance, rdpContext* context)
{
wfContext* wfc = (wfContext*) context;
wfreerdp_client_global_init();
if (!(wfreerdp_client_global_init()))
return FALSE;
if (!(context->channels = freerdp_channels_new()))
return FALSE;
instance->PreConnect = wf_pre_connect;
instance->PostConnect = wf_post_connect;
@ -1025,20 +1029,27 @@ int wfreerdp_client_new(freerdp* instance, rdpContext* context)
wfc->instance = instance;
wfc->settings = instance->settings;
context->channels = freerdp_channels_new();
return 0;
return TRUE;
}
void wfreerdp_client_free(freerdp* instance, rdpContext* context)
{
rdpChannels* channels = context->channels;
if (!context)
return;
if (context->channels)
{
freerdp_channels_close(context->channels, instance);
freerdp_channels_free(context->channels);
context->channels = NULL;
}
if (context->cache)
{
cache_free(context->cache);
freerdp_channels_close(channels, instance);
freerdp_channels_free(context->channels);
context->cache = NULL;
}
}
int wfreerdp_client_start(rdpContext* context)

View File

@ -1975,10 +1975,36 @@ void wf_cliprdr_init(wfContext* wfc, CliprdrClientContext* cliprdr)
clipboard = wfc->clipboard;
clipboard->wfc = wfc;
clipboard->context = cliprdr;
cliprdr->custom = (void*) wfc->clipboard;
clipboard->context = cliprdr;
clipboard->channels = context->channels;
clipboard->sync = FALSE;
clipboard->map_capacity = 32;
clipboard->map_size = 0;
if (!(clipboard->format_mappings = (formatMapping*) calloc(1, sizeof(formatMapping) * clipboard->map_capacity)))
goto fail_format_mappings;
clipboard->file_array_size = 32;
if (!(clipboard->file_names = (WCHAR**) calloc(1, clipboard->file_array_size * sizeof(WCHAR*))))
goto fail_file_names;
if (!(clipboard->fileDescriptor = (FILEDESCRIPTORW**) calloc(1, clipboard->file_array_size * sizeof(FILEDESCRIPTORW*))))
goto fail_file_descriptor;
if (!(clipboard->response_data_event = CreateEvent(NULL, TRUE, FALSE, _T("response_data_event"))))
goto fail_data_event;
if (!(clipboard->req_fevent = CreateEvent(NULL, TRUE, FALSE, _T("request_filecontents_event"))))
goto fail_filecontents_event;
clipboard->ID_FILEDESCRIPTORW = RegisterClipboardFormatW(CFSTR_FILEDESCRIPTORW);
clipboard->ID_FILECONTENTS = RegisterClipboardFormatW(CFSTR_FILECONTENTS);
clipboard->ID_PREFERREDDROPEFFECT = RegisterClipboardFormatW(CFSTR_PREFERREDDROPEFFECT);
if (!(clipboard->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) cliprdr_thread_func, clipboard, 0, NULL)))
goto fail_clipboard_thread;
cliprdr->MonitorReady = wf_cliprdr_monitor_ready;
cliprdr->ServerCapabilities = wf_cliprdr_server_capabilities;
cliprdr->ServerFormatList = wf_cliprdr_server_format_list;
@ -1989,27 +2015,30 @@ void wf_cliprdr_init(wfContext* wfc, CliprdrClientContext* cliprdr)
cliprdr->ServerFormatDataResponse = wf_cliprdr_server_format_data_response;
cliprdr->ServerFileContentsRequest = wf_cliprdr_server_file_contents_request;
cliprdr->ServerFileContentsResponse = wf_cliprdr_server_file_contents_response;
cliprdr->custom = (void*) wfc->clipboard;
clipboard->channels = context->channels;
clipboard->sync = FALSE;
return;
clipboard->map_capacity = 32;
clipboard->map_size = 0;
fail_clipboard_thread:
CloseHandle(clipboard->req_fevent);
clipboard->req_fevent = NULL;
fail_filecontents_event:
CloseHandle(clipboard->response_data_event);
clipboard->response_data_event = NULL;
fail_data_event:
free(clipboard->fileDescriptor);
clipboard->fileDescriptor = NULL;
fail_file_descriptor:
free(clipboard->file_names);
clipboard->file_names = NULL;
fail_file_names:
free(clipboard->format_mappings);
clipboard->format_mappings = NULL;
fail_format_mappings:
free(wfc->clipboard);
wfc->clipboard = NULL;
clipboard->format_mappings = (formatMapping*) calloc(1, sizeof(formatMapping) * clipboard->map_capacity);
clipboard->file_array_size = 32;
clipboard->file_names = (WCHAR**) calloc(1, clipboard->file_array_size * sizeof(WCHAR*));
clipboard->fileDescriptor = (FILEDESCRIPTORW**) calloc(1, clipboard->file_array_size * sizeof(FILEDESCRIPTORW*));
clipboard->response_data_event = CreateEvent(NULL, TRUE, FALSE, _T("response_data_event"));
clipboard->req_fevent = CreateEvent(NULL, TRUE, FALSE, _T("request_filecontents_event"));
clipboard->ID_FILEDESCRIPTORW = RegisterClipboardFormatW(CFSTR_FILEDESCRIPTORW);
clipboard->ID_FILECONTENTS = RegisterClipboardFormatW(CFSTR_FILECONTENTS);
clipboard->ID_PREFERREDDROPEFFECT = RegisterClipboardFormatW(CFSTR_PREFERREDDROPEFFECT);
clipboard->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) cliprdr_thread_func, clipboard, 0, NULL);
return;
}
void wf_cliprdr_uninit(wfContext* wfc, CliprdrClientContext* cliprdr)

View File

@ -406,14 +406,16 @@ BOOL wf_gdi_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmapUpdate)
if (bitsPerPixel < 32)
{
freerdp_client_codecs_prepare(codecs, FREERDP_CODEC_INTERLEAVED);
if (!freerdp_client_codecs_prepare(codecs, FREERDP_CODEC_INTERLEAVED))
return FALSE;
status = interleaved_decompress(codecs->interleaved, pSrcData, SrcSize, bitsPerPixel,
&pDstData, PIXEL_FORMAT_XRGB32, nWidth * 4, 0, 0, nWidth, nHeight, NULL);
}
else
{
freerdp_client_codecs_prepare(codecs, FREERDP_CODEC_PLANAR);
if (!freerdp_client_codecs_prepare(codecs, FREERDP_CODEC_PLANAR))
return FALSE;
status = planar_decompress(codecs->planar, pSrcData, SrcSize, &pDstData,
PIXEL_FORMAT_XRGB32, nWidth * 4, 0, 0, nWidth, nHeight, TRUE);
@ -675,7 +677,9 @@ void wf_gdi_surface_bits(wfContext* wfc, SURFACE_BITS_COMMAND* surface_bits_comm
if (surface_bits_command->codecID == RDP_CODEC_ID_REMOTEFX)
{
freerdp_client_codecs_prepare(wfc->codecs, FREERDP_CODEC_REMOTEFX);
if (!freerdp_client_codecs_prepare(wfc->codecs, FREERDP_CODEC_REMOTEFX))
return;
if (!(message = rfx_process_message(wfc->codecs->rfx, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength)))
{
WLog_ERR(TAG, "Failed to process RemoteFX message");
@ -715,7 +719,9 @@ void wf_gdi_surface_bits(wfContext* wfc, SURFACE_BITS_COMMAND* surface_bits_comm
}
else if (surface_bits_command->codecID == RDP_CODEC_ID_NSCODEC)
{
freerdp_client_codecs_prepare(wfc->codecs, FREERDP_CODEC_NSCODEC);
if (!freerdp_client_codecs_prepare(wfc->codecs, FREERDP_CODEC_NSCODEC))
return;
nsc_process_message(wfc->codecs->nsc, surface_bits_command->bpp, surface_bits_command->width, surface_bits_command->height,
surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength);
ZeroMemory(&bitmap_info, sizeof(bitmap_info));

View File

@ -171,14 +171,16 @@ void wf_Bitmap_Decompress(wfContext* wfc, rdpBitmap* bitmap,
{
if (bpp < 32)
{
freerdp_client_codecs_prepare(wfc->codecs, FREERDP_CODEC_INTERLEAVED);
if (!freerdp_client_codecs_prepare(wfc->codecs, FREERDP_CODEC_INTERLEAVED))
return;
status = interleaved_decompress(wfc->codecs->interleaved, pSrcData, SrcSize, bpp,
&pDstData, PIXEL_FORMAT_XRGB32, width * 4, 0, 0, width, height, NULL);
}
else
{
freerdp_client_codecs_prepare(wfc->codecs, FREERDP_CODEC_PLANAR);
if (!freerdp_client_codecs_prepare(wfc->codecs, FREERDP_CODEC_PLANAR))
return;
status = planar_decompress(wfc->codecs->planar, pSrcData, SrcSize, &pDstData,
PIXEL_FORMAT_XRGB32, width * 4, 0, 0, width, height, TRUE);

View File

@ -1658,19 +1658,27 @@ static int xfreerdp_client_stop(rdpContext* context)
return 0;
}
static int xfreerdp_client_new(freerdp* instance, rdpContext* context)
static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context)
{
rdpSettings* settings;
xfContext* xfc = (xfContext*) instance->context;
assert(context);
assert(xfc);
assert(!context->channels);
assert(!xfc->display);
assert(!xfc->mutex);
assert(!xfc->x11event);
if (!(context->channels = freerdp_channels_new()))
goto fail_channels_new;
instance->PreConnect = xf_pre_connect;
instance->PostConnect = xf_post_connect;
instance->PostDisconnect = xf_post_disconnect;
instance->Authenticate = xf_authenticate;
instance->VerifyCertificate = xf_verify_certificate;
instance->LogonErrorInfo = xf_logon_error_info;
assert(!context->channels);
context->channels = freerdp_channels_new();
settings = instance->settings;
xfc->settings = instance->context->settings;
@ -1693,23 +1701,21 @@ static int xfreerdp_client_new(freerdp* instance, rdpContext* context)
}
}
assert(!xfc->display);
xfc->display = XOpenDisplay(NULL);
if (!xfc->display)
{
WLog_ERR(TAG, "failed to open display: %s", XDisplayName(NULL));
WLog_ERR(TAG, "Please check that the $DISPLAY environment variable is properly set.");
return -1;
goto fail_open_display;
}
assert(!xfc->mutex);
xfc->mutex = CreateMutex(NULL, FALSE, NULL);
if (!xfc->mutex)
{
WLog_ERR(TAG, "Could not create mutex!");
return -1;
goto fail_create_mutex;
}
xfc->_NET_WM_ICON = XInternAtom(xfc->display, "_NET_WM_ICON", False);
@ -1741,8 +1747,13 @@ static int xfreerdp_client_new(freerdp* instance, rdpContext* context)
xfc->invert = (ImageByteOrder(xfc->display) == MSBFirst) ? TRUE : FALSE;
xfc->complex_regions = TRUE;
assert(!xfc->x11event);
xfc->x11event = CreateFileDescriptorEvent(NULL, FALSE, FALSE, xfc->xfds);
if (!xfc->x11event)
{
WLog_ERR(TAG, "Could not create xfds event");
goto fail_xfds_event;
}
xfc->colormap = DefaultColormap(xfc->display, xfc->screen_number);
xfc->format = PIXEL_FORMAT_XRGB32;
@ -1767,14 +1778,33 @@ static int xfreerdp_client_new(freerdp* instance, rdpContext* context)
xf_check_extensions(xfc);
if (!xf_get_pixmap_info(xfc))
return -1;
{
WLog_ERR(TAG, "Failed to get pixmap info");
goto fail_pixmap_info;
}
xfc->vscreen.monitors = calloc(16, sizeof(MONITOR_INFO));
if (!xfc->vscreen.monitors)
return -1;
goto fail_vscreen_monitors;
return 0;
return TRUE;
fail_vscreen_monitors:
fail_pixmap_info:
CloseHandle(xfc->x11event);
xfc->x11event = NULL;
fail_xfds_event:
CloseHandle(xfc->mutex);
xfc->mutex = NULL;
fail_create_mutex:
XCloseDisplay(xfc->display);
xfc->display = NULL;
fail_open_display:
freerdp_channels_free(context->channels);
context->channels = NULL;
fail_channels_new:
return FALSE;
}
static void xfreerdp_client_free(freerdp* instance, rdpContext* context)

View File

@ -385,14 +385,16 @@ BOOL xf_gdi_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmapUpdate)
if (bitsPerPixel < 32)
{
freerdp_client_codecs_prepare(codecs, FREERDP_CODEC_INTERLEAVED);
if (!freerdp_client_codecs_prepare(codecs, FREERDP_CODEC_INTERLEAVED))
return FALSE;
status = interleaved_decompress(codecs->interleaved, pSrcData, SrcSize, bitsPerPixel,
&pDstData, xfc->format, -1, 0, 0, nWidth, nHeight, xfc->palette);
}
else
{
freerdp_client_codecs_prepare(codecs, FREERDP_CODEC_PLANAR);
if (!freerdp_client_codecs_prepare(codecs, FREERDP_CODEC_PLANAR))
return FALSE;
status = planar_decompress(codecs->planar, pSrcData, SrcSize, &pDstData,
xfc->format, -1, 0, 0, nWidth, nHeight, TRUE);
@ -1176,11 +1178,16 @@ BOOL xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd)
if (cmd->codecID == RDP_CODEC_ID_REMOTEFX)
{
freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_REMOTEFX);
if (!freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_REMOTEFX))
{
xf_unlock_x11(xfc, FALSE);
return FALSE;
}
if (!(message = rfx_process_message(xfc->codecs->rfx, cmd->bitmapData, cmd->bitmapDataLength)))
{
WLog_ERR(TAG, "Failed to process RemoteFX message");
xf_unlock_x11(xfc, FALSE);
return FALSE;
}
@ -1196,7 +1203,12 @@ BOOL xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd)
xfc->bitmap_buffer = (BYTE*) _aligned_realloc(xfc->bitmap_buffer, xfc->bitmap_size, 16);
if (!xfc->bitmap_buffer)
{
rfx_message_free(xfc->codecs->rfx, message);
XSetClipMask(xfc->display, xfc->gc, None);
xf_unlock_x11(xfc, FALSE);
return FALSE;
}
}
/* Draw the tiles to primary surface, each is 64x64. */
@ -1241,7 +1253,11 @@ BOOL xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd)
}
else if (cmd->codecID == RDP_CODEC_ID_NSCODEC)
{
freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_NSCODEC);
if (!freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_NSCODEC))
{
xf_unlock_x11(xfc, FALSE);
return FALSE;
}
nsc_process_message(xfc->codecs->nsc, cmd->bpp, cmd->width, cmd->height, cmd->bitmapData, cmd->bitmapDataLength);
@ -1254,7 +1270,10 @@ BOOL xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd)
xfc->bitmap_buffer = (BYTE*) _aligned_realloc(xfc->bitmap_buffer, xfc->bitmap_size, 16);
if (!xfc->bitmap_buffer)
{
xf_unlock_x11(xfc, FALSE);
return FALSE;
}
}
pSrcData = xfc->codecs->nsc->BitmapData;
@ -1286,7 +1305,10 @@ BOOL xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd)
xfc->bitmap_buffer = (BYTE*) _aligned_realloc(xfc->bitmap_buffer, xfc->bitmap_size, 16);
if (!xfc->bitmap_buffer)
{
xf_unlock_x11(xfc, FALSE);
return FALSE;
}
}
pSrcData = cmd->bitmapData;

View File

@ -263,7 +263,8 @@ int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDP
REGION16 clippingRects;
RECTANGLE_16 clippingRect;
freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_REMOTEFX);
if (!freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_REMOTEFX))
return -1;
surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
@ -337,7 +338,8 @@ int xf_SurfaceCommand_ClearCodec(xfContext* xfc, RdpgfxClientContext* context, R
xfGfxSurface* surface;
RECTANGLE_16 invalidRect;
freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_CLEARCODEC);
if (!freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_CLEARCODEC))
return -1;
surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
@ -375,7 +377,8 @@ int xf_SurfaceCommand_Planar(xfContext* xfc, RdpgfxClientContext* context, RDPGF
xfGfxSurface* surface;
RECTANGLE_16 invalidRect;
freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_PLANAR);
if (!freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_PLANAR))
return -1;
surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
@ -410,7 +413,8 @@ int xf_SurfaceCommand_H264(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_
RDPGFX_H264_METABLOCK* meta;
RDPGFX_H264_BITMAP_STREAM* bs;
freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_H264);
if (!freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_H264))
return -1;
h264 = xfc->codecs->h264;
@ -455,7 +459,8 @@ int xf_SurfaceCommand_Alpha(xfContext* xfc, RdpgfxClientContext* context, RDPGFX
xfGfxSurface* surface;
RECTANGLE_16 invalidRect;
freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_ALPHACODEC);
if (!freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_ALPHACODEC))
return -1;
surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
@ -500,7 +505,8 @@ int xf_SurfaceCommand_Progressive(xfContext* xfc, RdpgfxClientContext* context,
RFX_PROGRESSIVE_TILE* tile;
PROGRESSIVE_BLOCK_REGION* region;
freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_PROGRESSIVE);
if (!freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_PROGRESSIVE))
return -1;
surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);

View File

@ -64,10 +64,11 @@ BOOL xf_Bitmap_New(rdpContext* context, rdpBitmap* bitmap)
if (depth != xfc->depth)
{
data = _aligned_malloc(bitmap->width * bitmap->height * 4, 16);
if (!data)
if (!(data = _aligned_malloc(bitmap->width * bitmap->height * 4, 16)))
{
xf_unlock_x11(xfc, FALSE);
return FALSE;
}
SrcFormat = gdi_get_pixel_format(bitmap->bpp, TRUE);
@ -162,14 +163,16 @@ BOOL xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
{
if (bpp < 32)
{
freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_INTERLEAVED);
if (!freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_INTERLEAVED))
return FALSE;
status = interleaved_decompress(xfc->codecs->interleaved, pSrcData, SrcSize, bpp,
&pDstData, xfc->format, -1, 0, 0, width, height, xfc->palette);
}
else
{
freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_PLANAR);
if (!freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_PLANAR))
return FALSE;
status = planar_decompress(xfc->codecs->planar, pSrcData, SrcSize,
&pDstData, xfc->format, -1, 0, 0, width, height, TRUE);
@ -228,10 +231,11 @@ BOOL xf_Pointer_New(rdpContext* context, rdpPointer* pointer)
ci.xhot = pointer->xPos;
ci.yhot = pointer->yPos;
ci.pixels = (XcursorPixel*) calloc(1, ci.width * ci.height * 4);
if (!ci.pixels)
if (!(ci.pixels = (XcursorPixel*) calloc(1, ci.width * ci.height * 4)))
{
xf_unlock_x11(xfc, FALSE);
return FALSE;
}
if ((pointer->andMaskData != 0) && (pointer->xorMaskData != 0))
{

View File

@ -29,7 +29,7 @@
#include <freerdp/client/cmdline.h>
#include <freerdp/client/channels.h>
int freerdp_client_common_new(freerdp* instance, rdpContext* context)
BOOL freerdp_client_common_new(freerdp* instance, rdpContext* context)
{
RDP_CLIENT_ENTRY_POINTS* pEntryPoints = instance->pClientEntryPoints;
return pEntryPoints->ClientNew(instance, context);
@ -64,7 +64,7 @@ rdpContext* freerdp_client_context_new(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
CopyMemory(instance->pClientEntryPoints, pEntryPoints, pEntryPoints->Size);
if (freerdp_context_new(instance) != 0)
if (!freerdp_context_new(instance))
goto out_fail2;
context = instance->context;

View File

@ -34,7 +34,7 @@ extern "C" {
typedef BOOL (*pRdpGlobalInit)(void);
typedef void (*pRdpGlobalUninit)(void);
typedef int (*pRdpClientNew)(freerdp* instance, rdpContext* context);
typedef BOOL (*pRdpClientNew)(freerdp* instance, rdpContext* context);
typedef void (*pRdpClientFree)(freerdp* instance, rdpContext* context);
typedef int (*pRdpClientStart)(rdpContext* context);

View File

@ -59,8 +59,8 @@ struct rdp_codecs
extern "C" {
#endif
FREERDP_API int freerdp_client_codecs_prepare(rdpCodecs* codecs, UINT32 flags);
FREERDP_API int freerdp_client_codecs_reset(rdpCodecs* codecs, UINT32 flags);
FREERDP_API BOOL freerdp_client_codecs_prepare(rdpCodecs* codecs, UINT32 flags);
FREERDP_API BOOL freerdp_client_codecs_reset(rdpCodecs* codecs, UINT32 flags);
FREERDP_API rdpCodecs* codecs_new(rdpContext* context);
FREERDP_API void codecs_free(rdpCodecs* codecs);

View File

@ -59,7 +59,7 @@ typedef RDP_CLIENT_ENTRY_POINTS_V1 RDP_CLIENT_ENTRY_POINTS;
extern "C" {
#endif
typedef int (*pContextNew)(freerdp* instance, rdpContext* context);
typedef BOOL (*pContextNew)(freerdp* instance, rdpContext* context);
typedef void (*pContextFree)(freerdp* instance, rdpContext* context);
typedef BOOL (*pPreConnect)(freerdp* instance);
@ -237,7 +237,7 @@ struct rdp_freerdp
UINT64 paddingE[80 - 66]; /* 66 */
};
FREERDP_API int freerdp_context_new(freerdp* instance);
FREERDP_API BOOL freerdp_context_new(freerdp* instance);
FREERDP_API void freerdp_context_free(freerdp* instance);
FREERDP_API BOOL freerdp_connect(freerdp* instance);

View File

@ -37,7 +37,7 @@ typedef BOOL (*psListenerGetFileDescriptor)(freerdp_listener* instance, void** r
typedef DWORD (*psListenerGetEventHandles)(freerdp_listener* instance, HANDLE* events, DWORD nCount);
typedef BOOL (*psListenerCheckFileDescriptor)(freerdp_listener* instance);
typedef void (*psListenerClose)(freerdp_listener* instance);
typedef void (*psPeerAccepted)(freerdp_listener* instance, freerdp_peer* client);
typedef BOOL (*psPeerAccepted)(freerdp_listener* instance, freerdp_peer* client);
struct rdp_freerdp_listener
{

View File

@ -29,7 +29,7 @@
#include <winpr/sspi.h>
typedef void (*psPeerContextNew)(freerdp_peer* client, rdpContext* context);
typedef BOOL (*psPeerContextNew)(freerdp_peer* client, rdpContext* context);
typedef void (*psPeerContextFree)(freerdp_peer* client, rdpContext* context);
typedef BOOL (*psPeerInitialize)(freerdp_peer* client);
@ -112,7 +112,7 @@ struct rdp_freerdp_peer
extern "C" {
#endif
FREERDP_API void freerdp_peer_context_new(freerdp_peer* client);
FREERDP_API BOOL freerdp_peer_context_new(freerdp_peer* client);
FREERDP_API void freerdp_peer_context_free(freerdp_peer* client);
FREERDP_API freerdp_peer* freerdp_peer_new(int sockfd);

View File

@ -989,6 +989,9 @@ RFX_MESSAGE* rfx_process_message(RFX_CONTEXT* context, BYTE* data, UINT32 length
BOOL ok = TRUE;
UINT16 expectedDataBlockType = WBT_FRAME_BEGIN;
if (!context || !data || !length)
goto fail;
if (!(s = Stream_New(data, length)))
goto fail;

View File

@ -103,6 +103,9 @@ void freerdp_channels_free(rdpChannels* channels)
ULONG_PTR* pKeys = NULL;
CHANNEL_OPEN_DATA* pChannelOpenData;
if (!channels)
return;
if (channels->queue)
{
MessageQueue_Free(channels->queue);

View File

@ -25,45 +25,52 @@
#include <freerdp/codecs.h>
int freerdp_client_codecs_prepare(rdpCodecs* codecs, UINT32 flags)
#define TAG FREERDP_TAG("core.codecs")
BOOL freerdp_client_codecs_prepare(rdpCodecs* codecs, UINT32 flags)
{
if (flags & FREERDP_CODEC_INTERLEAVED)
if (flags & FREERDP_CODEC_INTERLEAVED && !codecs->interleaved)
{
if (!codecs->interleaved)
if (!(codecs->interleaved = bitmap_interleaved_context_new(FALSE)))
{
codecs->interleaved = bitmap_interleaved_context_new(FALSE);
WLog_ERR(TAG, "Failed to create interleaved codec context");
return FALSE;
}
}
if (flags & FREERDP_CODEC_PLANAR)
if (flags & FREERDP_CODEC_PLANAR && !codecs->planar)
{
if (!codecs->planar)
if (!(codecs->planar = freerdp_bitmap_planar_context_new(FALSE, 64, 64)))
{
codecs->planar = freerdp_bitmap_planar_context_new(FALSE, 64, 64);
WLog_ERR(TAG, "Failed to create planar bitmap codec context");
return FALSE;
}
}
if (flags & FREERDP_CODEC_NSCODEC)
if (flags & FREERDP_CODEC_NSCODEC && !codecs->nsc)
{
if (!codecs->nsc)
if (!(codecs->nsc = nsc_context_new()))
{
codecs->nsc = nsc_context_new();
WLog_ERR(TAG, "Failed to create nsc codec context");
return FALSE;
}
}
if (flags & FREERDP_CODEC_REMOTEFX)
if (flags & FREERDP_CODEC_REMOTEFX && !codecs->rfx)
{
if (!codecs->rfx)
if (!(codecs->rfx = rfx_context_new(FALSE)))
{
codecs->rfx = rfx_context_new(FALSE);
WLog_ERR(TAG, "Failed to create rfx codec context");
return FALSE;
}
}
if (flags & FREERDP_CODEC_CLEARCODEC)
if (flags & FREERDP_CODEC_CLEARCODEC && !codecs->clear)
{
if (!codecs->clear)
if (!(codecs->clear = clear_context_new(FALSE)))
{
codecs->clear = clear_context_new(FALSE);
WLog_ERR(TAG, "Failed to create clear codec context");
return FALSE;
}
}
@ -72,26 +79,28 @@ int freerdp_client_codecs_prepare(rdpCodecs* codecs, UINT32 flags)
}
if (flags & FREERDP_CODEC_PROGRESSIVE)
if (flags & FREERDP_CODEC_PROGRESSIVE && !codecs->progressive)
{
if (!codecs->progressive)
if (!(codecs->progressive = progressive_context_new(FALSE)))
{
codecs->progressive = progressive_context_new(FALSE);
WLog_ERR(TAG, "Failed to create progressive codec context");
return FALSE;
}
}
if (flags & FREERDP_CODEC_H264)
if (flags & FREERDP_CODEC_H264 && !codecs->h264)
{
if (!codecs->h264)
if (!(codecs->h264 = h264_context_new(FALSE)))
{
codecs->h264 = h264_context_new(FALSE);
WLog_ERR(TAG, "Failed to create h264 codec context");
return FALSE;
}
}
return 1;
return TRUE;
}
int freerdp_client_codecs_reset(rdpCodecs* codecs, UINT32 flags)
BOOL freerdp_client_codecs_reset(rdpCodecs* codecs, UINT32 flags)
{
if (flags & FREERDP_CODEC_INTERLEAVED)
{
@ -154,7 +163,7 @@ int freerdp_client_codecs_reset(rdpCodecs* codecs, UINT32 flags)
}
}
return 1;
return TRUE;
}
rdpCodecs* codecs_new(rdpContext* context)

View File

@ -441,14 +441,15 @@ static wEventType FreeRDP_Events[] =
*
* @param instance - Pointer to the rdp_freerdp structure that will be initialized with the new context.
*/
int freerdp_context_new(freerdp* instance)
BOOL freerdp_context_new(freerdp* instance)
{
rdpRdp* rdp;
rdpContext* context;
BOOL ret = TRUE;
instance->context = (rdpContext*) calloc(1, instance->ContextSize);
if (!instance->context)
return -1;
return FALSE;
context = instance->context;
context->instance = instance;
@ -497,8 +498,10 @@ int freerdp_context_new(freerdp* instance)
update_register_client_callbacks(rdp->update);
IFCALL(instance->ContextNew, instance, instance->context);
return 0;
IFCALLRET(instance->ContextNew, ret, instance, instance->context);
if (ret)
return TRUE;
out_error_graphics_new:
rdp_free(rdp);
@ -508,7 +511,7 @@ out_error_metrics_new:
PubSub_Free(context->pubSub);
out_error_pubsub:
free(instance->context);
return -1;
return FALSE;
}
/** Deallocator function for a rdp context.

View File

@ -284,6 +284,7 @@ static BOOL freerdp_listener_check_fds(freerdp_listener* instance)
struct sockaddr_storage peer_addr;
rdpListener* listener = (rdpListener*) instance->listener;
static const BYTE localhost6_bytes[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
BOOL peer_accepted;
if (listener->num_sockfds < 1)
return FALSE;
@ -292,6 +293,7 @@ static BOOL freerdp_listener_check_fds(freerdp_listener* instance)
{
peer_addr_size = sizeof(peer_addr);
peer_sockfd = accept(listener->sockfds[i], (struct sockaddr*) &peer_addr, &peer_addr_size);
peer_accepted = FALSE;
if (peer_sockfd == -1)
{
@ -340,7 +342,14 @@ static BOOL freerdp_listener_check_fds(freerdp_listener* instance)
if (sin_addr)
inet_ntop(peer_addr.ss_family, sin_addr, client->hostname, sizeof(client->hostname));
IFCALL(instance->PeerAccepted, instance, client);
IFCALLRET(instance->PeerAccepted, peer_accepted, instance, client);
if (!peer_accepted)
{
WLog_ERR(TAG, "PeerAccepted callback failed");
closesocket((SOCKET) peer_sockfd);
freerdp_peer_free(client);
}
}
return TRUE;

View File

@ -621,36 +621,27 @@ static int freerdp_peer_drain_output_buffer(freerdp_peer* peer)
return transport_drain_output_buffer(transport);
}
void freerdp_peer_context_new(freerdp_peer* client)
BOOL freerdp_peer_context_new(freerdp_peer* client)
{
rdpRdp* rdp;
rdpContext* context;
BOOL ret = TRUE;
context = client->context = (rdpContext*) calloc(1, client->ContextSize);
if (!client)
return FALSE;
if (!context)
return;
if (!(context = (rdpContext*) calloc(1, client->ContextSize)))
goto fail_context;
client->context = context;
context->ServerMode = TRUE;
context->metrics = metrics_new(context);
if (!(context->metrics = metrics_new(context)))
goto fail_metrics;
if (!context->metrics)
{
client->context = NULL;
free(context);
return;
}
rdp = rdp_new(context);
if (!rdp)
{
metrics_free(context->metrics);
free(context);
client->context = NULL;
return;
}
if (!(rdp = rdp_new(context)))
goto fail_rdp;
client->input = rdp->input;
client->update = rdp->update;
@ -671,7 +662,8 @@ void freerdp_peer_context_new(freerdp_peer* client)
update_register_server_callbacks(client->update);
autodetect_register_server_callbacks(client->autodetect);
transport_attach(rdp->transport, client->sockfd);
if (!transport_attach(rdp->transport, client->sockfd))
goto fail_transport_attach;
rdp->transport->ReceiveCallback = peer_recv_callback;
rdp->transport->ReceiveExtra = client;
@ -680,8 +672,24 @@ void freerdp_peer_context_new(freerdp_peer* client)
client->IsWriteBlocked = freerdp_peer_is_write_blocked;
client->DrainOutputBuffer = freerdp_peer_drain_output_buffer;
IFCALL(client->ContextNew, client, client->context);
IFCALLRET(client->ContextNew, ret, client, client->context);
if (ret)
return TRUE;
WLog_ERR(TAG, "ContextNew callback failed");
fail_transport_attach:
rdp_free(client->context->rdp);
fail_rdp:
metrics_free(context->metrics);
fail_metrics:
free(client->context);
fail_context:
client->context = NULL;
WLog_ERR(TAG, "Failed to create new peer context");
return FALSE;
}
void freerdp_peer_context_free(freerdp_peer* client)

View File

@ -264,7 +264,8 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 por
if (sockfd < 1)
return FALSE;
transport_attach(transport, sockfd);
if (!transport_attach(transport, sockfd))
return FALSE;
status = TRUE;
}
@ -273,9 +274,20 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 por
{
if (transport->async)
{
transport->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
transport->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) transport_client_thread, transport, 0, NULL);
if (!(transport->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
{
WLog_ERR(TAG, "Failed to create transport stop event");
return FALSE;
}
if (!(transport->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) transport_client_thread, transport, 0, NULL)))
{
WLog_ERR(TAG, "Failed to create transport client thread");
CloseHandle(transport->stopEvent);
transport->stopEvent = NULL;
return FALSE;
}
}
}

View File

@ -486,14 +486,16 @@ static BOOL gdi_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmapUpdate)
if (bitsPerPixel < 32)
{
freerdp_client_codecs_prepare(codecs, FREERDP_CODEC_INTERLEAVED);
if (!freerdp_client_codecs_prepare(codecs, FREERDP_CODEC_INTERLEAVED))
return FALSE;
status = interleaved_decompress(codecs->interleaved, pSrcData, SrcSize, bitsPerPixel,
&pDstData, gdi->format, -1, 0, 0, nWidth, nHeight, gdi->palette);
}
else
{
freerdp_client_codecs_prepare(codecs, FREERDP_CODEC_PLANAR);
if (!freerdp_client_codecs_prepare(codecs, FREERDP_CODEC_PLANAR))
return FALSE;
status = planar_decompress(codecs->planar, pSrcData, SrcSize, &pDstData,
gdi->format, -1, 0, 0, nWidth, nHeight, TRUE);
@ -1023,7 +1025,8 @@ static BOOL gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd)
if (cmd->codecID == RDP_CODEC_ID_REMOTEFX)
{
freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_REMOTEFX);
if (!freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_REMOTEFX))
return FALSE;
if (!(message = rfx_process_message(gdi->codecs->rfx, cmd->bitmapData, cmd->bitmapDataLength)))
{
@ -1068,7 +1071,8 @@ static BOOL gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd)
}
else if (cmd->codecID == RDP_CODEC_ID_NSCODEC)
{
freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_NSCODEC);
if (!freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_NSCODEC))
return FALSE;
nsc_process_message(gdi->codecs->nsc, cmd->bpp, cmd->width, cmd->height, cmd->bitmapData, cmd->bitmapDataLength);

View File

@ -192,7 +192,8 @@ int gdi_SurfaceCommand_RemoteFX(rdpGdi* gdi, RdpgfxClientContext* context, RDPGF
REGION16 clippingRects;
RECTANGLE_16 clippingRect;
freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_REMOTEFX);
if (!freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_REMOTEFX))
return -1;
surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
@ -264,7 +265,8 @@ int gdi_SurfaceCommand_ClearCodec(rdpGdi* gdi, RdpgfxClientContext* context, RDP
gdiGfxSurface* surface;
RECTANGLE_16 invalidRect;
freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_CLEARCODEC);
if (!freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_CLEARCODEC))
return -1;
surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
@ -303,7 +305,8 @@ int gdi_SurfaceCommand_Planar(rdpGdi* gdi, RdpgfxClientContext* context, RDPGFX_
gdiGfxSurface* surface;
RECTANGLE_16 invalidRect;
freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_PLANAR);
if (!freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_PLANAR))
return -1;
surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
@ -337,7 +340,8 @@ int gdi_SurfaceCommand_H264(rdpGdi* gdi, RdpgfxClientContext* context, RDPGFX_SU
RDPGFX_H264_METABLOCK* meta;
RDPGFX_H264_BITMAP_STREAM* bs;
freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_H264);
if (!freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_H264))
return -1;
bs = (RDPGFX_H264_BITMAP_STREAM*) cmd->extra;
@ -380,7 +384,8 @@ int gdi_SurfaceCommand_Alpha(rdpGdi* gdi, RdpgfxClientContext* context, RDPGFX_S
gdiGfxSurface* surface;
RECTANGLE_16 invalidRect;
freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_ALPHACODEC);
if (!freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_ALPHACODEC))
return -1;
surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
@ -426,7 +431,8 @@ int gdi_SurfaceCommand_Progressive(rdpGdi* gdi, RdpgfxClientContext* context, RD
RFX_PROGRESSIVE_TILE* tile;
PROGRESSIVE_BLOCK_REGION* region;
freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_PROGRESSIVE);
if (!freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_PROGRESSIVE))
return -1;
surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);

View File

@ -175,14 +175,16 @@ BOOL gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
{
if (bpp < 32)
{
freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_INTERLEAVED);
if (!freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_INTERLEAVED))
return FALSE;
status = interleaved_decompress(gdi->codecs->interleaved, pSrcData, SrcSize, bpp,
&pDstData, gdi->format, -1, 0, 0, width, height, gdi->palette);
}
else
{
freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_PLANAR);
if (!freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_PLANAR))
return FALSE;
status = planar_decompress(gdi->codecs->planar, pSrcData, SrcSize, &pDstData,
gdi->format, -1, 0, 0, width, height, TRUE);

View File

@ -175,25 +175,44 @@ void mf_peer_rfx_update(freerdp_peer* client)
}
/* Called when we have a new peer connecting */
int mf_peer_context_new(freerdp_peer* client, mfPeerContext* context)
BOOL mf_peer_context_new(freerdp_peer* client, mfPeerContext* context)
{
context->info = mf_info_get_instance();
context->rfx_context = rfx_context_new(TRUE);
if (!(context->info = mf_info_get_instance()))
return FALSE;
if (!(context->rfx_context = rfx_context_new(TRUE)))
goto fail_rfx_context;
context->rfx_context->mode = RLGR3;
context->rfx_context->width = client->settings->DesktopWidth;
context->rfx_context->height = client->settings->DesktopHeight;
rfx_context_set_pixel_format(context->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8);
//context->nsc_context = nsc_context_new();
//if (!(context->nsc_context = nsc_context_new()))
// goto fail_nsc_context;
//nsc_context_set_pixel_format(context->nsc_context, RDP_PIXEL_FORMAT_B8G8R8A8);
context->s = Stream_New(NULL, 0xFFFF);
if (!(context->s = Stream_New(NULL, 0xFFFF)))
goto fail_stream_new;
context->vcm = WTSOpenServerA((LPSTR) client->context);
if (!context->vcm || context->vcm == INVALID_HANDLE_VALUE)
goto fail_open_server;
mf_info_peer_register(context->info, context);
return 0;
return TRUE;
fail_open_server:
Stream_Free(context->s, TRUE);
context->s = NULL;
fail_stream_new:
rfx_context_free(context->rfx_context);
context->rfx_context = NULL;
fail_rfx_context:
return FALSE;
}
/* Called after a peer disconnects */
@ -226,12 +245,14 @@ void mf_peer_context_free(freerdp_peer* client, mfPeerContext* context)
}
/* Called when a new client connects */
void mf_peer_init(freerdp_peer* client)
BOOL mf_peer_init(freerdp_peer* client)
{
client->ContextSize = sizeof(mfPeerContext);
client->ContextNew = (psPeerContextNew) mf_peer_context_new;
client->ContextFree = (psPeerContextFree) mf_peer_context_free;
freerdp_peer_context_new(client);
if (!freerdp_peer_context_new(client))
return FALSE;
info_event_queue = mf_event_queue_new();
@ -249,6 +270,8 @@ void mf_peer_init(freerdp_peer* client)
);
dispatch_resume(info_timer);
}
return TRUE;
}
BOOL mf_peer_post_connect(freerdp_peer* client)
@ -330,12 +353,17 @@ static void mf_peer_suppress_output(rdpContext* context, BYTE allow, RECTANGLE_1
}
void mf_peer_accepted(freerdp_listener* instance, freerdp_peer* client)
BOOL mf_peer_accepted(freerdp_listener* instance, freerdp_peer* client)
{
pthread_t th;
pthread_create(&th, 0, mf_peer_main_loop, client);
pthread_detach(th);
if (pthread_create(&th, 0, mf_peer_main_loop, client) == 0)
{
pthread_detach(th);
return TRUE;
}
return FALSE;
}
void* mf_peer_main_loop(void* arg)
@ -351,7 +379,11 @@ void* mf_peer_main_loop(void* arg)
memset(rfds, 0, sizeof(rfds));
mf_peer_init(client);
if (!mf_peer_init(client))
{
freerdp_peer_free(client);
return NULL;
}
/* Initialize the real server settings here */
client->settings->CertificateFile = _strdup("server.crt");

View File

@ -27,17 +27,17 @@ BOOL mf_peer_check_fds(freerdp_peer* client);
void mf_peer_rfx_update(freerdp_peer* client);
int mf_peer_context_new(freerdp_peer* client, mfPeerContext* context);
BOOL mf_peer_context_new(freerdp_peer* client, mfPeerContext* context);
void mf_peer_context_free(freerdp_peer* client, mfPeerContext* context);
void mf_peer_init(freerdp_peer* client);
BOOL mf_peer_init(freerdp_peer* client);
BOOL mf_peer_post_connect(freerdp_peer* client);
BOOL mf_peer_activate(freerdp_peer* client);
void mf_peer_synchronize_event(rdpInput* input, UINT32 flags);
void mf_peer_accepted(freerdp_listener* instance, freerdp_peer* client);
BOOL mf_peer_accepted(freerdp_listener* instance, freerdp_peer* client);
void* mf_peer_main_loop(void* arg);

View File

@ -108,7 +108,8 @@ int main(int argc, char* argv[])
WTSRegisterWtsApiFunctionTable(FreeRDP_InitWtsApi());
instance = freerdp_listener_new();
if (!(instance = freerdp_listener_new()))
return 1;
instance->PeerAccepted = mf_peer_accepted;

View File

@ -52,23 +52,46 @@
static char* test_pcap_file = NULL;
static BOOL test_dump_rfx_realtime = TRUE;
void test_peer_context_new(freerdp_peer* client, testPeerContext* context)
BOOL test_peer_context_new(freerdp_peer* client, testPeerContext* context)
{
context->rfx_context = rfx_context_new(TRUE);
if (!(context->rfx_context = rfx_context_new(TRUE)))
goto fail_rfx_context;
context->rfx_context->mode = RLGR3;
context->rfx_context->width = SAMPLE_SERVER_DEFAULT_WIDTH;
context->rfx_context->height = SAMPLE_SERVER_DEFAULT_HEIGHT;
rfx_context_set_pixel_format(context->rfx_context, RDP_PIXEL_FORMAT_R8G8B8);
context->nsc_context = nsc_context_new();
if (!(context->nsc_context = nsc_context_new()))
goto fail_nsc_context;
nsc_context_set_pixel_format(context->nsc_context, RDP_PIXEL_FORMAT_R8G8B8);
context->s = Stream_New(NULL, 65536);
if (!(context->s = Stream_New(NULL, 65536)))
goto fail_stream_new;
context->icon_x = -1;
context->icon_y = -1;
context->vcm = WTSOpenServerA((LPSTR) client->context);
if (!context->vcm || context->vcm == INVALID_HANDLE_VALUE)
goto fail_open_server;
return TRUE;
fail_open_server:
context->vcm = NULL;
Stream_Free(context->s, TRUE);
context->s = NULL;
fail_stream_new:
nsc_context_free(context->nsc_context);
context->nsc_context = NULL;
fail_nsc_context:
rfx_context_free(context->rfx_context);
context->rfx_context = NULL;
fail_rfx_context:
return FALSE;
}
void test_peer_context_free(freerdp_peer* client, testPeerContext* context)
@ -105,12 +128,12 @@ void test_peer_context_free(freerdp_peer* client, testPeerContext* context)
}
}
static void test_peer_init(freerdp_peer* client)
static BOOL test_peer_init(freerdp_peer* client)
{
client->ContextSize = sizeof(testPeerContext);
client->ContextNew = (psPeerContextNew) test_peer_context_new;
client->ContextFree = (psPeerContextFree) test_peer_context_free;
freerdp_peer_context_new(client);
return freerdp_peer_context_new(client);
}
static wStream* test_peer_stream_init(testPeerContext* context)
@ -509,10 +532,20 @@ BOOL tf_peer_post_connect(freerdp_peer* client)
if (context->debug_channel != NULL)
{
WLog_DBG(TAG, "Open channel rdpdbg.");
context->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!(context->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
{
WLog_ERR(TAG, "Failed to create stop event");
return FALSE;
}
context->debug_channel_thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) tf_debug_channel_thread_func, (void*) context, 0, NULL);
if (!(context->debug_channel_thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) tf_debug_channel_thread_func, (void*) context, 0, NULL)))
{
WLog_ERR(TAG, "Failed to create debug channel thread");
CloseHandle(context->stopEvent);
context->stopEvent = NULL;
return FALSE;
}
}
}
@ -674,7 +707,11 @@ static void* test_peer_mainloop(void* arg)
testPeerContext* context;
freerdp_peer* client = (freerdp_peer*) arg;
test_peer_init(client);
if (!test_peer_init(client))
{
freerdp_peer_free(client);
return NULL;
}
/* Initialize the real server settings here */
client->settings->CertificateFile = _strdup("server.crt");
@ -740,12 +777,16 @@ static void* test_peer_mainloop(void* arg)
return NULL;
}
static void test_peer_accepted(freerdp_listener* instance, freerdp_peer* client)
static BOOL test_peer_accepted(freerdp_listener* instance, freerdp_peer* client)
{
HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) test_peer_mainloop, (void*) client, 0, NULL);
if (hThread != NULL) {
CloseHandle(hThread);
return TRUE;
}
return FALSE;
}
static void test_server_mainloop(freerdp_listener* instance)

View File

@ -37,7 +37,7 @@
static wfInfo* wfInfoInstance = NULL;
static int _IDcount = 0;
int wf_info_lock(wfInfo* wfi)
BOOL wf_info_lock(wfInfo* wfi)
{
DWORD dRes;
@ -54,13 +54,13 @@ int wf_info_lock(wfInfo* wfi)
case WAIT_FAILED:
WLog_ERR(TAG, "wf_info_lock failed with 0x%08X", GetLastError());
return -1;
return FALSE;
}
return -1;
return FALSE;
}
int wf_info_try_lock(wfInfo* wfi, DWORD dwMilliseconds)
BOOL wf_info_try_lock(wfInfo* wfi, DWORD dwMilliseconds)
{
DWORD dRes;
@ -77,18 +77,18 @@ int wf_info_try_lock(wfInfo* wfi, DWORD dwMilliseconds)
case WAIT_FAILED:
WLog_ERR(TAG, "wf_info_try_lock failed with 0x%08X", GetLastError());
return -1;
return FALSE;
}
return -1;
return FALSE;
}
int wf_info_unlock(wfInfo* wfi)
BOOL wf_info_unlock(wfInfo* wfi)
{
if (ReleaseMutex(wfi->mutex) == 0)
if (!ReleaseMutex(wfi->mutex))
{
WLog_ERR(TAG, "wf_info_unlock failed with 0x%08X", GetLastError());
return -1;
return FALSE;
}
return TRUE;
@ -185,61 +185,70 @@ wfInfo* wf_info_get_instance()
return wfInfoInstance;
}
void wf_info_peer_register(wfInfo* wfi, wfPeerContext* context)
BOOL wf_info_peer_register(wfInfo* wfi, wfPeerContext* context)
{
if (wf_info_lock(wfi) > 0)
{
int i;
int peerId;
if (wfi->peerCount == WF_INFO_MAXPEERS)
{
context->socketClose = TRUE;
wf_info_unlock(wfi);
return;
}
int i;
int peerId;
context->info = wfi;
context->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!wfi || !context)
return FALSE;
//get the offset of the top left corner of selected screen
EnumDisplayMonitors(NULL, NULL, wf_info_monEnumCB, 0);
_IDcount = 0;
if (!wf_info_lock(wfi))
return FALSE;
if (wfi->peerCount == WF_INFO_MAXPEERS)
goto fail_peer_count;
context->info = wfi;
if (!(context->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
goto fail_update_event;
//get the offset of the top left corner of selected screen
EnumDisplayMonitors(NULL, NULL, wf_info_monEnumCB, 0);
_IDcount = 0;
#ifdef WITH_DXGI_1_2
if (wfi->peerCount == 0)
wf_dxgi_init(wfi);
if (wfi->peerCount == 0)
if (wf_dxgi_init(wfi) != 0)
goto fail_driver_init;
#else
if (wf_mirror_driver_activate(wfi) == FALSE)
{
context->socketClose = TRUE;
wf_info_unlock(wfi);
return;
}
if (!wf_mirror_driver_activate(wfi))
goto fail_driver_init;
#endif
//look through the array of peers until an empty slot
for(i=0; i<WF_INFO_MAXPEERS; ++i)
//look through the array of peers until an empty slot
for (i = 0; i < WF_INFO_MAXPEERS; ++i)
{
//empty index will be our peer id
if (wfi->peers[i] == NULL)
{
//empty index will be our peer id
if (wfi->peers[i] == NULL)
{
peerId = i;
break;
}
peerId = i;
break;
}
wfi->peers[peerId] = ((rdpContext*) context)->peer;
wfi->peers[peerId]->pId = peerId;
wfi->peerCount++;
WLog_INFO(TAG, "Registering Peer: id=%d #=%d", peerId, wfi->peerCount);
wf_info_unlock(wfi);
wfreerdp_server_peer_callback_event(peerId, WF_SRV_CALLBACK_EVENT_CONNECT);
}
wfi->peers[peerId] = ((rdpContext*) context)->peer;
wfi->peers[peerId]->pId = peerId;
wfi->peerCount++;
WLog_INFO(TAG, "Registering Peer: id=%d #=%d", peerId, wfi->peerCount);
wf_info_unlock(wfi);
wfreerdp_server_peer_callback_event(peerId, WF_SRV_CALLBACK_EVENT_CONNECT);
return TRUE;
fail_driver_init:
CloseHandle(context->updateEvent);
context->updateEvent = NULL;
fail_update_event:
fail_peer_count:
context->socketClose = TRUE;
wf_info_unlock(wfi);
return FALSE;
}
void wf_info_peer_unregister(wfInfo* wfi, wfPeerContext* context)
{
if (wf_info_lock(wfi) > 0)
if (wf_info_lock(wfi))
{
int peerId;

View File

@ -25,12 +25,12 @@
#define WF_INFO_DEFAULT_FPS 24
#define WF_INFO_MAXPEERS 32
int wf_info_lock(wfInfo* wfi);
int wf_info_try_lock(wfInfo* wfi, DWORD dwMilliseconds);
int wf_info_unlock(wfInfo* wfi);
BOOL wf_info_lock(wfInfo* wfi);
BOOL wf_info_try_lock(wfInfo* wfi, DWORD dwMilliseconds);
BOOL wf_info_unlock(wfInfo* wfi);
wfInfo* wf_info_get_instance(void);
void wf_info_peer_register(wfInfo* wfi, wfPeerContext* context);
BOOL wf_info_peer_register(wfInfo* wfi, wfPeerContext* context);
void wf_info_peer_unregister(wfInfo* wfi, wfPeerContext* context);
BOOL wf_info_have_updates(wfInfo* wfi);

View File

@ -38,11 +38,24 @@
#include "wf_peer.h"
void wf_peer_context_new(freerdp_peer* client, wfPeerContext* context)
BOOL wf_peer_context_new(freerdp_peer* client, wfPeerContext* context)
{
context->info = wf_info_get_instance();
if (!(context->info = wf_info_get_instance()))
return FALSE;
context->vcm = WTSOpenServerA((LPSTR) client->context);
wf_info_peer_register(context->info, context);
if (!context->vcm || context->vcm == INVALID_HANDLE_VALUE)
return FALSE;
if (!wf_info_peer_register(context->info, context))
{
WTSCloseServer(context->vcm);
context->vcm = NULL;
return FALSE;
}
return TRUE;
}
void wf_peer_context_free(freerdp_peer* client, wfPeerContext* context)
@ -60,13 +73,13 @@ void wf_peer_context_free(freerdp_peer* client, wfPeerContext* context)
WTSCloseServer(context->vcm);
}
void wf_peer_init(freerdp_peer* client)
BOOL wf_peer_init(freerdp_peer* client)
{
client->ContextSize = sizeof(wfPeerContext);
client->ContextNew = (psPeerContextNew) wf_peer_context_new;
client->ContextFree = (psPeerContextFree) wf_peer_context_free;
freerdp_peer_context_new(client);
return freerdp_peer_context_new(client);
}
BOOL wf_peer_post_connect(freerdp_peer* client)
@ -75,14 +88,14 @@ BOOL wf_peer_post_connect(freerdp_peer* client)
wfInfo* wfi;
rdpSettings* settings;
wfPeerContext* context = (wfPeerContext*) client->context;
wfi = context->info;
settings = client->settings;
if ((get_screen_info(wfi->screenID, NULL, &wfi->servscreen_width, &wfi->servscreen_height, &wfi->bitsPerPixel) == 0) ||
(wfi->servscreen_width == 0) ||
(wfi->servscreen_height == 0) ||
(wfi->bitsPerPixel == 0) )
(wfi->servscreen_width == 0) ||
(wfi->servscreen_height == 0) ||
(wfi->bitsPerPixel == 0) )
{
WLog_ERR(TAG, "postconnect: error getting screen info for screen %d", wfi->screenID);
WLog_ERR(TAG, "\t%dx%dx%d", wfi->servscreen_height, wfi->servscreen_width, wfi->bitsPerPixel);
@ -95,11 +108,11 @@ BOOL wf_peer_post_connect(freerdp_peer* client)
WLog_DBG(TAG, "Client requested resolution %dx%d, but will resize to %dx%d",
settings->DesktopWidth, settings->DesktopHeight, wfi->servscreen_width, wfi->servscreen_height);
*/
settings->DesktopWidth = wfi->servscreen_width;
settings->DesktopHeight = wfi->servscreen_height;
settings->ColorDepth = wfi->bitsPerPixel;
client->update->DesktopResize(client->update->context);
}
@ -115,13 +128,13 @@ BOOL wf_peer_activate(freerdp_peer* client)
{
wfInfo* wfi;
wfPeerContext* context = (wfPeerContext*) client->context;
wfi = context->info;
client->activated = TRUE;
wf_update_peer_activate(wfi, context);
wfreerdp_server_peer_callback_event(((rdpContext*) context)->peer->pId, WF_SRV_CALLBACK_EVENT_ACTIVATE);
return TRUE;
}
@ -133,12 +146,15 @@ BOOL wf_peer_logon(freerdp_peer* client, SEC_WINNT_AUTH_IDENTITY* identity, BOOL
void wf_peer_synchronize_event(rdpInput* input, UINT32 flags)
{
}
void wf_peer_accepted(freerdp_listener* instance, freerdp_peer* client)
BOOL wf_peer_accepted(freerdp_listener* instance, freerdp_peer* client)
{
CreateThread(NULL, 0, wf_peer_main_loop, client, 0, NULL);
if (!CreateThread(NULL, 0, wf_peer_main_loop, client, 0, NULL))
return FALSE;
return TRUE;
}
DWORD WINAPI wf_peer_socket_listener(LPVOID lpParam)
@ -150,7 +166,7 @@ DWORD WINAPI wf_peer_socket_listener(LPVOID lpParam)
fd_set rfds_set;
wfPeerContext* context;
freerdp_peer* client = (freerdp_peer*) lpParam;
ZeroMemory(rfds, sizeof(rfds));
context = (wfPeerContext*) client->context;
@ -181,7 +197,7 @@ DWORD WINAPI wf_peer_socket_listener(LPVOID lpParam)
break;
select(max_fds + 1, &rfds_set, NULL, NULL, NULL);
SetEvent(context->socketEvent);
WaitForSingleObject(context->socketSemaphore, INFINITE);
@ -219,30 +235,33 @@ DWORD WINAPI wf_peer_main_loop(LPVOID lpParam)
_putenv(home);
}
wf_peer_init(client);
if (!wf_peer_init(client))
goto fail_peer_init;
settings = client->settings;
settings->RemoteFxCodec = TRUE;
settings->ColorDepth = 32;
settings->NSCodec = FALSE;
settings->JpegCodec = FALSE;
wf_peer_read_settings(client);
client->PostConnect = wf_peer_post_connect;
client->Activate = wf_peer_activate;
client->Logon = wf_peer_logon;
client->input->SynchronizeEvent = wf_peer_synchronize_event;
client->input->KeyboardEvent = wf_peer_keyboard_event;
client->input->UnicodeKeyboardEvent = wf_peer_unicode_keyboard_event;
client->input->MouseEvent = wf_peer_mouse_event;
client->input->ExtendedMouseEvent = wf_peer_extended_mouse_event;
client->Initialize(client);
context = (wfPeerContext*) client->context;
if (!client->Initialize(client))
goto fail_client_initialize;
if (context->socketClose)
return 0;
goto fail_socked_closed;
context = (wfPeerContext*) client->context;
wfi = context->info;
@ -255,10 +274,15 @@ DWORD WINAPI wf_peer_main_loop(LPVOID lpParam)
client->input->ExtendedMouseEvent = wf_peer_extended_mouse_event_dummy;
}
context->socketEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
context->socketSemaphore = CreateSemaphore(NULL, 0, 1, NULL);
context->socketThread = CreateThread(NULL, 0, wf_peer_socket_listener, client, 0, NULL);
if (!(context->socketEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
goto fail_socket_event;
if (!(context->socketSemaphore = CreateSemaphore(NULL, 0, 1, NULL)))
goto fail_socket_semaphore;
if (!(context->socketThread = CreateThread(NULL, 0, wf_peer_socket_listener, client, 0, NULL)))
goto fail_socket_thread;
WLog_INFO(TAG, "We've got a client %s", client->local ? "(local)" : client->hostname);
nCount = 0;
handles[nCount++] = context->updateEvent;
@ -319,11 +343,21 @@ DWORD WINAPI wf_peer_main_loop(LPVOID lpParam)
}
wf_update_peer_deactivate(wfi, context);
client->Disconnect(client);
fail_socket_thread:
CloseHandle(context->socketSemaphore);
context->socketSemaphore = NULL;
fail_socket_semaphore:
CloseHandle(context->socketEvent);
context->socketEvent = NULL;
fail_socket_event:
fail_socked_closed:
fail_client_initialize:
freerdp_peer_context_free(client);
fail_peer_init:
freerdp_peer_free(client);
return 0;
}

View File

@ -26,10 +26,10 @@
void wf_peer_context_new(freerdp_peer* client, wfPeerContext* context);
BOOL wf_peer_context_new(freerdp_peer* client, wfPeerContext* context);
void wf_peer_context_free(freerdp_peer* client, wfPeerContext* context);
void wf_peer_init(freerdp_peer* client);
BOOL wf_peer_init(freerdp_peer* client);
void wf_dxgi_encode(freerdp_peer* client, UINT timeout);
void wf_rfx_encode(freerdp_peer* client);
@ -43,7 +43,7 @@ void wf_peer_send_changes(freerdp_peer* client);
void wf_detect_win_ver(void);
void wf_peer_accepted(freerdp_listener* instance, freerdp_peer* client);
BOOL wf_peer_accepted(freerdp_listener* instance, freerdp_peer* client);
DWORD WINAPI wf_peer_main_loop(LPVOID lpParam);

View File

@ -285,23 +285,29 @@ int shw_freerdp_client_stop(rdpContext* context)
return 0;
}
int shw_freerdp_client_new(freerdp* instance, rdpContext* context)
BOOL shw_freerdp_client_new(freerdp* instance, rdpContext* context)
{
shwContext* shw;
rdpSettings* settings;
shw = (shwContext*) instance->context;
if (!(shw->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
return FALSE;
if (!(context->channels = freerdp_channels_new()))
{
CloseHandle(shw->StopEvent);
shw->StopEvent = NULL;
return FALSE;
}
instance->PreConnect = shw_pre_connect;
instance->PostConnect = shw_post_connect;
instance->Authenticate = shw_authenticate;
instance->VerifyCertificate = shw_verify_certificate;
instance->VerifyX509Certificate = shw_verify_x509_certificate;
context->channels = freerdp_channels_new();
shw->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
settings = instance->settings;
shw->settings = instance->context->settings;
@ -355,7 +361,7 @@ int shw_freerdp_client_new(freerdp* instance, rdpContext* context)
settings->RedirectClipboard = TRUE;
settings->SupportDynamicChannels = TRUE;
return 0;
return TRUE;
}
void shw_freerdp_client_free(freerdp* instance, rdpContext* context)
@ -392,16 +398,28 @@ int win_shadow_rdp_init(winShadowSubsystem* subsystem)
shw_RdpClientEntry(&clientEntryPoints);
context = freerdp_client_context_new(&clientEntryPoints);
if (!(subsystem->RdpUpdateEnterEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
goto fail_enter_event;
if (!(subsystem->RdpUpdateLeaveEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
goto fail_leave_event;
if (!(context = freerdp_client_context_new(&clientEntryPoints)))
goto fail_context;
subsystem->shw = (shwContext*) context;
subsystem->shw->settings = context->settings;
subsystem->shw->subsystem = subsystem;
subsystem->RdpUpdateEnterEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
subsystem->RdpUpdateLeaveEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
return 1;
fail_context:
CloseHandle(subsystem->RdpUpdateLeaveEvent);
fail_leave_event:
CloseHandle(subsystem->RdpUpdateEnterEvent);
fail_enter_event:
return -1;
}
int win_shadow_rdp_start(winShadowSubsystem* subsystem)

View File

@ -47,20 +47,19 @@ int main(int argc, char** argv)
server = shadow_server_new();
if (!server)
return 0;
goto fail_server_new;
status = shadow_server_parse_command_line(server, argc, argv);
if ((status = shadow_server_parse_command_line(server, argc, argv)) < 0)
{
shadow_server_command_line_status_print(server, argc, argv, status);
goto fail_parse_command_line;
}
status = shadow_server_command_line_status_print(server, argc, argv, status);
if ((status = shadow_server_init(server)) < 0)
goto fail_server_init;
if (status < 0)
return 0;
if (shadow_server_init(server) < 0)
return 0;
if (shadow_server_start(server) < 0)
return 0;
if ((status = shadow_server_start(server)) < 0)
goto fail_server_start;
if (g_MessagePump)
{
@ -73,10 +72,18 @@ int main(int argc, char** argv)
WaitForSingleObject(server->thread, INFINITE);
GetExitCodeThread(server->thread, &dwExitCode);
if (!GetExitCodeThread(server->thread, &dwExitCode))
status = -1;
else
status = (int)dwExitCode;
fail_server_start:
shadow_server_uninit(server);
fail_server_init:
fail_parse_command_line:
shadow_server_free(server);
return 0;
fail_server_new:
return status;
}

View File

@ -33,7 +33,7 @@
#define TAG CLIENT_TAG("shadow")
void shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client)
BOOL shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client)
{
rdpSettings* settings;
rdpShadowServer* server;
@ -62,10 +62,13 @@ void shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client)
settings->TlsSecurity = TRUE;
settings->NlaSecurity = FALSE;
settings->CertificateFile = _strdup(server->CertificateFile);
settings->PrivateKeyFile = _strdup(server->PrivateKeyFile);
if (!(settings->CertificateFile = _strdup(server->CertificateFile)))
goto fail_cert_file;
if (!(settings->PrivateKeyFile = _strdup(server->PrivateKeyFile)))
goto fail_privkey_file;
if (!(settings->RdpKeyFile = _strdup(settings->PrivateKeyFile)))
goto fail_rdpkey_file;
settings->RdpKeyFile = _strdup(settings->PrivateKeyFile);
if (server->ipcSocket)
{
@ -77,17 +80,45 @@ void shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client)
client->mayView = server->mayView;
client->mayInteract = server->mayInteract;
InitializeCriticalSectionAndSpinCount(&(client->lock), 4000);
if (!InitializeCriticalSectionAndSpinCount(&(client->lock), 4000))
goto fail_client_lock;
region16_init(&(client->invalidRegion));
client->vcm = WTSOpenServerA((LPSTR) peer->context);
if (!client->vcm || client->vcm == INVALID_HANDLE_VALUE)
goto fail_open_server;
client->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!(client->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
goto fail_stop_event;
client->encoder = shadow_encoder_new(client);
if (!(client->encoder = shadow_encoder_new(client)))
goto fail_encoder_new;
ArrayList_Add(server->clients, (void*) client);
return TRUE;
fail_encoder_new:
CloseHandle(client->encoder);
client->encoder = NULL;
fail_stop_event:
WTSCloseServer((HANDLE) client->vcm);
client->vcm = NULL;
fail_open_server:
DeleteCriticalSection(&(client->lock));
fail_client_lock:
free(settings->RdpKeyFile);
settings->RdpKeyFile = NULL;
fail_rdpkey_file:
free(settings->PrivateKeyFile);
settings->PrivateKeyFile = NULL;
fail_privkey_file:
free(settings->CertificateFile);
settings->CertificateFile = NULL;
fail_cert_file:
return FALSE;
}
void shadow_client_context_free(freerdp_peer* peer, rdpShadowClient* client)
@ -1035,13 +1066,11 @@ void* shadow_client_thread(rdpShadowClient* client)
freerdp_peer_context_free(peer);
freerdp_peer_free(peer);
ExitThread(0);
return NULL;
}
void shadow_client_accepted(freerdp_listener* listener, freerdp_peer* peer)
BOOL shadow_client_accepted(freerdp_listener* listener, freerdp_peer* peer)
{
rdpShadowClient* client;
rdpShadowServer* server;
@ -1052,10 +1081,14 @@ void shadow_client_accepted(freerdp_listener* listener, freerdp_peer* peer)
peer->ContextSize = sizeof(rdpShadowClient);
peer->ContextNew = (psPeerContextNew) shadow_client_context_new;
peer->ContextFree = (psPeerContextFree) shadow_client_context_free;
freerdp_peer_context_new(peer);
if (!freerdp_peer_context_new(peer))
return FALSE;
client = (rdpShadowClient*) peer->context;
client->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)
shadow_client_thread, client, 0, NULL);
return TRUE;
}

View File

@ -26,7 +26,7 @@ extern "C" {
#endif
int shadow_client_surface_update(rdpShadowClient* client, REGION16* region);
void shadow_client_accepted(freerdp_listener* instance, freerdp_peer* client);
BOOL shadow_client_accepted(freerdp_listener* instance, freerdp_peer* client);
#ifdef __cplusplus
}

View File

@ -534,26 +534,29 @@ int shadow_server_init(rdpShadowServer* server)
WTSRegisterWtsApiFunctionTable(FreeRDP_InitWtsApi());
server->clients = ArrayList_New(TRUE);
if (!(server->clients = ArrayList_New(TRUE)))
goto fail_client_array;
server->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!(server->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
goto fail_stop_event;
InitializeCriticalSectionAndSpinCount(&(server->lock), 4000);
if (!InitializeCriticalSectionAndSpinCount(&(server->lock), 4000))
goto fail_server_lock;
status = shadow_server_init_config_path(server);
if (status < 0)
return -1;
goto fail_config_path;
status = shadow_server_init_certificate(server);
if (status < 0)
return -1;
goto fail_certificate;
server->listener = freerdp_listener_new();
if (!server->listener)
return -1;
goto fail_listener;
server->listener->info = (void*) server;
server->listener->PeerAccepted = shadow_client_accepted;
@ -561,11 +564,35 @@ int shadow_server_init(rdpShadowServer* server)
server->subsystem = shadow_subsystem_new(NULL);
if (!server->subsystem)
return -1;
goto fail_subsystem_new;
status = shadow_subsystem_init(server->subsystem, server);
return status;
if (status >= 0)
return status;
fail_subsystem_new:
freerdp_listener_free(server->listener);
server->listener = NULL;
fail_listener:
free(server->CertificateFile);
server->CertificateFile = NULL;
free(server->PrivateKeyFile);
server->PrivateKeyFile = NULL;
fail_certificate:
free(server->ConfigPath);
server->ConfigPath = NULL;
fail_config_path:
DeleteCriticalSection(&(server->lock));
fail_server_lock:
CloseHandle(server->StopEvent);
server->StopEvent = NULL;
fail_stop_event:
ArrayList_Free(server->clients);
server->clients = NULL;
fail_client_array:
WLog_ERR(TAG, "Failed to initialize shadow server");
return -1;
}
int shadow_server_uninit(rdpShadowServer* server)

View File

@ -126,32 +126,52 @@ rdpShadowSubsystem* shadow_subsystem_new(const char* name)
void shadow_subsystem_free(rdpShadowSubsystem* subsystem)
{
if (subsystem->ep.Free)
if (subsystem && subsystem->ep.Free)
subsystem->ep.Free(subsystem);
}
int shadow_subsystem_init(rdpShadowSubsystem* subsystem, rdpShadowServer* server)
{
int status;
int status = -1;
if (!subsystem || !subsystem->ep.Init)
return -1;
subsystem->server = server;
subsystem->selectedMonitor = server->selectedMonitor;
subsystem->MsgPipe = MessagePipe_New();
subsystem->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!(subsystem->MsgPipe = MessagePipe_New()))
goto fail;
if (!(subsystem->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
goto fail;
region16_init(&(subsystem->invalidRegion));
if (!subsystem->ep.Init)
return -1;
if ((status = subsystem->ep.Init(subsystem)) >= 0)
return status;
status = subsystem->ep.Init(subsystem);
fail:
if (subsystem->MsgPipe)
{
MessagePipe_Free(subsystem->MsgPipe);
subsystem->MsgPipe = NULL;
}
if (subsystem->updateEvent)
{
CloseHandle(subsystem->updateEvent);
subsystem->updateEvent = NULL;
}
return status;
}
void shadow_subsystem_uninit(rdpShadowSubsystem* subsystem)
{
if (!subsystem)
return;
if (subsystem->ep.Uninit)
subsystem->ep.Uninit(subsystem);
@ -175,7 +195,7 @@ int shadow_subsystem_start(rdpShadowSubsystem* subsystem)
{
int status;
if (!subsystem->ep.Start)
if (!subsystem || !subsystem->ep.Start)
return -1;
status = subsystem->ep.Start(subsystem);
@ -187,7 +207,7 @@ int shadow_subsystem_stop(rdpShadowSubsystem* subsystem)
{
int status;
if (!subsystem->ep.Stop)
if (!subsystem || !subsystem->ep.Stop)
return -1;
status = subsystem->ep.Stop(subsystem);

View File

@ -21,7 +21,7 @@ int TestCommMonitor(int argc, char* argv[])
if (!hComm || (hComm == INVALID_HANDLE_VALUE))
{
printf("CreateFileA failure: %s\n", lpFileName);
return 0;
return -1;
}
fSuccess = SetCommMask(hComm, EV_CTS | EV_DSR);
@ -29,11 +29,15 @@ int TestCommMonitor(int argc, char* argv[])
if (!fSuccess)
{
printf("SetCommMask failure: GetLastError() = %d\n", (int) GetLastError());
return 0;
return -1;
}
ZeroMemory(&overlapped, sizeof(OVERLAPPED));
overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!(overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
{
printf("CreateEvent failed: GetLastError() = %d\n", (int) GetLastError());
return -1;
}
if (WaitCommEvent(hComm, &dwEvtMask, &overlapped))
{
@ -58,7 +62,7 @@ int TestCommMonitor(int argc, char* argv[])
else
{
printf("WaitCommEvent failure: GetLastError() = %d\n", (int) dwError);
return 0;
return -1;
}
}

View File

@ -439,10 +439,26 @@ int TestPipeCreateNamedPipe(int argc, char* argv[])
#ifndef _WIN32
signal(SIGPIPE, SIG_IGN);
#endif
ReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
SingleThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) named_pipe_single_thread, NULL, 0, NULL);
ClientThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) named_pipe_client_thread, NULL, 0, NULL);
ServerThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) named_pipe_server_thread, NULL, 0, NULL);
if (!(ReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
{
printf("CreateEvent failure: (%d)\n", GetLastError());
return -1;
}
if (!(SingleThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) named_pipe_single_thread, NULL, 0, NULL)))
{
printf("CreateThread (SingleThread) failure: (%d)\n", GetLastError());
return -1;
}
if (!(ClientThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) named_pipe_client_thread, NULL, 0, NULL)))
{
printf("CreateThread (ClientThread) failure: (%d)\n", GetLastError());
return -1;
}
if (!(ServerThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) named_pipe_server_thread, NULL, 0, NULL)))
{
printf("CreateThread (ServerThread) failure: (%d)\n", GetLastError());
return -1;
}
WaitForSingleObject(SingleThread, INFINITE);
WaitForSingleObject(ClientThread, INFINITE);
WaitForSingleObject(ServerThread, INFINITE);

View File

@ -53,7 +53,13 @@ static void* named_pipe_client_thread(void* arg)
return NULL;
}
ZeroMemory(&overlapped, sizeof(OVERLAPPED));
hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!(hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
{
printf("CreateEvent failure: (%d)\n", GetLastError());
return NULL;
}
overlapped.hEvent = hEvent;
nNumberOfBytesToWrite = PIPE_BUFFER_SIZE;
FillMemory(lpWriteBuffer, PIPE_BUFFER_SIZE, 0x59);
@ -137,7 +143,13 @@ static void* named_pipe_server_thread(void* arg)
SetEvent(ReadyEvent);
ZeroMemory(&overlapped, sizeof(OVERLAPPED));
hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!(hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
{
printf("CreateEvent failure: (%d)\n", GetLastError());
return NULL;
}
overlapped.hEvent = hEvent;
fConnected = ConnectNamedPipe(hNamedPipe, &overlapped);
printf("ConnectNamedPipe status: %d\n", GetLastError());
@ -222,11 +234,26 @@ int TestPipeCreateNamedPipeOverlapped(int argc, char* argv[])
{
HANDLE ClientThread;
HANDLE ServerThread;
ReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
ClientThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) named_pipe_client_thread, NULL, 0, NULL);
ServerThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) named_pipe_server_thread, NULL, 0, NULL);
if (!(ReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
{
printf("CreateEvent failed: %d\n", GetLastError());
return -1;
}
if (!(ClientThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) named_pipe_client_thread, NULL, 0, NULL)))
{
printf("CreateThread (client) failed: %d\n", GetLastError());
return -1;
}
if (!(ServerThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) named_pipe_server_thread, NULL, 0, NULL)))
{
printf("CreateThread (server) failed: %d\n", GetLastError());
return -1;
}
WaitForSingleObject(ClientThread, INFINITE);
WaitForSingleObject(ServerThread, INFINITE);
/* FIXME: Since this function always returns 0 this test is very much useless */
return 0;
}

View File

@ -60,10 +60,12 @@ static void module_init()
static TP_POOL DEFAULT_POOL =
{
0, /* Minimum */
500, /* Maximum */
NULL, /* Threads */
0, /* ThreadCount */
0, /* DWORD Minimum */
500, /* DWORD Maximum */
NULL, /* wArrayList* Threads */
NULL, /* wQueue* PendingQueue */
NULL, /* HANDLE TerminateEvent */
NULL, /* wCountdownEvent* WorkComplete */
};
static void* thread_pool_work_func(void* arg)
@ -110,33 +112,62 @@ static void threads_close(void *thread)
CloseHandle(thread);
}
void InitializeThreadpool(PTP_POOL pool)
static BOOL InitializeThreadpool(PTP_POOL pool)
{
int index;
HANDLE thread;
if (!pool->Threads)
if (pool->Threads)
return TRUE;
pool->Minimum = 0;
pool->Maximum = 500;
if (!(pool->PendingQueue = Queue_New(TRUE, -1, -1)))
goto fail_queue_new;
if (!(pool->WorkComplete = CountdownEvent_New(0)))
goto fail_countdown_event;
if (!(pool->TerminateEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
goto fail_terminate_event;
if (!(pool->Threads = ArrayList_New(TRUE)))
goto fail_thread_array;
pool->Threads->object.fnObjectFree = threads_close;
for (index = 0; index < 4; index++)
{
pool->Minimum = 0;
pool->Maximum = 500;
pool->Threads = ArrayList_New(TRUE);
pool->Threads->object.fnObjectFree = threads_close;
pool->PendingQueue = Queue_New(TRUE, -1, -1);
pool->WorkComplete = CountdownEvent_New(0);
pool->TerminateEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
for (index = 0; index < 4; index++)
{
thread = CreateThread(NULL, 0,
if (!(thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) thread_pool_work_func,
(void*) pool, 0, NULL);
ArrayList_Add(pool->Threads, thread);
(void*) pool, 0, NULL)))
{
goto fail_create_threads;
}
ArrayList_Add(pool->Threads, thread);
}
return TRUE;
fail_create_threads:
SetEvent(pool->TerminateEvent);
ArrayList_Free(pool->Threads);
pool->Threads = NULL;
fail_thread_array:
CloseHandle(pool->TerminateEvent);
pool->TerminateEvent = NULL;
fail_terminate_event:
CountdownEvent_Free(pool->WorkComplete);
pool->WorkComplete = NULL;
fail_countdown_event:
Queue_Free(pool->PendingQueue);
pool->WorkComplete = NULL;
fail_queue_new:
return FALSE;
}
PTP_POOL GetDefaultThreadpool()
@ -145,7 +176,8 @@ PTP_POOL GetDefaultThreadpool()
pool = &DEFAULT_POOL;
InitializeThreadpool(pool);
if (!InitializeThreadpool(pool))
return NULL;
return pool;
}
@ -164,13 +196,17 @@ PTP_POOL CreateThreadpool(PVOID reserved)
if (pCreateThreadpool)
return pCreateThreadpool(reserved);
#else
pool = (PTP_POOL) calloc(1, sizeof(TP_POOL));
if (!(pool = (PTP_POOL) calloc(1, sizeof(TP_POOL))))
return NULL;
if (pool)
InitializeThreadpool(pool);
#endif
if (!InitializeThreadpool(pool))
{
free(pool);
return NULL;
}
return pool;
#endif
}
VOID CloseThreadpool(PTP_POOL ptpp)
@ -188,7 +224,17 @@ VOID CloseThreadpool(PTP_POOL ptpp)
CountdownEvent_Free(ptpp->WorkComplete);
CloseHandle(ptpp->TerminateEvent);
free(ptpp);
if (ptpp == &DEFAULT_POOL)
{
ptpp->Threads = NULL;
ptpp->PendingQueue = NULL;
ptpp->WorkComplete = NULL;
ptpp->TerminateEvent = NULL;
}
else
{
free(ptpp);
}
#endif
}

View File

@ -18,7 +18,11 @@ int TestPoolThread(int argc, char* argv[])
{
TP_POOL* pool;
pool = CreateThreadpool(NULL);
if (!(pool = CreateThreadpool(NULL)))
{
printf("CreateThreadpool failed\n");
return -1;
}
SetThreadpoolThreadMinimum(pool, 8); /* default is 0 */
SetThreadpoolThreadMaximum(pool, 64); /* default is 500 */

View File

@ -58,7 +58,11 @@ int TestPoolWork(int argc, char* argv[])
printf("Private Thread Pool\n");
pool = CreateThreadpool(NULL);
if (!(pool = CreateThreadpool(NULL)))
{
printf("CreateThreadpool failure\n");
return -1;
}
SetThreadpoolThreadMinimum(pool, 4);
SetThreadpoolThreadMaximum(pool, 8);

View File

@ -1398,8 +1398,14 @@ WINSCARDAPI HANDLE WINAPI PCSC_SCardAccessStartedEvent(void)
if (!g_StartedEvent)
{
g_StartedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
SetEvent(g_StartedEvent);
if (!(g_StartedEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
return NULL;
if (!SetEvent(g_StartedEvent))
{
CloseHandle(g_StartedEvent);
return NULL;
}
}
g_StartedEventRefCount++;

View File

@ -36,12 +36,26 @@ int TestSynchBarrier(int argc, char* argv[])
g_Count = 0;
g_Event = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!(g_Event = CreateEvent(NULL, TRUE, FALSE, NULL)))
{
printf("%s: CreateEvent failed. GetLastError() = 0x%08x", __FUNCTION__, GetLastError());
return -1;
}
InitializeCriticalSectionAndSpinCount(&g_Lock, 4000);
if (!InitializeCriticalSectionAndSpinCount(&g_Lock, 4000))
{
printf("%s: InitializeCriticalSectionAndSpinCount failed. GetLastError() = 0x%08x", __FUNCTION__, GetLastError());
CloseHandle(g_Event);
return -1;
}
if (!InitializeSynchronizationBarrier(&g_Barrier, 5, -1))
{
printf("%s: InitializeSynchronizationBarrier failed. GetLastError() = 0x%08x", __FUNCTION__, GetLastError());
DeleteCriticalSection(&g_Lock);
CloseHandle(g_Event);
return -1;
}
for (index = 0; index < 5; index++)
{

View File

@ -57,6 +57,11 @@ int TestSynchTimerQueue(int argc, char* argv[])
APC_DATA apcData[TIMER_COUNT];
g_Event = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!g_Event)
{
printf("CreateEvent failed (%d)\n", (int) GetLastError());
return -1;
}
hTimerQueue = CreateTimerQueue();

View File

@ -44,9 +44,16 @@ int TestSynchWaitableTimerAPC(int argc, char* argv[])
if (!apcData)
{
printf("Memory allocation failed\n");
return -1;
goto cleanup;
}
g_Event = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!g_Event)
{
printf("Failed to create event\n");
goto cleanup;
}
hTimer = CreateWaitableTimer(NULL, FALSE, NULL);
if (!hTimer)

View File

@ -152,20 +152,32 @@ wCountdownEvent* CountdownEvent_New(DWORD initialCount)
{
wCountdownEvent* countdown = NULL;
countdown = (wCountdownEvent*) malloc(sizeof(wCountdownEvent));
if (!(countdown = (wCountdownEvent*) calloc(1, sizeof(wCountdownEvent))))
return NULL;
if (countdown)
{
countdown->count = initialCount;
countdown->initialCount = initialCount;
InitializeCriticalSectionAndSpinCount(&countdown->lock, 4000);
countdown->event = CreateEvent(NULL, TRUE, FALSE, NULL);
countdown->count = initialCount;
countdown->initialCount = initialCount;
if (countdown->count == 0)
SetEvent(countdown->event);
}
if (!InitializeCriticalSectionAndSpinCount(&countdown->lock, 4000))
goto fail_critical_section;
if (!(countdown->event = CreateEvent(NULL, TRUE, FALSE, NULL)))
goto fail_create_event;
if (countdown->count == 0)
if (!SetEvent(countdown->event))
goto fail_set_event;
return countdown;
fail_set_event:
CloseHandle(countdown->event);
fail_create_event:
DeleteCriticalSection(&countdown->lock);
fail_critical_section:
free(countdown);
return NULL;
}
void CountdownEvent_Free(wCountdownEvent* countdown)