Missing commit routine support was mentioned here https://bugs.winehq.org/show_bug.cgi?id=56016. It's not clear how useful it is to implement yet.
-- v2: ntdll/tests: Add some tests for creating custom heaps.
From: Nikolay Sivov nsivov@codeweavers.com
--- dlls/ntdll/heap.c | 20 +++----------------- include/winternl.h | 22 +++++++++++++++++----- tools/winapi/win32.api | 2 +- 3 files changed, 21 insertions(+), 23 deletions(-)
diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c index 4dc3e7296b6..ec4e376bd4b 100644 --- a/dlls/ntdll/heap.c +++ b/dlls/ntdll/heap.c @@ -1490,23 +1490,9 @@ static void heap_set_debug_flags( HANDLE handle )
/*********************************************************************** * RtlCreateHeap (NTDLL.@) - * - * Create a new Heap. - * - * PARAMS - * flags [I] HEAP_ flags from "winnt.h" - * addr [I] Desired base address - * totalSize [I] Total size of the heap, or 0 for a growable heap - * commitSize [I] Amount of heap space to commit - * unknown [I] Not yet understood - * definition [I] Heap definition - * - * RETURNS - * Success: A HANDLE to the newly created heap. - * Failure: a NULL HANDLE. */ HANDLE WINAPI RtlCreateHeap( ULONG flags, void *addr, SIZE_T total_size, SIZE_T commit_size, - void *unknown, RTL_HEAP_DEFINITION *definition ) + void *lock, RTL_HEAP_PARAMETERS *params ) { struct entry *entry; struct heap *heap; @@ -1514,8 +1500,8 @@ HANDLE WINAPI RtlCreateHeap( ULONG flags, void *addr, SIZE_T total_size, SIZE_T SUBHEAP *subheap; unsigned int i;
- TRACE( "flags %#lx, addr %p, total_size %#Ix, commit_size %#Ix, unknown %p, definition %p\n", - flags, addr, total_size, commit_size, unknown, definition ); + TRACE( "flags %#lx, addr %p, total_size %#Ix, commit_size %#Ix, lock %p, params %p\n", + flags, addr, total_size, commit_size, lock, params );
flags &= ~(HEAP_TAIL_CHECKING_ENABLED|HEAP_FREE_CHECKING_ENABLED); if (process_heap) flags |= HEAP_PRIVATE; diff --git a/include/winternl.h b/include/winternl.h index ff8756211a1..b1687349ff6 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -2577,11 +2577,23 @@ typedef struct _PROCESS_STACK_ALLOCATION_INFORMATION_EX PROCESS_STACK_ALLOCATION_INFORMATION AllocInfo; } PROCESS_STACK_ALLOCATION_INFORMATION_EX, *PPROCESS_STACK_ALLOCATION_INFORMATION_EX;
-typedef struct _RTL_HEAP_DEFINITION { - ULONG Length; /* = sizeof(RTL_HEAP_DEFINITION) */ +typedef NTSTATUS (NTAPI RTL_HEAP_COMMIT_ROUTINE)(PVOID base, PVOID *address, PSIZE_T size); +typedef RTL_HEAP_COMMIT_ROUTINE *PRTL_HEAP_COMMIT_ROUTINE;
- ULONG Unknown[11]; -} RTL_HEAP_DEFINITION, *PRTL_HEAP_DEFINITION; +typedef struct _RTL_HEAP_PARAMETERS +{ + ULONG Length; + SIZE_T SegmentReserve; + SIZE_T SegmentCommit; + SIZE_T DeCommitFreeblockThreshold; + SIZE_T DeCommitTotalFreeThreshold; + SIZE_T MaximumAllocationSize; + SIZE_T VirtualMemoryThreshold; + SIZE_T InitialCommit; + SIZE_T InitialReserve; + PRTL_HEAP_COMMIT_ROUTINE CommitRoutine; + SIZE_T Reserved[2]; +} RTL_HEAP_PARAMETERS, *PRTL_HEAP_PARAMETERS;
typedef struct _RTL_RWLOCK { RTL_CRITICAL_SECTION rtlCS; @@ -4665,7 +4677,7 @@ NTSYSAPI NTSTATUS WINAPI RtlCreateAcl(PACL,DWORD,DWORD); NTSYSAPI NTSTATUS WINAPI RtlCreateActivationContext(HANDLE*,const void*); NTSYSAPI NTSTATUS WINAPI RtlCreateAtomTable(ULONG,RTL_ATOM_TABLE*); NTSYSAPI NTSTATUS WINAPI RtlCreateEnvironment(BOOLEAN, PWSTR*); -NTSYSAPI HANDLE WINAPI RtlCreateHeap(ULONG,PVOID,SIZE_T,SIZE_T,PVOID,PRTL_HEAP_DEFINITION); +NTSYSAPI HANDLE WINAPI RtlCreateHeap(ULONG,PVOID,SIZE_T,SIZE_T,PVOID,PRTL_HEAP_PARAMETERS); NTSYSAPI NTSTATUS WINAPI RtlCreateProcessParameters(RTL_USER_PROCESS_PARAMETERS**,const UNICODE_STRING*,const UNICODE_STRING*,const UNICODE_STRING*,const UNICODE_STRING*,PWSTR,const UNICODE_STRING*,const UNICODE_STRING*,const UNICODE_STRING*,const UNICODE_STRING*); NTSYSAPI NTSTATUS WINAPI RtlCreateProcessParametersEx(RTL_USER_PROCESS_PARAMETERS**,const UNICODE_STRING*,const UNICODE_STRING*,const UNICODE_STRING*,const UNICODE_STRING*,PWSTR,const UNICODE_STRING*,const UNICODE_STRING*,const UNICODE_STRING*,const UNICODE_STRING*,ULONG); NTSYSAPI PDEBUG_BUFFER WINAPI RtlCreateQueryDebugBuffer(ULONG,BOOLEAN); diff --git a/tools/winapi/win32.api b/tools/winapi/win32.api index db3c8e7941e..9e40b61654a 100644 --- a/tools/winapi/win32.api +++ b/tools/winapi/win32.api @@ -3344,7 +3344,7 @@ POBJECT_ATTRIBUTES PPRIVILEGE_SET PRTL_BITMAP PRTL_BITMAP_RUN -PRTL_HEAP_DEFINITION +PRTL_HEAP_PARAMETERS PRTL_QUERY_REGISTRY_TABLE PRTL_THREAD_START_ROUTINE PRTL_USER_PROCESS_PARAMETERS
From: Nikolay Sivov nsivov@codeweavers.com
--- dlls/ntdll/tests/rtl.c | 72 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+)
diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c index 442ad729540..03c31d7bf6b 100644 --- a/dlls/ntdll/tests/rtl.c +++ b/dlls/ntdll/tests/rtl.c @@ -3565,6 +3565,77 @@ static void test_RtlDestroyHeap(void) RtlRemoveVectoredExceptionHandler( handler ); }
+struct commit_routine_context +{ + void *base; + SIZE_T size; +}; + +static struct commit_routine_context commit_context; + +static NTSTATUS NTAPI test_commit_routine(void *base, void **address, SIZE_T *size) +{ + commit_context.base = base; + commit_context.size = *size; + + return VirtualAlloc(*address, *size, MEM_COMMIT, PAGE_READWRITE) ? 0 : STATUS_ASSERTION_FAILURE; +} + +static void test_RtlCreateHeap(void) +{ + void *ptr, *base, *reserve; + RTL_HEAP_PARAMETERS params; + HANDLE heap; + BOOL ret; + + heap = RtlCreateHeap(0, NULL, 0, 0, NULL, NULL); + ok(!!heap, "Failed to create a heap.\n"); + RtlDestroyHeap(heap); + + memset(¶ms, 0, sizeof(params)); + heap = RtlCreateHeap(0, NULL, 0, 0, NULL, ¶ms); + ok(!!heap, "Failed to create a heap.\n"); + RtlDestroyHeap(heap); + + params.Length = 1; + heap = RtlCreateHeap(0, NULL, 0, 0, NULL, ¶ms); + ok(!!heap, "Failed to create a heap.\n"); + RtlDestroyHeap(heap); + + params.Length = sizeof(params); + params.CommitRoutine = test_commit_routine; + params.InitialCommit = 0x1000; + params.InitialReserve = 0x10000; + + heap = RtlCreateHeap(0, NULL, 0, 0, NULL, ¶ms); + todo_wine + ok(!heap, "Unexpected heap.\n"); + if (heap) + RtlDestroyHeap(heap); + + reserve = VirtualAlloc(NULL, 0x10000, MEM_RESERVE, PAGE_READWRITE); + base = VirtualAlloc(reserve, 0x1000, MEM_COMMIT, PAGE_READWRITE); + ok(!!base, "Unexpected pointer.\n"); + + heap = RtlCreateHeap(0, base, 0, 0, NULL, ¶ms); + ok(!!heap, "Unexpected heap.\n"); + + /* Using block size above initially committed size to trigger + new allocation via user callback. */ + ptr = RtlAllocateHeap(heap, 0, 0x4000); + ok(!!ptr, "Failed to allocate a block.\n"); + todo_wine + ok(commit_context.base == base, "Unexpected base %p.\n", commit_context.base); + todo_wine + ok(!!commit_context.size, "Unexpected allocation size.\n"); + RtlFreeHeap(heap, 0, ptr); + RtlDestroyHeap(heap); + + ret = VirtualFree(reserve, 0, MEM_RELEASE); + todo_wine + ok(ret, "Unexpected return value.\n"); +} + static void test_RtlFirstFreeAce(void) { PACL acl; @@ -3711,6 +3782,7 @@ START_TEST(rtl) test_LdrRegisterDllNotification(); test_DbgPrint(); test_RtlDestroyHeap(); + test_RtlCreateHeap(); test_RtlFirstFreeAce(); test_RtlInitializeSid(); test_RtlValidSecurityDescriptor();