ReactOS  0.4.15-dev-3173-g40ee59d
RtlMultipleAllocateHeap.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS API Tests
3  * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4  * PURPOSE: Test for RtlMultipleAllocateHeap and RtlMultipleFreeHeap
5  * COPYRIGHT: Copyright 2020 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
6  */
7 #include "precomp.h"
8 
9 #include <pseh/pseh2.h>
10 
13 
16 
17 #define TEST_ALLOC(ret_expected,err_expected,threw_excepted,HeapHandle,Flags,Size,Count,Array) \
18  threw = 0; \
19  SetLastError(-1); \
20  _SEH2_TRY { \
21  ret = g_alloc((HeapHandle), (Flags), (Size), (Count), (Array)); \
22  err = GetLastError(); \
23  } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { \
24  threw = _SEH2_GetExceptionCode(); \
25  } \
26  _SEH2_END \
27  ok((ret) == (ret_expected), "ret excepted %d, but %d\n", (ret_expected), (ret)); \
28  ok((err) == (err_expected), "err excepted %d, but %d\n", (err_expected), (err)); \
29  ok((threw) == (threw_excepted), "threw excepted %d, but %d\n", (threw_excepted), (threw));
30 
31 #define TEST_ALLOC_NO_RET(err_expected,threw_excepted,HeapHandle,Flags,Size,Count,Array) \
32  threw = 0; \
33  SetLastError(-1); \
34  _SEH2_TRY { \
35  ret = g_alloc((HeapHandle), (Flags), (Size), (Count), (Array)); \
36  err = GetLastError(); \
37  } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { \
38  threw = _SEH2_GetExceptionCode(); \
39  } \
40  _SEH2_END \
41  ok((err) == (err_expected), "err excepted %d, but %d", (err_expected), (err)); \
42  ok((threw) == (threw_excepted), "threw excepted %d, but %d\n", (threw_excepted), (threw));
43 
44 #define TEST_FREE(ret_expected,err_expected,threw_excepted,HeapHandle,Flags,Count,Array) \
45  threw = 0; \
46  SetLastError(-1); \
47  _SEH2_TRY { \
48  ret = g_free((HeapHandle), (Flags), (Count), (Array)); \
49  err = GetLastError(); \
50  } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { \
51  threw = _SEH2_GetExceptionCode(); \
52  } \
53  _SEH2_END \
54  ok((ret) == (ret_expected), "ret excepted %d, but %d\n", (ret_expected), (ret)); \
55  ok((err) == (err_expected), "err excepted %d, but %d\n", (err_expected), (err)); \
56  ok((threw) == (threw_excepted), "threw excepted %d, but %d\n", (threw_excepted), (threw));
57 
58 #define ASSUME_ARRAY_ITEMS_ARE_NULL() \
59  ok(Array[0] == NULL, "Array[0] is expected as NULL\n"); \
60  ok(Array[1] == NULL, "Array[1] is expected as NULL\n"); \
61  ok(Array[2] == NULL, "Array[2] is expected as NULL\n");
62 
63 #define INT_EXPECTED(var,value) \
64  ok((var) == (value), #var " expected %d, but %d\n", (value), (var))
65 
66 static void
68 {
69  array[0] = p0;
70  array[1] = p1;
71  array[2] = p2;
72 }
73 
74 static void
76 {
77  INT ret, threw, err;
78  HANDLE HeapHandle = GetProcessHeap();
79  PVOID Array[3] = {NULL, NULL, NULL};
80 
81  // HeapHandle is non-NULL and array is NULL
82  TEST_ALLOC(0, -1, 0, HeapHandle, 0, 0, 0, NULL);
83  TEST_ALLOC(0, -1, 0xC0000005, HeapHandle, 0, 0, 1, NULL);
84  TEST_ALLOC(0, -1, 0, HeapHandle, 0, 1, 0, NULL);
85  TEST_ALLOC(0, -1, 0xC0000005, HeapHandle, 0, 1, 1, NULL);
86 
87  // Array is non-NULL and contents are NULL
88  set_array(Array, NULL, NULL, NULL);
89  TEST_ALLOC(0, -1, 0, HeapHandle, 0, 0, 0, Array);
91 
92  set_array(Array, NULL, NULL, NULL);
93  TEST_ALLOC(1, -1, 0, HeapHandle, 0, 0, 1, Array);
94  ok(Array[0] != NULL, "Array[0] is expected as non-NULL\n");
95  ok(Array[1] == NULL, "Array[1] is expected as NULL\n");
96  ok(Array[2] == NULL, "Array[2] is expected as NULL\n");
97 
98  set_array(Array, NULL, NULL, NULL);
99  TEST_ALLOC(0, -1, 0, HeapHandle, 0, 1, 0, Array);
101 
102  set_array(Array, NULL, NULL, NULL);
103  TEST_ALLOC(1, -1, 0, HeapHandle, 0, 1, 1, Array);
104  ok(Array[0] != NULL, "Array[0] is expected as non-NULL\n");
105  ok(Array[1] == NULL, "Array[1] is expected as NULL\n");
106  ok(Array[2] == NULL, "Array[2] is expected as NULL\n");
107 
108  set_array(Array, NULL, NULL, NULL);
109  TEST_ALLOC(2, -1, 0, HeapHandle, 0, 1, 2, Array);
110  ok(Array[0] != NULL, "Array[0] is expected as non-NULL\n");
111  ok(Array[1] != NULL, "Array[1] is expected as non-NULL\n");
112  ok(Array[2] == NULL, "Array[2] is expected as NULL\n");
113 
114  set_array(Array, NULL, NULL, NULL);
115  TEST_ALLOC(3, -1, 0, HeapHandle, 0, 1, 3, Array);
116  ok(Array[0] != NULL, "Array[0] is expected as non-NULL\n");
117  ok(Array[1] != NULL, "Array[1] is expected as non-NULL\n");
118  ok(Array[2] != NULL, "Array[2] is expected as non-NULL\n");
119 
120  // Array is non-NULL and contents are invalid pointers
121  set_array(Array, (PVOID)1, (PVOID)2, (PVOID)3);
122  TEST_ALLOC(0, -1, 0, HeapHandle, 0, 0, 0, Array);
123  ok(Array[0] == (PVOID)1, "Array[0] is expected as 1\n");
124  ok(Array[1] == (PVOID)2, "Array[1] is expected as 2\n");
125  ok(Array[2] == (PVOID)3, "Array[2] is expected as 3\n");
126 
127  set_array(Array, (PVOID)1, (PVOID)2, (PVOID)3);
128  TEST_ALLOC(1, -1, 0, HeapHandle, 0, 0, 1, Array);
129  ok(Array[0] != NULL, "Array[0] is expected as non-NULL\n");
130  ok(Array[1] == (PVOID)2, "Array[1] is expected as 2\n");
131  ok(Array[2] == (PVOID)3, "Array[2] is expected as 3\n");
132 
133  set_array(Array, (PVOID)1, (PVOID)2, (PVOID)3);
134  TEST_ALLOC(0, -1, 0, HeapHandle, 0, 1, 0, Array);
135  ok(Array[0] == (PVOID)1, "Array[0] is expected as 1\n");
136  ok(Array[1] == (PVOID)2, "Array[1] is expected as 2\n");
137  ok(Array[2] == (PVOID)3, "Array[2] is expected as 3\n");
138 
139  set_array(Array, (PVOID)1, (PVOID)2, (PVOID)3);
140  TEST_ALLOC(1, -1, 0, HeapHandle, 0, 1, 1, Array);
141  ok(Array[0] != NULL, "Array[0] is expected as non-NULL\n");
142  ok(Array[1] == (PVOID)2, "Array[1] is expected as non-NULL\n");
143  ok(Array[2] == (PVOID)3, "Array[2] is expected as NULL\n");
144 
145  set_array(Array, (PVOID)1, (PVOID)2, (PVOID)3);
146  TEST_ALLOC(2, -1, 0, HeapHandle, 0, 1, 2, Array);
147  ok(Array[0] != NULL, "Array[0] is expected as non-NULL\n");
148  ok(Array[1] != NULL, "Array[1] is expected as non-NULL\n");
149  ok(Array[2] == (PVOID)3, "Array[2] is expected as 3\n");
150 
151  set_array(Array, (PVOID)1, (PVOID)2, (PVOID)3);
152  TEST_ALLOC(3, -1, 0, HeapHandle, 0, 1, 3, Array);
153  ok(Array[0] != NULL, "Array[0] is expected as non-NULL\n");
154  ok(Array[1] != NULL, "Array[1] is expected as non-NULL\n");
155  ok(Array[2] != NULL, "Array[2] is expected as non-NULL\n");
156 
157  // Array is non-NULL and too large to allocate
158  set_array(Array, NULL, NULL, NULL);
159  TEST_ALLOC_NO_RET(ERROR_NOT_ENOUGH_MEMORY, 0, HeapHandle, 0, 0x5FFFFFFF, 3, Array);
160  ok(ret != 3, "excepted not allocated");
161  set_array(Array, NULL, NULL, NULL);
162  TEST_ALLOC_NO_RET(ERROR_NOT_ENOUGH_MEMORY, 0xC0000017, HeapHandle, HEAP_GENERATE_EXCEPTIONS, 0x5FFFFFFF, 3, Array);
163  ok(ret != 3, "excepted not allocated");
164 }
165 
166 static void
168 {
169  INT ret, threw, err;
170  HANDLE HeapHandle = GetProcessHeap();
171  PVOID Array[3] = {NULL, NULL, NULL};
172 
173  // HeapHandle is non-NULL and array is NULL
174  TEST_FREE(0, -1, 0, HeapHandle, 0, 0, NULL);
175  TEST_FREE(0, -1, 0, HeapHandle, 0, 0, NULL);
176  TEST_FREE(0, -1, 0xC0000005, HeapHandle, 0, 1, NULL);
177  TEST_FREE(0, -1, 0xC0000005, HeapHandle, 0, 2, NULL);
178  TEST_FREE(0, -1, 0xC0000005, HeapHandle, 0, 3, NULL);
179 
180  // Array is non-NULL and contents are NULL
181  set_array(Array, NULL, NULL, NULL);
182  TEST_FREE(0, -1, 0, HeapHandle, 0, 0, Array);
183  set_array(Array, NULL, NULL, NULL);
184  TEST_FREE(1, -1, 0, HeapHandle, 0, 1, Array);
185  set_array(Array, NULL, NULL, NULL);
186  TEST_FREE(2, -1, 0, HeapHandle, 0, 2, Array);
187  set_array(Array, NULL, NULL, NULL);
188  TEST_FREE(3, -1, 0, HeapHandle, 0, 3, Array);
189 
190  // Array is non-NULL and contents are invalid pointers
191  set_array(Array, (PVOID)1, (PVOID)2, (PVOID)3);
192  TEST_FREE(0, -1, 0, HeapHandle, 0, 0, Array);
193  set_array(Array, (PVOID)1, (PVOID)2, (PVOID)3);
194  TEST_FREE(0, ERROR_INVALID_PARAMETER, 0, HeapHandle, 0, 1, Array);
195  set_array(Array, (PVOID)1, (PVOID)2, (PVOID)3);
196  TEST_FREE(0, ERROR_INVALID_PARAMETER, 0, HeapHandle, 0, 2, Array);
197  set_array(Array, (PVOID)1, (PVOID)2, (PVOID)3);
198  TEST_FREE(0, ERROR_INVALID_PARAMETER, 0, HeapHandle, 0, 3, Array);
199 
200  // Array is non-NULL and contents are 1 valid pointer and 2 NULLs
201  set_array(Array, NULL, NULL, NULL);
202  ret = g_alloc(HeapHandle, 0, 1, 1, Array);
203  INT_EXPECTED(ret, 1);
204  TEST_FREE(0, -1, 0, HeapHandle, 0, 0, Array);
205 
206  set_array(Array, NULL, NULL, NULL);
207  ret = g_alloc(HeapHandle, 0, 1, 1, Array);
208  INT_EXPECTED(ret, 1);
209  TEST_FREE(1, -1, 0, HeapHandle, 0, 1, Array);
210 
211  set_array(Array, NULL, NULL, NULL);
212  ret = g_alloc(HeapHandle, 0, 1, 1, Array);
213  INT_EXPECTED(ret, 1);
214  TEST_FREE(2, -1, 0, HeapHandle, 0, 2, Array);
215 
216  set_array(Array, NULL, NULL, NULL);
217  ret = g_alloc(HeapHandle, 0, 1, 1, Array);
218  INT_EXPECTED(ret, 1);
219  TEST_FREE(3, -1, 0, HeapHandle, 0, 3, Array);
220 
221  // Array is non-NULL and contents are 1 valid pointer and 2 invalids
222  set_array(Array, NULL, (PVOID)2, (PVOID)3);
223  ret = g_alloc(HeapHandle, 0, 1, 1, Array);
224  INT_EXPECTED(ret, 1);
225  TEST_FREE(0, -1, 0, HeapHandle, 0, 0, Array);
226 
227  set_array(Array, NULL, (PVOID)2, (PVOID)3);
228  ret = g_alloc(HeapHandle, 0, 1, 1, Array);
229  INT_EXPECTED(ret, 1);
230  TEST_FREE(1, -1, 0, HeapHandle, 0, 1, Array);
231 
232  set_array(Array, NULL, (PVOID)2, (PVOID)3);
233  ret = g_alloc(HeapHandle, 0, 1, 1, Array);
234  INT_EXPECTED(ret, 1);
235  TEST_FREE(1, ERROR_INVALID_PARAMETER, 0, HeapHandle, 0, 2, Array);
236 
237  set_array(Array, NULL, (PVOID)2, (PVOID)3);
238  ret = g_alloc(HeapHandle, 0, 1, 1, Array);
239  INT_EXPECTED(ret, 1);
240  TEST_FREE(1, ERROR_INVALID_PARAMETER, 0, HeapHandle, 0, 3, Array);
241 
242  // Array is non-NULL and contents are 1 valid pointer and 2 invalids (generate exceptions)
243  set_array(Array, NULL, (PVOID)2, (PVOID)3);
244  ret = g_alloc(HeapHandle, 0, 1, 1, Array);
245  INT_EXPECTED(ret, 1);
246  TEST_FREE(0, -1, 0, HeapHandle, HEAP_GENERATE_EXCEPTIONS, 0, Array);
247 
248  set_array(Array, NULL, (PVOID)2, (PVOID)3);
249  ret = g_alloc(HeapHandle, 0, 1, 1, Array);
250  INT_EXPECTED(ret, 1);
251  TEST_FREE(1, -1, 0, HeapHandle, HEAP_GENERATE_EXCEPTIONS, 1, Array);
252 
253  set_array(Array, NULL, (PVOID)2, (PVOID)3);
254  ret = g_alloc(HeapHandle, 0, 1, 1, Array);
255  INT_EXPECTED(ret, 1);
256  TEST_FREE(1, ERROR_INVALID_PARAMETER, 0, HeapHandle, HEAP_GENERATE_EXCEPTIONS, 2, Array);
257 
258  set_array(Array, NULL, (PVOID)2, (PVOID)3);
259  ret = g_alloc(HeapHandle, 0, 1, 1, Array);
260  INT_EXPECTED(ret, 1);
261  TEST_FREE(1, ERROR_INVALID_PARAMETER, 0, HeapHandle, HEAP_GENERATE_EXCEPTIONS, 3, Array);
262 
263  // Array is non-NULL and contents are 3 valid pointers
264  set_array(Array, NULL, NULL, NULL);
265  ret = g_alloc(HeapHandle, 0, 3, 3, Array);
266  INT_EXPECTED(ret, 3);
267  TEST_FREE(3, -1, 0, HeapHandle, 0, 3, Array);
268 }
269 
271 {
272  HINSTANCE ntdll = LoadLibraryA("ntdll");
273 
274  g_alloc = (FN_RtlMultipleAllocateHeap)GetProcAddress(ntdll, "RtlMultipleAllocateHeap");
275  g_free = (FN_RtlMultipleFreeHeap)GetProcAddress(ntdll, "RtlMultipleFreeHeap");
276 
277  if (!g_alloc || !g_free)
278  {
279  skip("RtlMultipleAllocateHeap or RtlMultipleFreeHeap not found\n");
280  }
281  else
282  {
285  }
286 
287  FreeLibrary(ntdll);
288 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define IN
Definition: typedefs.h:39
static FN_RtlMultipleAllocateHeap g_alloc
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
static void set_array(PVOID *array, PVOID p0, PVOID p1, PVOID p2)
START_TEST(RtlMultipleAllocateHeap)
int32_t INT
Definition: typedefs.h:58
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryA(LPCSTR lpLibFileName)
Definition: loader.c:111
#define TEST_ALLOC(ret_expected, err_expected, threw_excepted, HeapHandle, Flags, Size, Count, Array)
void * PVOID
Definition: retypes.h:9
#define ASSUME_ARRAY_ITEMS_ARE_NULL()
#define FreeLibrary(x)
Definition: compat.h:607
#define INT_EXPECTED(var, value)
#define GetProcessHeap()
Definition: compat.h:595
int ret
#define err(...)
static void MultiHeapAllocTest()
ULONG_PTR SIZE_T
Definition: typedefs.h:80
ULONG NTAPI RtlMultipleAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size, IN ULONG Count, OUT PVOID *Array)
Definition: heap.c:4125
#define ok(value,...)
Definition: atltest.h:57
#define NULL
Definition: types.h:112
#define skip(...)
Definition: atltest.h:64
#define OUT
Definition: typedefs.h:40
#define TEST_FREE(ret_expected, err_expected, threw_excepted, HeapHandle, Flags, Count, Array)
static FN_RtlMultipleFreeHeap g_free
unsigned int ULONG
Definition: retypes.h:1
#define TEST_ALLOC_NO_RET(err_expected, threw_excepted, HeapHandle, Flags, Size, Count, Array)
#define GetProcAddress(x, y)
Definition: compat.h:612
ULONG(NTAPI * FN_RtlMultipleFreeHeap)(IN PVOID, IN ULONG, IN ULONG, OUT PVOID *)
static void MultiHeapFreeTest()
#define HEAP_GENERATE_EXCEPTIONS
Definition: nt_native.h:1694
ULONG(NTAPI * FN_RtlMultipleAllocateHeap)(IN PVOID, IN ULONG, IN SIZE_T, IN ULONG, OUT PVOID *)