ReactOS 0.4.15-dev-7788-g1ad9096
FLS.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS api tests
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Tests for FLS implementation details
5 * COPYRIGHT: Copyright 2018 Mark Jansen (mark.jansen@reactos.org)
6 */
7
8#include "precomp.h"
9#include <ndk/pstypes.h>
10#include <ndk/rtlfuncs.h>
11
12#include <pseh/pseh2.h>
13
14/* XP does not have these functions */
15static DWORD (WINAPI *pFlsAlloc)(PFLS_CALLBACK_FUNCTION);
16static BOOL (WINAPI *pFlsFree)(DWORD);
17static PVOID (WINAPI *pFlsGetValue)(DWORD);
18static BOOL (WINAPI *pFlsSetValue)(DWORD,PVOID);
19static BOOL (WINAPI *pRtlIsCriticalSectionLockedByThread)(RTL_CRITICAL_SECTION *);
20
21
22#define NtCurrentPeb() (NtCurrentTeb()->ProcessEnvironmentBlock)
23#define WINVER_2003 0x0502
24
33
34
36{
37 ok(lpFlsData == g_FlsData1, "Expected g_FlsData1(%p), got %p\n", g_FlsData1, lpFlsData);
39}
40
42{
43 ok(lpFlsData == g_FlsData2, "Expected g_FlsData2(%p), got %p\n", g_FlsData2, lpFlsData);
45}
46
48{
49 ok(lpFlsData == g_FlsData3, "Expected g_FlsData3(%p), got %p\n", g_FlsData3, lpFlsData);
50
52 ok(pRtlIsCriticalSectionLockedByThread(NtCurrentPeb()->FastPebLock), "Expected lock on PEB\n");
54 if (g_FlsExcept3)
55 {
57 }
58}
59
60typedef struct _FLS_CALLBACK_INFO
61{
65
66
68{
69 PFLS_CALLBACK_INFO FlsCallback;
70 PVOID* FlsData;
71 PVOID gotValue;
72
73 FlsCallback = (PFLS_CALLBACK_INFO)NtCurrentPeb()->FlsCallback;
74 FlsData = (PVOID*)NtCurrentTeb()->FlsData;
75
76 winetest_ok(FlsData != NULL, "Expected FlsData\n");
77 winetest_ok(FlsCallback != NULL, "Expected FlsCallback\n");
78
79 if (FlsData == NULL || FlsCallback == NULL)
80 {
81 winetest_skip("Unable to continue test\n");
82 return;
83 }
84
86 {
87 winetest_ok(NtCurrentPeb()->FlsCallback[dwIndex] == lpCallback,
88 "Expected NtCurrentPeb()->FlsCallback[%lu] to be %p, was %p\n",
89 dwIndex,
90 lpCallback,
91 NtCurrentPeb()->FlsCallback[dwIndex]);
92 }
93 else
94 {
95 winetest_ok(FlsCallback[dwIndex].lpCallback == lpCallback,
96 "Expected FlsCallback[%lu].lpCallback to be %p, was %p\n",
97 dwIndex,
98 lpCallback,
99 FlsCallback[dwIndex].lpCallback);
100 if (lpCallback != &FlsCallback3 || !g_FlsExcept3)
101 {
102 winetest_ok(FlsCallback[dwIndex].Unknown == NULL,
103 "Expected FlsCallback[%lu].Unknown to be %p, was %p\n",
104 dwIndex,
105 NULL,
106 FlsCallback[dwIndex].Unknown);
107 }
108 }
109 winetest_ok(FlsData[dwIndex + 2] == pValue,
110 "Expected FlsData[%lu + 2] to be %p, was %p\n",
111 dwIndex,
112 pValue,
113 FlsData[dwIndex + 2]);
114
115 gotValue = pFlsGetValue(dwIndex);
116 winetest_ok(gotValue == pValue, "Expected FlsGetValue(%lu) to be %p, was %p\n", dwIndex, pValue, gotValue);
117}
118
119#define ok_fls (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : ok_fls_
120
121static VOID init_funcs(void)
122{
123 HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
124 HMODULE hNTDLL = GetModuleHandleA("ntdll.dll");
125
126#define X(f) p##f = (void*)GetProcAddress(hKernel32, #f);
127 X(FlsAlloc);
128 X(FlsFree);
129 X(FlsGetValue);
130 X(FlsSetValue);
131#undef X
132 pRtlIsCriticalSectionLockedByThread = (void*)GetProcAddress(hNTDLL, "RtlIsCriticalSectionLockedByThread");
133}
134
135
136
138{
139 RTL_OSVERSIONINFOW rtlinfo = { sizeof(rtlinfo) };
140 DWORD dwIndex1, dwIndex2, dwIndex3, dwErr;
141 BOOL bRet;
142
143 init_funcs();
144 if (!pFlsAlloc || !pFlsFree || !pFlsGetValue || !pFlsSetValue)
145 {
146 skip("Fls functions not available\n");
147 return;
148 }
149 if (!pRtlIsCriticalSectionLockedByThread)
150 {
151 skip("RtlIsCriticalSectionLockedByThread function not available\n");
152 return;
153 }
154
155 RtlGetVersion(&rtlinfo);
156 g_WinVersion = (rtlinfo.dwMajorVersion << 8) | rtlinfo.dwMinorVersion;
157
158 dwIndex1 = pFlsAlloc(FlsCallback1);
159 ok(dwIndex1 != FLS_OUT_OF_INDEXES, "Unable to allocate FLS index\n");
160 dwIndex2 = pFlsAlloc(FlsCallback2);
161 ok(dwIndex2 != FLS_OUT_OF_INDEXES, "Unable to allocate FLS index\n");
162 ok(dwIndex1 != dwIndex2, "Expected different indexes, got %lu\n", dwIndex1);
163
164 dwIndex3 = pFlsAlloc(FlsCallback3);
165 ok(dwIndex3 != FLS_OUT_OF_INDEXES, "Unable to allocate FLS index\n");
166 ok(dwIndex1 != dwIndex3, "Expected different indexes, got %lu\n", dwIndex1);
167
168 if (dwIndex1 == FLS_OUT_OF_INDEXES || dwIndex2 == FLS_OUT_OF_INDEXES || dwIndex3 == FLS_OUT_OF_INDEXES)
169 {
170 skip("Unable to continue test\n");
171 return;
172 }
173
174 ok_fls(dwIndex1, g_FlsData1, &FlsCallback1);
175 ok_fls(dwIndex2, g_FlsData2, &FlsCallback2);
176 ok_fls(dwIndex3, g_FlsData3, &FlsCallback3);
177
178 g_FlsData1 = (PVOID)0x123456;
179 ok(pFlsSetValue(dwIndex1, g_FlsData1), "FlsSetValue(%lu, %p) failed\n", dwIndex1, g_FlsData1);
180
181 ok_fls(dwIndex1, g_FlsData1, &FlsCallback1);
182 ok_fls(dwIndex2, g_FlsData2, &FlsCallback2);
183 ok_fls(dwIndex3, g_FlsData3, &FlsCallback3);
184
188
189 g_FlsData2 = (PVOID)0x9876112;
190 ok(pFlsSetValue(dwIndex2, g_FlsData2), "FlsSetValue(%lu, %p) failed\n", dwIndex2, g_FlsData2);
191
192 ok_fls(dwIndex1, g_FlsData1, &FlsCallback1);
193 ok_fls(dwIndex2, g_FlsData2, &FlsCallback2);
194 ok_fls(dwIndex3, g_FlsData3, &FlsCallback3);
195
196
200
201 g_FlsData3 = (PVOID)0x98762;
202 ok(pFlsSetValue(dwIndex3, g_FlsData3), "FlsSetValue(%lu, %p) failed\n", dwIndex3, g_FlsData3);
203
204 ok_fls(dwIndex1, g_FlsData1, &FlsCallback1);
205 ok_fls(dwIndex2, g_FlsData2, &FlsCallback2);
206 ok_fls(dwIndex3, g_FlsData3, &FlsCallback3);
207
211
212 ok(pFlsFree(dwIndex1) == TRUE, "FlsFree(%lu) failed\n", dwIndex1);
214
215 ok_fls(dwIndex1, g_FlsData1, NULL);
216 ok_fls(dwIndex2, g_FlsData2, &FlsCallback2);
217 ok_fls(dwIndex3, g_FlsData3, &FlsCallback3);
218
222
225 {
226 bRet = pFlsFree(dwIndex3);
228 }
230 {
231 bRet = 12345;
232 dwErr = 0xdeaddead;
233 }
234 _SEH2_END;
235 ok(pRtlIsCriticalSectionLockedByThread(NtCurrentPeb()->FastPebLock) == FALSE, "Expected no lock on PEB\n");
236
237 ok(bRet == 12345, "FlsFree(%lu) should have failed, got %u\n", dwIndex3, bRet);
238 ok(dwErr == 0xdeaddead, "Expected GetLastError() to be 0xdeaddead, was %lx\n", dwErr);
239
240 ok_fls(dwIndex1, g_FlsData1, NULL);
241 ok_fls(dwIndex2, g_FlsData2, &FlsCallback2);
242 ok_fls(dwIndex3, g_FlsData3, &FlsCallback3);
243
247}
LONG g_FlsCalled2
Definition: FLS.c:29
PVOID g_FlsData1
Definition: FLS.c:26
VOID WINAPI FlsCallback3(PVOID lpFlsData)
Definition: FLS.c:47
LONG g_FlsCalled3
Definition: FLS.c:31
#define WINVER_2003
Definition: FLS.c:23
VOID WINAPI FlsCallback1(PVOID lpFlsData)
Definition: FLS.c:35
struct _FLS_CALLBACK_INFO * PFLS_CALLBACK_INFO
LONG g_FlsCalled1
Definition: FLS.c:27
void ok_fls_(DWORD dwIndex, PVOID pValue, PFLS_CALLBACK_FUNCTION lpCallback)
Definition: FLS.c:67
VOID WINAPI FlsCallback2(PVOID lpFlsData)
Definition: FLS.c:41
#define X(f)
struct _FLS_CALLBACK_INFO FLS_CALLBACK_INFO
#define NtCurrentPeb()
Definition: FLS.c:22
PVOID g_FlsData3
Definition: FLS.c:30
BOOL g_FlsExcept3
Definition: FLS.c:32
PVOID g_FlsData2
Definition: FLS.c:28
#define ok_fls
Definition: FLS.c:119
static PVOID
Definition: FLS.c:18
static DWORD g_WinVersion
Definition: FLS.c:25
static VOID init_funcs(void)
Definition: FLS.c:121
#define InterlockedIncrement
Definition: armddk.h:53
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
#define ok_int(expression, result)
Definition: atltest.h:134
DWORD dwErr
Definition: service.c:36
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
NTSTATUS NTAPI RtlGetVersion(IN OUT PRTL_OSVERSIONINFOW lpVersionInformation)
Definition: version.c:158
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define GetProcAddress(x, y)
Definition: compat.h:753
VOID WINAPI RaiseException(_In_ DWORD dwExceptionCode, _In_ DWORD dwExceptionFlags, _In_ DWORD nNumberOfArguments, _In_opt_ const ULONG_PTR *lpArguments)
Definition: except.c:700
PVOID WINAPI FlsGetValue(DWORD dwFlsIndex)
Definition: fiber.c:460
BOOL WINAPI FlsSetValue(DWORD dwFlsIndex, PVOID lpFlsData)
Definition: fiber.c:481
BOOL WINAPI FlsFree(DWORD dwFlsIndex)
Definition: fiber.c:400
DWORD WINAPI FlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback)
Definition: fiber.c:341
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
PWCHAR pValue
@ Unknown
Definition: i8042prt.h:114
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define NtCurrentTeb
RTL_CRITICAL_SECTION FastPebLock
Definition: ldrinit.c:79
HANDLE hKernel32
Definition: locale.c:13
#define BOOL
Definition: nt_native.h:43
#define DWORD
Definition: nt_native.h:44
long LONG
Definition: pedump.c:60
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
void __winetest_cdecl winetest_skip(const char *msg,...)
void __winetest_cdecl winetest_ok(int condition, const char *msg,...)
PFLS_CALLBACK_FUNCTION lpCallback
Definition: FLS.c:62
PVOID Unknown
Definition: FLS.c:63
ULONG dwMinorVersion
Definition: rtltypes.h:248
ULONG dwMajorVersion
Definition: rtltypes.h:247
#define EXCEPTION_NONCONTINUABLE
Definition: stubs.h:23
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define FLS_OUT_OF_INDEXES
Definition: winbase.h:576
VOID(WINAPI * PFLS_CALLBACK_FUNCTION)(PVOID)
Definition: winbase.h:1444
#define WINAPI
Definition: msvc.h:6