Procedural Epistemology Thinker RSS 2.0
 Wednesday, July 09, 2008

Terminal Server API Programming in C# (Part I)

 

Sorry for such a late response on my blog. Life has been very full for me. I now have a new job as a Senior Software Engineer at a awesome company named MPi (http://mpifix.com) This company is organized and sharp. I think probably the best development environment I've been in yet. (Well see how the camaraderie is).

Why do companies use RDP?

A RDP is a multi-channel protocol that allows a user to connect to a computer running Microsoft Terminal Services for the purpose of running programs installed on the server without having to install that same program on the client machine.

For example we install our application on a server hosted in their corporate office and then a bunch of other shops can run our program on their client machines without ever having to install it. Neat-o.

Scenario:

My first task at my new job was to identify a connecting Clients Public IP address, Hostname and Username.  The client can connect using RDP or thru a Citrix Farm. So I need to determine which they are connecting with and then gleam the information.

Research:

It turns out that Microsoft has a great Terminal Services API. Here is a reference link: http://msdn.microsoft.com/en-us/library/aa383468(VS.85).aspx

As I read more about RDP I found that on every server the RDP connection connects with a type listing a 3 character prefix “RDP” and any Citrix connection connected with “ICA” for example Type: RDPClient or ICAClient. Both of these are each stored in sessions on the server. Interesting don’t you think.. hmm.

Turns out the Terminal Services API has a public method named: WTSEnumerateSessions. This method has a WTS_INFO_CLASS enumeration type that contains your structure when you retrieve the information from WTSQuerySessionInformation. The method takes:

hServer: Handle to a terminal server.

Reserved: Just know this must be zero.

Version: This is the version of the enumeration request. Must be 1

ppSessionInfo: This is a pointer to a variable that receives a pointer to an array of the WTS_SESSION_INFO (another structure for the object).

pCount: A pointer to the variable that receives the number of WTS_SESSION_INFO structure.

Lets write some psuedo code utilizing the WTSEnumerateSessions.

1)      I need to use Pinvoke to import the Terminal Services API functions to use in my code.

a.       The assembling is “wtsapi32.dll

2)      The functions I need to accomplish using WTSEnumerateSessions are:

a.      WTSOpenServer

b.      WTSCloseServer

c.       WTSEnumerateSessions

d.      WTSQuerySessionInformation

                                                               i.      I need to manually pass the correct information to WTSQuerySessionInformation to setup the use of WTSEnumerateSessions.

e.       WTSFreeMemory

                                                               i.      Because I’lll be pulling the session info using pointers then after I’m finished I need to free up the buffer again using this method.

3)      WTS_SESSION_INFO: The wtsapi32 provides me with a existing structure that I can use to store information about a client session. The name of that struct is named WTS_SESSION_INFO. * *NOTE: Structs are great when all you care about is the properties of an object and they are going to be very small. Structs get put in the heap which when the object is orphaned or not used it falls off the heap. This in turn uses less memory. ^_^ less memory is a good thing. Only use what you need. Again only use Structs when it’s a small object (16 bytes or less) AND when you only care about the properties of the object.

4)      SessionInfoBag: I also want to create a public structure for my session object so I can pass it around my code. Because I only care about the properties and everything coming back from the wtsapi32 api are structs then a public struct is the perfect choice.

5)      Wrapper classes: For good design I’m going to wrap up my WTSOpenServer, WTSCloseServer and WTSQuerySessionInformation and add another layer of abstraction between the API and my code. This way if things change I can just change the wrapper class implementation and this makes code maintaince much easier.

6)      GetRDPSessions: This will be my main Public method that will utilize WTSEnumerateSessions. The meat and potatos so to speak.

 

In Part II, I’ll start implementing the code.

Wednesday, July 09, 2008 3:19:37 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] - Trackback
Technical | Terminal Services
Archive
<July 2008>
SunMonTueWedThuFriSat
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789
About the Author/Disclaimer
Currently I am a Senior Software Engineer at Mobile Productive Inc a automotive tech company. Check us out at http://www.mpifix.com

Experience
  • Project Management: 4 Years (Apple Computers)
  • Computer Instructor: 2 Years (CompUSA)
  • Developer: 4 Years (RemedyMD, HRN, MPi)

  • Education
  • B.S in Computer Science from Neumont University
  • Certificate of Continuing Education from MIT

  • Linkedin

    Disclaimer
    The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

    © Copyright 2009
    Joshua T Stroup
    Sign In
    Statistics
    Total Posts: 19
    This Year: 0
    This Month: 0
    This Week: 0
    Comments: 5
    All Content © 2009, Joshua T Stroup