From 08c5f648edb33ab280aff43885f68a73d3c3984a Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Mon, 26 Aug 2013 19:45:16 +0000 Subject: [PATCH] [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 --- reactos/drivers/sac/driver/concmd.c | 445 +++++++++++++++++++++--- reactos/drivers/sac/driver/conmgr.c | 17 +- reactos/drivers/sac/driver/sacdrv.h | 13 +- reactos/drivers/sac/driver/vtutf8chan.c | 5 +- reactos/include/reactos/mc/sacmsg.mc | 2 +- 5 files changed, 408 insertions(+), 74 deletions(-) diff --git a/reactos/drivers/sac/driver/concmd.c b/reactos/drivers/sac/driver/concmd.c index c515ce2dc48..5b7a13f5238 100644 --- a/reactos/drivers/sac/driver/concmd.c +++ b/reactos/drivers/sac/driver/concmd.c @@ -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"); } diff --git a/reactos/drivers/sac/driver/conmgr.c b/reactos/drivers/sac/driver/conmgr.c index b69d8ad838f..b99a103a6a8 100644 --- a/reactos/drivers/sac/driver/conmgr.c +++ b/reactos/drivers/sac/driver/conmgr.c @@ -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; } } diff --git a/reactos/drivers/sac/driver/sacdrv.h b/reactos/drivers/sac/driver/sacdrv.h index 5dfd18dce2b..74d03817d8e 100644 --- a/reactos/drivers/sac/driver/sacdrv.h +++ b/reactos/drivers/sac/driver/sacdrv.h @@ -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; diff --git a/reactos/drivers/sac/driver/vtutf8chan.c b/reactos/drivers/sac/driver/vtutf8chan.c index baff1981c3d..69317fb7bc6 100644 --- a/reactos/drivers/sac/driver/vtutf8chan.c +++ b/reactos/drivers/sac/driver/vtutf8chan.c @@ -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)) { diff --git a/reactos/include/reactos/mc/sacmsg.mc b/reactos/include/reactos/mc/sacmsg.mc index fd129bca0bb..65af01f64b5 100644 --- a/reactos/include/reactos/mc/sacmsg.mc +++ b/reactos/include/reactos/mc/sacmsg.mc @@ -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. .