Make sure we commit enough memory in a new subheap.

diff --git a/memory/heap.c b/memory/heap.c
index da3477c..8750588 100644
--- a/memory/heap.c
+++ b/memory/heap.c
@@ -33,16 +33,16 @@
 typedef struct tagARENA_INUSE
 {
     DWORD  size;                    /* Block size; must be the first field */
-    WORD   threadId;                /* Allocating thread id */
     WORD   magic;                   /* Magic number */
+    WORD   threadId;                /* Allocating thread id */
     void  *callerEIP;               /* EIP of caller upon allocation */
 } ARENA_INUSE;
 
 typedef struct tagARENA_FREE
 {
     DWORD                 size;     /* Block size; must be the first field */
-    WORD                  threadId; /* Freeing thread id */
     WORD                  magic;    /* Magic number */
+    WORD                  threadId; /* Freeing thread id */
     struct tagARENA_FREE *next;     /* Next free arena */
     struct tagARENA_FREE *prev;     /* Prev free arena */
 } ARENA_FREE;
@@ -446,7 +446,8 @@
     {
         HEAP_CreateFreeBlock( subheap, (char *)(pArena + 1) + size,
                               (pArena->size & ARENA_SIZE_MASK) - size );
-        pArena->size = (pArena->size & ~ARENA_SIZE_MASK) | size;
+	/* assign size plus previous arena flags */
+        pArena->size = size | (pArena->size & ~ARENA_SIZE_MASK);
     }
     else
     {
@@ -636,7 +637,12 @@
                  (DWORD)heap, size );
         return NULL;
     }
-    size += sizeof(SUBHEAP) + sizeof(ARENA_FREE);
+    /* make sure that we have a big enough size *committed* to fit another
+     * last free arena in !
+     * So just one heap struct, one first free arena which will eventually
+     * get inuse, and HEAP_MIN_BLOCK_SIZE for the second free arena that
+     * might get assigned all remaining free space in HEAP_ShrinkBlock() */
+    size += sizeof(SUBHEAP) + sizeof(ARENA_FREE) + HEAP_MIN_BLOCK_SIZE;
     if (!(subheap = HEAP_CreateSubHeap( heap, heap->flags, size,
                                         max( HEAP_DEF_SIZE, size ) )))
         return NULL;
@@ -721,6 +727,8 @@
     if (!(pArena->prev->size & ARENA_FLAG_FREE) ||
         (pArena->prev->magic != ARENA_FREE_MAGIC))
     { 
+	/* this often means that the prev arena got overwritten
+	 * by a memory write before that prev arena */
         ERR("Heap %08lx: prev arena %08lx invalid for %08lx\n", 
                  (DWORD)subheap->heap, (DWORD)pArena->prev, (DWORD)pArena );
         return FALSE;
@@ -1102,10 +1110,10 @@
     if (!heapPtr) return NULL;
     flags &= HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY;
     flags |= heapPtr->flags;
-    if (!(flags & HEAP_NO_SERIALIZE)) EnterCriticalSection( &heapPtr->critSection );
     size = (size + 3) & ~3;
     if (size < HEAP_MIN_BLOCK_SIZE) size = HEAP_MIN_BLOCK_SIZE;
 
+    if (!(flags & HEAP_NO_SERIALIZE)) EnterCriticalSection( &heapPtr->critSection );
     /* Locate a suitable free block */
 
     if (!(pArena = HEAP_FindFreeBlock( heapPtr, size, &subheap )))