//Copyright (c) 1998 - 1999 Microsoft Corporation /****************************************************************************** * * QUSER.C * * query user information * * *******************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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() */