*/
/*
* PROJECT: ReactOS kernel
- * FILE: ntoskrnl/dbg/kdb_cli.c
+ * FILE: ntoskrnl/kdbg/kdb_cli.c
* PURPOSE: Kernel debugger command line interface
* PROGRAMMER: Gregor Anich (blight@blight.eu.org)
* Hervé Poussineau
static BOOLEAN KdbpCmdTss(ULONG Argc, PCHAR Argv[]);
static BOOLEAN KdbpCmdBugCheck(ULONG Argc, PCHAR Argv[]);
+static BOOLEAN KdbpCmdReboot(ULONG Argc, PCHAR Argv[]);
static BOOLEAN KdbpCmdFilter(ULONG Argc, PCHAR Argv[]);
static BOOLEAN KdbpCmdSet(ULONG Argc, PCHAR Argv[]);
static BOOLEAN KdbpCmdHelp(ULONG Argc, PCHAR Argv[]);
static BOOLEAN KdbpCmdDmesg(ULONG Argc, PCHAR Argv[]);
+BOOLEAN ExpKdbgExtPool(ULONG Argc, PCHAR Argv[]);
+
#ifdef __ROS_DWARF__
static BOOLEAN KdbpCmdPrintStruct(ULONG Argc, PCHAR Argv[]);
#endif
/* GLOBALS *******************************************************************/
+static PKDBG_CLI_ROUTINE KdbCliCallbacks[10];
static BOOLEAN KdbUseIntelSyntax = FALSE; /* Set to TRUE for intel syntax */
static BOOLEAN KdbBreakOnModuleLoad = FALSE; /* Set to TRUE to break into KDB when a module is loaded */
/* Others */
{ NULL, NULL, "Others", NULL },
{ "bugcheck", "bugcheck", "Bugchecks the system.", KdbpCmdBugCheck },
+ { "reboot", "reboot", "Reboots the system.", KdbpCmdReboot},
{ "filter", "filter [error|warning|trace|info|level]+|-[componentname|default]", "Enable/disable debug channels", KdbpCmdFilter },
{ "set", "set [var] [value]", "Sets var to value or displays value of var.", KdbpCmdSet },
{ "dmesg", "dmesg", "Display debug messages on screen, with navigation on pages.", KdbpCmdDmesg },
{ "kmsg", "kmsg", "Kernel dmesg. Alias for dmesg.", KdbpCmdDmesg },
- { "help", "help", "Display help screen.", KdbpCmdHelp }
+ { "help", "help", "Display help screen.", KdbpCmdHelp },
+ { "!pool", "!pool [Address [Flags]]", "Display information about pool allocations.", ExpKdbgExtPool }
};
/* FUNCTIONS *****************************************************************/
}
ComponentTable[] =
{
- { "DEFAULT", DPFLTR_DEFAULT_ID },
+ { "DEFAULT", MAXULONG },
{ "SYSTEM", DPFLTR_SYSTEM_ID },
{ "SMSS", DPFLTR_SMSS_ID },
{ "SETUP", DPFLTR_SETUP_ID },
return Ok;
}
+BOOLEAN
+NTAPI
+KdbpGetHexNumber(
+ IN PCHAR pszNum,
+ OUT ULONG_PTR *pulValue)
+{
+ char *endptr;
+
+ /* Skip optional '0x' prefix */
+ if ((pszNum[0] == '0') && ((pszNum[1] == 'x') || (pszNum[1] == 'X')))
+ pszNum += 2;
+
+ /* Make a number from the string (hex) */
+ *pulValue = strtoul(pszNum, &endptr, 16);
+
+ return (*endptr == '\0');
+}
+
/*!\brief Evaluates an expression and displays the result.
*/
static BOOLEAN
else if (Argv[0][0] == 'c') /* cregs */
{
ULONG Cr0, Cr2, Cr3, Cr4;
- KDESCRIPTOR Gdtr, Idtr;
+ KDESCRIPTOR Gdtr = {0, 0, 0}, Idtr = {0, 0, 0};
USHORT Ldtr;
static const PCHAR Cr0Bits[32] = { " PE", " MP", " EM", " TS", " ET", " NE", NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
return FALSE;
}
+static BOOLEAN
+KdbpCmdReboot(
+ ULONG Argc,
+ PCHAR Argv[])
+{
+ /* Reboot immediately (we do not return) */
+ HalReturnToFirmware(HalRebootRoutine);
+ return FALSE;
+}
+
+
VOID
KdbpPager(
IN PCHAR Buffer,
if (Buffer != Orig)
{
KdbRepeatLastCommand = TRUE;
- RtlStringCbCopyA(LastCommand, sizeof(LastCommand), Orig);
*Buffer = '\0';
+ RtlStringCbCopyA(LastCommand, sizeof(LastCommand), Orig);
}
else if (KdbRepeatLastCommand)
RtlStringCbCopyA(Buffer, Size, LastCommand);
}
}
+
+BOOLEAN
+NTAPI
+KdbRegisterCliCallback(
+ PVOID Callback,
+ BOOLEAN Deregister)
+{
+ ULONG i;
+
+ /* Loop all entries */
+ for (i = 0; i < _countof(KdbCliCallbacks); i++)
+ {
+ /* Check if deregistering was requested */
+ if (Deregister)
+ {
+ /* Check if this entry is the one that was registered */
+ if (KdbCliCallbacks[i] == Callback)
+ {
+ /* Delete it and report success */
+ KdbCliCallbacks[i] = NULL;
+ return TRUE;
+ }
+ }
+ else
+ {
+ /* Check if this entry is free */
+ if (KdbCliCallbacks[i] == NULL)
+ {
+ /* Set it and and report success */
+ KdbCliCallbacks[i] = Callback;
+ return TRUE;
+ }
+ }
+ }
+
+ /* Unsuccessful */
+ return FALSE;
+}
+
+/*! \brief Invokes registered CLI callbacks until one of them handled the
+ * Command.
+ *
+ * \param Command - Command line to parse and execute if possible.
+ * \param Argc - Number of arguments in Argv
+ * \param Argv - Array of strings, each of them containing one argument.
+ *
+ * \return TRUE, if the command was handled, FALSE if it was not handled.
+ */
+static
+BOOLEAN
+KdbpInvokeCliCallbacks(
+ IN PCHAR Command,
+ IN ULONG Argc,
+ IN PCH Argv[])
+{
+ ULONG i;
+
+ /* Loop all entries */
+ for (i = 0; i < _countof(KdbCliCallbacks); i++)
+ {
+ /* Check if this entry is registered */
+ if (KdbCliCallbacks[i])
+ {
+ /* Invoke the callback and check if it handled the command */
+ if (KdbCliCallbacks[i](Command, Argc, Argv))
+ {
+ return TRUE;
+ }
+ }
+ }
+
+ /* None of the callbacks handled the command */
+ return FALSE;
+}
+
+
/*!\brief Parses command line and executes command if found
*
* \param Command Command line to parse and execute if possible.
ULONG i;
PCHAR p;
ULONG Argc;
+ // FIXME: for what do we need a 1024 characters command line and 256 tokens?
static PCH Argv[256];
static CHAR OrigCommand[1024];
}
}
+ /* Now invoke the registered callbacks */
+ if (KdbpInvokeCliCallbacks(Command, Argc, Argv))
+ {
+ return TRUE;
+ }
+
KdbpPrint("Command '%s' is unknown.\n", OrigCommand);
return TRUE;
}
* call this function if KdbInitFileBuffer is not NULL.
*/
VOID
-KdbpCliInterpretInitFile()
+KdbpCliInterpretInitFile(VOID)
{
PCHAR p1, p2;
INT i;
/*!\brief Called when KDB is initialized
*
- * Reads the KDBinit file from the SystemRoot\system32\drivers\etc directory and executes it.
+ * Reads the KDBinit file from the SystemRoot\System32\drivers\etc directory and executes it.
*/
VOID
-KdbpCliInit()
+KdbpCliInit(VOID)
{
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
ULONG OldEflags;
/* Initialize the object attributes */
- RtlInitUnicodeString(&FileName, L"\\SystemRoot\\system32\\drivers\\etc\\KDBinit");
+ RtlInitUnicodeString(&FileName, L"\\SystemRoot\\System32\\drivers\\etc\\KDBinit");
InitializeObjectAttributes(&ObjectAttributes, &FileName, 0, NULL, NULL);
/* Open the file */
- Status = ZwOpenFile(&hFile, FILE_READ_DATA, &ObjectAttributes, &Iosb, 0,
+ Status = ZwOpenFile(&hFile, FILE_READ_DATA | SYNCHRONIZE,
+ &ObjectAttributes, &Iosb, 0,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT |
FILE_NO_INTERMEDIATE_BUFFERING);
if (!NT_SUCCESS(Status))
{
- DPRINT("Could not open \\SystemRoot\\system32\\drivers\\etc\\KDBinit (Status 0x%x)", Status);
+ DPRINT("Could not open \\SystemRoot\\System32\\drivers\\etc\\KDBinit (Status 0x%x)", Status);
return;
}
if (!NT_SUCCESS(Status))
{
ZwClose(hFile);
- DPRINT("Could not query size of \\SystemRoot\\system32\\drivers\\etc\\KDBinit (Status 0x%x)", Status);
+ DPRINT("Could not query size of \\SystemRoot\\System32\\drivers\\etc\\KDBinit (Status 0x%x)", Status);
return;
}
FileSize = FileStdInfo.EndOfFile.u.LowPart;
* DbgPrompt does not null terminate, but it does
*/
*(PCHAR)(OutString + i) = 0;
-
- /* Print a new line */
- KdPortPutByteEx(&SerialPortInfo, '\r');
- KdPortPutByteEx(&SerialPortInfo, '\n');
-
- /* Release spinlock */
- KiReleaseSpinLock(&KdpSerialSpinLock);
-
- /* Lower IRQL back */
- KeLowerIrql(OldIrql);
-
- /* Return the length */
- return OutStringLength + 1;
+ break;
}
/* Write it back and print it to the log */
KeLowerIrql(OldIrql);
/* Return the length */
- return OutStringLength;
+ return i;
}