Index: include/internal/mm.h =================================================================== --- ntoskrnl/include/internal/mm.h (revision 72626) +++ ntoskrnl/include/internal/mm.h (working copy) @@ -1397,7 +1397,12 @@ POOL_TYPE PoolType, ULONG Tag); +VOID +NTAPI +ExReturnPoolQuota( + IN PVOID P); + /* mmsup.c *****************************************************************/ NTSTATUS Index: io/iomgr/irp.c =================================================================== --- ntoskrnl/io/iomgr/irp.c (revision 72626) +++ ntoskrnl/io/iomgr/irp.c (working copy) @@ -1649,6 +1649,14 @@ /* The free was within the Depth */ if (Irp) { + /* Remove the association with the process */ + if (Irp->AllocationFlags & IRP_QUOTA_CHARGED) + { + ExReturnPoolQuota(Irp); + Irp->AllocationFlags &= ~IRP_QUOTA_CHARGED; + } + + /* Add it to the lookaside list */ InterlockedPushEntrySList(&List->L.ListHead, (PSLIST_ENTRY)Irp); } Index: mm/ARM3/expool.c =================================================================== --- ntoskrnl/mm/ARM3/expool.c (revision 72626) +++ ntoskrnl/mm/ARM3/expool.c (working copy) @@ -1509,6 +1509,58 @@ *PagedPoolLookasideHits += 0; } +VOID +NTAPI +ExReturnPoolQuota(IN PVOID P) +{ + PPOOL_HEADER Entry; + POOL_TYPE PoolType; + USHORT BlockSize; + PEPROCESS Process; + + if ((ExpPoolFlags & POOL_FLAG_SPECIAL_POOL) && + (MmIsSpecialPoolAddress(P))) + { + return; + } + + Entry = P; + Entry--; + ASSERT((ULONG_PTR)Entry % POOL_BLOCK_SIZE == 0); + + PoolType = Entry->PoolType - 1; + BlockSize = Entry->BlockSize; + + if (PoolType & QUOTA_POOL_MASK) + { + Process = ((PVOID *)POOL_NEXT_BLOCK(Entry))[-1]; + ASSERT(Process != NULL); + if (Process) + { + if (Process->Pcb.Header.Type != ProcessObject) + { + DPRINT1("Object %p is not a process. Type %u, pool type 0x%x, block size %u\n", + Process, Process->Pcb.Header.Type, Entry->PoolType, BlockSize); + KeBugCheckEx(BAD_POOL_CALLER, + 0x0D, + (ULONG_PTR)P, + Entry->PoolTag, + (ULONG_PTR)Process); + } + DPRINT1("QUOTA: Return quota for Irp %p Process %p at %p, pool type %u\n", Irp, Process, ((PVOID *)POOL_NEXT_BLOCK(Entry)) - 1, Entry->PoolType); + ((PVOID *)POOL_NEXT_BLOCK(Entry))[-1] = NULL; + PsReturnPoolQuota(Process, + PoolType & BASE_POOL_TYPE_MASK, + BlockSize * POOL_BLOCK_SIZE); + ObDereferenceObject(Process); + } + } + else + { + DPRINT1("QUOTA: Irp %p Entry %p has pool type %u\n", PoolType); + } +} + /* PUBLIC FUNCTIONS ***********************************************************/ /* @@ -2285,9 +2337,11 @@ if ((Entry->PoolType - 1) & QUOTA_POOL_MASK) { Process = ((PVOID *)POOL_NEXT_BLOCK(Entry))[-1]; - ASSERT(Process != NULL); if (Process) { + DPRINT1("QUOTA: Allocation %p has Process %p at %p, pool type %u\n", P, Process, ((PVOID *)POOL_NEXT_BLOCK(Entry)) - 1, Entry->PoolType); + if ((LONG_PTR)Process < 0) + { if (Process->Pcb.Header.Type != ProcessObject) { DPRINT1("Object %p is not a process. Type %u, pool type 0x%x, block size %u\n", @@ -2300,6 +2354,7 @@ } PsReturnPoolQuota(Process, PoolType, BlockSize * POOL_BLOCK_SIZE); ObDereferenceObject(Process); + } } }