[NTOSKRNL]: Implement ExAllocatePoolWithQuotaTag. However PsChargeProcessPoolQuota is still unimplemented so nothing really gets charged (we do write the owner process, though).

svn path=/trunk/; revision=60002
This commit is contained in:
Alex Ionescu 2013-09-10 10:02:27 +00:00
parent 144100a4e2
commit 36f1e2f5d1

View file

@ -2511,11 +2511,114 @@ ExAllocatePoolWithQuotaTag(IN POOL_TYPE PoolType,
IN SIZE_T NumberOfBytes,
IN ULONG Tag)
{
BOOLEAN Raise = TRUE;
PVOID Buffer;
PPOOL_HEADER Entry;
NTSTATUS Status;
PEPROCESS Process = PsGetCurrentProcess();
//
// Allocate the pool
// Check if we should fail intead of raising an exception
//
UNIMPLEMENTED;
return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
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