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