From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/kernel32/tests/module.c | 1 - dlls/ntdll/loader.c | 37 +++++++++++++++++++++++++++++++----- 2 files changed, 32 insertions(+), 6 deletions(-)
diff --git a/dlls/kernel32/tests/module.c b/dlls/kernel32/tests/module.c index 9deb9463c7f..5c2fe51b4de 100644 --- a/dlls/kernel32/tests/module.c +++ b/dlls/kernel32/tests/module.c @@ -1736,7 +1736,6 @@ static void test_tls_links(void) ptr = teb->ThreadLocalStoragePointer; count = (ULONG)(ULONG_PTR)ptr[-2]; size = HeapSize(GetProcessHeap(), 0, ptr - 2); - todo_wine ok(size == (count + 2) * sizeof(void *), "got count %lu, size %Iu.\n", count, size);
for (i = 0; i < count; ++i) diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 5d386f49130..9670d0503a4 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -1360,6 +1360,34 @@ static void *alloc_thread_tls_slot( const IMAGE_TLS_DIRECTORY *dir ) }
+/* native places a control structure just below the TLS array */ +struct tls_array_control +{ + DWORD count; + void *unknown; +}; + + +static void *heap_alloc_tls_array( unsigned count ) +{ + C_ASSERT(sizeof(struct tls_array_control) == 2 * sizeof(void*)); + struct tls_array_control *ctrl; + + if ((ctrl = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, (2 + count) * sizeof(void*) ))) + { + ctrl->count = count; + ctrl = ctrl + 1; + } + return ctrl; +} + + +static void heap_free_tls_array( void *ptr ) +{ + RtlFreeHeap( GetProcessHeap(), 0, ((struct tls_array_control *)ptr) - 1); +} + + /************************************************************************* * alloc_tls_slot * @@ -1426,7 +1454,7 @@ static BOOL alloc_tls_slot( LDR_DATA_TABLE_ENTRY *mod ) if (old_module_count < tls_module_count) { void **old = teb->ThreadLocalStoragePointer; - void **new = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, tls_module_count * sizeof(*new)); + void **new = heap_alloc_tls_array( tls_module_count );
if (!new) return FALSE; if (old) memcpy( new, old, old_module_count * sizeof(*new) ); @@ -1649,8 +1677,7 @@ static NTSTATUS alloc_thread_tls(void) void **pointers; UINT i;
- if (!(pointers = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, - tls_module_count * sizeof(*pointers) ))) + if (!(pointers = heap_alloc_tls_array( tls_module_count ))) return STATUS_NO_MEMORY;
for (i = 0; i < tls_module_count; i++) @@ -1662,7 +1689,7 @@ static NTSTATUS alloc_thread_tls(void) if (!(pointers[i] = alloc_thread_tls_slot( dir ))) { while (i) heap_free_aligned( pointers[--i] ); - RtlFreeHeap( GetProcessHeap(), 0, pointers ); + heap_free_tls_array( pointers ); return STATUS_NO_MEMORY; } TRACE( "slot %u: %u/%lu bytes at %p\n", i, (UINT)(dir->EndAddressOfRawData - dir->StartAddressOfRawData), dir->SizeOfZeroFill, pointers[i] ); @@ -3973,7 +4000,7 @@ void WINAPI LdrShutdownThread(void) { NtCurrentTeb()->ThreadLocalStoragePointer = NULL; for (i = 0; i < tls_module_count; i++) heap_free_aligned( pointers[i] ); - RtlFreeHeap( GetProcessHeap(), 0, pointers ); + heap_free_tls_array( pointers ); } RtlProcessFlsData( NtCurrentTeb()->FlsSlots, 2 ); NtCurrentTeb()->FlsSlots = NULL;