diff --git a/patches/ntdll-FLS_Callbacks/0001-kernelbase-Maintain-FLS-storage-list-in-PEB.patch b/patches/ntdll-FLS_Callbacks/0001-kernelbase-Maintain-FLS-storage-list-in-PEB.patch deleted file mode 100644 index 52878a9c..00000000 --- a/patches/ntdll-FLS_Callbacks/0001-kernelbase-Maintain-FLS-storage-list-in-PEB.patch +++ /dev/null @@ -1,322 +0,0 @@ -From b0225150b6721f7c75124c534b8841aa1a8039bd Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Thu, 23 Apr 2020 14:32:23 +0300 -Subject: [PATCH] kernelbase: Maintain FLS storage list in PEB. - ---- - dlls/kernel32/tests/fiber.c | 35 ++++++++++++++++++++ - dlls/kernel32/tests/thread.c | 2 -- - dlls/kernelbase/thread.c | 63 +++++++++++++++++++++++++++--------- - dlls/ntdll/loader.c | 46 ++++++++++++++++++++++++++ - 4 files changed, 129 insertions(+), 17 deletions(-) - -diff --git a/dlls/kernel32/tests/fiber.c b/dlls/kernel32/tests/fiber.c -index 7501165dc87..2bcc3ee60c4 100644 ---- a/dlls/kernel32/tests/fiber.c -+++ b/dlls/kernel32/tests/fiber.c -@@ -19,6 +19,7 @@ - */ - - #include "wine/test.h" -+#include - - static LPVOID (WINAPI *pCreateFiber)(SIZE_T,LPFIBER_START_ROUTINE,LPVOID); - static LPVOID (WINAPI *pConvertThreadToFiber)(LPVOID); -@@ -171,8 +172,25 @@ static void test_FiberHandling(void) - if (pIsThreadAFiber) ok(!pIsThreadAFiber(), "IsThreadAFiber reported TRUE\n"); - } - -+static unsigned int list_size(const LIST_ENTRY *le) -+{ -+ unsigned int count = 0; -+ LIST_ENTRY *entry; -+ -+ for (entry = le->Flink; entry != le; entry = entry->Flink) -+ ++count; -+ -+ return count; -+} -+ -+#define FLS_TEST_INDEX_COUNT 2048 -+ - static void test_FiberLocalStorage(void) - { -+ static DWORD fls_indices[FLS_TEST_INDEX_COUNT]; -+ TEB *teb = NtCurrentTeb(); -+ unsigned int i, count; -+ PEB *peb = teb->Peb; - DWORD fls, fls_2; - BOOL ret; - void* val; -@@ -183,6 +201,23 @@ static void test_FiberLocalStorage(void) - return; - } - -+ ok(!!teb->FlsSlots, "Got NULL teb->FlsSlots.\n"); -+ ok(!!peb->FlsCallback, "Got NULL peb->FlsCallback.\n"); -+ -+ count = list_size(&peb->FlsListHead); -+ ok(count == 1, "Got unexpected FLS list size %u.\n", count); -+ -+ for (i = 0; i < FLS_TEST_INDEX_COUNT; ++i) -+ { -+ if ((fls_indices[i] = pFlsAlloc(NULL)) == FLS_OUT_OF_INDEXES) -+ break; -+ } -+ count = i; -+ ok(count <= 127, "Could allocate %u FLS indices.\n", count); -+ -+ for (i = 0; i < count; ++i) -+ pFlsFree(fls_indices[i]); -+ - /* Test an unallocated index - * FlsFree should fail - * FlsGetValue and FlsSetValue should succeed -diff --git a/dlls/kernel32/tests/thread.c b/dlls/kernel32/tests/thread.c -index bd9fe7fecef..79e2736bd9e 100644 ---- a/dlls/kernel32/tests/thread.c -+++ b/dlls/kernel32/tests/thread.c -@@ -2483,7 +2483,6 @@ START_TEST(thread) - } - return; - } -- - test_thread_info(); - test_reserved_tls(); - test_CreateRemoteThread(); -@@ -2511,6 +2510,5 @@ START_TEST(thread) - test_thread_fpu_cw(); - test_thread_actctx(); - test_thread_description(); -- - test_threadpool(); - } -diff --git a/dlls/kernelbase/thread.c b/dlls/kernelbase/thread.c -index f44f2ff6538..3423fe8c727 100644 ---- a/dlls/kernelbase/thread.c -+++ b/dlls/kernelbase/thread.c -@@ -38,6 +38,10 @@ - - WINE_DEFAULT_DEBUG_CHANNEL(thread); - -+static inline void **fls_addr_from_index(void *fls_slots, DWORD index) -+{ -+ return (void **)((BYTE *)fls_slots + sizeof(LIST_ENTRY)) + index; -+} - - /*********************************************************************** - * Threads -@@ -928,6 +932,19 @@ static void init_fiber_context( struct fiber_data *fiber ) - #endif - } - -+typedef void WINAPI (*FLS_LOCK_FUNCTION)(void *); -+ -+static void lock_fls_section(void) -+{ -+ if (NtCurrentTeb()->Peb->FlsCallback) -+ ((FLS_LOCK_FUNCTION)NtCurrentTeb()->Peb->FlsCallback[0])(NULL); -+} -+ -+static void unlock_fls_section(void) -+{ -+ if (NtCurrentTeb()->Peb->FlsCallback) -+ ((FLS_LOCK_FUNCTION)NtCurrentTeb()->Peb->FlsCallback[1])(NULL); -+} - - /*********************************************************************** - * CreateFiber (kernelbase.@) -@@ -1035,7 +1052,16 @@ void WINAPI DECLSPEC_HOTPATCH DeleteFiber( LPVOID fiber_ptr ) - RtlExitUserThread( 1 ); - } - RtlFreeUserStack( fiber->stack_allocation ); -- HeapFree( GetProcessHeap(), 0, fiber->fls_slots ); -+ -+ if (fiber->fls_slots) -+ { -+ lock_fls_section(); -+ RemoveEntryList( (LIST_ENTRY *)fiber->fls_slots ); -+ unlock_fls_section(); -+ -+ HeapFree( GetProcessHeap(), 0, fiber->fls_slots ); -+ } -+ - HeapFree( GetProcessHeap(), 0, fiber ); - } - -@@ -1057,6 +1083,19 @@ void WINAPI DECLSPEC_HOTPATCH SwitchToFiber( LPVOID fiber ) - struct fiber_data *new_fiber = fiber; - struct fiber_data *current_fiber = NtCurrentTeb()->Tib.u.FiberData; - -+ if (!new_fiber->fls_slots) -+ { -+ TEB *teb = NtCurrentTeb(); -+ PEB *peb = teb->Peb; -+ -+ new_fiber->fls_slots = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, -+ sizeof(LIST_ENTRY) + 8 * sizeof(peb->FlsBitmapBits) * sizeof(void*) ); -+ -+ lock_fls_section(); -+ InsertTailList(&peb->FlsListHead, (LIST_ENTRY *)new_fiber->fls_slots); -+ unlock_fls_section(); -+ } -+ - current_fiber->except = NtCurrentTeb()->Tib.ExceptionList; - current_fiber->stack_limit = NtCurrentTeb()->Tib.StackLimit; - current_fiber->fls_slots = NtCurrentTeb()->FlsSlots; -@@ -1082,9 +1121,7 @@ DWORD WINAPI DECLSPEC_HOTPATCH FlsAlloc( PFLS_CALLBACK_FUNCTION callback ) - PEB * const peb = NtCurrentTeb()->Peb; - - RtlAcquirePebLock(); -- if (!peb->FlsCallback && -- !(peb->FlsCallback = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, -- 8 * sizeof(peb->FlsBitmapBits) * sizeof(void*) ))) -+ if (!peb->FlsCallback) - { - SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - index = FLS_OUT_OF_INDEXES; -@@ -1094,9 +1131,7 @@ DWORD WINAPI DECLSPEC_HOTPATCH FlsAlloc( PFLS_CALLBACK_FUNCTION callback ) - index = RtlFindClearBitsAndSet( peb->FlsBitmap, 1, 1 ); - if (index != ~0U) - { -- if (!NtCurrentTeb()->FlsSlots && -- !(NtCurrentTeb()->FlsSlots = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, -- 8 * sizeof(peb->FlsBitmapBits) * sizeof(void*) ))) -+ if (!NtCurrentTeb()->FlsSlots) - { - RtlClearBits( peb->FlsBitmap, index, 1 ); - index = FLS_OUT_OF_INDEXES; -@@ -1104,8 +1139,8 @@ DWORD WINAPI DECLSPEC_HOTPATCH FlsAlloc( PFLS_CALLBACK_FUNCTION callback ) - } - else - { -- NtCurrentTeb()->FlsSlots[index] = 0; /* clear the value */ -- peb->FlsCallback[index] = callback; -+ *fls_addr_from_index(NtCurrentTeb()->FlsSlots, index) = NULL; /* clear the value */ -+ peb->FlsCallback[index + 2] = callback; - } - } - else SetLastError( ERROR_NO_MORE_ITEMS ); -@@ -1129,7 +1164,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH FlsFree( DWORD index ) - { - /* FIXME: call Fls callback */ - /* FIXME: add equivalent of ThreadZeroTlsCell here */ -- if (NtCurrentTeb()->FlsSlots) NtCurrentTeb()->FlsSlots[index] = 0; -+ if (NtCurrentTeb()->FlsSlots) *fls_addr_from_index(NtCurrentTeb()->FlsSlots, index) = NULL; - } - else SetLastError( ERROR_INVALID_PARAMETER ); - RtlReleasePebLock(); -@@ -1148,7 +1183,7 @@ PVOID WINAPI DECLSPEC_HOTPATCH FlsGetValue( DWORD index ) - return NULL; - } - SetLastError( ERROR_SUCCESS ); -- return NtCurrentTeb()->FlsSlots[index]; -+ return *fls_addr_from_index(NtCurrentTeb()->FlsSlots, index); - } - - -@@ -1162,14 +1197,12 @@ BOOL WINAPI DECLSPEC_HOTPATCH FlsSetValue( DWORD index, PVOID data ) - SetLastError( ERROR_INVALID_PARAMETER ); - return FALSE; - } -- if (!NtCurrentTeb()->FlsSlots && -- !(NtCurrentTeb()->FlsSlots = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, -- 8 * sizeof(NtCurrentTeb()->Peb->FlsBitmapBits) * sizeof(void*) ))) -+ if (!NtCurrentTeb()->FlsSlots) - { - SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - return FALSE; - } -- NtCurrentTeb()->FlsSlots[index] = data; -+ *fls_addr_from_index(NtCurrentTeb()->FlsSlots, index) = data; - return TRUE; - } - -diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c -index d3ade9555b3..84811217474 100644 ---- a/dlls/ntdll/loader.c -+++ b/dlls/ntdll/loader.c -@@ -168,6 +168,15 @@ static RTL_BITMAP tls_bitmap; - static RTL_BITMAP tls_expansion_bitmap; - static RTL_BITMAP fls_bitmap; - -+static CRITICAL_SECTION fls_section; -+static CRITICAL_SECTION_DEBUG fls_critsect_debug = -+{ -+ 0, 0, &fls_section, -+ { &fls_critsect_debug.ProcessLocksList, &fls_critsect_debug.ProcessLocksList }, -+ 0, 0, { (DWORD_PTR)(__FILE__ ": fls_section") } -+}; -+static CRITICAL_SECTION fls_section = { &fls_critsect_debug, -1, 0, 0, 0, 0 };; -+ - static WINE_MODREF *cached_modref; - static WINE_MODREF *current_modref; - static WINE_MODREF *last_failed_modref; -@@ -208,6 +217,16 @@ static RTL_UNLOAD_EVENT_TRACE unload_traces[RTL_UNLOAD_EVENT_TRACE_NUMBER]; - static RTL_UNLOAD_EVENT_TRACE *unload_trace_ptr; - static unsigned int unload_trace_seq; - -+static void WINAPI lock_fls_section( PVOID dummy ) -+{ -+ RtlEnterCriticalSection( &fls_section ); -+} -+ -+static void WINAPI unlock_fls_section( PVOID dummy ) -+{ -+ RtlLeaveCriticalSection( &fls_section ); -+} -+ - static void module_push_unload_trace( const LDR_DATA_TABLE_ENTRY *ldr ) - { - RTL_UNLOAD_EVENT_TRACE *ptr = &unload_traces[unload_trace_seq]; -@@ -3203,6 +3222,13 @@ void WINAPI LdrShutdownThread(void) - /* don't do any detach calls if process is exiting */ - if (process_detaching) return; - -+ if (NtCurrentTeb()->FlsSlots) -+ { -+ lock_fls_section( NULL ); -+ RemoveEntryList( (LIST_ENTRY *)NtCurrentTeb()->FlsSlots ); -+ unlock_fls_section( NULL ); -+ } -+ - RtlEnterCriticalSection( &loader_section ); - wm = get_modref( NtCurrentTeb()->Peb->ImageBaseAddress ); - -@@ -3416,6 +3442,7 @@ PIMAGE_NT_HEADERS WINAPI RtlImageNtHeader(HMODULE hModule) - */ - void WINAPI LdrInitializeThunk( CONTEXT *context, ULONG_PTR unknown2, ULONG_PTR unknown3, ULONG_PTR unknown4 ) - { -+ static const unsigned int fls_slot_count = 8 * sizeof(NtCurrentTeb()->Peb->FlsBitmapBits); - static int attach_done; - int i; - NTSTATUS status; -@@ -3466,6 +3493,25 @@ void WINAPI LdrInitializeThunk( CONTEXT *context, ULONG_PTR unknown2, ULONG_PTR - InsertHeadList( &tls_links, &NtCurrentTeb()->TlsLinks ); - RtlReleasePebLock(); - -+ if (!NtCurrentTeb()->Peb->FlsCallback) -+ { -+ NtCurrentTeb()->Peb->FlsCallback = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, -+ (fls_slot_count + 2) * sizeof(void*) ); -+ if (!NtCurrentTeb()->Peb->FlsCallback) -+ ERR( "No memory for FLS callbacks.\n" ); -+ -+ if (NtCurrentTeb()->Peb->FlsCallback) -+ { -+ NtCurrentTeb()->Peb->FlsCallback[0] = lock_fls_section; -+ NtCurrentTeb()->Peb->FlsCallback[1] = unlock_fls_section; -+ } -+ } -+ NtCurrentTeb()->FlsSlots = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, -+ sizeof(LIST_ENTRY) + fls_slot_count * sizeof(void*) ); -+ lock_fls_section( NULL ); -+ InsertTailList(&NtCurrentTeb()->Peb->FlsListHead, (LIST_ENTRY *)NtCurrentTeb()->FlsSlots); -+ unlock_fls_section( NULL ); -+ - if (!attach_done) /* first time around */ - { - attach_done = 1; --- -2.28.0 - diff --git a/patches/ntdll-FLS_Callbacks/0001-ntdll-Zero-all-FLS-slots-instances-in-RtlFlsFree.patch b/patches/ntdll-FLS_Callbacks/0001-ntdll-Zero-all-FLS-slots-instances-in-RtlFlsFree.patch new file mode 100644 index 00000000..8afb001d --- /dev/null +++ b/patches/ntdll-FLS_Callbacks/0001-ntdll-Zero-all-FLS-slots-instances-in-RtlFlsFree.patch @@ -0,0 +1,44 @@ +From fa80bc605c8cffa33475fbabc12cc0b79978b11e Mon Sep 17 00:00:00 2001 +From: Paul Gofman +Date: Thu, 1 Oct 2020 13:24:19 +0300 +Subject: [PATCH] ntdll: Zero all FLS slots instances in RtlFlsFree(). + +--- + dlls/ntdll/thread.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c +index cf6bddab0b4..95511391d34 100644 +--- a/dlls/ntdll/thread.c ++++ b/dlls/ntdll/thread.c +@@ -392,7 +392,7 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsFree( ULONG index ) + { + unsigned int chunk_index, idx; + FLS_INFO_CHUNK *chunk; +- TEB_FLS_DATA *fls; ++ LIST_ENTRY *entry; + + lock_fls_data(); + +@@ -410,10 +410,15 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsFree( ULONG index ) + return STATUS_INVALID_PARAMETER; + } + +- if ((fls = NtCurrentTeb()->FlsSlots) && fls->fls_data_chunks[chunk_index]) ++ for (entry = fls_data.fls_list_head.Flink; entry != &fls_data.fls_list_head; entry = entry->Flink) + { +- /* FIXME: call Fls callback */ +- fls->fls_data_chunks[chunk_index][idx + 1] = NULL; ++ TEB_FLS_DATA *fls = CONTAINING_RECORD(entry, TEB_FLS_DATA, fls_list_entry); ++ ++ if (fls->fls_data_chunks[chunk_index]) ++ { ++ /* FIXME: call Fls callback */ ++ fls->fls_data_chunks[chunk_index][idx + 1] = NULL; ++ } + } + + --chunk->count; +-- +2.26.2 + diff --git a/patches/ntdll-FLS_Callbacks/0002-kernelbase-Don-t-use-PEB-lock-for-FLS-data.patch b/patches/ntdll-FLS_Callbacks/0002-kernelbase-Don-t-use-PEB-lock-for-FLS-data.patch deleted file mode 100644 index 462b0a55..00000000 --- a/patches/ntdll-FLS_Callbacks/0002-kernelbase-Don-t-use-PEB-lock-for-FLS-data.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 55dbeff93ce46bfba9beaea7b9a67ba7fcd6df88 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Thu, 23 Apr 2020 19:44:32 +0300 -Subject: [PATCH] kernelbase: Don't use PEB lock for FLS data. - ---- - dlls/kernelbase/thread.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/dlls/kernelbase/thread.c b/dlls/kernelbase/thread.c -index 4409f120491..0ba67e1b6c9 100644 ---- a/dlls/kernelbase/thread.c -+++ b/dlls/kernelbase/thread.c -@@ -1108,7 +1108,7 @@ DWORD WINAPI DECLSPEC_HOTPATCH FlsAlloc( PFLS_CALLBACK_FUNCTION callback ) - DWORD index; - PEB * const peb = NtCurrentTeb()->Peb; - -- RtlAcquirePebLock(); -+ lock_fls_section(); - if (!peb->FlsCallback) - { - SetLastError( ERROR_NOT_ENOUGH_MEMORY ); -@@ -1133,7 +1133,7 @@ DWORD WINAPI DECLSPEC_HOTPATCH FlsAlloc( PFLS_CALLBACK_FUNCTION callback ) - } - else SetLastError( ERROR_NO_MORE_ITEMS ); - } -- RtlReleasePebLock(); -+ unlock_fls_section(); - return index; - } - -@@ -1145,7 +1145,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH FlsFree( DWORD index ) - { - BOOL ret; - -- RtlAcquirePebLock(); -+ lock_fls_section(); - ret = RtlAreBitsSet( NtCurrentTeb()->Peb->FlsBitmap, index, 1 ); - if (ret) RtlClearBits( NtCurrentTeb()->Peb->FlsBitmap, index, 1 ); - if (ret) -@@ -1155,7 +1155,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH FlsFree( DWORD index ) - if (NtCurrentTeb()->FlsSlots) *fls_addr_from_index(NtCurrentTeb()->FlsSlots, index) = NULL; - } - else SetLastError( ERROR_INVALID_PARAMETER ); -- RtlReleasePebLock(); -+ unlock_fls_section(); - return ret; - } - --- -2.25.3 - diff --git a/patches/ntdll-FLS_Callbacks/0002-ntdll-Call-FLS-callbacks.patch b/patches/ntdll-FLS_Callbacks/0002-ntdll-Call-FLS-callbacks.patch new file mode 100644 index 00000000..a4e09fe7 --- /dev/null +++ b/patches/ntdll-FLS_Callbacks/0002-ntdll-Call-FLS-callbacks.patch @@ -0,0 +1,370 @@ +From c1eaab70d4cd062e8d716dcc5c3a0578ea2fa367 Mon Sep 17 00:00:00 2001 +From: Paul Gofman +Date: Thu, 1 Oct 2020 16:58:06 +0300 +Subject: [PATCH] ntdll: Call FLS callbacks. + +--- + dlls/kernel32/tests/fiber.c | 24 +++++++++-- + dlls/kernel32/tests/loader.c | 79 ++++++++++++++++++++++++++---------- + dlls/ntdll/loader.c | 8 +++- + dlls/ntdll/thread.c | 38 +++++++++++++++-- + 4 files changed, 118 insertions(+), 31 deletions(-) + +diff --git a/dlls/kernel32/tests/fiber.c b/dlls/kernel32/tests/fiber.c +index 30f9152c39e..1b5d0d1393a 100644 +--- a/dlls/kernel32/tests/fiber.c ++++ b/dlls/kernel32/tests/fiber.c +@@ -223,8 +223,11 @@ static unsigned int check_linked_list(const LIST_ENTRY *le, const LIST_ENTRY *se + return count; + } + ++static unsigned int test_fls_callback_call_count; ++ + static void WINAPI test_fls_callback(void *data) + { ++ ++test_fls_callback_call_count; + } + + static unsigned int test_fls_chunk_size(unsigned int chunk_index) +@@ -377,8 +380,11 @@ static void test_FiberLocalStorage(void) + ok(status == STATUS_INVALID_PARAMETER, "Got unexpected status %#x.\n", status); + + g_fls_data->fls_callback_chunks[j]->callbacks[index].callback = test_fls_callback; ++ test_fls_callback_call_count = 0; + status = pRtlFlsFree(fls_indices[0x10]); + ok(!status, "Got unexpected status %#x.\n", status); ++ ok(test_fls_callback_call_count == 1, "Got unexpected callback call count %u.\n", ++ test_fls_callback_call_count); + + ok(!fls_data->fls_data_chunks[j][0], "Got unexpected fls_data->fls_data_chunks[%u][0] %p.\n", + j, fls_data->fls_data_chunks[j][0]); +@@ -405,7 +411,7 @@ static void test_FiberLocalStorage(void) + ok(val == (void *)0xdeadbeef, "Got unexpected val %p.\n", val); + ok(!new_fls_data, "Got unexpected teb->FlsSlots %p.\n", new_fls_data); + +- status = pRtlFlsSetValue(fls_indices[1], NULL); ++ status = pRtlFlsSetValue(fls_indices[1], (void *)(ULONG_PTR)0x28); + new_fls_data = teb->FlsSlots; + ok(!status, "Got unexpected status %#x.\n", status); + ok(!!new_fls_data, "Got unexpected teb->FlsSlots %p.\n", new_fls_data); +@@ -450,11 +456,15 @@ static void test_FiberLocalStorage(void) + ok(result == WAIT_OBJECT_0, "Got unexpected result %u.\n", result); + teb->FlsSlots = NULL; + ++ test_fls_callback_call_count = 0; + saved_entry = new_fls_data->fls_list_entry; + pRtlProcessFlsData(new_fls_data, 1); + ok(!teb->FlsSlots, "Got unexpected teb->FlsSlots %p.\n", teb->FlsSlots); + + teb->FlsSlots = fls_data; ++ ok(test_fls_callback_call_count == 1, "Got unexpected callback call count %u.\n", ++ test_fls_callback_call_count); ++ + SetEvent(test_fiberlocalstorage_done_event); + WaitForSingleObject(hthread, INFINITE); + CloseHandle(hthread); +@@ -467,7 +477,13 @@ static void test_FiberLocalStorage(void) + saved_entry.Blink); + size = HeapSize(GetProcessHeap(), 0, new_fls_data); + ok(size == sizeof(*new_fls_data), "Got unexpected size %p.\n", (void *)size); ++ test_fls_callback_call_count = 0; ++ i = test_fls_chunk_index_from_index(fls_indices[1], &index); ++ new_fls_data->fls_data_chunks[i][index + 1] = (void *)(ULONG_PTR)0x28; + pRtlProcessFlsData(new_fls_data, 2); ++ ok(!test_fls_callback_call_count, "Got unexpected callback call count %u.\n", ++ test_fls_callback_call_count); ++ + if (0) + { + /* crashes on Windows. */ +@@ -676,7 +692,7 @@ static void test_FiberLocalStorageCallback(PFLS_CALLBACK_FUNCTION cbfunc) + + ret = pFlsFree( fls ); + ok(ret, "FlsFree failed with error %u\n", GetLastError() ); +- todo_wine ok( cbCount == 1, "Wrong callback count: %d\n", cbCount ); ++ ok( cbCount == 1, "Wrong callback count: %d\n", cbCount ); + + /* Test that callback is not executed if value is NULL */ + cbCount = 0; +@@ -741,14 +757,14 @@ static void test_FiberLocalStorageWithFibers(PFLS_CALLBACK_FUNCTION cbfunc) + fls_value_to_set = val1; + pDeleteFiber(fibers[1]); + ok(fiberCount == 0, "Wrong fiber count: %d\n", fiberCount); +- todo_wine ok(cbCount == 1, "Wrong callback count: %d\n", cbCount); ++ ok(cbCount == 1, "Wrong callback count: %d\n", cbCount); + + fiberCount = 0; + cbCount = 0; + fls_value_to_set = val2; + pFlsFree(fls_index_to_set); + ok(fiberCount == 0, "Wrong fiber count: %d\n", fiberCount); +- todo_wine ok(cbCount == 2, "Wrong callback count: %d\n", cbCount); ++ ok(cbCount == 2, "Wrong callback count: %d\n", cbCount); + + fiberCount = 0; + cbCount = 0; +diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c +index a718c2c434f..d101104af1d 100644 +--- a/dlls/kernel32/tests/loader.c ++++ b/dlls/kernel32/tests/loader.c +@@ -2319,12 +2319,34 @@ static VOID WINAPI fls_callback(PVOID lpFlsData) + InterlockedIncrement(&fls_callback_count); + } + ++static LIST_ENTRY *fls_list_head; ++ ++static unsigned int check_linked_list(const LIST_ENTRY *le, const LIST_ENTRY *search_entry, unsigned int *index_found) ++{ ++ unsigned int count = 0; ++ LIST_ENTRY *entry; ++ ++ *index_found = ~0; ++ ++ for (entry = le->Flink; entry != le; entry = entry->Flink) ++ { ++ if (entry == search_entry) ++ { ++ ok(*index_found == ~0, "Duplicate list entry.\n"); ++ *index_found = count; ++ } ++ ++count; ++ } ++ return count; ++} ++ + static BOOL WINAPI dll_entry_point(HINSTANCE hinst, DWORD reason, LPVOID param) + { + static LONG noop_thread_started; +- static DWORD fls_index = FLS_OUT_OF_INDEXES; ++ static DWORD fls_index = FLS_OUT_OF_INDEXES, fls_index2 = FLS_OUT_OF_INDEXES; + static int fls_count = 0; + static int thread_detach_count = 0; ++ static int thread_count; + DWORD ret; + + ok(!inside_loader_lock, "inside_loader_lock should not be set\n"); +@@ -2353,8 +2375,11 @@ static BOOL WINAPI dll_entry_point(HINSTANCE hinst, DWORD reason, LPVOID param) + bret = pFlsSetValue(fls_index, (void*) 0x31415); + ok(bret, "FlsSetValue failed\n"); + fls_count++; +- } + ++ fls_index2 = pFlsAlloc(&fls_callback); ++ ok(fls_index2 != FLS_OUT_OF_INDEXES, "FlsAlloc returned %d\n", ret); ++ } ++ ++thread_count; + break; + case DLL_PROCESS_DETACH: + { +@@ -2424,18 +2449,12 @@ todo_wine + void* value; + SetLastError(0xdeadbeef); + value = pFlsGetValue(fls_index); +- todo_wine +- { +- ok(broken(value == (void*) 0x31415) || /* Win2k3 */ +- value == NULL, "FlsGetValue returned %p, expected NULL\n", value); +- } ++ ok(broken(value == (void*) 0x31415) || /* Win2k3 */ ++ value == NULL, "FlsGetValue returned %p, expected NULL\n", value); + ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError()); +- todo_wine +- { +- ok(broken(fls_callback_count == thread_detach_count) || /* Win2k3 */ +- fls_callback_count == thread_detach_count + 1, +- "wrong FLS callback count %d, expected %d\n", fls_callback_count, thread_detach_count + 1); +- } ++ ok(broken(fls_callback_count == thread_detach_count) || /* Win2k3 */ ++ fls_callback_count == thread_detach_count + 1, ++ "wrong FLS callback count %d, expected %d\n", fls_callback_count, thread_detach_count + 1); + } + if (pFlsFree) + { +@@ -2444,11 +2463,8 @@ todo_wine + ret = pFlsFree(fls_index); + ok(ret, "FlsFree failed with error %u\n", GetLastError()); + fls_index = FLS_OUT_OF_INDEXES; +- todo_wine +- { +- ok(fls_callback_count == fls_count, +- "wrong FLS callback count %d, expected %d\n", fls_callback_count, fls_count); +- } ++ ok(fls_callback_count == fls_count, ++ "wrong FLS callback count %d, expected %d\n", fls_callback_count, fls_count); + } + + ok(attached_thread_count >= 2, "attached thread count should be >= 2\n"); +@@ -2612,6 +2628,8 @@ todo_wine + case DLL_THREAD_ATTACH: + trace("dll: %p, DLL_THREAD_ATTACH, %p\n", hinst, param); + ++ ++thread_count; ++ + ret = pRtlDllShutdownInProgress(); + ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret); + +@@ -2639,6 +2657,7 @@ todo_wine + break; + case DLL_THREAD_DETACH: + trace("dll: %p, DLL_THREAD_DETACH, %p\n", hinst, param); ++ --thread_count; + thread_detach_count++; + + ret = pRtlDllShutdownInProgress(); +@@ -2657,15 +2676,25 @@ todo_wine + */ + if (pFlsGetValue && fls_index != FLS_OUT_OF_INDEXES) + { ++ unsigned int index, count; + void* value; ++ BOOL bret; ++ + SetLastError(0xdeadbeef); + value = pFlsGetValue(fls_index); +- todo_wine ++ ok(broken(value == (void*) 0x31415) || /* Win2k3 */ ++ !value, "FlsGetValue returned %p, expected NULL\n", value); ++ ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError()); ++ ++ bret = pFlsSetValue(fls_index2, (void*) 0x31415); ++ ok(bret, "FlsSetValue failed\n"); ++ ++ if (fls_list_head) + { +- ok(broken(value == (void*) 0x31415) || /* Win2k3 */ +- !value, "FlsGetValue returned %p, expected NULL\n", value); ++ count = check_linked_list(fls_list_head, &NtCurrentTeb()->FlsSlots->fls_list_entry, &index); ++ ok(count <= thread_count, "Got unexpected count %u, thread_count %u.\n", count, thread_count); ++ ok(index == ~0, "Got unexpected index %u.\n", index); + } +- ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError()); + } + + break; +@@ -2690,6 +2719,12 @@ static void child_process(const char *dll_name, DWORD target_offset) + + trace("phase %d: writing %p at %#x\n", test_dll_phase, dll_entry_point, target_offset); + ++ if (pFlsAlloc) ++ { ++ fls_list_head = NtCurrentTeb()->Peb->FlsListHead.Flink ? &NtCurrentTeb()->Peb->FlsListHead ++ : NtCurrentTeb()->FlsSlots->fls_list_entry.Flink; ++ } ++ + SetLastError(0xdeadbeef); + mutex = CreateMutexW(NULL, FALSE, NULL); + ok(mutex != 0, "CreateMutex error %d\n", GetLastError()); +diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c +index 38dfc7f7233..cfa07140d7f 100644 +--- a/dlls/ntdll/loader.c ++++ b/dlls/ntdll/loader.c +@@ -3354,6 +3354,10 @@ fail: + void WINAPI LdrShutdownProcess(void) + { + TRACE("()\n"); ++ ++ if (!process_detaching) ++ RtlProcessFlsData( NtCurrentTeb()->FlsSlots, 1 ); ++ + process_detaching = TRUE; + process_detach(); + } +@@ -3388,6 +3392,8 @@ void WINAPI LdrShutdownThread(void) + /* don't do any detach calls if process is exiting */ + if (process_detaching) return; + ++ RtlProcessFlsData( NtCurrentTeb()->FlsSlots, 1 ); ++ + RtlEnterCriticalSection( &loader_section ); + wm = get_modref( NtCurrentTeb()->Peb->ImageBaseAddress ); + +@@ -3414,7 +3420,7 @@ void WINAPI LdrShutdownThread(void) + for (i = 0; i < tls_module_count; i++) RtlFreeHeap( GetProcessHeap(), 0, pointers[i] ); + RtlFreeHeap( GetProcessHeap(), 0, pointers ); + } +- RtlProcessFlsData( NtCurrentTeb()->FlsSlots, 3 ); ++ RtlProcessFlsData( NtCurrentTeb()->FlsSlots, 2 ); + NtCurrentTeb()->FlsSlots = NULL; + RtlFreeHeap( GetProcessHeap(), 0, NtCurrentTeb()->TlsExpansionSlots ); + NtCurrentTeb()->TlsExpansionSlots = NULL; +diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c +index 95511391d34..2926d6173bf 100644 +--- a/dlls/ntdll/thread.c ++++ b/dlls/ntdll/thread.c +@@ -390,6 +390,7 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsAlloc( PFLS_CALLBACK_FUNCTION callback, + */ + NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsFree( ULONG index ) + { ++ PFLS_CALLBACK_FUNCTION callback; + unsigned int chunk_index, idx; + FLS_INFO_CHUNK *chunk; + LIST_ENTRY *entry; +@@ -404,7 +405,7 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsFree( ULONG index ) + + chunk_index = fls_chunk_index_from_index( index, &idx ); + if (!(chunk = fls_data.fls_callback_chunks[chunk_index]) +- || !chunk->callbacks[idx].callback) ++ || !(callback = chunk->callbacks[idx].callback)) + { + unlock_fls_data(); + return STATUS_INVALID_PARAMETER; +@@ -414,9 +415,15 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsFree( ULONG index ) + { + TEB_FLS_DATA *fls = CONTAINING_RECORD(entry, TEB_FLS_DATA, fls_list_entry); + +- if (fls->fls_data_chunks[chunk_index]) ++ if (fls->fls_data_chunks[chunk_index] && fls->fls_data_chunks[chunk_index][idx + 1]) + { +- /* FIXME: call Fls callback */ ++ if (callback != (void *)~(ULONG_PTR)0) ++ { ++ TRACE_(relay)("Calling FLS callback %p, arg %p.\n", callback, ++ fls->fls_data_chunks[chunk_index][idx + 1]); ++ ++ callback( fls->fls_data_chunks[chunk_index][idx + 1] ); ++ } + fls->fls_data_chunks[chunk_index][idx + 1] = NULL; + } + } +@@ -481,7 +488,7 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsGetValue( ULONG index, void **data ) + void WINAPI DECLSPEC_HOTPATCH RtlProcessFlsData( void *teb_fls_data, ULONG flags ) + { + TEB_FLS_DATA *fls = teb_fls_data; +- unsigned int i; ++ unsigned int i, index; + + TRACE_(thread)( "teb_fls_data %p, flags %#x.\n", teb_fls_data, flags ); + +@@ -494,6 +501,29 @@ void WINAPI DECLSPEC_HOTPATCH RtlProcessFlsData( void *teb_fls_data, ULONG flags + if (flags & 1) + { + lock_fls_data(); ++ for (i = 0; i < ARRAY_SIZE(fls->fls_data_chunks); ++i) ++ { ++ if (!fls->fls_data_chunks[i] || !fls_data.fls_callback_chunks[i] ++ || !fls_data.fls_callback_chunks[i]->count) ++ continue; ++ ++ for (index = 0; index < fls_chunk_size( i ); ++index) ++ { ++ PFLS_CALLBACK_FUNCTION callback = fls_data.fls_callback_chunks[i]->callbacks[index].callback; ++ ++ if (!fls->fls_data_chunks[i][index + 1]) ++ continue; ++ ++ if (callback && callback != (void *)~(ULONG_PTR)0) ++ { ++ TRACE_(relay)("Calling FLS callback %p, arg %p.\n", callback, ++ fls->fls_data_chunks[i][index + 1]); ++ ++ callback( fls->fls_data_chunks[i][index + 1] ); ++ } ++ fls->fls_data_chunks[i][index + 1] = NULL; ++ } ++ } + /* Not using RemoveEntryList() as Windows does not zero list entry here. */ + fls->fls_list_entry.Flink->Blink = fls->fls_list_entry.Blink; + fls->fls_list_entry.Blink->Flink = fls->fls_list_entry.Flink; +-- +2.26.2 + diff --git a/patches/ntdll-FLS_Callbacks/0003-kernelbase-Zero-all-FLS-slots-instances-in-FlsFree.patch b/patches/ntdll-FLS_Callbacks/0003-kernelbase-Zero-all-FLS-slots-instances-in-FlsFree.patch deleted file mode 100644 index 886ed1b4..00000000 --- a/patches/ntdll-FLS_Callbacks/0003-kernelbase-Zero-all-FLS-slots-instances-in-FlsFree.patch +++ /dev/null @@ -1,46 +0,0 @@ -From ee30a9aeb8db442a9cea52449959178f9d449d39 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Thu, 23 Apr 2020 15:00:48 +0300 -Subject: [PATCH] kernelbase: Zero all FLS slots instances in FlsFree(). - ---- - dlls/kernelbase/thread.c | 15 ++++++++++----- - 1 file changed, 10 insertions(+), 5 deletions(-) - -diff --git a/dlls/kernelbase/thread.c b/dlls/kernelbase/thread.c -index 0ba67e1b6c9..9a65630cca7 100644 ---- a/dlls/kernelbase/thread.c -+++ b/dlls/kernelbase/thread.c -@@ -1137,7 +1137,6 @@ DWORD WINAPI DECLSPEC_HOTPATCH FlsAlloc( PFLS_CALLBACK_FUNCTION callback ) - return index; - } - -- - /*********************************************************************** - * FlsFree (kernelbase.@) - */ -@@ -1148,11 +1147,17 @@ BOOL WINAPI DECLSPEC_HOTPATCH FlsFree( DWORD index ) - lock_fls_section(); - ret = RtlAreBitsSet( NtCurrentTeb()->Peb->FlsBitmap, index, 1 ); - if (ret) RtlClearBits( NtCurrentTeb()->Peb->FlsBitmap, index, 1 ); -- if (ret) -+ if (ret && NtCurrentTeb()->FlsSlots) - { -- /* FIXME: call Fls callback */ -- /* FIXME: add equivalent of ThreadZeroTlsCell here */ -- if (NtCurrentTeb()->FlsSlots) *fls_addr_from_index(NtCurrentTeb()->FlsSlots, index) = NULL; -+ LIST_ENTRY *entry; -+ -+ for (entry = NtCurrentTeb()->Peb->FlsListHead.Flink; -+ entry != &NtCurrentTeb()->Peb->FlsListHead; -+ entry = entry->Flink) -+ { -+ /* FIXME: call Fls callback */ -+ *fls_addr_from_index(entry, index) = NULL; -+ } - } - else SetLastError( ERROR_INVALID_PARAMETER ); - unlock_fls_section(); --- -2.25.3 - diff --git a/patches/ntdll-FLS_Callbacks/0004-ntdll-Call-FLS-callbacks-on-thread-shutdown.patch b/patches/ntdll-FLS_Callbacks/0004-ntdll-Call-FLS-callbacks-on-thread-shutdown.patch deleted file mode 100644 index 9549fa23..00000000 --- a/patches/ntdll-FLS_Callbacks/0004-ntdll-Call-FLS-callbacks-on-thread-shutdown.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 7a474e95ad8cb82140e541a65b2bf338b42c3090 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Thu, 23 Apr 2020 16:09:11 +0300 -Subject: [PATCH] ntdll: Call FLS callbacks on thread shutdown. - ---- - dlls/kernel32/tests/loader.c | 26 ++++++++------------------ - dlls/ntdll/loader.c | 30 ++++++++++++++++++++++++++++++ - 2 files changed, 38 insertions(+), 18 deletions(-) - -diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c -index 3ed3351c02e..9cddfb82d51 100644 ---- a/dlls/kernel32/tests/loader.c -+++ b/dlls/kernel32/tests/loader.c -@@ -2520,18 +2520,12 @@ todo_wine - void* value; - SetLastError(0xdeadbeef); - value = pFlsGetValue(fls_index); -- todo_wine -- { -- ok(broken(value == (void*) 0x31415) || /* Win2k3 */ -- value == NULL, "FlsGetValue returned %p, expected NULL\n", value); -- } -+ ok(broken(value == (void*) 0x31415) || /* Win2k3 */ -+ value == NULL, "FlsGetValue returned %p, expected NULL\n", value); - ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError()); -- todo_wine -- { -- ok(broken(fls_callback_count == thread_detach_count) || /* Win2k3 */ -- fls_callback_count == thread_detach_count + 1, -- "wrong FLS callback count %d, expected %d\n", fls_callback_count, thread_detach_count + 1); -- } -+ ok(broken(fls_callback_count == thread_detach_count) || /* Win2k3 */ -+ fls_callback_count == thread_detach_count + 1, -+ "wrong FLS callback count %d, expected %d\n", fls_callback_count, thread_detach_count + 1); - } - if (pFlsFree) - { -@@ -2726,8 +2720,7 @@ todo_wine - SetLastError(0xdeadbeef); - value = pFlsGetValue(fls_index); - ok(!value, "FlsGetValue returned %p, expected NULL\n", value); -- todo_wine -- ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError()); -+ ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError()); - ret = pFlsSetValue(fls_index, (void*) 0x31415); - ok(ret, "FlsSetValue failed\n"); - fls_count++; -@@ -2757,11 +2750,8 @@ todo_wine - void* value; - SetLastError(0xdeadbeef); - value = pFlsGetValue(fls_index); -- todo_wine -- { -- ok(broken(value == (void*) 0x31415) || /* Win2k3 */ -- !value, "FlsGetValue returned %p, expected NULL\n", value); -- } -+ ok(broken(value == (void*) 0x31415) || /* Win2k3 */ -+ !value, "FlsGetValue returned %p, expected NULL\n", value); - ok(GetLastError() == ERROR_SUCCESS, "FlsGetValue failed with error %u\n", GetLastError()); - } - -diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c -index 71ef1cfea0a..681b7f4b114 100644 ---- a/dlls/ntdll/loader.c -+++ b/dlls/ntdll/loader.c -@@ -1621,6 +1621,30 @@ static void attach_implicitly_loaded_dlls( LPVOID reserved ) - } - } - -+static void call_fls_callbacks(void) -+{ -+ PFLS_CALLBACK_FUNCTION *fls_callbacks; -+ PRTL_BITMAP fls_bitmap; -+ void **fls_slot_data; -+ DWORD fls_index; -+ -+ if ((fls_callbacks = (PFLS_CALLBACK_FUNCTION *)NtCurrentTeb()->Peb->FlsCallback) && NtCurrentTeb()->FlsSlots) -+ { -+ fls_slot_data = (void **)((BYTE *)NtCurrentTeb()->FlsSlots + sizeof(LIST_ENTRY)); -+ fls_bitmap = NtCurrentTeb()->Peb->FlsBitmap; -+ fls_index = 0; -+ for (fls_index = 0; fls_index < fls_bitmap->SizeOfBitMap; ++fls_index) -+ { -+ if (!RtlAreBitsSet( fls_bitmap, fls_index, 1 )) -+ continue; -+ -+ if (fls_callbacks[fls_index + 2] && fls_slot_data[fls_index]) -+ fls_callbacks[fls_index + 2](fls_slot_data[fls_index]); -+ -+ fls_slot_data[fls_index] = NULL; -+ } -+ } -+} - - /************************************************************************* - * process_detach -@@ -3898,6 +3922,11 @@ fail: - void WINAPI LdrShutdownProcess(void) - { - TRACE("()\n"); -+ -+ lock_fls_section(NULL); -+ call_fls_callbacks(); -+ unlock_fls_section(NULL); -+ - process_detaching = TRUE; - process_detach(); - } -@@ -3936,6 +3965,7 @@ void WINAPI LdrShutdownThread(void) - { - lock_fls_section( NULL ); - RemoveEntryList( (LIST_ENTRY *)NtCurrentTeb()->FlsSlots ); -+ call_fls_callbacks(); - unlock_fls_section( NULL ); - } - --- -2.25.3 - diff --git a/patches/ntdll-FLS_Callbacks/0005-kernelbase-Call-FLS-callbacks-from-FlsFree.patch b/patches/ntdll-FLS_Callbacks/0005-kernelbase-Call-FLS-callbacks-from-FlsFree.patch deleted file mode 100644 index 220f72ca..00000000 --- a/patches/ntdll-FLS_Callbacks/0005-kernelbase-Call-FLS-callbacks-from-FlsFree.patch +++ /dev/null @@ -1,85 +0,0 @@ -From f675a05f09d1173308ab138ffdfcaee125c3c0ba Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Thu, 23 Apr 2020 16:58:42 +0300 -Subject: [PATCH] kernelbase: Call FLS callbacks from FlsFree(). - ---- - dlls/kernel32/tests/fiber.c | 4 ++-- - dlls/kernel32/tests/loader.c | 7 ++----- - dlls/kernelbase/thread.c | 13 +++++++++++-- - 3 files changed, 15 insertions(+), 9 deletions(-) - -diff --git a/dlls/kernel32/tests/fiber.c b/dlls/kernel32/tests/fiber.c -index 2bcc3ee60c4..3aae0400d03 100644 ---- a/dlls/kernel32/tests/fiber.c -+++ b/dlls/kernel32/tests/fiber.c -@@ -344,7 +344,7 @@ static void test_FiberLocalStorageCallback(PFLS_CALLBACK_FUNCTION cbfunc) - - ret = pFlsFree( fls ); - ok(ret, "FlsFree failed with error %u\n", GetLastError() ); -- todo_wine ok( cbCount == 1, "Wrong callback count: %d\n", cbCount ); -+ ok( cbCount == 1, "Wrong callback count: %d\n", cbCount ); - - /* Test that callback is not executed if value is NULL */ - cbCount = 0; -@@ -416,7 +416,7 @@ static void test_FiberLocalStorageWithFibers(PFLS_CALLBACK_FUNCTION cbfunc) - fls_value_to_set = val2; - pFlsFree(fls_index_to_set); - ok(fiberCount == 0, "Wrong fiber count: %d\n", fiberCount); -- todo_wine ok(cbCount == 2, "Wrong callback count: %d\n", cbCount); -+ ok(cbCount == 2, "Wrong callback count: %d\n", cbCount); - - fiberCount = 0; - cbCount = 0; -diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c -index 9cddfb82d51..21af7b4ce7a 100644 ---- a/dlls/kernel32/tests/loader.c -+++ b/dlls/kernel32/tests/loader.c -@@ -2534,11 +2534,8 @@ todo_wine - ret = pFlsFree(fls_index); - ok(ret, "FlsFree failed with error %u\n", GetLastError()); - fls_index = FLS_OUT_OF_INDEXES; -- todo_wine -- { -- ok(fls_callback_count == fls_count, -- "wrong FLS callback count %d, expected %d\n", fls_callback_count, fls_count); -- } -+ ok(fls_callback_count == fls_count, -+ "wrong FLS callback count %d, expected %d\n", fls_callback_count, fls_count); - } - - ok(attached_thread_count >= 2, "attached thread count should be >= 2\n"); -diff --git a/dlls/kernelbase/thread.c b/dlls/kernelbase/thread.c -index 9a65630cca7..40ba9ea4f07 100644 ---- a/dlls/kernelbase/thread.c -+++ b/dlls/kernelbase/thread.c -@@ -1149,15 +1149,24 @@ BOOL WINAPI DECLSPEC_HOTPATCH FlsFree( DWORD index ) - if (ret) RtlClearBits( NtCurrentTeb()->Peb->FlsBitmap, index, 1 ); - if (ret && NtCurrentTeb()->FlsSlots) - { -+ PFLS_CALLBACK_FUNCTION *fls_callbacks; - LIST_ENTRY *entry; - -+ fls_callbacks = (PFLS_CALLBACK_FUNCTION *)NtCurrentTeb()->Peb->FlsCallback; -+ - for (entry = NtCurrentTeb()->Peb->FlsListHead.Flink; - entry != &NtCurrentTeb()->Peb->FlsListHead; - entry = entry->Flink) - { -- /* FIXME: call Fls callback */ -- *fls_addr_from_index(entry, index) = NULL; -+ void **value_ptr = fls_addr_from_index(entry, index); -+ -+ if (fls_callbacks && fls_callbacks[index + 2] && *value_ptr) -+ fls_callbacks[index + 2](*value_ptr); -+ -+ *value_ptr = NULL; - } -+ if (fls_callbacks) -+ fls_callbacks[index + 2] = NULL; - } - else SetLastError( ERROR_INVALID_PARAMETER ); - unlock_fls_section(); --- -2.25.3 - diff --git a/patches/ntdll-FLS_Callbacks/0006-kernelbase-Call-FLS-callbacks-from-DeleteFiber.patch b/patches/ntdll-FLS_Callbacks/0006-kernelbase-Call-FLS-callbacks-from-DeleteFiber.patch deleted file mode 100644 index 03e4d5f4..00000000 --- a/patches/ntdll-FLS_Callbacks/0006-kernelbase-Call-FLS-callbacks-from-DeleteFiber.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 9bd8f42cf95582935440a622c76a4579ba3659f6 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Thu, 23 Apr 2020 18:22:59 +0300 -Subject: [PATCH] kernelbase: Call FLS callbacks from DeleteFiber(). - ---- - dlls/kernel32/tests/fiber.c | 2 +- - dlls/kernelbase/thread.c | 26 +++++++++++++++++++++++++- - 2 files changed, 26 insertions(+), 2 deletions(-) - -diff --git a/dlls/kernel32/tests/fiber.c b/dlls/kernel32/tests/fiber.c -index 3aae0400d03..b6ae9cdc2f6 100644 ---- a/dlls/kernel32/tests/fiber.c -+++ b/dlls/kernel32/tests/fiber.c -@@ -409,7 +409,7 @@ static void test_FiberLocalStorageWithFibers(PFLS_CALLBACK_FUNCTION cbfunc) - fls_value_to_set = val1; - pDeleteFiber(fibers[1]); - ok(fiberCount == 0, "Wrong fiber count: %d\n", fiberCount); -- todo_wine ok(cbCount == 1, "Wrong callback count: %d\n", cbCount); -+ ok(cbCount == 1, "Wrong callback count: %d\n", cbCount); - - fiberCount = 0; - cbCount = 0; -diff --git a/dlls/kernelbase/thread.c b/dlls/kernelbase/thread.c -index 40ba9ea4f07..09dfe162e17 100644 ---- a/dlls/kernelbase/thread.c -+++ b/dlls/kernelbase/thread.c -@@ -1025,6 +1025,30 @@ LPVOID WINAPI DECLSPEC_HOTPATCH ConvertThreadToFiberEx( LPVOID param, DWORD flag - return fiber; - } - -+static void call_fls_callbacks(void **fls_slots) -+{ -+ PFLS_CALLBACK_FUNCTION *fls_callbacks; -+ PRTL_BITMAP fls_bitmap; -+ void **fls_slot_data; -+ DWORD fls_index; -+ -+ if ((fls_callbacks = (PFLS_CALLBACK_FUNCTION *)NtCurrentTeb()->Peb->FlsCallback)) -+ { -+ fls_slot_data = (void **)((BYTE *)fls_slots + sizeof(LIST_ENTRY)); -+ fls_bitmap = NtCurrentTeb()->Peb->FlsBitmap; -+ fls_index = 0; -+ for (fls_index = 0; fls_index < fls_bitmap->SizeOfBitMap; ++fls_index) -+ { -+ if (!RtlAreBitsSet( fls_bitmap, fls_index, 1 )) -+ continue; -+ -+ if (fls_callbacks[fls_index + 2] && fls_slot_data[fls_index]) -+ fls_callbacks[fls_index + 2](fls_slot_data[fls_index]); -+ -+ fls_slot_data[fls_index] = NULL; -+ } -+ } -+} - - /*********************************************************************** - * DeleteFiber (kernelbase.@) -@@ -1045,8 +1069,8 @@ void WINAPI DECLSPEC_HOTPATCH DeleteFiber( LPVOID fiber_ptr ) - { - lock_fls_section(); - RemoveEntryList( (LIST_ENTRY *)fiber->fls_slots ); -+ call_fls_callbacks(fiber->fls_slots); - unlock_fls_section(); -- - HeapFree( GetProcessHeap(), 0, fiber->fls_slots ); - } - --- -2.25.3 - diff --git a/patches/ntdll-FLS_Callbacks/definition b/patches/ntdll-FLS_Callbacks/definition index 785ea186..2b6d6949 100644 --- a/patches/ntdll-FLS_Callbacks/definition +++ b/patches/ntdll-FLS_Callbacks/definition @@ -1,2 +1,2 @@ Fixes: [49012] Application build with .NET CoreRT crashes due to FLS callbacks not being called -Disabled: True +Disabled: False diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 7fd177bb..b28d3b60 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -163,6 +163,7 @@ patch_enable_all () enable_ntdll_DOS_Attributes="$1" enable_ntdll_Dealloc_Thread_Stack="$1" enable_ntdll_Exception="$1" + enable_ntdll_FLS_Callbacks="$1" enable_ntdll_FileDispositionInformation="$1" enable_ntdll_FileFsFullSizeInformation="$1" enable_ntdll_Fix_Alignment="$1" @@ -579,6 +580,9 @@ patch_enable () ntdll-Exception) enable_ntdll_Exception="$2" ;; + ntdll-FLS_Callbacks) + enable_ntdll_FLS_Callbacks="$2" + ;; ntdll-FileDispositionInformation) enable_ntdll_FileDispositionInformation="$2" ;; @@ -2978,6 +2982,19 @@ if test "$enable_ntdll_Exception" -eq 1; then patch_apply ntdll-Exception/0002-ntdll-OutputDebugString-should-throw-the-exception-a.patch fi +# Patchset ntdll-FLS_Callbacks +# | +# | This patchset fixes the following Wine bugs: +# | * [#49012] Application build with .NET CoreRT crashes due to FLS callbacks not being called +# | +# | Modified files: +# | * dlls/kernel32/tests/fiber.c, dlls/kernel32/tests/loader.c, dlls/ntdll/loader.c, dlls/ntdll/thread.c +# | +if test "$enable_ntdll_FLS_Callbacks" -eq 1; then + patch_apply ntdll-FLS_Callbacks/0001-ntdll-Zero-all-FLS-slots-instances-in-RtlFlsFree.patch + patch_apply ntdll-FLS_Callbacks/0002-ntdll-Call-FLS-callbacks.patch +fi + # Patchset ntdll-FileFsFullSizeInformation # | # | Modified files: