Click here to Skip to main content
Click here to Skip to main content

Remote Assistance in XP: Programmatically establish an RDP session

, 6 Oct 2008 CPOL
Rate this:
Please Sign up or sign in to vote.
The way to automate the help assistant process in C++ without dirty scripting code.

Introduction

My article for RDP describes how to manage remote desktop sessions to provide assistance, but this is only for Vista, and lots of users (including myself!) still run XP. Here is the way to establish a remote assistance session without manually calling Help and Support.

My experimental project "Turbo Remote" uses this technique if it detects something less than Windows Vista.

Requirements

  • Windows XP or 2003. I haven't tested it in Vista, since in Vista, there is a clean API, as discussed.
  • Administrator privileges.
  • This must be done by a native application. That means that, if you try to run a 32-bit version of the code under x64, it will fail.
  • No encryption yet.

Contents

  • rdpxp.cpp/rdpxp.h - a simple class that provides the server implementation.

Implementation of the server step-by-step

The application that needs to create the "listening" session must perform the following:

  • Check the "Terminal Services" service to be running. If this service is not running, then it must be started, or nothing else will work. The application must return the service to its original state after the server is closed. This is implemented in my code in EnableTSS(bool), IsTSSEnabled(). (These have still to be implemented!)
  • Enable the HelpAssistant account by using the NetUserEnum and NetUserSetInfo functions. The application must disable the account if it was originally disabled. This is implemented with EnableHA(bool) and IsHAEnabled().
  • Enable Remote Assistance by setting the "fAllowToGetHelp" in HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Terminal Server to 1. Implemented in SetRARunning(bool) and IsRARunning().
  • Enable the group policy to accept remote assistance. Restore the keys if disabled previously. This is done in GetTicket(). The stuff is to:
    • Put "fAllowUnsolicited" , "fAllowUnsolicitedFullControl", "fAllowToGetHelp" to 1 (DWORD) in Software\\Microsoft\\Windows\\CurrentVersion\\ Group Policy Objects\\<X>\\Software\\policies\\Microsoft\\Windows NT\\Terminal Services. If there are keys under "Group Policy Objects", then enumerate it, and select the one that has the word "Machine" in it. If not, just put "LocalMachine". If the key does not exist at all, create it.
    • Create another key "RAUnsolicit" under it, and add a value with the name and value equal to your user name, say, Administrator.
  • Import the HelpServiceInterfaces.tlb to take the help interface.
  • #import "HelpServiceInterfaces.tlb" rename_namespace("HSITLB") named_guids\
        rename("EOF", "XX_EOF")\
        rename("GetUserName", "GetUserName_Renamed")\
        rename("EncryptFile", "EncryptFile_Renamed")\
        rename("DecryptFile", "DecryptFile_Renamed")\
        rename("ULONG_PTR","ULONG_PTR1")

    If the above code generates __missing__type errors (if you do not use ATL) , just replace the __missing__type with void*.

  • Create an IPCHService*.
  • CoCreateInstance(HSITLB::CLSID_PCHService, NULL, CLSCTX_LOCAL_SERVER, 
                   __uuidof(HSITLB::IPCHService),(void**)&p);

    Note the usage of CLSCTX_LOCAL_SERVER.

  • Call IPCHService::raw_RemoteConnectionParms(), providing the username, the computer name, the Terminal Services session ID (WTSGetActiveConsoleSessionId()), and the blob request, which has the following format:
  • "13;UNSOLICITED=1<X>;ID=<PCName>\\<Username>";

    Replace <PCName> and <Username> with the required values, and <X> with the string length of everything after <X>. For example: "13;UNSOLICITED=122;ID=GATOR\\Administrator". My PC name is GATOR, my user name is Administrator, and the total length of the string "ID=GATOR\Administrator" is 22.

  • You got the ticket!

Examining the ticket

The next thing you must do is to examine the ticket (which is something like that: 65538,1,192.168.1.21:3389;laptop:3389,*, KwRrNVpWH2g1vKfVlQUrJHKcpi8N1XA++9tQ+wnAXyE=,*,*,sdP7Lk3SFAXXcIrKpvLW6IJ8fg=) to replace the port 3389 (which is always placed there!) with the port that the Terminal Services Server is actually running. This port is located at "PortNumber" at HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\TerminalServer\WinStations\RDP-Tcp.

Creating the .MSRCINCIDENT file

This is a Unicode file (the BOM header \xFE\xFF must be present) with the following format:

<?xml version="1.0" encoding="Unicode" ?>
<UPLOADINFO TYPE="Escalated">
  <UPLOADDATA USERNAME="Administrator" 
    RCTICKET="<ticket>" RCTICKETENCRYPTED="0" 
    DtStart="X" DtLength="Y" L="0"/>
</UPLOADINFO>

X is the time that the ticket is created (standard UNIX format, use time()), and Y is this time + the length of the ticket. I have not yet found a way to support encrypted tickets.

After you have that file, you can send it via TCP/IP or other methods to the client.

Implementation of the client

The implementation of the client is simply receiving the msrcincident file and running it with Help and Support through ShellExecute().

History

  • 6 - 10 - 2008: First post.

License

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

Share

About the Author

Michael Chourdakis
Engineer
Greece Greece
I'm working in C++, PHP , Flash and DSP Programming, currently experimenting with Windows 7 technologies and professional audio applications.
 
I 've a PhD in Digital Signal Processing.
 
My home page: http://www.michaelchourdakis.com

Comments and Discussions

 
GeneralIssue with #import "HelpServiceInterfaces.tlb" Pinmemberbeckman168-Sep-09 0:51 
GeneralGetting Error C2065: 'Z' : undeclared identifier ~\rdpxp\rdpxp.cpp 247 tests32 Pinmemberbeckman161-Sep-09 5:08 
GeneralRe: Getting Error C2065: 'Z' : undeclared identifier ~\rdpxp\rdpxp.cpp 247 tests32 PinmemberMichael Chourdakis6-Sep-09 4:11 
GeneralRe: Getting Error C2065: 'Z' : undeclared identifier ~\rdpxp\rdpxp.cpp 247 tests32 Pinmemberbeckman166-Sep-09 23:35 
Thanks for providing the template.
 
One more issue is with #import statement.
 
I have imported "HelpServiceInterfaces.tlb"
 
#import "HelpServiceInterfaces.tlb" rename_namespace("HSITLB") named_guids\
rename("EOF", "XX_EOF")\
rename("GetUserName", "GetUserName_Renamed")\
rename("EncryptFile", "EncryptFile_Renamed")\
rename("DecryptFile", "DecryptFile_Renamed")\
rename("ULONG_PTR","ULONG_PTR1")
 
which auto-generates files helpserviceinterfaces.tlh and helpserviceinterfaces.tli.
 
The error is with a field 'ISAFRemoteDesktopSessionPtr' in helpserviceinterfaces.tlh, whose definition I cannot find.
 
Is there any other header or #import statements to be used.
 
I would appreciate your help.
 
Regards
Pankaj
Generali can't compile it .error:"can't fine *.tlb" or Pinmemberzkyin5-Apr-09 21:07 
QuestionGreat, but is there a way to create solicited RA ticket? Pinmemberfmguler19-Mar-09 0:39 
AnswerRe: Great, but is there a way to create solicited RA ticket? PinmemberMichael Chourdakis19-Mar-09 4:58 
GeneralRe: Great, but is there a way to create solicited RA ticket? Pinmemberzkyin5-Apr-09 21:15 
GeneralRe: Great, but is there a way to create solicited RA ticket? PinmemberMichael Chourdakis14-Apr-09 22:18 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.141220.1 | Last Updated 6 Oct 2008
Article Copyright 2008 by Michael Chourdakis
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid