2 * Unit test suite for heap functions
4 * Copyright 2003 Dimitrie O. Paun
5 * Copyright 2006 Detlef Riekenberg
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "wine/test.h"
29 #define MAGIC_DEAD 0xdeadbeef
31 static BOOL (WINAPI
*pHeapQueryInformation
)(HANDLE
, HEAP_INFORMATION_CLASS
, PVOID
, SIZE_T
, PSIZE_T
);
33 static SIZE_T
resize_9x(SIZE_T size
)
35 DWORD dwSizeAligned
= (size
+ 3) & ~3;
36 return max(dwSizeAligned
, 12); /* at least 12 bytes */
39 static void test_sized_HeapAlloc(int nbytes
)
42 char *buf
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, nbytes
);
43 ok(buf
!= NULL
, "allocate failed\n");
44 ok(buf
[0] == 0, "buffer not zeroed\n");
45 success
= HeapFree(GetProcessHeap(), 0, buf
);
46 ok(success
, "free failed\n");
49 static void test_sized_HeapReAlloc(int nbytes1
, int nbytes2
)
52 char *buf
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, nbytes1
);
53 ok(buf
!= NULL
, "allocate failed\n");
54 ok(buf
[0] == 0, "buffer not zeroed\n");
55 buf
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, buf
, nbytes2
);
56 ok(buf
!= NULL
, "reallocate failed\n");
57 ok(buf
[nbytes2
-1] == 0, "buffer not zeroed\n");
58 success
= HeapFree(GetProcessHeap(), 0, buf
);
59 ok(success
, "free failed\n");
62 static void test_heap(void)
72 /* Heap*() functions */
73 mem
= HeapAlloc(GetProcessHeap(), 0, 0);
74 ok(mem
!= NULL
, "memory not allocated for size 0\n");
75 HeapFree(GetProcessHeap(), 0, mem
);
77 mem
= HeapReAlloc(GetProcessHeap(), 0, NULL
, 10);
78 ok(mem
== NULL
, "memory allocated by HeapReAlloc\n");
80 for (size
= 0; size
<= 256; size
++)
83 mem
= HeapAlloc(GetProcessHeap(), 0, size
);
84 heap_size
= HeapSize(GetProcessHeap(), 0, mem
);
85 ok(heap_size
== size
|| heap_size
== resize_9x(size
),
86 "HeapSize returned %lu instead of %lu or %lu\n", heap_size
, size
, resize_9x(size
));
87 HeapFree(GetProcessHeap(), 0, mem
);
90 /* test some border cases of HeapAlloc and HeapReAlloc */
91 mem
= HeapAlloc(GetProcessHeap(), 0, 0);
92 ok(mem
!= NULL
, "memory not allocated for size 0\n");
93 msecond
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, mem
, ~(SIZE_T
)0 - 7);
94 ok(msecond
== NULL
, "HeapReAlloc(~0 - 7) should have failed\n");
95 msecond
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, mem
, ~(SIZE_T
)0);
96 ok(msecond
== NULL
, "HeapReAlloc(~0) should have failed\n");
97 HeapFree(GetProcessHeap(), 0, mem
);
98 mem
= HeapAlloc(GetProcessHeap(), 0, ~(SIZE_T
)0);
99 ok(mem
== NULL
, "memory allocated for size ~0\n");
101 /* large blocks must be 16-byte aligned */
102 mem
= HeapAlloc(GetProcessHeap(), 0, 512 * 1024);
103 ok( mem
!= NULL
, "failed for size 512K\n" );
104 ok( (ULONG_PTR
)mem
% 16 == 0 || broken((ULONG_PTR
)mem
% 16) /* win9x */,
105 "512K block not 16-byte aligned\n" );
106 HeapFree(GetProcessHeap(), 0, mem
);
108 /* Global*() functions */
109 gbl
= GlobalAlloc(GMEM_MOVEABLE
, 0);
110 ok(gbl
!= NULL
, "global memory not allocated for size 0\n");
112 gbl
= GlobalReAlloc(gbl
, 10, GMEM_MOVEABLE
);
113 ok(gbl
!= NULL
, "Can't realloc global memory\n");
114 size
= GlobalSize(gbl
);
115 ok(size
>= 10 && size
<= 16, "Memory not resized to size 10, instead size=%ld\n", size
);
117 gbl
= GlobalReAlloc(gbl
, 0, GMEM_MOVEABLE
);
118 ok(gbl
!= NULL
, "GlobalReAlloc should not fail on size 0\n");
120 size
= GlobalSize(gbl
);
121 ok(size
== 0, "Memory not resized to size 0, instead size=%ld\n", size
);
122 ok(GlobalFree(gbl
) == NULL
, "Memory not freed\n");
123 size
= GlobalSize(gbl
);
124 ok(size
== 0, "Memory should have been freed, size=%ld\n", size
);
126 gbl
= GlobalReAlloc(0, 10, GMEM_MOVEABLE
);
127 ok(gbl
== NULL
, "global realloc allocated memory\n");
129 /* GlobalLock / GlobalUnlock with a valid handle */
130 gbl
= GlobalAlloc(GMEM_MOVEABLE
, 256);
132 SetLastError(MAGIC_DEAD
);
133 mem
= GlobalLock(gbl
); /* #1 */
134 ok(mem
!= NULL
, "returned %p with %d (expected '!= NULL')\n", mem
, GetLastError());
135 SetLastError(MAGIC_DEAD
);
136 flags
= GlobalFlags(gbl
);
137 ok( flags
== 1, "returned 0x%04x with %d (expected '0x0001')\n",
138 flags
, GetLastError());
140 SetLastError(MAGIC_DEAD
);
141 msecond
= GlobalLock(gbl
); /* #2 */
142 ok( msecond
== mem
, "returned %p with %d (expected '%p')\n",
143 msecond
, GetLastError(), mem
);
144 SetLastError(MAGIC_DEAD
);
145 flags
= GlobalFlags(gbl
);
146 ok( flags
== 2, "returned 0x%04x with %d (expected '0x0002')\n",
147 flags
, GetLastError());
148 SetLastError(MAGIC_DEAD
);
150 SetLastError(MAGIC_DEAD
);
151 res
= GlobalUnlock(gbl
); /* #1 */
152 ok(res
, "returned %d with %d (expected '!= 0')\n", res
, GetLastError());
153 SetLastError(MAGIC_DEAD
);
154 flags
= GlobalFlags(gbl
);
155 ok( flags
, "returned 0x%04x with %d (expected '!= 0')\n",
156 flags
, GetLastError());
158 SetLastError(MAGIC_DEAD
);
159 res
= GlobalUnlock(gbl
); /* #0 */
160 /* NT: ERROR_SUCCESS (documented on MSDN), 9x: untouched */
161 ok(!res
&& ((GetLastError() == ERROR_SUCCESS
) || (GetLastError() == MAGIC_DEAD
)),
162 "returned %d with %d (expected '0' with: ERROR_SUCCESS or "
163 "MAGIC_DEAD)\n", res
, GetLastError());
164 SetLastError(MAGIC_DEAD
);
165 flags
= GlobalFlags(gbl
);
166 ok( !flags
, "returned 0x%04x with %d (expected '0')\n",
167 flags
, GetLastError());
169 /* Unlock an already unlocked Handle */
170 SetLastError(MAGIC_DEAD
);
171 res
= GlobalUnlock(gbl
);
172 /* NT: ERROR_NOT_LOCKED, 9x: untouched */
174 ((GetLastError() == ERROR_NOT_LOCKED
) || (GetLastError() == MAGIC_DEAD
)),
175 "returned %d with %d (expected '0' with: ERROR_NOT_LOCKED or "
176 "MAGIC_DEAD)\n", res
, GetLastError());
179 /* invalid handles are caught in windows: */
180 SetLastError(MAGIC_DEAD
);
181 hsecond
= GlobalFree(gbl
); /* invalid handle: free memory twice */
182 ok( (hsecond
== gbl
) && (GetLastError() == ERROR_INVALID_HANDLE
),
183 "returned %p with 0x%08x (expected %p with ERROR_INVALID_HANDLE)\n",
184 hsecond
, GetLastError(), gbl
);
185 SetLastError(MAGIC_DEAD
);
186 flags
= GlobalFlags(gbl
);
187 ok( (flags
== GMEM_INVALID_HANDLE
) && (GetLastError() == ERROR_INVALID_HANDLE
),
188 "returned 0x%04x with 0x%08x (expected GMEM_INVALID_HANDLE with "
189 "ERROR_INVALID_HANDLE)\n", flags
, GetLastError());
190 SetLastError(MAGIC_DEAD
);
191 size
= GlobalSize(gbl
);
192 ok( (size
== 0) && (GetLastError() == ERROR_INVALID_HANDLE
),
193 "returned %ld with 0x%08x (expected '0' with ERROR_INVALID_HANDLE)\n",
194 size
, GetLastError());
196 SetLastError(MAGIC_DEAD
);
197 mem
= GlobalLock(gbl
);
198 ok( (mem
== NULL
) && (GetLastError() == ERROR_INVALID_HANDLE
),
199 "returned %p with 0x%08x (expected NULL with ERROR_INVALID_HANDLE)\n",
200 mem
, GetLastError());
202 /* documented on MSDN: GlobalUnlock() return FALSE on failure.
203 Win9x and wine return FALSE with ERROR_INVALID_HANDLE, but on
204 NT 3.51 and XPsp2, TRUE with ERROR_INVALID_HANDLE is returned.
205 The similar Test for LocalUnlock() works on all Systems */
206 SetLastError(MAGIC_DEAD
);
207 res
= GlobalUnlock(gbl
);
208 ok(GetLastError() == ERROR_INVALID_HANDLE
,
209 "returned %d with %d (expected ERROR_INVALID_HANDLE)\n",
210 res
, GetLastError());
212 gbl
= GlobalAlloc(GMEM_DDESHARE
, 100);
215 mem
= GlobalFree(gbl
);
216 ok(mem
== NULL
, "Expected NULL, got %p\n", mem
);
219 if (sizeof(void *) != 8) /* crashes on 64-bit Vista */
221 SetLastError(MAGIC_DEAD
);
222 mem
= GlobalFree(gbl
);
223 ok(mem
== gbl
|| broken(mem
== NULL
) /* nt4 */, "Expected gbl, got %p\n", mem
);
225 ok(GetLastError() == ERROR_INVALID_HANDLE
||
226 GetLastError() == ERROR_INVALID_PARAMETER
, /* win9x */
227 "Expected ERROR_INVALID_HANDLE or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
230 gbl
= GlobalAlloc(GMEM_DDESHARE
, 100);
232 res
= GlobalUnlock(gbl
);
234 res
== 0, /* win9x */
235 "Expected 1 or 0, got %d\n", res
);
237 res
= GlobalUnlock(gbl
);
239 res
== 0, /* win9x */
240 "Expected 1 or 0, got %d\n", res
);
242 /* GlobalSize on an invalid handle */
243 if (sizeof(void *) != 8) /* crashes on 64-bit Vista */
245 SetLastError(MAGIC_DEAD
);
246 size
= GlobalSize((HGLOBAL
)0xc042);
247 ok(size
== 0, "Expected 0, got %ld\n", size
);
248 ok(GetLastError() == ERROR_INVALID_HANDLE
||
249 GetLastError() == ERROR_INVALID_PARAMETER
, /* win9x */
250 "Expected ERROR_INVALID_HANDLE or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
255 /* ####################################### */
256 /* Local*() functions */
257 gbl
= LocalAlloc(LMEM_MOVEABLE
, 0);
258 ok(gbl
!= NULL
, "local memory not allocated for size 0\n");
260 gbl
= LocalReAlloc(gbl
, 10, LMEM_MOVEABLE
);
261 ok(gbl
!= NULL
, "Can't realloc local memory\n");
262 size
= LocalSize(gbl
);
263 ok(size
>= 10 && size
<= 16, "Memory not resized to size 10, instead size=%ld\n", size
);
265 gbl
= LocalReAlloc(gbl
, 0, LMEM_MOVEABLE
);
266 ok(gbl
!= NULL
, "LocalReAlloc should not fail on size 0\n");
268 size
= LocalSize(gbl
);
269 ok(size
== 0, "Memory not resized to size 0, instead size=%ld\n", size
);
270 ok(LocalFree(gbl
) == NULL
, "Memory not freed\n");
271 size
= LocalSize(gbl
);
272 ok(size
== 0, "Memory should have been freed, size=%ld\n", size
);
274 gbl
= LocalReAlloc(0, 10, LMEM_MOVEABLE
);
275 ok(gbl
== NULL
, "local realloc allocated memory\n");
277 /* LocalLock / LocalUnlock with a valid handle */
278 gbl
= LocalAlloc(LMEM_MOVEABLE
, 256);
279 SetLastError(MAGIC_DEAD
);
280 mem
= LocalLock(gbl
); /* #1 */
281 ok(mem
!= NULL
, "returned %p with %d (expected '!= NULL')\n", mem
, GetLastError());
282 SetLastError(MAGIC_DEAD
);
283 flags
= LocalFlags(gbl
);
284 ok( flags
== 1, "returned 0x%04x with %d (expected '0x0001')\n",
285 flags
, GetLastError());
287 SetLastError(MAGIC_DEAD
);
288 msecond
= LocalLock(gbl
); /* #2 */
289 ok( msecond
== mem
, "returned %p with %d (expected '%p')\n",
290 msecond
, GetLastError(), mem
);
291 SetLastError(MAGIC_DEAD
);
292 flags
= LocalFlags(gbl
);
293 ok( flags
== 2, "returned 0x%04x with %d (expected '0x0002')\n",
294 flags
, GetLastError());
295 SetLastError(MAGIC_DEAD
);
297 SetLastError(MAGIC_DEAD
);
298 res
= LocalUnlock(gbl
); /* #1 */
299 ok(res
, "returned %d with %d (expected '!= 0')\n", res
, GetLastError());
300 SetLastError(MAGIC_DEAD
);
301 flags
= LocalFlags(gbl
);
302 ok( flags
, "returned 0x%04x with %d (expected '!= 0')\n",
303 flags
, GetLastError());
305 SetLastError(MAGIC_DEAD
);
306 res
= LocalUnlock(gbl
); /* #0 */
307 /* NT: ERROR_SUCCESS (documented on MSDN), 9x: untouched */
308 ok(!res
&& ((GetLastError() == ERROR_SUCCESS
) || (GetLastError() == MAGIC_DEAD
)),
309 "returned %d with %d (expected '0' with: ERROR_SUCCESS or "
310 "MAGIC_DEAD)\n", res
, GetLastError());
311 SetLastError(MAGIC_DEAD
);
312 flags
= LocalFlags(gbl
);
313 ok( !flags
, "returned 0x%04x with %d (expected '0')\n",
314 flags
, GetLastError());
316 /* Unlock an already unlocked Handle */
317 SetLastError(MAGIC_DEAD
);
318 res
= LocalUnlock(gbl
);
319 /* NT: ERROR_NOT_LOCKED, 9x: untouched */
321 ((GetLastError() == ERROR_NOT_LOCKED
) || (GetLastError() == MAGIC_DEAD
)),
322 "returned %d with %d (expected '0' with: ERROR_NOT_LOCKED or "
323 "MAGIC_DEAD)\n", res
, GetLastError());
326 /* invalid handles are caught in windows: */
327 SetLastError(MAGIC_DEAD
);
328 hsecond
= LocalFree(gbl
); /* invalid handle: free memory twice */
329 ok( (hsecond
== gbl
) && (GetLastError() == ERROR_INVALID_HANDLE
),
330 "returned %p with 0x%08x (expected %p with ERROR_INVALID_HANDLE)\n",
331 hsecond
, GetLastError(), gbl
);
332 SetLastError(MAGIC_DEAD
);
333 flags
= LocalFlags(gbl
);
334 ok( (flags
== LMEM_INVALID_HANDLE
) && (GetLastError() == ERROR_INVALID_HANDLE
),
335 "returned 0x%04x with 0x%08x (expected LMEM_INVALID_HANDLE with "
336 "ERROR_INVALID_HANDLE)\n", flags
, GetLastError());
337 SetLastError(MAGIC_DEAD
);
338 size
= LocalSize(gbl
);
339 ok( (size
== 0) && (GetLastError() == ERROR_INVALID_HANDLE
),
340 "returned %ld with 0x%08x (expected '0' with ERROR_INVALID_HANDLE)\n",
341 size
, GetLastError());
343 SetLastError(MAGIC_DEAD
);
344 mem
= LocalLock(gbl
);
345 ok( (mem
== NULL
) && (GetLastError() == ERROR_INVALID_HANDLE
),
346 "returned %p with 0x%08x (expected NULL with ERROR_INVALID_HANDLE)\n",
347 mem
, GetLastError());
349 /* This Test works the same on all Systems (GlobalUnlock() is different) */
350 SetLastError(MAGIC_DEAD
);
351 res
= LocalUnlock(gbl
);
352 ok(!res
&& (GetLastError() == ERROR_INVALID_HANDLE
),
353 "returned %d with %d (expected '0' with ERROR_INVALID_HANDLE)\n",
354 res
, GetLastError());
356 /* trying to lock empty memory should give an error */
357 gbl
= GlobalAlloc(GMEM_MOVEABLE
|GMEM_ZEROINIT
,0);
358 ok(gbl
!= NULL
, "returned NULL\n");
359 SetLastError(MAGIC_DEAD
);
360 mem
= GlobalLock(gbl
);
361 /* NT: ERROR_DISCARDED, 9x: untouched */
363 ((GetLastError() == ERROR_DISCARDED
) || (GetLastError() == MAGIC_DEAD
)),
364 "returned %p with 0x%x/%d (expected 'NULL' with: ERROR_DISCARDED or "
365 "MAGIC_DEAD)\n", mem
, GetLastError(), GetLastError());
370 static void test_obsolete_flags(void)
375 } test_global_flags
[] = {
376 {GMEM_FIXED
| GMEM_NOTIFY
, 0},
377 {GMEM_FIXED
| GMEM_DISCARDABLE
, 0},
378 {GMEM_MOVEABLE
| GMEM_NOTIFY
, 0},
379 {GMEM_MOVEABLE
| GMEM_DDESHARE
, GMEM_DDESHARE
},
380 {GMEM_MOVEABLE
| GMEM_NOT_BANKED
, 0},
381 {GMEM_MOVEABLE
| GMEM_NODISCARD
, 0},
382 {GMEM_MOVEABLE
| GMEM_DISCARDABLE
, GMEM_DISCARDABLE
},
383 {GMEM_MOVEABLE
| GMEM_DDESHARE
| GMEM_DISCARDABLE
| GMEM_LOWER
| GMEM_NOCOMPACT
| GMEM_NODISCARD
|
384 GMEM_NOT_BANKED
| GMEM_NOTIFY
, GMEM_DDESHARE
| GMEM_DISCARDABLE
},
391 UINT (WINAPI
*pGlobalFlags
)(HGLOBAL
);
393 pGlobalFlags
= (void *) GetProcAddress(GetModuleHandleA("kernel32"), "GlobalFlags");
397 win_skip("GlobalFlags is not available\n");
401 for (i
= 0; i
< sizeof(test_global_flags
)/sizeof(test_global_flags
[0]); i
++)
403 gbl
= GlobalAlloc(test_global_flags
[i
].flags
, 4);
404 ok(gbl
!= NULL
, "GlobalAlloc failed\n");
406 SetLastError(MAGIC_DEAD
);
407 resultflags
= pGlobalFlags(gbl
);
409 ok( resultflags
== test_global_flags
[i
].globalflags
||
410 broken(resultflags
== (test_global_flags
[i
].globalflags
& ~GMEM_DDESHARE
)), /* win9x */
411 "%u: expected 0x%08x, but returned 0x%08x with %d\n",
412 i
, test_global_flags
[i
].globalflags
, resultflags
, GetLastError() );
418 static void test_HeapQueryInformation(void)
424 pHeapQueryInformation
= (void *)GetProcAddress(GetModuleHandle("kernel32.dll"), "HeapQueryInformation");
425 if (!pHeapQueryInformation
)
427 win_skip("HeapQueryInformation is not available\n");
431 if (0) /* crashes under XP */
434 ret
= pHeapQueryInformation(0,
435 HeapCompatibilityInformation
,
436 &info
, sizeof(info
), &size
);
438 ret
= pHeapQueryInformation(GetProcessHeap(),
439 HeapCompatibilityInformation
,
440 NULL
, sizeof(info
), &size
);
444 SetLastError(0xdeadbeef);
445 ret
= pHeapQueryInformation(GetProcessHeap(),
446 HeapCompatibilityInformation
,
448 ok(!ret
, "HeapQueryInformation should fail\n");
449 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
450 "expected ERROR_INSUFFICIENT_BUFFER got %u\n", GetLastError());
451 ok(size
== sizeof(ULONG
), "expected 4, got %lu\n", size
);
453 SetLastError(0xdeadbeef);
454 ret
= pHeapQueryInformation(GetProcessHeap(),
455 HeapCompatibilityInformation
,
457 ok(!ret
, "HeapQueryInformation should fail\n");
458 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
459 "expected ERROR_INSUFFICIENT_BUFFER got %u\n", GetLastError());
462 SetLastError(0xdeadbeef);
463 ret
= pHeapQueryInformation(GetProcessHeap(),
464 HeapCompatibilityInformation
,
465 &info
, sizeof(info
) + 1, NULL
);
466 ok(ret
, "HeapQueryInformation error %u\n", GetLastError());
467 ok(info
== 0 || info
== 1 || info
== 2, "expected 0, 1 or 2, got %u\n", info
);
473 test_obsolete_flags();
475 /* Test both short and very long blocks */
476 test_sized_HeapAlloc(1);
477 test_sized_HeapAlloc(1 << 20);
478 test_sized_HeapReAlloc(1, 100);
479 test_sized_HeapReAlloc(1, (1 << 20));
480 test_sized_HeapReAlloc((1 << 20), (2 << 20));
481 test_sized_HeapReAlloc((1 << 20), 1);
482 test_HeapQueryInformation();