mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
c5a35ecd37
This is a PoC of what it's possible to realize thanks to an already existing hack in ntoskrnl :-). With this extension, on the kdb:> prompt, you're able to type in commands that will be handled by the FastFAT driver and not by the kernel, allowing internal debug, not possible otherwise. So far, three commands exist: - ?fat.vols: lists all the mounted volumes by FastFAT - ?fat.files: lists all the files on a specific volume (with their attributes) - ?fat.setdbgfile: allows watching on specifics files lifetime This is obviously only the begin and could be greatly improved. For instance, this is what allowed to debug CORE-14557
161 lines
4.3 KiB
C
161 lines
4.3 KiB
C
/*
|
|
* FILE: drivers/filesystems/fastfat/kdbg.c
|
|
* PURPOSE: KDBG extension.
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS kernel
|
|
* PROGRAMMER: Pierre Schweitzer (pierre@reactos.org)
|
|
*/
|
|
|
|
/* ------------------------------------------------------- INCLUDES */
|
|
|
|
#include "vfat.h"
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
/* -------------------------------------------------------- DEFINES */
|
|
|
|
#ifdef KDBG
|
|
UNICODE_STRING DebugFile = {0, 0, NULL};
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
vfatKdbgHandler(
|
|
IN PCHAR Command,
|
|
IN ULONG Argc,
|
|
IN PCH Argv[])
|
|
{
|
|
ULONG Len;
|
|
|
|
Len = strlen(Command);
|
|
if (Len < sizeof("?fat."))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (Command[0] != '?' || Command[1] != 'f' ||
|
|
Command[2] != 'a' || Command[3] != 't' ||
|
|
Command[4] != '.')
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
Command += (sizeof("?fat.") - sizeof(ANSI_NULL));
|
|
if (strcmp(Command, "vols") == 0)
|
|
{
|
|
ULONG Count = 0;
|
|
PLIST_ENTRY ListEntry;
|
|
PDEVICE_EXTENSION DeviceExt;
|
|
|
|
for (ListEntry = VfatGlobalData->VolumeListHead.Flink;
|
|
ListEntry != &VfatGlobalData->VolumeListHead;
|
|
ListEntry = ListEntry->Flink)
|
|
{
|
|
DeviceExt = CONTAINING_RECORD(ListEntry, DEVICE_EXTENSION, VolumeListEntry);
|
|
DPRINT1("Volume: %p with VCB: %p\n", DeviceExt->VolumeDevice, DeviceExt);
|
|
++Count;
|
|
}
|
|
|
|
if (Count == 0)
|
|
{
|
|
DPRINT1("No volume found\n");
|
|
}
|
|
}
|
|
else if (strcmp(Command, "files") == 0)
|
|
{
|
|
if (Argc != 2)
|
|
{
|
|
DPRINT1("Please provide a volume or a VCB!\n");
|
|
}
|
|
else
|
|
{
|
|
PLIST_ENTRY ListEntry;
|
|
PDEVICE_EXTENSION DeviceExt;
|
|
|
|
for (ListEntry = VfatGlobalData->VolumeListHead.Flink;
|
|
ListEntry != &VfatGlobalData->VolumeListHead;
|
|
ListEntry = ListEntry->Flink)
|
|
{
|
|
CHAR Volume[17];
|
|
|
|
DeviceExt = CONTAINING_RECORD(ListEntry, DEVICE_EXTENSION, VolumeListEntry);
|
|
sprintf(Volume, "%p", DeviceExt);
|
|
if (strcmp(Volume, Argv[1]) == 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
sprintf(Volume, "%p", DeviceExt->VolumeDevice);
|
|
if (strcmp(Volume, Argv[1]) == 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
DeviceExt = NULL;
|
|
}
|
|
|
|
if (DeviceExt == NULL)
|
|
{
|
|
DPRINT1("No volume %s found!\n", Argv[1]);
|
|
}
|
|
else
|
|
{
|
|
PVFATFCB Fcb;
|
|
|
|
for (ListEntry = DeviceExt->FcbListHead.Flink;
|
|
ListEntry != &DeviceExt->FcbListHead;
|
|
ListEntry = ListEntry->Flink)
|
|
{
|
|
Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry);
|
|
DPRINT1("FCB %p (ref: %d, oc: %d %s %s) for FO %p with path: %.*S\n",
|
|
Fcb, Fcb->RefCount, Fcb->OpenHandleCount,
|
|
((Fcb->Flags & FCB_CLEANED_UP) ? "U" : "NU"),
|
|
((Fcb->Flags & FCB_CLOSED) ? "C" : "NC"),
|
|
Fcb->FileObject, Fcb->PathNameU.Length, Fcb->PathNameU.Buffer);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (strcmp(Command, "setdbgfile") == 0)
|
|
{
|
|
if (Argc < 2)
|
|
{
|
|
if (DebugFile.Buffer != NULL)
|
|
{
|
|
ExFreePool(DebugFile.Buffer);
|
|
DebugFile.Length = 0;
|
|
DebugFile.MaximumLength = 0;
|
|
}
|
|
|
|
DPRINT1("Debug file reset\n");
|
|
}
|
|
else
|
|
{
|
|
NTSTATUS Status;
|
|
ANSI_STRING Source;
|
|
|
|
if (DebugFile.Buffer != NULL)
|
|
{
|
|
ExFreePool(DebugFile.Buffer);
|
|
DebugFile.Length = 0;
|
|
DebugFile.MaximumLength = 0;
|
|
}
|
|
|
|
RtlInitAnsiString(&Source, Argv[1]);
|
|
Status = RtlAnsiStringToUnicodeString(&DebugFile, &Source, TRUE);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Debug file set to: %.*S\n", DebugFile.Length, DebugFile.Buffer);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DPRINT1("Unknown command: %s\n", Command);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
#endif
|