Monday, December 06, 2010

Monitoring of logon/logout in terminal and client sessions

Introduction

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.

Sessions overview

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:

class CSessionOwner
   {
   public:
       ~CSessionOwner();
       static void GetSessions(std::vector<CSessionOwner> & vecSessions);
       static void GetActiveSessions(std::set<CSessionOwner> & setSessions);
               bool operator < (const CSessionOwner & other) const
       {
           return m_sid < other.GetSid();
       }
       int GetSid() const;
       bool IsActive() const;
       double GetLogonTime() const;
       std::wstring GetSessionUserName() const;
       std::wstring GetDomainName() const;
       std::wstring GetFullUserName() const;
   private:
       CSessionOwner(const int& sid);
       int m_sid;
   };

The GetSessions function encapsulates use of the WTSEnumerateSessions function to obtain the list of running sessions in the system.

void CSessionOwner::GetSessions(std::vector<CSessionOwner> & vecSessions)
{
   PWTS_SESSION_INFO pSessionInfo(NULL);
   DWORD count(0);
   if(!WTSEnumerateSessions( WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessionInfo, &count))
   {
       DWORD err = GetLastError();
       if (err == RPC_S_INVALID_BINDING)

Read more: Codeproject