1 /* 2 * PROJECT: ReactOS api tests 3 * LICENSE: GPLv2+ - See COPYING in the top level directory 4 * PURPOSE: Test for dbghelp PDB functions 5 * PROGRAMMER: Mark Jansen 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_exe(char szFile[MAX_PATH]); 30 void cleanup_msvc_exe(); 31 32 static HANDLE proc() 33 { 34 return GetCurrentProcess(); 35 } 36 37 static BOOL init_sym_imp(const char* file, int line) 38 { 39 if (!SymInitialize(proc(), NULL, FALSE)) 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() init_sym_imp(__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 can_enumerate(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, const char* szModuleName) 239 { 240 BOOL Ret; 241 char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; 242 PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; 243 244 DWORD64 BaseAddress; 245 DWORD dwErr; 246 247 if (!init_sym()) 248 return; 249 250 SetLastError(ERROR_SUCCESS); 251 BaseAddress = SymLoadModule64(hProc, NULL, szModuleName, NULL, 0x600000, 0); 252 dwErr = GetLastError(); 253 254 ok_ulonglong(BaseAddress, 0x600000); 255 ok_hex(dwErr, ERROR_SUCCESS); 256 257 if (!can_enumerate(hProc, BaseAddress)) 258 { 259 skip("dbghelp.dll too old or cannot enumerate symbols!\n"); 260 } 261 else 262 { 263 INIT_PSYM(buffer); 264 Ret = SymFromName(hProc, "DllMain", pSymbol); 265 ok_int(Ret, TRUE); 266 ok_ulonglong(pSymbol->ModBase, BaseAddress); 267 ok_hex(pSymbol->Flags, 0); 268 ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); 269 ok_hex(pSymbol->Tag, SymTagFunction); 270 ok_str(pSymbol->Name, "DllMain"); 271 272 INIT_PSYM(buffer); 273 Ret = SymFromName(hProc, "_DllMain@12", pSymbol); 274 ok_int(Ret, TRUE); 275 ok_ulonglong(pSymbol->ModBase, BaseAddress); 276 ok_hex(pSymbol->Flags, 0x400000); // ?? 277 ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); 278 ok_hex(pSymbol->Tag, SymTagPublicSymbol); 279 ok_str(pSymbol->Name, "_DllMain@12"); 280 281 INIT_PSYM(buffer); 282 Ret = SymFromName(hProc, "FfsChkdsk", pSymbol); 283 ok_int(Ret, TRUE); 284 ok_ulonglong(pSymbol->ModBase, BaseAddress); 285 ok_hex(pSymbol->Flags, 0); 286 ok_ulonglong(pSymbol->Address, BaseAddress + 0x1040); 287 ok_hex(pSymbol->Tag, SymTagFunction); 288 ok_str(pSymbol->Name, "FfsChkdsk"); 289 290 INIT_PSYM(buffer); 291 Ret = SymFromName(hProc, "_FfsChkdsk@24", pSymbol); 292 ok_int(Ret, TRUE); 293 ok_ulonglong(pSymbol->ModBase, BaseAddress); 294 ok_hex(pSymbol->Flags, 0x400000); // ?? 295 ok_ulonglong(pSymbol->Address, BaseAddress + 0x1040); 296 ok_hex(pSymbol->Tag, SymTagPublicSymbol); 297 ok_str(pSymbol->Name, "_FfsChkdsk@24"); 298 299 INIT_PSYM(buffer); 300 Ret = SymFromName(hProc, "FfsFormat", pSymbol); 301 ok_int(Ret, TRUE); 302 ok_ulonglong(pSymbol->ModBase, BaseAddress); 303 ok_hex(pSymbol->Flags, 0); 304 ok_ulonglong(pSymbol->Address, BaseAddress + 0x1070); 305 ok_hex(pSymbol->Tag, SymTagFunction); 306 ok_str(pSymbol->Name, "FfsFormat"); 307 308 INIT_PSYM(buffer); 309 Ret = SymFromName(hProc, "_FfsFormat@24", pSymbol); 310 ok_int(Ret, TRUE); 311 ok_ulonglong(pSymbol->ModBase, BaseAddress); 312 ok_hex(pSymbol->Flags, 0x400000); // ?? 313 ok_ulonglong(pSymbol->Address, BaseAddress + 0x1070); 314 ok_hex(pSymbol->Tag, SymTagPublicSymbol); 315 ok_str(pSymbol->Name, "_FfsFormat@24"); 316 } 317 318 deinit_sym(); 319 } 320 321 static void test_SymFromAddr(HANDLE hProc, const char* szModuleName) 322 { 323 BOOL Ret; 324 char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; 325 PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; 326 327 DWORD64 BaseAddress, Displacement; 328 DWORD dwErr; 329 330 if (!init_sym()) 331 return; 332 333 SetLastError(ERROR_SUCCESS); 334 BaseAddress = SymLoadModule64(hProc, NULL, szModuleName, NULL, 0x600000, 0); 335 dwErr = GetLastError(); 336 337 ok_ulonglong(BaseAddress, 0x600000); 338 ok_hex(dwErr, ERROR_SUCCESS); 339 340 /* No address found before load address of module */ 341 Displacement = 0; 342 INIT_PSYM(buffer); 343 Ret = SymFromAddr(hProc, BaseAddress -1, &Displacement, pSymbol); 344 dwErr = GetLastError(); 345 ok_int(Ret, FALSE); 346 ok_hex(dwErr, ERROR_MOD_NOT_FOUND); 347 348 /* Right at the start of the module is recognized as the first symbol found */ 349 Displacement = 0; 350 INIT_PSYM(buffer); 351 Ret = SymFromAddr(hProc, BaseAddress, &Displacement, pSymbol); 352 ok_int(Ret, TRUE); 353 ok_ulonglong(Displacement, 0xffffffffffffffff); 354 ok_ulonglong(pSymbol->ModBase, BaseAddress); 355 ok_hex(pSymbol->Flags, 0); 356 ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); 357 ok_hex(pSymbol->Tag, SymTagFunction); 358 ok_str(pSymbol->Name, "DllMain"); 359 360 /* The actual first instruction of the function */ 361 Displacement = 0; 362 INIT_PSYM(buffer); 363 Ret = SymFromAddr(hProc, BaseAddress + 0x1010, &Displacement, pSymbol); 364 ok_int(Ret, TRUE); 365 ok_ulonglong(Displacement, 0); 366 ok_ulonglong(pSymbol->ModBase, BaseAddress); 367 ok_hex(pSymbol->Flags, 0); 368 ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); 369 ok_hex(pSymbol->Tag, SymTagFunction); 370 ok_str(pSymbol->Name, "DllMain"); 371 372 /* The last instruction in the function */ 373 Displacement = 0; 374 INIT_PSYM(buffer); 375 Ret = SymFromAddr(hProc, BaseAddress + 0x102D, &Displacement, pSymbol); 376 ok_int(Ret, TRUE); 377 ok_ulonglong(Displacement, 0x1d); 378 ok_ulonglong(pSymbol->ModBase, BaseAddress); 379 ok_hex(pSymbol->Flags, 0); 380 ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); 381 ok_hex(pSymbol->Tag, SymTagFunction); 382 ok_str(pSymbol->Name, "DllMain"); 383 384 /* The padding below the function */ 385 Displacement = 0; 386 INIT_PSYM(buffer); 387 Ret = SymFromAddr(hProc, BaseAddress + 0x102E, &Displacement, pSymbol); 388 ok_int(Ret, TRUE); 389 ok_ulonglong(Displacement, 0x1e); 390 ok_ulonglong(pSymbol->ModBase, BaseAddress); 391 ok_hex(pSymbol->Flags, 0); 392 ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); 393 ok_hex(pSymbol->Tag, SymTagFunction); 394 ok_str(pSymbol->Name, "DllMain"); 395 396 /* One byte before the next function */ 397 Displacement = 0; 398 INIT_PSYM(buffer); 399 Ret = SymFromAddr(hProc, BaseAddress + 0x103f, &Displacement, pSymbol); 400 ok_int(Ret, TRUE); 401 ok_ulonglong(Displacement, 0x2f); 402 ok_ulonglong(pSymbol->ModBase, BaseAddress); 403 ok_hex(pSymbol->Flags, 0); 404 ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); 405 ok_hex(pSymbol->Tag, SymTagFunction); 406 ok_str(pSymbol->Name, "DllMain"); 407 408 /* First byte of the next function */ 409 Displacement = 0; 410 INIT_PSYM(buffer); 411 Ret = SymFromAddr(hProc, BaseAddress + 0x1040, &Displacement, pSymbol); 412 ok_int(Ret, TRUE); 413 ok_ulonglong(Displacement, 0); 414 ok_ulonglong(pSymbol->ModBase, BaseAddress); 415 ok_hex(pSymbol->Flags, 0); 416 ok_ulonglong(pSymbol->Address, BaseAddress + 0x1040); 417 ok_hex(pSymbol->Tag, SymTagFunction); 418 ok_str(pSymbol->Name, "FfsChkdsk"); 419 420 if (!can_enumerate(hProc, BaseAddress)) 421 { 422 skip("dbghelp.dll too old or cannot read this symbol!\n"); 423 } 424 else 425 { 426 /* .idata */ 427 Displacement = 0; 428 INIT_PSYM(buffer); 429 Ret = SymFromAddr(hProc, BaseAddress + 0x2000, &Displacement, pSymbol); 430 ok_int(Ret, TRUE); 431 ok_ulonglong(Displacement, 0); 432 ok_ulonglong(pSymbol->ModBase, BaseAddress); 433 ok_hex(pSymbol->Flags, 0); 434 ok_ulonglong(pSymbol->Address, BaseAddress + 0x2000); 435 ok_hex(pSymbol->Tag, SymTagPublicSymbol); 436 ok_str(pSymbol->Name, "__imp__DbgPrint"); 437 } 438 439 deinit_sym(); 440 } 441 442 typedef struct _test_context 443 { 444 DWORD64 BaseAddress; 445 SIZE_T Index; 446 } test_context; 447 448 static struct _test_data { 449 DWORD64 AddressOffset; 450 ULONG Size; 451 ULONG Tag; 452 const char* Name; 453 } test_data[] = { 454 /* TODO: Order is based on magic, should find entries based on name, and mark as 'seen' */ 455 { 0x1070, 36, SymTagFunction, "FfsFormat" }, 456 { 0x1010, 32, SymTagFunction, "DllMain" }, 457 { 0x1040, 36, SymTagFunction, "FfsChkdsk" }, 458 459 { 0x2100, 0, SymTagPublicSymbol, "__IMPORT_DESCRIPTOR_ntdll" }, 460 { 0x109a, 0, SymTagPublicSymbol, "_DbgPrint" }, 461 { 0x2004, 0, SymTagPublicSymbol, "\x7fntdll_NULL_THUNK_DATA" }, 462 { 0x2000, 0, SymTagPublicSymbol, "__imp__DbgPrint" }, 463 { 0x2114, 0, SymTagPublicSymbol, "__NULL_IMPORT_DESCRIPTOR" }, 464 }; 465 466 static BOOL CALLBACK EnumSymProc(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext) 467 { 468 test_context* ctx = UserContext; 469 470 if (ctx->Index < ARRAYSIZE(test_data)) 471 { 472 ok_ulonglong(pSymInfo->ModBase, ctx->BaseAddress); 473 ok_ulonglong(pSymInfo->Address, ctx->BaseAddress + test_data[ctx->Index].AddressOffset); 474 ok_hex(pSymInfo->Tag, test_data[ctx->Index].Tag); 475 ok_str(pSymInfo->Name, test_data[ctx->Index].Name); 476 477 ctx->Index++; 478 } 479 else 480 { 481 ok(0, "Out of bounds (%lu), max is: %i!\n", ctx->Index, ARRAYSIZE(test_data)); 482 } 483 484 return TRUE; 485 } 486 487 static void test_SymEnumSymbols(HANDLE hProc, const char* szModuleName) 488 { 489 BOOL Ret; 490 DWORD dwErr; 491 492 test_context ctx; 493 494 if (!init_sym()) 495 return; 496 497 ctx.Index = 0; 498 SetLastError(ERROR_SUCCESS); 499 ctx.BaseAddress = SymLoadModule64(hProc, NULL, szModuleName, NULL, 0x600000, 0); 500 dwErr = GetLastError(); 501 502 ok_ulonglong(ctx.BaseAddress, 0x600000); 503 ok_hex(dwErr, ERROR_SUCCESS); 504 505 if (!can_enumerate(hProc, ctx.BaseAddress)) 506 { 507 skip("dbghelp.dll too old or cannot enumerate symbols!\n"); 508 } 509 else 510 { 511 Ret = SymEnumSymbols(hProc, ctx.BaseAddress, NULL, EnumSymProc, &ctx); 512 ok_int(Ret, TRUE); 513 ok_int(ctx.Index, ARRAYSIZE(test_data)); 514 } 515 516 deinit_sym(); 517 } 518 519 typedef struct _symregcallback_context 520 { 521 UINT idx; 522 BOOL isANSI; 523 } symregcallback_context; 524 525 static struct _symregcallback_test_data { 526 ULONG ActionCode; 527 const char* Name; 528 } symregcallback_test_data[] = { 529 { CBA_DEFERRED_SYMBOL_LOAD_CANCEL }, 530 { CBA_DEFERRED_SYMBOL_LOAD_START }, 531 { CBA_READ_MEMORY }, 532 { CBA_DEFERRED_SYMBOL_LOAD_PARTIAL }, 533 { CBA_DEFERRED_SYMBOL_LOAD_COMPLETE } 534 }; 535 536 static BOOL CALLBACK SymRegisterCallback64Proc( 537 HANDLE hProcess, 538 ULONG ActionCode, 539 ULONG64 CallbackData, 540 ULONG64 UserContext) 541 { 542 symregcallback_context *ctx; 543 ctx = (symregcallback_context*)(ULONG_PTR)UserContext; 544 545 if (ctx->idx > sizeof(symregcallback_test_data)) 546 { 547 ok(FALSE, "SymRegisterCallback64Proc: Too many calls.\n"); 548 } 549 else 550 { 551 ok(ActionCode == symregcallback_test_data[ctx->idx].ActionCode, 552 "ActionCode (idx %u) expected %u, got %u\n", 553 ctx->idx, symregcallback_test_data[ctx->idx].ActionCode, ActionCode); 554 } 555 ctx->idx++; 556 557 return FALSE; 558 } 559 560 static void test_SymRegCallback(HANDLE hProc, const char* szModuleName, BOOL testANSI) 561 { 562 BOOL Ret; 563 DWORD dwErr; 564 ULONG64 BaseAddress; 565 symregcallback_context ctx; 566 567 ctx.idx = 0; 568 ctx.isANSI = testANSI; 569 570 if (!init_sym()) 571 return; 572 573 if (testANSI) 574 { 575 Ret = SymRegisterCallback64(hProc, SymRegisterCallback64Proc, (ULONG_PTR)&ctx); 576 } 577 else 578 { 579 Ret = SymRegisterCallbackW64(hProc, SymRegisterCallback64Proc, (ULONG_PTR)&ctx); 580 if (g_SymRegisterCallbackW64NotFound) 581 { 582 skip("SymRegisterCallbackW64 not found in dbghelp.dll\n"); 583 return; 584 } 585 } 586 587 ok_int(Ret, TRUE); 588 if (!Ret) 589 return; 590 591 SetLastError(ERROR_SUCCESS); 592 BaseAddress = SymLoadModule64(hProc, NULL, szModuleName, NULL, 0x600000, 0); 593 dwErr = GetLastError(); 594 595 ok_ulonglong(BaseAddress, 0x600000); 596 ok_hex(dwErr, ERROR_SUCCESS); 597 598 /* this is what we want to test ... we expect 5 calls */ 599 ok_int(ctx.idx, 5); 600 601 deinit_sym(); 602 } 603 604 START_TEST(pdb) 605 { 606 char szDllName[MAX_PATH]; 607 //create_compressed_files(); 608 609 DWORD Options = SymGetOptions(); 610 Options &= ~(SYMOPT_UNDNAME); 611 //Options |= SYMOPT_DEBUG; 612 SymSetOptions(Options); 613 614 if (!extract_msvc_exe(szDllName)) 615 { 616 ok(0, "Failed extracting files\n"); 617 return; 618 } 619 620 init_dbghelp_version(); 621 622 test_SymFromName(proc(), szDllName); 623 test_SymFromAddr(proc(), szDllName); 624 test_SymEnumSymbols(proc(), szDllName); 625 test_SymRegCallback(proc(), szDllName, TRUE); 626 test_SymRegCallback(proc(), szDllName, FALSE); 627 628 cleanup_msvc_exe(); 629 630 } 631