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

commit ac620c2e8ea7a14e7175ce32d1bfa74585f9ff36
Author:     Mark Jansen <mark.jan...@reactos.org>
AuthorDate: Sat Apr 7 23:41:53 2018 +0200
Commit:     Mark Jansen <mark.jan...@reactos.org>
CommitDate: Sun Apr 8 17:27:24 2018 +0200

    [KERNEL32] Implement FlsAlloc/FlsFree based on Wine's implementation.
---
 dll/apisets/api-ms-win-core-fibers-l1-1-0.spec |   8 +-
 dll/apisets/api-ms-win-core-fibers-l1-1-1.spec |   8 +-
 dll/win32/kernel32/client/fiber.c              | 148 ++++++++++++++++---------
 dll/win32/kernel32/kernel32.spec               |   8 +-
 4 files changed, 105 insertions(+), 67 deletions(-)

diff --git a/dll/apisets/api-ms-win-core-fibers-l1-1-0.spec 
b/dll/apisets/api-ms-win-core-fibers-l1-1-0.spec
index 32edaf83d2..4c4d859ad5 100644
--- a/dll/apisets/api-ms-win-core-fibers-l1-1-0.spec
+++ b/dll/apisets/api-ms-win-core-fibers-l1-1-0.spec
@@ -1,7 +1,7 @@
 
 # This file is autogenerated by update.py
 
-@ stub FlsAlloc
-@ stub FlsFree
-@ stub FlsGetValue
-@ stub FlsSetValue
+@ stdcall FlsAlloc() kernel32.FlsAlloc
+@ stdcall FlsFree() kernel32.FlsFree
+@ stdcall FlsGetValue() kernel32.FlsGetValue
+@ stdcall FlsSetValue() kernel32.FlsSetValue
diff --git a/dll/apisets/api-ms-win-core-fibers-l1-1-1.spec 
b/dll/apisets/api-ms-win-core-fibers-l1-1-1.spec
index f29bdf3060..504e62c345 100644
--- a/dll/apisets/api-ms-win-core-fibers-l1-1-1.spec
+++ b/dll/apisets/api-ms-win-core-fibers-l1-1-1.spec
@@ -1,8 +1,8 @@
 
 # This file is autogenerated by update.py
 
-@ stub FlsAlloc
-@ stub FlsFree
-@ stub FlsGetValue
-@ stub FlsSetValue
+@ stdcall FlsAlloc() kernel32.FlsAlloc
+@ stdcall FlsFree() kernel32.FlsFree
+@ stdcall FlsGetValue() kernel32.FlsGetValue
+@ stdcall FlsSetValue() kernel32.FlsSetValue
 @ stub IsThreadAFiber
diff --git a/dll/win32/kernel32/client/fiber.c 
b/dll/win32/kernel32/client/fiber.c
index 8daa28e1de..ce6cd2d150 100644
--- a/dll/win32/kernel32/client/fiber.c
+++ b/dll/win32/kernel32/client/fiber.c
@@ -312,32 +312,97 @@ IsThreadAFiber(VOID)
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
 DWORD
 WINAPI
 FlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback)
 {
-   (void)lpCallback;
+    DWORD dwFlsIndex;
+    PPEB Peb = NtCurrentPeb();
+    PVOID *ppFlsSlots;
 
-   UNIMPLEMENTED;
-   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-   return FLS_OUT_OF_INDEXES;
+    RtlAcquirePebLock();
+
+    ppFlsSlots = NtCurrentTeb()->FlsData;
+
+    if (!Peb->FlsCallback &&
+        !(Peb->FlsCallback = RtlAllocateHeap(RtlGetProcessHeap(), 
HEAP_ZERO_MEMORY,
+                                             FLS_MAXIMUM_AVAILABLE * 
sizeof(PVOID))))
+    {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        dwFlsIndex = FLS_OUT_OF_INDEXES;
+    }
+    else
+    {
+        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))))
+            {
+                RtlClearBits(Peb->FlsBitmap, dwFlsIndex, 1);
+                dwFlsIndex = FLS_OUT_OF_INDEXES;
+                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            }
+            else
+            {
+                if (!NtCurrentTeb()->FlsData)
+                    NtCurrentTeb()->FlsData = ppFlsSlots;
+
+                if (lpCallback)
+                    DPRINT1("FlsAlloc: Got lpCallback 0x%p, UNIMPLEMENTED!", 
lpCallback);
+
+                ppFlsSlots[dwFlsIndex + 2] = NULL; /* clear the value */
+                Peb->FlsCallback[dwFlsIndex] = lpCallback;
+            }
+        }
+        else
+        {
+            SetLastError(ERROR_NO_MORE_ITEMS);
+        }
+    }
+    RtlReleasePebLock();
+    return dwFlsIndex;
 }
 
 
 /*
- * @unimplemented
+ * @implemented
  */
 BOOL
 WINAPI
 FlsFree(DWORD dwFlsIndex)
 {
-    (void)dwFlsIndex;
+    BOOL ret;
+    PPEB Peb = NtCurrentPeb();
+    PVOID *ppFlsSlots;
+
+    if (dwFlsIndex >= FLS_MAXIMUM_AVAILABLE)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
 
-    UNIMPLEMENTED;
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
+    RtlAcquirePebLock();
+
+    ppFlsSlots = NtCurrentTeb()->FlsData;
+    ret = RtlAreBitsSet(Peb->FlsBitmap, dwFlsIndex, 1);
+    if (ret)
+    {
+        RtlClearBits(Peb->FlsBitmap, dwFlsIndex, 1);
+        /* FIXME: call Fls callback */
+        /* FIXME: add equivalent of ThreadZeroTlsCell here */
+        if (ppFlsSlots)
+            ppFlsSlots[dwFlsIndex + 2] = NULL;
+    }
+    else
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+    }
+    RtlReleasePebLock();
+    return ret;
 }
 
 
@@ -349,22 +414,16 @@ WINAPI
 FlsGetValue(DWORD dwFlsIndex)
 {
     PVOID *ppFlsSlots;
-    PVOID pRetVal;
-
-    if(dwFlsIndex >= 128) goto l_InvalidParam;
 
     ppFlsSlots = NtCurrentTeb()->FlsData;
+    if (!dwFlsIndex || dwFlsIndex >= FLS_MAXIMUM_AVAILABLE || !ppFlsSlots)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return NULL;
+    }
 
-    if(ppFlsSlots == NULL) goto l_InvalidParam;
-
-    SetLastError(0);
-    pRetVal = ppFlsSlots[dwFlsIndex + 2];
-
-    return pRetVal;
-
-l_InvalidParam:
-    SetLastError(ERROR_INVALID_PARAMETER);
-    return NULL;
+    SetLastError(ERROR_SUCCESS);
+    return ppFlsSlots[dwFlsIndex + 2];
 }
 
 
@@ -377,43 +436,22 @@ FlsSetValue(DWORD dwFlsIndex,
             PVOID lpFlsData)
 {
     PVOID *ppFlsSlots;
-    TEB *pTeb = NtCurrentTeb();
-
-    if(dwFlsIndex >= 128) goto l_InvalidParam;
 
-    ppFlsSlots = pTeb->FlsData;
-
-    if (ppFlsSlots == NULL)
+    if (!dwFlsIndex || dwFlsIndex >= FLS_MAXIMUM_AVAILABLE)
     {
-        PEB *pPeb = pTeb->ProcessEnvironmentBlock;
-
-        ppFlsSlots = RtlAllocateHeap(pPeb->ProcessHeap,
-                                     HEAP_ZERO_MEMORY,
-                                     (128 + 2) * sizeof(PVOID));
-        if(ppFlsSlots == NULL) goto l_OutOfMemory;
-
-        pTeb->FlsData = ppFlsSlots;
-
-        RtlAcquirePebLock();
-
-        /* TODO: initialization */
-
-        RtlReleasePebLock();
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
     }
-
+    if (!NtCurrentTeb()->FlsData &&
+        !(NtCurrentTeb()->FlsData = RtlAllocateHeap(RtlGetProcessHeap(), 
HEAP_ZERO_MEMORY,
+                                                    (FLS_MAXIMUM_AVAILABLE + 
2) * sizeof(PVOID))))
+    {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return FALSE;
+    }
+    ppFlsSlots = NtCurrentTeb()->FlsData;
     ppFlsSlots[dwFlsIndex + 2] = lpFlsData;
-
     return TRUE;
-
-l_OutOfMemory:
-    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-    goto l_Fail;
-
-l_InvalidParam:
-    SetLastError(ERROR_INVALID_PARAMETER);
-
-l_Fail:
-    return FALSE;
 }
 
 /* EOF */
diff --git a/dll/win32/kernel32/kernel32.spec b/dll/win32/kernel32/kernel32.spec
index 923545416f..25b47afc8e 100644
--- a/dll/win32/kernel32/kernel32.spec
+++ b/dll/win32/kernel32/kernel32.spec
@@ -235,10 +235,10 @@
 231 stdcall FindResourceW(long wstr wstr)
 232 stdcall FindVolumeClose(ptr)
 233 stdcall FindVolumeMountPointClose(ptr)
-;234 stdcall FlsAlloc(ptr)
-;235 stdcall FlsFree(long)
-;236 stdcall FlsGetValue(long)
-;237 stdcall FlsSetValue(long ptr)
+234 stdcall FlsAlloc(ptr)
+235 stdcall FlsFree(long)
+236 stdcall FlsGetValue(long)
+237 stdcall FlsSetValue(long ptr)
 238 stdcall FlushConsoleInputBuffer(long)
 239 stdcall FlushFileBuffers(long)
 240 stdcall FlushInstructionCache(long long long)

Reply via email to