https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c5a35ecd3761b9a4dbdc8…
commit c5a35ecd3761b9a4dbdc87c66447b70fb9d4e785
Author: Pierre Schweitzer <pierre(a)reactos.org>
AuthorDate: Sat Apr 28 09:34:10 2018 +0200
Commit: Pierre Schweitzer <pierre(a)reactos.org>
CommitDate: Sun Apr 29 12:15:11 2018 +0200
[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
---
drivers/filesystems/fastfat/CMakeLists.txt | 1 +
drivers/filesystems/fastfat/cleanup.c | 3 +
drivers/filesystems/fastfat/close.c | 3 +
drivers/filesystems/fastfat/fcb.c | 70 ++++++++++++-
drivers/filesystems/fastfat/iface.c | 28 +++++
drivers/filesystems/fastfat/kdbg.c | 161 +++++++++++++++++++++++++++++
drivers/filesystems/fastfat/vfat.h | 35 ++++++-
7 files changed, 297 insertions(+), 4 deletions(-)
diff --git a/drivers/filesystems/fastfat/CMakeLists.txt
b/drivers/filesystems/fastfat/CMakeLists.txt
index 087f9e3f62..cc69334b01 100644
--- a/drivers/filesystems/fastfat/CMakeLists.txt
+++ b/drivers/filesystems/fastfat/CMakeLists.txt
@@ -15,6 +15,7 @@ list(APPEND SOURCE
flush.c
fsctl.c
iface.c
+ kdbg.c
misc.c
pnp.c
rw.c
diff --git a/drivers/filesystems/fastfat/cleanup.c
b/drivers/filesystems/fastfat/cleanup.c
index 580ed807a3..3ab4a101d1 100644
--- a/drivers/filesystems/fastfat/cleanup.c
+++ b/drivers/filesystems/fastfat/cleanup.c
@@ -138,6 +138,9 @@ VfatCleanupFile(
}
FileObject->Flags |= FO_CLEANUP_COMPLETE;
+#ifdef KDBG
+ pFcb->Flags |= FCB_CLEANED_UP;
+#endif
ExReleaseResourceLite(&pFcb->PagingIoResource);
ExReleaseResourceLite(&pFcb->MainResource);
diff --git a/drivers/filesystems/fastfat/close.c b/drivers/filesystems/fastfat/close.c
index b4e5fda308..992ccac4c2 100644
--- a/drivers/filesystems/fastfat/close.c
+++ b/drivers/filesystems/fastfat/close.c
@@ -48,6 +48,9 @@ VfatCloseFile(
}
else
{
+#ifdef KDBG
+ pFcb->Flags |= FCB_CLOSED;
+#endif
vfatReleaseFCB(DeviceExt, pFcb);
}
diff --git a/drivers/filesystems/fastfat/fcb.c b/drivers/filesystems/fastfat/fcb.c
index f6734a675e..33124bc51b 100644
--- a/drivers/filesystems/fastfat/fcb.c
+++ b/drivers/filesystems/fastfat/fcb.c
@@ -24,6 +24,10 @@
#define TAG_FCB 'BCFV'
+#ifdef KDBG
+extern UNICODE_STRING DebugFile;
+#endif
+
/* -------------------------------------------------------- PUBLICS */
static
@@ -267,6 +271,13 @@ VOID
vfatDestroyFCB(
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);
if (!vfatFCBIsRoot(pFCB) &&
!BooleanFlagOn(pFCB->Flags, FCB_IS_FAT) &&
!BooleanFlagOn(pFCB->Flags, FCB_IS_VOLUME))
@@ -288,10 +299,28 @@ vfatFCBIsRoot(
}
VOID
+#ifndef KDBG
vfatGrabFCB(
+#else
+_vfatGrabFCB(
+#endif
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(pFCB != pVCB->VolumeFcb);
@@ -300,14 +329,32 @@ vfatGrabFCB(
}
VOID
+#ifndef KDBG
vfatReleaseFCB(
+#else
+_vfatReleaseFCB(
+#endif
PDEVICE_EXTENSION pVCB,
- PVFATFCB pFCB)
+ PVFATFCB pFCB
+#ifdef KDBG
+ ,
+ PCSTR File,
+ ULONG Line,
+ PCSTR Func
+#endif
+)
{
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",
pFCB, &pFCB->PathNameU, pFCB->RefCount);
+#endif
ASSERT(ExIsResourceAcquiredExclusive(&pVCB->DirResource));
@@ -605,6 +652,13 @@ vfatFCBInitializeCacheFromVolume(
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);
if (newCCB == NULL)
{
@@ -762,6 +816,13 @@ vfatAttachFCBToFileObject(
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);
if (newCCB == NULL)
{
@@ -774,6 +835,11 @@ vfatAttachFCBToFileObject(
fileObject->FsContext2 = newCCB;
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;
}
diff --git a/drivers/filesystems/fastfat/iface.c b/drivers/filesystems/fastfat/iface.c
index 02e570ea45..b73854dbcd 100644
--- a/drivers/filesystems/fastfat/iface.c
+++ b/drivers/filesystems/fastfat/iface.c
@@ -34,6 +34,24 @@
#pragma alloc_text(INIT, DriverEntry)
#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 *****************************************************************/
@@ -137,6 +155,16 @@ DriverEntry(
ExInitializeResourceLite(&VfatGlobalData->VolumeListLock);
InitializeListHead(&VfatGlobalData->VolumeListHead);
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;
}
diff --git a/drivers/filesystems/fastfat/kdbg.c b/drivers/filesystems/fastfat/kdbg.c
new file mode 100644
index 0000000000..b278329299
--- /dev/null
+++ b/drivers/filesystems/fastfat/kdbg.c
@@ -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(a)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
diff --git a/drivers/filesystems/fastfat/vfat.h b/drivers/filesystems/fastfat/vfat.h
index 429120c804..0de6a486a0 100644
--- a/drivers/filesystems/fastfat/vfat.h
+++ b/drivers/filesystems/fastfat/vfat.h
@@ -409,6 +409,10 @@ extern PVFAT_GLOBAL_DATA VfatGlobalData;
#define FCB_IS_PAGE_FILE 0x0008
#define FCB_IS_VOLUME 0x0010
#define FCB_IS_DIRTY 0x0020
+#ifdef KDBG
+#define FCB_CLEANED_UP 0x0040
+#define FCB_CLOSED 0x0080
+#endif
#define NODE_TYPE_FCB ((CSHORT)0x0502)
@@ -898,14 +902,41 @@ vfatDestroyCCB(
PVFATCCB pCcb);
VOID
+#ifndef KDBG
vfatGrabFCB(
+#else
+_vfatGrabFCB(
+#endif
PDEVICE_EXTENSION pVCB,
- PVFATFCB pFCB);
+ PVFATFCB pFCB
+#ifdef KDBG
+ ,
+ PCSTR File,
+ ULONG Line,
+ PCSTR Func
+#endif
+ );
VOID
+#ifndef KDBG
vfatReleaseFCB(
+#else
+_vfatReleaseFCB(
+#endif
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
vfatGrabFCBFromTable(