This article includes a description of the monitoring process for the session logon/logout, connect/disconnect (regarding terminal and client sessions). Obtained results will be then used in the next article ”Creating process in the session”.
This article deals with the session logon/logout notifications. For this purposes
WtsApi functions are used in the code. Project, which is attached to this article, is a simple service implemented for demonstration that writes all changes of session state to the log file. It is recommended to set service to start automatically on system start so it would be able to register the first session logon. It is recommended also to set the service dependence of
TermServ service, so the service will definitely get the first notification from WTS, otherwise if the function of
WtsApi is called before the dependent services of Remote Desktop Services have started, the
RPC_S_INVALID_BINDING error code may be returned.
This article has a connected article about creating process in logged session.
Read also: OS X Reverse Engineering
We start with the brief overview of sessions. Every interactive user is associated with a session object. Sessions are identified by the session ID (SID). Sessions can be either local or remote. The local session is associated with the interactive user physically logged on to the machine. Service processes are also assigned to the local session. This session is always assigned the ID of 0, and is also referred to as the console. Here, I mean the first physical session, so if you use Fast User Switching on Windows XP, the session ID will be incremented for each new session. This is correct for the Windows operating systems until Windows Vista. For these Windows versions, a console session can be any session with non-zero ID. Shortly, it was done to isolate services from interactive applications and prevent services from being hacked by end users. Anyway, we won’t go into detail of this theme. I just want to mention one nuance concerning the sessions running in the Terminal Services environment – there can be more than one interactive user in such session.
There are at least two ways to retrieve logon/logout event notification: System Event Notification Service (SENS) and the Windows Terminal Service (WTS). The connectivity functions and notifications of SENS are useful for applications written for mobile computers or computers connected to high latency local area networks, as it is written in msdn. We won’t stay for long on SENS description, because in this article we will use WTS API.
The Remote Desktop Services API (formerly known as Terminal Services) enables you to enumerate and manage Remote Desktop Session Host (RD Session Host) servers, client sessions, and processes; retrieve information about sessions and processes.
Sessions enumerating. WtsApi usage
For retrieving running session list and information about these sessions, the
CSessionOwner class is implemented:
GetSessions function encapsulates use of the
WTSEnumerateSessions function to obtain the list of running sessions in the system.
wts_resource class is used in the method code. It is my simple class-guard for work with WTS resource, which has a pointer to a resource as a class member and calls the
WTSFreeMemory function in its destructor. It has to be called because the
WTSEnumerateSessions function allocates memory for the buffer and the calling side has to free the returned buffer.
As it was described above, in case of the
WTSEnumerateSessions function failure,
RPC_S_INVALID_BINDING error code may be the indicator of the situation when one of the dependent
TermServ service is not started, so it is not an exceptional situation, and the best we can do is to add a log entry in this case.
CSessionOwner class methods are used to get information about the session, such as session ID, user name, connection state of session, etc. by calling
WTSQuerySessionInformation with required flag specifying the type of information to retrieve.
Important information of session is its connection state, that is returned by the
All possible connection states of session is described in the
_WTS_CONNECTSTATE_CLASS enum. An active session, no matter local or remote one, has connection state
WTSActive. When remote desktop connection is enabled on the server, one more session appears immediately besides the current local session with the
WTSListen state. Remote sessions that are not logged off but only closed, and the local session that is switched will have the
WTSDisconnected connection state. There are some states that can be interesting for process management in the session. Now, when we can get the list of active sessions, let’s describe how to monitor changes in it.
Monitoring of the user logon/logout, session connect/disconnect.
I use the
WTSWaitSystemEvent function in the sample project to wait for an event, such as the creation of a client session or a user logging on to the RD session host server.
Let’s take a look at the following class for work with
Functional code for sessions state monitoring is implemented in operator
(). It is an operator to use it with
boost::thread instead of a function. The following code has to run in the separate thread to get the notification about the changes of the session state. Here is sipmle illustration of the work with
There is a set of events to be processed: session logon/logoff, connect/disconnect. Obviously, you can set the flags to wait for any event you want, but in this example we suppose that we want to get notifications only about these four events.
Here I’ll wander a bit from the main point and say a few words about boost threads. Boost enables to use multiple threads of execution with shared data in portable C++ code. It provides the
boost::thread class for managing the threads, which is very simple and convenient to use.
The class given below is a wrapper for work with the boost thread:
Now we return to the
CSessionManager class and
UpdateSessionState function. It writes the information about the session to the log file– user name, log on or log out event:
GotSessionsSetGhanges function is designed to watch for changes of the session list:
Resulting sample project represents a service that monitors logging on/out of the active user local/remote session and connect/disconnect (disconnect for the terminal sessions or fast user switching for the local ones) using WTS API functions and writes every event to the log file, located in the same directory that the executable file is. To build the sources you have to set boost environment variable. The project supports x86 and x64 platforms. To build the solution boost environment variable has to be set, and it has to be built for both platforms. In this article boost 1.40.0 version is used.
- MSDN Remote Desktop API documentation (http://msdn.microsoft.com/en-us/library/aa383459%28v=VS.85%29.aspx)
- Boost libraries (http://www.boost.org/doc/libs/1_44_0/doc/html/thread/thread_management.html)
- Microsoft systems journal (http://www.microsoft.com/msj/1099/terminal/terminal.aspx)