769b5be5975f5a28cc3e781ce31ae92d7203a565
[reactos.git] / modules / rostests / apitests / kernel32 / FLS.c
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
18
19 #define NtCurrentPeb() (NtCurrentTeb()->ProcessEnvironmentBlock)
20 #define WINVER_2003 0x0502
21
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
28 VOID WINAPI FlsCallback1(PVOID lpFlsData)
29 {
30 ok(lpFlsData == g_FlsData1, "Expected g_FlsData1(%p), got %p\n", g_FlsData1, lpFlsData);
31 InterlockedIncrement(&g_FlsCalled1);
32 }
33
34 VOID WINAPI FlsCallback2(PVOID lpFlsData)
35 {
36 ok(lpFlsData == g_FlsData2, "Expected g_FlsData2(%p), got %p\n", g_FlsData2, lpFlsData);
37 InterlockedIncrement(&g_FlsCalled2);
38 }
39
40
41 typedef struct _FLS_CALLBACK_INFO
42 {
43 PFLS_CALLBACK_FUNCTION lpCallback;
44 PVOID Unknown;
45 } FLS_CALLBACK_INFO, *PFLS_CALLBACK_INFO;
46
47
48 void ok_fls_(DWORD dwIndex, PVOID pValue, PFLS_CALLBACK_FUNCTION lpCallback)
49 {
50 PFLS_CALLBACK_INFO FlsCallback;
51 PVOID* FlsData;
52 PVOID gotValue;
53
54 FlsCallback = (PFLS_CALLBACK_INFO)NtCurrentPeb()->FlsCallback;
55 FlsData = (PVOID*)NtCurrentTeb()->FlsData;
56
57 winetest_ok(FlsData != NULL, "Expected FlsData\n");
58 winetest_ok(FlsCallback != NULL, "Expected FlsCallback\n");
59
60 if (FlsData == NULL || FlsCallback == NULL)
61 {
62 winetest_skip("Unable to continue test\n");
63 return;
64 }
65
66 if (g_WinVersion <= WINVER_2003)
67 {
68 winetest_ok(NtCurrentPeb()->FlsCallback[dwIndex] == lpCallback,
69 "Expected NtCurrentPeb()->FlsCallback[%lu] to be %p, was %p\n",
70 dwIndex,
71 lpCallback,
72 NtCurrentPeb()->FlsCallback[dwIndex]);
73 }
74 else
75 {
76 winetest_ok(FlsCallback[dwIndex].lpCallback == lpCallback,
77 "Expected FlsCallback[%lu].lpCallback to be %p, was %p\n",
78 dwIndex,
79 lpCallback,
80 FlsCallback[dwIndex].lpCallback);
81 winetest_ok(FlsCallback[dwIndex].Unknown == NULL,
82 "Expected FlsCallback[%lu].Unknown to be %p, was %p\n",
83 dwIndex,
84 NULL,
85 FlsCallback[dwIndex].Unknown);
86 }
87 winetest_ok(FlsData[dwIndex + 2] == pValue,
88 "Expected FlsData[%lu + 2] to be %p, was %p\n",
89 dwIndex,
90 pValue,
91 FlsData[dwIndex + 2]);
92
93 gotValue = pFlsGetValue(dwIndex);
94 winetest_ok(gotValue == pValue, "Expected FlsGetValue(%lu) to be %p, was %p\n", dwIndex, pValue, gotValue);
95 }
96
97 #define ok_fls (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : ok_fls_
98
99 static VOID init_funcs(void)
100 {
101 HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
102
103 #define X(f) p##f = (void*)GetProcAddress(hKernel32, #f);
104 X(FlsAlloc);
105 X(FlsFree);
106 X(FlsGetValue);
107 X(FlsSetValue);
108 #undef X
109 }
110
111
112
113 START_TEST(FLS)
114 {
115 RTL_OSVERSIONINFOW rtlinfo = { sizeof(rtlinfo) };
116 DWORD dwIndex1, dwIndex2;
117
118 init_funcs();
119 if (!pFlsAlloc || !pFlsFree || !pFlsGetValue || !pFlsSetValue)
120 {
121 skip("Fls functions not available\n");
122 return;
123 }
124
125 RtlGetVersion(&rtlinfo);
126 g_WinVersion = (rtlinfo.dwMajorVersion << 8) | rtlinfo.dwMinorVersion;
127
128 dwIndex1 = pFlsAlloc(FlsCallback1);
129 ok(dwIndex1 != FLS_OUT_OF_INDEXES, "Unable to allocate FLS index\n");
130 dwIndex2 = pFlsAlloc(FlsCallback2);
131 ok(dwIndex2 != FLS_OUT_OF_INDEXES, "Unable to allocate FLS index\n");
132 ok(dwIndex1 != dwIndex2, "Expected different indexes, got %lu\n", dwIndex1);
133
134 if (dwIndex1 == FLS_OUT_OF_INDEXES || dwIndex2 == FLS_OUT_OF_INDEXES)
135 {
136 skip("Unable to continue test\n");
137 return;
138 }
139
140 ok_fls(dwIndex1, g_FlsData1, &FlsCallback1);
141 ok_fls(dwIndex2, g_FlsData2, &FlsCallback2);
142
143 g_FlsData1 = (PVOID)0x123456;
144 ok(pFlsSetValue(dwIndex1, g_FlsData1), "FlsSetValue(%lu, %p) failed\n", dwIndex1, g_FlsData1);
145
146 ok_fls(dwIndex1, g_FlsData1, &FlsCallback1);
147 ok_fls(dwIndex2, g_FlsData2, &FlsCallback2);
148
149 ok_int(g_FlsCalled1, 0);
150 ok_int(g_FlsCalled2, 0);
151
152 g_FlsData2 = (PVOID)0x9876112;
153 ok(pFlsSetValue(dwIndex2, g_FlsData2), "FlsSetValue(%lu, %p) failed\n", dwIndex2, g_FlsData2);
154
155 ok_fls(dwIndex1, g_FlsData1, &FlsCallback1);
156 ok_fls(dwIndex2, g_FlsData2, &FlsCallback2);
157
158 ok_int(g_FlsCalled1, 0);
159 ok_int(g_FlsCalled2, 0);
160
161 ok(pFlsFree(dwIndex1), "FlsFree(%lu) failed\n", dwIndex1);
162 g_FlsData1 = NULL;
163
164 ok_fls(dwIndex1, g_FlsData1, NULL);
165 ok_fls(dwIndex2, g_FlsData2, &FlsCallback2);
166
167 ok_int(g_FlsCalled1, 1);
168 ok_int(g_FlsCalled2, 0);
169 }