Index: include/internal/mm.h =================================================================== --- ntoskrnl/include/internal/mm.h (revision 72672) +++ 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 72672) +++ 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 72672) +++ ntoskrnl/mm/ARM3/expool.c (working copy) @@ -1509,6 +1509,53 @@ *PagedPoolLookasideHits += 0; } +VOID +NTAPI +ExReturnPoolQuota(IN PVOID P) +{ + PPOOL_HEADER Entry; + POOL_TYPE PoolType; + USHORT BlockSize; + PEPROCESS Process; + + Entry = P; + Entry--; + ASSERT((ULONG_PTR)Entry % POOL_BLOCK_SIZE == 0); + + if ((ExpPoolFlags & POOL_FLAG_SPECIAL_POOL) && + (MmIsSpecialPoolAddress(P))) + { + return; + } + + 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); + } + ((PVOID *)POOL_NEXT_BLOCK(Entry))[-1] = NULL; + PsReturnPoolQuota(Process, + PoolType & BASE_POOL_TYPE_MASK, + BlockSize * POOL_BLOCK_SIZE); + ObDereferenceObject(Process); + } + } +} + /* PUBLIC FUNCTIONS ***********************************************************/ /* @@ -2285,7 +2332,6 @@ if ((Entry->PoolType - 1) & QUOTA_POOL_MASK) { Process = ((PVOID *)POOL_NEXT_BLOCK(Entry))[-1]; - ASSERT(Process != NULL); if (Process) { if (Process->Pcb.Header.Type != ProcessObject)