Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

429 lines
14 KiB

/****************************************************************************/
/* qidle.c */
/* */
/* QueryIdle utility source */
/* */
/* Copyright (c) 1999 Microsoft Corporation */
/****************************************************************************/
/*
* Includes
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <winsta.h>
#pragma warning (push, 4)
#include "qidle.h"
#define MAX_SERVER_NAME 120
#define MAXADDR 16 // (255.255.255.255 null-terminated)
#define MAX_SEND_STRING 64
#define MAX_OUTPUT_STRING_LENGTH 80
const int BEEP_FREQUENCY = 880;
const int BEEP_DURATION = 500;
const int SLEEP_DURATION = 30000;
#define BEEPANDDONOTHING 0
#define LOGTHEMOFF 1
#define DISCONNECTTHEM 2
#define DEFAULT_PORT "9878"
/*
* Global variables
*/
SOCKET g_sockRoboServer = INVALID_SOCKET;
HANDLE g_hServer = NULL;
BOOL g_WinSockActivated = FALSE;
char g_SendString[MAX_SEND_STRING];
int g_DoToBadSessions = BEEPANDDONOTHING;
int g_Silent = FALSE;
/*
* Private function prototypes.
*/
typedef struct _ELAPSEDTIME {
USHORT days;
USHORT hours;
USHORT minutes;
USHORT seconds;
} ELAPSEDTIME, * PELAPSEDTIME;
int GetSMCNumber(wchar_t *psSmcName);
int SendToRS(char *senddata);
LARGE_INTEGER WINAPI
CalculateDiffTime( LARGE_INTEGER FirstTime, LARGE_INTEGER SecondTime )
{
LARGE_INTEGER DiffTime;
DiffTime.QuadPart = SecondTime.QuadPart - FirstTime.QuadPart;
DiffTime.QuadPart = DiffTime.QuadPart / 10000000;
return(DiffTime);
} // end CalculateDiffTime
int OutputUsage(wchar_t *psCommand) {
WCHAR sUsageText[MAX_OUTPUT_STRING_LENGTH];
LoadString(NULL, IDS_USAGETEXT, sUsageText, MAX_OUTPUT_STRING_LENGTH);
wprintf(sUsageText, psCommand);
return 0;
}
int ConnectToRoboServer(wchar_t *psRoboServerName) {
struct addrinfo *servai;
char psRSNameA[MAX_SERVER_NAME];
WSADATA wsaData;
WORD wVersionRequested;
WCHAR sErrorText[MAX_OUTPUT_STRING_LENGTH];
// Initialize Winsock
wVersionRequested = MAKEWORD( 2, 2 );
if (WSAStartup( wVersionRequested, &wsaData ) != 0) {
LoadString(NULL, IDS_WINSOCKNOINIT, sErrorText,
MAX_OUTPUT_STRING_LENGTH);
wprintf(sErrorText);
return -1;
}
g_WinSockActivated = TRUE;
WideCharToMultiByte(CP_ACP, 0, psRoboServerName, -1, psRSNameA,
MAX_SERVER_NAME, 0, 0);
if (getaddrinfo(psRSNameA, DEFAULT_PORT, NULL, &servai) != 0) {
LoadString(NULL, IDS_UNKNOWNHOST, sErrorText,
MAX_OUTPUT_STRING_LENGTH);
wprintf(sErrorText, psRoboServerName);
return -1;
}
g_sockRoboServer = socket(servai->ai_family, SOCK_STREAM, 0);
if (g_sockRoboServer == INVALID_SOCKET) {
LoadString(NULL, IDS_SOCKETERROR, sErrorText,
MAX_OUTPUT_STRING_LENGTH);
wprintf(sErrorText);
return -1;
}
if (connect(g_sockRoboServer, servai->ai_addr, (int) servai->ai_addrlen)
!= 0) {
LoadString(NULL, IDS_CONNECTERROR, sErrorText,
MAX_OUTPUT_STRING_LENGTH);
wprintf(sErrorText);
return -1;
}
// We've connected.
return 0;
}
int HandleDeadGuy(WINSTATIONINFORMATION winfoDeadGuy) {
WCHAR sOutputText[MAX_OUTPUT_STRING_LENGTH];
switch (g_DoToBadSessions) {
case LOGTHEMOFF:
// this is where we log him off
// figure out session number
// (session number == winfoDeadGuy.LogonId)
// log off session
LoadString(NULL, IDS_LOGGINGOFFIDLE, sOutputText,
MAX_OUTPUT_STRING_LENGTH);
wprintf(sOutputText);
if (WinStationReset(g_hServer, winfoDeadGuy.LogonId, TRUE)
== FALSE) {
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0,
GetLastError(), 0, sOutputText,
MAX_OUTPUT_STRING_LENGTH, 0);
}
// inform roboserver
sprintf(g_SendString, "restart %03d", GetSMCNumber(
winfoDeadGuy.UserName));
SendToRS(g_SendString);
break;
case BEEPANDDONOTHING:
sprintf(g_SendString, "idle %03d", GetSMCNumber(
winfoDeadGuy.UserName));
SendToRS(g_SendString);
if ( !g_Silent ) {
Beep(BEEP_FREQUENCY, BEEP_DURATION);
}
break;
case DISCONNECTTHEM:
break;
}
return 0;
}
// Function to handle CTRL+C so we can exit gracefully
BOOL WINAPI CleanUpHandler(DWORD dwCtrlType) {
WCHAR sOutputString[MAX_OUTPUT_STRING_LENGTH];
// Load the correct string from the string table and output it.
switch (dwCtrlType) {
case CTRL_C_EVENT:
LoadString(NULL, IDS_TERMCTRLC, sOutputString,
MAX_OUTPUT_STRING_LENGTH);
break;
case CTRL_BREAK_EVENT:
LoadString(NULL, IDS_TERMCTRLBREAK, sOutputString,
MAX_OUTPUT_STRING_LENGTH);
break;
case CTRL_CLOSE_EVENT:
LoadString(NULL, IDS_TERMCLOSE, sOutputString,
MAX_OUTPUT_STRING_LENGTH);
break;
case CTRL_LOGOFF_EVENT:
LoadString(NULL, IDS_TERMLOGOFF, sOutputString,
MAX_OUTPUT_STRING_LENGTH);
break;
case CTRL_SHUTDOWN_EVENT:
LoadString(NULL, IDS_TERMSHUTDOWN, sOutputString,
MAX_OUTPUT_STRING_LENGTH);
break;
}
wprintf(sOutputString);
// Perform cleanup activity
WinStationCloseServer(g_hServer);
if (g_WinSockActivated == TRUE)
WSACleanup();
ExitProcess(0);
return TRUE;
}
int __cdecl
wmain( int argc, wchar_t *argv[ ] )
{
PLOGONID pLogonId;
ULONG Entries;
ULONG ReturnLength;
WINSTATIONINFORMATION WSInformation;
WINSTATIONCLIENT WSClient;
SYSTEMTIME currloctime;
int numUsers;
int numOtherUsers;
ULONG i;
WCHAR sOutputString[MAX_OUTPUT_STRING_LENGTH];
WCHAR sIdleOutputString1[MAX_OUTPUT_STRING_LENGTH];
WCHAR sIdleOutputString2[MAX_OUTPUT_STRING_LENGTH];
WCHAR sDisconnectedOutputString[MAX_OUTPUT_STRING_LENGTH];
WCHAR sSummaryString[MAX_OUTPUT_STRING_LENGTH];
if ((argc < 2) || (argc > 4)) {
OutputUsage(argv[0]);
return -1;
}
if (wcscmp(argv[1], L"/?") == 0) {
OutputUsage(argv[0]);
return -1;
}
if ( argc > 2 ) {
if ( !wcscmp(argv[2], L"/s") || (argc > 3 && !wcscmp(argv[3], L"/s")) ) {
g_Silent = TRUE;
}
else {
OutputUsage(argv[0]);
return -1;
}
}
if (SetConsoleCtrlHandler(CleanUpHandler, TRUE) == 0) {
LoadString(NULL, IDS_CANTDOCTRLC, sOutputString,
MAX_OUTPUT_STRING_LENGTH);
wprintf(sOutputString);
return -1;
}
LoadString(NULL, IDS_TITLE_TEXT, sOutputString, MAX_OUTPUT_STRING_LENGTH);
wprintf(sOutputString);
g_hServer = WinStationOpenServer(argv[1]);
if (g_hServer == NULL) {
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0,
GetLastError(), 0, sOutputString,
MAX_OUTPUT_STRING_LENGTH, 0);
LoadString(NULL, IDS_ERROROPENINGSERVER, sOutputString,
MAX_OUTPUT_STRING_LENGTH);
wprintf(sOutputString, argv[1]);
return -1;
}
if (argc > 2) {
if (wcsncmp(argv[2], L"/r:", 3) == 0) {
if (ConnectToRoboServer(&(argv[2])[3]) == 0) {
g_DoToBadSessions = BEEPANDDONOTHING;
} else {
LoadString(NULL, IDS_ROBOSRVCONNECTERROR, sOutputString,
MAX_OUTPUT_STRING_LENGTH);
wprintf(sOutputString, &(argv[2])[3]);
}
}
}
LoadString(NULL, IDS_IDLESESSIONLINE1, sIdleOutputString1,
MAX_OUTPUT_STRING_LENGTH);
LoadString(NULL, IDS_IDLESESSIONLINE2, sIdleOutputString2,
MAX_OUTPUT_STRING_LENGTH);
LoadString(NULL, IDS_DISCONNECTED, sDisconnectedOutputString,
MAX_OUTPUT_STRING_LENGTH);
LoadString(NULL, IDS_SUMMARY, sSummaryString,
MAX_OUTPUT_STRING_LENGTH);
for ( ; ; ) {
#define MAX_DATE_STR_LEN 80
#define MAX_TIME_STR_LEN 80
WCHAR psDateStr[MAX_DATE_STR_LEN];
WCHAR psTimeStr[MAX_TIME_STR_LEN];
// Display the current time
GetLocalTime(&currloctime);
GetDateFormat(0, 0, &currloctime, NULL, psDateStr, MAX_DATE_STR_LEN);
GetTimeFormat(0, 0, &currloctime, NULL, psTimeStr, MAX_TIME_STR_LEN);
wprintf(L"%s %s\n", psDateStr, psTimeStr);
numUsers = 0;
numOtherUsers = 0;
if (WinStationEnumerate(g_hServer, &pLogonId, &Entries) == FALSE) {
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0,
GetLastError(), 0, sOutputString,
MAX_OUTPUT_STRING_LENGTH, 0);
break;
}
for (i = 0; i < Entries; i++) {
LARGE_INTEGER DiffTime;
LONG d_time;
ELAPSEDTIME IdleTime;
BOOLEAN bRetVal;
bRetVal = WinStationQueryInformation(g_hServer,
pLogonId[i].LogonId, WinStationInformation,
&WSInformation, sizeof(WSInformation), &ReturnLength);
if (bRetVal == FALSE) {
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0,
GetLastError(), 0, sOutputString,
MAX_OUTPUT_STRING_LENGTH, 0);
continue;
}
DiffTime = CalculateDiffTime(WSInformation.LastInputTime,
WSInformation.CurrentTime);
d_time = DiffTime.LowPart;
// Calculate the days, hours, minutes, seconds since specified
// time.
IdleTime.days = (USHORT)(d_time / 86400L); // days since
d_time = d_time % 86400L; // seconds => partial
// day
IdleTime.hours = (USHORT)(d_time / 3600L); // hours since
d_time = d_time % 3600L; // seconds => partial
// hour
IdleTime.minutes = (USHORT)(d_time / 60L); // minutes since
IdleTime.seconds = (USHORT)(d_time % 60L);// seconds remaining
if (WSInformation.ConnectState == State_Active) {
if (WinStationQueryInformationW(g_hServer, pLogonId[i].LogonId,
WinStationClient,
&WSClient, sizeof(WSClient), &ReturnLength) != FALSE) {
// 2 or more minutes == bad
if ((IdleTime.minutes > 1) || (IdleTime.hours > 0) ||
(IdleTime.days > 0)) {
// sIdleOutputString1, loaded above, is the first part of
// the format string. sIdleOutputString2, also loaded
// above, is the second part.
wprintf(sIdleOutputString1, WSInformation.
UserName, WSInformation.LogonId, WSClient.
ClientName);
wprintf(sIdleOutputString2, IdleTime.days,
IdleTime.hours, IdleTime.minutes);
if (wcsstr(WSInformation.UserName, L"smc") != 0)
HandleDeadGuy(WSInformation);
}
{
WCHAR *pPrefix = wcsstr(WSInformation.UserName, L"smc");
if ( pPrefix != NULL ) {
int index = wcstoul(pPrefix + 3, NULL, 10);
if ( index >= 1 &&
index <= 500 ) {
numUsers++;
} else {
numOtherUsers++;
}
}
}
} else {
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0,
GetLastError(), 0, sOutputString,
MAX_OUTPUT_STRING_LENGTH, 0);
wprintf(sOutputString);
}
} else if (WSInformation.ConnectState == State_Disconnected) {
wprintf(sDisconnectedOutputString, WSInformation.
UserName, WSInformation.LogonId);
}
}
wprintf(sSummaryString, numUsers, numOtherUsers);
// Sleep for a while
Sleep(SLEEP_DURATION);
wprintf(L"\n");
}
// In case an error broke out of the loop
GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, GetCurrentProcessId());
// required to shut the dumb ia64 compiler up--will not get here
return 0;
} /* main() */
// from a username of the format "smcxxx," where xxx is a three-digit
// 0-padded base 10 number, returns the number or -1 on error
int GetSMCNumber(wchar_t *psSmcName) {
return _wtoi(&psSmcName[3]);
}
// sends the data in senddata to the RoboServer connection. Returns
// SOCKET_ERROR on error, or the total number of bytes sent on success
int SendToRS(char *senddata) {
if (senddata != 0)
return send(g_sockRoboServer, senddata, (int) strlen(senddata) + 1, 0);
else
return SOCKET_ERROR;
}
#pragma warning (pop)