Remko Weijnen's Blog (Remko's Blog)

About Terminal Server, Citrix, Delphi and other stuff

Archive for the ‘Delphi’ Category

Using WTSWaitSystemEvent

If you develop an application for Terminal Server you might want to react on session events. This means that your application is notified when a user logs on, logs off or becomes idle. This can be done with the WTSWaitSystemEvent function. Implementing it is rather simple and could look something like this:

Notice that you would probably do this from a seperate thread otherwise you will block the main thread. To stop waiting for Events you send a special event:

Please note that there are at least 2 issues with this API, one with Windows 2000 and one with Windows Vista. On Windows 2000 events are reported twice for each actual event. Microsoft’s resolution?

The application should expect the event twice, and filter out the second occurrence.

Now how do we solve this? I would suggest introducing a small delay after an event trigger, this way you will probably not receive the duplicate event.

On Windows Vista there’s another issue: After you set the value of the EventMask parameter to WTS_EVENT_FLUSH in the WTSWaitSystemEvent function, no pending calls to the function return on a Windows Vista-based computer. Now what does this mean? It means that after sending WTS_EVENT_FLUSH the thread never responds! So there’s actually no nice way to end the thread, the only escape is a call to TerminateThread.

Microsoft does offer a hotfix, so my suggestion is a check on startup that will notify the user that he/she needs to install the hotfix. A version check can be done on winsta.dll, the version before the fix is 6.0.6000.16386. Hotfix version is 6.0.6000.20664. According to this article the fix will be included in Vista SP1.

References:

Undocumented API’s from Utildll

Several of Microsoft’s Terminal Server tools use undocumented API’s from Utildll.dll. For instance Terminal Server Admin uses it to get a localised connect state string and to format time strings like idle time, logon time etc.

Functions below seems to be the most usefull ones, I will add those to the JwaWinsta unit:

  • function StrConnectState (returns localised string of the given ConnectState)
  • DateTimeString (returns formatted date timestring according to user’s timesettings)
  • function CurrentDateTimeString (like the name says)
  • function ElapsedTimeString (returns formatted string with elapsed time as in TSAdmin)
  • function CalculateElapsedTime (returns elapsed time in seconds)
  • function CalculateDiffTime (returns time difference in seconds)
  • function GetUnknownString (returns localised “unknown” string)

Citrix has it’s own version of this DLL called CUtildll.dll which is similar but uses (Citrix) MUI for localising strings.

Delphi and Terminal Server Aware

When an application is not Terminal Server aware (also known as a legacy application), Terminal Server makes certain modifications to the legacy application to make it work properly in a multiuser environment. For example, Terminal Server will create a virtual Windows folder, such that each user gets a Windows folder instead of getting the system’s Windows directory. This gives users access to their own INI files. In addition, Terminal Server makes some adjustments to the registry for a legacy application. These modifications slow the loading of the legacy application on Terminal Server and require up to 8 MegaBytes extra memory. This behaviour can be avoided if the TSAware flag is present in the PE header of an executable as can be read here at MSDN.

But how do we set this property in Delphi?

In Windows.pas we can see that the constant is defined:

But how to use this in your application?
Add the line

somewhere below the uses clause and we’re done!

Offcourse you are now responsible for making your application Terminal Server compliant which according to Microsoft means: If an application is Terminal Server aware, it must neither rely on INI files nor write to the HKEY_CURRENT_USER registry during setup.

It has been a little silent on the JEDI Apilib project lately, but this will change!

We had some change in the team members: Marcel van Brakel, founder and large contributor of the project has signed off because he no longer actively uses Delphi. Christian Wimmer has joined the team and he is a very promising member.

Christian has been working on a new include model (optional) of the Jedi Apilib which has the advantage that you only need to use one unit (JwaWindows) for the whole library.

Chris has also published the JEDI Windows Security Code Library (Jwscl). This is library that tremendously simplifies using Win32 API calls from Delphi. At this point the library contains:

  • Windows Version
  • Token
  • Impersonation
  • Login
  • SID
  • Access Control List
  • Security Descriptor
  • Owner, Group, DACL, SACL
  • WindowStation
  • Desktop
  • LSA
  • Rights mapping
  • Secured Objects Files, Registry (+Inheritance), etc.
  • Credentials (Login Dialog)
  • Encryption (MS Crypto API)
  • Well Known SIDs
  • Privileges
  • Security Dialogs (The “ACL Editor” you see on the security yab when you rightclick object in Explorer)
  • Terminal Sessions
  • Unicode + Ansicode
  • Vista Elevation
  • Vista Integrity Level

Although Jwscl is in beta stage it is already very well useable.

(more…)

  • 0 Comments
  • Filed under: Delphi, Programming
  • How to get Client IP Address?

    When a client is connected to a Terminal Server Session you can use the Terminal Server API to retrieve the client’s local IP address.

    Start by enumerating all sessions with WtsEnumerateSessions and then for each session get the ClientAddress with a call to WTSQuerySessionInformation with the WTSClientAddress parameter. Sound simple, no?

    WTSQuerySessionInformation returns a pointer to a WTS_CLIENT_ADDRESS structure. You need to know that the IP address is located at on offset of 2 bytes in the Address member of WTS_CLIENT_ADDRESS.

    So here’s a sample:

    (more…)

    TSAdminEx

    You will probably know Microsofts Tool to Manage Terminal Server, it’s called Terminal Services Manager (you will probably know it as TSAdmin). It can be used to view information about terminal servers including all sessions, users, and processes for each terminal server.

    TSAdmin Screenshot

    I’m currently working on a TSAdmin replacement (codename TSAdminEx). Purpose is to show how to use the Terminal Server API’s and as a little bonus we will add some extra functionality to TSAdminEx.

    (more…)

    This is an often asked question but the solution is simple:

    So how does it work?
    First we obtain the user’s primary access token with the WtsQueryUserToken  API call. To call this function successfully, the calling application must be running within the context of the LocalSystem account and have the SE_TCB_NAME privilege (LocalSystem has this privilege by default). Since the function returns a primary acces token we can just pass this to CreateProcessAsUser and voila!

    (more…)

    Profile

    Tags

    Recent Tweets

    Views

    Donate


    Blogroll


    Categories


    Archives