Refactored channel error handling
* Fix WINPR_ASSERT if a client can not allocate new resources, terminated cleanly instead. * Add WINPR_ASSERT for lots of channel arguments
This commit is contained in:
parent
cde002f460
commit
95ecc6929a
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user