From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/kernel32/tests/heap.c | 3 --- dlls/ntdll/heap.c | 26 +++++++++++++++++--------- 2 files changed, 17 insertions(+), 12 deletions(-)
diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c index 91f582f36de..99602bd2969 100644 --- a/dlls/kernel32/tests/heap.c +++ b/dlls/kernel32/tests/heap.c @@ -354,9 +354,7 @@ static void test_HeapCreate(void) ok( !!ptrs[i], "HeapAlloc failed, error %lu\n", GetLastError() ); align |= (UINT_PTR)ptrs[i]; } - todo_wine_if( sizeof(void *) == 8 ) ok( !(align & (8 * sizeof(void *) - 1)), "got wrong alignment\n" ); - todo_wine_if( sizeof(void *) == 8 ) ok( align & (8 * sizeof(void *)), "got wrong alignment\n" ); for (i = 0; i < ARRAY_SIZE(ptrs); ++i) { @@ -2228,7 +2226,6 @@ static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags ok( !!ptr2, "HeapAlloc failed, error %lu\n", GetLastError() );
align = (UINT_PTR)ptr0 | (UINT_PTR)ptr1 | (UINT_PTR)ptr2; - todo_wine_if( sizeof(void *) == 8 || alloc_size == 0x7efe9 ) ok( !(align & (8 * sizeof(void *) - 1)), "wrong align\n" );
expect_size = max( alloc_size, 2 * sizeof(void *) ); diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c index 0ecff6f6cba..3184ae43dab 100644 --- a/dlls/ntdll/heap.c +++ b/dlls/ntdll/heap.c @@ -91,6 +91,7 @@ C_ASSERT( sizeof(struct block) == 8 ); #define BLOCK_FLAG_FREE 0x00000001 #define BLOCK_FLAG_PREV_FREE 0x00000002 #define BLOCK_FLAG_FREE_LINK 0x00000003 +#define BLOCK_FLAG_LARGE 0x00000004
/* entry to link free blocks in free lists */ @@ -103,18 +104,21 @@ struct DECLSPEC_ALIGN(ALIGNMENT) entry
C_ASSERT( sizeof(struct entry) == 2 * ALIGNMENT );
-typedef struct +typedef struct region { + SIZE_T __pad[sizeof(SIZE_T) / sizeof(DWORD)]; struct list entry; /* entry in heap large blocks list */ SIZE_T data_size; /* size of user data */ SIZE_T block_size; /* total size of virtual memory block */ - DWORD pad[2]; /* padding to ensure 16-byte alignment of data */ - DWORD size; /* fields for compatibility with normal arenas */ - DWORD magic; /* these must remain at the end of the structure */ + SIZE_T pad; /* padding to ensure 16-byte alignment of data */ + struct block block; } ARENA_LARGE;
+/* block must be last and aligned */ +C_ASSERT( sizeof(struct region) == offsetof(struct region, block) + sizeof(struct block) ); +C_ASSERT( sizeof(struct region) == 4 * ALIGNMENT ); + #define ARENA_SIZE_MASK (~3) -#define ARENA_LARGE_SIZE 0xfedcba90 /* magic value for 'size' field in large blocks */
/* Value for arena 'magic' field */ #define ARENA_INUSE_MAGIC 0x455355 @@ -800,8 +804,8 @@ static void *allocate_large_block( HEAP *heap, DWORD flags, SIZE_T size ) arena = address; arena->data_size = size; arena->block_size = block_size; - arena->size = ARENA_LARGE_SIZE; - arena->magic = ARENA_LARGE_MAGIC; + block_set_type( &arena->block, ARENA_LARGE_MAGIC ); + block_set_size( &arena->block, BLOCK_FLAG_LARGE, 0 ); list_add_tail( &heap->large_list, &arena->entry ); valgrind_make_noaccess( (char *)arena + sizeof(*arena) + arena->data_size, arena->block_size - sizeof(*arena) - arena->data_size ); @@ -875,8 +879,12 @@ static BOOL validate_large_arena( const HEAP *heap, const ARENA_LARGE *arena )
if ((ULONG_PTR)arena & COMMIT_MASK) err = "invalid block alignment"; - else if (arena->size != ARENA_LARGE_SIZE || arena->magic != ARENA_LARGE_MAGIC) - err = "invalid block header"; + else if (block_get_size( &arena->block )) + err = "invalid block size"; + else if (block_get_flags( &arena->block ) != BLOCK_FLAG_LARGE) + err = "invalid block flags"; + else if (block_get_type( &arena->block ) != ARENA_LARGE_MAGIC) + err = "invalid block type"; else if (!contains( arena, arena->block_size, arena + 1, arena->data_size )) err = "invalid block size";
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntdll/heap.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c index 3184ae43dab..3ac819a37ac 100644 --- a/dlls/ntdll/heap.c +++ b/dlls/ntdll/heap.c @@ -368,17 +368,21 @@ static inline void mark_block_tail( struct block *block, DWORD flags ) }
/* initialize contents of a newly created block of memory */ -static inline void initialize_block( void *ptr, SIZE_T size, DWORD flags ) +static inline void initialize_block( struct block *block, SIZE_T old_size, SIZE_T size, DWORD flags ) { + char *data = (char *)(block + 1); + + if (size <= old_size) return; + if (flags & HEAP_ZERO_MEMORY) { - valgrind_make_writable( ptr, size ); - memset( ptr, 0, size ); + valgrind_make_writable( data + old_size, size - old_size ); + memset( data + old_size, 0, size - old_size ); } else if (flags & HEAP_FREE_CHECKING_ENABLED) { - valgrind_make_writable( ptr, size ); - memset( ptr, ARENA_INUSE_FILLER, size ); + valgrind_make_writable( data + old_size, size - old_size ); + memset( data + old_size, ARENA_INUSE_FILLER, size - old_size ); } }
@@ -840,7 +844,7 @@ static void *realloc_large_block( HEAP *heap, DWORD flags, void *ptr, SIZE_T siz { /* FIXME: we could remap zero-pages instead */ valgrind_notify_resize( arena + 1, old_size, size ); - if (size > old_size) initialize_block( (char *)ptr + old_size, size - old_size, flags ); + initialize_block( &arena->block, old_size, size, flags ); arena->data_size = size; valgrind_make_noaccess( (char *)arena + sizeof(*arena) + arena->data_size, arena->block_size - sizeof(*arena) - arena->data_size ); @@ -1522,7 +1526,7 @@ static NTSTATUS heap_allocate( HEAP *heap, ULONG flags, SIZE_T size, void **ret
block_set_type( block, ARENA_INUSE_MAGIC ); shrink_used_block( subheap, block, 0, old_block_size, block_size, size ); - initialize_block( block + 1, size, flags ); + initialize_block( block, 0, size, flags ); mark_block_tail( block, flags );
*ret = block + 1; @@ -1643,7 +1647,7 @@ static NTSTATUS heap_reallocate( HEAP *heap, ULONG flags, void *ptr, SIZE_T size valgrind_notify_resize( block + 1, old_size, size ); shrink_used_block( subheap, block, block_get_flags( block ), old_block_size, block_size, size );
- if (size > old_size) initialize_block( (char *)(block + 1) + old_size, size - old_size, flags ); + initialize_block( block, old_size, size, flags ); mark_block_tail( block, flags );
/* Return the new arena */
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntdll/heap.c | 115 ++++++++++++++++++++++------------------------ 1 file changed, 56 insertions(+), 59 deletions(-)
diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c index 3ac819a37ac..afbf8703da0 100644 --- a/dlls/ntdll/heap.c +++ b/dlls/ntdll/heap.c @@ -162,15 +162,13 @@ static const SIZE_T free_list_sizes[] = }; #define HEAP_NB_FREE_LISTS (ARRAY_SIZE(free_list_sizes) + HEAP_NB_SMALL_FREE_LISTS)
-struct tagHEAP; - typedef struct DECLSPEC_ALIGN(ALIGNMENT) tagSUBHEAP { SIZE_T __pad[sizeof(SIZE_T) / sizeof(DWORD)]; SIZE_T size; /* Size of the whole sub-heap */ SIZE_T commitSize; /* Committed size of the sub-heap */ struct list entry; /* Entry in sub-heap list */ - struct tagHEAP *heap; /* Main heap structure */ + struct heap *heap; /* Main heap structure */ struct block block; } SUBHEAP;
@@ -178,7 +176,7 @@ typedef struct DECLSPEC_ALIGN(ALIGNMENT) tagSUBHEAP C_ASSERT( sizeof(SUBHEAP) == offsetof(SUBHEAP, block) + sizeof(struct block) ); C_ASSERT( sizeof(SUBHEAP) == 4 * ALIGNMENT );
-typedef struct tagHEAP +struct heap { /* win32/win64 */ DWORD_PTR unknown1[2]; /* 0000/0000 */ DWORD ffeeffee; /* 0008/0010 */ @@ -202,12 +200,12 @@ typedef struct tagHEAP RTL_CRITICAL_SECTION cs; struct entry free_lists[HEAP_NB_FREE_LISTS]; SUBHEAP subheap; -} HEAP; +};
/* subheap must be last and aligned */ -C_ASSERT( sizeof(HEAP) == offsetof(HEAP, subheap) + sizeof(SUBHEAP) ); -C_ASSERT( sizeof(HEAP) % ALIGNMENT == 0 ); -C_ASSERT( offsetof(HEAP, subheap) <= COMMIT_MASK ); +C_ASSERT( sizeof(struct heap) == offsetof(struct heap, subheap) + sizeof(SUBHEAP) ); +C_ASSERT( sizeof(struct heap) % ALIGNMENT == 0 ); +C_ASSERT( offsetof(struct heap, subheap) <= COMMIT_MASK );
#define HEAP_MAGIC ((DWORD)('H' | ('E'<<8) | ('A'<<16) | ('P'<<24)))
@@ -222,7 +220,7 @@ C_ASSERT( offsetof(HEAP, subheap) <= COMMIT_MASK ); #define HEAP_VALIDATE_PARAMS 0x40000000 #define HEAP_CHECKING_ENABLED 0x80000000
-static HEAP *processHeap; /* main process heap */ +static struct heap *processHeap; /* main process heap */
/* check if memory range a contains memory range b */ static inline BOOL contains( const void *a, SIZE_T a_size, const void *b, SIZE_T b_size ) @@ -312,7 +310,7 @@ static inline BOOL check_subheap( const SUBHEAP *subheap ) return contains( base, subheap->size, &subheap->block, base + subheap->commitSize - (char *)&subheap->block ); }
-static BOOL heap_validate( const HEAP *heap ); +static BOOL heap_validate( const struct heap *heap );
/* mark a block of memory as innacessible for debugging purposes */ static inline void valgrind_make_noaccess( void const *ptr, SIZE_T size ) @@ -428,7 +426,7 @@ static void valgrind_notify_free_all( SUBHEAP *subheap )
/* locate a free list entry of the appropriate size */ /* size is the size of the whole block including the arena header */ -static inline struct entry *find_free_list( HEAP *heap, SIZE_T block_size, BOOL last ) +static inline struct entry *find_free_list( struct heap *heap, SIZE_T block_size, BOOL last ) { struct entry *list, *end = heap->free_lists + ARRAY_SIZE(heap->free_lists); unsigned int i; @@ -456,32 +454,32 @@ static RTL_CRITICAL_SECTION_DEBUG process_heap_cs_debug = 0, 0, { (DWORD_PTR)(__FILE__ ": main process heap section") } };
-static inline ULONG heap_get_flags( const HEAP *heap, ULONG flags ) +static inline ULONG heap_get_flags( const struct heap *heap, ULONG flags ) { if (flags & (HEAP_TAIL_CHECKING_ENABLED | HEAP_FREE_CHECKING_ENABLED)) flags |= HEAP_CHECKING_ENABLED; flags &= HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY | HEAP_REALLOC_IN_PLACE_ONLY | HEAP_CHECKING_ENABLED; return heap->flags | flags; }
-static void heap_lock( HEAP *heap, ULONG flags ) +static void heap_lock( struct heap *heap, ULONG flags ) { if (heap_get_flags( heap, flags ) & HEAP_NO_SERIALIZE) return; RtlEnterCriticalSection( &heap->cs ); }
-static void heap_unlock( HEAP *heap, ULONG flags ) +static void heap_unlock( struct heap *heap, ULONG flags ) { if (heap_get_flags( heap, flags ) & HEAP_NO_SERIALIZE) return; RtlLeaveCriticalSection( &heap->cs ); }
-static void heap_set_status( const HEAP *heap, ULONG flags, NTSTATUS status ) +static void heap_set_status( const struct heap *heap, ULONG flags, NTSTATUS status ) { if (status == STATUS_NO_MEMORY && (flags & HEAP_GENERATE_EXCEPTIONS)) RtlRaiseStatus( status ); if (status) RtlSetLastWin32ErrorAndNtStatusFromNtStatus( status ); }
-static void heap_dump( const HEAP *heap ) +static void heap_dump( const struct heap *heap ) { const struct block *block; const ARENA_LARGE *large; @@ -490,7 +488,7 @@ static void heap_dump( const HEAP *heap ) SIZE_T size;
TRACE( "heap: %p\n", heap ); - TRACE( " next %p\n", LIST_ENTRY( heap->entry.next, HEAP, entry ) ); + TRACE( " next %p\n", LIST_ENTRY( heap->entry.next, struct heap, entry ) );
TRACE( " free_lists: %p\n", heap->free_lists ); for (i = 0; i < HEAP_NB_FREE_LISTS; i++) @@ -582,10 +580,9 @@ static const char *debugstr_heap_entry( struct rtl_heap_entry *entry ) * Pointer to the heap * NULL: Failure */ -static HEAP *HEAP_GetPtr( - HANDLE heap /* [in] Handle to the heap */ -) { - HEAP *heapPtr = heap; +static struct heap *HEAP_GetPtr( HANDLE heap ) +{ + struct heap *heapPtr = heap; BOOL valid = TRUE;
if (!heapPtr || (heapPtr->magic != HEAP_MAGIC)) @@ -610,7 +607,7 @@ static HEAP *HEAP_GetPtr( }
-static SUBHEAP *find_subheap( const HEAP *heap, const struct block *block, BOOL heap_walk ) +static SUBHEAP *find_subheap( const struct heap *heap, const struct block *block, BOOL heap_walk ) { SUBHEAP *subheap;
@@ -630,7 +627,7 @@ static SUBHEAP *find_subheap( const HEAP *heap, const struct block *block, BOOL static inline BOOL subheap_commit( SUBHEAP *subheap, const struct block *block, SIZE_T block_size ) { const char *end = (char *)subheap_base( subheap ) + subheap_size( subheap ), *commit_end; - HEAP *heap = subheap->heap; + struct heap *heap = subheap->heap; ULONG flags = heap->flags; SIZE_T size; void *addr; @@ -658,7 +655,7 @@ static inline BOOL subheap_commit( SUBHEAP *subheap, const struct block *block, static inline BOOL subheap_decommit( SUBHEAP *subheap, const void *commit_end ) { char *base = subheap_base( subheap ); - HEAP *heap = subheap->heap; + struct heap *heap = subheap->heap; SIZE_T size; void *addr;
@@ -684,7 +681,7 @@ static void create_free_block( SUBHEAP *subheap, struct block *block, SIZE_T blo { const char *end = (char *)block + block_size, *commit_end = subheap_commit_end( subheap ); struct entry *entry = (struct entry *)block, *list; - HEAP *heap = subheap->heap; + struct heap *heap = subheap->heap; DWORD flags = heap->flags; struct block *next;
@@ -723,7 +720,7 @@ static void create_free_block( SUBHEAP *subheap, struct block *block, SIZE_T blo
static void free_used_block( SUBHEAP *subheap, struct block *block ) { - HEAP *heap = subheap->heap; + struct heap *heap = subheap->heap; struct entry *entry; SIZE_T block_size;
@@ -791,7 +788,7 @@ static inline void shrink_used_block( SUBHEAP *subheap, struct block *block, UIN /*********************************************************************** * allocate_large_block */ -static void *allocate_large_block( HEAP *heap, DWORD flags, SIZE_T size ) +static void *allocate_large_block( struct heap *heap, DWORD flags, SIZE_T size ) { ARENA_LARGE *arena; SIZE_T block_size = ROUND_SIZE( sizeof(*arena) + size, COMMIT_MASK ); @@ -820,7 +817,7 @@ static void *allocate_large_block( HEAP *heap, DWORD flags, SIZE_T size ) /*********************************************************************** * free_large_block */ -static void free_large_block( HEAP *heap, void *ptr ) +static void free_large_block( struct heap *heap, void *ptr ) { ARENA_LARGE *arena = (ARENA_LARGE *)ptr - 1; LPVOID address = arena; @@ -834,7 +831,7 @@ static void free_large_block( HEAP *heap, void *ptr ) /*********************************************************************** * realloc_large_block */ -static void *realloc_large_block( HEAP *heap, DWORD flags, void *ptr, SIZE_T size ) +static void *realloc_large_block( struct heap *heap, DWORD flags, void *ptr, SIZE_T size ) { ARENA_LARGE *arena = (ARENA_LARGE *)ptr - 1; SIZE_T old_size = arena->data_size; @@ -867,7 +864,7 @@ static void *realloc_large_block( HEAP *heap, DWORD flags, void *ptr, SIZE_T siz /*********************************************************************** * find_large_block */ -static ARENA_LARGE *find_large_block( const HEAP *heap, const void *ptr ) +static ARENA_LARGE *find_large_block( const struct heap *heap, const void *ptr ) { ARENA_LARGE *arena;
@@ -877,7 +874,7 @@ static ARENA_LARGE *find_large_block( const HEAP *heap, const void *ptr ) return NULL; }
-static BOOL validate_large_arena( const HEAP *heap, const ARENA_LARGE *arena ) +static BOOL validate_large_arena( const struct heap *heap, const ARENA_LARGE *arena ) { const char *err = NULL;
@@ -904,7 +901,7 @@ static BOOL validate_large_arena( const HEAP *heap, const ARENA_LARGE *arena ) /*********************************************************************** * HEAP_CreateSubHeap */ -static SUBHEAP *HEAP_CreateSubHeap( HEAP *heap, LPVOID address, DWORD flags, +static SUBHEAP *HEAP_CreateSubHeap( struct heap *heap, LPVOID address, DWORD flags, SIZE_T commitSize, SIZE_T totalSize ) { struct entry *pEntry; @@ -1016,7 +1013,7 @@ static SUBHEAP *HEAP_CreateSubHeap( HEAP *heap, LPVOID address, DWORD flags, }
-static struct block *find_free_block( HEAP *heap, SIZE_T block_size, SUBHEAP **subheap ) +static struct block *find_free_block( struct heap *heap, SIZE_T block_size, SUBHEAP **subheap ) { struct list *ptr = &find_free_list( heap, block_size, FALSE )->entry; struct entry *entry; @@ -1072,7 +1069,7 @@ static struct block *find_free_block( HEAP *heap, SIZE_T block_size, SUBHEAP **s }
-static BOOL is_valid_free_block( const HEAP *heap, const struct block *block ) +static BOOL is_valid_free_block( const struct heap *heap, const struct block *block ) { const SUBHEAP *subheap; unsigned int i; @@ -1086,8 +1083,8 @@ static BOOL validate_free_block( const SUBHEAP *subheap, const struct block *blo { const char *err = NULL, *base = subheap_base( subheap ), *commit_end = subheap_commit_end( subheap ); const struct entry *entry = (struct entry *)block; + struct heap *heap = subheap->heap; const struct block *prev, *next; - HEAP *heap = subheap->heap; DWORD flags = heap->flags;
if ((ULONG_PTR)(block + 1) % ALIGNMENT) @@ -1139,7 +1136,7 @@ static BOOL validate_free_block( const SUBHEAP *subheap, const struct block *blo static BOOL validate_used_block( const SUBHEAP *subheap, const struct block *block ) { const char *err = NULL, *base = subheap_base( subheap ), *commit_end = subheap_commit_end( subheap ); - const HEAP *heap = subheap->heap; + const struct heap *heap = subheap->heap; DWORD flags = heap->flags; const struct block *next; int i; @@ -1192,7 +1189,7 @@ static BOOL validate_used_block( const SUBHEAP *subheap, const struct block *blo }
-static BOOL heap_validate_ptr( const HEAP *heap, const void *ptr, SUBHEAP **subheap ) +static BOOL heap_validate_ptr( const struct heap *heap, const void *ptr, SUBHEAP **subheap ) { const struct block *arena = (struct block *)ptr - 1; const ARENA_LARGE *large_arena; @@ -1211,7 +1208,7 @@ static BOOL heap_validate_ptr( const HEAP *heap, const void *ptr, SUBHEAP **subh return validate_used_block( *subheap, arena ); }
-static BOOL heap_validate( const HEAP *heap ) +static BOOL heap_validate( const struct heap *heap ) { const ARENA_LARGE *large_arena; const struct block *block; @@ -1245,7 +1242,7 @@ static BOOL heap_validate( const HEAP *heap ) return TRUE; }
-static inline struct block *unsafe_block_from_ptr( const HEAP *heap, const void *ptr, SUBHEAP **subheap ) +static inline struct block *unsafe_block_from_ptr( const struct heap *heap, const void *ptr, SUBHEAP **subheap ) { struct block *block = (struct block *)ptr - 1; const char *err = NULL, *base, *commit_end; @@ -1305,7 +1302,7 @@ static DWORD heap_flags_from_global_flag( DWORD flag ) */ static void heap_set_debug_flags( HANDLE handle ) { - HEAP *heap = HEAP_GetPtr( handle ); + struct heap *heap = HEAP_GetPtr( handle ); ULONG global_flags = RtlGetNtGlobalFlags(); DWORD flags, force_flags;
@@ -1382,8 +1379,8 @@ static void heap_set_debug_flags( HANDLE handle ) HANDLE WINAPI RtlCreateHeap( ULONG flags, PVOID addr, SIZE_T totalSize, SIZE_T commitSize, PVOID unknown, PRTL_HEAP_DEFINITION definition ) { + struct heap *heap; SUBHEAP *subheap; - HEAP *heap;
/* Allocate the heap block */
@@ -1428,7 +1425,7 @@ HANDLE WINAPI RtlCreateHeap( ULONG flags, PVOID addr, SIZE_T totalSize, SIZE_T c */ HANDLE WINAPI RtlDestroyHeap( HANDLE heap ) { - HEAP *heapPtr = HEAP_GetPtr( heap ); + struct heap *heapPtr = HEAP_GetPtr( heap ); SUBHEAP *subheap, *next; ARENA_LARGE *arena, *arena_next; struct block **pending, **tmp; @@ -1436,7 +1433,7 @@ HANDLE WINAPI RtlDestroyHeap( HANDLE heap ) void *addr;
TRACE("%p\n", heap ); - if (!heapPtr && heap && (((HEAP *)heap)->flags & HEAP_VALIDATE_PARAMS) && + if (!heapPtr && heap && (((struct heap *)heap)->flags & HEAP_VALIDATE_PARAMS) && NtCurrentTeb()->Peb->BeingDebugged) { DbgPrint( "Attempt to destroy an invalid heap\n" ); @@ -1486,7 +1483,7 @@ HANDLE WINAPI RtlDestroyHeap( HANDLE heap ) return 0; }
-static SIZE_T heap_get_block_size( HEAP *heap, ULONG flags, SIZE_T size ) +static SIZE_T heap_get_block_size( struct heap *heap, ULONG flags, SIZE_T size ) { static const ULONG padd_flags = HEAP_VALIDATE | HEAP_VALIDATE_ALL | HEAP_VALIDATE_PARAMS; static const ULONG check_flags = HEAP_TAIL_CHECKING_ENABLED | HEAP_FREE_CHECKING_ENABLED | HEAP_CHECKING_ENABLED; @@ -1502,7 +1499,7 @@ static SIZE_T heap_get_block_size( HEAP *heap, ULONG flags, SIZE_T size ) return ROUND_SIZE( size + overhead, ALIGNMENT - 1 ); }
-static NTSTATUS heap_allocate( HEAP *heap, ULONG flags, SIZE_T size, void **ret ) +static NTSTATUS heap_allocate( struct heap *heap, ULONG flags, SIZE_T size, void **ret ) { SIZE_T old_block_size, block_size; struct block *block; @@ -1538,9 +1535,9 @@ static NTSTATUS heap_allocate( HEAP *heap, ULONG flags, SIZE_T size, void **ret */ void *WINAPI DECLSPEC_HOTPATCH RtlAllocateHeap( HANDLE heap, ULONG flags, SIZE_T size ) { + struct heap *heapPtr; void *ptr = NULL; NTSTATUS status; - HEAP *heapPtr;
if (!(heapPtr = HEAP_GetPtr( heap ))) status = STATUS_INVALID_HANDLE; @@ -1559,7 +1556,7 @@ void *WINAPI DECLSPEC_HOTPATCH RtlAllocateHeap( HANDLE heap, ULONG flags, SIZE_T }
-static NTSTATUS heap_free( HEAP *heap, void *ptr ) +static NTSTATUS heap_free( struct heap *heap, void *ptr ) { struct block *block; SUBHEAP *subheap; @@ -1576,8 +1573,8 @@ static NTSTATUS heap_free( HEAP *heap, void *ptr ) */ BOOLEAN WINAPI DECLSPEC_HOTPATCH RtlFreeHeap( HANDLE heap, ULONG flags, void *ptr ) { + struct heap *heapPtr; NTSTATUS status; - HEAP *heapPtr;
if (!ptr) return TRUE;
@@ -1598,7 +1595,7 @@ BOOLEAN WINAPI DECLSPEC_HOTPATCH RtlFreeHeap( HANDLE heap, ULONG flags, void *pt }
-static NTSTATUS heap_reallocate( HEAP *heap, ULONG flags, void *ptr, SIZE_T size, void **ret ) +static NTSTATUS heap_reallocate( struct heap *heap, ULONG flags, void *ptr, SIZE_T size, void **ret ) { SIZE_T old_block_size, old_size, block_size; struct block *next, *block; @@ -1661,9 +1658,9 @@ static NTSTATUS heap_reallocate( HEAP *heap, ULONG flags, void *ptr, SIZE_T size */ void *WINAPI RtlReAllocateHeap( HANDLE heap, ULONG flags, void *ptr, SIZE_T size ) { + struct heap *heapPtr; void *ret = NULL; NTSTATUS status; - HEAP *heapPtr;
if (!ptr) return NULL;
@@ -1719,7 +1716,7 @@ ULONG WINAPI RtlCompactHeap( HANDLE heap, ULONG flags ) */ BOOLEAN WINAPI RtlLockHeap( HANDLE heap ) { - HEAP *heapPtr = HEAP_GetPtr( heap ); + struct heap *heapPtr = HEAP_GetPtr( heap ); if (!heapPtr) return FALSE; heap_lock( heapPtr, 0 ); return TRUE; @@ -1740,14 +1737,14 @@ BOOLEAN WINAPI RtlLockHeap( HANDLE heap ) */ BOOLEAN WINAPI RtlUnlockHeap( HANDLE heap ) { - HEAP *heapPtr = HEAP_GetPtr( heap ); + struct heap *heapPtr = HEAP_GetPtr( heap ); if (!heapPtr) return FALSE; heap_unlock( heapPtr, 0 ); return TRUE; }
-static NTSTATUS heap_size( HEAP *heap, const void *ptr, SIZE_T *size ) +static NTSTATUS heap_size( struct heap *heap, const void *ptr, SIZE_T *size ) { const struct block *block; SUBHEAP *subheap; @@ -1769,8 +1766,8 @@ static NTSTATUS heap_size( HEAP *heap, const void *ptr, SIZE_T *size ) SIZE_T WINAPI RtlSizeHeap( HANDLE heap, ULONG flags, const void *ptr ) { SIZE_T size = ~(SIZE_T)0; + struct heap *heapPtr; NTSTATUS status; - HEAP *heapPtr;
if (!(heapPtr = HEAP_GetPtr( heap ))) status = STATUS_INVALID_PARAMETER; @@ -1792,8 +1789,8 @@ SIZE_T WINAPI RtlSizeHeap( HANDLE heap, ULONG flags, const void *ptr ) */ BOOLEAN WINAPI RtlValidateHeap( HANDLE heap, ULONG flags, const void *ptr ) { + struct heap *heapPtr; SUBHEAP *subheap; - HEAP *heapPtr; BOOLEAN ret;
if (!(heapPtr = HEAP_GetPtr( heap ))) @@ -1811,7 +1808,7 @@ BOOLEAN WINAPI RtlValidateHeap( HANDLE heap, ULONG flags, const void *ptr ) }
-static NTSTATUS heap_walk_blocks( const HEAP *heap, const SUBHEAP *subheap, struct rtl_heap_entry *entry ) +static NTSTATUS heap_walk_blocks( const struct heap *heap, const SUBHEAP *subheap, struct rtl_heap_entry *entry ) { const char *base = subheap_base( subheap ), *commit_end = subheap_commit_end( subheap ), *end = base + subheap_size( subheap ); const struct block *block, *blocks = first_block( subheap ); @@ -1856,7 +1853,7 @@ static NTSTATUS heap_walk_blocks( const HEAP *heap, const SUBHEAP *subheap, stru return STATUS_SUCCESS; }
-static NTSTATUS heap_walk( const HEAP *heap, struct rtl_heap_entry *entry ) +static NTSTATUS heap_walk( const struct heap *heap, struct rtl_heap_entry *entry ) { const ARENA_LARGE *large; const struct list *next; @@ -1915,8 +1912,8 @@ static NTSTATUS heap_walk( const HEAP *heap, struct rtl_heap_entry *entry ) NTSTATUS WINAPI RtlWalkHeap( HANDLE heap, void *entry_ptr ) { struct rtl_heap_entry *entry = entry_ptr; + struct heap *heapPtr; NTSTATUS status; - HEAP *heapPtr;
if (!entry) return STATUS_INVALID_PARAMETER;
@@ -1959,7 +1956,7 @@ ULONG WINAPI RtlGetProcessHeaps( ULONG count, HANDLE *heaps ) { *heaps++ = processHeap; LIST_FOR_EACH( ptr, &processHeap->entry ) - *heaps++ = LIST_ENTRY( ptr, HEAP, entry ); + *heaps++ = LIST_ENTRY( ptr, struct heap, entry ); } RtlLeaveCriticalSection( &processHeap->cs ); return total;
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/kernel32/tests/heap.c | 3 +-- dlls/ntdll/heap.c | 5 +++-- 2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c index 99602bd2969..057342de9e9 100644 --- a/dlls/kernel32/tests/heap.c +++ b/dlls/kernel32/tests/heap.c @@ -2274,14 +2274,13 @@ static void test_block_layout( HANDLE heap, DWORD global_flags, DWORD heap_flags expect_size = max( alloc_size, 2 * sizeof(void *) ); expect_size = ALIGN_BLOCK_SIZE( expect_size + extra_size + 2 * sizeof(void *) ); diff = min( llabs( ptr2 - ptr1 ), llabs( ptr1 - ptr0 ) ); - todo_wine ok( diff == expect_size, "got diff %#Ix\n", diff );
ok( !memcmp( ptr0 + alloc_size, tail_buf, tail_size ), "missing block tail\n" ); ok( !memcmp( ptr1 + alloc_size, tail_buf, tail_size ), "missing block tail\n" ); ok( !memcmp( ptr2 + alloc_size, tail_buf, tail_size ), "missing block tail\n" );
- todo_wine + todo_wine_if( global_flags & FLG_HEAP_ENABLE_FREE_CHECK ) ok( !memcmp( ptr0 + alloc_size + tail_size, padd_buf, 2 * sizeof(void *) ), "unexpected padding\n" );
tmp_ptr = (void *)0xdeadbeef; diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c index afbf8703da0..ce2d2b920b5 100644 --- a/dlls/ntdll/heap.c +++ b/dlls/ntdll/heap.c @@ -214,6 +214,7 @@ C_ASSERT( offsetof(struct heap, subheap) <= COMMIT_MASK );
/* some undocumented flags (names are made up) */ #define HEAP_PRIVATE 0x00001000 +#define HEAP_ADD_USER_INFO 0x00000100 #define HEAP_PAGE_ALLOCS 0x01000000 #define HEAP_VALIDATE 0x10000000 #define HEAP_VALIDATE_ALL 0x20000000 @@ -457,7 +458,7 @@ static RTL_CRITICAL_SECTION_DEBUG process_heap_cs_debug = static inline ULONG heap_get_flags( const struct heap *heap, ULONG flags ) { if (flags & (HEAP_TAIL_CHECKING_ENABLED | HEAP_FREE_CHECKING_ENABLED)) flags |= HEAP_CHECKING_ENABLED; - flags &= HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY | HEAP_REALLOC_IN_PLACE_ONLY | HEAP_CHECKING_ENABLED; + flags &= HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY | HEAP_REALLOC_IN_PLACE_ONLY | HEAP_CHECKING_ENABLED | HEAP_ADD_USER_INFO; return heap->flags | flags; }
@@ -1485,7 +1486,7 @@ HANDLE WINAPI RtlDestroyHeap( HANDLE heap )
static SIZE_T heap_get_block_size( struct heap *heap, ULONG flags, SIZE_T size ) { - static const ULONG padd_flags = HEAP_VALIDATE | HEAP_VALIDATE_ALL | HEAP_VALIDATE_PARAMS; + static const ULONG padd_flags = HEAP_VALIDATE | HEAP_VALIDATE_ALL | HEAP_VALIDATE_PARAMS | HEAP_ADD_USER_INFO; static const ULONG check_flags = HEAP_TAIL_CHECKING_ENABLED | HEAP_FREE_CHECKING_ENABLED | HEAP_CHECKING_ENABLED; SIZE_T overhead;
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/kernelbase/memory.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c index cac456d01be..625ff56fdef 100644 --- a/dlls/kernelbase/memory.c +++ b/dlls/kernelbase/memory.c @@ -685,6 +685,9 @@ BOOL WINAPI DECLSPEC_HOTPATCH HeapWalk( HANDLE heap, PROCESS_HEAP_ENTRY *entry ) * Global/local heap functions ***********************************************************************/
+/* some undocumented flags (names are made up) */ +#define HEAP_ADD_USER_INFO 0x00000100 + /* not compatible with windows */ struct kernelbase_global_data { @@ -798,15 +801,15 @@ HGLOBAL WINAPI DECLSPEC_HOTPATCH GlobalFree( HLOCAL handle ) */ HLOCAL WINAPI DECLSPEC_HOTPATCH LocalAlloc( UINT flags, SIZE_T size ) { + DWORD heap_flags = HEAP_ADD_USER_INFO; HANDLE heap = GetProcessHeap(); struct mem_entry *mem; - DWORD heap_flags = 0; HLOCAL handle; void *ptr;
TRACE_(globalmem)( "flags %#x, size %#Ix\n", flags, size );
- if (flags & LMEM_ZEROINIT) heap_flags = HEAP_ZERO_MEMORY; + if (flags & LMEM_ZEROINIT) heap_flags |= HEAP_ZERO_MEMORY;
if (!(flags & LMEM_MOVEABLE)) /* pointer */ { @@ -936,13 +939,15 @@ LPVOID WINAPI DECLSPEC_HOTPATCH LocalLock( HLOCAL handle ) */ HLOCAL WINAPI DECLSPEC_HOTPATCH LocalReAlloc( HLOCAL handle, SIZE_T size, UINT flags ) { + DWORD heap_flags = HEAP_ADD_USER_INFO; struct mem_entry *mem; HLOCAL ret = 0; - DWORD heap_flags = (flags & LMEM_ZEROINIT) ? HEAP_ZERO_MEMORY : 0; void *ptr;
TRACE_(globalmem)( "handle %p, size %#Ix, flags %#x\n", handle, size, flags );
+ if (flags & LMEM_ZEROINIT) heap_flags |= HEAP_ZERO_MEMORY; + RtlLockHeap( GetProcessHeap() ); if (flags & LMEM_MODIFY) /* modify flags */ {
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/kernel32/heap.c | 2 + dlls/kernel32/tests/heap.c | 11 ---- dlls/kernelbase/memory.c | 108 ++++++++++++++----------------------- 3 files changed, 42 insertions(+), 79 deletions(-)
diff --git a/dlls/kernel32/heap.c b/dlls/kernel32/heap.c index df094c94257..6a1a02c814b 100644 --- a/dlls/kernel32/heap.c +++ b/dlls/kernel32/heap.c @@ -315,6 +315,8 @@ HGLOBAL WINAPI GlobalHandle( const void *ptr ) */ HGLOBAL WINAPI GlobalReAlloc( HGLOBAL handle, SIZE_T size, UINT flags ) { + struct mem_entry *mem; + if ((mem = unsafe_mem_from_HLOCAL( handle )) && mem->lock) return 0; return LocalReAlloc( handle, size, flags ); }
diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c index 057342de9e9..39d2aea3965 100644 --- a/dlls/kernel32/tests/heap.c +++ b/dlls/kernel32/tests/heap.c @@ -1633,9 +1633,7 @@ static void test_GlobalAlloc(void) mem = GlobalAlloc( GMEM_FIXED, 10 ); ok( !!mem, "GlobalAlloc failed, error %lu\n", GetLastError() ); tmp_mem = GlobalReAlloc( mem, 9, GMEM_MODIFY ); - todo_wine ok( !!tmp_mem, "GlobalAlloc failed, error %lu\n", GetLastError() ); - todo_wine ok( tmp_mem == mem, "got ptr %p, expected %p\n", tmp_mem, mem ); size = GlobalSize( mem ); ok( size == 10, "GlobalSize returned %Iu\n", size ); @@ -1649,9 +1647,7 @@ static void test_GlobalAlloc(void) "got error %lu\n", GetLastError() ); if (tmp_mem) mem = tmp_mem; tmp_mem = GlobalReAlloc( mem, 1024 * 1024, GMEM_MODIFY ); - todo_wine ok( !!tmp_mem, "GlobalAlloc failed, error %lu\n", GetLastError() ); - todo_wine ok( tmp_mem == mem, "got ptr %p, expected %p\n", tmp_mem, mem ); size = GlobalSize( mem ); ok( size == 10, "GlobalSize returned %Iu\n", size ); @@ -1986,9 +1982,7 @@ static void test_LocalAlloc(void) mem = LocalAlloc( LMEM_FIXED, 10 ); ok( !!mem, "LocalAlloc failed, error %lu\n", GetLastError() ); tmp_mem = LocalReAlloc( mem, 9, LMEM_MODIFY ); - todo_wine ok( !!tmp_mem, "LocalAlloc failed, error %lu\n", GetLastError() ); - todo_wine ok( tmp_mem == mem, "got ptr %p, expected %p\n", tmp_mem, mem ); size = LocalSize( mem ); ok( size == 10, "LocalSize returned %Iu\n", size ); @@ -2002,9 +1996,7 @@ static void test_LocalAlloc(void) "got error %lu\n", GetLastError() ); if (tmp_mem) mem = tmp_mem; tmp_mem = LocalReAlloc( mem, 1024 * 1024, LMEM_MODIFY ); - todo_wine ok( !!tmp_mem, "LocalAlloc failed, error %lu\n", GetLastError() ); - todo_wine ok( tmp_mem == mem, "got ptr %p, expected %p\n", tmp_mem, mem ); size = LocalSize( mem ); ok( size == 10, "LocalSize returned %Iu\n", size ); @@ -2103,13 +2095,10 @@ static void test_LocalAlloc(void) tmp_mem = LocalHandle( ptr ); ok( tmp_mem == mem, "LocalHandle returned unexpected handle\n" ); tmp_mem = LocalDiscard( mem ); - todo_wine ok( !!tmp_mem, "LocalDiscard failed, error %lu\n", GetLastError() ); - todo_wine ok( tmp_mem == mem, "LocalDiscard returned unexpected handle\n" ); ret = LocalUnlock( mem ); ok( !ret, "LocalUnlock succeeded, error %lu\n", GetLastError() ); - todo_wine ok( GetLastError() == ERROR_NOT_LOCKED, "got error %lu\n", GetLastError() );
tmp_mem = LocalDiscard( mem ); diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c index 625ff56fdef..4660bb4f561 100644 --- a/dlls/kernelbase/memory.c +++ b/dlls/kernelbase/memory.c @@ -939,7 +939,8 @@ LPVOID WINAPI DECLSPEC_HOTPATCH LocalLock( HLOCAL handle ) */ HLOCAL WINAPI DECLSPEC_HOTPATCH LocalReAlloc( HLOCAL handle, SIZE_T size, UINT flags ) { - DWORD heap_flags = HEAP_ADD_USER_INFO; + DWORD heap_flags = HEAP_ADD_USER_INFO | HEAP_NO_SERIALIZE; + HANDLE heap = GetProcessHeap(); struct mem_entry *mem; HLOCAL ret = 0; void *ptr; @@ -948,90 +949,61 @@ HLOCAL WINAPI DECLSPEC_HOTPATCH LocalReAlloc( HLOCAL handle, SIZE_T size, UINT f
if (flags & LMEM_ZEROINIT) heap_flags |= HEAP_ZERO_MEMORY;
- RtlLockHeap( GetProcessHeap() ); - if (flags & LMEM_MODIFY) /* modify flags */ + RtlLockHeap( heap ); + if ((ptr = unsafe_ptr_from_HLOCAL( handle ))) { - if (unsafe_ptr_from_HLOCAL( handle ) && (flags & LMEM_MOVEABLE)) + if (!(flags & LMEM_MOVEABLE)) { - /* make a fixed block moveable - * actually only NT is able to do this. But it's soo simple - */ - if (handle == 0) - { - WARN_(globalmem)( "null handle\n" ); - SetLastError( ERROR_NOACCESS ); - } - else - { - size = RtlSizeHeap( GetProcessHeap(), 0, handle ); - ret = LocalAlloc( flags, size ); - ptr = LocalLock( ret ); - memcpy( ptr, handle, size ); - LocalUnlock( ret ); - LocalFree( handle ); - } + heap_flags |= HEAP_REALLOC_IN_PLACE_ONLY; + if (!(flags & LMEM_MODIFY) || !(flags & LMEM_MOVEABLE)) ret = handle; + else ret = HeapReAlloc( heap, heap_flags, ptr, size ); } - else if ((mem = unsafe_mem_from_HLOCAL( handle )) && (flags & LMEM_DISCARDABLE)) + else if (flags & LMEM_MODIFY) { - /* change the flags to make our block "discardable" */ - mem->flags |= LMEM_DISCARDABLE >> 8; - ret = handle; + size = RtlSizeHeap( heap, 0, handle ); + ret = LocalAlloc( flags, size ); + ptr = LocalLock( ret ); + memcpy( ptr, handle, size ); + LocalUnlock( ret ); + LocalFree( handle ); } - else SetLastError( ERROR_INVALID_PARAMETER ); + else ret = HeapReAlloc( heap, heap_flags, handle, size ); } - else + else if ((mem = unsafe_mem_from_HLOCAL( handle ))) { - if ((ptr = unsafe_ptr_from_HLOCAL( handle ))) + if (!(flags & LMEM_MODIFY)) { - /* reallocate fixed memory */ - if (!(flags & LMEM_MOVEABLE)) heap_flags |= HEAP_REALLOC_IN_PLACE_ONLY; - ret = HeapReAlloc( GetProcessHeap(), heap_flags, ptr, size ); - } - else if ((mem = unsafe_mem_from_HLOCAL( handle ))) - { - /* reallocate a moveable block */ - if (size != 0) + if (size) { - if (size <= INT_MAX - HLOCAL_STORAGE) + if (!mem->ptr) ptr = HeapAlloc( heap, heap_flags, size + HLOCAL_STORAGE ); + else ptr = HeapReAlloc( heap, heap_flags, (char *)mem->ptr - HLOCAL_STORAGE, size + HLOCAL_STORAGE ); + if (!ptr) SetLastError( ERROR_OUTOFMEMORY ); + else { - if (mem->ptr) - { - if ((ptr = HeapReAlloc( GetProcessHeap(), heap_flags, (char *)mem->ptr - HLOCAL_STORAGE, - size + HLOCAL_STORAGE ))) - { - mem->ptr = (char *)ptr + HLOCAL_STORAGE; - ret = handle; - } - } - else - { - if ((ptr = HeapAlloc( GetProcessHeap(), heap_flags, size + HLOCAL_STORAGE ))) - { - *(HLOCAL *)ptr = handle; - mem->ptr = (char *)ptr + HLOCAL_STORAGE; - ret = handle; - } - } + mem->flags &= ~MEM_FLAG_DISCARDED; + mem->ptr = (char *)ptr + HLOCAL_STORAGE; + ret = handle; } - else SetLastError( ERROR_OUTOFMEMORY ); } else { - if (mem->lock == 0) - { - if (mem->ptr) - { - HeapFree( GetProcessHeap(), 0, (char *)mem->ptr - HLOCAL_STORAGE ); - mem->ptr = NULL; - } - ret = handle; - } - else WARN_(globalmem)( "not freeing memory associated with locked handle\n" ); + if (mem->ptr) HeapFree( heap, heap_flags, (char *)mem->ptr - HLOCAL_STORAGE ); + mem->flags |= MEM_FLAG_DISCARDED; + mem->lock = 0; + mem->ptr = NULL; + ret = handle; } } - else SetLastError( ERROR_INVALID_HANDLE ); + else if (flags & LMEM_DISCARDABLE) + { + mem->flags |= MEM_FLAG_DISCARDABLE; + ret = handle; + } + else SetLastError( ERROR_INVALID_PARAMETER ); } - RtlUnlockHeap( GetProcessHeap() ); + else SetLastError( ERROR_INVALID_HANDLE ); + RtlUnlockHeap( heap ); + return ret; }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=116146
Your paranoid android.
=== debian11 (32 bit WoW report) ===
kernel32: change.c:309: Test failed: should be ready change.c:339: Test failed: should be ready
6bf9b45286b685234f3da1280b59d11f550dfd23 breaks ole32:hglobalstream, I'll have a look.
This merge request was closed by Rémi Bernon.