Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/kernel32/tests/fiber.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/dlls/kernel32/tests/fiber.c b/dlls/kernel32/tests/fiber.c index 7501165dc87..db2bd0923b7 100644 --- a/dlls/kernel32/tests/fiber.c +++ b/dlls/kernel32/tests/fiber.c @@ -217,13 +217,12 @@ static void test_FiberLocalStorage(void)
SetLastError( 0xdeadbeef ); ret = pFlsSetValue( 128, (void*) 0x217 ); - ok( !ret, "setting fls index 128 (out of bounds) succeeded\n" ); - ok( GetLastError() == ERROR_INVALID_PARAMETER, + ok( ret || GetLastError() == ERROR_INVALID_PARAMETER, "setting fls index 128 (out of bounds) wrong error %u\n", GetLastError() );
SetLastError( 0xdeadbeef ); val = pFlsGetValue( 128 ); - ok( GetLastError() == ERROR_INVALID_PARAMETER, + ok( GetLastError() == ERROR_INVALID_PARAMETER || val == (void *)0x217, "getting fls index 128 (out of bounds) wrong error %u\n", GetLastError() );
/* Test index 0 */ @@ -276,7 +275,7 @@ static void test_FiberLocalStorage(void)
SetLastError( 0xdeadbeef ); val = pFlsGetValue( fls_2 ); - ok( val == NULL, "fls index %u wrong value %p\n", fls, val ); + ok( val == NULL || val == (void *)0xdeadbabe, "fls index %u wrong value %p\n", fls, val ); ok( GetLastError() == ERROR_SUCCESS, "getting fls index %u failed with error %u\n", fls_2, GetLastError() ); pFlsFree( fls_2 );
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- The idea is to move FLS handling to ntdll as is first and then proceed with the missing bits: - maintain FLS storage list; - use dedicate lock instead of PEB lock; - call FLS callbacks. Apart from the Rtl functions introduced by this series there is also RtlProcessFlsData() which seems to serve as a cleanup for FLS data storage responsible for removing storage from the linked list, calling FLS callbacks and freeing storage memory.
dlls/kernel32/tests/fiber.c | 42 ++++++++++++++++++++++++++++++++++++ dlls/kernelbase/thread.c | 33 ++++------------------------ dlls/ntdll/ntdll.spec | 1 + dlls/ntdll/thread.c | 43 +++++++++++++++++++++++++++++++++++++ include/winternl.h | 1 + 5 files changed, 91 insertions(+), 29 deletions(-)
diff --git a/dlls/kernel32/tests/fiber.c b/dlls/kernel32/tests/fiber.c index db2bd0923b7..b058dae7491 100644 --- a/dlls/kernel32/tests/fiber.c +++ b/dlls/kernel32/tests/fiber.c @@ -18,6 +18,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#include <stdarg.h> + +#include <ntstatus.h> +#define WIN32_NO_STATUS +#include <winternl.h> #include "wine/test.h"
static LPVOID (WINAPI *pCreateFiber)(SIZE_T,LPFIBER_START_ROUTINE,LPVOID); @@ -32,6 +37,7 @@ static DWORD (WINAPI *pFlsAlloc)(PFLS_CALLBACK_FUNCTION); static BOOL (WINAPI *pFlsFree)(DWORD); static PVOID (WINAPI *pFlsGetValue)(DWORD); static BOOL (WINAPI *pFlsSetValue)(DWORD,PVOID); +static NTSTATUS (WINAPI *pRtlFlsAlloc)(PFLS_CALLBACK_FUNCTION,DWORD*);
static void *fibers[3]; static BYTE testparam = 185; @@ -44,6 +50,7 @@ static int cbCount = 0; static VOID init_funcs(void) { HMODULE hKernel32 = GetModuleHandleA("kernel32.dll"); + HMODULE hntdll = GetModuleHandleA("ntdll.dll");
#define X(f) p##f = (void*)GetProcAddress(hKernel32, #f); X(CreateFiber); @@ -59,6 +66,11 @@ static VOID init_funcs(void) X(FlsGetValue); X(FlsSetValue); #undef X + +#define X(f) p##f = (void*)GetProcAddress(hntdll, #f); + X(RtlFlsAlloc); +#undef X + }
static VOID WINAPI FiberLocalStorageProc(PVOID lpFlsData) @@ -171,9 +183,14 @@ static void test_FiberHandling(void) if (pIsThreadAFiber) ok(!pIsThreadAFiber(), "IsThreadAFiber reported TRUE\n"); }
+#define FLS_TEST_INDEX_COUNT 4096 + static void test_FiberLocalStorage(void) { + static DWORD fls_indices[FLS_TEST_INDEX_COUNT]; + unsigned int i, count; DWORD fls, fls_2; + NTSTATUS status; BOOL ret; void* val;
@@ -183,6 +200,31 @@ static void test_FiberLocalStorage(void) return; }
+ if (pRtlFlsAlloc) + { + for (i = 0; i < FLS_TEST_INDEX_COUNT; ++i) + { + fls_indices[i] = 0xdeadbeef; + status = pRtlFlsAlloc(NULL, &fls_indices[i]); + ok(!status || status == STATUS_NO_MEMORY, "Got unexpected status %#x.\n", status); + if (status) + { + ok(fls_indices[i] == 0xdeadbeef, "Got unexpected index %#x.\n", fls_indices[i]); + break; + } + } + count = i; + /* FLS limits are increased since Win10 18312. */ + ok(count && (count <= 127 || (count > 4000 && count < 4096)), "Got unexpected count %u.\n", count); + + for (i = 0; i < count; ++i) + pFlsFree(fls_indices[i]); + } + else + { + win_skip("RtlFlsAlloc is not available.\n"); + } + /* Test an unallocated index * FlsFree should fail * FlsGetValue and FlsSetValue should succeed diff --git a/dlls/kernelbase/thread.c b/dlls/kernelbase/thread.c index f20d460d07d..bdc7502632b 100644 --- a/dlls/kernelbase/thread.c +++ b/dlls/kernelbase/thread.c @@ -1065,39 +1065,14 @@ void WINAPI DECLSPEC_HOTPATCH SwitchToFiber( LPVOID fiber ) */ DWORD WINAPI DECLSPEC_HOTPATCH FlsAlloc( PFLS_CALLBACK_FUNCTION callback ) { + NTSTATUS status; DWORD index; - PEB * const peb = NtCurrentTeb()->Peb;
- RtlAcquirePebLock(); - if (!peb->FlsCallback && - !(peb->FlsCallback = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, - 8 * sizeof(peb->FlsBitmapBits) * sizeof(void*) ))) + if ((status = RtlFlsAlloc( callback, &index ))) { - SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - index = FLS_OUT_OF_INDEXES; - } - else - { - 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*) ))) - { - RtlClearBits( peb->FlsBitmap, index, 1 ); - index = FLS_OUT_OF_INDEXES; - SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - } - else - { - NtCurrentTeb()->FlsSlots[index] = 0; /* clear the value */ - peb->FlsCallback[index] = callback; - } - } - else SetLastError( ERROR_NO_MORE_ITEMS ); + set_ntstatus( status ); + return FLS_OUT_OF_INDEXES; } - RtlReleasePebLock(); return index; }
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 0ec73d3d1d5..aac2af26f36 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -666,6 +666,7 @@ @ stdcall RtlFindSetRuns(ptr ptr long long) @ stdcall RtlFirstEntrySList(ptr) @ stdcall RtlFirstFreeAce(ptr ptr) +@ stdcall RtlFlsAlloc(ptr ptr) @ stub RtlFlushPropertySet # @ stub RtlFlushSecureMemoryCache @ stdcall RtlFormatCurrentUserKeyPath(ptr) diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index 0f31fe18a7d..f277a52dc06 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -246,3 +246,46 @@ TEB_ACTIVE_FRAME * WINAPI RtlGetFrame(void) { return NtCurrentTeb()->ActiveFrame; } + + +/*********************************************************************** + * Fibers + ***********************************************************************/ + + +/*********************************************************************** + * RtlFlsAlloc (NTDLL.@) + */ +NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsAlloc( PFLS_CALLBACK_FUNCTION callback, DWORD *ret_index ) +{ + PEB * const peb = NtCurrentTeb()->Peb; + NTSTATUS status = STATUS_NO_MEMORY; + DWORD index; + + RtlAcquirePebLock(); + if (peb->FlsCallback || + (peb->FlsCallback = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, + 8 * sizeof(peb->FlsBitmapBits) * sizeof(void*) ))) + { + index = RtlFindClearBitsAndSet( peb->FlsBitmap, 1, 1 ); + if (index != ~0U) + { + if (!NtCurrentTeb()->FlsSlots && + !(NtCurrentTeb()->FlsSlots = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, + 8 * sizeof(peb->FlsBitmapBits) * sizeof(void*) ))) + { + RtlClearBits( peb->FlsBitmap, index, 1 ); + } + else + { + NtCurrentTeb()->FlsSlots[index] = 0; /* clear the value */ + peb->FlsCallback[index] = callback; + status = STATUS_SUCCESS; + } + } + } + RtlReleasePebLock(); + if (!status) + *ret_index = index; + return status; +} diff --git a/include/winternl.h b/include/winternl.h index 7be69b29014..ba9d9442590 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -3371,6 +3371,7 @@ NTSYSAPI ULONG WINAPI RtlFindSetBits(PCRTL_BITMAP,ULONG,ULONG); NTSYSAPI ULONG WINAPI RtlFindSetBitsAndClear(PRTL_BITMAP,ULONG,ULONG); NTSYSAPI ULONG WINAPI RtlFindSetRuns(PCRTL_BITMAP,PRTL_BITMAP_RUN,ULONG,BOOLEAN); NTSYSAPI BOOLEAN WINAPI RtlFirstFreeAce(PACL,PACE_HEADER *); +NTSYSAPI NTSTATUS WINAPI RtlFlsAlloc(PFLS_CALLBACK_FUNCTION,ULONG *); NTSYSAPI NTSTATUS WINAPI RtlFormatCurrentUserKeyPath(PUNICODE_STRING); NTSYSAPI NTSTATUS WINAPI RtlFormatMessage(LPCWSTR,ULONG,BOOLEAN,BOOLEAN,BOOLEAN,__ms_va_list *,LPWSTR,ULONG,ULONG*); NTSYSAPI NTSTATUS WINAPI RtlFormatMessageEx(LPCWSTR,ULONG,BOOLEAN,BOOLEAN,BOOLEAN,__ms_va_list *,LPWSTR,ULONG,ULONG*,ULONG);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=79481
Your paranoid android.
=== debiant (build log) ===
The task timed out
=== debiant (build log) ===
The task timed out
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/kernel32/tests/fiber.c | 8 ++++++-- dlls/kernelbase/thread.c | 15 +-------------- dlls/ntdll/ntdll.spec | 1 + dlls/ntdll/thread.c | 24 +++++++++++++++++++++++- include/winternl.h | 1 + 5 files changed, 32 insertions(+), 17 deletions(-)
diff --git a/dlls/kernel32/tests/fiber.c b/dlls/kernel32/tests/fiber.c index b058dae7491..0304dcfcde0 100644 --- a/dlls/kernel32/tests/fiber.c +++ b/dlls/kernel32/tests/fiber.c @@ -38,7 +38,7 @@ static BOOL (WINAPI *pFlsFree)(DWORD); static PVOID (WINAPI *pFlsGetValue)(DWORD); static BOOL (WINAPI *pFlsSetValue)(DWORD,PVOID); static NTSTATUS (WINAPI *pRtlFlsAlloc)(PFLS_CALLBACK_FUNCTION,DWORD*); - +static NTSTATUS (WINAPI *pRtlFlsFree)(ULONG); static void *fibers[3]; static BYTE testparam = 185; static DWORD fls_index_to_set = FLS_OUT_OF_INDEXES; @@ -69,6 +69,7 @@ static VOID init_funcs(void)
#define X(f) p##f = (void*)GetProcAddress(hntdll, #f); X(RtlFlsAlloc); + X(RtlFlsFree); #undef X
} @@ -218,7 +219,10 @@ static void test_FiberLocalStorage(void) ok(count && (count <= 127 || (count > 4000 && count < 4096)), "Got unexpected count %u.\n", count);
for (i = 0; i < count; ++i) - pFlsFree(fls_indices[i]); + { + status = pRtlFlsFree(fls_indices[i]); + ok(!status, "Got unexpected status %#x.\n", status); + } } else { diff --git a/dlls/kernelbase/thread.c b/dlls/kernelbase/thread.c index bdc7502632b..2f304a06e9e 100644 --- a/dlls/kernelbase/thread.c +++ b/dlls/kernelbase/thread.c @@ -1082,20 +1082,7 @@ DWORD WINAPI DECLSPEC_HOTPATCH FlsAlloc( PFLS_CALLBACK_FUNCTION callback ) */ BOOL WINAPI DECLSPEC_HOTPATCH FlsFree( DWORD index ) { - BOOL ret; - - RtlAcquirePebLock(); - ret = RtlAreBitsSet( NtCurrentTeb()->Peb->FlsBitmap, index, 1 ); - if (ret) RtlClearBits( NtCurrentTeb()->Peb->FlsBitmap, index, 1 ); - if (ret) - { - /* FIXME: call Fls callback */ - /* FIXME: add equivalent of ThreadZeroTlsCell here */ - if (NtCurrentTeb()->FlsSlots) NtCurrentTeb()->FlsSlots[index] = 0; - } - else SetLastError( ERROR_INVALID_PARAMETER ); - RtlReleasePebLock(); - return ret; + return set_ntstatus( RtlFlsFree( index )); }
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index aac2af26f36..5cf7e31b01e 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -667,6 +667,7 @@ @ stdcall RtlFirstEntrySList(ptr) @ stdcall RtlFirstFreeAce(ptr ptr) @ stdcall RtlFlsAlloc(ptr ptr) +@ stdcall RtlFlsFree(long) @ stub RtlFlushPropertySet # @ stub RtlFlushSecureMemoryCache @ stdcall RtlFormatCurrentUserKeyPath(ptr) diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index f277a52dc06..bbec1f98728 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -256,7 +256,7 @@ TEB_ACTIVE_FRAME * WINAPI RtlGetFrame(void) /*********************************************************************** * RtlFlsAlloc (NTDLL.@) */ -NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsAlloc( PFLS_CALLBACK_FUNCTION callback, DWORD *ret_index ) +NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsAlloc( PFLS_CALLBACK_FUNCTION callback, ULONG *ret_index ) { PEB * const peb = NtCurrentTeb()->Peb; NTSTATUS status = STATUS_NO_MEMORY; @@ -289,3 +289,25 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsAlloc( PFLS_CALLBACK_FUNCTION callback, *ret_index = index; return status; } + + +/*********************************************************************** + * RtlFlsFree (NTDLL.@) + */ +NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsFree( ULONG index ) +{ + NTSTATUS status; + + RtlAcquirePebLock(); + if (RtlAreBitsSet( NtCurrentTeb()->Peb->FlsBitmap, index, 1 )) + { + RtlClearBits( NtCurrentTeb()->Peb->FlsBitmap, index, 1 ); + /* FIXME: call Fls callback */ + /* FIXME: add equivalent of ThreadZeroTlsCell here */ + if (NtCurrentTeb()->FlsSlots) NtCurrentTeb()->FlsSlots[index] = 0; + status = STATUS_SUCCESS; + } + else status = STATUS_INVALID_PARAMETER; + RtlReleasePebLock(); + return status; +} diff --git a/include/winternl.h b/include/winternl.h index ba9d9442590..117d34bbfdf 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -3372,6 +3372,7 @@ NTSYSAPI ULONG WINAPI RtlFindSetBitsAndClear(PRTL_BITMAP,ULONG,ULONG); NTSYSAPI ULONG WINAPI RtlFindSetRuns(PCRTL_BITMAP,PRTL_BITMAP_RUN,ULONG,BOOLEAN); NTSYSAPI BOOLEAN WINAPI RtlFirstFreeAce(PACL,PACE_HEADER *); NTSYSAPI NTSTATUS WINAPI RtlFlsAlloc(PFLS_CALLBACK_FUNCTION,ULONG *); +NTSYSAPI NTSTATUS WINAPI RtlFlsFree(ULONG); NTSYSAPI NTSTATUS WINAPI RtlFormatCurrentUserKeyPath(PUNICODE_STRING); NTSYSAPI NTSTATUS WINAPI RtlFormatMessage(LPCWSTR,ULONG,BOOLEAN,BOOLEAN,BOOLEAN,__ms_va_list *,LPWSTR,ULONG,ULONG*); NTSYSAPI NTSTATUS WINAPI RtlFormatMessageEx(LPCWSTR,ULONG,BOOLEAN,BOOLEAN,BOOLEAN,__ms_va_list *,LPWSTR,ULONG,ULONG*,ULONG);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=79482
Your paranoid android.
=== debiant (build log) ===
The task timed out
=== debiant (build log) ===
The task timed out
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/kernel32/tests/fiber.c | 14 ++++++++++++++ dlls/kernelbase/thread.c | 15 +-------------- dlls/ntdll/ntdll.spec | 1 + dlls/ntdll/thread.c | 18 ++++++++++++++++++ include/winternl.h | 1 + 5 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/dlls/kernel32/tests/fiber.c b/dlls/kernel32/tests/fiber.c index 0304dcfcde0..4ffbe8916da 100644 --- a/dlls/kernel32/tests/fiber.c +++ b/dlls/kernel32/tests/fiber.c @@ -39,6 +39,7 @@ static PVOID (WINAPI *pFlsGetValue)(DWORD); static BOOL (WINAPI *pFlsSetValue)(DWORD,PVOID); static NTSTATUS (WINAPI *pRtlFlsAlloc)(PFLS_CALLBACK_FUNCTION,DWORD*); static NTSTATUS (WINAPI *pRtlFlsFree)(ULONG); +static NTSTATUS (WINAPI *pRtlFlsSetValue)(ULONG,void *); static void *fibers[3]; static BYTE testparam = 185; static DWORD fls_index_to_set = FLS_OUT_OF_INDEXES; @@ -70,6 +71,7 @@ static VOID init_funcs(void) #define X(f) p##f = (void*)GetProcAddress(hntdll, #f); X(RtlFlsAlloc); X(RtlFlsFree); + X(RtlFlsSetValue); #undef X
} @@ -213,6 +215,11 @@ static void test_FiberLocalStorage(void) ok(fls_indices[i] == 0xdeadbeef, "Got unexpected index %#x.\n", fls_indices[i]); break; } + if (pRtlFlsSetValue) + { + status = pRtlFlsSetValue(fls_indices[i], (void *)(ULONG_PTR)(i + 1)); + ok(!status, "Got unexpected status %#x.\n", status); + } } count = i; /* FLS limits are increased since Win10 18312. */ @@ -280,6 +287,11 @@ static void test_FiberLocalStorage(void) ret = pFlsSetValue( 0, (void *)0xdeadbeef ); ok( !ret, "setting fls index 0 succeeded\n" ); ok( GetLastError() == ERROR_INVALID_PARAMETER, "setting fls index wrong error %u\n", GetLastError() ); + if (pRtlFlsSetValue) + { + status = pRtlFlsSetValue( 0, (void *)0xdeadbeef ); + ok( status == STATUS_INVALID_PARAMETER, "Got unexpected status %#x.\n", status ); + } SetLastError( 0xdeadbeef ); val = pFlsGetValue( 0 ); ok( !val, "fls index 0 wrong value %p\n", val ); @@ -291,8 +303,10 @@ static void test_FiberLocalStorage(void) ok( fls != 0, "fls index 0 allocated\n" ); val = pFlsGetValue( fls ); ok( !val, "fls index %u wrong value %p\n", fls, val ); + SetLastError( 0xdeadbeef ); ret = pFlsSetValue( fls, (void *)0xdeadbeef ); ok( ret, "setting fls index %u failed\n", fls ); + ok( GetLastError() == 0xdeadbeef, "setting fls index wrong error %u\n", GetLastError() ); SetLastError( 0xdeadbeef ); val = pFlsGetValue( fls ); ok( val == (void *)0xdeadbeef, "fls index %u wrong value %p\n", fls, val ); diff --git a/dlls/kernelbase/thread.c b/dlls/kernelbase/thread.c index 2f304a06e9e..567af0701df 100644 --- a/dlls/kernelbase/thread.c +++ b/dlls/kernelbase/thread.c @@ -1106,20 +1106,7 @@ PVOID WINAPI DECLSPEC_HOTPATCH FlsGetValue( DWORD index ) */ BOOL WINAPI DECLSPEC_HOTPATCH FlsSetValue( DWORD index, PVOID data ) { - if (!index || index >= 8 * sizeof(NtCurrentTeb()->Peb->FlsBitmapBits)) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return FALSE; - } - if (!NtCurrentTeb()->FlsSlots && - !(NtCurrentTeb()->FlsSlots = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, - 8 * sizeof(NtCurrentTeb()->Peb->FlsBitmapBits) * sizeof(void*) ))) - { - SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - return FALSE; - } - NtCurrentTeb()->FlsSlots[index] = data; - return TRUE; + return set_ntstatus( RtlFlsSetValue( index, data )); }
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 5cf7e31b01e..87ac9c6cb24 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -668,6 +668,7 @@ @ stdcall RtlFirstFreeAce(ptr ptr) @ stdcall RtlFlsAlloc(ptr ptr) @ stdcall RtlFlsFree(long) +@ stdcall RtlFlsSetValue(long ptr) @ stub RtlFlushPropertySet # @ stub RtlFlushSecureMemoryCache @ stdcall RtlFormatCurrentUserKeyPath(ptr) diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index bbec1f98728..15bfe4c3046 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -311,3 +311,21 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsFree( ULONG index ) RtlReleasePebLock(); return status; } + + +/*********************************************************************** + * RtlFlsSetValue (NTDLL.@) + */ +NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsSetValue( ULONG index, void *data ) +{ + if (!index || index >= 8 * sizeof(NtCurrentTeb()->Peb->FlsBitmapBits)) + return STATUS_INVALID_PARAMETER; + + if (!NtCurrentTeb()->FlsSlots && + !(NtCurrentTeb()->FlsSlots = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, + 8 * sizeof(NtCurrentTeb()->Peb->FlsBitmapBits) * sizeof(void*) ))) + return STATUS_NO_MEMORY; + + NtCurrentTeb()->FlsSlots[index] = data; + return STATUS_SUCCESS; +} diff --git a/include/winternl.h b/include/winternl.h index 117d34bbfdf..2e490dcfef7 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -3373,6 +3373,7 @@ NTSYSAPI ULONG WINAPI RtlFindSetRuns(PCRTL_BITMAP,PRTL_BITMAP_RUN,ULONG,BOOL NTSYSAPI BOOLEAN WINAPI RtlFirstFreeAce(PACL,PACE_HEADER *); NTSYSAPI NTSTATUS WINAPI RtlFlsAlloc(PFLS_CALLBACK_FUNCTION,ULONG *); NTSYSAPI NTSTATUS WINAPI RtlFlsFree(ULONG); +NTSYSAPI NTSTATUS WINAPI RtlFlsSetValue(ULONG,void *); NTSYSAPI NTSTATUS WINAPI RtlFormatCurrentUserKeyPath(PUNICODE_STRING); NTSYSAPI NTSTATUS WINAPI RtlFormatMessage(LPCWSTR,ULONG,BOOLEAN,BOOLEAN,BOOLEAN,__ms_va_list *,LPWSTR,ULONG,ULONG*); NTSYSAPI NTSTATUS WINAPI RtlFormatMessageEx(LPCWSTR,ULONG,BOOLEAN,BOOLEAN,BOOLEAN,__ms_va_list *,LPWSTR,ULONG,ULONG*,ULONG);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=79483
Your paranoid android.
=== debiant (build log) ===
The task timed out
=== debiant (build log) ===
The task timed out
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/kernel32/tests/fiber.c | 49 +++++++++++++++++++++++++++++++++++++ dlls/kernelbase/thread.c | 13 +++++----- dlls/ntdll/ntdll.spec | 1 + dlls/ntdll/thread.c | 14 +++++++++++ include/winternl.h | 1 + 5 files changed, 71 insertions(+), 7 deletions(-)
diff --git a/dlls/kernel32/tests/fiber.c b/dlls/kernel32/tests/fiber.c index 4ffbe8916da..b15bf468ea5 100644 --- a/dlls/kernel32/tests/fiber.c +++ b/dlls/kernel32/tests/fiber.c @@ -40,6 +40,7 @@ static BOOL (WINAPI *pFlsSetValue)(DWORD,PVOID); static NTSTATUS (WINAPI *pRtlFlsAlloc)(PFLS_CALLBACK_FUNCTION,DWORD*); static NTSTATUS (WINAPI *pRtlFlsFree)(ULONG); static NTSTATUS (WINAPI *pRtlFlsSetValue)(ULONG,void *); +static NTSTATUS (WINAPI *pRtlFlsGetValue)(ULONG,void **); static void *fibers[3]; static BYTE testparam = 185; static DWORD fls_index_to_set = FLS_OUT_OF_INDEXES; @@ -72,6 +73,7 @@ static VOID init_funcs(void) X(RtlFlsAlloc); X(RtlFlsFree); X(RtlFlsSetValue); + X(RtlFlsGetValue); #undef X
} @@ -205,6 +207,16 @@ static void test_FiberLocalStorage(void)
if (pRtlFlsAlloc) { + if (pRtlFlsGetValue) + { + status = pRtlFlsGetValue(0, NULL); + ok(status == STATUS_INVALID_PARAMETER, "Got unexpected status %#x.\n", status); + } + else + { + win_skip("RtlFlsGetValue is not available.\n"); + } + for (i = 0; i < FLS_TEST_INDEX_COUNT; ++i) { fls_indices[i] = 0xdeadbeef; @@ -225,8 +237,21 @@ static void test_FiberLocalStorage(void) /* FLS limits are increased since Win10 18312. */ ok(count && (count <= 127 || (count > 4000 && count < 4096)), "Got unexpected count %u.\n", count);
+ if (0) + { + /* crashes on Windows. */ + pRtlFlsGetValue(fls_indices[0], NULL); + } + for (i = 0; i < count; ++i) { + if (pRtlFlsGetValue) + { + status = pRtlFlsGetValue(fls_indices[i], &val); + ok(!status, "Got unexpected status %#x.\n", status); + ok(val == (void *)(ULONG_PTR)(i + 1), "Got unexpected val %p.\n", val); + } + status = pRtlFlsFree(fls_indices[i]); ok(!status, "Got unexpected status %#x.\n", status); } @@ -250,6 +275,14 @@ static void test_FiberLocalStorage(void) ok( val == NULL, "getting fls index 127 (unallocated) failed with error %u\n", GetLastError() );
+ if (pRtlFlsGetValue) + { + val = (void *)0xdeadbeef; + status = pRtlFlsGetValue(127, &val); + ok( !status, "Got unexpected status %#x.\n", status ); + ok( !val, "Got unexpected val %p.\n", val ); + } + ret = pFlsSetValue( 127, (void*) 0x217 ); ok( ret, "setting fls index 127 (unallocated) failed with error %u\n", GetLastError() );
@@ -259,6 +292,14 @@ static void test_FiberLocalStorage(void) ok( GetLastError() == ERROR_SUCCESS, "getting fls index 127 (unallocated) failed with error %u\n", GetLastError() );
+ if (pRtlFlsGetValue) + { + val = (void *)0xdeadbeef; + status = pRtlFlsGetValue(127, &val); + ok( !status, "Got unexpected status %#x.\n", status ); + ok( val == (void*)0x217, "Got unexpected val %p.\n", val ); + } + /* FlsFree, FlsGetValue, and FlsSetValue out of bounds should return * ERROR_INVALID_PARAMETER */ @@ -283,6 +324,14 @@ static void test_FiberLocalStorage(void) val = pFlsGetValue( 0 ); ok( !val, "fls index 0 set to %p\n", val ); ok( GetLastError() == ERROR_INVALID_PARAMETER, "setting fls index wrong error %u\n", GetLastError() ); + if (pRtlFlsGetValue) + { + val = (void *)0xdeadbeef; + status = pRtlFlsGetValue(0, &val); + ok( status == STATUS_INVALID_PARAMETER, "Got unexpected status %#x.\n", status ); + ok( val == (void*)0xdeadbeef, "Got unexpected val %p.\n", val ); + } + SetLastError( 0xdeadbeef ); ret = pFlsSetValue( 0, (void *)0xdeadbeef ); ok( !ret, "setting fls index 0 succeeded\n" ); diff --git a/dlls/kernelbase/thread.c b/dlls/kernelbase/thread.c index 567af0701df..3e6164c7862 100644 --- a/dlls/kernelbase/thread.c +++ b/dlls/kernelbase/thread.c @@ -1091,13 +1091,12 @@ BOOL WINAPI DECLSPEC_HOTPATCH FlsFree( DWORD index ) */ PVOID WINAPI DECLSPEC_HOTPATCH FlsGetValue( DWORD index ) { - if (!index || index >= 8 * sizeof(NtCurrentTeb()->Peb->FlsBitmapBits) || !NtCurrentTeb()->FlsSlots) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return NULL; - } - SetLastError( ERROR_SUCCESS ); - return NtCurrentTeb()->FlsSlots[index]; + NTSTATUS status; + void *data; + + SetLastError( RtlNtStatusToDosError( status = RtlFlsGetValue( index, &data ))); + + return status ? NULL : data; }
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 87ac9c6cb24..ce9f6281d5d 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -668,6 +668,7 @@ @ stdcall RtlFirstFreeAce(ptr ptr) @ stdcall RtlFlsAlloc(ptr ptr) @ stdcall RtlFlsFree(long) +@ stdcall RtlFlsGetValue(long ptr) @ stdcall RtlFlsSetValue(long ptr) @ stub RtlFlushPropertySet # @ stub RtlFlushSecureMemoryCache diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index 15bfe4c3046..716ef3b61d0 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -329,3 +329,17 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsSetValue( ULONG index, void *data ) NtCurrentTeb()->FlsSlots[index] = data; return STATUS_SUCCESS; } + + +/*********************************************************************** + * RtlFlsGetValue (NTDLL.@) + */ +NTSTATUS WINAPI DECLSPEC_HOTPATCH RtlFlsGetValue( ULONG index, void **data ) +{ + if (!index || index >= 8 * sizeof(NtCurrentTeb()->Peb->FlsBitmapBits) || !NtCurrentTeb()->FlsSlots) + return STATUS_INVALID_PARAMETER; + + *data = NtCurrentTeb()->FlsSlots[index]; + + return STATUS_SUCCESS; +} diff --git a/include/winternl.h b/include/winternl.h index 2e490dcfef7..82328167c9e 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -3373,6 +3373,7 @@ NTSYSAPI ULONG WINAPI RtlFindSetRuns(PCRTL_BITMAP,PRTL_BITMAP_RUN,ULONG,BOOL NTSYSAPI BOOLEAN WINAPI RtlFirstFreeAce(PACL,PACE_HEADER *); NTSYSAPI NTSTATUS WINAPI RtlFlsAlloc(PFLS_CALLBACK_FUNCTION,ULONG *); NTSYSAPI NTSTATUS WINAPI RtlFlsFree(ULONG); +NTSYSAPI NTSTATUS WINAPI RtlFlsGetValue(ULONG,void **); NTSYSAPI NTSTATUS WINAPI RtlFlsSetValue(ULONG,void *); NTSYSAPI NTSTATUS WINAPI RtlFormatCurrentUserKeyPath(PUNICODE_STRING); NTSYSAPI NTSTATUS WINAPI RtlFormatMessage(LPCWSTR,ULONG,BOOLEAN,BOOLEAN,BOOLEAN,__ms_va_list *,LPWSTR,ULONG,ULONG*);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=79484
Your paranoid android.
=== debiant (build log) ===
The task timed out
=== debiant (build log) ===
The task timed out