HANDLE WINAPI FreeRDP_WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName, DWORD flags) { UINT32 index; wStream* s; rdpMcs* mcs; BOOL joined = FALSE; freerdp_peer* client; rdpPeerChannel* channel; ULONG written; WTSVirtualChannelManager* vcm; if (SessionId == WTS_CURRENT_SESSION) return NULL; vcm = (WTSVirtualChannelManager*) HashTable_GetItemValue(g_ServerHandles, (void*)(UINT_PTR) SessionId); if (!vcm) return NULL; if (!(flags & WTS_CHANNEL_OPTION_DYNAMIC)) { return FreeRDP_WTSVirtualChannelOpen((HANDLE) vcm, SessionId, pVirtualName); } client = vcm->client; mcs = client->context->rdp->mcs; for (index = 0; index < mcs->channelCount; index++) { if (mcs->channels[index].joined && (strncmp(mcs->channels[index].Name, "drdynvc", 7) == 0)) { joined = TRUE; break; } } if (!joined) { SetLastError(ERROR_NOT_FOUND); return NULL; } if (!vcm->drdynvc_channel || (vcm->drdynvc_state != DRDYNVC_STATE_READY)) { SetLastError(ERROR_NOT_READY); return NULL; } channel = (rdpPeerChannel*) calloc(1, sizeof(rdpPeerChannel)); if (!channel) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return NULL; } channel->vcm = vcm; channel->client = client; channel->channelType = RDP_PEER_CHANNEL_TYPE_DVC; channel->receiveData = Stream_New(NULL, client->settings->VirtualChannelChunkSize); if (!channel->receiveData) { WLog_ERR(TAG, "Stream_New failed!"); goto error_receiveData; } channel->queue = MessageQueue_New(NULL); if (!channel->queue) goto error_queue; channel->channelId = InterlockedIncrement(&vcm->dvc_channel_id_seq); if (ArrayList_Add(vcm->dynamicVirtualChannels, channel) < 0) goto error_add; s = Stream_New(NULL, 64); if (!s) goto error_s; if (!wts_write_drdynvc_create_request(s, channel->channelId, pVirtualName)) goto error_create; if (!WTSVirtualChannelWrite(vcm->drdynvc_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written)) goto error_create; Stream_Free(s, TRUE); return channel; error_create: Stream_Free(s, TRUE); error_s: ArrayList_Remove(vcm->dynamicVirtualChannels, channel); error_add: MessageQueue_Free(channel->queue); error_queue: Stream_Free(channel->receiveData, TRUE); error_receiveData: free(channel); SetLastError(ERROR_NOT_ENOUGH_MEMORY); return NULL; }
void* WTSVirtualChannelOpenEx( /* __in */ WTSVirtualChannelManager* vcm, /* __in */ const char* pVirtualName, /* __in */ uint32 flags) { int i; int len; rdpPeerChannel* channel; freerdp_peer* client = vcm->client; STREAM* s; if ((flags & WTS_CHANNEL_OPTION_DYNAMIC) != 0) { if (vcm->drdynvc_channel == NULL || vcm->drdynvc_state != DRDYNVC_STATE_READY) { DEBUG_DVC("Dynamic virtual channel not ready."); return NULL; } channel = xnew(rdpPeerChannel); channel->vcm = vcm; channel->client = client; channel->channel_type = RDP_PEER_CHANNEL_TYPE_DVC; channel->receive_data = stream_new(client->settings->vc_chunk_size); channel->receive_event = wait_obj_new(); channel->receive_queue = list_new(); channel->mutex = freerdp_mutex_new(); freerdp_mutex_lock(vcm->mutex); channel->channel_id = vcm->dvc_channel_id_seq++; list_enqueue(vcm->dvc_channel_list, channel); freerdp_mutex_unlock(vcm->mutex); s = stream_new(64); wts_write_drdynvc_create_request(s, channel->channel_id, pVirtualName); WTSVirtualChannelWrite(vcm->drdynvc_channel, stream_get_head(s), stream_get_length(s), NULL); stream_free(s); DEBUG_DVC("ChannelId %d.%s (total %d)", channel->channel_id, pVirtualName, list_size(vcm->dvc_channel_list)); } else { len = strlen(pVirtualName); if (len > 8) return NULL; for (i = 0; i < client->settings->num_channels; i++) { if (client->settings->channels[i].joined && strncmp(client->settings->channels[i].name, pVirtualName, len) == 0) { break; } } if (i >= client->settings->num_channels) return NULL; channel = (rdpPeerChannel*) client->settings->channels[i].handle; if (channel == NULL) { channel = xnew(rdpPeerChannel); channel->vcm = vcm; channel->client = client; channel->channel_id = client->settings->channels[i].channel_id; channel->index = i; channel->channel_type = RDP_PEER_CHANNEL_TYPE_SVC; channel->receive_data = stream_new(client->settings->vc_chunk_size); channel->receive_event = wait_obj_new(); channel->receive_queue = list_new(); channel->mutex = freerdp_mutex_new(); client->settings->channels[i].handle = channel; } } return channel; }