https://git.reactos.org/?p=reactos.git;a=commitdiff;h=06eb99edefc821c932492…
commit 06eb99edefc821c9324923eae9eeebf0cf6f9d48
Author: Mark Jansen <mark.jansen(a)reactos.org>
AuthorDate: Thu May 10 22:23:16 2018 +0200
Commit: Mark Jansen <mark.jansen(a)reactos.org>
CommitDate: Sat Sep 15 17:56:03 2018 +0200
[NTDLL][KERNEL32] Implement FLS callbacks.
---
dll/ntdll/ldr/ldrinit.c | 26 +++++++++-
dll/win32/kernel32/client/fiber.c | 101 ++++++++++++++++++++++++++++----------
sdk/include/ndk/rtltypes.h | 11 +++++
3 files changed, 109 insertions(+), 29 deletions(-)
diff --git a/dll/ntdll/ldr/ldrinit.c b/dll/ntdll/ldr/ldrinit.c
index 14f0272dd3..e40db1717a 100644
--- a/dll/ntdll/ldr/ldrinit.c
+++ b/dll/ntdll/ldr/ldrinit.c
@@ -1207,8 +1207,29 @@ LdrShutdownThread(VOID)
/* Check for FLS Data */
if (Teb->FlsData)
{
- /* FIXME */
- DPRINT1("We don't support FLS Data yet\n");
+ /* Mimic BaseRundownFls */
+ ULONG n, FlsHighIndex;
+ PRTL_FLS_DATA pFlsData;
+ PFLS_CALLBACK_FUNCTION lpCallback;
+
+ pFlsData = Teb->FlsData;
+
+ RtlAcquirePebLock();
+ FlsHighIndex = NtCurrentPeb()->FlsHighIndex;
+ RemoveEntryList(&pFlsData->ListEntry);
+ RtlReleasePebLock();
+
+ for (n = 1; n <= FlsHighIndex; ++n)
+ {
+ lpCallback = NtCurrentPeb()->FlsCallback[n];
+ if (lpCallback && pFlsData->Data[n])
+ {
+ lpCallback(pFlsData->Data[n]);
+ }
+ }
+
+ RtlFreeHeap(RtlGetProcessHeap(), 0, pFlsData);
+ Teb->FlsData = NULL;
}
/* Check for Fiber data */
@@ -1786,6 +1807,7 @@ LdrpInitializeProcess(IN PCONTEXT Context,
Peb->FlsBitmapBits,
FLS_MAXIMUM_AVAILABLE);
RtlSetBit(&FlsBitMap, 0);
+ InitializeListHead(&Peb->FlsListHead);
/* Initialize TLS Bitmap */
RtlInitializeBitMap(&TlsBitMap,
diff --git a/dll/win32/kernel32/client/fiber.c b/dll/win32/kernel32/client/fiber.c
index a3a38ecd7f..47d2616e66 100644
--- a/dll/win32/kernel32/client/fiber.c
+++ b/dll/win32/kernel32/client/fiber.c
@@ -8,6 +8,7 @@
* KJK::Hyperion <noog(a)libero.it>
*/
#include <k32.h>
+#include <ndk/rtltypes.h>
#define NDEBUG
#include <debug.h>
@@ -21,6 +22,7 @@ C_ASSERT(FIELD_OFFSET(FIBER, FiberContext) == 0x14);
C_ASSERT(FIELD_OFFSET(FIBER, GuaranteedStackBytes) == 0x2E0);
C_ASSERT(FIELD_OFFSET(FIBER, FlsData) == 0x2E4);
C_ASSERT(FIELD_OFFSET(FIBER, ActivationContextStackPointer) == 0x2E8);
+C_ASSERT(RTL_FLS_MAXIMUM_AVAILABLE == FLS_MAXIMUM_AVAILABLE);
#endif // _M_IX86
/* PRIVATE FUNCTIONS **********************************************************/
@@ -29,7 +31,27 @@ VOID
WINAPI
BaseRundownFls(_In_ PVOID FlsData)
{
- /* No FLS support yet */
+ ULONG n, FlsHighIndex;
+ PRTL_FLS_DATA pFlsData;
+ PFLS_CALLBACK_FUNCTION lpCallback;
+
+ pFlsData = FlsData;
+
+ RtlAcquirePebLock();
+ FlsHighIndex = NtCurrentPeb()->FlsHighIndex;
+ RemoveEntryList(&pFlsData->ListEntry);
+ RtlReleasePebLock();
+
+ for (n = 1; n <= FlsHighIndex; ++n)
+ {
+ lpCallback = NtCurrentPeb()->FlsCallback[n];
+ if (lpCallback && pFlsData->Data[n])
+ {
+ lpCallback(pFlsData->Data[n]);
+ }
+ }
+
+ RtlFreeHeap(RtlGetProcessHeap(), 0, FlsData);
}
/* PUBLIC FUNCTIONS ***********************************************************/
@@ -61,7 +83,7 @@ ConvertFiberToThread(VOID)
/* Free the fiber */
ASSERT(FiberData != NULL);
- RtlFreeHeap(GetProcessHeap(),
+ RtlFreeHeap(RtlGetProcessHeap(),
0,
FiberData);
@@ -295,7 +317,7 @@ DeleteFiber(_In_ LPVOID lpFiber)
RtlFreeActivationContextStack(Fiber->ActivationContextStackPointer);
/* Free the fiber data */
- RtlFreeHeap(GetProcessHeap(),
+ RtlFreeHeap(RtlGetProcessHeap(),
0,
lpFiber);
}
@@ -320,11 +342,11 @@ FlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback)
{
DWORD dwFlsIndex;
PPEB Peb = NtCurrentPeb();
- PVOID *ppFlsSlots;
+ PRTL_FLS_DATA pFlsData;
RtlAcquirePebLock();
- ppFlsSlots = NtCurrentTeb()->FlsData;
+ pFlsData = NtCurrentTeb()->FlsData;
if (!Peb->FlsCallback &&
!(Peb->FlsCallback = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
@@ -338,9 +360,8 @@ FlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback)
dwFlsIndex = RtlFindClearBitsAndSet(Peb->FlsBitmap, 1, 1);
if (dwFlsIndex != FLS_OUT_OF_INDEXES)
{
- if (!ppFlsSlots &&
- !(ppFlsSlots = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
- (FLS_MAXIMUM_AVAILABLE + 2) *
sizeof(PVOID))))
+ if (!pFlsData &&
+ !(pFlsData = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(RTL_FLS_DATA))))
{
RtlClearBits(Peb->FlsBitmap, dwFlsIndex, 1);
dwFlsIndex = FLS_OUT_OF_INDEXES;
@@ -349,13 +370,16 @@ FlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback)
else
{
if (!NtCurrentTeb()->FlsData)
- NtCurrentTeb()->FlsData = ppFlsSlots;
+ {
+ NtCurrentTeb()->FlsData = pFlsData;
+ InsertTailList(&Peb->FlsListHead,
&pFlsData->ListEntry);
+ }
- if (lpCallback)
- DPRINT1("FlsAlloc: Got lpCallback 0x%p, UNIMPLEMENTED!\n",
lpCallback);
-
- ppFlsSlots[dwFlsIndex + 2] = NULL; /* clear the value */
+ pFlsData->Data[dwFlsIndex] = NULL; /* clear the value */
Peb->FlsCallback[dwFlsIndex] = lpCallback;
+
+ if (dwFlsIndex > Peb->FlsHighIndex)
+ Peb->FlsHighIndex = dwFlsIndex;
}
}
else
@@ -377,7 +401,6 @@ FlsFree(DWORD dwFlsIndex)
{
BOOL ret;
PPEB Peb = NtCurrentPeb();
- PVOID *ppFlsSlots;
if (dwFlsIndex >= FLS_MAXIMUM_AVAILABLE)
{
@@ -387,15 +410,30 @@ FlsFree(DWORD dwFlsIndex)
RtlAcquirePebLock();
- ppFlsSlots = NtCurrentTeb()->FlsData;
ret = RtlAreBitsSet(Peb->FlsBitmap, dwFlsIndex, 1);
if (ret)
{
+ PLIST_ENTRY Entry;
+ PFLS_CALLBACK_FUNCTION lpCallback;
+
RtlClearBits(Peb->FlsBitmap, dwFlsIndex, 1);
- /* FIXME: call Fls callback */
- /* FIXME: add equivalent of ThreadZeroTlsCell here */
- if (ppFlsSlots)
- ppFlsSlots[dwFlsIndex + 2] = NULL;
+ lpCallback = Peb->FlsCallback[dwFlsIndex];
+ Peb->FlsCallback[dwFlsIndex] = NULL;
+
+ for (Entry = Peb->FlsListHead.Flink; Entry != &Peb->FlsListHead; Entry
= Entry->Flink)
+ {
+ PRTL_FLS_DATA pFlsData;
+
+ pFlsData = CONTAINING_RECORD(Entry, RTL_FLS_DATA, ListEntry);
+ if (pFlsData->Data[dwFlsIndex])
+ {
+ if (lpCallback)
+ {
+ lpCallback(pFlsData->Data[dwFlsIndex]);
+ }
+ pFlsData->Data[dwFlsIndex] = NULL;
+ }
+ }
}
else
{
@@ -413,17 +451,17 @@ PVOID
WINAPI
FlsGetValue(DWORD dwFlsIndex)
{
- PVOID *ppFlsSlots;
+ PRTL_FLS_DATA pFlsData;
- ppFlsSlots = NtCurrentTeb()->FlsData;
- if (!dwFlsIndex || dwFlsIndex >= FLS_MAXIMUM_AVAILABLE || !ppFlsSlots)
+ pFlsData = NtCurrentTeb()->FlsData;
+ if (!dwFlsIndex || dwFlsIndex >= FLS_MAXIMUM_AVAILABLE || !pFlsData)
{
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
SetLastError(ERROR_SUCCESS);
- return ppFlsSlots[dwFlsIndex + 2];
+ return pFlsData->Data[dwFlsIndex];
}
@@ -435,22 +473,31 @@ WINAPI
FlsSetValue(DWORD dwFlsIndex,
PVOID lpFlsData)
{
- PVOID *ppFlsSlots;
+ PRTL_FLS_DATA pFlsData;
if (!dwFlsIndex || dwFlsIndex >= FLS_MAXIMUM_AVAILABLE)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
+
+ pFlsData = NtCurrentTeb()->FlsData;
+
if (!NtCurrentTeb()->FlsData &&
!(NtCurrentTeb()->FlsData = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
- (FLS_MAXIMUM_AVAILABLE + 2) *
sizeof(PVOID))))
+ sizeof(RTL_FLS_DATA))))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
- ppFlsSlots = NtCurrentTeb()->FlsData;
- ppFlsSlots[dwFlsIndex + 2] = lpFlsData;
+ if (!pFlsData)
+ {
+ pFlsData = NtCurrentTeb()->FlsData;
+ RtlAcquirePebLock();
+ InsertTailList(&NtCurrentPeb()->FlsListHead,
&pFlsData->ListEntry);
+ RtlReleasePebLock();
+ }
+ pFlsData->Data[dwFlsIndex] = lpFlsData;
return TRUE;
}
diff --git a/sdk/include/ndk/rtltypes.h b/sdk/include/ndk/rtltypes.h
index 7070564389..02d65a2971 100644
--- a/sdk/include/ndk/rtltypes.h
+++ b/sdk/include/ndk/rtltypes.h
@@ -1210,6 +1210,17 @@ typedef struct _RTL_DEBUG_INFORMATION
PVOID Reserved[4];
} RTL_DEBUG_INFORMATION, *PRTL_DEBUG_INFORMATION;
+//
+// Fiber local storage data
+//
+#define RTL_FLS_MAXIMUM_AVAILABLE 128
+typedef struct _RTL_FLS_DATA
+{
+ LIST_ENTRY ListEntry;
+ PVOID Data[RTL_FLS_MAXIMUM_AVAILABLE];
+} RTL_FLS_DATA, *PRTL_FLS_DATA;
+
+
//
// Unload Event Trace Structure for RtlGetUnloadEventTrace
//