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)
9 #include <ndk/pstypes.h>
10 #include <ndk/rtlfuncs.h>
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
);
19 #define NtCurrentPeb() (NtCurrentTeb()->ProcessEnvironmentBlock)
20 #define WINVER_2003 0x0502
22 static DWORD g_WinVersion
= 0;
23 PVOID g_FlsData1
= NULL
;
24 LONG g_FlsCalled1
= 0;
25 PVOID g_FlsData2
= NULL
;
26 LONG g_FlsCalled2
= 0;
27 PVOID g_FlsData3
= NULL
;
28 LONG g_FlsCalled3
= 0;
29 BOOL g_FlsExcept3
= FALSE
;
32 VOID WINAPI
FlsCallback1(PVOID lpFlsData
)
34 ok(lpFlsData
== g_FlsData1
, "Expected g_FlsData1(%p), got %p\n", g_FlsData1
, lpFlsData
);
35 InterlockedIncrement(&g_FlsCalled1
);
38 VOID WINAPI
FlsCallback2(PVOID lpFlsData
)
40 ok(lpFlsData
== g_FlsData2
, "Expected g_FlsData2(%p), got %p\n", g_FlsData2
, lpFlsData
);
41 InterlockedIncrement(&g_FlsCalled2
);
44 VOID WINAPI
FlsCallback3(PVOID lpFlsData
)
46 ok(lpFlsData
== g_FlsData3
, "Expected g_FlsData3(%p), got %p\n", g_FlsData3
, lpFlsData
);
48 if (g_WinVersion
<= WINVER_2003
)
49 ok(RtlIsCriticalSectionLockedByThread(NtCurrentPeb()->FastPebLock
), "Expected lock on PEB\n");
50 InterlockedIncrement(&g_FlsCalled3
);
53 RaiseException(ERROR_INVALID_PARAMETER
, EXCEPTION_NONCONTINUABLE
, 0, NULL
);
57 typedef struct _FLS_CALLBACK_INFO
59 PFLS_CALLBACK_FUNCTION lpCallback
;
61 } FLS_CALLBACK_INFO
, *PFLS_CALLBACK_INFO
;
64 void ok_fls_(DWORD dwIndex
, PVOID pValue
, PFLS_CALLBACK_FUNCTION lpCallback
)
66 PFLS_CALLBACK_INFO FlsCallback
;
70 FlsCallback
= (PFLS_CALLBACK_INFO
)NtCurrentPeb()->FlsCallback
;
71 FlsData
= (PVOID
*)NtCurrentTeb()->FlsData
;
73 winetest_ok(FlsData
!= NULL
, "Expected FlsData\n");
74 winetest_ok(FlsCallback
!= NULL
, "Expected FlsCallback\n");
76 if (FlsData
== NULL
|| FlsCallback
== NULL
)
78 winetest_skip("Unable to continue test\n");
82 if (g_WinVersion
<= WINVER_2003
)
84 winetest_ok(NtCurrentPeb()->FlsCallback
[dwIndex
] == lpCallback
,
85 "Expected NtCurrentPeb()->FlsCallback[%lu] to be %p, was %p\n",
88 NtCurrentPeb()->FlsCallback
[dwIndex
]);
92 winetest_ok(FlsCallback
[dwIndex
].lpCallback
== lpCallback
,
93 "Expected FlsCallback[%lu].lpCallback to be %p, was %p\n",
96 FlsCallback
[dwIndex
].lpCallback
);
97 if (lpCallback
!= &FlsCallback3
|| !g_FlsExcept3
)
99 winetest_ok(FlsCallback
[dwIndex
].Unknown
== NULL
,
100 "Expected FlsCallback[%lu].Unknown to be %p, was %p\n",
103 FlsCallback
[dwIndex
].Unknown
);
106 winetest_ok(FlsData
[dwIndex
+ 2] == pValue
,
107 "Expected FlsData[%lu + 2] to be %p, was %p\n",
110 FlsData
[dwIndex
+ 2]);
112 gotValue
= pFlsGetValue(dwIndex
);
113 winetest_ok(gotValue
== pValue
, "Expected FlsGetValue(%lu) to be %p, was %p\n", dwIndex
, pValue
, gotValue
);
116 #define ok_fls (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : ok_fls_
118 static VOID
init_funcs(void)
120 HMODULE hKernel32
= GetModuleHandleA("kernel32.dll");
122 #define X(f) p##f = (void*)GetProcAddress(hKernel32, #f);
134 RTL_OSVERSIONINFOW rtlinfo
= { sizeof(rtlinfo
) };
135 DWORD dwIndex1
, dwIndex2
, dwIndex3
, dwErr
;
139 if (!pFlsAlloc
|| !pFlsFree
|| !pFlsGetValue
|| !pFlsSetValue
)
141 skip("Fls functions not available\n");
145 RtlGetVersion(&rtlinfo
);
146 g_WinVersion
= (rtlinfo
.dwMajorVersion
<< 8) | rtlinfo
.dwMinorVersion
;
148 dwIndex1
= pFlsAlloc(FlsCallback1
);
149 ok(dwIndex1
!= FLS_OUT_OF_INDEXES
, "Unable to allocate FLS index\n");
150 dwIndex2
= pFlsAlloc(FlsCallback2
);
151 ok(dwIndex2
!= FLS_OUT_OF_INDEXES
, "Unable to allocate FLS index\n");
152 ok(dwIndex1
!= dwIndex2
, "Expected different indexes, got %lu\n", dwIndex1
);
154 dwIndex3
= pFlsAlloc(FlsCallback3
);
155 ok(dwIndex3
!= FLS_OUT_OF_INDEXES
, "Unable to allocate FLS index\n");
156 ok(dwIndex1
!= dwIndex3
, "Expected different indexes, got %lu\n", dwIndex1
);
158 if (dwIndex1
== FLS_OUT_OF_INDEXES
|| dwIndex2
== FLS_OUT_OF_INDEXES
|| dwIndex3
== FLS_OUT_OF_INDEXES
)
160 skip("Unable to continue test\n");
164 ok_fls(dwIndex1
, g_FlsData1
, &FlsCallback1
);
165 ok_fls(dwIndex2
, g_FlsData2
, &FlsCallback2
);
166 ok_fls(dwIndex3
, g_FlsData3
, &FlsCallback3
);
168 g_FlsData1
= (PVOID
)0x123456;
169 ok(pFlsSetValue(dwIndex1
, g_FlsData1
), "FlsSetValue(%lu, %p) failed\n", dwIndex1
, g_FlsData1
);
171 ok_fls(dwIndex1
, g_FlsData1
, &FlsCallback1
);
172 ok_fls(dwIndex2
, g_FlsData2
, &FlsCallback2
);
173 ok_fls(dwIndex3
, g_FlsData3
, &FlsCallback3
);
175 ok_int(g_FlsCalled1
, 0);
176 ok_int(g_FlsCalled2
, 0);
177 ok_int(g_FlsCalled3
, 0);
179 g_FlsData2
= (PVOID
)0x9876112;
180 ok(pFlsSetValue(dwIndex2
, g_FlsData2
), "FlsSetValue(%lu, %p) failed\n", dwIndex2
, g_FlsData2
);
182 ok_fls(dwIndex1
, g_FlsData1
, &FlsCallback1
);
183 ok_fls(dwIndex2
, g_FlsData2
, &FlsCallback2
);
184 ok_fls(dwIndex3
, g_FlsData3
, &FlsCallback3
);
187 ok_int(g_FlsCalled1
, 0);
188 ok_int(g_FlsCalled2
, 0);
189 ok_int(g_FlsCalled3
, 0);
191 g_FlsData3
= (PVOID
)0x98762;
192 ok(pFlsSetValue(dwIndex3
, g_FlsData3
), "FlsSetValue(%lu, %p) failed\n", dwIndex3
, g_FlsData3
);
194 ok_fls(dwIndex1
, g_FlsData1
, &FlsCallback1
);
195 ok_fls(dwIndex2
, g_FlsData2
, &FlsCallback2
);
196 ok_fls(dwIndex3
, g_FlsData3
, &FlsCallback3
);
198 ok_int(g_FlsCalled1
, 0);
199 ok_int(g_FlsCalled2
, 0);
200 ok_int(g_FlsCalled3
, 0);
202 ok(pFlsFree(dwIndex1
) == TRUE
, "FlsFree(%lu) failed\n", dwIndex1
);
205 ok_fls(dwIndex1
, g_FlsData1
, NULL
);
206 ok_fls(dwIndex2
, g_FlsData2
, &FlsCallback2
);
207 ok_fls(dwIndex3
, g_FlsData3
, &FlsCallback3
);
209 ok_int(g_FlsCalled1
, 1);
210 ok_int(g_FlsCalled2
, 0);
211 ok_int(g_FlsCalled3
, 0);
216 bRet
= pFlsFree(dwIndex3
);
217 dwErr
= GetLastError();
219 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
225 ok(RtlIsCriticalSectionLockedByThread(NtCurrentPeb()->FastPebLock
) == FALSE
, "Expected no lock on PEB\n");
227 ok(bRet
== 12345, "FlsFree(%lu) should have failed, got %u\n", dwIndex3
, bRet
);
228 ok(dwErr
== 0xdeaddead, "Expected GetLastError() to be 0xdeaddead, was %lx\n", dwErr
);
230 ok_fls(dwIndex1
, g_FlsData1
, NULL
);
231 ok_fls(dwIndex2
, g_FlsData2
, &FlsCallback2
);
232 ok_fls(dwIndex3
, g_FlsData3
, &FlsCallback3
);
234 ok_int(g_FlsCalled1
, 1);
235 ok_int(g_FlsCalled2
, 0);
236 ok_int(g_FlsCalled3
, 1);