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

