ReactOS 0.4.16-dev-197-g92996da
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
66static void
68{
69 array[0] = p0;
70 array[1] = p1;
71 array[2] = p2;
72}
73
74static 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
166static 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 INT_EXPECTED(var, value)
#define TEST_FREE(ret_expected, err_expected, threw_excepted, HeapHandle, Flags, Count, Array)
ULONG(NTAPI * FN_RtlMultipleAllocateHeap)(IN PVOID, IN ULONG, IN SIZE_T, IN ULONG, OUT PVOID *)
static FN_RtlMultipleFreeHeap g_free
#define TEST_ALLOC_NO_RET(err_expected, threw_excepted, HeapHandle, Flags, Size, Count, Array)
static FN_RtlMultipleAllocateHeap g_alloc
static void MultiHeapAllocTest()
static void MultiHeapFreeTest()
#define ASSUME_ARRAY_ITEMS_ARE_NULL()
ULONG(NTAPI * FN_RtlMultipleFreeHeap)(IN PVOID, IN ULONG, IN ULONG, OUT PVOID *)
#define TEST_ALLOC(ret_expected, err_expected, threw_excepted, HeapHandle, Flags, Size, Count, Array)
static void set_array(PVOID *array, PVOID p0, PVOID p1, PVOID p2)
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define NULL
Definition: types.h:112
#define GetProcessHeap()
Definition: compat.h:736
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define GetProcAddress(x, y)
Definition: compat.h:753
#define FreeLibrary(x)
Definition: compat.h:748
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryA(LPCSTR lpLibFileName)
Definition: loader.c:111
#define HEAP_GENERATE_EXCEPTIONS
Definition: nt_native.h:1694
#define err(...)
ULONG NTAPI RtlMultipleAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size, IN ULONG Count, OUT PVOID *Array)
Definition: heap.c:4131
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
ULONG_PTR SIZE_T
Definition: typedefs.h:80
int32_t INT
Definition: typedefs.h:58
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
int ret