[DBGHELP_APITEST] Skip the test when the function is not found
[reactos.git] / modules / rostests / apitests / dbghelp / pdb.c
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 }