[PATCH 5/5] kernelbase: Use the same HLOCAL flags / lock layout as native.

Rémi Bernon rbernon at codeweavers.com
Fri Apr 1 03:23:01 CDT 2022


Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 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 a8cdc8fc566..566206b7203 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;
 }
 
@@ -433,32 +437,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;
 }
 
 
@@ -493,10 +494,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 ccc84b4a9bd..82d3b7a8df3 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 );
         }
     }
-- 
2.35.1




More information about the wine-devel mailing list