mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
[FASTFAT] Introduce a KDBG extension.
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
This commit is contained in:
parent
cb20bf8c90
commit
c5a35ecd37
7 changed files with 297 additions and 4 deletions
|
@ -15,6 +15,7 @@ list(APPEND SOURCE
|
||||||
flush.c
|
flush.c
|
||||||
fsctl.c
|
fsctl.c
|
||||||
iface.c
|
iface.c
|
||||||
|
kdbg.c
|
||||||
misc.c
|
misc.c
|
||||||
pnp.c
|
pnp.c
|
||||||
rw.c
|
rw.c
|
||||||
|
|
|
@ -138,6 +138,9 @@ VfatCleanupFile(
|
||||||
}
|
}
|
||||||
|
|
||||||
FileObject->Flags |= FO_CLEANUP_COMPLETE;
|
FileObject->Flags |= FO_CLEANUP_COMPLETE;
|
||||||
|
#ifdef KDBG
|
||||||
|
pFcb->Flags |= FCB_CLEANED_UP;
|
||||||
|
#endif
|
||||||
|
|
||||||
ExReleaseResourceLite(&pFcb->PagingIoResource);
|
ExReleaseResourceLite(&pFcb->PagingIoResource);
|
||||||
ExReleaseResourceLite(&pFcb->MainResource);
|
ExReleaseResourceLite(&pFcb->MainResource);
|
||||||
|
|
|
@ -48,6 +48,9 @@ VfatCloseFile(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#ifdef KDBG
|
||||||
|
pFcb->Flags |= FCB_CLOSED;
|
||||||
|
#endif
|
||||||
vfatReleaseFCB(DeviceExt, pFcb);
|
vfatReleaseFCB(DeviceExt, pFcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,10 @@
|
||||||
|
|
||||||
#define TAG_FCB 'BCFV'
|
#define TAG_FCB 'BCFV'
|
||||||
|
|
||||||
|
#ifdef KDBG
|
||||||
|
extern UNICODE_STRING DebugFile;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* -------------------------------------------------------- PUBLICS */
|
/* -------------------------------------------------------- PUBLICS */
|
||||||
|
|
||||||
static
|
static
|
||||||
|
@ -267,6 +271,13 @@ VOID
|
||||||
vfatDestroyFCB(
|
vfatDestroyFCB(
|
||||||
PVFATFCB pFCB)
|
PVFATFCB pFCB)
|
||||||
{
|
{
|
||||||
|
#ifdef KDBG
|
||||||
|
if (DebugFile.Buffer != NULL && FsRtlIsNameInExpression(&DebugFile, &pFCB->LongNameU, FALSE, NULL))
|
||||||
|
{
|
||||||
|
DPRINT1("Destroying: %p (%wZ) %d\n", pFCB, &pFCB->PathNameU, pFCB->RefCount);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
FsRtlUninitializeFileLock(&pFCB->FileLock);
|
FsRtlUninitializeFileLock(&pFCB->FileLock);
|
||||||
if (!vfatFCBIsRoot(pFCB) &&
|
if (!vfatFCBIsRoot(pFCB) &&
|
||||||
!BooleanFlagOn(pFCB->Flags, FCB_IS_FAT) && !BooleanFlagOn(pFCB->Flags, FCB_IS_VOLUME))
|
!BooleanFlagOn(pFCB->Flags, FCB_IS_FAT) && !BooleanFlagOn(pFCB->Flags, FCB_IS_VOLUME))
|
||||||
|
@ -288,10 +299,28 @@ vfatFCBIsRoot(
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
#ifndef KDBG
|
||||||
vfatGrabFCB(
|
vfatGrabFCB(
|
||||||
|
#else
|
||||||
|
_vfatGrabFCB(
|
||||||
|
#endif
|
||||||
PDEVICE_EXTENSION pVCB,
|
PDEVICE_EXTENSION pVCB,
|
||||||
PVFATFCB pFCB)
|
PVFATFCB pFCB
|
||||||
|
#ifdef KDBG
|
||||||
|
,
|
||||||
|
PCSTR File,
|
||||||
|
ULONG Line,
|
||||||
|
PCSTR Func
|
||||||
|
#endif
|
||||||
|
)
|
||||||
{
|
{
|
||||||
|
#ifdef KDBG
|
||||||
|
if (DebugFile.Buffer != NULL && FsRtlIsNameInExpression(&DebugFile, &pFCB->LongNameU, FALSE, NULL))
|
||||||
|
{
|
||||||
|
DPRINT1("Inc ref count (%d, oc: %d) for: %p (%wZ) at: %s(%d) %s\n", pFCB->RefCount, pFCB->OpenHandleCount, pFCB, &pFCB->PathNameU, File, Line, Func);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ASSERT(ExIsResourceAcquiredExclusive(&pVCB->DirResource));
|
ASSERT(ExIsResourceAcquiredExclusive(&pVCB->DirResource));
|
||||||
|
|
||||||
ASSERT(pFCB != pVCB->VolumeFcb);
|
ASSERT(pFCB != pVCB->VolumeFcb);
|
||||||
|
@ -300,14 +329,32 @@ vfatGrabFCB(
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
#ifndef KDBG
|
||||||
vfatReleaseFCB(
|
vfatReleaseFCB(
|
||||||
|
#else
|
||||||
|
_vfatReleaseFCB(
|
||||||
|
#endif
|
||||||
PDEVICE_EXTENSION pVCB,
|
PDEVICE_EXTENSION pVCB,
|
||||||
PVFATFCB pFCB)
|
PVFATFCB pFCB
|
||||||
|
#ifdef KDBG
|
||||||
|
,
|
||||||
|
PCSTR File,
|
||||||
|
ULONG Line,
|
||||||
|
PCSTR Func
|
||||||
|
#endif
|
||||||
|
)
|
||||||
{
|
{
|
||||||
PVFATFCB tmpFcb;
|
PVFATFCB tmpFcb;
|
||||||
|
|
||||||
|
#ifdef KDBG
|
||||||
|
if (DebugFile.Buffer != NULL && FsRtlIsNameInExpression(&DebugFile, &pFCB->LongNameU, FALSE, NULL))
|
||||||
|
{
|
||||||
|
DPRINT1("Dec ref count (%d, oc: %d) for: %p (%wZ) at: %s(%d) %s\n", pFCB->RefCount, pFCB->OpenHandleCount, pFCB, &pFCB->PathNameU, File, Line, Func);
|
||||||
|
}
|
||||||
|
#else
|
||||||
DPRINT("releasing FCB at %p: %wZ, refCount:%d\n",
|
DPRINT("releasing FCB at %p: %wZ, refCount:%d\n",
|
||||||
pFCB, &pFCB->PathNameU, pFCB->RefCount);
|
pFCB, &pFCB->PathNameU, pFCB->RefCount);
|
||||||
|
#endif
|
||||||
|
|
||||||
ASSERT(ExIsResourceAcquiredExclusive(&pVCB->DirResource));
|
ASSERT(ExIsResourceAcquiredExclusive(&pVCB->DirResource));
|
||||||
|
|
||||||
|
@ -605,6 +652,13 @@ vfatFCBInitializeCacheFromVolume(
|
||||||
|
|
||||||
fileObject = IoCreateStreamFileObject (NULL, vcb->StorageDevice);
|
fileObject = IoCreateStreamFileObject (NULL, vcb->StorageDevice);
|
||||||
|
|
||||||
|
#ifdef KDBG
|
||||||
|
if (DebugFile.Buffer != NULL && FsRtlIsNameInExpression(&DebugFile, &fcb->LongNameU, FALSE, NULL))
|
||||||
|
{
|
||||||
|
DPRINT1("Attaching %p to %p (%d)\n", fcb, fileObject, fcb->RefCount);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
newCCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList);
|
newCCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList);
|
||||||
if (newCCB == NULL)
|
if (newCCB == NULL)
|
||||||
{
|
{
|
||||||
|
@ -762,6 +816,13 @@ vfatAttachFCBToFileObject(
|
||||||
|
|
||||||
UNREFERENCED_PARAMETER(vcb);
|
UNREFERENCED_PARAMETER(vcb);
|
||||||
|
|
||||||
|
#ifdef KDBG
|
||||||
|
if (DebugFile.Buffer != NULL && FsRtlIsNameInExpression(&DebugFile, &fcb->LongNameU, FALSE, NULL))
|
||||||
|
{
|
||||||
|
DPRINT1("Attaching %p to %p (%d)\n", fcb, fileObject, fcb->RefCount);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
newCCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList);
|
newCCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList);
|
||||||
if (newCCB == NULL)
|
if (newCCB == NULL)
|
||||||
{
|
{
|
||||||
|
@ -774,6 +835,11 @@ vfatAttachFCBToFileObject(
|
||||||
fileObject->FsContext2 = newCCB;
|
fileObject->FsContext2 = newCCB;
|
||||||
DPRINT("file open: fcb:%p PathName:%wZ\n", fcb, &fcb->PathNameU);
|
DPRINT("file open: fcb:%p PathName:%wZ\n", fcb, &fcb->PathNameU);
|
||||||
|
|
||||||
|
#ifdef KDBG
|
||||||
|
fcb->Flags &= ~FCB_CLEANED_UP;
|
||||||
|
fcb->Flags &= ~FCB_CLOSED;
|
||||||
|
#endif
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,24 @@
|
||||||
#pragma alloc_text(INIT, DriverEntry)
|
#pragma alloc_text(INIT, DriverEntry)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef KDBG
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
KdSystemDebugControl(IN ULONG Command,
|
||||||
|
IN PVOID InputBuffer,
|
||||||
|
IN ULONG InputBufferLength,
|
||||||
|
OUT PVOID OutputBuffer,
|
||||||
|
IN ULONG OutputBufferLength,
|
||||||
|
IN OUT PULONG ReturnLength,
|
||||||
|
IN KPROCESSOR_MODE PreviousMode);
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
vfatKdbgHandler(
|
||||||
|
IN PCHAR Command,
|
||||||
|
IN ULONG Argc,
|
||||||
|
IN PCH Argv[]);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* GLOBALS *****************************************************************/
|
/* GLOBALS *****************************************************************/
|
||||||
|
|
||||||
|
@ -137,6 +155,16 @@ DriverEntry(
|
||||||
ExInitializeResourceLite(&VfatGlobalData->VolumeListLock);
|
ExInitializeResourceLite(&VfatGlobalData->VolumeListLock);
|
||||||
InitializeListHead(&VfatGlobalData->VolumeListHead);
|
InitializeListHead(&VfatGlobalData->VolumeListHead);
|
||||||
IoRegisterFileSystem(DeviceObject);
|
IoRegisterFileSystem(DeviceObject);
|
||||||
|
|
||||||
|
#ifdef KDBG
|
||||||
|
{
|
||||||
|
BOOLEAN Registered;
|
||||||
|
|
||||||
|
Registered = KdSystemDebugControl('RbdK', vfatKdbgHandler, FALSE, NULL, 0, NULL, KernelMode);
|
||||||
|
DPRINT1("FastFAT KDBG extension registered: %s\n", (Registered ? "yes" : "no"));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
161
drivers/filesystems/fastfat/kdbg.c
Normal file
161
drivers/filesystems/fastfat/kdbg.c
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
/*
|
||||||
|
* 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
|
|
@ -409,6 +409,10 @@ extern PVFAT_GLOBAL_DATA VfatGlobalData;
|
||||||
#define FCB_IS_PAGE_FILE 0x0008
|
#define FCB_IS_PAGE_FILE 0x0008
|
||||||
#define FCB_IS_VOLUME 0x0010
|
#define FCB_IS_VOLUME 0x0010
|
||||||
#define FCB_IS_DIRTY 0x0020
|
#define FCB_IS_DIRTY 0x0020
|
||||||
|
#ifdef KDBG
|
||||||
|
#define FCB_CLEANED_UP 0x0040
|
||||||
|
#define FCB_CLOSED 0x0080
|
||||||
|
#endif
|
||||||
|
|
||||||
#define NODE_TYPE_FCB ((CSHORT)0x0502)
|
#define NODE_TYPE_FCB ((CSHORT)0x0502)
|
||||||
|
|
||||||
|
@ -898,14 +902,41 @@ vfatDestroyCCB(
|
||||||
PVFATCCB pCcb);
|
PVFATCCB pCcb);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
#ifndef KDBG
|
||||||
vfatGrabFCB(
|
vfatGrabFCB(
|
||||||
|
#else
|
||||||
|
_vfatGrabFCB(
|
||||||
|
#endif
|
||||||
PDEVICE_EXTENSION pVCB,
|
PDEVICE_EXTENSION pVCB,
|
||||||
PVFATFCB pFCB);
|
PVFATFCB pFCB
|
||||||
|
#ifdef KDBG
|
||||||
|
,
|
||||||
|
PCSTR File,
|
||||||
|
ULONG Line,
|
||||||
|
PCSTR Func
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
#ifndef KDBG
|
||||||
vfatReleaseFCB(
|
vfatReleaseFCB(
|
||||||
|
#else
|
||||||
|
_vfatReleaseFCB(
|
||||||
|
#endif
|
||||||
PDEVICE_EXTENSION pVCB,
|
PDEVICE_EXTENSION pVCB,
|
||||||
PVFATFCB pFCB);
|
PVFATFCB pFCB
|
||||||
|
#ifdef KDBG
|
||||||
|
,
|
||||||
|
PCSTR File,
|
||||||
|
ULONG Line,
|
||||||
|
PCSTR Func
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
|
#ifdef KDBG
|
||||||
|
#define vfatGrabFCB(v, f) _vfatGrabFCB(v, f, __FILE__, __LINE__, __FUNCTION__)
|
||||||
|
#define vfatReleaseFCB(v, f) _vfatReleaseFCB(v, f, __FILE__, __LINE__, __FUNCTION__)
|
||||||
|
#endif
|
||||||
|
|
||||||
PVFATFCB
|
PVFATFCB
|
||||||
vfatGrabFCBFromTable(
|
vfatGrabFCBFromTable(
|
||||||
|
|
Loading…
Reference in a new issue