use terminal services api to query for RDP logins, adding to who_list

This commit is contained in:
Doug MacEachern 2005-09-27 01:18:54 +00:00
parent 1212c2f03e
commit f64b36c0bd
2 changed files with 246 additions and 1 deletions

View File

@ -97,6 +97,84 @@ typedef struct _IP_ADAPTER_INFO {
/* end iptypes.h */ /* end iptypes.h */
/* from wtsapi32.h not in vs6.0 */
typedef enum {
WTSInitialProgram,
WTSApplicationName,
WTSWorkingDirectory,
WTSOEMId,
WTSSessionId,
WTSUserName,
WTSWinStationName,
WTSDomainName,
WTSConnectState,
WTSClientBuildNumber,
WTSClientName,
WTSClientDirectory,
WTSClientProductId,
WTSClientHardwareId,
WTSClientAddress,
WTSClientDisplay,
WTSClientProtocolType,
} WTS_INFO_CLASS;
typedef enum _WTS_CONNECTSTATE_CLASS {
WTSActive,
WTSConnected,
WTSConnectQuery,
WTSShadow,
WTSDisconnected,
WTSIdle,
WTSListen,
WTSReset,
WTSDown,
WTSInit
} WTS_CONNECTSTATE_CLASS;
#define WTS_PROTOCOL_TYPE_CONSOLE 0
#define WTS_PROTOCOL_TYPE_ICA 1
#define WTS_PROTOCOL_TYPE_RDP 2
typedef struct _WTS_SESSION_INFO {
DWORD SessionId;
LPTSTR pWinStationName;
DWORD State;
} WTS_SESSION_INFO, *PWTS_SESSION_INFO;
typedef struct _WTS_PROCESS_INFO {
DWORD SessionId;
DWORD ProcessId;
LPSTR pProcessName;
PSID pUserSid;
} WTS_PROCESS_INFO, *PWTS_PROCESS_INFO;
typedef struct _WTS_CLIENT_ADDRESS {
DWORD AddressFamily;
BYTE Address[20];
} WTS_CLIENT_ADDRESS, *PWTS_CLIENT_ADDRESS;
/* the WINSTATION_INFO stuff here is undocumented
* got the howto from google groups:
* http://redirx.com/?31gy
*/
typedef enum _WINSTATION_INFO_CLASS {
WinStationInformation = 8
} WINSTATION_INFO_CLASS;
typedef struct _WINSTATION_INFO {
BYTE Reserved1[72];
ULONG SessionId;
BYTE Reserved2[4];
FILETIME ConnectTime;
FILETIME DisconnectTime;
FILETIME LastInputTime;
FILETIME LoginTime;
BYTE Reserved3[1096];
FILETIME CurrentTime;
} WINSTATION_INFO, *PWINSTATION_INFO;
/* end wtsapi32.h */
#include <iprtrmib.h> #include <iprtrmib.h>
/* undocumented structures */ /* undocumented structures */
@ -126,7 +204,6 @@ typedef struct {
} MIB_UDPEXTABLE, *PMIB_UDPEXTABLE; } MIB_UDPEXTABLE, *PMIB_UDPEXTABLE;
/* end undocumented structures */ /* end undocumented structures */
typedef DWORD (CALLBACK *LPGETIPFORWARDTABLE)(PMIB_IPFORWARDTABLE, PULONG, BOOL); typedef DWORD (CALLBACK *LPGETIPFORWARDTABLE)(PMIB_IPFORWARDTABLE, PULONG, BOOL);
typedef DWORD (CALLBACK *LPGETIFTABLE)(PMIB_IFTABLE, PULONG, BOOL); typedef DWORD (CALLBACK *LPGETIFTABLE)(PMIB_IFTABLE, PULONG, BOOL);
@ -153,6 +230,24 @@ typedef BOOL (CALLBACK *LPENUMMODULES)(HANDLE, HMODULE*,
typedef DWORD (CALLBACK *LPGETMODULENAME)(HANDLE, HMODULE, typedef DWORD (CALLBACK *LPGETMODULENAME)(HANDLE, HMODULE,
LPTSTR, DWORD); LPTSTR, DWORD);
typedef BOOLEAN (CALLBACK *LPSTATIONQUERYINFO)(HANDLE,
ULONG,
WINSTATION_INFO_CLASS,
PVOID, ULONG, PULONG);
typedef BOOL (CALLBACK *LPWTSENUMERATESESSIONS)(HANDLE,
DWORD,
DWORD,
PWTS_SESSION_INFO *,
DWORD *);
typedef void (CALLBACK *LPWTSFREEMEMORY)(PVOID);
typedef BOOL (CALLBACK *LPWTSQUERYSESSION)(HANDLE,
DWORD,
WTS_INFO_CLASS,
LPSTR *, DWORD *);
/* no longer in the standard header files */ /* no longer in the standard header files */
typedef struct { typedef struct {
LARGE_INTEGER IdleTime; LARGE_INTEGER IdleTime;
@ -187,6 +282,8 @@ struct sigar_t {
HINSTANCE ip_handle; HINSTANCE ip_handle;
HINSTANCE nt_handle; HINSTANCE nt_handle;
HINSTANCE ps_handle; HINSTANCE ps_handle;
HINSTANCE wts_handle;
HINSTANCE sta_handle;
LPGETIFTABLE get_if_table; LPGETIFTABLE get_if_table;
LPGETIPFORWARDTABLE get_ipforward_table; LPGETIPFORWARDTABLE get_ipforward_table;
LPGETTCPTABLE get_tcp_table; LPGETTCPTABLE get_tcp_table;
@ -199,6 +296,10 @@ struct sigar_t {
LPENUMMODULES enum_modules; LPENUMMODULES enum_modules;
LPGETMODULENAME get_module_name; LPGETMODULENAME get_module_name;
sigar_win32_pinfo_t pinfo; sigar_win32_pinfo_t pinfo;
LPSTATIONQUERYINFO query_station;
LPWTSENUMERATESESSIONS wts_enum_sessions;
LPWTSFREEMEMORY wts_free;
LPWTSQUERYSESSION wts_query_session;
WORD ws_version; WORD ws_version;
int ws_error; int ws_error;
LPBYTE peb; //scratch pad for getting peb info LPBYTE peb; //scratch pad for getting peb info

View File

@ -258,6 +258,20 @@ int sigar_os_open(sigar_t **sigar)
(*sigar)->ps_handle = NULL; (*sigar)->ps_handle = NULL;
} }
if ((h = LoadLibrary("wtsapi32.dll"))) {
(*sigar)->wts_handle = h;
}
else {
(*sigar)->wts_handle = NULL;
}
if ((h = LoadLibrary("winsta.dll"))) {
(*sigar)->sta_handle = h;
}
else {
(*sigar)->sta_handle = NULL;
}
(*sigar)->pinfo.pid = -1; (*sigar)->pinfo.pid = -1;
(*sigar)->ws_version = 0; (*sigar)->ws_version = 0;
(*sigar)->ncpu = 0; (*sigar)->ncpu = 0;
@ -288,6 +302,14 @@ int sigar_os_close(sigar_t *sigar)
FreeLibrary(sigar->ps_handle); FreeLibrary(sigar->ps_handle);
} }
if (sigar->wts_handle) {
FreeLibrary(sigar->wts_handle);
}
if (sigar->sta_handle) {
FreeLibrary(sigar->sta_handle);
}
if (sigar->ws_version != 0) { if (sigar->ws_version != 0) {
WSACleanup(); WSACleanup();
} }
@ -2061,6 +2083,8 @@ int sigar_who_list_get_win32(sigar_t *sigar,
sigar_who_registry(sigar, wholist); sigar_who_registry(sigar, wholist);
sigar_who_wts(sigar, wholist);
return SIGAR_OK; return SIGAR_OK;
} }
@ -2235,3 +2259,123 @@ static int sigar_who_registry(sigar_t *sigar,
return SIGAR_OK; return SIGAR_OK;
} }
static int sigar_who_wts(sigar_t *sigar,
sigar_who_list_t *wholist)
{
DWORD count, i;
WTS_SESSION_INFO *sessions = NULL;
if (!sigar->wts_enum_sessions && sigar->wts_handle) {
sigar->wts_enum_sessions =
(LPWTSENUMERATESESSIONS)GetProcAddress(sigar->wts_handle,
"WTSEnumerateSessionsA");
sigar->wts_free =
(LPWTSFREEMEMORY)GetProcAddress(sigar->wts_handle,
"WTSFreeMemory");
sigar->wts_query_session =
(LPWTSQUERYSESSION)GetProcAddress(sigar->wts_handle,
"WTSQuerySessionInformationA");
sigar->query_station =
(LPSTATIONQUERYINFO)GetProcAddress(sigar->sta_handle,
"WinStationQueryInformationW");
}
if (!sigar->wts_enum_sessions) {
return ENOENT;
}
if (!sigar->wts_enum_sessions(0, 0, 1, &sessions, &count)) {
return GetLastError();
}
for (i=0; i<count; i++) {
DWORD bytes;
LPTSTR buffer;
DWORD sessionId = sessions[i].SessionId;
WINSTATION_INFO station_info;
sigar_who_t *who;
if (sessions[i].State != WTSActive) {
continue;
}
buffer = NULL;
bytes = 0;
if (sigar->wts_query_session(0,
sessionId,
WTSClientProtocolType,
&buffer,
&bytes))
{
DWORD type = *buffer;
sigar->wts_free(buffer);
if (type == WTS_PROTOCOL_TYPE_CONSOLE) {
continue;
}
}
SIGAR_WHO_LIST_GROW(wholist);
who = &wholist->data[wholist->number++];
SIGAR_SSTRCPY(who->device, sessions[i].pWinStationName);
buffer = NULL;
bytes = 0;
if (sigar->wts_query_session(0,
sessionId,
WTSClientAddress,
&buffer,
&bytes))
{
PWTS_CLIENT_ADDRESS client =
(PWTS_CLIENT_ADDRESS)buffer;
sprintf(who->host, "%u.%u.%u.%u",
client->Address[2],
client->Address[3],
client->Address[4],
client->Address[5]);
sigar->wts_free(buffer);
}
else {
SIGAR_SSTRCPY(who->host, "unknown");
}
buffer = NULL;
bytes = 0;
if (sigar->wts_query_session(0,
sessionId,
WTSUserName,
&buffer,
&bytes))
{
SIGAR_SSTRCPY(who->user, buffer);
sigar->wts_free(buffer);
}
else {
SIGAR_SSTRCPY(who->user, "unknown");
}
buffer = NULL;
bytes = 0;
if (sigar->query_station(0,
sessionId,
WinStationInformation,
&station_info,
sizeof(station_info),
&bytes))
{
who->time =
FileTimeToTime(&station_info.ConnectTime) / 1000000;
}
else {
who->time = 0;
}
}
sigar->wts_free(sessions);
return SIGAR_OK;
}