diff --git a/channels/audin/server/audin.c b/channels/audin/server/audin.c index 9f7506abb..31b3943f0 100644 --- a/channels/audin/server/audin.c +++ b/channels/audin/server/audin.c @@ -345,24 +345,16 @@ static void* audin_server_thread_func(void* arg) Stream_SetPosition(s, 0); + WTSVirtualChannelRead(audin->audin_channel, 0, NULL, 0, &BytesReturned); + if (BytesReturned < 1) + continue; + Stream_EnsureRemainingCapacity(s, BytesReturned); if (WTSVirtualChannelRead(audin->audin_channel, 0, (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned) == FALSE) { - if (BytesReturned == 0) - break; - - Stream_EnsureRemainingCapacity(s, BytesReturned); - - if (WTSVirtualChannelRead(audin->audin_channel, 0, (PCHAR) Stream_Buffer(s), - Stream_Capacity(s), &BytesReturned) == FALSE) - { - break; - } + break; } - if (BytesReturned < 1) - continue; - Stream_Read_UINT8(s, MessageId); BytesReturned--; diff --git a/channels/cliprdr/server/cliprdr_main.c b/channels/cliprdr/server/cliprdr_main.c index 0e94fabea..1a701e8a1 100644 --- a/channels/cliprdr/server/cliprdr_main.c +++ b/channels/cliprdr/server/cliprdr_main.c @@ -431,15 +431,14 @@ static void* cliprdr_server_thread(void* arg) break; } - if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0, - (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned)) + WTSVirtualChannelRead(context->priv->ChannelHandle, 0, NULL, 0, &BytesReturned); + if (BytesReturned < 1) + continue; + Stream_EnsureRemainingCapacity(s, BytesReturned); + if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, + (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned)) { - if (BytesReturned) - Stream_Seek(s, BytesReturned); - } - else - { - Stream_EnsureRemainingCapacity(s, BytesReturned); + break; } if (Stream_GetPosition(s) >= CLIPRDR_HEADER_LENGTH) diff --git a/channels/drdynvc/server/drdynvc_main.c b/channels/drdynvc/server/drdynvc_main.c index b6436c6a5..62cdafd57 100644 --- a/channels/drdynvc/server/drdynvc_main.c +++ b/channels/drdynvc/server/drdynvc_main.c @@ -67,15 +67,14 @@ static void* drdynvc_server_thread(void* arg) break; } - if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0, - (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned)) + WTSVirtualChannelRead(context->priv->ChannelHandle, 0, NULL, 0, &BytesReturned); + if (BytesReturned < 1) + continue; + Stream_EnsureRemainingCapacity(s, BytesReturned); + if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, + (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned)) { - if (BytesReturned) - Stream_Seek(s, BytesReturned); - } - else - { - Stream_EnsureRemainingCapacity(s, BytesReturned); + break; } } diff --git a/channels/encomsp/server/encomsp_main.c b/channels/encomsp/server/encomsp_main.c index 9d7fc5ae5..5f2ef2c71 100644 --- a/channels/encomsp/server/encomsp_main.c +++ b/channels/encomsp/server/encomsp_main.c @@ -72,15 +72,14 @@ static void* encomsp_server_thread(void* arg) break; } - if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0, - (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned)) + WTSVirtualChannelRead(context->priv->ChannelHandle, 0, NULL, 0, &BytesReturned); + if (BytesReturned < 1) + continue; + Stream_EnsureRemainingCapacity(s, BytesReturned); + if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, + (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned)) { - if (BytesReturned) - Stream_Seek(s, BytesReturned); - } - else - { - Stream_EnsureRemainingCapacity(s, BytesReturned); + break; } if (0) diff --git a/channels/rdpdr/server/rdpdr_main.c b/channels/rdpdr/server/rdpdr_main.c index 9b67388f0..09d768413 100644 --- a/channels/rdpdr/server/rdpdr_main.c +++ b/channels/rdpdr/server/rdpdr_main.c @@ -598,15 +598,14 @@ static void* rdpdr_server_thread(void* arg) break; } - if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0, (PCHAR) Stream_Pointer(s), - Stream_Capacity(s) - Stream_GetPosition(s), &BytesReturned)) + WTSVirtualChannelRead(context->priv->ChannelHandle, 0, NULL, 0, &BytesReturned); + if (BytesReturned < 1) + continue; + Stream_EnsureRemainingCapacity(s, BytesReturned); + if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, + (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned)) { - if (BytesReturned) - Stream_Seek(s, BytesReturned); - } - else - { - Stream_EnsureRemainingCapacity(s, BytesReturned); + break; } if (Stream_GetPosition(s) >= RDPDR_HEADER_LENGTH) diff --git a/channels/rdpsnd/server/rdpsnd_main.c b/channels/rdpsnd/server/rdpsnd_main.c index 8ad5cd984..74fe4ec14 100644 --- a/channels/rdpsnd/server/rdpsnd_main.c +++ b/channels/rdpsnd/server/rdpsnd_main.c @@ -626,7 +626,7 @@ BOOL rdpsnd_server_handle_messages(RdpsndServerContext *context) RdpsndServerPrivate *priv = context->priv; wStream *s = priv->input_stream; - if (!WTSVirtualChannelRead(priv->channelEvent, 0, (PCHAR)Stream_Pointer(s), priv->expectedBytes, &bytesReturned)) + if (!WTSVirtualChannelRead(priv->ChannelHandle, 0, (PCHAR)Stream_Pointer(s), priv->expectedBytes, &bytesReturned)) { if (GetLastError() == ERROR_NO_DATA) return TRUE; diff --git a/libfreerdp/core/server.c b/libfreerdp/core/server.c index 4e4e520e5..5f128de83 100644 --- a/libfreerdp/core/server.c +++ b/libfreerdp/core/server.c @@ -42,6 +42,15 @@ #define DEBUG_DVC(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #endif +struct _wtsChannelMessage +{ + UINT16 channelId; + UINT16 reserved; + UINT32 length; + UINT32 offset; +}; +typedef struct _wtsChannelMessage wtsChannelMessage; + static DWORD g_SessionId = 1; static wHashTable* g_ServerHandles = NULL; @@ -75,15 +84,16 @@ static rdpPeerChannel* wts_get_dvc_channel_by_id(WTSVirtualChannelManager* vcm, static void wts_queue_receive_data(rdpPeerChannel* channel, const BYTE* Buffer, UINT32 Length) { BYTE* buffer; - UINT32 length; - UINT16 channelId; + wtsChannelMessage* messageCtx; - length = Length; - buffer = (BYTE*) malloc(length); - CopyMemory(buffer, Buffer, length); - channelId = channel->channelId; + messageCtx = (wtsChannelMessage*) malloc(sizeof(wtsChannelMessage) + Length); + messageCtx->channelId = channel->channelId; + messageCtx->length = Length; + messageCtx->offset = 0; + buffer = (BYTE*) (messageCtx + 1); + CopyMemory(buffer, Buffer, Length); - MessageQueue_Post(channel->queue, (void*) (UINT_PTR) channelId, 0, (void*) buffer, (void*) (UINT_PTR) length); + MessageQueue_Post(channel->queue, messageCtx, 0, NULL, NULL); } static void wts_queue_send_item(rdpPeerChannel* channel, BYTE* Buffer, UINT32 Length) @@ -1027,28 +1037,35 @@ BOOL WINAPI FreeRDP_WTSVirtualChannelClose(HANDLE hChannelHandle) BOOL WINAPI FreeRDP_WTSVirtualChannelRead(HANDLE hChannelHandle, ULONG TimeOut, PCHAR Buffer, ULONG BufferSize, PULONG pBytesRead) { BYTE* buffer; - UINT32 length; - UINT16 channelId; wMessage message; + wtsChannelMessage* messageCtx; rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle; - if (!MessageQueue_Peek(channel->queue, &message, TRUE)) + if (!MessageQueue_Peek(channel->queue, &message, FALSE)) { + SetLastError(ERROR_NO_DATA); *pBytesRead = 0; - return TRUE; + return FALSE; } - channelId = (UINT16) (UINT_PTR) message.context; - buffer = (BYTE*) message.wParam; - length = (UINT32) (UINT_PTR) message.lParam; + messageCtx = (wtsChannelMessage*) (UINT_PTR) message.context; + buffer = (BYTE*) (messageCtx + 1); - *pBytesRead = length; + *pBytesRead = messageCtx->length - messageCtx->offset; + if (Buffer == NULL || BufferSize == 0) + { + return TRUE; + } + if (*pBytesRead > BufferSize) + *pBytesRead = BufferSize; - if (length > BufferSize) - return FALSE; - - CopyMemory(Buffer, buffer, length); - free(buffer); + CopyMemory(Buffer, buffer + messageCtx->offset, *pBytesRead); + messageCtx->offset += *pBytesRead; + if (messageCtx->offset >= messageCtx->length) + { + MessageQueue_Peek(channel->queue, &message, TRUE); + free(messageCtx); + } return TRUE; } diff --git a/server/Windows/wf_rdpsnd.c b/server/Windows/wf_rdpsnd.c index 0a4362d43..c37ab0570 100644 --- a/server/Windows/wf_rdpsnd.c +++ b/server/Windows/wf_rdpsnd.c @@ -160,7 +160,7 @@ BOOL wf_peer_rdpsnd_init(wfPeerContext* context) context->rdpsnd->Activated = wf_peer_rdpsnd_activated; - context->rdpsnd->Initialize(context->rdpsnd); + context->rdpsnd->Initialize(context->rdpsnd, TRUE); wf_rdpsnd_set_latest_peer(context);