1 /*
2 * PROJECT: ReactOS API tests
3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Tests for delayload
5 * PROGRAMMER: Mark Jansen
6 */
7
8 #include <apitest.h>
9
10 #include <apitest.h>
11 #include <strsafe.h>
12 #include <delayimp.h>
13
14 /* Some libraries to test against */
15 #include <mmsystem.h>
16 #include <winver.h>
17 #include <shlwapi.h>
18 #include <intshcut.h>
19 #include <sfc.h>
20 #include <imagehlp.h>
21 #include <mmddk.h>
22
23 #include <pseh/pseh2.h>
24
25 /* Compatibility with the MS defines */
26
27 #ifndef FACILITY_VISUALCPP
28 #define FACILITY_VISUALCPP ((LONG)0x6d)
29 #endif
30
31 #ifndef VcppException
32 #define VcppException(sev,err) ((sev) | (FACILITY_VISUALCPP<<16) | err)
33 #endif
34
35 #ifdef __REACTOS__
36 #define WINMM_DLLNAME "winmm.dll"
37 #else
38 #define WINMM_DLLNAME "WINMM.dll"
39 #endif
40
41 bool g_BreakFunctionName = false;
42 bool g_BrokenFunctionName = false;
43 bool g_BypassMost = false;
44 bool g_ExceptionIsModule = false;
45 bool g_ImportByName = true;
46 const char* g_ExpectedDll = NULL;
47 const char* g_ExpectedName = NULL;
48 char g_Target[100] = { 0 };
49
target(PDelayLoadInfo pdli)50 char* target(PDelayLoadInfo pdli)
51 {
52 if (g_Target[0] == '\0' && pdli)
53 {
54 if (pdli->dlp.fImportByName)
55 sprintf(g_Target, "%s!%s", pdli->szDll, pdli->dlp.szProcName);
56 else
57 sprintf(g_Target, "%s!#%lu", pdli->szDll, pdli->dlp.dwOrdinal);
58 }
59 return g_Target;
60 }
61
62
63 struct UnProtect
64 {
UnProtectUnProtect65 UnProtect(PVOID addr)
66 :mAddr(NULL), mProt(0)
67 {
68 if (IsBadWritePtr(addr, 1))
69 {
70 mAddr = addr;
71 VirtualProtect(addr, 1, PAGE_EXECUTE_READWRITE, &mProt);
72 }
73 }
~UnProtectUnProtect74 ~UnProtect()
75 {
76 DWORD dwOld;
77 if (mAddr)
78 VirtualProtect(mAddr, 1, mProt, &dwOld);
79 }
80
81 PVOID mAddr;
82 DWORD mProt;
83 };
84
85
86 unsigned* g_DliHookExpected = NULL;
87 size_t g_DliHookIndex = 0;
88 #define LAST_DLI 333
89
SetExpectedDli(unsigned * order)90 static void SetExpectedDli(unsigned* order)
91 {
92 g_DliHookExpected = order;
93 g_DliHookIndex = 0;
94 g_Target[0] = '\0';
95 }
96
CheckDli_imp(unsigned dliNotify,PDelayLoadInfo pdli,BOOL ErrorHandler)97 static void CheckDli_imp(unsigned dliNotify, PDelayLoadInfo pdli, BOOL ErrorHandler)
98 {
99 if (!g_DliHookExpected) return;
100
101 winetest_ok(dliNotify == g_DliHookExpected[g_DliHookIndex], "Expected dliNotify to be %u, was: %u for %s\n",
102 g_DliHookExpected[g_DliHookIndex], dliNotify, target(pdli));
103 if (ErrorHandler)
104 {
105 winetest_ok(dliNotify == dliFailGetProc || dliNotify == dliFailLoadLib,
106 "Expected code %u to be processed by the Hook, not the ErrorHandler for %s\n", dliNotify, target(pdli));
107 }
108 else
109 {
110 winetest_ok(dliNotify == dliStartProcessing || dliNotify == dliNotePreLoadLibrary ||
111 dliNotify == dliNotePreGetProcAddress || dliNotify == dliNoteEndProcessing,
112 "Expected code %u to be processed by the ErrorHandler, not the Hook for %s\n", dliNotify, target(pdli));
113 }
114 if (g_DliHookExpected[g_DliHookIndex] != LAST_DLI)
115 g_DliHookIndex++;
116 }
117
CheckDliDone_imp()118 static void CheckDliDone_imp()
119 {
120 if (!g_DliHookExpected) return;
121 winetest_ok(LAST_DLI == g_DliHookExpected[g_DliHookIndex],
122 "Expected g_DliHookExpected[g_DliHookIndex] to be %u, was: %u for %s\n",
123 LAST_DLI, g_DliHookExpected[g_DliHookIndex], target(NULL));
124 g_DliHookExpected = NULL;
125 g_Target[0] = '\0';
126 }
127
128 #define CheckDli (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : CheckDli_imp
129 #define CheckDliDone (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : CheckDliDone_imp
130
131
132 /* Replacement functions */
MyFunction()133 INT_PTR WINAPI MyFunction()
134 {
135 return 123;
136 }
137
MySfcIsKeyProtected(HKEY KeyHandle,LPCWSTR SubKeyName,REGSAM KeySam)138 BOOL WINAPI MySfcIsKeyProtected(HKEY KeyHandle, LPCWSTR SubKeyName, REGSAM KeySam)
139 {
140 return 12345;
141 }
142
143
144 static HMODULE g_VersionDll;
DliHook(unsigned dliNotify,PDelayLoadInfo pdli)145 FARPROC WINAPI DliHook(unsigned dliNotify, PDelayLoadInfo pdli)
146 {
147 ok(pdli && pdli->cb >= 36, "Expected a valid pointer with a struct that is big enough: %p, %lu\n",
148 pdli, pdli ? pdli->cb : 0u);
149 if (!pdli || pdli->cb < 36) return NULL;
150
151 CheckDli(dliNotify, pdli, FALSE);
152
153 if (g_BreakFunctionName && pdli->dlp.fImportByName)
154 {
155 g_BreakFunctionName = false;
156 g_BrokenFunctionName = true;
157 char* procname = (char*)pdli->dlp.szProcName;
158 UnProtect prot(procname);
159 char c = procname[0];
160 procname[0] = isupper(c) ? tolower(c) : toupper(c);
161 }
162
163 /* Validate dll name when required */
164 if (g_ExpectedDll && g_ExpectedName && !g_BrokenFunctionName)
165 {
166 ok(!strcmp(g_ExpectedDll, pdli->szDll), "Expected szDll to be '%s', but was: '%s'\n", g_ExpectedDll, pdli->szDll);
167 ok(pdli->dlp.fImportByName, "Expected import by name (%s!%s)\n", g_ExpectedDll, g_ExpectedName);
168 if (pdli->dlp.fImportByName)
169 {
170 ok(!strcmp(g_ExpectedName, pdli->dlp.szProcName), "Expected szProcName to be '%s', but was: '%s'\n",
171 g_ExpectedName, pdli->dlp.szProcName);
172 }
173 }
174
175
176 if (dliNotify == dliStartProcessing)
177 {
178 /* Test loadlib fail */
179 if (!_stricmp(pdli->szDll, "sfc_os.dll"))
180 {
181 char* dll = (char*)pdli->szDll;
182 UnProtect u(dll);
183 dll[0] = 'l'; dll[1] = '_'; dll[2] = 'm';
184 }
185 if (!_stricmp(pdli->szDll, "imagehlp.dll"))
186 {
187 char* dll = (char*)pdli->szDll;
188 UnProtect u(dll);
189 dll[0] = 'x'; dll[1] = 'x'; dll[2] = 'x'; dll[3] = 'x'; dll[4] = 'x';
190 }
191 /* Test bypass */
192 if (!_stricmp(pdli->szDll, "dbghelp.dll"))
193 return MyFunction;
194 }
195 else if (dliNotify == dliNotePreLoadLibrary)
196 {
197 /* Show that this value is actually used! */
198 if (!_stricmp(pdli->szDll, "version.dll"))
199 {
200 g_VersionDll = LoadLibraryA("version.dll");
201 return (FARPROC)1;
202 }
203
204 }
205 else if (dliNotify == dliNotePreGetProcAddress)
206 {
207 if (pdli->dlp.fImportByName && !strcmp(pdli->dlp.szProcName, "SfcIsKeyProtected"))
208 {
209 return (FARPROC)MySfcIsKeyProtected;
210 }
211 }
212
213 /* Parameter validation */
214 ok(pdli->ppfn != NULL, "Expected ppfn to be valid, was NULL for %s\n", target(pdli));
215 ok(pdli->szDll != NULL, "Expected szDll to be valid, was NULL for %s\n", target(pdli));
216 ok(pdli->dwLastError == ERROR_SUCCESS,
217 "Expected dwLastError to be ERROR_SUCCESS, was: %lu for %s\n", pdli->dwLastError, target(pdli));
218 ok(g_ImportByName == !!pdli->dlp.fImportByName, "Expected pdli->dlp.fImportByName to equal g_ImportByname\n");
219 if (pdli->dlp.fImportByName)
220 ok(pdli->dlp.szProcName != NULL, "Expected szProcName to be valid, was NULL for %s\n", target(pdli));
221 else
222 ok(pdli->dlp.dwOrdinal != 0, "Expected dwOrdinal to be valid, was NULL for %s\n", target(pdli));
223 switch(dliNotify)
224 {
225 case dliStartProcessing:
226 ok(pdli->hmodCur == NULL, "Expected hmodCur to be NULL, was: %p for %s\n", pdli->hmodCur, target(pdli));
227 ok(pdli->pfnCur == NULL, "Expected pfnCur to be NULL, was: %p for %s\n", pdli->pfnCur, target(pdli));
228 break;
229 case dliNotePreLoadLibrary:
230 ok(pdli->hmodCur == NULL, "Expected hmodCur to be NULL, was: %p for %s\n", pdli->hmodCur, target(pdli));
231 ok(pdli->pfnCur == NULL, "Expected pfnCur to be NULL, was: %p for %s\n", pdli->pfnCur, target(pdli));
232 break;
233 case dliNotePreGetProcAddress:
234 ok(pdli->hmodCur != NULL, "Expected hmodCur to be valid, was NULL for %s\n", target(pdli));
235 ok(pdli->pfnCur == NULL, "Expected pfnCur to be NULL, was: %p for %s\n", pdli->pfnCur, target(pdli));
236 break;
237 case dliNoteEndProcessing:
238 if (!g_BypassMost)
239 ok(pdli->hmodCur != NULL, "Expected hmodCur to be valid, was NULL for %s\n", target(pdli));
240 ok(pdli->pfnCur != NULL, "Expected pfnCur to be a valid pointer, was NULL for %s\n", target(pdli));
241 if (g_ExpectedDll && g_ExpectedName && !g_BrokenFunctionName)
242 {
243 FARPROC targetProc = GetProcAddress(GetModuleHandleA(g_ExpectedDll), g_ExpectedName);
244 ok(targetProc != NULL, "This should not happen, the function i need is unavail! (%s!%s)\n",
245 g_ExpectedDll, g_ExpectedName);
246 ok(targetProc == pdli->pfnCur, "Expected pfnCur to be %p, was %p for %s\n", targetProc, pdli->pfnCur, target(pdli));
247 ok(pdli->ppfn && targetProc == *pdli->ppfn,
248 "Expected ppfn to be valid and to result in %p, was: %p(%p) for %s\n",
249 target, pdli->ppfn, pdli->ppfn ? *pdli->ppfn : NULL, target(pdli));
250 }
251 break;
252 default:
253 break;
254 }
255 return NULL;
256 }
257
DliFailHook(unsigned dliNotify,PDelayLoadInfo pdli)258 FARPROC WINAPI DliFailHook(unsigned dliNotify, PDelayLoadInfo pdli)
259 {
260 ok(pdli && pdli->cb >= 36,
261 "Expected a valid pointer with a struct that is big enough: %p, %lu\n", pdli, pdli ? pdli->cb : 0u);
262 if (!pdli || pdli->cb < 36) return NULL;
263
264 CheckDli(dliNotify, pdli, TRUE);
265
266 /* Redirections / fixes */
267 if (dliNotify == dliFailLoadLib)
268 {
269 if (!_stricmp(pdli->szDll, "l_m_os.dll"))
270 return (FARPROC)LoadLibraryA("sfc_os.dll");
271 }
272 else if (dliNotify == dliFailGetProc)
273 {
274 if (pdli->dlp.fImportByName && pdli->hmodCur == (HMODULE)1)
275 {
276 return GetProcAddress(g_VersionDll, pdli->dlp.szProcName);
277 }
278 }
279
280 /* Parameter validation */
281 ok(pdli->ppfn != NULL, "Expected ppfn to be valid, was NULL for %s\n", target(pdli));
282 ok(pdli->szDll != NULL, "Expected szDll to be valid, was NULL for %s\n", target(pdli));
283 if (pdli->dlp.fImportByName)
284 ok(pdli->dlp.szProcName != NULL, "Expected szProcName to be valid, was NULL for %s\n", target(pdli));
285 else
286 ok(pdli->dlp.dwOrdinal != 0, "Expected dwOrdinal to be valid, was NULL for %s\n", target(pdli));
287 switch(dliNotify)
288 {
289 case dliFailLoadLib:
290 ok(pdli->hmodCur == NULL, "Expected hmodCur to be NULL, was: %p for %s\n", pdli->hmodCur, target(pdli));
291 ok(pdli->pfnCur == NULL, "Expected pfnCur to be NULL, was: %p for %s\n", pdli->pfnCur, target(pdli));
292 ok(pdli->dwLastError == ERROR_MOD_NOT_FOUND,
293 "Expected dwLastError to be ERROR_MOD_NOT_FOUND, was: %lu for %s\n", pdli->dwLastError, target(pdli));
294 break;
295 case dliFailGetProc:
296 ok(pdli->hmodCur != NULL, "Expected hmodCur to be valid, was NULL for %s\n", target(pdli));
297 ok(pdli->pfnCur == NULL, "Expected pfnCur to be NULL, was: %p for %s\n", pdli->pfnCur, target(pdli));
298 ok(pdli->dwLastError == ERROR_PROC_NOT_FOUND,
299 "Expected dwLastError to be ERROR_PROC_NOT_FOUND, was: %lu for %s\n", pdli->dwLastError, target(pdli));
300 break;
301 }
302
303 return NULL;
304 }
305
306
ExceptionFilter(IN PEXCEPTION_POINTERS ExceptionInfo,ULONG ExceptionCode)307 LONG ExceptionFilter(IN PEXCEPTION_POINTERS ExceptionInfo, ULONG ExceptionCode)
308 {
309 DWORD expected = VcppException(ERROR_SEVERITY_ERROR, (g_ExceptionIsModule ? ERROR_MOD_NOT_FOUND : ERROR_PROC_NOT_FOUND));
310 ok(ExceptionCode == expected, "Expected code to be 0x%lx, was: 0x%lx\n", expected, ExceptionCode);
311 ok(ExceptionInfo != NULL, "Expected to get exception info\n");
312 ok(ExceptionInfo->ExceptionRecord != NULL, "Expected to get a valid record info\n");
313
314 if (ExceptionCode != expected)
315 {
316 skip("Skipping other checks, this was not the exception we expected!\n");
317 return EXCEPTION_EXECUTE_HANDLER;
318 }
319
320 if (ExceptionInfo && ExceptionInfo->ExceptionRecord)
321 {
322 PEXCEPTION_RECORD ExceptionRecord = ExceptionInfo->ExceptionRecord;
323 ok(ExceptionRecord->ExceptionCode == expected, "Expected ExceptionCode to be 0x%lx, was 0x%lx\n",
324 expected, ExceptionRecord->ExceptionCode);
325 /* We can still continue. */
326 ok(ExceptionRecord->ExceptionFlags == 0, "Expected ExceptionFlags to be 0, was: 0x%lx\n",
327 ExceptionRecord->ExceptionFlags);
328 ok(ExceptionRecord->NumberParameters == 1, "Expected 1 parameter, got %lu\n",
329 ExceptionRecord->NumberParameters);
330 if (ExceptionRecord->NumberParameters == 1)
331 {
332 PDelayLoadInfo LoadInfo = (PDelayLoadInfo)ExceptionRecord->ExceptionInformation[0];
333 ok(LoadInfo && LoadInfo->cb >= 36, "Expected a valid pointer with a struct that is big enough: %p, %lu\n",
334 LoadInfo, LoadInfo ? LoadInfo->cb : 0);
335
336 if (g_ExpectedDll)
337 ok(!strcmp(g_ExpectedDll, LoadInfo->szDll), "Expected szDll to be '%s', but was: '%s'\n",
338 g_ExpectedDll, LoadInfo->szDll);
339 if (g_ExpectedName)
340 {
341 ok(LoadInfo->dlp.fImportByName, "Expected import by name\n");
342 if (LoadInfo->dlp.fImportByName)
343 {
344 ok(!strcmp(g_ExpectedName, LoadInfo->dlp.szProcName),
345 "Expected szProcName to be '%s', but was: '%s'\n", g_ExpectedName, LoadInfo->dlp.szProcName);
346
347 if (g_ExceptionIsModule)
348 {
349 HMODULE mod = LoadLibraryA("imagehlp.dll");
350 LoadInfo->pfnCur = GetProcAddress(mod, g_ExpectedName);
351 }
352 else
353 {
354 char buf[100];
355 char first = isupper(g_ExpectedName[0]) ? tolower(g_ExpectedName[0]) : toupper(g_ExpectedName[0]);
356 sprintf(buf, "%c%s", first, g_ExpectedName + 1);
357 LoadInfo->pfnCur = GetProcAddress(GetModuleHandleA(g_ExpectedDll), buf);
358 }
359 return LoadInfo->pfnCur ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER;
360 }
361 }
362 }
363 }
364
365 return EXCEPTION_EXECUTE_HANDLER;
366 }
367
368 /* We register one hook the 'default' way and one manually,
369 so that we can check that both fallback and registration work*/
370 extern "C"
371 {
372 extern PfnDliHook __pfnDliNotifyHook2;
373 //PfnDliHook __pfnDliFailureHook2 = DliFailHook;
374 }
375
376
377 bool g_UsePointers = false;
378
379 template<typename PTR>
Rva2Addr(PIMAGE_DOS_HEADER dos,RVA rva)380 PTR Rva2Addr(PIMAGE_DOS_HEADER dos, RVA rva)
381 {
382 /* Old delayload type */
383 if (g_UsePointers)
384 return reinterpret_cast<PTR>(rva);
385 return reinterpret_cast<PTR>((reinterpret_cast<PBYTE>(dos) + rva));
386 }
387
388
389 unsigned g_winmm_get_cur_task[] = { dliStartProcessing, dliNotePreLoadLibrary, dliNotePreGetProcAddress, dliNoteEndProcessing, LAST_DLI };
390 unsigned g_winmm_midi_out_close[] = { dliStartProcessing, dliNotePreGetProcAddress, dliNoteEndProcessing, LAST_DLI };
391 unsigned g_winmm_mide_in_close[] = { dliStartProcessing, dliNotePreGetProcAddress, dliFailGetProc, dliNoteEndProcessing, LAST_DLI };
392 unsigned g_sfc_key[] = { dliStartProcessing, dliNotePreLoadLibrary, dliFailLoadLib, dliNotePreGetProcAddress, dliNoteEndProcessing, LAST_DLI };
393 unsigned g_sfc_file[] = { dliStartProcessing, dliNotePreGetProcAddress, dliNoteEndProcessing, LAST_DLI };
394 unsigned g_version_a[] = { dliStartProcessing, dliNotePreLoadLibrary, dliNotePreGetProcAddress, dliFailGetProc, dliNoteEndProcessing, LAST_DLI };
395 unsigned g_version_w[] = { dliStartProcessing, dliNotePreGetProcAddress, dliFailGetProc, dliNoteEndProcessing, LAST_DLI };
396 unsigned g_scard[] = { dliStartProcessing, dliNoteEndProcessing, LAST_DLI };
397 unsigned g_shlwapi[] = { dliStartProcessing, dliNotePreLoadLibrary, dliNotePreGetProcAddress, dliNoteEndProcessing, LAST_DLI };
398 unsigned g_imagehlp[] = { dliStartProcessing, dliNotePreLoadLibrary, dliFailLoadLib, LAST_DLI }; /* This exception does not fire EndProcessing! */
399
400
401 //#define DELAYLOAD_SUPPORTS_UNLOADING
START_TEST(delayimp)402 START_TEST(delayimp)
403 {
404 __pfnDliNotifyHook2 = DliHook;
405 /* Verify that both scenario's work */
406 ok(__pfnDliNotifyHook2 == DliHook, "Expected __pfnDliNotifyHook2 to be DliHook(%p), but was: %p\n",
407 DliHook, __pfnDliNotifyHook2);
408 ok(__pfnDliFailureHook2 == NULL, "Expected __pfnDliFailureHook2 to be NULL, but was: %p\n",
409 __pfnDliFailureHook2);
410
411 __pfnDliFailureHook2 = DliFailHook;
412
413
414 PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)GetModuleHandle(NULL);
415
416 ok(dos->e_magic == IMAGE_DOS_SIGNATURE, "Expected a DOS header\n");
417 if (dos->e_magic != IMAGE_DOS_SIGNATURE)
418 return;
419
420 PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((PBYTE)dos + dos->e_lfanew);
421 PIMAGE_DATA_DIRECTORY delaydir = nt->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT;
422
423 /* Test some advanced features (loading / unloading) */
424 if (delaydir->Size != 0)
425 {
426 #if defined(_DELAY_IMP_VER) && _DELAY_IMP_VER == 2 && defined(DELAYLOAD_SUPPORTS_UNLOADING)
427 /* First, before mangling the delayload stuff, let's try some v2 functions */
428 HMODULE mod = GetModuleHandleA(WINMM_DLLNAME);
429 ok(mod == NULL, "Expected mod to be NULL, was %p\n", mod);
430 /* Now, a mistyped module (case sensitive!) */
431 HRESULT hr = __HrLoadAllImportsForDll("WiNmM.DlL");
432 ok(hr == HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND), "Expected hr to be HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND), was %lu\n", hr);
433 mod = GetModuleHandleA(WINMM_DLLNAME);
434 ok(mod == NULL, "Expected mod to be NULL, was %p\n", mod);
435
436 /* Let's load it */
437 hr = __HrLoadAllImportsForDll(WINMM_DLLNAME);
438 ok(hr == S_OK, "Expected hr to be S_OK, was %lu\n", hr);
439 mod = GetModuleHandleA(WINMM_DLLNAME);
440 ok(mod != NULL, "Expected mod to be valid, was NULL\n");
441
442 BOOL status = __FUnloadDelayLoadedDLL2(WINMM_DLLNAME);
443 ok(status == TRUE, "Expected __FUnloadDelayLoadedDLL2 to succeed\n");
444 mod = GetModuleHandleA(WINMM_DLLNAME);
445 ok(mod == NULL, "Expected mod to be NULL, was %p\n", mod);
446 #else
447 trace("Binary compiled without support for unloading\n");
448 #endif
449 }
450 else
451 {
452 skip("No IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT found, some advanced features might not work!\n");
453 }
454
455 /* Test the normal flow without a dll loaded */
456 SetExpectedDli(g_winmm_get_cur_task);
457 g_ExpectedDll = WINMM_DLLNAME;
458 g_ExpectedName = "mmGetCurrentTask";
459 DWORD task = mmGetCurrentTask();
460 ok(task == GetCurrentThreadId(), "Expected ret to be current thread id (0x%lx), was 0x%lx\n", GetCurrentThreadId(), task);
461 CheckDliDone();
462
463 /* Test the normal flow with a dll loaded */
464 SetExpectedDli(g_winmm_midi_out_close);
465 g_ExpectedDll = WINMM_DLLNAME;
466 g_ExpectedName = "midiOutClose";
467 DWORD err = midiOutClose((HMIDIOUT)(ULONG_PTR)0xdeadbeef);
468 ok(err == MMSYSERR_INVALHANDLE, "Expected err to be MMSYSERR_INVALHANDLE, was 0x%lx\n", err);
469 CheckDliDone();
470
471 /* Make sure GetProcAddress fails, also ignore the Failure hook, use the exception to set the address */
472 SetExpectedDli(g_winmm_mide_in_close);
473 g_ExpectedDll = WINMM_DLLNAME;
474 g_ExpectedName = "MixerClose";
475 g_BreakFunctionName = true;
476 _SEH2_TRY
477 {
478 err = mixerClose((HMIXER)(ULONG_PTR)0xdeadbeef);
479 }
480 _SEH2_EXCEPT(ExceptionFilter(_SEH2_GetExceptionInformation(), _SEH2_GetExceptionCode()))
481 {
482 err = _SEH2_GetExceptionCode();
483 }
484 _SEH2_END;
485 ok(err == MMSYSERR_INVALHANDLE, "Expected err to be MMSYSERR_INVALHANDLE, was 0x%lx\n", err);
486 CheckDliDone();
487 ok(g_BreakFunctionName == false, "Expected the functionname to be changed\n");
488
489 /* Make the LoadLib fail, manually load the library in the Failure Hook,
490 Respond to the dliNotePreGetProcAddress with an alternate function address */
491 SetExpectedDli(g_sfc_key);
492 BOOL ret = SfcIsKeyProtected(NULL, NULL, NULL);
493 ok(ret == 12345, "Expected ret to be 12345, was %u\n", ret); /* The original function returns FALSE! */
494 CheckDliDone();
495
496 /* Show that it works with the manually returned dll */
497 SetExpectedDli(g_sfc_file);
498 ret = SfcGetNextProtectedFile(NULL, NULL);
499 ok(ret == FALSE, "Expected ret to be FALSE, was %u\n", ret);
500 CheckDliDone();
501
502 /* Return a fake dll handle, so that we can see when it is being used, and manually return a function in the Failure Hook */
503 SetExpectedDli(g_version_a);
504 ret = GetFileVersionInfoA(NULL, NULL, NULL, NULL);
505 ok(ret == FALSE, "Expected ret to be FALSE, was %u\n", ret);
506 CheckDliDone();
507
508 /* Manually return a function in the failure hook, when the module is the previously set bad one */
509 SetExpectedDli(g_version_w);
510 ret = GetFileVersionInfoW(NULL, NULL, NULL, NULL);
511 ok(ret == FALSE, "Expected ret to be FALSE, was %u\n", ret);
512 CheckDliDone();
513
514 if (HIWORD(SymGetOptions) == NULL)
515 {
516 skip("SymGetOptions until CORE-6504 is fixed\n");
517 }
518 else
519 {
520 /* Completely bypass most hooks, by directly replying with a function address */
521 SetExpectedDli(g_scard);
522 g_BypassMost = true;
523 DWORD opt = SymGetOptions();
524 g_BypassMost = false;
525 ok(opt == 123, "Expected opt to be 123, was %lu\n", opt); /* The original function returns ERROR_INVALID_HANDLE */
526 CheckDliDone();
527 }
528
529 /* Import by ordinal */
530 g_ImportByName = false;
531 SetExpectedDli(g_shlwapi);
532 PARSEDURLA pua = { sizeof(pua), 0 };
533 HRESULT hr = ParseURLA("", &pua);
534 ok(hr == URL_E_INVALID_SYNTAX, "Expected tmp to be URL_E_INVALID_SYNTAX, was %lx\n", hr);
535 CheckDliDone();
536 g_ImportByName = true;
537
538 /* Handle LoadLib failure with an exception handler */
539 if (HIWORD(MapAndLoad) == NULL)
540 {
541 skip("MapAndLoad until CORE-6504 is fixed\n");
542 }
543 else
544 {
545 SetExpectedDli(g_imagehlp);
546 LOADED_IMAGE img = {0};
547 ret = 123;
548 g_ExceptionIsModule = true;
549 g_ExpectedDll = "xxxxxhlp.dll";
550 g_ExpectedName = "MapAndLoad";
551 _SEH2_TRY
552 {
553 ret = MapAndLoad("some_not_existing_file.aabbcc", NULL, &img, FALSE, TRUE);
554 }
555 _SEH2_EXCEPT(ExceptionFilter(_SEH2_GetExceptionInformation(), _SEH2_GetExceptionCode()))
556 {
557 ;
558 }
559 _SEH2_END;
560 g_ExceptionIsModule = false;
561 ok(ret == FALSE, "Expected ret to be FALSE, was %u\n", ret);
562 CheckDliDone();
563 }
564 }
565