diff --git a/channels/client/addin.c b/channels/client/addin.c index 11327403f..6339c54de 100644 --- a/channels/client/addin.c +++ b/channels/client/addin.c @@ -608,28 +608,25 @@ UINT channel_client_quit_handler(void* MsgsHandle) WINPR_ASSERT(internals->ctx); WINPR_ASSERT(internals->ctx->settings); + if (!(internals->ctx->settings->ThreadingFlags & THREADING_FLAGS_DISABLE_THREADS)) { - if (MessageQueue_PostQuit(internals->queue, 0) && - (WaitForSingleObject(internals->thread, INFINITE) == WAIT_FAILED)) + if (internals->queue && internals->thread) { - rc = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", rc); - return rc; + if (MessageQueue_PostQuit(internals->queue, 0) && + (WaitForSingleObject(internals->thread, INFINITE) == WAIT_FAILED)) + { + rc = GetLastError(); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", rc); + return rc; + } } MessageQueue_Free(internals->queue); CloseHandle(internals->thread); } - if (internals->data_in) - { - Stream_Free(internals->data_in, TRUE); - internals->data_in = NULL; - } - if (internals->channel_name) - { - free(internals->channel_name); - } + Stream_Free(internals->data_in, TRUE); + free(internals->channel_name); free(internals); return CHANNEL_RC_OK; } diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c index 98e1d9297..b21e790e0 100644 --- a/channels/drdynvc/client/drdynvc_main.c +++ b/channels/drdynvc/client/drdynvc_main.c @@ -775,6 +775,7 @@ static UINT drdynvc_send(drdynvcPlugin* drdynvc, wStream* s) status = CHANNEL_RC_BAD_CHANNEL_HANDLE; else { + WINPR_ASSERT(drdynvc->channelEntryPoints.pVirtualChannelWriteEx); status = drdynvc->channelEntryPoints.pVirtualChannelWriteEx( drdynvc->InitHandle, drdynvc->OpenHandle, Stream_Buffer(s), (UINT32)Stream_GetPosition(s), s); @@ -1499,6 +1500,7 @@ static UINT drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc, LPVO if (!drdynvc) return CHANNEL_RC_BAD_CHANNEL_HANDLE; + WINPR_ASSERT(drdynvc->channelEntryPoints.pVirtualChannelOpenEx); status = drdynvc->channelEntryPoints.pVirtualChannelOpenEx( drdynvc->InitHandle, &drdynvc->OpenHandle, drdynvc->channelDef.name, drdynvc_virtual_channel_open_event_ex); @@ -1556,24 +1558,32 @@ static UINT drdynvc_virtual_channel_event_disconnected(drdynvcPlugin* drdynvc) if (drdynvc->OpenHandle == 0) return CHANNEL_RC_OK; - if (!MessageQueue_PostQuit(drdynvc->queue, 0)) + if (drdynvc->queue) { - status = GetLastError(); - WLog_Print(drdynvc->log, WLOG_ERROR, "MessageQueue_PostQuit failed with error %" PRIu32 "", - status); - return status; + if (!MessageQueue_PostQuit(drdynvc->queue, 0)) + { + status = GetLastError(); + WLog_Print(drdynvc->log, WLOG_ERROR, + "MessageQueue_PostQuit failed with error %" PRIu32 "", status); + return status; + } } - if (WaitForSingleObject(drdynvc->thread, INFINITE) != WAIT_OBJECT_0) + if (drdynvc->thread) { - status = GetLastError(); - WLog_Print(drdynvc->log, WLOG_ERROR, "WaitForSingleObject failed with error %" PRIu32 "", - status); - return status; + if (WaitForSingleObject(drdynvc->thread, INFINITE) != WAIT_OBJECT_0) + { + status = GetLastError(); + WLog_Print(drdynvc->log, WLOG_ERROR, + "WaitForSingleObject failed with error %" PRIu32 "", status); + return status; + } + + CloseHandle(drdynvc->thread); + drdynvc->thread = NULL; } - CloseHandle(drdynvc->thread); - drdynvc->thread = NULL; + WINPR_ASSERT(drdynvc->channelEntryPoints.pVirtualChannelCloseEx); status = drdynvc->channelEntryPoints.pVirtualChannelCloseEx(drdynvc->InitHandle, drdynvc->OpenHandle); @@ -1584,7 +1594,8 @@ static UINT drdynvc_virtual_channel_event_disconnected(drdynvcPlugin* drdynvc) } dvcman_clear(drdynvc, drdynvc->channel_mgr); - MessageQueue_Clear(drdynvc->queue); + if (drdynvc->queue) + MessageQueue_Clear(drdynvc->queue); drdynvc->OpenHandle = 0; if (drdynvc->data_in) @@ -1811,6 +1822,8 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_EX pEntryPoints, PVOI CopyMemory(&(drdynvc->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX)); drdynvc->InitHandle = pInitHandle; + + WINPR_ASSERT(drdynvc->channelEntryPoints.pVirtualChannelInitEx); rc = drdynvc->channelEntryPoints.pVirtualChannelInitEx( drdynvc, context, pInitHandle, &drdynvc->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, drdynvc_virtual_channel_init_event_ex); diff --git a/channels/encomsp/client/encomsp_main.c b/channels/encomsp/client/encomsp_main.c index d698dcfe7..a908776a5 100644 --- a/channels/encomsp/client/encomsp_main.c +++ b/channels/encomsp/client/encomsp_main.c @@ -1175,18 +1175,23 @@ static UINT encomsp_virtual_channel_event_disconnected(encomspPlugin* encomsp) if (encomsp->OpenHandle == 0) return CHANNEL_RC_OK; - if (MessageQueue_PostQuit(encomsp->queue, 0) && - (WaitForSingleObject(encomsp->thread, INFINITE) == WAIT_FAILED)) + if (encomsp->queue && encomsp->thread) { - rc = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", rc); - return rc; + if (MessageQueue_PostQuit(encomsp->queue, 0) && + (WaitForSingleObject(encomsp->thread, INFINITE) == WAIT_FAILED)) + { + rc = GetLastError(); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", rc); + return rc; + } } MessageQueue_Free(encomsp->queue); CloseHandle(encomsp->thread); encomsp->queue = NULL; encomsp->thread = NULL; + + WINPR_ASSERT(encomsp->channelEntryPoints.pVirtualChannelCloseEx); rc = encomsp->channelEntryPoints.pVirtualChannelCloseEx(encomsp->InitHandle, encomsp->OpenHandle); diff --git a/channels/rail/client/rail_main.c b/channels/rail/client/rail_main.c index d8bebe18b..58a461cd3 100644 --- a/channels/rail/client/rail_main.c +++ b/channels/rail/client/rail_main.c @@ -602,11 +602,11 @@ static UINT rail_virtual_channel_event_disconnected(railPlugin* rail) { UINT rc; + channel_client_quit_handler(rail->MsgsHandle); if (rail->OpenHandle == 0) return CHANNEL_RC_OK; - channel_client_quit_handler(rail->MsgsHandle); - + WINPR_ASSERT(rail->channelEntryPoints.pVirtualChannelCloseEx); rc = rail->channelEntryPoints.pVirtualChannelCloseEx(rail->InitHandle, rail->OpenHandle); if (CHANNEL_RC_OK != rc) diff --git a/channels/rdp2tcp/client/rdp2tcp_main.c b/channels/rdp2tcp/client/rdp2tcp_main.c index d05b9ebe1..20c50d44c 100644 --- a/channels/rdp2tcp/client/rdp2tcp_main.c +++ b/channels/rdp2tcp/client/rdp2tcp_main.c @@ -182,6 +182,8 @@ static void closeChannel(Plugin* plugin) if (debug) puts("rdp2tcp closing channel"); + WINPR_ASSERT(plugin); + WINPR_ASSERT(plugin->channelEntryPoints.pVirtualChannelCloseEx); plugin->channelEntryPoints.pVirtualChannelCloseEx(plugin->initHandle, plugin->openHandle); } diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index e0834fa7b..dbc2242c2 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -1908,12 +1908,15 @@ static UINT rdpdr_virtual_channel_event_disconnected(rdpdrPlugin* rdpdr) if (rdpdr->OpenHandle == 0) return CHANNEL_RC_OK; - if (MessageQueue_PostQuit(rdpdr->queue, 0) && - (WaitForSingleObject(rdpdr->thread, INFINITE) == WAIT_FAILED)) + if (rdpdr->queue && rdpdr->thread) { - error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", error); - return error; + if (MessageQueue_PostQuit(rdpdr->queue, 0) && + (WaitForSingleObject(rdpdr->thread, INFINITE) == WAIT_FAILED)) + { + error = GetLastError(); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", error); + return error; + } } MessageQueue_Free(rdpdr->queue); @@ -1921,6 +1924,7 @@ static UINT rdpdr_virtual_channel_event_disconnected(rdpdrPlugin* rdpdr) rdpdr->queue = NULL; rdpdr->thread = NULL; + WINPR_ASSERT(rdpdr->channelEntryPoints.pVirtualChannelCloseEx); error = rdpdr->channelEntryPoints.pVirtualChannelCloseEx(rdpdr->InitHandle, rdpdr->OpenHandle); if (CHANNEL_RC_OK != error) diff --git a/channels/rdpsnd/client/rdpsnd_main.c b/channels/rdpsnd/client/rdpsnd_main.c index 28bc4bb2b..e7effb671 100644 --- a/channels/rdpsnd/client/rdpsnd_main.c +++ b/channels/rdpsnd/client/rdpsnd_main.c @@ -1191,16 +1191,6 @@ static UINT rdpsnd_virtual_channel_event_connected(rdpsndPlugin* rdpsnd, LPVOID WINPR_ASSERT(rdpsnd); - rdpsnd->dsp_context = freerdp_dsp_context_new(FALSE); - - if (!rdpsnd->dsp_context) - goto fail; - - rdpsnd->pool = StreamPool_New(TRUE, 4096); - - if (!rdpsnd->pool) - goto fail; - status = rdpsnd->channelEntryPoints.pVirtualChannelOpenEx( rdpsnd->InitHandle, &rdpsnd->OpenHandle, rdpsnd->channelDef.name, rdpsnd_virtual_channel_open_event_ex); @@ -1214,9 +1204,6 @@ static UINT rdpsnd_virtual_channel_event_connected(rdpsndPlugin* rdpsnd, LPVOID return rdpsnd_process_connect(rdpsnd); fail: - freerdp_dsp_context_free(rdpsnd->dsp_context); - StreamPool_Free(rdpsnd->pool); - return CHANNEL_RC_NO_MEMORY; } @@ -1229,26 +1216,26 @@ static UINT rdpsnd_virtual_channel_event_disconnected(rdpsndPlugin* rdpsnd) { UINT error; - if (rdpsnd->OpenHandle == 0) - return CHANNEL_RC_OK; - - if (rdpsnd->device) - IFCALL(rdpsnd->device->Close, rdpsnd->device); - - error = - rdpsnd->channelEntryPoints.pVirtualChannelCloseEx(rdpsnd->InitHandle, rdpsnd->OpenHandle); - - if (CHANNEL_RC_OK != error) + if (rdpsnd->OpenHandle != 0) { - WLog_ERR(TAG, "%s pVirtualChannelCloseEx failed with %s [%08" PRIX32 "]", - rdpsnd_is_dyn_str(rdpsnd->dynamic), WTSErrorToString(error), error); - return error; + if (rdpsnd->device) + IFCALL(rdpsnd->device->Close, rdpsnd->device); + + error = rdpsnd->channelEntryPoints.pVirtualChannelCloseEx(rdpsnd->InitHandle, + rdpsnd->OpenHandle); + + if (CHANNEL_RC_OK != error) + { + WLog_ERR(TAG, "%s pVirtualChannelCloseEx failed with %s [%08" PRIX32 "]", + rdpsnd_is_dyn_str(rdpsnd->dynamic), WTSErrorToString(error), error); + return error; + } + + rdpsnd->OpenHandle = 0; } - rdpsnd->OpenHandle = 0; - freerdp_dsp_context_free(rdpsnd->dsp_context); - StreamPool_Return(rdpsnd->pool, rdpsnd->data_in); - StreamPool_Free(rdpsnd->pool); + if (rdpsnd->pool) + StreamPool_Return(rdpsnd->pool, rdpsnd->data_in); audio_formats_free(rdpsnd->ClientFormats, rdpsnd->NumberOfClientFormats); rdpsnd->NumberOfClientFormats = 0; @@ -1272,6 +1259,38 @@ static void _queue_free(void* obj) Stream_Release(s); } +static void free_internals(rdpsndPlugin* rdpsnd) +{ + if (!rdpsnd) + return; + + freerdp_dsp_context_free(rdpsnd->dsp_context); + StreamPool_Free(rdpsnd->pool); + rdpsnd->pool = NULL; + rdpsnd->dsp_context = NULL; +} + +static BOOL allocate_internals(rdpsndPlugin* rdpsnd) +{ + WINPR_ASSERT(rdpsnd); + + if (!rdpsnd->pool) + { + rdpsnd->pool = StreamPool_New(TRUE, 4096); + if (!rdpsnd->pool) + return FALSE; + } + + if (!rdpsnd->dsp_context) + { + rdpsnd->dsp_context = freerdp_dsp_context_new(FALSE); + if (!rdpsnd->dsp_context) + return FALSE; + } + + return TRUE; +} + static DWORD WINAPI play_thread(LPVOID arg) { UINT error = CHANNEL_RC_OK; @@ -1320,6 +1339,10 @@ static UINT rdpsnd_virtual_channel_event_initialized(rdpsndPlugin* rdpsnd) rdpsnd->thread = CreateThread(NULL, 0, play_thread, rdpsnd, 0, NULL); if (!rdpsnd->thread) return CHANNEL_RC_INITIALIZATION_ERROR; + + if (!allocate_internals(rdpsnd)) + return CHANNEL_RC_NO_MEMORY; + return CHANNEL_RC_OK; } @@ -1327,7 +1350,9 @@ static void rdpsnd_virtual_channel_event_terminated(rdpsndPlugin* rdpsnd) { if (rdpsnd) { - MessageQueue_PostQuit(rdpsnd->queue, 0); + if (rdpsnd->queue) + MessageQueue_PostQuit(rdpsnd->queue, 0); + if (rdpsnd->thread) { WaitForSingleObject(rdpsnd->thread, INFINITE); @@ -1335,6 +1360,7 @@ static void rdpsnd_virtual_channel_event_terminated(rdpsndPlugin* rdpsnd) } MessageQueue_Free(rdpsnd->queue); + free_internals(rdpsnd); audio_formats_free(rdpsnd->fixed_format, 1); free(rdpsnd->subsystem); free(rdpsnd->device_name); @@ -1445,6 +1471,8 @@ BOOL VCAPITYPE rdpsnd_VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, CopyMemory(&(rdpsnd->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX)); rdpsnd->InitHandle = pInitHandle; + + WINPR_ASSERT(rdpsnd->channelEntryPoints.pVirtualChannelInitEx); rc = rdpsnd->channelEntryPoints.pVirtualChannelInitEx( rdpsnd, NULL, pInitHandle, &rdpsnd->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, rdpsnd_virtual_channel_init_event_ex); @@ -1463,21 +1491,17 @@ BOOL VCAPITYPE rdpsnd_VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, static UINT rdpsnd_on_open(IWTSVirtualChannelCallback* pChannelCallback) { RDPSND_CHANNEL_CALLBACK* callback = (RDPSND_CHANNEL_CALLBACK*)pChannelCallback; - rdpsndPlugin* rdpsnd = (rdpsndPlugin*)callback->plugin; + rdpsndPlugin* rdpsnd; - rdpsnd->dsp_context = freerdp_dsp_context_new(FALSE); - if (!rdpsnd->dsp_context) - goto fail; + WINPR_ASSERT(callback); - rdpsnd->pool = StreamPool_New(TRUE, 4096); - if (!rdpsnd->pool) - goto fail; + rdpsnd = (rdpsndPlugin*)callback->plugin; + WINPR_ASSERT(rdpsnd); + + if (!allocate_internals(rdpsnd)) + return ERROR_OUTOFMEMORY; return rdpsnd_process_connect(rdpsnd); -fail: - freerdp_dsp_context_free(rdpsnd->dsp_context); - StreamPool_Free(rdpsnd->pool); - return CHANNEL_RC_NO_MEMORY; } static UINT rdpsnd_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream* data) @@ -1510,17 +1534,19 @@ static UINT rdpsnd_on_data_received(IWTSVirtualChannelCallback* pChannelCallback static UINT rdpsnd_on_close(IWTSVirtualChannelCallback* pChannelCallback) { RDPSND_CHANNEL_CALLBACK* callback = (RDPSND_CHANNEL_CALLBACK*)pChannelCallback; - rdpsndPlugin* rdpsnd = (rdpsndPlugin*)callback->plugin; + rdpsndPlugin* rdpsnd; + + WINPR_ASSERT(callback); + + rdpsnd = (rdpsndPlugin*)callback->plugin; + WINPR_ASSERT(rdpsnd); if (rdpsnd->device) IFCALL(rdpsnd->device->Close, rdpsnd->device); - freerdp_dsp_context_free(rdpsnd->dsp_context); - rdpsnd->dsp_context = NULL; + if (rdpsnd->pool) { StreamPool_Return(rdpsnd->pool, rdpsnd->data_in); - StreamPool_Free(rdpsnd->pool); - rdpsnd->pool = NULL; } audio_formats_free(rdpsnd->ClientFormats, rdpsnd->NumberOfClientFormats); @@ -1535,6 +1561,7 @@ static UINT rdpsnd_on_close(IWTSVirtualChannelCallback* pChannelCallback) rdpsnd->device = NULL; } + free_internals(rdpsnd); free(pChannelCallback); return CHANNEL_RC_OK; } diff --git a/channels/remdesk/client/remdesk_main.c b/channels/remdesk/client/remdesk_main.c index 144f5d61b..1e72867c9 100644 --- a/channels/remdesk/client/remdesk_main.c +++ b/channels/remdesk/client/remdesk_main.c @@ -965,13 +965,10 @@ error_out: */ static UINT remdesk_virtual_channel_event_disconnected(remdeskPlugin* remdesk) { - UINT rc; + UINT rc = CHANNEL_RC_OK; WINPR_ASSERT(remdesk); - if (remdesk->OpenHandle == 0) - return CHANNEL_RC_OK; - if (remdesk->queue && remdesk->thread) { if (MessageQueue_PostQuit(remdesk->queue, 0) && @@ -983,26 +980,26 @@ static UINT remdesk_virtual_channel_event_disconnected(remdeskPlugin* remdesk) } } + if (remdesk->OpenHandle != 0) + { + WINPR_ASSERT(remdesk->channelEntryPoints.pVirtualChannelCloseEx); + rc = remdesk->channelEntryPoints.pVirtualChannelCloseEx(remdesk->InitHandle, + remdesk->OpenHandle); + + if (CHANNEL_RC_OK != rc) + { + WLog_ERR(TAG, "pVirtualChannelCloseEx failed with %s [%08" PRIX32 "]", + WTSErrorToString(rc), rc); + } + + remdesk->OpenHandle = 0; + } MessageQueue_Free(remdesk->queue); CloseHandle(remdesk->thread); - remdesk->queue = NULL; - remdesk->thread = NULL; - - WINPR_ASSERT(remdesk->channelEntryPoints.pVirtualChannelCloseEx); - rc = remdesk->channelEntryPoints.pVirtualChannelCloseEx(remdesk->InitHandle, - remdesk->OpenHandle); - - if (CHANNEL_RC_OK != rc) - { - WLog_ERR(TAG, "pVirtualChannelCloseEx failed with %s [%08" PRIX32 "]", WTSErrorToString(rc), - rc); - } - - remdesk->OpenHandle = 0; - Stream_Free(remdesk->data_in, TRUE); remdesk->data_in = NULL; - + remdesk->queue = NULL; + remdesk->thread = NULL; return rc; }