Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
My intent is to cleanup these functions to then re-implement them using a static handle table, shared between kernelbase and kernel32 through KernelBaseGetGlobalData(), as native does it (although we don't need the global data structure to be necessarily compatible).
The idea, is ultimately to have these functions a bit more robust, less dependent on exception handlers and heap pointers validation, and less dependent on the heap implementation itself. Native doesn't seem to be actually catching exceptions and it's possible to get crashes with bad pointer values.
dlls/kernel32/heap.c | 163 +++++++++++++++++++++---------------------- 1 file changed, 81 insertions(+), 82 deletions(-)
diff --git a/dlls/kernel32/heap.c b/dlls/kernel32/heap.c index 8e767d03211..7e366eb991e 100644 --- a/dlls/kernel32/heap.c +++ b/dlls/kernel32/heap.c @@ -231,11 +231,10 @@ BOOL WINAPI GlobalUnlock(HGLOBAL hmem) * Handle: Success * NULL: Failure */ -HGLOBAL WINAPI GlobalHandle( - LPCVOID pmem /* [in] Pointer to global memory block */ -) { +HGLOBAL WINAPI GlobalHandle( LPCVOID pmem ) +{ HGLOBAL handle; - PGLOBAL32_INTERN maybe_intern; + PGLOBAL32_INTERN maybe_intern; LPCVOID test;
if (!pmem) @@ -244,7 +243,7 @@ HGLOBAL WINAPI GlobalHandle( return 0; }
- RtlLockHeap(GetProcessHeap()); + RtlLockHeap( GetProcessHeap() ); __TRY { handle = 0; @@ -252,22 +251,25 @@ HGLOBAL WINAPI GlobalHandle( /* note that if pmem is a pointer to a block allocated by */ /* GlobalAlloc with GMEM_MOVEABLE then magic test in HeapValidate */ /* will fail. */ - if (ISPOINTER(pmem)) { - if (HeapValidate( GetProcessHeap(), HEAP_NO_SERIALIZE, pmem )) { - handle = (HGLOBAL)pmem; /* valid fixed block */ + if (ISPOINTER( pmem )) + { + if (HeapValidate( GetProcessHeap(), HEAP_NO_SERIALIZE, pmem )) + { + handle = (HGLOBAL)pmem; /* valid fixed block */ break; } - handle = POINTER_TO_HANDLE(pmem); - } else - handle = (HGLOBAL)pmem; + handle = POINTER_TO_HANDLE( pmem ); + } + else handle = (HGLOBAL)pmem;
/* Now test handle either passed in or retrieved from pointer */ maybe_intern = HANDLE_TO_INTERN( handle ); - if (maybe_intern->Magic == MAGIC_GLOBAL_USED) { + if (maybe_intern->Magic == MAGIC_GLOBAL_USED) + { test = maybe_intern->Pointer; if (HeapValidate( GetProcessHeap(), HEAP_NO_SERIALIZE, (const char *)test - HGLOBAL_STORAGE ) && /* obj(-handle) valid arena? */ - HeapValidate( GetProcessHeap(), HEAP_NO_SERIALIZE, maybe_intern )) /* intern valid arena? */ - break; /* valid moveable block */ + HeapValidate( GetProcessHeap(), HEAP_NO_SERIALIZE, maybe_intern )) /* intern valid arena? */ + break; /* valid moveable block */ } handle = 0; SetLastError( ERROR_INVALID_HANDLE ); @@ -278,12 +280,11 @@ HGLOBAL WINAPI GlobalHandle( handle = 0; } __ENDTRY - RtlUnlockHeap(GetProcessHeap()); + RtlUnlockHeap( GetProcessHeap() );
return handle; }
- /*********************************************************************** * GlobalReAlloc (KERNEL32.@) * @@ -317,50 +318,49 @@ HGLOBAL WINAPI GlobalReAlloc( HGLOBAL hmem, SIZE_T size, UINT flags ) */ SIZE_T WINAPI GlobalSize(HGLOBAL hmem) { - SIZE_T retval; - PGLOBAL32_INTERN pintern; + SIZE_T retval; + PGLOBAL32_INTERN pintern;
- if (!((ULONG_PTR)hmem >> 16)) - { - SetLastError(ERROR_INVALID_HANDLE); - return 0; - } + if (!((ULONG_PTR)hmem >> 16)) + { + SetLastError( ERROR_INVALID_HANDLE ); + return 0; + }
- if(ISPOINTER(hmem)) - { - retval=HeapSize(GetProcessHeap(), 0, hmem); + if (ISPOINTER( hmem )) + { + retval = HeapSize( GetProcessHeap(), 0, hmem ); + if (retval == ~(SIZE_T)0) /* It might be a GMEM_MOVEABLE data pointer */ + { + retval = HeapSize( GetProcessHeap(), 0, (char *)hmem - HGLOBAL_STORAGE ); + if (retval != ~(SIZE_T)0) retval -= HGLOBAL_STORAGE; + } + } + else + { + RtlLockHeap( GetProcessHeap() ); + pintern = HANDLE_TO_INTERN( hmem );
- if (retval == ~(SIZE_T)0) /* It might be a GMEM_MOVEABLE data pointer */ - { - retval = HeapSize(GetProcessHeap(), 0, (char*)hmem - HGLOBAL_STORAGE); - if (retval != ~(SIZE_T)0) retval -= HGLOBAL_STORAGE; - } - } - else - { - RtlLockHeap(GetProcessHeap()); - pintern=HANDLE_TO_INTERN(hmem); - - if(pintern->Magic==MAGIC_GLOBAL_USED) - { - if (!pintern->Pointer) /* handle case of GlobalAlloc( ??,0) */ - retval = 0; - else - { - retval = HeapSize(GetProcessHeap(), 0, (char *)pintern->Pointer - HGLOBAL_STORAGE ); - if (retval != ~(SIZE_T)0) retval -= HGLOBAL_STORAGE; - } - } - else - { - WARN("invalid handle %p (Magic: 0x%04x)\n", hmem, pintern->Magic); - SetLastError(ERROR_INVALID_HANDLE); - retval=0; - } - RtlUnlockHeap(GetProcessHeap()); - } - if (retval == ~(SIZE_T)0) retval = 0; - return retval; + if (pintern->Magic == MAGIC_GLOBAL_USED) + { + if (!pintern->Pointer) /* handle case of GlobalAlloc( ??,0) */ + retval = 0; + else + { + retval = HeapSize( GetProcessHeap(), 0, (char *)pintern->Pointer - HGLOBAL_STORAGE ); + if (retval != ~(SIZE_T)0) retval -= HGLOBAL_STORAGE; + } + } + else + { + WARN( "invalid handle %p (Magic: 0x%04x)\n", hmem, pintern->Magic ); + SetLastError( ERROR_INVALID_HANDLE ); + retval = 0; + } + RtlUnlockHeap( GetProcessHeap() ); + } + if (retval == ~(SIZE_T)0) retval = 0; + return retval; }
@@ -415,32 +415,31 @@ VOID WINAPI GlobalUnfix(HGLOBAL hmem) */ UINT WINAPI GlobalFlags(HGLOBAL hmem) { - DWORD retval; - PGLOBAL32_INTERN pintern; + DWORD retval; + PGLOBAL32_INTERN pintern;
- if(ISPOINTER(hmem)) - { - retval=0; - } - else - { - RtlLockHeap(GetProcessHeap()); - pintern=HANDLE_TO_INTERN(hmem); - if(pintern->Magic==MAGIC_GLOBAL_USED) - { - retval=pintern->LockCount + (pintern->Flags<<8); - if(pintern->Pointer==0) - retval|= GMEM_DISCARDED; - } - else - { - WARN("invalid handle %p (Magic: 0x%04x)\n", hmem, pintern->Magic); - SetLastError(ERROR_INVALID_HANDLE); - retval = GMEM_INVALID_HANDLE; - } - RtlUnlockHeap(GetProcessHeap()); - } - return retval; + if (ISPOINTER( hmem )) + { + retval = 0; + } + else + { + RtlLockHeap( GetProcessHeap() ); + pintern = HANDLE_TO_INTERN( hmem ); + if (pintern->Magic == MAGIC_GLOBAL_USED) + { + retval = pintern->LockCount + (pintern->Flags << 8); + if (pintern->Pointer == 0) retval |= GMEM_DISCARDED; + } + else + { + WARN( "invalid handle %p (Magic: 0x%04x)\n", hmem, pintern->Magic ); + SetLastError( ERROR_INVALID_HANDLE ); + retval = GMEM_INVALID_HANDLE; + } + RtlUnlockHeap( GetProcessHeap() ); + } + return retval; }
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/kernel32/heap.c | 111 ++++++++++++++++++++++--------------------- 1 file changed, 58 insertions(+), 53 deletions(-)
diff --git a/dlls/kernel32/heap.c b/dlls/kernel32/heap.c index 7e366eb991e..fefb88d6857 100644 --- a/dlls/kernel32/heap.c +++ b/dlls/kernel32/heap.c @@ -183,7 +183,7 @@ typedef struct __GLOBAL32_INTERN * Lock a global memory object and return a pointer to first byte of the memory * * PARAMS - * hmem [I] Handle of the global memory object + * handle [I] Handle of the global memory object * * RETURNS * Success: Pointer to first byte of the memory block @@ -193,9 +193,9 @@ typedef struct __GLOBAL32_INTERN * When the handle is invalid, last error is set to ERROR_INVALID_HANDLE * */ -LPVOID WINAPI GlobalLock(HGLOBAL hmem) +void *WINAPI GlobalLock( HGLOBAL handle ) { - return LocalLock( hmem ); + return LocalLock( handle ); }
@@ -205,7 +205,7 @@ LPVOID WINAPI GlobalLock(HGLOBAL hmem) * Unlock a global memory object. * * PARAMS - * hmem [I] Handle of the global memory object + * handle [I] Handle of the global memory object * * RETURNS * Success: Object is still locked @@ -215,10 +215,10 @@ LPVOID WINAPI GlobalLock(HGLOBAL hmem) * When the handle is invalid, last error is set to ERROR_INVALID_HANDLE * */ -BOOL WINAPI GlobalUnlock(HGLOBAL hmem) +BOOL WINAPI GlobalUnlock( HGLOBAL handle ) { - if (ISPOINTER( hmem )) return TRUE; - return LocalUnlock( hmem ); + if (ISPOINTER( handle )) return TRUE; + return LocalUnlock( handle ); }
@@ -231,13 +231,15 @@ BOOL WINAPI GlobalUnlock(HGLOBAL hmem) * Handle: Success * NULL: Failure */ -HGLOBAL WINAPI GlobalHandle( LPCVOID pmem ) +HGLOBAL WINAPI GlobalHandle( const void *ptr ) { + PGLOBAL32_INTERN mem; HGLOBAL handle; - PGLOBAL32_INTERN maybe_intern; LPCVOID test;
- if (!pmem) + TRACE_(globalmem)( "ptr %p\n", ptr ); + + if (!ptr) { SetLastError( ERROR_INVALID_PARAMETER ); return 0; @@ -248,27 +250,27 @@ HGLOBAL WINAPI GlobalHandle( LPCVOID pmem ) { handle = 0;
- /* note that if pmem is a pointer to a block allocated by */ + /* note that if ptr is a pointer to a block allocated by */ /* GlobalAlloc with GMEM_MOVEABLE then magic test in HeapValidate */ /* will fail. */ - if (ISPOINTER( pmem )) + if (ISPOINTER( ptr )) { - if (HeapValidate( GetProcessHeap(), HEAP_NO_SERIALIZE, pmem )) + if (HeapValidate( GetProcessHeap(), HEAP_NO_SERIALIZE, ptr )) { - handle = (HGLOBAL)pmem; /* valid fixed block */ + handle = (HGLOBAL)ptr; /* valid fixed block */ break; } - handle = POINTER_TO_HANDLE( pmem ); + handle = POINTER_TO_HANDLE( ptr ); } - else handle = (HGLOBAL)pmem; + else handle = (HGLOBAL)ptr;
/* Now test handle either passed in or retrieved from pointer */ - maybe_intern = HANDLE_TO_INTERN( handle ); - if (maybe_intern->Magic == MAGIC_GLOBAL_USED) + mem = HANDLE_TO_INTERN( handle ); + if (mem->Magic == MAGIC_GLOBAL_USED) { - test = maybe_intern->Pointer; + test = mem->Pointer; if (HeapValidate( GetProcessHeap(), HEAP_NO_SERIALIZE, (const char *)test - HGLOBAL_STORAGE ) && /* obj(-handle) valid arena? */ - HeapValidate( GetProcessHeap(), HEAP_NO_SERIALIZE, maybe_intern )) /* intern valid arena? */ + HeapValidate( GetProcessHeap(), HEAP_NO_SERIALIZE, mem )) /* intern valid arena? */ break; /* valid moveable block */ } handle = 0; @@ -294,9 +296,9 @@ HGLOBAL WINAPI GlobalHandle( LPCVOID pmem ) * Handle: Success * NULL: Failure */ -HGLOBAL WINAPI GlobalReAlloc( HGLOBAL hmem, SIZE_T size, UINT flags ) +HGLOBAL WINAPI GlobalReAlloc( HGLOBAL handle, SIZE_T size, UINT flags ) { - return LocalReAlloc( hmem, size, flags ); + return LocalReAlloc( handle, size, flags ); }
@@ -306,7 +308,7 @@ HGLOBAL WINAPI GlobalReAlloc( HGLOBAL hmem, SIZE_T size, UINT flags ) * Get the size of a global memory object. * * PARAMS - * hmem [I] Handle of the global memory object + * handle [I] Handle of the global memory object * * RETURNS * Failure: 0 @@ -316,44 +318,45 @@ HGLOBAL WINAPI GlobalReAlloc( HGLOBAL hmem, SIZE_T size, UINT flags ) * When the handle is invalid, last error is set to ERROR_INVALID_HANDLE * */ -SIZE_T WINAPI GlobalSize(HGLOBAL hmem) +SIZE_T WINAPI GlobalSize( HGLOBAL handle ) { + PGLOBAL32_INTERN mem; SIZE_T retval; - PGLOBAL32_INTERN pintern;
- if (!((ULONG_PTR)hmem >> 16)) + TRACE_(globalmem)( "handle %p\n", handle ); + + if (!((ULONG_PTR)handle >> 16)) { SetLastError( ERROR_INVALID_HANDLE ); return 0; }
- if (ISPOINTER( hmem )) + if (ISPOINTER( handle )) { - retval = HeapSize( GetProcessHeap(), 0, hmem ); + retval = HeapSize( GetProcessHeap(), 0, handle ); if (retval == ~(SIZE_T)0) /* It might be a GMEM_MOVEABLE data pointer */ { - retval = HeapSize( GetProcessHeap(), 0, (char *)hmem - HGLOBAL_STORAGE ); + retval = HeapSize( GetProcessHeap(), 0, (char *)handle - HGLOBAL_STORAGE ); if (retval != ~(SIZE_T)0) retval -= HGLOBAL_STORAGE; } } else { RtlLockHeap( GetProcessHeap() ); - pintern = HANDLE_TO_INTERN( hmem ); - - if (pintern->Magic == MAGIC_GLOBAL_USED) + mem = HANDLE_TO_INTERN( handle ); + if (mem->Magic == MAGIC_GLOBAL_USED) { - if (!pintern->Pointer) /* handle case of GlobalAlloc( ??,0) */ + if (!mem->Pointer) /* handle case of GlobalAlloc( ??,0) */ retval = 0; else { - retval = HeapSize( GetProcessHeap(), 0, (char *)pintern->Pointer - HGLOBAL_STORAGE ); + retval = HeapSize( GetProcessHeap(), 0, (char *)mem->Pointer - HGLOBAL_STORAGE ); if (retval != ~(SIZE_T)0) retval -= HGLOBAL_STORAGE; } } else { - WARN( "invalid handle %p (Magic: 0x%04x)\n", hmem, pintern->Magic ); + WARN_(globalmem)( "invalid handle %p\n", handle ); SetLastError( ERROR_INVALID_HANDLE ); retval = 0; } @@ -367,36 +370,36 @@ SIZE_T WINAPI GlobalSize(HGLOBAL hmem) /*********************************************************************** * GlobalWire (KERNEL32.@) */ -LPVOID WINAPI GlobalWire(HGLOBAL hmem) +void *WINAPI GlobalWire( HGLOBAL handle ) { - return GlobalLock( hmem ); + return GlobalLock( handle ); }
/*********************************************************************** * GlobalUnWire (KERNEL32.@) */ -BOOL WINAPI GlobalUnWire(HGLOBAL hmem) +BOOL WINAPI GlobalUnWire( HGLOBAL handle ) { - return GlobalUnlock( hmem); + return GlobalUnlock( handle ); }
/*********************************************************************** * GlobalFix (KERNEL32.@) */ -VOID WINAPI GlobalFix(HGLOBAL hmem) +VOID WINAPI GlobalFix( HGLOBAL handle ) { - GlobalLock( hmem ); + GlobalLock( handle ); }
/*********************************************************************** * GlobalUnfix (KERNEL32.@) */ -VOID WINAPI GlobalUnfix(HGLOBAL hmem) +VOID WINAPI GlobalUnfix( HGLOBAL handle ) { - GlobalUnlock( hmem); + GlobalUnlock( handle ); }
@@ -406,34 +409,36 @@ VOID WINAPI GlobalUnfix(HGLOBAL hmem) * Get information about a global memory object. * * PARAMS - * hmem [I] Handle of the global memory object + * handle [I] Handle of the global memory object * * RETURNS - * Failure: GMEM_INVALID_HANDLE, when the provided handle is invalid + * Failure: GMEM_INVALID_HANDLE, when the provided handle is invalid * Success: Value specifying allocation flags and lock count * */ -UINT WINAPI GlobalFlags(HGLOBAL hmem) +UINT WINAPI GlobalFlags( HGLOBAL handle ) { + PGLOBAL32_INTERN mem; DWORD retval; - PGLOBAL32_INTERN pintern;
- if (ISPOINTER( hmem )) + TRACE_(globalmem)( "handle %p\n", handle ); + + if (ISPOINTER( handle )) { retval = 0; } else { RtlLockHeap( GetProcessHeap() ); - pintern = HANDLE_TO_INTERN( hmem ); - if (pintern->Magic == MAGIC_GLOBAL_USED) + mem = HANDLE_TO_INTERN( handle ); + if (mem->Magic == MAGIC_GLOBAL_USED) { - retval = pintern->LockCount + (pintern->Flags << 8); - if (pintern->Pointer == 0) retval |= GMEM_DISCARDED; + retval = mem->LockCount + (mem->Flags << 8); + if (mem->Pointer == 0) retval |= GMEM_DISCARDED; } else { - WARN( "invalid handle %p (Magic: 0x%04x)\n", hmem, pintern->Magic ); + WARN_(globalmem)( "invalid handle %p\n", handle ); SetLastError( ERROR_INVALID_HANDLE ); retval = GMEM_INVALID_HANDLE; }
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/kernelbase/memory.c | 181 +++++++++++++++++++-------------------- 1 file changed, 90 insertions(+), 91 deletions(-)
diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c index 42ffd1bcdd9..8c818f33ca6 100644 --- a/dlls/kernelbase/memory.c +++ b/dlls/kernelbase/memory.c @@ -791,98 +791,97 @@ LPVOID WINAPI DECLSPEC_HOTPATCH LocalLock( HLOCAL hmem ) */ HLOCAL WINAPI DECLSPEC_HOTPATCH LocalReAlloc( HLOCAL hmem, SIZE_T size, UINT flags ) { - struct local_header *header; - void *ptr; - HLOCAL ret = 0; - DWORD heap_flags = (flags & LMEM_ZEROINIT) ? HEAP_ZERO_MEMORY : 0; + struct local_header *header; + void *ptr; + HLOCAL ret = 0; + DWORD heap_flags = (flags & LMEM_ZEROINIT) ? HEAP_ZERO_MEMORY : 0;
- RtlLockHeap( GetProcessHeap() ); - if (flags & LMEM_MODIFY) /* modify flags */ - { - if (is_pointer( hmem ) && (flags & LMEM_MOVEABLE)) - { - /* make a fixed block moveable - * actually only NT is able to do this. But it's soo simple - */ - if (hmem == 0) - { - WARN( "null handle\n"); - SetLastError( ERROR_NOACCESS ); - } - else - { - size = RtlSizeHeap( GetProcessHeap(), 0, hmem ); - ret = LocalAlloc( flags, size ); - ptr = LocalLock( ret ); - memcpy( ptr, hmem, size ); - LocalUnlock( ret ); - LocalFree( hmem ); - } - } - else if (!is_pointer( hmem ) && (flags & LMEM_DISCARDABLE)) - { - /* change the flags to make our block "discardable" */ - header = get_header( hmem ); - header->flags |= LMEM_DISCARDABLE >> 8; - ret = hmem; - } - else SetLastError( ERROR_INVALID_PARAMETER ); - } - else - { - if (is_pointer( hmem )) - { - /* reallocate fixed memory */ - if (!(flags & LMEM_MOVEABLE)) heap_flags |= HEAP_REALLOC_IN_PLACE_ONLY; - ret = HeapReAlloc( GetProcessHeap(), heap_flags, hmem, size ); - } - else - { - /* reallocate a moveable block */ - header = get_header( hmem ); - if (size != 0) - { - if (size <= INT_MAX - HLOCAL_STORAGE) - { - if (header->ptr) - { - if ((ptr = HeapReAlloc( GetProcessHeap(), heap_flags, - (char *)header->ptr - HLOCAL_STORAGE, - size + HLOCAL_STORAGE ))) - { - header->ptr = (char *)ptr + HLOCAL_STORAGE; - ret = hmem; - } - } - else - { - if ((ptr = HeapAlloc( GetProcessHeap(), heap_flags, size + HLOCAL_STORAGE ))) - { - *(HLOCAL *)ptr = hmem; - header->ptr = (char *)ptr + HLOCAL_STORAGE; - ret = hmem; - } - } - } - else SetLastError( ERROR_OUTOFMEMORY ); - } - else - { - if (header->lock == 0) - { - if (header->ptr) - { - HeapFree( GetProcessHeap(), 0, (char *)header->ptr - HLOCAL_STORAGE ); - header->ptr = NULL; - } - ret = hmem; - } - else WARN( "not freeing memory associated with locked handle\n" ); - } - } - } - RtlUnlockHeap( GetProcessHeap() ); - return ret; + RtlLockHeap( GetProcessHeap() ); + if (flags & LMEM_MODIFY) /* modify flags */ + { + if (is_pointer( hmem ) && (flags & LMEM_MOVEABLE)) + { + /* make a fixed block moveable + * actually only NT is able to do this. But it's soo simple + */ + if (hmem == 0) + { + WARN( "null handle\n" ); + SetLastError( ERROR_NOACCESS ); + } + else + { + size = RtlSizeHeap( GetProcessHeap(), 0, hmem ); + ret = LocalAlloc( flags, size ); + ptr = LocalLock( ret ); + memcpy( ptr, hmem, size ); + LocalUnlock( ret ); + LocalFree( hmem ); + } + } + else if (!is_pointer( hmem ) && (flags & LMEM_DISCARDABLE)) + { + /* change the flags to make our block "discardable" */ + header = get_header( hmem ); + header->flags |= LMEM_DISCARDABLE >> 8; + ret = hmem; + } + else SetLastError( ERROR_INVALID_PARAMETER ); + } + else + { + if (is_pointer( hmem )) + { + /* reallocate fixed memory */ + if (!(flags & LMEM_MOVEABLE)) heap_flags |= HEAP_REALLOC_IN_PLACE_ONLY; + ret = HeapReAlloc( GetProcessHeap(), heap_flags, hmem, size ); + } + else + { + /* reallocate a moveable block */ + header = get_header( hmem ); + if (size != 0) + { + if (size <= INT_MAX - HLOCAL_STORAGE) + { + if (header->ptr) + { + if ((ptr = HeapReAlloc( GetProcessHeap(), heap_flags, (char *)header->ptr - HLOCAL_STORAGE, + size + HLOCAL_STORAGE ))) + { + header->ptr = (char *)ptr + HLOCAL_STORAGE; + ret = hmem; + } + } + else + { + if ((ptr = HeapAlloc( GetProcessHeap(), heap_flags, size + HLOCAL_STORAGE ))) + { + *(HLOCAL *)ptr = hmem; + header->ptr = (char *)ptr + HLOCAL_STORAGE; + ret = hmem; + } + } + } + else SetLastError( ERROR_OUTOFMEMORY ); + } + else + { + if (header->lock == 0) + { + if (header->ptr) + { + HeapFree( GetProcessHeap(), 0, (char *)header->ptr - HLOCAL_STORAGE ); + header->ptr = NULL; + } + ret = hmem; + } + else WARN( "not freeing memory associated with locked handle\n" ); + } + } + } + RtlUnlockHeap( GetProcessHeap() ); + return ret; }
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/kernelbase/memory.c | 185 ++++++++++++++++++++------------------- 1 file changed, 97 insertions(+), 88 deletions(-)
diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c index 8c818f33ca6..3cb596e5814 100644 --- a/dlls/kernelbase/memory.c +++ b/dlls/kernelbase/memory.c @@ -41,6 +41,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(heap); WINE_DECLARE_DEBUG_CHANNEL(virtual); +WINE_DECLARE_DEBUG_CHANNEL(globalmem);
/*********************************************************************** @@ -579,7 +580,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH HeapWalk( HANDLE heap, PROCESS_HEAP_ENTRY *entry )
#include "pshpack1.h"
-struct local_header +struct mem_entry { WORD magic; void *ptr; @@ -597,19 +598,19 @@ struct local_header * the output jpeg's > 1 MB if not */ #define HLOCAL_STORAGE (sizeof(HLOCAL) * 2)
-static inline struct local_header *get_header( HLOCAL hmem ) +static inline struct mem_entry *mem_from_HLOCAL( HLOCAL handle ) { - return (struct local_header *)((char *)hmem - 2); + return (struct mem_entry *)((char *)handle - 2); }
-static inline HLOCAL get_handle( struct local_header *header ) +static inline HLOCAL HLOCAL_from_mem( struct mem_entry *mem ) { - return &header->ptr; + return &mem->ptr; }
-static inline BOOL is_pointer( HLOCAL hmem ) +static inline BOOL is_pointer( HLOCAL handle ) { - return !((ULONG_PTR)hmem & 2); + return !((ULONG_PTR)handle & 2); }
/*********************************************************************** @@ -630,9 +631,9 @@ HGLOBAL WINAPI DECLSPEC_HOTPATCH GlobalAlloc( UINT flags, SIZE_T size ) /*********************************************************************** * GlobalFree (kernelbase.@) */ -HGLOBAL WINAPI DECLSPEC_HOTPATCH GlobalFree( HLOCAL hmem ) +HGLOBAL WINAPI DECLSPEC_HOTPATCH GlobalFree( HLOCAL handle ) { - return LocalFree( hmem ); + return LocalFree( handle ); }
@@ -641,16 +642,18 @@ HGLOBAL WINAPI DECLSPEC_HOTPATCH GlobalFree( HLOCAL hmem ) */ HLOCAL WINAPI DECLSPEC_HOTPATCH LocalAlloc( UINT flags, SIZE_T size ) { - struct local_header *header; + struct mem_entry *mem; DWORD heap_flags = 0; void *ptr;
+ TRACE_(globalmem)( "flags %#x, size %#Ix\n", flags, size ); + if (flags & LMEM_ZEROINIT) heap_flags = HEAP_ZERO_MEMORY;
if (!(flags & LMEM_MOVEABLE)) /* pointer */ { ptr = HeapAlloc( GetProcessHeap(), heap_flags, size ); - TRACE( "(flags=%04x) returning %p\n", flags, ptr ); + TRACE_(globalmem)( "return %p\n", ptr ); return ptr; }
@@ -659,77 +662,77 @@ HLOCAL WINAPI DECLSPEC_HOTPATCH LocalAlloc( UINT flags, SIZE_T size ) SetLastError( ERROR_OUTOFMEMORY ); return 0; } - if (!(header = HeapAlloc( GetProcessHeap(), 0, sizeof(*header) ))) return 0; + if (!(mem = HeapAlloc( GetProcessHeap(), 0, sizeof(*mem) ))) return 0;
- header->magic = MAGIC_LOCAL_USED; - header->flags = flags >> 8; - header->lock = 0; + mem->magic = MAGIC_LOCAL_USED; + mem->flags = flags >> 8; + mem->lock = 0;
if (size) { if (!(ptr = HeapAlloc(GetProcessHeap(), heap_flags, size + HLOCAL_STORAGE ))) { - HeapFree( GetProcessHeap(), 0, header ); + HeapFree( GetProcessHeap(), 0, mem ); return 0; } - *(HLOCAL *)ptr = get_handle( header ); - header->ptr = (char *)ptr + HLOCAL_STORAGE; + *(HLOCAL *)ptr = HLOCAL_from_mem( mem ); + mem->ptr = (char *)ptr + HLOCAL_STORAGE; } - else header->ptr = NULL; + else mem->ptr = NULL;
- TRACE( "(flags=%04x) returning handle %p pointer %p\n", - flags, get_handle( header ), header->ptr ); - return get_handle( header ); + TRACE_(globalmem)( "return handle %p, ptr %p\n", HLOCAL_from_mem( mem ), mem->ptr ); + return HLOCAL_from_mem( mem ); }
/*********************************************************************** * LocalFree (kernelbase.@) */ -HLOCAL WINAPI DECLSPEC_HOTPATCH LocalFree( HLOCAL hmem ) +HLOCAL WINAPI DECLSPEC_HOTPATCH LocalFree( HLOCAL handle ) { - struct local_header *header; + struct mem_entry *mem; HLOCAL ret;
+ TRACE_(globalmem)( "handle %p\n", handle ); + RtlLockHeap( GetProcessHeap() ); __TRY { ret = 0; - if (is_pointer(hmem)) /* POINTER */ + if (is_pointer( handle )) /* POINTER */ { - if (!HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE, hmem )) + if (!HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE, handle )) { SetLastError( ERROR_INVALID_HANDLE ); - ret = hmem; + ret = handle; } } else /* HANDLE */ { - header = get_header( hmem ); - if (header->magic == MAGIC_LOCAL_USED) + mem = mem_from_HLOCAL( handle ); + if (mem->magic == MAGIC_LOCAL_USED) { - header->magic = 0xdead; - if (header->ptr) + mem->magic = 0xdead; + if (mem->ptr) { - if (!HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE, - (char *)header->ptr - HLOCAL_STORAGE )) - ret = hmem; + if (!HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE, (char *)mem->ptr - HLOCAL_STORAGE )) + ret = handle; } - if (!HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE, header )) ret = hmem; + if (!HeapFree( GetProcessHeap(), HEAP_NO_SERIALIZE, mem )) ret = handle; } else { - WARN( "invalid handle %p (magic: 0x%04x)\n", hmem, header->magic ); + WARN_(globalmem)( "invalid handle %p\n", handle ); SetLastError( ERROR_INVALID_HANDLE ); - ret = hmem; + ret = handle; } } } __EXCEPT_PAGE_FAULT { - WARN( "invalid handle %p\n", hmem ); + WARN_(globalmem)( "invalid handle %p\n", handle ); SetLastError( ERROR_INVALID_HANDLE ); - ret = hmem; + ret = handle; } __ENDTRY RtlUnlockHeap( GetProcessHeap() ); @@ -740,15 +743,17 @@ HLOCAL WINAPI DECLSPEC_HOTPATCH LocalFree( HLOCAL hmem ) /*********************************************************************** * LocalLock (kernelbase.@) */ -LPVOID WINAPI DECLSPEC_HOTPATCH LocalLock( HLOCAL hmem ) +LPVOID WINAPI DECLSPEC_HOTPATCH LocalLock( HLOCAL handle ) { void *ret = NULL;
- if (is_pointer( hmem )) + TRACE_(globalmem)( "handle %p\n", handle ); + + if (is_pointer( handle )) { __TRY { - volatile char *p = hmem; + volatile char *p = handle; *p |= 0; } __EXCEPT_PAGE_FAULT @@ -756,28 +761,28 @@ LPVOID WINAPI DECLSPEC_HOTPATCH LocalLock( HLOCAL hmem ) return NULL; } __ENDTRY - return hmem; + return handle; }
RtlLockHeap( GetProcessHeap() ); __TRY { - struct local_header *header = get_header( hmem ); - if (header->magic == MAGIC_LOCAL_USED) + struct mem_entry *mem = mem_from_HLOCAL( handle ); + if (mem->magic == MAGIC_LOCAL_USED) { - ret = header->ptr; - if (!header->ptr) SetLastError( ERROR_DISCARDED ); - else if (header->lock < LMEM_LOCKCOUNT) header->lock++; + ret = mem->ptr; + if (!mem->ptr) SetLastError( ERROR_DISCARDED ); + else if (mem->lock < LMEM_LOCKCOUNT) mem->lock++; } else { - WARN( "invalid handle %p (magic: 0x%04x)\n", hmem, header->magic ); + WARN_(globalmem)( "invalid handle %p\n", handle ); SetLastError( ERROR_INVALID_HANDLE ); } } __EXCEPT_PAGE_FAULT { - WARN("(%p): Page fault occurred ! Caused by bug ?\n", hmem); + WARN_(globalmem)( "(%p): Page fault occurred ! Caused by bug ?\n", handle ); SetLastError( ERROR_INVALID_HANDLE ); } __ENDTRY @@ -789,77 +794,79 @@ LPVOID WINAPI DECLSPEC_HOTPATCH LocalLock( HLOCAL hmem ) /*********************************************************************** * LocalReAlloc (kernelbase.@) */ -HLOCAL WINAPI DECLSPEC_HOTPATCH LocalReAlloc( HLOCAL hmem, SIZE_T size, UINT flags ) +HLOCAL WINAPI DECLSPEC_HOTPATCH LocalReAlloc( HLOCAL handle, SIZE_T size, UINT flags ) { - struct local_header *header; + struct mem_entry *mem; void *ptr; HLOCAL ret = 0; DWORD heap_flags = (flags & LMEM_ZEROINIT) ? HEAP_ZERO_MEMORY : 0;
+ TRACE_(globalmem)( "handle %p, size %#Ix, flags %#x\n", handle, size, flags ); + RtlLockHeap( GetProcessHeap() ); if (flags & LMEM_MODIFY) /* modify flags */ { - if (is_pointer( hmem ) && (flags & LMEM_MOVEABLE)) + if (is_pointer( handle ) && (flags & LMEM_MOVEABLE)) { /* make a fixed block moveable * actually only NT is able to do this. But it's soo simple */ - if (hmem == 0) + if (handle == 0) { - WARN( "null handle\n" ); + WARN_(globalmem)( "null handle\n" ); SetLastError( ERROR_NOACCESS ); } else { - size = RtlSizeHeap( GetProcessHeap(), 0, hmem ); + size = RtlSizeHeap( GetProcessHeap(), 0, handle ); ret = LocalAlloc( flags, size ); ptr = LocalLock( ret ); - memcpy( ptr, hmem, size ); + memcpy( ptr, handle, size ); LocalUnlock( ret ); - LocalFree( hmem ); + LocalFree( handle ); } } - else if (!is_pointer( hmem ) && (flags & LMEM_DISCARDABLE)) + else if (!is_pointer( handle ) && (flags & LMEM_DISCARDABLE)) { /* change the flags to make our block "discardable" */ - header = get_header( hmem ); - header->flags |= LMEM_DISCARDABLE >> 8; - ret = hmem; + mem = mem_from_HLOCAL( handle ); + mem->flags |= LMEM_DISCARDABLE >> 8; + ret = handle; } else SetLastError( ERROR_INVALID_PARAMETER ); } else { - if (is_pointer( hmem )) + if (is_pointer( handle )) { /* reallocate fixed memory */ if (!(flags & LMEM_MOVEABLE)) heap_flags |= HEAP_REALLOC_IN_PLACE_ONLY; - ret = HeapReAlloc( GetProcessHeap(), heap_flags, hmem, size ); + ret = HeapReAlloc( GetProcessHeap(), heap_flags, handle, size ); } else { /* reallocate a moveable block */ - header = get_header( hmem ); + mem = mem_from_HLOCAL( handle ); if (size != 0) { if (size <= INT_MAX - HLOCAL_STORAGE) { - if (header->ptr) + if (mem->ptr) { - if ((ptr = HeapReAlloc( GetProcessHeap(), heap_flags, (char *)header->ptr - HLOCAL_STORAGE, + if ((ptr = HeapReAlloc( GetProcessHeap(), heap_flags, (char *)mem->ptr - HLOCAL_STORAGE, size + HLOCAL_STORAGE ))) { - header->ptr = (char *)ptr + HLOCAL_STORAGE; - ret = hmem; + mem->ptr = (char *)ptr + HLOCAL_STORAGE; + ret = handle; } } else { if ((ptr = HeapAlloc( GetProcessHeap(), heap_flags, size + HLOCAL_STORAGE ))) { - *(HLOCAL *)ptr = hmem; - header->ptr = (char *)ptr + HLOCAL_STORAGE; - ret = hmem; + *(HLOCAL *)ptr = handle; + mem->ptr = (char *)ptr + HLOCAL_STORAGE; + ret = handle; } } } @@ -867,16 +874,16 @@ HLOCAL WINAPI DECLSPEC_HOTPATCH LocalReAlloc( HLOCAL hmem, SIZE_T size, UINT fla } else { - if (header->lock == 0) + if (mem->lock == 0) { - if (header->ptr) + if (mem->ptr) { - HeapFree( GetProcessHeap(), 0, (char *)header->ptr - HLOCAL_STORAGE ); - header->ptr = NULL; + HeapFree( GetProcessHeap(), 0, (char *)mem->ptr - HLOCAL_STORAGE ); + mem->ptr = NULL; } - ret = hmem; + ret = handle; } - else WARN( "not freeing memory associated with locked handle\n" ); + else WARN_(globalmem)( "not freeing memory associated with locked handle\n" ); } } } @@ -888,11 +895,13 @@ HLOCAL WINAPI DECLSPEC_HOTPATCH LocalReAlloc( HLOCAL hmem, SIZE_T size, UINT fla /*********************************************************************** * LocalUnlock (kernelbase.@) */ -BOOL WINAPI DECLSPEC_HOTPATCH LocalUnlock( HLOCAL hmem ) +BOOL WINAPI DECLSPEC_HOTPATCH LocalUnlock( HLOCAL handle ) { BOOL ret = FALSE;
- if (is_pointer( hmem )) + TRACE_(globalmem)( "handle %p\n", handle ); + + if (is_pointer( handle )) { SetLastError( ERROR_NOT_LOCKED ); return FALSE; @@ -901,30 +910,30 @@ BOOL WINAPI DECLSPEC_HOTPATCH LocalUnlock( HLOCAL hmem ) RtlLockHeap( GetProcessHeap() ); __TRY { - struct local_header *header = get_header( hmem ); - if (header->magic == MAGIC_LOCAL_USED) + struct mem_entry *mem = mem_from_HLOCAL( handle ); + if (mem->magic == MAGIC_LOCAL_USED) { - if (header->lock) + if (mem->lock) { - header->lock--; - ret = (header->lock != 0); + mem->lock--; + ret = (mem->lock != 0); if (!ret) SetLastError( NO_ERROR ); } else { - WARN( "%p not locked\n", hmem ); + WARN_(globalmem)( "%p not locked\n", handle ); SetLastError( ERROR_NOT_LOCKED ); } } else { - WARN( "invalid handle %p (Magic: 0x%04x)\n", hmem, header->magic ); + WARN_(globalmem)( "invalid handle %p\n", handle ); SetLastError( ERROR_INVALID_HANDLE ); } } __EXCEPT_PAGE_FAULT { - WARN("(%p): Page fault occurred ! Caused by bug ?\n", hmem); + WARN_(globalmem)( "(%p): Page fault occurred ! Caused by bug ?\n", handle ); SetLastError( ERROR_INVALID_PARAMETER ); } __ENDTRY