From f0f8f1c7d907f5fa27ad7848e6ba9e82a9117361 Mon Sep 17 00:00:00 2001 From: Mark Jansen Date: Tue, 8 May 2018 22:09:04 +0200 Subject: [PATCH] [KERNEL32_APITEST] Add test exposing FLS internals. --- .../rostests/apitests/kernel32/CMakeLists.txt | 1 + modules/rostests/apitests/kernel32/FLS.c | 169 ++++++++++++++++++ modules/rostests/apitests/kernel32/testlist.c | 2 + 3 files changed, 172 insertions(+) create mode 100644 modules/rostests/apitests/kernel32/FLS.c diff --git a/modules/rostests/apitests/kernel32/CMakeLists.txt b/modules/rostests/apitests/kernel32/CMakeLists.txt index 37c5b6adc87..455ee379208 100644 --- a/modules/rostests/apitests/kernel32/CMakeLists.txt +++ b/modules/rostests/apitests/kernel32/CMakeLists.txt @@ -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 index 00000000000..769b5be5975 --- /dev/null +++ b/modules/rostests/apitests/kernel32/FLS.c @@ -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 +#include + +/* 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); +} diff --git a/modules/rostests/apitests/kernel32/testlist.c b/modules/rostests/apitests/kernel32/testlist.c index 6364cab8042..8c671c1b68f 100644 --- a/modules/rostests/apitests/kernel32/testlist.c +++ b/modules/rostests/apitests/kernel32/testlist.c @@ -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 }, -- 2.17.1