Click here to Skip to main content
15,867,308 members
Articles / Programming Languages / C++

User Mode Transport of the Library Via Virtual Channels

,
Rate me:
Please Sign up or sign in to vote.
4.40/5 (5 votes)
15 Jun 2010CPOL3 min read 32.7K   714   10   8
In this article, we provide the library which can be used in client – server applications to cover transport layer using virtual channels.

General Description

Virtual channels are software extensions that can be used to add functional enhancements to a Remote Desktop Services application. Examples of functional enhancements may include support for special types of hardware, audio, or other additions to the core functionality provided by the Remote Desktop Services Remote Desktop Protocol (RDP).

To use virtual channels, you should provide the server-side and client-side modules of the virtual channels application. The server-side module can be a user-mode application or a kernel-mode driver. The client-side module must be a DLL.

Library Description

In this article, we provide the library which can be used in client – server applications to cover transport layer using virtual channels. Also we attached sample add-in project (client side) and sample server application.

The user interface definitions can be found in the RdcTransport.h header file. This is the master header and should be included in you project.

Interface Description

C++
struct IVirtChannel
{
    virtual ~IVirtChannel() { }
    virtual void Write(Buffer* pBuffer) = 0; // may take a long time, 
				// need synchronization for multithreading
};

This structure is used for writing data to the client\server side.

C++
struct IReadHandler
{
    virtual ~IReadHandler(){};
    virtual void OnRead(Buffer* pBuffer) throw() = 0;
    virtual void OnReadFail(const char* what) throw() = 0;
};

This structure is used for reading notifications from client\server side.

C++
struct IClientVirtChannelCallback
{
    virtual ~IClientVirtChannelCallback() { }
    virtual void OnConnect() = 0;
    virtual void OnDisconnect() = 0;
    virtual void OnTerminate() = 0;
};

Callback interfaces for providing information about the client side connection.

C++
struct IServerVirtChannelCallback
{
    virtual ~IServerVirtChannelCallback() { }
    virtual void OnDisconnect() = 0;
    virtual void OnReconnect() = 0;
};

Callback interfaces for providing information about the server side connection.

Build factory:

Client Side

C++
std::auto_ptr<ivirtchannel> CreateClientChannel(
    __in const char* szChannelName,
    __in PCHANNEL_ENTRY_POINTS pEntryPoints,
    __in IClientVirtChannelCallback* pCallback,
    __in IReadHandler* pReadHandler,
    __in bool bShowProtocol = false);</ivirtchannel>

Server Side

C++
std::auto_ptr<ivirtchannel> CreateServerChannel(
    __in const char* szChannelName,
    __in LPTSTR szAddinRGSName,
    __in IServerVirtChannelCallback* pCallback,
    __in IReadHandler* pReadHandler,
    __in bool bShowProtocol = false);

How To Use

Client Side

For the creation of the add-in DLL of the mstsc.exe file, you need to implement the following function in your DLL:

C++
BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS  pEntryPoints)
{
}

To work with the client side transport, you need to create the global object, which will contain your transport and provide read\write interfaces. You can do this in the following way:

C++
std::auto_ptr<:ivirtchannel> channel;

BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS  pEntryPoints)
{
    try
    {
        channel =  rdc_transport::CreateClientChannel
		("Test", pEntryPoints, &connection, &reader, false);
        
        return TRUE;
    }
    catch(...)
    {
        // TODO:: add log for example
        return false;
    }
}

where connection and reader are the objects, which implement the rdc_transport::IClientVirtChannelCallback and rdc_transport::IReadHandler interfaces.

Server Side

To use the server side of the virtual channel transport, you need to create the transport object in your code. This object provides read\write interfaces and contains the server side of the connection. For example, it can be performed in the main function:

C++
int main()
{
std::auto_ptr<rdc_transport::IVirtChannel> ch = 
	rdc_transport::CreateServerChannel("Test", L"Test",&cc, &rh);
}

where cc and rh are the objects, which implement the rdc_transport::IServerVirtChannelCallback and rdc_transport::IReadHandler interfaces.

To close the server side connection, destroy the ch object.

You can find the sample of implementation in the test solution.

Build Requirements

Software

  • Visual Studio 2008 sp1
  • Boost 1.40.0 source code (see http://boost.org)
  • Nullsoft Scriptable Install System (NSIS) 2.45 or higher (see http://nsis.sourceforge.net/). It is used only for the sample and is not required for the library.

Environment Variables

  • NSIS - should contain the path where NSIS is installed
  • BOOST_ROOT - should contain the path to the Boost directory

Preparing Build System

Before building the sample solution from the source code, you should perform several simple preliminary steps. First of all, you should install all the applications specified in the Build requirements section, and set the environment variables, which are also specified in the section mentioned above.

After that, you should build Boost libraries from the source code. To do this, go to the Boost directory (BOOST_ROOT) and invoke the following two commands one after another:)

  1. bootstrap.bat
  2. bjam.exe toolset=msvc --build-type=complete

That should be enough. For more detailed information, see the Boost documentation.

Links

History

  • 15th June, 2010: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Chief Technology Officer Apriorit Inc.
United States United States
ApriorIT is a software research and development company specializing in cybersecurity and data management technology engineering. We work for a broad range of clients from Fortune 500 technology leaders to small innovative startups building unique solutions.

As Apriorit offers integrated research&development services for the software projects in such areas as endpoint security, network security, data security, embedded Systems, and virtualization, we have strong kernel and driver development skills, huge system programming expertise, and are reals fans of research projects.

Our specialty is reverse engineering, we apply it for security testing and security-related projects.

A separate department of Apriorit works on large-scale business SaaS solutions, handling tasks from business analysis, data architecture design, and web development to performance optimization and DevOps.

Official site: https://www.apriorit.com
Clutch profile: https://clutch.co/profile/apriorit
This is a Organisation

33 members

Written By
Software Developer (Junior) ApriorIT
Ukraine Ukraine
Sergey Popenko.
22 years old.
The Driver Team`s software developer.
Master of the Applied Math faculty, the Dnipropetrovsk National University, Ukraine.

Comments and Discussions

 
QuestionClient to Server Messages Pin
Abhishek Parajuli17-May-13 3:33
Abhishek Parajuli17-May-13 3:33 
QuestionHanging server apps following CreateServerChannel calls from a DLL Pin
Desmond Kearns3-Aug-11 23:53
Desmond Kearns3-Aug-11 23:53 
AnswerRe: Hanging server apps following CreateServerChannel calls from a DLL Pin
Abhishek Parajuli15-May-13 7:30
Abhishek Parajuli15-May-13 7:30 
BugClient response messages not being cleared from the channel Buffer [modified] Pin
Desmond Kearns10-Jul-11 23:39
Desmond Kearns10-Jul-11 23:39 
Hi,

I'm using RDCTransportLib to pass messages across a Virtual Channel but have 1 outstanding issue relating to the Buffer passed to the Server applications OnRead handler not being cleared, here's an example of the problem:


1: Server-side App:Ch->write("Message1")
2: Client DLL:OnRead Buffer contains "Message1"
3: Client DLL:Ch->write("ACKMessage1");
4: Server-side App:OnRead Buffer contains "ACKMessage1"
5: Server-side App:Ch->Write("Message2")
6: Client DLL:OnRead Buffer contains "Message2"
7: Client DLL:Ch->Write("ACKMessage2")
8: Server-side App:OnRead Buffer NOW contains "ACKMessage1ACKMessage2"

I've tried reseting the Buffer contents on the server side as soon as the OnRead handler has processed the message and I also confirmed that the client side doesn't see the same problem i.e. Message2 is received correclty without being concatenated to Message1.

I've built two solutions and both exhibit the same problem so this points to something within RDCTransportLib.lib - I'll continue to debug the code but if this is a known problem I'd appreciate an update, I'll post my findings once I've got to the bottom of it!

Many Thanks
Des

modified on Thursday, August 4, 2011 5:53 AM

SuggestionRe: Client response messages not being cleared from the channel Buffer Pin
Desmond Kearns3-Aug-11 23:55
Desmond Kearns3-Aug-11 23:55 
GeneralRe: Client response messages not being cleared from the channel Buffer Pin
Abhishek Parajuli15-May-13 7:20
Abhishek Parajuli15-May-13 7:20 
QuestionWindows 7 / Windows 2008 R2 Pin
Xokar24-Feb-11 6:15
Xokar24-Feb-11 6:15 
AnswerRe: Windows 7 / Windows 2008 R2 Pin
Abhishek Parajuli15-May-13 7:18
Abhishek Parajuli15-May-13 7:18 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.