2

I'm writing a service application that needs to enumerate all current user sessions, and obtain their session IDs, and later see what processes are running for what session. I'm using the WTSEnumerateSessions() API, as well as WTSQuerySessionInformation() to obtain a session specific information. Unfortunately those WTS APIs are very unreliable.

On a Windows XP machine with Fast User Switching turned off, or on an XP machine joined to a domain, those APIs are not immediately available. They may fail with the RPC_S_INVALID_BINDING, or 1702, error code for as long as several minutes after the Windows XP boots up and my service starts.

I could not find any official documentation explaining how to handle such limitation. The one available via a search engine is to wait for the terminal services service to load up, which is of course possible, but becomes a MAJOR pain in the a** to implement.

So, if someone could answer the following I'd appreciate it:

  1. Are there any alternative APIs to work with session specific data, that are more reliable that those WTS ones? I mostly need to see current sessions on the machine, get a user name and session status. Also enumerate processes with session IDs for each process. (I know that this is possible, since GINA or a log-in screen, can do all that way before the terminal services load up.)
  2. Is there a 100% guaratee that WTS-class APIs (such as WTSEnumerateSessions(), WTSQuerySessionInformation() and WTSEnumerateProcesses()) will load up before my service starts up on any version of Windows Vista/Windows 7 machine?

Please note bofore and any stipulations that a VERY important.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
ahmd0
  • 16,633
  • 33
  • 137
  • 233

3 Answers3

4

Another API which could be helpful for you are LsaEnumerateLogonSessions and LsaGetLogonSessionData SECURITY_LOGON_SESSION_DATA having Session field. See the code example and this one. To get information about the session of the process you can use GetTokenInformation with TokenSessionId as parameter. To enumerate processes you can use NtQuerySystemInformation (see my old answer).

Community
  • 1
  • 1
Oleg
  • 220,925
  • 34
  • 403
  • 798
  • Thanks a lot! I've just implemented your approach using Lsa functions and it works great, except how do I know which sessions currently have a logged on user? Say, I have the SECURITY_LOGON_SESSION_DATA struct: http://msdn.microsoft.com/en-us/library/windows/desktop/aa380128(v=vs.85).aspx – ahmd0 Oct 29 '11 at 01:19
  • I suppose you could enumerate the process list. That works for all sessions > 0. Telling if 0 is logged in can be done by looking at the active desktop. – Joshua Oct 29 '11 at 04:16
  • I'm sorry, I'm not really following it... can you give more details? – ahmd0 Oct 29 '11 at 07:28
  • @ahmd0: Which additional information you need. Which information exactly you need **at the boot time**? It's the case which made you problems, isn't it? Do you have not problem to enumerate all processes? Enabling of Debug privilege can be always helpful because it allows you to access any handle. – Oleg Oct 29 '11 at 08:16
  • What I need to know is this. Say I got a bunch of LUID's for log on sessions using the LSA APIs you gave me. So how do I know which users actually logged in to the system? And also which session is the currently active user session? – ahmd0 Oct 30 '11 at 00:57
  • 1
    @ahmd0: I still not understand what you do and what you need. On the question "which session" you should answer with the value of `Session` field of `SECURITY_LOGON_SESSION_DATA` or `TokenSessionId` and not a `LUID`. If you find new `LUID`, then the user login took place. Every `LoginUser` call create `LUID` for example without creating new session. Do you want monitor user login/logout then you can do this in other way. [Winlogon Notification dll](http://msdn.microsoft.com/en-us/library/windows/desktop/aa380544(v=VS.85).aspx) can be used on XP. `ISensLogon2` of SENS is another way. – Oleg Oct 30 '11 at 09:33
  • Thanks. Again, I need this as a substitute for defunct WTSEnumerateSessions() API (on Windows XP). I call it from my own service that needs to know the list of session ID that currently have a logged on user. I managed to get this information by calling LsaEnumerateLogonSessions then LsaGetLogonSessionData on each of the sessions and then call WTSQueryUserToken on the 'session' returned by previous call. If the last API fails, I treat it as user not yet logged on to that session. It's my own discovery, so I'm not sure how correct is it? – ahmd0 Oct 30 '11 at 20:09
3

There are a few solutions suggested here. In summary:

  1. Make sure "TermSrv" is running (via dependency, manually starting/waiting for it, etc).
  2. Wait for the "Global\TermSrvReadyEvent" event to be set.
Community
  • 1
  • 1
Luke
  • 11,211
  • 2
  • 27
  • 38
  • Well, that's my whole "beef" with those WTS APIs. I don't want to wait for anything -- what is my service supposed to do in the meantime, what if the wait is 10 minutes, or more.... It's unacceptable! – ahmd0 Oct 28 '11 at 23:52
  • I guess it depends on what is causing the delay. On my XP laptop the terminal services service is set to run on-demand; maybe that's why it takes so long for the APIs to become available (e.g. nobody is trying to use it until much later). If you set your service to "automatic" and put a dependency on terminal services then maybe the APIs will become available sooner. – Luke Oct 29 '11 at 16:15
  • Thanks. It's not just me on my machine. It is a publicly available product. If you ask my guess as to what happens, the terminal services service (sp?) loads up early in case fast user switching is enabled. If it's off (or what is even more strange - in case XP is connected to a domain???) the system doesn't load it immediately. Which, really doesn't make sense at all, but wait... it's Windows, stuff like that is a given ))) We just need to make ways to patch "holes" in it ourselves... – ahmd0 Oct 29 '11 at 16:57
1

I think the #2 you ask about is guaranteed on Vista/7 since those APIs are required to function to create any process on any session > 0.

Joshua
  • 40,822
  • 8
  • 72
  • 132
  • 1
    Thank you for pointing it out. Although, can someone confirm this? It is quite important for me. Or, maybe there's some documentation on this subject? – ahmd0 Oct 28 '11 at 23:53