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