1 /* 2 * PROJECT: ReactOS api tests 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Test for dbghelp PDB functions 5 * COPYRIGHT: Copyright 2017-2019 Mark Jansen (mark.jansen@reactos.org) 6 */ 7 8 #include <ntstatus.h> 9 #define WIN32_NO_STATUS 10 #include <windows.h> 11 #include <dbghelp.h> 12 #include <cvconst.h> // SymTagXXX 13 #include <stdio.h> 14 #include <delayimp.h> 15 16 #include "wine/test.h" 17 18 extern PfnDliHook __pfnDliFailureHook2; 19 20 #define ok_ulonglong(expression, result) \ 21 do { \ 22 ULONG64 _value = (expression); \ 23 ULONG64 _result = (result); \ 24 ok(_value == (result), "Wrong value for '%s', expected: " #result " (%s), got: %s\n", \ 25 #expression, wine_dbgstr_longlong(_result), wine_dbgstr_longlong(_value)); \ 26 } while (0) 27 28 29 // data.c 30 void create_compressed_files(); 31 int extract_msvc_dll(char szFile[MAX_PATH], char szPath[MAX_PATH]); 32 void cleanup_msvc_dll(); 33 34 static HANDLE proc() 35 { 36 return GetCurrentProcess(); 37 } 38 39 static BOOL init_sym_imp(BOOL fInvadeProcess, const char* file, int line) 40 { 41 if (!SymInitialize(proc(), NULL, fInvadeProcess)) 42 { 43 DWORD err = GetLastError(); 44 ok_(file, line)(0, "Failed to init: 0x%x\n", err); 45 return FALSE; 46 } 47 return TRUE; 48 } 49 50 static void deinit_sym() 51 { 52 SymCleanup(proc()); 53 } 54 55 #define init_sym(fInvadeProcess) init_sym_imp(fInvadeProcess, __FILE__, __LINE__) 56 57 #define INIT_PSYM(buff) do { \ 58 memset((buff), 0, sizeof((buff))); \ 59 ((PSYMBOL_INFO)(buff))->SizeOfStruct = sizeof(SYMBOL_INFO); \ 60 ((PSYMBOL_INFO)(buff))->MaxNameLen = MAX_SYM_NAME; \ 61 } while (0) 62 63 /* modified copy of function from apitests/apphelp/apitest.c */ 64 BOOL get_module_version( 65 _In_ HMODULE mod, 66 _Out_ VS_FIXEDFILEINFO *fileinfo) 67 { 68 BOOL res = FALSE; 69 HRSRC hResInfo; 70 char *errmsg; 71 DWORD dwSize, errcode = 0; 72 UINT uLen; 73 HGLOBAL hResData = 0; 74 LPVOID pRes = NULL; 75 HLOCAL pResCopy = 0; 76 VS_FIXEDFILEINFO *lpFfi; 77 78 if (fileinfo == NULL) 79 { 80 errmsg = "fileinfo is NULL.\n"; 81 goto cleanup; 82 } 83 84 hResInfo = FindResource(mod, MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION); 85 if (hResInfo == 0) 86 { 87 errmsg = "FindResource failed"; 88 errcode = GetLastError(); 89 goto cleanup; 90 } 91 92 dwSize = SizeofResource(mod, hResInfo); 93 if (dwSize == 0) 94 { 95 errmsg = "SizeofResource failed"; 96 errcode = GetLastError(); 97 goto cleanup; 98 } 99 100 hResData = LoadResource(mod, hResInfo); 101 if (hResData == 0) 102 { 103 errmsg = "LoadResource failed"; 104 errcode = GetLastError(); 105 goto cleanup; 106 } 107 108 pRes = LockResource(hResData); 109 if (pRes == NULL) 110 { 111 errmsg = "LockResource failed"; 112 errcode = GetLastError(); 113 goto cleanup; 114 } 115 116 pResCopy = LocalAlloc(LMEM_FIXED, dwSize); 117 if (pResCopy == NULL) 118 { 119 errmsg = "LocalAlloc failed"; 120 errcode = GetLastError(); 121 goto cleanup; 122 } 123 124 CopyMemory(pResCopy, pRes, dwSize); 125 126 if (VerQueryValueW(pResCopy, L"\\", (LPVOID*)&lpFfi, &uLen)) 127 { 128 *fileinfo = *lpFfi; 129 res = TRUE; 130 } 131 132 cleanup: 133 /* cleanup */ 134 if (hResData != 0) 135 FreeResource(hResData); 136 if (pResCopy != NULL) 137 LocalFree(pResCopy); 138 /* if it was good */ 139 if (res == TRUE) 140 return TRUE; 141 /* failure path */ 142 if (errcode == 0) 143 trace("get_module_version - %s.\n", errmsg); 144 else 145 trace("get_module_version - %s (lasterror %d).\n", errmsg, errcode); 146 return FALSE; 147 } 148 149 static VS_FIXEDFILEINFO dbghelpFileVer; 150 static void init_dbghelp_version() 151 { 152 LPAPI_VERSION v; 153 WCHAR filenameW[MAX_PATH + 1]; 154 HMODULE hDLL; 155 DWORD fileLen; 156 VS_FIXEDFILEINFO fileInfo; 157 158 memset(&dbghelpFileVer, 0, sizeof(dbghelpFileVer)); 159 160 /* get internal file version */ 161 v = ImagehlpApiVersion(); 162 if (v == NULL) 163 return; 164 165 /* get module file version */ 166 hDLL = GetModuleHandleW(L"dbghelp.dll"); 167 if (hDLL == 0) 168 { 169 ok(FALSE, "Dbghelp.dll is not loaded!\n"); 170 return; 171 } 172 if (!get_module_version(hDLL, &fileInfo)) 173 memset(&fileInfo, 0, sizeof(fileInfo)); 174 dbghelpFileVer = fileInfo; 175 176 /* get full file path */ 177 fileLen = GetModuleFileNameW(hDLL, filenameW, MAX_PATH + 1); 178 if (fileLen == 0) 179 { 180 ok(FALSE, "GetModuleFileNameW for dbghelp.dll failed!\n"); 181 return; 182 } 183 184 trace("Using %S\n", filenameW); 185 trace(" API-Version: %hu.%hu.%hu (%hu)\n", 186 v->MajorVersion, v->MinorVersion, v->Revision, v->Reserved); 187 188 trace(" Fileversion: %hu.%hu.%hu.%hu\n", 189 HIWORD(fileInfo.dwProductVersionMS), 190 LOWORD(fileInfo.dwProductVersionMS), 191 HIWORD(fileInfo.dwProductVersionLS), 192 LOWORD(fileInfo.dwProductVersionLS)); 193 } 194 195 static 196 int g_SymRegisterCallbackW64NotFound = 0; 197 198 static 199 BOOL WINAPI SymRegisterCallbackW64_Stub(HANDLE hProcess, PSYMBOL_REGISTERED_CALLBACK64 CallbackFunction, ULONG64 UserContext) 200 { 201 g_SymRegisterCallbackW64NotFound++; 202 return FALSE; 203 } 204 205 /* A delay-load failure hook will be called when resolving a delay-load dependency (dll or function) fails */ 206 FARPROC WINAPI DliFailHook(unsigned dliNotify, PDelayLoadInfo pdli) 207 { 208 /* Was the failure a function, and did we get info */ 209 if (dliNotify == dliFailGetProc && pdli) 210 { 211 /* Is it our function? */ 212 if (pdli->dlp.fImportByName && !strcmp(pdli->dlp.szProcName, "SymRegisterCallbackW64")) 213 { 214 /* Redirect execution to the stub */ 215 return (FARPROC)SymRegisterCallbackW64_Stub; 216 } 217 } 218 /* This is not the function you are looking for, continue default behavior (throw exception) */ 219 return NULL; 220 } 221 222 /* Maybe our dbghelp.dll is too old? */ 223 static BOOL supports_pdb(HANDLE hProc, DWORD64 BaseAddress) 224 { 225 IMAGEHLP_MODULE64 ModuleInfo; 226 BOOL Ret; 227 228 memset(&ModuleInfo, 0, sizeof(ModuleInfo)); 229 ModuleInfo.SizeOfStruct = sizeof(ModuleInfo); 230 Ret = SymGetModuleInfo64(hProc, BaseAddress, &ModuleInfo); 231 232 return Ret && ModuleInfo.SymType == SymPdb; 233 } 234 235 236 static void test_SymFromName(HANDLE hProc, DWORD64 BaseAddress) 237 { 238 BOOL Ret; 239 char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; 240 PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; 241 242 if (!supports_pdb(hProc, BaseAddress)) 243 { 244 skip("dbghelp.dll too old or cannot enumerate symbols!\n"); 245 } 246 else 247 { 248 INIT_PSYM(buffer); 249 Ret = SymFromName(hProc, "DllMain", pSymbol); 250 ok_int(Ret, TRUE); 251 ok_ulonglong(pSymbol->ModBase, BaseAddress); 252 ok_hex(pSymbol->Flags, 0); 253 ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); 254 ok_hex(pSymbol->Tag, SymTagFunction); 255 ok_str(pSymbol->Name, "DllMain"); 256 257 INIT_PSYM(buffer); 258 Ret = SymFromName(hProc, "_DllMain@12", pSymbol); 259 ok_int(Ret, TRUE); 260 ok_ulonglong(pSymbol->ModBase, BaseAddress); 261 ok_hex(pSymbol->Flags, 0x400000); // ?? 262 ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); 263 ok_hex(pSymbol->Tag, SymTagPublicSymbol); 264 ok_str(pSymbol->Name, "_DllMain@12"); 265 266 INIT_PSYM(buffer); 267 Ret = SymFromName(hProc, "FfsChkdsk", pSymbol); 268 ok_int(Ret, TRUE); 269 ok_ulonglong(pSymbol->ModBase, BaseAddress); 270 ok_hex(pSymbol->Flags, 0); 271 ok_ulonglong(pSymbol->Address, BaseAddress + 0x1040); 272 ok_hex(pSymbol->Tag, SymTagFunction); 273 ok_str(pSymbol->Name, "FfsChkdsk"); 274 275 INIT_PSYM(buffer); 276 Ret = SymFromName(hProc, "_FfsChkdsk@24", pSymbol); 277 ok_int(Ret, TRUE); 278 ok_ulonglong(pSymbol->ModBase, BaseAddress); 279 ok_hex(pSymbol->Flags, 0x400000); // ?? 280 ok_ulonglong(pSymbol->Address, BaseAddress + 0x1040); 281 ok_hex(pSymbol->Tag, SymTagPublicSymbol); 282 ok_str(pSymbol->Name, "_FfsChkdsk@24"); 283 284 INIT_PSYM(buffer); 285 Ret = SymFromName(hProc, "FfsFormat", pSymbol); 286 ok_int(Ret, TRUE); 287 ok_ulonglong(pSymbol->ModBase, BaseAddress); 288 ok_hex(pSymbol->Flags, 0); 289 ok_ulonglong(pSymbol->Address, BaseAddress + 0x1070); 290 ok_hex(pSymbol->Tag, SymTagFunction); 291 ok_str(pSymbol->Name, "FfsFormat"); 292 293 INIT_PSYM(buffer); 294 Ret = SymFromName(hProc, "_FfsFormat@24", pSymbol); 295 ok_int(Ret, TRUE); 296 ok_ulonglong(pSymbol->ModBase, BaseAddress); 297 ok_hex(pSymbol->Flags, 0x400000); // ?? 298 ok_ulonglong(pSymbol->Address, BaseAddress + 0x1070); 299 ok_hex(pSymbol->Tag, SymTagPublicSymbol); 300 ok_str(pSymbol->Name, "_FfsFormat@24"); 301 } 302 } 303 304 static void test_SymFromAddr(HANDLE hProc, DWORD64 BaseAddress) 305 { 306 BOOL Ret; 307 char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; 308 PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; 309 310 DWORD64 Displacement; 311 DWORD dwErr; 312 313 /* No address found before load address of module */ 314 Displacement = 0; 315 INIT_PSYM(buffer); 316 Ret = SymFromAddr(hProc, BaseAddress -1, &Displacement, pSymbol); 317 dwErr = GetLastError(); 318 ok_int(Ret, FALSE); 319 ok_hex(dwErr, ERROR_MOD_NOT_FOUND); 320 321 /* Right at the start of the module is recognized as the first symbol found */ 322 Displacement = 0; 323 INIT_PSYM(buffer); 324 Ret = SymFromAddr(hProc, BaseAddress, &Displacement, pSymbol); 325 ok_int(Ret, TRUE); 326 ok_ulonglong(Displacement, 0xffffffffffffffff); 327 ok_ulonglong(pSymbol->ModBase, BaseAddress); 328 ok_hex(pSymbol->Flags, 0); 329 ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); 330 ok_hex(pSymbol->Tag, SymTagFunction); 331 ok_str(pSymbol->Name, "DllMain"); 332 333 /* The actual first instruction of the function */ 334 Displacement = 0; 335 INIT_PSYM(buffer); 336 Ret = SymFromAddr(hProc, BaseAddress + 0x1010, &Displacement, pSymbol); 337 ok_int(Ret, TRUE); 338 ok_ulonglong(Displacement, 0); 339 ok_ulonglong(pSymbol->ModBase, BaseAddress); 340 ok_hex(pSymbol->Flags, 0); 341 ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); 342 ok_hex(pSymbol->Tag, SymTagFunction); 343 ok_str(pSymbol->Name, "DllMain"); 344 345 /* The last instruction in the function */ 346 Displacement = 0; 347 INIT_PSYM(buffer); 348 Ret = SymFromAddr(hProc, BaseAddress + 0x102D, &Displacement, pSymbol); 349 ok_int(Ret, TRUE); 350 ok_ulonglong(Displacement, 0x1d); 351 ok_ulonglong(pSymbol->ModBase, BaseAddress); 352 ok_hex(pSymbol->Flags, 0); 353 ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); 354 ok_hex(pSymbol->Tag, SymTagFunction); 355 ok_str(pSymbol->Name, "DllMain"); 356 357 /* The padding below the function */ 358 Displacement = 0; 359 INIT_PSYM(buffer); 360 Ret = SymFromAddr(hProc, BaseAddress + 0x102E, &Displacement, pSymbol); 361 ok_int(Ret, TRUE); 362 ok_ulonglong(Displacement, 0x1e); 363 ok_ulonglong(pSymbol->ModBase, BaseAddress); 364 ok_hex(pSymbol->Flags, 0); 365 ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); 366 ok_hex(pSymbol->Tag, SymTagFunction); 367 ok_str(pSymbol->Name, "DllMain"); 368 369 /* One byte before the next function */ 370 Displacement = 0; 371 INIT_PSYM(buffer); 372 Ret = SymFromAddr(hProc, BaseAddress + 0x103f, &Displacement, pSymbol); 373 ok_int(Ret, TRUE); 374 ok_ulonglong(Displacement, 0x2f); 375 ok_ulonglong(pSymbol->ModBase, BaseAddress); 376 ok_hex(pSymbol->Flags, 0); 377 ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); 378 ok_hex(pSymbol->Tag, SymTagFunction); 379 ok_str(pSymbol->Name, "DllMain"); 380 381 /* First byte of the next function */ 382 Displacement = 0; 383 INIT_PSYM(buffer); 384 Ret = SymFromAddr(hProc, BaseAddress + 0x1040, &Displacement, pSymbol); 385 ok_int(Ret, TRUE); 386 ok_ulonglong(Displacement, 0); 387 ok_ulonglong(pSymbol->ModBase, BaseAddress); 388 ok_hex(pSymbol->Flags, 0); 389 ok_ulonglong(pSymbol->Address, BaseAddress + 0x1040); 390 ok_hex(pSymbol->Tag, SymTagFunction); 391 ok_str(pSymbol->Name, "FfsChkdsk"); 392 393 if (!supports_pdb(hProc, BaseAddress)) 394 { 395 skip("dbghelp.dll too old or cannot read this symbol!\n"); 396 } 397 else 398 { 399 /* .idata */ 400 Displacement = 0; 401 INIT_PSYM(buffer); 402 Ret = SymFromAddr(hProc, BaseAddress + 0x2000, &Displacement, pSymbol); 403 ok_int(Ret, TRUE); 404 ok_ulonglong(Displacement, 0); 405 ok_ulonglong(pSymbol->ModBase, BaseAddress); 406 ok_hex(pSymbol->Flags, 0); 407 ok_ulonglong(pSymbol->Address, BaseAddress + 0x2000); 408 ok_hex(pSymbol->Tag, SymTagPublicSymbol); 409 ok_str(pSymbol->Name, "__imp__DbgPrint"); 410 } 411 } 412 413 typedef struct _test_context 414 { 415 DWORD64 BaseAddress; 416 SIZE_T Index; 417 } test_context; 418 419 static struct _test_data { 420 DWORD64 AddressOffset; 421 ULONG Size; 422 ULONG Tag; 423 const char* Name; 424 } test_data[] = { 425 /* TODO: Order is based on magic, should find entries based on name, and mark as 'seen' */ 426 { 0x1070, 36, SymTagFunction, "FfsFormat" }, 427 { 0x1010, 32, SymTagFunction, "DllMain" }, 428 { 0x1040, 36, SymTagFunction, "FfsChkdsk" }, 429 430 { 0x2100, 0, SymTagPublicSymbol, "__IMPORT_DESCRIPTOR_ntdll" }, 431 { 0x109a, 0, SymTagPublicSymbol, "_DbgPrint" }, 432 { 0x2004, 0, SymTagPublicSymbol, "\x7fntdll_NULL_THUNK_DATA" }, 433 { 0x2000, 0, SymTagPublicSymbol, "__imp__DbgPrint" }, 434 { 0x2114, 0, SymTagPublicSymbol, "__NULL_IMPORT_DESCRIPTOR" }, 435 }; 436 437 static BOOL CALLBACK EnumSymProc(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext) 438 { 439 test_context* ctx = UserContext; 440 441 if (ctx->Index < ARRAYSIZE(test_data)) 442 { 443 ok_ulonglong(pSymInfo->ModBase, ctx->BaseAddress); 444 ok_ulonglong(pSymInfo->Address, ctx->BaseAddress + test_data[ctx->Index].AddressOffset); 445 ok_hex(pSymInfo->Tag, test_data[ctx->Index].Tag); 446 ok_str(pSymInfo->Name, test_data[ctx->Index].Name); 447 448 ctx->Index++; 449 } 450 else 451 { 452 ok(0, "Out of bounds (%lu), max is: %i!\n", ctx->Index, ARRAYSIZE(test_data)); 453 } 454 455 return TRUE; 456 } 457 458 static void test_SymEnumSymbols(HANDLE hProc, DWORD64 BaseAddress) 459 { 460 BOOL Ret; 461 test_context ctx; 462 463 ctx.Index = 0; 464 ctx.BaseAddress = BaseAddress; 465 466 if (!supports_pdb(hProc, ctx.BaseAddress)) 467 { 468 skip("dbghelp.dll too old or cannot enumerate symbols!\n"); 469 } 470 else 471 { 472 Ret = SymEnumSymbols(hProc, ctx.BaseAddress, NULL, EnumSymProc, &ctx); 473 ok_int(Ret, TRUE); 474 ok_int(ctx.Index, ARRAYSIZE(test_data)); 475 } 476 } 477 478 typedef struct _symregcallback_context 479 { 480 UINT idx; 481 BOOL isANSI; 482 } symregcallback_context; 483 484 static struct _symregcallback_test_data { 485 ULONG ActionCode; 486 } symregcallback_test_data[] = { 487 { CBA_DEFERRED_SYMBOL_LOAD_CANCEL }, 488 { CBA_DEFERRED_SYMBOL_LOAD_START }, 489 { CBA_READ_MEMORY }, 490 { CBA_DEFERRED_SYMBOL_LOAD_PARTIAL }, 491 { CBA_DEFERRED_SYMBOL_LOAD_COMPLETE } 492 }; 493 494 static BOOL CALLBACK SymRegisterCallback64Proc( 495 HANDLE hProcess, 496 ULONG ActionCode, 497 ULONG64 CallbackData, 498 ULONG64 UserContext) 499 { 500 symregcallback_context *ctx; 501 ctx = (symregcallback_context*)(ULONG_PTR)UserContext; 502 503 if (ctx->idx > sizeof(symregcallback_test_data)) 504 { 505 ok(FALSE, "SymRegisterCallback64Proc: Too many calls.\n"); 506 } 507 else 508 { 509 ok(ActionCode == symregcallback_test_data[ctx->idx].ActionCode, 510 "ActionCode (idx %u) expected %u, got %u\n", 511 ctx->idx, symregcallback_test_data[ctx->idx].ActionCode, ActionCode); 512 } 513 ctx->idx++; 514 515 return FALSE; 516 } 517 518 static void test_SymRegCallback(HANDLE hProc, const char* szModuleName, BOOL testANSI) 519 { 520 BOOL Ret; 521 DWORD dwErr; 522 ULONG64 BaseAddress; 523 symregcallback_context ctx; 524 525 ctx.idx = 0; 526 ctx.isANSI = testANSI; 527 528 if (!init_sym(FALSE)) 529 return; 530 531 if (testANSI) 532 { 533 Ret = SymRegisterCallback64(hProc, SymRegisterCallback64Proc, (ULONG_PTR)&ctx); 534 } 535 else 536 { 537 Ret = SymRegisterCallbackW64(hProc, SymRegisterCallback64Proc, (ULONG_PTR)&ctx); 538 if (g_SymRegisterCallbackW64NotFound) 539 { 540 skip("SymRegisterCallbackW64 not found in dbghelp.dll\n"); 541 return; 542 } 543 } 544 545 ok_int(Ret, TRUE); 546 if (!Ret) 547 return; 548 549 SetLastError(ERROR_SUCCESS); 550 BaseAddress = SymLoadModule64(hProc, NULL, szModuleName, NULL, 0x600000, 0); 551 dwErr = GetLastError(); 552 553 ok_ulonglong(BaseAddress, 0x600000); 554 ok_hex(dwErr, ERROR_SUCCESS); 555 556 /* this is what we want to test ... we expect 5 calls */ 557 ok_int(ctx.idx, 5); 558 559 deinit_sym(); 560 } 561 562 START_TEST(pdb) 563 { 564 char szDllName[MAX_PATH]; 565 char szDllPath[MAX_PATH], szOldDir[MAX_PATH]; 566 HMODULE hMod; 567 DWORD64 BaseAddress; 568 DWORD dwErr, Options; 569 570 Options = SymGetOptions(); 571 Options &= ~(SYMOPT_UNDNAME); 572 //Options |= SYMOPT_DEBUG; 573 SymSetOptions(Options); 574 575 if (!extract_msvc_dll(szDllName, szDllPath)) 576 { 577 ok(0, "Failed extracting files\n"); 578 return; 579 } 580 581 init_dbghelp_version(); 582 583 /* Register the failure hook using the magic name '__pfnDliFailureHook2'. */ 584 __pfnDliFailureHook2 = DliFailHook; 585 586 if (init_sym(FALSE)) 587 { 588 SetLastError(ERROR_SUCCESS); 589 BaseAddress = SymLoadModule64(proc(), NULL, szDllName, NULL, 0x600000, 0); 590 dwErr = GetLastError(); 591 592 ok_ulonglong(BaseAddress, 0x600000); 593 ok_hex(dwErr, ERROR_SUCCESS); 594 595 if (BaseAddress == 0x600000) 596 { 597 trace("Module loaded by SymLoadModule64\n"); 598 test_SymFromName(proc(), BaseAddress); 599 test_SymFromAddr(proc(), BaseAddress); 600 test_SymEnumSymbols(proc(), BaseAddress); 601 } 602 603 deinit_sym(); 604 } 605 606 /* This needs to load the module by itself */ 607 test_SymRegCallback(proc(), szDllName, TRUE); 608 test_SymRegCallback(proc(), szDllName, FALSE); 609 610 hMod = LoadLibraryA(szDllName); 611 if (hMod) 612 { 613 BaseAddress = (DWORD64)(DWORD_PTR)hMod; 614 /* Make sure we can find the pdb */ 615 GetCurrentDirectoryA(_countof(szOldDir), szOldDir); 616 SetCurrentDirectoryA(szDllPath); 617 /* Invade process */ 618 if (init_sym(TRUE)) 619 { 620 trace("Module loaded by LoadLibraryA\n"); 621 test_SymFromName(proc(), BaseAddress); 622 test_SymFromAddr(proc(), BaseAddress); 623 test_SymEnumSymbols(proc(), BaseAddress); 624 625 deinit_sym(); 626 } 627 /* Restore working dir */ 628 SetCurrentDirectoryA(szOldDir); 629 630 FreeLibrary(hMod); 631 } 632 633 cleanup_msvc_dll(); 634 } 635