[KERNEL32_APITEST] Add test exposing FLS internals.
authorMark Jansen <mark.jansen@reactos.org>
Tue, 8 May 2018 20:09:04 +0000 (22:09 +0200)
committerMark Jansen <mark.jansen@reactos.org>
Sat, 15 Sep 2018 15:55:57 +0000 (17:55 +0200)
modules/rostests/apitests/kernel32/CMakeLists.txt
modules/rostests/apitests/kernel32/FLS.c [new file with mode: 0644]
modules/rostests/apitests/kernel32/testlist.c

index 37c5b6a..455ee37 100644 (file)
@@ -11,6 +11,7 @@ list(APPEND SOURCE
     dosdev.c
     FindActCtxSectionStringW.c
     FindFiles.c
+    FLS.c
     FormatMessage.c
     GetComputerNameEx.c
     GetCurrentDirectory.c
diff --git a/modules/rostests/apitests/kernel32/FLS.c b/modules/rostests/apitests/kernel32/FLS.c
new file mode 100644 (file)
index 0000000..769b5be
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * PROJECT:     ReactOS api tests
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Tests for FLS implementation details
+ * COPYRIGHT:   Copyright 2018 Mark Jansen (mark.jansen@reactos.org)
+ */
+
+#include "precomp.h"
+#include <ndk/pstypes.h>
+#include <ndk/rtlfuncs.h>
+
+/* XP does not have these functions */
+static DWORD (WINAPI *pFlsAlloc)(PFLS_CALLBACK_FUNCTION);
+static BOOL (WINAPI *pFlsFree)(DWORD);
+static PVOID (WINAPI *pFlsGetValue)(DWORD);
+static BOOL (WINAPI *pFlsSetValue)(DWORD,PVOID);
+
+
+#define NtCurrentPeb() (NtCurrentTeb()->ProcessEnvironmentBlock)
+#define WINVER_2003    0x0502
+
+static DWORD g_WinVersion = 0;
+PVOID g_FlsData1 = NULL;
+LONG g_FlsCalled1 = 0;
+PVOID g_FlsData2 = NULL;
+LONG g_FlsCalled2 = 0;
+
+VOID WINAPI FlsCallback1(PVOID lpFlsData)
+{
+    ok(lpFlsData == g_FlsData1, "Expected g_FlsData1(%p), got %p\n", g_FlsData1, lpFlsData);
+    InterlockedIncrement(&g_FlsCalled1);
+}
+
+VOID WINAPI FlsCallback2(PVOID lpFlsData)
+{
+    ok(lpFlsData == g_FlsData2, "Expected g_FlsData2(%p), got %p\n", g_FlsData2, lpFlsData);
+    InterlockedIncrement(&g_FlsCalled2);
+}
+
+
+typedef struct _FLS_CALLBACK_INFO
+{
+    PFLS_CALLBACK_FUNCTION lpCallback;
+    PVOID Unknown;
+} FLS_CALLBACK_INFO, *PFLS_CALLBACK_INFO;
+
+
+void ok_fls_(DWORD dwIndex, PVOID pValue, PFLS_CALLBACK_FUNCTION lpCallback)
+{
+    PFLS_CALLBACK_INFO FlsCallback;
+    PVOID* FlsData;
+    PVOID gotValue;
+
+    FlsCallback = (PFLS_CALLBACK_INFO)NtCurrentPeb()->FlsCallback;
+    FlsData = (PVOID*)NtCurrentTeb()->FlsData;
+
+    winetest_ok(FlsData != NULL, "Expected FlsData\n");
+    winetest_ok(FlsCallback != NULL, "Expected FlsCallback\n");
+
+    if (FlsData == NULL || FlsCallback == NULL)
+    {
+        winetest_skip("Unable to continue test\n");
+        return;
+    }
+
+    if (g_WinVersion <= WINVER_2003)
+    {
+        winetest_ok(NtCurrentPeb()->FlsCallback[dwIndex] == lpCallback,
+                    "Expected NtCurrentPeb()->FlsCallback[%lu] to be %p, was %p\n",
+                    dwIndex,
+                    lpCallback,
+                    NtCurrentPeb()->FlsCallback[dwIndex]);
+    }
+    else
+    {
+        winetest_ok(FlsCallback[dwIndex].lpCallback == lpCallback,
+                    "Expected FlsCallback[%lu].lpCallback to be %p, was %p\n",
+                    dwIndex,
+                    lpCallback,
+                    FlsCallback[dwIndex].lpCallback);
+        winetest_ok(FlsCallback[dwIndex].Unknown == NULL,
+                    "Expected FlsCallback[%lu].Unknown to be %p, was %p\n",
+                    dwIndex,
+                    NULL,
+                    FlsCallback[dwIndex].Unknown);
+    }
+    winetest_ok(FlsData[dwIndex + 2] == pValue,
+                "Expected FlsData[%lu + 2] to be %p, was %p\n",
+                dwIndex,
+                pValue,
+                FlsData[dwIndex + 2]);
+
+    gotValue = pFlsGetValue(dwIndex);
+    winetest_ok(gotValue == pValue, "Expected FlsGetValue(%lu) to be %p, was %p\n", dwIndex, pValue, gotValue);
+}
+
+#define ok_fls         (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : ok_fls_
+
+static VOID init_funcs(void)
+{
+    HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
+
+#define X(f) p##f = (void*)GetProcAddress(hKernel32, #f);
+    X(FlsAlloc);
+    X(FlsFree);
+    X(FlsGetValue);
+    X(FlsSetValue);
+#undef X
+}
+
+
+
+START_TEST(FLS)
+{
+    RTL_OSVERSIONINFOW rtlinfo = { sizeof(rtlinfo) };
+    DWORD dwIndex1, dwIndex2;
+
+    init_funcs();
+    if (!pFlsAlloc || !pFlsFree || !pFlsGetValue || !pFlsSetValue)
+    {
+        skip("Fls functions not available\n");
+        return;
+    }
+
+    RtlGetVersion(&rtlinfo);
+    g_WinVersion = (rtlinfo.dwMajorVersion << 8) | rtlinfo.dwMinorVersion;
+
+    dwIndex1 = pFlsAlloc(FlsCallback1);
+    ok(dwIndex1 != FLS_OUT_OF_INDEXES, "Unable to allocate FLS index\n");
+    dwIndex2 = pFlsAlloc(FlsCallback2);
+    ok(dwIndex2 != FLS_OUT_OF_INDEXES, "Unable to allocate FLS index\n");
+    ok(dwIndex1 != dwIndex2, "Expected different indexes, got %lu\n", dwIndex1);
+
+    if (dwIndex1 == FLS_OUT_OF_INDEXES || dwIndex2 == FLS_OUT_OF_INDEXES)
+    {
+        skip("Unable to continue test\n");
+        return;
+    }
+
+    ok_fls(dwIndex1, g_FlsData1, &FlsCallback1);
+    ok_fls(dwIndex2, g_FlsData2, &FlsCallback2);
+
+    g_FlsData1 = (PVOID)0x123456;
+    ok(pFlsSetValue(dwIndex1, g_FlsData1), "FlsSetValue(%lu, %p) failed\n", dwIndex1, g_FlsData1);
+
+    ok_fls(dwIndex1, g_FlsData1, &FlsCallback1);
+    ok_fls(dwIndex2, g_FlsData2, &FlsCallback2);
+
+    ok_int(g_FlsCalled1, 0);
+    ok_int(g_FlsCalled2, 0);
+
+    g_FlsData2 = (PVOID)0x9876112;
+    ok(pFlsSetValue(dwIndex2, g_FlsData2), "FlsSetValue(%lu, %p) failed\n", dwIndex2, g_FlsData2);
+
+    ok_fls(dwIndex1, g_FlsData1, &FlsCallback1);
+    ok_fls(dwIndex2, g_FlsData2, &FlsCallback2);
+
+    ok_int(g_FlsCalled1, 0);
+    ok_int(g_FlsCalled2, 0);
+
+    ok(pFlsFree(dwIndex1), "FlsFree(%lu) failed\n", dwIndex1);
+    g_FlsData1 = NULL;
+
+    ok_fls(dwIndex1, g_FlsData1, NULL);
+    ok_fls(dwIndex2, g_FlsData2, &FlsCallback2);
+
+    ok_int(g_FlsCalled1, 1);
+    ok_int(g_FlsCalled2, 0);
+}
index 6364cab..8c671c1 100644 (file)
@@ -10,6 +10,7 @@ extern void func_DeviceIoControl(void);
 extern void func_dosdev(void);
 extern void func_FindActCtxSectionStringW(void);
 extern void func_FindFiles(void);
+extern void func_FLS(void);
 extern void func_FormatMessage(void);
 extern void func_GetComputerNameEx(void);
 extern void func_GetCurrentDirectory(void);
@@ -41,6 +42,7 @@ const struct test winetest_testlist[] =
     { "dosdev",                      func_dosdev },
     { "FindActCtxSectionStringW",    func_FindActCtxSectionStringW },
     { "FindFiles",                   func_FindFiles },
+    { "FLS",                         func_FLS },
     { "FormatMessage",               func_FormatMessage },
     { "GetComputerNameEx",           func_GetComputerNameEx },
     { "GetCurrentDirectory",         func_GetCurrentDirectory },