2 * Unit test suite for heap functions
4 * Copyright 2002 Geoffrey Hausheer
5 * Copyright 2003 Dimitrie O. Paun
6 * Copyright 2006 Detlef Riekenberg
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #include "wine/test.h"
33 /* some undocumented flags (names are made up) */
34 #define HEAP_ADD_USER_INFO 0x00000100
35 #define HEAP_PRIVATE 0x00001000
36 #define HEAP_PAGE_ALLOCS 0x01000000
37 #define HEAP_VALIDATE 0x10000000
38 #define HEAP_VALIDATE_ALL 0x20000000
39 #define HEAP_VALIDATE_PARAMS 0x40000000
41 #define BLOCK_ALIGN (2 * sizeof(void *) - 1)
42 #define ALIGN_BLOCK_SIZE(x) (((x) + BLOCK_ALIGN) & ~BLOCK_ALIGN)
44 /* use function pointers to avoid warnings for invalid parameter tests */
45 static LPVOID (WINAPI
*pHeapAlloc
)(HANDLE
,DWORD
,SIZE_T
);
46 static LPVOID (WINAPI
*pHeapReAlloc
)(HANDLE
,DWORD
,LPVOID
,SIZE_T
);
47 static BOOL (WINAPI
*pHeapFree
)(HANDLE
,DWORD
,LPVOID
);
48 static BOOL (WINAPI
*pGetPhysicallyInstalledSystemMemory
)( ULONGLONG
* );
49 static BOOLEAN (WINAPI
*pRtlGetUserInfoHeap
)(HANDLE
,ULONG
,void*,void**,ULONG
*);
50 static BOOLEAN (WINAPI
*pRtlSetUserValueHeap
)(HANDLE
,ULONG
,void*,void*);
51 static BOOLEAN (WINAPI
*pRtlSetUserFlagsHeap
)(HANDLE
,ULONG
,void*,ULONG
,ULONG
);
52 static HGLOBAL (WINAPI
*pGlobalAlloc
)(UINT
,SIZE_T
);
53 static HGLOBAL (WINAPI
*pGlobalFree
)(HGLOBAL
);
54 static HGLOBAL (WINAPI
*pLocalAlloc
)(UINT
,SIZE_T
);
55 static HGLOBAL (WINAPI
*pLocalFree
)(HLOCAL
);
56 static BOOL (WINAPI
*pHeapQueryInformation
)(HANDLE
,HEAP_INFORMATION_CLASS
,void*,SIZE_T
,SIZE_T
*);
57 static BOOL (WINAPI
*pHeapSetInformation
)(HANDLE
,HEAP_INFORMATION_CLASS
,void*,SIZE_T
);
58 static UINT (WINAPI
*pGlobalFlags
)(HGLOBAL
);
59 static ULONG (WINAPI
*pRtlGetNtGlobalFlags
)(void);
61 static void load_functions(void)
63 HMODULE kernel32
= GetModuleHandleW( L
"kernel32.dll" );
64 HMODULE ntdll
= GetModuleHandleW( L
"ntdll.dll" );
66 #define LOAD_FUNC(m, f) p ## f = (void *)GetProcAddress( m, #f );
67 LOAD_FUNC( kernel32
, HeapAlloc
);
68 LOAD_FUNC( kernel32
, HeapReAlloc
);
69 LOAD_FUNC( kernel32
, HeapFree
);
70 LOAD_FUNC( kernel32
, HeapQueryInformation
);
71 LOAD_FUNC( kernel32
, HeapSetInformation
);
72 LOAD_FUNC( kernel32
, GetPhysicallyInstalledSystemMemory
);
73 LOAD_FUNC( kernel32
, GlobalAlloc
);
74 LOAD_FUNC( kernel32
, GlobalFlags
);
75 LOAD_FUNC( kernel32
, GlobalFree
);
76 LOAD_FUNC( kernel32
, LocalAlloc
);
77 LOAD_FUNC( kernel32
, LocalFree
);
78 LOAD_FUNC( ntdll
, RtlGetNtGlobalFlags
);
79 LOAD_FUNC( ntdll
, RtlGetUserInfoHeap
);
80 LOAD_FUNC( ntdll
, RtlSetUserValueHeap
);
81 LOAD_FUNC( ntdll
, RtlSetUserFlagsHeap
);
98 /* undocumented RtlWalkHeap structure */
100 struct rtl_heap_entry
103 SIZE_T cbData
; /* differs from PROCESS_HEAP_ENTRY */
106 WORD wFlags
; /* value differs from PROCESS_HEAP_ENTRY */
113 DWORD dwCommittedSize
;
114 DWORD dwUnCommittedSize
;
121 /* rtl_heap_entry flags, names made up */
123 #define RTL_HEAP_ENTRY_BUSY 0x0001
124 #define RTL_HEAP_ENTRY_REGION 0x0002
125 #define RTL_HEAP_ENTRY_BLOCK 0x0010
126 #define RTL_HEAP_ENTRY_UNCOMMITTED 0x1000
127 #define RTL_HEAP_ENTRY_COMMITTED 0x4000
128 #define RTL_HEAP_ENTRY_LFH 0x8000
131 struct heap_thread_params
142 DWORD WINAPI
heap_thread_proc( void *arg
)
144 struct heap_thread_params
*params
= arg
;
149 SetEvent( params
->ready_event
);
151 while (!(res
= WaitForSingleObject( params
->start_event
, INFINITE
)) && !params
->done
)
155 ret
= HeapLock( params
->heap
);
156 ok( ret
, "HeapLock failed, error %lu\n", GetLastError() );
159 ptr
= HeapAlloc( params
->heap
, params
->flags
, 0 );
160 ok( !!ptr
, "HeapAlloc failed, error %lu\n", GetLastError() );
161 ret
= HeapFree( params
->heap
, params
->flags
, ptr
);
162 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
166 ret
= HeapUnlock( params
->heap
);
167 ok( ret
, "HeapUnlock failed, error %lu\n", GetLastError() );
170 SetEvent( params
->ready_event
);
172 ok( !res
, "WaitForSingleObject returned %#lx, error %lu\n", res
, GetLastError() );
178 static void test_HeapCreate(void)
180 static const BYTE buffer
[512] = {0};
181 SIZE_T alloc_size
= 0x8000 * sizeof(void *), size
, i
;
182 struct rtl_heap_entry rtl_entry
, rtl_entries
[256];
183 struct heap_thread_params thread_params
= {0};
184 PROCESS_HEAP_ENTRY entry
, entries
[256];
185 HANDLE heap
, heap1
, heaps
[8], thread
;
186 BYTE
*ptr
, *ptr1
, *ptrs
[128];
187 DWORD heap_count
, count
;
193 thread_params
.ready_event
= CreateEventW( NULL
, FALSE
, FALSE
, NULL
);
194 ok( !!thread_params
.ready_event
, "CreateEventW failed, error %lu\n", GetLastError() );
195 thread_params
.start_event
= CreateEventW( NULL
, FALSE
, FALSE
, NULL
);
196 ok( !!thread_params
.start_event
, "CreateEventW failed, error %lu\n", GetLastError() );
197 thread
= CreateThread( NULL
, 0, heap_thread_proc
, &thread_params
, 0, NULL
);
198 ok( !!thread
, "CreateThread failed, error %lu\n", GetLastError() );
199 res
= WaitForSingleObject( thread_params
.ready_event
, INFINITE
);
200 ok( !res
, "WaitForSingleObject returned %#lx, error %lu\n", res
, GetLastError() );
202 heap_count
= GetProcessHeaps( 0, NULL
);
203 ok( heap_count
<= 6, "GetProcessHeaps returned %lu\n", heap_count
);
205 /* check heap alignment */
207 heap
= HeapCreate( 0, 0, 0 );
208 ok( !!heap
, "HeapCreate failed, error %lu\n", GetLastError() );
209 ok( !((ULONG_PTR
)heap
& 0xffff), "wrong heap alignment\n" );
210 count
= GetProcessHeaps( 0, NULL
);
211 ok( count
== heap_count
+ 1, "GetProcessHeaps returned %lu\n", count
);
212 heap1
= HeapCreate( 0, 0, 0 );
213 ok( !!heap
, "HeapCreate failed, error %lu\n", GetLastError() );
214 ok( !((ULONG_PTR
)heap1
& 0xffff), "wrong heap alignment\n" );
215 count
= GetProcessHeaps( 0, NULL
);
216 ok( count
== heap_count
+ 2, "GetProcessHeaps returned %lu\n", count
);
217 count
= GetProcessHeaps( ARRAY_SIZE(heaps
), heaps
);
218 ok( count
== heap_count
+ 2, "GetProcessHeaps returned %lu\n", count
);
219 ok( heaps
[0] == GetProcessHeap(), "got wrong heap\n" );
221 ok( heaps
[heap_count
+ 0] == heap
, "got wrong heap\n" );
223 ok( heaps
[heap_count
+ 1] == heap1
, "got wrong heap\n" );
224 ret
= HeapDestroy( heap1
);
225 ok( ret
, "HeapDestroy failed, error %lu\n", GetLastError() );
226 ret
= HeapDestroy( heap
);
227 ok( ret
, "HeapDestroy failed, error %lu\n", GetLastError() );
228 count
= GetProcessHeaps( 0, NULL
);
229 ok( count
== heap_count
, "GetProcessHeaps returned %lu\n", count
);
233 heap
= HeapCreate( 0, 0, 0 );
234 ok( !!heap
, "HeapCreate failed, error %lu\n", GetLastError() );
235 ok( !((ULONG_PTR
)heap
& 0xffff), "wrong heap alignment\n" );
237 /* test some border cases */
239 ret
= HeapFree( NULL
, 0, NULL
);
240 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
241 ret
= HeapFree( heap
, 0, NULL
);
242 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
245 SetLastError( 0xdeadbeef );
246 ret
= HeapFree( heap
, 0, (void *)0xdeadbe00 );
247 ok( !ret
, "HeapFree succeeded\n" );
248 ok( GetLastError() == ERROR_NOACCESS
, "got error %lu\n", GetLastError() );
249 SetLastError( 0xdeadbeef );
250 ptr
= (BYTE
*)((UINT_PTR
)buffer
& ~63) + 64;
251 ret
= HeapFree( heap
, 0, ptr
);
252 ok( !ret
, "HeapFree succeeded\n" );
253 ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() );
256 SetLastError( 0xdeadbeef );
257 ptr
= HeapReAlloc( heap
, 0, NULL
, 1 );
258 ok( !ptr
, "HeapReAlloc succeeded\n" );
260 ok( GetLastError() == NO_ERROR
, "got error %lu\n", GetLastError() );
263 SetLastError( 0xdeadbeef );
264 ptr1
= HeapReAlloc( heap
, 0, (void *)0xdeadbe00, 1 );
265 ok( !ptr1
, "HeapReAlloc succeeded\n" );
266 ok( GetLastError() == ERROR_NOACCESS
, "got error %lu\n", GetLastError() );
267 ret
= HeapValidate( heap
, 0, (void *)0xdeadbe00 );
268 ok( !ret
, "HeapValidate succeeded\n" );
269 ok( GetLastError() == ERROR_NOACCESS
, "got error %lu\n", GetLastError() );
270 SetLastError( 0xdeadbeef );
271 ptr
= (BYTE
*)((UINT_PTR
)buffer
& ~63) + 64;
272 ptr1
= HeapReAlloc( heap
, 0, ptr
, 1 );
273 ok( !ptr1
, "HeapReAlloc succeeded\n" );
274 ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() );
277 SetLastError( 0xdeadbeef );
278 ret
= HeapValidate( heap
, 0, NULL
);
279 ok( ret
, "HeapValidate failed, error %lu\n", GetLastError() );
280 ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() );
281 ptr
= (BYTE
*)((UINT_PTR
)buffer
& ~63) + 64;
282 ret
= HeapValidate( heap
, 0, ptr
);
283 ok( !ret
, "HeapValidate succeeded\n" );
284 ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() );
286 ptr
= HeapAlloc( heap
, 0, 0 );
287 ok( !!ptr
, "HeapAlloc failed, error %lu\n", GetLastError() );
288 size
= HeapSize( heap
, 0, ptr
);
289 ok( size
== 0, "HeapSize returned %#Ix, error %lu\n", size
, GetLastError() );
290 ptr1
= pHeapReAlloc( heap
, 0, ptr
, ~(SIZE_T
)0 - 7 );
291 ok( !ptr1
, "HeapReAlloc succeeded\n" );
292 ptr1
= pHeapReAlloc( heap
, 0, ptr
, ~(SIZE_T
)0 );
293 ok( !ptr1
, "HeapReAlloc succeeded\n" );
294 ret
= HeapValidate( heap
, 0, ptr
);
295 ok( ret
, "HeapValidate failed, error %lu\n", GetLastError() );
296 ret
= pHeapFree( heap
, 0, ptr
);
297 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
298 SetLastError( 0xdeadbeef );
299 ret
= HeapValidate( heap
, 0, ptr
);
300 ok( !ret
, "HeapValidate succeeded\n" );
301 ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() );
303 ptr
= pHeapAlloc( heap
, 0, ~(SIZE_T
)0 );
304 ok( !ptr
, "HeapAlloc succeeded\n" );
306 ptr
= HeapAlloc( heap
, 0, 1 );
307 ok( !!ptr
, "HeapAlloc failed, error %lu\n", GetLastError() );
308 ptr1
= HeapReAlloc( heap
, 0, ptr
, 0 );
309 ok( !!ptr1
, "HeapReAlloc failed, error %lu\n", GetLastError() );
310 size
= HeapSize( heap
, 0, ptr1
);
311 ok( size
== 0, "HeapSize returned %#Ix, error %lu\n", size
, GetLastError() );
312 ret
= HeapFree( heap
, 0, ptr
);
313 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
315 ptr
= HeapAlloc( heap
, 0, 5 * alloc_size
+ 1 );
316 ok( !!ptr
, "HeapAlloc failed, error %lu\n", GetLastError() );
317 ret
= HeapFree( heap
, 0, ptr
);
318 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
320 ptr
= HeapAlloc( heap
, 0, alloc_size
);
321 ok( !!ptr
, "HeapAlloc failed, error %lu\n", GetLastError() );
322 size
= HeapSize( heap
, 0, ptr
);
323 ok( size
== alloc_size
, "HeapSize returned %#Ix, error %lu\n", size
, GetLastError() );
324 ptr1
= HeapAlloc( heap
, 0, 4 * alloc_size
);
325 ok( !!ptr1
, "HeapAlloc failed, error %lu\n", GetLastError() );
326 ret
= HeapFree( heap
, 0, ptr1
);
327 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
328 ret
= HeapFree( heap
, 0, ptr
);
329 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
331 /* test pointer alignment */
334 for (i
= 0; i
< ARRAY_SIZE(ptrs
); ++i
)
336 ptrs
[i
] = HeapAlloc( heap
, 0, alloc_size
);
337 ok( !!ptrs
[i
], "HeapAlloc failed, error %lu\n", GetLastError() );
338 align
|= (UINT_PTR
)ptrs
[i
];
340 ok( !(align
& (2 * sizeof(void *) - 1)), "got wrong alignment\n" );
341 ok( align
& (2 * sizeof(void *)), "got wrong alignment\n" );
342 for (i
= 0; i
< ARRAY_SIZE(ptrs
); ++i
)
344 ret
= HeapFree( heap
, 0, ptrs
[i
] );
345 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
349 for (i
= 0; i
< ARRAY_SIZE(ptrs
); ++i
)
351 ptrs
[i
] = HeapAlloc( heap
, 0, 4 * alloc_size
);
352 ok( !!ptrs
[i
], "HeapAlloc failed, error %lu\n", GetLastError() );
353 align
|= (UINT_PTR
)ptrs
[i
];
355 ok( !(align
& (8 * sizeof(void *) - 1)), "got wrong alignment\n" );
356 ok( align
& (8 * sizeof(void *)), "got wrong alignment\n" );
357 for (i
= 0; i
< ARRAY_SIZE(ptrs
); ++i
)
359 ret
= HeapFree( heap
, 0, ptrs
[i
] );
360 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
363 /* test HEAP_ZERO_MEMORY */
365 ptr
= HeapAlloc( heap
, HEAP_ZERO_MEMORY
, 1 );
366 ok( !!ptr
, "HeapAlloc failed, error %lu\n", GetLastError() );
367 size
= HeapSize( heap
, 0, ptr
);
368 ok( size
== 1, "HeapSize returned %#Ix, error %lu\n", size
, GetLastError() );
369 while (size
) if (ptr
[--size
]) break;
370 ok( !size
&& !ptr
[0], "memory wasn't zeroed\n" );
371 ret
= HeapFree( heap
, 0, ptr
);
372 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
374 ptr
= HeapAlloc( heap
, HEAP_ZERO_MEMORY
, (1 << 20) );
375 ok( !!ptr
, "HeapAlloc failed, error %lu\n", GetLastError() );
376 size
= HeapSize( heap
, 0, ptr
);
377 ok( size
== (1 << 20), "HeapSize returned %#Ix, error %lu\n", size
, GetLastError() );
378 while (size
) if (ptr
[--size
]) break;
379 ok( !size
&& !ptr
[0], "memory wasn't zeroed\n" );
380 ret
= HeapFree( heap
, 0, ptr
);
381 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
383 ptr
= HeapAlloc( heap
, HEAP_ZERO_MEMORY
, alloc_size
);
384 ok( !!ptr
, "HeapAlloc failed, error %lu\n", GetLastError() );
385 size
= HeapSize( heap
, 0, ptr
);
386 ok( size
== alloc_size
, "HeapSize returned %#Ix, error %lu\n", size
, GetLastError() );
387 while (size
) if (ptr
[--size
]) break;
388 ok( !size
&& !ptr
[0], "memory wasn't zeroed\n" );
390 ptr
= HeapReAlloc( heap
, HEAP_ZERO_MEMORY
, ptr
, 3 * alloc_size
);
391 ok( !!ptr
, "HeapReAlloc failed, error %lu\n", GetLastError() );
392 size
= HeapSize( heap
, 0, ptr
);
393 ok( size
== 3 * alloc_size
, "HeapSize returned %#Ix, error %lu\n", size
, GetLastError() );
394 while (size
) if (ptr
[--size
]) break;
395 ok( !size
&& !ptr
[0], "memory wasn't zeroed\n" );
397 /* shrinking a small-ish block in place and growing back is okay */
398 ptr1
= HeapReAlloc( heap
, HEAP_REALLOC_IN_PLACE_ONLY
, ptr
, alloc_size
* 3 / 2 );
399 ok( ptr1
== ptr
, "HeapReAlloc HEAP_REALLOC_IN_PLACE_ONLY failed, error %lu\n", GetLastError() );
400 ptr1
= HeapReAlloc( heap
, HEAP_REALLOC_IN_PLACE_ONLY
, ptr
, 2 * alloc_size
);
401 ok( ptr1
== ptr
, "HeapReAlloc HEAP_REALLOC_IN_PLACE_ONLY failed, error %lu\n", GetLastError() );
403 ptr
= HeapReAlloc( heap
, HEAP_ZERO_MEMORY
, ptr
, 1 );
404 ok( !!ptr
, "HeapReAlloc failed, error %lu\n", GetLastError() );
405 size
= HeapSize( heap
, 0, ptr
);
406 ok( size
== 1, "HeapSize returned %#Ix, error %lu\n", size
, GetLastError() );
407 while (size
) if (ptr
[--size
]) break;
408 ok( !size
&& !ptr
[0], "memory wasn't zeroed\n" );
410 ptr
= HeapReAlloc( heap
, HEAP_ZERO_MEMORY
, ptr
, (1 << 20) );
411 ok( !!ptr
, "HeapReAlloc failed, error %lu\n", GetLastError() );
412 size
= HeapSize( heap
, 0, ptr
);
413 ok( size
== (1 << 20), "HeapSize returned %#Ix, error %lu\n", size
, GetLastError() );
414 while (size
) if (ptr
[--size
]) break;
415 ok( !size
&& !ptr
[0], "memory wasn't zeroed\n" );
417 /* shrinking a very large block decommits pages and fail to grow in place */
418 ptr1
= HeapReAlloc( heap
, HEAP_REALLOC_IN_PLACE_ONLY
, ptr
, alloc_size
* 3 / 2 );
419 ok( ptr1
== ptr
, "HeapReAlloc HEAP_REALLOC_IN_PLACE_ONLY failed, error %lu\n", GetLastError() );
420 SetLastError( 0xdeadbeef );
421 ptr1
= HeapReAlloc( heap
, HEAP_REALLOC_IN_PLACE_ONLY
, ptr
, 2 * alloc_size
);
423 ok( ptr1
!= ptr
, "HeapReAlloc HEAP_REALLOC_IN_PLACE_ONLY succeeded\n" );
425 ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY
, "got error %lu\n", GetLastError() );
427 ret
= HeapFree( heap
, 0, ptr1
);
428 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
430 ret
= HeapDestroy( heap
);
431 ok( ret
, "HeapDestroy failed, error %lu\n", GetLastError() );
434 /* fixed size heaps */
436 heap
= HeapCreate( 0, alloc_size
, alloc_size
);
437 ok( !!heap
, "HeapCreate failed, error %lu\n", GetLastError() );
438 ok( !((ULONG_PTR
)heap
& 0xffff), "wrong heap alignment\n" );
440 /* threshold between failure and success varies, and w7pro64 has a much larger overhead. */
442 ptr
= HeapAlloc( heap
, 0, alloc_size
- (0x400 + 0x100 * sizeof(void *)) );
443 ok( !!ptr
, "HeapAlloc failed, error %lu\n", GetLastError() );
444 size
= HeapSize( heap
, 0, ptr
);
445 ok( size
== alloc_size
- (0x400 + 0x100 * sizeof(void *)),
446 "HeapSize returned %#Ix, error %lu\n", size
, GetLastError() );
447 ret
= HeapFree( heap
, 0, ptr
);
448 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
450 SetLastError( 0xdeadbeef );
451 ptr1
= HeapAlloc( heap
, 0, alloc_size
- (0x200 + 0x80 * sizeof(void *)) );
452 ok( !ptr1
, "HeapAlloc succeeded\n" );
453 ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY
, "got error %lu\n", GetLastError() );
454 ret
= HeapFree( heap
, 0, ptr1
);
455 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
457 ret
= HeapDestroy( heap
);
458 ok( ret
, "HeapDestroy failed, error %lu\n", GetLastError() );
461 heap
= HeapCreate( 0, 8 * alloc_size
, 8 * alloc_size
);
462 ok( !!heap
, "HeapCreate failed, error %lu\n", GetLastError() );
463 ok( !((ULONG_PTR
)heap
& 0xffff), "wrong heap alignment\n" );
465 ptr
= HeapAlloc( heap
, 0, 0 );
466 ok( !!ptr
, "HeapAlloc failed, error %lu\n", GetLastError() );
467 size
= HeapSize( heap
, 0, ptr
);
468 ok( size
== 0, "HeapSize returned %#Ix, error %lu\n", size
, GetLastError() );
469 ret
= HeapFree( heap
, 0, ptr
);
470 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
472 /* cannot allocate large blocks from fixed size heap */
474 SetLastError( 0xdeadbeef );
475 ptr1
= HeapAlloc( heap
, 0, 4 * alloc_size
);
476 ok( !ptr1
, "HeapAlloc succeeded\n" );
477 ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY
, "got error %lu\n", GetLastError() );
478 ret
= HeapFree( heap
, 0, ptr1
);
479 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
481 ptr
= HeapAlloc( heap
, 0, alloc_size
);
482 ok( !!ptr
, "HeapAlloc failed, error %lu\n", GetLastError() );
483 size
= HeapSize( heap
, 0, ptr
);
484 ok( size
== alloc_size
, "HeapSize returned %#Ix, error %lu\n", size
, GetLastError() );
485 SetLastError( 0xdeadbeef );
486 ptr1
= HeapAlloc( heap
, 0, 4 * alloc_size
);
487 ok( !ptr1
, "HeapAlloc succeeded\n" );
488 ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY
, "got error %lu\n", GetLastError() );
489 ret
= HeapFree( heap
, 0, ptr1
);
490 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
491 ret
= HeapFree( heap
, 0, ptr
);
492 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
494 ptr
= HeapAlloc( heap
, HEAP_ZERO_MEMORY
, alloc_size
);
495 ok( !!ptr
, "HeapAlloc failed, error %lu\n", GetLastError() );
496 size
= HeapSize( heap
, 0, ptr
);
497 ok( size
== alloc_size
, "HeapSize returned %#Ix, error %lu\n", size
, GetLastError() );
498 while (size
) if (ptr
[--size
]) break;
499 ok( !size
&& !ptr
[0], "memory wasn't zeroed\n" );
501 ptr
= HeapReAlloc( heap
, HEAP_ZERO_MEMORY
, ptr
, 2 * alloc_size
);
502 ok( !!ptr
, "HeapReAlloc failed, error %lu\n", GetLastError() );
503 size
= HeapSize( heap
, 0, ptr
);
504 ok( size
== 2 * alloc_size
, "HeapSize returned %#Ix, error %lu\n", size
, GetLastError() );
505 while (size
) if (ptr
[--size
]) break;
506 ok( !size
&& !ptr
[0], "memory wasn't zeroed\n" );
508 ptr1
= HeapReAlloc( heap
, HEAP_REALLOC_IN_PLACE_ONLY
, ptr
, alloc_size
* 3 / 2 );
509 ok( ptr1
== ptr
, "HeapReAlloc HEAP_REALLOC_IN_PLACE_ONLY failed, error %lu\n", GetLastError() );
510 ptr1
= HeapReAlloc( heap
, HEAP_REALLOC_IN_PLACE_ONLY
, ptr
, 2 * alloc_size
);
511 ok( ptr1
== ptr
, "HeapReAlloc HEAP_REALLOC_IN_PLACE_ONLY failed, error %lu\n", GetLastError() );
512 ret
= HeapFree( heap
, 0, ptr1
);
513 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
515 ret
= HeapDestroy( heap
);
516 ok( ret
, "HeapDestroy failed, error %lu\n", GetLastError() );
519 heap
= HeapCreate( 0, 0, 0 );
520 ok( !!heap
, "HeapCreate failed, error %lu\n", GetLastError() );
521 ok( !((ULONG_PTR
)heap
& 0xffff), "wrong heap alignment\n" );
524 memset( &rtl_entries
, 0, sizeof(rtl_entries
) );
525 memset( &rtl_entry
, 0xcd, sizeof(rtl_entry
) );
526 rtl_entry
.lpData
= NULL
;
527 SetLastError( 0xdeadbeef );
528 while (!RtlWalkHeap( heap
, &rtl_entry
)) rtl_entries
[count
++] = rtl_entry
;
529 ok( count
== 3, "got count %lu\n", count
);
532 memset( &entries
, 0, sizeof(entries
) );
533 memset( &entry
, 0xcd, sizeof(entry
) );
535 SetLastError( 0xdeadbeef );
536 while ((ret
= HeapWalk( heap
, &entry
))) entries
[count
++] = entry
;
537 ok( GetLastError() == ERROR_NO_MORE_ITEMS
, "got error %lu\n", GetLastError() );
538 ok( count
== 3, "got count %lu\n", count
);
540 for (i
= 0; i
< count
; ++i
)
542 winetest_push_context( "%Iu", i
);
543 ok( rtl_entries
[i
].lpData
== entries
[i
].lpData
, "got lpData %p\n", rtl_entries
[i
].lpData
);
544 ok( rtl_entries
[i
].cbData
== entries
[i
].cbData
, "got cbData %#Ix\n", rtl_entries
[i
].cbData
);
545 ok( rtl_entries
[i
].cbOverhead
== entries
[i
].cbOverhead
, "got cbOverhead %#x\n", rtl_entries
[i
].cbOverhead
);
546 ok( rtl_entries
[i
].iRegionIndex
== entries
[i
].iRegionIndex
, "got iRegionIndex %#x\n", rtl_entries
[i
].iRegionIndex
);
547 if (!entries
[i
].wFlags
)
548 ok( rtl_entries
[i
].wFlags
== 0, "got wFlags %#x\n", rtl_entries
[i
].wFlags
);
549 else if (entries
[i
].wFlags
& PROCESS_HEAP_ENTRY_BUSY
)
550 ok( rtl_entries
[i
].wFlags
== (RTL_HEAP_ENTRY_COMMITTED
|RTL_HEAP_ENTRY_BLOCK
|RTL_HEAP_ENTRY_BUSY
) || broken(rtl_entries
[i
].wFlags
== 0x411) /* win7 */,
551 "got wFlags %#x\n", rtl_entries
[i
].wFlags
);
552 else if (entries
[i
].wFlags
& PROCESS_HEAP_UNCOMMITTED_RANGE
)
553 ok( rtl_entries
[i
].wFlags
== RTL_HEAP_ENTRY_UNCOMMITTED
|| broken(rtl_entries
[i
].wFlags
== 0x100) /* win7 */,
554 "got wFlags %#x\n", rtl_entries
[i
].wFlags
);
555 else if (entries
[i
].wFlags
& PROCESS_HEAP_REGION
)
557 ok( rtl_entries
[i
].wFlags
== RTL_HEAP_ENTRY_REGION
, "got wFlags %#x\n", rtl_entries
[i
].wFlags
);
558 ok( rtl_entries
[i
].Region
.dwCommittedSize
== entries
[i
].Region
.dwCommittedSize
,
559 "got Region.dwCommittedSize %#lx\n", rtl_entries
[i
].Region
.dwCommittedSize
);
560 ok( rtl_entries
[i
].Region
.dwUnCommittedSize
== entries
[i
].Region
.dwUnCommittedSize
,
561 "got Region.dwUnCommittedSize %#lx\n", rtl_entries
[i
].Region
.dwUnCommittedSize
);
562 ok( rtl_entries
[i
].Region
.lpFirstBlock
== entries
[i
].Region
.lpFirstBlock
,
563 "got Region.lpFirstBlock %p\n", rtl_entries
[i
].Region
.lpFirstBlock
);
564 ok( rtl_entries
[i
].Region
.lpLastBlock
== entries
[i
].Region
.lpLastBlock
,
565 "got Region.lpLastBlock %p\n", rtl_entries
[i
].Region
.lpLastBlock
);
567 winetest_pop_context();
570 ok( entries
[0].wFlags
== PROCESS_HEAP_REGION
, "got wFlags %#x\n", entries
[0].wFlags
);
571 ok( entries
[0].lpData
== heap
, "got lpData %p\n", entries
[0].lpData
);
572 ok( entries
[0].cbData
<= 0x1000 /* sizeof(*heap) */, "got cbData %#lx\n", entries
[0].cbData
);
573 ok( entries
[0].cbOverhead
== 0, "got cbOverhead %#x\n", entries
[0].cbOverhead
);
574 ok( entries
[0].iRegionIndex
== 0, "got iRegionIndex %d\n", entries
[0].iRegionIndex
);
576 ok( entries
[0].Region
.dwCommittedSize
== 0x400 * sizeof(void *),
577 "got Region.dwCommittedSize %#lx\n", entries
[0].Region
.dwCommittedSize
);
578 ok( entries
[0].Region
.dwUnCommittedSize
== 0x10000 - entries
[0].Region
.dwCommittedSize
||
579 entries
[0].Region
.dwUnCommittedSize
== 0x10000 * sizeof(void *) - entries
[0].Region
.dwCommittedSize
/* win7 */,
580 "got Region.dwUnCommittedSize %#lx\n", entries
[0].Region
.dwUnCommittedSize
);
582 ok( (BYTE
*)entries
[0].Region
.lpFirstBlock
== (BYTE
*)entries
[0].lpData
+ entries
[0].cbData
+ 2 * sizeof(void *) ||
583 (BYTE
*)entries
[0].Region
.lpFirstBlock
== (BYTE
*)entries
[0].lpData
+ entries
[0].cbData
+ 4 * sizeof(void *),
584 "got Region.lpFirstBlock %p\n", entries
[0].Region
.lpFirstBlock
);
585 ok( entries
[0].Region
.lpLastBlock
== (BYTE
*)entries
[2].lpData
+ entries
[2].cbData
,
586 "got Region.lpLastBlock %p\n", entries
[0].Region
.lpLastBlock
);
588 ok( entries
[1].wFlags
== 0, "got wFlags %#x\n", entries
[1].wFlags
);
589 ok( entries
[1].lpData
!= NULL
, "got lpData %p\n", entries
[1].lpData
);
590 ok( entries
[1].cbData
!= 0, "got cbData %#lx\n", entries
[1].cbData
);
591 ok( entries
[1].cbOverhead
== 4 * sizeof(void *), "got cbOverhead %#x\n", entries
[1].cbOverhead
);
592 ok( entries
[1].iRegionIndex
== 0, "got iRegionIndex %d\n", entries
[1].iRegionIndex
);
594 ok( entries
[2].wFlags
== PROCESS_HEAP_UNCOMMITTED_RANGE
, "got wFlags %#x\n", entries
[2].wFlags
);
595 ok( entries
[2].lpData
== (BYTE
*)entries
[0].lpData
+ entries
[0].Region
.dwCommittedSize
,
596 "got lpData %p\n", entries
[2].lpData
);
597 ok( entries
[2].lpData
== (BYTE
*)entries
[1].lpData
+ entries
[1].cbData
+ 2 * entries
[1].cbOverhead
,
598 "got lpData %p\n", entries
[2].lpData
);
599 ok( entries
[2].cbData
== entries
[0].Region
.dwUnCommittedSize
- 0x1000 ||
600 entries
[2].cbData
== entries
[0].Region
.dwUnCommittedSize
/* win7 */,
601 "got cbData %#lx\n", entries
[2].cbData
);
602 ok( entries
[2].cbOverhead
== 0, "got cbOverhead %#x\n", entries
[2].cbOverhead
);
603 ok( entries
[2].iRegionIndex
== 0, "got iRegionIndex %d\n", entries
[2].iRegionIndex
);
605 ptr
= HeapAlloc( heap
, HEAP_ZERO_MEMORY
, 5 * alloc_size
);
606 ok( !!ptr
, "HeapAlloc failed, error %lu\n", GetLastError() );
609 memset( &rtl_entries
, 0, sizeof(rtl_entries
) );
610 memset( &rtl_entry
, 0xcd, sizeof(rtl_entry
) );
611 rtl_entry
.lpData
= NULL
;
612 SetLastError( 0xdeadbeef );
613 while (!RtlWalkHeap( heap
, &rtl_entry
)) rtl_entries
[count
++] = rtl_entry
;
614 ok( count
== 4, "got count %lu\n", count
);
616 memmove( entries
+ 16, entries
, 3 * sizeof(entry
) );
618 memset( &entry
, 0xcd, sizeof(entry
) );
620 SetLastError( 0xdeadbeef );
621 while ((ret
= HeapWalk( heap
, &entry
))) entries
[count
++] = entry
;
622 ok( GetLastError() == ERROR_NO_MORE_ITEMS
, "got error %lu\n", GetLastError() );
623 ok( count
== 4, "got count %lu\n", count
);
624 ok( !memcmp( entries
+ 16, entries
, 3 * sizeof(entry
) ), "entries differ\n" );
626 for (i
= 0; i
< count
; ++i
)
628 winetest_push_context( "%Iu", i
);
629 ok( rtl_entries
[i
].lpData
== entries
[i
].lpData
, "got lpData %p\n", rtl_entries
[i
].lpData
);
630 ok( rtl_entries
[i
].cbData
== entries
[i
].cbData
, "got cbData %#Ix\n", rtl_entries
[i
].cbData
);
631 ok( rtl_entries
[i
].cbOverhead
== entries
[i
].cbOverhead
, "got cbOverhead %#x\n", rtl_entries
[i
].cbOverhead
);
632 ok( rtl_entries
[i
].iRegionIndex
== entries
[i
].iRegionIndex
, "got iRegionIndex %#x\n", rtl_entries
[i
].iRegionIndex
);
633 if (!entries
[i
].wFlags
)
634 ok( rtl_entries
[i
].wFlags
== 0, "got wFlags %#x\n", rtl_entries
[i
].wFlags
);
635 else if (entries
[i
].wFlags
& PROCESS_HEAP_ENTRY_BUSY
)
636 ok( rtl_entries
[i
].wFlags
== (RTL_HEAP_ENTRY_COMMITTED
|RTL_HEAP_ENTRY_BLOCK
|RTL_HEAP_ENTRY_BUSY
) || broken(rtl_entries
[i
].wFlags
== 0x411) /* win7 */,
637 "got wFlags %#x\n", rtl_entries
[i
].wFlags
);
638 else if (entries
[i
].wFlags
& PROCESS_HEAP_UNCOMMITTED_RANGE
)
639 ok( rtl_entries
[i
].wFlags
== RTL_HEAP_ENTRY_UNCOMMITTED
|| broken(rtl_entries
[i
].wFlags
== 0x100) /* win7 */,
640 "got wFlags %#x\n", rtl_entries
[i
].wFlags
);
641 else if (entries
[i
].wFlags
& PROCESS_HEAP_REGION
)
643 ok( rtl_entries
[i
].wFlags
== RTL_HEAP_ENTRY_REGION
, "got wFlags %#x\n", rtl_entries
[i
].wFlags
);
644 ok( rtl_entries
[i
].Region
.dwCommittedSize
== entries
[i
].Region
.dwCommittedSize
,
645 "got Region.dwCommittedSize %#lx\n", rtl_entries
[i
].Region
.dwCommittedSize
);
646 ok( rtl_entries
[i
].Region
.dwUnCommittedSize
== entries
[i
].Region
.dwUnCommittedSize
,
647 "got Region.dwUnCommittedSize %#lx\n", rtl_entries
[i
].Region
.dwUnCommittedSize
);
648 ok( rtl_entries
[i
].Region
.lpFirstBlock
== entries
[i
].Region
.lpFirstBlock
,
649 "got Region.lpFirstBlock %p\n", rtl_entries
[i
].Region
.lpFirstBlock
);
650 ok( rtl_entries
[i
].Region
.lpLastBlock
== entries
[i
].Region
.lpLastBlock
,
651 "got Region.lpLastBlock %p\n", rtl_entries
[i
].Region
.lpLastBlock
);
653 winetest_pop_context();
656 ok( entries
[3].wFlags
== PROCESS_HEAP_ENTRY_BUSY
||
657 broken(entries
[3].wFlags
== (PROCESS_HEAP_ENTRY_BUSY
| PROCESS_HEAP_ENTRY_DDESHARE
)) /* win7 */,
658 "got wFlags %#x\n", entries
[3].wFlags
);
659 ok( entries
[3].lpData
== ptr
, "got lpData %p\n", entries
[3].lpData
);
660 ok( entries
[3].cbData
== 5 * alloc_size
, "got cbData %#lx\n", entries
[3].cbData
);
661 ok( entries
[3].cbOverhead
== 0 || entries
[3].cbOverhead
== 8 * sizeof(void *) /* win7 */,
662 "got cbOverhead %#x\n", entries
[3].cbOverhead
);
663 ok( entries
[3].iRegionIndex
== 64, "got iRegionIndex %d\n", entries
[3].iRegionIndex
);
665 ptr1
= HeapAlloc( heap
, HEAP_ZERO_MEMORY
, 5 * alloc_size
);
666 ok( !!ptr1
, "HeapAlloc failed, error %lu\n", GetLastError() );
669 memset( &rtl_entries
, 0, sizeof(rtl_entries
) );
670 memset( &rtl_entry
, 0xcd, sizeof(rtl_entry
) );
671 rtl_entry
.lpData
= NULL
;
672 SetLastError( 0xdeadbeef );
673 while (!RtlWalkHeap( heap
, &rtl_entry
)) rtl_entries
[count
++] = rtl_entry
;
674 ok( count
== 5, "got count %lu\n", count
);
676 memmove( entries
+ 16, entries
, 4 * sizeof(entry
) );
678 memset( &entry
, 0xcd, sizeof(entry
) );
680 SetLastError( 0xdeadbeef );
681 while ((ret
= HeapWalk( heap
, &entry
))) entries
[count
++] = entry
;
682 ok( GetLastError() == ERROR_NO_MORE_ITEMS
, "got error %lu\n", GetLastError() );
683 ok( count
== 5, "got count %lu\n", count
);
684 ok( !memcmp( entries
+ 16, entries
, 4 * sizeof(entry
) ), "entries differ\n" );
686 for (i
= 0; i
< count
; ++i
)
688 winetest_push_context( "%Iu", i
);
689 ok( rtl_entries
[i
].lpData
== entries
[i
].lpData
, "got lpData %p\n", rtl_entries
[i
].lpData
);
690 ok( rtl_entries
[i
].cbData
== entries
[i
].cbData
, "got cbData %#Ix\n", rtl_entries
[i
].cbData
);
691 ok( rtl_entries
[i
].cbOverhead
== entries
[i
].cbOverhead
, "got cbOverhead %#x\n", rtl_entries
[i
].cbOverhead
);
692 ok( rtl_entries
[i
].iRegionIndex
== entries
[i
].iRegionIndex
, "got iRegionIndex %#x\n", rtl_entries
[i
].iRegionIndex
);
693 if (!entries
[i
].wFlags
)
694 ok( rtl_entries
[i
].wFlags
== 0, "got wFlags %#x\n", rtl_entries
[i
].wFlags
);
695 else if (entries
[i
].wFlags
& PROCESS_HEAP_ENTRY_BUSY
)
696 ok( rtl_entries
[i
].wFlags
== (RTL_HEAP_ENTRY_COMMITTED
|RTL_HEAP_ENTRY_BLOCK
|RTL_HEAP_ENTRY_BUSY
) || broken(rtl_entries
[i
].wFlags
== 0x411) /* win7 */,
697 "got wFlags %#x\n", rtl_entries
[i
].wFlags
);
698 else if (entries
[i
].wFlags
& PROCESS_HEAP_UNCOMMITTED_RANGE
)
699 ok( rtl_entries
[i
].wFlags
== RTL_HEAP_ENTRY_UNCOMMITTED
|| broken(rtl_entries
[i
].wFlags
== 0x100) /* win7 */,
700 "got wFlags %#x\n", rtl_entries
[i
].wFlags
);
701 else if (entries
[i
].wFlags
& PROCESS_HEAP_REGION
)
703 ok( rtl_entries
[i
].wFlags
== RTL_HEAP_ENTRY_REGION
, "got wFlags %#x\n", rtl_entries
[i
].wFlags
);
704 ok( rtl_entries
[i
].Region
.dwCommittedSize
== entries
[i
].Region
.dwCommittedSize
,
705 "got Region.dwCommittedSize %#lx\n", rtl_entries
[i
].Region
.dwCommittedSize
);
706 ok( rtl_entries
[i
].Region
.dwUnCommittedSize
== entries
[i
].Region
.dwUnCommittedSize
,
707 "got Region.dwUnCommittedSize %#lx\n", rtl_entries
[i
].Region
.dwUnCommittedSize
);
708 ok( rtl_entries
[i
].Region
.lpFirstBlock
== entries
[i
].Region
.lpFirstBlock
,
709 "got Region.lpFirstBlock %p\n", rtl_entries
[i
].Region
.lpFirstBlock
);
710 ok( rtl_entries
[i
].Region
.lpLastBlock
== entries
[i
].Region
.lpLastBlock
,
711 "got Region.lpLastBlock %p\n", rtl_entries
[i
].Region
.lpLastBlock
);
713 winetest_pop_context();
716 ok( entries
[4].wFlags
== PROCESS_HEAP_ENTRY_BUSY
||
717 broken(entries
[4].wFlags
== (PROCESS_HEAP_ENTRY_BUSY
| PROCESS_HEAP_ENTRY_DDESHARE
)) /* win7 */,
718 "got wFlags %#x\n", entries
[4].wFlags
);
719 ok( entries
[4].lpData
== ptr1
, "got lpData %p\n", entries
[4].lpData
);
720 ok( entries
[4].cbData
== 5 * alloc_size
, "got cbData %#lx\n", entries
[4].cbData
);
721 ok( entries
[4].cbOverhead
== 0 || entries
[4].cbOverhead
== 8 * sizeof(void *) /* win7 */,
722 "got cbOverhead %#x\n", entries
[4].cbOverhead
);
723 ok( entries
[4].iRegionIndex
== 64, "got iRegionIndex %d\n", entries
[4].iRegionIndex
);
725 ret
= HeapFree( heap
, 0, ptr1
);
726 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
727 ret
= HeapFree( heap
, 0, ptr
);
728 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
730 memmove( entries
+ 16, entries
, 3 * sizeof(entry
) );
732 memset( &entry
, 0xcd, sizeof(entry
) );
734 SetLastError( 0xdeadbeef );
735 while ((ret
= HeapWalk( heap
, &entry
))) entries
[count
++] = entry
;
736 ok( GetLastError() == ERROR_NO_MORE_ITEMS
, "got error %lu\n", GetLastError() );
737 ok( count
== 3, "got count %lu\n", count
);
738 ok( !memcmp( entries
+ 16, entries
, 3 * sizeof(entry
) ), "entries differ\n" );
740 ptr
= HeapAlloc( heap
, HEAP_ZERO_MEMORY
, 123 );
741 ok( !!ptr
, "HeapAlloc failed, error %lu\n", GetLastError() );
743 memmove( entries
+ 16, entries
, 3 * sizeof(entry
) );
745 memset( &entry
, 0xcd, sizeof(entry
) );
747 SetLastError( 0xdeadbeef );
748 while ((ret
= HeapWalk( heap
, &entry
))) entries
[count
++] = entry
;
749 ok( GetLastError() == ERROR_NO_MORE_ITEMS
, "got error %lu\n", GetLastError() );
750 ok( count
== 4, "got count %lu\n", count
);
751 ok( !memcmp( entries
+ 16, entries
, 1 * sizeof(entry
) ), "entries differ\n" );
752 ok( memcmp( entries
+ 17, entries
+ 2, 2 * sizeof(entry
) ), "entries differ\n" );
754 ok( entries
[1].wFlags
== PROCESS_HEAP_ENTRY_BUSY
, "got wFlags %#x\n", entries
[1].wFlags
);
755 ok( entries
[1].lpData
== ptr
, "got lpData %p\n", entries
[1].lpData
);
756 ok( entries
[1].cbData
== 123, "got cbData %#lx\n", entries
[1].cbData
);
757 ok( entries
[1].cbOverhead
!= 0, "got cbOverhead %#x\n", entries
[1].cbOverhead
);
758 ok( entries
[1].iRegionIndex
== 0, "got iRegionIndex %d\n", entries
[1].iRegionIndex
);
760 ok( entries
[2].wFlags
== 0, "got wFlags %#x\n", entries
[2].wFlags
);
761 ok( entries
[2].lpData
== (BYTE
*)entries
[1].lpData
+ entries
[1].cbData
+ entries
[1].cbOverhead
+ 2 * sizeof(void *),
762 "got lpData %p\n", entries
[2].lpData
);
763 ok( entries
[2].cbData
!= 0, "got cbData %#lx\n", entries
[2].cbData
);
764 ok( entries
[2].cbOverhead
== 4 * sizeof(void *), "got cbOverhead %#x\n", entries
[2].cbOverhead
);
765 ok( entries
[2].iRegionIndex
== 0, "got iRegionIndex %d\n", entries
[2].iRegionIndex
);
767 ok( entries
[3].wFlags
== PROCESS_HEAP_UNCOMMITTED_RANGE
, "got wFlags %#x\n", entries
[3].wFlags
);
768 ok( entries
[3].lpData
== (BYTE
*)entries
[0].lpData
+ entries
[0].Region
.dwCommittedSize
,
769 "got lpData %p\n", entries
[3].lpData
);
770 ok( entries
[3].lpData
== (BYTE
*)entries
[2].lpData
+ entries
[2].cbData
+ 2 * entries
[2].cbOverhead
,
771 "got lpData %p\n", entries
[3].lpData
);
772 ok( entries
[3].cbData
== entries
[0].Region
.dwUnCommittedSize
- 0x1000 ||
773 entries
[3].cbData
== entries
[0].Region
.dwUnCommittedSize
/* win7 */,
774 "got cbData %#lx\n", entries
[3].cbData
);
775 ok( entries
[3].cbOverhead
== 0, "got cbOverhead %#x\n", entries
[3].cbOverhead
);
776 ok( entries
[3].iRegionIndex
== 0, "got iRegionIndex %d\n", entries
[3].iRegionIndex
);
778 ptr1
= HeapAlloc( heap
, HEAP_ZERO_MEMORY
, 456 );
779 ok( !!ptr1
, "HeapAlloc failed, error %lu\n", GetLastError() );
781 memmove( entries
+ 16, entries
, 4 * sizeof(entry
) );
783 memset( &entry
, 0xcd, sizeof(entry
) );
785 SetLastError( 0xdeadbeef );
786 while ((ret
= HeapWalk( heap
, &entry
))) entries
[count
++] = entry
;
787 ok( GetLastError() == ERROR_NO_MORE_ITEMS
, "got error %lu\n", GetLastError() );
788 ok( count
== 5, "got count %lu\n", count
);
789 ok( !memcmp( entries
+ 16, entries
, 2 * sizeof(entry
) ), "entries differ\n" );
790 ok( memcmp( entries
+ 18, entries
+ 3, 2 * sizeof(entry
) ), "entries differ\n" );
792 ok( entries
[2].wFlags
== PROCESS_HEAP_ENTRY_BUSY
, "got wFlags %#x\n", entries
[2].wFlags
);
793 ok( entries
[2].lpData
== ptr1
, "got lpData %p\n", entries
[2].lpData
);
794 ok( entries
[2].cbData
== 456, "got cbData %#lx\n", entries
[2].cbData
);
795 ok( entries
[2].cbOverhead
!= 0, "got cbOverhead %#x\n", entries
[2].cbOverhead
);
796 ok( entries
[2].iRegionIndex
== 0, "got iRegionIndex %d\n", entries
[2].iRegionIndex
);
798 ok( entries
[3].wFlags
== 0, "got wFlags %#x\n", entries
[3].wFlags
);
799 ok( entries
[3].lpData
== (BYTE
*)entries
[2].lpData
+ entries
[2].cbData
+ entries
[2].cbOverhead
+ 2 * sizeof(void *),
800 "got lpData %p\n", entries
[3].lpData
);
801 ok( entries
[3].cbData
!= 0, "got cbData %#lx\n", entries
[3].cbData
);
802 ok( entries
[3].cbOverhead
== 4 * sizeof(void *), "got cbOverhead %#x\n", entries
[3].cbOverhead
);
803 ok( entries
[3].iRegionIndex
== 0, "got iRegionIndex %d\n", entries
[3].iRegionIndex
);
805 ok( entries
[4].wFlags
== PROCESS_HEAP_UNCOMMITTED_RANGE
, "got wFlags %#x\n", entries
[4].wFlags
);
806 ok( entries
[4].lpData
== (BYTE
*)entries
[0].lpData
+ entries
[0].Region
.dwCommittedSize
,
807 "got lpData %p\n", entries
[4].lpData
);
808 ok( entries
[4].lpData
== (BYTE
*)entries
[3].lpData
+ entries
[3].cbData
+ 2 * entries
[3].cbOverhead
,
809 "got lpData %p\n", entries
[4].lpData
);
810 ok( entries
[4].cbData
== entries
[0].Region
.dwUnCommittedSize
- 0x1000 ||
811 entries
[4].cbData
== entries
[0].Region
.dwUnCommittedSize
/* win7 */,
812 "got cbData %#lx\n", entries
[4].cbData
);
813 ok( entries
[4].cbOverhead
== 0, "got cbOverhead %#x\n", entries
[4].cbOverhead
);
814 ok( entries
[4].iRegionIndex
== 0, "got iRegionIndex %d\n", entries
[4].iRegionIndex
);
816 ret
= HeapFree( heap
, 0, ptr1
);
817 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
818 ret
= HeapFree( heap
, 0, ptr
);
819 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
822 SetLastError( 0xdeadbeef );
823 ret
= pHeapQueryInformation( 0, HeapCompatibilityInformation
, &compat_info
, sizeof(compat_info
), &size
);
824 ok( !ret
, "HeapQueryInformation succeeded\n" );
825 ok( GetLastError() == ERROR_NOACCESS
, "got error %lu\n", GetLastError() );
826 ok( size
== 0, "got size %Iu\n", size
);
829 SetLastError( 0xdeadbeef );
830 ret
= pHeapQueryInformation( heap
, HeapCompatibilityInformation
, NULL
, 0, &size
);
831 ok( !ret
, "HeapQueryInformation succeeded\n" );
832 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "got error %lu\n", GetLastError() );
833 ok( size
== sizeof(ULONG
), "got size %Iu\n", size
);
835 SetLastError( 0xdeadbeef );
836 ret
= pHeapQueryInformation( heap
, HeapCompatibilityInformation
, NULL
, 0, NULL
);
837 ok( !ret
, "HeapQueryInformation succeeded\n" );
838 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "got error %lu\n", GetLastError() );
840 SetLastError( 0xdeadbeef );
841 compat_info
= 0xdeadbeef;
842 ret
= pHeapQueryInformation( heap
, HeapCompatibilityInformation
, &compat_info
, sizeof(compat_info
) + 1, NULL
);
843 ok( ret
, "HeapQueryInformation failed, error %lu\n", GetLastError() );
844 ok( compat_info
== 0, "got compat_info %lu\n", compat_info
);
846 ret
= HeapDestroy( heap
);
847 ok( ret
, "HeapDestroy failed, error %lu\n", GetLastError() );
850 /* check setting LFH compat info */
852 heap
= HeapCreate( 0, 0, 0 );
853 ok( !!heap
, "HeapCreate failed, error %lu\n", GetLastError() );
854 ok( !((ULONG_PTR
)heap
& 0xffff), "wrong heap alignment\n" );
856 ret
= pHeapQueryInformation( heap
, HeapCompatibilityInformation
, &compat_info
, sizeof(compat_info
), &size
);
857 ok( ret
, "HeapQueryInformation failed, error %lu\n", GetLastError() );
858 ok( compat_info
== 0, "got HeapCompatibilityInformation %lu\n", compat_info
);
861 ret
= pHeapSetInformation( heap
, HeapCompatibilityInformation
, &compat_info
, sizeof(compat_info
) );
862 ok( ret
, "HeapSetInformation failed, error %lu\n", GetLastError() );
863 ret
= pHeapQueryInformation( heap
, HeapCompatibilityInformation
, &compat_info
, sizeof(compat_info
), &size
);
864 ok( ret
, "HeapQueryInformation failed, error %lu\n", GetLastError() );
865 ok( compat_info
== 2, "got HeapCompatibilityInformation %lu\n", compat_info
);
867 /* cannot be undone */
870 SetLastError( 0xdeadbeef );
871 ret
= pHeapSetInformation( heap
, HeapCompatibilityInformation
, &compat_info
, sizeof(compat_info
) );
872 ok( !ret
, "HeapSetInformation succeeded\n" );
873 ok( GetLastError() == ERROR_GEN_FAILURE
, "got error %lu\n", GetLastError() );
875 SetLastError( 0xdeadbeef );
876 ret
= pHeapSetInformation( heap
, HeapCompatibilityInformation
, &compat_info
, sizeof(compat_info
) );
877 ok( !ret
, "HeapSetInformation succeeded\n" );
878 ok( GetLastError() == ERROR_GEN_FAILURE
, "got error %lu\n", GetLastError() );
879 ret
= pHeapQueryInformation( heap
, HeapCompatibilityInformation
, &compat_info
, sizeof(compat_info
), &size
);
880 ok( ret
, "HeapQueryInformation failed, error %lu\n", GetLastError() );
881 ok( compat_info
== 2, "got HeapCompatibilityInformation %lu\n", compat_info
);
883 ret
= HeapDestroy( heap
);
884 ok( ret
, "HeapDestroy failed, error %lu\n", GetLastError() );
887 /* cannot set LFH with HEAP_NO_SERIALIZE */
889 heap
= HeapCreate( HEAP_NO_SERIALIZE
, 0, 0 );
890 ok( !!heap
, "HeapCreate failed, error %lu\n", GetLastError() );
891 ok( !((ULONG_PTR
)heap
& 0xffff), "wrong heap alignment\n" );
893 ret
= pHeapQueryInformation( heap
, HeapCompatibilityInformation
, &compat_info
, sizeof(compat_info
), &size
);
894 ok( ret
, "HeapQueryInformation failed, error %lu\n", GetLastError() );
895 ok( compat_info
== 0, "got HeapCompatibilityInformation %lu\n", compat_info
);
898 SetLastError( 0xdeadbeef );
899 ret
= pHeapSetInformation( heap
, HeapCompatibilityInformation
, &compat_info
, sizeof(compat_info
) );
900 ok( !ret
, "HeapSetInformation succeeded\n" );
901 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "got error %lu\n", GetLastError() );
902 ret
= pHeapQueryInformation( heap
, HeapCompatibilityInformation
, &compat_info
, sizeof(compat_info
), &size
);
903 ok( ret
, "HeapQueryInformation failed, error %lu\n", GetLastError() );
904 ok( compat_info
== 0, "got HeapCompatibilityInformation %lu\n", compat_info
);
906 ret
= HeapDestroy( heap
);
907 ok( ret
, "HeapDestroy failed, error %lu\n", GetLastError() );
910 /* some allocation pattern automatically enables LFH */
912 heap
= HeapCreate( 0, 0, 0 );
913 ok( !!heap
, "HeapCreate failed, error %lu\n", GetLastError() );
914 ok( !((ULONG_PTR
)heap
& 0xffff), "wrong heap alignment\n" );
916 ret
= pHeapQueryInformation( heap
, HeapCompatibilityInformation
, &compat_info
, sizeof(compat_info
), &size
);
917 ok( ret
, "HeapQueryInformation failed, error %lu\n", GetLastError() );
918 ok( compat_info
== 0, "got HeapCompatibilityInformation %lu\n", compat_info
);
920 for (i
= 0; i
< 0x12; i
++) ptrs
[i
] = pHeapAlloc( heap
, 0, 0 );
921 for (i
= 0; i
< 0x12; i
++) HeapFree( heap
, 0, ptrs
[i
] );
923 ret
= pHeapQueryInformation( heap
, HeapCompatibilityInformation
, &compat_info
, sizeof(compat_info
), &size
);
924 ok( ret
, "HeapQueryInformation failed, error %lu\n", GetLastError() );
925 ok( compat_info
== 2, "got HeapCompatibilityInformation %lu\n", compat_info
);
927 ret
= HeapDestroy( heap
);
928 ok( ret
, "HeapDestroy failed, error %lu\n", GetLastError() );
931 /* LFH actually doesn't enable immediately, the pattern is required */
933 heap
= HeapCreate( 0, 0, 0 );
934 ok( !!heap
, "HeapCreate failed, error %lu\n", GetLastError() );
935 ok( !((ULONG_PTR
)heap
& 0xffff), "wrong heap alignment\n" );
938 ret
= pHeapSetInformation( heap
, HeapCompatibilityInformation
, &compat_info
, sizeof(compat_info
) );
939 ok( ret
, "HeapSetInformation failed, error %lu\n", GetLastError() );
940 ret
= pHeapQueryInformation( heap
, HeapCompatibilityInformation
, &compat_info
, sizeof(compat_info
), &size
);
941 ok( ret
, "HeapQueryInformation failed, error %lu\n", GetLastError() );
942 ok( compat_info
== 2, "got HeapCompatibilityInformation %lu\n", compat_info
);
944 for (i
= 0; i
< 0x11; i
++) ptrs
[i
] = pHeapAlloc( heap
, 0, 24 + 2 * sizeof(void *) );
945 for (i
= 0; i
< 0x11; i
++) HeapFree( heap
, 0, ptrs
[i
] );
948 memset( &entries
, 0xcd, sizeof(entries
) );
949 memset( &entry
, 0xcd, sizeof(entry
) );
951 SetLastError( 0xdeadbeef );
952 while ((ret
= HeapWalk( heap
, &entry
))) entries
[count
++] = entry
;
953 ok( GetLastError() == ERROR_NO_MORE_ITEMS
, "got error %lu\n", GetLastError() );
954 ok( count
== 3, "got count %lu\n", count
);
956 ok( entries
[0].wFlags
== PROCESS_HEAP_REGION
, "got wFlags %#x\n", entries
[0].wFlags
);
957 ok( entries
[0].lpData
== heap
, "got lpData %p\n", entries
[0].lpData
);
958 ok( entries
[0].cbData
<= 0x1000 /* sizeof(*heap) */, "got cbData %#lx\n", entries
[0].cbData
);
959 ok( entries
[0].cbOverhead
== 0, "got cbOverhead %#x\n", entries
[0].cbOverhead
);
960 ok( entries
[0].iRegionIndex
== 0, "got iRegionIndex %d\n", entries
[0].iRegionIndex
);
961 ok( entries
[1].wFlags
== 0, "got wFlags %#x\n", entries
[1].wFlags
);
962 ok( entries
[2].wFlags
== PROCESS_HEAP_UNCOMMITTED_RANGE
, "got wFlags %#x\n", entries
[2].wFlags
);
964 for (i
= 0; i
< 0x12; i
++) ptrs
[i
] = pHeapAlloc( heap
, 0, 24 + 2 * sizeof(void *) );
965 for (i
= 0; i
< 0x12; i
++) HeapFree( heap
, 0, ptrs
[i
] );
968 memset( &entries
, 0xcd, sizeof(entries
) );
969 memset( &entry
, 0xcd, sizeof(entry
) );
971 SetLastError( 0xdeadbeef );
972 while ((ret
= HeapWalk( heap
, &entry
))) entries
[count
++] = entry
;
973 ok( GetLastError() == ERROR_NO_MORE_ITEMS
, "got error %lu\n", GetLastError() );
975 ok( count
> 24, "got count %lu\n", count
);
976 if (count
< 2) count
= 2;
978 ok( entries
[0].wFlags
== PROCESS_HEAP_REGION
, "got wFlags %#x\n", entries
[0].wFlags
);
979 ok( entries
[0].lpData
== heap
, "got lpData %p\n", entries
[0].lpData
);
980 ok( entries
[0].cbData
<= 0x1000 /* sizeof(*heap) */, "got cbData %#lx\n", entries
[0].cbData
);
981 ok( entries
[0].cbOverhead
== 0, "got cbOverhead %#x\n", entries
[0].cbOverhead
);
982 ok( entries
[0].iRegionIndex
== 0, "got iRegionIndex %d\n", entries
[0].iRegionIndex
);
983 todo_wine
/* Wine currently reports the LFH group as a single block here */
984 ok( entries
[1].wFlags
== 0, "got wFlags %#x\n", entries
[1].wFlags
);
986 for (i
= 0; i
< 0x12; i
++)
989 ok( entries
[4 + i
].wFlags
== 0, "got wFlags %#x\n", entries
[4 + i
].wFlags
);
991 ok( entries
[4 + i
].cbData
== 0x20, "got cbData %#lx\n", entries
[4 + i
].cbData
);
993 ok( entries
[4 + i
].cbOverhead
== 2 * sizeof(void *), "got cbOverhead %#x\n", entries
[4 + i
].cbOverhead
);
996 if (entries
[count
- 1].wFlags
== PROCESS_HEAP_REGION
) /* > win7 */
997 ok( entries
[count
- 2].wFlags
== PROCESS_HEAP_UNCOMMITTED_RANGE
, "got wFlags %#x\n", entries
[count
- 2].wFlags
);
999 ok( entries
[count
- 1].wFlags
== PROCESS_HEAP_UNCOMMITTED_RANGE
, "got wFlags %#x\n", entries
[count
- 2].wFlags
);
1002 memset( &rtl_entries
, 0, sizeof(rtl_entries
) );
1003 memset( &rtl_entry
, 0xcd, sizeof(rtl_entry
) );
1004 rtl_entry
.lpData
= NULL
;
1005 SetLastError( 0xdeadbeef );
1006 while (!RtlWalkHeap( heap
, &rtl_entry
)) rtl_entries
[count
++] = rtl_entry
;
1008 ok( count
> 24, "got count %lu\n", count
);
1009 if (count
< 2) count
= 2;
1011 for (i
= 3; i
< count
; ++i
)
1013 winetest_push_context( "%Iu", i
);
1014 ok( rtl_entries
[i
].lpData
== entries
[i
].lpData
, "got lpData %p\n", rtl_entries
[i
].lpData
);
1015 ok( rtl_entries
[i
].cbData
== entries
[i
].cbData
, "got cbData %#Ix\n", rtl_entries
[i
].cbData
);
1016 ok( rtl_entries
[i
].cbOverhead
== entries
[i
].cbOverhead
, "got cbOverhead %#x\n", rtl_entries
[i
].cbOverhead
);
1017 ok( rtl_entries
[i
].iRegionIndex
== entries
[i
].iRegionIndex
, "got iRegionIndex %#x\n", rtl_entries
[i
].iRegionIndex
);
1018 if (!entries
[i
].wFlags
)
1019 ok( rtl_entries
[i
].wFlags
== 0 || rtl_entries
[i
].wFlags
== RTL_HEAP_ENTRY_LFH
, "got wFlags %#x\n", rtl_entries
[i
].wFlags
);
1020 else if (entries
[i
].wFlags
& PROCESS_HEAP_ENTRY_BUSY
)
1021 ok( rtl_entries
[i
].wFlags
== (RTL_HEAP_ENTRY_LFH
|RTL_HEAP_ENTRY_BUSY
) || broken(rtl_entries
[i
].wFlags
== 1) /* win7 */,
1022 "got wFlags %#x\n", rtl_entries
[i
].wFlags
);
1023 else if (entries
[i
].wFlags
& PROCESS_HEAP_UNCOMMITTED_RANGE
)
1024 ok( rtl_entries
[i
].wFlags
== RTL_HEAP_ENTRY_UNCOMMITTED
|| broken(rtl_entries
[i
].wFlags
== 0x100) /* win7 */,
1025 "got wFlags %#x\n", rtl_entries
[i
].wFlags
);
1026 else if (entries
[i
].wFlags
& PROCESS_HEAP_REGION
)
1028 ok( rtl_entries
[i
].wFlags
== (RTL_HEAP_ENTRY_LFH
|RTL_HEAP_ENTRY_REGION
), "got wFlags %#x\n", rtl_entries
[i
].wFlags
);
1029 ok( rtl_entries
[i
].Region
.dwCommittedSize
== entries
[i
].Region
.dwCommittedSize
,
1030 "got Region.dwCommittedSize %#lx\n", rtl_entries
[i
].Region
.dwCommittedSize
);
1031 ok( rtl_entries
[i
].Region
.dwUnCommittedSize
== entries
[i
].Region
.dwUnCommittedSize
,
1032 "got Region.dwUnCommittedSize %#lx\n", rtl_entries
[i
].Region
.dwUnCommittedSize
);
1033 ok( rtl_entries
[i
].Region
.lpFirstBlock
== entries
[i
].Region
.lpFirstBlock
,
1034 "got Region.lpFirstBlock %p\n", rtl_entries
[i
].Region
.lpFirstBlock
);
1035 ok( rtl_entries
[i
].Region
.lpLastBlock
== entries
[i
].Region
.lpLastBlock
,
1036 "got Region.lpLastBlock %p\n", rtl_entries
[i
].Region
.lpLastBlock
);
1038 winetest_pop_context();
1041 for (i
= 0; i
< 0x12; i
++) ptrs
[i
] = pHeapAlloc( heap
, 0, 24 + 2 * sizeof(void *) );
1044 memset( &entries
, 0xcd, sizeof(entries
) );
1045 memset( &entry
, 0xcd, sizeof(entry
) );
1046 entry
.lpData
= NULL
;
1047 SetLastError( 0xdeadbeef );
1048 while ((ret
= HeapWalk( heap
, &entry
))) entries
[count
++] = entry
;
1049 ok( GetLastError() == ERROR_NO_MORE_ITEMS
, "got error %lu\n", GetLastError() );
1051 ok( count
> 24, "got count %lu\n", count
);
1052 if (count
< 2) count
= 2;
1054 ok( entries
[0].wFlags
== PROCESS_HEAP_REGION
, "got wFlags %#x\n", entries
[0].wFlags
);
1055 ok( entries
[0].lpData
== heap
, "got lpData %p\n", entries
[0].lpData
);
1056 ok( entries
[0].cbData
<= 0x1000 /* sizeof(*heap) */, "got cbData %#lx\n", entries
[0].cbData
);
1057 ok( entries
[0].cbOverhead
== 0, "got cbOverhead %#x\n", entries
[0].cbOverhead
);
1058 ok( entries
[0].iRegionIndex
== 0, "got iRegionIndex %d\n", entries
[0].iRegionIndex
);
1059 ok( entries
[1].wFlags
== 0 || entries
[1].wFlags
== PROCESS_HEAP_ENTRY_BUSY
/* win7 */, "got wFlags %#x\n", entries
[1].wFlags
);
1061 for (i
= 1; i
< count
- 2; i
++)
1063 if (entries
[i
].wFlags
!= PROCESS_HEAP_ENTRY_BUSY
) continue;
1064 todo_wine
/* Wine currently reports the LFH group as a single block */
1065 ok( entries
[i
].cbData
== 0x18 + 2 * sizeof(void *), "got cbData %#lx\n", entries
[i
].cbData
);
1066 ok( entries
[i
].cbOverhead
== 0x8, "got cbOverhead %#x\n", entries
[i
].cbOverhead
);
1069 if (entries
[count
- 1].wFlags
== PROCESS_HEAP_REGION
) /* > win7 */
1070 ok( entries
[count
- 2].wFlags
== PROCESS_HEAP_UNCOMMITTED_RANGE
, "got wFlags %#x\n", entries
[count
- 2].wFlags
);
1072 ok( entries
[count
- 1].wFlags
== PROCESS_HEAP_UNCOMMITTED_RANGE
, "got wFlags %#x\n", entries
[count
- 2].wFlags
);
1075 memset( &rtl_entries
, 0, sizeof(rtl_entries
) );
1076 memset( &rtl_entry
, 0xcd, sizeof(rtl_entry
) );
1077 rtl_entry
.lpData
= NULL
;
1078 SetLastError( 0xdeadbeef );
1079 while (!RtlWalkHeap( heap
, &rtl_entry
)) rtl_entries
[count
++] = rtl_entry
;
1081 ok( count
> 24, "got count %lu\n", count
);
1082 if (count
< 2) count
= 2;
1084 for (i
= 3; i
< count
; ++i
)
1086 winetest_push_context( "%Iu", i
);
1087 ok( rtl_entries
[i
].lpData
== entries
[i
].lpData
, "got lpData %p\n", rtl_entries
[i
].lpData
);
1088 ok( rtl_entries
[i
].cbData
== entries
[i
].cbData
, "got cbData %#Ix\n", rtl_entries
[i
].cbData
);
1089 ok( rtl_entries
[i
].cbOverhead
== entries
[i
].cbOverhead
, "got cbOverhead %#x\n", rtl_entries
[i
].cbOverhead
);
1090 ok( rtl_entries
[i
].iRegionIndex
== entries
[i
].iRegionIndex
, "got iRegionIndex %#x\n", rtl_entries
[i
].iRegionIndex
);
1091 if (!entries
[i
].wFlags
)
1092 ok( rtl_entries
[i
].wFlags
== 0 || rtl_entries
[i
].wFlags
== RTL_HEAP_ENTRY_LFH
, "got wFlags %#x\n", rtl_entries
[i
].wFlags
);
1093 else if (entries
[i
].wFlags
& PROCESS_HEAP_ENTRY_BUSY
)
1096 ok( rtl_entries
[i
].wFlags
== (RTL_HEAP_ENTRY_LFH
|RTL_HEAP_ENTRY_BUSY
) || broken(rtl_entries
[i
].wFlags
== 1) /* win7 */,
1097 "got wFlags %#x\n", rtl_entries
[i
].wFlags
);
1099 else if (entries
[i
].wFlags
& PROCESS_HEAP_UNCOMMITTED_RANGE
)
1100 ok( rtl_entries
[i
].wFlags
== RTL_HEAP_ENTRY_UNCOMMITTED
|| broken(rtl_entries
[i
].wFlags
== 0x100) /* win7 */,
1101 "got wFlags %#x\n", rtl_entries
[i
].wFlags
);
1102 else if (entries
[i
].wFlags
& PROCESS_HEAP_REGION
)
1104 ok( rtl_entries
[i
].wFlags
== (RTL_HEAP_ENTRY_LFH
|RTL_HEAP_ENTRY_REGION
), "got wFlags %#x\n", rtl_entries
[i
].wFlags
);
1105 ok( rtl_entries
[i
].Region
.dwCommittedSize
== entries
[i
].Region
.dwCommittedSize
,
1106 "got Region.dwCommittedSize %#lx\n", rtl_entries
[i
].Region
.dwCommittedSize
);
1107 ok( rtl_entries
[i
].Region
.dwUnCommittedSize
== entries
[i
].Region
.dwUnCommittedSize
,
1108 "got Region.dwUnCommittedSize %#lx\n", rtl_entries
[i
].Region
.dwUnCommittedSize
);
1109 ok( rtl_entries
[i
].Region
.lpFirstBlock
== entries
[i
].Region
.lpFirstBlock
,
1110 "got Region.lpFirstBlock %p\n", rtl_entries
[i
].Region
.lpFirstBlock
);
1111 ok( rtl_entries
[i
].Region
.lpLastBlock
== entries
[i
].Region
.lpLastBlock
,
1112 "got Region.lpLastBlock %p\n", rtl_entries
[i
].Region
.lpLastBlock
);
1114 winetest_pop_context();
1117 for (i
= 0; i
< 0x12; i
++) HeapFree( heap
, 0, ptrs
[i
] );
1119 ret
= HeapDestroy( heap
);
1120 ok( ret
, "HeapDestroy failed, error %lu\n", GetLastError() );
1123 /* check HEAP_NO_SERIALIZE HeapCreate flag effect */
1125 heap
= HeapCreate( HEAP_NO_SERIALIZE
, 0, 0 );
1126 ok( !!heap
, "HeapCreate failed, error %lu\n", GetLastError() );
1127 ok( !((ULONG_PTR
)heap
& 0xffff), "wrong heap alignment\n" );
1129 ret
= HeapLock( heap
);
1130 ok( ret
, "HeapLock failed, error %lu\n", GetLastError() );
1131 thread_params
.heap
= heap
;
1132 thread_params
.lock
= TRUE
;
1133 thread_params
.flags
= 0;
1134 SetEvent( thread_params
.start_event
);
1135 res
= WaitForSingleObject( thread_params
.ready_event
, 100 );
1136 ok( !res
, "WaitForSingleObject returned %#lx, error %lu\n", res
, GetLastError() );
1137 ret
= HeapUnlock( heap
);
1138 ok( ret
, "HeapUnlock failed, error %lu\n", GetLastError() );
1140 ret
= HeapLock( heap
);
1141 ok( ret
, "HeapLock failed, error %lu\n", GetLastError() );
1142 thread_params
.heap
= heap
;
1143 thread_params
.lock
= FALSE
;
1144 thread_params
.flags
= 0;
1145 SetEvent( thread_params
.start_event
);
1146 res
= WaitForSingleObject( thread_params
.ready_event
, 100 );
1147 ok( !res
, "WaitForSingleObject returned %#lx, error %lu\n", res
, GetLastError() );
1148 ret
= HeapUnlock( heap
);
1149 ok( ret
, "HeapUnlock failed, error %lu\n", GetLastError() );
1151 ret
= HeapDestroy( heap
);
1152 ok( ret
, "HeapDestroy failed, error %lu\n", GetLastError() );
1155 /* check HEAP_NO_SERIALIZE HeapAlloc / HeapFree flag effect */
1157 heap
= HeapCreate( 0, 0, 0 );
1158 ok( !!heap
, "HeapCreate failed, error %lu\n", GetLastError() );
1159 ok( !((ULONG_PTR
)heap
& 0xffff), "wrong heap alignment\n" );
1161 ret
= HeapLock( heap
);
1162 ok( ret
, "HeapLock failed, error %lu\n", GetLastError() );
1163 thread_params
.heap
= heap
;
1164 thread_params
.lock
= TRUE
;
1165 thread_params
.flags
= 0;
1166 SetEvent( thread_params
.start_event
);
1167 res
= WaitForSingleObject( thread_params
.ready_event
, 100 );
1168 ok( res
== WAIT_TIMEOUT
, "WaitForSingleObject returned %#lx, error %lu\n", res
, GetLastError() );
1169 ret
= HeapUnlock( heap
);
1170 ok( ret
, "HeapUnlock failed, error %lu\n", GetLastError() );
1171 res
= WaitForSingleObject( thread_params
.ready_event
, 100 );
1172 ok( !res
, "WaitForSingleObject returned %#lx, error %lu\n", res
, GetLastError() );
1174 ret
= HeapLock( heap
);
1175 ok( ret
, "HeapLock failed, error %lu\n", GetLastError() );
1176 thread_params
.heap
= heap
;
1177 thread_params
.lock
= FALSE
;
1178 thread_params
.flags
= 0;
1179 SetEvent( thread_params
.start_event
);
1180 res
= WaitForSingleObject( thread_params
.ready_event
, 100 );
1181 ok( res
== WAIT_TIMEOUT
, "WaitForSingleObject returned %#lx, error %lu\n", res
, GetLastError() );
1182 ret
= HeapUnlock( heap
);
1183 ok( ret
, "HeapUnlock failed, error %lu\n", GetLastError() );
1184 res
= WaitForSingleObject( thread_params
.ready_event
, 100 );
1185 ok( !res
, "WaitForSingleObject returned %#lx, error %lu\n", res
, GetLastError() );
1187 ret
= HeapLock( heap
);
1188 ok( ret
, "HeapLock failed, error %lu\n", GetLastError() );
1189 thread_params
.heap
= heap
;
1190 thread_params
.lock
= FALSE
;
1191 thread_params
.flags
= HEAP_NO_SERIALIZE
;
1192 SetEvent( thread_params
.start_event
);
1193 res
= WaitForSingleObject( thread_params
.ready_event
, 100 );
1194 ok( !res
, "WaitForSingleObject returned %#lx, error %lu\n", res
, GetLastError() );
1195 ret
= HeapUnlock( heap
);
1196 ok( ret
, "HeapUnlock failed, error %lu\n", GetLastError() );
1198 ret
= HeapDestroy( heap
);
1199 ok( ret
, "HeapDestroy failed, error %lu\n", GetLastError() );
1202 /* check LFH heap locking */
1204 heap
= HeapCreate( 0, 0, 0 );
1205 ok( !!heap
, "HeapCreate failed, error %lu\n", GetLastError() );
1206 ok( !((ULONG_PTR
)heap
& 0xffff), "wrong heap alignment\n" );
1208 ret
= pHeapQueryInformation( heap
, HeapCompatibilityInformation
, &compat_info
, sizeof(compat_info
), &size
);
1209 ok( ret
, "HeapQueryInformation failed, error %lu\n", GetLastError() );
1210 ok( compat_info
== 0, "got HeapCompatibilityInformation %lu\n", compat_info
);
1212 for (i
= 0; i
< 0x12; i
++) ptrs
[i
] = pHeapAlloc( heap
, 0, 0 );
1213 for (i
= 0; i
< 0x12; i
++) HeapFree( heap
, 0, ptrs
[i
] );
1215 ret
= pHeapQueryInformation( heap
, HeapCompatibilityInformation
, &compat_info
, sizeof(compat_info
), &size
);
1216 ok( ret
, "HeapQueryInformation failed, error %lu\n", GetLastError() );
1217 ok( compat_info
== 2, "got HeapCompatibilityInformation %lu\n", compat_info
);
1219 /* locking is serialized */
1221 ret
= HeapLock( heap
);
1222 ok( ret
, "HeapLock failed, error %lu\n", GetLastError() );
1223 thread_params
.heap
= heap
;
1224 thread_params
.lock
= TRUE
;
1225 thread_params
.flags
= 0;
1226 SetEvent( thread_params
.start_event
);
1227 res
= WaitForSingleObject( thread_params
.ready_event
, 100 );
1228 ok( res
== WAIT_TIMEOUT
, "WaitForSingleObject returned %#lx, error %lu\n", res
, GetLastError() );
1229 ret
= HeapUnlock( heap
);
1230 ok( ret
, "HeapUnlock failed, error %lu\n", GetLastError() );
1231 res
= WaitForSingleObject( thread_params
.ready_event
, 100 );
1232 ok( !res
, "WaitForSingleObject returned %#lx, error %lu\n", res
, GetLastError() );
1234 /* but allocation is not */
1236 ret
= HeapLock( heap
);
1237 ok( ret
, "HeapLock failed, error %lu\n", GetLastError() );
1238 thread_params
.heap
= heap
;
1239 thread_params
.lock
= FALSE
;
1240 thread_params
.flags
= 0;
1241 SetEvent( thread_params
.start_event
);
1242 res
= WaitForSingleObject( thread_params
.ready_event
, 100 );
1243 ok( !res
, "WaitForSingleObject returned %#lx, error %lu\n", res
, GetLastError() );
1244 ret
= HeapUnlock( heap
);
1245 ok( ret
, "HeapUnlock failed, error %lu\n", GetLastError() );
1246 if (res
) res
= WaitForSingleObject( thread_params
.ready_event
, 100 );
1248 ret
= HeapDestroy( heap
);
1249 ok( ret
, "HeapDestroy failed, error %lu\n", GetLastError() );
1252 thread_params
.done
= TRUE
;
1253 SetEvent( thread_params
.start_event
);
1254 res
= WaitForSingleObject( thread
, INFINITE
);
1255 ok( !res
, "WaitForSingleObject returned %#lx, error %lu\n", res
, GetLastError() );
1256 CloseHandle( thread_params
.start_event
);
1257 CloseHandle( thread_params
.ready_event
);
1258 CloseHandle( thread
);
1268 static struct mem_entry
*mem_entry_from_HANDLE( HLOCAL handle
)
1270 return CONTAINING_RECORD( handle
, struct mem_entry
, ptr
);
1273 static BOOL
is_mem_entry( HLOCAL handle
)
1275 return ((UINT_PTR
)handle
& ((sizeof(void *) << 1) - 1)) == sizeof(void *);
1278 static void test_GlobalAlloc(void)
1280 static const UINT flags_tests
[] =
1282 GMEM_FIXED
| GMEM_NOTIFY
,
1283 GMEM_FIXED
| GMEM_DISCARDABLE
,
1284 GMEM_MOVEABLE
| GMEM_NOTIFY
,
1285 GMEM_MOVEABLE
| GMEM_DDESHARE
,
1286 GMEM_MOVEABLE
| GMEM_NOT_BANKED
,
1287 GMEM_MOVEABLE
| GMEM_NODISCARD
,
1288 GMEM_MOVEABLE
| GMEM_DISCARDABLE
,
1289 GMEM_MOVEABLE
| GMEM_DDESHARE
| GMEM_DISCARDABLE
| GMEM_LOWER
| GMEM_NOCOMPACT
| GMEM_NODISCARD
| GMEM_NOT_BANKED
| GMEM_NOTIFY
,
1291 static const UINT realloc_flags_tests
[] =
1294 GMEM_FIXED
| GMEM_MODIFY
,
1296 GMEM_MOVEABLE
| GMEM_MODIFY
,
1297 GMEM_MOVEABLE
| GMEM_DISCARDABLE
,
1298 GMEM_MOVEABLE
| GMEM_MODIFY
| GMEM_DISCARDABLE
,
1299 GMEM_MOVEABLE
| GMEM_DDESHARE
| GMEM_DISCARDABLE
| GMEM_LOWER
| GMEM_NOCOMPACT
| GMEM_NODISCARD
| GMEM_NOT_BANKED
| GMEM_NOTIFY
,
1300 GMEM_MOVEABLE
| GMEM_MODIFY
| GMEM_DDESHARE
| GMEM_DISCARDABLE
| GMEM_LOWER
| GMEM_NOCOMPACT
| GMEM_NODISCARD
| GMEM_NOT_BANKED
| GMEM_NOTIFY
,
1302 static const char zero_buffer
[100000] = {0};
1303 static const SIZE_T buffer_size
= ARRAY_SIZE(zero_buffer
);
1304 const HGLOBAL invalid_mem
= LongToHandle( 0xdeadbee0 + sizeof(void *) );
1305 SIZE_T size
, alloc_size
, small_size
= 12, nolfh_size
= 0x20000;
1306 void *const invalid_ptr
= LongToHandle( 0xdeadbee0 );
1307 HANDLE heap
= GetProcessHeap();
1308 PROCESS_HEAP_ENTRY walk_entry
;
1309 struct mem_entry
*entry
;
1310 HGLOBAL globals
[0x10000];
1311 HGLOBAL mem
, tmp_mem
;
1312 BYTE
*ptr
, *tmp_ptr
;
1317 mem
= GlobalFree( 0 );
1318 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
1319 mem
= GlobalReAlloc( 0, 10, GMEM_MOVEABLE
);
1320 ok( !mem
, "GlobalReAlloc succeeded\n" );
1322 for (i
= 0; i
< ARRAY_SIZE(globals
); ++i
)
1324 mem
= GlobalAlloc( GMEM_MOVEABLE
| GMEM_DISCARDABLE
, 0 );
1325 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1329 memset( &walk_entry
, 0xcd, sizeof(walk_entry
) );
1330 walk_entry
.lpData
= NULL
;
1331 ret
= HeapLock( heap
);
1332 ok( ret
, "HeapLock failed, error %lu\n", GetLastError() );
1333 while ((ret
= HeapWalk( heap
, &walk_entry
)))
1335 ok( !(walk_entry
.wFlags
& PROCESS_HEAP_ENTRY_MOVEABLE
), "got PROCESS_HEAP_ENTRY_MOVEABLE\n" );
1336 ok( !(walk_entry
.wFlags
& PROCESS_HEAP_ENTRY_DDESHARE
), "got PROCESS_HEAP_ENTRY_DDESHARE\n" );
1338 ok( GetLastError() == ERROR_NO_MORE_ITEMS
, "got error %lu\n", GetLastError() );
1339 ret
= HeapUnlock( heap
);
1340 ok( ret
, "HeapUnlock failed, error %lu\n", GetLastError() );
1342 SetLastError( 0xdeadbeef );
1343 mem
= GlobalAlloc( GMEM_MOVEABLE
| GMEM_DISCARDABLE
, 0 );
1344 ok( !mem
, "GlobalAlloc succeeded\n" );
1345 ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY
, "got error %lu\n", GetLastError() );
1346 SetLastError( 0xdeadbeef );
1347 mem
= LocalAlloc( LMEM_MOVEABLE
| LMEM_DISCARDABLE
, 0 );
1348 ok( !mem
, "LocalAlloc succeeded\n" );
1349 ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY
, "got error %lu\n", GetLastError() );
1351 mem
= GlobalAlloc( GMEM_DISCARDABLE
, 0 );
1352 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1353 mem
= GlobalFree( mem
);
1354 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
1356 for (i
= 0; i
< ARRAY_SIZE(globals
); ++i
)
1358 mem
= GlobalFree( globals
[i
] );
1359 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
1362 /* make sure LFH is enabled for some small block size */
1363 for (i
= 0; i
< 0x12; i
++) globals
[i
] = pGlobalAlloc( GMEM_FIXED
, small_size
);
1364 for (i
= 0; i
< 0x12; i
++) pGlobalFree( globals
[i
] );
1366 mem
= GlobalAlloc( GMEM_MOVEABLE
, 0 );
1367 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1368 mem
= GlobalReAlloc( mem
, 10, GMEM_MOVEABLE
);
1369 ok( !!mem
, "GlobalReAlloc failed, error %lu\n", GetLastError() );
1370 size
= GlobalSize( mem
);
1371 ok( size
>= 10 && size
<= 16, "GlobalSize returned %Iu\n", size
);
1372 mem
= GlobalReAlloc( mem
, 0, GMEM_MOVEABLE
);
1373 ok( !!mem
, "GlobalReAlloc failed, error %lu\n", GetLastError() );
1374 size
= GlobalSize( mem
);
1375 ok( size
== 0, "GlobalSize returned %Iu\n", size
);
1376 mem
= GlobalReAlloc( mem
, 10, GMEM_MOVEABLE
);
1377 ok( !!mem
, "GlobalReAlloc failed, error %lu\n", GetLastError() );
1378 size
= GlobalSize( mem
);
1379 ok( size
>= 10 && size
<= 16, "GlobalSize returned %Iu\n", size
);
1380 tmp_mem
= pGlobalFree( mem
);
1381 ok( !tmp_mem
, "GlobalFree failed, error %lu\n", GetLastError() );
1382 size
= GlobalSize( mem
);
1383 ok( size
== 0, "GlobalSize returned %Iu\n", size
);
1385 mem
= pGlobalAlloc( GMEM_MOVEABLE
| GMEM_DISCARDABLE
, 0 );
1386 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1387 entry
= mem_entry_from_HANDLE( mem
);
1388 size
= GlobalSize( mem
);
1389 ok( size
== 0, "GlobalSize returned %Iu\n", size
);
1390 ret
= HeapValidate( GetProcessHeap(), 0, entry
);
1391 ok( !ret
, "HeapValidate succeeded\n" );
1392 ok( entry
->flags
== 0xf, "got unexpected flags %#Ix\n", entry
->flags
);
1393 ok( !entry
->ptr
, "got unexpected ptr %p\n", entry
->ptr
);
1394 mem
= GlobalFree( mem
);
1395 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
1397 mem
= pGlobalAlloc( GMEM_MOVEABLE
, 0 );
1398 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1399 entry
= mem_entry_from_HANDLE( mem
);
1400 size
= GlobalSize( mem
);
1401 ok( size
== 0, "GlobalSize returned %Iu\n", size
);
1402 ret
= HeapValidate( GetProcessHeap(), 0, entry
);
1403 ok( !ret
, "HeapValidate succeeded\n" );
1404 ok( entry
->flags
== 0xb, "got unexpected flags %#Ix\n", entry
->flags
);
1405 ok( !entry
->ptr
, "got unexpected ptr %p\n", entry
->ptr
);
1406 mem
= GlobalFree( mem
);
1407 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
1409 for (alloc_size
= 1; alloc_size
< 0x10000000; alloc_size
<<= 5)
1411 winetest_push_context( "size %#Ix", alloc_size
);
1413 mem
= GlobalAlloc( GMEM_FIXED
, alloc_size
);
1414 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1415 ok( !((UINT_PTR
)mem
& sizeof(void *)), "got unexpected ptr align\n" );
1416 ok( !((UINT_PTR
)mem
& (sizeof(void *) - 1)), "got unexpected ptr align\n" );
1417 ret
= HeapValidate( GetProcessHeap(), 0, mem
);
1418 ok( ret
, "HeapValidate failed, error %lu\n", GetLastError() );
1419 tmp_mem
= GlobalFree( mem
);
1420 ok( !tmp_mem
, "GlobalFree failed, error %lu\n", GetLastError() );
1422 mem
= pGlobalAlloc( GMEM_MOVEABLE
, alloc_size
);
1423 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1424 ok( ((UINT_PTR
)mem
& sizeof(void *)), "got unexpected entry align\n" );
1425 ok( !((UINT_PTR
)mem
& (sizeof(void *) - 1)), "got unexpected entry align\n" );
1427 entry
= mem_entry_from_HANDLE( mem
);
1428 ret
= HeapValidate( GetProcessHeap(), 0, entry
);
1429 ok( !ret
, "HeapValidate succeeded\n" );
1430 ret
= HeapValidate( GetProcessHeap(), 0, entry
->ptr
);
1431 ok( ret
, "HeapValidate failed, error %lu\n", GetLastError() );
1432 size
= HeapSize( GetProcessHeap(), 0, entry
->ptr
);
1433 ok( size
== alloc_size
, "HeapSize returned %Iu\n", size
);
1435 tmp_mem
= invalid_mem
;
1436 tmp_flags
= 0xdeadbeef;
1437 ret
= pRtlGetUserInfoHeap( GetProcessHeap(), 0, entry
->ptr
, (void **)&tmp_mem
, &tmp_flags
);
1438 ok( ret
, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() );
1439 ok( tmp_mem
== mem
, "got user ptr %p\n", tmp_mem
);
1440 ok( tmp_flags
== 0x200, "got user flags %#lx\n", tmp_flags
);
1442 ret
= pRtlSetUserValueHeap( GetProcessHeap(), 0, entry
->ptr
, invalid_mem
);
1443 ok( ret
, "RtlSetUserValueHeap failed, error %lu\n", GetLastError() );
1444 tmp_mem
= GlobalHandle( entry
->ptr
);
1445 ok( tmp_mem
== invalid_mem
, "GlobalHandle returned unexpected handle\n" );
1446 ret
= pRtlSetUserValueHeap( GetProcessHeap(), 0, entry
->ptr
, mem
);
1447 ok( ret
, "RtlSetUserValueHeap failed, error %lu\n", GetLastError() );
1449 ptr
= GlobalLock( mem
);
1450 ok( !!ptr
, "GlobalLock failed, error %lu\n", GetLastError() );
1451 ok( ptr
!= mem
, "got unexpected ptr %p\n", ptr
);
1452 ok( ptr
== entry
->ptr
, "got unexpected ptr %p\n", ptr
);
1453 ok( !((UINT_PTR
)ptr
& sizeof(void *)), "got unexpected ptr align\n" );
1454 ok( !((UINT_PTR
)ptr
& (sizeof(void *) - 1)), "got unexpected ptr align\n" );
1455 for (i
= 1; i
< 0xff; ++i
)
1457 ok( entry
->flags
== ((i
<<16)|3), "got unexpected flags %#Ix\n", entry
->flags
);
1458 ptr
= GlobalLock( mem
);
1459 ok( !!ptr
, "GlobalLock failed, error %lu\n", GetLastError() );
1461 ptr
= GlobalLock( mem
);
1462 ok( !!ptr
, "GlobalLock failed, error %lu\n", GetLastError() );
1463 ok( entry
->flags
== 0xff0003, "got unexpected flags %#Ix\n", entry
->flags
);
1464 for (i
= 1; i
< 0xff; ++i
)
1466 ret
= GlobalUnlock( mem
);
1467 ok( ret
, "GlobalUnlock failed, error %lu\n", GetLastError() );
1469 ret
= GlobalUnlock( mem
);
1470 ok( !ret
, "GlobalUnlock succeeded, error %lu\n", GetLastError() );
1471 ok( entry
->flags
== 0x3, "got unexpected flags %#Ix\n", entry
->flags
);
1473 tmp_mem
= pGlobalFree( mem
);
1474 ok( !tmp_mem
, "GlobalFree failed, error %lu\n", GetLastError() );
1475 ok( !!entry
->flags
, "got unexpected flags %#Ix\n", entry
->flags
);
1476 ok( !((UINT_PTR
)entry
->flags
& sizeof(void *)), "got unexpected ptr align\n" );
1477 ok( !((UINT_PTR
)entry
->flags
& (sizeof(void *) - 1)), "got unexpected ptr align\n" );
1478 ok( !entry
->ptr
, "got unexpected ptr %p\n", entry
->ptr
);
1480 mem
= pGlobalAlloc( GMEM_MOVEABLE
| GMEM_DISCARDABLE
, 0 );
1481 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1482 entry
= mem_entry_from_HANDLE( mem
);
1483 ok( entry
->flags
== 0xf, "got unexpected flags %#Ix\n", entry
->flags
);
1484 ok( !entry
->ptr
, "got unexpected ptr %p\n", entry
->ptr
);
1485 flags
= GlobalFlags( mem
);
1486 ok( flags
== (GMEM_DISCARDED
| GMEM_DISCARDABLE
), "GlobalFlags returned %#x, error %lu\n", flags
, GetLastError() );
1487 mem
= GlobalFree( mem
);
1488 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
1490 mem
= pGlobalAlloc( GMEM_MOVEABLE
| GMEM_DISCARDABLE
, 1 );
1491 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1492 entry
= mem_entry_from_HANDLE( mem
);
1493 ok( entry
->flags
== 0x7, "got unexpected flags %#Ix\n", entry
->flags
);
1494 ok( !!entry
->ptr
, "got unexpected ptr %p\n", entry
->ptr
);
1495 flags
= GlobalFlags( mem
);
1496 ok( flags
== GMEM_DISCARDABLE
, "GlobalFlags returned %#x, error %lu\n", flags
, GetLastError() );
1497 mem
= GlobalFree( mem
);
1498 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
1500 mem
= pGlobalAlloc( GMEM_MOVEABLE
| GMEM_DISCARDABLE
| GMEM_DDESHARE
, 1 );
1501 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1502 entry
= mem_entry_from_HANDLE( mem
);
1503 ok( entry
->flags
== 0x8007, "got unexpected flags %#Ix\n", entry
->flags
);
1504 ok( !!entry
->ptr
, "got unexpected ptr %p\n", entry
->ptr
);
1505 flags
= GlobalFlags( mem
);
1506 ok( flags
== (GMEM_DISCARDABLE
| GMEM_DDESHARE
), "GlobalFlags returned %#x, error %lu\n", flags
, GetLastError() );
1507 mem
= GlobalFree( mem
);
1508 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
1510 winetest_pop_context();
1513 mem
= GlobalAlloc( GMEM_MOVEABLE
, 256 );
1514 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1515 ptr
= GlobalLock( mem
);
1516 ok( !!ptr
, "GlobalLock failed, error %lu\n", GetLastError() );
1517 ok( ptr
!= mem
, "got unexpected ptr %p\n", ptr
);
1518 tmp_mem
= GlobalHandle( ptr
);
1519 ok( tmp_mem
== mem
, "GlobalHandle returned unexpected handle\n" );
1520 flags
= GlobalFlags( mem
);
1521 ok( flags
== 1, "GlobalFlags returned %#x, error %lu\n", flags
, GetLastError() );
1522 tmp_ptr
= GlobalLock( mem
);
1523 ok( !!tmp_ptr
, "GlobalLock failed, error %lu\n", GetLastError() );
1524 ok( tmp_ptr
== ptr
, "got ptr %p, expected %p\n", tmp_ptr
, ptr
);
1525 flags
= GlobalFlags( mem
);
1526 ok( flags
== 2, "GlobalFlags returned %#x, error %lu\n", flags
, GetLastError() );
1527 ret
= GlobalUnlock( mem
);
1528 ok( ret
, "GlobalUnlock failed, error %lu\n", GetLastError() );
1529 flags
= GlobalFlags( mem
);
1530 ok( flags
== 1, "GlobalFlags returned %#x, error %lu\n", flags
, GetLastError() );
1531 SetLastError( 0xdeadbeef );
1532 ret
= GlobalUnlock( mem
);
1533 ok( !ret
, "GlobalUnlock succeeded\n" );
1534 ok( GetLastError() == ERROR_SUCCESS
, "got error %lu\n", GetLastError() );
1535 flags
= GlobalFlags( mem
);
1536 ok( !flags
, "GlobalFlags returned %#x, error %lu\n", flags
, GetLastError() );
1537 SetLastError( 0xdeadbeef );
1538 ret
= GlobalUnlock( mem
);
1539 ok( !ret
, "GlobalUnlock succeeded\n" );
1540 ok( GetLastError() == ERROR_NOT_LOCKED
, "got error %lu\n", GetLastError() );
1541 tmp_mem
= GlobalFree( mem
);
1542 ok( !tmp_mem
, "GlobalFree failed, error %lu\n", GetLastError() );
1544 mem
= GlobalAlloc( GMEM_DDESHARE
, 100 );
1545 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1546 tmp_mem
= pGlobalFree( mem
);
1547 ok( !tmp_mem
, "GlobalFree failed, error %lu\n", GetLastError() );
1548 if (sizeof(void *) != 8) /* crashes on 64-bit */
1550 SetLastError( 0xdeadbeef );
1551 tmp_mem
= pGlobalFree( mem
);
1552 ok( tmp_mem
== mem
, "GlobalFree succeeded\n" );
1553 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
1555 SetLastError( 0xdeadbeef );
1556 size
= GlobalSize( (HGLOBAL
)0xc042 );
1557 ok( size
== 0, "GlobalSize succeeded\n" );
1558 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
1561 /* freed handles are caught */
1562 mem
= GlobalAlloc( GMEM_MOVEABLE
, 256 );
1563 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1564 tmp_mem
= pGlobalFree( mem
);
1565 ok( !tmp_mem
, "GlobalFree failed, error %lu\n", GetLastError() );
1566 SetLastError( 0xdeadbeef );
1567 tmp_mem
= pGlobalFree( mem
);
1568 ok( tmp_mem
== mem
, "GlobalFree succeeded\n" );
1569 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
1570 SetLastError( 0xdeadbeef );
1571 flags
= GlobalFlags( mem
);
1572 ok( flags
== GMEM_INVALID_HANDLE
, "GlobalFlags succeeded\n" );
1573 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
1574 SetLastError( 0xdeadbeef );
1575 size
= GlobalSize( mem
);
1576 ok( size
== 0, "GlobalSize succeeded\n" );
1577 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
1578 SetLastError( 0xdeadbeef );
1579 ptr
= GlobalLock( mem
);
1580 ok( !ptr
, "GlobalLock succeeded\n" );
1581 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
1582 SetLastError( 0xdeadbeef );
1583 ret
= GlobalUnlock( mem
);
1585 ok( ret
, "GlobalUnlock failed, error %lu\n", GetLastError() );
1586 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
1587 SetLastError( 0xdeadbeef );
1588 tmp_mem
= GlobalReAlloc( mem
, 0, GMEM_MOVEABLE
);
1589 ok( !tmp_mem
, "GlobalReAlloc succeeded\n" );
1590 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
1591 if (sizeof(void *) != 8) /* crashes on 64-bit */
1593 SetLastError( 0xdeadbeef );
1594 tmp_mem
= GlobalHandle( mem
);
1595 ok( !tmp_mem
, "GlobalHandle succeeded\n" );
1596 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
1599 /* invalid handles are caught */
1600 SetLastError( 0xdeadbeef );
1601 tmp_mem
= pGlobalFree( invalid_mem
);
1602 ok( tmp_mem
== invalid_mem
, "GlobalFree succeeded\n" );
1603 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
1604 SetLastError( 0xdeadbeef );
1605 flags
= GlobalFlags( invalid_mem
);
1606 ok( flags
== GMEM_INVALID_HANDLE
, "GlobalFlags succeeded\n" );
1607 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
1608 SetLastError( 0xdeadbeef );
1609 size
= GlobalSize( invalid_mem
);
1610 ok( size
== 0, "GlobalSize succeeded\n" );
1611 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
1612 SetLastError( 0xdeadbeef );
1613 ptr
= GlobalLock( invalid_mem
);
1614 ok( !ptr
, "GlobalLock succeeded\n" );
1615 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
1616 SetLastError( 0xdeadbeef );
1617 ret
= GlobalUnlock( invalid_mem
);
1619 ok( ret
, "GlobalUnlock failed, error %lu\n", GetLastError() );
1620 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
1621 SetLastError( 0xdeadbeef );
1622 tmp_mem
= GlobalReAlloc( invalid_mem
, 0, GMEM_MOVEABLE
);
1623 ok( !tmp_mem
, "GlobalReAlloc succeeded\n" );
1624 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
1625 if (sizeof(void *) != 8) /* crashes on 64-bit */
1627 SetLastError( 0xdeadbeef );
1628 tmp_mem
= GlobalHandle( invalid_mem
);
1629 ok( !tmp_mem
, "GlobalHandle succeeded\n" );
1630 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
1631 SetLastError( 0xdeadbeef );
1632 ret
= pRtlGetUserInfoHeap( GetProcessHeap(), 0, invalid_mem
, (void **)&tmp_ptr
, &tmp_flags
);
1633 ok( !ret
, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() );
1634 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "got error %lu\n", GetLastError() );
1637 /* invalid pointers are caught */
1638 SetLastError( 0xdeadbeef );
1639 tmp_mem
= pGlobalFree( invalid_ptr
);
1640 ok( tmp_mem
== invalid_ptr
, "GlobalFree succeeded\n" );
1642 ok( GetLastError() == ERROR_NOACCESS
, "got error %lu\n", GetLastError() );
1643 SetLastError( 0xdeadbeef );
1644 flags
= GlobalFlags( invalid_ptr
);
1646 ok( flags
== GMEM_INVALID_HANDLE
, "GlobalFlags succeeded\n" );
1648 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
1649 SetLastError( 0xdeadbeef );
1650 size
= GlobalSize( invalid_ptr
);
1651 ok( size
== 0, "GlobalSize succeeded\n" );
1652 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
1653 SetLastError( 0xdeadbeef );
1654 ptr
= GlobalLock( invalid_ptr
);
1655 ok( !ptr
, "GlobalLock succeeded\n" );
1657 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
1658 SetLastError( 0xdeadbeef );
1659 ret
= GlobalUnlock( invalid_ptr
);
1660 ok( ret
, "GlobalUnlock failed, error %lu\n", GetLastError() );
1661 ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() );
1662 SetLastError( 0xdeadbeef );
1663 tmp_mem
= GlobalReAlloc( invalid_ptr
, 0, GMEM_MOVEABLE
);
1664 ok( !tmp_mem
, "GlobalReAlloc succeeded\n" );
1666 ok( GetLastError() == ERROR_NOACCESS
, "got error %lu\n", GetLastError() );
1667 SetLastError( 0xdeadbeef );
1668 tmp_mem
= GlobalHandle( invalid_ptr
);
1669 ok( !tmp_mem
, "GlobalHandle succeeded\n" );
1670 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
1671 if (0) /* crashes */
1673 SetLastError( 0xdeadbeef );
1674 ret
= pRtlGetUserInfoHeap( GetProcessHeap(), 0, invalid_ptr
, (void **)&tmp_ptr
, &tmp_flags
);
1675 ok( ret
, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() );
1676 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
1679 /* GMEM_FIXED block doesn't allow resize, though it succeeds with GMEM_MODIFY */
1680 mem
= GlobalAlloc( GMEM_FIXED
, small_size
);
1681 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1682 tmp_mem
= GlobalReAlloc( mem
, small_size
- 1, GMEM_MODIFY
);
1683 ok( !!tmp_mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1684 ok( tmp_mem
== mem
, "got ptr %p, expected %p\n", tmp_mem
, mem
);
1685 size
= GlobalSize( mem
);
1686 ok( size
== small_size
, "GlobalSize returned %Iu\n", size
);
1687 SetLastError( 0xdeadbeef );
1688 tmp_mem
= GlobalReAlloc( mem
, small_size
, 0 );
1689 ok( !tmp_mem
, "GlobalReAlloc succeeded\n" );
1690 ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY
, "got error %lu\n", GetLastError() );
1691 if (tmp_mem
) mem
= tmp_mem
;
1692 tmp_mem
= GlobalReAlloc( mem
, 1024 * 1024, GMEM_MODIFY
);
1693 ok( !!tmp_mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1694 ok( tmp_mem
== mem
, "got ptr %p, expected %p\n", tmp_mem
, mem
);
1695 size
= GlobalSize( mem
);
1696 ok( size
== small_size
, "GlobalSize returned %Iu\n", size
);
1697 mem
= GlobalFree( mem
);
1698 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
1700 /* GMEM_FIXED block can be relocated with GMEM_MOVEABLE */
1701 mem
= GlobalAlloc( GMEM_FIXED
, small_size
);
1702 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1703 tmp_mem
= GlobalReAlloc( mem
, small_size
+ 1, GMEM_MOVEABLE
);
1704 ok( !!tmp_mem
, "GlobalReAlloc failed, error %lu\n", GetLastError() );
1705 ok( tmp_mem
!= mem
, "GlobalReAlloc didn't relocate memory\n" );
1706 ptr
= GlobalLock( tmp_mem
);
1707 ok( !!ptr
, "GlobalLock failed, error %lu\n", GetLastError() );
1708 ok( ptr
== tmp_mem
, "got ptr %p, expected %p\n", ptr
, tmp_mem
);
1709 mem
= GlobalFree( tmp_mem
);
1710 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
1712 /* test GlobalReAlloc flags / GlobalLock combinations */
1714 for (i
= 0; i
< ARRAY_SIZE(realloc_flags_tests
); i
++)
1716 struct mem_entry expect_entry
, entry
;
1717 BOOL expect_convert
;
1719 flags
= realloc_flags_tests
[i
];
1720 expect_convert
= (flags
& (GMEM_MOVEABLE
| GMEM_MODIFY
)) == (GMEM_MOVEABLE
| GMEM_MODIFY
);
1722 winetest_push_context( "flags %#x", flags
);
1724 mem
= pGlobalAlloc( GMEM_FIXED
, small_size
);
1725 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1726 ok( !is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
1728 tmp_mem
= GlobalReAlloc( mem
, 512, flags
);
1729 if (!expect_convert
)
1731 ok( !is_mem_entry( tmp_mem
), "unexpected moveable %p\n", tmp_mem
);
1732 if (flags
== GMEM_MODIFY
) ok( tmp_mem
== mem
, "GlobalReAlloc returned %p\n", tmp_mem
);
1733 else if (flags
!= GMEM_MOVEABLE
) ok( !tmp_mem
, "GlobalReAlloc succeeded\n" );
1734 else ok( tmp_mem
!= mem
, "GlobalReAlloc returned %p\n", tmp_mem
);
1738 ok( is_mem_entry( tmp_mem
), "unexpected moveable %p\n", tmp_mem
);
1739 entry
= *mem_entry_from_HANDLE( tmp_mem
);
1740 todo_wine
ok( entry
.ptr
!= mem
, "got ptr %p was %p\n", entry
.ptr
, mem
);
1741 if (flags
& GMEM_DISCARDABLE
) ok( (entry
.flags
& 0x7fff) == 0x7, "got flags %#Ix\n", entry
.flags
);
1742 else ok( (entry
.flags
& 0x7fff) == 0x3, "got flags %#Ix\n", entry
.flags
);
1744 if (tmp_mem
) mem
= tmp_mem
;
1746 size
= GlobalSize( mem
);
1747 if (flags
== GMEM_MOVEABLE
) ok( size
== 512, "GlobalSize returned %Iu\n", size
);
1748 else ok( size
== small_size
, "GlobalSize returned %Iu\n", size
);
1750 mem
= GlobalFree( mem
);
1751 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
1754 mem
= pGlobalAlloc( GMEM_FIXED
, nolfh_size
);
1755 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1756 ok( !is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
1758 tmp_mem
= GlobalReAlloc( mem
, nolfh_size
+ 512, flags
);
1759 if (!expect_convert
)
1761 ok( !is_mem_entry( tmp_mem
), "unexpected moveable %p\n", tmp_mem
);
1762 if (flags
& GMEM_DISCARDABLE
) ok( !tmp_mem
, "GlobalReAlloc succeeded\n" );
1763 else ok( tmp_mem
== mem
, "GlobalReAlloc returned %p\n", tmp_mem
);
1767 ok( is_mem_entry( tmp_mem
), "unexpected moveable %p\n", tmp_mem
);
1768 entry
= *mem_entry_from_HANDLE( tmp_mem
);
1769 todo_wine
ok( entry
.ptr
!= mem
, "got ptr %p was %p\n", entry
.ptr
, mem
);
1770 if (flags
& GMEM_DISCARDABLE
) ok( (entry
.flags
& 0x7fff) == 0x7, "got flags %#Ix\n", entry
.flags
);
1771 else ok( (entry
.flags
& 0x7fff) == 0x3, "got flags %#Ix\n", entry
.flags
);
1773 if (tmp_mem
) mem
= tmp_mem
;
1775 size
= GlobalSize( mem
);
1776 if (flags
& (GMEM_MODIFY
| GMEM_DISCARDABLE
)) ok( size
== nolfh_size
, "GlobalSize returned %Iu\n", size
);
1777 else ok( size
== nolfh_size
+ 512, "GlobalSize returned %Iu\n", size
);
1779 mem
= GlobalFree( mem
);
1780 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
1783 mem
= pGlobalAlloc( GMEM_FIXED
, small_size
);
1784 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1785 ok( !is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
1787 tmp_mem
= GlobalReAlloc( mem
, 10, flags
);
1788 if (!expect_convert
)
1790 ok( !is_mem_entry( tmp_mem
), "unexpected moveable %p\n", tmp_mem
);
1791 if (flags
== GMEM_MODIFY
) ok( tmp_mem
== mem
, "GlobalReAlloc returned %p\n", tmp_mem
);
1792 else if (flags
!= GMEM_MOVEABLE
) todo_wine_if(!flags
) ok( !tmp_mem
, "GlobalReAlloc succeeded\n" );
1793 else todo_wine
ok( tmp_mem
!= mem
, "GlobalReAlloc returned %p\n", tmp_mem
);
1797 ok( is_mem_entry( tmp_mem
), "unexpected moveable %p\n", tmp_mem
);
1798 entry
= *mem_entry_from_HANDLE( tmp_mem
);
1799 ok( entry
.ptr
== ptr
, "got ptr %p was %p\n", entry
.ptr
, ptr
);
1800 if (flags
& GMEM_DISCARDABLE
) ok( (entry
.flags
& 0x7fff) == 0x7, "got flags %#Ix\n", entry
.flags
);
1801 else ok( (entry
.flags
& 0x7fff) == 0x3, "got flags %#Ix\n", entry
.flags
);
1803 if (tmp_mem
) mem
= tmp_mem
;
1805 size
= GlobalSize( mem
);
1806 if (flags
== GMEM_MOVEABLE
) ok( size
== 10, "GlobalSize returned %Iu\n", size
);
1807 else todo_wine_if(!flags
) ok( size
== small_size
, "GlobalSize returned %Iu\n", size
);
1809 mem
= GlobalFree( mem
);
1810 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
1813 mem
= pGlobalAlloc( GMEM_FIXED
, nolfh_size
);
1814 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1815 ok( !is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
1817 tmp_mem
= GlobalReAlloc( mem
, 10, flags
);
1818 if (!expect_convert
)
1820 ok( !is_mem_entry( tmp_mem
), "unexpected moveable %p\n", tmp_mem
);
1821 if (flags
& GMEM_DISCARDABLE
) ok( !tmp_mem
, "GlobalReAlloc succeeded\n" );
1822 else ok( tmp_mem
== mem
, "GlobalReAlloc returned %p\n", tmp_mem
);
1826 ok( is_mem_entry( tmp_mem
), "unexpected moveable %p\n", tmp_mem
);
1827 entry
= *mem_entry_from_HANDLE( tmp_mem
);
1828 ok( entry
.ptr
!= ptr
, "got ptr %p was %p\n", entry
.ptr
, ptr
);
1829 if (flags
& GMEM_DISCARDABLE
) ok( (entry
.flags
& 0x7fff) == 0x7, "got flags %#Ix\n", entry
.flags
);
1830 else ok( (entry
.flags
& 0x7fff) == 0x3, "got flags %#Ix\n", entry
.flags
);
1832 if (tmp_mem
) mem
= tmp_mem
;
1834 size
= GlobalSize( mem
);
1835 if (flags
& (GMEM_MODIFY
| GMEM_DISCARDABLE
)) ok( size
== nolfh_size
, "GlobalSize returned %Iu\n", size
);
1836 else ok( size
== 10, "GlobalSize returned %Iu\n", size
);
1838 mem
= GlobalFree( mem
);
1839 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
1842 mem
= pGlobalAlloc( GMEM_FIXED
, small_size
);
1843 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1844 ok( !is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
1846 tmp_mem
= GlobalReAlloc( mem
, 0, flags
);
1847 if (!expect_convert
)
1849 ok( !is_mem_entry( tmp_mem
), "unexpected moveable %p\n", tmp_mem
);
1850 if (flags
== GMEM_MODIFY
) ok( tmp_mem
== mem
, "GlobalReAlloc returned %p\n", tmp_mem
);
1851 else if (flags
!= GMEM_MOVEABLE
) ok( !tmp_mem
, "GlobalReAlloc succeeded\n" );
1852 else ok( tmp_mem
!= mem
, "GlobalReAlloc returned %p\n", tmp_mem
);
1856 ok( is_mem_entry( tmp_mem
), "unexpected moveable %p\n", tmp_mem
);
1857 entry
= *mem_entry_from_HANDLE( tmp_mem
);
1858 ok( entry
.ptr
== ptr
, "got ptr %p was %p\n", entry
.ptr
, ptr
);
1859 if (flags
& GMEM_DISCARDABLE
) ok( (entry
.flags
& 0x7fff) == 0x7, "got flags %#Ix\n", entry
.flags
);
1860 else ok( (entry
.flags
& 0x7fff) == 0x3, "got flags %#Ix\n", entry
.flags
);
1862 if (tmp_mem
) mem
= tmp_mem
;
1864 size
= GlobalSize( mem
);
1865 if (flags
== GMEM_MOVEABLE
) ok( size
== 0 || broken( size
== 1 ) /* w7 */, "GlobalSize returned %Iu\n", size
);
1866 else ok( size
== small_size
, "GlobalSize returned %Iu\n", size
);
1868 mem
= GlobalFree( mem
);
1869 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
1872 mem
= pGlobalAlloc( GMEM_FIXED
, nolfh_size
);
1873 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1874 ok( !is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
1876 tmp_mem
= GlobalReAlloc( mem
, 0, flags
);
1877 if (!expect_convert
)
1879 ok( !is_mem_entry( tmp_mem
), "unexpected moveable %p\n", tmp_mem
);
1880 if (flags
& GMEM_DISCARDABLE
) ok( !tmp_mem
, "GlobalReAlloc succeeded\n" );
1881 else ok( tmp_mem
== mem
, "GlobalReAlloc returned %p\n", tmp_mem
);
1885 ok( is_mem_entry( tmp_mem
), "unexpected moveable %p\n", tmp_mem
);
1886 entry
= *mem_entry_from_HANDLE( tmp_mem
);
1887 ok( entry
.ptr
!= ptr
, "got ptr %p was %p\n", entry
.ptr
, ptr
);
1888 if (flags
& GMEM_DISCARDABLE
) ok( (entry
.flags
& 0x7fff) == 0x7, "got flags %#Ix\n", entry
.flags
);
1889 else ok( (entry
.flags
& 0x7fff) == 0x3, "got flags %#Ix\n", entry
.flags
);
1891 if (tmp_mem
) mem
= tmp_mem
;
1893 size
= GlobalSize( mem
);
1894 if (flags
& (GMEM_MODIFY
| GMEM_DISCARDABLE
)) ok( size
== nolfh_size
, "GlobalSize returned %Iu\n", size
);
1895 else ok( size
== 0 || broken( size
== 1 ) /* w7 */, "GlobalSize returned %Iu\n", size
);
1897 mem
= GlobalFree( mem
);
1898 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
1901 mem
= pGlobalAlloc( GMEM_MOVEABLE
, small_size
);
1902 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1903 ok( is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
1904 ptr
= GlobalLock( mem
);
1905 ok( !!ptr
, "GlobalLock failed, error %lu\n", GetLastError() );
1906 expect_entry
= *mem_entry_from_HANDLE( mem
);
1908 tmp_mem
= GlobalReAlloc( mem
, 512, flags
);
1909 if (flags
& GMEM_MODIFY
) ok( tmp_mem
== mem
, "GlobalReAlloc returned %p\n", tmp_mem
);
1910 else if (flags
& GMEM_DISCARDABLE
) ok( !tmp_mem
, "GlobalReAlloc succeeded\n" );
1911 else if (flags
& GMEM_MOVEABLE
) ok( tmp_mem
== mem
, "GlobalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
1912 else ok( !tmp_mem
, "GlobalReAlloc succeeded\n" );
1913 entry
= *mem_entry_from_HANDLE( mem
);
1914 if ((flags
& GMEM_DISCARDABLE
) && (flags
& GMEM_MODIFY
)) expect_entry
.flags
|= 4;
1915 if (flags
== GMEM_MOVEABLE
) ok( entry
.ptr
!= expect_entry
.ptr
, "got unexpected ptr %p\n", entry
.ptr
);
1916 else ok( entry
.ptr
== expect_entry
.ptr
, "got ptr %p\n", entry
.ptr
);
1917 ok( entry
.flags
== expect_entry
.flags
, "got flags %#Ix was %#Ix\n", entry
.flags
, expect_entry
.flags
);
1919 size
= GlobalSize( mem
);
1920 if (flags
== GMEM_MOVEABLE
) ok( size
== 512, "GlobalSize returned %Iu\n", size
);
1921 else ok( size
== small_size
, "GlobalSize returned %Iu\n", size
);
1923 ret
= GlobalUnlock( mem
);
1924 ok( !ret
, "GlobalUnlock succeeded\n" );
1925 mem
= GlobalFree( mem
);
1926 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
1929 mem
= pGlobalAlloc( GMEM_MOVEABLE
, small_size
);
1930 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1931 ok( is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
1932 ptr
= GlobalLock( mem
);
1933 ok( !!ptr
, "GlobalLock failed, error %lu\n", GetLastError() );
1934 expect_entry
= *mem_entry_from_HANDLE( mem
);
1936 tmp_mem
= GlobalReAlloc( mem
, 10, flags
);
1937 if (flags
& GMEM_MODIFY
) ok( tmp_mem
== mem
, "GlobalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
1938 else if (flags
& GMEM_DISCARDABLE
) ok( !tmp_mem
, "GlobalReAlloc succeeded\n" );
1939 else ok( tmp_mem
== mem
, "GlobalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
1940 entry
= *mem_entry_from_HANDLE( mem
);
1941 if ((flags
& GMEM_DISCARDABLE
) && (flags
& GMEM_MODIFY
)) expect_entry
.flags
|= 4;
1942 ok( entry
.ptr
== expect_entry
.ptr
, "got ptr %p was %p\n", entry
.ptr
, expect_entry
.ptr
);
1943 ok( entry
.flags
== expect_entry
.flags
, "got flags %#Ix was %#Ix\n", entry
.flags
, expect_entry
.flags
);
1945 size
= GlobalSize( mem
);
1946 if (flags
& (GMEM_DISCARDABLE
| GMEM_MODIFY
)) ok( size
== small_size
, "GlobalSize returned %Iu\n", size
);
1947 else ok( size
== 10, "GlobalSize returned %Iu\n", size
);
1949 ret
= GlobalUnlock( mem
);
1950 ok( !ret
, "GlobalUnlock succeeded\n" );
1951 mem
= GlobalFree( mem
);
1952 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
1955 mem
= pGlobalAlloc( GMEM_MOVEABLE
, small_size
);
1956 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1957 ok( is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
1958 ptr
= GlobalLock( mem
);
1959 ok( !!ptr
, "GlobalLock failed, error %lu\n", GetLastError() );
1960 expect_entry
= *mem_entry_from_HANDLE( mem
);
1962 tmp_mem
= GlobalReAlloc( mem
, 0, flags
);
1963 if (flags
& GMEM_MODIFY
) ok( tmp_mem
== mem
, "GlobalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
1964 else ok( !tmp_mem
, "GlobalReAlloc succeeded\n" );
1965 entry
= *mem_entry_from_HANDLE( mem
);
1966 if ((flags
& GMEM_DISCARDABLE
) && (flags
& GMEM_MODIFY
)) expect_entry
.flags
|= 4;
1967 ok( entry
.ptr
== expect_entry
.ptr
, "got ptr %p was %p\n", entry
.ptr
, expect_entry
.ptr
);
1968 ok( entry
.flags
== expect_entry
.flags
, "got flags %#Ix was %#Ix\n", entry
.flags
, expect_entry
.flags
);
1970 size
= GlobalSize( mem
);
1971 ok( size
== small_size
, "GlobalSize returned %Iu\n", size
);
1973 ret
= GlobalUnlock( mem
);
1974 ok( !ret
, "GlobalUnlock succeeded\n" );
1975 mem
= GlobalFree( mem
);
1976 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
1979 mem
= pGlobalAlloc( GMEM_MOVEABLE
, small_size
);
1980 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
1981 ok( is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
1982 expect_entry
= *mem_entry_from_HANDLE( mem
);
1984 tmp_mem
= GlobalReAlloc( mem
, 512, flags
);
1985 if (flags
& GMEM_MODIFY
) ok( tmp_mem
== mem
, "GlobalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
1986 else if (flags
& GMEM_DISCARDABLE
) ok( !tmp_mem
, "GlobalReAlloc succeeded\n" );
1987 else ok( tmp_mem
== mem
, "GlobalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
1988 entry
= *mem_entry_from_HANDLE( mem
);
1989 if ((flags
& GMEM_DISCARDABLE
) && (flags
& GMEM_MODIFY
)) expect_entry
.flags
|= 4;
1990 if (flags
& (GMEM_DISCARDABLE
| GMEM_MODIFY
)) ok( entry
.ptr
== expect_entry
.ptr
, "got ptr %p\n", entry
.ptr
);
1991 else ok( entry
.ptr
!= expect_entry
.ptr
, "got unexpected ptr %p\n", entry
.ptr
);
1992 ok( entry
.flags
== expect_entry
.flags
, "got flags %#Ix was %#Ix\n", entry
.flags
, expect_entry
.flags
);
1994 size
= GlobalSize( mem
);
1995 if (flags
& (GMEM_DISCARDABLE
| GMEM_MODIFY
)) ok( size
== small_size
, "GlobalSize returned %Iu\n", size
);
1996 else ok( size
== 512, "GlobalSize returned %Iu\n", size
);
1998 mem
= GlobalFree( mem
);
1999 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
2002 mem
= pGlobalAlloc( GMEM_MOVEABLE
, small_size
);
2003 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
2004 ok( is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
2005 expect_entry
= *mem_entry_from_HANDLE( mem
);
2007 tmp_mem
= GlobalReAlloc( mem
, 10, flags
);
2008 if (flags
& GMEM_MODIFY
) ok( tmp_mem
== mem
, "GlobalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
2009 else if (flags
& GMEM_DISCARDABLE
) ok( !tmp_mem
, "GlobalReAlloc succeeded\n" );
2010 else ok( tmp_mem
== mem
, "GlobalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
2011 entry
= *mem_entry_from_HANDLE( mem
);
2012 if ((flags
& GMEM_DISCARDABLE
) && (flags
& GMEM_MODIFY
)) expect_entry
.flags
|= 4;
2013 ok( entry
.ptr
== expect_entry
.ptr
, "got ptr %p was %p\n", entry
.ptr
, expect_entry
.ptr
);
2014 ok( entry
.flags
== expect_entry
.flags
, "got flags %#Ix was %#Ix\n", entry
.flags
, expect_entry
.flags
);
2016 size
= GlobalSize( mem
);
2017 if (flags
& (GMEM_DISCARDABLE
| GMEM_MODIFY
)) ok( size
== small_size
, "GlobalSize returned %Iu\n", size
);
2018 else ok( size
== 10, "GlobalSize returned %Iu\n", size
);
2020 mem
= GlobalFree( mem
);
2021 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
2024 mem
= pGlobalAlloc( GMEM_MOVEABLE
, small_size
);
2025 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
2026 ok( is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
2027 expect_entry
= *mem_entry_from_HANDLE( mem
);
2029 tmp_mem
= GlobalReAlloc( mem
, 0, flags
);
2030 if (flags
& GMEM_MODIFY
) ok( tmp_mem
== mem
, "GlobalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
2031 else if (flags
== GMEM_FIXED
) ok( !tmp_mem
, "GlobalReAlloc succeeded\n" );
2032 else if (flags
& GMEM_DISCARDABLE
) ok( !tmp_mem
, "GlobalReAlloc succeeded\n" );
2033 else ok( tmp_mem
== mem
, "GlobalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
2034 entry
= *mem_entry_from_HANDLE( mem
);
2035 if (flags
== GMEM_MOVEABLE
)
2037 expect_entry
.flags
|= 8;
2038 expect_entry
.ptr
= NULL
;
2040 else if ((flags
& GMEM_DISCARDABLE
) && (flags
& GMEM_MODIFY
)) expect_entry
.flags
|= 4;
2041 ok( entry
.ptr
== expect_entry
.ptr
, "got ptr %p was %p\n", entry
.ptr
, expect_entry
.ptr
);
2042 ok( entry
.flags
== expect_entry
.flags
, "got flags %#Ix was %#Ix\n", entry
.flags
, expect_entry
.flags
);
2044 size
= GlobalSize( mem
);
2045 if (flags
== GMEM_MOVEABLE
) ok( size
== 0, "GlobalSize returned %Iu\n", size
);
2046 else ok( size
== small_size
, "GlobalSize returned %Iu\n", size
);
2048 mem
= GlobalFree( mem
);
2049 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
2051 winetest_pop_context();
2054 mem
= GlobalAlloc( GMEM_DDESHARE
, 100 );
2055 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
2056 ret
= GlobalUnlock( mem
);
2057 ok( ret
, "GlobalUnlock failed, error %lu\n", GetLastError() );
2058 ret
= GlobalUnlock( mem
);
2059 ok( ret
, "GlobalUnlock failed, error %lu\n", GetLastError() );
2061 memset( &walk_entry
, 0xcd, sizeof(walk_entry
) );
2062 walk_entry
.lpData
= NULL
;
2063 ret
= HeapLock( heap
);
2064 ok( ret
, "HeapLock failed, error %lu\n", GetLastError() );
2065 while ((ret
= HeapWalk( heap
, &walk_entry
)))
2067 ok( !(walk_entry
.wFlags
& PROCESS_HEAP_ENTRY_MOVEABLE
), "got PROCESS_HEAP_ENTRY_MOVEABLE\n" );
2068 ok( !(walk_entry
.wFlags
& PROCESS_HEAP_ENTRY_DDESHARE
), "got PROCESS_HEAP_ENTRY_DDESHARE\n" );
2070 ok( GetLastError() == ERROR_NO_MORE_ITEMS
, "got error %lu\n", GetLastError() );
2071 ret
= HeapUnlock( heap
);
2072 ok( ret
, "HeapUnlock failed, error %lu\n", GetLastError() );
2074 mem
= GlobalFree( mem
);
2075 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
2077 mem
= GlobalAlloc( GMEM_FIXED
, 100 );
2078 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
2079 ret
= GlobalUnlock( mem
);
2080 ok( ret
, "GlobalUnlock failed, error %lu\n", GetLastError() );
2081 tmp_mem
= GlobalHandle( mem
);
2082 ok( tmp_mem
== mem
, "GlobalHandle returned unexpected handle\n" );
2083 mem
= GlobalFree( mem
);
2084 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
2086 mem
= GlobalAlloc( GMEM_FIXED
, 0 );
2087 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
2088 size
= GlobalSize( mem
);
2089 ok( size
== 1, "GlobalSize returned %Iu\n", size
);
2090 mem
= GlobalFree( mem
);
2091 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
2093 /* trying to lock empty memory should give an error */
2094 mem
= GlobalAlloc( GMEM_MOVEABLE
| GMEM_ZEROINIT
, 0 );
2095 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
2096 SetLastError( 0xdeadbeef );
2097 ptr
= GlobalLock( mem
);
2098 ok( !ptr
, "GlobalLock succeeded\n" );
2099 ok( GetLastError() == ERROR_DISCARDED
, "got error %lu\n", GetLastError() );
2100 mem
= GlobalFree( mem
);
2101 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
2103 mem
= GlobalAlloc( 0, buffer_size
);
2104 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
2105 size
= GlobalSize( mem
);
2106 ok( size
>= buffer_size
, "GlobalSize returned %Iu, error %lu\n", size
, GetLastError() );
2107 mem
= GlobalFree( mem
);
2108 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
2110 mem
= GlobalAlloc( GMEM_ZEROINIT
, buffer_size
);
2111 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
2112 size
= GlobalSize( mem
);
2113 ok( size
>= buffer_size
, "GlobalSize returned %Iu, error %lu\n", size
, GetLastError() );
2114 ptr
= GlobalLock( mem
);
2115 ok( !!ptr
, "GlobalLock failed, error %lu\n", GetLastError() );
2116 ok( ptr
== mem
, "got ptr %p, expected %p\n", ptr
, mem
);
2117 ok( !memcmp( ptr
, zero_buffer
, buffer_size
), "GlobalAlloc didn't clear memory\n" );
2119 /* Check that we can change GMEM_FIXED to GMEM_MOVEABLE */
2120 mem
= GlobalReAlloc( mem
, 0, GMEM_MODIFY
| GMEM_MOVEABLE
);
2121 ok( !!mem
, "GlobalReAlloc failed, error %lu\n", GetLastError() );
2122 ok( mem
!= ptr
, "GlobalReAlloc returned unexpected handle\n" );
2123 size
= GlobalSize( mem
);
2124 ok( size
== buffer_size
, "GlobalSize returned %Iu, error %lu\n", size
, GetLastError() );
2126 ptr
= GlobalLock( mem
);
2127 ok( !!ptr
, "GlobalLock failed, error %lu\n", GetLastError() );
2128 ok( ptr
!= mem
, "got unexpected ptr %p\n", ptr
);
2129 ret
= GlobalUnlock( mem
);
2130 ok( !ret
, "GlobalUnlock succeeded, error %lu\n", GetLastError() );
2131 ok( GetLastError() == NO_ERROR
, "got error %lu\n", GetLastError() );
2133 tmp_mem
= GlobalReAlloc( mem
, 2 * buffer_size
, GMEM_MOVEABLE
| GMEM_ZEROINIT
);
2134 ok( !!tmp_mem
, "GlobalReAlloc failed\n" );
2135 ok( tmp_mem
== mem
|| broken( tmp_mem
!= mem
) /* happens sometimes?? */,
2136 "GlobalReAlloc returned unexpected handle\n" );
2139 size
= GlobalSize( mem
);
2140 ok( size
>= 2 * buffer_size
, "GlobalSize returned %Iu, error %lu\n", size
, GetLastError() );
2141 ptr
= GlobalLock( mem
);
2142 ok( !!ptr
, "GlobalLock failed, error %lu\n", GetLastError() );
2143 ok( ptr
!= mem
, "got unexpected ptr %p\n", ptr
);
2144 ok( !memcmp( ptr
, zero_buffer
, buffer_size
), "GlobalReAlloc didn't clear memory\n" );
2145 ok( !memcmp( ptr
+ buffer_size
, zero_buffer
, buffer_size
),
2146 "GlobalReAlloc didn't clear memory\n" );
2148 tmp_mem
= GlobalHandle( ptr
);
2149 ok( tmp_mem
== mem
, "GlobalHandle returned unexpected handle\n" );
2150 /* Check that we can't discard locked memory */
2151 SetLastError( 0xdeadbeef );
2152 tmp_mem
= GlobalDiscard( mem
);
2153 ok( !tmp_mem
, "GlobalDiscard succeeded\n" );
2154 ret
= GlobalUnlock( mem
);
2155 ok( !ret
, "GlobalUnlock succeeded, error %lu\n", GetLastError() );
2156 ok( GetLastError() == NO_ERROR
, "got error %lu\n", GetLastError() );
2158 tmp_mem
= GlobalDiscard( mem
);
2159 ok( tmp_mem
== mem
, "GlobalDiscard failed, error %lu\n", GetLastError() );
2160 mem
= GlobalFree( mem
);
2161 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
2163 for (i
= 0; i
< ARRAY_SIZE(flags_tests
); i
++)
2165 mem
= GlobalAlloc( flags_tests
[i
], 4 );
2166 ok( !!mem
, "GlobalAlloc failed, error %lu\n", GetLastError() );
2167 flags
= GlobalFlags( mem
);
2168 ok( !(flags
& ~(GMEM_DDESHARE
| GMEM_DISCARDABLE
)), "got flags %#x, error %lu\n", flags
, GetLastError() );
2169 mem
= GlobalFree( mem
);
2170 ok( !mem
, "GlobalFree failed, error %lu\n", GetLastError() );
2173 ptr
= HeapAlloc( GetProcessHeap(), 0, 16 );
2174 ok( !!ptr
, "HeapAlloc failed, error %lu\n", GetLastError() );
2175 SetLastError( 0xdeadbeef );
2176 tmp_mem
= GlobalHandle( ptr
);
2177 ok( !!tmp_mem
, "GlobalHandle failed, error %lu\n", GetLastError() );
2178 ok( tmp_mem
== ptr
, "GlobalHandle returned unexpected handle\n" );
2179 tmp_ptr
= (void *)0xdeadbeef;
2180 tmp_flags
= 0xdeadbeef;
2181 ret
= pRtlGetUserInfoHeap( GetProcessHeap(), 0, ptr
, (void **)&tmp_ptr
, &tmp_flags
);
2182 ok( ret
, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() );
2183 ok( tmp_ptr
== (void *)0xdeadbeef, "got user value %p\n", tmp_ptr
);
2184 ok( tmp_flags
== 0, "got user flags %#lx\n", tmp_flags
);
2185 ret
= HeapFree( GetProcessHeap(), 0, ptr
);
2186 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
2189 static void test_LocalAlloc(void)
2191 static const UINT flags_tests
[] =
2194 LMEM_FIXED
| LMEM_DISCARDABLE
,
2196 LMEM_MOVEABLE
| LMEM_NODISCARD
,
2197 LMEM_MOVEABLE
| LMEM_DISCARDABLE
,
2198 LMEM_MOVEABLE
| LMEM_DISCARDABLE
| LMEM_NOCOMPACT
| LMEM_NODISCARD
,
2200 static const UINT realloc_flags_tests
[] =
2203 LMEM_FIXED
| LMEM_MODIFY
,
2205 LMEM_MOVEABLE
| LMEM_MODIFY
,
2206 LMEM_MOVEABLE
| LMEM_DISCARDABLE
,
2207 LMEM_MOVEABLE
| LMEM_MODIFY
| LMEM_DISCARDABLE
,
2208 LMEM_MOVEABLE
| LMEM_DISCARDABLE
| LMEM_NOCOMPACT
| LMEM_NODISCARD
,
2209 LMEM_MOVEABLE
| LMEM_MODIFY
| LMEM_DISCARDABLE
| LMEM_NOCOMPACT
| LMEM_NODISCARD
,
2211 static const char zero_buffer
[100000] = {0};
2212 static const SIZE_T buffer_size
= ARRAY_SIZE(zero_buffer
);
2213 const HLOCAL invalid_mem
= LongToHandle( 0xdeadbee0 + sizeof(void *) );
2214 void *const invalid_ptr
= LongToHandle( 0xdeadbee0 );
2215 SIZE_T size
, small_size
= 12, nolfh_size
= 0x20000;
2216 HLOCAL locals
[0x10000];
2217 HLOCAL mem
, tmp_mem
;
2218 BYTE
*ptr
, *tmp_ptr
;
2223 mem
= LocalFree( 0 );
2224 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2225 mem
= LocalReAlloc( 0, 10, LMEM_MOVEABLE
);
2226 ok( !mem
, "LocalReAlloc succeeded\n" );
2228 for (i
= 0; i
< ARRAY_SIZE(locals
); ++i
)
2230 mem
= LocalAlloc( LMEM_MOVEABLE
| LMEM_DISCARDABLE
, 0 );
2231 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2235 SetLastError( 0xdeadbeef );
2236 mem
= LocalAlloc( LMEM_MOVEABLE
| LMEM_DISCARDABLE
, 0 );
2237 ok( !mem
, "LocalAlloc succeeded\n" );
2238 ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY
, "got error %lu\n", GetLastError() );
2239 SetLastError( 0xdeadbeef );
2240 mem
= GlobalAlloc( GMEM_MOVEABLE
| GMEM_DISCARDABLE
, 0 );
2241 ok( !mem
, "GlobalAlloc succeeded\n" );
2242 ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY
, "got error %lu\n", GetLastError() );
2244 mem
= LocalAlloc( LMEM_DISCARDABLE
, 0 );
2245 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2246 mem
= LocalFree( mem
);
2247 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2249 for (i
= 0; i
< ARRAY_SIZE(locals
); ++i
)
2251 mem
= LocalFree( locals
[i
] );
2252 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2255 /* make sure LFH is enabled for some small block size */
2256 for (i
= 0; i
< 0x12; i
++) locals
[i
] = pLocalAlloc( LMEM_FIXED
, small_size
);
2257 for (i
= 0; i
< 0x12; i
++) LocalFree( locals
[i
] );
2259 mem
= LocalAlloc( LMEM_MOVEABLE
, 0 );
2260 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2261 mem
= LocalReAlloc( mem
, 10, LMEM_MOVEABLE
);
2262 ok( !!mem
, "LocalReAlloc failed, error %lu\n", GetLastError() );
2263 size
= LocalSize( mem
);
2264 ok( size
>= 10 && size
<= 16, "LocalSize returned %Iu\n", size
);
2265 mem
= LocalReAlloc( mem
, 0, LMEM_MOVEABLE
);
2266 ok( !!mem
, "LocalReAlloc failed, error %lu\n", GetLastError() );
2267 size
= LocalSize( mem
);
2268 ok( size
== 0, "LocalSize returned %Iu\n", size
);
2269 mem
= LocalReAlloc( mem
, 10, LMEM_MOVEABLE
);
2270 ok( !!mem
, "LocalReAlloc failed, error %lu\n", GetLastError() );
2271 size
= LocalSize( mem
);
2272 ok( size
>= 10 && size
<= 16, "LocalSize returned %Iu\n", size
);
2273 tmp_mem
= pLocalFree( mem
);
2274 ok( !tmp_mem
, "LocalFree failed, error %lu\n", GetLastError() );
2275 size
= LocalSize( mem
);
2276 ok( size
== 0, "LocalSize returned %Iu\n", size
);
2278 mem
= LocalAlloc( LMEM_MOVEABLE
, 256 );
2279 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2280 ptr
= LocalLock( mem
);
2281 ok( !!ptr
, "LocalLock failed, error %lu\n", GetLastError() );
2282 ok( ptr
!= mem
, "got unexpected ptr %p\n", ptr
);
2283 tmp_mem
= LocalHandle( ptr
);
2284 ok( tmp_mem
== mem
, "LocalHandle returned unexpected handle\n" );
2285 flags
= LocalFlags( mem
);
2286 ok( flags
== 1, "LocalFlags returned %#x, error %lu\n", flags
, GetLastError() );
2287 tmp_ptr
= LocalLock( mem
);
2288 ok( !!tmp_ptr
, "LocalLock failed, error %lu\n", GetLastError() );
2289 ok( tmp_ptr
== ptr
, "got ptr %p, expected %p\n", tmp_ptr
, ptr
);
2290 flags
= LocalFlags( mem
);
2291 ok( flags
== 2, "LocalFlags returned %#x, error %lu\n", flags
, GetLastError() );
2292 ret
= LocalUnlock( mem
);
2293 ok( ret
, "LocalUnlock failed, error %lu\n", GetLastError() );
2294 flags
= LocalFlags( mem
);
2295 ok( flags
== 1, "LocalFlags returned %#x, error %lu\n", flags
, GetLastError() );
2296 SetLastError( 0xdeadbeef );
2297 ret
= LocalUnlock( mem
);
2298 ok( !ret
, "LocalUnlock succeeded\n" );
2299 ok( GetLastError() == ERROR_SUCCESS
, "got error %lu\n", GetLastError() );
2300 flags
= LocalFlags( mem
);
2301 ok( !flags
, "LocalFlags returned %#x, error %lu\n", flags
, GetLastError() );
2302 SetLastError( 0xdeadbeef );
2303 ret
= LocalUnlock( mem
);
2304 ok( !ret
, "LocalUnlock succeeded\n" );
2305 ok( GetLastError() == ERROR_NOT_LOCKED
, "got error %lu\n", GetLastError() );
2306 tmp_mem
= LocalFree( mem
);
2307 ok( !tmp_mem
, "LocalFree failed, error %lu\n", GetLastError() );
2309 /* freed handles are caught */
2310 mem
= LocalAlloc( LMEM_MOVEABLE
, 256 );
2311 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2312 tmp_mem
= pLocalFree( mem
);
2313 ok( !tmp_mem
, "LocalFree failed, error %lu\n", GetLastError() );
2314 SetLastError( 0xdeadbeef );
2315 tmp_mem
= pLocalFree( mem
);
2316 ok( tmp_mem
== mem
, "LocalFree succeeded\n" );
2317 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
2318 SetLastError( 0xdeadbeef );
2319 flags
= LocalFlags( mem
);
2320 ok( flags
== LMEM_INVALID_HANDLE
, "LocalFlags succeeded\n" );
2321 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
2322 SetLastError( 0xdeadbeef );
2323 size
= LocalSize( mem
);
2324 ok( size
== 0, "LocalSize succeeded\n" );
2325 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
2326 SetLastError( 0xdeadbeef );
2327 ptr
= LocalLock( mem
);
2328 ok( !ptr
, "LocalLock succeeded\n" );
2329 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
2330 SetLastError( 0xdeadbeef );
2331 ret
= LocalUnlock( mem
);
2332 ok( !ret
, "LocalUnlock succeeded\n" );
2333 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
2334 SetLastError( 0xdeadbeef );
2335 tmp_mem
= LocalReAlloc( mem
, 0, LMEM_MOVEABLE
);
2336 ok( !tmp_mem
, "LocalReAlloc succeeded\n" );
2337 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
2338 if (sizeof(void *) != 8) /* crashes on 64-bit */
2340 SetLastError( 0xdeadbeef );
2341 tmp_mem
= LocalHandle( mem
);
2342 ok( !tmp_mem
, "LocalHandle succeeded\n" );
2343 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
2346 /* invalid handles are caught */
2347 SetLastError( 0xdeadbeef );
2348 tmp_mem
= pLocalFree( invalid_mem
);
2349 ok( tmp_mem
== invalid_mem
, "LocalFree succeeded\n" );
2350 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
2351 SetLastError( 0xdeadbeef );
2352 flags
= LocalFlags( invalid_mem
);
2353 ok( flags
== LMEM_INVALID_HANDLE
, "LocalFlags succeeded\n" );
2354 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
2355 SetLastError( 0xdeadbeef );
2356 size
= LocalSize( invalid_mem
);
2357 ok( size
== 0, "LocalSize succeeded\n" );
2358 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
2359 SetLastError( 0xdeadbeef );
2360 ptr
= LocalLock( invalid_mem
);
2361 ok( !ptr
, "LocalLock succeeded\n" );
2362 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
2363 SetLastError( 0xdeadbeef );
2364 ret
= LocalUnlock( invalid_mem
);
2365 ok( !ret
, "LocalUnlock succeeded\n" );
2366 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
2367 SetLastError( 0xdeadbeef );
2368 tmp_mem
= LocalReAlloc( invalid_mem
, 0, LMEM_MOVEABLE
);
2369 ok( !tmp_mem
, "LocalReAlloc succeeded\n" );
2370 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
2371 if (sizeof(void *) != 8) /* crashes on 64-bit */
2373 SetLastError( 0xdeadbeef );
2374 tmp_mem
= LocalHandle( invalid_mem
);
2375 ok( !tmp_mem
, "LocalHandle succeeded\n" );
2376 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
2379 /* invalid pointers are caught */
2380 SetLastError( 0xdeadbeef );
2381 tmp_mem
= pLocalFree( invalid_ptr
);
2382 ok( tmp_mem
== invalid_ptr
, "LocalFree succeeded\n" );
2384 ok( GetLastError() == ERROR_NOACCESS
, "got error %lu\n", GetLastError() );
2385 SetLastError( 0xdeadbeef );
2386 flags
= LocalFlags( invalid_ptr
);
2388 ok( flags
== LMEM_INVALID_HANDLE
, "LocalFlags succeeded\n" );
2390 ok( GetLastError() == ERROR_NOACCESS
, "got error %lu\n", GetLastError() );
2391 SetLastError( 0xdeadbeef );
2392 size
= LocalSize( invalid_ptr
);
2393 ok( size
== 0, "LocalSize succeeded\n" );
2394 ok( GetLastError() == ERROR_INVALID_HANDLE
, "got error %lu\n", GetLastError() );
2395 SetLastError( 0xdeadbeef );
2396 ptr
= LocalLock( invalid_ptr
);
2397 ok( !ptr
, "LocalLock succeeded\n" );
2398 ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() );
2399 SetLastError( 0xdeadbeef );
2400 ret
= LocalUnlock( invalid_ptr
);
2401 ok( !ret
, "LocalUnlock succeeded\n" );
2402 ok( GetLastError() == ERROR_NOT_LOCKED
, "got error %lu\n", GetLastError() );
2403 SetLastError( 0xdeadbeef );
2404 tmp_mem
= LocalReAlloc( invalid_ptr
, 0, LMEM_MOVEABLE
);
2405 ok( !tmp_mem
, "LocalReAlloc succeeded\n" );
2407 ok( GetLastError() == ERROR_NOACCESS
, "got error %lu\n", GetLastError() );
2408 SetLastError( 0xdeadbeef );
2409 tmp_mem
= LocalHandle( invalid_ptr
);
2410 ok( !tmp_mem
, "LocalHandle succeeded\n" );
2412 ok( GetLastError() == ERROR_NOACCESS
, "got error %lu\n", GetLastError() );
2414 /* LMEM_FIXED block doesn't allow resize, though it succeeds with LMEM_MODIFY */
2415 mem
= LocalAlloc( LMEM_FIXED
, small_size
);
2416 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2417 tmp_mem
= LocalReAlloc( mem
, small_size
- 1, LMEM_MODIFY
);
2418 ok( !!tmp_mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2419 ok( tmp_mem
== mem
, "got ptr %p, expected %p\n", tmp_mem
, mem
);
2420 size
= LocalSize( mem
);
2421 ok( size
== small_size
, "LocalSize returned %Iu\n", size
);
2422 SetLastError( 0xdeadbeef );
2423 tmp_mem
= LocalReAlloc( mem
, small_size
, 0 );
2424 ok( !tmp_mem
, "LocalReAlloc succeeded\n" );
2425 ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY
, "got error %lu\n", GetLastError() );
2426 if (tmp_mem
) mem
= tmp_mem
;
2427 tmp_mem
= LocalReAlloc( mem
, 1024 * 1024, LMEM_MODIFY
);
2428 ok( !!tmp_mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2429 ok( tmp_mem
== mem
, "got ptr %p, expected %p\n", tmp_mem
, mem
);
2430 size
= LocalSize( mem
);
2431 ok( size
== small_size
, "LocalSize returned %Iu\n", size
);
2432 mem
= LocalFree( mem
);
2433 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2435 /* LMEM_FIXED block can be relocated with LMEM_MOVEABLE */
2436 mem
= LocalAlloc( LMEM_FIXED
, small_size
);
2437 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2438 tmp_mem
= LocalReAlloc( mem
, small_size
+ 1, LMEM_MOVEABLE
);
2439 ok( !!tmp_mem
, "LocalReAlloc failed, error %lu\n", GetLastError() );
2440 ok( tmp_mem
!= mem
, "LocalReAlloc didn't relocate memory\n" );
2441 ptr
= LocalLock( tmp_mem
);
2442 ok( !!ptr
, "LocalLock failed, error %lu\n", GetLastError() );
2443 ok( ptr
== tmp_mem
, "got ptr %p, expected %p\n", ptr
, tmp_mem
);
2444 tmp_mem
= LocalFree( tmp_mem
);
2445 ok( !tmp_mem
, "LocalFree failed, error %lu\n", GetLastError() );
2447 /* test LocalReAlloc flags / LocalLock / size combinations */
2449 for (i
= 0; i
< ARRAY_SIZE(realloc_flags_tests
); i
++)
2451 struct mem_entry expect_entry
, entry
;
2453 flags
= realloc_flags_tests
[i
];
2455 winetest_push_context( "flags %#x", flags
);
2457 mem
= pLocalAlloc( LMEM_FIXED
, small_size
);
2458 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2459 ok( !is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
2461 tmp_mem
= LocalReAlloc( mem
, 512, flags
);
2462 ok( !is_mem_entry( tmp_mem
), "unexpected moveable %p\n", tmp_mem
);
2463 if (flags
& LMEM_MODIFY
) ok( tmp_mem
== mem
, "LocalReAlloc returned %p\n", tmp_mem
);
2464 else if (flags
!= LMEM_MOVEABLE
) ok( !tmp_mem
, "LocalReAlloc succeeded\n" );
2465 else ok( tmp_mem
!= mem
, "LocalReAlloc returned %p\n", tmp_mem
);
2466 if (tmp_mem
) mem
= tmp_mem
;
2468 size
= LocalSize( mem
);
2469 if (flags
== LMEM_MOVEABLE
) ok( size
== 512, "LocalSize returned %Iu\n", size
);
2470 else ok( size
== small_size
, "LocalSize returned %Iu\n", size
);
2472 mem
= LocalFree( mem
);
2473 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2476 mem
= pLocalAlloc( LMEM_FIXED
, nolfh_size
);
2477 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2478 ok( !is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
2479 tmp_mem
= LocalReAlloc( mem
, nolfh_size
+ 512, flags
);
2480 ok( !is_mem_entry( tmp_mem
), "unexpected moveable %p\n", tmp_mem
);
2481 if (flags
& LMEM_MODIFY
) ok( tmp_mem
== mem
, "LocalReAlloc returned %p\n", tmp_mem
);
2482 else if (flags
& LMEM_DISCARDABLE
) ok( !tmp_mem
, "LocalReAlloc succeeded\n" );
2483 else ok( tmp_mem
== mem
, "LocalReAlloc returned %p\n", tmp_mem
);
2484 size
= LocalSize( mem
);
2485 if (flags
& (LMEM_DISCARDABLE
| LMEM_MODIFY
)) ok( size
== nolfh_size
, "LocalSize returned %Iu\n", size
);
2486 else ok( size
== nolfh_size
+ 512, "LocalSize returned %Iu\n", size
);
2487 mem
= LocalFree( mem
);
2488 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2491 mem
= pLocalAlloc( LMEM_FIXED
, small_size
);
2492 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2493 ok( !is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
2495 tmp_mem
= LocalReAlloc( mem
, 10, flags
);
2496 ok( !is_mem_entry( tmp_mem
), "unexpected moveable %p\n", tmp_mem
);
2497 if (flags
& LMEM_MODIFY
) ok( tmp_mem
== mem
, "LocalReAlloc returned %p\n", tmp_mem
);
2498 else if (flags
!= LMEM_MOVEABLE
) todo_wine_if(!flags
) ok( !tmp_mem
, "LocalReAlloc succeeded\n" );
2499 else todo_wine
ok( tmp_mem
!= mem
, "LocalReAlloc returned %p\n", tmp_mem
);
2500 if (tmp_mem
) mem
= tmp_mem
;
2502 size
= LocalSize( mem
);
2503 if (flags
== LMEM_MOVEABLE
) ok( size
== 10, "LocalSize returned %Iu\n", size
);
2504 else todo_wine_if(!flags
) ok( size
== small_size
, "LocalSize returned %Iu\n", size
);
2506 mem
= LocalFree( mem
);
2507 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2510 mem
= pLocalAlloc( LMEM_FIXED
, nolfh_size
);
2511 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2512 ok( !is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
2513 tmp_mem
= LocalReAlloc( mem
, 10, flags
);
2514 ok( !is_mem_entry( tmp_mem
), "unexpected moveable %p\n", tmp_mem
);
2515 if (flags
& LMEM_MODIFY
) ok( tmp_mem
== mem
, "LocalReAlloc returned %p\n", tmp_mem
);
2516 else if (flags
& LMEM_DISCARDABLE
) ok( !tmp_mem
, "LocalReAlloc succeeded\n" );
2517 else ok( tmp_mem
== mem
, "LocalReAlloc returned %p\n", tmp_mem
);
2518 size
= LocalSize( mem
);
2519 if (flags
& (LMEM_DISCARDABLE
| LMEM_MODIFY
)) ok( size
== nolfh_size
, "LocalSize returned %Iu\n", size
);
2520 else ok( size
== 10, "LocalSize returned %Iu\n", size
);
2521 mem
= LocalFree( mem
);
2522 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2525 mem
= pLocalAlloc( LMEM_FIXED
, small_size
);
2526 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2527 ok( !is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
2529 tmp_mem
= LocalReAlloc( mem
, 0, flags
);
2530 ok( !is_mem_entry( tmp_mem
), "unexpected moveable %p\n", tmp_mem
);
2531 if (flags
& LMEM_MODIFY
) ok( tmp_mem
== mem
, "LocalReAlloc returned %p\n", tmp_mem
);
2532 else if (flags
!= LMEM_MOVEABLE
) ok( !tmp_mem
, "LocalReAlloc succeeded\n" );
2533 else ok( tmp_mem
!= mem
, "LocalReAlloc returned %p\n", tmp_mem
);
2534 if (tmp_mem
) mem
= tmp_mem
;
2536 size
= LocalSize( mem
);
2537 if (flags
== LMEM_MOVEABLE
) ok( size
== 0 || broken( size
== 1 ) /* w7 */, "LocalSize returned %Iu\n", size
);
2538 else ok( size
== small_size
, "LocalSize returned %Iu\n", size
);
2540 mem
= LocalFree( mem
);
2541 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2544 mem
= pLocalAlloc( LMEM_FIXED
, nolfh_size
);
2545 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2546 ok( !is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
2547 tmp_mem
= LocalReAlloc( mem
, 0, flags
);
2548 ok( !is_mem_entry( tmp_mem
), "unexpected moveable %p\n", tmp_mem
);
2549 if (flags
& LMEM_MODIFY
) ok( tmp_mem
== mem
, "LocalReAlloc returned %p\n", tmp_mem
);
2550 else if (flags
& LMEM_DISCARDABLE
) ok( !tmp_mem
, "LocalReAlloc succeeded\n" );
2551 else ok( tmp_mem
== mem
, "LocalReAlloc returned %p\n", tmp_mem
);
2552 size
= LocalSize( mem
);
2553 if (flags
& (LMEM_DISCARDABLE
| LMEM_MODIFY
)) ok( size
== nolfh_size
, "LocalSize returned %Iu\n", size
);
2554 else ok( size
== 0 || broken( size
== 1 ) /* w7 */, "LocalSize returned %Iu\n", size
);
2555 mem
= LocalFree( mem
);
2556 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2559 mem
= pLocalAlloc( LMEM_MOVEABLE
, small_size
);
2560 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2561 ok( is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
2562 ptr
= LocalLock( mem
);
2563 ok( !!ptr
, "LocalLock failed, error %lu\n", GetLastError() );
2564 expect_entry
= *mem_entry_from_HANDLE( mem
);
2566 tmp_mem
= LocalReAlloc( mem
, 512, flags
);
2567 if (flags
& LMEM_MODIFY
) ok( tmp_mem
== mem
, "LocalReAlloc returned %p\n", tmp_mem
);
2568 else if (flags
& LMEM_DISCARDABLE
) ok( !tmp_mem
, "LocalReAlloc succeeded\n" );
2569 else if (flags
& LMEM_MOVEABLE
) ok( tmp_mem
== mem
, "LocalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
2570 else ok( !tmp_mem
, "LocalReAlloc succeeded\n" );
2571 entry
= *mem_entry_from_HANDLE( mem
);
2572 if ((flags
& LMEM_DISCARDABLE
) && (flags
& LMEM_MODIFY
)) expect_entry
.flags
|= 4;
2573 if (flags
== LMEM_MOVEABLE
) ok( entry
.ptr
!= expect_entry
.ptr
, "got unexpected ptr %p\n", entry
.ptr
);
2574 else ok( entry
.ptr
== expect_entry
.ptr
, "got ptr %p\n", entry
.ptr
);
2575 ok( entry
.flags
== expect_entry
.flags
, "got flags %#Ix was %#Ix\n", entry
.flags
, expect_entry
.flags
);
2577 size
= LocalSize( mem
);
2578 if (flags
== LMEM_MOVEABLE
) ok( size
== 512, "LocalSize returned %Iu\n", size
);
2579 else ok( size
== small_size
, "LocalSize returned %Iu\n", size
);
2581 ret
= LocalUnlock( mem
);
2582 ok( !ret
, "LocalUnlock succeeded\n" );
2583 mem
= LocalFree( mem
);
2584 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2587 mem
= pLocalAlloc( LMEM_MOVEABLE
, nolfh_size
);
2588 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2589 ok( is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
2590 ptr
= LocalLock( mem
);
2591 ok( !!ptr
, "LocalLock failed, error %lu\n", GetLastError() );
2592 expect_entry
= *mem_entry_from_HANDLE( mem
);
2594 tmp_mem
= LocalReAlloc( mem
, nolfh_size
+ 512, flags
);
2595 if (flags
& LMEM_MODIFY
) ok( tmp_mem
== mem
, "LocalReAlloc returned %p\n", tmp_mem
);
2596 else if (flags
& LMEM_DISCARDABLE
) ok( !tmp_mem
, "LocalReAlloc succeeded\n" );
2597 else ok( tmp_mem
== mem
, "LocalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
2598 entry
= *mem_entry_from_HANDLE( mem
);
2599 if ((flags
& LMEM_DISCARDABLE
) && (flags
& LMEM_MODIFY
)) expect_entry
.flags
|= 4;
2600 ok( entry
.ptr
== expect_entry
.ptr
, "got ptr %p\n", entry
.ptr
);
2601 ok( entry
.flags
== expect_entry
.flags
, "got flags %#Ix was %#Ix\n", entry
.flags
, expect_entry
.flags
);
2603 size
= LocalSize( mem
);
2604 if (flags
& (LMEM_DISCARDABLE
| LMEM_MODIFY
)) ok( size
== nolfh_size
, "LocalSize returned %Iu\n", size
);
2605 else ok( size
== nolfh_size
+ 512, "LocalSize returned %Iu\n", size
);
2607 ret
= LocalUnlock( mem
);
2608 ok( !ret
, "LocalUnlock succeeded\n" );
2609 mem
= LocalFree( mem
);
2610 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2613 mem
= pLocalAlloc( LMEM_MOVEABLE
, small_size
);
2614 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2615 ok( is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
2616 ptr
= LocalLock( mem
);
2617 ok( !!ptr
, "LocalLock failed, error %lu\n", GetLastError() );
2618 expect_entry
= *mem_entry_from_HANDLE( mem
);
2620 tmp_mem
= LocalReAlloc( mem
, 10, flags
);
2621 if (flags
& LMEM_MODIFY
) ok( tmp_mem
== mem
, "LocalReAlloc returned %p\n", tmp_mem
);
2622 else if (flags
& LMEM_DISCARDABLE
) ok( !tmp_mem
, "LocalReAlloc succeeded\n" );
2623 else ok( tmp_mem
== mem
, "LocalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
2624 entry
= *mem_entry_from_HANDLE( mem
);
2625 if ((flags
& LMEM_DISCARDABLE
) && (flags
& LMEM_MODIFY
)) expect_entry
.flags
|= 4;
2626 ok( entry
.ptr
== expect_entry
.ptr
, "got ptr %p was %p\n", entry
.ptr
, expect_entry
.ptr
);
2627 ok( entry
.flags
== expect_entry
.flags
, "got flags %#Ix was %#Ix\n", entry
.flags
, expect_entry
.flags
);
2629 size
= LocalSize( mem
);
2630 if (flags
& (LMEM_DISCARDABLE
| LMEM_MODIFY
)) ok( size
== small_size
, "LocalSize returned %Iu\n", size
);
2631 else ok( size
== 10, "LocalSize returned %Iu\n", size
);
2633 ret
= LocalUnlock( mem
);
2634 ok( !ret
, "LocalUnlock succeeded\n" );
2635 mem
= LocalFree( mem
);
2636 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2639 mem
= pLocalAlloc( LMEM_MOVEABLE
, nolfh_size
);
2640 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2641 ok( is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
2642 ptr
= LocalLock( mem
);
2643 ok( !!ptr
, "LocalLock failed, error %lu\n", GetLastError() );
2644 expect_entry
= *mem_entry_from_HANDLE( mem
);
2646 tmp_mem
= LocalReAlloc( mem
, 10, flags
);
2647 if (flags
& LMEM_MODIFY
) ok( tmp_mem
== mem
, "LocalReAlloc returned %p\n", tmp_mem
);
2648 else if (flags
& LMEM_DISCARDABLE
) ok( !tmp_mem
, "LocalReAlloc succeeded\n" );
2649 else ok( tmp_mem
== mem
, "LocalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
2650 entry
= *mem_entry_from_HANDLE( mem
);
2651 if ((flags
& LMEM_DISCARDABLE
) && (flags
& LMEM_MODIFY
)) expect_entry
.flags
|= 4;
2652 ok( entry
.ptr
== expect_entry
.ptr
, "got ptr %p was %p\n", entry
.ptr
, expect_entry
.ptr
);
2653 ok( entry
.flags
== expect_entry
.flags
, "got flags %#Ix was %#Ix\n", entry
.flags
, expect_entry
.flags
);
2655 size
= LocalSize( mem
);
2656 if (flags
& (LMEM_DISCARDABLE
| LMEM_MODIFY
)) ok( size
== nolfh_size
, "LocalSize returned %Iu\n", size
);
2657 else ok( size
== 10, "LocalSize returned %Iu\n", size
);
2659 ret
= LocalUnlock( mem
);
2660 ok( !ret
, "LocalUnlock succeeded\n" );
2661 mem
= LocalFree( mem
);
2662 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2665 mem
= pLocalAlloc( LMEM_MOVEABLE
, small_size
);
2666 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2667 ok( is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
2668 ptr
= LocalLock( mem
);
2669 ok( !!ptr
, "LocalLock failed, error %lu\n", GetLastError() );
2670 expect_entry
= *mem_entry_from_HANDLE( mem
);
2672 tmp_mem
= LocalReAlloc( mem
, 0, flags
);
2673 if (flags
& LMEM_MODIFY
) ok( tmp_mem
== mem
, "LocalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
2674 else ok( !tmp_mem
, "LocalReAlloc succeeded\n" );
2675 entry
= *mem_entry_from_HANDLE( mem
);
2676 if ((flags
& LMEM_DISCARDABLE
) && (flags
& LMEM_MODIFY
)) expect_entry
.flags
|= 4;
2677 ok( entry
.ptr
== expect_entry
.ptr
, "got ptr %p was %p\n", entry
.ptr
, expect_entry
.ptr
);
2678 ok( entry
.flags
== expect_entry
.flags
, "got flags %#Ix was %#Ix\n", entry
.flags
, expect_entry
.flags
);
2680 size
= LocalSize( mem
);
2681 ok( size
== small_size
, "LocalSize returned %Iu\n", size
);
2683 ret
= LocalUnlock( mem
);
2684 ok( !ret
, "LocalUnlock succeeded\n" );
2685 mem
= LocalFree( mem
);
2686 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2689 mem
= pLocalAlloc( LMEM_MOVEABLE
, nolfh_size
);
2690 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2691 ok( is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
2692 ptr
= LocalLock( mem
);
2693 ok( !!ptr
, "LocalLock failed, error %lu\n", GetLastError() );
2694 expect_entry
= *mem_entry_from_HANDLE( mem
);
2696 tmp_mem
= LocalReAlloc( mem
, 0, flags
);
2697 if (flags
& LMEM_MODIFY
) ok( tmp_mem
== mem
, "LocalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
2698 else ok( !tmp_mem
, "LocalReAlloc succeeded\n" );
2699 entry
= *mem_entry_from_HANDLE( mem
);
2700 if ((flags
& LMEM_DISCARDABLE
) && (flags
& LMEM_MODIFY
)) expect_entry
.flags
|= 4;
2701 ok( entry
.ptr
== expect_entry
.ptr
, "got ptr %p was %p\n", entry
.ptr
, expect_entry
.ptr
);
2702 ok( entry
.flags
== expect_entry
.flags
, "got flags %#Ix was %#Ix\n", entry
.flags
, expect_entry
.flags
);
2704 size
= LocalSize( mem
);
2705 ok( size
== nolfh_size
, "LocalSize returned %Iu\n", size
);
2707 ret
= LocalUnlock( mem
);
2708 ok( !ret
, "LocalUnlock succeeded\n" );
2709 mem
= LocalFree( mem
);
2710 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2713 mem
= pLocalAlloc( LMEM_MOVEABLE
, small_size
);
2714 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2715 ok( is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
2716 expect_entry
= *mem_entry_from_HANDLE( mem
);
2718 tmp_mem
= LocalReAlloc( mem
, 512, flags
);
2719 if (flags
& LMEM_MODIFY
) ok( tmp_mem
== mem
, "LocalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
2720 else if (flags
& LMEM_DISCARDABLE
) ok( !tmp_mem
, "LocalReAlloc succeeded\n" );
2721 else ok( tmp_mem
== mem
, "LocalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
2722 entry
= *mem_entry_from_HANDLE( mem
);
2723 if ((flags
& LMEM_DISCARDABLE
) && (flags
& LMEM_MODIFY
)) expect_entry
.flags
|= 4;
2724 if (flags
& (LMEM_DISCARDABLE
| LMEM_MODIFY
)) ok( entry
.ptr
== expect_entry
.ptr
, "got ptr %p\n", entry
.ptr
);
2725 else ok( entry
.ptr
!= expect_entry
.ptr
, "got unexpected ptr %p\n", entry
.ptr
);
2726 ok( entry
.flags
== expect_entry
.flags
, "got flags %#Ix was %#Ix\n", entry
.flags
, expect_entry
.flags
);
2728 size
= LocalSize( mem
);
2729 if (flags
& (LMEM_DISCARDABLE
| LMEM_MODIFY
)) ok( size
== small_size
, "LocalSize returned %Iu\n", size
);
2730 else ok( size
== 512, "LocalSize returned %Iu\n", size
);
2732 mem
= LocalFree( mem
);
2733 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2736 mem
= pLocalAlloc( LMEM_MOVEABLE
, nolfh_size
);
2737 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2738 ok( is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
2739 expect_entry
= *mem_entry_from_HANDLE( mem
);
2741 tmp_mem
= LocalReAlloc( mem
, nolfh_size
+ 512, flags
);
2742 if (flags
& LMEM_MODIFY
) ok( tmp_mem
== mem
, "LocalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
2743 else if (flags
& LMEM_DISCARDABLE
) ok( !tmp_mem
, "LocalReAlloc succeeded\n" );
2744 else ok( tmp_mem
== mem
, "LocalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
2745 entry
= *mem_entry_from_HANDLE( mem
);
2746 if ((flags
& LMEM_DISCARDABLE
) && (flags
& LMEM_MODIFY
)) expect_entry
.flags
|= 4;
2747 ok( entry
.ptr
== expect_entry
.ptr
, "got unexpected ptr %p\n", entry
.ptr
);
2748 ok( entry
.flags
== expect_entry
.flags
, "got flags %#Ix was %#Ix\n", entry
.flags
, expect_entry
.flags
);
2750 size
= LocalSize( mem
);
2751 if (flags
& (LMEM_DISCARDABLE
| LMEM_MODIFY
)) ok( size
== nolfh_size
, "LocalSize returned %Iu\n", size
);
2752 else ok( size
== nolfh_size
+ 512, "LocalSize returned %Iu\n", size
);
2754 mem
= LocalFree( mem
);
2755 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2758 mem
= pLocalAlloc( LMEM_MOVEABLE
, small_size
);
2759 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2760 ok( is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
2761 expect_entry
= *mem_entry_from_HANDLE( mem
);
2763 tmp_mem
= LocalReAlloc( mem
, 10, flags
);
2764 if (flags
& LMEM_MODIFY
) ok( tmp_mem
== mem
, "LocalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
2765 else if (flags
& LMEM_DISCARDABLE
) ok( !tmp_mem
, "LocalReAlloc succeeded\n" );
2766 else ok( tmp_mem
== mem
, "LocalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
2767 entry
= *mem_entry_from_HANDLE( mem
);
2768 if ((flags
& LMEM_DISCARDABLE
) && (flags
& LMEM_MODIFY
)) expect_entry
.flags
|= 4;
2769 ok( entry
.ptr
== expect_entry
.ptr
, "got ptr %p was %p\n", entry
.ptr
, expect_entry
.ptr
);
2770 ok( entry
.flags
== expect_entry
.flags
, "got flags %#Ix was %#Ix\n", entry
.flags
, expect_entry
.flags
);
2772 size
= LocalSize( mem
);
2773 if (flags
& (LMEM_DISCARDABLE
| LMEM_MODIFY
)) ok( size
== small_size
, "LocalSize returned %Iu\n", size
);
2774 else ok( size
== 10, "LocalSize returned %Iu\n", size
);
2776 mem
= LocalFree( mem
);
2777 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2780 mem
= pLocalAlloc( LMEM_MOVEABLE
, nolfh_size
);
2781 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2782 ok( is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
2783 expect_entry
= *mem_entry_from_HANDLE( mem
);
2785 tmp_mem
= LocalReAlloc( mem
, 10, flags
);
2786 if (flags
& LMEM_MODIFY
) ok( tmp_mem
== mem
, "LocalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
2787 else if (flags
& LMEM_DISCARDABLE
) ok( !tmp_mem
, "LocalReAlloc succeeded\n" );
2788 else ok( tmp_mem
== mem
, "LocalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
2789 entry
= *mem_entry_from_HANDLE( mem
);
2790 if ((flags
& LMEM_DISCARDABLE
) && (flags
& LMEM_MODIFY
)) expect_entry
.flags
|= 4;
2791 ok( entry
.ptr
== expect_entry
.ptr
, "got ptr %p was %p\n", entry
.ptr
, expect_entry
.ptr
);
2792 ok( entry
.flags
== expect_entry
.flags
, "got flags %#Ix was %#Ix\n", entry
.flags
, expect_entry
.flags
);
2794 size
= LocalSize( mem
);
2795 if (flags
& (LMEM_DISCARDABLE
| LMEM_MODIFY
)) ok( size
== nolfh_size
, "LocalSize returned %Iu\n", size
);
2796 else ok( size
== 10, "LocalSize returned %Iu\n", size
);
2798 mem
= LocalFree( mem
);
2799 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2802 mem
= pLocalAlloc( LMEM_MOVEABLE
, small_size
);
2803 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2804 ok( is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
2805 expect_entry
= *mem_entry_from_HANDLE( mem
);
2807 tmp_mem
= LocalReAlloc( mem
, 0, flags
);
2808 if (flags
& LMEM_MODIFY
) ok( tmp_mem
== mem
, "LocalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
2809 else if (flags
== LMEM_FIXED
) ok( !tmp_mem
, "LocalReAlloc succeeded\n" );
2810 else if (flags
& LMEM_DISCARDABLE
) ok( !tmp_mem
, "LocalReAlloc succeeded\n" );
2811 else ok( tmp_mem
== mem
, "LocalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
2812 entry
= *mem_entry_from_HANDLE( mem
);
2813 if (flags
== LMEM_MOVEABLE
)
2815 expect_entry
.flags
|= 8;
2816 expect_entry
.ptr
= NULL
;
2818 else if ((flags
& LMEM_DISCARDABLE
) && (flags
& LMEM_MODIFY
)) expect_entry
.flags
|= 4;
2819 ok( entry
.ptr
== expect_entry
.ptr
, "got ptr %p was %p\n", entry
.ptr
, expect_entry
.ptr
);
2820 ok( entry
.flags
== expect_entry
.flags
, "got flags %#Ix was %#Ix\n", entry
.flags
, expect_entry
.flags
);
2822 size
= LocalSize( mem
);
2823 if (flags
== LMEM_MOVEABLE
) ok( size
== 0, "LocalSize returned %Iu\n", size
);
2824 else ok( size
== small_size
, "LocalSize returned %Iu\n", size
);
2826 mem
= LocalFree( mem
);
2827 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2830 mem
= pLocalAlloc( LMEM_MOVEABLE
, nolfh_size
);
2831 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2832 ok( is_mem_entry( mem
), "unexpected moveable %p\n", mem
);
2833 expect_entry
= *mem_entry_from_HANDLE( mem
);
2835 tmp_mem
= LocalReAlloc( mem
, 0, flags
);
2836 if (flags
& LMEM_MODIFY
) ok( tmp_mem
== mem
, "LocalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
2837 else if (flags
== LMEM_FIXED
) ok( !tmp_mem
, "LocalReAlloc succeeded\n" );
2838 else if (flags
& LMEM_DISCARDABLE
) ok( !tmp_mem
, "LocalReAlloc succeeded\n" );
2839 else ok( tmp_mem
== mem
, "LocalReAlloc returned %p, error %lu\n", tmp_mem
, GetLastError() );
2840 entry
= *mem_entry_from_HANDLE( mem
);
2841 if (flags
== LMEM_MOVEABLE
)
2843 expect_entry
.flags
|= 8;
2844 expect_entry
.ptr
= NULL
;
2846 else if ((flags
& LMEM_DISCARDABLE
) && (flags
& LMEM_MODIFY
)) expect_entry
.flags
|= 4;
2847 ok( entry
.ptr
== expect_entry
.ptr
, "got ptr %p was %p\n", entry
.ptr
, expect_entry
.ptr
);
2848 ok( entry
.flags
== expect_entry
.flags
, "got flags %#Ix was %#Ix\n", entry
.flags
, expect_entry
.flags
);
2850 size
= LocalSize( mem
);
2851 if (flags
== LMEM_MOVEABLE
) ok( size
== 0, "LocalSize returned %Iu\n", size
);
2852 else ok( size
== nolfh_size
, "LocalSize returned %Iu\n", size
);
2854 mem
= LocalFree( mem
);
2855 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2857 winetest_pop_context();
2860 mem
= LocalAlloc( LMEM_FIXED
, 100 );
2861 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2862 SetLastError( 0xdeadbeef );
2863 ret
= LocalUnlock( mem
);
2864 ok( !ret
, "LocalUnlock succeeded\n" );
2865 ok( GetLastError() == ERROR_NOT_LOCKED
, "got error %lu\n", GetLastError() );
2866 tmp_mem
= LocalHandle( mem
);
2867 ok( tmp_mem
== mem
, "LocalHandle returned unexpected handle\n" );
2868 mem
= LocalFree( mem
);
2869 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2871 mem
= LocalAlloc( LMEM_FIXED
, 0 );
2872 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2873 SetLastError( 0xdeadbeef );
2874 size
= LocalSize( mem
);
2875 ok( size
== 0, "LocalSize returned %Iu\n", size
);
2876 mem
= LocalFree( mem
);
2877 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2879 /* trying to lock empty memory should give an error */
2880 mem
= LocalAlloc( LMEM_MOVEABLE
| LMEM_ZEROINIT
, 0 );
2881 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2882 SetLastError( 0xdeadbeef );
2883 ptr
= LocalLock( mem
);
2884 ok( !ptr
, "LocalLock succeeded\n" );
2885 ok( GetLastError() == ERROR_DISCARDED
, "got error %lu\n", GetLastError() );
2886 mem
= LocalFree( mem
);
2887 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2889 mem
= LocalAlloc( 0, buffer_size
);
2890 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2891 size
= LocalSize( mem
);
2892 ok( size
>= buffer_size
, "LocalSize returned %Iu, error %lu\n", size
, GetLastError() );
2893 mem
= LocalFree( mem
);
2894 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2896 mem
= LocalAlloc( LMEM_ZEROINIT
, buffer_size
);
2897 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2898 size
= LocalSize( mem
);
2899 ok( size
>= buffer_size
, "LocalSize returned %Iu, error %lu\n", size
, GetLastError() );
2900 ptr
= LocalLock( mem
);
2901 ok( !!ptr
, "LocalLock failed, error %lu\n", GetLastError() );
2902 ok( ptr
== mem
, "got ptr %p, expected %p\n", ptr
, mem
);
2903 ok( !memcmp( ptr
, zero_buffer
, buffer_size
), "LocalAlloc didn't clear memory\n" );
2905 /* Check that we cannot change LMEM_FIXED to LMEM_MOVEABLE */
2906 mem
= LocalReAlloc( mem
, 0, LMEM_MODIFY
| LMEM_MOVEABLE
);
2907 ok( !!mem
, "LocalReAlloc failed, error %lu\n", GetLastError() );
2908 ok( mem
== ptr
, "LocalReAlloc returned unexpected handle\n" );
2909 size
= LocalSize( mem
);
2910 ok( size
== buffer_size
, "LocalSize returned %Iu, error %lu\n", size
, GetLastError() );
2912 ptr
= LocalLock( mem
);
2913 ok( !!ptr
, "LocalLock failed, error %lu\n", GetLastError() );
2914 ok( ptr
== mem
, "got unexpected ptr %p\n", ptr
);
2915 ret
= LocalUnlock( mem
);
2916 ok( !ret
, "LocalUnlock succeeded, error %lu\n", GetLastError() );
2917 ok( GetLastError() == ERROR_NOT_LOCKED
, "got error %lu\n", GetLastError() );
2919 tmp_mem
= LocalReAlloc( mem
, 2 * buffer_size
, LMEM_MOVEABLE
| LMEM_ZEROINIT
);
2920 ok( !!tmp_mem
, "LocalReAlloc failed\n" );
2921 ok( tmp_mem
== mem
|| broken( tmp_mem
!= mem
) /* happens sometimes?? */,
2922 "LocalReAlloc returned unexpected handle\n" );
2925 size
= LocalSize( mem
);
2926 ok( size
>= 2 * buffer_size
, "LocalSize returned %Iu, error %lu\n", size
, GetLastError() );
2927 ptr
= LocalLock( mem
);
2928 ok( !!ptr
, "LocalLock failed, error %lu\n", GetLastError() );
2929 ok( ptr
== mem
, "got unexpected ptr %p\n", ptr
);
2930 ok( !memcmp( ptr
, zero_buffer
, buffer_size
), "LocalReAlloc didn't clear memory\n" );
2931 ok( !memcmp( ptr
+ buffer_size
, zero_buffer
, buffer_size
),
2932 "LocalReAlloc didn't clear memory\n" );
2934 tmp_mem
= LocalHandle( ptr
);
2935 ok( tmp_mem
== mem
, "LocalHandle returned unexpected handle\n" );
2936 tmp_mem
= LocalDiscard( mem
);
2937 ok( !!tmp_mem
, "LocalDiscard failed, error %lu\n", GetLastError() );
2938 ok( tmp_mem
== mem
, "LocalDiscard returned unexpected handle\n" );
2939 ret
= LocalUnlock( mem
);
2940 ok( !ret
, "LocalUnlock succeeded, error %lu\n", GetLastError() );
2941 ok( GetLastError() == ERROR_NOT_LOCKED
, "got error %lu\n", GetLastError() );
2943 tmp_mem
= LocalDiscard( mem
);
2944 ok( tmp_mem
== mem
, "LocalDiscard failed, error %lu\n", GetLastError() );
2945 mem
= LocalFree( mem
);
2946 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2948 for (i
= 0; i
< ARRAY_SIZE(flags_tests
); i
++)
2950 mem
= LocalAlloc( flags_tests
[i
], 4 );
2951 ok( !!mem
, "LocalAlloc failed, error %lu\n", GetLastError() );
2952 flags
= LocalFlags( mem
);
2953 ok( !(flags
& ~LMEM_DISCARDABLE
), "got flags %#x, error %lu\n", flags
, GetLastError() );
2954 mem
= LocalFree( mem
);
2955 ok( !mem
, "LocalFree failed, error %lu\n", GetLastError() );
2958 ptr
= HeapAlloc( GetProcessHeap(), 0, 16 );
2959 ok( !!ptr
, "HeapAlloc failed, error %lu\n", GetLastError() );
2960 SetLastError( 0xdeadbeef );
2961 tmp_mem
= LocalHandle( ptr
);
2962 ok( !!tmp_mem
, "LocalHandle failed, error %lu\n", GetLastError() );
2963 ok( tmp_mem
== ptr
, "LocalHandle returned unexpected handle\n" );
2964 tmp_ptr
= (void *)0xdeadbeef;
2965 tmp_flags
= 0xdeadbeef;
2966 ret
= pRtlGetUserInfoHeap( GetProcessHeap(), 0, ptr
, (void **)&tmp_ptr
, &tmp_flags
);
2967 ok( ret
, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() );
2968 ok( tmp_ptr
== (void *)0xdeadbeef, "got user value %p\n", tmp_ptr
);
2969 ok( tmp_flags
== 0, "got user flags %#lx\n", tmp_flags
);
2970 ret
= HeapFree( GetProcessHeap(), 0, ptr
);
2971 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
2974 static void test_block_layout( HANDLE heap
, DWORD global_flags
, DWORD heap_flags
, DWORD alloc_flags
)
2976 DWORD padd_flags
= HEAP_VALIDATE
| HEAP_VALIDATE_ALL
| HEAP_VALIDATE_PARAMS
;
2977 SIZE_T expect_size
, diff
, alloc_size
, extra_size
, tail_size
= 0;
2978 unsigned char *ptr0
, *ptr1
, *ptr2
, tail
;
2979 char tail_buf
[64], padd_buf
[64];
2980 void *tmp_ptr
, **user_ptr
;
2985 if (global_flags
& (FLG_HEAP_DISABLE_COALESCING
|FLG_HEAP_PAGE_ALLOCS
|FLG_POOL_ENABLE_TAGGING
|
2986 FLG_HEAP_ENABLE_TAGGING
|FLG_HEAP_ENABLE_TAG_BY_DLL
))
2988 skip( "skipping block tests\n" );
2992 if (!global_flags
&& !alloc_flags
) extra_size
= 8;
2993 else extra_size
= 2 * sizeof(void *);
2994 if (heap_flags
& HEAP_TAIL_CHECKING_ENABLED
) extra_size
+= 2 * sizeof(void *);
2995 if (heap_flags
& padd_flags
) extra_size
+= 2 * sizeof(void *);
2997 if ((heap_flags
& HEAP_TAIL_CHECKING_ENABLED
)) tail_size
= 2 * sizeof(void *);
2998 memset( tail_buf
, 0xab, sizeof(tail_buf
) );
2999 memset( padd_buf
, 0, sizeof(padd_buf
) );
3001 for (alloc_size
= 0x20000 * sizeof(void *) - 0x3000; alloc_size
> 0; alloc_size
>>= 1)
3003 winetest_push_context( "size %#Ix", alloc_size
);
3005 ptr0
= pHeapAlloc( heap
, alloc_flags
|HEAP_ZERO_MEMORY
, alloc_size
);
3006 ok( !!ptr0
, "HeapAlloc failed, error %lu\n", GetLastError() );
3007 ptr1
= pHeapAlloc( heap
, alloc_flags
|HEAP_ZERO_MEMORY
, alloc_size
);
3008 ok( !!ptr1
, "HeapAlloc failed, error %lu\n", GetLastError() );
3009 ptr2
= pHeapAlloc( heap
, alloc_flags
|HEAP_ZERO_MEMORY
, alloc_size
);
3010 ok( !!ptr2
, "HeapAlloc failed, error %lu\n", GetLastError() );
3012 align
= (UINT_PTR
)ptr0
| (UINT_PTR
)ptr1
| (UINT_PTR
)ptr2
;
3013 ok( !(align
& (2 * sizeof(void *) - 1)), "wrong align\n" );
3015 expect_size
= max( alloc_size
, 2 * sizeof(void *) );
3016 expect_size
= ALIGN_BLOCK_SIZE( expect_size
+ extra_size
);
3017 diff
= min( llabs( ptr2
- ptr1
), llabs( ptr1
- ptr0
) );
3018 todo_wine_if( (!global_flags
&& alloc_size
< 2 * sizeof(void *)) ||
3019 ((heap_flags
& HEAP_FREE_CHECKING_ENABLED
) && diff
>= 0x100000) )
3020 ok( diff
== expect_size
, "got diff %#Ix exp %#Ix\n", diff
, expect_size
);
3021 ok( !memcmp( ptr0
+ alloc_size
, tail_buf
, tail_size
), "missing block tail\n" );
3022 ok( !memcmp( ptr1
+ alloc_size
, tail_buf
, tail_size
), "missing block tail\n" );
3023 ok( !memcmp( ptr2
+ alloc_size
, tail_buf
, tail_size
), "missing block tail\n" );
3025 ret
= HeapFree( heap
, 0, ptr2
);
3026 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
3027 ret
= HeapFree( heap
, 0, ptr1
);
3028 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
3029 ret
= HeapFree( heap
, 0, ptr0
);
3030 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
3032 winetest_pop_context();
3034 if (diff
!= expect_size
)
3037 win_skip("skipping sizes\n");
3043 /* between the two thresholds, tail may still be set but block position is inconsistent */
3045 alloc_size
= 0x20000 * sizeof(void *) - 0x2000;
3046 winetest_push_context( "size %#Ix", alloc_size
);
3048 ptr0
= pHeapAlloc( heap
, alloc_flags
|HEAP_ZERO_MEMORY
, alloc_size
);
3049 ok( !!ptr0
, "HeapAlloc failed, error %lu\n", GetLastError() );
3050 ok( !((UINT_PTR
)ptr0
& (2 * sizeof(void *) - 1)), "got unexpected ptr align\n" );
3052 ok( !memcmp( ptr0
+ alloc_size
, tail_buf
, tail_size
), "missing block tail\n" );
3054 ret
= HeapFree( heap
, 0, ptr0
);
3055 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
3057 winetest_pop_context();
3060 for (alloc_size
= 0x20000 * sizeof(void *) - 0x1000; alloc_size
< 0x800000; alloc_size
<<= 1)
3062 winetest_push_context( "size %#Ix", alloc_size
);
3064 ptr0
= pHeapAlloc( heap
, alloc_flags
|HEAP_ZERO_MEMORY
, alloc_size
);
3065 ok( !!ptr0
, "HeapAlloc failed, error %lu\n", GetLastError() );
3066 ptr1
= pHeapAlloc( heap
, alloc_flags
, alloc_size
);
3067 ok( !!ptr1
, "HeapAlloc failed, error %lu\n", GetLastError() );
3068 ptr2
= pHeapAlloc( heap
, alloc_flags
, alloc_size
);
3069 ok( !!ptr2
, "HeapAlloc failed, error %lu\n", GetLastError() );
3071 align
= (UINT_PTR
)ptr0
| (UINT_PTR
)ptr1
| (UINT_PTR
)ptr2
;
3072 ok( !(align
& (8 * sizeof(void *) - 1)), "wrong align\n" );
3074 expect_size
= max( alloc_size
, 2 * sizeof(void *) );
3075 expect_size
= ALIGN_BLOCK_SIZE( expect_size
+ extra_size
);
3076 diff
= min( llabs( ptr2
- ptr1
), llabs( ptr1
- ptr0
) );
3077 todo_wine_if( alloc_size
== 0x7efe9 )
3078 ok( diff
> expect_size
, "got diff %#Ix\n", diff
);
3080 tail
= ptr0
[alloc_size
] | ptr1
[alloc_size
] | ptr2
[alloc_size
];
3081 ok( !tail
, "got tail\n" );
3083 ret
= HeapFree( heap
, 0, ptr2
);
3084 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
3085 ret
= HeapFree( heap
, 0, ptr1
);
3086 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
3087 ret
= HeapFree( heap
, 0, ptr0
);
3088 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
3089 winetest_pop_context();
3091 if (diff
== expect_size
|| (align
& (8 * sizeof(void *) - 1)) || tail
)
3094 win_skip("skipping sizes\n");
3099 /* Undocumented HEAP_ADD_USER_INFO flag can be used to force an additional padding
3100 * on small block sizes. Small block use it to store user info, larger blocks
3101 * store them in their block header instead.
3103 * RtlGetUserInfoHeap also requires the flag to work consistently, and otherwise
3104 * causes crashes when heap flags are used, or on 32-bit.
3106 if (!(heap_flags
& padd_flags
))
3108 alloc_size
= 0x1000;
3109 winetest_push_context( "size %#Ix", alloc_size
);
3110 ptr0
= pHeapAlloc( heap
, 0xc00|HEAP_ADD_USER_INFO
, alloc_size
);
3111 ok( !!ptr0
, "HeapAlloc failed, error %lu\n", GetLastError() );
3112 ptr1
= HeapAlloc( heap
, 0x200|HEAP_ADD_USER_INFO
, alloc_size
);
3113 ok( !!ptr1
, "HeapAlloc failed, error %lu\n", GetLastError() );
3114 ptr2
= HeapAlloc( heap
, HEAP_ADD_USER_INFO
, alloc_size
);
3115 ok( !!ptr2
, "HeapAlloc failed, error %lu\n", GetLastError() );
3117 expect_size
= max( alloc_size
, 2 * sizeof(void *) );
3118 expect_size
= ALIGN_BLOCK_SIZE( expect_size
+ extra_size
+ 2 * sizeof(void *) );
3119 diff
= min( llabs( ptr2
- ptr1
), llabs( ptr1
- ptr0
) );
3120 ok( diff
== expect_size
, "got diff %#Ix\n", diff
);
3122 ok( !memcmp( ptr0
+ alloc_size
, tail_buf
, tail_size
), "missing block tail\n" );
3123 ok( !memcmp( ptr1
+ alloc_size
, tail_buf
, tail_size
), "missing block tail\n" );
3124 ok( !memcmp( ptr2
+ alloc_size
, tail_buf
, tail_size
), "missing block tail\n" );
3126 ok( !memcmp( ptr0
+ alloc_size
+ tail_size
, padd_buf
, 2 * sizeof(void *) ), "unexpected padding\n" );
3128 tmp_ptr
= (void *)0xdeadbeef;
3129 tmp_flags
= 0xdeadbeef;
3130 ret
= pRtlGetUserInfoHeap( heap
, 0, ptr0
, (void **)&tmp_ptr
, &tmp_flags
);
3131 ok( ret
, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() );
3132 ok( tmp_ptr
== NULL
, "got ptr %p\n", tmp_ptr
);
3133 ok( tmp_flags
== 0xc00, "got flags %#lx\n", tmp_flags
);
3135 tmp_ptr
= (void *)0xdeadbeef;
3136 tmp_flags
= 0xdeadbeef;
3137 ret
= pRtlGetUserInfoHeap( heap
, 0, ptr1
, (void **)&tmp_ptr
, &tmp_flags
);
3138 ok( ret
, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() );
3139 ok( tmp_ptr
== NULL
, "got ptr %p\n", tmp_ptr
);
3140 ok( tmp_flags
== 0x200, "got flags %#lx\n", tmp_flags
);
3142 ret
= pRtlSetUserValueHeap( heap
, 0, ptr0
, (void *)0xdeadbeef );
3143 ok( ret
, "RtlSetUserValueHeap failed, error %lu\n", GetLastError() );
3144 SetLastError( 0xdeadbeef );
3145 ret
= pRtlSetUserFlagsHeap( heap
, 0, ptr0
, 0, 0x1000 );
3146 ok( !ret
, "RtlSetUserFlagsHeap succeeded\n" );
3147 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "got error %lu\n", GetLastError() );
3148 SetLastError( 0xdeadbeef );
3149 ret
= pRtlSetUserFlagsHeap( heap
, 0, ptr0
, 0x100, 0 );
3150 ok( !ret
, "RtlSetUserFlagsHeap succeeded\n" );
3151 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "got error %lu\n", GetLastError() );
3152 ret
= pRtlSetUserFlagsHeap( heap
, 0, ptr0
, 0x400, 0x200 );
3153 ok( ret
, "RtlSetUserFlagsHeap failed, error %lu\n", GetLastError() );
3157 ret
= pRtlGetUserInfoHeap( heap
, 0, ptr0
, (void **)&tmp_ptr
, &tmp_flags
);
3158 ok( ret
, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() );
3159 ok( tmp_ptr
== (void *)0xdeadbeef, "got ptr %p\n", tmp_ptr
);
3160 ok( tmp_flags
== 0xa00 || broken(tmp_flags
== 0xc00) /* w1064v1507 */,
3161 "got flags %#lx\n", tmp_flags
);
3163 user_ptr
= (void **)(ptr0
+ alloc_size
+ tail_size
);
3164 ok( user_ptr
[1] == (void *)0xdeadbeef, "unexpected user value\n" );
3165 user_ptr
[0] = (void *)0xdeadbeef;
3166 user_ptr
[1] = (void *)0xdeadbee0;
3170 ret
= pRtlGetUserInfoHeap( heap
, 0, ptr0
, (void **)&tmp_ptr
, &tmp_flags
);
3171 ok( ret
, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() );
3172 ok( tmp_ptr
== (void *)0xdeadbee0, "got ptr %p\n", tmp_ptr
);
3173 ok( tmp_flags
== 0xa00 || broken(tmp_flags
== 0xc00) /* w1064v1507 */,
3174 "got flags %#lx\n", tmp_flags
);
3176 ret
= HeapFree( heap
, 0, ptr2
);
3177 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
3178 ret
= HeapFree( heap
, 0, ptr1
);
3179 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
3180 ret
= HeapFree( heap
, 0, ptr0
);
3181 ok( ret
, "HeapFree failed, error %lu\n", GetLastError() );
3182 winetest_pop_context();
3186 static void test_heap_checks( DWORD flags
)
3190 SIZE_T i
, size
, large_size
= 3000 * 1024 + 37;
3192 if (flags
& HEAP_PAGE_ALLOCS
) return; /* no tests for that case yet */
3194 p
= pHeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, 17 );
3195 ok( p
!= NULL
, "HeapAlloc failed\n" );
3197 ret
= HeapValidate( GetProcessHeap(), 0, p
);
3198 ok( ret
, "HeapValidate failed\n" );
3200 size
= HeapSize( GetProcessHeap(), 0, p
);
3201 ok( size
== 17, "Wrong size %Iu\n", size
);
3203 ok( p
[14] == 0, "wrong data %x\n", p
[14] );
3204 ok( p
[15] == 0, "wrong data %x\n", p
[15] );
3205 ok( p
[16] == 0, "wrong data %x\n", p
[16] );
3207 if (flags
& HEAP_TAIL_CHECKING_ENABLED
)
3209 ok( p
[17] == 0xab, "wrong padding %x\n", p
[17] );
3210 ok( p
[18] == 0xab, "wrong padding %x\n", p
[18] );
3211 ok( p
[19] == 0xab, "wrong padding %x\n", p
[19] );
3214 p2
= HeapReAlloc( GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY
, p
, 14 );
3217 if (flags
& HEAP_TAIL_CHECKING_ENABLED
)
3219 ok( p
[14] == 0xab, "wrong padding %x\n", p
[14] );
3220 ok( p
[15] == 0xab, "wrong padding %x\n", p
[15] );
3221 ok( p
[16] == 0xab, "wrong padding %x\n", p
[16] );
3225 ok( p
[14] == 0, "wrong padding %x\n", p
[14] );
3226 ok( p
[15] == 0, "wrong padding %x\n", p
[15] );
3229 else skip( "realloc in place failed\n");
3231 ret
= HeapFree( GetProcessHeap(), 0, p
);
3232 ok( ret
, "HeapFree failed\n" );
3234 p
= pHeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, 17 );
3235 ok( p
!= NULL
, "HeapAlloc failed\n" );
3239 if (flags
& HEAP_TAIL_CHECKING_ENABLED
)
3241 ret
= HeapValidate( GetProcessHeap(), 0, p
);
3242 ok( !ret
, "HeapValidate succeeded\n" );
3244 /* other calls only check when HEAP_VALIDATE is set */
3245 if (flags
& HEAP_VALIDATE
)
3247 size
= HeapSize( GetProcessHeap(), 0, p
);
3248 ok( size
== ~(SIZE_T
)0 || broken(size
== ~0u), "Wrong size %Iu\n", size
);
3250 p2
= HeapReAlloc( GetProcessHeap(), 0, p
, 14 );
3251 ok( p2
== NULL
, "HeapReAlloc succeeded\n" );
3253 ret
= HeapFree( GetProcessHeap(), 0, p
);
3254 ok( !ret
|| broken(sizeof(void*) == 8), /* not caught on xp64 */
3255 "HeapFree succeeded\n" );
3259 size
= HeapSize( GetProcessHeap(), 0, p
);
3260 ok( size
== 17, "Wrong size %Iu\n", size
);
3262 p2
= HeapReAlloc( GetProcessHeap(), 0, p
, 14 );
3263 ok( p2
!= NULL
, "HeapReAlloc failed\n" );
3267 ret
= HeapFree( GetProcessHeap(), 0, p
);
3268 ok( ret
, "HeapFree failed\n" );
3270 if (flags
& HEAP_FREE_CHECKING_ENABLED
)
3275 p
= pHeapAlloc( GetProcessHeap(), 0, size
);
3276 ok( !!p
, "HeapAlloc failed\n" );
3279 ok( p32
[0] == 0xbaadf00d, "got %#x\n", p32
[0] );
3280 memcpy( &tmp
, p
+ size
- 3, 3 );
3281 ok( tmp
!= 0xadf00d, "got %#x\n", tmp
);
3282 memset( p
, 0xcc, size
);
3285 p
= pHeapReAlloc( GetProcessHeap(), 0, p
, size
);
3286 ok( !!p
, "HeapReAlloc failed\n" );
3289 ok( p32
[0] == 0xcccccccc, "got %#x\n", p32
[0] );
3290 ok( p32
[1] << 8 == 0xcccccc00, "got %#x\n", p32
[1] );
3291 ok( p32
[2] == 0xbaadf00d, "got %#x\n", p32
[2] );
3292 memcpy( &tmp
, p
+ size
- 3, 3 );
3293 ok( tmp
!= 0xadf00d, "got %#x\n", tmp
);
3295 ret
= pHeapFree( GetProcessHeap(), 0, p
);
3296 ok( ret
, "failed.\n" );
3299 p
= HeapAlloc( GetProcessHeap(), 0, 37 );
3300 ok( p
!= NULL
, "HeapAlloc failed\n" );
3301 memset( p
, 0xcc, 37 );
3303 ret
= pHeapFree( GetProcessHeap(), 0, p
);
3304 ok( ret
, "HeapFree failed\n" );
3306 if (flags
& HEAP_FREE_CHECKING_ENABLED
)
3308 ok( p
[16] == 0xee, "wrong data %x\n", p
[16] );
3309 ok( p
[17] == 0xfe, "wrong data %x\n", p
[17] );
3310 ok( p
[18] == 0xee, "wrong data %x\n", p
[18] );
3311 ok( p
[19] == 0xfe, "wrong data %x\n", p
[19] );
3313 ret
= HeapValidate( GetProcessHeap(), 0, NULL
);
3314 ok( ret
, "HeapValidate failed\n" );
3318 ret
= HeapValidate( GetProcessHeap(), 0, NULL
);
3319 ok( !ret
, "HeapValidate succeeded\n" );
3322 ret
= HeapValidate( GetProcessHeap(), 0, NULL
);
3323 ok( ret
, "HeapValidate failed\n" );
3326 /* now test large blocks */
3328 p
= pHeapAlloc( GetProcessHeap(), 0, large_size
);
3329 ok( p
!= NULL
, "HeapAlloc failed\n" );
3331 ret
= HeapValidate( GetProcessHeap(), 0, p
);
3332 ok( ret
, "HeapValidate failed\n" );
3334 size
= HeapSize( GetProcessHeap(), 0, p
);
3335 ok( size
== large_size
, "Wrong size %Iu\n", size
);
3337 ok( p
[large_size
- 2] == 0, "wrong data %x\n", p
[large_size
- 2] );
3338 ok( p
[large_size
- 1] == 0, "wrong data %x\n", p
[large_size
- 1] );
3340 if (flags
& HEAP_TAIL_CHECKING_ENABLED
)
3342 /* Windows doesn't do tail checking on large blocks */
3343 ok( p
[large_size
] == 0, "wrong data %x\n", p
[large_size
] );
3344 ok( p
[large_size
+ 1] == 0, "wrong data %x\n", p
[large_size
+ 1] );
3345 ok( p
[large_size
+ 2] == 0, "wrong data %x\n", p
[large_size
+ 2] );
3348 ret
= HeapFree( GetProcessHeap(), 0, p
);
3349 ok( ret
, "HeapFree failed\n" );
3351 /* test block sizes when tail checking */
3352 if (flags
& HEAP_TAIL_CHECKING_ENABLED
)
3354 for (size
= 0; size
< 64; size
++)
3356 p
= HeapAlloc( GetProcessHeap(), 0, size
);
3357 for (i
= 0; i
< 32; i
++) if (p
[size
+ i
] != 0xab) break;
3358 ok( i
>= 8, "only %Iu tail bytes for size %Iu\n", i
, size
);
3359 HeapFree( GetProcessHeap(), 0, p
);
3364 static void test_debug_heap( const char *argv0
, DWORD flags
)
3366 char keyname
[MAX_PATH
];
3367 char buffer
[MAX_PATH
];
3368 PROCESS_INFORMATION info
;
3369 STARTUPINFOA startup
;
3373 const char *basename
;
3375 if ((basename
= strrchr( argv0
, '\\' ))) basename
++;
3376 else basename
= argv0
;
3378 sprintf( keyname
, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\%s",
3380 if (!strcmp( keyname
+ strlen(keyname
) - 3, ".so" )) keyname
[strlen(keyname
) - 3] = 0;
3382 err
= RegCreateKeyA( HKEY_LOCAL_MACHINE
, keyname
, &hkey
);
3383 if (err
== ERROR_ACCESS_DENIED
)
3385 skip("Not authorized to change the image file execution options\n");
3388 ok( !err
, "failed to create '%s' error %lu\n", keyname
, err
);
3391 if (flags
== 0xdeadbeef) /* magic value for unsetting it */
3392 RegDeleteValueA( hkey
, "GlobalFlag" );
3394 RegSetValueExA( hkey
, "GlobalFlag", 0, REG_DWORD
, (BYTE
*)&flags
, sizeof(flags
) );
3396 memset( &startup
, 0, sizeof(startup
) );
3397 startup
.cb
= sizeof(startup
);
3399 sprintf( buffer
, "%s heap.c 0x%lx", argv0
, flags
);
3400 ret
= CreateProcessA( NULL
, buffer
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &startup
, &info
);
3401 ok( ret
, "failed to create child process error %lu\n", GetLastError() );
3404 wait_child_process( info
.hProcess
);
3405 CloseHandle( info
.hThread
);
3406 CloseHandle( info
.hProcess
);
3408 RegDeleteValueA( hkey
, "GlobalFlag" );
3409 RegCloseKey( hkey
);
3410 RegDeleteKeyA( HKEY_LOCAL_MACHINE
, keyname
);
3413 static DWORD
heap_flags_from_global_flag( DWORD flag
)
3417 if (flag
& FLG_HEAP_ENABLE_TAIL_CHECK
)
3418 ret
|= HEAP_TAIL_CHECKING_ENABLED
;
3419 if (flag
& FLG_HEAP_ENABLE_FREE_CHECK
)
3420 ret
|= HEAP_FREE_CHECKING_ENABLED
;
3421 if (flag
& FLG_HEAP_VALIDATE_PARAMETERS
)
3422 ret
|= HEAP_VALIDATE_PARAMS
| HEAP_TAIL_CHECKING_ENABLED
| HEAP_FREE_CHECKING_ENABLED
;
3423 if (flag
& FLG_HEAP_VALIDATE_ALL
)
3424 ret
|= HEAP_VALIDATE_ALL
| HEAP_TAIL_CHECKING_ENABLED
| HEAP_FREE_CHECKING_ENABLED
;
3425 if (flag
& FLG_HEAP_DISABLE_COALESCING
)
3426 ret
|= HEAP_DISABLE_COALESCE_ON_FREE
;
3427 if (flag
& FLG_HEAP_PAGE_ALLOCS
)
3428 ret
|= HEAP_PAGE_ALLOCS
;
3432 static void test_heap_layout( HANDLE handle
, DWORD global_flag
, DWORD heap_flags
)
3434 DWORD force_flags
= heap_flags
& ~(HEAP_SHARED
|HEAP_DISABLE_COALESCE_ON_FREE
);
3435 struct heap
*heap
= handle
;
3437 if (global_flag
& FLG_HEAP_ENABLE_TAGGING
) heap_flags
|= HEAP_SHARED
;
3438 if (!(global_flag
& FLG_HEAP_PAGE_ALLOCS
)) force_flags
&= ~(HEAP_GROWABLE
|HEAP_PRIVATE
);
3440 ok( heap
->force_flags
== force_flags
, "got force_flags %#x\n", heap
->force_flags
);
3441 ok( heap
->flags
== heap_flags
, "got flags %#x\n", heap
->flags
);
3443 if (heap
->flags
& HEAP_PAGE_ALLOCS
)
3445 struct heap expect_heap
;
3446 memset( &expect_heap
, 0xee, sizeof(expect_heap
) );
3447 expect_heap
.force_flags
= heap
->force_flags
;
3448 expect_heap
.flags
= heap
->flags
;
3450 ok( !memcmp( heap
, &expect_heap
, sizeof(expect_heap
) ), "got unexpected data\n" );
3454 ok( heap
->ffeeffee
== 0xffeeffee, "got ffeeffee %#x\n", heap
->ffeeffee
);
3455 ok( heap
->auto_flags
== (heap_flags
& HEAP_GROWABLE
) || !heap
->auto_flags
,
3456 "got auto_flags %#x\n", heap
->auto_flags
);
3460 static void test_child_heap( const char *arg
)
3463 DWORD global_flags
= strtoul( arg
, 0, 16 ), type
, size
= sizeof(buffer
);
3469 if (global_flags
== 0xdeadbeef) /* global_flags value comes from Session Manager global flags */
3471 ret
= RegOpenKeyA( HKEY_LOCAL_MACHINE
, "SYSTEM\\CurrentControlSet\\Control\\Session Manager", &hkey
);
3474 skip( "Session Manager flags not set\n" );
3478 ret
= RegQueryValueExA( hkey
, "GlobalFlag", 0, &type
, (BYTE
*)buffer
, &size
);
3479 ok( ret
, "RegQueryValueExA failed, error %lu\n", GetLastError() );
3481 if (type
== REG_DWORD
) global_flags
= *(DWORD
*)buffer
;
3482 else if (type
== REG_SZ
) global_flags
= strtoul( buffer
, 0, 16 );
3484 ret
= RegCloseKey( hkey
);
3485 ok( ret
, "RegCloseKey failed, error %lu\n", GetLastError() );
3487 if (global_flags
&& !pRtlGetNtGlobalFlags()) /* not working on NT4 */
3489 win_skip( "global flags not set\n" );
3493 heap_flags
= heap_flags_from_global_flag( global_flags
);
3494 trace( "testing global flags %#lx, heap flags %08lx\n", global_flags
, heap_flags
);
3496 ok( pRtlGetNtGlobalFlags() == global_flags
, "got global flags %#lx\n", pRtlGetNtGlobalFlags() );
3498 test_heap_layout( GetProcessHeap(), global_flags
, heap_flags
|HEAP_GROWABLE
);
3500 heap
= HeapCreate( 0, 0, 0 );
3501 ok( heap
!= GetProcessHeap(), "got unexpected heap\n" );
3502 test_heap_layout( heap
, global_flags
, heap_flags
|HEAP_GROWABLE
|HEAP_PRIVATE
);
3503 ret
= HeapDestroy( heap
);
3504 ok( ret
, "HeapDestroy failed, error %lu\n", GetLastError() );
3506 heap
= HeapCreate( HEAP_NO_SERIALIZE
, 0, 0 );
3507 ok( heap
!= GetProcessHeap(), "got unexpected heap\n" );
3508 test_heap_layout( heap
, global_flags
, heap_flags
|HEAP_NO_SERIALIZE
|HEAP_GROWABLE
|HEAP_PRIVATE
);
3509 test_block_layout( heap
, global_flags
, heap_flags
|HEAP_NO_SERIALIZE
|HEAP_GROWABLE
|HEAP_PRIVATE
, 0 );
3510 ret
= HeapDestroy( heap
);
3511 ok( ret
, "HeapDestroy failed, error %lu\n", GetLastError() );
3513 heap
= HeapCreate( HEAP_TAIL_CHECKING_ENABLED
|HEAP_FREE_CHECKING_ENABLED
|HEAP_NO_SERIALIZE
, 0, 0 );
3514 ok( heap
!= GetProcessHeap(), "got unexpected heap\n" );
3515 test_heap_layout( heap
, global_flags
, heap_flags
|HEAP_NO_SERIALIZE
|HEAP_GROWABLE
|HEAP_PRIVATE
);
3516 ret
= HeapDestroy( heap
);
3517 ok( ret
, "HeapDestroy failed, error %lu\n", GetLastError() );
3519 heap
= HeapCreate( HEAP_NO_SERIALIZE
, 0, 0 );
3520 ok( heap
!= GetProcessHeap(), "got unexpected heap\n" );
3521 test_block_layout( heap
, global_flags
, heap_flags
|HEAP_NO_SERIALIZE
|HEAP_GROWABLE
|HEAP_PRIVATE
,
3522 HEAP_TAIL_CHECKING_ENABLED
|HEAP_FREE_CHECKING_ENABLED
);
3523 ret
= HeapDestroy( heap
);
3524 ok( ret
, "HeapDestroy failed, error %lu\n", GetLastError() );
3526 heap
= HeapCreate( 0, 0x1000, 0x10000 );
3527 ok( heap
!= GetProcessHeap(), "got unexpected heap\n" );
3528 test_heap_layout( heap
, global_flags
, heap_flags
|HEAP_PRIVATE
);
3529 ret
= HeapDestroy( heap
);
3530 ok( ret
, "HeapDestroy failed, error %lu\n", GetLastError() );
3532 heap
= HeapCreate( HEAP_SHARED
, 0, 0 );
3533 ok( heap
!= GetProcessHeap(), "got unexpected heap\n" );
3534 test_heap_layout( heap
, global_flags
, heap_flags
|HEAP_GROWABLE
|HEAP_PRIVATE
);
3535 ret
= HeapDestroy( heap
);
3536 ok( ret
, "HeapDestroy failed, error %lu\n", GetLastError() );
3538 test_heap_checks( heap_flags
);
3541 static void test_GetPhysicallyInstalledSystemMemory(void)
3543 MEMORYSTATUSEX memstatus
;
3544 ULONGLONG total_memory
;
3547 if (!pGetPhysicallyInstalledSystemMemory
)
3549 win_skip("GetPhysicallyInstalledSystemMemory is not available\n");
3553 SetLastError(0xdeadbeef);
3554 ret
= pGetPhysicallyInstalledSystemMemory(NULL
);
3555 ok(!ret
, "GetPhysicallyInstalledSystemMemory should fail\n");
3556 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
3557 "expected ERROR_INVALID_PARAMETER, got %lu\n", GetLastError());
3560 ret
= pGetPhysicallyInstalledSystemMemory(&total_memory
);
3561 ok(ret
, "GetPhysicallyInstalledSystemMemory unexpectedly failed (%lu)\n", GetLastError());
3562 ok(total_memory
!= 0, "expected total_memory != 0\n");
3564 memstatus
.dwLength
= sizeof(memstatus
);
3565 ret
= GlobalMemoryStatusEx(&memstatus
);
3566 ok(ret
, "GlobalMemoryStatusEx unexpectedly failed\n");
3567 ok(total_memory
>= memstatus
.ullTotalPhys
/ 1024,
3568 "expected total_memory >= memstatus.ullTotalPhys / 1024\n");
3571 static void test_GlobalMemoryStatus(void)
3573 char buffer
[sizeof(SYSTEM_PERFORMANCE_INFORMATION
) + 16]; /* some Win 7 versions need a larger info */
3574 SYSTEM_PERFORMANCE_INFORMATION
*perf_info
= (void *)buffer
;
3575 SYSTEM_BASIC_INFORMATION basic_info
;
3576 MEMORYSTATUSEX memex
= {0}, expect
;
3577 MEMORYSTATUS mem
= {0};
3582 SetLastError( 0xdeadbeef );
3583 ret
= GlobalMemoryStatusEx( &memex
);
3584 ok( !ret
, "GlobalMemoryStatusEx succeeded\n" );
3585 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "got error %lu\n", GetLastError() );
3586 SetLastError( 0xdeadbeef );
3587 GlobalMemoryStatus( &mem
);
3588 ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() );
3590 status
= NtQuerySystemInformation( SystemBasicInformation
, &basic_info
, sizeof(basic_info
), NULL
);
3591 ok( !status
, "NtQuerySystemInformation returned %#lx\n", status
);
3592 status
= NtQuerySystemInformation( SystemPerformanceInformation
, perf_info
, sizeof(buffer
), NULL
);
3593 ok( !status
, "NtQuerySystemInformation returned %#lx\n", status
);
3594 status
= NtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters
, &vmc
, sizeof(vmc
), NULL
);
3595 ok( !status
, "NtQueryInformationProcess returned %#lx\n", status
);
3596 mem
.dwLength
= sizeof(MEMORYSTATUS
);
3597 GlobalMemoryStatus( &mem
);
3598 memex
.dwLength
= sizeof(MEMORYSTATUSEX
);
3599 ret
= GlobalMemoryStatusEx( &memex
);
3600 ok( ret
, "GlobalMemoryStatusEx succeeded\n" );
3602 ok( basic_info
.PageSize
, "got 0 PageSize\n" );
3603 ok( basic_info
.MmNumberOfPhysicalPages
, "got 0 MmNumberOfPhysicalPages\n" );
3604 ok( !!basic_info
.HighestUserAddress
, "got 0 HighestUserAddress\n" );
3605 ok( !!basic_info
.LowestUserAddress
, "got 0 LowestUserAddress\n" );
3606 ok( perf_info
->TotalCommittedPages
, "got 0 TotalCommittedPages\n" );
3607 ok( perf_info
->TotalCommitLimit
, "got 0 TotalCommitLimit\n" );
3608 ok( perf_info
->AvailablePages
, "got 0 AvailablePages\n" );
3610 expect
.dwMemoryLoad
= (memex
.ullTotalPhys
- memex
.ullAvailPhys
) / (memex
.ullTotalPhys
/ 100);
3611 expect
.ullTotalPhys
= (ULONGLONG
)basic_info
.MmNumberOfPhysicalPages
* basic_info
.PageSize
;
3612 expect
.ullAvailPhys
= (ULONGLONG
)perf_info
->AvailablePages
* basic_info
.PageSize
;
3613 expect
.ullTotalPageFile
= (ULONGLONG
)perf_info
->TotalCommitLimit
* basic_info
.PageSize
;
3614 expect
.ullAvailPageFile
= (ULONGLONG
)(perf_info
->TotalCommitLimit
- perf_info
->TotalCommittedPages
) * basic_info
.PageSize
;
3615 expect
.ullTotalVirtual
= (ULONG_PTR
)basic_info
.HighestUserAddress
- (ULONG_PTR
)basic_info
.LowestUserAddress
+ 1;
3616 expect
.ullAvailVirtual
= expect
.ullTotalVirtual
- (ULONGLONG
)vmc
.WorkingSetSize
/* approximate */;
3617 expect
.ullAvailExtendedVirtual
= 0;
3619 /* allow some variability, info sources are not always in sync */
3620 #define IS_WITHIN_RANGE(a, b) (((a) - (b) + (256 * basic_info.PageSize)) <= (512 * basic_info.PageSize))
3622 ok( memex
.dwMemoryLoad
== expect
.dwMemoryLoad
, "got dwMemoryLoad %lu\n", memex
.dwMemoryLoad
);
3623 ok( memex
.ullTotalPhys
== expect
.ullTotalPhys
, "got ullTotalPhys %#I64x\n", memex
.ullTotalPhys
);
3624 ok( IS_WITHIN_RANGE( memex
.ullAvailPhys
, expect
.ullAvailPhys
), "got ullAvailPhys %#I64x\n", memex
.ullAvailPhys
);
3625 ok( memex
.ullTotalPageFile
== expect
.ullTotalPageFile
, "got ullTotalPageFile %#I64x\n", memex
.ullTotalPageFile
);
3626 ok( IS_WITHIN_RANGE( memex
.ullAvailPageFile
, expect
.ullAvailPageFile
), "got ullAvailPageFile %#I64x\n", memex
.ullAvailPageFile
);
3627 ok( memex
.ullTotalVirtual
== expect
.ullTotalVirtual
, "got ullTotalVirtual %#I64x\n", memex
.ullTotalVirtual
);
3628 ok( memex
.ullAvailVirtual
<= expect
.ullAvailVirtual
, "got ullAvailVirtual %#I64x\n", memex
.ullAvailVirtual
);
3629 ok( memex
.ullAvailExtendedVirtual
== 0, "got ullAvailExtendedVirtual %#I64x\n", memex
.ullAvailExtendedVirtual
);
3631 ok( mem
.dwMemoryLoad
== memex
.dwMemoryLoad
, "got dwMemoryLoad %lu\n", mem
.dwMemoryLoad
);
3632 ok( mem
.dwTotalPhys
== min( ~(SIZE_T
)0 >> 1, memex
.ullTotalPhys
) ||
3633 broken( mem
.dwTotalPhys
== ~(SIZE_T
)0 ) /* Win <= 8.1 with RAM size > 4GB */,
3634 "got dwTotalPhys %#Ix\n", mem
.dwTotalPhys
);
3635 ok( IS_WITHIN_RANGE( mem
.dwAvailPhys
, min( ~(SIZE_T
)0 >> 1, memex
.ullAvailPhys
) ) ||
3636 broken( mem
.dwAvailPhys
== ~(SIZE_T
)0 ) /* Win <= 8.1 with RAM size > 4GB */,
3637 "got dwAvailPhys %#Ix\n", mem
.dwAvailPhys
);
3639 todo_wine_if(memex
.ullTotalPageFile
> 0xfff7ffff)
3641 ok( mem
.dwTotalPageFile
== min( ~(SIZE_T
)0, memex
.ullTotalPageFile
), "got dwTotalPageFile %#Ix\n", mem
.dwTotalPageFile
);
3642 ok( IS_WITHIN_RANGE( mem
.dwAvailPageFile
, min( ~(SIZE_T
)0, memex
.ullAvailPageFile
) ), "got dwAvailPageFile %#Ix\n", mem
.dwAvailPageFile
);
3643 ok( mem
.dwTotalVirtual
== memex
.ullTotalVirtual
, "got dwTotalVirtual %#Ix\n", mem
.dwTotalVirtual
);
3644 ok( mem
.dwAvailVirtual
== memex
.ullAvailVirtual
, "got dwAvailVirtual %#Ix\n", mem
.dwAvailVirtual
);
3646 #undef IS_WITHIN_RANGE
3649 static void get_valloc_info( void *mem
, char **base
, SIZE_T
*alloc_size
)
3651 MEMORY_BASIC_INFORMATION info
, info2
;
3655 size
= VirtualQuery( mem
, &info
, sizeof(info
) );
3656 ok( size
== sizeof(info
), "got %Iu.\n", size
);
3659 p
= info
.AllocationBase
;
3662 size
= VirtualQuery( p
, &info2
, sizeof(info2
) );
3663 ok( size
== sizeof(info
), "got %Iu.\n", size
);
3664 if (info2
.AllocationBase
!= info
.AllocationBase
)
3666 ok( info2
.State
== MEM_RESERVE
|| info2
.State
== MEM_COMMIT
, "got %#lx.\n", info2
.State
);
3667 p
+= info2
.RegionSize
;
3670 *base
= info
.AllocationBase
;
3671 *alloc_size
= p
- *base
;
3674 static void test_heap_size( SIZE_T initial_size
)
3676 static const SIZE_T default_heap_size
= 0x10000, init_grow_size
= 0x100000, max_grow_size
= 0xfd0000;
3678 BOOL initial_subheap
= TRUE
, max_size_reached
= FALSE
;
3679 SIZE_T alloc_size
, current_subheap_size
;
3680 char *base
, *current_base
;
3685 winetest_push_context( "init size %#Ix", initial_size
);
3686 heap
= HeapCreate( HEAP_NO_SERIALIZE
, initial_size
, 0 );
3687 get_valloc_info( heap
, ¤t_base
, &alloc_size
);
3689 ok( alloc_size
== initial_size
+ default_heap_size
|| broken( (initial_size
&& alloc_size
== initial_size
)
3690 || (!initial_size
&& (alloc_size
== default_heap_size
* sizeof(void*))) ) /* Win7 */,
3691 "got %#Ix.\n", alloc_size
);
3693 current_subheap_size
= alloc_size
;
3694 for (i
= 0; i
< 100; ++i
)
3696 winetest_push_context( "i %u, current_subheap_size %#Ix", i
, current_subheap_size
);
3697 p
= HeapAlloc( heap
, 0, 0x60000 );
3698 get_valloc_info( p
, &base
, &alloc_size
);
3699 if (base
!= current_base
)
3701 current_base
= base
;
3702 if (initial_subheap
)
3704 current_subheap_size
= init_grow_size
;
3705 initial_subheap
= FALSE
;
3709 current_subheap_size
= min( current_subheap_size
* 2, max_grow_size
);
3710 if (current_subheap_size
== max_grow_size
)
3711 max_size_reached
= TRUE
;
3714 ok( alloc_size
== current_subheap_size
, "got %#Ix.\n", alloc_size
);
3715 winetest_pop_context();
3717 ok( max_size_reached
, "Did not reach maximum subheap size.\n" );
3719 HeapDestroy( heap
);
3720 winetest_pop_context();
3723 static void test_heap_sizes(void)
3725 test_heap_size( 0 );
3726 test_heap_size( 0x80000 );
3727 test_heap_size( 0x150000 );
3737 argc
= winetest_get_mainargs( &argv
);
3740 test_child_heap( argv
[2] );
3748 test_GetPhysicallyInstalledSystemMemory();
3749 test_GlobalMemoryStatus();
3751 if (pRtlGetNtGlobalFlags
)
3753 test_debug_heap( argv
[0], 0 );
3754 test_debug_heap( argv
[0], FLG_HEAP_ENABLE_TAIL_CHECK
);
3755 test_debug_heap( argv
[0], FLG_HEAP_ENABLE_FREE_CHECK
);
3756 test_debug_heap( argv
[0], FLG_HEAP_VALIDATE_PARAMETERS
);
3757 test_debug_heap( argv
[0], FLG_HEAP_VALIDATE_ALL
);
3758 test_debug_heap( argv
[0], FLG_POOL_ENABLE_TAGGING
);
3759 test_debug_heap( argv
[0], FLG_HEAP_ENABLE_TAGGING
);
3760 test_debug_heap( argv
[0], FLG_HEAP_ENABLE_TAG_BY_DLL
);
3761 test_debug_heap( argv
[0], FLG_HEAP_DISABLE_COALESCING
);
3762 test_debug_heap( argv
[0], FLG_HEAP_PAGE_ALLOCS
);
3763 test_debug_heap( argv
[0], 0xdeadbeef );
3765 else win_skip( "RtlGetNtGlobalFlags not found, skipping heap debug tests\n" );