#define TAG_POOLTEST 'tstP'
+#define BASE_POOL_TYPE_MASK 1
+#define QUOTA_POOL_MASK 8
+
+static
+LONG
+GetRefCount(
+ _In_ PVOID Object)
+{
+ POBJECT_HEADER Header = OBJECT_TO_OBJECT_HEADER(Object);
+ return Header->PointerCount;
+}
+
static VOID PoolsTest(VOID)
{
PVOID Ptr;
// now test allocating lots of small/medium blocks
AllocNumber = 100000;
- Allocs = ExAllocatePoolWithTag(PagedPool, sizeof(Allocs) * AllocNumber, TAG_POOLTEST);
+ Allocs = ExAllocatePoolWithTag(PagedPool, sizeof(*Allocs) * AllocNumber, TAG_POOLTEST);
// alloc blocks
for (i=0; i<AllocNumber; i++)
ExFreePoolWithTag(Memory, 'MyTa');
}
+static
+VOID
+TestPoolQuota(VOID)
+{
+ PEPROCESS Process = PsGetCurrentProcess();
+ PEPROCESS StoredProcess;
+ PVOID Memory;
+ LONG InitialRefCount;
+ LONG RefCount;
+ USHORT PoolType;
+
+ InitialRefCount = GetRefCount(Process);
+
+ /* We get some memory from this function, and it's properly aligned.
+ * Also, it takes a reference to the process, and releases it on free */
+ Memory = ExAllocatePoolWithQuotaTag(PagedPool | POOL_QUOTA_FAIL_INSTEAD_OF_RAISE,
+ sizeof(LIST_ENTRY),
+ 'tQmK');
+ ok(Memory != NULL, "ExAllocatePoolWithQuotaTag returned NULL\n");
+ if (!skip(Memory != NULL, "No memory\n"))
+ {
+ ok((ULONG_PTR)Memory % sizeof(LIST_ENTRY) == 0,
+ "Allocation %p is badly aligned\n",
+ Memory);
+ RefCount = GetRefCount(Process);
+ ok_eq_long(RefCount, InitialRefCount + 1);
+
+ /* A pointer to the process is found right before the next pool header */
+ StoredProcess = ((PVOID *)((ULONG_PTR)Memory + 2 * sizeof(LIST_ENTRY)))[-1];
+ ok_eq_pointer(StoredProcess, Process);
+
+ /* Pool type should have QUOTA_POOL_MASK set */
+ PoolType = KmtGetPoolType(Memory);
+ ok(PoolType != 0, "PoolType is 0\n");
+ PoolType--;
+ ok(PoolType & QUOTA_POOL_MASK, "PoolType = %x\n", PoolType);
+ ok((PoolType & BASE_POOL_TYPE_MASK) == PagedPool, "PoolType = %x\n", PoolType);
+
+ ExFreePoolWithTag(Memory, 'tQmK');
+ RefCount = GetRefCount(Process);
+ ok_eq_long(RefCount, InitialRefCount);
+ }
+
+ /* Large allocations are page-aligned, don't reference the process */
+ Memory = ExAllocatePoolWithQuotaTag(PagedPool | POOL_QUOTA_FAIL_INSTEAD_OF_RAISE,
+ PAGE_SIZE,
+ 'tQmK');
+ ok(Memory != NULL, "ExAllocatePoolWithQuotaTag returned NULL\n");
+ if (!skip(Memory != NULL, "No memory\n"))
+ {
+ ok((ULONG_PTR)Memory % PAGE_SIZE == 0,
+ "Allocation %p is badly aligned\n",
+ Memory);
+ RefCount = GetRefCount(Process);
+ ok_eq_long(RefCount, InitialRefCount);
+ ExFreePoolWithTag(Memory, 'tQmK');
+ RefCount = GetRefCount(Process);
+ ok_eq_long(RefCount, InitialRefCount);
+ }
+
+ /* Function raises by default */
+ KmtStartSeh()
+ Memory = ExAllocatePoolWithQuotaTag(PagedPool,
+ 0x7FFFFFFF,
+ 'tQmK');
+ if (Memory)
+ ExFreePoolWithTag(Memory, 'tQmK');
+ KmtEndSeh(STATUS_INSUFFICIENT_RESOURCES);
+
+ /* Function returns NULL with POOL_QUOTA_FAIL_INSTEAD_OF_RAISE */
+ KmtStartSeh()
+ Memory = ExAllocatePoolWithQuotaTag(PagedPool | POOL_QUOTA_FAIL_INSTEAD_OF_RAISE,
+ 0x7FFFFFFF,
+ 'tQmK');
+ ok(Memory == NULL, "Successfully got 2GB block: %p\n", Memory);
+ if (Memory)
+ ExFreePoolWithTag(Memory, 'tQmK');
+ KmtEndSeh(STATUS_SUCCESS);
+}
+
START_TEST(ExPools)
{
PoolsTest();
PoolsCorruption();
TestPoolTags();
+ TestPoolQuota();
}