Author: ion Date: Tue Sep 10 10:02:27 2013 New Revision: 60002
URL: http://svn.reactos.org/svn/reactos?rev=60002&view=rev Log: [NTOSKRNL]: Implement ExAllocatePoolWithQuotaTag. However PsChargeProcessPoolQuota is still unimplemented so nothing really gets charged (we do write the owner process, though).
Modified: trunk/reactos/ntoskrnl/mm/ARM3/expool.c
Modified: trunk/reactos/ntoskrnl/mm/ARM3/expool.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/expool.c?r... ============================================================================== --- trunk/reactos/ntoskrnl/mm/ARM3/expool.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/ARM3/expool.c [iso-8859-1] Tue Sep 10 10:02:27 2013 @@ -2511,11 +2511,114 @@ IN SIZE_T NumberOfBytes, IN ULONG Tag) { - // - // Allocate the pool - // - UNIMPLEMENTED; - return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag); + BOOLEAN Raise = TRUE; + PVOID Buffer; + PPOOL_HEADER Entry; + NTSTATUS Status; + PEPROCESS Process = PsGetCurrentProcess(); + + // + // Check if we should fail intead of raising an exception + // + if (PoolType & POOL_QUOTA_FAIL_INSTEAD_OF_RAISE) + { + Raise = FALSE; + PoolType &= ~POOL_QUOTA_FAIL_INSTEAD_OF_RAISE; + } + + // + // Inject the pool quota mask + // + PoolType += QUOTA_POOL_MASK; + + // + // Check if we have enough space to add the quota owner process, as long as + // this isn't the system process, which never gets charged quota + // + ASSERT(NumberOfBytes != 0); + if ((NumberOfBytes <= (PAGE_SIZE - sizeof(POOL_BLOCK_SIZE) - sizeof(PVOID))) && + (Process != PsInitialSystemProcess)) + { + // + // Add space for our EPROCESS pointer + // + NumberOfBytes += sizeof(PEPROCESS); + } + else + { + // + // We won't be able to store the pointer, so don't use quota for this + // + PoolType -= QUOTA_POOL_MASK; + } + + // + // Allocate the pool buffer now + // + Buffer = ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag); + + // + // If the buffer is page-aligned, this is a large page allocation and we + // won't touch it + // + if (PAGE_ALIGN(Buffer) != Buffer) + { + // + // Also if special pool is enabled, and this was allocated from there, + // we won't touch it either + // + if ((ExpPoolFlags & POOL_FLAG_SPECIAL_POOL) && + (MmIsSpecialPoolAddress(Buffer))) + { + return Buffer; + } + + // + // If it wasn't actually allocated with quota charges, ignore it too + // + if (!(PoolType & QUOTA_POOL_MASK)) return Buffer; + + // + // If this is the system process, we don't charge quota, so ignore + // + if (Process == PsInitialSystemProcess) return Buffer; + + // + // Actually go and charge quota for the process now + // + Entry = POOL_ENTRY(Buffer); + Status = PsChargeProcessPoolQuota(Process, + PoolType & BASE_POOL_TYPE_MASK, + Entry->BlockSize * sizeof(POOL_BLOCK_SIZE)); + if (!NT_SUCCESS(Status)) + { + // + // Quota failed, back out the allocation, clear the owner, and fail + // + *(PVOID*)((ULONG_PTR)POOL_NEXT_BLOCK(Entry) - sizeof(PVOID)) = NULL; + ExFreePoolWithTag(Buffer, Tag); + if (Raise) RtlRaiseStatus(Status); + return NULL; + } + + // + // Quota worked, write the owner and then reference it before returning + // + *(PVOID*)((ULONG_PTR)POOL_NEXT_BLOCK(Entry) - sizeof(PVOID)) = Process; + ObReferenceObject(Process); + } + else if (!(Buffer) && (Raise)) + { + // + // The allocation failed, raise an error if we are in raise mode + // + RtlRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); + } + + // + // Return the allocated buffer + // + return Buffer; }
#if DBG && KDBG