1497 lines
41 KiB
C
1497 lines
41 KiB
C
|
/****************************************************************************
|
|||
|
|
|||
|
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;
|
|||
|
}
|
|||
|
|