ReactOS  0.4.14-dev-57-g333b8f1
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 /* XP does not have these functions */
13 static DWORD (WINAPI *pFlsAlloc)(PFLS_CALLBACK_FUNCTION);
14 static BOOL (WINAPI *pFlsFree)(DWORD);
15 static PVOID (WINAPI *pFlsGetValue)(DWORD);
16 static BOOL (WINAPI *pFlsSetValue)(DWORD,PVOID);
17 static BOOL (WINAPI *pRtlIsCriticalSectionLockedByThread)(RTL_CRITICAL_SECTION *);
18 
19 
20 #define NtCurrentPeb() (NtCurrentTeb()->ProcessEnvironmentBlock)
21 #define WINVER_2003 0x0502
22 
23 static DWORD g_WinVersion = 0;
31 
32 
34 {
35  ok(lpFlsData == g_FlsData1, "Expected g_FlsData1(%p), got %p\n", g_FlsData1, lpFlsData);
37 }
38 
40 {
41  ok(lpFlsData == g_FlsData2, "Expected g_FlsData2(%p), got %p\n", g_FlsData2, lpFlsData);
43 }
44 
46 {
47  ok(lpFlsData == g_FlsData3, "Expected g_FlsData3(%p), got %p\n", g_FlsData3, lpFlsData);
48 
50  ok(pRtlIsCriticalSectionLockedByThread(NtCurrentPeb()->FastPebLock), "Expected lock on PEB\n");
52  if (g_FlsExcept3)
53  {
55  }
56 }
57 
58 typedef struct _FLS_CALLBACK_INFO
59 {
63 
64 
65 void ok_fls_(DWORD dwIndex, PVOID pValue, PFLS_CALLBACK_FUNCTION lpCallback)
66 {
67  PFLS_CALLBACK_INFO FlsCallback;
68  PVOID* FlsData;
69  PVOID gotValue;
70 
71  FlsCallback = (PFLS_CALLBACK_INFO)NtCurrentPeb()->FlsCallback;
72  FlsData = (PVOID*)NtCurrentTeb()->FlsData;
73 
74  winetest_ok(FlsData != NULL, "Expected FlsData\n");
75  winetest_ok(FlsCallback != NULL, "Expected FlsCallback\n");
76 
77  if (FlsData == NULL || FlsCallback == NULL)
78  {
79  winetest_skip("Unable to continue test\n");
80  return;
81  }
82 
84  {
85  winetest_ok(NtCurrentPeb()->FlsCallback[dwIndex] == lpCallback,
86  "Expected NtCurrentPeb()->FlsCallback[%lu] to be %p, was %p\n",
87  dwIndex,
88  lpCallback,
89  NtCurrentPeb()->FlsCallback[dwIndex]);
90  }
91  else
92  {
93  winetest_ok(FlsCallback[dwIndex].lpCallback == lpCallback,
94  "Expected FlsCallback[%lu].lpCallback to be %p, was %p\n",
95  dwIndex,
96  lpCallback,
97  FlsCallback[dwIndex].lpCallback);
98  if (lpCallback != &FlsCallback3 || !g_FlsExcept3)
99  {
100  winetest_ok(FlsCallback[dwIndex].Unknown == NULL,
101  "Expected FlsCallback[%lu].Unknown to be %p, was %p\n",
102  dwIndex,
103  NULL,
104  FlsCallback[dwIndex].Unknown);
105  }
106  }
107  winetest_ok(FlsData[dwIndex + 2] == pValue,
108  "Expected FlsData[%lu + 2] to be %p, was %p\n",
109  dwIndex,
110  pValue,
111  FlsData[dwIndex + 2]);
112 
113  gotValue = pFlsGetValue(dwIndex);
114  winetest_ok(gotValue == pValue, "Expected FlsGetValue(%lu) to be %p, was %p\n", dwIndex, pValue, gotValue);
115 }
116 
117 #define ok_fls (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : ok_fls_
118 
119 static VOID init_funcs(void)
120 {
121  HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
122  HMODULE hNTDLL = GetModuleHandleA("ntdll.dll");
123 
124 #define X(f) p##f = (void*)GetProcAddress(hKernel32, #f);
125  X(FlsAlloc);
126  X(FlsFree);
127  X(FlsGetValue);
128  X(FlsSetValue);
129 #undef X
130  pRtlIsCriticalSectionLockedByThread = (void*)GetProcAddress(hNTDLL, "RtlIsCriticalSectionLockedByThread");
131 }
132 
133 
134 
136 {
137  RTL_OSVERSIONINFOW rtlinfo = { sizeof(rtlinfo) };
138  DWORD dwIndex1, dwIndex2, dwIndex3, dwErr;
139  BOOL bRet;
140 
141  init_funcs();
142  if (!pFlsAlloc || !pFlsFree || !pFlsGetValue || !pFlsSetValue)
143  {
144  skip("Fls functions not available\n");
145  return;
146  }
147  if (!pRtlIsCriticalSectionLockedByThread)
148  {
149  skip("RtlIsCriticalSectionLockedByThread function not available\n");
150  return;
151  }
152 
153  RtlGetVersion(&rtlinfo);
154  g_WinVersion = (rtlinfo.dwMajorVersion << 8) | rtlinfo.dwMinorVersion;
155 
156  dwIndex1 = pFlsAlloc(FlsCallback1);
157  ok(dwIndex1 != FLS_OUT_OF_INDEXES, "Unable to allocate FLS index\n");
158  dwIndex2 = pFlsAlloc(FlsCallback2);
159  ok(dwIndex2 != FLS_OUT_OF_INDEXES, "Unable to allocate FLS index\n");
160  ok(dwIndex1 != dwIndex2, "Expected different indexes, got %lu\n", dwIndex1);
161 
162  dwIndex3 = pFlsAlloc(FlsCallback3);
163  ok(dwIndex3 != FLS_OUT_OF_INDEXES, "Unable to allocate FLS index\n");
164  ok(dwIndex1 != dwIndex3, "Expected different indexes, got %lu\n", dwIndex1);
165 
166  if (dwIndex1 == FLS_OUT_OF_INDEXES || dwIndex2 == FLS_OUT_OF_INDEXES || dwIndex3 == FLS_OUT_OF_INDEXES)
167  {
168  skip("Unable to continue test\n");
169  return;
170  }
171 
172  ok_fls(dwIndex1, g_FlsData1, &FlsCallback1);
173  ok_fls(dwIndex2, g_FlsData2, &FlsCallback2);
174  ok_fls(dwIndex3, g_FlsData3, &FlsCallback3);
175 
176  g_FlsData1 = (PVOID)0x123456;
177  ok(pFlsSetValue(dwIndex1, g_FlsData1), "FlsSetValue(%lu, %p) failed\n", dwIndex1, g_FlsData1);
178 
179  ok_fls(dwIndex1, g_FlsData1, &FlsCallback1);
180  ok_fls(dwIndex2, g_FlsData2, &FlsCallback2);
181  ok_fls(dwIndex3, g_FlsData3, &FlsCallback3);
182 
183  ok_int(g_FlsCalled1, 0);
184  ok_int(g_FlsCalled2, 0);
185  ok_int(g_FlsCalled3, 0);
186 
187  g_FlsData2 = (PVOID)0x9876112;
188  ok(pFlsSetValue(dwIndex2, g_FlsData2), "FlsSetValue(%lu, %p) failed\n", dwIndex2, g_FlsData2);
189 
190  ok_fls(dwIndex1, g_FlsData1, &FlsCallback1);
191  ok_fls(dwIndex2, g_FlsData2, &FlsCallback2);
192  ok_fls(dwIndex3, g_FlsData3, &FlsCallback3);
193 
194 
195  ok_int(g_FlsCalled1, 0);
196  ok_int(g_FlsCalled2, 0);
197  ok_int(g_FlsCalled3, 0);
198 
199  g_FlsData3 = (PVOID)0x98762;
200  ok(pFlsSetValue(dwIndex3, g_FlsData3), "FlsSetValue(%lu, %p) failed\n", dwIndex3, g_FlsData3);
201 
202  ok_fls(dwIndex1, g_FlsData1, &FlsCallback1);
203  ok_fls(dwIndex2, g_FlsData2, &FlsCallback2);
204  ok_fls(dwIndex3, g_FlsData3, &FlsCallback3);
205 
206  ok_int(g_FlsCalled1, 0);
207  ok_int(g_FlsCalled2, 0);
208  ok_int(g_FlsCalled3, 0);
209 
210  ok(pFlsFree(dwIndex1) == TRUE, "FlsFree(%lu) failed\n", dwIndex1);
211  g_FlsData1 = NULL;
212 
213  ok_fls(dwIndex1, g_FlsData1, NULL);
214  ok_fls(dwIndex2, g_FlsData2, &FlsCallback2);
215  ok_fls(dwIndex3, g_FlsData3, &FlsCallback3);
216 
217  ok_int(g_FlsCalled1, 1);
218  ok_int(g_FlsCalled2, 0);
219  ok_int(g_FlsCalled3, 0);
220 
221  g_FlsExcept3 = TRUE;
222  _SEH2_TRY
223  {
224  bRet = pFlsFree(dwIndex3);
225  dwErr = GetLastError();
226  }
228  {
229  bRet = 12345;
230  dwErr = 0xdeaddead;
231  }
232  _SEH2_END;
233  ok(pRtlIsCriticalSectionLockedByThread(NtCurrentPeb()->FastPebLock) == FALSE, "Expected no lock on PEB\n");
234 
235  ok(bRet == 12345, "FlsFree(%lu) should have failed, got %u\n", dwIndex3, bRet);
236  ok(dwErr == 0xdeaddead, "Expected GetLastError() to be 0xdeaddead, was %lx\n", dwErr);
237 
238  ok_fls(dwIndex1, g_FlsData1, NULL);
239  ok_fls(dwIndex2, g_FlsData2, &FlsCallback2);
240  ok_fls(dwIndex3, g_FlsData3, &FlsCallback3);
241 
242  ok_int(g_FlsCalled1, 1);
243  ok_int(g_FlsCalled2, 0);
244  ok_int(g_FlsCalled3, 1);
245 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
LONG g_FlsCalled2
Definition: FLS.c:27
LONG g_FlsCalled1
Definition: FLS.c:25
struct _FLS_CALLBACK_INFO * PFLS_CALLBACK_INFO
static PVOID
Definition: FLS.c:16
PVOID g_FlsData2
Definition: FLS.c:26
#define TRUE
Definition: types.h:120
#define WINVER_2003
Definition: FLS.c:21
NTSTATUS NTAPI RtlGetVersion(IN OUT PRTL_OSVERSIONINFOW lpVersionInformation)
Definition: version.c:158
#define FLS_OUT_OF_INDEXES
Definition: winbase.h:557
struct _FLS_CALLBACK_INFO FLS_CALLBACK_INFO
VOID(WINAPI * PFLS_CALLBACK_FUNCTION)(PVOID)
Definition: winbase.h:1397
PVOID g_FlsData3
Definition: FLS.c:28
START_TEST(FLS)
Definition: FLS.c:135
BOOL WINAPI FlsSetValue(DWORD dwFlsIndex, PVOID lpFlsData)
Definition: fiber.c:481
#define EXCEPTION_NONCONTINUABLE
Definition: rtltypes.h:150
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
_SEH2_TRY
Definition: create.c:4250
DWORD WINAPI FlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback)
Definition: fiber.c:341
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
PVOID WINAPI FlsGetValue(DWORD dwFlsIndex)
Definition: fiber.c:460
smooth NULL
Definition: ftsmooth.c:416
#define ok_int(expression, result)
Definition: atltest.h:134
static DWORD g_WinVersion
Definition: FLS.c:23
static BOOL(WINAPI *pFlsFree)(DWORD)
PFLS_CALLBACK_FUNCTION lpCallback
Definition: FLS.c:60
DWORD dwErr
Definition: service.c:36
PVOID Unknown
Definition: FLS.c:61
BOOL g_FlsExcept3
Definition: FLS.c:30
ULONG dwMajorVersion
Definition: rtltypes.h:243
void __winetest_cdecl winetest_ok(int condition, const char *msg,...)
LONG g_FlsCalled3
Definition: FLS.c:29
#define ok_fls
Definition: FLS.c:117
#define WINAPI
Definition: msvc.h:8
VOID WINAPI FlsCallback3(PVOID lpFlsData)
Definition: FLS.c:45
PVOID g_FlsData1
Definition: FLS.c:24
unsigned long DWORD
Definition: ntddk_ex.h:95
#define X(f)
void ok_fls_(DWORD dwIndex, PVOID pValue, PFLS_CALLBACK_FUNCTION lpCallback)
Definition: FLS.c:65
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:821
_SEH2_END
Definition: create.c:4424
#define InterlockedIncrement
Definition: armddk.h:53
FORCEINLINE struct _TEB * NtCurrentTeb(VOID)
Definition: psfuncs.h:420
VOID WINAPI RaiseException(IN DWORD dwExceptionCode, IN DWORD dwExceptionFlags, IN DWORD nNumberOfArguments, IN CONST ULONG_PTR *lpArguments OPTIONAL)
Definition: except.c:693
#define NtCurrentPeb()
Definition: FLS.c:20
RTL_CRITICAL_SECTION FastPebLock
Definition: ldrinit.c:79
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
ULONG dwMinorVersion
Definition: rtltypes.h:244
static VOID init_funcs(void)
Definition: FLS.c:119
void __winetest_cdecl winetest_skip(const char *msg,...)
#define GetProcAddress(x, y)
Definition: compat.h:410
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
VOID WINAPI FlsCallback2(PVOID lpFlsData)
Definition: FLS.c:39
BOOL WINAPI FlsFree(DWORD dwFlsIndex)
Definition: fiber.c:400
static DWORD(WINAPI *pFlsAlloc)(PFLS_CALLBACK_FUNCTION)
VOID WINAPI FlsCallback1(PVOID lpFlsData)
Definition: FLS.c:33