From: Eric Pouech epouech@codeweavers.com
Required for some Chrome integration.
Wine-Bugs: https://bugs.winehq.org/show_bug.cgi?id=57700
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/kernel32/tests/loader.c | 2 -- dlls/kernel32/tests/module.c | 1 - dlls/ntdll/loader.c | 70 +++++++++++++++++++++++++++--------- 3 files changed, 54 insertions(+), 19 deletions(-)
diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c index d0249b35b97..38ee1f0a6c7 100644 --- a/dlls/kernel32/tests/loader.c +++ b/dlls/kernel32/tests/loader.c @@ -2326,10 +2326,8 @@ static void test_import_resolution(void) { SIZE_T s; /* should be aligned on 1024 bytes, 10 lower bits at 0 */ - todo_wine_if( (DWORD_PTR)str & 0x3ff ) ok( !((DWORD_PTR)str & 0x3ff), "wrong alignment %p\n", str ); s = HeapSize( GetProcessHeap(), 0, ((void **)str)[-1] ); - todo_wine ok( s != (SIZE_T)-1, "Error %Ix\n", s); } ok(ptr->tls_index_hi == 0, "TLS Index written as a short, high half: %d\n", ptr->tls_index_hi); diff --git a/dlls/kernel32/tests/module.c b/dlls/kernel32/tests/module.c index b3ac6917a8f..9deb9463c7f 100644 --- a/dlls/kernel32/tests/module.c +++ b/dlls/kernel32/tests/module.c @@ -1742,7 +1742,6 @@ static void test_tls_links(void) for (i = 0; i < count; ++i) { if (!ptr[i]) continue; - todo_wine size = HeapSize(GetProcessHeap(), 0, ((void **)ptr[i])[-1]); ok(size && size < 100000, "got %Iu.\n", size); } diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 67c4aa546bc..5d386f49130 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -1314,6 +1314,52 @@ static BOOL is_dll_native_subsystem( LDR_DATA_TABLE_ENTRY *mod, const IMAGE_NT_H return TRUE; }
+/* use in pair heap_(alloc|free)_aligned to manage aligned memory allocations */ +static void *heap_alloc_aligned( unsigned size, unsigned align ) +{ + char *ptr; + DWORD_PTR mask = ((DWORD_PTR)1 << align) - 1; + + size += sizeof(void *) + mask; + if ((ptr = RtlAllocateHeap( GetProcessHeap(), 0, size ))) + { + void *unaligned_ptr = ptr; + + /* align block and store unaligned pointer just below the returned block */ + ptr = (char *)(((DWORD_PTR)ptr + sizeof(void *) + mask) & ~mask); + ((void **)ptr)[-1] = unaligned_ptr; + } + return ptr; +} + + +static BOOLEAN heap_free_aligned( void *ptr ) +{ + return ptr ? RtlFreeHeap( GetProcessHeap(), 0, ((void **)ptr)[-1] ) : TRUE; +} + + +/* Allocates the slot from a TLS directory (potentially realigning if necessary) + * - must be freed with heap_free_aligned + */ +static void *alloc_thread_tls_slot( const IMAGE_TLS_DIRECTORY *dir ) +{ + UINT size = dir->EndAddressOfRawData - dir->StartAddressOfRawData; + unsigned align; + void *ptr; + + align = (dir->Characteristics & IMAGE_SCN_ALIGN_MASK) >> 20; + if (!align) align = 5; /* default */ + if ((ptr = heap_alloc_aligned( size + dir->SizeOfZeroFill, align ))) + { + memcpy( ptr, (void *)dir->StartAddressOfRawData, size ); + memset( (char *)ptr + size, 0, dir->SizeOfZeroFill ); + } + + return ptr; +} + + /************************************************************************* * alloc_tls_slot * @@ -1389,15 +1435,12 @@ static BOOL alloc_tls_slot( LDR_DATA_TABLE_ENTRY *mod ) /* FIXME: can't free old block here, should be freed at thread exit */ }
- if (!(new_ptr = RtlAllocateHeap( GetProcessHeap(), 0, size + dir->SizeOfZeroFill ))) return -1; - memcpy( new_ptr, (void *)dir->StartAddressOfRawData, size ); - memset( (char *)new_ptr + size, 0, dir->SizeOfZeroFill ); + if (!(new_ptr = alloc_thread_tls_slot( dir ))) return -1;
TRACE( "thread %04lx slot %lu: %lu/%lu bytes at %p\n", HandleToULong(teb->ClientId.UniqueThread), i, size, dir->SizeOfZeroFill, new_ptr );
- RtlFreeHeap( GetProcessHeap(), 0, - InterlockedExchangePointer( (void **)teb->ThreadLocalStoragePointer + i, new_ptr )); + heap_free_aligned( InterlockedExchangePointer( (void **)teb->ThreadLocalStoragePointer + i, new_ptr )); } if (thread) NtClose( thread );
@@ -1604,7 +1647,7 @@ static WINE_MODREF *alloc_module( HMODULE hModule, const UNICODE_STRING *nt_name static NTSTATUS alloc_thread_tls(void) { void **pointers; - UINT i, size; + UINT i;
if (!(pointers = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, tls_module_count * sizeof(*pointers) ))) @@ -1614,20 +1657,15 @@ static NTSTATUS alloc_thread_tls(void) { const IMAGE_TLS_DIRECTORY *dir = &tls_dirs[i];
- if (!dir) continue; - size = dir->EndAddressOfRawData - dir->StartAddressOfRawData; - if (!size && !dir->SizeOfZeroFill) continue; + if (!dir || (dir->EndAddressOfRawData == dir->StartAddressOfRawData && !dir->SizeOfZeroFill)) continue;
- if (!(pointers[i] = RtlAllocateHeap( GetProcessHeap(), 0, size + dir->SizeOfZeroFill ))) + if (!(pointers[i] = alloc_thread_tls_slot( dir ))) { - while (i) RtlFreeHeap( GetProcessHeap(), 0, pointers[--i] ); + while (i) heap_free_aligned( pointers[--i] ); RtlFreeHeap( GetProcessHeap(), 0, pointers ); return STATUS_NO_MEMORY; } - memcpy( pointers[i], (void *)dir->StartAddressOfRawData, size ); - memset( (char *)pointers[i] + size, 0, dir->SizeOfZeroFill ); - - TRACE( "slot %u: %u/%lu bytes at %p\n", i, size, dir->SizeOfZeroFill, pointers[i] ); + TRACE( "slot %u: %u/%lu bytes at %p\n", i, (UINT)(dir->EndAddressOfRawData - dir->StartAddressOfRawData), dir->SizeOfZeroFill, pointers[i] ); } NtCurrentTeb()->ThreadLocalStoragePointer = pointers; return STATUS_SUCCESS; @@ -3934,7 +3972,7 @@ void WINAPI LdrShutdownThread(void) if ((pointers = NtCurrentTeb()->ThreadLocalStoragePointer)) { NtCurrentTeb()->ThreadLocalStoragePointer = NULL; - for (i = 0; i < tls_module_count; i++) RtlFreeHeap( GetProcessHeap(), 0, pointers[i] ); + for (i = 0; i < tls_module_count; i++) heap_free_aligned( pointers[i] ); RtlFreeHeap( GetProcessHeap(), 0, pointers ); } RtlProcessFlsData( NtCurrentTeb()->FlsSlots, 2 );