[SACDRV]: Implement DoCrashCommand.

[SACDRV]: Cleanups and fixes. You can now use "Shutdown", "crashdump" and "restart" in the !SAC and the commands work as expected.
[SACDRV]: Implement GetTListInfo and DoTlistCommand. PrintTListInfo is next to actually show the output.

svn path=/trunk/; revision=59838
This commit is contained in:
Alex Ionescu 2013-08-26 19:45:16 +00:00
parent 12796b070e
commit 08c5f648ed
5 changed files with 408 additions and 74 deletions

View file

@ -12,7 +12,7 @@
/* GLOBALS *******************************************************************/
PWCHAR GlobalBuffer;
PVOID GlobalBuffer;
ULONG GlobalBufferSize;
/* FUNCTIONS *****************************************************************/
@ -57,30 +57,269 @@ DoChannelSwitchByIndexCommand(
return STATUS_NOT_IMPLEMENTED;
}
typedef struct _SAC_SYSTEM_INFORMATION
{
SYSTEM_BASIC_INFORMATION BasicInfo;
SYSTEM_TIMEOFDAY_INFORMATION TimeInfo;
SYSTEM_FILECACHE_INFORMATION CacheInfo;
SYSTEM_PERFORMANCE_INFORMATION PerfInfo;
ULONG RemainingSize;
ULONG ProcessDataOffset;
// SYSTEM_PAGEFILE_INFORMATION PageFileInfo;
// SYSTEM_PROCESS_INFORMATINO ProcessInfo;
} SAC_SYSTEM_INFORMATION, *PSAC_SYSTEM_INFORMATION;
NTSTATUS
GetTListInfo(
IN PVOID TListData,
IN ULONG InputSize,
IN ULONG TotalSize
)
NTAPI
GetTListInfo(IN PSAC_SYSTEM_INFORMATION SacInfo,
IN ULONG InputSize,
OUT PULONG TotalSize)
{
return STATUS_NOT_IMPLEMENTED;
NTSTATUS Status;
ULONG BufferLength, ReturnLength, RemainingSize;
PSYSTEM_PAGEFILE_INFORMATION PageFileInfo;
PSYSTEM_PROCESS_INFORMATION ProcessInfo;
ULONG_PTR P;
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Entering.\n");
/* Assume failure */
*TotalSize = 0;
/* Bail out if the buffer is way too small */
if (InputSize < 4)
{
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting, no memory.\n");
return STATUS_NO_MEMORY;
}
/* Make sure it's at least big enough to hold the static structure */
BufferLength = InputSize - sizeof(SAC_SYSTEM_INFORMATION);
if ((INT)InputSize - sizeof(SAC_SYSTEM_INFORMATION) < 0)
{
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting, no memory (2).\n");
return STATUS_NO_MEMORY;
}
/* Query the time */
Status = ZwQuerySystemInformation(SystemTimeOfDayInformation,
&SacInfo->TimeInfo,
sizeof(SacInfo->TimeInfo),
NULL);
if (!NT_SUCCESS(Status))
{
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting, error.\n");
return Status;
}
/* Query basic information */
Status = ZwQuerySystemInformation(SystemBasicInformation,
&SacInfo->BasicInfo,
sizeof(SacInfo->BasicInfo),
NULL);
if (!NT_SUCCESS(Status))
{
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting, error (2).\n");
return Status;
}
/* Now query the pagefile information, which comes right after */
P = (ULONG_PTR)(SacInfo + 1);
PageFileInfo = (PSYSTEM_PAGEFILE_INFORMATION)P;
Status = ZwQuerySystemInformation(SystemPageFileInformation,
PageFileInfo,
BufferLength,
&ReturnLength);
if (!NT_SUCCESS(Status) || !(ReturnLength))
{
/* We failed -- is it because our buffer was too small? */
if (BufferLength < ReturnLength)
{
/* Bail out */
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting, no memory(5).\n");
return STATUS_NO_MEMORY;
}
/* Some other reason, assume the buffer is now full */
SacInfo->RemainingSize = 0;
}
else
{
/* This is the leftover data */
SacInfo->RemainingSize = InputSize - BufferLength;
/* This much has now been consumed, and where we are now */
BufferLength -= ReturnLength;
P += ReturnLength;
/* Are we out of memory? */
if ((LONG)BufferLength < 0)
{
/* Bail out */
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting, no memory(3).\n");
return STATUS_NO_MEMORY;
}
/* All good, loop the pagefile data now */
while (TRUE)
{
/* Is the pagefile name too big to fit? */
if (PageFileInfo->PageFileName.Length > (LONG)BufferLength)
{
/* Bail out */
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting, error(3).\n");
return STATUS_INFO_LENGTH_MISMATCH;
}
/* Copy the name into our own buffer */
RtlCopyMemory((PVOID)P,
PageFileInfo->PageFileName.Buffer,
PageFileInfo->PageFileName.Length);
PageFileInfo->PageFileName.Buffer = (PWCHAR)P;
/* Update buffer lengths and offset */
BufferLength -= PageFileInfo->PageFileName.Length;
P += PageFileInfo->PageFileName.Length;
/* Are we out of memory? */
if ((LONG)BufferLength < 0)
{
/* Bail out */
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting, no memory(4).\n");
return STATUS_NO_MEMORY;
}
/* If this was the only pagefile, break out */
if (!PageFileInfo->NextEntryOffset) break;
/* Otherwise, move to the next one */
PageFileInfo = (PVOID)((ULONG_PTR)PageFileInfo +
PageFileInfo->NextEntryOffset);
}
}
/* Next, query the file cache information */
Status = ZwQuerySystemInformation(SystemFileCacheInformation,
&SacInfo->CacheInfo,
sizeof(SacInfo->CacheInfo),
NULL);
if (!NT_SUCCESS(Status))
{
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting, error (4).\n");
return Status;
}
/* And then the performance information */
Status = ZwQuerySystemInformation(SystemPerformanceInformation,
&SacInfo->PerfInfo,
sizeof(SacInfo->PerfInfo),
NULL);
if (!NT_SUCCESS(Status))
{
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting, error(5).\n");
return Status;
}
/* Finally, align the buffer to query process and thread information */
P = ALIGN_UP(P, SYSTEM_PROCESS_INFORMATION);
RemainingSize = (ULONG_PTR)SacInfo + InputSize - P;
/* Are we out of memory? */
if ((LONG)RemainingSize < 0)
{
/* Bail out */
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting, no memory (6).\n");
return STATUS_NO_MEMORY;
}
/* Now query the processes and threads */
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)P;
Status = ZwQuerySystemInformation(SystemProcessInformation,
ProcessInfo,
RemainingSize,
&ReturnLength);
if (!NT_SUCCESS(Status))
{
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting, error(6).\n");
return Status;
}
/* The first process name will be right after this buffer */
P += ReturnLength;
/* The caller should look for process info over here */
SacInfo->ProcessDataOffset = InputSize - RemainingSize;
/* This is how much buffer data we have left -- are we out? */
BufferLength = RemainingSize - ReturnLength;
if ((LONG)BufferLength < 0)
{
/* Bail out */
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting, no memory(7).\n");
return STATUS_NO_MEMORY;
}
/* All good and ready to parse the process and thread list */
while (TRUE)
{
/* Does the process have a name? */
if (ProcessInfo->ImageName.Buffer)
{
/* Is the process name too big to fit? */
if ((LONG)BufferLength < ProcessInfo->ImageName.Length)
{
/* Bail out */
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting, error(7).\n");
return STATUS_INFO_LENGTH_MISMATCH;
}
/* Copy the name into our own buffer */
RtlCopyMemory((PVOID)P,
ProcessInfo->ImageName.Buffer,
ProcessInfo->ImageName.Length);
ProcessInfo->ImageName.Buffer = (PWCHAR)P;
/* Update buffer lengths and offset */
BufferLength -= ProcessInfo->ImageName.Length;
P += ProcessInfo->ImageName.Length;
/* Are we out of memory? */
if ((LONG)BufferLength < 0)
{
/* Bail out */
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting, no memory(8).\n");
return STATUS_NO_MEMORY;
}
}
/* If this was the only process, break out */
if (!ProcessInfo->NextEntryOffset) break;
/* Otherwise, move to the next one */
ProcessInfo = (PVOID)((ULONG_PTR)ProcessInfo +
ProcessInfo->NextEntryOffset);
}
/* All done! */
SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting.\n");
*TotalSize = InputSize - BufferLength;
return STATUS_SUCCESS;
}
VOID
PrintTListInfo(
IN PVOID TListData
)
NTAPI
PrintTListInfo(IN PSAC_SYSTEM_INFORMATION SacInfo)
{
SAC_DBG(1, "Testing: %d %d %I64d\n",
SacInfo->BasicInfo.NumberOfPhysicalPages,
SacInfo->PerfInfo.AvailablePages,
SacInfo->TimeInfo.BootTime);
}
VOID
PutMore(
OUT PBOOLEAN ScreenFull
)
NTAPI
PutMore(OUT PBOOLEAN ScreenFull)
{
*ScreenFull = FALSE;
}
BOOLEAN
@ -167,144 +406,234 @@ VOID
NTAPI
DoFullInfoCommand(VOID)
{
/* Flip the flag */
GlobalDoThreads = !GlobalDoThreads;
/* Print out the new state */
SacPutSimpleMessage(GlobalDoThreads ? 8 : 7);
}
VOID
NTAPI
DoPagingCommand(VOID)
{
/* Flip the flag */
GlobalPagingNeeded = !GlobalPagingNeeded;
/* Print out the new state */
SacPutSimpleMessage(GlobalPagingNeeded ? 10 : 9);
}
VOID
NTAPI
DoSetTimeCommand(IN PCHAR InputTime)
{
SAC_DBG(1, "Entering\n");
}
VOID
NTAPI
DoKillCommand(IN PCHAR KillString)
{
SAC_DBG(1, "Entering\n");
}
VOID
NTAPI
DoLowerPriorityCommand(IN PCHAR PrioString)
{
SAC_DBG(1, "Entering\n");
}
VOID
NTAPI
DoRaisePriorityCommand(IN PCHAR PrioString)
{
SAC_DBG(1, "Entering\n");
}
VOID
NTAPI
DoLimitMemoryCommand(IN PCHAR LimitString)
{
SAC_DBG(1, "Entering\n");
}
VOID
NTAPI
DoCrashCommand(VOID)
{
SAC_DBG(1, "SAC DoCrashCommand: Entering.\n");
/* Crash the machine */
KeBugCheckEx(MANUALLY_INITIATED_CRASH, 0, 0, 0, 0);
__debugbreak();
}
VOID
NTAPI
DoMachineInformationCommand(VOID)
{
SAC_DBG(1, "Entering\n");
}
VOID
NTAPI
DoChannelCommand(IN PCHAR ChannelString)
{
SAC_DBG(1, "Entering\n");
}
VOID
NTAPI
DoCmdCommand(IN PCHAR InputString)
{
SAC_DBG(1, "Entering\n");
}
VOID
NTAPI
DoLockCommand(VOID)
{
SAC_DBG(1, "Entering\n");
}
#define PRINT_HELP_MESSAGE(x) \
{ \
Count += NewCount; \
NewCount = GetMessageLineCount(x); \
if ( (NewCount + Count) > SAC_VTUTF8_COL_HEIGHT) \
{ \
PutMore(&ScreenFull); \
if (ScreenFull) return; \
Count = 0; \
} \
SacPutSimpleMessage(x); \
FORCEINLINE
BOOLEAN
PrintHelpMessage(IN ULONG MessageId,
IN OUT PULONG Count)
{
BOOLEAN ScreenFull;
ULONG NewCount;
/* Get the amount of lines this message will take */
NewCount = GetMessageLineCount(MessageId);
if ((NewCount + *Count) > SAC_VTUTF8_ROW_HEIGHT)
{
/* We are going to overflow the screen, wait for input */
PutMore(&ScreenFull);
if (ScreenFull) return FALSE;
*Count = 0;
}
/* Print out the message and update the amount of lines printed */
SacPutSimpleMessage(MessageId);
*Count += NewCount;
return TRUE;
}
VOID
NTAPI
DoHelpCommand(VOID)
{
ULONG NewCount = 0, Count = 0;
BOOLEAN ScreenFull = FALSE;
ULONG Count = 0;
PRINT_HELP_MESSAGE(112);
PRINT_HELP_MESSAGE(12);
PRINT_HELP_MESSAGE(13);
PRINT_HELP_MESSAGE(14);
PRINT_HELP_MESSAGE(15);
PRINT_HELP_MESSAGE(16);
PRINT_HELP_MESSAGE(31);
PRINT_HELP_MESSAGE(18);
PRINT_HELP_MESSAGE(19);
PRINT_HELP_MESSAGE(32);
PRINT_HELP_MESSAGE(20);
PRINT_HELP_MESSAGE(21);
PRINT_HELP_MESSAGE(22);
PRINT_HELP_MESSAGE(23);
PRINT_HELP_MESSAGE(24);
PRINT_HELP_MESSAGE(25);
PRINT_HELP_MESSAGE(27);
PRINT_HELP_MESSAGE(28);
PRINT_HELP_MESSAGE(29);
/* Print out all the help messages */
if (!PrintHelpMessage(112, &Count)) return;
if (!PrintHelpMessage(12, &Count)) return;
if (!PrintHelpMessage(13, &Count)) return;
if (!PrintHelpMessage(14, &Count)) return;
if (!PrintHelpMessage(15, &Count)) return;
if (!PrintHelpMessage(16, &Count)) return;
if (!PrintHelpMessage(31, &Count)) return;
if (!PrintHelpMessage(18, &Count)) return;
if (!PrintHelpMessage(19, &Count)) return;
if (!PrintHelpMessage(32, &Count)) return;
if (!PrintHelpMessage(20, &Count)) return;
if (!PrintHelpMessage(21, &Count)) return;
if (!PrintHelpMessage(22, &Count)) return;
if (!PrintHelpMessage(23, &Count)) return;
if (!PrintHelpMessage(24, &Count)) return;
if (!PrintHelpMessage(25, &Count)) return;
if (!PrintHelpMessage(27, &Count)) return;
if (!PrintHelpMessage(28, &Count)) return;
if (!PrintHelpMessage(29, &Count)) return;
}
VOID
NTAPI
DoGetNetInfo(IN BOOLEAN DoPrint)
{
SAC_DBG(1, "Entering\n");
}
VOID
NTAPI
DoSetIpAddressCommand(IN PCHAR IpString)
{
SAC_DBG(1, "Entering\n");
}
VOID
NTAPI
DoTlistCommand(VOID)
{
NTSTATUS Status;
PVOID NewGlobalBuffer;
ULONG Size;
SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC DoTlistCommand: Entering.\n");
/* Check if a global buffer already exists */
if (!GlobalBuffer)
{
/* It doesn't, allocate one */
GlobalBuffer = SacAllocatePool(4096, GLOBAL_BLOCK_TAG);
if (GlobalBuffer)
{
/* Remember its current size */
GlobalBufferSize = 4096;
}
else
{
/* Out of memory, bail out */
SacPutSimpleMessage(11);
SAC_DBG(1, "SAC DoTlistCommand: Exiting.\n");
return;
}
}
/* Loop as long as the buffer is too small */
while (TRUE)
{
/* Get the process list */
Status = GetTListInfo(GlobalBuffer, GlobalBufferSize, &Size);
if ((Status != STATUS_NO_MEMORY) &&
(Status != STATUS_INFO_LENGTH_MISMATCH))
{
/* It fits! Bail out */
break;
}
/* We need a new bigger buffer */
NewGlobalBuffer = SacAllocatePool(GlobalBufferSize + 4096,
GLOBAL_BLOCK_TAG);
if (!NewGlobalBuffer)
{
/* Out of memory, bail out */
SacPutSimpleMessage(11);
SAC_DBG(1, "SAC DoTlistCommand: Exiting.\n");
return;
}
/* Free the old one, update state */
SacFreePool(GlobalBuffer);
GlobalBufferSize += 4096;
GlobalBuffer = NewGlobalBuffer;
}
/* Did we get here because we have the whole list? */
if (!NT_SUCCESS(Status))
{
/* Nope, print out a failure message */
SacPutSimpleMessage(68);
swprintf(GlobalBuffer, GetMessage(48), Status);
SacPutString(GlobalBuffer);
}
else
{
/* Yep, print out the list */
PrintTListInfo(GlobalBuffer);
}
SAC_DBG(1, "SAC DoTlistCommand: Exiting.\n");
}

View file

@ -30,6 +30,8 @@ PSAC_CHANNEL ExecutePostConsumerCommandData;
BOOLEAN InputInEscape, InputInEscTab, ConMgrLastCharWasCR;
CHAR InputBuffer[80];
BOOLEAN GlobalPagingNeeded, GlobalDoThreads;
/* FUNCTIONS *****************************************************************/
VOID
@ -447,11 +449,6 @@ ConMgrChannelOWrite(IN PSAC_CHANNEL Channel,
return Status;
}
#define Shutdown 1
#define Restart 3
#define Nothing 0
BOOLEAN GlobalPagingNeeded;
VOID
NTAPI
ConMgrProcessInputLine(VOID)
@ -566,7 +563,7 @@ ConMgrProcessInputLine(VOID)
}
else if ((InputBuffer[0] != '\n') && (InputBuffer[0] != ANSI_NULL))
{
SacPutSimpleMessage(105);
SacPutSimpleMessage(SAC_UNKNOWN_COMMAND);
}
}
@ -851,25 +848,25 @@ ConMgrWorkerProcessEvents(IN PSAC_DEVICE_EXTENSION DeviceExtension)
ConMgrSerialPortConsumer();
switch (ExecutePostConsumerCommand)
{
case 1:
case Restart:
/* A reboot was sent, do it */
DoRebootCommand(FALSE);
break;
case 2:
case Close:
/* A close was sent, do it */
ChanMgrCloseChannel(ExecutePostConsumerCommandData);
ChanMgrReleaseChannel(ExecutePostConsumerCommandData);
break;
case 3:
case Shutdown:
/* A shutdown was sent, do it */
DoRebootCommand(TRUE);
break;
}
/* Clear the serial port consumer state */
ExecutePostConsumerCommand = 0;
ExecutePostConsumerCommand = Nothing;
ExecutePostConsumerCommandData = NULL;
}
}

View file

@ -261,6 +261,17 @@ typedef enum _SAC_ANSI_DISPATCH
SacAnsiClearBoldAttribute
} SAC_ANSI_DISPATCH;
//
// Commands that the consumer and producer share
//
typedef enum _SAC_POST_COMMANDS
{
Nothing,
Shutdown,
Close,
Restart
} SAC_POST_COMMANDS;
//
// SAC supports 3 different channel output types
//
@ -1232,7 +1243,7 @@ extern LONG CurrentChannelRefCount;
extern PCHAR SerialPortBuffer;
extern LONG SerialPortConsumerIndex, SerialPortProducerIndex;
extern PCHAR Utf8ConversionBuffer;
extern BOOLEAN GlobalPagingNeeded;
extern BOOLEAN GlobalPagingNeeded, GlobalDoThreads;
extern ULONG Utf8ConversionBufferSize;
extern BOOLEAN CommandConsoleLaunchingEnabled;

View file

@ -881,7 +881,6 @@ VTUTF8ChannelOFlush(IN PSAC_CHANNEL Channel)
if (Utf8Count)
{
/* Write it out on the wire */
SAC_DBG(1, "Row: %d\tCol : %d\t\tValue : (%c) -> (%c)\n", R, C, *TmpBuffer, *Utf8ConversionBuffer);
Status = ConMgrWriteData(Channel, Utf8ConversionBuffer, Utf8Count);
if (!NT_SUCCESS(Status)) goto Quickie;
}
@ -949,7 +948,6 @@ VTUTF8ChannelOWrite2(IN PSAC_CHANNEL Channel,
{
/* Check what the character is */
pwch = &String[i];
SAC_DBG(1, "Writing on VT-UTF8: (%lx)\n", *pwch);
switch (*pwch)
{
/* It's an escape sequence... */
@ -1003,7 +1001,7 @@ VTUTF8ChannelOWrite2(IN PSAC_CHANNEL Channel,
/* Now we're left with the before-last row, zero it out */
ASSERT(R == (SAC_VTUTF8_ROW_HEIGHT - 1));
RtlZeroMemory(&Cursor[R], sizeof(Cursor[R]));
RtlZeroMemory(&Cursor->Cell[R], sizeof(Cursor->Cell[R]));
/* Reset the row back by one */
Channel->CursorRow--;
@ -1178,7 +1176,6 @@ VTUTF8ChannelOWrite(IN PSAC_CHANNEL Channel,
CHECK_PARAMETER2(String);
/* Call the lower level function */
SAC_DBG(1, "Writing on VT-UTF8: %S\n", String);
Status = VTUTF8ChannelOWrite2(Channel, (PWCHAR)String, Length / sizeof(WCHAR));
if (NT_SUCCESS(Status))
{

View file

@ -513,7 +513,7 @@ Computer identification information is unavailable.
.
MessageId=105
SymbolicName=SACDRV_105
SymbolicName=SAC_UNKNOWN_COMMAND
Language=English
Unrecognized command. Try the 'help' command for more details.
.