use terminal services api to query for RDP logins, adding to who_list
This commit is contained in:
parent
1212c2f03e
commit
f64b36c0bd
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue