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 
proc()34 static HANDLE proc()
35 {
36     return GetCurrentProcess();
37 }
38 
init_sym_imp(BOOL fInvadeProcess,const char * file,int line)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 
deinit_sym()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 */
get_module_version(_In_ HMODULE mod,_Out_ VS_FIXEDFILEINFO * fileinfo)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;
init_dbghelp_version()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
SymRegisterCallbackW64_Stub(HANDLE hProcess,PSYMBOL_REGISTERED_CALLBACK64 CallbackFunction,ULONG64 UserContext)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 */
DliFailHook(unsigned dliNotify,PDelayLoadInfo pdli)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? */
supports_pdb(HANDLE hProc,DWORD64 BaseAddress)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 
test_SymFromName(HANDLE hProc,DWORD64 BaseAddress)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 
test_SymFromAddr(HANDLE hProc,DWORD64 BaseAddress)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     if (!supports_pdb(hProc, BaseAddress))
314     {
315         skip("dbghelp.dll too old or cannot enumerate symbols!\n");
316     }
317     else
318     {
319 
320         /* No address found before load address of module */
321         Displacement = 0;
322         INIT_PSYM(buffer);
323         Ret = SymFromAddr(hProc, BaseAddress -1, &Displacement, pSymbol);
324         dwErr = GetLastError();
325         ok_int(Ret, FALSE);
326         ok_hex(dwErr, ERROR_MOD_NOT_FOUND);
327 
328         /* Right at the start of the module is recognized as the first symbol found */
329         Displacement = 0;
330         INIT_PSYM(buffer);
331         Ret = SymFromAddr(hProc, BaseAddress, &Displacement, pSymbol);
332         ok_int(Ret, TRUE);
333         ok_ulonglong(Displacement, 0xffffffffffffffff);
334         ok_ulonglong(pSymbol->ModBase, BaseAddress);
335         ok_hex(pSymbol->Flags, 0);
336         ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010);
337         ok_hex(pSymbol->Tag, SymTagFunction);
338         ok_str(pSymbol->Name, "DllMain");
339 
340         /* The actual first instruction of the function */
341         Displacement = 0;
342         INIT_PSYM(buffer);
343         Ret = SymFromAddr(hProc, BaseAddress + 0x1010, &Displacement, pSymbol);
344         ok_int(Ret, TRUE);
345         ok_ulonglong(Displacement, 0);
346         ok_ulonglong(pSymbol->ModBase, BaseAddress);
347         ok_hex(pSymbol->Flags, 0);
348         ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010);
349         ok_hex(pSymbol->Tag, SymTagFunction);
350         ok_str(pSymbol->Name, "DllMain");
351 
352         /* The last instruction in the function */
353         Displacement = 0;
354         INIT_PSYM(buffer);
355         Ret = SymFromAddr(hProc, BaseAddress + 0x102D, &Displacement, pSymbol);
356         ok_int(Ret, TRUE);
357         ok_ulonglong(Displacement, 0x1d);
358         ok_ulonglong(pSymbol->ModBase, BaseAddress);
359         ok_hex(pSymbol->Flags, 0);
360         ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010);
361         ok_hex(pSymbol->Tag, SymTagFunction);
362         ok_str(pSymbol->Name, "DllMain");
363 
364         /* The padding below the function */
365         Displacement = 0;
366         INIT_PSYM(buffer);
367         Ret = SymFromAddr(hProc, BaseAddress + 0x102E, &Displacement, pSymbol);
368         ok_int(Ret, TRUE);
369         ok_ulonglong(Displacement, 0x1e);
370         ok_ulonglong(pSymbol->ModBase, BaseAddress);
371         ok_hex(pSymbol->Flags, 0);
372         ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010);
373         ok_hex(pSymbol->Tag, SymTagFunction);
374         ok_str(pSymbol->Name, "DllMain");
375 
376         /* One byte before the next function */
377         Displacement = 0;
378         INIT_PSYM(buffer);
379         Ret = SymFromAddr(hProc, BaseAddress + 0x103f, &Displacement, pSymbol);
380         ok_int(Ret, TRUE);
381         ok_ulonglong(Displacement, 0x2f);
382         ok_ulonglong(pSymbol->ModBase, BaseAddress);
383         ok_hex(pSymbol->Flags, 0);
384         ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010);
385         ok_hex(pSymbol->Tag, SymTagFunction);
386         ok_str(pSymbol->Name, "DllMain");
387 
388         /* First byte of the next function */
389         Displacement = 0;
390         INIT_PSYM(buffer);
391         Ret = SymFromAddr(hProc, BaseAddress + 0x1040, &Displacement, pSymbol);
392         ok_int(Ret, TRUE);
393         ok_ulonglong(Displacement, 0);
394         ok_ulonglong(pSymbol->ModBase, BaseAddress);
395         ok_hex(pSymbol->Flags, 0);
396         ok_ulonglong(pSymbol->Address, BaseAddress + 0x1040);
397         ok_hex(pSymbol->Tag, SymTagFunction);
398         ok_str(pSymbol->Name, "FfsChkdsk");
399 
400         /* .idata */
401         Displacement = 0;
402         INIT_PSYM(buffer);
403         Ret = SymFromAddr(hProc, BaseAddress + 0x2000, &Displacement, pSymbol);
404         ok_int(Ret, TRUE);
405         ok_ulonglong(Displacement, 0);
406         ok_ulonglong(pSymbol->ModBase, BaseAddress);
407         ok_hex(pSymbol->Flags, 0);
408         ok_ulonglong(pSymbol->Address, BaseAddress + 0x2000);
409         ok_hex(pSymbol->Tag, SymTagPublicSymbol);
410         ok_str(pSymbol->Name, "__imp__DbgPrint");
411     }
412 }
413 
414 typedef struct _test_context
415 {
416     DWORD64 BaseAddress;
417     SIZE_T Index;
418 } test_context;
419 
420 static struct _test_data {
421     DWORD64 AddressOffset;
422     ULONG Size;
423     ULONG Tag;
424     const char* Name;
425 } test_data[] = {
426     /* TODO: Order is based on magic, should find entries based on name, and mark as 'seen' */
427     { 0x1070, 36, SymTagFunction, "FfsFormat" },
428     { 0x1010, 32, SymTagFunction, "DllMain" },
429     { 0x1040, 36, SymTagFunction, "FfsChkdsk" },
430 
431     { 0x2100, 0, SymTagPublicSymbol, "__IMPORT_DESCRIPTOR_ntdll" },
432     { 0x109a, 0, SymTagPublicSymbol, "_DbgPrint" },
433     { 0x2004, 0, SymTagPublicSymbol, "\x7fntdll_NULL_THUNK_DATA" },
434     { 0x2000, 0, SymTagPublicSymbol, "__imp__DbgPrint" },
435     { 0x2114, 0, SymTagPublicSymbol, "__NULL_IMPORT_DESCRIPTOR" },
436 };
437 
EnumSymProc(PSYMBOL_INFO pSymInfo,ULONG SymbolSize,PVOID UserContext)438 static BOOL CALLBACK EnumSymProc(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext)
439 {
440     test_context* ctx = UserContext;
441 
442     if (ctx->Index < ARRAYSIZE(test_data))
443     {
444         ok_ulonglong(pSymInfo->ModBase, ctx->BaseAddress);
445         ok_ulonglong(pSymInfo->Address, ctx->BaseAddress + test_data[ctx->Index].AddressOffset);
446         ok_hex(pSymInfo->Tag, test_data[ctx->Index].Tag);
447         ok_str(pSymInfo->Name, test_data[ctx->Index].Name);
448 
449         ctx->Index++;
450     }
451     else
452     {
453         ok(0, "Out of bounds (%lu), max is: %i!\n", ctx->Index, ARRAYSIZE(test_data));
454     }
455 
456     return TRUE;
457 }
458 
test_SymEnumSymbols(HANDLE hProc,DWORD64 BaseAddress)459 static void test_SymEnumSymbols(HANDLE hProc, DWORD64 BaseAddress)
460 {
461     BOOL Ret;
462     test_context ctx;
463 
464     ctx.Index = 0;
465     ctx.BaseAddress = BaseAddress;
466 
467     if (!supports_pdb(hProc, ctx.BaseAddress))
468     {
469         skip("dbghelp.dll too old or cannot enumerate symbols!\n");
470     }
471     else
472     {
473         Ret = SymEnumSymbols(hProc, ctx.BaseAddress, NULL, EnumSymProc, &ctx);
474         ok_int(Ret, TRUE);
475         ok_int(ctx.Index, ARRAYSIZE(test_data));
476     }
477 }
478 
479 typedef struct _symregcallback_context
480 {
481     UINT idx;
482     BOOL isANSI;
483 } symregcallback_context;
484 
485 static struct _symregcallback_test_data {
486     ULONG ActionCode;
487 } symregcallback_test_data[] = {
488     { CBA_DEFERRED_SYMBOL_LOAD_CANCEL },
489     { CBA_DEFERRED_SYMBOL_LOAD_START },
490     { CBA_READ_MEMORY },
491     { CBA_DEFERRED_SYMBOL_LOAD_PARTIAL },
492     { CBA_DEFERRED_SYMBOL_LOAD_COMPLETE }
493 };
494 
SymRegisterCallback64Proc(HANDLE hProcess,ULONG ActionCode,ULONG64 CallbackData,ULONG64 UserContext)495 static BOOL CALLBACK SymRegisterCallback64Proc(
496     HANDLE hProcess,
497     ULONG ActionCode,
498     ULONG64 CallbackData,
499     ULONG64 UserContext)
500 {
501     symregcallback_context *ctx;
502     ctx = (symregcallback_context*)(ULONG_PTR)UserContext;
503 
504     if (ctx->idx > sizeof(symregcallback_test_data))
505     {
506         ok(FALSE, "SymRegisterCallback64Proc: Too many calls.\n");
507     }
508     else
509     {
510         ok(ActionCode == symregcallback_test_data[ctx->idx].ActionCode,
511             "ActionCode (idx %u) expected %u, got %u\n",
512             ctx->idx, symregcallback_test_data[ctx->idx].ActionCode, ActionCode);
513     }
514     ctx->idx++;
515 
516     return FALSE;
517 }
518 
test_SymRegCallback(HANDLE hProc,const char * szModuleName,BOOL testANSI)519 static void test_SymRegCallback(HANDLE hProc, const char* szModuleName, BOOL testANSI)
520 {
521     BOOL Ret;
522     DWORD dwErr;
523     ULONG64 BaseAddress;
524     symregcallback_context ctx;
525 
526     ctx.idx = 0;
527     ctx.isANSI = testANSI;
528 
529     if (!init_sym(FALSE))
530         return;
531 
532     if (testANSI)
533     {
534         Ret = SymRegisterCallback64(hProc, SymRegisterCallback64Proc, (ULONG_PTR)&ctx);
535     }
536     else
537     {
538         Ret = SymRegisterCallbackW64(hProc, SymRegisterCallback64Proc, (ULONG_PTR)&ctx);
539         if (g_SymRegisterCallbackW64NotFound)
540         {
541             skip("SymRegisterCallbackW64 not found in dbghelp.dll\n");
542             return;
543         }
544     }
545 
546     ok_int(Ret, TRUE);
547     if (!Ret)
548         return;
549 
550     SetLastError(ERROR_SUCCESS);
551     BaseAddress = SymLoadModule64(hProc, NULL, szModuleName, NULL, 0x600000, 0);
552     dwErr = GetLastError();
553 
554     ok_ulonglong(BaseAddress, 0x600000);
555     ok_hex(dwErr, ERROR_SUCCESS);
556 
557     /* this is what we want to test ... we expect 5 calls */
558     ok_int(ctx.idx, 5);
559 
560     deinit_sym();
561 }
562 
START_TEST(pdb)563 START_TEST(pdb)
564 {
565     char szDllName[MAX_PATH];
566     char szDllPath[MAX_PATH], szOldDir[MAX_PATH];
567     HMODULE hMod;
568     DWORD64 BaseAddress;
569     DWORD dwErr, Options;
570 
571     Options = SymGetOptions();
572     Options &= ~(SYMOPT_UNDNAME);
573     //Options |= SYMOPT_DEBUG;
574     SymSetOptions(Options);
575 
576     if (!extract_msvc_dll(szDllName, szDllPath))
577     {
578         ok(0, "Failed extracting files\n");
579         return;
580     }
581 
582     init_dbghelp_version();
583 
584     /* Register the failure hook using the magic name '__pfnDliFailureHook2'. */
585     __pfnDliFailureHook2 = DliFailHook;
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     hMod = LoadLibraryA(szDllName);
612     if (hMod)
613     {
614         BaseAddress = (DWORD64)(DWORD_PTR)hMod;
615         /* Make sure we can find the pdb */
616         GetCurrentDirectoryA(_countof(szOldDir), szOldDir);
617         SetCurrentDirectoryA(szDllPath);
618         /* Invade process */
619         if (init_sym(TRUE))
620         {
621             trace("Module loaded by LoadLibraryA\n");
622             test_SymFromName(proc(), BaseAddress);
623             test_SymFromAddr(proc(), BaseAddress);
624             test_SymEnumSymbols(proc(), BaseAddress);
625 
626             deinit_sym();
627         }
628         /* Restore working dir */
629         SetCurrentDirectoryA(szOldDir);
630 
631         FreeLibrary(hMod);
632     }
633 
634     cleanup_msvc_dll();
635 }
636