Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53474
-- v2: kernelbase: Only discard HLOCAL with LMEM_MOVEABLE and if not locked. kernel32: Return success from GlobalReAlloc with locked HGLOBAL pointer. kernelbase: Avoid moving locked HLOCAL pointer without LMEM_MOVEABLE. kernelbase: Handle LMEM_DISCARDABLE flag specifically in LocalReAlloc. kernelbase: Handle LMEM_MODIFY flag first in LocalReAlloc. kernelbase: Don't try in-place HeapReAlloc in LocalReAlloc. user32: Call GlobalReAlloc with GMEM_MOVEABLE flag. winemac.drv: Call GlobalReAlloc with GMEM_MOVEABLE flag. riched20: Call GlobalReAlloc with GMEM_MOVEABLE flag. ole32: Call GlobalReAlloc with GMEM_MOVEABLE flag. comdlg32: Call GlobalReAlloc with GMEM_MOVEABLE flag. kernel32/tests: Add more (Global|Local)ReAlloc tests.
From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53474 --- dlls/kernel32/tests/heap.c | 588 ++++++++++++++++++++++++++++++++++++- 1 file changed, 586 insertions(+), 2 deletions(-)
diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c index 3e861f52248..b94532a72f4 100644 --- a/dlls/kernel32/tests/heap.c +++ b/dlls/kernel32/tests/heap.c @@ -51,6 +51,7 @@ static BOOLEAN (WINAPI *pRtlSetUserValueHeap)(HANDLE,ULONG,void*,void*); static BOOLEAN (WINAPI *pRtlSetUserFlagsHeap)(HANDLE,ULONG,void*,ULONG,ULONG); static HGLOBAL (WINAPI *pGlobalAlloc)(UINT,SIZE_T); static HGLOBAL (WINAPI *pGlobalFree)(HGLOBAL); +static HGLOBAL (WINAPI *pLocalAlloc)(UINT,SIZE_T); static HGLOBAL (WINAPI *pLocalFree)(HLOCAL);
#define MAKE_FUNC(f) static typeof(f) *p ## f @@ -75,6 +76,7 @@ static void load_functions(void) LOAD_FUNC( kernel32, GlobalAlloc ); LOAD_FUNC( kernel32, GlobalFlags ); LOAD_FUNC( kernel32, GlobalFree ); + LOAD_FUNC( kernel32, LocalAlloc ); LOAD_FUNC( kernel32, LocalFree ); LOAD_FUNC( ntdll, RtlGetNtGlobalFlags ); LOAD_FUNC( ntdll, RtlGetUserInfoHeap ); @@ -1264,6 +1266,11 @@ static struct mem_entry *mem_entry_from_HANDLE( HLOCAL handle ) return CONTAINING_RECORD( handle, struct mem_entry, ptr ); }
+static BOOL is_mem_entry( HLOCAL handle ) +{ + return ((UINT_PTR)handle & ((sizeof(void *) << 1) - 1)) == sizeof(void *); +} + static void test_GlobalAlloc(void) { static const UINT flags_tests[] = @@ -1277,6 +1284,17 @@ static void test_GlobalAlloc(void) GMEM_MOVEABLE | GMEM_DISCARDABLE, GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_DISCARDABLE | GMEM_LOWER | GMEM_NOCOMPACT | GMEM_NODISCARD | GMEM_NOT_BANKED | GMEM_NOTIFY, }; + static const UINT realloc_flags_tests[] = + { + GMEM_FIXED, + GMEM_FIXED | GMEM_MODIFY, + GMEM_MOVEABLE, + GMEM_MOVEABLE | GMEM_MODIFY, + GMEM_MOVEABLE | GMEM_DISCARDABLE, + GMEM_MOVEABLE | GMEM_MODIFY | GMEM_DISCARDABLE, + GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_DISCARDABLE | GMEM_LOWER | GMEM_NOCOMPACT | GMEM_NODISCARD | GMEM_NOT_BANKED | GMEM_NOTIFY, + GMEM_MOVEABLE | GMEM_MODIFY | GMEM_DDESHARE | GMEM_DISCARDABLE | GMEM_LOWER | GMEM_NOCOMPACT | GMEM_NODISCARD | GMEM_NOT_BANKED | GMEM_NOTIFY, + }; static const char zero_buffer[100000] = {0}; static const SIZE_T buffer_size = ARRAY_SIZE(zero_buffer); const HGLOBAL invalid_mem = LongToHandle( 0xdeadbee0 + sizeof(void *) ); @@ -1686,7 +1704,307 @@ static void test_GlobalAlloc(void) ptr = GlobalLock( tmp_mem ); ok( !!ptr, "GlobalLock failed, error %lu\n", GetLastError() ); ok( ptr == tmp_mem, "got ptr %p, expected %p\n", ptr, tmp_mem ); - GlobalFree( tmp_mem ); + mem = GlobalFree( tmp_mem ); + ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() ); + + /* test GlobalReAlloc flags / GlobalLock combinations */ + + for (i = 0; i < ARRAY_SIZE(realloc_flags_tests); i++) + { + struct mem_entry expect_entry, entry; + BOOL expect_convert; + + flags = realloc_flags_tests[i]; + expect_convert = (flags & (GMEM_MOVEABLE | GMEM_MODIFY)) == (GMEM_MOVEABLE | GMEM_MODIFY); + + winetest_push_context( "flags %#x", flags ); + + mem = pGlobalAlloc( GMEM_FIXED, 10 ); + ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() ); + ok( !is_mem_entry( mem ), "unexpected moveable %p\n", mem ); + + tmp_mem = GlobalReAlloc( mem, 512, flags ); + if (!expect_convert) + { + ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem ); + if (flags == GMEM_MODIFY) ok( tmp_mem == mem, "GlobalReAlloc returned %p\n", tmp_mem ); + else if (flags != GMEM_MOVEABLE) todo_wine_if(flags) ok( !tmp_mem, "GlobalReAlloc succeeded\n" ); + else ok( tmp_mem != mem, "GlobalReAlloc returned %p\n", tmp_mem ); + } + else + { + ok( is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem ); + entry = *mem_entry_from_HANDLE( tmp_mem ); + todo_wine ok( entry.ptr != mem, "got ptr %p was %p\n", entry.ptr, mem ); + if (flags & GMEM_DISCARDABLE) ok( (entry.flags & 0x7fff) == 0x7, "got flags %#Ix\n", entry.flags ); + else ok( (entry.flags & 0x7fff) == 0x3, "got flags %#Ix\n", entry.flags ); + } + if (tmp_mem) mem = tmp_mem; + + size = GlobalSize( mem ); + if (flags == GMEM_MOVEABLE) ok( size == 512, "GlobalSize returned %Iu\n", size ); + else + { + todo_wine_if(flags && (flags & GMEM_MOVEABLE) && !(flags & GMEM_MODIFY)) + ok( size == 10, "GlobalSize returned %Iu\n", size ); + } + + mem = GlobalFree( mem ); + ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() ); + + + mem = pGlobalAlloc( GMEM_FIXED, 12 ); + ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() ); + ok( !is_mem_entry( mem ), "unexpected moveable %p\n", mem ); + + tmp_mem = GlobalReAlloc( mem, 10, flags ); + if (!expect_convert) + { + ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem ); + if (flags == GMEM_MODIFY) ok( tmp_mem == mem, "GlobalReAlloc returned %p\n", tmp_mem ); + else if (flags != GMEM_MOVEABLE) todo_wine ok( !tmp_mem || broken( tmp_mem == mem ) /* w8 */, "GlobalReAlloc succeeded\n" ); + else todo_wine ok( tmp_mem != mem, "GlobalReAlloc returned %p\n", tmp_mem ); + } + else + { + ok( is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem ); + entry = *mem_entry_from_HANDLE( tmp_mem ); + ok( entry.ptr == ptr, "got ptr %p was %p\n", entry.ptr, ptr ); + if (flags & GMEM_DISCARDABLE) ok( (entry.flags & 0x7fff) == 0x7, "got flags %#Ix\n", entry.flags ); + else ok( (entry.flags & 0x7fff) == 0x3, "got flags %#Ix\n", entry.flags ); + } + if (tmp_mem) mem = tmp_mem; + + size = GlobalSize( mem ); + if (flags == GMEM_MOVEABLE) ok( size == 10, "GlobalSize returned %Iu\n", size ); + else if (flags) + { + todo_wine_if((flags & GMEM_MOVEABLE) && !(flags & GMEM_MODIFY)) + ok( size == 12, "GlobalSize returned %Iu\n", size ); + } + else todo_wine ok( size == 12 || broken( size == 10 ) /* w8 */, "GlobalSize returned %Iu\n", size ); + + mem = GlobalFree( mem ); + ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() ); + + + mem = pGlobalAlloc( GMEM_FIXED, 12 ); + ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() ); + ok( !is_mem_entry( mem ), "unexpected moveable %p\n", mem ); + + tmp_mem = GlobalReAlloc( mem, 0, flags ); + if (!expect_convert) + { + ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem ); + if (flags == GMEM_MODIFY) ok( tmp_mem == mem, "GlobalReAlloc returned %p\n", tmp_mem ); + else if (flags != GMEM_MOVEABLE) todo_wine ok( !tmp_mem || broken( tmp_mem == mem ) /* w8 */, "GlobalReAlloc succeeded\n" ); + else todo_wine ok( tmp_mem != mem, "GlobalReAlloc returned %p\n", tmp_mem ); + } + else + { + ok( is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem ); + entry = *mem_entry_from_HANDLE( tmp_mem ); + ok( entry.ptr == ptr, "got ptr %p was %p\n", entry.ptr, ptr ); + if (flags & GMEM_DISCARDABLE) ok( (entry.flags & 0x7fff) == 0x7, "got flags %#Ix\n", entry.flags ); + else ok( (entry.flags & 0x7fff) == 0x3, "got flags %#Ix\n", entry.flags ); + } + if (tmp_mem) mem = tmp_mem; + + size = GlobalSize( mem ); + if (flags == GMEM_MOVEABLE) ok( size == 0 || broken( size == 1 ) /* w7 */, "GlobalSize returned %Iu\n", size ); + else if (flags) + { + todo_wine_if((flags & GMEM_MOVEABLE) && !(flags & GMEM_MODIFY)) + ok( size == 12, "GlobalSize returned %Iu\n", size ); + } + else todo_wine ok( size == 12 || broken( size == 0 ) /* w8 */, "GlobalSize returned %Iu\n", size ); + + mem = GlobalFree( mem ); + ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() ); + + + mem = pGlobalAlloc( GMEM_MOVEABLE, 10 ); + ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() ); + ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem ); + ptr = GlobalLock( mem ); + ok( !!ptr, "GlobalLock failed, error %lu\n", GetLastError() ); + expect_entry = *mem_entry_from_HANDLE( mem ); + + tmp_mem = GlobalReAlloc( mem, 512, flags ); + if (!(flags & GMEM_MODIFY) && ((flags & GMEM_DISCARDABLE) || !(flags & GMEM_MOVEABLE))) + ok( !tmp_mem, "GlobalReAlloc succeeded\n" ); + else + { + todo_wine + ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); + } + entry = *mem_entry_from_HANDLE( mem ); + if ((flags & GMEM_DISCARDABLE) && (flags & GMEM_MODIFY)) expect_entry.flags |= 4; + if (flags == GMEM_MOVEABLE) + todo_wine ok( entry.ptr != expect_entry.ptr, "got unexpected ptr %p\n", entry.ptr ); + else + ok( entry.ptr == expect_entry.ptr, "got ptr %p\n", entry.ptr ); + todo_wine_if((flags & GMEM_MODIFY) && (flags & GMEM_MOVEABLE) && flags != (GMEM_MODIFY | GMEM_MOVEABLE)) + ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); + size = GlobalSize( mem ); + if (flags == GMEM_MOVEABLE) + todo_wine ok( size == 512, "GlobalSize returned %Iu\n", size ); + else + ok( size == 10, "GlobalSize returned %Iu\n", size ); + + ret = GlobalUnlock( mem ); + ok( !ret, "GlobalUnlock succeeded\n" ); + mem = GlobalFree( mem ); + ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() ); + + + mem = pGlobalAlloc( GMEM_MOVEABLE, 12 ); + ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() ); + ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem ); + ptr = GlobalLock( mem ); + ok( !!ptr, "GlobalLock failed, error %lu\n", GetLastError() ); + expect_entry = *mem_entry_from_HANDLE( mem ); + + tmp_mem = GlobalReAlloc( mem, 10, flags ); + if (!(flags & GMEM_MODIFY) && (flags & GMEM_DISCARDABLE)) + ok( !tmp_mem, "GlobalReAlloc succeeded\n" ); + else + todo_wine ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); + entry = *mem_entry_from_HANDLE( mem ); + if ((flags & GMEM_DISCARDABLE) && (flags & GMEM_MODIFY)) expect_entry.flags |= 4; + ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr ); + todo_wine_if((flags & GMEM_DISCARDABLE) && (flags & GMEM_MODIFY)) + ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); + size = GlobalSize( mem ); + if ((flags & GMEM_DISCARDABLE) || (flags & GMEM_MODIFY)) + ok( size == 12, "GlobalSize returned %Iu\n", size ); + else + todo_wine_if(!(flags & GMEM_MODIFY)) ok( size == 10, "GlobalSize returned %Iu\n", size ); + + ret = GlobalUnlock( mem ); + ok( !ret, "GlobalUnlock succeeded\n" ); + mem = GlobalFree( mem ); + ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() ); + + + mem = pGlobalAlloc( GMEM_MOVEABLE, 12 ); + ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() ); + ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem ); + ptr = GlobalLock( mem ); + ok( !!ptr, "GlobalLock failed, error %lu\n", GetLastError() ); + expect_entry = *mem_entry_from_HANDLE( mem ); + + tmp_mem = GlobalReAlloc( mem, 0, flags ); + if (flags & GMEM_MODIFY) + todo_wine ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); + else + ok( !tmp_mem, "GlobalReAlloc succeeded\n" ); + entry = *mem_entry_from_HANDLE( mem ); + if ((flags & GMEM_DISCARDABLE) && (flags & GMEM_MODIFY)) expect_entry.flags |= 4; + ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr ); + todo_wine_if((flags & GMEM_MODIFY) && (flags & GMEM_DISCARDABLE)) + ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); + size = GlobalSize( mem ); + ok( size == 12, "GlobalSize returned %Iu\n", size ); + + ret = GlobalUnlock( mem ); + ok( !ret, "GlobalUnlock succeeded\n" ); + mem = GlobalFree( mem ); + ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() ); + + + mem = pGlobalAlloc( GMEM_MOVEABLE, 10 ); + ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() ); + ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem ); + expect_entry = *mem_entry_from_HANDLE( mem ); + + tmp_mem = GlobalReAlloc( mem, 512, flags ); + if (!(flags & GMEM_MODIFY) && (flags & GMEM_DISCARDABLE)) + todo_wine ok( !tmp_mem, "GlobalReAlloc succeeded\n" ); + else + { + todo_wine_if(flags && (!(flags & GMEM_MOVEABLE) || flags == (GMEM_MODIFY | GMEM_MOVEABLE))) + ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); + } + entry = *mem_entry_from_HANDLE( mem ); + if ((flags & GMEM_DISCARDABLE) && (flags & GMEM_MODIFY)) expect_entry.flags |= 4; + if ((flags & GMEM_DISCARDABLE) || (flags & GMEM_MODIFY)) + todo_wine_if(!(flags & GMEM_MODIFY)) ok( entry.ptr == expect_entry.ptr, "got ptr %p\n", entry.ptr ); + else + ok( entry.ptr != expect_entry.ptr, "got unexpected ptr %p\n", entry.ptr ); + ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); + size = GlobalSize( mem ); + if ((flags & GMEM_DISCARDABLE) || (flags & GMEM_MODIFY)) + todo_wine_if(!(flags & GMEM_MODIFY)) ok( size == 10, "GlobalSize returned %Iu\n", size ); + else + ok( size == 512, "GlobalSize returned %Iu\n", size ); + + mem = GlobalFree( mem ); + ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() ); + + + mem = pGlobalAlloc( GMEM_MOVEABLE, 12 ); + ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() ); + ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem ); + expect_entry = *mem_entry_from_HANDLE( mem ); + + tmp_mem = GlobalReAlloc( mem, 10, flags ); + if (!(flags & GMEM_MODIFY) && (flags & GMEM_DISCARDABLE)) + todo_wine ok( !tmp_mem, "GlobalReAlloc succeeded\n" ); + else + { + todo_wine_if(flags && (!(flags & GMEM_MOVEABLE) || flags == (GMEM_MODIFY | GMEM_MOVEABLE))) + ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); + } + entry = *mem_entry_from_HANDLE( mem ); + if ((flags & GMEM_DISCARDABLE) && (flags & GMEM_MODIFY)) expect_entry.flags |= 4; + ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr ); + ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); + size = GlobalSize( mem ); + if ((flags & GMEM_DISCARDABLE) || (flags & GMEM_MODIFY)) + todo_wine_if(!(flags & GMEM_MODIFY)) ok( size == 12, "GlobalSize returned %Iu\n", size ); + else + ok( size == 10, "GlobalSize returned %Iu\n", size ); + + mem = GlobalFree( mem ); + ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() ); + + + mem = pGlobalAlloc( GMEM_MOVEABLE, 12 ); + ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() ); + ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem ); + expect_entry = *mem_entry_from_HANDLE( mem ); + + tmp_mem = GlobalReAlloc( mem, 0, flags ); + if (flags == GMEM_FIXED) + todo_wine ok( !tmp_mem, "GlobalReAlloc succeeded\n" ); + else if (!(flags & GMEM_MODIFY) && (flags & GMEM_DISCARDABLE)) + todo_wine ok( !tmp_mem, "GlobalReAlloc succeeded\n" ); + else + { + todo_wine_if(!(flags & GMEM_MOVEABLE) || flags == (GMEM_MODIFY | GMEM_MOVEABLE)) + ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); + } + entry = *mem_entry_from_HANDLE( mem ); + if (flags == GMEM_MOVEABLE) + { + expect_entry.flags |= 8; + expect_entry.ptr = NULL; + } + else if ((flags & GMEM_DISCARDABLE) && (flags & GMEM_MODIFY)) expect_entry.flags |= 4; + todo_wine_if(!(flags & GMEM_MODIFY) && (flags != GMEM_MOVEABLE)) + ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr ); + todo_wine_if(!(flags & GMEM_MODIFY) && (flags != GMEM_MOVEABLE)) + ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); + size = GlobalSize( mem ); + if (flags == GMEM_MOVEABLE) ok( size == 0, "GlobalSize returned %Iu\n", size ); + else todo_wine_if(!(flags & GMEM_MODIFY)) ok( size == 12, "GlobalSize returned %Iu\n", size ); + + mem = GlobalFree( mem ); + ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() ); + + winetest_pop_context(); + }
mem = GlobalAlloc( GMEM_DDESHARE, 100 ); ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() ); @@ -1834,6 +2152,17 @@ static void test_LocalAlloc(void) LMEM_MOVEABLE | LMEM_DISCARDABLE, LMEM_MOVEABLE | LMEM_DISCARDABLE | LMEM_NOCOMPACT | LMEM_NODISCARD, }; + static const UINT realloc_flags_tests[] = + { + LMEM_FIXED, + LMEM_FIXED | LMEM_MODIFY, + LMEM_MOVEABLE, + LMEM_MOVEABLE | LMEM_MODIFY, + LMEM_MOVEABLE | LMEM_DISCARDABLE, + LMEM_MOVEABLE | LMEM_MODIFY | LMEM_DISCARDABLE, + LMEM_MOVEABLE | LMEM_DISCARDABLE | LMEM_NOCOMPACT | LMEM_NODISCARD, + LMEM_MOVEABLE | LMEM_MODIFY | LMEM_DISCARDABLE | LMEM_NOCOMPACT | LMEM_NODISCARD, + }; static const char zero_buffer[100000] = {0}; static const SIZE_T buffer_size = ARRAY_SIZE(zero_buffer); const HLOCAL invalid_mem = LongToHandle( 0xdeadbee0 + sizeof(void *) ); @@ -2069,7 +2398,262 @@ static void test_LocalAlloc(void) ptr = LocalLock( tmp_mem ); ok( !!ptr, "LocalLock failed, error %lu\n", GetLastError() ); ok( ptr == tmp_mem, "got ptr %p, expected %p\n", ptr, tmp_mem ); - LocalFree( tmp_mem ); + tmp_mem = LocalFree( tmp_mem ); + ok( !tmp_mem, "LocalFree failed, error %lu\n", GetLastError() ); + + /* test LocalReAlloc flags / LocalLock / size combinations */ + + for (i = 0; i < ARRAY_SIZE(realloc_flags_tests); i++) + { + struct mem_entry expect_entry, entry; + + flags = realloc_flags_tests[i]; + + winetest_push_context( "flags %#x", flags ); + + mem = pLocalAlloc( LMEM_FIXED, 10 ); + ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() ); + ok( !is_mem_entry( mem ), "unexpected moveable %p\n", mem ); + + tmp_mem = LocalReAlloc( mem, 512, flags ); + ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem ); + if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p\n", tmp_mem ); + else if (flags != LMEM_MOVEABLE) todo_wine_if(flags) ok( !tmp_mem, "LocalReAlloc succeeded\n" ); + else ok( tmp_mem != mem, "LocalReAlloc returned %p\n", tmp_mem ); + if (tmp_mem) mem = tmp_mem; + + size = LocalSize( mem ); + if (flags == LMEM_MOVEABLE) ok( size == 512, "LocalSize returned %Iu\n", size ); + else todo_wine_if(flags && !(flags & LMEM_MODIFY)) ok( size == 10, "LocalSize returned %Iu\n", size ); + + mem = LocalFree( mem ); + ok( !mem, "LocalFree failed, error %lu\n", GetLastError() ); + + + mem = pLocalAlloc( LMEM_FIXED, 12 ); + ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() ); + ok( !is_mem_entry( mem ), "unexpected moveable %p\n", mem ); + + tmp_mem = LocalReAlloc( mem, 10, flags ); + ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem ); + if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p\n", tmp_mem ); + else if (flags != LMEM_MOVEABLE) todo_wine ok( !tmp_mem, "LocalReAlloc succeeded\n" ); + else todo_wine ok( tmp_mem != mem, "LocalReAlloc returned %p\n", tmp_mem ); + if (tmp_mem) mem = tmp_mem; + + size = LocalSize( mem ); + if (flags == LMEM_MOVEABLE) ok( size == 10, "LocalSize returned %Iu\n", size ); + else if (flags) todo_wine_if(!(flags & LMEM_MODIFY)) ok( size == 12, "LocalSize returned %Iu\n", size ); + else todo_wine ok( size == 12, "LocalSize returned %Iu\n", size ); + + mem = LocalFree( mem ); + ok( !mem, "LocalFree failed, error %lu\n", GetLastError() ); + + + mem = pLocalAlloc( LMEM_FIXED, 12 ); + ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() ); + ok( !is_mem_entry( mem ), "unexpected moveable %p\n", mem ); + + tmp_mem = LocalReAlloc( mem, 0, flags ); + ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem ); + if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p\n", tmp_mem ); + else if (flags != LMEM_MOVEABLE) todo_wine ok( !tmp_mem, "LocalReAlloc succeeded\n" ); + else todo_wine ok( tmp_mem != mem, "LocalReAlloc returned %p\n", tmp_mem ); + if (tmp_mem) mem = tmp_mem; + + size = LocalSize( mem ); + if (flags == LMEM_MOVEABLE) ok( size == 0 || broken( size == 1 ) /* w7 */, "LocalSize returned %Iu\n", size ); + else if (flags) todo_wine_if(!(flags & LMEM_MODIFY)) ok( size == 12, "LocalSize returned %Iu\n", size ); + else todo_wine ok( size == 12, "LocalSize returned %Iu\n", size ); + + mem = LocalFree( mem ); + ok( !mem, "LocalFree failed, error %lu\n", GetLastError() ); + + + mem = pLocalAlloc( LMEM_MOVEABLE, 10 ); + ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() ); + ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem ); + ptr = LocalLock( mem ); + ok( !!ptr, "LocalLock failed, error %lu\n", GetLastError() ); + expect_entry = *mem_entry_from_HANDLE( mem ); + + tmp_mem = LocalReAlloc( mem, 512, flags ); + if (!(flags & LMEM_MODIFY) && ((flags & LMEM_DISCARDABLE) || !(flags & LMEM_MOVEABLE))) + todo_wine ok( !tmp_mem, "LocalReAlloc succeeded\n" ); + else + { + todo_wine_if((!(flags & LMEM_MOVEABLE) || flags == (LMEM_MODIFY | LMEM_MOVEABLE))) + ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); + } + entry = *mem_entry_from_HANDLE( mem ); + if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4; + if (flags == LMEM_MOVEABLE) ok( entry.ptr != expect_entry.ptr, "got unexpected ptr %p\n", entry.ptr ); + else todo_wine_if(!(flags & LMEM_MODIFY)) ok( entry.ptr == expect_entry.ptr, "got ptr %p\n", entry.ptr ); + ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); + size = LocalSize( mem ); + if (flags == LMEM_MOVEABLE) ok( size == 512, "LocalSize returned %Iu\n", size ); + else todo_wine_if(!(flags & LMEM_MODIFY)) ok( size == 10, "LocalSize returned %Iu\n", size ); + + ret = LocalUnlock( mem ); + ok( !ret, "LocalUnlock succeeded\n" ); + mem = LocalFree( mem ); + ok( !mem, "LocalFree failed, error %lu\n", GetLastError() ); + + + mem = pLocalAlloc( LMEM_MOVEABLE, 12 ); + ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() ); + ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem ); + ptr = LocalLock( mem ); + ok( !!ptr, "LocalLock failed, error %lu\n", GetLastError() ); + expect_entry = *mem_entry_from_HANDLE( mem ); + + tmp_mem = LocalReAlloc( mem, 10, flags ); + if (!(flags & LMEM_MODIFY) && (flags & LMEM_DISCARDABLE)) + todo_wine ok( !tmp_mem, "LocalReAlloc succeeded\n" ); + else + { + todo_wine_if(flags && (!(flags & LMEM_MOVEABLE) || flags == (LMEM_MODIFY | LMEM_MOVEABLE))) + ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); + } + entry = *mem_entry_from_HANDLE( mem ); + if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4; + ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr ); + ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); + size = LocalSize( mem ); + if ((flags & LMEM_DISCARDABLE) || (flags & LMEM_MODIFY)) + todo_wine_if(!(flags & LMEM_MODIFY)) ok( size == 12, "LocalSize returned %Iu\n", size ); + else + ok( size == 10, "LocalSize returned %Iu\n", size ); + + ret = LocalUnlock( mem ); + ok( !ret, "LocalUnlock succeeded\n" ); + mem = LocalFree( mem ); + ok( !mem, "LocalFree failed, error %lu\n", GetLastError() ); + + + mem = pLocalAlloc( LMEM_MOVEABLE, 12 ); + ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() ); + ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem ); + ptr = LocalLock( mem ); + ok( !!ptr, "LocalLock failed, error %lu\n", GetLastError() ); + expect_entry = *mem_entry_from_HANDLE( mem ); + + tmp_mem = LocalReAlloc( mem, 0, flags ); + if (flags & LMEM_MODIFY) + { + todo_wine_if(!(flags & LMEM_MOVEABLE) || (flags == (LMEM_MOVEABLE | LMEM_MODIFY))) + ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); + } + else + todo_wine ok( !tmp_mem, "LocalReAlloc succeeded\n" ); + entry = *mem_entry_from_HANDLE( mem ); + if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4; + todo_wine_if(!(flags & LMEM_MODIFY)) + ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr ); + todo_wine_if(!(flags & LMEM_MODIFY)) + ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); + size = LocalSize( mem ); + todo_wine_if(!(flags & LMEM_MODIFY)) + ok( size == 12, "LocalSize returned %Iu\n", size ); + + ret = LocalUnlock( mem ); + ok( !ret, "LocalUnlock succeeded\n" ); + mem = LocalFree( mem ); + ok( !mem, "LocalFree failed, error %lu\n", GetLastError() ); + + + mem = pLocalAlloc( LMEM_MOVEABLE, 10 ); + ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() ); + ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem ); + expect_entry = *mem_entry_from_HANDLE( mem ); + + tmp_mem = LocalReAlloc( mem, 512, flags ); + if (!(flags & LMEM_MODIFY) && (flags & LMEM_DISCARDABLE)) + todo_wine ok( !tmp_mem, "LocalReAlloc succeeded\n" ); + else + { + todo_wine_if(flags && (!(flags & LMEM_MOVEABLE) || flags == (LMEM_MODIFY | LMEM_MOVEABLE))) + ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); + } + entry = *mem_entry_from_HANDLE( mem ); + if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4; + if ((flags & LMEM_DISCARDABLE) || (flags & LMEM_MODIFY)) + todo_wine_if(!(flags & LMEM_MODIFY)) ok( entry.ptr == expect_entry.ptr, "got ptr %p\n", entry.ptr ); + else + ok( entry.ptr != expect_entry.ptr, "got unexpected ptr %p\n", entry.ptr ); + ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); + size = LocalSize( mem ); + if ((flags & LMEM_DISCARDABLE) || (flags & LMEM_MODIFY)) + todo_wine_if(!(flags & LMEM_MODIFY)) ok( size == 10, "LocalSize returned %Iu\n", size ); + else + ok( size == 512, "LocalSize returned %Iu\n", size ); + + mem = LocalFree( mem ); + ok( !mem, "LocalFree failed, error %lu\n", GetLastError() ); + + + mem = pLocalAlloc( LMEM_MOVEABLE, 12 ); + ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() ); + ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem ); + expect_entry = *mem_entry_from_HANDLE( mem ); + + tmp_mem = LocalReAlloc( mem, 10, flags ); + if (!(flags & LMEM_MODIFY) && (flags & LMEM_DISCARDABLE)) + todo_wine ok( !tmp_mem, "LocalReAlloc succeeded\n" ); + else + { + todo_wine_if(flags && (!(flags & LMEM_MOVEABLE) || flags == (LMEM_MODIFY | LMEM_MOVEABLE))) + ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); + } + entry = *mem_entry_from_HANDLE( mem ); + if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4; + ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr ); + ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); + size = LocalSize( mem ); + if ((flags & LMEM_DISCARDABLE) || (flags & LMEM_MODIFY)) + todo_wine_if(!(flags & LMEM_MODIFY)) ok( size == 12, "LocalSize returned %Iu\n", size ); + else + ok( size == 10, "LocalSize returned %Iu\n", size ); + + mem = LocalFree( mem ); + ok( !mem, "LocalFree failed, error %lu\n", GetLastError() ); + + + mem = pLocalAlloc( LMEM_MOVEABLE, 12 ); + ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() ); + ok( is_mem_entry( mem ), "unexpected moveable %p\n", mem ); + expect_entry = *mem_entry_from_HANDLE( mem ); + + tmp_mem = LocalReAlloc( mem, 0, flags ); + if (flags == LMEM_FIXED) + todo_wine ok( !tmp_mem, "LocalReAlloc succeeded\n" ); + else if (!(flags & LMEM_MODIFY) && (flags & LMEM_DISCARDABLE)) + todo_wine ok( !tmp_mem, "LocalReAlloc succeeded\n" ); + else + { + todo_wine_if(!(flags & LMEM_MOVEABLE) || flags == (LMEM_MODIFY | LMEM_MOVEABLE)) + ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); + } + entry = *mem_entry_from_HANDLE( mem ); + if (flags == LMEM_MOVEABLE) + { + expect_entry.flags |= 8; + expect_entry.ptr = NULL; + } + else if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4; + todo_wine_if(!(flags & LMEM_MODIFY) && (flags != LMEM_MOVEABLE)) + ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr ); + todo_wine_if(!(flags & LMEM_MODIFY) && (flags != LMEM_MOVEABLE)) + ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); + size = LocalSize( mem ); + if (flags == LMEM_MOVEABLE) ok( size == 0, "LocalSize returned %Iu\n", size ); + else todo_wine_if(!(flags & LMEM_MODIFY)) ok( size == 12, "LocalSize returned %Iu\n", size ); + + mem = LocalFree( mem ); + ok( !mem, "LocalFree failed, error %lu\n", GetLastError() ); + + winetest_pop_context(); + }
mem = LocalAlloc( LMEM_FIXED, 100 ); ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53474 --- dlls/comdlg32/printdlg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/comdlg32/printdlg.c b/dlls/comdlg32/printdlg.c index 5925ef64a20..bb9a9f78330 100644 --- a/dlls/comdlg32/printdlg.c +++ b/dlls/comdlg32/printdlg.c @@ -252,7 +252,7 @@ static HGLOBAL update_devmode_handleW(HGLOBAL hdm, DEVMODEW *dm) /* Increase / alloc the global memory block, when needed */ if ((dm->dmSize + dm->dmDriverExtra) > size) { if (hdm) - hdm = GlobalReAlloc(hdm, dm->dmSize + dm->dmDriverExtra, 0); + hdm = GlobalReAlloc(hdm, dm->dmSize + dm->dmDriverExtra, GMEM_MOVEABLE); else hdm = GlobalAlloc(GMEM_MOVEABLE, dm->dmSize + dm->dmDriverExtra); } @@ -280,7 +280,7 @@ static HGLOBAL update_devmode_handleA(HGLOBAL hdm, DEVMODEA *dm) /* Increase / alloc the global memory block, when needed */ if ((dm->dmSize + dm->dmDriverExtra) > size) { if (hdm) - hdm = GlobalReAlloc(hdm, dm->dmSize + dm->dmDriverExtra, 0); + hdm = GlobalReAlloc(hdm, dm->dmSize + dm->dmDriverExtra, GMEM_MOVEABLE); else hdm = GlobalAlloc(GMEM_MOVEABLE, dm->dmSize + dm->dmDriverExtra); }
From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53474 --- dlls/ole32/memlockbytes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/ole32/memlockbytes.c b/dlls/ole32/memlockbytes.c index f974e4229eb..163d25a97aa 100644 --- a/dlls/ole32/memlockbytes.c +++ b/dlls/ole32/memlockbytes.c @@ -424,7 +424,7 @@ static HRESULT WINAPI HGLOBALLockBytesImpl_SetSize( /* * Re allocate the HGlobal to fit the new size of the stream. */ - supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0); + supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, GMEM_MOVEABLE);
if (supportHandle == 0) return STG_E_MEDIUMFULL;
From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53474 --- dlls/riched20/clipboard.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/riched20/clipboard.c b/dlls/riched20/clipboard.c index 3a8440ffcd6..c94951b8f6f 100644 --- a/dlls/riched20/clipboard.c +++ b/dlls/riched20/clipboard.c @@ -375,7 +375,7 @@ static DWORD CALLBACK ME_AppendToHGLOBAL(DWORD_PTR dwCookie, LPBYTE lpBuff, LONG if (pData->nLength+cb+1 >= cb) { /* round up to 2^17 */ int nNewSize = (((nMaxSize+cb+1)|0x1FFFF)+1) & 0xFFFE0000; - pData->hData = GlobalReAlloc(pData->hData, nNewSize, 0); + pData->hData = GlobalReAlloc(pData->hData, nNewSize, GMEM_MOVEABLE); } pDest = GlobalLock(pData->hData); memcpy(pDest + pData->nLength, lpBuff, cb); @@ -397,7 +397,7 @@ static HGLOBAL get_rtf_text(ME_TextEditor *editor, const ME_Cursor *start, int n es.dwCookie = (DWORD_PTR)&gds; es.pfnCallback = ME_AppendToHGLOBAL; ME_StreamOutRange(editor, SF_RTF, start, nChars, &es); - GlobalReAlloc(gds.hData, gds.nLength+1, 0); + GlobalReAlloc(gds.hData, gds.nLength+1, GMEM_MOVEABLE); return gds.hData; }
From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53474 --- dlls/winemac.drv/dragdrop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/winemac.drv/dragdrop.c b/dlls/winemac.drv/dragdrop.c index abb3dac2a3b..45615c68b71 100644 --- a/dlls/winemac.drv/dragdrop.c +++ b/dlls/winemac.drv/dragdrop.c @@ -105,7 +105,7 @@ static HANDLE get_pasteboard_data(UINT64 pasteboard, UINT desired_format) params.data = GlobalLock(handle); status = MACDRV_CALL(dnd_get_data, ¶ms); GlobalUnlock(handle); - if (!status) return GlobalReAlloc(handle, params.size, 0); + if (!status) return GlobalReAlloc(handle, params.size, GMEM_MOVEABLE); GlobalFree(handle); if (status != STATUS_BUFFER_OVERFLOW) return 0; }
From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53474 --- dlls/user32/clipboard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/user32/clipboard.c b/dlls/user32/clipboard.c index 8ae20e53189..db86b447148 100644 --- a/dlls/user32/clipboard.c +++ b/dlls/user32/clipboard.c @@ -189,7 +189,7 @@ static HANDLE marshal_data( UINT format, HANDLE handle, size_t *ret_size ) /* rebuild the target handle from the data received in GetClipboardData */ static HANDLE unmarshal_data( UINT format, void *data, data_size_t size ) { - HANDLE handle = GlobalReAlloc( data, size, 0 ); /* release unused space */ + HANDLE handle = GlobalReAlloc( data, size, GMEM_MOVEABLE ); /* release unused space */
switch (format) {
From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53474 --- dlls/kernel32/tests/heap.c | 20 ++++++++------------ dlls/kernelbase/memory.c | 4 ++-- 2 files changed, 10 insertions(+), 14 deletions(-)
diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c index b94532a72f4..e047ada185e 100644 --- a/dlls/kernel32/tests/heap.c +++ b/dlls/kernel32/tests/heap.c @@ -1678,10 +1678,8 @@ static void test_GlobalAlloc(void) ok( size == 10, "GlobalSize returned %Iu\n", size ); SetLastError( 0xdeadbeef ); tmp_mem = GlobalReAlloc( mem, 10, 0 ); - todo_wine ok( !tmp_mem || broken( tmp_mem == mem ) /* w1064v1507 / w1064v1607 */, "GlobalReAlloc succeeded\n" ); - todo_wine ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY || broken( GetLastError() == 0xdeadbeef ) /* w1064v1507 / w1064v1607 */, "got error %lu\n", GetLastError() ); if (tmp_mem) mem = tmp_mem; @@ -1762,7 +1760,7 @@ static void test_GlobalAlloc(void) { ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem ); if (flags == GMEM_MODIFY) ok( tmp_mem == mem, "GlobalReAlloc returned %p\n", tmp_mem ); - else if (flags != GMEM_MOVEABLE) todo_wine ok( !tmp_mem || broken( tmp_mem == mem ) /* w8 */, "GlobalReAlloc succeeded\n" ); + else if (flags != GMEM_MOVEABLE) todo_wine_if(flags) ok( !tmp_mem || broken( tmp_mem == mem ) /* w8 */, "GlobalReAlloc succeeded\n" ); else todo_wine ok( tmp_mem != mem, "GlobalReAlloc returned %p\n", tmp_mem ); } else @@ -1782,7 +1780,7 @@ static void test_GlobalAlloc(void) todo_wine_if((flags & GMEM_MOVEABLE) && !(flags & GMEM_MODIFY)) ok( size == 12, "GlobalSize returned %Iu\n", size ); } - else todo_wine ok( size == 12 || broken( size == 10 ) /* w8 */, "GlobalSize returned %Iu\n", size ); + else ok( size == 12 || broken( size == 10 ) /* w8 */, "GlobalSize returned %Iu\n", size );
mem = GlobalFree( mem ); ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() ); @@ -1797,7 +1795,7 @@ static void test_GlobalAlloc(void) { ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem ); if (flags == GMEM_MODIFY) ok( tmp_mem == mem, "GlobalReAlloc returned %p\n", tmp_mem ); - else if (flags != GMEM_MOVEABLE) todo_wine ok( !tmp_mem || broken( tmp_mem == mem ) /* w8 */, "GlobalReAlloc succeeded\n" ); + else if (flags != GMEM_MOVEABLE) todo_wine_if(flags) ok( !tmp_mem || broken( tmp_mem == mem ) /* w8 */, "GlobalReAlloc succeeded\n" ); else todo_wine ok( tmp_mem != mem, "GlobalReAlloc returned %p\n", tmp_mem ); } else @@ -1817,7 +1815,7 @@ static void test_GlobalAlloc(void) todo_wine_if((flags & GMEM_MOVEABLE) && !(flags & GMEM_MODIFY)) ok( size == 12, "GlobalSize returned %Iu\n", size ); } - else todo_wine ok( size == 12 || broken( size == 0 ) /* w8 */, "GlobalSize returned %Iu\n", size ); + else ok( size == 12 || broken( size == 0 ) /* w8 */, "GlobalSize returned %Iu\n", size );
mem = GlobalFree( mem ); ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() ); @@ -2372,10 +2370,8 @@ static void test_LocalAlloc(void) ok( size == 10, "LocalSize returned %Iu\n", size ); SetLastError( 0xdeadbeef ); tmp_mem = LocalReAlloc( mem, 10, 0 ); - todo_wine ok( !tmp_mem || broken( tmp_mem == mem ) /* w1064v1507 / w1064v1607 */, "LocalReAlloc succeeded\n" ); - todo_wine ok( GetLastError() == ERROR_NOT_ENOUGH_MEMORY || broken( GetLastError() == 0xdeadbeef ) /* w1064v1507 / w1064v1607 */, "got error %lu\n", GetLastError() ); if (tmp_mem) mem = tmp_mem; @@ -2437,14 +2433,14 @@ static void test_LocalAlloc(void) tmp_mem = LocalReAlloc( mem, 10, flags ); ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem ); if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p\n", tmp_mem ); - else if (flags != LMEM_MOVEABLE) todo_wine ok( !tmp_mem, "LocalReAlloc succeeded\n" ); + else if (flags != LMEM_MOVEABLE) todo_wine_if(flags) ok( !tmp_mem, "LocalReAlloc succeeded\n" ); else todo_wine ok( tmp_mem != mem, "LocalReAlloc returned %p\n", tmp_mem ); if (tmp_mem) mem = tmp_mem;
size = LocalSize( mem ); if (flags == LMEM_MOVEABLE) ok( size == 10, "LocalSize returned %Iu\n", size ); else if (flags) todo_wine_if(!(flags & LMEM_MODIFY)) ok( size == 12, "LocalSize returned %Iu\n", size ); - else todo_wine ok( size == 12, "LocalSize returned %Iu\n", size ); + else ok( size == 12, "LocalSize returned %Iu\n", size );
mem = LocalFree( mem ); ok( !mem, "LocalFree failed, error %lu\n", GetLastError() ); @@ -2457,14 +2453,14 @@ static void test_LocalAlloc(void) tmp_mem = LocalReAlloc( mem, 0, flags ); ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem ); if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p\n", tmp_mem ); - else if (flags != LMEM_MOVEABLE) todo_wine ok( !tmp_mem, "LocalReAlloc succeeded\n" ); + else if (flags != LMEM_MOVEABLE) todo_wine_if(flags) ok( !tmp_mem, "LocalReAlloc succeeded\n" ); else todo_wine ok( tmp_mem != mem, "LocalReAlloc returned %p\n", tmp_mem ); if (tmp_mem) mem = tmp_mem;
size = LocalSize( mem ); if (flags == LMEM_MOVEABLE) ok( size == 0 || broken( size == 1 ) /* w7 */, "LocalSize returned %Iu\n", size ); else if (flags) todo_wine_if(!(flags & LMEM_MODIFY)) ok( size == 12, "LocalSize returned %Iu\n", size ); - else todo_wine ok( size == 12, "LocalSize returned %Iu\n", size ); + else ok( size == 12, "LocalSize returned %Iu\n", size );
mem = LocalFree( mem ); ok( !mem, "LocalFree failed, error %lu\n", GetLastError() ); diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c index 4c462c1633b..5710ee3b082 100644 --- a/dlls/kernelbase/memory.c +++ b/dlls/kernelbase/memory.c @@ -990,13 +990,13 @@ HLOCAL WINAPI DECLSPEC_HOTPATCH LocalReAlloc( HLOCAL handle, SIZE_T size, UINT f HeapValidate( heap, HEAP_NO_SERIALIZE, ptr )) { if (flags & LMEM_MODIFY) ret = handle; - else + else if (flags & LMEM_MOVEABLE) { - if (!(flags & LMEM_MOVEABLE)) heap_flags |= HEAP_REALLOC_IN_PLACE_ONLY; ret = HeapReAlloc( heap, heap_flags, ptr, size ); if (ret) RtlSetUserValueHeap( heap, heap_flags, ret, ret ); else SetLastError( ERROR_NOT_ENOUGH_MEMORY ); } + else SetLastError( ERROR_NOT_ENOUGH_MEMORY ); } else if ((mem = unsafe_mem_from_HLOCAL( handle ))) {
From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53474 --- dlls/kernel32/tests/heap.c | 31 ++----------------------------- dlls/kernelbase/memory.c | 13 ++++++------- 2 files changed, 8 insertions(+), 36 deletions(-)
diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c index e047ada185e..fb6e4aa56f8 100644 --- a/dlls/kernel32/tests/heap.c +++ b/dlls/kernel32/tests/heap.c @@ -1743,7 +1743,7 @@ static void test_GlobalAlloc(void) if (flags == GMEM_MOVEABLE) ok( size == 512, "GlobalSize returned %Iu\n", size ); else { - todo_wine_if(flags && (flags & GMEM_MOVEABLE) && !(flags & GMEM_MODIFY)) + todo_wine_if((flags & GMEM_DISCARDABLE) && !(flags & GMEM_MODIFY)) ok( size == 10, "GlobalSize returned %Iu\n", size ); }
@@ -1777,7 +1777,7 @@ static void test_GlobalAlloc(void) if (flags == GMEM_MOVEABLE) ok( size == 10, "GlobalSize returned %Iu\n", size ); else if (flags) { - todo_wine_if((flags & GMEM_MOVEABLE) && !(flags & GMEM_MODIFY)) + todo_wine_if((flags & GMEM_DISCARDABLE) && (flags & (GMEM_MODIFY | GMEM_MOVEABLE | GMEM_DISCARDABLE)) != (GMEM_MODIFY | GMEM_MOVEABLE | GMEM_DISCARDABLE)) ok( size == 12, "GlobalSize returned %Iu\n", size ); } else ok( size == 12 || broken( size == 10 ) /* w8 */, "GlobalSize returned %Iu\n", size ); @@ -1920,10 +1920,7 @@ static void test_GlobalAlloc(void) if (!(flags & GMEM_MODIFY) && (flags & GMEM_DISCARDABLE)) todo_wine ok( !tmp_mem, "GlobalReAlloc succeeded\n" ); else - { - todo_wine_if(flags && (!(flags & GMEM_MOVEABLE) || flags == (GMEM_MODIFY | GMEM_MOVEABLE))) ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); - } entry = *mem_entry_from_HANDLE( mem ); if ((flags & GMEM_DISCARDABLE) && (flags & GMEM_MODIFY)) expect_entry.flags |= 4; if ((flags & GMEM_DISCARDABLE) || (flags & GMEM_MODIFY)) @@ -1950,10 +1947,7 @@ static void test_GlobalAlloc(void) if (!(flags & GMEM_MODIFY) && (flags & GMEM_DISCARDABLE)) todo_wine ok( !tmp_mem, "GlobalReAlloc succeeded\n" ); else - { - todo_wine_if(flags && (!(flags & GMEM_MOVEABLE) || flags == (GMEM_MODIFY | GMEM_MOVEABLE))) ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); - } entry = *mem_entry_from_HANDLE( mem ); if ((flags & GMEM_DISCARDABLE) && (flags & GMEM_MODIFY)) expect_entry.flags |= 4; ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr ); @@ -1979,10 +1973,7 @@ static void test_GlobalAlloc(void) else if (!(flags & GMEM_MODIFY) && (flags & GMEM_DISCARDABLE)) todo_wine ok( !tmp_mem, "GlobalReAlloc succeeded\n" ); else - { - todo_wine_if(!(flags & GMEM_MOVEABLE) || flags == (GMEM_MODIFY | GMEM_MOVEABLE)) ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); - } entry = *mem_entry_from_HANDLE( mem ); if (flags == GMEM_MOVEABLE) { @@ -2477,10 +2468,7 @@ static void test_LocalAlloc(void) if (!(flags & LMEM_MODIFY) && ((flags & LMEM_DISCARDABLE) || !(flags & LMEM_MOVEABLE))) todo_wine ok( !tmp_mem, "LocalReAlloc succeeded\n" ); else - { - todo_wine_if((!(flags & LMEM_MOVEABLE) || flags == (LMEM_MODIFY | LMEM_MOVEABLE))) ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); - } entry = *mem_entry_from_HANDLE( mem ); if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4; if (flags == LMEM_MOVEABLE) ok( entry.ptr != expect_entry.ptr, "got unexpected ptr %p\n", entry.ptr ); @@ -2507,10 +2495,7 @@ static void test_LocalAlloc(void) if (!(flags & LMEM_MODIFY) && (flags & LMEM_DISCARDABLE)) todo_wine ok( !tmp_mem, "LocalReAlloc succeeded\n" ); else - { - todo_wine_if(flags && (!(flags & LMEM_MOVEABLE) || flags == (LMEM_MODIFY | LMEM_MOVEABLE))) ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); - } entry = *mem_entry_from_HANDLE( mem ); if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4; ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr ); @@ -2536,10 +2521,7 @@ static void test_LocalAlloc(void)
tmp_mem = LocalReAlloc( mem, 0, flags ); if (flags & LMEM_MODIFY) - { - todo_wine_if(!(flags & LMEM_MOVEABLE) || (flags == (LMEM_MOVEABLE | LMEM_MODIFY))) ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); - } else todo_wine ok( !tmp_mem, "LocalReAlloc succeeded\n" ); entry = *mem_entry_from_HANDLE( mem ); @@ -2567,10 +2549,7 @@ static void test_LocalAlloc(void) if (!(flags & LMEM_MODIFY) && (flags & LMEM_DISCARDABLE)) todo_wine ok( !tmp_mem, "LocalReAlloc succeeded\n" ); else - { - todo_wine_if(flags && (!(flags & LMEM_MOVEABLE) || flags == (LMEM_MODIFY | LMEM_MOVEABLE))) ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); - } entry = *mem_entry_from_HANDLE( mem ); if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4; if ((flags & LMEM_DISCARDABLE) || (flags & LMEM_MODIFY)) @@ -2597,10 +2576,7 @@ static void test_LocalAlloc(void) if (!(flags & LMEM_MODIFY) && (flags & LMEM_DISCARDABLE)) todo_wine ok( !tmp_mem, "LocalReAlloc succeeded\n" ); else - { - todo_wine_if(flags && (!(flags & LMEM_MOVEABLE) || flags == (LMEM_MODIFY | LMEM_MOVEABLE))) ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); - } entry = *mem_entry_from_HANDLE( mem ); if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4; ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr ); @@ -2626,10 +2602,7 @@ static void test_LocalAlloc(void) else if (!(flags & LMEM_MODIFY) && (flags & LMEM_DISCARDABLE)) todo_wine ok( !tmp_mem, "LocalReAlloc succeeded\n" ); else - { - todo_wine_if(!(flags & LMEM_MOVEABLE) || flags == (LMEM_MODIFY | LMEM_MOVEABLE)) ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); - } entry = *mem_entry_from_HANDLE( mem ); if (flags == LMEM_MOVEABLE) { diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c index 5710ee3b082..324caf4b5b6 100644 --- a/dlls/kernelbase/memory.c +++ b/dlls/kernelbase/memory.c @@ -1000,7 +1000,12 @@ HLOCAL WINAPI DECLSPEC_HOTPATCH LocalReAlloc( HLOCAL handle, SIZE_T size, UINT f } else if ((mem = unsafe_mem_from_HLOCAL( handle ))) { - if (!(flags & LMEM_MODIFY)) + if (flags & LMEM_MODIFY) + { + if (flags & LMEM_DISCARDABLE) mem->flags |= MEM_FLAG_DISCARDABLE; + ret = handle; + } + else { if (size) { @@ -1025,12 +1030,6 @@ HLOCAL WINAPI DECLSPEC_HOTPATCH LocalReAlloc( HLOCAL handle, SIZE_T size, UINT f ret = handle; } } - else if (flags & LMEM_DISCARDABLE) - { - mem->flags |= MEM_FLAG_DISCARDABLE; - ret = handle; - } - else SetLastError( ERROR_INVALID_PARAMETER ); } else SetLastError( ERROR_INVALID_HANDLE ); RtlUnlockHeap( heap );
From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53474 --- dlls/kernel32/tests/heap.c | 93 +++++++++++++++++--------------------- dlls/kernelbase/memory.c | 2 + 2 files changed, 44 insertions(+), 51 deletions(-)
diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c index fb6e4aa56f8..941d1f6e182 100644 --- a/dlls/kernel32/tests/heap.c +++ b/dlls/kernel32/tests/heap.c @@ -1726,7 +1726,7 @@ static void test_GlobalAlloc(void) { ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem ); if (flags == GMEM_MODIFY) ok( tmp_mem == mem, "GlobalReAlloc returned %p\n", tmp_mem ); - else if (flags != GMEM_MOVEABLE) todo_wine_if(flags) ok( !tmp_mem, "GlobalReAlloc succeeded\n" ); + else if (flags != GMEM_MOVEABLE) ok( !tmp_mem, "GlobalReAlloc succeeded\n" ); else ok( tmp_mem != mem, "GlobalReAlloc returned %p\n", tmp_mem ); } else @@ -1741,11 +1741,7 @@ static void test_GlobalAlloc(void)
size = GlobalSize( mem ); if (flags == GMEM_MOVEABLE) ok( size == 512, "GlobalSize returned %Iu\n", size ); - else - { - todo_wine_if((flags & GMEM_DISCARDABLE) && !(flags & GMEM_MODIFY)) - ok( size == 10, "GlobalSize returned %Iu\n", size ); - } + else ok( size == 10, "GlobalSize returned %Iu\n", size );
mem = GlobalFree( mem ); ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() ); @@ -1760,7 +1756,7 @@ static void test_GlobalAlloc(void) { ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem ); if (flags == GMEM_MODIFY) ok( tmp_mem == mem, "GlobalReAlloc returned %p\n", tmp_mem ); - else if (flags != GMEM_MOVEABLE) todo_wine_if(flags) ok( !tmp_mem || broken( tmp_mem == mem ) /* w8 */, "GlobalReAlloc succeeded\n" ); + else if (flags != GMEM_MOVEABLE) ok( !tmp_mem || broken( tmp_mem == mem ) /* w8 */, "GlobalReAlloc succeeded\n" ); else todo_wine ok( tmp_mem != mem, "GlobalReAlloc returned %p\n", tmp_mem ); } else @@ -1775,11 +1771,7 @@ static void test_GlobalAlloc(void)
size = GlobalSize( mem ); if (flags == GMEM_MOVEABLE) ok( size == 10, "GlobalSize returned %Iu\n", size ); - else if (flags) - { - todo_wine_if((flags & GMEM_DISCARDABLE) && (flags & (GMEM_MODIFY | GMEM_MOVEABLE | GMEM_DISCARDABLE)) != (GMEM_MODIFY | GMEM_MOVEABLE | GMEM_DISCARDABLE)) - ok( size == 12, "GlobalSize returned %Iu\n", size ); - } + else if (flags) ok( size == 12, "GlobalSize returned %Iu\n", size ); else ok( size == 12 || broken( size == 10 ) /* w8 */, "GlobalSize returned %Iu\n", size );
mem = GlobalFree( mem ); @@ -1795,7 +1787,7 @@ static void test_GlobalAlloc(void) { ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem ); if (flags == GMEM_MODIFY) ok( tmp_mem == mem, "GlobalReAlloc returned %p\n", tmp_mem ); - else if (flags != GMEM_MOVEABLE) todo_wine_if(flags) ok( !tmp_mem || broken( tmp_mem == mem ) /* w8 */, "GlobalReAlloc succeeded\n" ); + else if (flags != GMEM_MOVEABLE) ok( !tmp_mem || broken( tmp_mem == mem ) /* w8 */, "GlobalReAlloc succeeded\n" ); else todo_wine ok( tmp_mem != mem, "GlobalReAlloc returned %p\n", tmp_mem ); } else @@ -1810,11 +1802,7 @@ static void test_GlobalAlloc(void)
size = GlobalSize( mem ); if (flags == GMEM_MOVEABLE) ok( size == 0 || broken( size == 1 ) /* w7 */, "GlobalSize returned %Iu\n", size ); - else if (flags) - { - todo_wine_if((flags & GMEM_MOVEABLE) && !(flags & GMEM_MODIFY)) - ok( size == 12, "GlobalSize returned %Iu\n", size ); - } + else if (flags) ok( size == 12, "GlobalSize returned %Iu\n", size ); else ok( size == 12 || broken( size == 0 ) /* w8 */, "GlobalSize returned %Iu\n", size );
mem = GlobalFree( mem ); @@ -1918,19 +1906,19 @@ static void test_GlobalAlloc(void)
tmp_mem = GlobalReAlloc( mem, 512, flags ); if (!(flags & GMEM_MODIFY) && (flags & GMEM_DISCARDABLE)) - todo_wine ok( !tmp_mem, "GlobalReAlloc succeeded\n" ); + ok( !tmp_mem, "GlobalReAlloc succeeded\n" ); else ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); entry = *mem_entry_from_HANDLE( mem ); if ((flags & GMEM_DISCARDABLE) && (flags & GMEM_MODIFY)) expect_entry.flags |= 4; if ((flags & GMEM_DISCARDABLE) || (flags & GMEM_MODIFY)) - todo_wine_if(!(flags & GMEM_MODIFY)) ok( entry.ptr == expect_entry.ptr, "got ptr %p\n", entry.ptr ); + ok( entry.ptr == expect_entry.ptr, "got ptr %p\n", entry.ptr ); else ok( entry.ptr != expect_entry.ptr, "got unexpected ptr %p\n", entry.ptr ); ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); size = GlobalSize( mem ); if ((flags & GMEM_DISCARDABLE) || (flags & GMEM_MODIFY)) - todo_wine_if(!(flags & GMEM_MODIFY)) ok( size == 10, "GlobalSize returned %Iu\n", size ); + ok( size == 10, "GlobalSize returned %Iu\n", size ); else ok( size == 512, "GlobalSize returned %Iu\n", size );
@@ -1945,7 +1933,7 @@ static void test_GlobalAlloc(void)
tmp_mem = GlobalReAlloc( mem, 10, flags ); if (!(flags & GMEM_MODIFY) && (flags & GMEM_DISCARDABLE)) - todo_wine ok( !tmp_mem, "GlobalReAlloc succeeded\n" ); + ok( !tmp_mem, "GlobalReAlloc succeeded\n" ); else ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); entry = *mem_entry_from_HANDLE( mem ); @@ -1954,7 +1942,7 @@ static void test_GlobalAlloc(void) ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); size = GlobalSize( mem ); if ((flags & GMEM_DISCARDABLE) || (flags & GMEM_MODIFY)) - todo_wine_if(!(flags & GMEM_MODIFY)) ok( size == 12, "GlobalSize returned %Iu\n", size ); + ok( size == 12, "GlobalSize returned %Iu\n", size ); else ok( size == 10, "GlobalSize returned %Iu\n", size );
@@ -1971,7 +1959,7 @@ static void test_GlobalAlloc(void) if (flags == GMEM_FIXED) todo_wine ok( !tmp_mem, "GlobalReAlloc succeeded\n" ); else if (!(flags & GMEM_MODIFY) && (flags & GMEM_DISCARDABLE)) - todo_wine ok( !tmp_mem, "GlobalReAlloc succeeded\n" ); + ok( !tmp_mem, "GlobalReAlloc succeeded\n" ); else ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); entry = *mem_entry_from_HANDLE( mem ); @@ -1981,13 +1969,13 @@ static void test_GlobalAlloc(void) expect_entry.ptr = NULL; } else if ((flags & GMEM_DISCARDABLE) && (flags & GMEM_MODIFY)) expect_entry.flags |= 4; - todo_wine_if(!(flags & GMEM_MODIFY) && (flags != GMEM_MOVEABLE)) + todo_wine_if(!flags) ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr ); - todo_wine_if(!(flags & GMEM_MODIFY) && (flags != GMEM_MOVEABLE)) + todo_wine_if(!flags) ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); size = GlobalSize( mem ); if (flags == GMEM_MOVEABLE) ok( size == 0, "GlobalSize returned %Iu\n", size ); - else todo_wine_if(!(flags & GMEM_MODIFY)) ok( size == 12, "GlobalSize returned %Iu\n", size ); + else todo_wine_if(!flags) ok( size == 12, "GlobalSize returned %Iu\n", size );
mem = GlobalFree( mem ); ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() ); @@ -2405,13 +2393,13 @@ static void test_LocalAlloc(void) tmp_mem = LocalReAlloc( mem, 512, flags ); ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem ); if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p\n", tmp_mem ); - else if (flags != LMEM_MOVEABLE) todo_wine_if(flags) ok( !tmp_mem, "LocalReAlloc succeeded\n" ); + else if (flags != LMEM_MOVEABLE) ok( !tmp_mem, "LocalReAlloc succeeded\n" ); else ok( tmp_mem != mem, "LocalReAlloc returned %p\n", tmp_mem ); if (tmp_mem) mem = tmp_mem;
size = LocalSize( mem ); if (flags == LMEM_MOVEABLE) ok( size == 512, "LocalSize returned %Iu\n", size ); - else todo_wine_if(flags && !(flags & LMEM_MODIFY)) ok( size == 10, "LocalSize returned %Iu\n", size ); + else ok( size == 10, "LocalSize returned %Iu\n", size );
mem = LocalFree( mem ); ok( !mem, "LocalFree failed, error %lu\n", GetLastError() ); @@ -2424,13 +2412,13 @@ static void test_LocalAlloc(void) tmp_mem = LocalReAlloc( mem, 10, flags ); ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem ); if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p\n", tmp_mem ); - else if (flags != LMEM_MOVEABLE) todo_wine_if(flags) ok( !tmp_mem, "LocalReAlloc succeeded\n" ); + else if (flags != LMEM_MOVEABLE) ok( !tmp_mem, "LocalReAlloc succeeded\n" ); else todo_wine ok( tmp_mem != mem, "LocalReAlloc returned %p\n", tmp_mem ); if (tmp_mem) mem = tmp_mem;
size = LocalSize( mem ); if (flags == LMEM_MOVEABLE) ok( size == 10, "LocalSize returned %Iu\n", size ); - else if (flags) todo_wine_if(!(flags & LMEM_MODIFY)) ok( size == 12, "LocalSize returned %Iu\n", size ); + else if (flags) ok( size == 12, "LocalSize returned %Iu\n", size ); else ok( size == 12, "LocalSize returned %Iu\n", size );
mem = LocalFree( mem ); @@ -2444,13 +2432,13 @@ static void test_LocalAlloc(void) tmp_mem = LocalReAlloc( mem, 0, flags ); ok( !is_mem_entry( tmp_mem ), "unexpected moveable %p\n", tmp_mem ); if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p\n", tmp_mem ); - else if (flags != LMEM_MOVEABLE) todo_wine_if(flags) ok( !tmp_mem, "LocalReAlloc succeeded\n" ); + else if (flags != LMEM_MOVEABLE) ok( !tmp_mem, "LocalReAlloc succeeded\n" ); else todo_wine ok( tmp_mem != mem, "LocalReAlloc returned %p\n", tmp_mem ); if (tmp_mem) mem = tmp_mem;
size = LocalSize( mem ); if (flags == LMEM_MOVEABLE) ok( size == 0 || broken( size == 1 ) /* w7 */, "LocalSize returned %Iu\n", size ); - else if (flags) todo_wine_if(!(flags & LMEM_MODIFY)) ok( size == 12, "LocalSize returned %Iu\n", size ); + else if (flags) ok( size == 12, "LocalSize returned %Iu\n", size ); else ok( size == 12, "LocalSize returned %Iu\n", size );
mem = LocalFree( mem ); @@ -2466,17 +2454,17 @@ static void test_LocalAlloc(void)
tmp_mem = LocalReAlloc( mem, 512, flags ); if (!(flags & LMEM_MODIFY) && ((flags & LMEM_DISCARDABLE) || !(flags & LMEM_MOVEABLE))) - todo_wine ok( !tmp_mem, "LocalReAlloc succeeded\n" ); + todo_wine_if(flags == LMEM_FIXED) ok( !tmp_mem, "LocalReAlloc succeeded\n" ); else ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); entry = *mem_entry_from_HANDLE( mem ); if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4; if (flags == LMEM_MOVEABLE) ok( entry.ptr != expect_entry.ptr, "got unexpected ptr %p\n", entry.ptr ); - else todo_wine_if(!(flags & LMEM_MODIFY)) ok( entry.ptr == expect_entry.ptr, "got ptr %p\n", entry.ptr ); + else todo_wine_if(flags == LMEM_FIXED) ok( entry.ptr == expect_entry.ptr, "got ptr %p\n", entry.ptr ); ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); size = LocalSize( mem ); if (flags == LMEM_MOVEABLE) ok( size == 512, "LocalSize returned %Iu\n", size ); - else todo_wine_if(!(flags & LMEM_MODIFY)) ok( size == 10, "LocalSize returned %Iu\n", size ); + else todo_wine_if(flags == LMEM_FIXED) ok( size == 10, "LocalSize returned %Iu\n", size );
ret = LocalUnlock( mem ); ok( !ret, "LocalUnlock succeeded\n" ); @@ -2493,7 +2481,7 @@ static void test_LocalAlloc(void)
tmp_mem = LocalReAlloc( mem, 10, flags ); if (!(flags & LMEM_MODIFY) && (flags & LMEM_DISCARDABLE)) - todo_wine ok( !tmp_mem, "LocalReAlloc succeeded\n" ); + ok( !tmp_mem, "LocalReAlloc succeeded\n" ); else ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); entry = *mem_entry_from_HANDLE( mem ); @@ -2502,7 +2490,7 @@ static void test_LocalAlloc(void) ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); size = LocalSize( mem ); if ((flags & LMEM_DISCARDABLE) || (flags & LMEM_MODIFY)) - todo_wine_if(!(flags & LMEM_MODIFY)) ok( size == 12, "LocalSize returned %Iu\n", size ); + ok( size == 12, "LocalSize returned %Iu\n", size ); else ok( size == 10, "LocalSize returned %Iu\n", size );
@@ -2523,15 +2511,18 @@ static void test_LocalAlloc(void) if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); else - todo_wine ok( !tmp_mem, "LocalReAlloc succeeded\n" ); + { + todo_wine_if(flags == LMEM_FIXED || flags == LMEM_MOVEABLE) + ok( !tmp_mem, "LocalReAlloc succeeded\n" ); + } entry = *mem_entry_from_HANDLE( mem ); if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4; - todo_wine_if(!(flags & LMEM_MODIFY)) + todo_wine_if(flags == LMEM_FIXED || flags == LMEM_MOVEABLE) ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr ); - todo_wine_if(!(flags & LMEM_MODIFY)) + todo_wine_if(flags == LMEM_FIXED || flags == LMEM_MOVEABLE) ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); size = LocalSize( mem ); - todo_wine_if(!(flags & LMEM_MODIFY)) + todo_wine_if(flags == LMEM_FIXED || flags == LMEM_MOVEABLE) ok( size == 12, "LocalSize returned %Iu\n", size );
ret = LocalUnlock( mem ); @@ -2547,19 +2538,19 @@ static void test_LocalAlloc(void)
tmp_mem = LocalReAlloc( mem, 512, flags ); if (!(flags & LMEM_MODIFY) && (flags & LMEM_DISCARDABLE)) - todo_wine ok( !tmp_mem, "LocalReAlloc succeeded\n" ); + ok( !tmp_mem, "LocalReAlloc succeeded\n" ); else ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); entry = *mem_entry_from_HANDLE( mem ); if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4; if ((flags & LMEM_DISCARDABLE) || (flags & LMEM_MODIFY)) - todo_wine_if(!(flags & LMEM_MODIFY)) ok( entry.ptr == expect_entry.ptr, "got ptr %p\n", entry.ptr ); + ok( entry.ptr == expect_entry.ptr, "got ptr %p\n", entry.ptr ); else ok( entry.ptr != expect_entry.ptr, "got unexpected ptr %p\n", entry.ptr ); ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); size = LocalSize( mem ); if ((flags & LMEM_DISCARDABLE) || (flags & LMEM_MODIFY)) - todo_wine_if(!(flags & LMEM_MODIFY)) ok( size == 10, "LocalSize returned %Iu\n", size ); + ok( size == 10, "LocalSize returned %Iu\n", size ); else ok( size == 512, "LocalSize returned %Iu\n", size );
@@ -2574,7 +2565,7 @@ static void test_LocalAlloc(void)
tmp_mem = LocalReAlloc( mem, 10, flags ); if (!(flags & LMEM_MODIFY) && (flags & LMEM_DISCARDABLE)) - todo_wine ok( !tmp_mem, "LocalReAlloc succeeded\n" ); + ok( !tmp_mem, "LocalReAlloc succeeded\n" ); else ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); entry = *mem_entry_from_HANDLE( mem ); @@ -2583,7 +2574,7 @@ static void test_LocalAlloc(void) ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); size = LocalSize( mem ); if ((flags & LMEM_DISCARDABLE) || (flags & LMEM_MODIFY)) - todo_wine_if(!(flags & LMEM_MODIFY)) ok( size == 12, "LocalSize returned %Iu\n", size ); + ok( size == 12, "LocalSize returned %Iu\n", size ); else ok( size == 10, "LocalSize returned %Iu\n", size );
@@ -2600,7 +2591,7 @@ static void test_LocalAlloc(void) if (flags == LMEM_FIXED) todo_wine ok( !tmp_mem, "LocalReAlloc succeeded\n" ); else if (!(flags & LMEM_MODIFY) && (flags & LMEM_DISCARDABLE)) - todo_wine ok( !tmp_mem, "LocalReAlloc succeeded\n" ); + ok( !tmp_mem, "LocalReAlloc succeeded\n" ); else ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); entry = *mem_entry_from_HANDLE( mem ); @@ -2610,13 +2601,13 @@ static void test_LocalAlloc(void) expect_entry.ptr = NULL; } else if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4; - todo_wine_if(!(flags & LMEM_MODIFY) && (flags != LMEM_MOVEABLE)) + todo_wine_if(!flags) ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr ); - todo_wine_if(!(flags & LMEM_MODIFY) && (flags != LMEM_MOVEABLE)) + todo_wine_if(!flags) ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); size = LocalSize( mem ); if (flags == LMEM_MOVEABLE) ok( size == 0, "LocalSize returned %Iu\n", size ); - else todo_wine_if(!(flags & LMEM_MODIFY)) ok( size == 12, "LocalSize returned %Iu\n", size ); + else todo_wine_if(!(flags & (LMEM_MODIFY | LMEM_DISCARDABLE))) ok( size == 12, "LocalSize returned %Iu\n", size );
mem = LocalFree( mem ); ok( !mem, "LocalFree failed, error %lu\n", GetLastError() ); diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c index 324caf4b5b6..98f5eabc316 100644 --- a/dlls/kernelbase/memory.c +++ b/dlls/kernelbase/memory.c @@ -990,6 +990,7 @@ HLOCAL WINAPI DECLSPEC_HOTPATCH LocalReAlloc( HLOCAL handle, SIZE_T size, UINT f HeapValidate( heap, HEAP_NO_SERIALIZE, ptr )) { if (flags & LMEM_MODIFY) ret = handle; + else if (flags & LMEM_DISCARDABLE) SetLastError( ERROR_INVALID_PARAMETER ); else if (flags & LMEM_MOVEABLE) { ret = HeapReAlloc( heap, heap_flags, ptr, size ); @@ -1005,6 +1006,7 @@ HLOCAL WINAPI DECLSPEC_HOTPATCH LocalReAlloc( HLOCAL handle, SIZE_T size, UINT f if (flags & LMEM_DISCARDABLE) mem->flags |= MEM_FLAG_DISCARDABLE; ret = handle; } + else if (flags & LMEM_DISCARDABLE) SetLastError( ERROR_INVALID_PARAMETER ); else { if (size)
From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53474 --- dlls/kernel32/tests/heap.c | 6 +++--- dlls/kernelbase/memory.c | 1 + 2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c index 941d1f6e182..f66a6135591 100644 --- a/dlls/kernel32/tests/heap.c +++ b/dlls/kernel32/tests/heap.c @@ -2454,17 +2454,17 @@ static void test_LocalAlloc(void)
tmp_mem = LocalReAlloc( mem, 512, flags ); if (!(flags & LMEM_MODIFY) && ((flags & LMEM_DISCARDABLE) || !(flags & LMEM_MOVEABLE))) - todo_wine_if(flags == LMEM_FIXED) ok( !tmp_mem, "LocalReAlloc succeeded\n" ); + ok( !tmp_mem, "LocalReAlloc succeeded\n" ); else ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); entry = *mem_entry_from_HANDLE( mem ); if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4; if (flags == LMEM_MOVEABLE) ok( entry.ptr != expect_entry.ptr, "got unexpected ptr %p\n", entry.ptr ); - else todo_wine_if(flags == LMEM_FIXED) ok( entry.ptr == expect_entry.ptr, "got ptr %p\n", entry.ptr ); + else ok( entry.ptr == expect_entry.ptr, "got ptr %p\n", entry.ptr ); ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); size = LocalSize( mem ); if (flags == LMEM_MOVEABLE) ok( size == 512, "LocalSize returned %Iu\n", size ); - else todo_wine_if(flags == LMEM_FIXED) ok( size == 10, "LocalSize returned %Iu\n", size ); + else ok( size == 10, "LocalSize returned %Iu\n", size );
ret = LocalUnlock( mem ); ok( !ret, "LocalUnlock succeeded\n" ); diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c index 98f5eabc316..baf17c075b4 100644 --- a/dlls/kernelbase/memory.c +++ b/dlls/kernelbase/memory.c @@ -1011,6 +1011,7 @@ HLOCAL WINAPI DECLSPEC_HOTPATCH LocalReAlloc( HLOCAL handle, SIZE_T size, UINT f { if (size) { + if (mem->lock && !(flags & LMEM_MOVEABLE)) heap_flags |= HEAP_REALLOC_IN_PLACE_ONLY; if (!mem->ptr) ptr = HeapAlloc( heap, heap_flags, size ); else ptr = HeapReAlloc( heap, heap_flags, mem->ptr, size );
From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53474 --- dlls/kernel32/heap.c | 5 ++++- dlls/kernel32/tests/heap.c | 16 +++++----------- 2 files changed, 9 insertions(+), 12 deletions(-)
diff --git a/dlls/kernel32/heap.c b/dlls/kernel32/heap.c index 9e1da01778d..3ea3b348376 100644 --- a/dlls/kernel32/heap.c +++ b/dlls/kernel32/heap.c @@ -195,7 +195,10 @@ HGLOBAL WINAPI GlobalReAlloc( HGLOBAL handle, SIZE_T size, UINT flags ) struct mem_entry *mem; void *ptr;
- if ((mem = unsafe_mem_from_HLOCAL( handle )) && mem->lock) return 0; + if (!(flags & GMEM_MODIFY) && (mem = unsafe_mem_from_HLOCAL( handle )) && + mem->lock && (!size || (flags & GMEM_DISCARDABLE))) + return 0; + if (!(handle = LocalReAlloc( handle, size, flags ))) return 0;
/* GlobalReAlloc allows changing GMEM_FIXED to GMEM_MOVEABLE with GMEM_MODIFY */ diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c index f66a6135591..883b75e5e39 100644 --- a/dlls/kernel32/tests/heap.c +++ b/dlls/kernel32/tests/heap.c @@ -1820,21 +1820,17 @@ static void test_GlobalAlloc(void) if (!(flags & GMEM_MODIFY) && ((flags & GMEM_DISCARDABLE) || !(flags & GMEM_MOVEABLE))) ok( !tmp_mem, "GlobalReAlloc succeeded\n" ); else - { - todo_wine ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); - } entry = *mem_entry_from_HANDLE( mem ); if ((flags & GMEM_DISCARDABLE) && (flags & GMEM_MODIFY)) expect_entry.flags |= 4; if (flags == GMEM_MOVEABLE) - todo_wine ok( entry.ptr != expect_entry.ptr, "got unexpected ptr %p\n", entry.ptr ); + ok( entry.ptr != expect_entry.ptr, "got unexpected ptr %p\n", entry.ptr ); else ok( entry.ptr == expect_entry.ptr, "got ptr %p\n", entry.ptr ); - todo_wine_if((flags & GMEM_MODIFY) && (flags & GMEM_MOVEABLE) && flags != (GMEM_MODIFY | GMEM_MOVEABLE)) ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); size = GlobalSize( mem ); if (flags == GMEM_MOVEABLE) - todo_wine ok( size == 512, "GlobalSize returned %Iu\n", size ); + ok( size == 512, "GlobalSize returned %Iu\n", size ); else ok( size == 10, "GlobalSize returned %Iu\n", size );
@@ -1855,17 +1851,16 @@ static void test_GlobalAlloc(void) if (!(flags & GMEM_MODIFY) && (flags & GMEM_DISCARDABLE)) ok( !tmp_mem, "GlobalReAlloc succeeded\n" ); else - todo_wine ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); + ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); entry = *mem_entry_from_HANDLE( mem ); if ((flags & GMEM_DISCARDABLE) && (flags & GMEM_MODIFY)) expect_entry.flags |= 4; ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr ); - todo_wine_if((flags & GMEM_DISCARDABLE) && (flags & GMEM_MODIFY)) ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); size = GlobalSize( mem ); if ((flags & GMEM_DISCARDABLE) || (flags & GMEM_MODIFY)) ok( size == 12, "GlobalSize returned %Iu\n", size ); else - todo_wine_if(!(flags & GMEM_MODIFY)) ok( size == 10, "GlobalSize returned %Iu\n", size ); + ok( size == 10, "GlobalSize returned %Iu\n", size );
ret = GlobalUnlock( mem ); ok( !ret, "GlobalUnlock succeeded\n" ); @@ -1882,13 +1877,12 @@ static void test_GlobalAlloc(void)
tmp_mem = GlobalReAlloc( mem, 0, flags ); if (flags & GMEM_MODIFY) - todo_wine ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); + ok( tmp_mem == mem, "GlobalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); else ok( !tmp_mem, "GlobalReAlloc succeeded\n" ); entry = *mem_entry_from_HANDLE( mem ); if ((flags & GMEM_DISCARDABLE) && (flags & GMEM_MODIFY)) expect_entry.flags |= 4; ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr ); - todo_wine_if((flags & GMEM_MODIFY) && (flags & GMEM_DISCARDABLE)) ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); size = GlobalSize( mem ); ok( size == 12, "GlobalSize returned %Iu\n", size );
From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53474 --- dlls/kernel32/tests/heap.c | 18 ++++-------------- dlls/kernelbase/memory.c | 4 ++-- 2 files changed, 6 insertions(+), 16 deletions(-)
diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c index 883b75e5e39..61970d39cd8 100644 --- a/dlls/kernel32/tests/heap.c +++ b/dlls/kernel32/tests/heap.c @@ -1951,7 +1951,7 @@ static void test_GlobalAlloc(void)
tmp_mem = GlobalReAlloc( mem, 0, flags ); if (flags == GMEM_FIXED) - todo_wine ok( !tmp_mem, "GlobalReAlloc succeeded\n" ); + ok( !tmp_mem, "GlobalReAlloc succeeded\n" ); else if (!(flags & GMEM_MODIFY) && (flags & GMEM_DISCARDABLE)) ok( !tmp_mem, "GlobalReAlloc succeeded\n" ); else @@ -1963,13 +1963,11 @@ static void test_GlobalAlloc(void) expect_entry.ptr = NULL; } else if ((flags & GMEM_DISCARDABLE) && (flags & GMEM_MODIFY)) expect_entry.flags |= 4; - todo_wine_if(!flags) ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr ); - todo_wine_if(!flags) ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); size = GlobalSize( mem ); if (flags == GMEM_MOVEABLE) ok( size == 0, "GlobalSize returned %Iu\n", size ); - else todo_wine_if(!flags) ok( size == 12, "GlobalSize returned %Iu\n", size ); + else ok( size == 12, "GlobalSize returned %Iu\n", size );
mem = GlobalFree( mem ); ok( !mem, "GlobalFree failed, error %lu\n", GetLastError() ); @@ -2505,18 +2503,12 @@ static void test_LocalAlloc(void) if (flags & LMEM_MODIFY) ok( tmp_mem == mem, "LocalReAlloc returned %p, error %lu\n", tmp_mem, GetLastError() ); else - { - todo_wine_if(flags == LMEM_FIXED || flags == LMEM_MOVEABLE) ok( !tmp_mem, "LocalReAlloc succeeded\n" ); - } entry = *mem_entry_from_HANDLE( mem ); if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4; - todo_wine_if(flags == LMEM_FIXED || flags == LMEM_MOVEABLE) ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr ); - todo_wine_if(flags == LMEM_FIXED || flags == LMEM_MOVEABLE) ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); size = LocalSize( mem ); - todo_wine_if(flags == LMEM_FIXED || flags == LMEM_MOVEABLE) ok( size == 12, "LocalSize returned %Iu\n", size );
ret = LocalUnlock( mem ); @@ -2583,7 +2575,7 @@ static void test_LocalAlloc(void)
tmp_mem = LocalReAlloc( mem, 0, flags ); if (flags == LMEM_FIXED) - todo_wine ok( !tmp_mem, "LocalReAlloc succeeded\n" ); + ok( !tmp_mem, "LocalReAlloc succeeded\n" ); else if (!(flags & LMEM_MODIFY) && (flags & LMEM_DISCARDABLE)) ok( !tmp_mem, "LocalReAlloc succeeded\n" ); else @@ -2595,13 +2587,11 @@ static void test_LocalAlloc(void) expect_entry.ptr = NULL; } else if ((flags & LMEM_DISCARDABLE) && (flags & LMEM_MODIFY)) expect_entry.flags |= 4; - todo_wine_if(!flags) ok( entry.ptr == expect_entry.ptr, "got ptr %p was %p\n", entry.ptr, expect_entry.ptr ); - todo_wine_if(!flags) ok( entry.flags == expect_entry.flags, "got flags %#Ix was %#Ix\n", entry.flags, expect_entry.flags ); size = LocalSize( mem ); if (flags == LMEM_MOVEABLE) ok( size == 0, "LocalSize returned %Iu\n", size ); - else todo_wine_if(!(flags & (LMEM_MODIFY | LMEM_DISCARDABLE))) ok( size == 12, "LocalSize returned %Iu\n", size ); + else ok( size == 12, "LocalSize returned %Iu\n", size );
mem = LocalFree( mem ); ok( !mem, "LocalFree failed, error %lu\n", GetLastError() ); diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c index baf17c075b4..df7c07c2700 100644 --- a/dlls/kernelbase/memory.c +++ b/dlls/kernelbase/memory.c @@ -1024,14 +1024,14 @@ HLOCAL WINAPI DECLSPEC_HOTPATCH LocalReAlloc( HLOCAL handle, SIZE_T size, UINT f ret = handle; } } - else + else if ((flags & LMEM_MOVEABLE) && !mem->lock) { HeapFree( heap, heap_flags, mem->ptr ); mem->flags |= MEM_FLAG_DISCARDED; - mem->lock = 0; mem->ptr = NULL; ret = handle; } + else SetLastError( ERROR_INVALID_PARAMETER ); } } else SetLastError( ERROR_INVALID_HANDLE );
v2: Keep the broken test results, they are indeed sometimes broken on Windows.
This merge request was approved by Esme Povirk.
Note that I'm only looking at the ole32 part, I haven't reviewed the full MR.