ReactOS  r75192
ExPools.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS kernel-mode tests
3  * LICENSE: LGPLv2+ - See COPYING.LIB in the top level directory
4  * PURPOSE: Kernel-Mode Test Suite Pools test routines KM-Test
5  * PROGRAMMER: Aleksey Bragin <aleksey@reactos.org>
6  */
7 
8 #include <kmt_test.h>
9 
10 #define NDEBUG
11 #include <debug.h>
12 
13 #define TAG_POOLTEST 'tstP'
14 
15 #define BASE_POOL_TYPE_MASK 1
16 #define QUOTA_POOL_MASK 8
17 
18 static
19 LONG
22 {
24  return Header->PointerCount;
25 }
26 
28 {
29  PVOID Ptr;
30  ULONG AllocSize, i, AllocNumber;
31  PVOID *Allocs;
32 
33  // Stress-test nonpaged pool
34  for (i=1; i<10000; i++)
35  {
36  // make up some increasing, a bit irregular size
37  AllocSize = i*10;
38 
39  if (i % 10)
40  AllocSize++;
41 
42  if (i % 25)
43  AllocSize += 13;
44 
45  // start with non-paged pool
47 
48  // it may fail due to no-memory condition
49  if (!Ptr) break;
50 
51  // try to fully fill it
52  RtlFillMemory(Ptr, AllocSize, 0xAB);
53 
54  // free it
56  }
57 
58  // now paged one
59  for (i=1; i<10000; i++)
60  {
61  // make up some increasing, a bit irregular size
62  AllocSize = i*50;
63 
64  if (i % 10)
65  AllocSize++;
66 
67  if (i % 25)
68  AllocSize += 13;
69 
70  // start with non-paged pool
71  Ptr = ExAllocatePoolWithTag(PagedPool, AllocSize, TAG_POOLTEST);
72 
73  // it may fail due to no-memory condition
74  if (!Ptr) break;
75 
76  // try to fully fill it
77  RtlFillMemory(Ptr, AllocSize, 0xAB);
78 
79  // free it
81  }
82 
83  // test super-big allocations
84  /*AllocSize = 2UL * 1024 * 1024 * 1024;
85  Ptr = ExAllocatePoolWithTag(NonPagedPool, AllocSize, TAG_POOLTEST);
86  ok(Ptr == NULL, "Allocating 2Gb of nonpaged pool should fail\n");
87 
88  Ptr = ExAllocatePoolWithTag(PagedPool, AllocSize, TAG_POOLTEST);
89  ok(Ptr == NULL, "Allocating 2Gb of paged pool should fail\n");*/
90 
91  // now test allocating lots of small/medium blocks
92  AllocNumber = 100000;
93  Allocs = ExAllocatePoolWithTag(PagedPool, sizeof(*Allocs) * AllocNumber, TAG_POOLTEST);
94 
95  // alloc blocks
96  for (i=0; i<AllocNumber; i++)
97  {
98  AllocSize = 42;
99  Allocs[i] = ExAllocatePoolWithTag(NonPagedPool, AllocSize, TAG_POOLTEST);
100  }
101 
102  // now free them
103  for (i=0; i<AllocNumber; i++)
104  {
105  ExFreePoolWithTag(Allocs[i], TAG_POOLTEST);
106  }
107 
108 
110 }
111 
113 {
114  PULONG Ptr;
115  ULONG AllocSize;
116 
117  // start with non-paged pool
118  AllocSize = 4096 + 0x10;
120 
121  // touch all bytes, it shouldn't cause an exception
122  RtlZeroMemory(Ptr, AllocSize);
123 
124 /* TODO: These fail because accessing invalid memory doesn't necessarily
125  cause an access violation */
126 #ifdef THIS_DOESNT_WORK
127  // test buffer overrun, right after our allocation ends
128  _SEH2_TRY
129  {
130  TestPtr = (PULONG)((PUCHAR)Ptr + AllocSize);
131  //Ptr[4] = 0xd33dbeef;
132  *TestPtr = 0xd33dbeef;
133  }
135  {
136  /* Get the status */
138  } _SEH2_END;
139 
140  ok(Status == STATUS_ACCESS_VIOLATION, "Exception should occur, but got Status 0x%08lX\n", Status);
141 
142  // test overrun in a distant byte range, but within 4096KB
143  _SEH2_TRY
144  {
145  Ptr[2020] = 0xdeadb33f;
146  }
148  {
149  /* Get the status */
151  } _SEH2_END;
152 
153  ok(Status == STATUS_ACCESS_VIOLATION, "Exception should occur, but got Status 0x%08lX\n", Status);
154 #endif
155 
156  // free the pool
158 }
159 
160 static
161 VOID
163 {
164  PVOID Memory;
165 
166  Memory = ExAllocatePoolWithTag(PagedPool, 8, 'MyTa');
167  ok_eq_tag(KmtGetPoolTag(Memory), 'MyTa');
168  ExFreePoolWithTag(Memory, 'MyTa');
169 
170  Memory = ExAllocatePoolWithTag(PagedPool, PAGE_SIZE, 'MyTa');
171  ok_eq_tag(KmtGetPoolTag(Memory), 'TooL');
172  ExFreePoolWithTag(Memory, 'MyTa');
173 
174  Memory = ExAllocatePoolWithTag(PagedPool, PAGE_SIZE - 3 * sizeof(PVOID), 'MyTa');
175  ok_eq_tag(KmtGetPoolTag(Memory), 'TooL');
176  ExFreePoolWithTag(Memory, 'MyTa');
177 
178  Memory = ExAllocatePoolWithTag(PagedPool, PAGE_SIZE - 4 * sizeof(PVOID) + 1, 'MyTa');
179  ok_eq_tag(KmtGetPoolTag(Memory), 'TooL');
180  ExFreePoolWithTag(Memory, 'MyTa');
181 
182  Memory = ExAllocatePoolWithTag(PagedPool, PAGE_SIZE - 4 * sizeof(PVOID), 'MyTa');
183  ok_eq_tag(KmtGetPoolTag(Memory), 'MyTa');
184  ExFreePoolWithTag(Memory, 'MyTa');
185 }
186 
187 static
188 VOID
190 {
192  PEPROCESS StoredProcess;
193  PVOID Memory;
194  LONG InitialRefCount;
195  LONG RefCount;
197 
198  InitialRefCount = GetRefCount(Process);
199 
200  /* We get some memory from this function, and it's properly aligned.
201  * Also, it takes a reference to the process, and releases it on free */
203  sizeof(LIST_ENTRY),
204  'tQmK');
205  ok(Memory != NULL, "ExAllocatePoolWithQuotaTag returned NULL\n");
206  if (!skip(Memory != NULL, "No memory\n"))
207  {
208  ok((ULONG_PTR)Memory % sizeof(LIST_ENTRY) == 0,
209  "Allocation %p is badly aligned\n",
210  Memory);
211  RefCount = GetRefCount(Process);
212  ok_eq_long(RefCount, InitialRefCount + 1);
213 
214  /* A pointer to the process is found right before the next pool header */
215  StoredProcess = ((PVOID *)((ULONG_PTR)Memory + 2 * sizeof(LIST_ENTRY)))[-1];
216  ok_eq_pointer(StoredProcess, Process);
217 
218  /* Pool type should have QUOTA_POOL_MASK set */
219  PoolType = KmtGetPoolType(Memory);
220  ok(PoolType != 0, "PoolType is 0\n");
221  PoolType--;
222  ok(PoolType & QUOTA_POOL_MASK, "PoolType = %x\n", PoolType);
223  ok((PoolType & BASE_POOL_TYPE_MASK) == PagedPool, "PoolType = %x\n", PoolType);
224 
225  ExFreePoolWithTag(Memory, 'tQmK');
226  RefCount = GetRefCount(Process);
227  ok_eq_long(RefCount, InitialRefCount);
228  }
229 
230  /* Large allocations are page-aligned, don't reference the process */
232  PAGE_SIZE,
233  'tQmK');
234  ok(Memory != NULL, "ExAllocatePoolWithQuotaTag returned NULL\n");
235  if (!skip(Memory != NULL, "No memory\n"))
236  {
237  ok((ULONG_PTR)Memory % PAGE_SIZE == 0,
238  "Allocation %p is badly aligned\n",
239  Memory);
240  RefCount = GetRefCount(Process);
241  ok_eq_long(RefCount, InitialRefCount);
242  ExFreePoolWithTag(Memory, 'tQmK');
243  RefCount = GetRefCount(Process);
244  ok_eq_long(RefCount, InitialRefCount);
245  }
246 
247  /* Function raises by default */
248  KmtStartSeh()
250  0x7FFFFFFF,
251  'tQmK');
252  if (Memory)
253  ExFreePoolWithTag(Memory, 'tQmK');
255 
256  /* Function returns NULL with POOL_QUOTA_FAIL_INSTEAD_OF_RAISE */
257  KmtStartSeh()
259  0x7FFFFFFF,
260  'tQmK');
261  ok(Memory == NULL, "Successfully got 2GB block: %p\n", Memory);
262  if (Memory)
263  ExFreePoolWithTag(Memory, 'tQmK');
265 }
266 
267 START_TEST(ExPools)
268 {
269  PoolsTest();
270  PoolsCorruption();
271  TestPoolTags();
272  TestPoolQuota();
273 }
DWORD *typedef PVOID
Definition: winlogon.h:52
#define STATUS_SUCCESS
Definition: contextmenu.cpp:55
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
PVOID NTAPI ExAllocatePoolWithQuotaTag(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN ULONG Tag)
Definition: expool.c:2611
static VOID PoolsCorruption(VOID)
Definition: ExPools.c:112
#define ok_eq_pointer(value, expected)
unsigned char * PUCHAR
Definition: retypes.h:3
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
#define KmtEndSeh(ExpectedStatus)
Definition: kmt_test.h:237
static LONG GetRefCount(_In_ PVOID Object)
Definition: ExPools.c:20
LONG PointerCount
Definition: obtypes.h:481
uint32_t ULONG_PTR
Definition: typedefs.h:64
#define OBJECT_TO_OBJECT_HEADER(o)
Definition: obtypes.h:111
GLenum GLclampf GLint i
Definition: glfuncs.h:14
Definition: Header.h:8
long LONG
Definition: pedump.c:60
#define _SEH2_END
Definition: pseh2_64.h:7
static VOID TestPoolTags(VOID)
Definition: ExPools.c:162
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
smooth NULL
Definition: ftsmooth.c:513
#define ok_eq_tag(value, expected)
Definition: kmt_test.h:217
#define BASE_POOL_TYPE_MASK
Definition: ExPools.c:15
static VOID TestPoolQuota(VOID)
Definition: ExPools.c:189
ACPI_EFI_MEMORY_TYPE UINTN ACPI_EFI_PHYSICAL_ADDRESS * Memory
Definition: acefiex.h:525
static IUnknown Object
Definition: main.c:512
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
USHORT KmtGetPoolType(PVOID Memory)
IN REFCLSID IN PUNKNOWN IN POOL_TYPE PoolType
Definition: unknown.h:68
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: typedefs.h:118
#define KmtStartSeh()
Definition: kmt_test.h:231
Status
Definition: gdiplustypes.h:24
#define _In_
Definition: no_sal2.h:204
#define QUOTA_POOL_MASK
Definition: ExPools.c:16
#define TAG_POOLTEST
Definition: ExPools.c:13
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:228
unsigned short USHORT
Definition: pedump.c:61
ULONG KmtGetPoolTag(PVOID Memory)
#define skip(...)
Definition: CString.cpp:57
#define _SEH2_TRY
Definition: pseh2_64.h:5
unsigned int * PULONG
Definition: retypes.h:1
START_TEST(ExPools)
Definition: ExPools.c:267
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ok(value,...)
Definition: CImage.cpp:33
#define POOL_QUOTA_FAIL_INSTEAD_OF_RAISE
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1097
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
#define LIST_ENTRY(type)
Definition: queue.h:175
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
#define ok_eq_long(value, expected)
Definition: kmt_test.h:194
static VOID PoolsTest(VOID)
Definition: ExPools.c:27