https://git.reactos.org/?p=reactos.git;a=commitdiff;h=06eb99edefc821c9324923eae9eeebf0cf6f9d48

commit 06eb99edefc821c9324923eae9eeebf0cf6f9d48
Author:     Mark Jansen <[email protected]>
AuthorDate: Thu May 10 22:23:16 2018 +0200
Commit:     Mark Jansen <[email protected]>
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 <[email protected]>
  */
 #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
 //

Reply via email to