Make LocalNext() return correct handles, addresses, flags and lock values for moveable blocks. Previous implementation just returned the arena block pointer and flags for fixed blocks. Needed for applications that use toolhelp to find their own memory blocks.

Dirk Niggemann dirk.niggemann at gmail.com
Thu Feb 13 13:32:14 CST 2020


Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48523
Signed-off-by: Dirk Niggemann <dirk.niggemann at gmail.com>
---
 dlls/toolhelp.dll16/toolhelp.c | 55 ++++++++++++++++++++++++++++++----
 1 file changed, 50 insertions(+), 5 deletions(-)

diff --git a/dlls/toolhelp.dll16/toolhelp.c b/dlls/toolhelp.dll16/toolhelp.c
index f2b520b6a1..5fe5afe988 100644
--- a/dlls/toolhelp.dll16/toolhelp.c
+++ b/dlls/toolhelp.dll16/toolhelp.c
@@ -90,6 +90,30 @@ typedef struct
 #define LOCAL_ARENA_HEADER( handle) ((handle) - LOCAL_ARENA_HEADER_SIZE)
 #define LOCAL_ARENA_PTR(ptr,arena)  ((LOCALARENA *)((char *)(ptr)+(arena)))
 
+#ifdef ALLOW_UNALIGNED_ACCESS
+# define MOVEABLE_PREFIX sizeof(HLOCAL16)
+#else
+# define MOVEABLE_PREFIX sizeof(int)
+#endif
+
+/* Layout of a handle entry table
+ *
+ * WORD                     count of entries
+ * LOCALHANDLEENTRY[count]  entries
+ * WORD                     near ptr to next table
+ */
+typedef struct
+{
+    WORD addr;                /* Address of the MOVEABLE block */
+    BYTE flags;               /* Flags for this block */
+    BYTE lock;                /* Lock count */
+} LOCALHANDLEENTRY;
+
+
+#define HANDLE_FIXED(handle) (((handle) & 3) == 0)
+#define HANDLE_MOVEABLE(handle) (((handle) & 3) == 2)
+
+
 typedef struct
 {
     WORD null;        /* Always 0 */
@@ -349,15 +373,36 @@ BOOL16 WINAPI LocalNext16( LOCALENTRY *pLocalEntry )
     WORD ds = GlobalHandleToSel16( pLocalEntry->hHeap );
     char *ptr = MapSL( MAKESEGPTR( ds, 0 ) );
     LOCALARENA *pArena;
+    WORD table, lhandle;
+    LOCALHEAPINFO *pInfo = get_local_heap( ds );
 
-    if (!get_local_heap( ds )) return FALSE;
-    if (!pLocalEntry->wNext) return FALSE;
+    if ( !pInfo ) return FALSE;
+    if ( !pLocalEntry->wNext ) return FALSE;
+    table = pInfo->htable;
     pArena = LOCAL_ARENA_PTR( ptr, pLocalEntry->wNext );
-
-    pLocalEntry->hHandle   = pLocalEntry->wNext + LOCAL_ARENA_HEADER_SIZE;
-    pLocalEntry->wAddress  = pLocalEntry->hHandle;
+    pLocalEntry->wAddress  = pLocalEntry->wNext + LOCAL_ARENA_HEADER_SIZE;
+    lhandle                = pLocalEntry->wAddress;
     pLocalEntry->wFlags    = (pArena->prev & 3) + 1;
     pLocalEntry->wcLock    = 0;
+    /* Find the address in the entry tables */
+    while (table)
+    {
+        WORD count = *(WORD *)(ptr + table);
+        LOCALHANDLEENTRY *pEntry = (LOCALHANDLEENTRY*)(ptr+table+sizeof(WORD));
+        for (; count > 0; count--, pEntry++)
+            if (pEntry->addr == lhandle + MOVEABLE_PREFIX)
+            {
+                lhandle = (HLOCAL16)((char *)pEntry - ptr);
+                table = 0;
+                pLocalEntry->wAddress  = pEntry->addr;
+                pLocalEntry->wFlags    = pEntry->flags;
+                pLocalEntry->wcLock    = pEntry->lock;
+                TRACE("moveable handle %04x\n", lhandle);
+                break;
+            }
+        if ( table ) table = *(WORD *)pEntry;
+    }
+    pLocalEntry->hHandle   = lhandle;
     pLocalEntry->wType     = LT_NORMAL;
     if (pArena->next != pLocalEntry->wNext)  /* last one? */
         pLocalEntry->wNext = pArena->next;
-- 
2.17.2 (Apple Git-113)




More information about the wine-devel mailing list