void FREE(void* pv) { #ifdef _DEBUG if (NULL != pv) // under debug always initialize to -1 to catch unitialize errors. { #if later // malloc doesn't have a size so need to keep track separately, should be able if keep track of heap UINT cb; Assert(LMEM_INVALID_HANDLE != LocalFlags(pv)); cb = LocalSize(pv); // returns zero on failure memset(pv, MEMFREEVALUE, cb); #endif } Assert(pv); #endif // _DEBUG free(pv); // LocalFree(pv); }
static void test_heap(void) { LPVOID mem; LPVOID msecond; DWORD res; UINT flags; HGLOBAL gbl; HGLOBAL hsecond; SIZE_T size, size2; const SIZE_T max_size = 1024, init_size = 10; /* Heap*() functions */ mem = HeapAlloc(GetProcessHeap(), 0, 0); ok(mem != NULL, "memory not allocated for size 0\n"); HeapFree(GetProcessHeap(), 0, mem); mem = HeapReAlloc(GetProcessHeap(), 0, NULL, 10); ok(mem == NULL, "memory allocated by HeapReAlloc\n"); for (size = 0; size <= 256; size++) { SIZE_T heap_size; mem = HeapAlloc(GetProcessHeap(), 0, size); heap_size = HeapSize(GetProcessHeap(), 0, mem); ok(heap_size == size || heap_size == resize_9x(size), "HeapSize returned %lu instead of %lu or %lu\n", heap_size, size, resize_9x(size)); HeapFree(GetProcessHeap(), 0, mem); } /* test some border cases of HeapAlloc and HeapReAlloc */ mem = HeapAlloc(GetProcessHeap(), 0, 0); ok(mem != NULL, "memory not allocated for size 0\n"); msecond = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, mem, ~(SIZE_T)0 - 7); ok(msecond == NULL, "HeapReAlloc(~0 - 7) should have failed\n"); msecond = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, mem, ~(SIZE_T)0); ok(msecond == NULL, "HeapReAlloc(~0) should have failed\n"); HeapFree(GetProcessHeap(), 0, mem); mem = HeapAlloc(GetProcessHeap(), 0, ~(SIZE_T)0); ok(mem == NULL, "memory allocated for size ~0\n"); /* large blocks must be 16-byte aligned */ mem = HeapAlloc(GetProcessHeap(), 0, 512 * 1024); ok( mem != NULL, "failed for size 512K\n" ); ok( (ULONG_PTR)mem % 16 == 0 || broken((ULONG_PTR)mem % 16) /* win9x */, "512K block not 16-byte aligned\n" ); HeapFree(GetProcessHeap(), 0, mem); /* Global*() functions */ gbl = GlobalAlloc(GMEM_MOVEABLE, 0); ok(gbl != NULL, "global memory not allocated for size 0\n"); gbl = GlobalReAlloc(gbl, 10, GMEM_MOVEABLE); ok(gbl != NULL, "Can't realloc global memory\n"); size = GlobalSize(gbl); ok(size >= 10 && size <= 16, "Memory not resized to size 10, instead size=%ld\n", size); gbl = GlobalReAlloc(gbl, 0, GMEM_MOVEABLE); ok(gbl != NULL, "GlobalReAlloc should not fail on size 0\n"); size = GlobalSize(gbl); ok(size == 0, "Memory not resized to size 0, instead size=%ld\n", size); ok(GlobalFree(gbl) == NULL, "Memory not freed\n"); size = GlobalSize(gbl); ok(size == 0, "Memory should have been freed, size=%ld\n", size); gbl = GlobalReAlloc(0, 10, GMEM_MOVEABLE); ok(gbl == NULL, "global realloc allocated memory\n"); /* GlobalLock / GlobalUnlock with a valid handle */ gbl = GlobalAlloc(GMEM_MOVEABLE, 256); SetLastError(MAGIC_DEAD); mem = GlobalLock(gbl); /* #1 */ ok(mem != NULL, "returned %p with %d (expected '!= NULL')\n", mem, GetLastError()); SetLastError(MAGIC_DEAD); flags = GlobalFlags(gbl); ok( flags == 1, "returned 0x%04x with %d (expected '0x0001')\n", flags, GetLastError()); SetLastError(MAGIC_DEAD); msecond = GlobalLock(gbl); /* #2 */ ok( msecond == mem, "returned %p with %d (expected '%p')\n", msecond, GetLastError(), mem); SetLastError(MAGIC_DEAD); flags = GlobalFlags(gbl); ok( flags == 2, "returned 0x%04x with %d (expected '0x0002')\n", flags, GetLastError()); SetLastError(MAGIC_DEAD); SetLastError(MAGIC_DEAD); res = GlobalUnlock(gbl); /* #1 */ ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError()); SetLastError(MAGIC_DEAD); flags = GlobalFlags(gbl); ok( flags , "returned 0x%04x with %d (expected '!= 0')\n", flags, GetLastError()); SetLastError(MAGIC_DEAD); res = GlobalUnlock(gbl); /* #0 */ /* NT: ERROR_SUCCESS (documented on MSDN), 9x: untouched */ ok(!res && ((GetLastError() == ERROR_SUCCESS) || (GetLastError() == MAGIC_DEAD)), "returned %d with %d (expected '0' with: ERROR_SUCCESS or " "MAGIC_DEAD)\n", res, GetLastError()); SetLastError(MAGIC_DEAD); flags = GlobalFlags(gbl); ok( !flags , "returned 0x%04x with %d (expected '0')\n", flags, GetLastError()); /* Unlock an already unlocked Handle */ SetLastError(MAGIC_DEAD); res = GlobalUnlock(gbl); /* NT: ERROR_NOT_LOCKED, 9x: untouched */ ok( !res && ((GetLastError() == ERROR_NOT_LOCKED) || (GetLastError() == MAGIC_DEAD)), "returned %d with %d (expected '0' with: ERROR_NOT_LOCKED or " "MAGIC_DEAD)\n", res, GetLastError()); GlobalFree(gbl); /* invalid handles are caught in windows: */ SetLastError(MAGIC_DEAD); hsecond = GlobalFree(gbl); /* invalid handle: free memory twice */ ok( (hsecond == gbl) && (GetLastError() == ERROR_INVALID_HANDLE), "returned %p with 0x%08x (expected %p with ERROR_INVALID_HANDLE)\n", hsecond, GetLastError(), gbl); SetLastError(MAGIC_DEAD); flags = GlobalFlags(gbl); ok( (flags == GMEM_INVALID_HANDLE) && (GetLastError() == ERROR_INVALID_HANDLE), "returned 0x%04x with 0x%08x (expected GMEM_INVALID_HANDLE with " "ERROR_INVALID_HANDLE)\n", flags, GetLastError()); SetLastError(MAGIC_DEAD); size = GlobalSize(gbl); ok( (size == 0) && (GetLastError() == ERROR_INVALID_HANDLE), "returned %ld with 0x%08x (expected '0' with ERROR_INVALID_HANDLE)\n", size, GetLastError()); SetLastError(MAGIC_DEAD); mem = GlobalLock(gbl); ok( (mem == NULL) && (GetLastError() == ERROR_INVALID_HANDLE), "returned %p with 0x%08x (expected NULL with ERROR_INVALID_HANDLE)\n", mem, GetLastError()); /* documented on MSDN: GlobalUnlock() return FALSE on failure. Win9x and wine return FALSE with ERROR_INVALID_HANDLE, but on NT 3.51 and XPsp2, TRUE with ERROR_INVALID_HANDLE is returned. The similar Test for LocalUnlock() works on all Systems */ SetLastError(MAGIC_DEAD); res = GlobalUnlock(gbl); ok(GetLastError() == ERROR_INVALID_HANDLE, "returned %d with %d (expected ERROR_INVALID_HANDLE)\n", res, GetLastError()); gbl = GlobalAlloc(GMEM_DDESHARE, 100); /* first free */ mem = GlobalFree(gbl); ok(mem == NULL, "Expected NULL, got %p\n", mem); /* invalid free */ if (sizeof(void *) != 8) /* crashes on 64-bit Vista */ { SetLastError(MAGIC_DEAD); mem = GlobalFree(gbl); ok(mem == gbl || broken(mem == NULL) /* nt4 */, "Expected gbl, got %p\n", mem); if (mem == gbl) ok(GetLastError() == ERROR_INVALID_HANDLE || GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */ "Expected ERROR_INVALID_HANDLE or ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); } /* GMEM_FIXED block expands in place only without flags */ for (size = 1; size <= max_size; size <<= 1) { gbl = GlobalAlloc(GMEM_FIXED, init_size); SetLastError(MAGIC_DEAD); hsecond = GlobalReAlloc(gbl, size + init_size, 0); ok(hsecond == gbl || (hsecond == NULL && GetLastError() == ERROR_NOT_ENOUGH_MEMORY), "got %p with %x (expected %p or NULL) @%ld\n", hsecond, GetLastError(), gbl, size); GlobalFree(gbl); } /* GMEM_FIXED block can be relocated with GMEM_MOVEABLE */ for (size = 1; size <= max_size; size <<= 1) { gbl = GlobalAlloc(GMEM_FIXED, init_size); SetLastError(MAGIC_DEAD); hsecond = GlobalReAlloc(gbl, size + init_size, GMEM_MOVEABLE); ok(hsecond != NULL, "got %p with %x (expected non-NULL) @%ld\n", hsecond, GetLastError(), size); mem = GlobalLock(hsecond); ok(mem == hsecond, "got %p (expected %p) @%ld\n", mem, hsecond, size); GlobalFree(hsecond); } gbl = GlobalAlloc(GMEM_DDESHARE, 100); res = GlobalUnlock(gbl); ok(res == 1 || broken(res == 0), /* win9x */ "Expected 1 or 0, got %d\n", res); res = GlobalUnlock(gbl); ok(res == 1 || broken(res == 0), /* win9x */ "Expected 1 or 0, got %d\n", res); GlobalFree(gbl); gbl = GlobalAlloc(GMEM_FIXED, 100); SetLastError(0xdeadbeef); res = GlobalUnlock(gbl); ok(res == 1 || broken(res == 0), /* win9x */ "Expected 1 or 0, got %d\n", res); ok(GetLastError() == 0xdeadbeef, "got %d\n", GetLastError()); GlobalFree(gbl); /* GlobalSize on an invalid handle */ if (sizeof(void *) != 8) /* crashes on 64-bit Vista */ { SetLastError(MAGIC_DEAD); size = GlobalSize((HGLOBAL)0xc042); ok(size == 0, "Expected 0, got %ld\n", size); ok(GetLastError() == ERROR_INVALID_HANDLE || GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */ "Expected ERROR_INVALID_HANDLE or ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); } gbl = GlobalAlloc( GMEM_FIXED, 0 ); SetLastError(0xdeadbeef); size = GlobalSize( gbl ); ok( size == 1, "wrong size %lu\n", size ); GlobalFree( gbl ); /* ####################################### */ /* Local*() functions */ gbl = LocalAlloc(LMEM_MOVEABLE, 0); ok(gbl != NULL, "local memory not allocated for size 0\n"); gbl = LocalReAlloc(gbl, 10, LMEM_MOVEABLE); ok(gbl != NULL, "Can't realloc local memory\n"); size = LocalSize(gbl); ok(size >= 10 && size <= 16, "Memory not resized to size 10, instead size=%ld\n", size); gbl = LocalReAlloc(gbl, 0, LMEM_MOVEABLE); ok(gbl != NULL, "LocalReAlloc should not fail on size 0\n"); size = LocalSize(gbl); ok(size == 0, "Memory not resized to size 0, instead size=%ld\n", size); ok(LocalFree(gbl) == NULL, "Memory not freed\n"); size = LocalSize(gbl); ok(size == 0, "Memory should have been freed, size=%ld\n", size); gbl = LocalReAlloc(0, 10, LMEM_MOVEABLE); ok(gbl == NULL, "local realloc allocated memory\n"); /* LocalLock / LocalUnlock with a valid handle */ gbl = LocalAlloc(LMEM_MOVEABLE, 256); SetLastError(MAGIC_DEAD); mem = LocalLock(gbl); /* #1 */ ok(mem != NULL, "returned %p with %d (expected '!= NULL')\n", mem, GetLastError()); SetLastError(MAGIC_DEAD); flags = LocalFlags(gbl); ok( flags == 1, "returned 0x%04x with %d (expected '0x0001')\n", flags, GetLastError()); SetLastError(MAGIC_DEAD); msecond = LocalLock(gbl); /* #2 */ ok( msecond == mem, "returned %p with %d (expected '%p')\n", msecond, GetLastError(), mem); SetLastError(MAGIC_DEAD); flags = LocalFlags(gbl); ok( flags == 2, "returned 0x%04x with %d (expected '0x0002')\n", flags, GetLastError()); SetLastError(MAGIC_DEAD); SetLastError(MAGIC_DEAD); res = LocalUnlock(gbl); /* #1 */ ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError()); SetLastError(MAGIC_DEAD); flags = LocalFlags(gbl); ok( flags , "returned 0x%04x with %d (expected '!= 0')\n", flags, GetLastError()); SetLastError(MAGIC_DEAD); res = LocalUnlock(gbl); /* #0 */ /* NT: ERROR_SUCCESS (documented on MSDN), 9x: untouched */ ok(!res && ((GetLastError() == ERROR_SUCCESS) || (GetLastError() == MAGIC_DEAD)), "returned %d with %d (expected '0' with: ERROR_SUCCESS or " "MAGIC_DEAD)\n", res, GetLastError()); SetLastError(MAGIC_DEAD); flags = LocalFlags(gbl); ok( !flags , "returned 0x%04x with %d (expected '0')\n", flags, GetLastError()); /* Unlock an already unlocked Handle */ SetLastError(MAGIC_DEAD); res = LocalUnlock(gbl); /* NT: ERROR_NOT_LOCKED, 9x: untouched */ ok( !res && ((GetLastError() == ERROR_NOT_LOCKED) || (GetLastError() == MAGIC_DEAD)), "returned %d with %d (expected '0' with: ERROR_NOT_LOCKED or " "MAGIC_DEAD)\n", res, GetLastError()); LocalFree(gbl); /* invalid handles are caught in windows: */ SetLastError(MAGIC_DEAD); hsecond = LocalFree(gbl); /* invalid handle: free memory twice */ ok( (hsecond == gbl) && (GetLastError() == ERROR_INVALID_HANDLE), "returned %p with 0x%08x (expected %p with ERROR_INVALID_HANDLE)\n", hsecond, GetLastError(), gbl); SetLastError(MAGIC_DEAD); flags = LocalFlags(gbl); ok( (flags == LMEM_INVALID_HANDLE) && (GetLastError() == ERROR_INVALID_HANDLE), "returned 0x%04x with 0x%08x (expected LMEM_INVALID_HANDLE with " "ERROR_INVALID_HANDLE)\n", flags, GetLastError()); SetLastError(MAGIC_DEAD); size = LocalSize(gbl); ok( (size == 0) && (GetLastError() == ERROR_INVALID_HANDLE), "returned %ld with 0x%08x (expected '0' with ERROR_INVALID_HANDLE)\n", size, GetLastError()); SetLastError(MAGIC_DEAD); mem = LocalLock(gbl); ok( (mem == NULL) && (GetLastError() == ERROR_INVALID_HANDLE), "returned %p with 0x%08x (expected NULL with ERROR_INVALID_HANDLE)\n", mem, GetLastError()); /* This Test works the same on all Systems (GlobalUnlock() is different) */ SetLastError(MAGIC_DEAD); res = LocalUnlock(gbl); ok(!res && (GetLastError() == ERROR_INVALID_HANDLE), "returned %d with %d (expected '0' with ERROR_INVALID_HANDLE)\n", res, GetLastError()); /* LMEM_FIXED block expands in place only without flags */ for (size = 1; size <= max_size; size <<= 1) { gbl = LocalAlloc(LMEM_FIXED, init_size); SetLastError(MAGIC_DEAD); hsecond = LocalReAlloc(gbl, size + init_size, 0); ok(hsecond == gbl || (hsecond == NULL && GetLastError() == ERROR_NOT_ENOUGH_MEMORY), "got %p with %x (expected %p or NULL) @%ld\n", hsecond, GetLastError(), gbl, size); LocalFree(gbl); } /* LMEM_FIXED memory can be relocated with LMEM_MOVEABLE */ for (size = 1; size <= max_size; size <<= 1) { gbl = LocalAlloc(LMEM_FIXED, init_size); SetLastError(MAGIC_DEAD); hsecond = LocalReAlloc(gbl, size + init_size, LMEM_MOVEABLE); ok(hsecond != NULL, "got %p with %x (expected non-NULL) @%ld\n", hsecond, GetLastError(), size); mem = LocalLock(hsecond); ok(mem == hsecond, "got %p (expected %p) @%ld\n", mem, hsecond, size); LocalFree(hsecond); } /* trying to unlock pointer from LocalAlloc */ gbl = LocalAlloc(LMEM_FIXED, 100); SetLastError(0xdeadbeef); res = LocalUnlock(gbl); ok(res == 0, "Expected 0, got %d\n", res); ok(GetLastError() == ERROR_NOT_LOCKED || broken(GetLastError() == 0xdeadbeef) /* win9x */, "got %d\n", GetLastError()); LocalFree(gbl); gbl = LocalAlloc( LMEM_FIXED, 0 ); SetLastError(0xdeadbeef); size = LocalSize( gbl ); ok( !size || broken(size == 1), /* vistau64 */ "wrong size %lu\n", size ); LocalFree( gbl ); /* trying to lock empty memory should give an error */ gbl = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,0); ok(gbl != NULL, "returned NULL\n"); SetLastError(MAGIC_DEAD); mem = GlobalLock(gbl); /* NT: ERROR_DISCARDED, 9x: untouched */ ok( (mem == NULL) && ((GetLastError() == ERROR_DISCARDED) || (GetLastError() == MAGIC_DEAD)), "returned %p with 0x%x/%d (expected 'NULL' with: ERROR_DISCARDED or " "MAGIC_DEAD)\n", mem, GetLastError(), GetLastError()); GlobalFree(gbl); /* trying to get size from data pointer (GMEM_MOVEABLE) */ gbl = GlobalAlloc(GMEM_MOVEABLE, 0x123); ok(gbl != NULL, "returned NULL\n"); mem = GlobalLock(gbl); ok(mem != NULL, "returned NULL.\n"); ok(gbl != mem, "unexpectedly equal.\n"); size = GlobalSize(gbl); size2 = GlobalSize(mem); ok(size == 0x123, "got %lu\n", size); ok(size2 == 0x123, "got %lu\n", size2); GlobalFree(gbl); /* trying to get size from data pointer (GMEM_FIXED) */ gbl = GlobalAlloc(GMEM_FIXED, 0x123); ok(gbl != NULL, "returned NULL\n"); mem = GlobalLock(gbl); ok(mem != NULL, "returned NULL.\n"); ok(gbl == mem, "got %p, %p.\n", gbl, mem); size = GlobalSize(gbl); ok(size == 0x123, "got %lu\n", size); GlobalFree(gbl); size = GlobalSize((void *)0xdeadbee0); ok(size == 0, "got %lu\n", size); }