BOOL rdpsnd_server_handle_messages(RdpsndServerContext *context) { DWORD bytesReturned; BOOL ret; RdpsndServerPrivate *priv = context->priv; wStream *s = priv->input_stream; if (!WTSVirtualChannelRead(priv->ChannelHandle, 0, (PCHAR)Stream_Pointer(s), priv->expectedBytes, &bytesReturned)) { if (GetLastError() == ERROR_NO_DATA) return TRUE; CLOG_ERR( "%s: channel connection closed\n", __FUNCTION__); return FALSE; } priv->expectedBytes -= bytesReturned; Stream_Seek(s, bytesReturned); if (priv->expectedBytes) return TRUE; Stream_SetPosition(s, 0); if (priv->waitingHeader) { /* header case */ Stream_Read_UINT8(s, priv->msgType); Stream_Seek_UINT8(s); /* bPad */ Stream_Read_UINT16(s, priv->expectedBytes); priv->waitingHeader = FALSE; Stream_SetPosition(s, 0); if (priv->expectedBytes) { Stream_EnsureCapacity(s, priv->expectedBytes); return TRUE; } } /* when here we have the header + the body */ #ifdef WITH_DEBUG_SND CLOG_ERR( "%s: message type %d\n", __FUNCTION__, priv->msgType); #endif priv->expectedBytes = 4; priv->waitingHeader = TRUE; switch (priv->msgType) { case SNDC_WAVECONFIRM: ret = rdpsnd_server_recv_waveconfirm(context, s); break; case SNDC_FORMATS: ret = rdpsnd_server_recv_formats(context, s); break; case SNDC_QUALITYMODE: ret = rdpsnd_server_recv_quality_mode(context, s); Stream_SetPosition(s, 0); /* in case the Activated callback tries to treat some messages */ if (ret) { IFCALL(context->Activated, context); } break; default: CLOG_ERR( "%s: UNKOWN MESSAGE TYPE!! (%#0X)\n\n", __FUNCTION__, priv->msgType); ret = FALSE; break; } Stream_SetPosition(s, 0); return ret; }
static void* rdpsnd_server_thread(void* arg) { wStream* s; DWORD status; DWORD nCount; void* buffer; BYTE msgType; UINT16 BodySize; HANDLE events[8]; HANDLE ChannelEvent; DWORD BytesReturned; RdpsndServerContext* context; BOOL doRun; context = (RdpsndServerContext *)arg; buffer = NULL; BytesReturned = 0; ChannelEvent = NULL; s = Stream_New(NULL, 4096); if (!s) return NULL; if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned)) { if (BytesReturned == sizeof(HANDLE)) CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE)); WTSFreeMemory(buffer); } nCount = 0; if (ChannelEvent) events[nCount++] = ChannelEvent; events[nCount++] = context->priv->StopEvent; if (!rdpsnd_server_send_formats(context, s)) goto out; doRun = TRUE; while (doRun) { status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0) break; Stream_SetPosition(s, 0); if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, (PCHAR)Stream_Buffer(s), Stream_Capacity(s), &BytesReturned)) { if (!BytesReturned) break; Stream_EnsureRemainingCapacity(s, BytesReturned); if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, (PCHAR)Stream_Buffer(s), Stream_Capacity(s), &BytesReturned)) break; } if (Stream_GetRemainingLength(s) < 4) break; Stream_Read_UINT8(s, msgType); Stream_Seek_UINT8(s); /* bPad */ Stream_Read_UINT16(s, BodySize); if (Stream_GetRemainingLength(s) < BodySize) break; switch (msgType) { case SNDC_WAVECONFIRM: doRun = rdpsnd_server_recv_waveconfirm(context, s); break; case SNDC_QUALITYMODE: doRun = rdpsnd_server_recv_quality_mode(context, s); break; case SNDC_FORMATS: doRun = rdpsnd_server_recv_formats(context, s); if (doRun) { IFCALL(context->Activated, context); } break; default: fprintf(stderr, "%s: UNKOWN MESSAGE TYPE!! (%#0X)\n\n", __FUNCTION__, msgType); break; } } out: Stream_Free(s, TRUE); return NULL; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT rdpsnd_server_handle_messages(RdpsndServerContext *context) { DWORD bytesReturned; UINT ret = CHANNEL_RC_OK; RdpsndServerPrivate *priv = context->priv; wStream *s = priv->input_stream; if (!WTSVirtualChannelRead(priv->ChannelHandle, 0, (PCHAR)Stream_Pointer(s), priv->expectedBytes, &bytesReturned)) { if (GetLastError() == ERROR_NO_DATA) return ERROR_NO_DATA; WLog_ERR(TAG, "channel connection closed"); return ERROR_INTERNAL_ERROR; } priv->expectedBytes -= bytesReturned; Stream_Seek(s, bytesReturned); if (priv->expectedBytes) return CHANNEL_RC_OK; Stream_SealLength(s); Stream_SetPosition(s, 0); if (priv->waitingHeader) { /* header case */ Stream_Read_UINT8(s, priv->msgType); Stream_Seek_UINT8(s); /* bPad */ Stream_Read_UINT16(s, priv->expectedBytes); priv->waitingHeader = FALSE; Stream_SetPosition(s, 0); if (priv->expectedBytes) { if (!Stream_EnsureCapacity(s, priv->expectedBytes)) { WLog_ERR(TAG, "Stream_EnsureCapacity failed!"); return CHANNEL_RC_NO_MEMORY; } return CHANNEL_RC_OK; } } /* when here we have the header + the body */ #ifdef WITH_DEBUG_SND WLog_DBG(TAG, "message type %d", priv->msgType); #endif priv->expectedBytes = 4; priv->waitingHeader = TRUE; switch (priv->msgType) { case SNDC_WAVECONFIRM: ret = rdpsnd_server_recv_waveconfirm(context, s); break; case SNDC_FORMATS: ret = rdpsnd_server_recv_formats(context, s); if ((ret == CHANNEL_RC_OK) && (context->clientVersion < 6)) IFCALL(context->Activated, context); break; case SNDC_QUALITYMODE: ret = rdpsnd_server_recv_quality_mode(context, s); Stream_SetPosition(s, 0); /* in case the Activated callback tries to treat some messages */ if ((ret == CHANNEL_RC_OK) && (context->clientVersion >= 6)) IFCALL(context->Activated, context); break; default: WLog_ERR(TAG, "UNKOWN MESSAGE TYPE!! (%#0X)", priv->msgType); ret = ERROR_INVALID_DATA; break; } Stream_SetPosition(s, 0); return ret; }