Updated and reenabled ntdll-FLS_Callbacks patchset.

This commit is contained in:
Paul Gofman 2020-10-10 15:22:28 +03:00
parent 6ea9eb634f
commit b49e874386
10 changed files with 432 additions and 697 deletions

View File

@ -1,322 +0,0 @@
From b0225150b6721f7c75124c534b8841aa1a8039bd Mon Sep 17 00:00:00 2001
From: Paul Gofman <pgofman@codeweavers.com>
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 <winternl.h>
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

View File

@ -0,0 +1,44 @@
From fa80bc605c8cffa33475fbabc12cc0b79978b11e Mon Sep 17 00:00:00 2001
From: Paul Gofman <pgofman@codeweavers.com>
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

View File

@ -1,52 +0,0 @@
From 55dbeff93ce46bfba9beaea7b9a67ba7fcd6df88 Mon Sep 17 00:00:00 2001
From: Paul Gofman <pgofman@codeweavers.com>
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

View File

@ -0,0 +1,370 @@
From c1eaab70d4cd062e8d716dcc5c3a0578ea2fa367 Mon Sep 17 00:00:00 2001
From: Paul Gofman <pgofman@codeweavers.com>
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

View File

@ -1,46 +0,0 @@
From ee30a9aeb8db442a9cea52449959178f9d449d39 Mon Sep 17 00:00:00 2001
From: Paul Gofman <pgofman@codeweavers.com>
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

View File

@ -1,120 +0,0 @@
From 7a474e95ad8cb82140e541a65b2bf338b42c3090 Mon Sep 17 00:00:00 2001
From: Paul Gofman <pgofman@codeweavers.com>
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

View File

@ -1,85 +0,0 @@
From f675a05f09d1173308ab138ffdfcaee125c3c0ba Mon Sep 17 00:00:00 2001
From: Paul Gofman <pgofman@codeweavers.com>
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

View File

@ -1,71 +0,0 @@
From 9bd8f42cf95582935440a622c76a4579ba3659f6 Mon Sep 17 00:00:00 2001
From: Paul Gofman <pgofman@codeweavers.com>
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

View File

@ -1,2 +1,2 @@
Fixes: [49012] Application build with .NET CoreRT crashes due to FLS callbacks not being called
Disabled: True
Disabled: False

View File

@ -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: