windows-nt/Source/XPSP1/NT/termsrv/admtools/quser/quser.c
2020-09-26 16:20:57 +08:00

491 lines
13 KiB
C

//Copyright (c) 1998 - 1999 Microsoft Corporation
/******************************************************************************
*
* QUSER.C
*
* query user information
*
*
*******************************************************************************/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <winstaw.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <utilsub.h>
#include <process.h>
#include <string.h>
#include <malloc.h>
#include <locale.h>
#include <printfoa.h>
#include "quser.h"
HANDLE hServerName = SERVERNAME_CURRENT;
WCHAR ServerName[MAX_IDS_LEN+1];
WCHAR user_string[MAX_IDS_LEN+1];
USHORT help_flag = FALSE;
ULONG CurrentLogonId = (ULONG) -1;
BOOLEAN MatchedOne = FALSE;
TOKMAP ptm[] = {
{L" ", TMFLAG_OPTIONAL, TMFORM_STRING, MAX_IDS_LEN, user_string},
{L"/server", TMFLAG_OPTIONAL, TMFORM_STRING, MAX_IDS_LEN, ServerName},
{L"/?", TMFLAG_OPTIONAL, TMFORM_BOOLEAN,sizeof(USHORT), &help_flag},
{0, 0, 0, 0, 0}
};
/*
* Local function prototypes.
*/
void DisplayLastInputTime( LARGE_INTEGER * pCurrentTime, LARGE_INTEGER * pTime );
void DisplayUserInfo( HANDLE hServer , PLOGONID pId, PWCHAR pMatchName );
void Usage( BOOLEAN bError );
/*******************************************************************************
*
* main
*
******************************************************************************/
int __cdecl
main(INT argc, CHAR **argv)
{
PLOGONID pLogonId;
UINT TermCount;
ULONG Status;
ULONG rc;
WCHAR **argvW;
int i;
setlocale(LC_ALL, ".OCP");
/*
* Massage the command line.
*/
argvW = MassageCommandLine((DWORD)argc);
if (argvW == NULL) {
ErrorPrintf(IDS_ERROR_MALLOC);
return(FAILURE);
}
/*
* parse the cmd line without parsing the program name (argc-1, argv+1)
*/
rc = ParseCommandLine(argc-1, argvW+1, ptm, 0);
/*
* Check for error from ParseCommandLine
*/
if ( help_flag || (rc && !(rc & PARSE_FLAG_NO_PARMS)) ) {
if ( !help_flag ) {
Usage(TRUE);
return(FAILURE);
} else {
Usage(FALSE);
return(SUCCESS);
}
}
// If no remote server was specified, then check if we are running under Terminal Server
if ((!IsTokenPresent(ptm, L"/server") ) && (!AreWeRunningTerminalServices()))
{
ErrorPrintf(IDS_ERROR_NOT_TS);
return(FAILURE);
}
/*
* Open the specified server
*/
if( ServerName[0] ) {
hServerName = WinStationOpenServer( ServerName );
if( hServerName == NULL ) {
StringErrorPrintf(IDS_ERROR_SERVER,ServerName);
PutStdErr( GetLastError(), 0 );
return(FAILURE);
}
}
/*
* if no user input, then default to all usernames on system
*/
if ( !(*user_string) )
wcscpy( user_string, L"*" );
/*
* Get current LogonId
*/
CurrentLogonId = GetCurrentLogonId();
/*
* Get list of active WinStations & display user info.
*/
if ( WinStationEnumerate( hServerName, &pLogonId, &TermCount) ) {
for ( i=0; i< (int)TermCount; i++ )
DisplayUserInfo( hServerName , &pLogonId[i], user_string );
WinStationFreeMemory(pLogonId);
} else {
Status = GetLastError();
ErrorPrintf(IDS_ERROR_WINSTATION_ENUMERATE, Status);
PutStdErr( Status, 0 );
return(FAILURE);
}
/*
* Check for at least one match
*/
if ( !MatchedOne ) {
StringErrorPrintf(IDS_ERROR_USER_NOT_FOUND, user_string);
return(FAILURE);
}
return(SUCCESS);
}
/*******************************************************************************
*
* DisplayTime
*
* This routine displays time
*
*
* ENTRY:
* pTime (input)
* pointer to system time
*
* EXIT:
* nothing
*
******************************************************************************/
void
DisplayTime( LARGE_INTEGER * pTime )
{
FILETIME LocalTime;
SYSTEMTIME stime;
LPTSTR lpTimeStr;
int nLen;
TCHAR TimeString[MAX_DATE_TIME_LENGTH];
if ( FileTimeToLocalFileTime( (FILETIME*)pTime, &LocalTime ) &&
FileTimeToSystemTime( &LocalTime, &stime ) ) {
//NBD
// wprintf( L"%02d/%02d/%02d %02d:%02d",
// stime.wMonth, stime.wDay, stime.wYear % 100,
// stime.wHour, stime.wMinute );
//
//Get DateFormat
nLen = GetDateFormat(
LOCALE_USER_DEFAULT,
DATE_SHORTDATE,
&stime,
NULL,
NULL,
0);
if (nLen == 0)
{
goto unknowntime;
}
lpTimeStr = (LPTSTR) GlobalAlloc(GPTR, (nLen + 1) * sizeof(TCHAR));
if (lpTimeStr == NULL)
{
goto unknowntime;
}
nLen = GetDateFormat(
LOCALE_USER_DEFAULT,
DATE_SHORTDATE,
&stime,
NULL,
lpTimeStr,
nLen);
if (nLen == 0)
{
goto unknowntime;
}
wcscpy(TimeString, lpTimeStr);
wcscat(TimeString, L" ");
GlobalFree(lpTimeStr);
//Get Time Format
nLen = GetTimeFormat(
LOCALE_USER_DEFAULT,
TIME_NOSECONDS,
&stime,
NULL,
NULL,
0);
if (nLen == 0)
{
goto unknowntime;
}
lpTimeStr = (LPTSTR) GlobalAlloc(GPTR, (nLen + 1) * sizeof(TCHAR));
if (lpTimeStr == NULL)
{
goto unknowntime;
}
nLen = GetTimeFormat(
LOCALE_USER_DEFAULT,
TIME_NOSECONDS,
&stime,
NULL,
lpTimeStr,
nLen);
if (nLen == 0)
{
goto unknowntime;
}
wcscat(TimeString, lpTimeStr);
GlobalFree(lpTimeStr);
wprintf(TimeString );
return;
unknowntime:
// Use a localized "unknown" string if at all possible
wprintf(GetUnknownString() ? GetUnknownString() : L"Unknown");
return;
}
} /* DisplayTime() */
/*******************************************************************************
*
* DisplayLastInputTime
*
* This routine displays the time of last terminal input
*
*
* ENTRY:
* pCurrentTime
* pointer to current system time
* pTime (input)
* pointer to system time of last input
*
* EXIT:
* nothing
*
******************************************************************************/
void
DisplayLastInputTime( LARGE_INTEGER * pCurrentTime, LARGE_INTEGER * pTime )
{
LARGE_INTEGER InputTime;
LARGE_INTEGER CurrentTime;
LARGE_INTEGER DiffTime;
ULONG d_time;
ULONG minutes;
ULONG hours;
ULONG days;
WCHAR buf[40];
if ( (pTime->HighPart == 0 && pTime->LowPart == 0 ) ||
(pCurrentTime->HighPart == 0 && pCurrentTime->LowPart == 0 ) ) {
goto badtime;
}
/*
* Get the number of seconds since last input
*/
DiffTime = RtlLargeIntegerSubtract( *pCurrentTime, *pTime );
DiffTime = RtlExtendedLargeIntegerDivide( DiffTime, 10000000, NULL );
d_time = DiffTime.LowPart;
/*
* Get the number of 'days:hours:minutes' since last input
*/
days = (USHORT)(d_time / 86400L); // days since last input
d_time = d_time % 86400L; // seconds into partial day
hours = (USHORT)(d_time / 3600L); // hours since last input
d_time = d_time % 3600L; // seconds into partial hour
minutes = (USHORT)(d_time / 60L); // minutes since last input
/*
* Output
*/
if ( days > 0 )
wsprintf( buf, L"%u+%02u:%02u", days, hours, minutes );
else if ( hours > 0 )
wsprintf( buf, L"%u:%02u", hours, minutes );
else if ( minutes > 0 )
wsprintf( buf, L"%u", minutes );
else
wsprintf( buf, L"." );
wprintf( L"%9s ", buf );
return;
/*
* error returns
*/
badtime:
if (LoadString(NULL, IDS_NONE, buf, sizeof(buf) / sizeof( WCHAR ) ) != 0)
{
wprintf(buf);
}
else
{
wprintf( L" none " );
}
} /* DisplayLastInputTime() */
/*******************************************************************************
*
* DisplayUserInfo
*
* This routine displays user information for one user
*
*
* ENTRY:
* hServer ( input )
* handle to termsrv
* LogonId (input)
* window station id
* pUsername (input)
* user name to display (or winstation name)
*
* EXIT:
* nothing
*
******************************************************************************/
void
DisplayUserInfo( HANDLE hServer , PLOGONID pId, PWCHAR pMatchName )
{
WINSTATIONINFORMATION Info;
ULONG Length;
ULONG LogonId;
LogonId = pId->LogonId;
if( WinStationObjectMatch( hServer, pId, pMatchName ) ) {
/*
* Query information
*/
if ( !WinStationQueryInformation( hServer,
LogonId,
WinStationInformation,
&Info,
sizeof(Info),
&Length ) ) {
goto done;
}
if ( Info.UserName[0] == UNICODE_NULL )
goto done;
TruncateString( _wcslwr(Info.UserName), 20 );
TruncateString( _wcslwr(Info.WinStationName), 15 );
/*
* If first time - output title
*/
if ( !MatchedOne ) {
Message(IDS_TITLE);
MatchedOne = TRUE;
}
/* output current */
if ( (hServer == SERVERNAME_CURRENT) && (Info.LogonId == CurrentLogonId ) )
wprintf( L">" );
else
wprintf( L" " );
{
#define MAX_PRINTFOA_BUFFER_SIZE 1024
char pUserName[MAX_PRINTFOA_BUFFER_SIZE];
char pWinStationName[MAX_PRINTFOA_BUFFER_SIZE];
char pConnectState[MAX_PRINTFOA_BUFFER_SIZE];
WideCharToMultiByte(CP_OEMCP, 0,
Info.UserName, -1,
pUserName, sizeof(pUserName),
NULL, NULL);
WideCharToMultiByte(CP_OEMCP, 0,
Info.WinStationName, -1,
pWinStationName, sizeof(pWinStationName),
NULL, NULL);
WideCharToMultiByte(CP_OEMCP, 0,
StrConnectState(Info.ConnectState, TRUE), -1,
pConnectState, sizeof(pConnectState),
NULL, NULL);
fprintf( stdout,"%-20s %-15s ", pUserName,
(Info.ConnectState == State_Disconnected) ?
"" : pWinStationName );
fprintf( stdout,"%4u %-6s ", Info.LogonId, pConnectState );
}
DisplayLastInputTime( &Info.CurrentTime, &Info.LastInputTime );
DisplayTime( &Info.LogonTime );
wprintf( L"\n" );
}
done:
return;
} /* DisplayUserInfo() */
/*******************************************************************************
*
* Usage
*
* Output the usage message for this utility.
*
* ENTRY:
* bError (input)
* TRUE if the 'invalid parameter(s)' message should preceed the usage
* message and the output go to stderr; FALSE for no such error
* string and output goes to stdout.
*
* EXIT:
*
*
******************************************************************************/
void
Usage( BOOLEAN bError )
{
if ( bError ) {
ErrorPrintf(IDS_ERROR_INVALID_PARAMETERS);
ErrorPrintf(IDS_HELP_USAGE1);
ErrorPrintf(IDS_HELP_USAGE2);
ErrorPrintf(IDS_HELP_USAGE3);
ErrorPrintf(IDS_HELP_USAGE4);
ErrorPrintf(IDS_HELP_USAGE5);
ErrorPrintf(IDS_HELP_USAGE6);
} else {
Message(IDS_HELP_USAGE1);
Message(IDS_HELP_USAGE2);
Message(IDS_HELP_USAGE3);
Message(IDS_HELP_USAGE4);
Message(IDS_HELP_USAGE5);
Message(IDS_HELP_USAGE6);
}
} /* Usage() */