Download full document:

Programming guide

Virtual channels are referred to by a seven-character (or shorter) ASCII name. In several previous versions of the ICA protocol, virtual channels were numbered; the numbers are now assigned dynamically based on the ASCII name, making implementation easier.

When developing virtual channel code for internal use only, you can use any seven-character name that does not conflict with existing virtual channels. Use only upper and lowercase ASCII letters and numbers. Follow the existing naming convention when adding your own virtual channels.

The predefined channels, which begin with the OEM identifier CTX, are for use only by Citrix.

Design Suggestions

Follow these suggestions to make your virtual channels easier to design and enhance:

  • When you design your own virtual channel protocol, allow for the flexibility to add features. Virtual channels have version numbers that are exchanged during initialization so that both the client and the server detect the maximum level of functionality that can be used. For example, if the client is at Version 3 and the server is at Version 5, the server does not send any packets with functionality beyond Version 3 because the client does not know how to interpret the newer packets.
  • Because the server side of a virtual channel protocol can be implemented as a separate process, it is easier to write code that interfaces with the Citrix-provided virtual channel support on the server than on the client (where the code must fit into an existing code structure). The server side of a virtual channel simply opens the channel, reads from and writes to it, and closes it when done. Writing code for the server-side is similar to writing an application, which uses services exported by the system. It is easier to write an application to handle the virtual channel communication because it can then be run once for each ICA connection supporting the virtual channel. Writing for the client-side is similar to writing a driver, which must provide services to the system in addition to using system services. If a service is written, it must manage multiple connections.
  • If you are designing new hardware for use with new virtual channels (for example, an improved compressed video format), make sure the hardware can be detected so that the client can determine whether or not it is installed. Then the client can communicate to the server if the hardware is available before the server uses the new data format. Optionally, you could have the virtual driver translate the new data format for use with older hardware.
  • There might be limitations preventing your new virtual channel from performing at an optimum level. If the client is connecting to the server running XenApp through a modem or serial connection, the bandwidth might not be great enough to properly support audio or video data. You can make your protocol adaptive, so that as bandwidth decreases, performance degrades gracefully, possibly by sending sound normally but reducing the frame rate of the video to fit the available bandwidth.
  • To identify where problems are occurring (connection, implementation, or protocol), first get the connection and communication working. Then, after the virtual channel is complete and debugged, do some time trials and record the results. These results establish a baseline for measuring further optimizations such as compression and other enhancements so that the channel requires less bandwidth.
  • The time stamp in the pVdPoll variable can be helpful for resolving timing issues in your virtual driver. It is a ULONG containing the current time in milliseconds. The pVdPoll variable is a pointer to a DLLPOLL structure. See Dllapi.h (in src/inc/) for definitions of these structures.

Server-Side Functions Overview

For information on configuring server-side functionalities on the SDK, see XenApp and XenDesktop SDK.