--- /dev/null
+/*++
+
+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);
+ }
+}
+