[NTDLL][KERNEL32] Implement FLS callbacks.
authorMark Jansen <mark.jansen@reactos.org>
Thu, 10 May 2018 20:23:16 +0000 (22:23 +0200)
committerMark Jansen <mark.jansen@reactos.org>
Sat, 15 Sep 2018 15:56:03 +0000 (17:56 +0200)
dll/ntdll/ldr/ldrinit.c
dll/win32/kernel32/client/fiber.c
sdk/include/ndk/rtltypes.h

index 14f0272..e40db17 100644 (file)
@@ -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,
index a3a38ec..47d2616 100644 (file)
@@ -8,6 +8,7 @@
  *              KJK::Hyperion <noog@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;
 }
 
index 7070564..02d65a2 100644 (file)
@@ -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
 //