reactos/sdk/lib/drivers/wdf/shared/object/km/wdfpoolkm.cpp

275 lines
6 KiB
C++
Raw Normal View History

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