[APPSHIM_APITEST] Add test for IgnoreLoadLibrary
[reactos.git] / modules / rostests / apitests / appshim / ignoreloadlib.c
1 /*
2 * PROJECT: appshim_apitest
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Tests for IgnoreLoadLibrary shim
5 * COPYRIGHT: Copyright 2019 Mark Jansen (mark.jansen@reactos.org)
6 */
7
8 #include <ntstatus.h>
9 #define WIN32_NO_STATUS
10 #include <windows.h>
11 #include <ntndk.h>
12 #include "wine/test.h"
13
14 #include "appshim_apitest.h"
15
16 static DWORD g_WinVersion;
17 static tGETHOOKAPIS pGetHookAPIs;
18 static HMODULE g_hSentinelModule = (HMODULE)&pGetHookAPIs; /* Not a valid hmodule, so a nice sentinel */
19 static HMODULE g_h123 = (HMODULE)123;
20 static HMODULE g_h111 = (HMODULE)111;
21 static HMODULE g_h0 = (HMODULE)0;
22
23 typedef HMODULE(WINAPI* LOADLIBRARYAPROC)(LPCSTR lpLibFileName);
24 typedef HMODULE(WINAPI* LOADLIBRARYWPROC)(LPCWSTR lpLibFileName);
25 typedef HMODULE(WINAPI* LOADLIBRARYEXAPROC)(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
26 typedef HMODULE(WINAPI* LOADLIBRARYEXWPROC)(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
27
28
29 UINT
30 WINAPI
31 GetErrorMode(VOID)
32 {
33 NTSTATUS Status;
34 UINT ErrMode;
35
36 /* Query the current setting */
37 Status = NtQueryInformationProcess(NtCurrentProcess(),
38 ProcessDefaultHardErrorMode,
39 &ErrMode,
40 sizeof(ErrMode),
41 NULL);
42 if (!NT_SUCCESS(Status))
43 {
44 /* Fail if we couldn't query */
45 return 0;
46 }
47
48 /* Check if NOT failing critical errors was requested */
49 if (ErrMode & SEM_FAILCRITICALERRORS)
50 {
51 /* Mask it out, since the native API works differently */
52 ErrMode &= ~SEM_FAILCRITICALERRORS;
53 }
54 else
55 {
56 /* OR it if the caller didn't, due to different native semantics */
57 ErrMode |= SEM_FAILCRITICALERRORS;
58 }
59
60 /* Return the mode */
61 return ErrMode;
62 }
63
64 static HMODULE WINAPI my_LoadLibraryA(PCSTR Name)
65 {
66 DWORD dwErrorMode = GetErrorMode();
67 ok(dwErrorMode == (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX),
68 "Unexpected error mode: 0x%x\n", dwErrorMode);
69 return g_hSentinelModule;
70 }
71
72 static HMODULE WINAPI my_LoadLibraryExA(PCSTR Name, HANDLE hFile, DWORD dwFlags)
73 {
74 DWORD dwErrorMode = GetErrorMode();
75 ok(dwErrorMode == (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX),
76 "Unexpected error mode: 0x%x\n", dwErrorMode);
77 return g_hSentinelModule;
78 }
79
80 static HMODULE WINAPI my_LoadLibraryW(PCWSTR Name)
81 {
82 DWORD dwErrorMode = GetErrorMode();
83 ok(dwErrorMode == (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX),
84 "Unexpected error mode: 0x%x\n", dwErrorMode);
85 return g_hSentinelModule;
86 }
87
88 static HMODULE WINAPI my_LoadLibraryExW(PCWSTR Name, HANDLE hFile, DWORD dwFlags)
89 {
90 DWORD dwErrorMode = GetErrorMode();
91 ok(dwErrorMode == (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX),
92 "Unexpected error mode: 0x%x\n", dwErrorMode);
93 return g_hSentinelModule;
94 }
95
96
97 static void test_LoadLibraryA(PHOOKAPI hook)
98 {
99 LOADLIBRARYAPROC proc;
100 DWORD dwErrorMode, dwOldErrorMode;
101
102 hook->OriginalFunction = my_LoadLibraryA;
103 proc = hook->ReplacementFunction;
104
105 dwOldErrorMode = GetErrorMode();
106
107 /* Exact names return what is specified */
108 ok_ptr(proc("test123.dll"), g_h123);
109 ok_ptr(proc("test111"), g_h111);
110 /* Extension is not added */
111 ok_ptr(proc("test111.dll"), g_hSentinelModule);
112 /* Zero can be specified */
113 ok_ptr(proc("Something.mark"), g_h0);
114 /* Or default returned */
115 ok_ptr(proc("empty"), g_h0);
116
117 /* Paths, do not have to be valid */
118 ok_ptr(proc("\\test123.dll"), g_h123);
119 ok_ptr(proc("/test123.dll"), g_h123);
120 ok_ptr(proc("\\\\\\\\test123.dll"), g_h123);
121 ok_ptr(proc("////test123.dll"), g_h123);
122 ok_ptr(proc("mypath:something\\does\\not\\matter\\test123.dll"), g_h123);
123 ok_ptr(proc("/put/whatever/you/want/here/test123.dll"), g_h123);
124
125 /* path separator is checked, not just any point in the path */
126 ok_ptr(proc("-test123.dll"), g_hSentinelModule);
127 ok_ptr(proc("test123.dll-"), g_hSentinelModule);
128
129 dwErrorMode = GetErrorMode();
130 ok(dwErrorMode == dwOldErrorMode, "ErrorMode changed, was 0x%x, is 0x%x\n", dwOldErrorMode, dwErrorMode);
131 }
132
133 static void test_LoadLibraryW(PHOOKAPI hook)
134 {
135 LOADLIBRARYWPROC proc;
136 DWORD dwErrorMode, dwOldErrorMode;
137
138 hook->OriginalFunction = my_LoadLibraryW;
139 proc = hook->ReplacementFunction;
140
141 dwOldErrorMode = GetErrorMode();
142
143 /* Exact names return what is specified */
144 ok_ptr(proc(L"test123.dll"), g_h123);
145 ok_ptr(proc(L"test111"), g_h111);
146 /* Extension is not added */
147 ok_ptr(proc(L"test111.dll"), g_hSentinelModule);
148 /* Zero can be specified */
149 ok_ptr(proc(L"Something.mark"), g_h0);
150 /* Or default returned */
151 ok_ptr(proc(L"empty"), g_h0);
152
153 /* Paths, do not have to be valid */
154 ok_ptr(proc(L"\\test123.dll"), g_h123);
155 ok_ptr(proc(L"/test123.dll"), g_h123);
156 ok_ptr(proc(L"\\\\\\\\test123.dll"), g_h123);
157 ok_ptr(proc(L"////test123.dll"), g_h123);
158 ok_ptr(proc(L"mypath:something\\does\\not\\matter\\test123.dll"), g_h123);
159 ok_ptr(proc(L"/put/whatever/you/want/here/test123.dll"), g_h123);
160
161 /* path separator is checked, not just any point in the path */
162 ok_ptr(proc(L"-test123.dll"), g_hSentinelModule);
163 ok_ptr(proc(L"test123.dll-"), g_hSentinelModule);
164
165 dwErrorMode = GetErrorMode();
166 ok(dwErrorMode == dwOldErrorMode, "ErrorMode changed, was 0x%x, is 0x%x\n", dwOldErrorMode, dwErrorMode);
167 }
168
169 static void test_LoadLibraryExA(PHOOKAPI hook)
170 {
171 LOADLIBRARYEXAPROC proc;
172 DWORD dwErrorMode, dwOldErrorMode;
173
174 hook->OriginalFunction = my_LoadLibraryExA;
175 proc = hook->ReplacementFunction;
176
177 dwOldErrorMode = GetErrorMode();
178
179 /* Exact names return what is specified */
180 ok_ptr(proc("test123.dll", INVALID_HANDLE_VALUE, 0), g_h123);
181 ok_ptr(proc("test111", INVALID_HANDLE_VALUE, 0), g_h111);
182 /* Extension is not added */
183 ok_ptr(proc("test111.dll", INVALID_HANDLE_VALUE, 0), g_hSentinelModule);
184 /* Zero can be specified */
185 ok_ptr(proc("Something.mark", INVALID_HANDLE_VALUE, 0), g_h0);
186 /* Or default returned */
187 ok_ptr(proc("empty", INVALID_HANDLE_VALUE, 0), g_h0);
188
189 /* Paths, do not have to be valid */
190 ok_ptr(proc("\\test123.dll", INVALID_HANDLE_VALUE, 0), g_h123);
191 ok_ptr(proc("/test123.dll", INVALID_HANDLE_VALUE, 0), g_h123);
192 ok_ptr(proc("\\\\\\\\test123.dll", INVALID_HANDLE_VALUE, 0), g_h123);
193 ok_ptr(proc("////test123.dll", INVALID_HANDLE_VALUE, 0), g_h123);
194 ok_ptr(proc("mypath:something\\does\\not\\matter\\test123.dll", INVALID_HANDLE_VALUE, 0), g_h123);
195 ok_ptr(proc("/put/whatever/you/want/here/test123.dll", INVALID_HANDLE_VALUE, 0), g_h123);
196
197 /* path separator is checked, not just any point in the path */
198 ok_ptr(proc("-test123.dll", INVALID_HANDLE_VALUE, 0), g_hSentinelModule);
199 ok_ptr(proc("test123.dll-", INVALID_HANDLE_VALUE, 0), g_hSentinelModule);
200
201 dwErrorMode = GetErrorMode();
202 ok(dwErrorMode == dwOldErrorMode, "ErrorMode changed, was 0x%x, is 0x%x\n", dwOldErrorMode, dwErrorMode);
203 }
204
205 static void test_LoadLibraryExW(PHOOKAPI hook)
206 {
207 LOADLIBRARYEXWPROC proc;
208 DWORD dwErrorMode, dwOldErrorMode;
209
210 hook->OriginalFunction = my_LoadLibraryExW;
211 proc = hook->ReplacementFunction;
212
213 dwOldErrorMode = GetErrorMode();
214
215 /* Exact names return what is specified */
216 ok_ptr(proc(L"test123.dll", INVALID_HANDLE_VALUE, 0), g_h123);
217 ok_ptr(proc(L"test111", INVALID_HANDLE_VALUE, 0), g_h111);
218 /* Extension is not added */
219 ok_ptr(proc(L"test111.dll", INVALID_HANDLE_VALUE, 0), g_hSentinelModule);
220 /* Zero can be specified */
221 ok_ptr(proc(L"Something.mark", INVALID_HANDLE_VALUE, 0), g_h0);
222 /* Or default returned */
223 ok_ptr(proc(L"empty", INVALID_HANDLE_VALUE, 0), g_h0);
224
225 /* Paths, do not have to be valid */
226 ok_ptr(proc(L"\\test123.dll", INVALID_HANDLE_VALUE, 0), g_h123);
227 ok_ptr(proc(L"/test123.dll", INVALID_HANDLE_VALUE, 0), g_h123);
228 ok_ptr(proc(L"\\\\\\\\test123.dll", INVALID_HANDLE_VALUE, 0), g_h123);
229 ok_ptr(proc(L"////test123.dll", INVALID_HANDLE_VALUE, 0), g_h123);
230 ok_ptr(proc(L"mypath:something\\does\\not\\matter\\test123.dll", INVALID_HANDLE_VALUE, 0), g_h123);
231 ok_ptr(proc(L"/put/whatever/you/want/here/test123.dll", INVALID_HANDLE_VALUE, 0), g_h123);
232
233 /* path separator is checked, not just any point in the path */
234 ok_ptr(proc(L"-test123.dll", INVALID_HANDLE_VALUE, 0), g_hSentinelModule);
235 ok_ptr(proc(L"test123.dll-", INVALID_HANDLE_VALUE, 0), g_hSentinelModule);
236
237 dwErrorMode = GetErrorMode();
238 ok(dwErrorMode == dwOldErrorMode, "ErrorMode changed, was 0x%x, is 0x%x\n", dwOldErrorMode, dwErrorMode);
239 }
240
241 /* versionlie.c */
242 DWORD get_host_winver(void);
243
244 START_TEST(ignoreloadlib)
245 {
246 DWORD num_shims = 0, n, dwErrorMode;
247 PHOOKAPI hook;
248
249 g_WinVersion = get_host_winver();
250
251 if (g_WinVersion < _WIN32_WINNT_WIN8)
252 pGetHookAPIs = LoadShimDLL2(L"aclayers.dll");
253 else
254 pGetHookAPIs = LoadShimDLL2(L"acgenral.dll");
255
256 if (!pGetHookAPIs)
257 {
258 skip("GetHookAPIs not found\n");
259 return;
260 }
261
262 hook = pGetHookAPIs("test123.dll:123;test111:111;Something.mark:0;empty", L"IgnoreLoadLibrary", &num_shims);
263
264 ok(hook != NULL, "Expected hook to be a valid pointer\n");
265 ok(num_shims == 4, "Expected num_shims to be 0, was: %u\n", num_shims);
266
267 if (!hook || num_shims != 4)
268 return;
269
270 dwErrorMode = GetErrorMode();
271 trace("Error mode: 0x%x\n", dwErrorMode);
272
273 for (n = 0; n < num_shims; ++n)
274 {
275 ok_str(hook[n].LibraryName, "KERNEL32.DLL");
276 if (!_stricmp(hook[n].FunctionName, "LoadLibraryA"))
277 {
278 ok_int(n, 0);
279 test_LoadLibraryA(hook + n);
280 }
281 else if (!_stricmp(hook[n].FunctionName, "LoadLibraryExA"))
282 {
283 ok_int(n, 1);
284 test_LoadLibraryExA(hook + n);
285 }
286 else if (!_stricmp(hook[n].FunctionName, "LoadLibraryW"))
287 {
288 ok_int(n, 2);
289 test_LoadLibraryW(hook + n);
290 }
291 else if (!_stricmp(hook[n].FunctionName, "LoadLibraryExW"))
292 {
293 ok_int(n, 3);
294 test_LoadLibraryExW(hook + n);
295 }
296 else
297 {
298 ok(0, "Unknown function %s\n", hook[n].FunctionName);
299 }
300 }
301 }