Implemented Local32Info, stubs for Local32First/Next (KERNEL.444-446).
diff --git a/if1632/toolhelp.spec b/if1632/toolhelp.spec
index 8f56c8b..dbbcbec 100644
--- a/if1632/toolhelp.spec
+++ b/if1632/toolhelp.spec
@@ -35,6 +35,6 @@
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 78c865e..bb0a572 100644
--- a/include/toolhelp.h
+++ b/include/toolhelp.h
@@ -160,6 +160,40 @@
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 b73d1d0..2e3f580 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 @@
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;
+}