toolhelp: Return correct handle, address, flag and lock values in LocalNext() for moveable blocks.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48523
Signed-off-by: Dirk Niggemann <dirk.niggemann@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Dirk Niggemann 2020-02-13 19:32:14 +00:00 committed by Alexandre Julliard
parent 50440e28bb
commit 22173f708e
1 changed files with 40 additions and 4 deletions

View File

@ -90,6 +90,22 @@ typedef struct
#define LOCAL_ARENA_HEADER( handle) ((handle) - LOCAL_ARENA_HEADER_SIZE)
#define LOCAL_ARENA_PTR(ptr,arena) ((LOCALARENA *)((char *)(ptr)+(arena)))
#define MOVEABLE_PREFIX sizeof(HLOCAL16)
/* 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;
typedef struct
{
WORD null; /* Always 0 */
@ -349,15 +365,35 @@ 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 (!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;
pLocalEntry->wFlags = (pArena->prev & 3) + 1;
pLocalEntry->wcLock = 0;
/* Find the address in the entry tables */
lhandle = pLocalEntry->wAddress;
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;
break;
}
if (table) table = *(WORD *)pEntry;
}
pLocalEntry->hHandle = lhandle;
pLocalEntry->wType = LT_NORMAL;
if (pArena->next != pLocalEntry->wNext) /* last one? */
pLocalEntry->wNext = pArena->next;