//----------------------------------------------------------------------
//
// PsLoggedOn
//
// Copyright (C) 1999 Mark Russinovich
// Systems Internals
// http://www.sysinternals.com
//
// This program displays the logons for the specified computer.
//
//----------------------------------------------------------------------
#include <tchar.h>
#include <stdio.h>
#include <assert.h>
#include <windows.h>
#include <lm.h>
//
// Length of name strings
//
#define MAX_NAME_STRING 1024
//
// Reset a line
//
#define RESETLINE L"\r \r"
//--------------------------------------------------------------------
//
// PrintWin32Error
//
// Translates a Win32 error into a text equivalent
//
//--------------------------------------------------------------------
void PrintWin32Error( LPWSTR ErrorMessage, DWORD ErrorCode )
{
LPVOID lpMsgBuf;
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, ErrorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPWSTR) &lpMsgBuf, 0, NULL );
wprintf(L"%s: %s\n", ErrorMessage, lpMsgBuf );
LocalFree( lpMsgBuf );
}
//--------------------------------------------------------------------
//
// DisplayLogonTime
//
// If detail mode is on, shows the logon time.
//
//--------------------------------------------------------------------
VOID DisplayLogonTime( PSYSTEMTIME LogonTime )
{
TCHAR logonDateString[MAX_PATH];
TCHAR logonTimeString[MAX_PATH];
GetDateFormat( LOCALE_USER_DEFAULT, 0,
LogonTime, NULL,
logonDateString, sizeof(logonDateString)/sizeof(TCHAR));
GetTimeFormat( LOCALE_USER_DEFAULT, 0,
LogonTime, NULL,
logonTimeString, sizeof(logonTimeString)/sizeof(TCHAR));
wprintf(L" %s %s ", logonDateString, logonTimeString );
}
//--------------------------------------------------------------------
//
// GetSessionLogonTime
//
// Calculates the remote logon time by taking the current time
// and subtracting the number of seconds the user has been logged on.
//
//--------------------------------------------------------------------
VOID GetSessionLogonTime( DWORD Seconds,
PSYSTEMTIME LogonTime )
{
ULARGE_INTEGER fileTimeInteger;
FILETIME fileTime;
GetLocalTime( LogonTime );
SystemTimeToFileTime( LogonTime, &fileTime );
fileTimeInteger = *(PULARGE_INTEGER) &fileTime;
fileTimeInteger.QuadPart -= Seconds * 10000000;
fileTime = *(PFILETIME) &fileTimeInteger;
FileTimeToSystemTime( &fileTime, LogonTime );
}
//--------------------------------------------------------------------
//
// GetLocalLogonTime
//
// Retrieves the logon time of the local user.
//
//--------------------------------------------------------------------
BOOLEAN GetLocalLogonTime( HKEY hCurrentUsers,
LPWSTR UserSid,
PSYSTEMTIME LogonTime )
{
HKEY hKey;
TCHAR keyName[MAX_PATH];
TCHAR class[1024];
DWORD classSize;
DWORD subKeys;
DWORD maxSubKeyLen;
DWORD maxClassLen;
DWORD values;
DWORD maxValueNameLen;
DWORD maxValueLen;
DWORD secDescLen;
FILETIME lastWriteTime;
_stprintf( keyName, _T("%s\\Volatile Environment"), UserSid );
if( RegOpenKey( hCurrentUsers, keyName, &hKey )) {
return FALSE;
}
classSize = sizeof(class);
if( RegQueryInfoKey( hKey,
class, &classSize, NULL,
&subKeys, &maxSubKeyLen,
&maxClassLen,
&values, &maxValueNameLen, &maxValueLen,
&secDescLen,
&lastWriteTime )) {
RegCloseKey( hKey );
return FALSE;
}
FileTimeToLocalFileTime( &lastWriteTime, &lastWriteTime );
FileTimeToSystemTime( &lastWriteTime, LogonTime );
RegCloseKey( hKey );
return TRUE;
}
//--------------------------------------------------------------------
//
// DisplayLocalLogons
//
// Scans the HKEY_USERS key of the specified computer to see who
// has their profile loaded. Returns true if someone is logged on.
//
//--------------------------------------------------------------------
BOOLEAN DisplayLocalLogons( BOOLEAN ShowDetail,
LPWSTR ServerName, LPWSTR UserName )
{
BOOLEAN first = TRUE;
TCHAR errorMessage[1024];
TCHAR userName[MAX_NAME_STRING], domainName[MAX_NAME_STRING];
TCHAR subKeyName[MAX_PATH];
DWORD subKeyNameSize, index;
DWORD userNameSize, domainNameSize;
FILETIME lastWriteTime;
HKEY usersKey;
PSID sid;
SID_NAME_USE sidType;
SID_IDENTIFIER_AUTHORITY authority;
BYTE subAuthorityCount;
DWORD authorityVal, revision;
SYSTEMTIME logonTime;
DWORD subAuthorityVal[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
//
// Use RegConnectRegistry so that we work with remote computers
//
if( ServerName ) {
wprintf(L"Connecting to Registry of %s...", ServerName );
fflush( stdout );
if( RegConnectRegistry( ServerName, HKEY_USERS, &usersKey ) != ERROR_SUCCESS) {
wprintf(RESETLINE);
wprintf( L"Error opening HKEY_USERS for %s\n", ServerName );
return FALSE;
}
wprintf(RESETLINE);
} else {
if( RegOpenKey( HKEY_USERS, NULL, &usersKey ) != ERROR_SUCCESS ) {
wprintf( errorMessage, L"Error opening HKEY_USERS" );
PrintWin32Error( errorMessage, GetLastError() );
return FALSE;
}
}
//
// Enumerate keys under HKEY_USERS
//
index = 0;
subKeyNameSize = sizeof( subKeyName );
while( RegEnumKeyEx( usersKey, index, subKeyName, &subKeyNameSize,
NULL, NULL, NULL, &lastWriteTime ) == ERROR_SUCCESS ) {
//
// Ignore the default subkey and win2K user class subkeys
//
if( wcsicmp( subKeyName, L".default" ) &&
!wcsstr( subKeyName, L"Classes")) {
//
// Convert the textual SID into a binary SID
//
subAuthorityCount= swscanf( subKeyName, L"S-%d-%x-%lu-%lu-%lu-%lu-%lu-%lu-%lu-%lu",
&revision, &authorityVal,
&subAuthorityVal[0],
&subAuthorityVal[1],
&subAuthorityVal[2],
&subAuthorityVal[3],
&subAuthorityVal[4],
&subAuthorityVal[5],
&subAuthorityVal[6],
&subAuthorityVal[7] );
if( subAuthorityCount >= 3 ) {
subAuthorityCount -= 2;
//
// Note: we can only deal with authority values
// of 4 bytes in length
//
authority.Value[5] = *(PBYTE) &authorityVal;
authority.Value[4] = *((PBYTE) &authorityVal+1);
authority.Value[3] = *((PBYTE) &authorityVal+2);
authority.Value[2] = *((PBYTE) &authorityVal+3);
authority.Value[1] = 0;
authority.Value[0] = 0;
//
// Initialize variables for subsequent operations
//
sid = NULL;
userNameSize = MAX_NAME_STRING;
domainNameSize = MAX_NAME_STRING;
if( AllocateAndInitializeSid( &authority,
subAuthorityCount,
subAuthorityVal[0],
subAuthorityVal[1],
subAuthorityVal[2],
subAuthorityVal[3],
subAuthorityVal[4],
subAuthorityVal[5],
subAuthorityVal[6],
subAuthorityVal[7],
&sid )) {
//
// We can finally lookup the account name
//
if( LookupAccountSid( ServerName,
sid,
userName,
&userNameSize,
domainName,
&domainNameSize,
&sidType )) {
//
// We've successfully looked up the user name
//
if( first && !UserName ) {
wprintf(L"Users logged on locally:\n");
first = FALSE;
}
if( !UserName || !wcsicmp( UserName, userName )) {
first = FALSE;
if( ShowDetail ) {
if( GetLocalLogonTime( usersKey, subKeyName, &logonTime )) {
DisplayLogonTime( &logonTime );
} else {
wprintf(L" Error: could not retrieve logon time\n");
}
}
if( UserName ) wprintf(RESETLINE L"%s\\%s logged onto %s locally.\n",
domainName, UserName, ServerName );
else wprintf( L"%s%s\\%s\n", ShowDetail ? "" : " ", domainName, userName );
}
}
}
if( sid ) FreeSid( sid );
}
}
subKeyNameSize = sizeof( subKeyName );
index++;
}
RegCloseKey( usersKey );
if( first && !UserName ) wprintf(L"No one is logged on locally.\n");
return !first;
}
//--------------------------------------------------------------------
//
// DisplaySessionLogons
//
// Uses the NetEnumSession API to see who is logged on via access
// to a resource share.
//
//--------------------------------------------------------------------
BOOLEAN DisplaySessionLogons( BOOLEAN ShowDetail,
LPWSTR ServerName, LPWSTR UserName )
{
LPSESSION_INFO_10 pBuf = NULL;
LPSESSION_INFO_10 pTmpBuf;
DWORD dwLevel = 10;
DWORD dwPrefMaxLen = 0xFFFFFFFF;
DWORD dwEntriesRead = 0;
DWORD dwTotalEntries = 0;
DWORD dwResumeHandle = 0;
DWORD i;
DWORD dwTotalCount = 0;
LPWSTR pszClientName = NULL;
LPWSTR pszUserName = NULL;
NET_API_STATUS nStatus;
PSID sid;
DWORD sidSize, domainNameSize;
BYTE sidBuffer[MAX_SID_SIZE];
TCHAR domainName[MAX_NAME_STRING];
SID_NAME_USE sidType;
BOOLEAN first = TRUE;
SYSTEMTIME logonTime;
//
// Now display session logons
//
do {
nStatus = NetSessionEnum( ServerName,
pszClientName,
pszUserName,
dwLevel,
(LPBYTE*)&pBuf,
dwPrefMaxLen,
&dwEntriesRead,
&dwTotalEntries,
&dwResumeHandle);
if ((nStatus == NERR_Success) || (nStatus == ERROR_MORE_DATA)) {
if ((pTmpBuf = pBuf) != NULL) {
for (i = 0; (i < dwEntriesRead); i++) {
assert(pTmpBuf != NULL);
if (pTmpBuf == NULL) {
fprintf(stderr, "An access violation has occurred\n");
break;
}
//
// Take the name and look up a SID so that we can get full domain/user
// information
//
sid = (PSID) sidBuffer;
sidSize = sizeof( sidBuffer );
domainNameSize = sizeof( domainName );
if( pTmpBuf->sesi10_username[0] ) {
if( first && !UserName ) {
wprintf(L"\nUsers logged on via resource shares:\n");
first = FALSE;
}
if( LookupAccountName( pTmpBuf->sesi10_cname ,
pTmpBuf->sesi10_username,
sid,
&sidSize,
domainName,
&domainNameSize,
&sidType )) {
if( !UserName || !wcsicmp( UserName, pTmpBuf->sesi10_username )) {
first = FALSE;
if( ShowDetail ) {
GetSessionLogonTime( pTmpBuf->sesi10_time, &logonTime );
DisplayLogonTime( &logonTime );
}
if( UserName ) wprintf(RESETLINE L"%s\\%s logged onto %s remotely.\n",
domainName, UserName, ServerName );
else wprintf(L"%s%s\\%s\n", ShowDetail ? "" : " ", domainName, pTmpBuf->sesi10_username );
}
} else {
if( !UserName || !wcsicmp( UserName, pTmpBuf->sesi10_username )) {
first = FALSE;
if( ShowDetail ) {
GetSessionLogonTime( pTmpBuf->sesi10_time, &logonTime );
DisplayLogonTime( &logonTime );
}
if( UserName ) wprintf(L"\r%s\\%s logged onto %s remotely.\n",
ServerName, UserName, ServerName );
else wprintf(L"%s%s\\%s\n", ShowDetail ? "" : " ", ServerName, pTmpBuf->sesi10_username );
}
}
}
pTmpBuf++;
dwTotalCount++;
}
}
} else {
wprintf(L"Unable to query resource logons\n");
first = FALSE;
}
if (pBuf != NULL) {
NetApiBufferFree(pBuf);
pBuf = NULL;
}
} while (nStatus == ERROR_MORE_DATA);
if (pBuf != NULL)
NetApiBufferFree(pBuf);
if( first && !UserName ) wprintf(L"\nNo one is logged on via resource shares.\n");
return !first;
}
//--------------------------------------------------------------------
//
// Usage
//
// Show valid arguments.
//
//--------------------------------------------------------------------
int Usage( wchar_t *ProgramName )
{
wprintf(L"Usage: %s [-l] [-x] [\\\\computername]\n"
L" or %s [username]\n", ProgramName, ProgramName);
wprintf(L"-l Show only local logons\n");
wprintf(L"-x Don't show logon times\n");
wprintf(L"\n");
return -1;
}
//--------------------------------------------------------------------
//
// wmain
//
// Run the show.
//
//--------------------------------------------------------------------
int wmain( int argc, wchar_t *argv[])
{
LPWSTR pszServerName = NULL;
LPWSTR pszUserName = NULL;
PSERVER_INFO_100 serverInfo = NULL;
DWORD entries, totalEntries, resumeHandle, i;
DWORD status;
BOOLEAN showDetail = TRUE;
BOOLEAN showLocalOnly = FALSE;
int arg;
int count = 0;
printf("\nPsLoggedOn v1.21 - Logon Session Displayer\n");
printf("Copyright (C) 1999-2000 Mark Russinovich\n");
printf("SysInternals - www.sysinternals.com\n\n");
if (argc > 3) {
return Usage( argv[0] );
}
for( arg = 1; arg < argc; arg++ ) {
switch( argv[arg][0] ) {
case L'-':
case L'/':
switch( argv[arg][1] ) {
case L'?':
return Usage( argv[0] );
case L'l':
case L'L':
showLocalOnly = TRUE;
break;
case L'x':
case L'X':
showDetail = FALSE;
break;
default:
break;
}
break;
default:
if( argv[arg][0] != L'\\' ) {
if( pszUserName ) return Usage( argv[0] );
pszUserName = argv[arg];
} else {
if( pszServerName ) return Usage( argv[0] );
pszServerName = argv[arg];
}
}
}
if( pszUserName ) {
do {
status = NetServerEnum( NULL, 100, (PBYTE *) &serverInfo, -1,
&entries, &totalEntries, SV_TYPE_NT,
NULL, &resumeHandle );
if( status == NERR_Success || status == ERROR_MORE_DATA ) {
for( i = 0; i < entries; i++ ) {
wprintf(L"Checking %s...", serverInfo[i].sv100_name );
fflush( stdout );
count += (int) DisplayLocalLogons( showDetail, serverInfo[i].sv100_name, pszUserName );
if( !showLocalOnly ) {
count += (int) DisplaySessionLogons( showDetail, serverInfo[i].sv100_name, pszUserName );
}
}
} else if( status != ERROR_MORE_DATA ) {
PrintWin32Error( L"Error browing network", status );
}
if( serverInfo ) {
NetApiBufferFree(serverInfo);
serverInfo = NULL;
}
} while( status == ERROR_MORE_DATA );
if( serverInfo ) {
NetApiBufferFree(serverInfo);
serverInfo = NULL;
}
if( !count && status == NERR_Success ) wprintf( L"\r%s is not logged on to any computer.\n\n", pszUserName );
} else {
//
// Display local logons
//
DisplayLocalLogons( showDetail, pszServerName, NULL );
//
// Display session logons
//
if( !showLocalOnly ) DisplaySessionLogons( showDetail, pszServerName, NULL );
}
return 0;
}