void cliprdr_process_format_list_event(cliprdrPlugin* cliprdr, RDP_CB_FORMAT_LIST_EVENT* cb_event) { int i; wStream* s; DEBUG_CLIPRDR("Sending Clipboard Format List"); if (cb_event->raw_format_data) { s = cliprdr_packet_new(CB_FORMAT_LIST, 0, cb_event->raw_format_data_size); Stream_Write(s, cb_event->raw_format_data, cb_event->raw_format_data_size); } else { wStream* body = Stream_New(NULL, 64); for (i = 0; i < cb_event->num_formats; i++) { const char* name; int name_length; switch (cb_event->formats[i]) { case CB_FORMAT_HTML: name = CFSTR_HTML; name_length = sizeof(CFSTR_HTML); break; case CB_FORMAT_PNG: name = CFSTR_PNG; name_length = sizeof(CFSTR_PNG); break; case CB_FORMAT_JPEG: name = CFSTR_JPEG; name_length = sizeof(CFSTR_JPEG); break; case CB_FORMAT_GIF: name = CFSTR_GIF; name_length = sizeof(CFSTR_GIF); break; default: name = "\0\0"; name_length = 2; break; } if (!cliprdr->use_long_format_names) name_length = 32; Stream_EnsureRemainingCapacity(body, Stream_Capacity(body) + 4 + name_length); Stream_Write_UINT32(body, cb_event->formats[i]); Stream_Write(body, name, name_length); } s = cliprdr_packet_new(CB_FORMAT_LIST, 0, Stream_Capacity(body)); Stream_Write(s, Stream_Buffer(body), Stream_Capacity(body)); Stream_Free(body, TRUE); } cliprdr_packet_send(cliprdr, s); }
static void* tf_debug_channel_thread_func(void* arg) { void* fd; wStream* s; void* buffer; DWORD BytesReturned = 0; testPeerContext* context = (testPeerContext*) arg; if (WTSVirtualChannelQuery(context->debug_channel, WTSVirtualFileHandle, &buffer, &BytesReturned) == TRUE) { fd = *((void**) buffer); WTSFreeMemory(buffer); context->event = CreateWaitObjectEvent(NULL, TRUE, FALSE, fd); } s = Stream_New(NULL, 4096); WTSVirtualChannelWrite(context->debug_channel, (PCHAR) "test1", 5, NULL); while (1) { WaitForSingleObject(context->event, INFINITE); if (WaitForSingleObject(context->stopEvent, 0) == WAIT_OBJECT_0) break; Stream_SetPosition(s, 0); if (WTSVirtualChannelRead(context->debug_channel, 0, (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned) == FALSE) { if (BytesReturned == 0) break; Stream_EnsureRemainingCapacity(s, BytesReturned); if (WTSVirtualChannelRead(context->debug_channel, 0, (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned) == FALSE) { /* should not happen */ break; } } Stream_SetPosition(s, BytesReturned); printf("got %lu bytes\n", BytesReturned); } Stream_Free(s, TRUE); return 0; }
wStream* StreamPool_Take(wStreamPool* pool, size_t size) { int index; int foundIndex; wStream* s = NULL; if (pool->synchronized) EnterCriticalSection(&pool->lock); if (size == 0) size = pool->defaultSize; foundIndex = -1; for (index = 0; index < pool->aSize; index++) { s = pool->aArray[index]; if (Stream_Capacity(s) >= size) { foundIndex = index; break; } } if (foundIndex < 0) { s = Stream_New(NULL, size); if (!s) goto out_fail; } else { Stream_SetPosition(s, 0); Stream_SetLength(s, Stream_Capacity(s)); StreamPool_ShiftAvailable(pool, foundIndex, -1); } if (s) { s->pool = pool; s->count = 1; StreamPool_AddUsed(pool, s); } out_fail: if (pool->synchronized) LeaveCriticalSection(&pool->lock); return s; }
int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, wStream* data) { int status = 0; DVCMAN_CHANNEL* channel; UINT32 dataSize = Stream_GetRemainingLength(data); channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId); if (!channel) { DEBUG_WARN("ChannelId %d not found!", ChannelId); return 1; } if (channel->dvc_data) { /* Fragmented data */ if (Stream_GetPosition(channel->dvc_data) + dataSize > (UINT32) Stream_Capacity(channel->dvc_data)) { DEBUG_WARN("data exceeding declared length!"); Stream_Release(channel->dvc_data); channel->dvc_data = NULL; return 1; } Stream_Write(channel->dvc_data, Stream_Pointer(data), dataSize); if (((size_t) Stream_GetPosition(channel->dvc_data)) >= Stream_Capacity(channel->dvc_data)) { Stream_SealLength(channel->dvc_data); Stream_SetPosition(channel->dvc_data, 0); status = channel->channel_callback->OnDataReceived(channel->channel_callback, channel->dvc_data); Stream_Release(channel->dvc_data); channel->dvc_data = NULL; } } else { status = channel->channel_callback->OnDataReceived(channel->channel_callback, data); } return status; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT rail_virtual_channel_event_data_received(railPlugin* rail, void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) { wStream* data_in; if ((dataFlags & CHANNEL_FLAG_SUSPEND) || (dataFlags & CHANNEL_FLAG_RESUME)) { return CHANNEL_RC_OK; } if (dataFlags & CHANNEL_FLAG_FIRST) { if (rail->data_in) Stream_Free(rail->data_in, TRUE); rail->data_in = Stream_New(NULL, totalLength); if (!rail->data_in) { WLog_ERR(TAG, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } } data_in = rail->data_in; if (!Stream_EnsureRemainingCapacity(data_in, (int) dataLength)) { WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); return CHANNEL_RC_NO_MEMORY; } Stream_Write(data_in, pData, dataLength); if (dataFlags & CHANNEL_FLAG_LAST) { if (Stream_Capacity(data_in) != Stream_GetPosition(data_in)) { WLog_ERR(TAG, "rail_plugin_process_received: read error"); return ERROR_INTERNAL_ERROR; } rail->data_in = NULL; Stream_SealLength(data_in); Stream_SetPosition(data_in, 0); if (!MessageQueue_Post(rail->queue, NULL, 0, (void*) data_in, NULL)) { WLog_ERR(TAG, "MessageQueue_Post failed!"); return ERROR_INTERNAL_ERROR; } } return CHANNEL_RC_OK; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc, void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) { wStream* data_in; if ((dataFlags & CHANNEL_FLAG_SUSPEND) || (dataFlags & CHANNEL_FLAG_RESUME)) { return CHANNEL_RC_OK; } if (dataFlags & CHANNEL_FLAG_FIRST) { if (drdynvc->data_in) Stream_Free(drdynvc->data_in, TRUE); drdynvc->data_in = Stream_New(NULL, totalLength); } if (!(data_in = drdynvc->data_in)) { WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } if (!Stream_EnsureRemainingCapacity(data_in, dataLength)) { WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!"); Stream_Free(drdynvc->data_in, TRUE); drdynvc->data_in = NULL; return ERROR_INTERNAL_ERROR; } Stream_Write(data_in, pData, dataLength); if (dataFlags & CHANNEL_FLAG_LAST) { if (Stream_Capacity(data_in) != Stream_GetPosition(data_in)) { WLog_Print(drdynvc->log, WLOG_ERROR, "drdynvc_plugin_process_received: read error"); return ERROR_INVALID_DATA; } drdynvc->data_in = NULL; Stream_SealLength(data_in); Stream_SetPosition(data_in, 0); if (!MessageQueue_Post(drdynvc->queue, NULL, 0, (void*) data_in, NULL)) { WLog_Print(drdynvc->log, WLOG_ERROR, "MessageQueue_Post failed!"); return ERROR_INTERNAL_ERROR; } } return CHANNEL_RC_OK; }
int dvcman_receive_channel_data(IWTSVirtualChannelManager *pChannelMgr, UINT32 ChannelId, BYTE *data, UINT32 data_size) { int error = 0; DVCMAN_CHANNEL *channel; channel = (DVCMAN_CHANNEL *) dvcman_find_channel_by_id(pChannelMgr, ChannelId); if (!channel) { DEBUG_WARN("ChannelId %d not found!", ChannelId); return 1; } if (channel->dvc_data) { /* Fragmented data */ if (Stream_GetPosition(channel->dvc_data) + data_size > (UINT32) Stream_Capacity(channel->dvc_data)) { DEBUG_WARN("data exceeding declared length!"); Stream_Free(channel->dvc_data, TRUE); channel->dvc_data = NULL; return 1; } Stream_Write(channel->dvc_data, data, data_size); if (((size_t) Stream_GetPosition(channel->dvc_data)) >= Stream_Capacity(channel->dvc_data)) { error = channel->channel_callback->OnDataReceived(channel->channel_callback, Stream_Capacity(channel->dvc_data), Stream_Buffer(channel->dvc_data)); Stream_Free(channel->dvc_data, TRUE); channel->dvc_data = NULL; } } else { assert(channel->channel_callback); assert(channel->channel_callback->OnDataReceived); error = channel->channel_callback->OnDataReceived(channel->channel_callback, data_size, data); } return error; }
wStream* rdg_receive_packet(rdpRdg* rdg) { int status; wStream* s; RdgPacketHeader* packet; UINT32 readCount = 0; s = Stream_New(NULL, 1024); if (!s) return NULL; packet = (RdgPacketHeader*) Stream_Buffer(s); while (readCount < sizeof(RdgPacketHeader)) { status = BIO_read(rdg->tlsOut->bio, Stream_Pointer(s), sizeof(RdgPacketHeader) - readCount); if (status < 0) { continue; } readCount += status; Stream_Seek(s, readCount); } if (Stream_Capacity(s) < packet->packetLength) { if (!Stream_EnsureCapacity(s, packet->packetLength)) { Stream_Free(s, TRUE); return NULL; } packet = (RdgPacketHeader*) Stream_Buffer(s); } while (readCount < packet->packetLength) { status = BIO_read(rdg->tlsOut->bio, Stream_Pointer(s), packet->packetLength - readCount); if (status < 0) { continue; } readCount += status; Stream_Seek(s, readCount); } Stream_SealLength(s); return s; }
void tf_peer_dump_rfx(freerdp_peer* client) { wStream* s; UINT32 prev_seconds; UINT32 prev_useconds; rdpUpdate* update; rdpPcap* pcap_rfx; pcap_record record; s = Stream_New(NULL, 512); update = client->update; client->update->pcap_rfx = pcap_open(test_pcap_file, FALSE); pcap_rfx = client->update->pcap_rfx; if (pcap_rfx == NULL) return; prev_seconds = prev_useconds = 0; while (pcap_has_next_record(pcap_rfx)) { pcap_get_next_record_header(pcap_rfx, &record); Stream_Buffer(s) = realloc(Stream_Buffer(s), record.length); record.data = Stream_Buffer(s); Stream_Capacity(s) = record.length; pcap_get_next_record_content(pcap_rfx, &record); Stream_Pointer(s) = Stream_Buffer(s) + Stream_Capacity(s); if (test_dump_rfx_realtime && test_sleep_tsdiff(&prev_seconds, &prev_useconds, record.header.ts_sec, record.header.ts_usec) == FALSE) break; update->SurfaceCommand(update->context, s); if (client->CheckFileDescriptor(client) != TRUE) break; } }
int cliprdr_client_format_list(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList) { wStream* s; UINT32 index; int length = 0; int formatNameSize; CLIPRDR_FORMAT* format; cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle; for (index = 0; index < formatList->numFormats; index++) { format = (CLIPRDR_FORMAT*) &(formatList->formats[index]); length += 4; formatNameSize = 2; if (format->formatName) formatNameSize = MultiByteToWideChar(CP_UTF8, 0, format->formatName, -1, NULL, 0) * 2; length += formatNameSize; } s = cliprdr_packet_new(CB_FORMAT_LIST, 0, length); for (index = 0; index < formatList->numFormats; index++) { format = (CLIPRDR_FORMAT*) &(formatList->formats[index]); Stream_Write_UINT32(s, format->formatId); /* formatId (4 bytes) */ if (format->formatName) { int cchWideChar; LPWSTR lpWideCharStr; lpWideCharStr = (LPWSTR) Stream_Pointer(s); cchWideChar = (Stream_Capacity(s) - Stream_GetPosition(s)) / 2; formatNameSize = MultiByteToWideChar(CP_UTF8, 0, format->formatName, -1, lpWideCharStr, cchWideChar) * 2; Stream_Seek(s, formatNameSize); } else { Stream_Write_UINT16(s, 0); } } WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientFormatList: numFormats: %d", formatList->numFormats); cliprdr_packet_send(cliprdr, s); return 0; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT dvcman_receive_channel_data(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, wStream* data) { UINT status = CHANNEL_RC_OK; DVCMAN_CHANNEL* channel; size_t dataSize = Stream_GetRemainingLength(data); channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId); if (!channel) { /* Windows 8.1 tries to open channels not created. * Ignore cases like this. */ WLog_Print(drdynvc->log, WLOG_ERROR, "ChannelId %"PRIu32" not found!", ChannelId); return CHANNEL_RC_OK; } if (channel->dvc_data) { /* Fragmented data */ if (Stream_GetPosition(channel->dvc_data) + dataSize > Stream_Capacity(channel->dvc_data)) { WLog_Print(drdynvc->log, WLOG_ERROR, "data exceeding declared length!"); Stream_Release(channel->dvc_data); channel->dvc_data = NULL; return ERROR_INVALID_DATA; } Stream_Copy(data, channel->dvc_data, dataSize); if (Stream_GetPosition(channel->dvc_data) >= channel->dvc_data_length) { Stream_SealLength(channel->dvc_data); Stream_SetPosition(channel->dvc_data, 0); status = channel->channel_callback->OnDataReceived(channel->channel_callback, channel->dvc_data); Stream_Release(channel->dvc_data); channel->dvc_data = NULL; } } else { status = channel->channel_callback->OnDataReceived(channel->channel_callback, data); } return status; }
wStream* StreamPool_Take(wStreamPool* pool, size_t size) { int index; int foundIndex; wStream* s = NULL; BOOL found = FALSE; if (pool->synchronized) WaitForSingleObject(pool->mutex, INFINITE); if (size == 0) size = pool->defaultSize; for (index = 0; index < pool->aSize; index++) { s = pool->aArray[index]; if (Stream_Capacity(s) >= size) { foundIndex = index; found = TRUE; break; } } if (!found) { s = Stream_New(NULL, size); } else { StreamPool_ShiftAvailable(pool, foundIndex, -1); Stream_EnsureCapacity(s, size); Stream_Pointer(s) = Stream_Buffer(s); } s->pool = pool; s->count = 1; StreamPool_AddUsed(pool, s); if (pool->synchronized) ReleaseMutex(pool->mutex); return s; }
wStream* StreamPool_Take(wStreamPool* pool, size_t size) { int index; int foundIndex; wStream* s = NULL; BOOL found = FALSE; if (pool->synchronized) EnterCriticalSection(&pool->lock); if (size == 0) size = pool->defaultSize; for (index = 0; index < pool->aSize; index++) { s = pool->aArray[index]; if (Stream_Capacity(s) >= size) { foundIndex = index; found = TRUE; break; } } if (!found) { s = Stream_New(NULL, size); } else { StreamPool_ShiftAvailable(pool, foundIndex, -1); Stream_EnsureCapacity(s, size); Stream_Pointer(s) = Stream_Buffer(s); } s->pool = pool; s->count = 1; StreamPool_AddUsed(pool, s); if (pool->synchronized) LeaveCriticalSection(&pool->lock); return s; }
BOOL tf_peer_dump_rfx(freerdp_peer* client) { wStream* s; UINT32 prev_seconds; UINT32 prev_useconds; rdpUpdate* update; rdpPcap* pcap_rfx; pcap_record record; s = Stream_New(NULL, 512); if (!s) return FALSE; update = client->update; if (!(pcap_rfx = pcap_open(test_pcap_file, FALSE))) return FALSE; prev_seconds = prev_useconds = 0; while (pcap_has_next_record(pcap_rfx)) { if (!pcap_get_next_record_header(pcap_rfx, &record)) break; if (!Stream_EnsureCapacity(s, record.length)) break; record.data = Stream_Buffer(s); pcap_get_next_record_content(pcap_rfx, &record); Stream_SetPointer(s, Stream_Buffer(s) + Stream_Capacity(s)); if (test_dump_rfx_realtime && test_sleep_tsdiff(&prev_seconds, &prev_useconds, record.header.ts_sec, record.header.ts_usec) == FALSE) break; update->SurfaceCommand(update->context, s); if (client->CheckFileDescriptor(client) != TRUE) break; } Stream_Free(s, TRUE); pcap_close(pcap_rfx); return TRUE; }
static void rail_virtual_channel_event_data_received(railPlugin* rail, void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) { wStream* data_in; if ((dataFlags & CHANNEL_FLAG_SUSPEND) || (dataFlags & CHANNEL_FLAG_RESUME)) { return; } if (dataFlags & CHANNEL_FLAG_FIRST) { if (rail->data_in) Stream_Free(rail->data_in, TRUE); rail->data_in = Stream_New(NULL, totalLength); if (!rail->data_in) { WLog_ERR(TAG, "%s: unable to allocate data_in", __FUNCTION__); return; } } data_in = rail->data_in; if (!Stream_EnsureRemainingCapacity(data_in, (int) dataLength)) { WLog_ERR(TAG, "%s: unable to grow data_in to %d", __FUNCTION__, dataLength); return; } Stream_Write(data_in, pData, dataLength); if (dataFlags & CHANNEL_FLAG_LAST) { if (Stream_Capacity(data_in) != Stream_GetPosition(data_in)) { WLog_ERR(TAG, "rail_plugin_process_received: read error"); } rail->data_in = NULL; Stream_SealLength(data_in); Stream_SetPosition(data_in, 0); MessageQueue_Post(rail->queue, NULL, 0, (void*) data_in, NULL); } }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, wStream* data) { UINT status = CHANNEL_RC_OK; DVCMAN_CHANNEL* channel; size_t dataSize = Stream_GetRemainingLength(data); channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId); if (!channel) { WLog_ERR(TAG, "ChannelId %d not found!", ChannelId); return ERROR_INTERNAL_ERROR; } if (channel->dvc_data) { /* Fragmented data */ if (Stream_GetPosition(channel->dvc_data) + dataSize > (UINT32) Stream_Capacity(channel->dvc_data)) { WLog_ERR(TAG, "data exceeding declared length!"); Stream_Release(channel->dvc_data); channel->dvc_data = NULL; return ERROR_INVALID_DATA; } Stream_Write(channel->dvc_data, Stream_Pointer(data), dataSize); if (((size_t) Stream_GetPosition(channel->dvc_data)) >= channel->dvc_data_length) { Stream_SealLength(channel->dvc_data); Stream_SetPosition(channel->dvc_data, 0); status = channel->channel_callback->OnDataReceived(channel->channel_callback, channel->dvc_data); Stream_Release(channel->dvc_data); channel->dvc_data = NULL; } } else { status = channel->channel_callback->OnDataReceived(channel->channel_callback, data); } return status; }
static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) { wStream* s; if ((dataFlags & CHANNEL_FLAG_SUSPEND) || (dataFlags & CHANNEL_FLAG_RESUME)) { /* * According to MS-RDPBCGR 2.2.6.1, "All virtual channel traffic MUST be suspended. * This flag is only valid in server-to-client virtual channel traffic. It MUST be * ignored in client-to-server data." Thus it would be best practice to cease data * transmission. However, simply returning here avoids a crash. */ return; } if (dataFlags & CHANNEL_FLAG_FIRST) { if (plugin->data_in != NULL) Stream_Free(plugin->data_in, TRUE); plugin->data_in = Stream_New(NULL, totalLength); } s = plugin->data_in; Stream_EnsureRemainingCapacity(s, (int) dataLength); Stream_Write(s, pData, dataLength); if (dataFlags & CHANNEL_FLAG_LAST) { if (Stream_Capacity(s) != Stream_GetPosition(s)) { fprintf(stderr, "svc_plugin_process_received: read error\n"); } plugin->data_in = NULL; Stream_SealLength(s); Stream_SetPosition(s, 0); MessageQueue_Post(plugin->MsgPipe->In, NULL, 0, (void*) s, NULL); } }
wStream* StreamPool_Find(wStreamPool* pool, BYTE* ptr) { int index; wStream* s = NULL; BOOL found = FALSE; WaitForSingleObject(pool->mutex, INFINITE); for (index = 0; index < pool->uSize; index++) { s = pool->uArray[index]; if ((ptr >= Stream_Buffer(s)) && (ptr < (Stream_Buffer(s) + Stream_Capacity(s)))) { found = TRUE; break; } } ReleaseMutex(pool->mutex); return (found) ? s : NULL; }
wStream* StreamPool_Find(wStreamPool* pool, BYTE* ptr) { int index; wStream* s = NULL; BOOL found = FALSE; EnterCriticalSection(&pool->lock); for (index = 0; index < pool->uSize; index++) { s = pool->uArray[index]; if ((ptr >= Stream_Buffer(s)) && (ptr < (Stream_Buffer(s) + Stream_Capacity(s)))) { found = TRUE; break; } } LeaveCriticalSection(&pool->lock); return (found) ? s : NULL; }
static void remdesk_virtual_channel_event_data_received(remdeskPlugin* remdesk, void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) { wStream* data_in; if ((dataFlags & CHANNEL_FLAG_SUSPEND) || (dataFlags & CHANNEL_FLAG_RESUME)) { return; } if (dataFlags & CHANNEL_FLAG_FIRST) { if (remdesk->data_in) Stream_Free(remdesk->data_in, TRUE); remdesk->data_in = Stream_New(NULL, totalLength); } data_in = remdesk->data_in; Stream_EnsureRemainingCapacity(data_in, (int) dataLength); Stream_Write(data_in, pData, dataLength); if (dataFlags & CHANNEL_FLAG_LAST) { if (Stream_Capacity(data_in) != Stream_GetPosition(data_in)) { WLog_ERR(TAG, "read error"); } remdesk->data_in = NULL; Stream_SealLength(data_in); Stream_SetPosition(data_in, 0); MessageQueue_Post(remdesk->MsgPipe->In, NULL, 0, (void*) data_in, NULL); } }
/** * Function description * Write RDPGFX_CMDID_WIRETOSURFACE_1 or RDPGFX_CMDID_WIRETOSURFACE_2 * to the stream according to RDPGFX_SURFACE_COMMAND message * * @return 0 on success, otherwise a Win32 error code */ static UINT rdpgfx_write_surface_command(wStream* s, RDPGFX_SURFACE_COMMAND* cmd) { UINT error = CHANNEL_RC_OK; RDPGFX_AVC420_BITMAP_STREAM* havc420 = NULL; RDPGFX_AVC444_BITMAP_STREAM* havc444 = NULL; UINT32 bitmapDataStart = 0; UINT32 bitmapDataLength = 0; UINT8 pixelFormat = 0; switch (cmd->format) { case PIXEL_FORMAT_BGRX32: pixelFormat = GFX_PIXEL_FORMAT_XRGB_8888; break; case PIXEL_FORMAT_BGRA32: pixelFormat = GFX_PIXEL_FORMAT_ARGB_8888; break; default: WLog_ERR(TAG, "Format %s not supported!", GetColorFormatName(cmd->format)); return ERROR_INVALID_DATA; } if (cmd->codecId == RDPGFX_CODECID_CAPROGRESSIVE || cmd->codecId == RDPGFX_CODECID_CAPROGRESSIVE_V2) { /* Write RDPGFX_CMDID_WIRETOSURFACE_2 format for CAPROGRESSIVE */ Stream_Write_UINT16(s, cmd->surfaceId); /* surfaceId (2 bytes) */ Stream_Write_UINT16(s, cmd->codecId); /* codecId (2 bytes) */ Stream_Write_UINT32(s, cmd->contextId); /* codecContextId (4 bytes) */ Stream_Write_UINT8(s, pixelFormat); /* pixelFormat (1 byte) */ Stream_Write_UINT32(s, cmd->length); /* bitmapDataLength (4 bytes) */ Stream_Write(s, cmd->data, cmd->length); } else { /* Write RDPGFX_CMDID_WIRETOSURFACE_1 format for others */ Stream_Write_UINT16(s, cmd->surfaceId); /* surfaceId (2 bytes) */ Stream_Write_UINT16(s, cmd->codecId); /* codecId (2 bytes) */ Stream_Write_UINT8(s, pixelFormat); /* pixelFormat (1 byte) */ Stream_Write_UINT16(s, cmd->left); /* left (2 bytes) */ Stream_Write_UINT16(s, cmd->top); /* top (2 bytes) */ Stream_Write_UINT16(s, cmd->right); /* right (2 bytes) */ Stream_Write_UINT16(s, cmd->bottom); /* bottom (2 bytes) */ Stream_Write_UINT32(s, cmd->length); /* bitmapDataLength (4 bytes) */ bitmapDataStart = Stream_GetPosition(s); if (cmd->codecId == RDPGFX_CODECID_AVC420) { havc420 = (RDPGFX_AVC420_BITMAP_STREAM*)cmd->extra; error = rdpgfx_write_h264_avc420(s, havc420); if (error != CHANNEL_RC_OK) { WLog_ERR(TAG, "rdpgfx_write_h264_avc420 failed!"); return error; } } else if (cmd->codecId == RDPGFX_CODECID_AVC444) { havc444 = (RDPGFX_AVC444_BITMAP_STREAM*)cmd->extra; havc420 = &(havc444->bitstream[0]); /* avc420EncodedBitstreamInfo (4 bytes) */ Stream_Write_UINT32(s, havc420->length | (havc444->LC << 30UL)); /* avc420EncodedBitstream1 */ error = rdpgfx_write_h264_avc420(s, havc420); if (error != CHANNEL_RC_OK) { WLog_ERR(TAG, "rdpgfx_write_h264_avc420 failed!"); return error; } /* avc420EncodedBitstream2 */ if (havc444->LC == 0) { havc420 = &(havc444->bitstream[0]); error = rdpgfx_write_h264_avc420(s, havc420); if (error != CHANNEL_RC_OK) { WLog_ERR(TAG, "rdpgfx_write_h264_avc420 failed!"); return error; } } } else { Stream_Write(s, cmd->data, cmd->length); } assert(Stream_GetPosition(s) <= Stream_Capacity(s)); /* Fill actual bitmap data length */ bitmapDataLength = Stream_GetPosition(s) - bitmapDataStart; Stream_SetPosition(s, bitmapDataStart - sizeof(UINT32)); Stream_Write_UINT32(s, bitmapDataLength); /* bitmapDataLength (4 bytes) */ Stream_Seek(s, bitmapDataLength); } return error; }
static void* rdpdr_server_thread(void* arg) { wStream* s; DWORD status; DWORD nCount; void* buffer; int position; HANDLE events[8]; RDPDR_HEADER header; HANDLE ChannelEvent; DWORD BytesReturned; RdpdrServerContext* context; context = (RdpdrServerContext*) arg; buffer = NULL; BytesReturned = 0; ChannelEvent = NULL; s = Stream_New(NULL, 4096); if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE) { if (BytesReturned == sizeof(HANDLE)) CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE)); WTSFreeMemory(buffer); } nCount = 0; events[nCount++] = ChannelEvent; events[nCount++] = context->priv->StopEvent; rdpdr_server_send_announce_request(context); while (1) { BytesReturned = 0; status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0) { break; } 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)) { break; } if (Stream_GetPosition(s) >= RDPDR_HEADER_LENGTH) { position = Stream_GetPosition(s); Stream_SetPosition(s, 0); Stream_Read_UINT16(s, header.Component); /* Component (2 bytes) */ Stream_Read_UINT16(s, header.PacketId); /* PacketId (2 bytes) */ Stream_SetPosition(s, position); Stream_SealLength(s); Stream_SetPosition(s, RDPDR_HEADER_LENGTH); rdpdr_server_receive_pdu(context, s, &header); Stream_SetPosition(s, 0); } } Stream_Free(s, TRUE); return NULL; }
static void* encomsp_server_thread(void* arg) { wStream* s; DWORD nCount; void* buffer; HANDLE events[8]; HANDLE ChannelEvent; DWORD BytesReturned; ENCOMSP_ORDER_HEADER* header; EncomspServerContext* context; UINT error = CHANNEL_RC_OK; DWORD status; context = (EncomspServerContext*) arg; buffer = NULL; BytesReturned = 0; ChannelEvent = NULL; s = Stream_New(NULL, 4096); if (!s) { WLog_ERR(TAG, "Stream_New failed!"); error = CHANNEL_RC_NO_MEMORY; goto out; } if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE) { if (BytesReturned == sizeof(HANDLE)) CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE)); WTSFreeMemory(buffer); } nCount = 0; events[nCount++] = ChannelEvent; events[nCount++] = context->priv->StopEvent; while (1) { status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForMultipleObjects failed with error %u", error); break; } status = WaitForSingleObject(context->priv->StopEvent, 0); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForSingleObject failed with error %u", error); break; } if (status == WAIT_OBJECT_0) { break; } WTSVirtualChannelRead(context->priv->ChannelHandle, 0, NULL, 0, &BytesReturned); if (BytesReturned < 1) continue; if (!Stream_EnsureRemainingCapacity(s, BytesReturned)) { WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); error = CHANNEL_RC_NO_MEMORY; break; } if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned)) { WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); error = ERROR_INTERNAL_ERROR; break; } if (Stream_GetPosition(s) >= ENCOMSP_ORDER_HEADER_SIZE) { header = (ENCOMSP_ORDER_HEADER*) Stream_Buffer(s); if (header->Length >= Stream_GetPosition(s)) { Stream_SealLength(s); Stream_SetPosition(s, 0); if ((error = encomsp_server_receive_pdu(context, s))) { WLog_ERR(TAG, "encomsp_server_receive_pdu failed with error %u!", error); break; } Stream_SetPosition(s, 0); } } } Stream_Free(s, TRUE); out: if (error && context->rdpcontext) setChannelError(context->rdpcontext, error, "encomsp_server_thread reported an error"); ExitThread((DWORD)error); return NULL; }
BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, int length, UINT16 securityFlags) { BYTE cmac[8]; BYTE wmac[8]; if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS) { UINT16 len; BYTE version, pad; BYTE* sig; if (Stream_GetRemainingLength(s) < 12) return FALSE; Stream_Read_UINT16(s, len); /* 0x10 */ Stream_Read_UINT8(s, version); /* 0x1 */ Stream_Read_UINT8(s, pad); sig = Stream_Pointer(s); Stream_Seek(s, 8); /* signature */ length -= 12; if (!security_fips_decrypt(Stream_Pointer(s), length, rdp)) { fprintf(stderr, "FATAL: cannot decrypt\n"); return FALSE; /* TODO */ } if (!security_fips_check_signature(Stream_Pointer(s), length - pad, sig, rdp)) { fprintf(stderr, "FATAL: invalid packet signature\n"); return FALSE; /* TODO */ } /* is this what needs adjusting? */ Stream_Capacity(s) -= pad; return TRUE; } if (Stream_GetRemainingLength(s) < 8) return FALSE; Stream_Read(s, wmac, sizeof(wmac)); length -= sizeof(wmac); if (!security_decrypt(Stream_Pointer(s), length, rdp)) return FALSE; if (securityFlags & SEC_SECURE_CHECKSUM) security_salted_mac_signature(rdp, Stream_Pointer(s), length, FALSE, cmac); else security_mac_signature(rdp, Stream_Pointer(s), length, cmac); if (memcmp(wmac, cmac, sizeof(wmac)) != 0) { fprintf(stderr, "WARNING: invalid packet signature\n"); /* * Because Standard RDP Security is totally broken, * and cannot protect against MITM, don't treat signature * verification failure as critical. This at least enables * us to work with broken RDP clients and servers that * generate invalid signatures. */ //return FALSE; } return TRUE; }
static BOOL TestStream_Verify(wStream* s, int mincap, int len, size_t pos) { if (Stream_Buffer(s) == NULL) { printf("stream buffer is null\n"); return FALSE; } if (Stream_Pointer(s) == NULL) { printf("stream pointer is null\n"); return FALSE; } if (Stream_Pointer(s) < Stream_Buffer(s)) { printf("stream pointer (%p) or buffer (%p) is invalid\n", (void*) Stream_Pointer(s), (void*) Stream_Buffer(s)); return FALSE; } if (Stream_Capacity(s) < mincap) { printf("stream capacity is %"PRIuz" but minimum expected value is %d\n", Stream_Capacity(s), mincap); return FALSE; } if (Stream_Length(s) != len) { printf("stream has unexpected length (%"PRIuz" instead of %d)\n", Stream_Length(s), len); return FALSE; } if (Stream_GetPosition(s) != pos) { printf("stream has unexpected position (%"PRIuz" instead of %d)\n", Stream_GetPosition(s), pos); return FALSE; } if (Stream_GetPosition(s) > Stream_Length(s)) { printf("stream position (%"PRIuz") exceeds length (%"PRIuz")\n", Stream_GetPosition(s), Stream_Length(s)); return FALSE; } if (Stream_GetPosition(s) > Stream_Capacity(s)) { printf("stream position (%"PRIuz") exceeds capacity (%"PRIuz")\n", Stream_GetPosition(s), Stream_Capacity(s)); return FALSE; } if (Stream_Length(s) > Stream_Capacity(s)) { printf("stream length (%"PRIuz") exceeds capacity (%"PRIuz")\n", Stream_Length(s), Stream_Capacity(s)); return FALSE; } if (Stream_GetRemainingLength(s) != len - pos) { printf("stream remaining length (%"PRIuz" instead of %d)\n", Stream_GetRemainingLength(s), len - pos); return FALSE; } return TRUE; }
static void* echo_server_thread_func(void* arg) { wStream* s; void* buffer; DWORD nCount; HANDLE events[8]; BOOL ready = FALSE; HANDLE ChannelEvent; DWORD BytesReturned = 0; echo_server* echo = (echo_server*) arg; UINT error; DWORD status; if ((error = echo_server_open_channel(echo))) { UINT error2 = 0; WLog_ERR(TAG, "echo_server_open_channel failed with error %lu!", error); IFCALLRET(echo->context.OpenResult, error2, &echo->context, ECHO_SERVER_OPEN_RESULT_NOTSUPPORTED); if (error2) WLog_ERR(TAG, "echo server's OpenResult callback failed with error %lu", error2); goto out; } buffer = NULL; BytesReturned = 0; ChannelEvent = NULL; if (WTSVirtualChannelQuery(echo->echo_channel, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE) { if (BytesReturned == sizeof(HANDLE)) CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE)); WTSFreeMemory(buffer); } nCount = 0; events[nCount++] = echo->stopEvent; events[nCount++] = ChannelEvent; /* Wait for the client to confirm that the Graphics Pipeline dynamic channel is ready */ while (1) { status = WaitForMultipleObjects(nCount, events, FALSE, 100); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu", error); break; } if (status == WAIT_OBJECT_0) { IFCALLRET(echo->context.OpenResult, error, &echo->context, ECHO_SERVER_OPEN_RESULT_CLOSED); if (error) WLog_ERR(TAG, "OpenResult failed with error %lu!", error); break; } if (WTSVirtualChannelQuery(echo->echo_channel, WTSVirtualChannelReady, &buffer, &BytesReturned) == FALSE) { IFCALLRET(echo->context.OpenResult, error, &echo->context, ECHO_SERVER_OPEN_RESULT_ERROR); if (error) WLog_ERR(TAG, "OpenResult failed with error %lu!", error); break; } ready = *((BOOL*) buffer); WTSFreeMemory(buffer); if (ready) { IFCALLRET(echo->context.OpenResult, error, &echo->context, ECHO_SERVER_OPEN_RESULT_OK); if (error) WLog_ERR(TAG, "OpenResult failed with error %lu!", error); break; } } s = Stream_New(NULL, 4096); if (!s) { WLog_ERR(TAG, "Stream_New failed!"); WTSVirtualChannelClose(echo->echo_channel); ExitThread((DWORD)ERROR_NOT_ENOUGH_MEMORY); return NULL; } while (ready) { status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu", error); break; } if (status == WAIT_OBJECT_0) break; Stream_SetPosition(s, 0); WTSVirtualChannelRead(echo->echo_channel, 0, NULL, 0, &BytesReturned); if (BytesReturned < 1) continue; if (!Stream_EnsureRemainingCapacity(s, BytesReturned)) { WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); error = CHANNEL_RC_NO_MEMORY; break; } if (WTSVirtualChannelRead(echo->echo_channel, 0, (PCHAR) Stream_Buffer(s), (ULONG) Stream_Capacity(s), &BytesReturned) == FALSE) { WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); error = ERROR_INTERNAL_ERROR; break; } IFCALLRET(echo->context.Response, error, &echo->context, (BYTE*) Stream_Buffer(s), BytesReturned); if (error) { WLog_ERR(TAG, "Response failed with error %lu!", error); break; } } Stream_Free(s, TRUE); WTSVirtualChannelClose(echo->echo_channel); echo->echo_channel = NULL; out: if (error && echo->context.rdpcontext) setChannelError(echo->context.rdpcontext, error, "echo_server_thread_func reported an error"); ExitThread((DWORD)error); return NULL; }
void Stream_EnsureRemainingCapacity(wStream* s, size_t size) { if (Stream_GetPosition(s) + size > Stream_Capacity(s)) Stream_EnsureCapacity(s, Stream_Capacity(s) + size); }
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; }
static void* audin_server_thread_func(void* arg) { wStream* s; void* buffer; DWORD nCount; BYTE MessageId; HANDLE events[8]; BOOL ready = FALSE; HANDLE ChannelEvent; DWORD BytesReturned = 0; audin_server* audin = (audin_server*) arg; UINT error = CHANNEL_RC_OK; DWORD status; buffer = NULL; BytesReturned = 0; ChannelEvent = NULL; if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE) { if (BytesReturned == sizeof(HANDLE)) CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE)); WTSFreeMemory(buffer); } else { WLog_ERR(TAG, "WTSVirtualChannelQuery failed"); error = ERROR_INTERNAL_ERROR; goto out; } nCount = 0; events[nCount++] = audin->stopEvent; events[nCount++] = ChannelEvent; /* Wait for the client to confirm that the Audio Input dynamic channel is ready */ while (1) { if ((status = WaitForMultipleObjects(nCount, events, FALSE, 100)) == WAIT_OBJECT_0) goto out; if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu", error); goto out; } if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualChannelReady, &buffer, &BytesReturned) == FALSE) { WLog_ERR(TAG, "WTSVirtualChannelQuery failed"); error = ERROR_INTERNAL_ERROR; goto out; } ready = *((BOOL*) buffer); WTSFreeMemory(buffer); if (ready) break; } s = Stream_New(NULL, 4096); if (!s) { WLog_ERR(TAG, "Stream_New failed!"); error = CHANNEL_RC_NO_MEMORY; goto out; } if (ready) { if ((error = audin_server_send_version(audin, s))) { WLog_ERR(TAG, "audin_server_send_version failed with error %lu!", error); goto out_capacity; } } while (ready) { if ((status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE)) == WAIT_OBJECT_0) break; if (status == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu", error); goto out; } Stream_SetPosition(s, 0); if (!WTSVirtualChannelRead(audin->audin_channel, 0, NULL, 0, &BytesReturned)) { WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); error = ERROR_INTERNAL_ERROR; break; } if (BytesReturned < 1) continue; if (!Stream_EnsureRemainingCapacity(s, BytesReturned)) break; if (WTSVirtualChannelRead(audin->audin_channel, 0, (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned) == FALSE) { WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); error = ERROR_INTERNAL_ERROR; break; } Stream_Read_UINT8(s, MessageId); BytesReturned--; switch (MessageId) { case MSG_SNDIN_VERSION: if ((error = audin_server_recv_version(audin, s, BytesReturned))) { WLog_ERR(TAG, "audin_server_recv_version failed with error %lu!", error); goto out_capacity; } if ((error = audin_server_send_formats(audin, s))) { WLog_ERR(TAG, "audin_server_send_formats failed with error %lu!", error); goto out_capacity; } break; case MSG_SNDIN_FORMATS: if ((error = audin_server_recv_formats(audin, s, BytesReturned))) { WLog_ERR(TAG, "audin_server_recv_formats failed with error %lu!", error); goto out_capacity; } if ((error = audin_server_send_open(audin, s))) { WLog_ERR(TAG, "audin_server_send_open failed with error %lu!", error); goto out_capacity; } break; case MSG_SNDIN_OPEN_REPLY: if ((error = audin_server_recv_open_reply(audin, s, BytesReturned))) { WLog_ERR(TAG, "audin_server_recv_open_reply failed with error %lu!", error); goto out_capacity; } break; case MSG_SNDIN_DATA_INCOMING: break; case MSG_SNDIN_DATA: if ((error = audin_server_recv_data(audin, s, BytesReturned))) { WLog_ERR(TAG, "audin_server_recv_data failed with error %lu!", error); goto out_capacity; }; break; case MSG_SNDIN_FORMATCHANGE: break; default: WLog_ERR(TAG, "audin_server_thread_func: unknown MessageId %d", MessageId); break; } } out_capacity: Stream_Free(s, TRUE); out: WTSVirtualChannelClose(audin->audin_channel); audin->audin_channel = NULL; if (error && audin->context.rdpcontext) setChannelError(audin->context.rdpcontext, error, "audin_server_thread_func reported an error"); ExitThread((DWORD)error); return NULL; }
/* * Handle rpdgfx messages - server side * * @param Server side context * * @return 0 on success * ERROR_NO_DATA if no data could be read this time * otherwise a Win32 error code */ UINT rdpgfx_server_handle_messages(RdpgfxServerContext* context) { DWORD BytesReturned; void* buffer; UINT ret = CHANNEL_RC_OK; RdpgfxServerPrivate* priv = context->priv; wStream* s = priv->input_stream; /* Check whether the dynamic channel is ready */ if (!priv->isReady) { if (WTSVirtualChannelQuery(priv->rdpgfx_channel, WTSVirtualChannelReady, &buffer, &BytesReturned) == FALSE) { if (GetLastError() == ERROR_NO_DATA) return ERROR_NO_DATA; WLog_ERR(TAG, "WTSVirtualChannelQuery failed"); return ERROR_INTERNAL_ERROR; } priv->isReady = *((BOOL*) buffer); WTSFreeMemory(buffer); } /* Consume channel event only after the gfx dynamic channel is ready */ if (priv->isReady) { Stream_SetPosition(s, 0); if (!WTSVirtualChannelRead(priv->rdpgfx_channel, 0, NULL, 0, &BytesReturned)) { if (GetLastError() == ERROR_NO_DATA) return ERROR_NO_DATA; WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); return ERROR_INTERNAL_ERROR; } if (BytesReturned < 1) return CHANNEL_RC_OK; if (!Stream_EnsureRemainingCapacity(s, BytesReturned)) { WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); return CHANNEL_RC_NO_MEMORY; } if (WTSVirtualChannelRead(priv->rdpgfx_channel, 0, (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned) == FALSE) { WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); return ERROR_INTERNAL_ERROR; } Stream_SetLength(s, BytesReturned); Stream_SetPosition(s, 0); while (((size_t) Stream_GetPosition(s)) < Stream_Length(s)) { if ((ret = rdpgfx_server_receive_pdu(context, s))) { WLog_ERR(TAG, "rdpgfx_server_receive_pdu " "failed with error %u!", ret); return ret; } } } return ret; }