[PATCH 4/5] kernelbase: Cleanup and simplify LocalReAlloc.
Rémi Bernon
wine at gitlab.winehq.org
Tue Jun 7 13:33:43 CDT 2022
From: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
dlls/kernel32/heap.c | 2 +
dlls/kernel32/tests/heap.c | 11 ----
dlls/kernelbase/memory.c | 111 ++++++++++++++-----------------------
3 files changed, 45 insertions(+), 79 deletions(-)
diff --git a/dlls/kernel32/heap.c b/dlls/kernel32/heap.c
index df094c94257..6a1a02c814b 100644
--- a/dlls/kernel32/heap.c
+++ b/dlls/kernel32/heap.c
@@ -315,6 +315,8 @@ HGLOBAL WINAPI GlobalHandle( const void *ptr )
*/
HGLOBAL WINAPI GlobalReAlloc( HGLOBAL handle, SIZE_T size, UINT flags )
{
+ struct mem_entry *mem;
+ if ((mem = unsafe_mem_from_HLOCAL( handle )) && mem->lock) return 0;
return LocalReAlloc( handle, size, flags );
}
diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c
index 97f4d9c9fe3..c237d515648 100644
--- a/dlls/kernel32/tests/heap.c
+++ b/dlls/kernel32/tests/heap.c
@@ -1635,9 +1635,7 @@ static void test_GlobalAlloc(void)
mem = GlobalAlloc( GMEM_FIXED, 10 );
ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
tmp_mem = GlobalReAlloc( mem, 9, GMEM_MODIFY );
- todo_wine
ok( !!tmp_mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
- todo_wine
ok( tmp_mem == mem, "got ptr %p, expected %p\n", tmp_mem, mem );
size = GlobalSize( mem );
ok( size == 10, "GlobalSize returned %Iu\n", size );
@@ -1651,9 +1649,7 @@ static void test_GlobalAlloc(void)
"got error %lu\n", GetLastError() );
if (tmp_mem) mem = tmp_mem;
tmp_mem = GlobalReAlloc( mem, 1024 * 1024, GMEM_MODIFY );
- todo_wine
ok( !!tmp_mem, "GlobalAlloc failed, error %lu\n", GetLastError() );
- todo_wine
ok( tmp_mem == mem, "got ptr %p, expected %p\n", tmp_mem, mem );
size = GlobalSize( mem );
ok( size == 10, "GlobalSize returned %Iu\n", size );
@@ -1988,9 +1984,7 @@ static void test_LocalAlloc(void)
mem = LocalAlloc( LMEM_FIXED, 10 );
ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() );
tmp_mem = LocalReAlloc( mem, 9, LMEM_MODIFY );
- todo_wine
ok( !!tmp_mem, "LocalAlloc failed, error %lu\n", GetLastError() );
- todo_wine
ok( tmp_mem == mem, "got ptr %p, expected %p\n", tmp_mem, mem );
size = LocalSize( mem );
ok( size == 10, "LocalSize returned %Iu\n", size );
@@ -2004,9 +1998,7 @@ static void test_LocalAlloc(void)
"got error %lu\n", GetLastError() );
if (tmp_mem) mem = tmp_mem;
tmp_mem = LocalReAlloc( mem, 1024 * 1024, LMEM_MODIFY );
- todo_wine
ok( !!tmp_mem, "LocalAlloc failed, error %lu\n", GetLastError() );
- todo_wine
ok( tmp_mem == mem, "got ptr %p, expected %p\n", tmp_mem, mem );
size = LocalSize( mem );
ok( size == 10, "LocalSize returned %Iu\n", size );
@@ -2105,13 +2097,10 @@ static void test_LocalAlloc(void)
tmp_mem = LocalHandle( ptr );
ok( tmp_mem == mem, "LocalHandle returned unexpected handle\n" );
tmp_mem = LocalDiscard( mem );
- todo_wine
ok( !!tmp_mem, "LocalDiscard failed, error %lu\n", GetLastError() );
- todo_wine
ok( tmp_mem == mem, "LocalDiscard returned unexpected handle\n" );
ret = LocalUnlock( mem );
ok( !ret, "LocalUnlock succeeded, error %lu\n", GetLastError() );
- todo_wine
ok( GetLastError() == ERROR_NOT_LOCKED, "got error %lu\n", GetLastError() );
tmp_mem = LocalDiscard( mem );
diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c
index 776f0aafa18..341b859b555 100644
--- a/dlls/kernelbase/memory.c
+++ b/dlls/kernelbase/memory.c
@@ -868,6 +868,7 @@ HLOCAL WINAPI DECLSPEC_HOTPATCH LocalAlloc( UINT flags, SIZE_T size )
if (!size) mem->flags |= MEM_FLAG_DISCARDED;
else
{
+ if (size + HLOCAL_STORAGE < size) goto failed;
if (!(ptr = HeapAlloc( heap, heap_flags, size + HLOCAL_STORAGE ))) goto failed;
*(HLOCAL *)ptr = handle;
mem->ptr = (char *)ptr + HLOCAL_STORAGE;
@@ -967,7 +968,8 @@ LPVOID WINAPI DECLSPEC_HOTPATCH LocalLock( HLOCAL handle )
*/
HLOCAL WINAPI DECLSPEC_HOTPATCH LocalReAlloc( HLOCAL handle, SIZE_T size, UINT flags )
{
- DWORD heap_flags = HEAP_ADD_USER_INFO;
+ DWORD heap_flags = HEAP_ADD_USER_INFO | HEAP_NO_SERIALIZE;
+ HANDLE heap = GetProcessHeap();
struct mem_entry *mem;
HLOCAL ret = 0;
void *ptr;
@@ -976,90 +978,63 @@ HLOCAL WINAPI DECLSPEC_HOTPATCH LocalReAlloc( HLOCAL handle, SIZE_T size, UINT f
if (flags & LMEM_ZEROINIT) heap_flags |= HEAP_ZERO_MEMORY;
- RtlLockHeap( GetProcessHeap() );
- if (flags & LMEM_MODIFY) /* modify flags */
+ RtlLockHeap( heap );
+ if ((ptr = unsafe_ptr_from_HLOCAL( handle )))
{
- if (unsafe_ptr_from_HLOCAL( handle ) && (flags & LMEM_MOVEABLE))
+ if (!(flags & LMEM_MOVEABLE))
{
- /* make a fixed block moveable
- * actually only NT is able to do this. But it's soo simple
- */
- if (handle == 0)
- {
- WARN_(globalmem)( "null handle\n" );
- SetLastError( ERROR_NOACCESS );
- }
- else
- {
- size = RtlSizeHeap( GetProcessHeap(), 0, handle );
- ret = LocalAlloc( flags, size );
- ptr = LocalLock( ret );
- memcpy( ptr, handle, size );
- LocalUnlock( ret );
- LocalFree( handle );
- }
+ heap_flags |= HEAP_REALLOC_IN_PLACE_ONLY;
+ if (!(flags & LMEM_MODIFY) || !(flags & LMEM_MOVEABLE)) ret = handle;
+ else ret = HeapReAlloc( heap, heap_flags, ptr, size );
}
- else if ((mem = unsafe_mem_from_HLOCAL( handle )) && (flags & LMEM_DISCARDABLE))
+ else if (flags & LMEM_MODIFY)
{
- /* change the flags to make our block "discardable" */
- mem->flags |= LMEM_DISCARDABLE >> 8;
- ret = handle;
+ size = RtlSizeHeap( heap, 0, handle );
+ ret = LocalAlloc( flags, size );
+ ptr = LocalLock( ret );
+ memcpy( ptr, handle, size );
+ LocalUnlock( ret );
+ LocalFree( handle );
}
- else SetLastError( ERROR_INVALID_PARAMETER );
+ else ret = HeapReAlloc( heap, heap_flags, handle, size );
}
- else
+ else if ((mem = unsafe_mem_from_HLOCAL( handle )))
{
- if ((ptr = unsafe_ptr_from_HLOCAL( handle )))
+ if (!(flags & LMEM_MODIFY))
{
- /* reallocate fixed memory */
- if (!(flags & LMEM_MOVEABLE)) heap_flags |= HEAP_REALLOC_IN_PLACE_ONLY;
- ret = HeapReAlloc( GetProcessHeap(), heap_flags, ptr, size );
- }
- else if ((mem = unsafe_mem_from_HLOCAL( handle )))
- {
- /* reallocate a moveable block */
- if (size != 0)
+ if (size)
{
- if (size <= INT_MAX - HLOCAL_STORAGE)
+ if (size + HLOCAL_STORAGE < size) ptr = NULL;
+ else if (!mem->ptr) ptr = HeapAlloc( heap, heap_flags, size + HLOCAL_STORAGE );
+ else ptr = HeapReAlloc( heap, heap_flags, (char *)mem->ptr - HLOCAL_STORAGE, size + HLOCAL_STORAGE );
+
+ if (!ptr) SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+ else
{
- if (mem->ptr)
- {
- if ((ptr = HeapReAlloc( GetProcessHeap(), heap_flags, (char *)mem->ptr - HLOCAL_STORAGE,
- size + HLOCAL_STORAGE )))
- {
- mem->ptr = (char *)ptr + HLOCAL_STORAGE;
- ret = handle;
- }
- }
- else
- {
- if ((ptr = HeapAlloc( GetProcessHeap(), heap_flags, size + HLOCAL_STORAGE )))
- {
- *(HLOCAL *)ptr = handle;
- mem->ptr = (char *)ptr + HLOCAL_STORAGE;
- ret = handle;
- }
- }
+ mem->flags &= ~MEM_FLAG_DISCARDED;
+ mem->ptr = (char *)ptr + HLOCAL_STORAGE;
+ ret = handle;
}
- else SetLastError( ERROR_OUTOFMEMORY );
}
else
{
- if (mem->lock == 0)
- {
- if (mem->ptr)
- {
- HeapFree( GetProcessHeap(), 0, (char *)mem->ptr - HLOCAL_STORAGE );
- mem->ptr = NULL;
- }
- ret = handle;
- }
- else WARN_(globalmem)( "not freeing memory associated with locked handle\n" );
+ if (mem->ptr) HeapFree( heap, heap_flags, (char *)mem->ptr - HLOCAL_STORAGE );
+ mem->flags |= MEM_FLAG_DISCARDED;
+ mem->lock = 0;
+ mem->ptr = NULL;
+ ret = handle;
}
}
- else SetLastError( ERROR_INVALID_HANDLE );
+ else if (flags & LMEM_DISCARDABLE)
+ {
+ mem->flags |= MEM_FLAG_DISCARDABLE;
+ ret = handle;
+ }
+ else SetLastError( ERROR_INVALID_PARAMETER );
}
- RtlUnlockHeap( GetProcessHeap() );
+ else SetLastError( ERROR_INVALID_HANDLE );
+ RtlUnlockHeap( heap );
+
return ret;
}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/201
More information about the wine-devel
mailing list