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;
+}