Files
3fe5b8b0bb [SDK][WDF][USBDEX][NTOSKRNL_VISTA] Fully enable KMDF (#8396)
[SDK][WDFLDR] Add kmdf loader driver
[SDK][WDF] Add kmdf drver init static library
[SDK][WDF] Modify kmdf driver for working with wdfldr driver
[SDK][CDROM] Cdrom driver dynamically linking with kmdf
[SDK][WDF] Add kmdfdriver module type
[SDK][WDF][USBDEX][NTOSKRNL_VISTA] Fully enable KMDF
[KMDF][WDFLDR][WDF01000] Fix Windows 10 Compatibility WDFLDR and WDF01000
[WDF01000] NO_KERNEL_LIST_ENTRY_CHECKS for wdf01000 3rd party code

This PR is an accumulation of three peoples work, with the goal of the trying to get WDF to work like it should.
This has been tested in combination with some extra NT6+ ntoskrnl against multiple drivers.

---------

Co-authored-by: Max Korostil <[email protected]>
Co-authored-by: Victor Perevertkin <[email protected]>
Co-authored-by: Adam Słaboń <[email protected]>
Co-authored-by: Hermès BÉLUSCA - MAÏTO <[email protected]>
2025-11-03 06:38:52 -08:00

275 lines
6.0 KiB
C++

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