Dynamic Virtual Channels
refer http://blogs.msdn.com/b/rds/archive/2007/09/20/dynamic-virtual-channels.aspx
An important goal of the Terminal Services (TS) team is to provide a product that can easily be extended by third parties to better meet their needs. While TS has always supported virtual channels, they had their limitations, including the limited number of channels and the difficulty involved in writing virtual channel applications. For the 6.1 version of the client, and Windows Vista SP1 or Windows Server 2008 on the server side, Dynamic Virtual Channels (DVCs) can be used. DVCs address the limitations of the old virtual channels. This article outlines the basics of DVCs and shows how to write a complete DVC application and client plug-in to add basic file transfer support to Terminal Services.
DVC Basics
What are Virtual Channels?
Virtual channels are bi-directional connection streams provided through the RDP protocol. Virtual channels allow third parties to establish a data pipe between the TS client and server to extend the functionality of the Remote Desktop Protocol (RDP). Examples of extra functionality provided through virtual channels are cross-TS-connection clipboard, drive, printer and smart card redirection. There are two types of virtual channels: static and dynamic. Due to the limitations of static virtual channels referenced above, dynamic virtual channels are the preferred way to extend TS functionality.
Client and Server DVC components
On the TS client side the DVC is handled through a TS client plug-in. This plug-in is a COM object, whose registered CLSID is passed to the TS client through the registry (see the attached sample). The COM object must implement the IWTSPlugininterface. On the server side any arbitrary component running in the current session can use the WTS API to establish the DVC connection, as well as send and receive data.
Channel Initialization and Usage
Client Side
1) The TS client loads the DVC plug-ins from the registry:
HKCU\Software\Microsoft\Terminal Server Client\Default\AddIns
2) The TS client invokes the Initialize() method on IWTSPlugin; and passes an IWTSVirtualChannelManager
HRESULT CTsClientPlgn::Initialize(
IWTSVirtualChannelManager *pChannelMgr
)
3) During initialization, or at any arbitrary point, the plug-in is expected to use the IWTSVirtualChannelManager to create a connection listener and pass an IWTSListenerCallback
hr = pChannelMgr->CreateListener(TSTELE_CHANNEL_NAME,
0,
pListenerCallback,
&pListener);
4) IWTSListenerCallback is notified of connection requests on the channel; IWTSListenerCallback receives anIWTSVirtualChannel for every new connection and returns a corresponding IWTSVirtualChannelCallback
HRESULT CTsListenerCallback::OnNewChannelConnection(
IWTSVirtualChannel *pChannel,
BSTR data,
BOOL *pbAccept,
IWTSVirtualChannelCallback **ppCallback )
{
*pbAccept = TRUE;
_pChannelCallback->AddRef();
*ppCallback = _pChannelCallback;
pChannel->AddRef();
_pChannel = pChannel;
5) The plug-in uses the IWTSVirtualChannel to write to and close the channel
hr = _pChannel->Write(sizeof(HRESULT), (PBYTE) &hr, NULL);
hr = _pChannel->Close();
6) The plug-in receives incoming data and channel close notifications on the IWTSVirtualChannelCallback
HRESULT CTsChannelCallback::OnDataReceived(
ULONG cbSize,
BYTE *pBuffer
);
HRESULT CTsChannelCallback::OnClose();
Server Side
1) An application issues a WTSVirtualChannelOpenEx with the WTS_CHANNEL_OPTION_DYNAMIC flag to establish the DVC connection.
hWTSHandle = WTSVirtualChannelOpenEx(
WTS_CURRENT_SESSION,
TSTELE_CHANNEL_NAME,
WTS_CHANNEL_OPTION_DYNAMIC);
2) Using the WTS handle received from the previous call a WTSVirtualChannelQuery is used to get a read/write file handle for the channel
NOTE: DuplicateHandle() is needed to be able to access the channel after freeing hWTSHandle (i.e. calling WTSVirtualChannelClose()). The output handle from DuplicateHandle() needs to be closed using CloseHandle().
BOOL bSucc = WTSVirtualChannelQuery(
hWTSHandle,
WTSVirtualFileHandle,
&vcFileHandlePtr,
&len);
...
HANDLE hWTSFileHandle = *(HANDLE *)vcFileHandlePtr;
...
bSucc = DuplicateHandle(
GetCurrentProcess(),
hWTSFileHandle,
GetCurrentProcess(),
&_hDVC,
0,
FALSE,
DUPLICATE_SAME_ACCESS);
3) Overlapped ReadFile() and WriteFile() calls are issued on the channel file handle
bRet = ReadFile(_hDVC, ReadBuf, CHANNEL_PDU_LENGTH, &BytesRead, &ovr);
bRet = WriteFile(_hDVC, pPacket, RequiredLen, &BytesWrit, &ovr);
4) To close the connection the channel file handle is closed
CloseHandle(_hDVC);
Sample: TS-Teleport
TS-Teleport is a sample application to demonstrate the end to end use of the DVC APIs. It implements a simple protocol to transport files from the TS server session to the desktop of the client machine. It does not rely on similar TS functionality like drive redirection.
![]()
The server component is a shell extension that adds an “RDP Client Desktop” entry to the “Send To” context menu. Upon receiving the list of highlighted files which the user elected to “Send to the RDP Client Desktop”, the shell extension opens the DVC and streams the files through. Upon receiving the file names and data, the client component creates those files and directories on the desktop.
The server sends a series of state dependent requests to the client by writing on the DVC and for each request it reads the status through a DVC read. Requests are start and end pairs for files and directories and data packets for file data.
Sample Files and Instructions
Please follow the link below to access sample files and instructions, including source code and installation how-to.
http://blogs.msdn.com/ts/pages/ts-teleport-sample-instructions.aspx
Dynamic Virtual Channels的更多相关文章
- PatentTips – GPU Saving and Restoring Thread Group Operating State
BACKGROUND OF THE INVENTION The present invention relates generally to single-instruction, multiple- ...
- Satisfying memory ordering requirements between partial reads and non-snoop accesses
A method and apparatus for preserving memory ordering in a cache coherent link based interconnect in ...
- Architectures for concurrent graphics processing operations
BACKGROUND 1. Field The present invention generally relates to rendering two-dimension representatio ...
- Cross-Domain Security For Data Vault
Cross-domain security for data vault is described. At least one database is accessible from a plural ...
- Massively parallel supercomputer
A novel massively parallel supercomputer of hundreds of teraOPS-scale includes node architectures ba ...
- s5p6818 Overview
S5P6818: 64bit Octa-Core, High Performance, Advanced 3D Graphics, Full-HD Multimedia Video, A53 Core ...
- HLS入门收集(1)
使用HLS各种问题 关于求指数函数 exp(x) 在HLS中使用exp(x),也就是指数函数.不能导出RTL到EDK也就是Pcore 只能导出为VIVADO IP:相关解释:见官方论坛 http:/ ...
- C++的静态分发(CRTP)和动态分发(虚函数多态)的比较
虚函数是C++实现多态的工具,在运行时根据虚表决定调用合适的函数.这被称作动态分发.虚函数很好的实现了多态的要求,但是在运行时引入了一些开销,包括: 对每一个虚函数的调用都需要额外的指针寻址 虚函数通 ...
- Down to the TLP: How PCI express devices talk (Part II)
http://xillybus.com/tutorials/pci-express-tlp-pcie-primer-tutorial-guide-2 Data Link Layer Packets A ...
随机推荐
- OpenGL 4.3配置教程
OpenGL 4.3配置教程 下载开发包 需要下载的开发包主要包含如下几个组件:freeglut+glew+ OpenGL.Development.Cookbook+源码+GLM+SOIL. Open ...
- OAF 中对文字实现html效果及对超级长文本实现默认换行,对只读的messageTextInput中的内容自动换行
今天遇到一个需求,客户注册页面客户化了一个超级长的注册须知,内容很多.但是样式相对又要做起来好看点. 注册须知的内容使用多个message拼接而成. 老大说rawText支持html样式,于是我想到了 ...
- [CareerCup] 6.1 Find Heavy Bottle 寻找重瓶子
6.1 You have 20 bottles of pills. 19 bottles have 1.0 gram pills, but one has pills of weight 1.1 gr ...
- 如何使用Iveely的数据存储引擎 Iveely Database
Iveely 数据存储引擎是为Iveely 搜索引擎提供数据存储的机制. 适用于:频繁数据插入.数据读取.数据更改或者删除数据不适合Iveely Database,存储结构是按照搜索引擎数据存储要求( ...
- bcd 8421码
bcd码表: 比如一个字符串 String s = "0200" 按对照表转换成二进制 02 : 0000 0010 00 : 0000 0000 s转换为字节的时候 02和00分 ...
- Git.Framework 框架随手记--ORM查询数据集合 一
本文记录Git.Framework之ORM中最为浓墨重彩的一篇,查询集合.根据自己做的项目统计这个是使用频率最高的一个. 一. 查询集合方法简介 (1)List<T> GetList(); ...
- Linq之Expression进阶
目录 写在前面 系列文章 表达式树解析 表达式树特性 编译表达树 总结 写在前面 让我们首先简单回顾一下上篇文章介绍的内容,上篇文章介绍了表达式树的基本概念(表达式树又称为“表达式目录树”,以数据形式 ...
- Javascript基础系列之(五)条件语句(if条件语句)
if 是flash的常用语法之一,其格式如下 if(coditon) statement1 (else statement2) 其中,coditon可以是任何表达式,甚至不比是真正的布尔值,因为Jav ...
- Grovvy初识
1.Groovy和Java对比 Groovy的松散的语法允许省略分号和修饰符 除非另行指定,Grovvy的所有内容都为public Grovvy允许定义简单脚本,同时无需定义正规的class对象 Gr ...
- nginx web加密访问
有时我们会有这么一种需求,就是你的网站并不想提供一个公共的访问或者某些页面不希望公开, 我们希望的是某些特定的客户端可以访问.那么我们可以在访问时要求进行身份认证,就如给你自己的家门加一把锁,以拒绝那 ...