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