[WDF] Add Windows Driver Framework files
[reactos.git] / sdk / lib / drivers / wdf / shared / object / km / wdfpoolkm.cpp
diff --git a/sdk/lib/drivers/wdf/shared/object/km/wdfpoolkm.cpp b/sdk/lib/drivers/wdf/shared/object/km/wdfpoolkm.cpp
new file mode 100644 (file)
index 0000000..8795026
--- /dev/null
@@ -0,0 +1,272 @@
+/*++
+
+Copyright (c) Microsoft Corporation
+
+Module Name:
+
+    wdfpoolkm.cpp
+
+Abstract:
+
+    This module implements the driver frameworks pool routines
+    functionality only applicable in kernel mode
+
+Author:
+
+
+
+
+Environment:
+
+    Kernel mode only
+
+Revision History:
+
+
+--*/
+
+#include "fxobjectpch.hpp"
+
+// We use DoTraceMessage
+extern "C" {
+#if defined(EVENT_TRACING)
+#include "wdfpoolkm.tmh"
+#endif
+}
+
+// undo the previous masking
+#undef IoAllocateMdl
+#undef IoFreeMdl
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+NTKERNELAPI
+PMDL
+IoAllocateMdl(
+    __in_opt __drv_aliasesMem PVOID VirtualAddress,
+    __in ULONG Length,
+    __in BOOLEAN SecondaryBuffer,
+    __in BOOLEAN ChargeQuota,
+    __inout_opt PIRP Irp
+    );
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+NTKERNELAPI
+VOID
+IoFreeMdl(
+    PMDL Mdl
+    );
+
+//
+// Windows Driver Framework Pool Tracking
+//
+// This module implements a generic pool tracking mechanism
+// if pool verifier mode is enabled.
+//
+// There can be multiple pools, each represented by a FX_POOL header.
+//
+// When the framework is supplied as a DLL, there is a global
+// pool that represents allocations for the framework DLL itself.  These
+// allocations are pool allocations and object allocations.
+//
+// The driver's pool allocations are not currently tracked.  If the driver needs
+// to use pool outside of the framework objects, it calls the WDM
+// ExAllocatePoolWithTag and ExFreePool(WithTag) APIs.
+//
+
+
+
+PMDL
+FxMdlAllocateDebug(
+    __in PFX_DRIVER_GLOBALS FxDriverGlobals,
+    __in FxObject* Owner,
+    __in PVOID VirtualAddress,
+    __in ULONG Length,
+    __in BOOLEAN SecondaryBuffer,
+    __in BOOLEAN ChargeQuota,
+    __in PVOID CallersAddress
+    )
+{
+    FxDriverGlobalsDebugExtension* pExtension;
+    FxAllocatedMdls* pAllocated, **ppNext;
+    ULONG i;
+    PMDL pMdl;
+    KIRQL irql;
+
+    pExtension = FxDriverGlobals->DebugExtension;
+    if (pExtension == NULL) {
+        return IoAllocateMdl(VirtualAddress,
+                             Length,
+                             SecondaryBuffer,
+                             ChargeQuota,
+                             NULL);
+    }
+
+    pAllocated = &pExtension->AllocatedMdls;
+    ppNext = NULL;
+    pMdl = NULL;
+
+    KeAcquireSpinLock(&pExtension->AllocatedMdlsLock, &irql);
+
+    while (pAllocated != NULL && pAllocated->Count == NUM_MDLS_IN_INFO) {
+        ppNext = &pAllocated->Next;
+        pAllocated = pAllocated->Next;
+    }
+
+    if (pAllocated == NULL) {
+        //
+        // No more entries, allocate a new table
+        //
+        pAllocated = (FxAllocatedMdls*) ExAllocatePoolWithTag(
+            NonPagedPool, sizeof(FxAllocatedMdls), FxDriverGlobals->Tag);
+
+        if (pAllocated != NULL) {
+            //
+            // Zero out the new buffer and link it in to the list
+            //
+            RtlZeroMemory(pAllocated, sizeof(*pAllocated));
+            *ppNext = pAllocated;
+        }
+        else {
+            //
+            // Could not allocate a new table, return error
+            //
+            KeReleaseSpinLock(&pExtension->AllocatedMdlsLock, irql);
+
+            return NULL;
+        }
+    }
+
+    for (i = 0; i < NUM_MDLS_IN_INFO; i++) {
+        if (pAllocated->Info[i].Mdl != NULL) {
+            continue;
+        }
+
+        pMdl =  IoAllocateMdl(VirtualAddress,
+                              Length,
+                              SecondaryBuffer,
+                              ChargeQuota,
+                              NULL);
+
+        if (pMdl != NULL) {
+            pAllocated->Info[i].Mdl = pMdl;
+            pAllocated->Info[i].Owner = Owner;
+            pAllocated->Info[i].Caller = CallersAddress;
+            pAllocated->Count++;
+        }
+        break;
+    }
+
+    KeReleaseSpinLock(&pExtension->AllocatedMdlsLock, irql);
+
+    return pMdl;
+}
+
+VOID
+FxMdlFreeDebug(
+    __in PFX_DRIVER_GLOBALS FxDriverGlobals,
+    __in PMDL Mdl
+    )
+{
+    FxDriverGlobalsDebugExtension* pExtension;
+    FxAllocatedMdls* pAllocated, **ppNext;
+    ULONG i;
+    KIRQL irql;
+    BOOLEAN found;
+
+    pExtension = FxDriverGlobals->DebugExtension;
+    if (pExtension == NULL) {
+        IoFreeMdl(Mdl);
+        return;
+    }
+
+    found = FALSE;
+
+    pAllocated = &pExtension->AllocatedMdls;
+    ppNext = NULL;
+
+    KeAcquireSpinLock(&pExtension->AllocatedMdlsLock, &irql);
+
+    while (pAllocated != NULL) {
+        for (i = 0; i < NUM_MDLS_IN_INFO; i++) {
+            if (pAllocated->Info[i].Mdl != Mdl) {
+                continue;
+            }
+
+            RtlZeroMemory(&pAllocated->Info[i],
+                          sizeof(pAllocated->Info[i]));
+
+            pAllocated->Count--;
+
+            if (pAllocated->Count == 0 &&
+                pAllocated != &pExtension->AllocatedMdls) {
+                //
+                // Remove the current table from the chain
+                //
+                *ppNext = pAllocated->Next;
+
+                //
+                // And free it
+                //
+                ExFreePool(pAllocated);
+            }
+
+            IoFreeMdl(Mdl);
+            found = TRUE;
+            break;
+        }
+
+        if (found) {
+            break;
+        }
+
+        ppNext = &pAllocated->Next;
+        pAllocated = pAllocated->Next;
+    }
+
+    KeReleaseSpinLock(&pExtension->AllocatedMdlsLock, irql);
+
+    if (found == FALSE) {
+
+
+
+        FxVerifierDbgBreakPoint(FxDriverGlobals);
+    }
+}
+
+VOID
+FxMdlDump(
+    __in PFX_DRIVER_GLOBALS FxDriverGlobals
+    )
+{
+    FxAllocatedMdls *pCur;
+    BOOLEAN leak;
+
+    if (FxDriverGlobals->DebugExtension == NULL) {
+        return;
+    }
+
+    leak = FALSE;
+
+    for (pCur = &FxDriverGlobals->DebugExtension->AllocatedMdls;
+         pCur != NULL;
+         pCur = pCur->Next) {
+        ULONG i;
+
+        for (i = 0; i < NUM_MDLS_IN_INFO; i++) {
+            if (pCur->Info[i].Mdl != NULL) {
+                leak = TRUE;
+
+                DoTraceLevelMessage(
+                    FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
+                    "PMDL 0x%p leaked, FxObject owner %p, Callers Address %p",
+                    pCur->Info[i].Mdl, pCur->Info[i].Owner,
+                    pCur->Info[i].Caller);
+            }
+        }
+    }
+
+    if (leak) {
+        FxVerifierDbgBreakPoint(FxDriverGlobals);
+    }
+}
+