https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d6dc1fd2310ed67891edc27a49aacc2eb11220f3

commit d6dc1fd2310ed67891edc27a49aacc2eb11220f3
Author:     Pierre Schweitzer <pie...@reactos.org>
AuthorDate: Tue Jan 1 21:58:18 2019 +0100
Commit:     Pierre Schweitzer <pie...@reactos.org>
CommitDate: Tue Jan 1 22:00:56 2019 +0100

    [NTOSKRNL] Add a raw implementation of !irpfind in kdbg
    
    This is far from perfect, and totally doesn't match the
    WinDBG way of doing it. Instead of browsing pool to find
    matching 'IRP' tags, we just browse all the processes
    to find the queued IRP. This requires the IRPs to be queued,
    obviously, and will make us miss the leaked IRPs, for instance.
    
    Proper way to do it would be to implement !poolfind and then
    rely on its implementation to find our IRPs.
    
    Perhaps later ;-)
---
 ntoskrnl/kdbg/kdb_cli.c |   3 ++
 ntoskrnl/ps/process.c   | 115 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 118 insertions(+)

diff --git a/ntoskrnl/kdbg/kdb_cli.c b/ntoskrnl/kdbg/kdb_cli.c
index 3fce1977d9..37ad987b79 100644
--- a/ntoskrnl/kdbg/kdb_cli.c
+++ b/ntoskrnl/kdbg/kdb_cli.c
@@ -96,6 +96,8 @@ BOOLEAN ExpKdbgExtPoolUsed(ULONG Argc, PCHAR Argv[]);
 BOOLEAN ExpKdbgExtFileCache(ULONG Argc, PCHAR Argv[]);
 BOOLEAN ExpKdbgExtDefWrites(ULONG Argc, PCHAR Argv[]);
 
+BOOLEAN PspKdbgIrpFind(ULONG Argc, PCHAR Argv[]);
+
 #ifdef __ROS_DWARF__
 static BOOLEAN KdbpCmdPrintStruct(ULONG Argc, PCHAR Argv[]);
 #endif
@@ -190,6 +192,7 @@ static const struct
     { "!poolused", "!poolused [Flags [Tag]]", "Display pool usage.", 
ExpKdbgExtPoolUsed },
     { "!filecache", "!filecache", "Display cache usage.", ExpKdbgExtFileCache 
},
     { "!defwrites", "!defwrites", "Display cache write values.", 
ExpKdbgExtDefWrites },
+    { "!irpfind", "!irpfind [criteria data]", "Lists IRPs potentially matching 
criteria", PspKdbgIrpFind },
 };
 
 /* FUNCTIONS *****************************************************************/
diff --git a/ntoskrnl/ps/process.c b/ntoskrnl/ps/process.c
index c6962762e3..3554d601c1 100644
--- a/ntoskrnl/ps/process.c
+++ b/ntoskrnl/ps/process.c
@@ -1614,4 +1614,119 @@ NtOpenProcess(OUT PHANDLE ProcessHandle,
     /* Return status */
     return Status;
 }
+
+#if DBG && defined(KDBG)
+BOOLEAN
+PspKdbgIrpFind(
+    ULONG Argc,
+    PCHAR Argv[])
+{
+    PLIST_ENTRY PsEntry, TdEntry, IrpEntry;
+    PEPROCESS Process = NULL;
+    PETHREAD Thread = NULL;
+    PIRP Irp = NULL;
+    PIO_STACK_LOCATION IoStack = NULL;
+    PUNICODE_STRING DriverName;
+    ULONG_PTR SData = 0;
+    ULONG Criteria = 0;
+
+    /*
+     * FIXME: To improve, badly
+     * This should just be a wrapper over !poolfind
+     * As a hack, here we just browse all the queued IRPs
+     * and return them
+     * If that's not *that* wrong, it makes sure that leaked
+     * IRPs are invisible!
+     * We also don't care about pool type, nor address start
+     */
+
+    /* Gets the criteria and its data */
+    if (Argc > 2)
+    {
+        if (!KdbpGetHexNumber(Argv[2], &SData))
+        {
+            SData = 0;
+        }
+        else
+        {
+            if (strcmp(Argv[1], "device") == 0)
+            {
+                Criteria = 0x1;
+            }
+            else if (strcmp(Argv[1], "fileobject") == 0)
+            {
+                Criteria = 0x2;
+            }
+            else if (strcmp(Argv[1], "mdlprocess") == 0)
+            {
+                Criteria = 0x4;
+            }
+            else if (strcmp(Argv[1], "thread") == 0)
+            {
+                Criteria = 0x8;
+            }
+            else if (strcmp(Argv[1], "userevent") == 0)
+            {
+                Criteria = 0x10;
+            }
+            else if (strcmp(Argv[1], "arg") == 0)
+            {
+                Criteria = 0x1f;
+            }
+        }
+    }
+
+    PsEntry = PsActiveProcessHead.Flink;
+    /* Loop the process list */
+    while (PsEntry != &PsActiveProcessHead)
+    {
+        /* Get the process */
+        Process = CONTAINING_RECORD(PsEntry, EPROCESS, ActiveProcessLinks);
+
+        /* Loop the thread list */
+        TdEntry = Process->ThreadListHead.Flink;
+        while (TdEntry != &Process->ThreadListHead)
+        {
+            /* Get the thread */
+            Thread = CONTAINING_RECORD(TdEntry, ETHREAD, ThreadListEntry);
+
+            /* Loop the IRP list */
+            IrpEntry = Thread->IrpList.Flink;
+            while (IrpEntry != &Thread->IrpList)
+            {
+                /* Get the IRP and its current stack */
+                Irp = CONTAINING_RECORD(IrpEntry, IRP, ThreadListEntry);
+                IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+                /* Get associated driver */
+                if (IoStack->DeviceObject && 
IoStack->DeviceObject->DriverObject)
+                    DriverName = 
&IoStack->DeviceObject->DriverObject->DriverName;
+                else
+                    DriverName = NULL;
+
+                /* Display if: no data, no criteria or if criteria matches 
data */
+                if (SData == 0 || Criteria == 0 ||
+                    (Criteria & 0x1 && SData == 
(ULONG_PTR)IoStack->DeviceObject) ||
+                    (Criteria & 0x2 && SData == 
(ULONG_PTR)Irp->Tail.Overlay.OriginalFileObject) ||
+                    (Criteria & 0x4 && Irp->MdlAddress && SData == 
(ULONG_PTR)Irp->MdlAddress->Process) ||
+                    (Criteria & 0x8 && SData == 
(ULONG_PTR)Irp->Tail.Overlay.Thread) ||
+                    (Criteria & 0x10 && SData == (ULONG_PTR)Irp->UserEvent))
+                {
+                    KdbpPrint("%p Thread %p current stack belongs to %wZ\n", 
Irp, Thread, DriverName);
+                }
+
+                IrpEntry = IrpEntry->Flink;
+            }
+
+            TdEntry = TdEntry->Flink;
+        }
+
+        PsEntry = PsEntry->Flink;
+    }
+
+    return TRUE;
+}
+
+#endif // DBG && KDBG
+
 /* EOF */

Reply via email to