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 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 { 65 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 } 74 ~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 90 static void SetExpectedDli(unsigned* order) 91 { 92 g_DliHookExpected = order; 93 g_DliHookIndex = 0; 94 g_Target[0] = '\0'; 95 } 96 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 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 */ 133 INT_PTR WINAPI MyFunction() 134 { 135 return 123; 136 } 137 138 BOOL WINAPI MySfcIsKeyProtected(HKEY KeyHandle, LPCWSTR SubKeyName, REGSAM KeySam) 139 { 140 return 12345; 141 } 142 143 144 static HMODULE g_VersionDll; 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 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 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> 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 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