[RFC PATCH 05/11] ntdll: Add extended heap type and LFH stubs.

Rémi Bernon rbernon at codeweavers.com
Wed May 6 07:09:57 CDT 2020


---
 dlls/ntdll/Makefile.in  |  1 +
 dlls/ntdll/heap.c       | 68 +++++++++++++++++++++++++++++++++++++----
 dlls/ntdll/heap_lfh.c   | 55 +++++++++++++++++++++++++++++++++
 dlls/ntdll/ntdll_misc.h | 12 ++++++++
 4 files changed, 130 insertions(+), 6 deletions(-)
 create mode 100644 dlls/ntdll/heap_lfh.c

diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in
index 7971ef98cf0f..5ec734a045e5 100644
--- a/dlls/ntdll/Makefile.in
+++ b/dlls/ntdll/Makefile.in
@@ -21,6 +21,7 @@ C_SRCS = \
 	file.c \
 	handletable.c \
 	heap.c \
+	heap_lfh.c \
 	large_int.c \
 	loader.c \
 	loadorder.c \
diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c
index 2d6c8e0ca19f..ca3d05450e71 100644
--- a/dlls/ntdll/heap.c
+++ b/dlls/ntdll/heap.c
@@ -164,6 +164,7 @@ typedef struct tagHEAP
     ARENA_INUSE    **pending_free;  /* Ring buffer for pending free requests */
     RTL_CRITICAL_SECTION critSection; /* Critical section for serialization */
     FREE_LIST_ENTRY *freeList;      /* Free lists */
+    int              extended_type; /* Extended heap type */
 } HEAP;
 
 #define HEAP_MAGIC       ((DWORD)('H' | ('E'<<8) | ('A'<<16) | ('P'<<24)))
@@ -1511,6 +1512,8 @@ void heap_set_debug_flags( HANDLE handle )
                                               MAX_FREE_PENDING * sizeof(*heap->pending_free) );
         heap->pending_pos = 0;
     }
+
+    HEAP_lfh_set_debug_flags( flags );
 }
 
 
@@ -1554,11 +1557,13 @@ HANDLE WINAPI RtlCreateHeap( ULONG flags, PVOID addr, SIZE_T totalSize, SIZE_T c
         HEAP *heapPtr = subheap->heap;
         RtlEnterCriticalSection( &processHeap->critSection );
         list_add_head( &processHeap->entry, &heapPtr->entry );
+        heapPtr->extended_type = HEAP_STD;
         RtlLeaveCriticalSection( &processHeap->critSection );
     }
     else if (!addr)
     {
         processHeap = subheap->heap;  /* assume the first heap we create is the process main heap */
+        processHeap->extended_type = HEAP_STD;
         list_init( &processHeap->entry );
     }
 
@@ -1644,6 +1649,7 @@ HANDLE WINAPI RtlDestroyHeap( HANDLE heap )
 void * WINAPI DECLSPEC_HOTPATCH RtlAllocateHeap( HANDLE heap, ULONG flags, SIZE_T size )
 {
     HEAP *heapPtr;
+    void *ptr;
 
     if (!(heapPtr = HEAP_GetPtr( heap )))
         return NULL;
@@ -1651,7 +1657,15 @@ void * WINAPI DECLSPEC_HOTPATCH RtlAllocateHeap( HANDLE heap, ULONG flags, SIZE_
     flags &= HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY;
     flags |= heapPtr->flags;
 
-    return HEAP_std_allocate( heapPtr, flags, size );
+    switch (heapPtr->extended_type)
+    {
+    case HEAP_LFH:
+        if ((ptr = HEAP_lfh_allocate( heapPtr, flags, size )))
+            return ptr;
+        /* fallthrough */
+    default:
+        return HEAP_std_allocate( heapPtr, flags, size );
+    }
 }
 
 void * HEAP_std_allocate( HEAP *heapPtr, ULONG flags, SIZE_T size )
@@ -1750,7 +1764,15 @@ BOOLEAN WINAPI DECLSPEC_HOTPATCH RtlFreeHeap( HANDLE heap, ULONG flags, void *pt
     flags &= HEAP_NO_SERIALIZE;
     flags |= heapPtr->flags;
 
-    return HEAP_std_free( heapPtr, flags, ptr );
+    switch (heapPtr->extended_type)
+    {
+    case HEAP_LFH:
+        if (HEAP_lfh_validate( heapPtr, flags, ptr ))
+            return HEAP_lfh_free( heapPtr, flags, ptr );
+        /* fallthrough */
+    default:
+        return HEAP_std_free( heapPtr, flags, ptr );
+    }
 }
 
 BOOLEAN HEAP_std_free( HEAP *heapPtr, ULONG flags, void *ptr )
@@ -1818,7 +1840,15 @@ PVOID WINAPI RtlReAllocateHeap( HANDLE heap, ULONG flags, PVOID ptr, SIZE_T size
              HEAP_REALLOC_IN_PLACE_ONLY;
     flags |= heapPtr->flags;
 
-    return HEAP_std_reallocate( heapPtr, flags, ptr, size );
+    switch (heapPtr->extended_type)
+    {
+    case HEAP_LFH:
+        if (HEAP_lfh_validate( heapPtr, flags, ptr ))
+            return HEAP_lfh_reallocate( heapPtr, flags, ptr, size );
+        /* fallthrough */
+    default:
+        return HEAP_std_reallocate( heapPtr, flags, ptr, size );
+    }
 }
 
 void *HEAP_std_reallocate( HEAP *heapPtr, ULONG flags, void *ptr, SIZE_T size )
@@ -2038,7 +2068,15 @@ SIZE_T WINAPI RtlSizeHeap( HANDLE heap, ULONG flags, const void *ptr )
     flags &= HEAP_NO_SERIALIZE;
     flags |= heapPtr->flags;
 
-    return HEAP_std_get_allocated_size( heapPtr, flags, ptr );
+    switch (heapPtr->extended_type)
+    {
+    case HEAP_LFH:
+        if (HEAP_lfh_validate( heapPtr, flags, ptr ))
+            return HEAP_lfh_get_allocated_size( heapPtr, flags, ptr );
+        /* fallthrough */
+    default:
+        return HEAP_std_get_allocated_size( heapPtr, flags, ptr );
+    }
 }
 
 SIZE_T HEAP_std_get_allocated_size( HEAP *heapPtr, ULONG flags, const void *ptr )
@@ -2095,7 +2133,17 @@ BOOLEAN WINAPI RtlValidateHeap( HANDLE heap, ULONG flags, LPCVOID ptr )
     flags &= HEAP_NO_SERIALIZE;
     flags |= heapPtr->flags;
 
-    return HEAP_std_validate( heapPtr, flags, ptr );
+    switch (heapPtr->extended_type)
+    {
+    case HEAP_LFH:
+        if (!HEAP_lfh_validate( heapPtr, flags, ptr ))
+            return FALSE;
+        /* only fallback to std heap if pointer is NULL or didn't validate */
+        if (ptr) return TRUE;
+        /* fallthrough */
+    default:
+        return HEAP_std_validate( heapPtr, flags, ptr );
+    }
 }
 
 BOOLEAN HEAP_std_validate( HEAP *heapPtr, ULONG flags, const void *ptr )
@@ -2268,6 +2316,13 @@ ULONG WINAPI RtlGetProcessHeaps( ULONG count, HANDLE *heaps )
 NTSTATUS WINAPI RtlQueryHeapInformation( HANDLE heap, HEAP_INFORMATION_CLASS info_class,
                                          PVOID info, SIZE_T size_in, PSIZE_T size_out)
 {
+    HEAP *heapPtr;
+
+    TRACE("%p %d %p %ld\n", heap, info_class, info, size_in);
+
+    if (!(heapPtr = HEAP_GetPtr( heap )))
+        return STATUS_INVALID_PARAMETER;
+
     switch (info_class)
     {
     case HeapCompatibilityInformation:
@@ -2276,7 +2331,7 @@ NTSTATUS WINAPI RtlQueryHeapInformation( HANDLE heap, HEAP_INFORMATION_CLASS inf
         if (size_in < sizeof(ULONG))
             return STATUS_BUFFER_TOO_SMALL;
 
-        *(ULONG *)info = 0; /* standard heap */
+        *(ULONG *)info = heapPtr->extended_type;
         return STATUS_SUCCESS;
 
     default:
@@ -2296,4 +2351,5 @@ NTSTATUS WINAPI RtlSetHeapInformation( HANDLE heap, HEAP_INFORMATION_CLASS info_
 
 void HEAP_notify_thread_destroy( BOOLEAN last )
 {
+    HEAP_lfh_notify_thread_destroy( last );
 }
diff --git a/dlls/ntdll/heap_lfh.c b/dlls/ntdll/heap_lfh.c
new file mode 100644
index 000000000000..8dc3a3914839
--- /dev/null
+++ b/dlls/ntdll/heap_lfh.c
@@ -0,0 +1,55 @@
+/*
+ * Wine Low Fragmentation Heap
+ *
+ * Copyright 2020 Remi Bernon for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "ntdll_misc.h"
+
+void *HEAP_lfh_allocate(struct tagHEAP *std_heap, ULONG flags, SIZE_T size)
+{
+    return NULL;
+}
+
+BOOLEAN HEAP_lfh_free(struct tagHEAP *std_heap, ULONG flags, void *ptr)
+{
+    return FALSE;
+}
+
+void *HEAP_lfh_reallocate(struct tagHEAP *std_heap, ULONG flags, void *ptr, SIZE_T size)
+{
+    return NULL;
+}
+
+SIZE_T HEAP_lfh_get_allocated_size(struct tagHEAP *std_heap, ULONG flags, const void *ptr)
+{
+    return ~(SIZE_T)0;
+}
+
+BOOLEAN HEAP_lfh_validate(struct tagHEAP *std_heap, ULONG flags, const void *ptr)
+{
+    if (ptr) return FALSE;
+    else return TRUE;
+}
+
+void HEAP_lfh_notify_thread_destroy(BOOLEAN last)
+{
+}
+
+void HEAP_lfh_set_debug_flags(ULONG flags)
+{
+}
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
index 3369eb980a5f..fbf01b729df0 100644
--- a/dlls/ntdll/ntdll_misc.h
+++ b/dlls/ntdll/ntdll_misc.h
@@ -283,6 +283,10 @@ static inline int get_unix_exit_code( NTSTATUS status )
     return status;
 }
 
+#define HEAP_STD 0
+#define HEAP_LAL 1
+#define HEAP_LFH 2
+
 struct tagHEAP;
 void   *HEAP_std_allocate( struct tagHEAP *heap, ULONG flags, SIZE_T size );
 BOOLEAN HEAP_std_free( struct tagHEAP *heap, ULONG flags, void *ptr );
@@ -290,7 +294,15 @@ void   *HEAP_std_reallocate( struct tagHEAP *heap, ULONG flags, void *ptr, SIZE_
 SIZE_T  HEAP_std_get_allocated_size( struct tagHEAP *heap, ULONG flags, const void *ptr );
 BOOLEAN HEAP_std_validate( struct tagHEAP *heap, ULONG flags, const void *ptr );
 
+void   *HEAP_lfh_allocate( struct tagHEAP *std_heap, ULONG flags, SIZE_T size );
+BOOLEAN HEAP_lfh_free( struct tagHEAP *std_heap, ULONG flags, void *ptr );
+void   *HEAP_lfh_reallocate( struct tagHEAP *std_heap, ULONG flags, void *ptr, SIZE_T size );
+SIZE_T  HEAP_lfh_get_allocated_size( struct tagHEAP *std_heap, ULONG flags, const void *ptr );
+BOOLEAN HEAP_lfh_validate( struct tagHEAP *std_heap, ULONG flags, const void *ptr );
+
 void HEAP_notify_thread_destroy( BOOLEAN last );
+void HEAP_lfh_notify_thread_destroy( BOOLEAN last );
+void HEAP_lfh_set_debug_flags( ULONG flags );
 
 extern mode_t FILE_umask DECLSPEC_HIDDEN;
 extern HANDLE keyed_event DECLSPEC_HIDDEN;
-- 
2.26.1




More information about the wine-devel mailing list