static int drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s) { int pos; int status; UINT32 ChannelId; wStream* data_out; int channel_status; if (drdynvc->state == DRDYNVC_STATE_CAPABILITIES) { /** * For some reason the server does not always send the * capabilities pdu as it should. When this happens, * send a capabilities response. */ drdynvc->version = 3; drdynvc_send_capability_response(drdynvc); drdynvc->state = DRDYNVC_STATE_READY; } ChannelId = drdynvc_read_variable_uint(s, cbChId); pos = Stream_GetPosition(s); DEBUG_DVC("ChannelId=%d ChannelName=%s", ChannelId, Stream_Pointer(s)); channel_status = dvcman_create_channel(drdynvc->channel_mgr, ChannelId, (char*) Stream_Pointer(s)); data_out = Stream_New(NULL, pos + 4); Stream_Write_UINT8(data_out, 0x10 | cbChId); Stream_SetPosition(s, 1); Stream_Copy(data_out, s, pos - 1); if (channel_status == 0) { DEBUG_DVC("channel created"); Stream_Write_UINT32(data_out, 0); } else { DEBUG_DVC("no listener"); Stream_Write_UINT32(data_out, (UINT32)(-1)); } status = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out); if (status != CHANNEL_RC_OK) { DEBUG_WARN("VirtualChannelWrite failed %d", status); return 1; } if (channel_status == 0) { dvcman_open_channel(drdynvc->channel_mgr, ChannelId); } 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; }
int tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman) { UINT32 i; UINT32 v; UINT32 pos; UINT32 CapabilityType; UINT32 cbCapabilityLength; UINT32 numHostCapabilities; pos = Stream_GetPosition(ifman->output); Stream_EnsureRemainingCapacity(ifman->output, ifman->input_size + 4); Stream_Copy(ifman->output, ifman->input, ifman->input_size); Stream_SetPosition(ifman->output, pos); Stream_Read_UINT32(ifman->output, numHostCapabilities); for (i = 0; i < numHostCapabilities; i++) { Stream_Read_UINT32(ifman->output, CapabilityType); Stream_Read_UINT32(ifman->output, cbCapabilityLength); pos = Stream_GetPosition(ifman->output); switch (CapabilityType) { case 1: /* Protocol version request */ Stream_Read_UINT32(ifman->output, v); DEBUG_DVC("server protocol version %d", v); break; case 2: /* Supported platform */ Stream_Peek_UINT32(ifman->output, v); DEBUG_DVC("server supported platform %d", v); /* Claim that we support both MF and DShow platforms. */ Stream_Write_UINT32(ifman->output, MMREDIR_CAPABILITY_PLATFORM_MF | MMREDIR_CAPABILITY_PLATFORM_DSHOW); break; default: DEBUG_WARN("unknown capability type %d", CapabilityType); break; } Stream_SetPosition(ifman->output, pos + cbCapabilityLength); } Stream_Write_UINT32(ifman->output, 0); /* Result */ ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB; return 0; }
static BOOL TestStream_Copy(void) { BOOL rc = FALSE; const BYTE data[] = "someteststreamdata"; wStream* s = Stream_New(NULL, sizeof(data)); wStream* d = Stream_New(NULL, sizeof(data)); if (!s || !d) goto out; if (s->pointer != s->buffer) goto out; Stream_Write(s, data, sizeof(data)); if (memcmp(Stream_Buffer(s), data, sizeof(data)) != 0) goto out; if (s->pointer != s->buffer + sizeof(data)) goto out; Stream_SetPosition(s, 0); if (s->pointer != s->buffer) goto out; Stream_Copy(s, d, sizeof(data)); if (s->pointer != s->buffer + sizeof(data)) goto out; if (d->pointer != d->buffer + sizeof(data)) goto out; if (Stream_GetPosition(s) != Stream_GetPosition(d)) goto out; if (memcmp(Stream_Buffer(s), data, sizeof(data)) != 0) goto out; if (memcmp(Stream_Buffer(d), data, sizeof(data)) != 0) goto out; rc = TRUE; out: Stream_Free(s, TRUE); Stream_Free(d, TRUE); return rc; }
static int drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s) { int pos; int status; UINT32 ChannelId; wStream* data_out; ChannelId = drdynvc_read_variable_uint(s, cbChId); pos = Stream_GetPosition(s); DEBUG_DVC("ChannelId=%d ChannelName=%s", ChannelId, Stream_Pointer(s)); status = dvcman_create_channel(drdynvc->channel_mgr, ChannelId, (char*) Stream_Pointer(s)); data_out = Stream_New(NULL, pos + 4); Stream_Write_UINT8(data_out, 0x10 | cbChId); Stream_SetPosition(s, 1); Stream_Copy(data_out, s, pos - 1); if (status == 0) { DEBUG_DVC("channel created"); Stream_Write_UINT32(data_out, 0); } else { DEBUG_DVC("no listener"); Stream_Write_UINT32(data_out, (UINT32)(-1)); } status = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out); if (status != CHANNEL_RC_OK) { DEBUG_WARN("VirtualChannelWrite failed %d", status); return 1; } return 0; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s) { size_t pos; UINT status; UINT32 ChannelId; wStream* data_out; UINT channel_status; char* name; size_t length; if (!drdynvc) return CHANNEL_RC_BAD_CHANNEL_HANDLE; if (drdynvc->state == DRDYNVC_STATE_CAPABILITIES) { /** * For some reason the server does not always send the * capabilities pdu as it should. When this happens, * send a capabilities response. */ drdynvc->version = 3; if ((status = drdynvc_send_capability_response(drdynvc))) { WLog_Print(drdynvc->log, WLOG_ERROR, "drdynvc_send_capability_response failed!"); return status; } drdynvc->state = DRDYNVC_STATE_READY; } if (Stream_GetRemainingLength(s) < drdynvc_cblen_to_bytes(cbChId)) return ERROR_INVALID_DATA; ChannelId = drdynvc_read_variable_uint(s, cbChId); pos = Stream_GetPosition(s); name = (char*)Stream_Pointer(s); length = Stream_GetRemainingLength(s); if (strnlen(name, length) >= length) return ERROR_INVALID_DATA; WLog_Print(drdynvc->log, WLOG_DEBUG, "process_create_request: ChannelId=%"PRIu32" ChannelName=%s", ChannelId, name); channel_status = dvcman_create_channel(drdynvc, drdynvc->channel_mgr, ChannelId, name); data_out = Stream_New(NULL, pos + 4); if (!data_out) { WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } Stream_Write_UINT8(data_out, 0x10 | cbChId); Stream_SetPosition(s, 1); Stream_Copy(s, data_out, pos - 1); if (channel_status == CHANNEL_RC_OK) { WLog_Print(drdynvc->log, WLOG_DEBUG, "channel created"); Stream_Write_UINT32(data_out, 0); } else { WLog_Print(drdynvc->log, WLOG_DEBUG, "no listener"); Stream_Write_UINT32(data_out, (UINT32)0xC0000001); /* same code used by mstsc */ } status = drdynvc_send(drdynvc, data_out); if (status != CHANNEL_RC_OK) { WLog_Print(drdynvc->log, WLOG_ERROR, "VirtualChannelWriteEx failed with %s [%08"PRIX32"]", WTSErrorToString(status), status); return status; } if (channel_status == CHANNEL_RC_OK) { if ((status = dvcman_open_channel(drdynvc, drdynvc->channel_mgr, ChannelId))) { WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_open_channel failed with error %"PRIu32"!", status); return status; } } else { if ((status = dvcman_close_channel(drdynvc->channel_mgr, ChannelId))) WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_close_channel failed with error %"PRIu32"!", status); } return status; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s) { unsigned long pos; UINT status; UINT32 ChannelId; wStream* data_out; UINT channel_status; if (drdynvc->state == DRDYNVC_STATE_CAPABILITIES) { /** * For some reason the server does not always send the * capabilities pdu as it should. When this happens, * send a capabilities response. */ drdynvc->version = 3; if ((status = drdynvc_send_capability_response(drdynvc))) { WLog_ERR(TAG, "drdynvc_send_capability_response failed!"); return status; } drdynvc->state = DRDYNVC_STATE_READY; } ChannelId = drdynvc_read_variable_uint(s, cbChId); pos = Stream_GetPosition(s); WLog_DBG(TAG, "process_create_request: ChannelId=%d ChannelName=%s", ChannelId, Stream_Pointer(s)); channel_status = dvcman_create_channel(drdynvc->channel_mgr, ChannelId, (char*) Stream_Pointer(s)); data_out = Stream_New(NULL, pos + 4); if (!s) { WLog_ERR(TAG, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } Stream_Write_UINT8(data_out, 0x10 | cbChId); Stream_SetPosition(s, 1); Stream_Copy(s, data_out, pos - 1); if (channel_status == CHANNEL_RC_OK) { WLog_DBG(TAG, "channel created"); Stream_Write_UINT32(data_out, 0); } else { WLog_DBG(TAG, "no listener"); Stream_Write_UINT32(data_out, (UINT32) 0xC0000001); /* same code used by mstsc */ } status = drdynvc_send(drdynvc, data_out); if (status != CHANNEL_RC_OK) { WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]", WTSErrorToString(status), status); return status; } if (channel_status == CHANNEL_RC_OK) { if ((status = dvcman_open_channel(drdynvc->channel_mgr, ChannelId))) { WLog_ERR(TAG, "dvcman_open_channel failed with error %lu!", status); return status; } } else { if ((status = dvcman_close_channel(drdynvc->channel_mgr, ChannelId))) WLog_ERR(TAG, "dvcman_close_channel failed with error %lu!", status); } return status; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman) { UINT32 i; UINT32 v; UINT32 pos; UINT32 CapabilityType; UINT32 cbCapabilityLength; UINT32 numHostCapabilities; if (!Stream_EnsureRemainingCapacity(ifman->output, ifman->input_size + 4)) return ERROR_OUTOFMEMORY; pos = Stream_GetPosition(ifman->output); Stream_Copy(ifman->input, ifman->output, ifman->input_size); Stream_SetPosition(ifman->output, pos); if (Stream_GetRemainingLength(ifman->output) < 4) return ERROR_INVALID_DATA; Stream_Read_UINT32(ifman->output, numHostCapabilities); for (i = 0; i < numHostCapabilities; i++) { if (Stream_GetRemainingLength(ifman->output) < 8) return ERROR_INVALID_DATA; Stream_Read_UINT32(ifman->output, CapabilityType); Stream_Read_UINT32(ifman->output, cbCapabilityLength); if (Stream_GetRemainingLength(ifman->output) < cbCapabilityLength) return ERROR_INVALID_DATA; pos = Stream_GetPosition(ifman->output); switch (CapabilityType) { case 1: /* Protocol version request */ if (Stream_GetRemainingLength(ifman->output) < 4) return ERROR_INVALID_DATA; Stream_Read_UINT32(ifman->output, v); DEBUG_TSMF("server protocol version %d", v); break; case 2: /* Supported platform */ if (Stream_GetRemainingLength(ifman->output) < 4) return ERROR_INVALID_DATA; Stream_Peek_UINT32(ifman->output, v); DEBUG_TSMF("server supported platform %d", v); /* Claim that we support both MF and DShow platforms. */ Stream_Write_UINT32(ifman->output, MMREDIR_CAPABILITY_PLATFORM_MF | MMREDIR_CAPABILITY_PLATFORM_DSHOW); break; default: WLog_ERR(TAG, "skipping unknown capability type %d", CapabilityType); break; } Stream_SetPosition(ifman->output, pos + cbCapabilityLength); } Stream_Write_UINT32(ifman->output, 0); /* Result */ ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB; return CHANNEL_RC_OK; }