ReactOS  0.4.13-dev-92-gf251225
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
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 
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 */
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 static
268 VOID
270 {
272  PVOID *BigAllocations;
273  const ULONG MaxAllocations = 1024 * 128;
274  ULONG NumAllocations;
275 
277  {
278  BigAllocations = ExAllocatePoolWithTag(PoolType,
279  MaxAllocations * sizeof(*BigAllocations),
280  'ABmK');
281 
282  /* Allocate a lot of pages (== big pool allocations) */
283  for (NumAllocations = 0; NumAllocations < MaxAllocations; NumAllocations++)
284  {
285  BigAllocations[NumAllocations] = ExAllocatePoolWithTag(PoolType,
286  PAGE_SIZE,
287  'aPmK');
288  if (BigAllocations[NumAllocations] == NULL)
289  {
290  NumAllocations--;
291  break;
292  }
293  }
294 
295  trace("Got %lu allocations for PoolType %d\n", NumAllocations, PoolType);
296 
297  /* Free them */
298  for (; NumAllocations < MaxAllocations; NumAllocations--)
299  {
300  ASSERT(BigAllocations[NumAllocations] != NULL);
301  ExFreePoolWithTag(BigAllocations[NumAllocations],
302  'aPmK');
303  }
304  ExFreePoolWithTag(BigAllocations, 'ABmK');
305  }
306 }
307 
308 START_TEST(ExPools)
309 {
310  PoolsTest();
311  PoolsCorruption();
312  TestPoolTags();
313  TestPoolQuota();
315 }
static BYTE Memory[0x20]
Definition: ps2.c:54
static VOID TestBigPoolExpansion(VOID)
Definition: ExPools.c:269
#define trace(...)
Definition: kmt_test.h:217
#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:2939
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:283
static LONG GetRefCount(_In_ PVOID Object)
Definition: ExPools.c:20
_SEH2_TRY
Definition: create.c:4250
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define OBJECT_TO_OBJECT_HEADER(o)
Definition: obtypes.h:111
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
Definition: Header.h:8
long LONG
Definition: pedump.c:60
static VOID TestPoolTags(VOID)
Definition: ExPools.c:162
#define ok(value,...)
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
smooth NULL
Definition: ftsmooth.c:416
#define ok_eq_tag(value, expected)
Definition: kmt_test.h:263
#define BASE_POOL_TYPE_MASK
Definition: ExPools.c:15
static VOID TestPoolQuota(VOID)
Definition: ExPools.c:189
INT POOL_TYPE
Definition: typedefs.h:76
static IUnknown Object
Definition: main.c:512
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
USHORT KmtGetPoolType(PVOID Memory)
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: typedefs.h:117
#define KmtStartSeh()
Definition: kmt_test.h:277
Status
Definition: gdiplustypes.h:24
#define _In_
Definition: no_sal2.h:204
_SEH2_END
Definition: create.c:4424
#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)
unsigned int * PULONG
Definition: retypes.h:1
#define skip(...)
START_TEST(ExPools)
Definition: ExPools.c:308
_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:261
#define POOL_QUOTA_FAIL_INSTEAD_OF_RAISE
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
#define LIST_ENTRY(type)
Definition: queue.h:175
return STATUS_SUCCESS
Definition: btrfs.c:2725
_Must_inspect_result_ _In_ FLT_CONTEXT_TYPE _In_ SIZE_T _In_ POOL_TYPE PoolType
Definition: fltkernel.h:1444
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
#define ok_eq_long(value, expected)
Definition: kmt_test.h:240
static VOID PoolsTest(VOID)
Definition: ExPools.c:27