diff --git a/libfreerdp/core/peer.c b/libfreerdp/core/peer.c index 2c982024a..c5d71ae5e 100644 --- a/libfreerdp/core/peer.c +++ b/libfreerdp/core/peer.c @@ -93,14 +93,11 @@ static HANDLE freerdp_peer_virtual_channel_open(freerdp_peer* client, const char return (HANDLE)peerChannel; } - peerChannel = (rdpPeerChannel*)calloc(1, sizeof(rdpPeerChannel)); + peerChannel = server_channel_common_new(client, index, mcsChannel->ChannelId, 128, NULL, name); if (peerChannel) { - peerChannel->index = index; - peerChannel->client = client; peerChannel->channelFlags = flags; - peerChannel->channelId = mcsChannel->ChannelId; peerChannel->mcsChannel = mcsChannel; mcsChannel->handle = (void*)peerChannel; } @@ -122,7 +119,7 @@ static BOOL freerdp_peer_virtual_channel_close(freerdp_peer* client, HANDLE hCha mcsChannel = peerChannel->mcsChannel; WINPR_ASSERT(mcsChannel); mcsChannel->handle = NULL; - free(peerChannel); + server_channel_common_free(peerChannel); return TRUE; } diff --git a/libfreerdp/core/server.c b/libfreerdp/core/server.c index c4fe36deb..84e32f4d3 100644 --- a/libfreerdp/core/server.c +++ b/libfreerdp/core/server.c @@ -944,7 +944,10 @@ static void wts_virtual_channel_manager_free_message(void* obj) } } -static void channel_free(rdpPeerChannel* channel); +static void channel_free(rdpPeerChannel* channel) +{ + server_channel_common_free(channel); +} static void array_channel_free(void* ptr) { @@ -1230,23 +1233,15 @@ static void peer_channel_queue_free_message(void* obj) msg->context = NULL; } -void channel_free(rdpPeerChannel* channel) -{ - if (!channel) - return; - - MessageQueue_Free(channel->queue); - Stream_Free(channel->receiveData, TRUE); - free(channel); -} - static rdpPeerChannel* channel_new(WTSVirtualChannelManager* vcm, freerdp_peer* client, UINT32 ChannelId, UINT16 index, UINT16 type, size_t chunkSize, const char* name) { - size_t len; wObject queueCallbacks = { 0 }; - rdpPeerChannel* channel = (rdpPeerChannel*)calloc(1, sizeof(rdpPeerChannel)); + queueCallbacks.fnObjectFree = peer_channel_queue_free_message; + + rdpPeerChannel* channel = + server_channel_common_new(client, index, ChannelId, chunkSize, &queueCallbacks, name); WINPR_ASSERT(vcm); WINPR_ASSERT(client); @@ -1254,27 +1249,10 @@ static rdpPeerChannel* channel_new(WTSVirtualChannelManager* vcm, freerdp_peer* if (!channel) goto fail; - len = strnlen(name, sizeof(channel->channelName) - 1); - strncpy(channel->channelName, name, len); - channel->vcm = vcm; - channel->client = client; - channel->channelId = ChannelId; - channel->index = index; channel->channelType = type; channel->creationStatus = (type == RDP_PEER_CHANNEL_TYPE_SVC) ? ERROR_SUCCESS : ERROR_OPERATION_IN_PROGRESS; - channel->receiveData = Stream_New(NULL, chunkSize); - - if (!channel->receiveData) - goto fail; - - queueCallbacks.fnObjectFree = peer_channel_queue_free_message; - - channel->queue = MessageQueue_New(&queueCallbacks); - - if (!channel->queue) - goto fail; return channel; fail: @@ -1479,8 +1457,7 @@ BOOL WINAPI FreeRDP_WTSVirtualChannelClose(HANDLE hChannelHandle) { rdpMcsChannel* cur = &mcs->channels[channel->index]; rdpPeerChannel* peerChannel = (rdpPeerChannel*)cur->handle; - if (peerChannel) - channel_free(peerChannel); + channel_free(peerChannel); cur->handle = NULL; } } @@ -1568,11 +1545,12 @@ BOOL WINAPI FreeRDP_WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, UINT32 written; UINT32 totalWritten = 0; rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle; - BOOL ret = TRUE; + BOOL ret = FALSE; if (!channel) return FALSE; + EnterCriticalSection(&channel->writeLock); WINPR_ASSERT(channel->vcm); if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC) { @@ -1582,7 +1560,7 @@ BOOL WINAPI FreeRDP_WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, if (!buffer) { SetLastError(E_OUTOFMEMORY); - return FALSE; + goto fail; } CopyMemory(buffer, Buffer, length); @@ -1592,7 +1570,7 @@ BOOL WINAPI FreeRDP_WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, else if (!channel->vcm->drdynvc_channel || (channel->vcm->drdynvc_state != DRDYNVC_STATE_READY)) { DEBUG_DVC("drdynvc not ready"); - return FALSE; + goto fail; } else { @@ -1610,7 +1588,7 @@ BOOL WINAPI FreeRDP_WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, { WLog_ERR(TAG, "Stream_New failed!"); SetLastError(E_OUTOFMEMORY); - return FALSE; + goto fail; } buffer = Stream_Buffer(s); @@ -1639,13 +1617,17 @@ BOOL WINAPI FreeRDP_WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, Length -= written; Buffer += written; totalWritten += written; - ret = wts_queue_send_item(channel->vcm->drdynvc_channel, buffer, length); + if (!wts_queue_send_item(channel->vcm->drdynvc_channel, buffer, length)) + goto fail; } } if (pBytesWritten) *pBytesWritten = totalWritten; + ret = TRUE; +fail: + LeaveCriticalSection(&channel->writeLock); return ret; } @@ -1936,3 +1918,41 @@ BOOL WINAPI FreeRDP_WTSLogonUser(HANDLE hServer, LPCSTR username, LPCSTR passwor { return FALSE; } + +void server_channel_common_free(rdpPeerChannel* channel) +{ + if (!channel) + return; + MessageQueue_Free(channel->queue); + Stream_Free(channel->receiveData, TRUE); + DeleteCriticalSection(&channel->writeLock); + free(channel); +} + +rdpPeerChannel* server_channel_common_new(freerdp_peer* client, UINT16 index, UINT32 channelId, + size_t chunkSize, const wObject* callback, + const char* name) +{ + rdpPeerChannel* channel = (rdpPeerChannel*)calloc(1, sizeof(rdpPeerChannel)); + if (!channel) + return NULL; + + InitializeCriticalSection(&channel->writeLock); + + channel->receiveData = Stream_New(NULL, chunkSize); + if (!channel->receiveData) + goto fail; + + channel->queue = MessageQueue_New(callback); + if (!channel->queue) + goto fail; + + channel->index = index; + channel->client = client; + channel->channelId = channelId; + strncpy(channel->channelName, name, ARRAYSIZE(channel->channelName) - 1); + return channel; +fail: + server_channel_common_free(channel); + return NULL; +} diff --git a/libfreerdp/core/server.h b/libfreerdp/core/server.h index bcefa49f1..cbafa4d90 100644 --- a/libfreerdp/core/server.h +++ b/libfreerdp/core/server.h @@ -69,6 +69,7 @@ struct rdp_peer_channel rdpMcsChannel* mcsChannel; char channelName[128]; + CRITICAL_SECTION writeLock; }; struct WTSVirtualChannelManager @@ -264,4 +265,9 @@ FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSLogoffUser(HANDLE hServer); FREERDP_LOCAL BOOL WINAPI FreeRDP_WTSLogonUser(HANDLE hServer, LPCSTR username, LPCSTR password, LPCSTR domain); +FREERDP_LOCAL rdpPeerChannel* server_channel_common_new(freerdp_peer* client, UINT16 index, + UINT32 channelId, size_t chunkSize, + const wObject* callback, const char* name); +FREERDP_LOCAL void server_channel_common_free(rdpPeerChannel*); + #endif /* FREERDP_LIB_CORE_SERVER_H */