diff --git a/if1632/toolhelp.spec b/if1632/toolhelp.spec index 8f56c8b10c3..dbbcbecbec2 100644 --- a/if1632/toolhelp.spec +++ b/if1632/toolhelp.spec @@ -35,6 +35,6 @@ type win16 81 stub TASKSETCSIP 82 stub TASKGETCSIP 83 stub TASKSWITCH -84 stub LOCAL32INFO -85 stub LOCAL32FIRST -86 stub LOCAL32NEXT +84 pascal16 Local32Info(ptr word) Local32Info +85 pascal16 Local32First(ptr word) Local32First +86 pascal16 Local32Next(ptr) Local32Next diff --git a/include/toolhelp.h b/include/toolhelp.h index 78c865e64b4..bb0a572f79f 100644 --- a/include/toolhelp.h +++ b/include/toolhelp.h @@ -160,6 +160,40 @@ BOOL16 WINAPI LocalInfo( LOCALINFO *pLocalInfo, HGLOBAL16 handle ); BOOL16 WINAPI LocalFirst( LOCALENTRY *pLocalEntry, HGLOBAL16 handle ); BOOL16 WINAPI LocalNext( LOCALENTRY *pLocalEntry ); +/* Local 32-bit heap */ + +typedef struct +{ + DWORD dwSize; /* 00 */ + DWORD dwMemReserved; /* 04 */ + DWORD dwMemCommitted; /* 08 */ + DWORD dwTotalFree; /* 0C */ + DWORD dwLargestFreeBlock; /* 10 */ + DWORD dwcFreeHandles; /* 14 */ +} LOCAL32INFO; + +typedef struct +{ + DWORD dwSize; /* 00 */ + WORD hHandle; /* 04 */ + DWORD dwAddress; /* 06 */ + DWORD dwSizeBlock; /* 0A */ + WORD wFlags; /* 0E */ + WORD wType; /* 10 */ + WORD hHeap; /* 12 */ + WORD wHeapType; /* 14 */ + DWORD dwNext; /* 16 */ + DWORD dwNextAlt; /* 1A */ +} LOCAL32ENTRY; + +/* LOCAL32ENTRY.wHeapType flags same as LOCALENTRY.wHeapType flags */ +/* LOCAL32ENTRY.wFlags same as LOCALENTRY.wFlags */ +/* LOCAL32ENTRY.wType same as LOCALENTRY.wType */ + +BOOL16 WINAPI Local32Info( LOCAL32INFO *pLocal32Info, HGLOBAL16 handle ); +BOOL16 WINAPI Local32First( LOCAL32ENTRY *pLocal32Entry, HGLOBAL16 handle ); +BOOL16 WINAPI Local32Next( LOCAL32ENTRY *pLocal32Entry ); + /* modules */ diff --git a/memory/heap.c b/memory/heap.c index b73d1d05969..2e3f5800ea4 100644 --- a/memory/heap.c +++ b/memory/heap.c @@ -15,6 +15,7 @@ #include "winerror.h" #include "winnt.h" #include "heap.h" +#include "toolhelp.h" #include "debug.h" /* Note: the heap data structures are based on what Pietrek describes in his @@ -1833,4 +1834,99 @@ WORD WINAPI Local32GetSegment( HANDLE32 heap ) return header->segment; } +/*********************************************************************** + * Local32_GetHeap + */ +static LOCAL32HEADER *Local32_GetHeap( HGLOBAL16 handle ) +{ + WORD selector = GlobalHandleToSel( handle ); + DWORD base = GetSelectorBase( selector ); + DWORD limit = GetSelectorLimit( selector ); + + /* Hmmm. This is a somewhat stupid heuristic, but Windows 95 does + it this way ... */ + + if ( limit > 0x10000 && ((LOCAL32HEADER *)base)->magic == LOCAL32_MAGIC ) + return (LOCAL32HEADER *)base; + + base += 0x10000; + limit -= 0x10000; + + if ( limit > 0x10000 && ((LOCAL32HEADER *)base)->magic == LOCAL32_MAGIC ) + return (LOCAL32HEADER *)base; + + return NULL; +} + +/*********************************************************************** + * Local32Info (KERNEL.444) (TOOLHELP.84) + */ +BOOL16 WINAPI Local32Info( LOCAL32INFO *pLocal32Info, HGLOBAL16 handle ) +{ + SUBHEAP *heapPtr; + LPBYTE ptr; + int i; + + LOCAL32HEADER *header = Local32_GetHeap( handle ); + if ( !header ) return FALSE; + + if ( !pLocal32Info || pLocal32Info->dwSize < sizeof(LOCAL32INFO) ) + return FALSE; + + heapPtr = (SUBHEAP *)HEAP_GetPtr( header->heap ); + pLocal32Info->dwMemReserved = heapPtr->size; + pLocal32Info->dwMemCommitted = heapPtr->commitSize; + pLocal32Info->dwTotalFree = 0L; + pLocal32Info->dwLargestFreeBlock = 0L; + + /* Note: Local32 heaps always have only one subheap! */ + ptr = (LPBYTE)heapPtr + heapPtr->headerSize; + while ( ptr < (LPBYTE)heapPtr + heapPtr->size ) + { + if (*(DWORD *)ptr & ARENA_FLAG_FREE) + { + ARENA_FREE *pArena = (ARENA_FREE *)ptr; + DWORD size = (pArena->size & ARENA_SIZE_MASK); + ptr += sizeof(*pArena) + size; + + pLocal32Info->dwTotalFree += size; + if ( size > pLocal32Info->dwLargestFreeBlock ) + pLocal32Info->dwLargestFreeBlock = size; + } + else + { + ARENA_INUSE *pArena = (ARENA_INUSE *)ptr; + DWORD size = (pArena->size & ARENA_SIZE_MASK); + ptr += sizeof(*pArena) + size; + } + } + + pLocal32Info->dwcFreeHandles = 0; + for ( i = 0; i < HTABLE_NPAGES; i++ ) + { + if ( header->freeListFirst[i] == 0xffff ) break; + pLocal32Info->dwcFreeHandles += header->freeListSize[i]; + } + pLocal32Info->dwcFreeHandles += (HTABLE_NPAGES - i) * HTABLE_PAGESIZE/4; + + return TRUE; +} + +/*********************************************************************** + * Local32First (KERNEL.445) (TOOLHELP.85) + */ +BOOL16 WINAPI Local32First( LOCAL32ENTRY *pLocal32Entry, HGLOBAL16 handle ) +{ + FIXME( heap, "(%p, %04X): stub!\n", pLocal32Entry, handle ); + return FALSE; +} + +/*********************************************************************** + * Local32Next (KERNEL.446) (TOOLHELP.86) + */ +BOOL16 WINAPI Local32Next( LOCAL32ENTRY *pLocal32Entry ) +{ + FIXME( heap, "(%p): stub!\n", pLocal32Entry ); + return FALSE; +}