static BOOL audin_server_open(audin_server_context* context) { audin_server* audin = (audin_server*) context; if (!audin->thread) { PULONG pSessionId = NULL; DWORD BytesReturned = 0; audin->SessionId = WTS_CURRENT_SESSION; if (WTSQuerySessionInformationA(context->vcm, WTS_CURRENT_SESSION, WTSSessionId, (LPSTR*) &pSessionId, &BytesReturned)) { audin->SessionId = (DWORD) *pSessionId; WTSFreeMemory(pSessionId); } audin->audin_channel = WTSVirtualChannelOpenEx(audin->SessionId, "AUDIO_INPUT", WTS_CHANNEL_OPTION_DYNAMIC); if (!audin->audin_channel) return FALSE; audin->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); audin->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) audin_server_thread_func, (void*) audin, 0, NULL); return TRUE; } return FALSE; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT rdpei_server_init(RdpeiServerContext *context) { void *buffer = NULL; DWORD bytesReturned; RdpeiServerPrivate *priv = context->priv; priv->channelHandle = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, RDPEI_DVC_CHANNEL_NAME, WTS_CHANNEL_OPTION_DYNAMIC); if (!priv->channelHandle) { WLog_ERR(TAG, "WTSVirtualChannelOpenEx failed!"); return CHANNEL_RC_INITIALIZATION_ERROR; } if (!WTSVirtualChannelQuery(priv->channelHandle, WTSVirtualEventHandle, &buffer, &bytesReturned) || (bytesReturned != sizeof(HANDLE))) { WLog_ERR(TAG, "WTSVirtualChannelQuery failed or invalid invalid returned size(%d)!", bytesReturned); if (buffer) WTSFreeMemory(buffer); goto out_close; } CopyMemory(&priv->eventHandle, buffer, sizeof(HANDLE)); WTSFreeMemory(buffer); return CHANNEL_RC_OK; out_close: WTSVirtualChannelClose(priv->channelHandle); return CHANNEL_RC_INITIALIZATION_ERROR; }
int rdpei_server_init(RdpeiServerContext *context) { void *buffer = NULL; DWORD bytesReturned; RdpeiServerPrivate *priv = context->priv; priv->channelHandle = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, RDPEI_DVC_CHANNEL_NAME, WTS_CHANNEL_OPTION_DYNAMIC); if (!priv->channelHandle) { fprintf(stderr, "%s: unable to open channel\n", __FUNCTION__); return -1; } if (!WTSVirtualChannelQuery(priv->channelHandle, WTSVirtualEventHandle, &buffer, &bytesReturned) || (bytesReturned != sizeof(HANDLE))) { fprintf(stderr, "%s: error during WTSVirtualChannelQuery(WTSVirtualEventHandle) or invalid returned size(%d)\n", __FUNCTION__, bytesReturned); if (buffer) WTSFreeMemory(buffer); goto out_close; } CopyMemory(&priv->eventHandle, buffer, sizeof(HANDLE)); WTSFreeMemory(buffer); return 0; out_close: WTSVirtualChannelClose(priv->channelHandle); return -1; }
/* * Open a dynamic channel with the name given in szChannelName * the output file handle can be used in ReadFile/WriteFile calls */ DWORD OpenDynamicChannel(LPCSTR szChannelName, HANDLE* phFile) { HANDLE hWTSHandle = NULL; HANDLE hWTSFileHandle; PVOID vcFileHandlePtr = NULL; DWORD len; DWORD rc = ERROR_SUCCESS; hWTSHandle = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, (LPSTR)szChannelName, WTS_CHANNEL_OPTION_DYNAMIC); if (!hWTSHandle) { rc = GetLastError(); printf("WTSVirtualChannelOpenEx API Call Failed: GetLastError() = %d\n", GetLastError()); goto exitpt; } BOOL bSucc = WTSVirtualChannelQuery(hWTSHandle, WTSVirtualFileHandle, &vcFileHandlePtr, &len); if ( !bSucc ) { rc = GetLastError(); goto exitpt; } if ( len != sizeof( HANDLE )) { rc = ERROR_INVALID_PARAMETER; goto exitpt; } hWTSFileHandle = *(HANDLE *)vcFileHandlePtr; bSucc = DuplicateHandle( GetCurrentProcess(), hWTSFileHandle, GetCurrentProcess(), phFile, 0, FALSE, DUPLICATE_SAME_ACCESS ); if ( !bSucc ) { rc = GetLastError(); goto exitpt; } rc = ERROR_SUCCESS; exitpt: if ( vcFileHandlePtr ) { WTSFreeMemory( vcFileHandlePtr ); } if ( hWTSHandle ) { WTSVirtualChannelClose( hWTSHandle ); } return rc; }
boolean tf_peer_post_connect(freerdp_peer* client) { int i; testPeerContext* context = (testPeerContext*) client->context; /** * This callback is called when the entire connection sequence is done, i.e. we've received the * Font List PDU from the client and sent out the Font Map PDU. * The server may start sending graphics output and receiving keyboard/mouse input after this * callback returns. */ printf("Client %s is activated (osMajorType %d osMinorType %d)", client->hostname, client->settings->os_major_type, client->settings->os_minor_type); if (client->settings->autologon) { printf(" and wants to login automatically as %s\\%s", client->settings->domain ? client->settings->domain : "", client->settings->username); /* A real server may perform OS login here if NLA is not executed previously. */ } printf("\n"); printf("Client requested desktop: %dx%dx%d\n", client->settings->width, client->settings->height, client->settings->color_depth); /* A real server should tag the peer as activated here and start sending updates in mainloop. */ test_peer_load_icon(client); /* Iterate all channel names requested by the client and activate those supported by the server */ for (i = 0; i < client->settings->num_channels; i++) { if (client->settings->channels[i].joined) { if (strncmp(client->settings->channels[i].name, "rdpdbg", 6) == 0) { context->debug_channel = WTSVirtualChannelOpenEx(context->vcm, "rdpdbg", 0); if (context->debug_channel != NULL) { printf("Open channel rdpdbg.\n"); context->debug_channel_thread = freerdp_thread_new(); freerdp_thread_start(context->debug_channel_thread, tf_debug_channel_thread_func, context); } } } } /* Return false here would stop the execution of the peer mainloop. */ return true; }
int main() { // Initialize the data for send/receive char* data; char* data1; data = (char*)malloc(DSIZE); data1 = (char*)malloc(DSIZE); memset(data, 0xca, DSIZE); memset(data1, 0, DSIZE); // Open the skel channel in current session void* channel = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, "skel", 0); unsigned long written = 0; // Write the data to the channel bool ret = WTSVirtualChannelWrite(channel, data, DSIZE, &written); if (!ret) { long err = GetLastError(); fprintf(stderr, "error 0x%8.8x\n", err); return 1; } ret = WTSVirtualChannelRead(channel, 100, data1, DSIZE, &written); if (!ret) { long err = GetLastError(); fprintf(stderr, "error 0x%8.8x\n", err); return 1; } if (written != DSIZE) { fprintf(stderr, "error read %d\n", written); return 1; } ret = WTSVirtualChannelClose(channel); if (memcmp(data, data1, DSIZE) == 0) { } else { fprintf(stderr, "error data no match\n"); return 1; } fprintf(stderr, "Success!\n"); Sleep(2000); return 0; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT echo_server_open_channel(echo_server* echo) { DWORD Error; HANDLE hEvent; DWORD StartTick; DWORD BytesReturned = 0; PULONG pSessionId = NULL; if (WTSQuerySessionInformationA(echo->context.vcm, WTS_CURRENT_SESSION, WTSSessionId, (LPSTR*) &pSessionId, &BytesReturned) == FALSE) { WLog_ERR(TAG, "WTSQuerySessionInformationA failed!"); return ERROR_INTERNAL_ERROR; } echo->SessionId = (DWORD) * pSessionId; WTSFreeMemory(pSessionId); hEvent = WTSVirtualChannelManagerGetEventHandle(echo->context.vcm); StartTick = GetTickCount(); while (echo->echo_channel == NULL) { if (WaitForSingleObject(hEvent, 1000) == WAIT_FAILED) { Error = GetLastError(); WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", Error); return Error; } echo->echo_channel = WTSVirtualChannelOpenEx(echo->SessionId, "ECHO", WTS_CHANNEL_OPTION_DYNAMIC); if (echo->echo_channel) break; Error = GetLastError(); if (Error == ERROR_NOT_FOUND) break; if (GetTickCount() - StartTick > 5000) break; } return echo->echo_channel ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; }
static BOOL audin_server_open(audin_server_context* context) { audin_server* audin = (audin_server*) context; if (!audin->thread) { PULONG pSessionId = NULL; DWORD BytesReturned = 0; audin->SessionId = WTS_CURRENT_SESSION; if (WTSQuerySessionInformationA(context->vcm, WTS_CURRENT_SESSION, WTSSessionId, (LPSTR*) &pSessionId, &BytesReturned)) { audin->SessionId = (DWORD) * pSessionId; WTSFreeMemory(pSessionId); } audin->audin_channel = WTSVirtualChannelOpenEx(audin->SessionId, "AUDIO_INPUT", WTS_CHANNEL_OPTION_DYNAMIC); if (!audin->audin_channel) { WLog_ERR(TAG, "WTSVirtualChannelOpenEx failed!"); return FALSE; } if (!(audin->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) { WLog_ERR(TAG, "CreateEvent failed!"); return FALSE; } if (!(audin->thread = CreateThread(NULL, 0, audin_server_thread_func, (void*) audin, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); CloseHandle(audin->stopEvent); audin->stopEvent = NULL; return FALSE; } return TRUE; } WLog_ERR(TAG, "thread already running!"); return FALSE; }
/** * @brief Open a virtual connection to remote client * * @return 0 on success, -1 on failure ******************************************************************************/ int OurInterface::openVirtualChannel() { /* is channel already open? */ if (channel) return -1; /* open a virtual channel and connect to remote client */ channel = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, "xrdpvr", 0); if (channel == NULL) { emit on_ErrorMsg("Connection failure", "Error connecting to remote client. Application will close now"); return -1; } return 0; }
static boolean audin_server_open(audin_server_context* context) { audin_server* audin = (audin_server*) context; if (audin->audin_channel_thread == NULL) { audin->audin_channel = WTSVirtualChannelOpenEx(context->vcm, "AUDIO_INPUT", WTS_CHANNEL_OPTION_DYNAMIC); if (audin->audin_channel == NULL) return false; audin->audin_channel_thread = freerdp_thread_new(); freerdp_thread_start(audin->audin_channel_thread, audin_server_thread_func, audin); return true; } return false; }
static boolean rdpsnd_server_initialize(rdpsnd_server_context* context) { rdpsnd_server* rdpsnd = (rdpsnd_server*) context; rdpsnd->rdpsnd_channel = WTSVirtualChannelOpenEx(context->vcm, "rdpsnd", 0); if (rdpsnd->rdpsnd_channel != NULL) { rdpsnd->rdpsnd_pdu = stream_new(4096); rdpsnd->rdpsnd_channel_thread = freerdp_thread_new(); freerdp_thread_start(rdpsnd->rdpsnd_channel_thread, rdpsnd_server_thread_func, rdpsnd); return true; } else { return false; } }
BOOL WTSVirtualChannelManagerCheckFileDescriptor(WTSVirtualChannelManager* vcm) { BOOL result = TRUE; wts_data_item* item; rdpPeerChannel* channel; UINT32 dynvc_caps; if (vcm->drdynvc_state == DRDYNVC_STATE_NONE && vcm->client->activated) { /* Initialize drdynvc channel once and only once. */ vcm->drdynvc_state = DRDYNVC_STATE_INITIALIZED; channel = WTSVirtualChannelOpenEx(vcm, "drdynvc", 0); if (channel) { vcm->drdynvc_channel = channel; dynvc_caps = 0x00010050; /* DYNVC_CAPS_VERSION1 (4 bytes) */ WTSVirtualChannelWrite(channel, (BYTE*) &dynvc_caps, sizeof(dynvc_caps), NULL); } } ResetEvent(vcm->send_event); WaitForSingleObject(vcm->mutex, INFINITE); while ((item = (wts_data_item*) list_dequeue(vcm->send_queue)) != NULL) { if (vcm->client->SendChannelData(vcm->client, item->channel_id, item->buffer, item->length) == FALSE) { result = FALSE; } wts_data_item_free(item); if (result == FALSE) break; } ReleaseMutex(vcm->mutex); return result; }
boolean WTSVirtualChannelManagerCheckFileDescriptor(WTSVirtualChannelManager* vcm) { boolean result = true; wts_data_item* item; rdpPeerChannel* channel; uint32 dynvc_caps; if (vcm->drdynvc_state == DRDYNVC_STATE_NONE && vcm->client->activated) { /* Initialize drdynvc channel once and only once. */ vcm->drdynvc_state = DRDYNVC_STATE_INITIALIZED; channel = WTSVirtualChannelOpenEx(vcm, "drdynvc", 0); if (channel) { vcm->drdynvc_channel = channel; dynvc_caps = 0x00010050; /* DYNVC_CAPS_VERSION1 (4 bytes) */ WTSVirtualChannelWrite(channel, (uint8*) &dynvc_caps, sizeof(dynvc_caps), NULL); } } wait_obj_clear(vcm->send_event); freerdp_mutex_lock(vcm->mutex); while ((item = (wts_data_item*) list_dequeue(vcm->send_queue)) != NULL) { if (vcm->client->SendChannelData(vcm->client, item->channel_id, item->buffer, item->length) == false) { result = false; } wts_data_item_free(item); if (result == false) break; } freerdp_mutex_unlock(vcm->mutex); return result; }
HRESULT CTsTeleportShellExt::GetVirtualChannelHandle(HANDLE *phFile) { HRESULT hr = S_OK; HANDLE hWTSHandle = NULL; PVOID vcFileHandlePtr = NULL; // // Open Virtual channel // hWTSHandle = WTSVirtualChannelOpenEx( WTS_CURRENT_SESSION, TSTELE_CHANNEL_NAME, WTS_CHANNEL_OPTION_DYNAMIC); if (NULL == hWTSHandle) { hr = HRESULT_FROM_WIN32(GetLastError()); } LEAVE_IF_FAILED("WTSVirtualChannelOpenEx failed"); // // Get channel file handle // DWORD len; BOOL bSucc = WTSVirtualChannelQuery( hWTSHandle, WTSVirtualFileHandle, &vcFileHandlePtr, &len); if (!bSucc) { hr = HRESULT_FROM_WIN32(GetLastError()); } LEAVE_IF_FAILED("WTSVirtualChannelQuery failed"); if (len != sizeof(HANDLE)) { hr = E_UNEXPECTED; } LEAVE_IF_FAILED("WTSVirtualChannelQuery return unexpected"); HANDLE hWTSFileHandle = *(HANDLE *)vcFileHandlePtr; // // Duplicate handle so that we can close // bSucc = DuplicateHandle( GetCurrentProcess(), hWTSFileHandle, GetCurrentProcess(), phFile, 0, FALSE, DUPLICATE_SAME_ACCESS); if (!bSucc) { hr = HRESULT_FROM_WIN32(GetLastError()); } LEAVE_IF_FAILED("DuplicateHandle failed"); _Function_Exit: // // Cleanup // if (vcFileHandlePtr) { WTSFreeMemory(vcFileHandlePtr); } if (hWTSHandle) { WTSVirtualChannelClose(hWTSHandle); } return hr; }
static BOOL rdpgfx_server_open(RdpgfxServerContext* context) { RdpgfxServerPrivate* priv = (RdpgfxServerPrivate*) context->priv; void* buffer = NULL; if (!priv->isOpened) { PULONG pSessionId = NULL; DWORD BytesReturned = 0; priv->SessionId = WTS_CURRENT_SESSION; if (WTSQuerySessionInformationA(context->vcm, WTS_CURRENT_SESSION, WTSSessionId, (LPSTR*) &pSessionId, &BytesReturned) == FALSE) { WLog_ERR(TAG, "WTSQuerySessionInformationA failed!"); return FALSE; } priv->SessionId = (DWORD) * pSessionId; WTSFreeMemory(pSessionId); priv->rdpgfx_channel = WTSVirtualChannelOpenEx(priv->SessionId, RDPGFX_DVC_CHANNEL_NAME, WTS_CHANNEL_OPTION_DYNAMIC); if (!priv->rdpgfx_channel) { WLog_ERR(TAG, "WTSVirtualChannelOpenEx failed!"); return FALSE; } /* Query for channel event handle */ if (!WTSVirtualChannelQuery(priv->rdpgfx_channel, WTSVirtualEventHandle, &buffer, &BytesReturned) || (BytesReturned != sizeof(HANDLE))) { WLog_ERR(TAG, "WTSVirtualChannelQuery failed " "or invalid returned size(%d)", BytesReturned); if (buffer) WTSFreeMemory(buffer); goto out_close; } CopyMemory(&priv->channelEvent, buffer, sizeof(HANDLE)); WTSFreeMemory(buffer); if (!(priv->zgfx = zgfx_context_new(TRUE))) { WLog_ERR(TAG, "Create zgfx context failed!"); goto out_close; } if (priv->ownThread) { if (!(priv->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) { WLog_ERR(TAG, "CreateEvent failed!"); goto out_zgfx; } if (!(priv->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) rdpgfx_server_thread_func, (void*) context, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); goto out_stopEvent; } } priv->isOpened = TRUE; priv->isReady = FALSE; return TRUE; } WLog_ERR(TAG, "RDPGFX channel is already opened!"); return FALSE; out_stopEvent: CloseHandle(priv->stopEvent); priv->stopEvent = NULL; out_zgfx: zgfx_context_free(priv->zgfx); priv->zgfx = NULL; out_close: WTSVirtualChannelClose(priv->rdpgfx_channel); priv->rdpgfx_channel = NULL; priv->channelEvent = NULL; return FALSE; }
BOOL tf_peer_post_connect(freerdp_peer* client) { int i; testPeerContext* context = (testPeerContext*) client->context; /** * This callback is called when the entire connection sequence is done, i.e. we've received the * Font List PDU from the client and sent out the Font Map PDU. * The server may start sending graphics output and receiving keyboard/mouse input after this * callback returns. */ printf("Client %s is activated (osMajorType %d osMinorType %d)", client->local ? "(local)" : client->hostname, client->settings->OsMajorType, client->settings->OsMinorType); if (client->settings->AutoLogonEnabled) { printf(" and wants to login automatically as %s\\%s", client->settings->Domain ? client->settings->Domain : "", client->settings->Username); /* A real server may perform OS login here if NLA is not executed previously. */ } printf("\n"); printf("Client requested desktop: %dx%dx%d\n", client->settings->DesktopWidth, client->settings->DesktopHeight, client->settings->ColorDepth); /* A real server should tag the peer as activated here and start sending updates in main loop. */ test_peer_load_icon(client); /* Iterate all channel names requested by the client and activate those supported by the server */ for (i = 0; i < client->settings->ChannelCount; i++) { if (client->settings->ChannelDefArray[i].joined) { if (strncmp(client->settings->ChannelDefArray[i].Name, "rdpdbg", 6) == 0) { context->debug_channel = WTSVirtualChannelOpenEx(context->vcm, "rdpdbg", 0); if (context->debug_channel != NULL) { printf("Open channel rdpdbg.\n"); context->debug_channel_thread = freerdp_thread_new(); freerdp_thread_start(context->debug_channel_thread, tf_debug_channel_thread_func, context); } } else if (strncmp(client->settings->ChannelDefArray[i].Name, "rdpsnd", 6) == 0) { sf_peer_rdpsnd_init(context); /* Audio Output */ } } } /* Dynamic Virtual Channels */ sf_peer_audin_init(context); /* Audio Input */ /* Return FALSE here would stop the execution of the peer main loop. */ return TRUE; }