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