mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
Updated and reenabled ntdll-FLS_Callbacks patchset.
This commit is contained in:
parent
6ea9eb634f
commit
b49e874386
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
370
patches/ntdll-FLS_Callbacks/0002-ntdll-Call-FLS-callbacks.patch
Normal file
370
patches/ntdll-FLS_Callbacks/0002-ntdll-Call-FLS-callbacks.patch
Normal 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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,2 +1,2 @@
|
||||
Fixes: [49012] Application build with .NET CoreRT crashes due to FLS callbacks not being called
|
||||
Disabled: True
|
||||
Disabled: False
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user