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