[HEAP]
[reactos.git] / reactos / lib / rtl / heap.c
index 72a5e32..d3b0efc 100644 (file)
@@ -83,10 +83,15 @@ typedef struct tagARENA_FREE
 
 #define ARENA_FLAG_FREE        0x00000001  /* flags OR'ed with arena size */
 #define ARENA_FLAG_PREV_FREE   0x00000002
-#define ARENA_SIZE_MASK        (~3)
 #define ARENA_INUSE_MAGIC      0x455355        /* Value for arena 'magic' field */
 #define ARENA_FREE_MAGIC       0x45455246      /* Value for arena 'magic' field */
 
+#ifndef _WIN64
+#define ARENA_SIZE_MASK        (~3L)
+#else
+#define ARENA_SIZE_MASK        (~7L)
+#endif
+
 #define ARENA_INUSE_FILLER     0x55
 #define ARENA_FREE_FILLER      0xaa
 
@@ -110,10 +115,10 @@ typedef struct tagARENA_FREE
 /* Max size of the blocks on the free lists */
 static const DWORD HEAP_freeListSizes[HEAP_NB_FREE_LISTS] =
 {
-    0x10, 0x20, 0x80, 0x200, ~0UL
+    0x10, 0x20, 0x80, 0x200, MAXULONG
 };
 
-typedef struct
+typedef union
 {
     ARENA_FREE  arena;
     void        *aligment[4];
@@ -145,8 +150,8 @@ typedef struct tagHEAP
 {
     SUBHEAP          subheap;       /* First sub-heap */
     struct list      entry;         /* Entry in process heap list */
-    RTL_CRITICAL_SECTION critSection; /* Critical section for serialization */
-    FREE_LIST_ENTRY  freeList[HEAP_NB_FREE_LISTS];  /* Free lists */
+    HEAP_LOCK        lock;          /* Critical section for serialization */
+    DECLSPEC_ALIGN(8) FREE_LIST_ENTRY  freeList[HEAP_NB_FREE_LISTS];  /* Free lists */
     DWORD            flags;         /* Heap flags */
     DWORD            magic;         /* Magic number */
     PRTL_HEAP_COMMIT_ROUTINE commitRoutine;
@@ -712,15 +717,15 @@ static BOOL HEAP_InitSubHeap( HEAP *heap, LPVOID address, DWORD flags,
           {
             if (!processHeap)  /* do it by hand to avoid memory allocations */
             {
-                heap->critSection.DebugInfo      = &process_heap_critsect_debug;
-                heap->critSection.LockCount      = -1;
-                heap->critSection.RecursionCount = 0;
-                heap->critSection.OwningThread   = 0;
-                heap->critSection.LockSemaphore  = 0;
-                heap->critSection.SpinCount      = 0;
-                process_heap_critsect_debug.CriticalSection = &heap->critSection;
+                heap->lock.CriticalSection.DebugInfo      = &process_heap_critsect_debug;
+                heap->lock.CriticalSection.LockCount      = -1;
+                heap->lock.CriticalSection.RecursionCount = 0;
+                heap->lock.CriticalSection.OwningThread   = 0;
+                heap->lock.CriticalSection.LockSemaphore  = 0;
+                heap->lock.CriticalSection.SpinCount      = 0;
+                process_heap_critsect_debug.CriticalSection = &heap->lock.CriticalSection;
             }
-            else RtlInitializeHeapLock( &heap->critSection );
+            else RtlInitializeHeapLock( &heap->lock );
           }
     }
 
@@ -1089,7 +1094,7 @@ static BOOL HEAP_IsRealArena( HEAP *heapPtr,   /* [in] ptr to the heap */
     flags |= heapPtr->flags;
     /* calling HeapLock may result in infinite recursion, so do the critsect directly */
     if (!(flags & HEAP_NO_SERIALIZE))
-        RtlEnterHeapLock( &heapPtr->critSection );
+        RtlEnterHeapLock( &heapPtr->lock );
 
     if (block)
     {
@@ -1108,7 +1113,7 @@ static BOOL HEAP_IsRealArena( HEAP *heapPtr,   /* [in] ptr to the heap */
             ret = HEAP_ValidateInUseArena( subheap, (const ARENA_INUSE *)block - 1, quiet );
 
         if (!(flags & HEAP_NO_SERIALIZE))
-            RtlLeaveHeapLock( &heapPtr->critSection );
+            RtlLeaveHeapLock( &heapPtr->lock );
         return ret;
     }
 
@@ -1138,7 +1143,7 @@ static BOOL HEAP_IsRealArena( HEAP *heapPtr,   /* [in] ptr to the heap */
         subheap = subheap->next;
     }
 
-    if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveHeapLock( &heapPtr->critSection );
+    if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveHeapLock( &heapPtr->lock );
     return ret;
 }
 
@@ -1176,9 +1181,9 @@ RtlCreateHeap(ULONG flags,
         if (processHeap)
         {
             HEAP *heapPtr = subheap->heap;
-            RtlEnterHeapLock( &processHeap->critSection );
+            RtlEnterHeapLock( &processHeap->lock );
             list_add_head( &processHeap->entry, &heapPtr->entry );
-            RtlLeaveHeapLock( &processHeap->critSection );
+            RtlLeaveHeapLock( &processHeap->lock );
         }
         else
         {
@@ -1219,12 +1224,12 @@ RtlDestroyHeap(HANDLE heap) /* [in] Handle of heap */
          return heap; /* cannot delete the main process heap */
 
       /* remove it from the per-process list */
-      RtlEnterHeapLock( &processHeap->critSection );
+      RtlEnterHeapLock( &processHeap->lock );
       list_remove( &heapPtr->entry );
-      RtlLeaveHeapLock( &processHeap->critSection );
+      RtlLeaveHeapLock( &processHeap->lock );
    }
 
-    RtlDeleteHeapLock( &heapPtr->critSection );
+    RtlDeleteHeapLock( &heapPtr->lock );
     subheap = &heapPtr->subheap;
     while (subheap)
     {
@@ -1249,7 +1254,7 @@ RtlDestroyHeap(HANDLE heap) /* [in] Handle of heap */
 PVOID NTAPI
 RtlAllocateHeap(HANDLE heap,   /* [in] Handle of private heap block */
                 ULONG flags,   /* [in] Heap allocation control flags */
-                ULONG size)    /* [in] Number of bytes to allocate */
+                SIZE_T size)    /* [in] Number of bytes to allocate */
 {
    ARENA_FREE *pArena;
    ARENA_INUSE *pInUse;
@@ -1276,13 +1281,13 @@ RtlAllocateHeap(HANDLE heap,   /* [in] Handle of private heap block */
 
     if (rounded_size < HEAP_MIN_DATA_SIZE) rounded_size = HEAP_MIN_DATA_SIZE;
 
-    if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterHeapLock( &heapPtr->critSection );
+    if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterHeapLock( &heapPtr->lock );
     /* Locate a suitable free block */
     if (!(pArena = HEAP_FindFreeBlock( heapPtr, rounded_size, &subheap )))
     {
         TRACE("(%p,%08lx,%08lx): returning NULL\n",
                   heap, flags, size  );
-        if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveHeapLock( &heapPtr->critSection );
+        if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveHeapLock( &heapPtr->lock );
         if (flags & HEAP_GENERATE_EXCEPTIONS) RtlRaiseStatus( STATUS_NO_MEMORY );
         return NULL;
     }
@@ -1314,7 +1319,7 @@ RtlAllocateHeap(HANDLE heap,   /* [in] Handle of private heap block */
     else
         mark_block_uninitialized( pInUse + 1, pInUse->size & ARENA_SIZE_MASK );
 
-    if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveHeapLock( &heapPtr->critSection );
+    if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveHeapLock( &heapPtr->lock );
 
     TRACE("(%p,%08lx,%08lx): returning %p\n", heap, flags, size, pInUse + 1 );
     return (LPVOID)(pInUse + 1);
@@ -1352,10 +1357,10 @@ BOOLEAN NTAPI RtlFreeHeap(
 
     flags &= HEAP_NO_SERIALIZE;
     flags |= heapPtr->flags;
-    if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterHeapLock( &heapPtr->critSection );
+    if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterHeapLock( &heapPtr->lock );
     if (!HEAP_IsRealArena( heapPtr, HEAP_NO_SERIALIZE, ptr, QUIET ))
     {
-        if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveHeapLock( &heapPtr->critSection );
+        if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveHeapLock( &heapPtr->lock );
         RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_PARAMETER );
         TRACE("(%p,%08lx,%p): returning FALSE\n", heap, flags, ptr );
         return FALSE;
@@ -1371,13 +1376,13 @@ BOOLEAN NTAPI RtlFreeHeap(
 
     HEAP_MakeInUseBlockFree( subheap, pInUse );
 
-    if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveHeapLock( &heapPtr->critSection );
+    if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveHeapLock( &heapPtr->lock );
 
     TRACE("(%p,%08lx,%p): returning TRUE\n", heap, flags, ptr );
     return TRUE;
 
 error:
-    if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveHeapLock( &heapPtr->critSection );
+    if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveHeapLock( &heapPtr->lock );
     RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_PARAMETER );
     TRACE("(%p,%08x,%p): returning FALSE\n", heap, flags, ptr );
     return FALSE;
@@ -1422,7 +1427,7 @@ PVOID NTAPI RtlReAllocateHeap(
    //Flags &= HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY |
    //         HEAP_REALLOC_IN_PLACE_ONLY;
     flags |= heapPtr->flags;
-    if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterHeapLock( &heapPtr->critSection );
+    if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterHeapLock( &heapPtr->lock );
 
     rounded_size = ROUND_SIZE(size);
     if (rounded_size < size) goto oom;  /* overflow */
@@ -1505,19 +1510,19 @@ PVOID NTAPI RtlReAllocateHeap(
 
     /* Return the new arena */
 done:
-    if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveHeapLock( &heapPtr->critSection );
+    if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveHeapLock( &heapPtr->lock );
     TRACE("(%p,%08lx,%p,%08lx): returning %p\n", heap, flags, ptr, size, pArena + 1 );
     return (LPVOID)(pArena + 1);
 
 oom:
-     if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveHeapLock( &heapPtr->critSection );
+     if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveHeapLock( &heapPtr->lock );
      if (flags & HEAP_GENERATE_EXCEPTIONS) RtlRaiseStatus( STATUS_NO_MEMORY );
      RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_NO_MEMORY );
      TRACE("(%p,%08x,%p,%08lx): returning oom\n", heap, flags, ptr, size );
      return NULL;
 
 error:
-    if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveHeapLock( &heapPtr->critSection );
+    if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveHeapLock( &heapPtr->lock );
     RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_PARAMETER );
     TRACE("(%p,%08x,%p,%08lx): returning error\n", heap, flags, ptr, size );
     return NULL;
@@ -1557,7 +1562,7 @@ RtlLockHeap(IN HANDLE Heap)
    HEAP *heapPtr = HEAP_GetPtr( Heap );
    if (!heapPtr)
       return FALSE;
-   RtlEnterHeapLock( &heapPtr->critSection );
+   RtlEnterHeapLock( &heapPtr->lock );
    return TRUE;
 }
 
@@ -1581,7 +1586,7 @@ RtlUnlockHeap(HANDLE Heap)
    HEAP *heapPtr = HEAP_GetPtr( Heap );
    if (!heapPtr)
       return FALSE;
-   RtlLeaveHeapLock( &heapPtr->critSection );
+   RtlLeaveHeapLock( &heapPtr->lock );
    return TRUE;
 }
 
@@ -1599,35 +1604,35 @@ RtlUnlockHeap(HANDLE Heap)
  *
  * @implemented
  */
-ULONG NTAPI
+SIZE_T NTAPI
 RtlSizeHeap(
    HANDLE heap,
    ULONG flags,
    PVOID ptr
 )
 {
-   SIZE_T ret;
+    SIZE_T ret;
     HEAP *heapPtr = HEAP_GetPtr( heap );
 
     if (!heapPtr)
     {
         RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_HANDLE );
-        return ~0UL;
+        return MAXULONG;
     }
     flags &= HEAP_NO_SERIALIZE;
     flags |= heapPtr->flags;
-    if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterHeapLock( &heapPtr->critSection );
+    if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterHeapLock( &heapPtr->lock );
     if (!HEAP_IsRealArena( heapPtr, HEAP_NO_SERIALIZE, ptr, QUIET ))
     {
         RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_PARAMETER );
-        ret = ~0UL;
+        ret = MAXULONG;
     }
     else
     {
         const ARENA_INUSE *pArena = (const ARENA_INUSE *)ptr - 1;
         ret = (pArena->size & ARENA_SIZE_MASK) - pArena->unused_bytes;
     }
-    if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveHeapLock( &heapPtr->critSection );
+    if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveHeapLock( &heapPtr->lock );
 
     TRACE("(%p,%08lx,%p): returning %08lx\n", heap, flags, ptr, ret );
     return ret;
@@ -1689,7 +1694,7 @@ RtlEnumProcessHeaps(PHEAP_ENUMERATION_ROUTINE HeapEnumerationRoutine,
     NTSTATUS Status = STATUS_SUCCESS;
 
     struct list *ptr=NULL;
-    RtlEnterHeapLock(&processHeap->critSection);
+    RtlEnterHeapLock(&processHeap->lock);
     Status=HeapEnumerationRoutine(processHeap,lParam);
 
     LIST_FOR_EACH( ptr, &processHeap->entry )
@@ -1698,7 +1703,7 @@ RtlEnumProcessHeaps(PHEAP_ENUMERATION_ROUTINE HeapEnumerationRoutine,
         Status = HeapEnumerationRoutine(ptr,lParam);
     }
 
-    RtlLeaveHeapLock(&processHeap->critSection);
+    RtlLeaveHeapLock(&processHeap->lock);
 
     return Status;
 }
@@ -1714,7 +1719,7 @@ RtlGetProcessHeaps(ULONG count,
     ULONG total = 1;  /* main heap */
     struct list *ptr;
     ULONG i=0;
-    RtlEnterHeapLock( &processHeap->critSection );
+    RtlEnterHeapLock( &processHeap->lock );
     LIST_FOR_EACH( ptr, &processHeap->entry ) total++;
     //if (total <= count)
     {
@@ -1727,7 +1732,7 @@ RtlGetProcessHeaps(ULONG count,
             *(heaps++) = LIST_ENTRY( ptr, HEAP, entry );
         }
     }
-    RtlLeaveHeapLock( &processHeap->critSection );
+    RtlLeaveHeapLock( &processHeap->lock );
     return i;
 }
 
@@ -1741,7 +1746,7 @@ RtlValidateProcessHeaps(VOID)
    BOOLEAN Result = TRUE;
    HEAP ** pptr;
 
-   RtlEnterHeapLock( &processHeap->critSection );
+   RtlEnterHeapLock( &processHeap->lock );
 
    for (pptr = (HEAP**)&NtCurrentPeb()->ProcessHeaps; *pptr; pptr++)
    {
@@ -1752,7 +1757,7 @@ RtlValidateProcessHeaps(VOID)
       }
    }
 
-   RtlLeaveHeapLock( &processHeap->critSection );
+   RtlLeaveHeapLock( &processHeap->lock );
    return Result;
 }
 
@@ -1807,7 +1812,8 @@ NTAPI
 RtlSetUserFlagsHeap(IN PVOID HeapHandle,
                     IN ULONG Flags,
                     IN PVOID BaseAddress,
-                    IN ULONG UserFlags)
+                    IN ULONG UserFlagsReset,
+                    IN ULONG UserFlagsSet)
 {
     HEAP *heapPtr;
     PHEAP_USER_DATA udata;
@@ -1824,7 +1830,7 @@ RtlSetUserFlagsHeap(IN PVOID HeapHandle,
         udata = HEAP_AllocUserData(heapPtr, BaseAddress);
         if (!udata) return FALSE;
     }
-    udata->UserFlags = UserFlags & HEAP_SETTABLE_USER_FLAGS;
+    udata->UserFlags = UserFlagsSet & HEAP_SETTABLE_USER_FLAGS;
     return TRUE;
 }
 
@@ -1891,7 +1897,7 @@ NTAPI
 RtlExtendHeap(IN HANDLE Heap,
               IN ULONG Flags,
               IN PVOID P,
-              IN ULONG Size)
+              IN SIZE_T Size)
 {
     /* TODO */
     UNIMPLEMENTED;
@@ -1928,7 +1934,7 @@ RtlProtectHeap(IN PVOID HeapHandle,
     return NULL;
 }
 
-DWORD
+NTSTATUS
 NTAPI
 RtlSetHeapInformation(IN HANDLE HeapHandle OPTIONAL,
                       IN HEAP_INFORMATION_CLASS HeapInformationClass,
@@ -1939,7 +1945,7 @@ RtlSetHeapInformation(IN HANDLE HeapHandle OPTIONAL,
     return 0;
 }
 
-DWORD
+NTSTATUS
 NTAPI
 RtlQueryHeapInformation(HANDLE HeapHandle,
                         HEAP_INFORMATION_CLASS HeapInformationClass,
@@ -1947,27 +1953,49 @@ RtlQueryHeapInformation(HANDLE HeapHandle,
                         SIZE_T HeapInformationLength OPTIONAL,
                         PSIZE_T ReturnLength OPTIONAL)
 {
-    UNIMPLEMENTED;
-    return 0;
+    HEAP *heapPtr;
+
+    heapPtr = HEAP_GetPtr(HeapHandle);
+    if (!heapPtr)
+    {
+        RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_HANDLE );
+        return FALSE;
+    }
+
+    UNIMPLEMENTED
+
+    switch (HeapInformationClass)
+    {
+        case HeapCompatibilityInformation:
+            if (ReturnLength) *ReturnLength = sizeof(ULONG);
+
+            if (HeapInformationLength < sizeof(ULONG))
+                return STATUS_BUFFER_TOO_SMALL;
+
+            *(ULONG *)HeapInformation = 0; /* standard heap */
+            return STATUS_SUCCESS;
+        default:
+            return STATUS_INVALID_INFO_CLASS;
+    }
 }
 
-DWORD
+NTSTATUS
 NTAPI
 RtlMultipleAllocateHeap(IN PVOID HeapHandle,
-                        IN DWORD Flags,
+                        IN ULONG Flags,
                         IN SIZE_T Size,
-                        IN DWORD Count,
+                        IN ULONG Count,
                         OUT PVOID *Array)
 {
     UNIMPLEMENTED;
     return 0;
 }
 
-DWORD
+NTSTATUS
 NTAPI
 RtlMultipleFreeHeap(IN PVOID HeapHandle,
-                    IN DWORD Flags,
-                    IN DWORD Count,
+                    IN ULONG Flags,
+                    IN ULONG Count,
                     OUT PVOID *Array)
 {
     UNIMPLEMENTED;