ReactOS 0.4.16-dev-2207-geb15453
heap.c
Go to the documentation of this file.
1/*
2 * Unit test suite for heap functions
3 *
4 * Copyright 2002 Geoffrey Hausheer
5 * Copyright 2003 Dimitrie O. Paun
6 * Copyright 2006 Detlef Riekenberg
7 *
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.
12 *
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.
17 *
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
21 */
22
23#include <stdarg.h>
24#include <stdlib.h>
25#include <stdio.h>
26
27#include "windef.h"
28#include "winbase.h"
29#include "winreg.h"
30#include "winternl.h"
31#include "wine/test.h"
32
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
40
41#define BLOCK_ALIGN (2 * sizeof(void *) - 1)
42#define ALIGN_BLOCK_SIZE(x) (((x) + BLOCK_ALIGN) & ~BLOCK_ALIGN)
43
44/* use function pointers to avoid warnings for invalid parameter tests */
45static LPVOID (WINAPI *pHeapAlloc)(HANDLE,DWORD,SIZE_T);
46static LPVOID (WINAPI *pHeapReAlloc)(HANDLE,DWORD,LPVOID,SIZE_T);
47static BOOL (WINAPI *pHeapFree)(HANDLE,DWORD,LPVOID);
48static BOOL (WINAPI *pGetPhysicallyInstalledSystemMemory)( ULONGLONG * );
49static BOOLEAN (WINAPI *pRtlGetUserInfoHeap)(HANDLE,ULONG,void*,void**,ULONG*);
50static BOOLEAN (WINAPI *pRtlSetUserValueHeap)(HANDLE,ULONG,void*,void*);
51static BOOLEAN (WINAPI *pRtlSetUserFlagsHeap)(HANDLE,ULONG,void*,ULONG,ULONG);
52static HGLOBAL (WINAPI *pGlobalAlloc)(UINT,SIZE_T);
53static HGLOBAL (WINAPI *pGlobalFree)(HGLOBAL);
54static HGLOBAL (WINAPI *pLocalAlloc)(UINT,SIZE_T);
55static HGLOBAL (WINAPI *pLocalFree)(HLOCAL);
56static BOOL (WINAPI *pHeapQueryInformation)(HANDLE,HEAP_INFORMATION_CLASS,void*,SIZE_T,SIZE_T*);
57static BOOL (WINAPI *pHeapSetInformation)(HANDLE,HEAP_INFORMATION_CLASS,void*,SIZE_T);
58static UINT (WINAPI *pGlobalFlags)(HGLOBAL);
59static ULONG (WINAPI *pRtlGetNtGlobalFlags)(void);
60
61static void load_functions(void)
62{
63 HMODULE kernel32 = GetModuleHandleW( L"kernel32.dll" );
64 HMODULE ntdll = GetModuleHandleW( L"ntdll.dll" );
65
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 );
71 LOAD_FUNC( kernel32, HeapSetInformation );
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 );
82#undef LOAD_FUNC
83}
84
85struct heap
86{
95};
96
97
98/* undocumented RtlWalkHeap structure */
99
100struct rtl_heap_entry
101{
103 SIZE_T cbData; /* differs from PROCESS_HEAP_ENTRY */
106 WORD wFlags; /* value differs from PROCESS_HEAP_ENTRY */
107 union {
108 struct {
109 HANDLE hMem;
110 DWORD dwReserved[3];
112 struct {
118 };
119};
120
121/* rtl_heap_entry flags, names made up */
122
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
129
130
132{
136
140};
141
143{
144 struct heap_thread_params *params = arg;
145 void *ptr;
146 DWORD res;
147 BOOL ret;
148
149 SetEvent( params->ready_event );
150
151 while (!(res = WaitForSingleObject( params->start_event, INFINITE )) && !params->done)
152 {
153 if (params->lock)
154 {
155 ret = HeapLock( params->heap );
156 ok( ret, "HeapLock failed, error %lu\n", GetLastError() );
157 }
158
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() );
163
164 if (params->lock)
165 {
166 ret = HeapUnlock( params->heap );
167 ok( ret, "HeapUnlock failed, error %lu\n", GetLastError() );
168 }
169
170 SetEvent( params->ready_event );
171 }
172 ok( !res, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() );
173
174 return 0;
175}
176
177
178static void test_HeapCreate(void)
179{
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;
188 ULONG compat_info;
190 DWORD res;
191 BOOL ret;
192
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() );
201
202 heap_count = GetProcessHeaps( 0, NULL );
203 ok( heap_count <= 6, "GetProcessHeaps returned %lu\n", heap_count );
204
205 /* check heap alignment */
206
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" );
220 ok( heaps[heap_count + 0] == heap, "got wrong heap\n" );
222 ok( heaps[heap_count + 1] == heap1, "got wrong heap\n" );
223 ret = HeapDestroy( heap1 );
224 ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() );
225 ret = HeapDestroy( heap );
226 ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() );
227 count = GetProcessHeaps( 0, NULL );
228 ok( count == heap_count, "GetProcessHeaps returned %lu\n", count );
229
230 /* growable heap */
231
232 heap = HeapCreate( 0, 0, 0 );
233 ok( !!heap, "HeapCreate failed, error %lu\n", GetLastError() );
234 ok( !((ULONG_PTR)heap & 0xffff), "wrong heap alignment\n" );
235
236 /* test some border cases */
237
238 ret = HeapFree( NULL, 0, NULL );
239 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
240 ret = HeapFree( heap, 0, NULL );
241 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
242 if (0) /* crashes */
243 {
244 SetLastError( 0xdeadbeef );
245 ret = HeapFree( heap, 0, (void *)0xdeadbe00 );
246 ok( !ret, "HeapFree succeeded\n" );
247 ok( GetLastError() == ERROR_NOACCESS, "got error %lu\n", GetLastError() );
248 SetLastError( 0xdeadbeef );
249 ptr = (BYTE *)((UINT_PTR)buffer & ~63) + 64;
250 ret = HeapFree( heap, 0, ptr );
251 ok( !ret, "HeapFree succeeded\n" );
252 ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() );
253 }
254
255 SetLastError( 0xdeadbeef );
256 ptr = HeapReAlloc( heap, 0, NULL, 1 );
257 ok( !ptr, "HeapReAlloc succeeded\n" );
259 ok( GetLastError() == NO_ERROR, "got error %lu\n", GetLastError() );
260 if (0) /* crashes */
261 {
262 SetLastError( 0xdeadbeef );
263 ptr1 = HeapReAlloc( heap, 0, (void *)0xdeadbe00, 1 );
264 ok( !ptr1, "HeapReAlloc succeeded\n" );
265 ok( GetLastError() == ERROR_NOACCESS, "got error %lu\n", GetLastError() );
266 ret = HeapValidate( heap, 0, (void *)0xdeadbe00 );
267 ok( !ret, "HeapValidate succeeded\n" );
268 ok( GetLastError() == ERROR_NOACCESS, "got error %lu\n", GetLastError() );
269 SetLastError( 0xdeadbeef );
270 ptr = (BYTE *)((UINT_PTR)buffer & ~63) + 64;
271 ptr1 = HeapReAlloc( heap, 0, ptr, 1 );
272 ok( !ptr1, "HeapReAlloc succeeded\n" );
273 ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() );
274 }
275
276 SetLastError( 0xdeadbeef );
277 ret = HeapValidate( heap, 0, NULL );
278 ok( ret, "HeapValidate failed, error %lu\n", GetLastError() );
279 ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() );
280 ptr = (BYTE *)((UINT_PTR)buffer & ~63) + 64;
281 ret = HeapValidate( heap, 0, ptr );
282 ok( !ret, "HeapValidate succeeded\n" );
283 ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() );
284
285 ptr = HeapAlloc( heap, 0, 0 );
286 ok( !!ptr, "HeapAlloc failed, error %lu\n", GetLastError() );
287 size = HeapSize( heap, 0, ptr );
288 ok( size == 0, "HeapSize returned %#Ix, error %lu\n", size, GetLastError() );
289 ptr1 = pHeapReAlloc( heap, 0, ptr, ~(SIZE_T)0 - 7 );
290 ok( !ptr1, "HeapReAlloc succeeded\n" );
291 ptr1 = pHeapReAlloc( heap, 0, ptr, ~(SIZE_T)0 );
292 ok( !ptr1, "HeapReAlloc succeeded\n" );
293 ret = HeapValidate( heap, 0, ptr );
294 ok( ret, "HeapValidate failed, error %lu\n", GetLastError() );
295 ret = pHeapFree( heap, 0, ptr );
296 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
297 SetLastError( 0xdeadbeef );
298 ret = HeapValidate( heap, 0, ptr );
299 ok( !ret, "HeapValidate succeeded\n" );
300 ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() );
301
302 ptr = pHeapAlloc( heap, 0, ~(SIZE_T)0 );
303 ok( !ptr, "HeapAlloc succeeded\n" );
304
305 ptr = HeapAlloc( heap, 0, 1 );
306 ok( !!ptr, "HeapAlloc failed, error %lu\n", GetLastError() );
307 ptr1 = HeapReAlloc( heap, 0, ptr, 0 );
308 ok( !!ptr1, "HeapReAlloc failed, error %lu\n", GetLastError() );
309 size = HeapSize( heap, 0, ptr1 );
310 ok( size == 0, "HeapSize returned %#Ix, error %lu\n", size, GetLastError() );
311 ret = HeapFree( heap, 0, ptr );
312 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
313
314 ptr = HeapAlloc( heap, 0, 5 * alloc_size + 1 );
315 ok( !!ptr, "HeapAlloc failed, error %lu\n", GetLastError() );
316 ret = HeapFree( heap, 0, ptr );
317 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
318
319 ptr = HeapAlloc( heap, 0, alloc_size );
320 ok( !!ptr, "HeapAlloc failed, error %lu\n", GetLastError() );
321 size = HeapSize( heap, 0, ptr );
322 ok( size == alloc_size, "HeapSize returned %#Ix, error %lu\n", size, GetLastError() );
323 ptr1 = HeapAlloc( heap, 0, 4 * alloc_size );
324 ok( !!ptr1, "HeapAlloc failed, error %lu\n", GetLastError() );
325 ret = HeapFree( heap, 0, ptr1 );
326 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
327 ret = HeapFree( heap, 0, ptr );
328 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
329
330 /* test pointer alignment */
331
332 align = 0;
333 for (i = 0; i < ARRAY_SIZE(ptrs); ++i)
334 {
335 ptrs[i] = HeapAlloc( heap, 0, alloc_size );
336 ok( !!ptrs[i], "HeapAlloc failed, error %lu\n", GetLastError() );
337 align |= (UINT_PTR)ptrs[i];
338 }
339 ok( !(align & (2 * sizeof(void *) - 1)), "got wrong alignment\n" );
340 ok( align & (2 * sizeof(void *)), "got wrong alignment\n" );
341 for (i = 0; i < ARRAY_SIZE(ptrs); ++i)
342 {
343 ret = HeapFree( heap, 0, ptrs[i] );
344 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
345 }
346
347 align = 0;
348 for (i = 0; i < ARRAY_SIZE(ptrs); ++i)
349 {
350 ptrs[i] = HeapAlloc( heap, 0, 4 * alloc_size );
351 ok( !!ptrs[i], "HeapAlloc failed, error %lu\n", GetLastError() );
352 align |= (UINT_PTR)ptrs[i];
353 }
354 ok( !(align & (8 * sizeof(void *) - 1)), "got wrong alignment\n" );
355 ok( align & (8 * sizeof(void *)), "got wrong alignment\n" );
356 for (i = 0; i < ARRAY_SIZE(ptrs); ++i)
357 {
358 ret = HeapFree( heap, 0, ptrs[i] );
359 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
360 }
361
362 /* test HEAP_ZERO_MEMORY */
363
365 ok( !!ptr, "HeapAlloc failed, error %lu\n", GetLastError() );
366 size = HeapSize( heap, 0, ptr );
367 ok( size == 1, "HeapSize returned %#Ix, error %lu\n", size, GetLastError() );
368 while (size) if (ptr[--size]) break;
369 ok( !size && !ptr[0], "memory wasn't zeroed\n" );
370 ret = HeapFree( heap, 0, ptr );
371 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
372
373 ptr = HeapAlloc( heap, HEAP_ZERO_MEMORY, (1 << 20) );
374 ok( !!ptr, "HeapAlloc failed, error %lu\n", GetLastError() );
375 size = HeapSize( heap, 0, ptr );
376 ok( size == (1 << 20), "HeapSize returned %#Ix, error %lu\n", size, GetLastError() );
377 while (size) if (ptr[--size]) break;
378 ok( !size && !ptr[0], "memory wasn't zeroed\n" );
379 ret = HeapFree( heap, 0, ptr );
380 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
381
382 ptr = HeapAlloc( heap, HEAP_ZERO_MEMORY, alloc_size );
383 ok( !!ptr, "HeapAlloc failed, error %lu\n", GetLastError() );
384 size = HeapSize( heap, 0, ptr );
385 ok( size == alloc_size, "HeapSize returned %#Ix, error %lu\n", size, GetLastError() );
386 while (size) if (ptr[--size]) break;
387 ok( !size && !ptr[0], "memory wasn't zeroed\n" );
388
389 ptr = HeapReAlloc( heap, HEAP_ZERO_MEMORY, ptr, 3 * alloc_size );
390 ok( !!ptr, "HeapReAlloc failed, error %lu\n", GetLastError() );
391 size = HeapSize( heap, 0, ptr );
392 ok( size == 3 * alloc_size, "HeapSize returned %#Ix, error %lu\n", size, GetLastError() );
393 while (size) if (ptr[--size]) break;
394 ok( !size && !ptr[0], "memory wasn't zeroed\n" );
395
396 /* shrinking a small-ish block in place and growing back is okay */
397 ptr1 = HeapReAlloc( heap, HEAP_REALLOC_IN_PLACE_ONLY, ptr, alloc_size * 3 / 2 );
398 ok( ptr1 == ptr, "HeapReAlloc HEAP_REALLOC_IN_PLACE_ONLY failed, error %lu\n", GetLastError() );
399 ptr1 = HeapReAlloc( heap, HEAP_REALLOC_IN_PLACE_ONLY, ptr, 2 * alloc_size );
400 ok( ptr1 == ptr, "HeapReAlloc HEAP_REALLOC_IN_PLACE_ONLY failed, error %lu\n", GetLastError() );
401
403 ok( !!ptr, "HeapReAlloc failed, error %lu\n", GetLastError() );
404 size = HeapSize( heap, 0, ptr );
405 ok( size == 1, "HeapSize returned %#Ix, error %lu\n", size, GetLastError() );
406 while (size) if (ptr[--size]) break;
407 ok( !size && !ptr[0], "memory wasn't zeroed\n" );
408
409 ptr = HeapReAlloc( heap, HEAP_ZERO_MEMORY, ptr, (1 << 20) );
410 ok( !!ptr, "HeapReAlloc failed, error %lu\n", GetLastError() );
411 size = HeapSize( heap, 0, ptr );
412 ok( size == (1 << 20), "HeapSize returned %#Ix, error %lu\n", size, GetLastError() );
413 while (size) if (ptr[--size]) break;
414 ok( !size && !ptr[0], "memory wasn't zeroed\n" );
415
416 /* shrinking a very large block decommits pages and fail to grow in place */
417 ptr1 = HeapReAlloc( heap, HEAP_REALLOC_IN_PLACE_ONLY, ptr, alloc_size * 3 / 2 );
418 ok( ptr1 == ptr, "HeapReAlloc HEAP_REALLOC_IN_PLACE_ONLY failed, error %lu\n", GetLastError() );
419 SetLastError( 0xdeadbeef );
420 ptr1 = HeapReAlloc( heap, HEAP_REALLOC_IN_PLACE_ONLY, ptr, 2 * alloc_size );
422 ok( ptr1 != ptr, "HeapReAlloc HEAP_REALLOC_IN_PLACE_ONLY succeeded\n" );
424#ifdef __REACTOS__
425 ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY || broken(GetLastError() == 0xdeadbeef) /* WS03 */, "got error %lu\n", GetLastError() );
426#else
427 ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY, "got error %lu\n", GetLastError() );
428#endif
429
430 ret = HeapFree( heap, 0, ptr1 );
431 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
432
433 ret = HeapDestroy( heap );
434 ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() );
435
436
437 /* fixed size heaps */
438
439 heap = HeapCreate( 0, alloc_size, alloc_size );
440 ok( !!heap, "HeapCreate failed, error %lu\n", GetLastError() );
441 ok( !((ULONG_PTR)heap & 0xffff), "wrong heap alignment\n" );
442
443 /* threshold between failure and success varies, and w7pro64 has a much larger overhead. */
444
445#ifdef __REACTOS__
446 if (is_reactos()) {
447 ok(FALSE, "FIXME: The rest of this test crashes on ReactOS!\n");
448 return;
449 }
450#endif
451 ptr = HeapAlloc( heap, 0, alloc_size - (0x400 + 0x100 * sizeof(void *)) );
452 ok( !!ptr, "HeapAlloc failed, error %lu\n", GetLastError() );
453 size = HeapSize( heap, 0, ptr );
454 ok( size == alloc_size - (0x400 + 0x100 * sizeof(void *)),
455 "HeapSize returned %#Ix, error %lu\n", size, GetLastError() );
456 ret = HeapFree( heap, 0, ptr );
457 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
458
459 SetLastError( 0xdeadbeef );
460 ptr1 = HeapAlloc( heap, 0, alloc_size - (0x200 + 0x80 * sizeof(void *)) );
461 ok( !ptr1, "HeapAlloc succeeded\n" );
462 ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY, "got error %lu\n", GetLastError() );
463 ret = HeapFree( heap, 0, ptr1 );
464 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
465
466 ret = HeapDestroy( heap );
467 ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() );
468
469
470 heap = HeapCreate( 0, 8 * alloc_size, 8 * alloc_size );
471 ok( !!heap, "HeapCreate failed, error %lu\n", GetLastError() );
472 ok( !((ULONG_PTR)heap & 0xffff), "wrong heap alignment\n" );
473
474 ptr = HeapAlloc( heap, 0, 0 );
475 ok( !!ptr, "HeapAlloc failed, error %lu\n", GetLastError() );
476 size = HeapSize( heap, 0, ptr );
477 ok( size == 0, "HeapSize returned %#Ix, error %lu\n", size, GetLastError() );
478 ret = HeapFree( heap, 0, ptr );
479 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
480
481 /* cannot allocate large blocks from fixed size heap */
482
483 SetLastError( 0xdeadbeef );
484 ptr1 = HeapAlloc( heap, 0, 4 * alloc_size );
485 ok( !ptr1, "HeapAlloc succeeded\n" );
486#ifdef __REACTOS__
487 ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY || broken(GetLastError() == ERROR_INSUFFICIENT_BUFFER) /* WS03 */, "got error %lu\n", GetLastError() );
488#else
489 ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY, "got error %lu\n", GetLastError() );
490#endif
491 ret = HeapFree( heap, 0, ptr1 );
492 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
493
494 ptr = HeapAlloc( heap, 0, 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 SetLastError( 0xdeadbeef );
499 ptr1 = HeapAlloc( heap, 0, 4 * alloc_size );
500 ok( !ptr1, "HeapAlloc succeeded\n" );
501#ifdef __REACTOS__
502 ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY || broken(GetLastError() == ERROR_INSUFFICIENT_BUFFER) /* WS03 */, "got error %lu\n", GetLastError() );
503#else
504 ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY, "got error %lu\n", GetLastError() );
505#endif
506 ret = HeapFree( heap, 0, ptr1 );
507 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
508 ret = HeapFree( heap, 0, ptr );
509 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
510
511 ptr = HeapAlloc( heap, HEAP_ZERO_MEMORY, alloc_size );
512 ok( !!ptr, "HeapAlloc failed, error %lu\n", GetLastError() );
513 size = HeapSize( heap, 0, ptr );
514 ok( size == alloc_size, "HeapSize returned %#Ix, error %lu\n", size, GetLastError() );
515 while (size) if (ptr[--size]) break;
516 ok( !size && !ptr[0], "memory wasn't zeroed\n" );
517
518 ptr = HeapReAlloc( heap, HEAP_ZERO_MEMORY, ptr, 2 * alloc_size );
519 ok( !!ptr, "HeapReAlloc failed, error %lu\n", GetLastError() );
520 size = HeapSize( heap, 0, ptr );
521 ok( size == 2 * alloc_size, "HeapSize returned %#Ix, error %lu\n", size, GetLastError() );
522 while (size) if (ptr[--size]) break;
523 ok( !size && !ptr[0], "memory wasn't zeroed\n" );
524
525 ptr1 = HeapReAlloc( heap, HEAP_REALLOC_IN_PLACE_ONLY, ptr, alloc_size * 3 / 2 );
526 ok( ptr1 == ptr, "HeapReAlloc HEAP_REALLOC_IN_PLACE_ONLY failed, error %lu\n", GetLastError() );
527 ptr1 = HeapReAlloc( heap, HEAP_REALLOC_IN_PLACE_ONLY, ptr, 2 * alloc_size );
528 ok( ptr1 == ptr, "HeapReAlloc HEAP_REALLOC_IN_PLACE_ONLY failed, error %lu\n", GetLastError() );
529 ret = HeapFree( heap, 0, ptr1 );
530 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
531
532 ret = HeapDestroy( heap );
533 ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() );
534
535
536 heap = HeapCreate( 0, 0, 0 );
537 ok( !!heap, "HeapCreate failed, error %lu\n", GetLastError() );
538 ok( !((ULONG_PTR)heap & 0xffff), "wrong heap alignment\n" );
539
540 count = 0;
541 memset( &rtl_entries, 0, sizeof(rtl_entries) );
542 memset( &rtl_entry, 0xcd, sizeof(rtl_entry) );
543 rtl_entry.lpData = NULL;
544 SetLastError( 0xdeadbeef );
545 while (!RtlWalkHeap( heap, &rtl_entry )) rtl_entries[count++] = rtl_entry;
546#ifdef __REACTOS__
547 ok( count == 3 || broken(count == 4) /* WS03 */, "got count %lu\n", count );
548#else
549 ok( count == 3, "got count %lu\n", count );
550#endif
551
552 count = 0;
553 memset( &entries, 0, sizeof(entries) );
554 memset( &entry, 0xcd, sizeof(entry) );
555 entry.lpData = NULL;
556 SetLastError( 0xdeadbeef );
557 while ((ret = HeapWalk( heap, &entry ))) entries[count++] = entry;
558 ok( GetLastError() == ERROR_NO_MORE_ITEMS, "got error %lu\n", GetLastError() );
559#ifdef __REACTOS__
560 ok( count == 3 || broken(count == 4) /* WS03 */, "got count %lu\n", count );
561#else
562 ok( count == 3, "got count %lu\n", count );
563#endif
564
565 for (i = 0; i < count; ++i)
566 {
567 winetest_push_context( "%Iu", i );
568 ok( rtl_entries[i].lpData == entries[i].lpData, "got lpData %p\n", rtl_entries[i].lpData );
569 ok( rtl_entries[i].cbData == entries[i].cbData, "got cbData %#Ix\n", rtl_entries[i].cbData );
570 ok( rtl_entries[i].cbOverhead == entries[i].cbOverhead, "got cbOverhead %#x\n", rtl_entries[i].cbOverhead );
571 ok( rtl_entries[i].iRegionIndex == entries[i].iRegionIndex, "got iRegionIndex %#x\n", rtl_entries[i].iRegionIndex );
572 if (!entries[i].wFlags)
573 ok( rtl_entries[i].wFlags == 0, "got wFlags %#x\n", rtl_entries[i].wFlags );
574 else if (entries[i].wFlags & PROCESS_HEAP_ENTRY_BUSY)
575#ifdef __REACTOS__
576 ok( rtl_entries[i].wFlags == (RTL_HEAP_ENTRY_COMMITTED|RTL_HEAP_ENTRY_BLOCK|RTL_HEAP_ENTRY_BUSY) || broken(rtl_entries[i].wFlags == 0x411) /* win7 */ || broken(rtl_entries[i].wFlags == RTL_HEAP_ENTRY_BUSY) /* WS03 */,
577#else
578 ok( rtl_entries[i].wFlags == (RTL_HEAP_ENTRY_COMMITTED|RTL_HEAP_ENTRY_BLOCK|RTL_HEAP_ENTRY_BUSY) || broken(rtl_entries[i].wFlags == 0x411) /* win7 */,
579#endif
580 "got wFlags %#x\n", rtl_entries[i].wFlags );
581 else if (entries[i].wFlags & PROCESS_HEAP_UNCOMMITTED_RANGE)
582 ok( rtl_entries[i].wFlags == RTL_HEAP_ENTRY_UNCOMMITTED || broken(rtl_entries[i].wFlags == 0x100) /* win7 */,
583 "got wFlags %#x\n", rtl_entries[i].wFlags );
584 else if (entries[i].wFlags & PROCESS_HEAP_REGION)
585 {
586 ok( rtl_entries[i].wFlags == RTL_HEAP_ENTRY_REGION, "got wFlags %#x\n", rtl_entries[i].wFlags );
587 ok( rtl_entries[i].Region.dwCommittedSize == entries[i].Region.dwCommittedSize,
588 "got Region.dwCommittedSize %#lx\n", rtl_entries[i].Region.dwCommittedSize );
589 ok( rtl_entries[i].Region.dwUnCommittedSize == entries[i].Region.dwUnCommittedSize,
590 "got Region.dwUnCommittedSize %#lx\n", rtl_entries[i].Region.dwUnCommittedSize );
591 ok( rtl_entries[i].Region.lpFirstBlock == entries[i].Region.lpFirstBlock,
592 "got Region.lpFirstBlock %p\n", rtl_entries[i].Region.lpFirstBlock );
593 ok( rtl_entries[i].Region.lpLastBlock == entries[i].Region.lpLastBlock,
594 "got Region.lpLastBlock %p\n", rtl_entries[i].Region.lpLastBlock );
595 }
597 }
598
599#ifdef __REACTOS__
601#endif
602 ok( entries[0].wFlags == PROCESS_HEAP_REGION, "got wFlags %#x\n", entries[0].wFlags );
603 ok( entries[0].lpData == heap, "got lpData %p\n", entries[0].lpData );
604 ok( entries[0].cbData <= 0x1000 /* sizeof(*heap) */, "got cbData %#lx\n", entries[0].cbData );
605 ok( entries[0].cbOverhead == 0, "got cbOverhead %#x\n", entries[0].cbOverhead );
606 ok( entries[0].iRegionIndex == 0, "got iRegionIndex %d\n", entries[0].iRegionIndex );
608 ok( entries[0].Region.dwCommittedSize == 0x400 * sizeof(void *),
609 "got Region.dwCommittedSize %#lx\n", entries[0].Region.dwCommittedSize );
610 ok( entries[0].Region.dwUnCommittedSize == 0x10000 - entries[0].Region.dwCommittedSize ||
611 entries[0].Region.dwUnCommittedSize == 0x10000 * sizeof(void *) - entries[0].Region.dwCommittedSize /* win7 */,
612 "got Region.dwUnCommittedSize %#lx\n", entries[0].Region.dwUnCommittedSize );
614 ok( (BYTE *)entries[0].Region.lpFirstBlock == (BYTE *)entries[0].lpData + entries[0].cbData + 2 * sizeof(void *) ||
615 (BYTE *)entries[0].Region.lpFirstBlock == (BYTE *)entries[0].lpData + entries[0].cbData + 4 * sizeof(void *),
616 "got Region.lpFirstBlock %p\n", entries[0].Region.lpFirstBlock );
617 ok( entries[0].Region.lpLastBlock == (BYTE *)entries[2].lpData + entries[2].cbData,
618 "got Region.lpLastBlock %p\n", entries[0].Region.lpLastBlock );
619
620 ok( entries[1].wFlags == 0, "got wFlags %#x\n", entries[1].wFlags );
621 ok( entries[1].lpData != NULL, "got lpData %p\n", entries[1].lpData );
622 ok( entries[1].cbData != 0, "got cbData %#lx\n", entries[1].cbData );
623 ok( entries[1].cbOverhead == 4 * sizeof(void *), "got cbOverhead %#x\n", entries[1].cbOverhead );
624 ok( entries[1].iRegionIndex == 0, "got iRegionIndex %d\n", entries[1].iRegionIndex );
625
626 ok( entries[2].wFlags == PROCESS_HEAP_UNCOMMITTED_RANGE, "got wFlags %#x\n", entries[2].wFlags );
627 ok( entries[2].lpData == (BYTE *)entries[0].lpData + entries[0].Region.dwCommittedSize,
628 "got lpData %p\n", entries[2].lpData );
629 ok( entries[2].lpData == (BYTE *)entries[1].lpData + entries[1].cbData + 2 * entries[1].cbOverhead,
630 "got lpData %p\n", entries[2].lpData );
631 ok( entries[2].cbData == entries[0].Region.dwUnCommittedSize - 0x1000 ||
632 entries[2].cbData == entries[0].Region.dwUnCommittedSize /* win7 */,
633 "got cbData %#lx\n", entries[2].cbData );
634 ok( entries[2].cbOverhead == 0, "got cbOverhead %#x\n", entries[2].cbOverhead );
635 ok( entries[2].iRegionIndex == 0, "got iRegionIndex %d\n", entries[2].iRegionIndex );
636#ifdef __REACTOS__
637 }
638#endif
639
640 ptr = HeapAlloc( heap, HEAP_ZERO_MEMORY, 5 * alloc_size );
641 ok( !!ptr, "HeapAlloc failed, error %lu\n", GetLastError() );
642
643 count = 0;
644 memset( &rtl_entries, 0, sizeof(rtl_entries) );
645 memset( &rtl_entry, 0xcd, sizeof(rtl_entry) );
646 rtl_entry.lpData = NULL;
647 SetLastError( 0xdeadbeef );
648 while (!RtlWalkHeap( heap, &rtl_entry )) rtl_entries[count++] = rtl_entry;
649#ifdef __REACTOS__
650 ok( count == 4 || broken(count == 5) /* WS03 */, "got count %lu\n", count );
651#else
652 ok( count == 4, "got count %lu\n", count );
653#endif
654
655 memmove( entries + 16, entries, 3 * sizeof(entry) );
656 count = 0;
657 memset( &entry, 0xcd, sizeof(entry) );
658 entry.lpData = NULL;
659 SetLastError( 0xdeadbeef );
660 while ((ret = HeapWalk( heap, &entry ))) entries[count++] = entry;
661 ok( GetLastError() == ERROR_NO_MORE_ITEMS, "got error %lu\n", GetLastError() );
662#ifdef __REACTOS__
663 ok( count == 4 || broken(count == 5) /* WS03 */, "got count %lu\n", count );
664#else
665 ok( count == 4, "got count %lu\n", count );
666#endif
667 ok( !memcmp( entries + 16, entries, 3 * sizeof(entry) ), "entries differ\n" );
668
669 for (i = 0; i < count; ++i)
670 {
671 winetest_push_context( "%Iu", i );
672 ok( rtl_entries[i].lpData == entries[i].lpData, "got lpData %p\n", rtl_entries[i].lpData );
673 ok( rtl_entries[i].cbData == entries[i].cbData, "got cbData %#Ix\n", rtl_entries[i].cbData );
674 ok( rtl_entries[i].cbOverhead == entries[i].cbOverhead, "got cbOverhead %#x\n", rtl_entries[i].cbOverhead );
675 ok( rtl_entries[i].iRegionIndex == entries[i].iRegionIndex, "got iRegionIndex %#x\n", rtl_entries[i].iRegionIndex );
676 if (!entries[i].wFlags)
677 ok( rtl_entries[i].wFlags == 0, "got wFlags %#x\n", rtl_entries[i].wFlags );
678 else if (entries[i].wFlags & PROCESS_HEAP_ENTRY_BUSY)
679#ifdef __REACTOS__
680 ok( rtl_entries[i].wFlags == (RTL_HEAP_ENTRY_COMMITTED|RTL_HEAP_ENTRY_BLOCK|RTL_HEAP_ENTRY_BUSY) || broken(rtl_entries[i].wFlags == 0x411) /* win7 */ || broken(rtl_entries[i].wFlags == RTL_HEAP_ENTRY_BUSY) /* WS03 */ || broken(rtl_entries[i].wFlags == (RTL_HEAP_ENTRY_BLOCK|0x9)) /* WS03 */,
681#else
682 ok( rtl_entries[i].wFlags == (RTL_HEAP_ENTRY_COMMITTED|RTL_HEAP_ENTRY_BLOCK|RTL_HEAP_ENTRY_BUSY) || broken(rtl_entries[i].wFlags == 0x411) /* win7 */,
683#endif
684 "got wFlags %#x\n", rtl_entries[i].wFlags );
685 else if (entries[i].wFlags & PROCESS_HEAP_UNCOMMITTED_RANGE)
686 ok( rtl_entries[i].wFlags == RTL_HEAP_ENTRY_UNCOMMITTED || broken(rtl_entries[i].wFlags == 0x100) /* win7 */,
687 "got wFlags %#x\n", rtl_entries[i].wFlags );
688 else if (entries[i].wFlags & PROCESS_HEAP_REGION)
689 {
690 ok( rtl_entries[i].wFlags == RTL_HEAP_ENTRY_REGION, "got wFlags %#x\n", rtl_entries[i].wFlags );
691 ok( rtl_entries[i].Region.dwCommittedSize == entries[i].Region.dwCommittedSize,
692 "got Region.dwCommittedSize %#lx\n", rtl_entries[i].Region.dwCommittedSize );
693 ok( rtl_entries[i].Region.dwUnCommittedSize == entries[i].Region.dwUnCommittedSize,
694 "got Region.dwUnCommittedSize %#lx\n", rtl_entries[i].Region.dwUnCommittedSize );
695 ok( rtl_entries[i].Region.lpFirstBlock == entries[i].Region.lpFirstBlock,
696 "got Region.lpFirstBlock %p\n", rtl_entries[i].Region.lpFirstBlock );
697 ok( rtl_entries[i].Region.lpLastBlock == entries[i].Region.lpLastBlock,
698 "got Region.lpLastBlock %p\n", rtl_entries[i].Region.lpLastBlock );
699 }
701 }
702
703 ok( entries[3].wFlags == PROCESS_HEAP_ENTRY_BUSY ||
704#ifdef __REACTOS__
705 broken(entries[3].wFlags == (PROCESS_HEAP_ENTRY_BUSY | PROCESS_HEAP_ENTRY_DDESHARE)) /* win7 */ || broken(entries[3].wFlags == PROCESS_HEAP_UNCOMMITTED_RANGE) /* WS03 */,
706#else
708#endif
709 "got wFlags %#x\n", entries[3].wFlags );
710#ifdef __REACTOS__
712#endif
713 ok( entries[3].lpData == ptr, "got lpData %p\n", entries[3].lpData );
714 ok( entries[3].cbData == 5 * alloc_size, "got cbData %#lx\n", entries[3].cbData );
715#ifdef __REACTOS__
716 }
717#endif
718 ok( entries[3].cbOverhead == 0 || entries[3].cbOverhead == 8 * sizeof(void *) /* win7 */,
719 "got cbOverhead %#x\n", entries[3].cbOverhead );
720#ifdef __REACTOS__
721 ok( entries[3].iRegionIndex == 64 || broken(entries[3].iRegionIndex == 0) /* WS03 */, "got iRegionIndex %d\n", entries[3].iRegionIndex );
722#else
723 ok( entries[3].iRegionIndex == 64, "got iRegionIndex %d\n", entries[3].iRegionIndex );
724#endif
725
726 ptr1 = HeapAlloc( heap, HEAP_ZERO_MEMORY, 5 * alloc_size );
727 ok( !!ptr1, "HeapAlloc failed, error %lu\n", GetLastError() );
728
729 count = 0;
730 memset( &rtl_entries, 0, sizeof(rtl_entries) );
731 memset( &rtl_entry, 0xcd, sizeof(rtl_entry) );
732 rtl_entry.lpData = NULL;
733 SetLastError( 0xdeadbeef );
734 while (!RtlWalkHeap( heap, &rtl_entry )) rtl_entries[count++] = rtl_entry;
735#ifdef __REACTOS__
736 ok( count == 5 || broken(count == 6) /* WS03 */, "got count %lu\n", count );
737#else
738 ok( count == 5, "got count %lu\n", count );
739#endif
740
741 memmove( entries + 16, entries, 4 * sizeof(entry) );
742 count = 0;
743 memset( &entry, 0xcd, sizeof(entry) );
744 entry.lpData = NULL;
745 SetLastError( 0xdeadbeef );
746 while ((ret = HeapWalk( heap, &entry ))) entries[count++] = entry;
747 ok( GetLastError() == ERROR_NO_MORE_ITEMS, "got error %lu\n", GetLastError() );
748#ifdef __REACTOS__
749 ok( count == 5 || broken(count == 6) /* WS03 */, "got count %lu\n", count );
750#else
751 ok( count == 5, "got count %lu\n", count );
752#endif
753 ok( !memcmp( entries + 16, entries, 4 * sizeof(entry) ), "entries differ\n" );
754
755 for (i = 0; i < count; ++i)
756 {
757 winetest_push_context( "%Iu", i );
758 ok( rtl_entries[i].lpData == entries[i].lpData, "got lpData %p\n", rtl_entries[i].lpData );
759 ok( rtl_entries[i].cbData == entries[i].cbData, "got cbData %#Ix\n", rtl_entries[i].cbData );
760 ok( rtl_entries[i].cbOverhead == entries[i].cbOverhead, "got cbOverhead %#x\n", rtl_entries[i].cbOverhead );
761 ok( rtl_entries[i].iRegionIndex == entries[i].iRegionIndex, "got iRegionIndex %#x\n", rtl_entries[i].iRegionIndex );
762 if (!entries[i].wFlags)
763 ok( rtl_entries[i].wFlags == 0, "got wFlags %#x\n", rtl_entries[i].wFlags );
764 else if (entries[i].wFlags & PROCESS_HEAP_ENTRY_BUSY)
765#ifdef __REACTOS__
766 ok( rtl_entries[i].wFlags == (RTL_HEAP_ENTRY_COMMITTED|RTL_HEAP_ENTRY_BLOCK|RTL_HEAP_ENTRY_BUSY) || broken(rtl_entries[i].wFlags == 0x411) /* win7 */ || broken(rtl_entries[i].wFlags == RTL_HEAP_ENTRY_BUSY) /* WS03 */ || broken(rtl_entries[i].wFlags == (RTL_HEAP_ENTRY_BLOCK|0x9)) /* WS03 */,
767#else
768 ok( rtl_entries[i].wFlags == (RTL_HEAP_ENTRY_COMMITTED|RTL_HEAP_ENTRY_BLOCK|RTL_HEAP_ENTRY_BUSY) || broken(rtl_entries[i].wFlags == 0x411) /* win7 */,
769#endif
770 "got wFlags %#x\n", rtl_entries[i].wFlags );
771 else if (entries[i].wFlags & PROCESS_HEAP_UNCOMMITTED_RANGE)
772 ok( rtl_entries[i].wFlags == RTL_HEAP_ENTRY_UNCOMMITTED || broken(rtl_entries[i].wFlags == 0x100) /* win7 */,
773 "got wFlags %#x\n", rtl_entries[i].wFlags );
774 else if (entries[i].wFlags & PROCESS_HEAP_REGION)
775 {
776 ok( rtl_entries[i].wFlags == RTL_HEAP_ENTRY_REGION, "got wFlags %#x\n", rtl_entries[i].wFlags );
777 ok( rtl_entries[i].Region.dwCommittedSize == entries[i].Region.dwCommittedSize,
778 "got Region.dwCommittedSize %#lx\n", rtl_entries[i].Region.dwCommittedSize );
779 ok( rtl_entries[i].Region.dwUnCommittedSize == entries[i].Region.dwUnCommittedSize,
780 "got Region.dwUnCommittedSize %#lx\n", rtl_entries[i].Region.dwUnCommittedSize );
781 ok( rtl_entries[i].Region.lpFirstBlock == entries[i].Region.lpFirstBlock,
782 "got Region.lpFirstBlock %p\n", rtl_entries[i].Region.lpFirstBlock );
783 ok( rtl_entries[i].Region.lpLastBlock == entries[i].Region.lpLastBlock,
784 "got Region.lpLastBlock %p\n", rtl_entries[i].Region.lpLastBlock );
785 }
787 }
788
789 ok( entries[4].wFlags == PROCESS_HEAP_ENTRY_BUSY ||
791 "got wFlags %#x\n", entries[4].wFlags );
792#ifdef __REACTOS__
794#endif
795 ok( entries[4].lpData == ptr1, "got lpData %p\n", entries[4].lpData );
796 ok( entries[4].cbData == 5 * alloc_size, "got cbData %#lx\n", entries[4].cbData );
797 ok( entries[4].cbOverhead == 0 || entries[4].cbOverhead == 8 * sizeof(void *) /* win7 */,
798 "got cbOverhead %#x\n", entries[4].cbOverhead );
799 ok( entries[4].iRegionIndex == 64, "got iRegionIndex %d\n", entries[4].iRegionIndex );
800
801 ret = HeapFree( heap, 0, ptr1 );
802 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
803 ret = HeapFree( heap, 0, ptr );
804 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
805
806 memmove( entries + 16, entries, 3 * sizeof(entry) );
807 count = 0;
808 memset( &entry, 0xcd, sizeof(entry) );
809 entry.lpData = NULL;
810 SetLastError( 0xdeadbeef );
811 while ((ret = HeapWalk( heap, &entry ))) entries[count++] = entry;
812 ok( GetLastError() == ERROR_NO_MORE_ITEMS, "got error %lu\n", GetLastError() );
813#ifdef __REACTOS__
814 ok( count == 3 || broken(count == 4) /* WS03 */, "got count %lu\n", count );
815#else
816 ok( count == 3, "got count %lu\n", count );
817#endif
818 ok( !memcmp( entries + 16, entries, 3 * sizeof(entry) ), "entries differ\n" );
819
821 ok( !!ptr, "HeapAlloc failed, error %lu\n", GetLastError() );
822
823 memmove( entries + 16, entries, 3 * sizeof(entry) );
824 count = 0;
825 memset( &entry, 0xcd, sizeof(entry) );
826 entry.lpData = NULL;
827 SetLastError( 0xdeadbeef );
828 while ((ret = HeapWalk( heap, &entry ))) entries[count++] = entry;
829 ok( GetLastError() == ERROR_NO_MORE_ITEMS, "got error %lu\n", GetLastError() );
830#ifdef __REACTOS__
831 ok( count == 4 || broken(count == 5) /* WS03 */, "got count %lu\n", count );
832#else
833 ok( count == 4, "got count %lu\n", count );
834#endif
835 ok( !memcmp( entries + 16, entries, 1 * sizeof(entry) ), "entries differ\n" );
836 ok( memcmp( entries + 17, entries + 2, 2 * sizeof(entry) ), "entries differ\n" );
837
838#ifdef __REACTOS__
840#endif
841 ok( entries[1].wFlags == PROCESS_HEAP_ENTRY_BUSY, "got wFlags %#x\n", entries[1].wFlags );
842 ok( entries[1].lpData == ptr, "got lpData %p\n", entries[1].lpData );
843 ok( entries[1].cbData == 123, "got cbData %#lx\n", entries[1].cbData );
844 ok( entries[1].cbOverhead != 0, "got cbOverhead %#x\n", entries[1].cbOverhead );
845 ok( entries[1].iRegionIndex == 0, "got iRegionIndex %d\n", entries[1].iRegionIndex );
846
847 ok( entries[2].wFlags == 0, "got wFlags %#x\n", entries[2].wFlags );
848 ok( entries[2].lpData == (BYTE *)entries[1].lpData + entries[1].cbData + entries[1].cbOverhead + 2 * sizeof(void *),
849 "got lpData %p\n", entries[2].lpData );
850 ok( entries[2].cbData != 0, "got cbData %#lx\n", entries[2].cbData );
851 ok( entries[2].cbOverhead == 4 * sizeof(void *), "got cbOverhead %#x\n", entries[2].cbOverhead );
852 ok( entries[2].iRegionIndex == 0, "got iRegionIndex %d\n", entries[2].iRegionIndex );
853
854 ok( entries[3].wFlags == PROCESS_HEAP_UNCOMMITTED_RANGE, "got wFlags %#x\n", entries[3].wFlags );
855 ok( entries[3].lpData == (BYTE *)entries[0].lpData + entries[0].Region.dwCommittedSize,
856 "got lpData %p\n", entries[3].lpData );
857 ok( entries[3].lpData == (BYTE *)entries[2].lpData + entries[2].cbData + 2 * entries[2].cbOverhead,
858 "got lpData %p\n", entries[3].lpData );
859 ok( entries[3].cbData == entries[0].Region.dwUnCommittedSize - 0x1000 ||
860 entries[3].cbData == entries[0].Region.dwUnCommittedSize /* win7 */,
861 "got cbData %#lx\n", entries[3].cbData );
862 ok( entries[3].cbOverhead == 0, "got cbOverhead %#x\n", entries[3].cbOverhead );
863 ok( entries[3].iRegionIndex == 0, "got iRegionIndex %d\n", entries[3].iRegionIndex );
864#ifdef __REACTOS__
865 }
866#endif
867
868 ptr1 = HeapAlloc( heap, HEAP_ZERO_MEMORY, 456 );
869 ok( !!ptr1, "HeapAlloc failed, error %lu\n", GetLastError() );
870
871 memmove( entries + 16, entries, 4 * sizeof(entry) );
872 count = 0;
873 memset( &entry, 0xcd, sizeof(entry) );
874 entry.lpData = NULL;
875 SetLastError( 0xdeadbeef );
876 while ((ret = HeapWalk( heap, &entry ))) entries[count++] = entry;
877 ok( GetLastError() == ERROR_NO_MORE_ITEMS, "got error %lu\n", GetLastError() );
878#ifdef __REACTOS__
879 ok( count == 5 || broken(count == 6) /* WS03 */, "got count %lu\n", count );
880#else
881 ok( count == 5, "got count %lu\n", count );
882#endif
883 ok( !memcmp( entries + 16, entries, 2 * sizeof(entry) ), "entries differ\n" );
884 ok( memcmp( entries + 18, entries + 3, 2 * sizeof(entry) ), "entries differ\n" );
885
886#ifdef __REACTOS__
888#endif
889 ok( entries[2].wFlags == PROCESS_HEAP_ENTRY_BUSY, "got wFlags %#x\n", entries[2].wFlags );
890 ok( entries[2].lpData == ptr1, "got lpData %p\n", entries[2].lpData );
891 ok( entries[2].cbData == 456, "got cbData %#lx\n", entries[2].cbData );
892 ok( entries[2].cbOverhead != 0, "got cbOverhead %#x\n", entries[2].cbOverhead );
893 ok( entries[2].iRegionIndex == 0, "got iRegionIndex %d\n", entries[2].iRegionIndex );
894
895 ok( entries[3].wFlags == 0, "got wFlags %#x\n", entries[3].wFlags );
896 ok( entries[3].lpData == (BYTE *)entries[2].lpData + entries[2].cbData + entries[2].cbOverhead + 2 * sizeof(void *),
897 "got lpData %p\n", entries[3].lpData );
898 ok( entries[3].cbData != 0, "got cbData %#lx\n", entries[3].cbData );
899 ok( entries[3].cbOverhead == 4 * sizeof(void *), "got cbOverhead %#x\n", entries[3].cbOverhead );
900 ok( entries[3].iRegionIndex == 0, "got iRegionIndex %d\n", entries[3].iRegionIndex );
901
902 ok( entries[4].wFlags == PROCESS_HEAP_UNCOMMITTED_RANGE, "got wFlags %#x\n", entries[4].wFlags );
903 ok( entries[4].lpData == (BYTE *)entries[0].lpData + entries[0].Region.dwCommittedSize,
904 "got lpData %p\n", entries[4].lpData );
905 ok( entries[4].lpData == (BYTE *)entries[3].lpData + entries[3].cbData + 2 * entries[3].cbOverhead,
906 "got lpData %p\n", entries[4].lpData );
907 ok( entries[4].cbData == entries[0].Region.dwUnCommittedSize - 0x1000 ||
908 entries[4].cbData == entries[0].Region.dwUnCommittedSize /* win7 */,
909 "got cbData %#lx\n", entries[4].cbData );
910 ok( entries[4].cbOverhead == 0, "got cbOverhead %#x\n", entries[4].cbOverhead );
911 ok( entries[4].iRegionIndex == 0, "got iRegionIndex %d\n", entries[4].iRegionIndex );
912#ifdef __REACTOS__
913 }
914#endif
915
916 ret = HeapFree( heap, 0, ptr1 );
917 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
918 ret = HeapFree( heap, 0, ptr );
919 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
920
921#ifdef __REACTOS__
922 if (GetNTVersion() >= _WIN32_WINNT_VISTA) { /* NOTE: This crashes on WS03. */
923#endif
924 size = 0;
925 SetLastError( 0xdeadbeef );
926 ret = pHeapQueryInformation( 0, HeapCompatibilityInformation, &compat_info, sizeof(compat_info), &size );
927 ok( !ret, "HeapQueryInformation succeeded\n" );
928 ok( GetLastError() == ERROR_NOACCESS, "got error %lu\n", GetLastError() );
929 ok( size == 0, "got size %Iu\n", size );
930#ifdef __REACTOS__
931 }
932#endif
933
934 size = 0;
935 SetLastError( 0xdeadbeef );
936 ret = pHeapQueryInformation( heap, HeapCompatibilityInformation, NULL, 0, &size );
937 ok( !ret, "HeapQueryInformation succeeded\n" );
938 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got error %lu\n", GetLastError() );
939 ok( size == sizeof(ULONG), "got size %Iu\n", size );
940
941 SetLastError( 0xdeadbeef );
942 ret = pHeapQueryInformation( heap, HeapCompatibilityInformation, NULL, 0, NULL );
943 ok( !ret, "HeapQueryInformation succeeded\n" );
944 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got error %lu\n", GetLastError() );
945
946 SetLastError( 0xdeadbeef );
947 compat_info = 0xdeadbeef;
948 ret = pHeapQueryInformation( heap, HeapCompatibilityInformation, &compat_info, sizeof(compat_info) + 1, NULL );
949 ok( ret, "HeapQueryInformation failed, error %lu\n", GetLastError() );
950 ok( compat_info == 0, "got compat_info %lu\n", compat_info );
951
952 ret = HeapDestroy( heap );
953 ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() );
954
955
956 /* check setting LFH compat info */
957
958 heap = HeapCreate( 0, 0, 0 );
959 ok( !!heap, "HeapCreate failed, error %lu\n", GetLastError() );
960 ok( !((ULONG_PTR)heap & 0xffff), "wrong heap alignment\n" );
961
962 ret = pHeapQueryInformation( heap, HeapCompatibilityInformation, &compat_info, sizeof(compat_info), &size );
963 ok( ret, "HeapQueryInformation failed, error %lu\n", GetLastError() );
964#ifdef __REACTOS__
965 ok( compat_info == 0 || broken(compat_info == 1) /* WS03 */, "got HeapCompatibilityInformation %lu\n", compat_info );
966#else
967 ok( compat_info == 0, "got HeapCompatibilityInformation %lu\n", compat_info );
968#endif
969
970 compat_info = 2;
971 ret = pHeapSetInformation( heap, HeapCompatibilityInformation, &compat_info, sizeof(compat_info) );
972 ok( ret, "HeapSetInformation failed, error %lu\n", GetLastError() );
973 ret = pHeapQueryInformation( heap, HeapCompatibilityInformation, &compat_info, sizeof(compat_info), &size );
974 ok( ret, "HeapQueryInformation failed, error %lu\n", GetLastError() );
975 ok( compat_info == 2, "got HeapCompatibilityInformation %lu\n", compat_info );
976
977 /* cannot be undone */
978
979 compat_info = 0;
980 SetLastError( 0xdeadbeef );
981 ret = pHeapSetInformation( heap, HeapCompatibilityInformation, &compat_info, sizeof(compat_info) );
982 ok( !ret, "HeapSetInformation succeeded\n" );
983 ok( GetLastError() == ERROR_GEN_FAILURE, "got error %lu\n", GetLastError() );
984 compat_info = 1;
985 SetLastError( 0xdeadbeef );
986 ret = pHeapSetInformation( heap, HeapCompatibilityInformation, &compat_info, sizeof(compat_info) );
987 ok( !ret, "HeapSetInformation succeeded\n" );
988 ok( GetLastError() == ERROR_GEN_FAILURE, "got error %lu\n", GetLastError() );
989 ret = pHeapQueryInformation( heap, HeapCompatibilityInformation, &compat_info, sizeof(compat_info), &size );
990 ok( ret, "HeapQueryInformation failed, error %lu\n", GetLastError() );
991 ok( compat_info == 2, "got HeapCompatibilityInformation %lu\n", compat_info );
992
993 ret = HeapDestroy( heap );
994 ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() );
995
996
997 /* cannot set LFH with HEAP_NO_SERIALIZE */
998
1000 ok( !!heap, "HeapCreate failed, error %lu\n", GetLastError() );
1001 ok( !((ULONG_PTR)heap & 0xffff), "wrong heap alignment\n" );
1002
1003 ret = pHeapQueryInformation( heap, HeapCompatibilityInformation, &compat_info, sizeof(compat_info), &size );
1004 ok( ret, "HeapQueryInformation failed, error %lu\n", GetLastError() );
1005 ok( compat_info == 0, "got HeapCompatibilityInformation %lu\n", compat_info );
1006
1007 compat_info = 2;
1008 SetLastError( 0xdeadbeef );
1009 ret = pHeapSetInformation( heap, HeapCompatibilityInformation, &compat_info, sizeof(compat_info) );
1010 ok( !ret, "HeapSetInformation succeeded\n" );
1011#ifdef __REACTOS__
1012 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == ERROR_GEN_FAILURE) /* WS03 */, "got error %lu\n", GetLastError() );
1013#else
1014 ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
1015#endif
1016 ret = pHeapQueryInformation( heap, HeapCompatibilityInformation, &compat_info, sizeof(compat_info), &size );
1017 ok( ret, "HeapQueryInformation failed, error %lu\n", GetLastError() );
1018 ok( compat_info == 0, "got HeapCompatibilityInformation %lu\n", compat_info );
1019
1020 ret = HeapDestroy( heap );
1021 ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() );
1022
1023
1024 /* some allocation pattern automatically enables LFH */
1025
1026 heap = HeapCreate( 0, 0, 0 );
1027 ok( !!heap, "HeapCreate failed, error %lu\n", GetLastError() );
1028 ok( !((ULONG_PTR)heap & 0xffff), "wrong heap alignment\n" );
1029
1030 ret = pHeapQueryInformation( heap, HeapCompatibilityInformation, &compat_info, sizeof(compat_info), &size );
1031 ok( ret, "HeapQueryInformation failed, error %lu\n", GetLastError() );
1032#ifdef __REACTOS__
1033 ok( compat_info == 0 || broken(compat_info == 1) /* WS03 */, "got HeapCompatibilityInformation %lu\n", compat_info );
1034#else
1035 ok( compat_info == 0, "got HeapCompatibilityInformation %lu\n", compat_info );
1036#endif
1037
1038 for (i = 0; i < 0x12; i++) ptrs[i] = pHeapAlloc( heap, 0, 0 );
1039 for (i = 0; i < 0x12; i++) HeapFree( heap, 0, ptrs[i] );
1040
1041 ret = pHeapQueryInformation( heap, HeapCompatibilityInformation, &compat_info, sizeof(compat_info), &size );
1042 ok( ret, "HeapQueryInformation failed, error %lu\n", GetLastError() );
1043#ifdef __REACTOS__
1044 ok( compat_info == 2 || broken(compat_info == 1) /* WS03 */, "got HeapCompatibilityInformation %lu\n", compat_info );
1045#else
1046 ok( compat_info == 2, "got HeapCompatibilityInformation %lu\n", compat_info );
1047#endif
1048
1049 ret = HeapDestroy( heap );
1050 ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() );
1051
1052
1053 /* LFH actually doesn't enable immediately, the pattern is required */
1054
1055 heap = HeapCreate( 0, 0, 0 );
1056 ok( !!heap, "HeapCreate failed, error %lu\n", GetLastError() );
1057 ok( !((ULONG_PTR)heap & 0xffff), "wrong heap alignment\n" );
1058
1059 compat_info = 2;
1060 ret = pHeapSetInformation( heap, HeapCompatibilityInformation, &compat_info, sizeof(compat_info) );
1061 ok( ret, "HeapSetInformation failed, error %lu\n", GetLastError() );
1062 ret = pHeapQueryInformation( heap, HeapCompatibilityInformation, &compat_info, sizeof(compat_info), &size );
1063 ok( ret, "HeapQueryInformation failed, error %lu\n", GetLastError() );
1064 ok( compat_info == 2, "got HeapCompatibilityInformation %lu\n", compat_info );
1065
1066 for (i = 0; i < 0x11; i++) ptrs[i] = pHeapAlloc( heap, 0, 24 + 2 * sizeof(void *) );
1067 for (i = 0; i < 0x11; i++) HeapFree( heap, 0, ptrs[i] );
1068
1069 count = 0;
1070 memset( &entries, 0xcd, sizeof(entries) );
1071 memset( &entry, 0xcd, sizeof(entry) );
1072 entry.lpData = NULL;
1073 SetLastError( 0xdeadbeef );
1074 while ((ret = HeapWalk( heap, &entry ))) entries[count++] = entry;
1075 ok( GetLastError() == ERROR_NO_MORE_ITEMS, "got error %lu\n", GetLastError() );
1076#ifdef __REACTOS__
1077 ok( count == 3 || broken(count == 7) /* WS03 */, "got count %lu\n", count );
1078#else
1079 ok( count == 3, "got count %lu\n", count );
1080#endif
1081
1082#ifdef __REACTOS__
1084#endif
1085 ok( entries[0].wFlags == PROCESS_HEAP_REGION, "got wFlags %#x\n", entries[0].wFlags );
1086 ok( entries[0].lpData == heap, "got lpData %p\n", entries[0].lpData );
1087 ok( entries[0].cbData <= 0x1000 /* sizeof(*heap) */, "got cbData %#lx\n", entries[0].cbData );
1088 ok( entries[0].cbOverhead == 0, "got cbOverhead %#x\n", entries[0].cbOverhead );
1089 ok( entries[0].iRegionIndex == 0, "got iRegionIndex %d\n", entries[0].iRegionIndex );
1090 ok( entries[1].wFlags == 0, "got wFlags %#x\n", entries[1].wFlags );
1091 ok( entries[2].wFlags == PROCESS_HEAP_UNCOMMITTED_RANGE, "got wFlags %#x\n", entries[2].wFlags );
1092#ifdef __REACTOS__
1093 }
1094#endif
1095
1096 for (i = 0; i < 0x12; i++) ptrs[i] = pHeapAlloc( heap, 0, 24 + 2 * sizeof(void *) );
1097 for (i = 0; i < 0x12; i++) HeapFree( heap, 0, ptrs[i] );
1098
1099 count = 0;
1100 memset( &entries, 0xcd, sizeof(entries) );
1101 memset( &entry, 0xcd, sizeof(entry) );
1102 entry.lpData = NULL;
1103 SetLastError( 0xdeadbeef );
1104 while ((ret = HeapWalk( heap, &entry ))) entries[count++] = entry;
1105 ok( GetLastError() == ERROR_NO_MORE_ITEMS, "got error %lu\n", GetLastError() );
1106 todo_wine
1107#ifdef __REACTOS__
1109#endif
1110 ok( count > 24, "got count %lu\n", count );
1111 if (count < 2) count = 2;
1112
1113#ifdef __REACTOS__
1115#endif
1116 ok( entries[0].wFlags == PROCESS_HEAP_REGION, "got wFlags %#x\n", entries[0].wFlags );
1117 ok( entries[0].lpData == heap, "got lpData %p\n", entries[0].lpData );
1118 ok( entries[0].cbData <= 0x1000 /* sizeof(*heap) */, "got cbData %#lx\n", entries[0].cbData );
1119 ok( entries[0].cbOverhead == 0, "got cbOverhead %#x\n", entries[0].cbOverhead );
1120 ok( entries[0].iRegionIndex == 0, "got iRegionIndex %d\n", entries[0].iRegionIndex );
1121 todo_wine /* Wine currently reports the LFH group as a single block here */
1122 ok( entries[1].wFlags == 0, "got wFlags %#x\n", entries[1].wFlags );
1123
1124 for (i = 0; i < 0x12; i++)
1125 {
1126 todo_wine
1127 ok( entries[4 + i].wFlags == 0, "got wFlags %#x\n", entries[4 + i].wFlags );
1128 todo_wine
1129 ok( entries[4 + i].cbData == 0x20, "got cbData %#lx\n", entries[4 + i].cbData );
1130 todo_wine
1131 ok( entries[4 + i].cbOverhead == 2 * sizeof(void *), "got cbOverhead %#x\n", entries[4 + i].cbOverhead );
1132 }
1133#ifdef __REACTOS__
1134 }
1135#endif
1136
1137 if (entries[count - 1].wFlags == PROCESS_HEAP_REGION) /* > win7 */
1138 ok( entries[count - 2].wFlags == PROCESS_HEAP_UNCOMMITTED_RANGE, "got wFlags %#x\n", entries[count - 2].wFlags );
1139 else
1140 ok( entries[count - 1].wFlags == PROCESS_HEAP_UNCOMMITTED_RANGE, "got wFlags %#x\n", entries[count - 2].wFlags );
1141
1142 count = 0;
1143 memset( &rtl_entries, 0, sizeof(rtl_entries) );
1144 memset( &rtl_entry, 0xcd, sizeof(rtl_entry) );
1145 rtl_entry.lpData = NULL;
1146 SetLastError( 0xdeadbeef );
1147 while (!RtlWalkHeap( heap, &rtl_entry )) rtl_entries[count++] = rtl_entry;
1148 todo_wine
1149#ifdef __REACTOS__
1151#endif
1152 ok( count > 24, "got count %lu\n", count );
1153 if (count < 2) count = 2;
1154
1155 for (i = 3; i < count; ++i)
1156 {
1157 winetest_push_context( "%Iu", i );
1158 ok( rtl_entries[i].lpData == entries[i].lpData, "got lpData %p\n", rtl_entries[i].lpData );
1159 ok( rtl_entries[i].cbData == entries[i].cbData, "got cbData %#Ix\n", rtl_entries[i].cbData );
1160 ok( rtl_entries[i].cbOverhead == entries[i].cbOverhead, "got cbOverhead %#x\n", rtl_entries[i].cbOverhead );
1161 ok( rtl_entries[i].iRegionIndex == entries[i].iRegionIndex, "got iRegionIndex %#x\n", rtl_entries[i].iRegionIndex );
1162 if (!entries[i].wFlags)
1163 ok( rtl_entries[i].wFlags == 0 || rtl_entries[i].wFlags == RTL_HEAP_ENTRY_LFH, "got wFlags %#x\n", rtl_entries[i].wFlags );
1164 else if (entries[i].wFlags & PROCESS_HEAP_ENTRY_BUSY)
1165 ok( rtl_entries[i].wFlags == (RTL_HEAP_ENTRY_LFH|RTL_HEAP_ENTRY_BUSY) || broken(rtl_entries[i].wFlags == 1) /* win7 */,
1166 "got wFlags %#x\n", rtl_entries[i].wFlags );
1167 else if (entries[i].wFlags & PROCESS_HEAP_UNCOMMITTED_RANGE)
1168 ok( rtl_entries[i].wFlags == RTL_HEAP_ENTRY_UNCOMMITTED || broken(rtl_entries[i].wFlags == 0x100) /* win7 */,
1169 "got wFlags %#x\n", rtl_entries[i].wFlags );
1170 else if (entries[i].wFlags & PROCESS_HEAP_REGION)
1171 {
1172 ok( rtl_entries[i].wFlags == (RTL_HEAP_ENTRY_LFH|RTL_HEAP_ENTRY_REGION), "got wFlags %#x\n", rtl_entries[i].wFlags );
1173 ok( rtl_entries[i].Region.dwCommittedSize == entries[i].Region.dwCommittedSize,
1174 "got Region.dwCommittedSize %#lx\n", rtl_entries[i].Region.dwCommittedSize );
1175 ok( rtl_entries[i].Region.dwUnCommittedSize == entries[i].Region.dwUnCommittedSize,
1176 "got Region.dwUnCommittedSize %#lx\n", rtl_entries[i].Region.dwUnCommittedSize );
1177 ok( rtl_entries[i].Region.lpFirstBlock == entries[i].Region.lpFirstBlock,
1178 "got Region.lpFirstBlock %p\n", rtl_entries[i].Region.lpFirstBlock );
1179 ok( rtl_entries[i].Region.lpLastBlock == entries[i].Region.lpLastBlock,
1180 "got Region.lpLastBlock %p\n", rtl_entries[i].Region.lpLastBlock );
1181 }
1183 }
1184
1185 for (i = 0; i < 0x12; i++) ptrs[i] = pHeapAlloc( heap, 0, 24 + 2 * sizeof(void *) );
1186
1187 count = 0;
1188 memset( &entries, 0xcd, sizeof(entries) );
1189 memset( &entry, 0xcd, sizeof(entry) );
1190 entry.lpData = NULL;
1191 SetLastError( 0xdeadbeef );
1192 while ((ret = HeapWalk( heap, &entry ))) entries[count++] = entry;
1193 ok( GetLastError() == ERROR_NO_MORE_ITEMS, "got error %lu\n", GetLastError() );
1194 todo_wine
1195 ok( count > 24, "got count %lu\n", count );
1196 if (count < 2) count = 2;
1197
1198#ifdef __REACTOS__
1200#endif
1201 ok( entries[0].wFlags == PROCESS_HEAP_REGION, "got wFlags %#x\n", entries[0].wFlags );
1202 ok( entries[0].lpData == heap, "got lpData %p\n", entries[0].lpData );
1203 ok( entries[0].cbData <= 0x1000 /* sizeof(*heap) */, "got cbData %#lx\n", entries[0].cbData );
1204 ok( entries[0].cbOverhead == 0, "got cbOverhead %#x\n", entries[0].cbOverhead );
1205 ok( entries[0].iRegionIndex == 0, "got iRegionIndex %d\n", entries[0].iRegionIndex );
1206 ok( entries[1].wFlags == 0 || entries[1].wFlags == PROCESS_HEAP_ENTRY_BUSY /* win7 */, "got wFlags %#x\n", entries[1].wFlags );
1207
1208 for (i = 1; i < count - 2; i++)
1209 {
1210 if (entries[i].wFlags != PROCESS_HEAP_ENTRY_BUSY) continue;
1211 todo_wine /* Wine currently reports the LFH group as a single block */
1212 ok( entries[i].cbData == 0x18 + 2 * sizeof(void *), "got cbData %#lx\n", entries[i].cbData );
1213 ok( entries[i].cbOverhead == 0x8, "got cbOverhead %#x\n", entries[i].cbOverhead );
1214 }
1215#ifdef __REACTOS__
1216 }
1217#endif
1218
1219 if (entries[count - 1].wFlags == PROCESS_HEAP_REGION) /* > win7 */
1220 ok( entries[count - 2].wFlags == PROCESS_HEAP_UNCOMMITTED_RANGE, "got wFlags %#x\n", entries[count - 2].wFlags );
1221 else
1222 ok( entries[count - 1].wFlags == PROCESS_HEAP_UNCOMMITTED_RANGE, "got wFlags %#x\n", entries[count - 2].wFlags );
1223
1224 count = 0;
1225 memset( &rtl_entries, 0, sizeof(rtl_entries) );
1226 memset( &rtl_entry, 0xcd, sizeof(rtl_entry) );
1227 rtl_entry.lpData = NULL;
1228 SetLastError( 0xdeadbeef );
1229 while (!RtlWalkHeap( heap, &rtl_entry )) rtl_entries[count++] = rtl_entry;
1230 todo_wine
1231 ok( count > 24, "got count %lu\n", count );
1232 if (count < 2) count = 2;
1233
1234 for (i = 3; i < count; ++i)
1235 {
1236 winetest_push_context( "%Iu", i );
1237 ok( rtl_entries[i].lpData == entries[i].lpData, "got lpData %p\n", rtl_entries[i].lpData );
1238 ok( rtl_entries[i].cbData == entries[i].cbData, "got cbData %#Ix\n", rtl_entries[i].cbData );
1239 ok( rtl_entries[i].cbOverhead == entries[i].cbOverhead, "got cbOverhead %#x\n", rtl_entries[i].cbOverhead );
1240 ok( rtl_entries[i].iRegionIndex == entries[i].iRegionIndex, "got iRegionIndex %#x\n", rtl_entries[i].iRegionIndex );
1241 if (!entries[i].wFlags)
1242 ok( rtl_entries[i].wFlags == 0 || rtl_entries[i].wFlags == RTL_HEAP_ENTRY_LFH, "got wFlags %#x\n", rtl_entries[i].wFlags );
1243 else if (entries[i].wFlags & PROCESS_HEAP_ENTRY_BUSY)
1244 {
1245 todo_wine
1246 ok( rtl_entries[i].wFlags == (RTL_HEAP_ENTRY_LFH|RTL_HEAP_ENTRY_BUSY) || broken(rtl_entries[i].wFlags == 1) /* win7 */,
1247 "got wFlags %#x\n", rtl_entries[i].wFlags );
1248 }
1249 else if (entries[i].wFlags & PROCESS_HEAP_UNCOMMITTED_RANGE)
1250 ok( rtl_entries[i].wFlags == RTL_HEAP_ENTRY_UNCOMMITTED || broken(rtl_entries[i].wFlags == 0x100) /* win7 */,
1251 "got wFlags %#x\n", rtl_entries[i].wFlags );
1252 else if (entries[i].wFlags & PROCESS_HEAP_REGION)
1253 {
1254 ok( rtl_entries[i].wFlags == (RTL_HEAP_ENTRY_LFH|RTL_HEAP_ENTRY_REGION), "got wFlags %#x\n", rtl_entries[i].wFlags );
1255 ok( rtl_entries[i].Region.dwCommittedSize == entries[i].Region.dwCommittedSize,
1256 "got Region.dwCommittedSize %#lx\n", rtl_entries[i].Region.dwCommittedSize );
1257 ok( rtl_entries[i].Region.dwUnCommittedSize == entries[i].Region.dwUnCommittedSize,
1258 "got Region.dwUnCommittedSize %#lx\n", rtl_entries[i].Region.dwUnCommittedSize );
1259 ok( rtl_entries[i].Region.lpFirstBlock == entries[i].Region.lpFirstBlock,
1260 "got Region.lpFirstBlock %p\n", rtl_entries[i].Region.lpFirstBlock );
1261 ok( rtl_entries[i].Region.lpLastBlock == entries[i].Region.lpLastBlock,
1262 "got Region.lpLastBlock %p\n", rtl_entries[i].Region.lpLastBlock );
1263 }
1265 }
1266
1267 for (i = 0; i < 0x12; i++) HeapFree( heap, 0, ptrs[i] );
1268
1269 ret = HeapDestroy( heap );
1270 ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() );
1271
1272
1273 /* check HEAP_NO_SERIALIZE HeapCreate flag effect */
1274
1276 ok( !!heap, "HeapCreate failed, error %lu\n", GetLastError() );
1277 ok( !((ULONG_PTR)heap & 0xffff), "wrong heap alignment\n" );
1278
1279 ret = HeapLock( heap );
1280 ok( ret, "HeapLock failed, error %lu\n", GetLastError() );
1281 thread_params.heap = heap;
1282 thread_params.lock = TRUE;
1283 thread_params.flags = 0;
1284 SetEvent( thread_params.start_event );
1285 res = WaitForSingleObject( thread_params.ready_event, 100 );
1286 ok( !res, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() );
1287 ret = HeapUnlock( heap );
1288 ok( ret, "HeapUnlock failed, error %lu\n", GetLastError() );
1289
1290 ret = HeapLock( heap );
1291 ok( ret, "HeapLock failed, error %lu\n", GetLastError() );
1292 thread_params.heap = heap;
1293 thread_params.lock = FALSE;
1294 thread_params.flags = 0;
1295 SetEvent( thread_params.start_event );
1296 res = WaitForSingleObject( thread_params.ready_event, 100 );
1297 ok( !res, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() );
1298 ret = HeapUnlock( heap );
1299 ok( ret, "HeapUnlock failed, error %lu\n", GetLastError() );
1300
1301 ret = HeapDestroy( heap );
1302 ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() );
1303
1304
1305 /* check HEAP_NO_SERIALIZE HeapAlloc / HeapFree flag effect */
1306
1307 heap = HeapCreate( 0, 0, 0 );
1308 ok( !!heap, "HeapCreate failed, error %lu\n", GetLastError() );
1309 ok( !((ULONG_PTR)heap & 0xffff), "wrong heap alignment\n" );
1310
1311 ret = HeapLock( heap );
1312 ok( ret, "HeapLock failed, error %lu\n", GetLastError() );
1313 thread_params.heap = heap;
1314 thread_params.lock = TRUE;
1315 thread_params.flags = 0;
1316 SetEvent( thread_params.start_event );
1317 res = WaitForSingleObject( thread_params.ready_event, 100 );
1318 ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() );
1319 ret = HeapUnlock( heap );
1320 ok( ret, "HeapUnlock failed, error %lu\n", GetLastError() );
1321 res = WaitForSingleObject( thread_params.ready_event, 100 );
1322 ok( !res, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() );
1323
1324 ret = HeapLock( heap );
1325 ok( ret, "HeapLock failed, error %lu\n", GetLastError() );
1326 thread_params.heap = heap;
1327 thread_params.lock = FALSE;
1328 thread_params.flags = 0;
1329 SetEvent( thread_params.start_event );
1330 res = WaitForSingleObject( thread_params.ready_event, 100 );
1331 ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() );
1332 ret = HeapUnlock( heap );
1333 ok( ret, "HeapUnlock failed, error %lu\n", GetLastError() );
1334 res = WaitForSingleObject( thread_params.ready_event, 100 );
1335 ok( !res, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() );
1336
1337 ret = HeapLock( heap );
1338 ok( ret, "HeapLock failed, error %lu\n", GetLastError() );
1339 thread_params.heap = heap;
1340 thread_params.lock = FALSE;
1341 thread_params.flags = HEAP_NO_SERIALIZE;
1342 SetEvent( thread_params.start_event );
1343 res = WaitForSingleObject( thread_params.ready_event, 100 );
1344 ok( !res, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() );
1345 ret = HeapUnlock( heap );
1346 ok( ret, "HeapUnlock failed, error %lu\n", GetLastError() );
1347
1348 ret = HeapDestroy( heap );
1349 ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() );
1350
1351
1352 /* check LFH heap locking */
1353
1354 heap = HeapCreate( 0, 0, 0 );
1355 ok( !!heap, "HeapCreate failed, error %lu\n", GetLastError() );
1356 ok( !((ULONG_PTR)heap & 0xffff), "wrong heap alignment\n" );
1357
1358 ret = pHeapQueryInformation( heap, HeapCompatibilityInformation, &compat_info, sizeof(compat_info), &size );
1359 ok( ret, "HeapQueryInformation failed, error %lu\n", GetLastError() );
1360#ifdef __REACTOS__
1361 ok( compat_info == 0 || broken(compat_info == 1) /* WS03 */, "got HeapCompatibilityInformation %lu\n", compat_info );
1362#else
1363 ok( compat_info == 0, "got HeapCompatibilityInformation %lu\n", compat_info );
1364#endif
1365
1366 for (i = 0; i < 0x12; i++) ptrs[i] = pHeapAlloc( heap, 0, 0 );
1367 for (i = 0; i < 0x12; i++) HeapFree( heap, 0, ptrs[i] );
1368
1369 ret = pHeapQueryInformation( heap, HeapCompatibilityInformation, &compat_info, sizeof(compat_info), &size );
1370 ok( ret, "HeapQueryInformation failed, error %lu\n", GetLastError() );
1371#ifdef __REACTOS__
1372 ok( compat_info == 2 || broken(compat_info == 1) /* WS03 */, "got HeapCompatibilityInformation %lu\n", compat_info );
1373#else
1374 ok( compat_info == 2, "got HeapCompatibilityInformation %lu\n", compat_info );
1375#endif
1376
1377 /* locking is serialized */
1378
1379 ret = HeapLock( heap );
1380 ok( ret, "HeapLock failed, error %lu\n", GetLastError() );
1381 thread_params.heap = heap;
1382 thread_params.lock = TRUE;
1383 thread_params.flags = 0;
1384 SetEvent( thread_params.start_event );
1385 res = WaitForSingleObject( thread_params.ready_event, 100 );
1386 ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() );
1387 ret = HeapUnlock( heap );
1388 ok( ret, "HeapUnlock failed, error %lu\n", GetLastError() );
1389 res = WaitForSingleObject( thread_params.ready_event, 100 );
1390 ok( !res, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() );
1391
1392 /* but allocation is not */
1393
1394 ret = HeapLock( heap );
1395 ok( ret, "HeapLock failed, error %lu\n", GetLastError() );
1396 thread_params.heap = heap;
1397 thread_params.lock = FALSE;
1398 thread_params.flags = 0;
1399 SetEvent( thread_params.start_event );
1400 res = WaitForSingleObject( thread_params.ready_event, 100 );
1401#ifdef __REACTOS__
1403#endif
1404 ok( !res, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() );
1405 ret = HeapUnlock( heap );
1406 ok( ret, "HeapUnlock failed, error %lu\n", GetLastError() );
1407 if (res) res = WaitForSingleObject( thread_params.ready_event, 100 );
1408
1409 ret = HeapDestroy( heap );
1410 ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() );
1411
1412
1413 thread_params.done = TRUE;
1414 SetEvent( thread_params.start_event );
1416 ok( !res, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() );
1417 CloseHandle( thread_params.start_event );
1418 CloseHandle( thread_params.ready_event );
1420}
1421
1422
1423struct mem_entry
1424{
1426 void *ptr;
1427};
1428
1430{
1431 return CONTAINING_RECORD( handle, struct mem_entry, ptr );
1432}
1433
1435{
1436 return ((UINT_PTR)handle & ((sizeof(void *) << 1) - 1)) == sizeof(void *);
1437}
1438
1439static void test_GlobalAlloc(void)
1440{
1441 static const UINT flags_tests[] =
1442 {
1451 };
1452 static const UINT realloc_flags_tests[] =
1453 {
1454 GMEM_FIXED,
1462 };
1463 static const char zero_buffer[100000] = {0};
1464 static const SIZE_T buffer_size = ARRAY_SIZE(zero_buffer);
1465 const HGLOBAL invalid_mem = LongToHandle( 0xdeadbee0 + sizeof(void *) );
1466 SIZE_T size, alloc_size, small_size = 12, nolfh_size = 0x20000;
1467 void *const invalid_ptr = LongToHandle( 0xdeadbee0 );
1469 PROCESS_HEAP_ENTRY walk_entry;
1470 struct mem_entry *entry;
1471 HGLOBAL globals[0x10000];
1472 HGLOBAL mem, tmp_mem;
1473 BYTE *ptr, *tmp_ptr;
1474 ULONG tmp_flags;
1475 UINT i, flags;
1476 BOOL ret;
1477
1478 mem = GlobalFree( 0 );
1479 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
1480 mem = GlobalReAlloc( 0, 10, GMEM_MOVEABLE );
1481 ok( !mem, "GlobalReAlloc succeeded\n" );
1482
1483 for (i = 0; i < ARRAY_SIZE(globals); ++i)
1484 {
1486 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
1487 globals[i] = mem;
1488 }
1489
1490 memset( &walk_entry, 0xcd, sizeof(walk_entry) );
1491 walk_entry.lpData = NULL;
1492 ret = HeapLock( heap );
1493 ok( ret, "HeapLock failed, error %lu\n", GetLastError() );
1494 while ((ret = HeapWalk( heap, &walk_entry )))
1495 {
1496 ok( !(walk_entry.wFlags & PROCESS_HEAP_ENTRY_MOVEABLE), "got PROCESS_HEAP_ENTRY_MOVEABLE\n" );
1497 ok( !(walk_entry.wFlags & PROCESS_HEAP_ENTRY_DDESHARE), "got PROCESS_HEAP_ENTRY_DDESHARE\n" );
1498 }
1499 ok( GetLastError() == ERROR_NO_MORE_ITEMS, "got error %lu\n", GetLastError() );
1500 ret = HeapUnlock( heap );
1501 ok( ret, "HeapUnlock failed, error %lu\n", GetLastError() );
1502
1503 SetLastError( 0xdeadbeef );
1505 ok( !mem, "GlobalAlloc succeeded\n" );
1506 ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY, "got error %lu\n", GetLastError() );
1507 SetLastError( 0xdeadbeef );
1509 ok( !mem, "LocalAlloc succeeded\n" );
1510 ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY, "got error %lu\n", GetLastError() );
1511
1513 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
1514 mem = GlobalFree( mem );
1515 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
1516
1517 for (i = 0; i < ARRAY_SIZE(globals); ++i)
1518 {
1519 mem = GlobalFree( globals[i] );
1520 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
1521 }
1522
1523 /* make sure LFH is enabled for some small block size */
1524 for (i = 0; i < 0x12; i++) globals[i] = pGlobalAlloc( GMEM_FIXED, small_size );
1525 for (i = 0; i < 0x12; i++) pGlobalFree( globals[i] );
1526
1528 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
1530 ok( !!mem, "GlobalReAlloc failed, error %lu\n", GetLastError() );
1531 size = GlobalSize( mem );
1532 ok( size >= 10 && size <= 16, "GlobalSize returned %Iu\n", size );
1534 ok( !!mem, "GlobalReAlloc failed, error %lu\n", GetLastError() );
1535 size = GlobalSize( mem );
1536 ok( size == 0, "GlobalSize returned %Iu\n", size );
1538 ok( !!mem, "GlobalReAlloc failed, error %lu\n", GetLastError() );
1539 size = GlobalSize( mem );
1540 ok( size >= 10 && size <= 16, "GlobalSize returned %Iu\n", size );
1541 tmp_mem = pGlobalFree( mem );
1542 ok( !tmp_mem, "GlobalFree failed, error %lu\n", GetLastError() );
1543 size = GlobalSize( mem );
1544 ok( size == 0, "GlobalSize returned %Iu\n", size );
1545
1546 mem = pGlobalAlloc( GMEM_MOVEABLE | GMEM_DISCARDABLE, 0 );
1547 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
1549 size = GlobalSize( mem );
1550 ok( size == 0, "GlobalSize returned %Iu\n", size );
1552 ok( !ret, "HeapValidate succeeded\n" );
1553 ok( entry->flags == 0xf, "got unexpected flags %#Ix\n", entry->flags );
1554 ok( !entry->ptr, "got unexpected ptr %p\n", entry->ptr );
1555 mem = GlobalFree( mem );
1556 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
1557
1558 mem = pGlobalAlloc( GMEM_MOVEABLE, 0 );
1559 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
1561 size = GlobalSize( mem );
1562 ok( size == 0, "GlobalSize returned %Iu\n", size );
1564 ok( !ret, "HeapValidate succeeded\n" );
1565 ok( entry->flags == 0xb, "got unexpected flags %#Ix\n", entry->flags );
1566 ok( !entry->ptr, "got unexpected ptr %p\n", entry->ptr );
1567 mem = GlobalFree( mem );
1568 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
1569
1570 for (alloc_size = 1; alloc_size < 0x10000000; alloc_size <<= 5)
1571 {
1572 winetest_push_context( "size %#Ix", alloc_size );
1573
1574 mem = GlobalAlloc( GMEM_FIXED, alloc_size );
1575 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
1576 ok( !((UINT_PTR)mem & sizeof(void *)), "got unexpected ptr align\n" );
1577 ok( !((UINT_PTR)mem & (sizeof(void *) - 1)), "got unexpected ptr align\n" );
1579 ok( ret, "HeapValidate failed, error %lu\n", GetLastError() );
1580 tmp_mem = GlobalFree( mem );
1581 ok( !tmp_mem, "GlobalFree failed, error %lu\n", GetLastError() );
1582
1583 mem = pGlobalAlloc( GMEM_MOVEABLE, alloc_size );
1584 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
1585 ok( ((UINT_PTR)mem & sizeof(void *)), "got unexpected entry align\n" );
1586 ok( !((UINT_PTR)mem & (sizeof(void *) - 1)), "got unexpected entry align\n" );
1587
1590 ok( !ret, "HeapValidate succeeded\n" );
1591 ret = HeapValidate( GetProcessHeap(), 0, entry->ptr );
1592 ok( ret, "HeapValidate failed, error %lu\n", GetLastError() );
1593 size = HeapSize( GetProcessHeap(), 0, entry->ptr );
1594 ok( size == alloc_size, "HeapSize returned %Iu\n", size );
1595
1596 tmp_mem = invalid_mem;
1597 tmp_flags = 0xdeadbeef;
1598 ret = pRtlGetUserInfoHeap( GetProcessHeap(), 0, entry->ptr, (void **)&tmp_mem, &tmp_flags );
1599 ok( ret, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() );
1600 ok( tmp_mem == mem, "got user ptr %p\n", tmp_mem );
1601 ok( tmp_flags == 0x200, "got user flags %#lx\n", tmp_flags );
1602
1603 ret = pRtlSetUserValueHeap( GetProcessHeap(), 0, entry->ptr, invalid_mem );
1604 ok( ret, "RtlSetUserValueHeap failed, error %lu\n", GetLastError() );
1605 tmp_mem = GlobalHandle( entry->ptr );
1606 ok( tmp_mem == invalid_mem, "GlobalHandle returned unexpected handle\n" );
1607 ret = pRtlSetUserValueHeap( GetProcessHeap(), 0, entry->ptr, mem );
1608 ok( ret, "RtlSetUserValueHeap failed, error %lu\n", GetLastError() );
1609
1610 ptr = GlobalLock( mem );
1611 ok( !!ptr, "GlobalLock failed, error %lu\n", GetLastError() );
1612 ok( ptr != mem, "got unexpected ptr %p\n", ptr );
1613 ok( ptr == entry->ptr, "got unexpected ptr %p\n", ptr );
1614 ok( !((UINT_PTR)ptr & sizeof(void *)), "got unexpected ptr align\n" );
1615 ok( !((UINT_PTR)ptr & (sizeof(void *) - 1)), "got unexpected ptr align\n" );
1616 for (i = 1; i < 0xff; ++i)
1617 {
1618 ok( entry->flags == ((i<<16)|3), "got unexpected flags %#Ix\n", entry->flags );
1619 ptr = GlobalLock( mem );
1620 ok( !!ptr, "GlobalLock failed, error %lu\n", GetLastError() );
1621 }
1622 ptr = GlobalLock( mem );
1623 ok( !!ptr, "GlobalLock failed, error %lu\n", GetLastError() );
1624 ok( entry->flags == 0xff0003, "got unexpected flags %#Ix\n", entry->flags );
1625 for (i = 1; i < 0xff; ++i)
1626 {
1627 ret = GlobalUnlock( mem );
1628 ok( ret, "GlobalUnlock failed, error %lu\n", GetLastError() );
1629 }
1630 ret = GlobalUnlock( mem );
1631 ok( !ret, "GlobalUnlock succeeded, error %lu\n", GetLastError() );
1632 ok( entry->flags == 0x3, "got unexpected flags %#Ix\n", entry->flags );
1633
1634 tmp_mem = pGlobalFree( mem );
1635 ok( !tmp_mem, "GlobalFree failed, error %lu\n", GetLastError() );
1636 ok( !!entry->flags, "got unexpected flags %#Ix\n", entry->flags );
1637 ok( !((UINT_PTR)entry->flags & sizeof(void *)), "got unexpected ptr align\n" );
1638 ok( !((UINT_PTR)entry->flags & (sizeof(void *) - 1)), "got unexpected ptr align\n" );
1639 ok( !entry->ptr, "got unexpected ptr %p\n", entry->ptr );
1640
1641 mem = pGlobalAlloc( GMEM_MOVEABLE | GMEM_DISCARDABLE, 0 );
1642 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
1644 ok( entry->flags == 0xf, "got unexpected flags %#Ix\n", entry->flags );
1645 ok( !entry->ptr, "got unexpected ptr %p\n", entry->ptr );
1646 flags = GlobalFlags( mem );
1647 ok( flags == (GMEM_DISCARDED | GMEM_DISCARDABLE), "GlobalFlags returned %#x, error %lu\n", flags, GetLastError() );
1648 mem = GlobalFree( mem );
1649 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
1650
1651 mem = pGlobalAlloc( GMEM_MOVEABLE | GMEM_DISCARDABLE, 1 );
1652 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
1654 ok( entry->flags == 0x7, "got unexpected flags %#Ix\n", entry->flags );
1655 ok( !!entry->ptr, "got unexpected ptr %p\n", entry->ptr );
1656 flags = GlobalFlags( mem );
1657 ok( flags == GMEM_DISCARDABLE, "GlobalFlags returned %#x, error %lu\n", flags, GetLastError() );
1658 mem = GlobalFree( mem );
1659 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
1660
1661 mem = pGlobalAlloc( GMEM_MOVEABLE | GMEM_DISCARDABLE | GMEM_DDESHARE, 1 );
1662 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
1664 ok( entry->flags == 0x8007, "got unexpected flags %#Ix\n", entry->flags );
1665 ok( !!entry->ptr, "got unexpected ptr %p\n", entry->ptr );
1666 flags = GlobalFlags( mem );
1667 ok( flags == (GMEM_DISCARDABLE | GMEM_DDESHARE), "GlobalFlags returned %#x, error %lu\n", flags, GetLastError() );
1668 mem = GlobalFree( mem );
1669 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
1670
1672 }
1673
1674 mem = GlobalAlloc( GMEM_MOVEABLE, 256 );
1675 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
1676 ptr = GlobalLock( mem );
1677 ok( !!ptr, "GlobalLock failed, error %lu\n", GetLastError() );
1678 ok( ptr != mem, "got unexpected ptr %p\n", ptr );
1679 tmp_mem = GlobalHandle( ptr );
1680 ok( tmp_mem == mem, "GlobalHandle returned unexpected handle\n" );
1681 flags = GlobalFlags( mem );
1682 ok( flags == 1, "GlobalFlags returned %#x, error %lu\n", flags, GetLastError() );
1683 tmp_ptr = GlobalLock( mem );
1684 ok( !!tmp_ptr, "GlobalLock failed, error %lu\n", GetLastError() );
1685 ok( tmp_ptr == ptr, "got ptr %p, expected %p\n", tmp_ptr, ptr );
1686 flags = GlobalFlags( mem );
1687 ok( flags == 2, "GlobalFlags returned %#x, error %lu\n", flags, GetLastError() );
1688 ret = GlobalUnlock( mem );
1689 ok( ret, "GlobalUnlock failed, error %lu\n", GetLastError() );
1690 flags = GlobalFlags( mem );
1691 ok( flags == 1, "GlobalFlags returned %#x, error %lu\n", flags, GetLastError() );
1692 SetLastError( 0xdeadbeef );
1693 ret = GlobalUnlock( mem );
1694 ok( !ret, "GlobalUnlock succeeded\n" );
1695 ok( GetLastError() == ERROR_SUCCESS, "got error %lu\n", GetLastError() );
1696 flags = GlobalFlags( mem );
1697 ok( !flags, "GlobalFlags returned %#x, error %lu\n", flags, GetLastError() );
1698 SetLastError( 0xdeadbeef );
1699 ret = GlobalUnlock( mem );
1700 ok( !ret, "GlobalUnlock succeeded\n" );
1701 ok( GetLastError() == ERROR_NOT_LOCKED, "got error %lu\n", GetLastError() );
1702 tmp_mem = GlobalFree( mem );
1703 ok( !tmp_mem, "GlobalFree failed, error %lu\n", GetLastError() );
1704
1705 mem = GlobalAlloc( GMEM_DDESHARE, 100 );
1706 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
1707 tmp_mem = pGlobalFree( mem );
1708 ok( !tmp_mem, "GlobalFree failed, error %lu\n", GetLastError() );
1709 if (sizeof(void *) != 8) /* crashes on 64-bit */
1710 {
1711 SetLastError( 0xdeadbeef );
1712 tmp_mem = pGlobalFree( mem );
1713 ok( tmp_mem == mem, "GlobalFree succeeded\n" );
1714 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
1715
1716 SetLastError( 0xdeadbeef );
1717 size = GlobalSize( (HGLOBAL)0xc042 );
1718 ok( size == 0, "GlobalSize succeeded\n" );
1719 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
1720 }
1721
1722 /* freed handles are caught */
1723 mem = GlobalAlloc( GMEM_MOVEABLE, 256 );
1724 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
1725 tmp_mem = pGlobalFree( mem );
1726 ok( !tmp_mem, "GlobalFree failed, error %lu\n", GetLastError() );
1727 SetLastError( 0xdeadbeef );
1728 tmp_mem = pGlobalFree( mem );
1729 ok( tmp_mem == mem, "GlobalFree succeeded\n" );
1730 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
1731 SetLastError( 0xdeadbeef );
1732 flags = GlobalFlags( mem );
1733 ok( flags == GMEM_INVALID_HANDLE, "GlobalFlags succeeded\n" );
1734 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
1735 SetLastError( 0xdeadbeef );
1736 size = GlobalSize( mem );
1737 ok( size == 0, "GlobalSize succeeded\n" );
1738 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
1739 SetLastError( 0xdeadbeef );
1740 ptr = GlobalLock( mem );
1741 ok( !ptr, "GlobalLock succeeded\n" );
1742 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
1743 SetLastError( 0xdeadbeef );
1744 ret = GlobalUnlock( mem );
1745 todo_wine
1746 ok( ret, "GlobalUnlock failed, error %lu\n", GetLastError() );
1747 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
1748 SetLastError( 0xdeadbeef );
1749 tmp_mem = GlobalReAlloc( mem, 0, GMEM_MOVEABLE );
1750 ok( !tmp_mem, "GlobalReAlloc succeeded\n" );
1751 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
1752#ifdef __REACTOS__
1753 if (sizeof(void *) != 8 && GetNTVersion() >= _WIN32_WINNT_VISTA) /* crashes on 64-bit, invalid on WS03 */
1754#else
1755 if (sizeof(void *) != 8) /* crashes on 64-bit */
1756#endif
1757 {
1758 SetLastError( 0xdeadbeef );
1759 tmp_mem = GlobalHandle( mem );
1760 ok( !tmp_mem, "GlobalHandle succeeded\n" );
1761 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
1762 }
1763
1764#ifdef __REACTOS__
1765 if (is_reactos()) {
1766 ok(FALSE, "FIXME: invalid handle and invalid pointer tests crash on ReactOS!\n");
1767 } else {
1768#endif
1769 /* invalid handles are caught */
1770 SetLastError( 0xdeadbeef );
1771 tmp_mem = pGlobalFree( invalid_mem );
1772 ok( tmp_mem == invalid_mem, "GlobalFree succeeded\n" );
1773 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
1774 SetLastError( 0xdeadbeef );
1775 flags = GlobalFlags( invalid_mem );
1776 ok( flags == GMEM_INVALID_HANDLE, "GlobalFlags succeeded\n" );
1777 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
1778 SetLastError( 0xdeadbeef );
1779 size = GlobalSize( invalid_mem );
1780 ok( size == 0, "GlobalSize succeeded\n" );
1781 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
1782 SetLastError( 0xdeadbeef );
1783 ptr = GlobalLock( invalid_mem );
1784 ok( !ptr, "GlobalLock succeeded\n" );
1785 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
1786 SetLastError( 0xdeadbeef );
1787 ret = GlobalUnlock( invalid_mem );
1788 todo_wine
1789 ok( ret, "GlobalUnlock failed, error %lu\n", GetLastError() );
1790 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
1791 SetLastError( 0xdeadbeef );
1792 tmp_mem = GlobalReAlloc( invalid_mem, 0, GMEM_MOVEABLE );
1793 ok( !tmp_mem, "GlobalReAlloc succeeded\n" );
1794 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
1795 if (sizeof(void *) != 8) /* crashes on 64-bit */
1796 {
1797 SetLastError( 0xdeadbeef );
1798 tmp_mem = GlobalHandle( invalid_mem );
1799 ok( !tmp_mem, "GlobalHandle succeeded\n" );
1800 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
1801 SetLastError( 0xdeadbeef );
1802 ret = pRtlGetUserInfoHeap( GetProcessHeap(), 0, invalid_mem, (void **)&tmp_ptr, &tmp_flags );
1803 ok( !ret, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() );
1804#ifdef __REACTOS__
1805 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == ERROR_NOACCESS) /* WS03 */, "got error %lu\n", GetLastError() );
1806#else
1807 ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
1808#endif
1809 }
1810
1811 /* invalid pointers are caught */
1812 SetLastError( 0xdeadbeef );
1813 tmp_mem = pGlobalFree( invalid_ptr );
1814 ok( tmp_mem == invalid_ptr, "GlobalFree succeeded\n" );
1815 todo_wine
1816#ifdef __REACTOS__
1817 ok( GetLastError() == ERROR_NOACCESS || broken(GetLastError() == ERROR_INVALID_HANDLE) /* WS03 */, "got error %lu\n", GetLastError() );
1818#else
1819 ok( GetLastError() == ERROR_NOACCESS, "got error %lu\n", GetLastError() );
1820#endif
1821 SetLastError( 0xdeadbeef );
1822 flags = GlobalFlags( invalid_ptr );
1823 todo_wine
1824 ok( flags == GMEM_INVALID_HANDLE, "GlobalFlags succeeded\n" );
1825 todo_wine
1826 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
1827 SetLastError( 0xdeadbeef );
1828 size = GlobalSize( invalid_ptr );
1829 ok( size == 0, "GlobalSize succeeded\n" );
1830 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
1831 SetLastError( 0xdeadbeef );
1832 ptr = GlobalLock( invalid_ptr );
1833 ok( !ptr, "GlobalLock succeeded\n" );
1834 todo_wine
1835 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
1836 SetLastError( 0xdeadbeef );
1837 ret = GlobalUnlock( invalid_ptr );
1838 ok( ret, "GlobalUnlock failed, error %lu\n", GetLastError() );
1839 ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() );
1840 SetLastError( 0xdeadbeef );
1841 tmp_mem = GlobalReAlloc( invalid_ptr, 0, GMEM_MOVEABLE );
1842 ok( !tmp_mem, "GlobalReAlloc succeeded\n" );
1843 todo_wine
1844 ok( GetLastError() == ERROR_NOACCESS, "got error %lu\n", GetLastError() );
1845 SetLastError( 0xdeadbeef );
1846 tmp_mem = GlobalHandle( invalid_ptr );
1847 ok( !tmp_mem, "GlobalHandle succeeded\n" );
1848 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
1849 if (0) /* crashes */
1850 {
1851 SetLastError( 0xdeadbeef );
1852 ret = pRtlGetUserInfoHeap( GetProcessHeap(), 0, invalid_ptr, (void **)&tmp_ptr, &tmp_flags );
1853 ok( ret, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() );
1854 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
1855 }
1856#ifdef __REACTOS__
1857 }
1858#endif
1859
1860 /* GMEM_FIXED block doesn't allow resize, though it succeeds with GMEM_MODIFY */
1861 mem = GlobalAlloc( GMEM_FIXED, small_size );
1862 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
1863 tmp_mem = GlobalReAlloc( mem, small_size - 1, GMEM_MODIFY );
1864 ok( !!tmp_mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
1865 ok( tmp_mem == mem, "got ptr %p, expected %p\n", tmp_mem, mem );
1866 size = GlobalSize( mem );
1867 ok( size == small_size, "GlobalSize returned %Iu\n", size );
1868 SetLastError( 0xdeadbeef );
1869#ifdef __REACTOS__
1871#endif
1872 tmp_mem = GlobalReAlloc( mem, small_size, 0 );
1873 ok( !tmp_mem, "GlobalReAlloc succeeded\n" );
1874 ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY, "got error %lu\n", GetLastError() );
1875#ifdef __REACTOS__
1876 }
1877#endif
1878 if (tmp_mem) mem = tmp_mem;
1879 tmp_mem = GlobalReAlloc( mem, 1024 * 1024, GMEM_MODIFY );
1880 ok( !!tmp_mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
1881 ok( tmp_mem == mem, "got ptr %p, expected %p\n", tmp_mem, mem );
1882 size = GlobalSize( mem );
1883 ok( size == small_size, "GlobalSize returned %Iu\n", size );
1884 mem = GlobalFree( mem );
1885 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
1886
1887 /* GMEM_FIXED block can be relocated with GMEM_MOVEABLE */
1888 mem = GlobalAlloc( GMEM_FIXED, small_size );
1889 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
1890 tmp_mem = GlobalReAlloc( mem, small_size + 1, GMEM_MOVEABLE );
1891 ok( !!tmp_mem, "GlobalReAlloc failed, error %lu\n", GetLastError() );
1892#ifdef __REACTOS__
1894#endif
1895 ok( tmp_mem != mem, "GlobalReAlloc didn't relocate memory\n" );
1896 ptr = GlobalLock( tmp_mem );
1897 ok( !!ptr, "GlobalLock failed, error %lu\n", GetLastError() );
1898 ok( ptr == tmp_mem, "got ptr %p, expected %p\n", ptr, tmp_mem );
1899 mem = GlobalFree( tmp_mem );
1900 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
1901
1902 /* test GlobalReAlloc flags / GlobalLock combinations */
1903#ifdef __REACTOS__
1904 if (GetNTVersion() < _WIN32_WINNT_VISTA) { skip("realloc_flags_tests invalid for WS03.\n"); }
1905 else {
1906#endif
1907 for (i = 0; i < ARRAY_SIZE(realloc_flags_tests); i++)
1908 {
1909 struct mem_entry expect_entry, entry;
1910 BOOL expect_convert;
1911
1912 flags = realloc_flags_tests[i];
1913 expect_convert = (flags & (GMEM_MOVEABLE | GMEM_MODIFY)) == (GMEM_MOVEABLE | GMEM_MODIFY);
1914
1915 winetest_push_context( "flags %#x", flags );
1916
1917 mem = pGlobalAlloc( GMEM_FIXED, small_size );
1918 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
1919 ok( !is_mem_entry( mem ), "unexpected moveable %p\n", mem );
1920
1921 tmp_mem = GlobalReAlloc( mem, 512, flags );
1922 if (!expect_convert)
1923 {
1924 ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem );
1925 if (flags == GMEM_MODIFY) ok( tmp_mem == mem, "GlobalReAlloc returned %p\n", tmp_mem );
1926 else if (flags != GMEM_MOVEABLE) ok( !tmp_mem, "GlobalReAlloc succeeded\n" );
1927 else ok( tmp_mem != mem, "GlobalReAlloc returned %p\n", tmp_mem );
1928 }
1929 else
1930 {
1931 ok( is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem );
1932 entry = *mem_entry_from_HANDLE( tmp_mem );
1933 todo_wine ok( entry.ptr != mem, "got ptr %p was %p\n", entry.ptr, mem );
1934 if (flags & GMEM_DISCARDABLE) ok( (entry.flags & 0x7fff) == 0x7, "got flags %#Ix\n", entry.flags );
1935 else ok( (entry.flags & 0x7fff) == 0x3, "got flags %#Ix\n", entry.flags );
1936 }
1937 if (tmp_mem) mem = tmp_mem;
1938
1939 size = GlobalSize( mem );
1940 if (flags == GMEM_MOVEABLE) ok( size == 512, "GlobalSize returned %Iu\n", size );
1941 else ok( size == small_size, "GlobalSize returned %Iu\n", size );
1942
1943 mem = GlobalFree( mem );
1944 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
1945
1946
1947 mem = pGlobalAlloc( GMEM_FIXED, nolfh_size );
1948 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
1949 ok( !is_mem_entry( mem ), "unexpected moveable %p\n", mem );
1950
1951 tmp_mem = GlobalReAlloc( mem, nolfh_size + 512, flags );
1952 if (!expect_convert)
1953 {
1954 ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem );
1955 if (flags & GMEM_DISCARDABLE) ok( !tmp_mem, "GlobalReAlloc succeeded\n" );
1956 else ok( tmp_mem == mem, "GlobalReAlloc returned %p\n", tmp_mem );
1957 }
1958 else
1959 {
1960 ok( is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem );
1961 entry = *mem_entry_from_HANDLE( tmp_mem );
1962 todo_wine ok( entry.ptr != mem, "got ptr %p was %p\n", entry.ptr, mem );
1963 if (flags & GMEM_DISCARDABLE) ok( (entry.flags & 0x7fff) == 0x7, "got flags %#Ix\n", entry.flags );
1964 else ok( (entry.flags & 0x7fff) == 0x3, "got flags %#Ix\n", entry.flags );
1965 }
1966 if (tmp_mem) mem = tmp_mem;
1967
1968 size = GlobalSize( mem );
1969 if (flags & (GMEM_MODIFY | GMEM_DISCARDABLE)) ok( size == nolfh_size, "GlobalSize returned %Iu\n", size );
1970 else ok( size == nolfh_size + 512, "GlobalSize returned %Iu\n", size );
1971
1972 mem = GlobalFree( mem );
1973 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
1974
1975
1976 mem = pGlobalAlloc( GMEM_FIXED, small_size );
1977 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
1978 ok( !is_mem_entry( mem ), "unexpected moveable %p\n", mem );
1979
1980 tmp_mem = GlobalReAlloc( mem, 10, flags );
1981 if (!expect_convert)
1982 {
1983 ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem );
1984 if (flags == GMEM_MODIFY) ok( tmp_mem == mem, "GlobalReAlloc returned %p\n", tmp_mem );
1985 else if (flags != GMEM_MOVEABLE) todo_wine_if(!flags) ok( !tmp_mem, "GlobalReAlloc succeeded\n" );
1986 else todo_wine ok( tmp_mem != mem, "GlobalReAlloc returned %p\n", tmp_mem );
1987 }
1988 else
1989 {
1990 ok( is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem );
1991 entry = *mem_entry_from_HANDLE( tmp_mem );
1992 ok( entry.ptr == ptr, "got ptr %p was %p\n", entry.ptr, ptr );
1993 if (flags & GMEM_DISCARDABLE) ok( (entry.flags & 0x7fff) == 0x7, "got flags %#Ix\n", entry.flags );
1994 else ok( (entry.flags & 0x7fff) == 0x3, "got flags %#Ix\n", entry.flags );
1995 }
1996 if (tmp_mem) mem = tmp_mem;
1997
1998 size = GlobalSize( mem );
1999 if (flags == GMEM_MOVEABLE) ok( size == 10, "GlobalSize returned %Iu\n", size );
2000 else todo_wine_if(!flags) ok( size == small_size, "GlobalSize returned %Iu\n", size );
2001
2002 mem = GlobalFree( mem );
2003 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
2004
2005
2006 mem = pGlobalAlloc( GMEM_FIXED, nolfh_size );
2007 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
2008 ok( !is_mem_entry( mem ), "unexpected moveable %p\n", mem );
2009
2010 tmp_mem = GlobalReAlloc( mem, 10, flags );
2011 if (!expect_convert)
2012 {
2013 ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem );
2014 if (flags & GMEM_DISCARDABLE) ok( !tmp_mem, "GlobalReAlloc succeeded\n" );
2015 else ok( tmp_mem == mem, "GlobalReAlloc returned %p\n", tmp_mem );
2016 }
2017 else
2018 {
2019 ok( is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem );
2020 entry = *mem_entry_from_HANDLE( tmp_mem );
2021 ok( entry.ptr != ptr, "got ptr %p was %p\n", entry.ptr, ptr );
2022 if (flags & GMEM_DISCARDABLE) ok( (entry.flags & 0x7fff) == 0x7, "got flags %#Ix\n", entry.flags );
2023 else ok( (entry.flags & 0x7fff) == 0x3, "got flags %#Ix\n", entry.flags );
2024 }
2025 if (tmp_mem) mem = tmp_mem;
2026
2027 size = GlobalSize( mem );
2028 if (flags & (GMEM_MODIFY | GMEM_DISCARDABLE)) ok( size == nolfh_size, "GlobalSize returned %Iu\n", size );
2029 else ok( size == 10, "GlobalSize returned %Iu\n", size );
2030
2031 mem = GlobalFree( mem );
2032 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
2033
2034
2035 mem = pGlobalAlloc( GMEM_FIXED, small_size );
2036 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
2037 ok( !is_mem_entry( mem ), "unexpected moveable %p\n", mem );
2038
2039 tmp_mem = GlobalReAlloc( mem, 0, flags );
2040 if (!expect_convert)
2041 {
2042 ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem );
2043 if (flags == GMEM_MODIFY) ok( tmp_mem == mem, "GlobalReAlloc returned %p\n", tmp_mem );
2044 else if (flags != GMEM_MOVEABLE) ok( !tmp_mem, "GlobalReAlloc succeeded\n" );
2045 else ok( tmp_mem != mem, "GlobalReAlloc returned %p\n", tmp_mem );
2046 }
2047 else
2048 {
2049 ok( is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem );
2050 entry = *mem_entry_from_HANDLE( tmp_mem );
2051 ok( entry.ptr == ptr, "got ptr %p was %p\n", entry.ptr, ptr );
2052 if (flags & GMEM_DISCARDABLE) ok( (entry.flags & 0x7fff) == 0x7, "got flags %#Ix\n", entry.flags );
2053 else ok( (entry.flags & 0x7fff) == 0x3, "got flags %#Ix\n", entry.flags );
2054 }
2055 if (tmp_mem) mem = tmp_mem;
2056
2057 size = GlobalSize( mem );
2058 if (flags == GMEM_MOVEABLE) ok( size == 0 || broken( size == 1 ) /* w7 */, "GlobalSize returned %Iu\n", size );
2059 else ok( size == small_size, "GlobalSize returned %Iu\n", size );
2060
2061 mem = GlobalFree( mem );
2062 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
2063
2064
2065 mem = pGlobalAlloc( GMEM_FIXED, nolfh_size );
2066 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
2067 ok( !is_mem_entry( mem ), "unexpected moveable %p\n", mem );
2068
2069 tmp_mem = GlobalReAlloc( mem, 0, flags );
2070 if (!expect_convert)
2071 {
2072 ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem );
2073 if (flags & GMEM_DISCARDABLE) ok( !tmp_mem, "GlobalReAlloc succeeded\n" );
2074 else ok( tmp_mem == mem, "GlobalReAlloc returned %p\n", tmp_mem );
2075 }
2076 else
2077 {
2078 ok( is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem );
2079 entry = *mem_entry_from_HANDLE( tmp_mem );
2080 ok( entry.ptr != ptr, "got ptr %p was %p\n", entry.ptr, ptr );
2081 if (flags & GMEM_DISCARDABLE) ok( (entry.flags & 0x7fff) == 0x7, "got flags %#Ix\n", entry.flags );
2082 else ok( (entry.flags & 0x7fff) == 0x3, "got flags %#Ix\n", entry.flags );
2083 }
2084 if (tmp_mem) mem = tmp_mem;
2085
2086 size = GlobalSize( mem );
2087 if (flags & (GMEM_MODIFY | GMEM_DISCARDABLE)) ok( size == nolfh_size, "GlobalSize returned %Iu\n", size );
2088 else ok( size == 0 || broken( size == 1 ) /* w7 */, "GlobalSize returned %Iu\n", size );
2089
2090 mem = GlobalFree( mem );
2091 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
2092
2093
2094 mem = pGlobalAlloc( GMEM_MOVEABLE, small_size );
2095 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
2096 ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem );
2097 ptr = GlobalLock( mem );
2098 ok( !!ptr, "GlobalLock failed, error %lu\n", GetLastError() );
2099 expect_entry = *mem_entry_from_HANDLE( mem );
2100
2101 tmp_mem = GlobalReAlloc( mem, 512, flags );
2102 if (flags & GMEM_MODIFY) ok( tmp_mem == mem, "GlobalReAlloc returned %p\n", tmp_mem );
2103 else if (flags & GMEM_DISCARDABLE) ok( !tmp_mem, "GlobalReAlloc succeeded\n" );
2104 else if (flags & GMEM_MOVEABLE) ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
2105#ifdef __REACTOS__
2106 else ok( !tmp_mem || broken(GetNTVersion() == _WIN32_WINNT_VISTA), "GlobalReAlloc succeeded\n" );
2107#else
2108 else ok( !tmp_mem, "GlobalReAlloc succeeded\n" );
2109#endif
2111 if ((flags & GMEM_DISCARDABLE) && (flags & GMEM_MODIFY)) expect_entry.flags |= 4;
2112#ifdef __REACTOS__
2113 if (flags == GMEM_MOVEABLE) ok( entry.ptr != expect_entry.ptr || broken(GetNTVersion() == _WIN32_WINNT_VISTA), "got unexpected ptr %p\n", entry.ptr );
2114#else
2115 if (flags == GMEM_MOVEABLE) ok( entry.ptr != expect_entry.ptr, "got unexpected ptr %p\n", entry.ptr );
2116#endif
2117 else ok( entry.ptr == expect_entry.ptr, "got ptr %p\n", entry.ptr );
2118 ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags );
2119
2120 size = GlobalSize( mem );
2121 if (flags == GMEM_MOVEABLE) ok( size == 512, "GlobalSize returned %Iu\n", size );
2122#ifdef __REACTOS__
2123 else ok( size == small_size || broken(size == 512) /* Vista */, "GlobalSize returned %Iu\n", size );
2124#else
2125 else ok( size == small_size, "GlobalSize returned %Iu\n", size );
2126#endif
2127
2128 ret = GlobalUnlock( mem );
2129 ok( !ret, "GlobalUnlock succeeded\n" );
2130 mem = GlobalFree( mem );
2131 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
2132
2133
2134 mem = pGlobalAlloc( GMEM_MOVEABLE, small_size );
2135 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
2136 ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem );
2137 ptr = GlobalLock( mem );
2138 ok( !!ptr, "GlobalLock failed, error %lu\n", GetLastError() );
2139 expect_entry = *mem_entry_from_HANDLE( mem );
2140
2141 tmp_mem = GlobalReAlloc( mem, 10, flags );
2142 if (flags & GMEM_MODIFY) ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
2143 else if (flags & GMEM_DISCARDABLE) ok( !tmp_mem, "GlobalReAlloc succeeded\n" );
2144 else ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
2146 if ((flags & GMEM_DISCARDABLE) && (flags & GMEM_MODIFY)) expect_entry.flags |= 4;
2147 ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr );
2148 ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags );
2149
2150 size = GlobalSize( mem );
2151 if (flags & (GMEM_DISCARDABLE | GMEM_MODIFY)) ok( size == small_size, "GlobalSize returned %Iu\n", size );
2152 else ok( size == 10, "GlobalSize returned %Iu\n", size );
2153
2154 ret = GlobalUnlock( mem );
2155 ok( !ret, "GlobalUnlock succeeded\n" );
2156 mem = GlobalFree( mem );
2157 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
2158
2159
2160 mem = pGlobalAlloc( GMEM_MOVEABLE, small_size );
2161 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
2162 ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem );
2163 ptr = GlobalLock( mem );
2164 ok( !!ptr, "GlobalLock failed, error %lu\n", GetLastError() );
2165 expect_entry = *mem_entry_from_HANDLE( mem );
2166
2167 tmp_mem = GlobalReAlloc( mem, 0, flags );
2168 if (flags & GMEM_MODIFY) ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
2169 else ok( !tmp_mem, "GlobalReAlloc succeeded\n" );
2171 if ((flags & GMEM_DISCARDABLE) && (flags & GMEM_MODIFY)) expect_entry.flags |= 4;
2172 ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr );
2173 ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags );
2174
2175 size = GlobalSize( mem );
2176 ok( size == small_size, "GlobalSize returned %Iu\n", size );
2177
2178 ret = GlobalUnlock( mem );
2179 ok( !ret, "GlobalUnlock succeeded\n" );
2180 mem = GlobalFree( mem );
2181 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
2182
2183
2184 mem = pGlobalAlloc( GMEM_MOVEABLE, small_size );
2185 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
2186 ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem );
2187 expect_entry = *mem_entry_from_HANDLE( mem );
2188
2189 tmp_mem = GlobalReAlloc( mem, 512, flags );
2190 if (flags & GMEM_MODIFY) ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
2191 else if (flags & GMEM_DISCARDABLE) ok( !tmp_mem, "GlobalReAlloc succeeded\n" );
2192 else ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
2194 if ((flags & GMEM_DISCARDABLE) && (flags & GMEM_MODIFY)) expect_entry.flags |= 4;
2195 if (flags & (GMEM_DISCARDABLE | GMEM_MODIFY)) ok( entry.ptr == expect_entry.ptr, "got ptr %p\n", entry.ptr );
2196#ifdef __REACTOS__
2197 else ok( entry.ptr != expect_entry.ptr || broken(GetNTVersion() == _WIN32_WINNT_VISTA), "got unexpected ptr %p\n", entry.ptr );
2198#else
2199 else ok( entry.ptr != expect_entry.ptr, "got unexpected ptr %p\n", entry.ptr );
2200#endif
2201 ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags );
2202
2203 size = GlobalSize( mem );
2204 if (flags & (GMEM_DISCARDABLE | GMEM_MODIFY)) ok( size == small_size, "GlobalSize returned %Iu\n", size );
2205 else ok( size == 512, "GlobalSize returned %Iu\n", size );
2206
2207 mem = GlobalFree( mem );
2208 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
2209
2210
2211 mem = pGlobalAlloc( GMEM_MOVEABLE, small_size );
2212 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
2213 ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem );
2214 expect_entry = *mem_entry_from_HANDLE( mem );
2215
2216 tmp_mem = GlobalReAlloc( mem, 10, flags );
2217 if (flags & GMEM_MODIFY) ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
2218 else if (flags & GMEM_DISCARDABLE) ok( !tmp_mem, "GlobalReAlloc succeeded\n" );
2219 else ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
2221 if ((flags & GMEM_DISCARDABLE) && (flags & GMEM_MODIFY)) expect_entry.flags |= 4;
2222 ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr );
2223 ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags );
2224
2225 size = GlobalSize( mem );
2226 if (flags & (GMEM_DISCARDABLE | GMEM_MODIFY)) ok( size == small_size, "GlobalSize returned %Iu\n", size );
2227 else ok( size == 10, "GlobalSize returned %Iu\n", size );
2228
2229 mem = GlobalFree( mem );
2230 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
2231
2232
2233 mem = pGlobalAlloc( GMEM_MOVEABLE, small_size );
2234 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
2235 ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem );
2236 expect_entry = *mem_entry_from_HANDLE( mem );
2237
2238 tmp_mem = GlobalReAlloc( mem, 0, flags );
2239 if (flags & GMEM_MODIFY) ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
2240 else if (flags == GMEM_FIXED) ok( !tmp_mem, "GlobalReAlloc succeeded\n" );
2241 else if (flags & GMEM_DISCARDABLE) ok( !tmp_mem, "GlobalReAlloc succeeded\n" );
2242 else ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
2244 if (flags == GMEM_MOVEABLE)
2245 {
2246 expect_entry.flags |= 8;
2247 expect_entry.ptr = NULL;
2248 }
2249 else if ((flags & GMEM_DISCARDABLE) && (flags & GMEM_MODIFY)) expect_entry.flags |= 4;
2250 ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr );
2251 ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags );
2252
2253 size = GlobalSize( mem );
2254 if (flags == GMEM_MOVEABLE) ok( size == 0, "GlobalSize returned %Iu\n", size );
2255 else ok( size == small_size, "GlobalSize returned %Iu\n", size );
2256
2257 mem = GlobalFree( mem );
2258 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
2259
2261 }
2262#ifdef __REACTOS__
2263 }
2264#endif
2265
2266 mem = GlobalAlloc( GMEM_DDESHARE, 100 );
2267 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
2268 ret = GlobalUnlock( mem );
2269 ok( ret, "GlobalUnlock failed, error %lu\n", GetLastError() );
2270 ret = GlobalUnlock( mem );
2271 ok( ret, "GlobalUnlock failed, error %lu\n", GetLastError() );
2272
2273 memset( &walk_entry, 0xcd, sizeof(walk_entry) );
2274 walk_entry.lpData = NULL;
2275 ret = HeapLock( heap );
2276 ok( ret, "HeapLock failed, error %lu\n", GetLastError() );
2277 while ((ret = HeapWalk( heap, &walk_entry )))
2278 {
2279 ok( !(walk_entry.wFlags & PROCESS_HEAP_ENTRY_MOVEABLE), "got PROCESS_HEAP_ENTRY_MOVEABLE\n" );
2280 ok( !(walk_entry.wFlags & PROCESS_HEAP_ENTRY_DDESHARE), "got PROCESS_HEAP_ENTRY_DDESHARE\n" );
2281 }
2282 ok( GetLastError() == ERROR_NO_MORE_ITEMS, "got error %lu\n", GetLastError() );
2283 ret = HeapUnlock( heap );
2284 ok( ret, "HeapUnlock failed, error %lu\n", GetLastError() );
2285
2286 mem = GlobalFree( mem );
2287 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
2288
2289 mem = GlobalAlloc( GMEM_FIXED, 100 );
2290 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
2291 ret = GlobalUnlock( mem );
2292 ok( ret, "GlobalUnlock failed, error %lu\n", GetLastError() );
2293 tmp_mem = GlobalHandle( mem );
2294 ok( tmp_mem == mem, "GlobalHandle returned unexpected handle\n" );
2295 mem = GlobalFree( mem );
2296 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
2297
2298 mem = GlobalAlloc( GMEM_FIXED, 0 );
2299 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
2300 size = GlobalSize( mem );
2301 ok( size == 1, "GlobalSize returned %Iu\n", size );
2302 mem = GlobalFree( mem );
2303 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
2304
2305 /* trying to lock empty memory should give an error */
2307 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
2308 SetLastError( 0xdeadbeef );
2309 ptr = GlobalLock( mem );
2310 ok( !ptr, "GlobalLock succeeded\n" );
2311 ok( GetLastError() == ERROR_DISCARDED, "got error %lu\n", GetLastError() );
2312 mem = GlobalFree( mem );
2313 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
2314
2315 mem = GlobalAlloc( 0, buffer_size );
2316 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
2317 size = GlobalSize( mem );
2318 ok( size >= buffer_size, "GlobalSize returned %Iu, error %lu\n", size, GetLastError() );
2319 mem = GlobalFree( mem );
2320 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
2321
2323 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
2324 size = GlobalSize( mem );
2325 ok( size >= buffer_size, "GlobalSize returned %Iu, error %lu\n", size, GetLastError() );
2326 ptr = GlobalLock( mem );
2327 ok( !!ptr, "GlobalLock failed, error %lu\n", GetLastError() );
2328 ok( ptr == mem, "got ptr %p, expected %p\n", ptr, mem );
2329 ok( !memcmp( ptr, zero_buffer, buffer_size ), "GlobalAlloc didn't clear memory\n" );
2330
2331 /* Check that we can change GMEM_FIXED to GMEM_MOVEABLE */
2333 ok( !!mem, "GlobalReAlloc failed, error %lu\n", GetLastError() );
2334 ok( mem != ptr, "GlobalReAlloc returned unexpected handle\n" );
2335 size = GlobalSize( mem );
2336 ok( size == buffer_size, "GlobalSize returned %Iu, error %lu\n", size, GetLastError() );
2337
2338 ptr = GlobalLock( mem );
2339 ok( !!ptr, "GlobalLock failed, error %lu\n", GetLastError() );
2340 ok( ptr != mem, "got unexpected ptr %p\n", ptr );
2341 ret = GlobalUnlock( mem );
2342 ok( !ret, "GlobalUnlock succeeded, error %lu\n", GetLastError() );
2343 ok( GetLastError() == NO_ERROR, "got error %lu\n", GetLastError() );
2344
2346 ok( !!tmp_mem, "GlobalReAlloc failed\n" );
2347 ok( tmp_mem == mem || broken( tmp_mem != mem ) /* happens sometimes?? */,
2348 "GlobalReAlloc returned unexpected handle\n" );
2349 mem = tmp_mem;
2350
2351 size = GlobalSize( mem );
2352 ok( size >= 2 * buffer_size, "GlobalSize returned %Iu, error %lu\n", size, GetLastError() );
2353 ptr = GlobalLock( mem );
2354 ok( !!ptr, "GlobalLock failed, error %lu\n", GetLastError() );
2355 ok( ptr != mem, "got unexpected ptr %p\n", ptr );
2356 ok( !memcmp( ptr, zero_buffer, buffer_size ), "GlobalReAlloc didn't clear memory\n" );
2357 ok( !memcmp( ptr + buffer_size, zero_buffer, buffer_size ),
2358 "GlobalReAlloc didn't clear memory\n" );
2359
2360 tmp_mem = GlobalHandle( ptr );
2361 ok( tmp_mem == mem, "GlobalHandle returned unexpected handle\n" );
2362 /* Check that we can't discard locked memory */
2363 SetLastError( 0xdeadbeef );
2364 tmp_mem = GlobalDiscard( mem );
2365 ok( !tmp_mem, "GlobalDiscard succeeded\n" );
2366 ret = GlobalUnlock( mem );
2367 ok( !ret, "GlobalUnlock succeeded, error %lu\n", GetLastError() );
2368 ok( GetLastError() == NO_ERROR, "got error %lu\n", GetLastError() );
2369
2370 tmp_mem = GlobalDiscard( mem );
2371 ok( tmp_mem == mem, "GlobalDiscard failed, error %lu\n", GetLastError() );
2372 mem = GlobalFree( mem );
2373 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
2374
2375 for (i = 0; i < ARRAY_SIZE(flags_tests); i++)
2376 {
2377 mem = GlobalAlloc( flags_tests[i], 4 );
2378 ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
2379 flags = GlobalFlags( mem );
2380 ok( !(flags & ~(GMEM_DDESHARE | GMEM_DISCARDABLE)), "got flags %#x, error %lu\n", flags, GetLastError() );
2381 mem = GlobalFree( mem );
2382 ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() );
2383 }
2384
2385 ptr = HeapAlloc( GetProcessHeap(), 0, 16 );
2386 ok( !!ptr, "HeapAlloc failed, error %lu\n", GetLastError() );
2387 SetLastError( 0xdeadbeef );
2388 tmp_mem = GlobalHandle( ptr );
2389 ok( !!tmp_mem, "GlobalHandle failed, error %lu\n", GetLastError() );
2390 ok( tmp_mem == ptr, "GlobalHandle returned unexpected handle\n" );
2391 tmp_ptr = (void *)0xdeadbeef;
2392 tmp_flags = 0xdeadbeef;
2393 ret = pRtlGetUserInfoHeap( GetProcessHeap(), 0, ptr, (void **)&tmp_ptr, &tmp_flags );
2394 ok( ret, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() );
2395 ok( tmp_ptr == (void *)0xdeadbeef, "got user value %p\n", tmp_ptr );
2396 ok( tmp_flags == 0, "got user flags %#lx\n", tmp_flags );
2397 ret = HeapFree( GetProcessHeap(), 0, ptr );
2398 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
2399}
2400
2401static void test_LocalAlloc(void)
2402{
2403 static const UINT flags_tests[] =
2404 {
2405 LMEM_FIXED,
2411 };
2412 static const UINT realloc_flags_tests[] =
2413 {
2414 LMEM_FIXED,
2422 };
2423 static const char zero_buffer[100000] = {0};
2424 static const SIZE_T buffer_size = ARRAY_SIZE(zero_buffer);
2425 const HLOCAL invalid_mem = LongToHandle( 0xdeadbee0 + sizeof(void *) );
2426 void *const invalid_ptr = LongToHandle( 0xdeadbee0 );
2427 SIZE_T size, small_size = 12, nolfh_size = 0x20000;
2428 HLOCAL locals[0x10000];
2429 HLOCAL mem, tmp_mem;
2430 BYTE *ptr, *tmp_ptr;
2431 ULONG tmp_flags;
2432 UINT i, flags;
2433 BOOL ret;
2434
2435 mem = LocalFree( 0 );
2436 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
2437 mem = LocalReAlloc( 0, 10, LMEM_MOVEABLE );
2438 ok( !mem, "LocalReAlloc succeeded\n" );
2439
2440 for (i = 0; i < ARRAY_SIZE(locals); ++i)
2441 {
2443 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
2444 locals[i] = mem;
2445 }
2446
2447 SetLastError( 0xdeadbeef );
2449 ok( !mem, "LocalAlloc succeeded\n" );
2450 ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY, "got error %lu\n", GetLastError() );
2451 SetLastError( 0xdeadbeef );
2453 ok( !mem, "GlobalAlloc succeeded\n" );
2454 ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY, "got error %lu\n", GetLastError() );
2455
2457 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
2458 mem = LocalFree( mem );
2459 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
2460
2461 for (i = 0; i < ARRAY_SIZE(locals); ++i)
2462 {
2463 mem = LocalFree( locals[i] );
2464 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
2465 }
2466
2467 /* make sure LFH is enabled for some small block size */
2468 for (i = 0; i < 0x12; i++) locals[i] = pLocalAlloc( LMEM_FIXED, small_size );
2469 for (i = 0; i < 0x12; i++) LocalFree( locals[i] );
2470
2472 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
2474 ok( !!mem, "LocalReAlloc failed, error %lu\n", GetLastError() );
2475 size = LocalSize( mem );
2476 ok( size >= 10 && size <= 16, "LocalSize returned %Iu\n", size );
2478 ok( !!mem, "LocalReAlloc failed, error %lu\n", GetLastError() );
2479 size = LocalSize( mem );
2480 ok( size == 0, "LocalSize returned %Iu\n", size );
2482 ok( !!mem, "LocalReAlloc failed, error %lu\n", GetLastError() );
2483 size = LocalSize( mem );
2484 ok( size >= 10 && size <= 16, "LocalSize returned %Iu\n", size );
2485 tmp_mem = pLocalFree( mem );
2486 ok( !tmp_mem, "LocalFree failed, error %lu\n", GetLastError() );
2487 size = LocalSize( mem );
2488 ok( size == 0, "LocalSize returned %Iu\n", size );
2489
2490 mem = LocalAlloc( LMEM_MOVEABLE, 256 );
2491 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
2492 ptr = LocalLock( mem );
2493 ok( !!ptr, "LocalLock failed, error %lu\n", GetLastError() );
2494 ok( ptr != mem, "got unexpected ptr %p\n", ptr );
2495 tmp_mem = LocalHandle( ptr );
2496 ok( tmp_mem == mem, "LocalHandle returned unexpected handle\n" );
2497 flags = LocalFlags( mem );
2498 ok( flags == 1, "LocalFlags returned %#x, error %lu\n", flags, GetLastError() );
2499 tmp_ptr = LocalLock( mem );
2500 ok( !!tmp_ptr, "LocalLock failed, error %lu\n", GetLastError() );
2501 ok( tmp_ptr == ptr, "got ptr %p, expected %p\n", tmp_ptr, ptr );
2502 flags = LocalFlags( mem );
2503 ok( flags == 2, "LocalFlags returned %#x, error %lu\n", flags, GetLastError() );
2504 ret = LocalUnlock( mem );
2505 ok( ret, "LocalUnlock failed, error %lu\n", GetLastError() );
2506 flags = LocalFlags( mem );
2507 ok( flags == 1, "LocalFlags returned %#x, error %lu\n", flags, GetLastError() );
2508 SetLastError( 0xdeadbeef );
2509 ret = LocalUnlock( mem );
2510 ok( !ret, "LocalUnlock succeeded\n" );
2511 ok( GetLastError() == ERROR_SUCCESS, "got error %lu\n", GetLastError() );
2512 flags = LocalFlags( mem );
2513 ok( !flags, "LocalFlags returned %#x, error %lu\n", flags, GetLastError() );
2514 SetLastError( 0xdeadbeef );
2515 ret = LocalUnlock( mem );
2516 ok( !ret, "LocalUnlock succeeded\n" );
2517 ok( GetLastError() == ERROR_NOT_LOCKED, "got error %lu\n", GetLastError() );
2518 tmp_mem = LocalFree( mem );
2519 ok( !tmp_mem, "LocalFree failed, error %lu\n", GetLastError() );
2520
2521 /* freed handles are caught */
2522 mem = LocalAlloc( LMEM_MOVEABLE, 256 );
2523 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
2524 tmp_mem = pLocalFree( mem );
2525 ok( !tmp_mem, "LocalFree failed, error %lu\n", GetLastError() );
2526 SetLastError( 0xdeadbeef );
2527 tmp_mem = pLocalFree( mem );
2528 ok( tmp_mem == mem, "LocalFree succeeded\n" );
2529 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
2530 SetLastError( 0xdeadbeef );
2531 flags = LocalFlags( mem );
2532 ok( flags == LMEM_INVALID_HANDLE, "LocalFlags succeeded\n" );
2533 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
2534 SetLastError( 0xdeadbeef );
2535 size = LocalSize( mem );
2536 ok( size == 0, "LocalSize succeeded\n" );
2537 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
2538 SetLastError( 0xdeadbeef );
2539 ptr = LocalLock( mem );
2540 ok( !ptr, "LocalLock succeeded\n" );
2541 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
2542 SetLastError( 0xdeadbeef );
2543 ret = LocalUnlock( mem );
2544 ok( !ret, "LocalUnlock succeeded\n" );
2545 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
2546 SetLastError( 0xdeadbeef );
2547 tmp_mem = LocalReAlloc( mem, 0, LMEM_MOVEABLE );
2548 ok( !tmp_mem, "LocalReAlloc succeeded\n" );
2549 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
2550 if (sizeof(void *) != 8) /* crashes on 64-bit */
2551 {
2552 SetLastError( 0xdeadbeef );
2553 tmp_mem = LocalHandle( mem );
2554 ok( !tmp_mem, "LocalHandle succeeded\n" );
2555 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
2556 }
2557
2558#ifdef __REACTOS__
2559 if (is_reactos()) {
2560 ok(FALSE, "FIXME: invalid handle and invalid pointer tests crash on ReactOS!\n");
2561 } else {
2562#endif
2563 /* invalid handles are caught */
2564 SetLastError( 0xdeadbeef );
2565 tmp_mem = pLocalFree( invalid_mem );
2566 ok( tmp_mem == invalid_mem, "LocalFree succeeded\n" );
2567 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
2568 SetLastError( 0xdeadbeef );
2569 flags = LocalFlags( invalid_mem );
2570 ok( flags == LMEM_INVALID_HANDLE, "LocalFlags succeeded\n" );
2571 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
2572 SetLastError( 0xdeadbeef );
2573 size = LocalSize( invalid_mem );
2574 ok( size == 0, "LocalSize succeeded\n" );
2575 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
2576 SetLastError( 0xdeadbeef );
2577 ptr = LocalLock( invalid_mem );
2578 ok( !ptr, "LocalLock succeeded\n" );
2579 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
2580 SetLastError( 0xdeadbeef );
2581 ret = LocalUnlock( invalid_mem );
2582 ok( !ret, "LocalUnlock succeeded\n" );
2583 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
2584 SetLastError( 0xdeadbeef );
2585 tmp_mem = LocalReAlloc( invalid_mem, 0, LMEM_MOVEABLE );
2586 ok( !tmp_mem, "LocalReAlloc succeeded\n" );
2587 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
2588 if (sizeof(void *) != 8) /* crashes on 64-bit */
2589 {
2590 SetLastError( 0xdeadbeef );
2591 tmp_mem = LocalHandle( invalid_mem );
2592 ok( !tmp_mem, "LocalHandle succeeded\n" );
2593 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
2594 }
2595
2596 /* invalid pointers are caught */
2597 SetLastError( 0xdeadbeef );
2598 tmp_mem = pLocalFree( invalid_ptr );
2599 ok( tmp_mem == invalid_ptr, "LocalFree succeeded\n" );
2600 todo_wine
2601#ifdef __REACTOS__
2602 ok( GetLastError() == ERROR_NOACCESS || broken(GetLastError() == ERROR_INVALID_HANDLE) /* WS03 */, "got error %lu\n", GetLastError() );
2603#else
2604 ok( GetLastError() == ERROR_NOACCESS, "got error %lu\n", GetLastError() );
2605#endif
2606 SetLastError( 0xdeadbeef );
2607 flags = LocalFlags( invalid_ptr );
2608 todo_wine
2609 ok( flags == LMEM_INVALID_HANDLE, "LocalFlags succeeded\n" );
2610 todo_wine
2611#ifdef __REACTOS__
2612 ok( GetLastError() == ERROR_NOACCESS || broken(GetLastError() == ERROR_INVALID_HANDLE) /* WS03 */, "got error %lu\n", GetLastError() );
2613#else
2614 ok( GetLastError() == ERROR_NOACCESS, "got error %lu\n", GetLastError() );
2615#endif
2616 SetLastError( 0xdeadbeef );
2617 size = LocalSize( invalid_ptr );
2618 ok( size == 0, "LocalSize succeeded\n" );
2619 ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() );
2620 SetLastError( 0xdeadbeef );
2621 ptr = LocalLock( invalid_ptr );
2622 ok( !ptr, "LocalLock succeeded\n" );
2623 ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() );
2624 SetLastError( 0xdeadbeef );
2625 ret = LocalUnlock( invalid_ptr );
2626 ok( !ret, "LocalUnlock succeeded\n" );
2627 ok( GetLastError() == ERROR_NOT_LOCKED, "got error %lu\n", GetLastError() );
2628 SetLastError( 0xdeadbeef );
2629 tmp_mem = LocalReAlloc( invalid_ptr, 0, LMEM_MOVEABLE );
2630 ok( !tmp_mem, "LocalReAlloc succeeded\n" );
2631 todo_wine
2632 ok( GetLastError() == ERROR_NOACCESS, "got error %lu\n", GetLastError() );
2633 SetLastError( 0xdeadbeef );
2634 tmp_mem = LocalHandle( invalid_ptr );
2635 ok( !tmp_mem, "LocalHandle succeeded\n" );
2636 todo_wine
2637#ifdef __REACTOS__
2638 ok( GetLastError() == ERROR_NOACCESS || broken(GetLastError() == ERROR_INVALID_HANDLE) /* WS03 */, "got error %lu\n", GetLastError() );
2639#else
2640 ok( GetLastError() == ERROR_NOACCESS, "got error %lu\n", GetLastError() );
2641#endif
2642#ifdef __REACTOS__
2643 }
2644#endif
2645
2646 /* LMEM_FIXED block doesn't allow resize, though it succeeds with LMEM_MODIFY */
2647 mem = LocalAlloc( LMEM_FIXED, small_size );
2648 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
2649 tmp_mem = LocalReAlloc( mem, small_size - 1, LMEM_MODIFY );
2650 ok( !!tmp_mem, "LocalAlloc failed, error %lu\n", GetLastError() );
2651 ok( tmp_mem == mem, "got ptr %p, expected %p\n", tmp_mem, mem );
2652 size = LocalSize( mem );
2653 ok( size == small_size, "LocalSize returned %Iu\n", size );
2654 SetLastError( 0xdeadbeef );
2655#ifdef __REACTOS__
2657#endif
2658 tmp_mem = LocalReAlloc( mem, small_size, 0 );
2659 ok( !tmp_mem, "LocalReAlloc succeeded\n" );
2660 ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY, "got error %lu\n", GetLastError() );
2661#ifdef __REACTOS__
2662 }
2663#endif
2664 if (tmp_mem) mem = tmp_mem;
2665 tmp_mem = LocalReAlloc( mem, 1024 * 1024, LMEM_MODIFY );
2666 ok( !!tmp_mem, "LocalAlloc failed, error %lu\n", GetLastError() );
2667 ok( tmp_mem == mem, "got ptr %p, expected %p\n", tmp_mem, mem );
2668 size = LocalSize( mem );
2669 ok( size == small_size, "LocalSize returned %Iu\n", size );
2670 mem = LocalFree( mem );
2671 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
2672
2673 /* LMEM_FIXED block can be relocated with LMEM_MOVEABLE */
2674 mem = LocalAlloc( LMEM_FIXED, small_size );
2675 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
2676 tmp_mem = LocalReAlloc( mem, small_size + 1, LMEM_MOVEABLE );
2677 ok( !!tmp_mem, "LocalReAlloc failed, error %lu\n", GetLastError() );
2678#ifdef __REACTOS__
2680#endif
2681 ok( tmp_mem != mem, "LocalReAlloc didn't relocate memory\n" );
2682 ptr = LocalLock( tmp_mem );
2683 ok( !!ptr, "LocalLock failed, error %lu\n", GetLastError() );
2684 ok( ptr == tmp_mem, "got ptr %p, expected %p\n", ptr, tmp_mem );
2685 tmp_mem = LocalFree( tmp_mem );
2686 ok( !tmp_mem, "LocalFree failed, error %lu\n", GetLastError() );
2687
2688 /* test LocalReAlloc flags / LocalLock / size combinations */
2689
2690#ifdef __REACTOS__
2692 skip("realloc_flags_tests invalid for WS03.\n");
2693 } else {
2694#endif
2695 for (i = 0; i < ARRAY_SIZE(realloc_flags_tests); i++)
2696 {
2697 struct mem_entry expect_entry, entry;
2698
2699 flags = realloc_flags_tests[i];
2700
2701 winetest_push_context( "flags %#x", flags );
2702
2703 mem = pLocalAlloc( LMEM_FIXED, small_size );
2704 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
2705 ok( !is_mem_entry( mem ), "unexpected moveable %p\n", mem );
2706
2707 tmp_mem = LocalReAlloc( mem, 512, flags );
2708 ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem );
2709 if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p\n", tmp_mem );
2710 else if (flags != LMEM_MOVEABLE) ok( !tmp_mem, "LocalReAlloc succeeded\n" );
2711 else ok( tmp_mem != mem, "LocalReAlloc returned %p\n", tmp_mem );
2712 if (tmp_mem) mem = tmp_mem;
2713
2714 size = LocalSize( mem );
2715 if (flags == LMEM_MOVEABLE) ok( size == 512, "LocalSize returned %Iu\n", size );
2716 else ok( size == small_size, "LocalSize returned %Iu\n", size );
2717
2718 mem = LocalFree( mem );
2719 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
2720
2721
2722 mem = pLocalAlloc( LMEM_FIXED, nolfh_size );
2723 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
2724 ok( !is_mem_entry( mem ), "unexpected moveable %p\n", mem );
2725 tmp_mem = LocalReAlloc( mem, nolfh_size + 512, flags );
2726 ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem );
2727 if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p\n", tmp_mem );
2728 else if (flags & LMEM_DISCARDABLE) ok( !tmp_mem, "LocalReAlloc succeeded\n" );
2729 else ok( tmp_mem == mem, "LocalReAlloc returned %p\n", tmp_mem );
2730 size = LocalSize( mem );
2731 if (flags & (LMEM_DISCARDABLE | LMEM_MODIFY)) ok( size == nolfh_size, "LocalSize returned %Iu\n", size );
2732 else ok( size == nolfh_size + 512, "LocalSize returned %Iu\n", size );
2733 mem = LocalFree( mem );
2734 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
2735
2736
2737 mem = pLocalAlloc( LMEM_FIXED, small_size );
2738 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
2739 ok( !is_mem_entry( mem ), "unexpected moveable %p\n", mem );
2740
2741 tmp_mem = LocalReAlloc( mem, 10, flags );
2742 ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem );
2743 if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p\n", tmp_mem );
2744 else if (flags != LMEM_MOVEABLE) todo_wine_if(!flags) ok( !tmp_mem, "LocalReAlloc succeeded\n" );
2745 else todo_wine ok( tmp_mem != mem, "LocalReAlloc returned %p\n", tmp_mem );
2746 if (tmp_mem) mem = tmp_mem;
2747
2748 size = LocalSize( mem );
2749 if (flags == LMEM_MOVEABLE) ok( size == 10, "LocalSize returned %Iu\n", size );
2750 else todo_wine_if(!flags) ok( size == small_size, "LocalSize returned %Iu\n", size );
2751
2752 mem = LocalFree( mem );
2753 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
2754
2755
2756 mem = pLocalAlloc( LMEM_FIXED, nolfh_size );
2757 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
2758 ok( !is_mem_entry( mem ), "unexpected moveable %p\n", mem );
2759 tmp_mem = LocalReAlloc( mem, 10, flags );
2760 ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem );
2761 if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p\n", tmp_mem );
2762 else if (flags & LMEM_DISCARDABLE) ok( !tmp_mem, "LocalReAlloc succeeded\n" );
2763 else ok( tmp_mem == mem, "LocalReAlloc returned %p\n", tmp_mem );
2764 size = LocalSize( mem );
2765 if (flags & (LMEM_DISCARDABLE | LMEM_MODIFY)) ok( size == nolfh_size, "LocalSize returned %Iu\n", size );
2766 else ok( size == 10, "LocalSize returned %Iu\n", size );
2767 mem = LocalFree( mem );
2768 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
2769
2770
2771 mem = pLocalAlloc( LMEM_FIXED, small_size );
2772 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
2773 ok( !is_mem_entry( mem ), "unexpected moveable %p\n", mem );
2774
2775 tmp_mem = LocalReAlloc( mem, 0, flags );
2776 ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem );
2777 if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p\n", tmp_mem );
2778 else if (flags != LMEM_MOVEABLE) ok( !tmp_mem, "LocalReAlloc succeeded\n" );
2779 else ok( tmp_mem != mem, "LocalReAlloc returned %p\n", tmp_mem );
2780 if (tmp_mem) mem = tmp_mem;
2781
2782 size = LocalSize( mem );
2783 if (flags == LMEM_MOVEABLE) ok( size == 0 || broken( size == 1 ) /* w7 */, "LocalSize returned %Iu\n", size );
2784 else ok( size == small_size, "LocalSize returned %Iu\n", size );
2785
2786 mem = LocalFree( mem );
2787 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
2788
2789
2790 mem = pLocalAlloc( LMEM_FIXED, nolfh_size );
2791 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
2792 ok( !is_mem_entry( mem ), "unexpected moveable %p\n", mem );
2793 tmp_mem = LocalReAlloc( mem, 0, flags );
2794 ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem );
2795 if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p\n", tmp_mem );
2796 else if (flags & LMEM_DISCARDABLE) ok( !tmp_mem, "LocalReAlloc succeeded\n" );
2797 else ok( tmp_mem == mem, "LocalReAlloc returned %p\n", tmp_mem );
2798 size = LocalSize( mem );
2799 if (flags & (LMEM_DISCARDABLE | LMEM_MODIFY)) ok( size == nolfh_size, "LocalSize returned %Iu\n", size );
2800 else ok( size == 0 || broken( size == 1 ) /* w7 */, "LocalSize returned %Iu\n", size );
2801 mem = LocalFree( mem );
2802 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
2803
2804
2805 mem = pLocalAlloc( LMEM_MOVEABLE, small_size );
2806 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
2807 ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem );
2808 ptr = LocalLock( mem );
2809 ok( !!ptr, "LocalLock failed, error %lu\n", GetLastError() );
2810 expect_entry = *mem_entry_from_HANDLE( mem );
2811
2812 tmp_mem = LocalReAlloc( mem, 512, flags );
2813 if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p\n", tmp_mem );
2814 else if (flags & LMEM_DISCARDABLE) ok( !tmp_mem, "LocalReAlloc succeeded\n" );
2815 else if (flags & LMEM_MOVEABLE) ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
2816#ifdef __REACTOS__
2817 else ok( !tmp_mem || broken(GetNTVersion() == _WIN32_WINNT_VISTA), "LocalReAlloc succeeded\n" );
2818#else
2819 else ok( !tmp_mem, "LocalReAlloc succeeded\n" );
2820#endif
2822 if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4;
2823#ifdef __REACTOS__
2824 if (flags == LMEM_MOVEABLE) ok( entry.ptr != expect_entry.ptr || broken(GetNTVersion() == _WIN32_WINNT_VISTA), "got unexpected ptr %p\n", entry.ptr );
2825#else
2826 if (flags == LMEM_MOVEABLE) ok( entry.ptr != expect_entry.ptr, "got unexpected ptr %p\n", entry.ptr );
2827#endif
2828 else ok( entry.ptr == expect_entry.ptr, "got ptr %p\n", entry.ptr );
2829 ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags );
2830
2831 size = LocalSize( mem );
2832 if (flags == LMEM_MOVEABLE) ok( size == 512, "LocalSize returned %Iu\n", size );
2833#ifdef __REACTOS__
2834 else ok( size == small_size || broken(size == 512) /* Vista */, "LocalSize returned %Iu\n", size );
2835#else
2836 else ok( size == small_size, "LocalSize returned %Iu\n", size );
2837#endif
2838
2839 ret = LocalUnlock( mem );
2840 ok( !ret, "LocalUnlock succeeded\n" );
2841 mem = LocalFree( mem );
2842 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
2843
2844
2845 mem = pLocalAlloc( LMEM_MOVEABLE, nolfh_size );
2846 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
2847 ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem );
2848 ptr = LocalLock( mem );
2849 ok( !!ptr, "LocalLock failed, error %lu\n", GetLastError() );
2850 expect_entry = *mem_entry_from_HANDLE( mem );
2851
2852 tmp_mem = LocalReAlloc( mem, nolfh_size + 512, flags );
2853 if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p\n", tmp_mem );
2854 else if (flags & LMEM_DISCARDABLE) ok( !tmp_mem, "LocalReAlloc succeeded\n" );
2855 else ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
2857 if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4;
2858 ok( entry.ptr == expect_entry.ptr, "got ptr %p\n", entry.ptr );
2859 ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags );
2860
2861 size = LocalSize( mem );
2862 if (flags & (LMEM_DISCARDABLE | LMEM_MODIFY)) ok( size == nolfh_size, "LocalSize returned %Iu\n", size );
2863 else ok( size == nolfh_size + 512, "LocalSize returned %Iu\n", size );
2864
2865 ret = LocalUnlock( mem );
2866 ok( !ret, "LocalUnlock succeeded\n" );
2867 mem = LocalFree( mem );
2868 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
2869
2870
2871 mem = pLocalAlloc( LMEM_MOVEABLE, small_size );
2872 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
2873 ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem );
2874 ptr = LocalLock( mem );
2875 ok( !!ptr, "LocalLock failed, error %lu\n", GetLastError() );
2876 expect_entry = *mem_entry_from_HANDLE( mem );
2877
2878 tmp_mem = LocalReAlloc( mem, 10, flags );
2879 if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p\n", tmp_mem );
2880 else if (flags & LMEM_DISCARDABLE) ok( !tmp_mem, "LocalReAlloc succeeded\n" );
2881 else ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
2883 if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4;
2884 ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr );
2885 ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags );
2886
2887 size = LocalSize( mem );
2888 if (flags & (LMEM_DISCARDABLE | LMEM_MODIFY)) ok( size == small_size, "LocalSize returned %Iu\n", size );
2889 else ok( size == 10, "LocalSize returned %Iu\n", size );
2890
2891 ret = LocalUnlock( mem );
2892 ok( !ret, "LocalUnlock succeeded\n" );
2893 mem = LocalFree( mem );
2894 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
2895
2896
2897 mem = pLocalAlloc( LMEM_MOVEABLE, nolfh_size );
2898 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
2899 ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem );
2900 ptr = LocalLock( mem );
2901 ok( !!ptr, "LocalLock failed, error %lu\n", GetLastError() );
2902 expect_entry = *mem_entry_from_HANDLE( mem );
2903
2904 tmp_mem = LocalReAlloc( mem, 10, flags );
2905 if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p\n", tmp_mem );
2906 else if (flags & LMEM_DISCARDABLE) ok( !tmp_mem, "LocalReAlloc succeeded\n" );
2907 else ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
2909 if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4;
2910 ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr );
2911 ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags );
2912
2913 size = LocalSize( mem );
2914 if (flags & (LMEM_DISCARDABLE | LMEM_MODIFY)) ok( size == nolfh_size, "LocalSize returned %Iu\n", size );
2915 else ok( size == 10, "LocalSize returned %Iu\n", size );
2916
2917 ret = LocalUnlock( mem );
2918 ok( !ret, "LocalUnlock succeeded\n" );
2919 mem = LocalFree( mem );
2920 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
2921
2922
2923 mem = pLocalAlloc( LMEM_MOVEABLE, small_size );
2924 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
2925 ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem );
2926 ptr = LocalLock( mem );
2927 ok( !!ptr, "LocalLock failed, error %lu\n", GetLastError() );
2928 expect_entry = *mem_entry_from_HANDLE( mem );
2929
2930 tmp_mem = LocalReAlloc( mem, 0, flags );
2931 if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
2932 else ok( !tmp_mem, "LocalReAlloc succeeded\n" );
2934 if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4;
2935 ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr );
2936 ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags );
2937
2938 size = LocalSize( mem );
2939 ok( size == small_size, "LocalSize returned %Iu\n", size );
2940
2941 ret = LocalUnlock( mem );
2942 ok( !ret, "LocalUnlock succeeded\n" );
2943 mem = LocalFree( mem );
2944 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
2945
2946
2947 mem = pLocalAlloc( LMEM_MOVEABLE, nolfh_size );
2948 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
2949 ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem );
2950 ptr = LocalLock( mem );
2951 ok( !!ptr, "LocalLock failed, error %lu\n", GetLastError() );
2952 expect_entry = *mem_entry_from_HANDLE( mem );
2953
2954 tmp_mem = LocalReAlloc( mem, 0, flags );
2955 if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
2956 else ok( !tmp_mem, "LocalReAlloc succeeded\n" );
2958 if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4;
2959 ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr );
2960 ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags );
2961
2962 size = LocalSize( mem );
2963 ok( size == nolfh_size, "LocalSize returned %Iu\n", size );
2964
2965 ret = LocalUnlock( mem );
2966 ok( !ret, "LocalUnlock succeeded\n" );
2967 mem = LocalFree( mem );
2968 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
2969
2970
2971 mem = pLocalAlloc( LMEM_MOVEABLE, small_size );
2972 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
2973 ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem );
2974 expect_entry = *mem_entry_from_HANDLE( mem );
2975
2976 tmp_mem = LocalReAlloc( mem, 512, flags );
2977 if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
2978 else if (flags & LMEM_DISCARDABLE) ok( !tmp_mem, "LocalReAlloc succeeded\n" );
2979 else ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
2981 if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4;
2982 if (flags & (LMEM_DISCARDABLE | LMEM_MODIFY)) ok( entry.ptr == expect_entry.ptr, "got ptr %p\n", entry.ptr );
2983#ifdef __REACTOS__
2984 else ok( entry.ptr != expect_entry.ptr || broken(GetNTVersion() == _WIN32_WINNT_VISTA), "got unexpected ptr %p\n", entry.ptr );
2985#else
2986 else ok( entry.ptr != expect_entry.ptr, "got unexpected ptr %p\n", entry.ptr );
2987#endif
2988 ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags );
2989
2990 size = LocalSize( mem );
2991 if (flags & (LMEM_DISCARDABLE | LMEM_MODIFY)) ok( size == small_size, "LocalSize returned %Iu\n", size );
2992 else ok( size == 512, "LocalSize returned %Iu\n", size );
2993
2994 mem = LocalFree( mem );
2995 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
2996
2997
2998 mem = pLocalAlloc( LMEM_MOVEABLE, nolfh_size );
2999 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
3000 ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem );
3001 expect_entry = *mem_entry_from_HANDLE( mem );
3002
3003 tmp_mem = LocalReAlloc( mem, nolfh_size + 512, flags );
3004 if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
3005 else if (flags & LMEM_DISCARDABLE) ok( !tmp_mem, "LocalReAlloc succeeded\n" );
3006 else ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
3008 if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4;
3009 ok( entry.ptr == expect_entry.ptr, "got unexpected ptr %p\n", entry.ptr );
3010 ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags );
3011
3012 size = LocalSize( mem );
3013 if (flags & (LMEM_DISCARDABLE | LMEM_MODIFY)) ok( size == nolfh_size, "LocalSize returned %Iu\n", size );
3014 else ok( size == nolfh_size + 512, "LocalSize returned %Iu\n", size );
3015
3016 mem = LocalFree( mem );
3017 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
3018
3019
3020 mem = pLocalAlloc( LMEM_MOVEABLE, small_size );
3021 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
3022 ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem );
3023 expect_entry = *mem_entry_from_HANDLE( mem );
3024
3025 tmp_mem = LocalReAlloc( mem, 10, flags );
3026 if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
3027 else if (flags & LMEM_DISCARDABLE) ok( !tmp_mem, "LocalReAlloc succeeded\n" );
3028 else ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
3030 if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4;
3031 ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr );
3032 ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags );
3033
3034 size = LocalSize( mem );
3035 if (flags & (LMEM_DISCARDABLE | LMEM_MODIFY)) ok( size == small_size, "LocalSize returned %Iu\n", size );
3036 else ok( size == 10, "LocalSize returned %Iu\n", size );
3037
3038 mem = LocalFree( mem );
3039 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
3040
3041
3042 mem = pLocalAlloc( LMEM_MOVEABLE, nolfh_size );
3043 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
3044 ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem );
3045 expect_entry = *mem_entry_from_HANDLE( mem );
3046
3047 tmp_mem = LocalReAlloc( mem, 10, flags );
3048 if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
3049 else if (flags & LMEM_DISCARDABLE) ok( !tmp_mem, "LocalReAlloc succeeded\n" );
3050 else ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
3052 if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4;
3053 ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr );
3054 ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags );
3055
3056 size = LocalSize( mem );
3057 if (flags & (LMEM_DISCARDABLE | LMEM_MODIFY)) ok( size == nolfh_size, "LocalSize returned %Iu\n", size );
3058 else ok( size == 10, "LocalSize returned %Iu\n", size );
3059
3060 mem = LocalFree( mem );
3061 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
3062
3063
3064 mem = pLocalAlloc( LMEM_MOVEABLE, small_size );
3065 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
3066 ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem );
3067 expect_entry = *mem_entry_from_HANDLE( mem );
3068
3069 tmp_mem = LocalReAlloc( mem, 0, flags );
3070 if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
3071 else if (flags == LMEM_FIXED) ok( !tmp_mem, "LocalReAlloc succeeded\n" );
3072 else if (flags & LMEM_DISCARDABLE) ok( !tmp_mem, "LocalReAlloc succeeded\n" );
3073 else ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
3075 if (flags == LMEM_MOVEABLE)
3076 {
3077 expect_entry.flags |= 8;
3078 expect_entry.ptr = NULL;
3079 }
3080 else if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4;
3081 ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr );
3082 ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags );
3083
3084 size = LocalSize( mem );
3085 if (flags == LMEM_MOVEABLE) ok( size == 0, "LocalSize returned %Iu\n", size );
3086 else ok( size == small_size, "LocalSize returned %Iu\n", size );
3087
3088 mem = LocalFree( mem );
3089 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
3090
3091
3092 mem = pLocalAlloc( LMEM_MOVEABLE, nolfh_size );
3093 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
3094 ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem );
3095 expect_entry = *mem_entry_from_HANDLE( mem );
3096
3097 tmp_mem = LocalReAlloc( mem, 0, flags );
3098 if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
3099 else if (flags == LMEM_FIXED) ok( !tmp_mem, "LocalReAlloc succeeded\n" );
3100 else if (flags & LMEM_DISCARDABLE) ok( !tmp_mem, "LocalReAlloc succeeded\n" );
3101 else ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() );
3103 if (flags == LMEM_MOVEABLE)
3104 {
3105 expect_entry.flags |= 8;
3106 expect_entry.ptr = NULL;
3107 }
3108 else if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4;
3109 ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr );
3110 ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags );
3111
3112 size = LocalSize( mem );
3113 if (flags == LMEM_MOVEABLE) ok( size == 0, "LocalSize returned %Iu\n", size );
3114 else ok( size == nolfh_size, "LocalSize returned %Iu\n", size );
3115
3116 mem = LocalFree( mem );
3117 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
3118
3120 }
3121#ifdef __REACTOS__
3122 }
3123#endif
3124
3125 mem = LocalAlloc( LMEM_FIXED, 100 );
3126 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
3127 SetLastError( 0xdeadbeef );
3128 ret = LocalUnlock( mem );
3129 ok( !ret, "LocalUnlock succeeded\n" );
3130 ok( GetLastError() == ERROR_NOT_LOCKED, "got error %lu\n", GetLastError() );
3131 tmp_mem = LocalHandle( mem );
3132 ok( tmp_mem == mem, "LocalHandle returned unexpected handle\n" );
3133 mem = LocalFree( mem );
3134 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
3135
3136 mem = LocalAlloc( LMEM_FIXED, 0 );
3137 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
3138 SetLastError( 0xdeadbeef );
3139 size = LocalSize( mem );
3140#ifdef __REACTOS__
3141 ok( size == 0 || broken(size == 1) /* Vista */, "LocalSize returned %Iu\n", size );
3142#else
3143 ok( size == 0, "LocalSize returned %Iu\n", size );
3144#endif
3145 mem = LocalFree( mem );
3146 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
3147
3148 /* trying to lock empty memory should give an error */
3150 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
3151 SetLastError( 0xdeadbeef );
3152 ptr = LocalLock( mem );
3153 ok( !ptr, "LocalLock succeeded\n" );
3154 ok( GetLastError() == ERROR_DISCARDED, "got error %lu\n", GetLastError() );
3155 mem = LocalFree( mem );
3156 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
3157
3158 mem = LocalAlloc( 0, buffer_size );
3159 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
3160 size = LocalSize( mem );
3161 ok( size >= buffer_size, "LocalSize returned %Iu, error %lu\n", size, GetLastError() );
3162 mem = LocalFree( mem );
3163 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
3164
3166 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
3167 size = LocalSize( mem );
3168 ok( size >= buffer_size, "LocalSize returned %Iu, error %lu\n", size, GetLastError() );
3169 ptr = LocalLock( mem );
3170 ok( !!ptr, "LocalLock failed, error %lu\n", GetLastError() );
3171 ok( ptr == mem, "got ptr %p, expected %p\n", ptr, mem );
3172 ok( !memcmp( ptr, zero_buffer, buffer_size ), "LocalAlloc didn't clear memory\n" );
3173
3174 /* Check that we cannot change LMEM_FIXED to LMEM_MOVEABLE */
3176 ok( !!mem, "LocalReAlloc failed, error %lu\n", GetLastError() );
3177 ok( mem == ptr, "LocalReAlloc returned unexpected handle\n" );
3178 size = LocalSize( mem );
3179 ok( size == buffer_size, "LocalSize returned %Iu, error %lu\n", size, GetLastError() );
3180
3181 ptr = LocalLock( mem );
3182 ok( !!ptr, "LocalLock failed, error %lu\n", GetLastError() );
3183 ok( ptr == mem, "got unexpected ptr %p\n", ptr );
3184 ret = LocalUnlock( mem );
3185 ok( !ret, "LocalUnlock succeeded, error %lu\n", GetLastError() );
3186 ok( GetLastError() == ERROR_NOT_LOCKED, "got error %lu\n", GetLastError() );
3187
3189 ok( !!tmp_mem, "LocalReAlloc failed\n" );
3190 ok( tmp_mem == mem || broken( tmp_mem != mem ) /* happens sometimes?? */,
3191 "LocalReAlloc returned unexpected handle\n" );
3192 mem = tmp_mem;
3193
3194 size = LocalSize( mem );
3195 ok( size >= 2 * buffer_size, "LocalSize returned %Iu, error %lu\n", size, GetLastError() );
3196 ptr = LocalLock( mem );
3197 ok( !!ptr, "LocalLock failed, error %lu\n", GetLastError() );
3198 ok( ptr == mem, "got unexpected ptr %p\n", ptr );
3199 ok( !memcmp( ptr, zero_buffer, buffer_size ), "LocalReAlloc didn't clear memory\n" );
3200 ok( !memcmp( ptr + buffer_size, zero_buffer, buffer_size ),
3201 "LocalReAlloc didn't clear memory\n" );
3202
3203 tmp_mem = LocalHandle( ptr );
3204 ok( tmp_mem == mem, "LocalHandle returned unexpected handle\n" );
3205 tmp_mem = LocalDiscard( mem );
3206 ok( !!tmp_mem, "LocalDiscard failed, error %lu\n", GetLastError() );
3207 ok( tmp_mem == mem, "LocalDiscard returned unexpected handle\n" );
3208 ret = LocalUnlock( mem );
3209 ok( !ret, "LocalUnlock succeeded, error %lu\n", GetLastError() );
3210 ok( GetLastError() == ERROR_NOT_LOCKED, "got error %lu\n", GetLastError() );
3211
3212 tmp_mem = LocalDiscard( mem );
3213 ok( tmp_mem == mem, "LocalDiscard failed, error %lu\n", GetLastError() );
3214 mem = LocalFree( mem );
3215 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
3216
3217 for (i = 0; i < ARRAY_SIZE(flags_tests); i++)
3218 {
3219 mem = LocalAlloc( flags_tests[i], 4 );
3220 ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
3221 flags = LocalFlags( mem );
3222 ok( !(flags & ~LMEM_DISCARDABLE), "got flags %#x, error %lu\n", flags, GetLastError() );
3223 mem = LocalFree( mem );
3224 ok( !mem, "LocalFree failed, error %lu\n", GetLastError() );
3225 }
3226
3227 ptr = HeapAlloc( GetProcessHeap(), 0, 16 );
3228 ok( !!ptr, "HeapAlloc failed, error %lu\n", GetLastError() );
3229 SetLastError( 0xdeadbeef );
3230 tmp_mem = LocalHandle( ptr );
3231 ok( !!tmp_mem, "LocalHandle failed, error %lu\n", GetLastError() );
3232 ok( tmp_mem == ptr, "LocalHandle returned unexpected handle\n" );
3233 tmp_ptr = (void *)0xdeadbeef;
3234 tmp_flags = 0xdeadbeef;
3235 ret = pRtlGetUserInfoHeap( GetProcessHeap(), 0, ptr, (void **)&tmp_ptr, &tmp_flags );
3236 ok( ret, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() );
3237 ok( tmp_ptr == (void *)0xdeadbeef, "got user value %p\n", tmp_ptr );
3238 ok( tmp_flags == 0, "got user flags %#lx\n", tmp_flags );
3239 ret = HeapFree( GetProcessHeap(), 0, ptr );
3240 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
3241}
3242
3243static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags, DWORD alloc_flags )
3244{
3246 SIZE_T expect_size, diff, alloc_size, extra_size, tail_size = 0;
3247 unsigned char *ptr0, *ptr1, *ptr2, tail;
3248 char tail_buf[64], padd_buf[64];
3249 void *tmp_ptr, **user_ptr;
3250 ULONG tmp_flags;
3252 BOOL ret;
3253
3256 {
3257 skip( "skipping block tests\n" );
3258 return;
3259 }
3260
3261 if (!global_flags && !alloc_flags) extra_size = 8;
3262 else extra_size = 2 * sizeof(void *);
3263 if (heap_flags & HEAP_TAIL_CHECKING_ENABLED) extra_size += 2 * sizeof(void *);
3264 if (heap_flags & padd_flags) extra_size += 2 * sizeof(void *);
3265
3266 if ((heap_flags & HEAP_TAIL_CHECKING_ENABLED)) tail_size = 2 * sizeof(void *);
3267 memset( tail_buf, 0xab, sizeof(tail_buf) );
3268 memset( padd_buf, 0, sizeof(padd_buf) );
3269
3270 for (alloc_size = 0x20000 * sizeof(void *) - 0x3000; alloc_size > 0; alloc_size >>= 1)
3271 {
3272 winetest_push_context( "size %#Ix", alloc_size );
3273
3274 ptr0 = pHeapAlloc( heap, alloc_flags|HEAP_ZERO_MEMORY, alloc_size );
3275 ok( !!ptr0, "HeapAlloc failed, error %lu\n", GetLastError() );
3276 ptr1 = pHeapAlloc( heap, alloc_flags|HEAP_ZERO_MEMORY, alloc_size );
3277 ok( !!ptr1, "HeapAlloc failed, error %lu\n", GetLastError() );
3278 ptr2 = pHeapAlloc( heap, alloc_flags|HEAP_ZERO_MEMORY, alloc_size );
3279 ok( !!ptr2, "HeapAlloc failed, error %lu\n", GetLastError() );
3280
3281 align = (UINT_PTR)ptr0 | (UINT_PTR)ptr1 | (UINT_PTR)ptr2;
3282 ok( !(align & (2 * sizeof(void *) - 1)), "wrong align\n" );
3283
3284 expect_size = max( alloc_size, 2 * sizeof(void *) );
3285 expect_size = ALIGN_BLOCK_SIZE( expect_size + extra_size );
3286 diff = min( llabs( ptr2 - ptr1 ), llabs( ptr1 - ptr0 ) );
3287 todo_wine_if( (!global_flags && alloc_size < 2 * sizeof(void *)) ||
3288 ((heap_flags & HEAP_FREE_CHECKING_ENABLED) && diff >= 0x100000) )
3289#ifdef __REACTOS__
3291#endif
3292 ok( diff == expect_size, "got diff %#Ix exp %#Ix\n", diff, expect_size );
3293 ok( !memcmp( ptr0 + alloc_size, tail_buf, tail_size ), "missing block tail\n" );
3294 ok( !memcmp( ptr1 + alloc_size, tail_buf, tail_size ), "missing block tail\n" );
3295 ok( !memcmp( ptr2 + alloc_size, tail_buf, tail_size ), "missing block tail\n" );
3296
3297 ret = HeapFree( heap, 0, ptr2 );
3298 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
3299 ret = HeapFree( heap, 0, ptr1 );
3300 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
3301 ret = HeapFree( heap, 0, ptr0 );
3302 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
3303
3305
3306 if (diff != expect_size)
3307 {
3308 todo_wine
3309 win_skip("skipping sizes\n");
3310 break;
3311 }
3312 }
3313
3314
3315 /* between the two thresholds, tail may still be set but block position is inconsistent */
3316
3317 alloc_size = 0x20000 * sizeof(void *) - 0x2000;
3318 winetest_push_context( "size %#Ix", alloc_size );
3319
3320 ptr0 = pHeapAlloc( heap, alloc_flags|HEAP_ZERO_MEMORY, alloc_size );
3321 ok( !!ptr0, "HeapAlloc failed, error %lu\n", GetLastError() );
3322 ok( !((UINT_PTR)ptr0 & (2 * sizeof(void *) - 1)), "got unexpected ptr align\n" );
3323
3324 ok( !memcmp( ptr0 + alloc_size, tail_buf, tail_size ), "missing block tail\n" );
3325
3326 ret = HeapFree( heap, 0, ptr0 );
3327 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
3328
3330
3331
3332 for (alloc_size = 0x20000 * sizeof(void *) - 0x1000; alloc_size < 0x800000; alloc_size <<= 1)
3333 {
3334 winetest_push_context( "size %#Ix", alloc_size );
3335
3336 ptr0 = pHeapAlloc( heap, alloc_flags|HEAP_ZERO_MEMORY, alloc_size );
3337 ok( !!ptr0, "HeapAlloc failed, error %lu\n", GetLastError() );
3338 ptr1 = pHeapAlloc( heap, alloc_flags, alloc_size );
3339 ok( !!ptr1, "HeapAlloc failed, error %lu\n", GetLastError() );
3340 ptr2 = pHeapAlloc( heap, alloc_flags, alloc_size );
3341 ok( !!ptr2, "HeapAlloc failed, error %lu\n", GetLastError() );
3342
3343 align = (UINT_PTR)ptr0 | (UINT_PTR)ptr1 | (UINT_PTR)ptr2;
3344 ok( !(align & (8 * sizeof(void *) - 1)), "wrong align\n" );
3345
3346 expect_size = max( alloc_size, 2 * sizeof(void *) );
3347 expect_size = ALIGN_BLOCK_SIZE( expect_size + extra_size );
3348 diff = min( llabs( ptr2 - ptr1 ), llabs( ptr1 - ptr0 ) );
3349 todo_wine_if( alloc_size == 0x7efe9 )
3350 ok( diff > expect_size, "got diff %#Ix\n", diff );
3351
3352 tail = ptr0[alloc_size] | ptr1[alloc_size] | ptr2[alloc_size];
3353 ok( !tail, "got tail\n" );
3354
3355 ret = HeapFree( heap, 0, ptr2 );
3356 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
3357 ret = HeapFree( heap, 0, ptr1 );
3358 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
3359 ret = HeapFree( heap, 0, ptr0 );
3360 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
3362
3363 if (diff == expect_size || (align & (8 * sizeof(void *) - 1)) || tail)
3364 {
3365 todo_wine
3366 win_skip("skipping sizes\n");
3367 break;
3368 }
3369 }
3370
3371 /* Undocumented HEAP_ADD_USER_INFO flag can be used to force an additional padding
3372 * on small block sizes. Small block use it to store user info, larger blocks
3373 * store them in their block header instead.
3374 *
3375 * RtlGetUserInfoHeap also requires the flag to work consistently, and otherwise
3376 * causes crashes when heap flags are used, or on 32-bit.
3377 */
3378 if (!(heap_flags & padd_flags))
3379 {
3380 alloc_size = 0x1000;
3381 winetest_push_context( "size %#Ix", alloc_size );
3382 ptr0 = pHeapAlloc( heap, 0xc00|HEAP_ADD_USER_INFO, alloc_size );
3383 ok( !!ptr0, "HeapAlloc failed, error %lu\n", GetLastError() );
3384 ptr1 = HeapAlloc( heap, 0x200|HEAP_ADD_USER_INFO, alloc_size );
3385 ok( !!ptr1, "HeapAlloc failed, error %lu\n", GetLastError() );
3386 ptr2 = HeapAlloc( heap, HEAP_ADD_USER_INFO, alloc_size );
3387 ok( !!ptr2, "HeapAlloc failed, error %lu\n", GetLastError() );
3388
3389 expect_size = max( alloc_size, 2 * sizeof(void *) );
3390 expect_size = ALIGN_BLOCK_SIZE( expect_size + extra_size + 2 * sizeof(void *) );
3391 diff = min( llabs( ptr2 - ptr1 ), llabs( ptr1 - ptr0 ) );
3392 ok( diff == expect_size, "got diff %#Ix\n", diff );
3393
3394 ok( !memcmp( ptr0 + alloc_size, tail_buf, tail_size ), "missing block tail\n" );
3395 ok( !memcmp( ptr1 + alloc_size, tail_buf, tail_size ), "missing block tail\n" );
3396 ok( !memcmp( ptr2 + alloc_size, tail_buf, tail_size ), "missing block tail\n" );
3397
3398 ok( !memcmp( ptr0 + alloc_size + tail_size, padd_buf, 2 * sizeof(void *) ), "unexpected padding\n" );
3399
3400 tmp_ptr = (void *)0xdeadbeef;
3401 tmp_flags = 0xdeadbeef;
3402 ret = pRtlGetUserInfoHeap( heap, 0, ptr0, (void **)&tmp_ptr, &tmp_flags );
3403 ok( ret, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() );
3404 ok( tmp_ptr == NULL, "got ptr %p\n", tmp_ptr );
3405 ok( tmp_flags == 0xc00, "got flags %#lx\n", tmp_flags );
3406
3407 tmp_ptr = (void *)0xdeadbeef;
3408 tmp_flags = 0xdeadbeef;
3409 ret = pRtlGetUserInfoHeap( heap, 0, ptr1, (void **)&tmp_ptr, &tmp_flags );
3410 ok( ret, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() );
3411 ok( tmp_ptr == NULL, "got ptr %p\n", tmp_ptr );
3412 ok( tmp_flags == 0x200, "got flags %#lx\n", tmp_flags );
3413
3414 ret = pRtlSetUserValueHeap( heap, 0, ptr0, (void *)0xdeadbeef );
3415 ok( ret, "RtlSetUserValueHeap failed, error %lu\n", GetLastError() );
3416 SetLastError( 0xdeadbeef );
3417 ret = pRtlSetUserFlagsHeap( heap, 0, ptr0, 0, 0x1000 );
3418#ifdef __REACTOS__
3420#endif
3421 ok( !ret, "RtlSetUserFlagsHeap succeeded\n" );
3422#ifdef __REACTOS__
3423 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == 0xdeadbeef) /* WS03 */, "got error %lu\n", GetLastError() );
3424#else
3425 ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
3426#endif
3427 SetLastError( 0xdeadbeef );
3428 ret = pRtlSetUserFlagsHeap( heap, 0, ptr0, 0x100, 0 );
3429#ifdef __REACTOS__
3431#endif
3432 ok( !ret, "RtlSetUserFlagsHeap succeeded\n" );
3433#ifdef __REACTOS__
3434 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == 0xdeadbeef) /* WS03 */, "got error %lu\n", GetLastError() );
3435#else
3436 ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
3437#endif
3438 ret = pRtlSetUserFlagsHeap( heap, 0, ptr0, 0x400, 0x200 );
3439 ok( ret, "RtlSetUserFlagsHeap failed, error %lu\n", GetLastError() );
3440
3441 tmp_ptr = NULL;
3442 tmp_flags = 0;
3443 ret = pRtlGetUserInfoHeap( heap, 0, ptr0, (void **)&tmp_ptr, &tmp_flags );
3444 ok( ret, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() );
3445 ok( tmp_ptr == (void *)0xdeadbeef, "got ptr %p\n", tmp_ptr );
3446 ok( tmp_flags == 0xa00 || broken(tmp_flags == 0xc00) /* w1064v1507 */,
3447 "got flags %#lx\n", tmp_flags );
3448
3449 user_ptr = (void **)(ptr0 + alloc_size + tail_size);
3450 ok( user_ptr[1] == (void *)0xdeadbeef, "unexpected user value\n" );
3451 user_ptr[0] = (void *)0xdeadbeef;
3452 user_ptr[1] = (void *)0xdeadbee0;
3453
3454 tmp_ptr = NULL;
3455 tmp_flags = 0;
3456 ret = pRtlGetUserInfoHeap( heap, 0, ptr0, (void **)&tmp_ptr, &tmp_flags );
3457 ok( ret, "RtlGetUserInfoHeap failed, error %lu\n", GetLastError() );
3458 ok( tmp_ptr == (void *)0xdeadbee0, "got ptr %p\n", tmp_ptr );
3459 ok( tmp_flags == 0xa00 || broken(tmp_flags == 0xc00) /* w1064v1507 */,
3460 "got flags %#lx\n", tmp_flags );
3461
3462 ret = HeapFree( heap, 0, ptr2 );
3463 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
3464 ret = HeapFree( heap, 0, ptr1 );
3465 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
3466 ret = HeapFree( heap, 0, ptr0 );
3467 ok( ret, "HeapFree failed, error %lu\n", GetLastError() );
3469 }
3470}
3471
3473{
3474 BYTE old, *p, *p2;
3475 BOOL ret;
3476 SIZE_T i, size, large_size = 3000 * 1024 + 37;
3477
3478 if (flags & HEAP_PAGE_ALLOCS) return; /* no tests for that case yet */
3479
3480 p = pHeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 17 );
3481 ok( p != NULL, "HeapAlloc failed\n" );
3482
3483 ret = HeapValidate( GetProcessHeap(), 0, p );
3484 ok( ret, "HeapValidate failed\n" );
3485
3486 size = HeapSize( GetProcessHeap(), 0, p );
3487 ok( size == 17, "Wrong size %Iu\n", size );
3488
3489 ok( p[14] == 0, "wrong data %x\n", p[14] );
3490 ok( p[15] == 0, "wrong data %x\n", p[15] );
3491 ok( p[16] == 0, "wrong data %x\n", p[16] );
3492
3494 {
3495 ok( p[17] == 0xab, "wrong padding %x\n", p[17] );
3496 ok( p[18] == 0xab, "wrong padding %x\n", p[18] );
3497 ok( p[19] == 0xab, "wrong padding %x\n", p[19] );
3498 }
3499
3501 if (p2 == p)
3502 {
3504 {
3505 ok( p[14] == 0xab, "wrong padding %x\n", p[14] );
3506 ok( p[15] == 0xab, "wrong padding %x\n", p[15] );
3507 ok( p[16] == 0xab, "wrong padding %x\n", p[16] );
3508 }
3509 else
3510 {
3511 ok( p[14] == 0, "wrong padding %x\n", p[14] );
3512 ok( p[15] == 0, "wrong padding %x\n", p[15] );
3513 }
3514 }
3515 else skip( "realloc in place failed\n");
3516
3517 ret = HeapFree( GetProcessHeap(), 0, p );
3518 ok( ret, "HeapFree failed\n" );
3519
3520 p = pHeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 17 );
3521 ok( p != NULL, "HeapAlloc failed\n" );
3522 old = p[17];
3523 p[17] = 0xcc;
3524
3526 {
3527 ret = HeapValidate( GetProcessHeap(), 0, p );
3528 ok( !ret, "HeapValidate succeeded\n" );
3529
3530 /* other calls only check when HEAP_VALIDATE is set */
3531 if (flags & HEAP_VALIDATE)
3532 {
3533 size = HeapSize( GetProcessHeap(), 0, p );
3534 ok( size == ~(SIZE_T)0 || broken(size == ~0u), "Wrong size %Iu\n", size );
3535
3536 p2 = HeapReAlloc( GetProcessHeap(), 0, p, 14 );
3537 ok( p2 == NULL, "HeapReAlloc succeeded\n" );
3538
3539 ret = HeapFree( GetProcessHeap(), 0, p );
3540 ok( !ret || broken(sizeof(void*) == 8), /* not caught on xp64 */
3541 "HeapFree succeeded\n" );
3542 }
3543
3544 p[17] = old;
3545 size = HeapSize( GetProcessHeap(), 0, p );
3546 ok( size == 17, "Wrong size %Iu\n", size );
3547
3548 p2 = HeapReAlloc( GetProcessHeap(), 0, p, 14 );
3549 ok( p2 != NULL, "HeapReAlloc failed\n" );
3550 p = p2;
3551 }
3552
3553 ret = HeapFree( GetProcessHeap(), 0, p );
3554 ok( ret, "HeapFree failed\n" );
3555
3557 {
3558 UINT *p32, tmp = 0;
3559
3560 size = 4 + 3;
3561 p = pHeapAlloc( GetProcessHeap(), 0, size );
3562 ok( !!p, "HeapAlloc failed\n" );
3563 p32 = (UINT *)p;
3564
3565 ok( p32[0] == 0xbaadf00d, "got %#x\n", p32[0] );
3566 memcpy( &tmp, p + size - 3, 3 );
3567 ok( tmp != 0xadf00d, "got %#x\n", tmp );
3568 memset( p, 0xcc, size );
3569
3570 size += 2 * 4;
3571 p = pHeapReAlloc( GetProcessHeap(), 0, p, size );
3572 ok( !!p, "HeapReAlloc failed\n" );
3573 p32 = (UINT *)p;
3574
3575 ok( p32[0] == 0xcccccccc, "got %#x\n", p32[0] );
3576 ok( p32[1] << 8 == 0xcccccc00, "got %#x\n", p32[1] );
3577 ok( p32[2] == 0xbaadf00d, "got %#x\n", p32[2] );
3578 memcpy( &tmp, p + size - 3, 3 );
3579 ok( tmp != 0xadf00d, "got %#x\n", tmp );
3580
3581 ret = pHeapFree( GetProcessHeap(), 0, p );
3582 ok( ret, "failed.\n" );
3583 }
3584
3585 p = HeapAlloc( GetProcessHeap(), 0, 37 );
3586 ok( p != NULL, "HeapAlloc failed\n" );
3587 memset( p, 0xcc, 37 );
3588
3589 ret = pHeapFree( GetProcessHeap(), 0, p );
3590 ok( ret, "HeapFree failed\n" );
3591
3593 {
3594 ok( p[16] == 0xee, "wrong data %x\n", p[16] );
3595 ok( p[17] == 0xfe, "wrong data %x\n", p[17] );
3596 ok( p[18] == 0xee, "wrong data %x\n", p[18] );
3597 ok( p[19] == 0xfe, "wrong data %x\n", p[19] );
3598
3600 ok( ret, "HeapValidate failed\n" );
3601
3602 old = p[16];
3603 p[16] = 0xcc;
3605 ok( !ret, "HeapValidate succeeded\n" );
3606
3607 p[16] = old;
3609 ok( ret, "HeapValidate failed\n" );
3610 }
3611
3612 /* now test large blocks */
3613
3614 p = pHeapAlloc( GetProcessHeap(), 0, large_size );
3615 ok( p != NULL, "HeapAlloc failed\n" );
3616
3617 ret = HeapValidate( GetProcessHeap(), 0, p );
3618 ok( ret, "HeapValidate failed\n" );
3619
3620 size = HeapSize( GetProcessHeap(), 0, p );
3621 ok( size == large_size, "Wrong size %Iu\n", size );
3622
3623 ok( p[large_size - 2] == 0, "wrong data %x\n", p[large_size - 2] );
3624 ok( p[large_size - 1] == 0, "wrong data %x\n", p[large_size - 1] );
3625
3627 {
3628 /* Windows doesn't do tail checking on large blocks */
3629 ok( p[large_size] == 0, "wrong data %x\n", p[large_size] );
3630 ok( p[large_size + 1] == 0, "wrong data %x\n", p[large_size + 1] );
3631 ok( p[large_size + 2] == 0, "wrong data %x\n", p[large_size + 2] );
3632 }
3633
3634 ret = HeapFree( GetProcessHeap(), 0, p );
3635 ok( ret, "HeapFree failed\n" );
3636
3637 /* test block sizes when tail checking */
3639 {
3640 for (size = 0; size < 64; size++)
3641 {
3642 p = HeapAlloc( GetProcessHeap(), 0, size );
3643 for (i = 0; i < 32; i++) if (p[size + i] != 0xab) break;
3644 ok( i >= 8, "only %Iu tail bytes for size %Iu\n", i, size );
3645 HeapFree( GetProcessHeap(), 0, p );
3646 }
3647 }
3648}
3649
3650static void test_debug_heap( const char *argv0, DWORD flags )
3651{
3652 char keyname[MAX_PATH];
3653 char buffer[MAX_PATH];
3656 BOOL ret;
3657 DWORD err;
3658 HKEY hkey;
3659 const char *basename;
3660
3661 if ((basename = strrchr( argv0, '\\' ))) basename++;
3662 else basename = argv0;
3663
3664 sprintf( keyname, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\%s",
3665 basename );
3666 if (!strcmp( keyname + strlen(keyname) - 3, ".so" )) keyname[strlen(keyname) - 3] = 0;
3667
3668 err = RegCreateKeyA( HKEY_LOCAL_MACHINE, keyname, &hkey );
3669 if (err == ERROR_ACCESS_DENIED)
3670 {
3671 skip("Not authorized to change the image file execution options\n");
3672 return;
3673 }
3674 ok( !err, "failed to create '%s' error %lu\n", keyname, err );
3675 if (err) return;
3676
3677 if (flags == 0xdeadbeef) /* magic value for unsetting it */
3678 RegDeleteValueA( hkey, "GlobalFlag" );
3679 else
3680 RegSetValueExA( hkey, "GlobalFlag", 0, REG_DWORD, (BYTE *)&flags, sizeof(flags) );
3681
3682 memset( &startup, 0, sizeof(startup) );
3683 startup.cb = sizeof(startup);
3684
3685 sprintf( buffer, "%s heap.c 0x%lx", argv0, flags );
3687 ok( ret, "failed to create child process error %lu\n", GetLastError() );
3688 if (ret)
3689 {
3690 wait_child_process( info.hProcess );
3691 CloseHandle( info.hThread );
3692 CloseHandle( info.hProcess );
3693 }
3694 RegDeleteValueA( hkey, "GlobalFlag" );
3695 RegCloseKey( hkey );
3697}
3698
3700{
3701 DWORD ret = 0;
3702
3715 return ret;
3716}
3717
3718static void test_heap_layout( HANDLE handle, DWORD global_flag, DWORD heap_flags )
3719{
3720 DWORD force_flags = heap_flags & ~(HEAP_SHARED|HEAP_DISABLE_COALESCE_ON_FREE);
3721 struct heap *heap = handle;
3722
3723#ifdef __REACTOS__
3725 skip("test_heap_layout() is invalid on WS03.\n");
3726 return;
3727 }
3728#endif
3729 if (global_flag & FLG_HEAP_ENABLE_TAGGING) heap_flags |= HEAP_SHARED;
3730 if (!(global_flag & FLG_HEAP_PAGE_ALLOCS)) force_flags &= ~(HEAP_GROWABLE|HEAP_PRIVATE);
3731
3732 ok( heap->force_flags == force_flags, "got force_flags %#x\n", heap->force_flags );
3733 ok( heap->flags == heap_flags, "got flags %#x\n", heap->flags );
3734
3736 {
3737 struct heap expect_heap;
3738 memset( &expect_heap, 0xee, sizeof(expect_heap) );
3739 expect_heap.force_flags = heap->force_flags;
3740 expect_heap.flags = heap->flags;
3741 todo_wine
3742 ok( !memcmp( heap, &expect_heap, sizeof(expect_heap) ), "got unexpected data\n" );
3743 }
3744 else
3745 {
3746 ok( heap->ffeeffee == 0xffeeffee, "got ffeeffee %#x\n", heap->ffeeffee );
3747 ok( heap->auto_flags == (heap_flags & HEAP_GROWABLE) || !heap->auto_flags,
3748 "got auto_flags %#x\n", heap->auto_flags );
3749 }
3750}
3751
3752static void test_child_heap( const char *arg )
3753{
3754 char buffer[32];
3755 DWORD global_flags = strtoul( arg, 0, 16 ), type, size = sizeof(buffer);
3756 DWORD heap_flags;
3757 HANDLE heap;
3758 HKEY hkey;
3759 BOOL ret;
3760
3761 if (global_flags == 0xdeadbeef) /* global_flags value comes from Session Manager global flags */
3762 {
3763 ret = RegOpenKeyA( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Session Manager", &hkey );
3764 if (!ret)
3765 {
3766 skip( "Session Manager flags not set\n" );
3767 return;
3768 }
3769
3770 ret = RegQueryValueExA( hkey, "GlobalFlag", 0, &type, (BYTE *)buffer, &size );
3771 ok( ret, "RegQueryValueExA failed, error %lu\n", GetLastError() );
3772
3773 if (type == REG_DWORD) global_flags = *(DWORD *)buffer;
3774 else if (type == REG_SZ) global_flags = strtoul( buffer, 0, 16 );
3775
3776 ret = RegCloseKey( hkey );
3777 ok( ret, "RegCloseKey failed, error %lu\n", GetLastError() );
3778 }
3779 if (global_flags && !pRtlGetNtGlobalFlags()) /* not working on NT4 */
3780 {
3781 win_skip( "global flags not set\n" );
3782 return;
3783 }
3784
3785 heap_flags = heap_flags_from_global_flag( global_flags );
3786 trace( "testing global flags %#lx, heap flags %08lx\n", global_flags, heap_flags );
3787
3788 ok( pRtlGetNtGlobalFlags() == global_flags, "got global flags %#lx\n", pRtlGetNtGlobalFlags() );
3789
3790 test_heap_layout( GetProcessHeap(), global_flags, heap_flags|HEAP_GROWABLE );
3791
3792 heap = HeapCreate( 0, 0, 0 );
3793 ok( heap != GetProcessHeap(), "got unexpected heap\n" );
3794 test_heap_layout( heap, global_flags, heap_flags|HEAP_GROWABLE|HEAP_PRIVATE );
3795 ret = HeapDestroy( heap );
3796 ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() );
3797
3799 ok( heap != GetProcessHeap(), "got unexpected heap\n" );
3801 test_block_layout( heap, global_flags, heap_flags|HEAP_NO_SERIALIZE|HEAP_GROWABLE|HEAP_PRIVATE, 0 );
3802 ret = HeapDestroy( heap );
3803 ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() );
3804
3806 ok( heap != GetProcessHeap(), "got unexpected heap\n" );
3808 ret = HeapDestroy( heap );
3809 ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() );
3810
3812 ok( heap != GetProcessHeap(), "got unexpected heap\n" );
3815 ret = HeapDestroy( heap );
3816 ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() );
3817
3818 heap = HeapCreate( 0, 0x1000, 0x10000 );
3819 ok( heap != GetProcessHeap(), "got unexpected heap\n" );
3820 test_heap_layout( heap, global_flags, heap_flags|HEAP_PRIVATE );
3821 ret = HeapDestroy( heap );
3822 ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() );
3823
3824 heap = HeapCreate( HEAP_SHARED, 0, 0 );
3825 ok( heap != GetProcessHeap(), "got unexpected heap\n" );
3826 test_heap_layout( heap, global_flags, heap_flags|HEAP_GROWABLE|HEAP_PRIVATE );
3827 ret = HeapDestroy( heap );
3828 ok( ret, "HeapDestroy failed, error %lu\n", GetLastError() );
3829
3830 test_heap_checks( heap_flags );
3831}
3832
3834{
3835 MEMORYSTATUSEX memstatus;
3836 ULONGLONG total_memory;
3837 BOOL ret;
3838
3839 if (!pGetPhysicallyInstalledSystemMemory)
3840 {
3841 win_skip("GetPhysicallyInstalledSystemMemory is not available\n");
3842 return;
3843 }
3844
3845 SetLastError(0xdeadbeef);
3846 ret = pGetPhysicallyInstalledSystemMemory(NULL);
3847 ok(!ret, "GetPhysicallyInstalledSystemMemory should fail\n");
3849 "expected ERROR_INVALID_PARAMETER, got %lu\n", GetLastError());
3850
3851 total_memory = 0;
3852 ret = pGetPhysicallyInstalledSystemMemory(&total_memory);
3853#ifdef __REACTOS__
3854 ok(ret || broken(GetLastError() == ERROR_INVALID_FUNCTION) /* Vista x64 ROS testbot */, "GetPhysicallyInstalledSystemMemory unexpectedly failed (%lu)\n", GetLastError());
3855 if (ret)
3856 ok(total_memory != 0, "expected total_memory != 0\n");
3857#else
3858 ok(ret, "GetPhysicallyInstalledSystemMemory unexpectedly failed (%lu)\n", GetLastError());
3859 ok(total_memory != 0, "expected total_memory != 0\n");
3860#endif
3861
3862 memstatus.dwLength = sizeof(memstatus);
3863 ret = GlobalMemoryStatusEx(&memstatus);
3864 ok(ret, "GlobalMemoryStatusEx unexpectedly failed\n");
3865#ifdef __REACTOS__
3866 ok(total_memory >= memstatus.ullTotalPhys / 1024 || broken(total_memory == 0) /* Vista x64 ROS testbot */,
3867 "expected total_memory >= memstatus.ullTotalPhys / 1024\n");
3868#else
3869 ok(total_memory >= memstatus.ullTotalPhys / 1024,
3870 "expected total_memory >= memstatus.ullTotalPhys / 1024\n");
3871#endif
3872}
3873
3875{
3876 char buffer[sizeof(SYSTEM_PERFORMANCE_INFORMATION) + 16]; /* some Win 7 versions need a larger info */
3877 SYSTEM_PERFORMANCE_INFORMATION *perf_info = (void *)buffer;
3878 SYSTEM_BASIC_INFORMATION basic_info;
3879 MEMORYSTATUSEX memex = {0}, expect;
3880 MEMORYSTATUS mem = {0};
3881 VM_COUNTERS_EX vmc;
3883 BOOL ret;
3884
3885 SetLastError( 0xdeadbeef );
3886 ret = GlobalMemoryStatusEx( &memex );
3887 ok( !ret, "GlobalMemoryStatusEx succeeded\n" );
3888 ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
3889 SetLastError( 0xdeadbeef );
3891 ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() );
3892
3893 status = NtQuerySystemInformation( SystemBasicInformation, &basic_info, sizeof(basic_info), NULL );
3894 ok( !status, "NtQuerySystemInformation returned %#lx\n", status );
3896 ok( !status, "NtQuerySystemInformation returned %#lx\n", status );
3898 ok( !status, "NtQueryInformationProcess returned %#lx\n", status );
3899 mem.dwLength = sizeof(MEMORYSTATUS);
3901 memex.dwLength = sizeof(MEMORYSTATUSEX);
3902 ret = GlobalMemoryStatusEx( &memex );
3903 ok( ret, "GlobalMemoryStatusEx succeeded\n" );
3904
3905 ok( basic_info.PageSize, "got 0 PageSize\n" );
3906 ok( basic_info.MmNumberOfPhysicalPages, "got 0 MmNumberOfPhysicalPages\n" );
3907 ok( !!basic_info.HighestUserAddress, "got 0 HighestUserAddress\n" );
3908 ok( !!basic_info.LowestUserAddress, "got 0 LowestUserAddress\n" );
3909 ok( perf_info->TotalCommittedPages, "got 0 TotalCommittedPages\n" );
3910 ok( perf_info->TotalCommitLimit, "got 0 TotalCommitLimit\n" );
3911 ok( perf_info->AvailablePages, "got 0 AvailablePages\n" );
3912
3913 expect.dwMemoryLoad = (memex.ullTotalPhys - memex.ullAvailPhys) / (memex.ullTotalPhys / 100);
3914 expect.ullTotalPhys = (ULONGLONG)basic_info.MmNumberOfPhysicalPages * basic_info.PageSize;
3915 expect.ullAvailPhys = (ULONGLONG)perf_info->AvailablePages * basic_info.PageSize;
3916 expect.ullTotalPageFile = (ULONGLONG)perf_info->TotalCommitLimit * basic_info.PageSize;
3917 expect.ullAvailPageFile = (ULONGLONG)(perf_info->TotalCommitLimit - perf_info->TotalCommittedPages) * basic_info.PageSize;
3918 expect.ullTotalVirtual = (ULONG_PTR)basic_info.HighestUserAddress - (ULONG_PTR)basic_info.LowestUserAddress + 1;
3919 expect.ullAvailVirtual = expect.ullTotalVirtual - (ULONGLONG)vmc.WorkingSetSize /* approximate */;
3920 expect.ullAvailExtendedVirtual = 0;
3921
3922/* allow some variability, info sources are not always in sync */
3923#define IS_WITHIN_RANGE(a, b) (((a) - (b) + (256 * basic_info.PageSize)) <= (512 * basic_info.PageSize))
3924
3925 ok( memex.dwMemoryLoad == expect.dwMemoryLoad, "got dwMemoryLoad %lu\n", memex.dwMemoryLoad );
3926 ok( memex.ullTotalPhys == expect.ullTotalPhys, "got ullTotalPhys %#I64x\n", memex.ullTotalPhys );
3927 ok( IS_WITHIN_RANGE( memex.ullAvailPhys, expect.ullAvailPhys ), "got ullAvailPhys %#I64x\n", memex.ullAvailPhys );
3928 ok( memex.ullTotalPageFile == expect.ullTotalPageFile, "got ullTotalPageFile %#I64x\n", memex.ullTotalPageFile );
3929 ok( IS_WITHIN_RANGE( memex.ullAvailPageFile, expect.ullAvailPageFile ), "got ullAvailPageFile %#I64x\n", memex.ullAvailPageFile );
3930 ok( memex.ullTotalVirtual == expect.ullTotalVirtual, "got ullTotalVirtual %#I64x\n", memex.ullTotalVirtual );
3931 ok( memex.ullAvailVirtual <= expect.ullAvailVirtual, "got ullAvailVirtual %#I64x\n", memex.ullAvailVirtual );
3932 ok( memex.ullAvailExtendedVirtual == 0, "got ullAvailExtendedVirtual %#I64x\n", memex.ullAvailExtendedVirtual );
3933
3934 ok( mem.dwMemoryLoad == memex.dwMemoryLoad, "got dwMemoryLoad %lu\n", mem.dwMemoryLoad );
3935 ok( mem.dwTotalPhys == min( ~(SIZE_T)0 >> 1, memex.ullTotalPhys ) ||
3936 broken( mem.dwTotalPhys == ~(SIZE_T)0 ) /* Win <= 8.1 with RAM size > 4GB */,
3937 "got dwTotalPhys %#Ix\n", mem.dwTotalPhys );
3938 ok( IS_WITHIN_RANGE( mem.dwAvailPhys, min( ~(SIZE_T)0 >> 1, memex.ullAvailPhys ) ) ||
3939 broken( mem.dwAvailPhys == ~(SIZE_T)0 ) /* Win <= 8.1 with RAM size > 4GB */,
3940 "got dwAvailPhys %#Ix\n", mem.dwAvailPhys );
3941#ifndef _WIN64
3942 todo_wine_if(memex.ullTotalPageFile > 0xfff7ffff)
3943#endif
3944 ok( mem.dwTotalPageFile == min( ~(SIZE_T)0, memex.ullTotalPageFile ), "got dwTotalPageFile %#Ix\n", mem.dwTotalPageFile );
3945 ok( IS_WITHIN_RANGE( mem.dwAvailPageFile, min( ~(SIZE_T)0, memex.ullAvailPageFile ) ), "got dwAvailPageFile %#Ix\n", mem.dwAvailPageFile );
3946 ok( mem.dwTotalVirtual == memex.ullTotalVirtual, "got dwTotalVirtual %#Ix\n", mem.dwTotalVirtual );
3947 ok( mem.dwAvailVirtual == memex.ullAvailVirtual, "got dwAvailVirtual %#Ix\n", mem.dwAvailVirtual );
3948
3949#undef IS_WITHIN_RANGE
3950}
3951
3952static void get_valloc_info( void *mem, char **base, SIZE_T *alloc_size )
3953{
3955 SIZE_T size;
3956 char *p;
3957
3958 size = VirtualQuery( mem, &info, sizeof(info) );
3959 ok( size == sizeof(info), "got %Iu.\n", size );
3960
3961 info2 = info;
3962 p = info.AllocationBase;
3963 while (1)
3964 {
3965 size = VirtualQuery( p, &info2, sizeof(info2) );
3966 ok( size == sizeof(info), "got %Iu.\n", size );
3967 if (info2.AllocationBase != info.AllocationBase)
3968 break;
3969 ok( info2.State == MEM_RESERVE || info2.State == MEM_COMMIT, "got %#lx.\n", info2.State );
3970 p += info2.RegionSize;
3971 }
3972
3973 *base = info.AllocationBase;
3974 *alloc_size = p - *base;
3975}
3976
3977static void test_heap_size( SIZE_T initial_size )
3978{
3979 static const SIZE_T default_heap_size = 0x10000, init_grow_size = 0x100000, max_grow_size = 0xfd0000;
3980
3981 BOOL initial_subheap = TRUE, max_size_reached = FALSE;
3982 SIZE_T alloc_size, current_subheap_size;
3983 char *base, *current_base;
3984 unsigned int i;
3985 HANDLE heap;
3986 void *p;
3987
3988 winetest_push_context( "init size %#Ix", initial_size );
3989 heap = HeapCreate( HEAP_NO_SERIALIZE, initial_size, 0 );
3990 get_valloc_info( heap, &current_base, &alloc_size );
3991
3992 ok( alloc_size == initial_size + default_heap_size || broken( (initial_size && alloc_size == initial_size)
3993 || (!initial_size && (alloc_size == default_heap_size * sizeof(void*))) ) /* Win7 */,
3994 "got %#Ix.\n", alloc_size );
3995
3996 current_subheap_size = alloc_size;
3997 for (i = 0; i < 100; ++i)
3998 {
3999 winetest_push_context( "i %u, current_subheap_size %#Ix", i, current_subheap_size );
4000 p = HeapAlloc( heap, 0, 0x60000 );
4001 get_valloc_info( p, &base, &alloc_size );
4002 if (base != current_base)
4003 {
4004 current_base = base;
4005 if (initial_subheap)
4006 {
4007 current_subheap_size = init_grow_size;
4008 initial_subheap = FALSE;
4009 }
4010 else
4011 {
4012 current_subheap_size = min( current_subheap_size * 2, max_grow_size );
4013 if (current_subheap_size == max_grow_size)
4014 max_size_reached = TRUE;
4015 }
4016 }
4017 ok( alloc_size == current_subheap_size, "got %#Ix.\n", alloc_size );
4019 }
4020 ok( max_size_reached, "Did not reach maximum subheap size.\n" );
4021
4022 HeapDestroy( heap );
4024}
4025
4026static void test_heap_sizes(void)
4027{
4028 unsigned int i;
4029 SIZE_T size, round_size = 0x400 * sizeof(void*);
4030 char *base;
4031
4032#ifdef __REACTOS__
4034 skip("test_heap_sizes() is invalid for WS03.\n");
4035 return;
4036 }
4037#endif
4038 test_heap_size( 0 );
4039 test_heap_size( 0x80000 );
4040 test_heap_size( 0x150000 );
4041
4042 for (i = 1; i < 0x100; i++)
4043 {
4044 HANDLE heap = HeapCreate( 0, i * 0x100, i * 0x100 );
4045 ok( heap != NULL, "%x: creation failed\n", i * 0x100 );
4047 ok( size == ((i * 0x100 + round_size - 1) & ~(round_size - 1)),
4048 "%x: wrong size %Ix\n", i * 0x100, size );
4049 HeapDestroy( heap );
4050 }
4051}
4052
4054{
4055 int argc;
4056 char **argv;
4057
4058#if defined(__REACTOS__) && defined(SKIPBADHEAP_K32_WINETEST)
4059 if (is_reactos()) {
4060 ok(FALSE, "FIXME: These tests are too rough on ReactOS heap manager on x64. It will eventually finish but it takes over an hour to complete the test suite with it which isn't acceptable.\n");
4061 return;
4062 }
4063#endif
4065
4067 if (argc >= 3)
4068 {
4069 test_child_heap( argv[2] );
4070 return;
4071 }
4072
4076
4079
4080 if (pRtlGetNtGlobalFlags)
4081 {
4082 test_debug_heap( argv[0], 0 );
4092 test_debug_heap( argv[0], 0xdeadbeef );
4093 }
4094 else win_skip( "RtlGetNtGlobalFlags not found, skipping heap debug tests\n" );
4096}
static int argc
Definition: ServiceArgs.c:12
#define expect(EXPECTED, GOT)
Definition: SystemMenu.c:483
struct outqueuenode * tail
Definition: adnsresfilter.c:66
static void startup(void)
#define GetNTVersion()
Definition: apitest.h:17
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define broken(x)
Definition: atltest.h:178
#define START_TEST(x)
Definition: atltest.h:75
LONG NTSTATUS
Definition: precomp.h:26
#define ARRAY_SIZE(A)
Definition: main.h:20
static HANDLE thread
Definition: service.c:33
#define LongToHandle(h)
Definition: basetsd.h:76
#define RegCloseKey(hKey)
Definition: registry.h:49
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define NO_ERROR
Definition: dderror.h:5
#define WAIT_TIMEOUT
Definition: dderror.h:14
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define ERROR_INVALID_FUNCTION
Definition: dderror.h:6
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
LONG WINAPI RegCreateKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:1179
LONG WINAPI RegSetValueExA(HKEY hKey, LPCSTR lpValueName, DWORD Reserved, DWORD dwType, CONST BYTE *lpData, DWORD cbData)
Definition: reg.c:4799
LONG WINAPI RegOpenKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3234
LONG WINAPI RegDeleteValueA(HKEY hKey, LPCSTR lpValueName)
Definition: reg.c:2287
LONG WINAPI RegQueryValueExA(_In_ HKEY hkeyorg, _In_ LPCSTR name, _In_ LPDWORD reserved, _Out_opt_ LPDWORD type, _Out_opt_ LPBYTE data, _Inout_opt_ LPDWORD count)
Definition: reg.c:4009
LONG WINAPI RegDeleteKeyA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey)
Definition: reg.c:1224
#define CloseHandle
Definition: compat.h:739
#define GetProcessHeap()
Definition: compat.h:736
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define SetLastError(x)
Definition: compat.h:752
#define HeapAlloc
Definition: compat.h:733
#define HeapReAlloc
Definition: compat.h:734
#define GetCurrentProcess()
Definition: compat.h:759
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
Definition: proc.c:4749
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
BOOL WINAPI DECLSPEC_HOTPATCH GetPhysicallyInstalledSystemMemory(ULONGLONG *memory)
Definition: memory.c:1314
static void basename(LPCWSTR path, LPWSTR name)
Definition: profile.c:38
static HANDLE heap
Definition: heap.c:44
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2802
_ACRTIMP __int64 __cdecl llabs(__int64)
_ACRTIMP __msvcrt_ulong __cdecl strtoul(const char *, char **, int)
Definition: string.c:1859
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3319
_ACRTIMP char *__cdecl strrchr(const char *, int)
Definition: string.c:3298
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
#define INFINITE
Definition: serial.h:102
#define ULONG_PTR
Definition: config.h:101
int align(int length, int align)
Definition: dsound8.c:36
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
@ SystemBasicInformation
Definition: ntddk_ex.h:11
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint res
Definition: glext.h:9613
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLenum const GLfloat * params
Definition: glext.h:5645
GLbitfield flags
Definition: glext.h:7161
GLfloat GLfloat p
Definition: glext.h:8902
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean flag
Definition: glfuncs.h:52
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
BOOL WINAPI HeapQueryInformation(HANDLE HeapHandle, HEAP_INFORMATION_CLASS HeapInformationClass, PVOID HeapInformation OPTIONAL, SIZE_T HeapInformationLength OPTIONAL, PSIZE_T ReturnLength OPTIONAL)
Definition: heapmem.c:314
HGLOBAL NTAPI GlobalHandle(LPCVOID pMem)
Definition: heapmem.c:705
HANDLE WINAPI HeapCreate(DWORD flOptions, SIZE_T dwInitialSize, SIZE_T dwMaximumSize)
Definition: heapmem.c:45
HGLOBAL NTAPI GlobalFree(HGLOBAL hMem)
Definition: heapmem.c:611
HGLOBAL NTAPI GlobalReAlloc(HGLOBAL hMem, SIZE_T dwBytes, UINT uFlags)
Definition: heapmem.c:825
UINT NTAPI GlobalFlags(HGLOBAL hMem)
Definition: heapmem.c:520
HLOCAL NTAPI LocalReAlloc(HLOCAL hMem, SIZE_T dwBytes, UINT uFlags)
Definition: heapmem.c:1625
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190
HLOCAL NTAPI LocalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:1390
BOOL WINAPI HeapLock(HANDLE hHeap)
Definition: heapmem.c:123
LPVOID NTAPI LocalLock(HLOCAL hMem)
Definition: heapmem.c:1616
BOOL NTAPI LocalUnlock(HLOCAL hMem)
Definition: heapmem.c:1805
BOOL WINAPI HeapValidate(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem)
Definition: heapmem.c:156
BOOL WINAPI HeapUnlock(HANDLE hHeap)
Definition: heapmem.c:134
VOID NTAPI GlobalMemoryStatus(LPMEMORYSTATUS lpBuffer)
Definition: heapmem.c:1365
BOOL WINAPI HeapSetInformation(HANDLE HeapHandle, HEAP_INFORMATION_CLASS HeapInformationClass, PVOID HeapInformation OPTIONAL, SIZE_T HeapInformationLength OPTIONAL)
Definition: heapmem.c:342
BOOL WINAPI HeapDestroy(HANDLE hHeap)
Definition: heapmem.c:85
SIZE_T NTAPI LocalSize(HLOCAL hMem)
Definition: heapmem.c:1794
BOOL WINAPI HeapWalk(HANDLE hHeap, LPPROCESS_HEAP_ENTRY lpEntry)
Definition: heapmem.c:291
HLOCAL NTAPI LocalHandle(LPCVOID pMem)
Definition: heapmem.c:1605
UINT NTAPI LocalFlags(HLOCAL hMem)
Definition: heapmem.c:1520
HGLOBAL NTAPI GlobalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:368
SIZE_T NTAPI GlobalSize(HGLOBAL hMem)
Definition: heapmem.c:1090
DWORD WINAPI GetProcessHeaps(DWORD NumberOfHeaps, PHANDLE ProcessHeaps)
Definition: heapmem.c:111
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1594
BOOL NTAPI GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer)
Definition: heapmem.c:1272
#define FLG_HEAP_DISABLE_COALESCING
Definition: pstypes.h:80
#define FLG_HEAP_ENABLE_TAGGING
Definition: pstypes.h:66
#define FLG_HEAP_PAGE_ALLOCS
Definition: pstypes.h:84
#define FLG_POOL_ENABLE_TAGGING
Definition: pstypes.h:65
#define FLG_HEAP_ENABLE_FREE_CHECK
Definition: pstypes.h:61
#define FLG_HEAP_VALIDATE_PARAMETERS
Definition: pstypes.h:62
#define FLG_HEAP_ENABLE_TAIL_CHECK
Definition: pstypes.h:60
#define FLG_HEAP_VALIDATE_ALL
Definition: pstypes.h:63
#define FLG_HEAP_ENABLE_TAG_BY_DLL
Definition: pstypes.h:70
NTSYSAPI BOOLEAN WINAPI RtlSetUserFlagsHeap(HANDLE, ULONG, void *, ULONG, ULONG)
NTSYSAPI NTSTATUS WINAPI RtlWalkHeap(HANDLE, PVOID)
@ ProcessVmCounters
Definition: winternl.h:1885
NTSYSAPI BOOLEAN WINAPI RtlGetUserInfoHeap(HANDLE, ULONG, void *, void **, ULONG *)
NTSYSAPI ULONG WINAPI RtlGetNtGlobalFlags(void)
Definition: libsupp.c:95
NTSYSAPI BOOLEAN WINAPI RtlSetUserValueHeap(HANDLE, ULONG, void *, void *)
static ERESOURCE GlobalLock
Definition: sys_arch.c:8
uint32_t entry
Definition: isohybrid.c:63
#define REG_SZ
Definition: layer.c:22
#define SystemPerformanceInformation
Definition: memtest.h:87
struct _SYSTEM_PERFORMANCE_INFORMATION SYSTEM_PERFORMANCE_INFORMATION
void __cdecl void __cdecl void __cdecl void __cdecl void __cdecl winetest_push_context(const char *fmt,...) __WINE_PRINTF_ATTR(1
#define win_skip
Definition: minitest.h:67
#define todo_wine_if(is_todo)
Definition: minitest.h:81
void __cdecl void __cdecl void __cdecl void __cdecl void __cdecl void winetest_pop_context(void)
#define todo_wine
Definition: minitest.h:80
#define LMEM_MOVEABLE
Definition: minwinbase.h:82
#define LocalDiscard(m)
Definition: minwinbase.h:98
#define LMEM_ZEROINIT
Definition: minwinbase.h:85
#define PROCESS_HEAP_ENTRY_DDESHARE
Definition: minwinbase.h:79
#define PROCESS_HEAP_UNCOMMITTED_RANGE
Definition: minwinbase.h:76
#define PROCESS_HEAP_ENTRY_MOVEABLE
Definition: minwinbase.h:78
#define PROCESS_HEAP_ENTRY_BUSY
Definition: minwinbase.h:77
#define LMEM_INVALID_HANDLE
Definition: minwinbase.h:89
#define PROCESS_HEAP_REGION
Definition: minwinbase.h:75
#define LMEM_DISCARDABLE
Definition: minwinbase.h:87
#define LMEM_NODISCARD
Definition: minwinbase.h:84
#define LMEM_NOCOMPACT
Definition: minwinbase.h:83
#define LMEM_FIXED
Definition: minwinbase.h:81
#define LMEM_MODIFY
Definition: minwinbase.h:86
HANDLE HLOCAL
Definition: minwindef.h:199
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
static PVOID ptr
Definition: dispmode.c:27
#define sprintf
Definition: sprintf.c:45
static HMODULE ntdll
Definition: debugger.c:59
#define RTL_HEAP_ENTRY_BUSY
Definition: heap.c:123
static void test_GetPhysicallyInstalledSystemMemory(void)
Definition: heap.c:3833
static void test_heap_sizes(void)
Definition: heap.c:4026
static void test_child_heap(const char *arg)
Definition: heap.c:3752
#define RTL_HEAP_ENTRY_REGION
Definition: heap.c:124
#define HEAP_PRIVATE
Definition: heap.c:35
#define HEAP_VALIDATE
Definition: heap.c:37
static void test_GlobalAlloc(void)
Definition: heap.c:1439
static ULONG
Definition: heap.c:49
static void test_LocalAlloc(void)
Definition: heap.c:2401
static void test_debug_heap(const char *argv0, DWORD flags)
Definition: heap.c:3650
static DWORD heap_flags_from_global_flag(DWORD flag)
Definition: heap.c:3699
static struct mem_entry * mem_entry_from_HANDLE(HLOCAL handle)
Definition: heap.c:1429
static void test_heap_checks(DWORD flags)
Definition: heap.c:3472
static void load_functions(void)
Definition: heap.c:61
static void test_GlobalMemoryStatus(void)
Definition: heap.c:3874
#define LOAD_FUNC(m, f)
static DWORD
Definition: heap.c:45
#define HEAP_VALIDATE_PARAMS
Definition: heap.c:39
#define ALIGN_BLOCK_SIZE(x)
Definition: heap.c:42
#define HEAP_ADD_USER_INFO
Definition: heap.c:34
static void get_valloc_info(void *mem, char **base, SIZE_T *alloc_size)
Definition: heap.c:3952
#define HEAP_VALIDATE_ALL
Definition: heap.c:38
static void test_block_layout(HANDLE heap, DWORD global_flags, DWORD heap_flags, DWORD alloc_flags)
Definition: heap.c:3243
#define RTL_HEAP_ENTRY_UNCOMMITTED
Definition: heap.c:126
static void test_heap_layout(HANDLE handle, DWORD global_flag, DWORD heap_flags)
Definition: heap.c:3718
#define RTL_HEAP_ENTRY_COMMITTED
Definition: heap.c:127
static LPVOID
Definition: heap.c:46
static void test_HeapCreate(void)
Definition: heap.c:178
static SIZE_T
Definition: heap.c:45
static HEAP_INFORMATION_CLASS
Definition: heap.c:56
static void test_heap_size(SIZE_T initial_size)
Definition: heap.c:3977
#define RTL_HEAP_ENTRY_LFH
Definition: heap.c:128
#define RTL_HEAP_ENTRY_BLOCK
Definition: heap.c:125
DWORD WINAPI heap_thread_proc(void *arg)
Definition: heap.c:142
#define IS_WITHIN_RANGE(a, b)
static BOOL is_mem_entry(HLOCAL handle)
Definition: heap.c:1434
#define HEAP_PAGE_ALLOCS
Definition: heap.c:36
#define min(a, b)
Definition: monoChain.cc:55
#define argv
Definition: mplay32.c:18
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
_In_ HANDLE _In_ DWORD _In_ DWORD _Inout_opt_ LPOVERLAPPED _In_opt_ LPTRANSMIT_FILE_BUFFERS _In_ DWORD dwReserved
Definition: mswsock.h:95
unsigned int UINT
Definition: ndis.h:50
@ HeapCompatibilityInformation
Definition: rtltypes.h:482
#define HEAP_FREE_CHECKING_ENABLED
Definition: nt_native.h:1701
#define HEAP_DISABLE_COALESCE_ON_FREE
Definition: nt_native.h:1702
#define HEAP_TAIL_CHECKING_ENABLED
Definition: nt_native.h:1700
#define HEAP_GROWABLE
Definition: nt_native.h:1696
#define BOOL
Definition: nt_native.h:43
#define MEM_RESERVE
Definition: nt_native.h:1317
#define HEAP_REALLOC_IN_PLACE_ONLY
Definition: nt_native.h:1699
#define MEM_COMMIT
Definition: nt_native.h:1316
#define HEAP_NO_SERIALIZE
Definition: nt_native.h:1695
NTSTATUS NTAPI NtQueryInformationProcess(_In_ HANDLE ProcessHandle, _In_ PROCESSINFOCLASS ProcessInformationClass, _Out_writes_bytes_to_opt_(ProcessInformationLength, *ReturnLength) PVOID ProcessInformation, _In_ ULONG ProcessInformationLength, _Out_opt_ PULONG ReturnLength)
Definition: query.c:211
#define HGLOBAL
Definition: ole.h:15
#define BOOLEAN
Definition: pedump.c:73
_In_opt_ _In_opt_ _In_ _In_ DWORD cbData
Definition: shlwapi.h:761
#define err(...)
#define REG_DWORD
Definition: sdbapi.c:615
#define is_reactos()
Definition: test.h:1041
int winetest_get_mainargs(char ***pargv)
#define wait_child_process
Definition: test.h:177
#define memset(x, y, z)
Definition: compat.h:39
#define _WIN32_WINNT_VISTA
Definition: sdkddkver.h:25
static char argv0[MAX_PATH]
Definition: shlexec.c:49
wchar_t const *const size_t const buffer_size
Definition: stat.cpp:95
NTSYSAPI NTSTATUS NTAPI NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInfoClass, OUT PVOID SystemInfoBuffer, IN ULONG SystemInfoBufferSize, OUT PULONG BytesReturned OPTIONAL)
Definition: minwinbase.h:361
struct _PROCESS_HEAP_ENTRY::@3252::@3254 Region
WORD wFlags
Definition: minwinbase.h:366
PVOID lpData
Definition: minwinbase.h:362
DWORD cbData
Definition: minwinbase.h:363
SIZE_T WorkingSetSize
Definition: winternl.h:3150
HANDLE start_event
Definition: heap.c:134
HANDLE heap
Definition: heap.c:137
HANDLE ready_event
Definition: heap.c:133
Definition: heap.c:86
UINT flags
Definition: heap.c:93
UINT_PTR unknown1[2]
Definition: heap.c:87
UINT auto_flags
Definition: heap.c:89
UINT force_flags
Definition: heap.c:94
UINT_PTR unknown4[3]
Definition: heap.c:92
UINT unknown3[2]
Definition: heap.c:91
UINT ffeeffee
Definition: heap.c:88
UINT_PTR unknown2[7]
Definition: heap.c:90
Definition: memory.c:890
UINT_PTR flags
Definition: heap.c:1425
WORD flags
Definition: memory.c:895
void * ptr
Definition: memory.c:900
Definition: mem.c:349
Definition: memory.c:793
struct rtl_heap_entry::@513::@515 Block
LPVOID lpLastBlock
Definition: memory.c:808
LPVOID lpFirstBlock
Definition: memory.c:807
DWORD dwUnCommittedSize
Definition: memory.c:806
BYTE cbOverhead
Definition: memory.c:796
WORD wFlags
Definition: memory.c:798
struct rtl_heap_entry::@513::@516 Region
DWORD dwCommittedSize
Definition: memory.c:805
LPVOID lpData
Definition: memory.c:794
HANDLE hMem
Definition: memory.c:801
SIZE_T cbData
Definition: memory.c:795
BYTE iRegionIndex
Definition: memory.c:797
Definition: ps.c:97
#define max(a, b)
Definition: svc.c:63
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:651
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
PVOID HANDLE
Definition: typedefs.h:73
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
SIZE_T NTAPI VirtualQuery(IN LPCVOID lpAddress, OUT PMEMORY_BASIC_INFORMATION lpBuffer, IN SIZE_T dwLength)
Definition: virtmem.c:211
SIZE_T WINAPI HeapSize(HANDLE, DWORD, LPCVOID)
#define GMEM_DISCARDABLE
Definition: winbase.h:323
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
struct _MEMORYSTATUS MEMORYSTATUS
#define GMEM_DISCARDED
Definition: winbase.h:331
#define GMEM_LOWER
Definition: winbase.h:324
#define GMEM_INVALID_HANDLE
Definition: winbase.h:332
#define GMEM_NOCOMPACT
Definition: winbase.h:325
#define GMEM_ZEROINIT
Definition: winbase.h:330
#define GMEM_FIXED
Definition: winbase.h:317
#define GMEM_NODISCARD
Definition: winbase.h:326
#define GMEM_MODIFY
Definition: winbase.h:319
#define GMEM_NOT_BANKED
Definition: winbase.h:327
#define GMEM_MOVEABLE
Definition: winbase.h:318
#define GMEM_DDESHARE
Definition: winbase.h:322
#define GMEM_NOTIFY
Definition: winbase.h:328
#define GlobalDiscard(m)
Definition: winbase.h:2333
WINBASEAPI _In_ DWORD _Out_ _In_ WORD wFlags
Definition: wincon_undoc.h:337
void * arg
Definition: msvc.h:10
#define WINAPI
Definition: msvc.h:6
#define ERROR_GEN_FAILURE
Definition: winerror.h:256
#define ERROR_DISCARDED
Definition: winerror.h:351
#define ERROR_NOT_LOCKED
Definition: winerror.h:352
#define ERROR_NOACCESS
Definition: winerror.h:902
#define HEAP_SHARED
Definition: winnt.h:180
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
unsigned char BYTE
Definition: xxhash.c:193