Nadim Abdo and Jay French
Microsoft Corporation
June 2000
Summary: Provides details for implementing scriptable virtual channels in a Terminal Services Web application, and also includes preliminary documentation for the Terminal Services ActiveX Client Control properties and methods. (29 printed pages)
Introduction
Implementing Scriptable Virtual Channels with the TSAC
Terminal Services ActiveX Client Control Properties and Methods
Secured Settings Interface
Secured Settings Interface Methods
IMsTscAx Interface Methods
Events Interface
IMsTscAdvancedSettings Interface
The IMsTscNonScriptable Interface
Microsoft® Terminal Services technology is a powerful tool for enterprises wanting to reduce their total cost of operation and provide centralized application deployment across the organization. With the release of the Terminal Services Advanced Client (TSAC) as a ValueAdd component on Microsoft Windows® 2000 Server, Service Pack 1, the Terminal Services solution is now extended to the Web. For example, organizations needing to deploy line of business applications to remote offices can do so by means of a Terminal server and a Web server running ASP pages, such as the sample pages supplied with the TSAC. On the client side, all that is needed is Internet Explorer, a connection to the World Wide Web, and appropriate access rights.
This article provides details for implementing scriptable virtual channels in a Terminal Services Web application, and also provides preliminary documentation for the Terminal Services ActiveX® Client Control properties and methods. The article does not discuss the properties and methods in detail, but it does give a preview of their use and function. For more information about deploying the Terminal Services Active X Client control, see the Microsoft® Terminal Services ActiveX® Client Control Deployment Guide, which is included with the TSAC. For more information about creating and deploying virtual channel applications, see the Terminal Services Virtual Channels section of the Platform SDK. You can also download the control. For information about implementing and using the TSAC, including redistribution, read the TSAC Frequently Asked Questions document.
Virtual channels technology provides the means for organizations to extend the Terminal Services Remote Desktop Protocol (RDP) to incorporate functional enhancements needed for a specific application. These enhancements might include support for special types of hardware, redirection of data types beyond those which can be redirected using methods provided in the core protocol, and so on.
A virtual channel application has two parts, a client side and a server side. The server side is an executable program running on the Terminal server. Prior to the release of the Terminal Services Advanced Client, implementing virtual channels applications on the client side required developers to create and register a client Dynamic Link Library (DLL), which had to be loaded into memory on the client computer when the Terminal Services client program was run. This method is still supported, and instructions for installing and registering the virtual channel client DLL are provided in the documentation included with the TSAC. However, a much simpler and more efficient method exists. With the TSAC, all client-side virtual channel operations can be scripted, considerably reducing the administrative overhead for deployment.
The following procedure outlines the steps for implementing scriptable virtual channels with the TSAC. Examples are in VBScript and assume that the Terminal Services ActiveX Client Control is named MsTsc.
IMsTscAx::CreateVirtualChannels (BSTR channelNameList)
For example:
MsTsc.CreateVirtualChannels("mychan1,mychan2")
Read the Terminal Services Virtual Channels article for information on virtual channel naming restrictions.
MsTsc.connect
IMsTscAx::SendOnVirtualChannel(BSTR channelName,BSTR dataToSend)
For example:
MsTsc.SendOnVirtualChannel("mychan1","hello from the client")
void IMsTscAxEvents::OnChannelReceivedData([in]BSTR chanName,[in]BSTR data)
For example:
Sub MsTsc.OnChannelReceivedData(chanName,data) Msgbox("received data:" &data& "on virtual channel:" &chanName) End sub
The Terminal Services ActiveX Client Control contains four scriptable interfaces.
In addition, the terminal services ActiveX control includes one interface—IMsTscNonScriptable—that can only be accessed directly through the vtable.
For security reasons, some properties of the Terminal Services ActiveX Client Control object are restricted to certain Internet Explorer security zones. This means that when a user browsing the Web accesses the page from a computer in a less secure zone, these properties are disabled. These restricted properties are contained in the Secured Settings Interface. They are available in the following Internet Explorer security zones:
They are disabled in these zones:
If you call these restricted properties within your Terminal Services Web application, you should use the following ActiveX Client Control properties to check for and access Secured Settings properties:
The following sample VBScript can be used to launch Microsoft Notepad upon connection. It should be called before the Connect method is called.
if MsTsc.SecuredSettingsEnabled then MsTsc.SecuredSettings.StartProgram = "notepad.exe" else msgbox "Cannot access secured setting (startprogram) in the current browser zone" end if
Note that if the terminal services control is not hosted in a web browser (that is, if it is hosted in a VB app) the secured settings interface is always available.
This method is used to specify which program to start on the remote server upon connection.
HRESULT put_StartProgram(BSTR startProgram);
This method retrieves the currently set StartProgram property.
HRESULT get_StartProgram(BSTR* pStartProgram);
This method specifies the current working directory if a starting program is set with StartProgram.
HRESULT put_WorkDir(BSTR workDir);
This method retrieves the WorkDir property.
HRESULT get_WorkDir(BSTR* pWorkDir);
This method sets the FullScreen mode for the client control.
HRESULT put_FullScreen(BOOL fullScreen);
This method retrieves the FullScreen state of the client control.
HRESULT get_FullScreen(BOOL* pFullScreen);
This method sets the name of the server to which to connect. This can also be an IP address.
HRESULT put_Server(BSTR Server);
This property can be set only if the control is not in the connected state. This property returns E_FAIL if it is called when the control is connected. You can check for the connected state by using the get_Connected method.
This method retrieves the server property.
HRESULT get_Server(BSTR* pServer);
This method sets the domain to which the specified user logs on.
HRESULT put_Domain(BSTR Domain);
This property can be set only if the control is not in the connected state. It returns E_FAIL if it is called when the control is connected. You can check for the connected state by using the get_Connected method.
This method retrieves the domain property.
HRESULT get_Domain(BSTR* pDomain);
This method sets the username for logon.
HRESULT put_UserName(BSTR UserName);
This property can be set only if the control is not in the connected state. It returns E_FAIL if it is called when the control is connected. You can check for the connected state by using the get_Connected method.
This method retrieves the username property.
HRESULT get_UserName(BSTR* pUserName);
This method sets the DisconnectedText property. This is a text string that appears centered in the control before a connection is established.
HRESULT put_DisconnectedText(BSTR DisconnectedText);
This property can be set only if the control is not in the connected state. It returns E_FAIL if it is called when the control is connected. You can check for the connected state by using the get_Connected method.
This method retrieves the DisconnectedText property.
HRESULT get_DisconnectedText(BSTR* pDisconnectedText);
This method sets the ConnectingText property. This is a text string that appears centered in the control while the control is connecting. For example, a status message such as "Connecting to server…" can be displayed.
HRESULT put_ConnectingText(BSTR ConnectingText);
This property can be set only if the control is not in the connected state. It returns E_FAIL if it is called when the control is connected. You can check for the connected state by using the get_Connected method.
This method retrieves the ConnectingText property.
HRESULT get_ConnectingText(BSTR* pConnectingText);
This method retrieves the Connected property.
HRESULT get_Connected(short* pConnected);
This method sets the control's initial remote desktop width in pixels. Setting this property is optional, but it must be set before the Connect method is called. If a desktop width is not specified, the desktop width is set to the width of the control. After a connection is established, any changes to the control's width do not change the remote desktop width. Instead, the control brings up scroll bars or centers the remote desktop, as appropriate.
HRESULT put_DesktopWidth(LONG desktopWidth);
This method retrieves the current remote desktop width.
HRESULT get_DesktopWidth(LONG* pDesktopWidth);
This method sets the control's initial remote desktop height in pixels. Setting this property is optional, but it must be set before the Connect method is called. If a desktop height is not specified, the desktop height is set to the height of the control. After a connection is established, any changes to the control's height do not change the remote desktop height. Instead, the control brings up scroll bars or centers the remote desktop as appropriate.
HRESULT put_DesktopHeight(LONG desktopHeight);
This method retrieves the current remote desktop height.
HRESULT get_DesktopHeight(LONG* pDesktopHeight);
This method specifies that the control should establish the Terminal server connection immediately upon instantiation. This property is most useful when the control properties are set in the parameter list of an <OBJECT> tag, rather than through script calls.
HRESULT put_StartConnected(BOOL startConnected);
This method retrieves the StartConnected property.
HRESULT get_StartConnected(BOOL* pStartConnected);
This method retrieves a Boolean value that indicates whether or not the control has displayed a horizontal scroll bar.
HRESULT get_HorizontalScrollBarVisible(BOOL* pSBVisible);
This method retrieves a Boolean value that indicates whether or not the control has displayed a vertical scroll bar.
HRESULT get_VerticalScrollBarVisible(BOOL* pSBVisible);
This method sets the window title that appears when the control is in FullScreen mode.
HRESULT put_FullScreenTitle(BSTR fullScreenTitle);
This method retrieves the encryption strength of the control. For the TSAC, this is always 128 because the TSAC control supports encryption up to and including 128 bits. The 128-bit control can still connect to 56 bit encryption TS servers.
HRESULT get_CipherStrength(LONG* pCipherStrength);
This method retrieves a version string for the control.
HRESULT get_Version(BSTR* pVersion);
This method retrieves a Boolean value indicating whether or not the secured settings interface is available (that is, if the page containing the control is currently in one of the allowed Internet Explorer security zones). See Notes on using the Secured Settings Interface properties for a list of allowed and disallowed Security Zones.
HRESULT get_SecuredSettingsEnabled(BOOL* pSecuredSettingsEnabled);
This method retrieves the SecuredSettings interface (IMsTscSecuredSettings). See get_SecuredSettingsEnabled for restrictions on when this interface is available.
HRESULT get_SecuredSettings (IMsTscSecuredSettings** ppSecuredSettings);
This method retrieves the AdvancedSettings interface (IMsTscAdvancedSettings).
HRESULT get_AdvancedSettings (IMsTscAdvancedSettings** ppAdvancedSettings);
This method initiates a connection that uses the current properties that have been set on the control. The only required property is the server name (see put_Server).
HRESULT Connect ();
This method returns E_FAIL if it is called while the control is already connected or in the connecting state.
Note also that after Connect has been called, most of the control properties can no longer be set (they return FAILURE) until the control is back in the disconnected state.
The minimum set of method calls necessary for a successful connection is put_Server followed by Connect.
If the DesktopWidth/DesktopHeight properties are not specified, the control sets the initial desktop width and height to the dimensions of the control at connect time.
This method disconnects the active connection.
HRESULT Disconnect ();
This method creates a client-side virtual channel object for each virtual channel name specified in the channelNameList. (See Implementing Scriptable Virtual Channels with TSAC.)
HRESULT CreateVirtualChannels (BSTR channelNameList);
This method is used to send data to the server over a virtual channel that has been previously created with the CreateVirtualChannels method.
HRESULT SendOnVirtualChannel (BSTR channelName,BSTR dataToSend);
This event is called when the client control begins connecting to a server in response to a Connect method call.
HRESULT OnConnecting ();
Sub MsTsc.OnConnecting() Msgbox("Connecting”) End sub
This event is called when the client control has established a connection with a terminal server. At the point the event has fired login has not yet completed. See the OnLoginComplete event for more information.
HRESULT OnConnected ();
This event is called when the client control has successfully logged on to a terminal server (following the Windows Logon dialog box).
HRESULT OnLoginComplete();
Sub MsTsc.OnLoginComplete() Msgbox("Login has completed”) End sub
This event is called when the client control has been disconnected from the terminal server.
HRESULT OnDisconnected(long disconnectReason);
1 | Local Disconnection (not an error) |
2 | Remote Disconnection by user (not an error) |
3 | Remote Disconnection by server (not an error) |
260 | DNS Lookup Failed |
262 | Out of memory condition |
264 | Connection Timed Out |
516 | WinSock socket connect failed |
518 | Out of memory condition |
520 | Host Not Found error (GetHostByName failed). |
772 | WinSock send call failed |
774 | Out of memory condition |
776 | Invalid IP address specified |
1028 | WinSock recv call failed |
1030 | Invalid Security Data |
1032 | Internal error (code 1032) |
1286 | Invalid Encryption Method |
1288 | DNS Lookup failed |
1540 | GetHostByName call failed |
1542 | Invalid server security data |
1544 | Internal Error (timer error) |
1796 | Timeout occurred |
1798 | Failed to unpack server certificate |
2052 | Bad IP address specified |
2054 | Internal Security Error |
2308 | Socket closed |
2310 | Internal Security Error |
2566 | Internal Security Error |
2822 | Encryption error |
3078 | Decryption error |
This event is called when the client enters FullScreen mode; for example, when the user presses the FullScreen mode shortcut key combination (CTRL + ALT + BREAK).
HRESULT OnEnterFullScreenMode();
This event is called when the client leaves FullScreen mode; for example, when the user presses the FullScreen mode shortcut key combination (CTRL + ALT + BREAK).
HRESULT OnLeaveFullScreenMode();
This event is called when the client receives data on a scriptable virtual channel.
HRESULT OnChannelReceivedData(BSTR chanName, BSTR data);
This event is called when the client requests to switch to FullScreen mode and the IMsTscAdvancedSettings::put_ContainerHandledFullScreen property is set. See IMsTscAdvancedSettings::put_ContainerHandledFullScreen for more information about this event.
HRESULT OnRequestGoFullScreen();
This event is called when the client requests to leave FullScreen mode and the IMsTscAdvancedSettings::put_ContainerHandledFullScreen property is set. See IMsTscAdvancedSettings::put_ContainerHandledFullScreen for more information about this event.
HRESULT OnRequestLeaveFullScreen();
This event is called when the client control encounters a fatal error. In response to this event, the container displays an error message and shuts down.
HRESULT OnFatalError(long errorCode);
Value | Meaning |
0 | An unknown error has occurred |
1 | Internal error code 1 |
2 | Out of memory error |
3 | Window creation error |
4 | Internal error code 2 |
5 | Internal error code 3 (Invalid state) |
100 | Winsock initialization error |
This event is called when the client control encounters a non-fatal error.
HRESULT OnWarning(long warningCode);
Value | Meaning |
1 | Bitmap cache corrupted warning |
This event is called to indicate the client control's remote desktop size has changed in response, for example, to shadowing a session with a different resolution.
HRESULT OnRemoteDesktopSizeChange (long width, long height);
This method enables or disables compression.
HRESULT put_Compress (long compress);
This method retrieves the compression property.
HRESULT get_Compress (long* pCompress);
This method enables or disables bitmap caching. Note the misspelling of the method and its parameter in the released version of the control.
HRESULT put_BitmapPeristence (long bitmapPeristence);
This method retrieves the BitmapPeristence property. Note the misspelling of the method and its parameter in the released version of the control.
HRESULT get_BitmapPeristence (long* pBitmapPeristence);
This method specifies the names of virtual channel client .dll(s).
HRESULT put_PluginDlls (BSTR pluginList);
This method sets the container-handled FullScreen property, which specifies that it is the container's responsibility to handle switching into and out of FullScreen mode. This method should be used only if the container needs fine level control over FullScreen mode behavior. When this property is set, the control does not enter or leave FullScreen mode in response to the FullScreen mode shortcut key combination (CTRL+ALT+BREAK); instead, the OnRequestGoFullScreen and OnRequestLeaveFullScreen events are called. See the IMsTscAxEvents Interface for more information about these events.
HRESULT put_containerHandledFullScreen (BOOL containerHandledFullScreen);
This method retrieves the ContainerHandledFullScreen property.
HRESULT get_containerHandledFullScreen (BOOL* pContainerHandledFullScreen);
This method disables the internal client side component that controls printer redirection and clipboard redirection.
HRESULT DisableRdpdr (BOOL disableRdpdr);
This method retrieves the disableRdpdr property.
HRESULT DisableRdpdr (BOOL* pDisableRdpdr);
This method specifies what icon to use when the client is in fullscreen mode.
HRESULT put_IconFile (BSTR IconFile);
This method sets the index of the icon within the chosen IconFile (see the put_IconFile method for more information).
HRESULT put_IconIndex (LONG IconIndex);
The ImsTscNonScriptable interface contains properties and methods that relate to applying a password to the Terminal Services ActiveX client control. The interface can be used to configure automatic logon to Terminal servers. With automatic logon, the user is not presented with a Windows Logon dialog box at connection time.
Note
Automatic logon can also be enabled at the server with the Terminal Services Configuration tool (Tscc.msc). A server administrator can use this tool to assign a specific password to a connection in cases where automated logons are necessary.
The ImsTscNonScriptable is also intentionally non-scriptable and can only be accessed through vtable binding (for example, from C or C++ code). The password properties were placed in a non-scriptable interface to improve security. If these methods were scriptable, it could encourage Web developers to be careless about password security. For this reason, the main use of this interface is to allow automatic password logon access in scenarios where the control is hosted in a custom-written container.
It is also possible to write a secondary scriptable ActiveX control that can be placed on a Web page to allow scriptable access to the password property. For the reasons outlined above, Microsoft does not provide such a control. Third party developers can develop such functionality, but they should be very careful about the security considerations of password passing by their underlying Web application. In addition, it will be a third party’s responsibility to ensure the security of their control before digitally signing it as safe for scripting.
Providing a password to the control is completely optional. Three separate password formats are supported:
If a password is to be provided to the control, only one of the three forms should be applied to the control before initiating the connection with a call to the Connect() method.
The methods below can be used to specify the passwords in one of the three forms. They also allow for conversion between clear text passwords and one of the two encoded forms. To do this conversion, set a password in clear text form and then retrieve it in one of the two encoded forms.
Sets the password in clear text format. This method can be used to provide a connection password in clear text form.
HRESULT put_ClearTextPassword(BSTR ClearTextPassword);
This method can also be called to set a clear text password that is to be converted to one of the other supported forms (see PortablePassword and BinaryPassword methods).
After the password is set, it is not possible to retrieve it in clear text format.
This property can be set only if the control is not in the connected state. This property returns E_FAIL if it is called when the control is connected. You can check for the connected state by using the get_Connected method.
Sets the password in portable encoded format. This method can be used to specify a connection password in portable form.
HRESULT put_PortablePassword(BSTR PortablePassword);
The UserName, Domain, and PortableSalt properties must also be set to allow an automatic logon to happen. If the password fails to authenticate the user, the Windows Logon box is displayed at the server to prompt the user for the password.
This property can be set only if the control is not in the connected state. This property returns E_FAIL if it is called when the control is connected. You can check for the connected state by using the get_Connected method.
Retrieves the password in portable encoded format. This method can be called after the password is set in clear text format using the put_ClearTextPassword method to retrieve the password in portable form.
HRESULT get_PortablePassword(BSTR* pPortablePassword);
A portable password/salt pair appears as a string of HEX digits.
Sets the portable salt part of a portable password.
HRESULT put_PortableSalt(BSTR PortableSalt);
Retrieves the password’s portable salt. This method can be called to retrieve the password’s portable salt after the password has been set in clear text format using put_ClearTextPassword. A portable password consists of a portable password and portable salt pair.
HRESULT get_PortableSalt(BSTR* pPortableSalt);
Sets the password in binary format. This method can be used to specify a connection password in binary form.
HRESULT put_BinaryPassword(BSTR BinaryPassword);
The UserName, Domain, and BinarySalt properties must also be set to allow an automatic logon. If the password fails to authenticate the user, the Windows Logon box is displayed at the server to prompt the user for the password.
Apply only those binary encoded passwords that were generated by converting clear text passwords to binary password/salt pairs using the control’s get_BinaryPassword/get_BinarySalt methods.
This property can be set only if the control is not in the connected state. This property returns E_FAIL if it is called when the control is connected. You can check for the connected state by using the get_Connected method.
Retrieves the password in binary encoded format. This method can be called to retrieve the password in binary encoded (non-portable) form after the password has been set in clear text format using put_ClearTextPassword
HRESULT get_BinaryPassword(BSTR* pBinaryPassword);
A binary encoded password/salt pair does not appear in human readable form.
Sets the binary salt portion of a binary encoded (non-portable) password.
HRESULT put_BinarySalt(BSTR BinarySalt);
Retrieves the password’s binary salt. This method can be called to retrieve the password’s binary salt after the password has been set in clear text format using put_ClearTextPassword. A binary encoded (non-portable) password consists of a binary password and binary salt pair.
HRESULT get_BinarySalt(BSTR* pBinarySalt);
Call this method to reset all password states in the control. This clears passwords stored in any of the three forms: ClearText, portable encoded, or binary encoded (non-portable).
This method can be used to reset the password after disconnecting from one connection, ensuring that a subsequent connection (with the same instance of the control) does not automatically log on with the previously set password.
HRESULT ResetPassword();