From dee510bd32db810c89235dc5c60ba73bffb82775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= Date: Mon, 4 Apr 2022 10:02:02 +0200 Subject: [PATCH] kernelbase: Use the same HLOCAL flags / lock layout as native. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RĂ©mi Bernon Signed-off-by: Alexandre Julliard --- dlls/kernel32/heap.c | 54 ++++++++++++++++++++------------------ dlls/kernel32/tests/heap.c | 8 ------ dlls/kernelbase/memory.c | 41 ++++++++++++++++++----------- 3 files changed, 53 insertions(+), 50 deletions(-) diff --git a/dlls/kernel32/heap.c b/dlls/kernel32/heap.c index 20505b673ec..df094c94257 100644 --- a/dlls/kernel32/heap.c +++ b/dlls/kernel32/heap.c @@ -147,14 +147,19 @@ BOOL WINAPI HeapDestroy( HANDLE heap /* [in] Handle of heap */ ) * Global/local heap functions, keep in sync with kernelbase/memory.c ***********************************************************************/ +#define MEM_FLAG_USED 1 +#define MEM_FLAG_MOVEABLE 2 +#define MEM_FLAG_DISCARDABLE 4 +#define MEM_FLAG_DISCARDED 8 +#define MEM_FLAG_DDESHARE 0x8000 + struct mem_entry { union { struct { - WORD magic; - BYTE flags; + WORD flags; BYTE lock; }; void *next_free; @@ -166,7 +171,6 @@ C_ASSERT(sizeof(struct mem_entry) == 2 * sizeof(void *)); struct kernelbase_global_data *kernelbase_global_data; -#define MAGIC_LOCAL_USED 0x5342 #define POINTER_TO_HANDLE( p ) (*(((const HGLOBAL *)( p )) - 2)) /* align the storage needed for the HLOCAL on an 8-byte boundary thus * LocalAlloc/LocalReAlloc'ing with LMEM_MOVEABLE of memory with @@ -181,7 +185,7 @@ static inline struct mem_entry *unsafe_mem_from_HLOCAL( HLOCAL handle ) struct kernelbase_global_data *data = kernelbase_global_data; if (((UINT_PTR)handle & ((sizeof(void *) << 1) - 1)) != sizeof(void *)) return NULL; if (mem < data->mem_entries || mem >= data->mem_entries_end) return NULL; - if (mem->magic != MAGIC_LOCAL_USED) return NULL; + if (!(mem->flags & MEM_FLAG_USED)) return NULL; return mem; } @@ -431,32 +435,29 @@ VOID WINAPI GlobalUnfix( HGLOBAL handle ) */ UINT WINAPI GlobalFlags( HGLOBAL handle ) { + HANDLE heap = GetProcessHeap(); struct mem_entry *mem; - DWORD retval; + UINT flags; - TRACE_(globalmem)( "handle %p\n", handle ); + if (unsafe_ptr_from_HLOCAL( handle )) return 0; - if (unsafe_ptr_from_HLOCAL( handle )) + RtlLockHeap( heap ); + if ((mem = unsafe_mem_from_HLOCAL( handle ))) { - retval = 0; + flags = mem->lock; + if (mem->flags & MEM_FLAG_DISCARDABLE) flags |= GMEM_DISCARDABLE; + if (mem->flags & MEM_FLAG_DISCARDED) flags |= GMEM_DISCARDED; + if (mem->flags & MEM_FLAG_DDESHARE) flags |= GMEM_DDESHARE; } else { - RtlLockHeap( GetProcessHeap() ); - if ((mem = unsafe_mem_from_HLOCAL( handle ))) - { - retval = mem->lock + (mem->flags << 8); - if (mem->ptr == 0) retval |= GMEM_DISCARDED; - } - else - { - WARN_(globalmem)( "invalid handle %p\n", handle ); - SetLastError( ERROR_INVALID_HANDLE ); - retval = GMEM_INVALID_HANDLE; - } - RtlUnlockHeap( GetProcessHeap() ); + WARN_(globalmem)( "invalid handle %p\n", handle ); + SetLastError( ERROR_INVALID_HANDLE ); + flags = GMEM_INVALID_HANDLE; } - return retval; + RtlUnlockHeap( heap ); + + return flags; } @@ -491,10 +492,11 @@ SIZE_T WINAPI LocalCompact( UINT minfree ) * Windows memory management does not provide a separate local heap * and global heap. */ -UINT WINAPI LocalFlags( - HLOCAL handle /* [in] Handle of memory object */ -) { - return GlobalFlags( handle ); +UINT WINAPI LocalFlags( HLOCAL handle ) +{ + UINT flags = GlobalFlags( handle ); + if (flags & GMEM_DISCARDABLE) flags |= LMEM_DISCARDABLE; + return flags; } diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c index 5d6383a49e5..566e2d6b987 100644 --- a/dlls/kernel32/tests/heap.c +++ b/dlls/kernel32/tests/heap.c @@ -334,7 +334,6 @@ static void test_GlobalAlloc(void) ok( size == 0, "GlobalSize returned %Iu\n", size ); ret = HeapValidate( GetProcessHeap(), 0, entry ); ok( !ret, "HeapValidate succeeded\n" ); - todo_wine ok( entry->flags == 0xf, "got unexpected flags %#Ix\n", entry->flags ); ok( !entry->ptr, "got unexpected ptr %p\n", entry->ptr ); mem = GlobalFree( mem ); @@ -347,7 +346,6 @@ static void test_GlobalAlloc(void) ok( size == 0, "GlobalSize returned %Iu\n", size ); ret = HeapValidate( GetProcessHeap(), 0, entry ); ok( !ret, "HeapValidate succeeded\n" ); - todo_wine ok( entry->flags == 0xb, "got unexpected flags %#Ix\n", entry->flags ); ok( !entry->ptr, "got unexpected ptr %p\n", entry->ptr ); mem = GlobalFree( mem ); @@ -389,14 +387,12 @@ static void test_GlobalAlloc(void) ok( !((UINT_PTR)ptr & (sizeof(void *) - 1)), "got unexpected ptr align\n" ); for (i = 1; i < 0xff; ++i) { - todo_wine ok( entry->flags == ((i<<16)|3), "got unexpected flags %#Ix\n", entry->flags ); ptr = GlobalLock( mem ); ok( !!ptr, "GlobalLock failed, error %lu\n", GetLastError() ); } ptr = GlobalLock( mem ); ok( !!ptr, "GlobalLock failed, error %lu\n", GetLastError() ); - todo_wine ok( entry->flags == 0xff0003, "got unexpected flags %#Ix\n", entry->flags ); for (i = 1; i < 0xff; ++i) { @@ -405,7 +401,6 @@ static void test_GlobalAlloc(void) } ret = GlobalUnlock( mem ); ok( !ret, "GlobalUnlock succeeded, error %lu\n", GetLastError() ); - todo_wine ok( entry->flags == 0x3, "got unexpected flags %#Ix\n", entry->flags ); tmp_mem = GlobalFree( mem ); @@ -418,7 +413,6 @@ static void test_GlobalAlloc(void) mem = GlobalAlloc( GMEM_MOVEABLE | GMEM_DISCARDABLE, 0 ); ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() ); entry = mem_entry_from_HANDLE( mem ); - todo_wine ok( entry->flags == 0xf, "got unexpected flags %#Ix\n", entry->flags ); ok( !entry->ptr, "got unexpected ptr %p\n", entry->ptr ); flags = GlobalFlags( mem ); @@ -429,7 +423,6 @@ static void test_GlobalAlloc(void) mem = GlobalAlloc( GMEM_MOVEABLE | GMEM_DISCARDABLE, 1 ); ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() ); entry = mem_entry_from_HANDLE( mem ); - todo_wine ok( entry->flags == 0x7, "got unexpected flags %#Ix\n", entry->flags ); ok( !!entry->ptr, "got unexpected ptr %p\n", entry->ptr ); flags = GlobalFlags( mem ); @@ -440,7 +433,6 @@ static void test_GlobalAlloc(void) mem = GlobalAlloc( GMEM_MOVEABLE | GMEM_DISCARDABLE | GMEM_DDESHARE, 1 ); ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() ); entry = mem_entry_from_HANDLE( mem ); - todo_wine ok( entry->flags == 0x8007, "got unexpected flags %#Ix\n", entry->flags ); ok( !!entry->ptr, "got unexpected ptr %p\n", entry->ptr ); flags = GlobalFlags( mem ); diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c index 06dbc66b7b9..21e7c5ef9d9 100644 --- a/dlls/kernelbase/memory.c +++ b/dlls/kernelbase/memory.c @@ -585,14 +585,19 @@ struct kernelbase_global_data struct mem_entry *mem_entries_end; }; +#define MEM_FLAG_USED 1 +#define MEM_FLAG_MOVEABLE 2 +#define MEM_FLAG_DISCARDABLE 4 +#define MEM_FLAG_DISCARDED 8 +#define MEM_FLAG_DDESHARE 0x8000 + struct mem_entry { union { struct { - WORD magic; - BYTE flags; + WORD flags; BYTE lock; }; void *next_free; @@ -612,7 +617,6 @@ static struct kernelbase_global_data kernelbase_global_data = .mem_entries_end = mem_entries + MAX_MEM_HANDLES, }; -#define MAGIC_LOCAL_USED 0x5342 /* align the storage needed for the HLOCAL on an 8-byte boundary thus * LocalAlloc/LocalReAlloc'ing with LMEM_MOVEABLE of memory with * size = 8*k, where k=1,2,3,... allocs exactly the given size. @@ -626,12 +630,13 @@ static inline struct mem_entry *unsafe_mem_from_HLOCAL( HLOCAL handle ) struct kernelbase_global_data *data = &kernelbase_global_data; if (((UINT_PTR)handle & ((sizeof(void *) << 1) - 1)) != sizeof(void *)) return NULL; if (mem < data->mem_entries || mem >= data->mem_entries_end) return NULL; - if (mem->magic != MAGIC_LOCAL_USED) return NULL; + if (!(mem->flags & MEM_FLAG_USED)) return NULL; return mem; } static inline HLOCAL HLOCAL_from_mem( struct mem_entry *mem ) { + if (!mem) return 0; return &mem->ptr; } @@ -657,13 +662,18 @@ void *WINAPI KernelBaseGetGlobalData(void) */ HGLOBAL WINAPI DECLSPEC_HOTPATCH GlobalAlloc( UINT flags, SIZE_T size ) { - /* mask out obsolete flags */ - flags &= ~(GMEM_NOCOMPACT | GMEM_NOT_BANKED | GMEM_NOTIFY); + struct mem_entry *mem; + HGLOBAL handle; /* LocalAlloc allows a 0-size fixed block, but GlobalAlloc doesn't */ if (!(flags & GMEM_MOVEABLE) && !size) size = 1; - return LocalAlloc( flags, size ); + handle = LocalAlloc( flags, size ); + + if ((mem = unsafe_mem_from_HLOCAL( handle )) && (flags & GMEM_DDESHARE)) + mem->flags |= MEM_FLAG_DDESHARE; + + return handle; } @@ -712,12 +722,13 @@ HLOCAL WINAPI DECLSPEC_HOTPATCH LocalAlloc( UINT flags, SIZE_T size ) if (!mem) goto failed; handle = HLOCAL_from_mem( mem ); - mem->magic = MAGIC_LOCAL_USED; - mem->flags = flags >> 8; + mem->flags = MEM_FLAG_USED | MEM_FLAG_MOVEABLE; + if (flags & LMEM_DISCARDABLE) mem->flags |= MEM_FLAG_DISCARDABLE; mem->lock = 0; mem->ptr = NULL; - if (size) + if (!size) mem->flags |= MEM_FLAG_DISCARDED; + else { if (!(ptr = HeapAlloc( heap, heap_flags, size + HLOCAL_STORAGE ))) goto failed; *(HLOCAL *)ptr = handle; @@ -798,9 +809,8 @@ LPVOID WINAPI DECLSPEC_HOTPATCH LocalLock( HLOCAL handle ) RtlLockHeap( heap ); if ((mem = unsafe_mem_from_HLOCAL( handle ))) { - ret = mem->ptr; - if (!mem->ptr) SetLastError( ERROR_DISCARDED ); - else if (mem->lock < LMEM_LOCKCOUNT) mem->lock++; + if (!(ret = mem->ptr)) SetLastError( ERROR_DISCARDED ); + else if (!++mem->lock) mem->lock--; } else { @@ -935,13 +945,12 @@ BOOL WINAPI DECLSPEC_HOTPATCH LocalUnlock( HLOCAL handle ) { if (mem->lock) { - mem->lock--; - ret = (mem->lock != 0); + ret = (--mem->lock != 0); if (!ret) SetLastError( NO_ERROR ); } else { - WARN_(globalmem)( "%p not locked\n", handle ); + WARN_(globalmem)( "handle %p not locked\n", handle ); SetLastError( ERROR_NOT_LOCKED ); } }