Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48523 Signed-off-by: Dirk Niggemann dirk.niggemann@gmail.com --- dlls/toolhelp.dll16/toolhelp.c | 86 ++++++++++++++++++++++++++++++---- 1 file changed, 76 insertions(+), 10 deletions(-)
diff --git a/dlls/toolhelp.dll16/toolhelp.c b/dlls/toolhelp.dll16/toolhelp.c index f2b520b6a1..42d8474719 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 */ @@ -326,12 +350,33 @@ BOOL16 WINAPI LocalFirst16( LOCALENTRY *pLocalEntry, HGLOBAL16 handle ) WORD ds = GlobalHandleToSel16( handle ); char *ptr = MapSL( MAKESEGPTR( ds, 0 ) ); LOCALHEAPINFO *pInfo = get_local_heap( ds ); - if (!pInfo) return FALSE; + WORD table, lhandle;
- pLocalEntry->hHandle = pInfo->first + LOCAL_ARENA_HEADER_SIZE; - pLocalEntry->wAddress = pLocalEntry->hHandle; - pLocalEntry->wFlags = LF_FIXED; - pLocalEntry->wcLock = 0; + if (!pInfo) return FALSE; + table = pInfo->htable; + pLocalEntry->wAddress = pInfo->first + LOCAL_ARENA_HEADER_SIZE; + lhandle = pLocalEntry->wAddress; + pLocalEntry->wFlags = LF_FIXED; + pLocalEntry->wcLock = 0; + /* Find the address in the moveable 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; pLocalEntry->hHeap = handle; pLocalEntry->wHeapType = NORMAL_HEAP; @@ -349,15 +394,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;