windows-nt/Source/XPSP1/NT/base/remoteboot/rcc/serial/main.c

1497 lines
41 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/****************************************************************************
Copyright (c) Microsoft Corporation 1997
All rights reserved
***************************************************************************/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <winsock2.h>
#include <ntexapi.h>
#include <devioctl.h>
#include <stdlib.h>
#include <rccxport.h>
#include "rcclib.h"
#include "error.h"
ULONG GlobalBufferCurrentSize;
char *GlobalBuffer = NULL;
ULONG GlobalCommandLineSize;
char *GlobalCommandLine = NULL;
ULONG GlobalReadIndex;
BOOL GlobalPagingNeeded = TRUE;
BOOL GlobalDoThreads = TRUE;
UCHAR *StateTable[] = {
"Initialized",
"Ready",
"Running",
"Standby",
"Terminated",
"Wait:",
"Transition",
"Unknown",
"Unknown",
"Unknown",
"Unknown",
"Unknown"
};
UCHAR *WaitTable[] = {
"Executive",
"FreePage",
"PageIn",
"PoolAllocation",
"DelayExecution",
"Suspended",
"UserRequest",
"Executive",
"FreePage",
"PageIn",
"PoolAllocation",
"DelayExecution",
"Suspended",
"UserRequest",
"EventPairHigh",
"EventPairLow",
"LpcReceive",
"LpcReply",
"VirtualMemory",
"PageOut",
"Spare1",
"Spare2",
"Spare3",
"Spare4",
"Spare5",
"Spare6",
"Spare7",
"Unknown",
"Unknown",
"Unknown"
};
UCHAR *Empty = " ";
DWORD
RCCSrvReportEventA(
DWORD EventID,
DWORD EventType,
DWORD NumStrings,
DWORD DataLength,
LPSTR *Strings,
LPVOID Data
);
DWORD
RCCSrvGetCommandLine(
IN HANDLE ComPortHandle,
OUT PBOOL ControlC
);
DWORD
RCCSrvPrintMsg(
IN HANDLE ComPortHandle,
IN DWORD MessageId,
IN DWORD SystemErrorCode
);
DWORD
RCCSrvPrint(
IN HANDLE ComPortHandle,
IN PUCHAR Buffer,
IN DWORD BufferSize
);
VOID
RCCSrvPrintTListInfo(
IN HANDLE ComPortHandle,
IN PRCC_RSP_TLIST Buffer
);
VOID
RCCSrvPutMore(
IN HANDLE ComPortHandle,
OUT PBOOL ControlC
);
BOOL
AreYouSure(
IN HANDLE ComPortHandle
);
//
//
// Main routine
//
//
int
__cdecl
main(
int argc,
char *argv[]
)
{
NTSTATUS Status;
HANDLE ComPortHandle;
HANDLE RCCHandle = NULL;
DWORD Error;
DWORD BytesReturned;
DWORD ProcessId;
DWORD PrintMessage = 0;
char *NewBuffer;
DWORD ThisProcessId;
DWORD MemoryLimit;
DWORD DataLength;
PUCHAR ComPort;
DCB Dcb;
char *pch;
char *pTemp;
char Command;
BOOL Abort;
STRING String1, String2;
//
// Init the library
//
Error = RCCLibInit(&GlobalBuffer, &GlobalBufferCurrentSize);
if (Error != ERROR_SUCCESS) {
PrintMessage = ERROR_RCCSRV_LIB_INIT_FAILED;
goto Exit;
}
//
// Check for arguments
//
if ((argc > 3) ||
((argc > 1) && ((argv[1][0] == '-') || (argv[1][0] == '/')))) {
PrintMessage = MSG_RCCSRV_USAGE;
goto Exit;
}
//
// Allocate memory for the command line
//
GlobalCommandLine = VirtualAlloc(NULL,
80 * sizeof(char),
MEM_COMMIT,
PAGE_READWRITE | PAGE_NOCACHE
);
if (GlobalCommandLine == NULL) {
//
// Log an error!
//
RCCSrvReportEventA(ERROR_RCCSRV_INITIAL_ALLOC_FAILED,
EVENTLOG_ERROR_TYPE,
0,
0,
NULL,
NULL
);
PrintMessage = MSG_RCCSRV_GENERAL_FAILURE;
goto Exit;
}
GlobalCommandLineSize = 80 * sizeof(char);
//
// Remember our process ID, so people cannot kill us.
//
ThisProcessId = GetCurrentProcessId();
//
// Open the Remote Command Console driver
//
RCCHandle = CreateFile("\\\\.\\RCC",
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING, // create disposition.
0,
0
);
if (RCCHandle == INVALID_HANDLE_VALUE) {
RCCHandle = NULL;
Error = GetLastError();
RCCSrvReportEventA(ERROR_RCCSRV_OPEN_RCCDRIVER_FAILED,
EVENTLOG_ERROR_TYPE,
0,
0,
NULL,
NULL
);
}
//
// Open the serial port
//
if (argc > 1) {
ComPort = argv[1];
} else {
ComPort = "COM1";
}
ComPortHandle = CreateFile(ComPort,
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
0,
NULL,
OPEN_EXISTING, // create disposition.
0,
0
);
if (ComPortHandle == INVALID_HANDLE_VALUE) {
//
// Log an error!
//
Error = GetLastError();
RCCSrvReportEventA(ERROR_RCCSRV_OPEN_COMPORT_FAILED,
EVENTLOG_ERROR_TYPE,
0,
0,
NULL,
NULL
);
PrintMessage = MSG_RCCSRV_GENERAL_FAILURE;
goto Exit;
}
//
// Set the serial port line characteristics
//
Dcb.DCBlength = sizeof(DCB);
if (!GetCommState(ComPortHandle, &Dcb)) {
//
// Log an error!
//
Error = GetLastError();
RCCSrvReportEventA(ERROR_RCCSRV_OPEN_COMPORT_FAILED,
EVENTLOG_ERROR_TYPE,
0,
0,
NULL,
NULL
);
PrintMessage = MSG_RCCSRV_GENERAL_FAILURE;
goto Exit;
}
if (argc > 2) {
Dcb.BaudRate = atoi(argv[2]);
} else {
Dcb.BaudRate = 9600;
}
Dcb.ByteSize = 8;
Dcb.Parity = NOPARITY;
Dcb.StopBits = ONESTOPBIT;
if (!SetCommState(ComPortHandle, &Dcb)) {
//
// Log an error!
//
Error = GetLastError();
RCCSrvReportEventA(ERROR_RCCSRV_OPEN_COMPORT_FAILED,
EVENTLOG_ERROR_TYPE,
0,
0,
NULL,
NULL
);
PrintMessage = MSG_RCCSRV_GENERAL_FAILURE;
goto Exit;
}
while (1) {
//
// Write the prompt
//
Error = RCCSrvPrintMsg(ComPortHandle, MSG_RCCSRV_PROMPT, 0);
if (Error != ERROR_SUCCESS) {
RCCSrvReportEventA(ERROR_RCCSRV_SEND_FAILED,
EVENTLOG_ERROR_TYPE,
0,
sizeof(DWORD),
NULL,
&Error
);
goto Exit;
}
//
// Get any response.
//
Error = RCCSrvGetCommandLine(ComPortHandle, &Abort);
if (Error != ERROR_SUCCESS) {
RCCSrvReportEventA(ERROR_RCCSRV_RCV_FAILED,
EVENTLOG_ERROR_TYPE,
0,
sizeof(DWORD),
NULL,
&Error
);
goto Exit;
}
if (Abort) {
continue;
}
//
// It completed, so we have data in the buffer - verify it and process the message.
//
pch = GlobalCommandLine;
while (((*pch == ' ') || (*pch == '\t')) &&
(pch < (GlobalCommandLine + GlobalCommandLineSize))) {
pch++;
}
if (pch >= (GlobalCommandLine + GlobalCommandLineSize)) {
continue;
}
Command = *pch;
switch (Command) {
case 'c':
case 'C':
//
// Compare the command
//
pTemp = pch;
while ((*pch != '\0') && (*pch != ' ') &&
(pch < (GlobalCommandLine + GlobalCommandLineSize))) {
pch++;
}
if (pch >= (GlobalCommandLine + GlobalCommandLineSize)) {
continue;
}
*pch = '\0';
RtlInitString(&String1, "crashdump");
RtlInitString(&String2, pTemp);
if (!RtlEqualString(&String1, &String2, TRUE)) {
RCCSrvPrintMsg(ComPortHandle, MSG_RCCSRV_HELP, 0);
continue;
}
if (RCCHandle == NULL) {
RCCSrvPrintMsg(ComPortHandle, ERROR_RCCSRV_OPEN_RCCDRIVER_FAILED, 0);
} else {
//
// Send back an acknowledgement that we got the command before starting the crash.
//
if (AreYouSure(ComPortHandle)) {
RCCSrvPrintMsg(ComPortHandle, MSG_RCCSRV_CRASHING, 0);
if (!DeviceIoControl(RCCHandle,
CTL_CODE(FILE_DEVICE_NETWORK, 0x3, METHOD_NEITHER, FILE_ANY_ACCESS),
NULL,
0,
NULL,
0,
&BytesReturned,
NULL
)) {
RCCSrvPrintMsg(ComPortHandle, ERROR_RCCSRV_CRASH_FAILED, 0);
}
}
}
break;
case 'f':
case 'F':
//
// Toggle paging
//
GlobalDoThreads = !GlobalDoThreads;
if (GlobalDoThreads) {
RCCSrvPrintMsg(ComPortHandle, MSG_RCCSRV_THREADS_ENABLED, 0);
} else {
RCCSrvPrintMsg(ComPortHandle, MSG_RCCSRV_THREADS_DISABLED, 0);
}
break;
case 'k':
case 'K':
//
// Skip to next argument (process id)
//
while ((*pch != ' ') &&
(pch < (GlobalCommandLine + GlobalCommandLineSize))) {
pch++;
}
if (pch >= (GlobalCommandLine + GlobalCommandLineSize)) {
continue;
}
while ((*pch == ' ') &&
(pch < (GlobalCommandLine + GlobalCommandLineSize))) {
pch++;
}
if (pch >= (GlobalCommandLine + GlobalCommandLineSize)) {
continue;
}
ProcessId = atoi(pch);
if (ProcessId != ThisProcessId) {
Error = RCCLibKillProcess(ProcessId);
} else {
Error = ERROR_INVALID_PARAMETER;
}
if (Error == ERROR_SUCCESS) {
RCCSrvPrintMsg(ComPortHandle, MSG_RCCSRV_RESULT_SUCCESS, 0);
} else {
RCCSrvPrintMsg(ComPortHandle, MSG_RCCSRV_RESULT_FAILURE, Error);
}
break;
case 'l':
case 'L':
//
// Skip to next argument (process id)
//
while ((*pch != ' ') &&
(pch < (GlobalCommandLine + GlobalCommandLineSize))) {
pch++;
}
if (pch >= (GlobalCommandLine + GlobalCommandLineSize)) {
continue;
}
while ((*pch == ' ') &&
(pch < (GlobalCommandLine + GlobalCommandLineSize))) {
pch++;
}
if (pch >= (GlobalCommandLine + GlobalCommandLineSize)) {
continue;
}
ProcessId = atoi(pch);
if (ProcessId != ThisProcessId) {
Error = RCCLibLowerProcessPriority(ProcessId);
} else {
Error = ERROR_INVALID_PARAMETER;
}
if (Error == ERROR_SUCCESS) {
RCCSrvPrintMsg(ComPortHandle, MSG_RCCSRV_RESULT_SUCCESS, 0);
} else {
RCCSrvPrintMsg(ComPortHandle, MSG_RCCSRV_RESULT_FAILURE, Error);
}
break;
case 'm':
case 'M':
//
// Skip to next argument (process id)
//
while ((*pch != ' ') &&
(pch < (GlobalCommandLine + GlobalCommandLineSize))) {
pch++;
}
if (pch >= (GlobalCommandLine + GlobalCommandLineSize)) {
continue;
}
while ((*pch == ' ') &&
(pch < (GlobalCommandLine + GlobalCommandLineSize))) {
pch++;
}
if (pch >= (GlobalCommandLine + GlobalCommandLineSize)) {
continue;
}
ProcessId = atoi(pch);
//
// Skip to next argument (kb-allowed)
//
while ((*pch != ' ') &&
(pch < (GlobalCommandLine + GlobalCommandLineSize))) {
pch++;
}
if (pch >= (GlobalCommandLine + GlobalCommandLineSize)) {
continue;
}
while ((*pch == ' ') &&
(pch < (GlobalCommandLine + GlobalCommandLineSize))) {
pch++;
}
if (pch >= (GlobalCommandLine + GlobalCommandLineSize)) {
continue;
}
MemoryLimit = atoi(pch);
if (ProcessId != ThisProcessId) {
Error = RCCLibLimitProcessMemory(ProcessId, MemoryLimit);
} else {
Error = ERROR_INVALID_PARAMETER;
}
if (Error == ERROR_SUCCESS) {
RCCSrvPrintMsg(ComPortHandle, MSG_RCCSRV_RESULT_SUCCESS, 0);
} else {
RCCSrvPrintMsg(ComPortHandle, MSG_RCCSRV_RESULT_FAILURE, Error);
}
break;
case 'p':
case 'P':
//
// Toggle paging
//
GlobalPagingNeeded = !GlobalPagingNeeded;
if (GlobalPagingNeeded) {
RCCSrvPrintMsg(ComPortHandle, MSG_RCCSRV_PAGING_ENABLED, 0);
} else {
RCCSrvPrintMsg(ComPortHandle, MSG_RCCSRV_PAGING_DISABLED, 0);
}
break;
case 'r':
case 'R':
//
// Compare the command
//
pTemp = pch;
while ((*pch != '\0') && (*pch != ' ') &&
(pch < (GlobalCommandLine + GlobalCommandLineSize))) {
pch++;
}
if (pch >= (GlobalCommandLine + GlobalCommandLineSize)) {
continue;
}
*pch = '\0';
RtlInitString(&String1, "reboot");
RtlInitString(&String2, pTemp);
if (!RtlEqualString(&String1, &String2, TRUE)) {
RCCSrvPrintMsg(ComPortHandle, MSG_RCCSRV_HELP, 0);
continue;
}
//
// Send back an acknowledgement that we got the command before starting the reboot.
//
if (AreYouSure(ComPortHandle)) {
RCCSrvPrintMsg(ComPortHandle, MSG_RCCSRV_SHUTTING_DOWN, 0);
NtShutdownSystem(ShutdownReboot);
}
break;
case 's':
case 'S':
//
// Compare the command
//
RtlInitString(&String1, "shutdown");
pTemp = pch;
while ((*pch != '\0') && (*pch != ' ') &&
(pch < (GlobalCommandLine + GlobalCommandLineSize))) {
pch++;
}
if (pch >= (GlobalCommandLine + GlobalCommandLineSize)) {
continue;
}
*pch = '\0';
RtlInitString(&String2, pTemp);
if (!RtlEqualString(&String1, &String2, TRUE)) {
RCCSrvPrintMsg(ComPortHandle, MSG_RCCSRV_HELP, 0);
continue;
}
//
// Send back an acknowledgement that we got the command before starting the reboot.
//
if (AreYouSure(ComPortHandle)) {
RCCSrvPrintMsg(ComPortHandle, MSG_RCCSRV_SHUTTING_DOWN, 0);
NtShutdownSystem(ShutdownNoReboot);
}
break;
case 't':
case 'T':
RetryTList:
Error = RCCLibGetTListInfo((PRCC_RSP_TLIST)GlobalBuffer,
(LONG)GlobalBufferCurrentSize,
&DataLength
);
//
// Try to get more memory, if not available, then just fail without out of memory error.
//
if (Error == ERROR_OUTOFMEMORY) {
Error = RCCLibIncreaseMemory(&GlobalBuffer, &GlobalBufferCurrentSize);
if (Error == ERROR_SUCCESS) {
goto RetryTList;
}
RCCSrvPrintMsg(ComPortHandle, MSG_RCCSRV_OUT_OF_MEMORY, 0);
break;
}
RCCSrvPrintTListInfo(ComPortHandle, (PRCC_RSP_TLIST)GlobalBuffer);
break;
//
// Help
//
case '?':
RCCSrvPrintMsg(ComPortHandle, MSG_RCCSRV_HELP, 0);
break;
default:
RCCSrvPrintMsg(ComPortHandle, MSG_RCCSRV_INVALID_COMMAND, 0);
break;
}
}
Exit:
if (PrintMessage != 0) {
BytesReturned = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_HMODULE |
FORMAT_MESSAGE_ARGUMENT_ARRAY,
NULL,
PrintMessage,
0,
(LPTSTR)&NewBuffer,
0,
(va_list *)&Error
);
if (BytesReturned != 0) {
printf(NewBuffer);
LocalFree(NewBuffer);
}
}
RCCLibExit(GlobalBuffer, GlobalBufferCurrentSize);
if (GlobalCommandLine != NULL) {
VirtualFree(GlobalCommandLine, GlobalCommandLineSize, MEM_DECOMMIT);
}
if (RCCHandle != NULL) {
NtClose(RCCHandle);
}
return 0;
}
DWORD
RCCSrvReportEventA(
DWORD EventID,
DWORD EventType,
DWORD NumStrings,
DWORD DataLength,
LPSTR *Strings,
LPVOID Data
)
/*++
Routine Description:
This function writes the specified (EventID) log at the end of the
eventlog.
Arguments:
EventID - The specific event identifier. This identifies the
message that goes with this event.
EventType - Specifies the type of event being logged. This
parameter can have one of the following
values:
Value Meaning
EVENTLOG_ERROR_TYPE Error event
EVENTLOG_WARNING_TYPE Warning event
EVENTLOG_INFORMATION_TYPE Information event
NumStrings - Specifies the number of strings that are in the array
at 'Strings'. A value of zero indicates no strings
are present.
DataLength - Specifies the number of bytes of event-specific raw
(binary) data to write to the log. If cbData is
zero, no event-specific data is present.
Strings - Points to a buffer containing an array of null-terminated
strings that are merged into the message before
displaying to the user. This parameter must be a valid
pointer (or NULL), even if cStrings is zero.
Data - Buffer containing the raw data. This parameter must be a
valid pointer (or NULL), even if cbData is zero.
Return Value:
Returns the WIN32 extended error obtained by GetLastError().
NOTE : This function works slow since it calls the open and close
eventlog source everytime.
--*/
{
HANDLE EventlogHandle;
DWORD ReturnCode;
//
// open eventlog section.
//
EventlogHandle = RegisterEventSourceW(NULL, L"RCCSer");
if (EventlogHandle == NULL) {
ReturnCode = GetLastError();
goto Cleanup;
}
//
// Log the error code specified
//
if(!ReportEventA(EventlogHandle,
(WORD)EventType,
0, // event category
EventID,
NULL,
(WORD)NumStrings,
DataLength,
Strings,
Data
)) {
ReturnCode = GetLastError();
goto Cleanup;
}
ReturnCode = ERROR_SUCCESS;
Cleanup:
if (EventlogHandle != NULL) {
DeregisterEventSource(EventlogHandle);
}
return ReturnCode;
}
DWORD
RCCSrvGetCommandLine(
IN HANDLE ComPortHandle,
OUT PBOOL ControlC
)
{
DWORD Bytes;
DWORD i;
GlobalReadIndex = 0;
*ControlC = FALSE;
do {
if (GlobalReadIndex == GlobalCommandLineSize) {
GlobalReadIndex--;
}
//
// Read a (possibly) partial command line.
//
if (!ReadFile(ComPortHandle,
&(GlobalCommandLine[GlobalReadIndex]),
1,
&Bytes,
NULL
)) {
return GetLastError();
}
if (GlobalCommandLine[GlobalReadIndex] == 0x3) {
*ControlC = TRUE;
return ERROR_SUCCESS;
}
if ((GlobalCommandLine[GlobalReadIndex] == 0x8) || // backspace (^h)
(GlobalCommandLine[GlobalReadIndex] == 0x7F)) { // delete
if (GlobalReadIndex > 0) {
WriteFile(ComPortHandle,
&(GlobalCommandLine[GlobalReadIndex]),
1,
&Bytes,
NULL
);
GlobalReadIndex--;
}
} else {
WriteFile(ComPortHandle,
&(GlobalCommandLine[GlobalReadIndex]),
1,
&Bytes,
NULL
);
GlobalReadIndex++;
}
} while ((GlobalReadIndex == 0) || (GlobalCommandLine[GlobalReadIndex - 1] != '\r'));
GlobalCommandLine[GlobalReadIndex - 1] = '\0';
RCCSrvPrint(ComPortHandle, "\n", sizeof("\n") - 1);
return ERROR_SUCCESS;
}
DWORD
RCCSrvPrintMsg(
IN HANDLE ComPortHandle,
IN DWORD MessageId,
IN DWORD SystemErrorCode
)
{
DWORD Bytes;
UCHAR OutBuffer[512];
Bytes = FormatMessageA(FORMAT_MESSAGE_FROM_HMODULE,
NULL,
MessageId,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
OutBuffer,
ARRAYSIZE(OutBuffer)),
NULL
);
ASSERT(Bytes != 0);
if (MessageId == MSG_RCCSRV_PROMPT) {
Bytes -= 2; // remove the \r\n that get added in .mc files
}
RCCSrvPrint(ComPortHandle, OutBuffer, Bytes);
if (SystemErrorCode != 0) {
Bytes = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
SystemErrorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
OutBuffer,
ARRAYSIZE(OutBuffer),
NULL
);
if (Bytes == 0) {
Bytes = FormatMessageA(FORMAT_MESSAGE_FROM_HMODULE,
NULL,
MSG_RCCSRV_ERROR_NOT_DEFINED,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
OutBuffer,
ARRAYSIZE(OutBuffer),
(LPVOID)&SystemErrorCode
);
ASSERT(Bytes != 0);
}
RCCSrvPrint(ComPortHandle, OutBuffer, Bytes);
RCCSrvPrint(ComPortHandle, "\r\n\r\n", sizeof("\r\n\r\n") - 1);
}
return ERROR_SUCCESS;
}
DWORD
RCCSrvPrint(
IN HANDLE ComPortHandle,
IN PUCHAR Buffer,
IN DWORD BufferSize
)
{
DWORD BytesWritten;
if (!WriteFile(ComPortHandle, Buffer, BufferSize, &BytesWritten, NULL)) {
return GetLastError();
}
return ERROR_SUCCESS;
}
VOID
RCCSrvPrintTListInfo(
IN HANDLE ComPortHandle,
IN PRCC_RSP_TLIST Buffer
)
{
LARGE_INTEGER Time;
TIME_FIELDS UserTime;
TIME_FIELDS KernelTime;
TIME_FIELDS UpTime;
ULONG TotalOffset;
SIZE_T SumCommit;
SIZE_T SumWorkingSet;
PSYSTEM_PROCESS_INFORMATION ProcessInfo;
PSYSTEM_THREAD_INFORMATION ThreadInfo;
PSYSTEM_PAGEFILE_INFORMATION PageFileInfo;
ULONG i;
PUCHAR ProcessInfoStart;
PUCHAR BufferStart = (PUCHAR)Buffer;
ANSI_STRING pname;
ULONG LineNumber = 0;
UCHAR OutputBuffer[200]; // should never be more than 80, but just to be safe....
BOOL Stop;
Time.QuadPart = Buffer->TimeOfDayInfo.CurrentTime.QuadPart - Buffer->TimeOfDayInfo.BootTime.QuadPart;
RtlTimeToElapsedTimeFields(&Time, &UpTime);
sprintf(OutputBuffer,
"memory: %4ld kb uptime:%3ld %2ld:%02ld:%02ld.%03ld \r\n\r\n",
Buffer->BasicInfo.NumberOfPhysicalPages * (Buffer->BasicInfo.PageSize / 1024),
UpTime.Day,
UpTime.Hour,
UpTime.Minute,
UpTime.Second,
UpTime.Milliseconds
);
RCCSrvPrint(ComPortHandle, OutputBuffer, strlen(OutputBuffer));
LineNumber += 2;
PageFileInfo = (PSYSTEM_PAGEFILE_INFORMATION)(BufferStart + Buffer->PagefileInfoOffset);
//
// Print out the page file information.
//
if (Buffer->PagefileInfoOffset == 0) {
sprintf(OutputBuffer, "no page files in use\r\n");
RCCSrvPrint(ComPortHandle, OutputBuffer, strlen(OutputBuffer));
LineNumber++;
} else {
for (; ; ) {
PageFileInfo->PageFileName.Buffer = (PWCHAR)(((PUCHAR)BufferStart) +
(ULONG_PTR)(PageFileInfo->PageFileName.Buffer));
sprintf(OutputBuffer, "PageFile: %wZ\r\n", &PageFileInfo->PageFileName);
RCCSrvPrint(ComPortHandle, OutputBuffer, strlen(OutputBuffer));
LineNumber++;
sprintf(OutputBuffer, "\tCurrent Size: %6ld kb Total Used: %6ld kb Peak Used %6ld kb\r\n",
PageFileInfo->TotalSize * (Buffer->BasicInfo.PageSize/1024),
PageFileInfo->TotalInUse * (Buffer->BasicInfo.PageSize/1024),
PageFileInfo->PeakUsage * (Buffer->BasicInfo.PageSize/1024)
);
RCCSrvPrint(ComPortHandle, OutputBuffer, strlen(OutputBuffer));
LineNumber++;
if (PageFileInfo->NextEntryOffset == 0) {
break;
}
PageFileInfo = (PSYSTEM_PAGEFILE_INFORMATION)((PCHAR)PageFileInfo + PageFileInfo->NextEntryOffset);
}
}
//
// display pmon style process output, then detailed output that includes
// per thread stuff
//
if (Buffer->ProcessInfoOffset == 0) {
return;
}
TotalOffset = 0;
SumCommit = 0;
SumWorkingSet = 0;
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)(BufferStart + Buffer->ProcessInfoOffset);
ProcessInfoStart = (PUCHAR)ProcessInfo;
while (TRUE) {
SumCommit += ProcessInfo->PrivatePageCount / 1024;
SumWorkingSet += ProcessInfo->WorkingSetSize / 1024;
if (ProcessInfo->NextEntryOffset == 0) {
break;
}
TotalOffset += ProcessInfo->NextEntryOffset;
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)(ProcessInfoStart +TotalOffset);
}
SumWorkingSet += Buffer->FileCache.CurrentSize/1024;
if (LineNumber > 17) {
RCCSrvPutMore(ComPortHandle, &Stop);
if (Stop) {
return;
}
LineNumber = 0;
}
sprintf(OutputBuffer,
"\r\n Memory:%7ldK Avail:%7ldK TotalWs:%7ldK InRam Kernel:%5ldK P:%5ldK\r\n",
Buffer->BasicInfo.NumberOfPhysicalPages * (Buffer->BasicInfo.PageSize/1024),
Buffer->PerfInfo.AvailablePages * (Buffer->BasicInfo.PageSize/1024),
SumWorkingSet,
(Buffer->PerfInfo.ResidentSystemCodePage + Buffer->PerfInfo.ResidentSystemDriverPage) *
(Buffer->BasicInfo.PageSize/1024),
(Buffer->PerfInfo.ResidentPagedPoolPage) * (Buffer->BasicInfo.PageSize/1024)
);
RCCSrvPrint(ComPortHandle, OutputBuffer, strlen(OutputBuffer));
LineNumber += 2;
if (LineNumber > 18) {
RCCSrvPutMore(ComPortHandle, &Stop);
if (Stop) {
return;
}
LineNumber = 0;
}
sprintf(OutputBuffer,
" Commit:%7ldK/%7ldK Limit:%7ldK Peak:%7ldK Pool N:%5ldK P:%5ldK\r\n",
Buffer->PerfInfo.CommittedPages * (Buffer->BasicInfo.PageSize/1024),
SumCommit,
Buffer->PerfInfo.CommitLimit * (Buffer->BasicInfo.PageSize/1024),
Buffer->PerfInfo.PeakCommitment * (Buffer->BasicInfo.PageSize/1024),
Buffer->PerfInfo.NonPagedPoolPages * (Buffer->BasicInfo.PageSize/1024),
Buffer->PerfInfo.PagedPoolPages * (Buffer->BasicInfo.PageSize/1024)
);
RCCSrvPrint(ComPortHandle, OutputBuffer, strlen(OutputBuffer));
LineNumber++;
if (LineNumber > 18) {
RCCSrvPutMore(ComPortHandle, &Stop);
if (Stop) {
return;
}
LineNumber = 0;
}
sprintf(OutputBuffer, "\r\n");
RCCSrvPrint(ComPortHandle, OutputBuffer, strlen(OutputBuffer));
RCCSrvPutMore(ComPortHandle, &Stop);
if (Stop) {
return;
}
LineNumber = 0;
sprintf(OutputBuffer, " User Time Kernel Time Ws Faults Commit Pri Hnd Thd Pid Name\r\n");
RCCSrvPrint(ComPortHandle, OutputBuffer, strlen(OutputBuffer));
LineNumber++;
sprintf(OutputBuffer,
" %6ld %8ld %s\r\n",
Buffer->FileCache.CurrentSize/1024,
Buffer->FileCache.PageFaultCount,
"File Cache"
);
RCCSrvPrint(ComPortHandle, OutputBuffer, strlen(OutputBuffer));
LineNumber++;
TotalOffset = 0;
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)(BufferStart + Buffer->ProcessInfoOffset);
while (TRUE) {
pname.Buffer = NULL;
if (ProcessInfo->ImageName.Buffer) {
ProcessInfo->ImageName.Buffer = (PWCHAR)(BufferStart + (ULONG_PTR)(ProcessInfo->ImageName.Buffer));
RtlUnicodeStringToAnsiString(&pname,(PUNICODE_STRING)&ProcessInfo->ImageName,TRUE);
}
RtlTimeToElapsedTimeFields(&ProcessInfo->UserTime, &UserTime);
RtlTimeToElapsedTimeFields(&ProcessInfo->KernelTime, &KernelTime);
sprintf(OutputBuffer,
"%3ld:%02ld:%02ld.%03ld %3ld:%02ld:%02ld.%03ld",
UserTime.Hour,
UserTime.Minute,
UserTime.Second,
UserTime.Milliseconds,
KernelTime.Hour,
KernelTime.Minute,
KernelTime.Second,
KernelTime.Milliseconds
);
RCCSrvPrint(ComPortHandle, OutputBuffer, strlen(OutputBuffer));
sprintf(OutputBuffer,
"%6ld %8ld %7ld",
ProcessInfo->WorkingSetSize / 1024,
ProcessInfo->PageFaultCount,
ProcessInfo->PrivatePageCount / 1024
);
RCCSrvPrint(ComPortHandle, OutputBuffer, strlen(OutputBuffer));
sprintf(OutputBuffer,
" %2ld %4ld %3ld %3ld %s\r\n",
ProcessInfo->BasePriority,
ProcessInfo->HandleCount,
ProcessInfo->NumberOfThreads,
HandleToUlong(ProcessInfo->UniqueProcessId),
ProcessInfo->UniqueProcessId == 0 ?
"Idle Process" :
(ProcessInfo->ImageName.Buffer ? pname.Buffer : "System")
);
RCCSrvPrint(ComPortHandle, OutputBuffer, strlen(OutputBuffer));
LineNumber++;
if (LineNumber > 18) {
RCCSrvPutMore(ComPortHandle, &Stop);
if (Stop) {
return;
}
LineNumber = 0;
if (GlobalPagingNeeded) {
sprintf(OutputBuffer, " User Time Kernel Time Ws Faults Commit Pri Hnd Thd Pid Name\r\n");
RCCSrvPrint(ComPortHandle, OutputBuffer, strlen(OutputBuffer));
}
LineNumber++;
}
if (pname.Buffer) {
RtlFreeAnsiString(&pname);
}
if (ProcessInfo->NextEntryOffset == 0) {
break;
}
TotalOffset += ProcessInfo->NextEntryOffset;
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)(ProcessInfoStart + TotalOffset);
}
if (!GlobalDoThreads) {
return;
}
//
// Beginning of normal old style pstat output
//
TotalOffset = 0;
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)(BufferStart + Buffer->ProcessInfoOffset);
RCCSrvPutMore(ComPortHandle, &Stop);
if (Stop) {
return;
}
LineNumber = 0;
sprintf(OutputBuffer, "\r\n");
RCCSrvPrint(ComPortHandle, OutputBuffer, strlen(OutputBuffer));
LineNumber++;
while (TRUE) {
pname.Buffer = NULL;
if (ProcessInfo->ImageName.Buffer) {
RtlUnicodeStringToAnsiString(&pname,(PUNICODE_STRING)&ProcessInfo->ImageName,TRUE);
}
sprintf(OutputBuffer,
"pid:%3lx pri:%2ld Hnd:%5ld Pf:%7ld Ws:%7ldK %s\r\n",
HandleToUlong(ProcessInfo->UniqueProcessId),
ProcessInfo->BasePriority,
ProcessInfo->HandleCount,
ProcessInfo->PageFaultCount,
ProcessInfo->WorkingSetSize / 1024,
ProcessInfo->UniqueProcessId == 0 ? "Idle Process" : (
ProcessInfo->ImageName.Buffer ? pname.Buffer : "System")
);
RCCSrvPrint(ComPortHandle, OutputBuffer, strlen(OutputBuffer));
LineNumber++;
if (LineNumber > 18) {
RCCSrvPutMore(ComPortHandle, &Stop);
if (Stop) {
return;
}
LineNumber = 0;
}
if (pname.Buffer) {
RtlFreeAnsiString(&pname);
}
i = 0;
ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(ProcessInfo + 1);
if (ProcessInfo->NumberOfThreads) {
if ((LineNumber < 18) || !GlobalPagingNeeded) {
sprintf(OutputBuffer, " tid pri Ctx Swtch StrtAddr User Time Kernel Time State\r\n");
RCCSrvPrint(ComPortHandle, OutputBuffer, strlen(OutputBuffer));
LineNumber++;
} else {
RCCSrvPutMore(ComPortHandle, &Stop);
if (Stop) {
return;
}
LineNumber = 0;
}
}
while (i < ProcessInfo->NumberOfThreads) {
RtlTimeToElapsedTimeFields ( &ThreadInfo->UserTime, &UserTime);
RtlTimeToElapsedTimeFields ( &ThreadInfo->KernelTime, &KernelTime);
sprintf(OutputBuffer,
" %3lx %2ld %9ld %p",
ProcessInfo->UniqueProcessId == 0 ? 0 : HandleToUlong(ThreadInfo->ClientId.UniqueThread),
ProcessInfo->UniqueProcessId == 0 ? 0 : ThreadInfo->Priority,
ThreadInfo->ContextSwitches,
ProcessInfo->UniqueProcessId == 0 ? 0 : ThreadInfo->StartAddress
);
RCCSrvPrint(ComPortHandle, OutputBuffer, strlen(OutputBuffer));
sprintf(OutputBuffer,
" %2ld:%02ld:%02ld.%03ld %2ld:%02ld:%02ld.%03ld",
UserTime.Hour,
UserTime.Minute,
UserTime.Second,
UserTime.Milliseconds,
KernelTime.Hour,
KernelTime.Minute,
KernelTime.Second,
KernelTime.Milliseconds
);
RCCSrvPrint(ComPortHandle, OutputBuffer, strlen(OutputBuffer));
sprintf(OutputBuffer,
" %s%s\r\n",
StateTable[ThreadInfo->ThreadState],
(ThreadInfo->ThreadState == 5) ? WaitTable[ThreadInfo->WaitReason] : Empty
);
RCCSrvPrint(ComPortHandle, OutputBuffer, strlen(OutputBuffer));
LineNumber++;
if (LineNumber > 18) {
RCCSrvPutMore(ComPortHandle, &Stop);
if (Stop) {
return;
}
LineNumber = 0;
if (GlobalPagingNeeded) {
sprintf(OutputBuffer, " tid pri Ctx Swtch StrtAddr User Time Kernel Time State\r\n");
RCCSrvPrint(ComPortHandle, OutputBuffer, strlen(OutputBuffer));
}
LineNumber++;
}
ThreadInfo += 1;
i += 1;
}
if (ProcessInfo->NextEntryOffset == 0) {
break;
}
TotalOffset += ProcessInfo->NextEntryOffset;
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)(ProcessInfoStart + TotalOffset);
sprintf(OutputBuffer, "\r\n");
RCCSrvPrint(ComPortHandle, OutputBuffer, strlen(OutputBuffer));
LineNumber++;
if (LineNumber > 18) {
RCCSrvPutMore(ComPortHandle, &Stop);
if (Stop) {
return;
}
LineNumber = 0;
}
}
}
VOID
RCCSrvPutMore(
IN HANDLE ComPortHandle,
OUT PBOOL Stop
)
{
if (GlobalPagingNeeded) {
RCCSrvPrintMsg(ComPortHandle, MSG_RCCSRV_MORE, 0);
RCCSrvGetCommandLine(ComPortHandle, Stop);
} else {
*Stop = FALSE;
}
}
BOOL
AreYouSure(
IN HANDLE ComPortHandle
)
{
BOOL Stop;
RCCSrvPrintMsg(ComPortHandle, MSG_RCCSRV_ARE_YOU_SURE, 0);
RCCSrvGetCommandLine(ComPortHandle, &Stop);
if (!Stop && ((GlobalCommandLine[0] == 'y') || (GlobalCommandLine[0] == 'Y'))) {
return TRUE;
}
return FALSE;
}