ReactOS  0.4.13-dev-482-ge57f103
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 #define MAGIC_DEAD 0xdeadbeef
34 
35 /* some undocumented flags (names are made up) */
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 static BOOL (WINAPI *pHeapQueryInformation)(HANDLE, HEAP_INFORMATION_CLASS, PVOID, SIZE_T, PSIZE_T);
42 static BOOL (WINAPI *pGetPhysicallyInstalledSystemMemory)(ULONGLONG *);
43 static ULONG (WINAPI *pRtlGetNtGlobalFlags)(void);
44 
46 {
51 };
52 
54 {
55  DWORD dwSizeAligned = (size + 3) & ~3;
56  return max(dwSizeAligned, 12); /* at least 12 bytes */
57 }
58 
59 static void test_sized_HeapAlloc(int nbytes)
60 {
61  BOOL success;
62  char *buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nbytes);
63  ok(buf != NULL, "allocate failed\n");
64  ok(buf[0] == 0, "buffer not zeroed\n");
66  ok(success, "free failed\n");
67 }
68 
69 static void test_sized_HeapReAlloc(int nbytes1, int nbytes2)
70 {
71  BOOL success;
72  char *buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nbytes1);
73  ok(buf != NULL, "allocate failed\n");
74  ok(buf[0] == 0, "buffer not zeroed\n");
76  ok(buf != NULL, "reallocate failed\n");
77  ok(buf[nbytes2-1] == 0, "buffer not zeroed\n");
79  ok(success, "free failed\n");
80 }
81 
82 static void test_heap(void)
83 {
84  LPVOID mem;
85  LPVOID msecond;
86  DWORD res;
87  UINT flags;
88  HGLOBAL gbl;
89  HGLOBAL hsecond;
90  SIZE_T size, size2;
91  const SIZE_T max_size = 1024, init_size = 10;
92  /* use function pointers to avoid warnings for invalid parameter tests */
93  LPVOID (WINAPI *pHeapAlloc)(HANDLE,DWORD,SIZE_T);
94  LPVOID (WINAPI *pHeapReAlloc)(HANDLE,DWORD,LPVOID,SIZE_T);
95 
96  pHeapAlloc = (void *)GetProcAddress( GetModuleHandleA("kernel32"), "HeapAlloc" );
97  pHeapReAlloc = (void *)GetProcAddress( GetModuleHandleA("kernel32"), "HeapReAlloc" );
98 
99  /* Heap*() functions */
100  mem = HeapAlloc(GetProcessHeap(), 0, 0);
101  ok(mem != NULL, "memory not allocated for size 0\n");
102  HeapFree(GetProcessHeap(), 0, mem);
103 
104  mem = HeapReAlloc(GetProcessHeap(), 0, NULL, 10);
105  ok(mem == NULL, "memory allocated by HeapReAlloc\n");
106 
107  for (size = 0; size <= 256; size++)
108  {
109  SIZE_T heap_size;
110  mem = HeapAlloc(GetProcessHeap(), 0, size);
111  heap_size = HeapSize(GetProcessHeap(), 0, mem);
112  ok(heap_size == size || heap_size == resize_9x(size),
113  "HeapSize returned %lu instead of %lu or %lu\n", heap_size, size, resize_9x(size));
114  HeapFree(GetProcessHeap(), 0, mem);
115  }
116 
117  /* test some border cases of HeapAlloc and HeapReAlloc */
118  mem = HeapAlloc(GetProcessHeap(), 0, 0);
119  ok(mem != NULL, "memory not allocated for size 0\n");
120  msecond = pHeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, mem, ~(SIZE_T)0 - 7);
121  ok(msecond == NULL, "HeapReAlloc(~0 - 7) should have failed\n");
122  msecond = pHeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, mem, ~(SIZE_T)0);
123  ok(msecond == NULL, "HeapReAlloc(~0) should have failed\n");
124  HeapFree(GetProcessHeap(), 0, mem);
125  mem = pHeapAlloc(GetProcessHeap(), 0, ~(SIZE_T)0);
126  ok(mem == NULL, "memory allocated for size ~0\n");
127  mem = HeapAlloc(GetProcessHeap(), 0, 17);
128  msecond = HeapReAlloc(GetProcessHeap(), 0, mem, 0);
129  ok(msecond != NULL, "HeapReAlloc(0) should have succeeded\n");
130  size = HeapSize(GetProcessHeap(), 0, msecond);
131  ok(size == 0 || broken(size == 1) /* some vista and win7 */,
132  "HeapSize should have returned 0 instead of %lu\n", size);
133  HeapFree(GetProcessHeap(), 0, msecond);
134 
135  /* large blocks must be 16-byte aligned */
136  mem = HeapAlloc(GetProcessHeap(), 0, 512 * 1024);
137  ok( mem != NULL, "failed for size 512K\n" );
138  ok( (ULONG_PTR)mem % 16 == 0 || broken((ULONG_PTR)mem % 16) /* win9x */,
139  "512K block not 16-byte aligned\n" );
140  HeapFree(GetProcessHeap(), 0, mem);
141 
142  /* Global*() functions */
143  gbl = GlobalAlloc(GMEM_MOVEABLE, 0);
144  ok(gbl != NULL, "global memory not allocated for size 0\n");
145 
146  gbl = GlobalReAlloc(gbl, 10, GMEM_MOVEABLE);
147  ok(gbl != NULL, "Can't realloc global memory\n");
148  size = GlobalSize(gbl);
149  ok(size >= 10 && size <= 16, "Memory not resized to size 10, instead size=%ld\n", size);
150 
151  gbl = GlobalReAlloc(gbl, 0, GMEM_MOVEABLE);
152  ok(gbl != NULL, "GlobalReAlloc should not fail on size 0\n");
153 
154  size = GlobalSize(gbl);
155  ok(size == 0, "Memory not resized to size 0, instead size=%ld\n", size);
156  ok(GlobalFree(gbl) == NULL, "Memory not freed\n");
157  size = GlobalSize(gbl);
158  ok(size == 0, "Memory should have been freed, size=%ld\n", size);
159 
160  gbl = GlobalReAlloc(0, 10, GMEM_MOVEABLE);
161  ok(gbl == NULL, "global realloc allocated memory\n");
162 
163  /* GlobalLock / GlobalUnlock with a valid handle */
164  gbl = GlobalAlloc(GMEM_MOVEABLE, 256);
165 
167  mem = GlobalLock(gbl); /* #1 */
168  ok(mem != NULL, "returned %p with %d (expected '!= NULL')\n", mem, GetLastError());
170  flags = GlobalFlags(gbl);
171  ok( flags == 1, "returned 0x%04x with %d (expected '0x0001')\n",
172  flags, GetLastError());
173 
175  msecond = GlobalLock(gbl); /* #2 */
176  ok( msecond == mem, "returned %p with %d (expected '%p')\n",
177  msecond, GetLastError(), mem);
179  flags = GlobalFlags(gbl);
180  ok( flags == 2, "returned 0x%04x with %d (expected '0x0002')\n",
181  flags, GetLastError());
183 
185  res = GlobalUnlock(gbl); /* #1 */
186  ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
188  flags = GlobalFlags(gbl);
189  ok( flags , "returned 0x%04x with %d (expected '!= 0')\n",
190  flags, GetLastError());
191 
193  res = GlobalUnlock(gbl); /* #0 */
194  /* NT: ERROR_SUCCESS (documented on MSDN), 9x: untouched */
195  ok(!res && ((GetLastError() == ERROR_SUCCESS) || (GetLastError() == MAGIC_DEAD)),
196  "returned %d with %d (expected '0' with: ERROR_SUCCESS or "
197  "MAGIC_DEAD)\n", res, GetLastError());
199  flags = GlobalFlags(gbl);
200  ok( !flags , "returned 0x%04x with %d (expected '0')\n",
201  flags, GetLastError());
202 
203  /* Unlock an already unlocked Handle */
205  res = GlobalUnlock(gbl);
206  /* NT: ERROR_NOT_LOCKED, 9x: untouched */
207  ok( !res &&
209  "returned %d with %d (expected '0' with: ERROR_NOT_LOCKED or "
210  "MAGIC_DEAD)\n", res, GetLastError());
211 
212  GlobalFree(gbl);
213  /* invalid handles are caught in windows: */
215  hsecond = GlobalFree(gbl); /* invalid handle: free memory twice */
216  ok( (hsecond == gbl) && (GetLastError() == ERROR_INVALID_HANDLE),
217  "returned %p with 0x%08x (expected %p with ERROR_INVALID_HANDLE)\n",
218  hsecond, GetLastError(), gbl);
220  hsecond = GlobalFree(LongToHandle(0xdeadbeef)); /* bogus handle */
221  ok( (hsecond == LongToHandle(0xdeadbeef)) && (GetLastError() == ERROR_INVALID_HANDLE),
222  "returned %p with 0x%08x (expected %p with ERROR_INVALID_HANDLE)\n",
223  hsecond, GetLastError(), LongToHandle(0xdeadbeef));
225  hsecond = GlobalFree(LongToHandle(0xdeadbee0)); /* bogus pointer */
226  ok( (hsecond == LongToHandle(0xdeadbee0)) &&
227  ((GetLastError() == ERROR_INVALID_HANDLE) || broken(GetLastError() == ERROR_NOACCESS) /* wvista+ */),
228  "returned %p with 0x%08x (expected %p with ERROR_NOACCESS)\n",
229  hsecond, GetLastError(), LongToHandle(0xdeadbee0));
230 
232  flags = GlobalFlags(gbl);
234  "returned 0x%04x with 0x%08x (expected GMEM_INVALID_HANDLE with "
235  "ERROR_INVALID_HANDLE)\n", flags, GetLastError());
237  size = GlobalSize(gbl);
238  ok( (size == 0) && (GetLastError() == ERROR_INVALID_HANDLE),
239  "returned %ld with 0x%08x (expected '0' with ERROR_INVALID_HANDLE)\n",
240  size, GetLastError());
241 
243  mem = GlobalLock(gbl);
244  ok( (mem == NULL) && (GetLastError() == ERROR_INVALID_HANDLE),
245  "returned %p with 0x%08x (expected NULL with ERROR_INVALID_HANDLE)\n",
246  mem, GetLastError());
247 
248  /* documented on MSDN: GlobalUnlock() return FALSE on failure.
249  Win9x and wine return FALSE with ERROR_INVALID_HANDLE, but on
250  NT 3.51 and XPsp2, TRUE with ERROR_INVALID_HANDLE is returned.
251  The similar Test for LocalUnlock() works on all Systems */
253  res = GlobalUnlock(gbl);
255  "returned %d with %d (expected ERROR_INVALID_HANDLE)\n",
256  res, GetLastError());
257 
258  gbl = GlobalAlloc(GMEM_DDESHARE, 100);
259 
260  /* first free */
261  mem = GlobalFree(gbl);
262  ok(mem == NULL, "Expected NULL, got %p\n", mem);
263 
264  /* invalid free */
265  if (sizeof(void *) != 8) /* crashes on 64-bit */
266  {
268  mem = GlobalFree(gbl);
269  ok(mem == gbl || broken(mem == NULL) /* nt4 */, "Expected gbl, got %p\n", mem);
270  if (mem == gbl)
272  GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
273  "Expected ERROR_INVALID_HANDLE or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
274  }
275 
276  /* GMEM_FIXED block expands in place only without flags */
277  for (size = 1; size <= max_size; size <<= 1) {
278  gbl = GlobalAlloc(GMEM_FIXED, init_size);
280  hsecond = GlobalReAlloc(gbl, size + init_size, 0);
281  ok(hsecond == gbl || (hsecond == NULL && GetLastError() == ERROR_NOT_ENOUGH_MEMORY),
282  "got %p with %x (expected %p or NULL) @%ld\n", hsecond, GetLastError(), gbl, size);
283  GlobalFree(gbl);
284  }
285 
286  /* GMEM_FIXED block can be relocated with GMEM_MOVEABLE */
287  for (size = 1; size <= max_size; size <<= 1) {
288  gbl = GlobalAlloc(GMEM_FIXED, init_size);
290  hsecond = GlobalReAlloc(gbl, size + init_size, GMEM_MOVEABLE);
291  ok(hsecond != NULL,
292  "got %p with %x (expected non-NULL) @%ld\n", hsecond, GetLastError(), size);
293  mem = GlobalLock(hsecond);
294  ok(mem == hsecond, "got %p (expected %p) @%ld\n", mem, hsecond, size);
295  GlobalFree(hsecond);
296  }
297 
298  gbl = GlobalAlloc(GMEM_DDESHARE, 100);
299 
300  res = GlobalUnlock(gbl);
301  ok(res == 1 ||
302  broken(res == 0), /* win9x */
303  "Expected 1 or 0, got %d\n", res);
304 
305  res = GlobalUnlock(gbl);
306  ok(res == 1 ||
307  broken(res == 0), /* win9x */
308  "Expected 1 or 0, got %d\n", res);
309 
310  GlobalFree(gbl);
311 
312  gbl = GlobalAlloc(GMEM_FIXED, 100);
313 
314  SetLastError(0xdeadbeef);
315  res = GlobalUnlock(gbl);
316  ok(res == 1 ||
317  broken(res == 0), /* win9x */
318  "Expected 1 or 0, got %d\n", res);
319  ok(GetLastError() == 0xdeadbeef, "got %d\n", GetLastError());
320 
321  GlobalFree(gbl);
322 
323  /* GlobalSize on an invalid handle */
324  if (sizeof(void *) != 8) /* crashes on 64-bit Vista */
325  {
327  size = GlobalSize((HGLOBAL)0xc042);
328  ok(size == 0, "Expected 0, got %ld\n", size);
330  GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
331  "Expected ERROR_INVALID_HANDLE or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
332  }
333 
334  gbl = GlobalAlloc( GMEM_FIXED, 0 );
335  SetLastError(0xdeadbeef);
336  size = GlobalSize( gbl );
337  ok( size == 1, "wrong size %lu\n", size );
338  GlobalFree( gbl );
339 
340  /* ####################################### */
341  /* Local*() functions */
342  gbl = LocalAlloc(LMEM_MOVEABLE, 0);
343  ok(gbl != NULL, "local memory not allocated for size 0\n");
344 
345  gbl = LocalReAlloc(gbl, 10, LMEM_MOVEABLE);
346  ok(gbl != NULL, "Can't realloc local memory\n");
347  size = LocalSize(gbl);
348  ok(size >= 10 && size <= 16, "Memory not resized to size 10, instead size=%ld\n", size);
349 
350  gbl = LocalReAlloc(gbl, 0, LMEM_MOVEABLE);
351  ok(gbl != NULL, "LocalReAlloc should not fail on size 0\n");
352 
353  size = LocalSize(gbl);
354  ok(size == 0, "Memory not resized to size 0, instead size=%ld\n", size);
355  ok(LocalFree(gbl) == NULL, "Memory not freed\n");
356  size = LocalSize(gbl);
357  ok(size == 0, "Memory should have been freed, size=%ld\n", size);
358 
359  gbl = LocalReAlloc(0, 10, LMEM_MOVEABLE);
360  ok(gbl == NULL, "local realloc allocated memory\n");
361 
362  /* LocalLock / LocalUnlock with a valid handle */
363  gbl = LocalAlloc(LMEM_MOVEABLE, 256);
365  mem = LocalLock(gbl); /* #1 */
366  ok(mem != NULL, "returned %p with %d (expected '!= NULL')\n", mem, GetLastError());
368  flags = LocalFlags(gbl);
369  ok( flags == 1, "returned 0x%04x with %d (expected '0x0001')\n",
370  flags, GetLastError());
371 
373  msecond = LocalLock(gbl); /* #2 */
374  ok( msecond == mem, "returned %p with %d (expected '%p')\n",
375  msecond, GetLastError(), mem);
377  flags = LocalFlags(gbl);
378  ok( flags == 2, "returned 0x%04x with %d (expected '0x0002')\n",
379  flags, GetLastError());
381 
383  res = LocalUnlock(gbl); /* #1 */
384  ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
386  flags = LocalFlags(gbl);
387  ok( flags , "returned 0x%04x with %d (expected '!= 0')\n",
388  flags, GetLastError());
389 
391  res = LocalUnlock(gbl); /* #0 */
392  /* NT: ERROR_SUCCESS (documented on MSDN), 9x: untouched */
393  ok(!res && ((GetLastError() == ERROR_SUCCESS) || (GetLastError() == MAGIC_DEAD)),
394  "returned %d with %d (expected '0' with: ERROR_SUCCESS or "
395  "MAGIC_DEAD)\n", res, GetLastError());
397  flags = LocalFlags(gbl);
398  ok( !flags , "returned 0x%04x with %d (expected '0')\n",
399  flags, GetLastError());
400 
401  /* Unlock an already unlocked Handle */
403  res = LocalUnlock(gbl);
404  /* NT: ERROR_NOT_LOCKED, 9x: untouched */
405  ok( !res &&
407  "returned %d with %d (expected '0' with: ERROR_NOT_LOCKED or "
408  "MAGIC_DEAD)\n", res, GetLastError());
409 
410  LocalFree(gbl);
411  /* invalid handles are caught in windows: */
413  hsecond = LocalFree(gbl); /* invalid handle: free memory twice */
414  ok( (hsecond == gbl) && (GetLastError() == ERROR_INVALID_HANDLE),
415  "returned %p with 0x%08x (expected %p with ERROR_INVALID_HANDLE)\n",
416  hsecond, GetLastError(), gbl);
418  flags = LocalFlags(gbl);
420  "returned 0x%04x with 0x%08x (expected LMEM_INVALID_HANDLE with "
421  "ERROR_INVALID_HANDLE)\n", flags, GetLastError());
423  size = LocalSize(gbl);
424  ok( (size == 0) && (GetLastError() == ERROR_INVALID_HANDLE),
425  "returned %ld with 0x%08x (expected '0' with ERROR_INVALID_HANDLE)\n",
426  size, GetLastError());
427 
429  mem = LocalLock(gbl);
430  ok( (mem == NULL) && (GetLastError() == ERROR_INVALID_HANDLE),
431  "returned %p with 0x%08x (expected NULL with ERROR_INVALID_HANDLE)\n",
432  mem, GetLastError());
433 
434  /* This Test works the same on all Systems (GlobalUnlock() is different) */
436  res = LocalUnlock(gbl);
438  "returned %d with %d (expected '0' with ERROR_INVALID_HANDLE)\n",
439  res, GetLastError());
440 
441  /* LMEM_FIXED block expands in place only without flags */
442  for (size = 1; size <= max_size; size <<= 1) {
443  gbl = LocalAlloc(LMEM_FIXED, init_size);
445  hsecond = LocalReAlloc(gbl, size + init_size, 0);
446  ok(hsecond == gbl || (hsecond == NULL && GetLastError() == ERROR_NOT_ENOUGH_MEMORY),
447  "got %p with %x (expected %p or NULL) @%ld\n", hsecond, GetLastError(), gbl, size);
448  LocalFree(gbl);
449  }
450 
451  /* LMEM_FIXED memory can be relocated with LMEM_MOVEABLE */
452  for (size = 1; size <= max_size; size <<= 1) {
453  gbl = LocalAlloc(LMEM_FIXED, init_size);
455  hsecond = LocalReAlloc(gbl, size + init_size, LMEM_MOVEABLE);
456  ok(hsecond != NULL,
457  "got %p with %x (expected non-NULL) @%ld\n", hsecond, GetLastError(), size);
458  mem = LocalLock(hsecond);
459  ok(mem == hsecond, "got %p (expected %p) @%ld\n", mem, hsecond, size);
460  LocalFree(hsecond);
461  }
462 
463  /* trying to unlock pointer from LocalAlloc */
464  gbl = LocalAlloc(LMEM_FIXED, 100);
465  SetLastError(0xdeadbeef);
466  res = LocalUnlock(gbl);
467  ok(res == 0, "Expected 0, got %d\n", res);
469  broken(GetLastError() == 0xdeadbeef) /* win9x */, "got %d\n", GetLastError());
470  LocalFree(gbl);
471 
472  gbl = LocalAlloc( LMEM_FIXED, 0 );
473  SetLastError(0xdeadbeef);
474  size = LocalSize( gbl );
475  ok( !size || broken(size == 1), /* vistau64 */
476  "wrong size %lu\n", size );
477  LocalFree( gbl );
478 
479  /* trying to lock empty memory should give an error */
481  ok(gbl != NULL, "returned NULL\n");
483  mem = GlobalLock(gbl);
484  /* NT: ERROR_DISCARDED, 9x: untouched */
485  ok( (mem == NULL) &&
487  "returned %p with 0x%x/%d (expected 'NULL' with: ERROR_DISCARDED or "
488  "MAGIC_DEAD)\n", mem, GetLastError(), GetLastError());
489 
490  GlobalFree(gbl);
491 
492  /* trying to get size from data pointer (GMEM_MOVEABLE) */
493  gbl = GlobalAlloc(GMEM_MOVEABLE, 0x123);
494  ok(gbl != NULL, "returned NULL\n");
495  mem = GlobalLock(gbl);
496  ok(mem != NULL, "returned NULL.\n");
497  ok(gbl != mem, "unexpectedly equal.\n");
498 
499  size = GlobalSize(gbl);
500  size2 = GlobalSize(mem);
501  ok(size == 0x123, "got %lu\n", size);
502  ok(size2 == 0x123, "got %lu\n", size2);
503 
504  GlobalFree(gbl);
505 
506  /* trying to get size from data pointer (GMEM_FIXED) */
507  gbl = GlobalAlloc(GMEM_FIXED, 0x123);
508  ok(gbl != NULL, "returned NULL\n");
509  mem = GlobalLock(gbl);
510  ok(mem != NULL, "returned NULL.\n");
511  ok(gbl == mem, "got %p, %p.\n", gbl, mem);
512 
513  size = GlobalSize(gbl);
514  ok(size == 0x123, "got %lu\n", size);
515 
516  GlobalFree(gbl);
517 
518  size = GlobalSize((void *)0xdeadbee0);
519  ok(size == 0, "got %lu\n", size);
520 
521 }
522 
523 
524 static void test_HeapCreate(void)
525 {
526  SYSTEM_INFO sysInfo;
527  ULONG memchunk;
528  HANDLE heap;
529  LPVOID mem1,mem1a,mem3;
530  UCHAR *mem2,*mem2a;
531  UINT i;
532  BOOL error;
533  DWORD dwSize;
534 
535  /* Retrieve the page size for this system */
536  GetSystemInfo(&sysInfo);
537  ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
538 
539  /* Create a Heap with a minimum and maximum size */
540  /* Note that Windows and Wine seem to behave a bit differently with respect
541  to memory allocation. In Windows, you can't access all the memory
542  specified in the heap (due to overhead), so choosing a reasonable maximum
543  size for the heap was done mostly by trial-and-error on Win2k. It may need
544  more tweaking for otherWindows variants.
545  */
546  memchunk=10*sysInfo.dwPageSize;
547  heap=HeapCreate(0,2*memchunk,5*memchunk);
548  ok( !((ULONG_PTR)heap & 0xffff), "heap %p not 64K aligned\n", heap );
549 
550  /* Check that HeapCreate allocated the right amount of ram */
551  mem1=HeapAlloc(heap,0,5*memchunk+1);
552  ok(mem1==NULL,"HeapCreate allocated more Ram than it should have\n");
553  HeapFree(heap,0,mem1);
554 
555  /* Check that a normal alloc works */
556  mem1=HeapAlloc(heap,0,memchunk);
557  ok(mem1!=NULL,"HeapAlloc failed\n");
558  if(mem1) {
559  ok(HeapSize(heap,0,mem1)>=memchunk, "HeapAlloc should return a big enough memory block\n");
560  }
561 
562  /* Check that a 'zeroing' alloc works */
563  mem2=HeapAlloc(heap,HEAP_ZERO_MEMORY,memchunk);
564  ok(mem2!=NULL,"HeapAlloc failed\n");
565  if(mem2) {
566  ok(HeapSize(heap,0,mem2)>=memchunk,"HeapAlloc should return a big enough memory block\n");
567  error=FALSE;
568  for(i=0;i<memchunk;i++) {
569  if(mem2[i]!=0) {
570  error=TRUE;
571  }
572  }
573  ok(!error,"HeapAlloc should have zeroed out its allocated memory\n");
574  }
575 
576  /* Check that HeapAlloc returns NULL when requested way too much memory */
577  mem3=HeapAlloc(heap,0,5*memchunk);
578  ok(mem3==NULL,"HeapAlloc should return NULL\n");
579  if(mem3) {
580  ok(HeapFree(heap,0,mem3),"HeapFree didn't pass successfully\n");
581  }
582 
583  /* Check that HeapReAlloc works */
584  mem2a=HeapReAlloc(heap,HEAP_ZERO_MEMORY,mem2,memchunk+5*sysInfo.dwPageSize);
585  ok(mem2a!=NULL,"HeapReAlloc failed\n");
586  if(mem2a) {
587  ok(HeapSize(heap,0,mem2a)>=memchunk+5*sysInfo.dwPageSize,"HeapReAlloc failed\n");
588  error=FALSE;
589  for(i=0;i<5*sysInfo.dwPageSize;i++) {
590  if(mem2a[memchunk+i]!=0) {
591  error=TRUE;
592  }
593  }
594  ok(!error,"HeapReAlloc should have zeroed out its allocated memory\n");
595  }
596 
597  /* Check that HeapReAlloc honours HEAP_REALLOC_IN_PLACE_ONLY */
598  error=FALSE;
599  mem1a=HeapReAlloc(heap,HEAP_REALLOC_IN_PLACE_ONLY,mem1,memchunk+sysInfo.dwPageSize);
600  if(mem1a!=NULL) {
601  if(mem1a!=mem1) {
602  error=TRUE;
603  }
604  }
605  ok(mem1a==NULL || !error,"HeapReAlloc didn't honour HEAP_REALLOC_IN_PLACE_ONLY\n");
606 
607  /* Check that HeapFree works correctly */
608  if(mem1a) {
609  ok(HeapFree(heap,0,mem1a),"HeapFree failed\n");
610  } else {
611  ok(HeapFree(heap,0,mem1),"HeapFree failed\n");
612  }
613  if(mem2a) {
614  ok(HeapFree(heap,0,mem2a),"HeapFree failed\n");
615  } else {
616  ok(HeapFree(heap,0,mem2),"HeapFree failed\n");
617  }
618 
619  /* 0-length buffer */
620  mem1 = HeapAlloc(heap, 0, 0);
621  ok(mem1 != NULL, "Reserved memory\n");
622 
623  dwSize = HeapSize(heap, 0, mem1);
624  /* should work with 0-length buffer */
625  ok(dwSize < 0xFFFFFFFF, "The size of the 0-length buffer\n");
626  ok(HeapFree(heap, 0, mem1), "Freed the 0-length buffer\n");
627 
628  /* Check that HeapDestroy works */
629  ok(HeapDestroy(heap),"HeapDestroy failed\n");
630 }
631 
632 
633 static void test_GlobalAlloc(void)
634 {
635  ULONG memchunk;
636  HGLOBAL mem1,mem2,mem2a,mem2b;
637  UCHAR *mem2ptr;
638  UINT i;
639  BOOL error;
640  memchunk=100000;
641 
643  /* Check that a normal alloc works */
644  mem1=GlobalAlloc(0,memchunk);
645  ok(mem1!=NULL,"GlobalAlloc failed\n");
646  if(mem1) {
647  ok(GlobalSize(mem1)>=memchunk, "GlobalAlloc should return a big enough memory block\n");
648  }
649 
650  /* Check that a 'zeroing' alloc works */
651  mem2=GlobalAlloc(GMEM_ZEROINIT,memchunk);
652  ok(mem2!=NULL,"GlobalAlloc failed: error=%d\n",GetLastError());
653  if(mem2) {
654  ok(GlobalSize(mem2)>=memchunk,"GlobalAlloc should return a big enough memory block\n");
655  mem2ptr=GlobalLock(mem2);
656  ok(mem2ptr==mem2,"GlobalLock should have returned the same memory as was allocated\n");
657  if(mem2ptr) {
658  error=FALSE;
659  for(i=0;i<memchunk;i++) {
660  if(mem2ptr[i]!=0) {
661  error=TRUE;
662  }
663  }
664  ok(!error,"GlobalAlloc should have zeroed out its allocated memory\n");
665  }
666  }
667  /* Check that GlobalReAlloc works */
668  /* Check that we can change GMEM_FIXED to GMEM_MOVEABLE */
669  mem2a=GlobalReAlloc(mem2,0,GMEM_MODIFY | GMEM_MOVEABLE);
670  if(mem2a!=NULL) {
671  mem2=mem2a;
672  mem2ptr=GlobalLock(mem2a);
673  ok(mem2ptr!=NULL && !GlobalUnlock(mem2a)&&GetLastError()==NO_ERROR,
674  "Converting from FIXED to MOVEABLE didn't REALLY work\n");
675  }
676 
677  /* Check that ReAllocing memory works as expected */
678  mem2a=GlobalReAlloc(mem2,2*memchunk,GMEM_MOVEABLE | GMEM_ZEROINIT);
679  ok(mem2a!=NULL,"GlobalReAlloc failed\n");
680  if(mem2a) {
681  ok(GlobalSize(mem2a)>=2*memchunk,"GlobalReAlloc failed\n");
682  mem2ptr=GlobalLock(mem2a);
683  ok(mem2ptr!=NULL,"GlobalLock Failed\n");
684  if(mem2ptr) {
685  error=FALSE;
686  for(i=0;i<memchunk;i++) {
687  if(mem2ptr[memchunk+i]!=0) {
688  error=TRUE;
689  }
690  }
691  ok(!error,"GlobalReAlloc should have zeroed out its allocated memory\n");
692 
693  /* Check that GlobalHandle works */
694  mem2b=GlobalHandle(mem2ptr);
695  ok(mem2b==mem2a,"GlobalHandle didn't return the correct memory handle %p/%p for %p\n",
696  mem2a, mem2b, mem2ptr);
697  /* Check that we can't discard locked memory */
698  mem2b=GlobalDiscard(mem2a);
699  if(mem2b==NULL) {
700  ok(!GlobalUnlock(mem2a) && GetLastError()==NO_ERROR,"GlobalUnlock Failed\n");
701  }
702  }
703  }
704  if(mem1) {
705  ok(GlobalFree(mem1)==NULL,"GlobalFree failed\n");
706  }
707  if(mem2a) {
708  ok(GlobalFree(mem2a)==NULL,"GlobalFree failed\n");
709  } else {
710  ok(GlobalFree(mem2)==NULL,"GlobalFree failed\n");
711  }
712 }
713 
714 
715 static void test_LocalAlloc(void)
716 {
717  ULONG memchunk;
718  HLOCAL mem1,mem2,mem2a,mem2b;
719  UCHAR *mem2ptr;
720  UINT i;
721  BOOL error;
722  memchunk=100000;
723 
724  /* Check that a normal alloc works */
725  mem1=LocalAlloc(0,memchunk);
726  ok(mem1!=NULL,"LocalAlloc failed: error=%d\n",GetLastError());
727  if(mem1) {
728  ok(LocalSize(mem1)>=memchunk, "LocalAlloc should return a big enough memory block\n");
729  }
730 
731  /* Check that a 'zeroing' and lock alloc works */
732  mem2=LocalAlloc(LMEM_ZEROINIT|LMEM_MOVEABLE,memchunk);
733  ok(mem2!=NULL,"LocalAlloc failed: error=%d\n",GetLastError());
734  if(mem2) {
735  ok(LocalSize(mem2)>=memchunk,"LocalAlloc should return a big enough memory block\n");
736  mem2ptr=LocalLock(mem2);
737  ok(mem2ptr!=NULL,"LocalLock: error=%d\n",GetLastError());
738  if(mem2ptr) {
739  error=FALSE;
740  for(i=0;i<memchunk;i++) {
741  if(mem2ptr[i]!=0) {
742  error=TRUE;
743  }
744  }
745  ok(!error,"LocalAlloc should have zeroed out its allocated memory\n");
746  SetLastError(0);
747  error=LocalUnlock(mem2);
748  ok(!error && GetLastError()==NO_ERROR,
749  "LocalUnlock Failed: rc=%d err=%d\n",error,GetLastError());
750  }
751  }
752  mem2a=LocalFree(mem2);
753  ok(mem2a==NULL, "LocalFree failed: %p\n",mem2a);
754 
755  /* Reallocate mem2 as moveable memory */
756  mem2=LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT,memchunk);
757  ok(mem2!=NULL, "LocalAlloc failed to create moveable memory, error=%d\n",GetLastError());
758 
759  /* Check that ReAllocing memory works as expected */
760  mem2a=LocalReAlloc(mem2,2*memchunk,LMEM_MOVEABLE | LMEM_ZEROINIT);
761  ok(mem2a!=NULL,"LocalReAlloc failed, error=%d\n",GetLastError());
762  if(mem2a) {
763  ok(LocalSize(mem2a)>=2*memchunk,"LocalReAlloc failed\n");
764  mem2ptr=LocalLock(mem2a);
765  ok(mem2ptr!=NULL,"LocalLock Failed\n");
766  if(mem2ptr) {
767  error=FALSE;
768  for(i=0;i<memchunk;i++) {
769  if(mem2ptr[memchunk+i]!=0) {
770  error=TRUE;
771  }
772  }
773  ok(!error,"LocalReAlloc should have zeroed out its allocated memory\n");
774  /* Check that LocalHandle works */
775  mem2b=LocalHandle(mem2ptr);
776  ok(mem2b==mem2a,"LocalHandle didn't return the correct memory handle %p/%p for %p\n",
777  mem2a, mem2b, mem2ptr);
778  /* Check that we can't discard locked memory */
779  mem2b=LocalDiscard(mem2a);
780  ok(mem2b==NULL,"Discarded memory we shouldn't have\n");
782  ok(!LocalUnlock(mem2a) && GetLastError()==NO_ERROR, "LocalUnlock Failed\n");
783  }
784  }
785  if(mem1) {
786  ok(LocalFree(mem1)==NULL,"LocalFree failed\n");
787  }
788  if(mem2a) {
789  ok(LocalFree(mem2a)==NULL,"LocalFree failed\n");
790  } else {
791  ok(LocalFree(mem2)==NULL,"LocalFree failed\n");
792  }
793 }
794 
795 static void test_obsolete_flags(void)
796 {
797  static struct {
798  UINT flags;
799  UINT globalflags;
800  } test_global_flags[] = {
801  {GMEM_FIXED | GMEM_NOTIFY, 0},
803  {GMEM_MOVEABLE | GMEM_NOTIFY, 0},
810  };
811 
812  unsigned int i;
813  HGLOBAL gbl;
814  UINT resultflags;
815 
816  UINT (WINAPI *pGlobalFlags)(HGLOBAL);
817 
818  pGlobalFlags = (void *) GetProcAddress(GetModuleHandleA("kernel32"), "GlobalFlags");
819 
820  if (!pGlobalFlags)
821  {
822  win_skip("GlobalFlags is not available\n");
823  return;
824  }
825 
826  for (i = 0; i < sizeof(test_global_flags)/sizeof(test_global_flags[0]); i++)
827  {
828  gbl = GlobalAlloc(test_global_flags[i].flags, 4);
829  ok(gbl != NULL, "GlobalAlloc failed\n");
830 
832  resultflags = pGlobalFlags(gbl);
833 
834  ok( resultflags == test_global_flags[i].globalflags ||
835  broken(resultflags == (test_global_flags[i].globalflags & ~GMEM_DDESHARE)), /* win9x */
836  "%u: expected 0x%08x, but returned 0x%08x with %d\n",
837  i, test_global_flags[i].globalflags, resultflags, GetLastError() );
838 
839  GlobalFree(gbl);
840  }
841 }
842 
843 static void test_HeapQueryInformation(void)
844 {
845  ULONG info;
846  SIZE_T size;
847  BOOL ret;
848 
849  pHeapQueryInformation = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "HeapQueryInformation");
850  if (!pHeapQueryInformation)
851  {
852  win_skip("HeapQueryInformation is not available\n");
853  return;
854  }
855 
856  if (0) /* crashes under XP */
857  {
858  size = 0;
859  pHeapQueryInformation(0,
861  &info, sizeof(info), &size);
862  size = 0;
863  pHeapQueryInformation(GetProcessHeap(),
865  NULL, sizeof(info), &size);
866  }
867 
868  size = 0;
869  SetLastError(0xdeadbeef);
870  ret = pHeapQueryInformation(GetProcessHeap(),
872  NULL, 0, &size);
873  ok(!ret, "HeapQueryInformation should fail\n");
875  "expected ERROR_INSUFFICIENT_BUFFER got %u\n", GetLastError());
876  ok(size == sizeof(ULONG), "expected 4, got %lu\n", size);
877 
878  SetLastError(0xdeadbeef);
879  ret = pHeapQueryInformation(GetProcessHeap(),
881  NULL, 0, NULL);
882  ok(!ret, "HeapQueryInformation should fail\n");
884  "expected ERROR_INSUFFICIENT_BUFFER got %u\n", GetLastError());
885 
886  info = 0xdeadbeaf;
887  SetLastError(0xdeadbeef);
888  ret = pHeapQueryInformation(GetProcessHeap(),
890  &info, sizeof(info) + 1, NULL);
891  ok(ret, "HeapQueryInformation error %u\n", GetLastError());
892  ok(info == 0 || info == 1 || info == 2, "expected 0, 1 or 2, got %u\n", info);
893 }
894 
896 {
897  BYTE old, *p, *p2;
898  BOOL ret;
899  SIZE_T i, size, large_size = 3000 * 1024 + 37;
900 
901  if (flags & HEAP_PAGE_ALLOCS) return; /* no tests for that case yet */
902  trace( "testing heap flags %08x\n", flags );
903 
905  ok( p != NULL, "HeapAlloc failed\n" );
906 
907  ret = HeapValidate( GetProcessHeap(), 0, p );
908  ok( ret, "HeapValidate failed\n" );
909 
910  size = HeapSize( GetProcessHeap(), 0, p );
911  ok( size == 17, "Wrong size %lu\n", size );
912 
913  ok( p[14] == 0, "wrong data %x\n", p[14] );
914  ok( p[15] == 0, "wrong data %x\n", p[15] );
915  ok( p[16] == 0, "wrong data %x\n", p[16] );
916 
918  {
919  ok( p[17] == 0xab, "wrong padding %x\n", p[17] );
920  ok( p[18] == 0xab, "wrong padding %x\n", p[18] );
921  ok( p[19] == 0xab, "wrong padding %x\n", p[19] );
922  }
923 
925  if (p2 == p)
926  {
928  {
929  ok( p[14] == 0xab, "wrong padding %x\n", p[14] );
930  ok( p[15] == 0xab, "wrong padding %x\n", p[15] );
931  ok( p[16] == 0xab, "wrong padding %x\n", p[16] );
932  }
933  else
934  {
935  ok( p[14] == 0, "wrong padding %x\n", p[14] );
936  ok( p[15] == 0, "wrong padding %x\n", p[15] );
937  }
938  }
939  else skip( "realloc in place failed\n");
940 
941  ret = HeapFree( GetProcessHeap(), 0, p );
942  ok( ret, "HeapFree failed\n" );
943 
945  ok( p != NULL, "HeapAlloc failed\n" );
946  old = p[17];
947  p[17] = 0xcc;
948 
950  {
951  ret = HeapValidate( GetProcessHeap(), 0, p );
952  ok( !ret, "HeapValidate succeeded\n" );
953 
954  /* other calls only check when HEAP_VALIDATE is set */
955  if (flags & HEAP_VALIDATE)
956  {
957  size = HeapSize( GetProcessHeap(), 0, p );
958  ok( size == ~(SIZE_T)0 || broken(size == ~0u), "Wrong size %lu\n", size );
959 
960  p2 = HeapReAlloc( GetProcessHeap(), 0, p, 14 );
961  ok( p2 == NULL, "HeapReAlloc succeeded\n" );
962 
963  ret = HeapFree( GetProcessHeap(), 0, p );
964  ok( !ret || broken(sizeof(void*) == 8), /* not caught on xp64 */
965  "HeapFree succeeded\n" );
966  }
967 
968  p[17] = old;
969  size = HeapSize( GetProcessHeap(), 0, p );
970  ok( size == 17, "Wrong size %lu\n", size );
971 
972  p2 = HeapReAlloc( GetProcessHeap(), 0, p, 14 );
973  ok( p2 != NULL, "HeapReAlloc failed\n" );
974  p = p2;
975  }
976 
977  ret = HeapFree( GetProcessHeap(), 0, p );
978  ok( ret, "HeapFree failed\n" );
979 
980  p = HeapAlloc( GetProcessHeap(), 0, 37 );
981  ok( p != NULL, "HeapAlloc failed\n" );
982  memset( p, 0xcc, 37 );
983 
984  ret = HeapFree( GetProcessHeap(), 0, p );
985  ok( ret, "HeapFree failed\n" );
986 
988  {
989  ok( p[16] == 0xee, "wrong data %x\n", p[16] );
990  ok( p[17] == 0xfe, "wrong data %x\n", p[17] );
991  ok( p[18] == 0xee, "wrong data %x\n", p[18] );
992  ok( p[19] == 0xfe, "wrong data %x\n", p[19] );
993 
994  ret = HeapValidate( GetProcessHeap(), 0, NULL );
995  ok( ret, "HeapValidate failed\n" );
996 
997  old = p[16];
998  p[16] = 0xcc;
999  ret = HeapValidate( GetProcessHeap(), 0, NULL );
1000  ok( !ret, "HeapValidate succeeded\n" );
1001 
1002  p[16] = old;
1003  ret = HeapValidate( GetProcessHeap(), 0, NULL );
1004  ok( ret, "HeapValidate failed\n" );
1005  }
1006 
1007  /* now test large blocks */
1008 
1009  p = HeapAlloc( GetProcessHeap(), 0, large_size );
1010  ok( p != NULL, "HeapAlloc failed\n" );
1011 
1012  ret = HeapValidate( GetProcessHeap(), 0, p );
1013  ok( ret, "HeapValidate failed\n" );
1014 
1015  size = HeapSize( GetProcessHeap(), 0, p );
1016  ok( size == large_size, "Wrong size %lu\n", size );
1017 
1018  ok( p[large_size - 2] == 0, "wrong data %x\n", p[large_size - 2] );
1019  ok( p[large_size - 1] == 0, "wrong data %x\n", p[large_size - 1] );
1020 
1022  {
1023  /* Windows doesn't do tail checking on large blocks */
1024  ok( p[large_size] == 0xab || broken(p[large_size] == 0), "wrong data %x\n", p[large_size] );
1025  ok( p[large_size+1] == 0xab || broken(p[large_size+1] == 0), "wrong data %x\n", p[large_size+1] );
1026  ok( p[large_size+2] == 0xab || broken(p[large_size+2] == 0), "wrong data %x\n", p[large_size+2] );
1027  if (p[large_size] == 0xab)
1028  {
1029  p[large_size] = 0xcc;
1030  ret = HeapValidate( GetProcessHeap(), 0, p );
1031  ok( !ret, "HeapValidate succeeded\n" );
1032 
1033  /* other calls only check when HEAP_VALIDATE is set */
1034  if (flags & HEAP_VALIDATE)
1035  {
1036  size = HeapSize( GetProcessHeap(), 0, p );
1037  ok( size == ~(SIZE_T)0, "Wrong size %lu\n", size );
1038 
1039  p2 = HeapReAlloc( GetProcessHeap(), 0, p, large_size - 3 );
1040  ok( p2 == NULL, "HeapReAlloc succeeded\n" );
1041 
1042  ret = HeapFree( GetProcessHeap(), 0, p );
1043  ok( !ret, "HeapFree succeeded\n" );
1044  }
1045  p[large_size] = 0xab;
1046  }
1047  }
1048 
1049  ret = HeapFree( GetProcessHeap(), 0, p );
1050  ok( ret, "HeapFree failed\n" );
1051 
1052  /* test block sizes when tail checking */
1054  {
1055  for (size = 0; size < 64; size++)
1056  {
1057  p = HeapAlloc( GetProcessHeap(), 0, size );
1058  for (i = 0; i < 32; i++) if (p[size + i] != 0xab) break;
1059  ok( i >= 8, "only %lu tail bytes for size %lu\n", i, size );
1060  HeapFree( GetProcessHeap(), 0, p );
1061  }
1062  }
1063 }
1064 
1065 static void test_debug_heap( const char *argv0, DWORD flags )
1066 {
1067  char keyname[MAX_PATH];
1068  char buffer[MAX_PATH];
1071  BOOL ret;
1072  DWORD err;
1073  HKEY hkey;
1074  const char *basename;
1075 
1076  if ((basename = strrchr( argv0, '\\' ))) basename++;
1077  else basename = argv0;
1078 
1079  sprintf( keyname, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\%s",
1080  basename );
1081  if (!strcmp( keyname + strlen(keyname) - 3, ".so" )) keyname[strlen(keyname) - 3] = 0;
1082 
1083  err = RegCreateKeyA( HKEY_LOCAL_MACHINE, keyname, &hkey );
1084  if (err == ERROR_ACCESS_DENIED)
1085  {
1086  skip("Not authorized to change the image file execution options\n");
1087  return;
1088  }
1089  ok( !err, "failed to create '%s' error %u\n", keyname, err );
1090  if (err) return;
1091 
1092  if (flags == 0xdeadbeef) /* magic value for unsetting it */
1093  RegDeleteValueA( hkey, "GlobalFlag" );
1094  else
1095  RegSetValueExA( hkey, "GlobalFlag", 0, REG_DWORD, (BYTE *)&flags, sizeof(flags) );
1096 
1097  memset( &startup, 0, sizeof(startup) );
1098  startup.cb = sizeof(startup);
1099 
1100  sprintf( buffer, "%s heap.c 0x%x", argv0, flags );
1102  ok( ret, "failed to create child process error %u\n", GetLastError() );
1103  if (ret)
1104  {
1105  winetest_wait_child_process( info.hProcess );
1106  CloseHandle( info.hThread );
1107  CloseHandle( info.hProcess );
1108  }
1109  RegDeleteValueA( hkey, "GlobalFlag" );
1110  RegCloseKey( hkey );
1111  RegDeleteKeyA( HKEY_LOCAL_MACHINE, keyname );
1112 }
1113 
1115 {
1116  DWORD ret = 0;
1117 
1128  if (flag & FLG_HEAP_PAGE_ALLOCS)
1130  return ret;
1131 }
1132 
1133 static void test_child_heap( const char *arg )
1134 {
1135  struct heap_layout *heap = GetProcessHeap();
1136  DWORD expected = strtoul( arg, 0, 16 );
1137  DWORD expect_heap;
1138 
1139  if (expected == 0xdeadbeef) /* expected value comes from Session Manager global flags */
1140  {
1141  HKEY hkey;
1142  expected = 0;
1143  if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Session Manager", &hkey ))
1144  {
1145  char buffer[32];
1146  DWORD type, size = sizeof(buffer);
1147 
1148  if (!RegQueryValueExA( hkey, "GlobalFlag", 0, &type, (BYTE *)buffer, &size ))
1149  {
1150  if (type == REG_DWORD) expected = *(DWORD *)buffer;
1151  else if (type == REG_SZ) expected = strtoul( buffer, 0, 16 );
1152  }
1153  RegCloseKey( hkey );
1154  }
1155  }
1156  if (expected && !pRtlGetNtGlobalFlags()) /* not working on NT4 */
1157  {
1158  win_skip( "global flags not set\n" );
1159  return;
1160  }
1161 
1162  ok( pRtlGetNtGlobalFlags() == expected,
1163  "%s: got global flags %08x expected %08x\n", arg, pRtlGetNtGlobalFlags(), expected );
1164 
1165  expect_heap = heap_flags_from_global_flag( expected );
1166 
1167  if (!(heap->flags & HEAP_GROWABLE) || heap->pattern == 0xffeeffee) /* vista layout */
1168  {
1169  ok( (heap->flags & ~HEAP_GROWABLE) == 0, "%s: got heap flags %08x\n", arg, heap->flags );
1170  }
1171  else if (heap->pattern == 0xeeeeeeee && heap->flags == 0xeeeeeeee)
1172  {
1173  ok( expected & FLG_HEAP_PAGE_ALLOCS, "%s: got heap flags 0xeeeeeeee without page alloc\n", arg );
1174  }
1175  else
1176  {
1177  ok( heap->flags == (expect_heap | HEAP_GROWABLE),
1178  "%s: got heap flags %08x expected %08x\n", arg, heap->flags, expect_heap );
1179  ok( heap->force_flags == (expect_heap & ~0x18000080),
1180  "%s: got heap force flags %08x expected %08x\n", arg, heap->force_flags, expect_heap );
1181  expect_heap = heap->flags;
1182  }
1183 
1184  test_heap_checks( expect_heap );
1185 }
1186 
1188 {
1189  HMODULE kernel32 = GetModuleHandleA("kernel32.dll");
1190  MEMORYSTATUSEX memstatus;
1191  ULONGLONG total_memory;
1192  BOOL ret;
1193 
1194  pGetPhysicallyInstalledSystemMemory = (void *)GetProcAddress(kernel32, "GetPhysicallyInstalledSystemMemory");
1195  if (!pGetPhysicallyInstalledSystemMemory)
1196  {
1197  win_skip("GetPhysicallyInstalledSystemMemory is not available\n");
1198  return;
1199  }
1200 
1201  SetLastError(0xdeadbeef);
1202  ret = pGetPhysicallyInstalledSystemMemory(NULL);
1203  ok(!ret, "GetPhysicallyInstalledSystemMemory should fail\n");
1205  "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1206 
1207  total_memory = 0;
1208  ret = pGetPhysicallyInstalledSystemMemory(&total_memory);
1209  ok(ret, "GetPhysicallyInstalledSystemMemory unexpectedly failed\n");
1210  ok(total_memory != 0, "expected total_memory != 0\n");
1211 
1212  memstatus.dwLength = sizeof(memstatus);
1213  ret = GlobalMemoryStatusEx(&memstatus);
1214  ok(ret, "GlobalMemoryStatusEx unexpectedly failed\n");
1215  ok(total_memory >= memstatus.ullTotalPhys / 1024,
1216  "expected total_memory >= memstatus.ullTotalPhys / 1024\n");
1217 }
1218 
1220 {
1221  int argc;
1222  char **argv;
1223 
1224  pRtlGetNtGlobalFlags = (void *)GetProcAddress( GetModuleHandleA("ntdll.dll"), "RtlGetNtGlobalFlags" );
1225 
1227  if (argc >= 3)
1228  {
1229  test_child_heap( argv[2] );
1230  return;
1231  }
1232 
1233  test_heap();
1235  test_HeapCreate();
1236  test_GlobalAlloc();
1237  test_LocalAlloc();
1238 
1239  /* Test both short and very long blocks */
1241  test_sized_HeapAlloc(1 << 20);
1242  test_sized_HeapReAlloc(1, 100);
1243  test_sized_HeapReAlloc(1, (1 << 20));
1244  test_sized_HeapReAlloc((1 << 20), (2 << 20));
1245  test_sized_HeapReAlloc((1 << 20), 1);
1246 
1249 
1250  if (pRtlGetNtGlobalFlags)
1251  {
1252  test_debug_heap( argv[0], 0 );
1262  test_debug_heap( argv[0], 0xdeadbeef );
1263  }
1264  else win_skip( "RtlGetNtGlobalFlags not found, skipping heap debug tests\n" );
1265 }
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
#define FLG_HEAP_DISABLE_COALESCING
Definition: pstypes.h:80
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
HANDLE HGLOBAL
Definition: windef.h:243
#define HEAP_PAGE_ALLOCS
Definition: heap.c:36
LONG WINAPI RegOpenKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3257
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:4023
static int argc
Definition: ServiceArgs.c:12
#define trace(...)
Definition: kmt_test.h:217
static void test_debug_heap(const char *argv0, DWORD flags)
Definition: heap.c:1065
#define max(a, b)
Definition: svc.c:63
UINT32 strtoul(const char *String, char **Terminator, UINT32 Base)
Definition: utclib.c:696
static ULONG(WINAPI *pRtlGetNtGlobalFlags)(void)
#define TRUE
Definition: types.h:120
HGLOBAL NTAPI GlobalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:368
#define CloseHandle
Definition: compat.h:398
BOOL NTAPI LocalUnlock(HLOCAL hMem)
Definition: heapmem.c:1788
#define ERROR_SUCCESS
Definition: deptool.c:10
#define LocalDiscard(m)
Definition: winbase.h:2629
#define error(str)
Definition: mkdosfs.c:1605
HGLOBAL NTAPI GlobalReAlloc(HGLOBAL hMem, SIZE_T dwBytes, UINT uFlags)
Definition: heapmem.c:825
#define GMEM_NODISCARD
Definition: winbase.h:299
#define HEAP_VALIDATE
Definition: heap.c:37
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
DWORD force_flags
Definition: heap.c:50
HANDLE WINAPI HeapCreate(DWORD flOptions, SIZE_T dwInitialSize, SIZE_T dwMaximumSize)
Definition: heapmem.c:45
static void basename(LPCWSTR path, LPWSTR name)
Definition: profile.c:38
UINT NTAPI GlobalFlags(HGLOBAL hMem)
Definition: heapmem.c:520
#define FLG_HEAP_ENABLE_TAIL_CHECK
Definition: pstypes.h:60
static SIZE_T resize_9x(SIZE_T size)
Definition: heap.c:53
#define ERROR_INVALID_HANDLE
Definition: compat.h:88
static void test_heap_checks(DWORD flags)
Definition: heap.c:895
#define HEAP_VALIDATE_PARAMS
Definition: heap.c:39
#define GMEM_INVALID_HANDLE
Definition: winbase.h:305
#define HEAP_DISABLE_COALESCE_ON_FREE
Definition: nt_native.h:1699
static void test_sized_HeapReAlloc(int nbytes1, int nbytes2)
Definition: heap.c:69
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
BOOL WINAPI HeapValidate(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem)
Definition: heapmem.c:156
GLuint buffer
Definition: glext.h:5915
int startup(int argc, const char *argv[])
Definition: startup.c:430
static PVOID
Definition: heap.c:41
HGLOBAL NTAPI GlobalHandle(LPCVOID pMem)
Definition: heapmem.c:705
SIZE_T NTAPI LocalSize(HLOCAL hMem)
Definition: heapmem.c:1777
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
#define HEAP_TAIL_CHECKING_ENABLED
Definition: nt_native.h:1697
#define argv
Definition: mplay32.c:18
static SIZE_T
Definition: heap.c:41
#define NO_ERROR
Definition: dderror.h:5
SIZE_T WINAPI HeapSize(HANDLE, DWORD, LPCVOID)
#define DWORD
Definition: nt_native.h:44
struct _test_info info[]
Definition: SetCursorPos.c:19
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define sprintf(buf, format,...)
Definition: sprintf.c:55
SIZE_T NTAPI GlobalSize(HGLOBAL hMem)
Definition: heapmem.c:1090
BOOL WINAPI HeapDestroy(HANDLE hHeap)
Definition: heapmem.c:85
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
#define ERROR_NOACCESS
Definition: winerror.h:578
static void test_child_heap(const char *arg)
Definition: heap.c:1133
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
#define ERROR_ACCESS_DENIED
Definition: compat.h:87
static void test_GlobalAlloc(void)
Definition: heap.c:633
unsigned int BOOL
Definition: ntddk_ex.h:94
#define ok(value,...)
static INT max_size
Definition: history.c:51
DWORD pattern
Definition: heap.c:48
#define GMEM_DISCARDABLE
Definition: winbase.h:296
smooth NULL
Definition: ftsmooth.c:416
LONG WINAPI RegCreateKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:1177
#define HEAP_FREE_CHECKING_ENABLED
Definition: nt_native.h:1698
#define LMEM_FIXED
Definition: winbase.h:349
#define GMEM_NOTIFY
Definition: winbase.h:301
#define LMEM_INVALID_HANDLE
Definition: winbase.h:359
GLsizeiptr size
Definition: glext.h:5919
DWORD flags
Definition: heap.c:49
#define GetProcessHeap()
Definition: compat.h:395
static void(__cdecl *p_aligned_free)(void *)
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
#define LMEM_ZEROINIT
Definition: winbase.h:356
#define GMEM_NOT_BANKED
Definition: winbase.h:300
uint64_t ULONGLONG
Definition: typedefs.h:65
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:4772
#define FLG_HEAP_PAGE_ALLOCS
Definition: pstypes.h:84
#define MAX_PATH
Definition: compat.h:26
#define GlobalDiscard(m)
Definition: winbase.h:2518
#define WINAPI
Definition: msvc.h:8
static void test_sized_HeapAlloc(int nbytes)
Definition: heap.c:59
#define HEAP_GROWABLE
Definition: nt_native.h:1693
#define LMEM_MOVEABLE
Definition: winbase.h:350
unsigned long DWORD
Definition: ntddk_ex.h:95
PVOID HANDLE
Definition: typedefs.h:71
HGLOBAL NTAPI GlobalFree(HGLOBAL hMem)
Definition: heapmem.c:611
#define success(from, fromstr, to, tostr)
#define SetLastError(x)
Definition: compat.h:409
static PSIZE_T
Definition: heap.c:41
static void test_GetPhysicallyInstalledSystemMemory(void)
Definition: heap.c:1187
#define MAGIC_DEAD
Definition: heap.c:33
#define LPVOID
Definition: nt_native.h:45
int winetest_get_mainargs(char ***pargv)
GLbitfield flags
Definition: glext.h:7161
unsigned char UCHAR
Definition: xmlstorage.h:181
int ret
LPVOID NTAPI GlobalLock(HGLOBAL hMem)
Definition: heapmem.c:755
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
#define GMEM_FIXED
Definition: winbase.h:290
#define GMEM_NOCOMPACT
Definition: winbase.h:298
#define FLG_HEAP_ENABLE_FREE_CHECK
Definition: pstypes.h:61
#define LongToHandle(h)
Definition: basetsd.h:82
unsigned char BYTE
Definition: mem.h:68
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:819
static char argv0[MAX_PATH]
Definition: shlexec.c:56
#define err(...)
static DWORD heap_flags_from_global_flag(DWORD flag)
Definition: heap.c:1114
uint32_t DWORD_PTR
Definition: typedefs.h:63
#define broken(x)
Definition: _sntprintf.h:21
void winetest_wait_child_process(HANDLE process)
static void test_HeapQueryInformation(void)
Definition: heap.c:843
static void test_obsolete_flags(void)
Definition: heap.c:795
LONG WINAPI RegDeleteKeyA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey)
Definition: reg.c:1222
ULONG_PTR SIZE_T
Definition: typedefs.h:78
DWORD dwPageSize
Definition: winbase.h:1126
HLOCAL NTAPI LocalReAlloc(HLOCAL hMem, SIZE_T dwBytes, UINT uFlags)
Definition: heapmem.c:1608
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1577
static void test_HeapCreate(void)
Definition: heap.c:524
LPVOID NTAPI LocalLock(HLOCAL hMem)
Definition: heapmem.c:1599
#define HeapReAlloc
Definition: compat.h:393
LONG WINAPI RegDeleteValueA(HKEY hKey, LPCSTR lpValueName)
Definition: reg.c:2319
#define FLG_HEAP_ENABLE_TAG_BY_DLL
Definition: pstypes.h:70
#define GMEM_MODIFY
Definition: winbase.h:292
VOID WINAPI GetSystemInfo(IN LPSYSTEM_INFO lpSystemInfo)
Definition: sysinfo.c:142
unsigned int UINT
Definition: ndis.h:50
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
UINT NTAPI LocalFlags(HLOCAL hMem)
Definition: heapmem.c:1503
#define GMEM_DDESHARE
Definition: winbase.h:295
#define skip(...)
START_TEST(heap)
Definition: heap.c:1219
#define GMEM_LOWER
Definition: winbase.h:297
static void test_LocalAlloc(void)
Definition: heap.c:715
#define FLG_HEAP_VALIDATE_ALL
Definition: pstypes.h:63
Definition: mem.c:156
#define HEAP_VALIDATE_ALL
Definition: heap.c:38
GLuint res
Definition: glext.h:9613
static void test_heap(void)
Definition: heap.c:82
unsigned int ULONG
Definition: retypes.h:1
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define GetProcAddress(x, y)
Definition: compat.h:410
BOOL NTAPI GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer)
Definition: heapmem.c:1272
HLOCAL NTAPI LocalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:1373
HLOCAL NTAPI LocalHandle(LPCVOID pMem)
Definition: heapmem.c:1588
#define FLG_HEAP_ENABLE_TAGGING
Definition: pstypes.h:66
LONG WINAPI RegSetValueExA(HKEY hKey, LPCSTR lpValueName, DWORD Reserved, DWORD dwType, CONST BYTE *lpData, DWORD cbData)
Definition: reg.c:4812
#define ERROR_NOT_LOCKED
Definition: winerror.h:230
GLfloat GLfloat p
Definition: glext.h:8902
static BOOL(WINAPI *pHeapQueryInformation)(HANDLE
#define memset(x, y, z)
Definition: compat.h:39
#define REG_DWORD
Definition: sdbapi.c:596
DWORD_PTR unknown[2]
Definition: heap.c:47
#define win_skip
Definition: test.h:141
#define HEAP_REALLOC_IN_PLACE_ONLY
Definition: nt_native.h:1696
#define HeapFree(x, y, z)
Definition: compat.h:394
#define GMEM_MOVEABLE
Definition: winbase.h:291
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:54
#define GMEM_ZEROINIT
Definition: winbase.h:303
#define FLG_POOL_ENABLE_TAGGING
Definition: pstypes.h:65
BOOL expected
Definition: store.c:2063
#define ERROR_DISCARDED
Definition: winerror.h:229
static HEAP_INFORMATION_CLASS
Definition: heap.c:41
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define REG_SZ
Definition: layer.c:22
#define FLG_HEAP_VALIDATE_PARAMETERS
Definition: pstypes.h:62