虚通道技术

 vitual channel program

一.Virtual Channel的实现

RDP5.1支持虚拟通道(virtual channel,下同)技术。虚拟通道是自定义的一套与RDP协议相关联的独立的数据格式。这项技术使我们不必去改变RDP协议,而增加新的功能。

下面几种情况下最适合使用虚拟通道技术。当然,其他的一些情况也可能会使用虚拟通道,我们并不对虚拟通道机制的使用做特别的限制。
1.普通的核心设备,比如串口或打印机
2.重定向文件系统
3.用户程序,比如远程的剪切和复制
4.音频设备

一个虚拟通道程序需要一个客户端组件和一个服务器端组件构成:
1.服务器端组件运行在终端服务服务器上,它可以是一个用户程序或是一个核心设备。
2.客户端组件是一个动态连接库,当终端服务的客户端程序运行时必须把它加载到内存中。

下面几个段落描述了这些组件:
Virtual Channel Server Application
Virtual Channel Client
Virtual Channel Client Registration
Remote-Control Persistent Virtual Channels


二.Virtual Channel Server Application
使用虚拟通道技术程序的组件必须是一个在终端服务的服务器端运行的一个客户会话中的程序。你必须提供运行这个程序的方法。以下的几个方法可以实现程序的运行,比如做一个登陆脚本,或一个在开始文件夹中的计划或脚本。当然也可以由用户自己激活程序。

你必须把虚拟通道的服务器端程序保存在注册表中,方法是在注册表下面的路径中加入一个子键。HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\TerminalServer\Addins

服务器端程序可以通过调用WTSVirtualChannelOpen来得到一个虚拟通道的句柄,在程序中可以通过这个句柄使用下面的一些方法。
WTSVirtualChannelClose
关闭虚拟通道
WTSVirtualChannelPurgeInput
清除在一个虚拟通道中,客户端发来的所有的输入数据的请求
WTSVirtualChannelPurgeOutput
清除在一个虚拟通道中,客户端发来的所有的输出数据的请求
WTSVirtualChannelQuery
返回一个指定虚拟通道的信息
WTSVirtualChannelRead
从一个虚拟通道的末端服务器中读数据
WTSVirtualChannelWrite
从一个虚拟通道的末端服务器中写数据

Virtual Channel Client
虚拟通道程序的客户端组件是一个动态连接库,这个dll在客户计算机的终端服务初始化时被加载。这个dll必须被注册到客户计算机中。更多的信息,请看下一篇文章Virtual Channel Client Registration。

客户端dll导出了一个VirtualChannelEntry函数,这个函数在终端服务初始化时被调用。这个VirtualChannelEntry入口指向一个CHANNEL_ENTRY_POINTS结构的指针。这个指针将被下面几个函数使用到,这些函数时客户dll用来访问虚拟通道的函数。

三.VirtualChannelInit
注册使用的虚拟通道的名称,并提供一个VirtualChannelInitEvent回调函数,通过这个回调,终端服务提示客户端一些事件和客户连接
VirtualChannelOpen
打开一个指定虚拟通道末端的客户,并提供VirtualChannelOpenEvent回调函数,通过这个回调终端服务提示客户端一些事件和客户连接
VirtualChannelWrite
在虚拟通道中写数据。终端服务把这些数据发送到虚拟通道的服务器端。.服务器调用WTSVirtualChannelRead函数来读取这些数据。
VirtualChannelClose
关闭一个虚拟通道

VirtualChannelEntry函数必须调用VirtualChannelInit函数来初始化一个虚拟通道的访问。当调用VirtualChannelInit时,必须通过VirtualChannelInitEvent回调函数的一个指针。终端服务在初始化完成是调用这个函数,并在与一个终端服务器建立连接后再次调用这个函数。

在连接建立之后,你可以调用VirtualChannelOpen函数来打开由VirtualChannelInit函数注册的虚拟通道。VirtualChannelOpen函数将为你的VirtualChannelOpenEvent回调函数指定一个指针。

当VirtualChannelOpen函数调用返回后,你可以调用VirtualChannelWrite函数来写虚拟通道了。写的过程是异步的,因此你不必释放或重新分配缓冲区,直到VirtualChannelOpenEvent函数说明这个写的过程已经完成。

当你调用VirtualChannelWrite函数时,你可以通过一些用户数据来参看写过程的状态,当调用VirtualChannelOpenEvent时,终端服务将调用通过返回的用户数据通知你写的过程已经完成。在虚拟通道末端的服务器上,服务器插件调用WTSVirtualChannelRead函数来读取这些数据。

当服务器端组件把这些数据写入服务器的时候,终端服务也可以调用VirtualChannelOpenEvent函数得到相应的信息。服务器端组件是通过调用WTSVirtualChannelWrite函数把数据写入到服务器的。

客户端和服务器端组件可以在虚拟通道中写入任意大小的数据。然而,在发送数据之前,终端服务将把这些数据分割成CHANNEL_CHUNK_LENGTH字节大小的片断。终端服务为每一个数据片断调用VirtualChannelOpenEvent函数,而不是把这些数据重新建立成原是大小的包。每一次调用VirtualChannelOpenEvent显示数据片段的大小,并显示出是发送数据的开始、中间或是末尾。

VirtualChannelClose函数用来关闭一个通道。然而,你并不必须显示的使用这个函数。因为当一个哭户从服务器上断开连接时,终端服务会自动的关闭所有的通道。


四.Virtual Channel Client Registration
你必须在注册表中注册客户端dll的名称。方法是在下面路径之一加入子键.
HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Default\Addins
HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\connection\Addins

加入到Default\Addins键下会应用于所有的连接。加入到connection\Addins键下仅仅应用于指定的连接。裂解可以使用连接管理器创建和管理。

子键可以是任意的名称,它必须包含一个REG_SZ或者REG_EXPAND_SZ型的值。并且也可以再加一个REG_DWORD值。REG_SZ或者REG_EXPAND_SZ值的原型如下。
Name = DLLname

如果使用一个REG_EXPAND_SZ值,那么它包括一个未扩展的环境变量,这个变量将在运行时扩展。DLLname的值是一个全路径。如果DLLname没有包括一个全路径,那么将应用标准的Dll搜索路径。

REG_DWORD值的原型如下。
RemoteControlPersistent = flag

flag的值是1或0,0是默认值。如果是1,那么这个插件将不会得到远程控制开始与结束的信息。如果是0,这个插件将不会得到远程控制开始与结束的信息。

五.Remote-Control Persistent Virtual Channels
在Windows CE .NET和Windows XP中,一个DLL可以指定一个或多个虚拟通道作为永久远程控制。这样的通道在客户的一个连接会话连接或断开时都不会被关闭。数据将继续通过这个通道被发送和接收。没有被指定为永久远程控制的虚拟通道将被关闭。永久远程控制的虚拟通道通过调用VirtualChannelInit函数指定。参阅VirtualChannelInit函数会得到更多的信息。

六.Disabling Terminal Services Features
为了增强安全性,你可以选择屏蔽终端服务的一些功能,比如当使用Remote Desktop ActiveX Control连接时的剪切板的重定向和指针的重定向。

怎么屏蔽终端服务的功能
1.在客户计算机的注册表中加入下面的键。
HKEY_LOCAL_MACHINE\Software\Microsoft\Terminal Server\DisableClipRedirection
HKEY_LOCAL_MACHINE\Software\Microsoft\Terminal Server\DisablePrinterRedirection
2.把这两个键的值设置为0。

posted on 2010-10-25 15:27  遥望大海,云卷云舒  阅读(3084)  评论(0编辑  收藏  举报