1c2c66affSColin Finck /*
2c2c66affSColin Finck * PROJECT: ReactOS api tests
3b8a1a612SMark Jansen * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4c2c66affSColin Finck * PURPOSE: Test for dbghelp PDB functions
5b8a1a612SMark Jansen * COPYRIGHT: Copyright 2017-2019 Mark Jansen (mark.jansen@reactos.org)
6c2c66affSColin Finck */
7c2c66affSColin Finck
8c2c66affSColin Finck #include <ntstatus.h>
9c2c66affSColin Finck #define WIN32_NO_STATUS
10c2c66affSColin Finck #include <windows.h>
11c2c66affSColin Finck #include <dbghelp.h>
12c2c66affSColin Finck #include <cvconst.h> // SymTagXXX
13c2c66affSColin Finck #include <stdio.h>
14c296ee51SMark Jansen #include <delayimp.h>
15c2c66affSColin Finck
16c2c66affSColin Finck #include "wine/test.h"
17c2c66affSColin Finck
18522e9f6dSVictor Perevertkin extern PfnDliHook __pfnDliFailureHook2;
19522e9f6dSVictor Perevertkin
20c2c66affSColin Finck #define ok_ulonglong(expression, result) \
21c2c66affSColin Finck do { \
22c2c66affSColin Finck ULONG64 _value = (expression); \
23c2c66affSColin Finck ULONG64 _result = (result); \
24c2c66affSColin Finck ok(_value == (result), "Wrong value for '%s', expected: " #result " (%s), got: %s\n", \
25c2c66affSColin Finck #expression, wine_dbgstr_longlong(_result), wine_dbgstr_longlong(_value)); \
26c2c66affSColin Finck } while (0)
27c2c66affSColin Finck
28c2c66affSColin Finck
29c2c66affSColin Finck // data.c
30c2c66affSColin Finck void create_compressed_files();
31b8a1a612SMark Jansen int extract_msvc_dll(char szFile[MAX_PATH], char szPath[MAX_PATH]);
32b8a1a612SMark Jansen void cleanup_msvc_dll();
33c2c66affSColin Finck
proc()34c2c66affSColin Finck static HANDLE proc()
35c2c66affSColin Finck {
36c2c66affSColin Finck return GetCurrentProcess();
37c2c66affSColin Finck }
38c2c66affSColin Finck
init_sym_imp(BOOL fInvadeProcess,const char * file,int line)39b8a1a612SMark Jansen static BOOL init_sym_imp(BOOL fInvadeProcess, const char* file, int line)
40c2c66affSColin Finck {
41b8a1a612SMark Jansen if (!SymInitialize(proc(), NULL, fInvadeProcess))
42c2c66affSColin Finck {
43c2c66affSColin Finck DWORD err = GetLastError();
44c2c66affSColin Finck ok_(file, line)(0, "Failed to init: 0x%x\n", err);
45c2c66affSColin Finck return FALSE;
46c2c66affSColin Finck }
47c2c66affSColin Finck return TRUE;
48c2c66affSColin Finck }
49c2c66affSColin Finck
deinit_sym()50c2c66affSColin Finck static void deinit_sym()
51c2c66affSColin Finck {
52c2c66affSColin Finck SymCleanup(proc());
53c2c66affSColin Finck }
54c2c66affSColin Finck
55b8a1a612SMark Jansen #define init_sym(fInvadeProcess) init_sym_imp(fInvadeProcess, __FILE__, __LINE__)
56c2c66affSColin Finck
57c2c66affSColin Finck #define INIT_PSYM(buff) do { \
58c2c66affSColin Finck memset((buff), 0, sizeof((buff))); \
59c2c66affSColin Finck ((PSYMBOL_INFO)(buff))->SizeOfStruct = sizeof(SYMBOL_INFO); \
60c2c66affSColin Finck ((PSYMBOL_INFO)(buff))->MaxNameLen = MAX_SYM_NAME; \
61c2c66affSColin Finck } while (0)
62c2c66affSColin Finck
63184255ffSAndreas Maier /* modified copy of function from apitests/apphelp/apitest.c */
get_module_version(_In_ HMODULE mod,_Out_ VS_FIXEDFILEINFO * fileinfo)64184255ffSAndreas Maier BOOL get_module_version(
65184255ffSAndreas Maier _In_ HMODULE mod,
66184255ffSAndreas Maier _Out_ VS_FIXEDFILEINFO *fileinfo)
67184255ffSAndreas Maier {
68184255ffSAndreas Maier BOOL res = FALSE;
69184255ffSAndreas Maier HRSRC hResInfo;
70184255ffSAndreas Maier char *errmsg;
71184255ffSAndreas Maier DWORD dwSize, errcode = 0;
72184255ffSAndreas Maier UINT uLen;
73184255ffSAndreas Maier HGLOBAL hResData = 0;
74184255ffSAndreas Maier LPVOID pRes = NULL;
75184255ffSAndreas Maier HLOCAL pResCopy = 0;
76184255ffSAndreas Maier VS_FIXEDFILEINFO *lpFfi;
77184255ffSAndreas Maier
78184255ffSAndreas Maier if (fileinfo == NULL)
79184255ffSAndreas Maier {
80184255ffSAndreas Maier errmsg = "fileinfo is NULL.\n";
81184255ffSAndreas Maier goto cleanup;
82184255ffSAndreas Maier }
83184255ffSAndreas Maier
84184255ffSAndreas Maier hResInfo = FindResource(mod, MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION);
85184255ffSAndreas Maier if (hResInfo == 0)
86184255ffSAndreas Maier {
87184255ffSAndreas Maier errmsg = "FindResource failed";
88184255ffSAndreas Maier errcode = GetLastError();
89184255ffSAndreas Maier goto cleanup;
90184255ffSAndreas Maier }
91184255ffSAndreas Maier
92184255ffSAndreas Maier dwSize = SizeofResource(mod, hResInfo);
93184255ffSAndreas Maier if (dwSize == 0)
94184255ffSAndreas Maier {
95184255ffSAndreas Maier errmsg = "SizeofResource failed";
96184255ffSAndreas Maier errcode = GetLastError();
97184255ffSAndreas Maier goto cleanup;
98184255ffSAndreas Maier }
99184255ffSAndreas Maier
100184255ffSAndreas Maier hResData = LoadResource(mod, hResInfo);
101184255ffSAndreas Maier if (hResData == 0)
102184255ffSAndreas Maier {
103184255ffSAndreas Maier errmsg = "LoadResource failed";
104184255ffSAndreas Maier errcode = GetLastError();
105184255ffSAndreas Maier goto cleanup;
106184255ffSAndreas Maier }
107184255ffSAndreas Maier
108184255ffSAndreas Maier pRes = LockResource(hResData);
109184255ffSAndreas Maier if (pRes == NULL)
110184255ffSAndreas Maier {
111184255ffSAndreas Maier errmsg = "LockResource failed";
112184255ffSAndreas Maier errcode = GetLastError();
113184255ffSAndreas Maier goto cleanup;
114184255ffSAndreas Maier }
115184255ffSAndreas Maier
116184255ffSAndreas Maier pResCopy = LocalAlloc(LMEM_FIXED, dwSize);
117184255ffSAndreas Maier if (pResCopy == NULL)
118184255ffSAndreas Maier {
119184255ffSAndreas Maier errmsg = "LocalAlloc failed";
120184255ffSAndreas Maier errcode = GetLastError();
121184255ffSAndreas Maier goto cleanup;
122184255ffSAndreas Maier }
123184255ffSAndreas Maier
124184255ffSAndreas Maier CopyMemory(pResCopy, pRes, dwSize);
125184255ffSAndreas Maier
126184255ffSAndreas Maier if (VerQueryValueW(pResCopy, L"\\", (LPVOID*)&lpFfi, &uLen))
127184255ffSAndreas Maier {
128184255ffSAndreas Maier *fileinfo = *lpFfi;
129184255ffSAndreas Maier res = TRUE;
130184255ffSAndreas Maier }
131184255ffSAndreas Maier
132184255ffSAndreas Maier cleanup:
133184255ffSAndreas Maier /* cleanup */
134184255ffSAndreas Maier if (hResData != 0)
135184255ffSAndreas Maier FreeResource(hResData);
136184255ffSAndreas Maier if (pResCopy != NULL)
137184255ffSAndreas Maier LocalFree(pResCopy);
138184255ffSAndreas Maier /* if it was good */
139184255ffSAndreas Maier if (res == TRUE)
140184255ffSAndreas Maier return TRUE;
141184255ffSAndreas Maier /* failure path */
142184255ffSAndreas Maier if (errcode == 0)
143184255ffSAndreas Maier trace("get_module_version - %s.\n", errmsg);
144184255ffSAndreas Maier else
145184255ffSAndreas Maier trace("get_module_version - %s (lasterror %d).\n", errmsg, errcode);
146184255ffSAndreas Maier return FALSE;
147184255ffSAndreas Maier }
148184255ffSAndreas Maier
149184255ffSAndreas Maier static VS_FIXEDFILEINFO dbghelpFileVer;
init_dbghelp_version()150184255ffSAndreas Maier static void init_dbghelp_version()
151184255ffSAndreas Maier {
152184255ffSAndreas Maier LPAPI_VERSION v;
153184255ffSAndreas Maier WCHAR filenameW[MAX_PATH + 1];
154184255ffSAndreas Maier HMODULE hDLL;
155184255ffSAndreas Maier DWORD fileLen;
156184255ffSAndreas Maier VS_FIXEDFILEINFO fileInfo;
157184255ffSAndreas Maier
158184255ffSAndreas Maier memset(&dbghelpFileVer, 0, sizeof(dbghelpFileVer));
159184255ffSAndreas Maier
160184255ffSAndreas Maier /* get internal file version */
161184255ffSAndreas Maier v = ImagehlpApiVersion();
162184255ffSAndreas Maier if (v == NULL)
163184255ffSAndreas Maier return;
164184255ffSAndreas Maier
165184255ffSAndreas Maier /* get module file version */
166184255ffSAndreas Maier hDLL = GetModuleHandleW(L"dbghelp.dll");
167184255ffSAndreas Maier if (hDLL == 0)
168184255ffSAndreas Maier {
169184255ffSAndreas Maier ok(FALSE, "Dbghelp.dll is not loaded!\n");
170184255ffSAndreas Maier return;
171184255ffSAndreas Maier }
172184255ffSAndreas Maier if (!get_module_version(hDLL, &fileInfo))
173184255ffSAndreas Maier memset(&fileInfo, 0, sizeof(fileInfo));
174184255ffSAndreas Maier dbghelpFileVer = fileInfo;
175184255ffSAndreas Maier
176184255ffSAndreas Maier /* get full file path */
177184255ffSAndreas Maier fileLen = GetModuleFileNameW(hDLL, filenameW, MAX_PATH + 1);
178184255ffSAndreas Maier if (fileLen == 0)
179184255ffSAndreas Maier {
180184255ffSAndreas Maier ok(FALSE, "GetModuleFileNameW for dbghelp.dll failed!\n");
181184255ffSAndreas Maier return;
182184255ffSAndreas Maier }
183184255ffSAndreas Maier
184184255ffSAndreas Maier trace("Using %S\n", filenameW);
185184255ffSAndreas Maier trace(" API-Version: %hu.%hu.%hu (%hu)\n",
186184255ffSAndreas Maier v->MajorVersion, v->MinorVersion, v->Revision, v->Reserved);
187184255ffSAndreas Maier
188184255ffSAndreas Maier trace(" Fileversion: %hu.%hu.%hu.%hu\n",
189184255ffSAndreas Maier HIWORD(fileInfo.dwProductVersionMS),
190184255ffSAndreas Maier LOWORD(fileInfo.dwProductVersionMS),
191184255ffSAndreas Maier HIWORD(fileInfo.dwProductVersionLS),
192184255ffSAndreas Maier LOWORD(fileInfo.dwProductVersionLS));
193184255ffSAndreas Maier }
194c2c66affSColin Finck
195c296ee51SMark Jansen static
196c296ee51SMark Jansen int g_SymRegisterCallbackW64NotFound = 0;
197c296ee51SMark Jansen
198c296ee51SMark Jansen static
SymRegisterCallbackW64_Stub(HANDLE hProcess,PSYMBOL_REGISTERED_CALLBACK64 CallbackFunction,ULONG64 UserContext)199c296ee51SMark Jansen BOOL WINAPI SymRegisterCallbackW64_Stub(HANDLE hProcess, PSYMBOL_REGISTERED_CALLBACK64 CallbackFunction, ULONG64 UserContext)
200c296ee51SMark Jansen {
201c296ee51SMark Jansen g_SymRegisterCallbackW64NotFound++;
202c296ee51SMark Jansen return FALSE;
203c296ee51SMark Jansen }
204c296ee51SMark Jansen
205c296ee51SMark Jansen /* A delay-load failure hook will be called when resolving a delay-load dependency (dll or function) fails */
DliFailHook(unsigned dliNotify,PDelayLoadInfo pdli)206c296ee51SMark Jansen FARPROC WINAPI DliFailHook(unsigned dliNotify, PDelayLoadInfo pdli)
207c296ee51SMark Jansen {
208c296ee51SMark Jansen /* Was the failure a function, and did we get info */
209c296ee51SMark Jansen if (dliNotify == dliFailGetProc && pdli)
210c296ee51SMark Jansen {
211c296ee51SMark Jansen /* Is it our function? */
212c296ee51SMark Jansen if (pdli->dlp.fImportByName && !strcmp(pdli->dlp.szProcName, "SymRegisterCallbackW64"))
213c296ee51SMark Jansen {
214c296ee51SMark Jansen /* Redirect execution to the stub */
215c296ee51SMark Jansen return (FARPROC)SymRegisterCallbackW64_Stub;
216c296ee51SMark Jansen }
217c296ee51SMark Jansen }
218c296ee51SMark Jansen /* This is not the function you are looking for, continue default behavior (throw exception) */
219c296ee51SMark Jansen return NULL;
220c296ee51SMark Jansen }
221c296ee51SMark Jansen
222c2c66affSColin Finck /* Maybe our dbghelp.dll is too old? */
supports_pdb(HANDLE hProc,DWORD64 BaseAddress)223b8a1a612SMark Jansen static BOOL supports_pdb(HANDLE hProc, DWORD64 BaseAddress)
224c2c66affSColin Finck {
225c2c66affSColin Finck IMAGEHLP_MODULE64 ModuleInfo;
226c2c66affSColin Finck BOOL Ret;
227c2c66affSColin Finck
228c2c66affSColin Finck memset(&ModuleInfo, 0, sizeof(ModuleInfo));
229c2c66affSColin Finck ModuleInfo.SizeOfStruct = sizeof(ModuleInfo);
230c2c66affSColin Finck Ret = SymGetModuleInfo64(hProc, BaseAddress, &ModuleInfo);
231c2c66affSColin Finck
232c2c66affSColin Finck return Ret && ModuleInfo.SymType == SymPdb;
233c2c66affSColin Finck }
234c2c66affSColin Finck
235c2c66affSColin Finck
test_SymFromName(HANDLE hProc,DWORD64 BaseAddress)236b8a1a612SMark Jansen static void test_SymFromName(HANDLE hProc, DWORD64 BaseAddress)
237c2c66affSColin Finck {
238c2c66affSColin Finck BOOL Ret;
239c2c66affSColin Finck char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
240c2c66affSColin Finck PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
241c2c66affSColin Finck
242b8a1a612SMark Jansen if (!supports_pdb(hProc, BaseAddress))
243c2c66affSColin Finck {
244c2c66affSColin Finck skip("dbghelp.dll too old or cannot enumerate symbols!\n");
245c2c66affSColin Finck }
246c2c66affSColin Finck else
247c2c66affSColin Finck {
248c2c66affSColin Finck INIT_PSYM(buffer);
249c2c66affSColin Finck Ret = SymFromName(hProc, "DllMain", pSymbol);
250c2c66affSColin Finck ok_int(Ret, TRUE);
251c2c66affSColin Finck ok_ulonglong(pSymbol->ModBase, BaseAddress);
252c2c66affSColin Finck ok_hex(pSymbol->Flags, 0);
253c2c66affSColin Finck ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010);
254c2c66affSColin Finck ok_hex(pSymbol->Tag, SymTagFunction);
255c2c66affSColin Finck ok_str(pSymbol->Name, "DllMain");
256c2c66affSColin Finck
257c2c66affSColin Finck INIT_PSYM(buffer);
258c2c66affSColin Finck Ret = SymFromName(hProc, "_DllMain@12", pSymbol);
259c2c66affSColin Finck ok_int(Ret, TRUE);
260c2c66affSColin Finck ok_ulonglong(pSymbol->ModBase, BaseAddress);
261c2c66affSColin Finck ok_hex(pSymbol->Flags, 0x400000); // ??
262c2c66affSColin Finck ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010);
263c2c66affSColin Finck ok_hex(pSymbol->Tag, SymTagPublicSymbol);
264c2c66affSColin Finck ok_str(pSymbol->Name, "_DllMain@12");
265c2c66affSColin Finck
266c2c66affSColin Finck INIT_PSYM(buffer);
267c2c66affSColin Finck Ret = SymFromName(hProc, "FfsChkdsk", pSymbol);
268c2c66affSColin Finck ok_int(Ret, TRUE);
269c2c66affSColin Finck ok_ulonglong(pSymbol->ModBase, BaseAddress);
270c2c66affSColin Finck ok_hex(pSymbol->Flags, 0);
271c2c66affSColin Finck ok_ulonglong(pSymbol->Address, BaseAddress + 0x1040);
272c2c66affSColin Finck ok_hex(pSymbol->Tag, SymTagFunction);
273c2c66affSColin Finck ok_str(pSymbol->Name, "FfsChkdsk");
274c2c66affSColin Finck
275c2c66affSColin Finck INIT_PSYM(buffer);
276c2c66affSColin Finck Ret = SymFromName(hProc, "_FfsChkdsk@24", pSymbol);
277c2c66affSColin Finck ok_int(Ret, TRUE);
278c2c66affSColin Finck ok_ulonglong(pSymbol->ModBase, BaseAddress);
279c2c66affSColin Finck ok_hex(pSymbol->Flags, 0x400000); // ??
280c2c66affSColin Finck ok_ulonglong(pSymbol->Address, BaseAddress + 0x1040);
281c2c66affSColin Finck ok_hex(pSymbol->Tag, SymTagPublicSymbol);
282c2c66affSColin Finck ok_str(pSymbol->Name, "_FfsChkdsk@24");
283c2c66affSColin Finck
284c2c66affSColin Finck INIT_PSYM(buffer);
285c2c66affSColin Finck Ret = SymFromName(hProc, "FfsFormat", pSymbol);
286c2c66affSColin Finck ok_int(Ret, TRUE);
287c2c66affSColin Finck ok_ulonglong(pSymbol->ModBase, BaseAddress);
288c2c66affSColin Finck ok_hex(pSymbol->Flags, 0);
289c2c66affSColin Finck ok_ulonglong(pSymbol->Address, BaseAddress + 0x1070);
290c2c66affSColin Finck ok_hex(pSymbol->Tag, SymTagFunction);
291c2c66affSColin Finck ok_str(pSymbol->Name, "FfsFormat");
292c2c66affSColin Finck
293c2c66affSColin Finck INIT_PSYM(buffer);
294c2c66affSColin Finck Ret = SymFromName(hProc, "_FfsFormat@24", pSymbol);
295c2c66affSColin Finck ok_int(Ret, TRUE);
296c2c66affSColin Finck ok_ulonglong(pSymbol->ModBase, BaseAddress);
297c2c66affSColin Finck ok_hex(pSymbol->Flags, 0x400000); // ??
298c2c66affSColin Finck ok_ulonglong(pSymbol->Address, BaseAddress + 0x1070);
299c2c66affSColin Finck ok_hex(pSymbol->Tag, SymTagPublicSymbol);
300c2c66affSColin Finck ok_str(pSymbol->Name, "_FfsFormat@24");
301c2c66affSColin Finck }
302c2c66affSColin Finck }
303c2c66affSColin Finck
test_SymFromAddr(HANDLE hProc,DWORD64 BaseAddress)304b8a1a612SMark Jansen static void test_SymFromAddr(HANDLE hProc, DWORD64 BaseAddress)
305c2c66affSColin Finck {
306c2c66affSColin Finck BOOL Ret;
307c2c66affSColin Finck char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
308c2c66affSColin Finck PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
309c2c66affSColin Finck
310b8a1a612SMark Jansen DWORD64 Displacement;
311c2c66affSColin Finck DWORD dwErr;
312c2c66affSColin Finck
313*eeaddf5bSMark Jansen if (!supports_pdb(hProc, BaseAddress))
314*eeaddf5bSMark Jansen {
315*eeaddf5bSMark Jansen skip("dbghelp.dll too old or cannot enumerate symbols!\n");
316*eeaddf5bSMark Jansen }
317*eeaddf5bSMark Jansen else
318*eeaddf5bSMark Jansen {
319*eeaddf5bSMark Jansen
320c2c66affSColin Finck /* No address found before load address of module */
321c2c66affSColin Finck Displacement = 0;
322c2c66affSColin Finck INIT_PSYM(buffer);
323c2c66affSColin Finck Ret = SymFromAddr(hProc, BaseAddress -1, &Displacement, pSymbol);
324c2c66affSColin Finck dwErr = GetLastError();
325c2c66affSColin Finck ok_int(Ret, FALSE);
326c2c66affSColin Finck ok_hex(dwErr, ERROR_MOD_NOT_FOUND);
327c2c66affSColin Finck
328c2c66affSColin Finck /* Right at the start of the module is recognized as the first symbol found */
329c2c66affSColin Finck Displacement = 0;
330c2c66affSColin Finck INIT_PSYM(buffer);
331c2c66affSColin Finck Ret = SymFromAddr(hProc, BaseAddress, &Displacement, pSymbol);
332c2c66affSColin Finck ok_int(Ret, TRUE);
333c2c66affSColin Finck ok_ulonglong(Displacement, 0xffffffffffffffff);
334c2c66affSColin Finck ok_ulonglong(pSymbol->ModBase, BaseAddress);
335c2c66affSColin Finck ok_hex(pSymbol->Flags, 0);
336c2c66affSColin Finck ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010);
337c2c66affSColin Finck ok_hex(pSymbol->Tag, SymTagFunction);
338c2c66affSColin Finck ok_str(pSymbol->Name, "DllMain");
339c2c66affSColin Finck
340c2c66affSColin Finck /* The actual first instruction of the function */
341c2c66affSColin Finck Displacement = 0;
342c2c66affSColin Finck INIT_PSYM(buffer);
343c2c66affSColin Finck Ret = SymFromAddr(hProc, BaseAddress + 0x1010, &Displacement, pSymbol);
344c2c66affSColin Finck ok_int(Ret, TRUE);
345c2c66affSColin Finck ok_ulonglong(Displacement, 0);
346c2c66affSColin Finck ok_ulonglong(pSymbol->ModBase, BaseAddress);
347c2c66affSColin Finck ok_hex(pSymbol->Flags, 0);
348c2c66affSColin Finck ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010);
349c2c66affSColin Finck ok_hex(pSymbol->Tag, SymTagFunction);
350c2c66affSColin Finck ok_str(pSymbol->Name, "DllMain");
351c2c66affSColin Finck
352c2c66affSColin Finck /* The last instruction in the function */
353c2c66affSColin Finck Displacement = 0;
354c2c66affSColin Finck INIT_PSYM(buffer);
355c2c66affSColin Finck Ret = SymFromAddr(hProc, BaseAddress + 0x102D, &Displacement, pSymbol);
356c2c66affSColin Finck ok_int(Ret, TRUE);
357c2c66affSColin Finck ok_ulonglong(Displacement, 0x1d);
358c2c66affSColin Finck ok_ulonglong(pSymbol->ModBase, BaseAddress);
359c2c66affSColin Finck ok_hex(pSymbol->Flags, 0);
360c2c66affSColin Finck ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010);
361c2c66affSColin Finck ok_hex(pSymbol->Tag, SymTagFunction);
362c2c66affSColin Finck ok_str(pSymbol->Name, "DllMain");
363c2c66affSColin Finck
364c2c66affSColin Finck /* The padding below the function */
365c2c66affSColin Finck Displacement = 0;
366c2c66affSColin Finck INIT_PSYM(buffer);
367c2c66affSColin Finck Ret = SymFromAddr(hProc, BaseAddress + 0x102E, &Displacement, pSymbol);
368c2c66affSColin Finck ok_int(Ret, TRUE);
369c2c66affSColin Finck ok_ulonglong(Displacement, 0x1e);
370c2c66affSColin Finck ok_ulonglong(pSymbol->ModBase, BaseAddress);
371c2c66affSColin Finck ok_hex(pSymbol->Flags, 0);
372c2c66affSColin Finck ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010);
373c2c66affSColin Finck ok_hex(pSymbol->Tag, SymTagFunction);
374c2c66affSColin Finck ok_str(pSymbol->Name, "DllMain");
375c2c66affSColin Finck
376c2c66affSColin Finck /* One byte before the next function */
377c2c66affSColin Finck Displacement = 0;
378c2c66affSColin Finck INIT_PSYM(buffer);
379c2c66affSColin Finck Ret = SymFromAddr(hProc, BaseAddress + 0x103f, &Displacement, pSymbol);
380c2c66affSColin Finck ok_int(Ret, TRUE);
381c2c66affSColin Finck ok_ulonglong(Displacement, 0x2f);
382c2c66affSColin Finck ok_ulonglong(pSymbol->ModBase, BaseAddress);
383c2c66affSColin Finck ok_hex(pSymbol->Flags, 0);
384c2c66affSColin Finck ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010);
385c2c66affSColin Finck ok_hex(pSymbol->Tag, SymTagFunction);
386c2c66affSColin Finck ok_str(pSymbol->Name, "DllMain");
387c2c66affSColin Finck
388c2c66affSColin Finck /* First byte of the next function */
389c2c66affSColin Finck Displacement = 0;
390c2c66affSColin Finck INIT_PSYM(buffer);
391c2c66affSColin Finck Ret = SymFromAddr(hProc, BaseAddress + 0x1040, &Displacement, pSymbol);
392c2c66affSColin Finck ok_int(Ret, TRUE);
393c2c66affSColin Finck ok_ulonglong(Displacement, 0);
394c2c66affSColin Finck ok_ulonglong(pSymbol->ModBase, BaseAddress);
395c2c66affSColin Finck ok_hex(pSymbol->Flags, 0);
396c2c66affSColin Finck ok_ulonglong(pSymbol->Address, BaseAddress + 0x1040);
397c2c66affSColin Finck ok_hex(pSymbol->Tag, SymTagFunction);
398c2c66affSColin Finck ok_str(pSymbol->Name, "FfsChkdsk");
399c2c66affSColin Finck
400c2c66affSColin Finck /* .idata */
401c2c66affSColin Finck Displacement = 0;
402c2c66affSColin Finck INIT_PSYM(buffer);
403c2c66affSColin Finck Ret = SymFromAddr(hProc, BaseAddress + 0x2000, &Displacement, pSymbol);
404c2c66affSColin Finck ok_int(Ret, TRUE);
405c2c66affSColin Finck ok_ulonglong(Displacement, 0);
406c2c66affSColin Finck ok_ulonglong(pSymbol->ModBase, BaseAddress);
407c2c66affSColin Finck ok_hex(pSymbol->Flags, 0);
408c2c66affSColin Finck ok_ulonglong(pSymbol->Address, BaseAddress + 0x2000);
409c2c66affSColin Finck ok_hex(pSymbol->Tag, SymTagPublicSymbol);
410c2c66affSColin Finck ok_str(pSymbol->Name, "__imp__DbgPrint");
411c2c66affSColin Finck }
412c2c66affSColin Finck }
413c2c66affSColin Finck
414c2c66affSColin Finck typedef struct _test_context
415c2c66affSColin Finck {
416c2c66affSColin Finck DWORD64 BaseAddress;
417c2c66affSColin Finck SIZE_T Index;
418c2c66affSColin Finck } test_context;
419c2c66affSColin Finck
420c2c66affSColin Finck static struct _test_data {
421c2c66affSColin Finck DWORD64 AddressOffset;
422c2c66affSColin Finck ULONG Size;
423c2c66affSColin Finck ULONG Tag;
424c2c66affSColin Finck const char* Name;
425c2c66affSColin Finck } test_data[] = {
426c2c66affSColin Finck /* TODO: Order is based on magic, should find entries based on name, and mark as 'seen' */
427c2c66affSColin Finck { 0x1070, 36, SymTagFunction, "FfsFormat" },
428c2c66affSColin Finck { 0x1010, 32, SymTagFunction, "DllMain" },
429c2c66affSColin Finck { 0x1040, 36, SymTagFunction, "FfsChkdsk" },
430c2c66affSColin Finck
431c2c66affSColin Finck { 0x2100, 0, SymTagPublicSymbol, "__IMPORT_DESCRIPTOR_ntdll" },
432c2c66affSColin Finck { 0x109a, 0, SymTagPublicSymbol, "_DbgPrint" },
433c2c66affSColin Finck { 0x2004, 0, SymTagPublicSymbol, "\x7fntdll_NULL_THUNK_DATA" },
434c2c66affSColin Finck { 0x2000, 0, SymTagPublicSymbol, "__imp__DbgPrint" },
435c2c66affSColin Finck { 0x2114, 0, SymTagPublicSymbol, "__NULL_IMPORT_DESCRIPTOR" },
436c2c66affSColin Finck };
437c2c66affSColin Finck
EnumSymProc(PSYMBOL_INFO pSymInfo,ULONG SymbolSize,PVOID UserContext)438c2c66affSColin Finck static BOOL CALLBACK EnumSymProc(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext)
439c2c66affSColin Finck {
440c2c66affSColin Finck test_context* ctx = UserContext;
441c2c66affSColin Finck
442c2c66affSColin Finck if (ctx->Index < ARRAYSIZE(test_data))
443c2c66affSColin Finck {
444c2c66affSColin Finck ok_ulonglong(pSymInfo->ModBase, ctx->BaseAddress);
445c2c66affSColin Finck ok_ulonglong(pSymInfo->Address, ctx->BaseAddress + test_data[ctx->Index].AddressOffset);
446c2c66affSColin Finck ok_hex(pSymInfo->Tag, test_data[ctx->Index].Tag);
447c2c66affSColin Finck ok_str(pSymInfo->Name, test_data[ctx->Index].Name);
448c2c66affSColin Finck
449c2c66affSColin Finck ctx->Index++;
450c2c66affSColin Finck }
451c2c66affSColin Finck else
452c2c66affSColin Finck {
453c2c66affSColin Finck ok(0, "Out of bounds (%lu), max is: %i!\n", ctx->Index, ARRAYSIZE(test_data));
454c2c66affSColin Finck }
455c2c66affSColin Finck
456c2c66affSColin Finck return TRUE;
457c2c66affSColin Finck }
458c2c66affSColin Finck
test_SymEnumSymbols(HANDLE hProc,DWORD64 BaseAddress)459b8a1a612SMark Jansen static void test_SymEnumSymbols(HANDLE hProc, DWORD64 BaseAddress)
460c2c66affSColin Finck {
461c2c66affSColin Finck BOOL Ret;
462c2c66affSColin Finck test_context ctx;
463c2c66affSColin Finck
464c2c66affSColin Finck ctx.Index = 0;
465b8a1a612SMark Jansen ctx.BaseAddress = BaseAddress;
466c2c66affSColin Finck
467b8a1a612SMark Jansen if (!supports_pdb(hProc, ctx.BaseAddress))
468c2c66affSColin Finck {
469c2c66affSColin Finck skip("dbghelp.dll too old or cannot enumerate symbols!\n");
470c2c66affSColin Finck }
471c2c66affSColin Finck else
472c2c66affSColin Finck {
473c2c66affSColin Finck Ret = SymEnumSymbols(hProc, ctx.BaseAddress, NULL, EnumSymProc, &ctx);
474c2c66affSColin Finck ok_int(Ret, TRUE);
475c2c66affSColin Finck ok_int(ctx.Index, ARRAYSIZE(test_data));
476c2c66affSColin Finck }
477c2c66affSColin Finck }
478c2c66affSColin Finck
479184255ffSAndreas Maier typedef struct _symregcallback_context
480184255ffSAndreas Maier {
481184255ffSAndreas Maier UINT idx;
482184255ffSAndreas Maier BOOL isANSI;
483184255ffSAndreas Maier } symregcallback_context;
484184255ffSAndreas Maier
485184255ffSAndreas Maier static struct _symregcallback_test_data {
486184255ffSAndreas Maier ULONG ActionCode;
487184255ffSAndreas Maier } symregcallback_test_data[] = {
488184255ffSAndreas Maier { CBA_DEFERRED_SYMBOL_LOAD_CANCEL },
489184255ffSAndreas Maier { CBA_DEFERRED_SYMBOL_LOAD_START },
490184255ffSAndreas Maier { CBA_READ_MEMORY },
491184255ffSAndreas Maier { CBA_DEFERRED_SYMBOL_LOAD_PARTIAL },
492184255ffSAndreas Maier { CBA_DEFERRED_SYMBOL_LOAD_COMPLETE }
493184255ffSAndreas Maier };
494184255ffSAndreas Maier
SymRegisterCallback64Proc(HANDLE hProcess,ULONG ActionCode,ULONG64 CallbackData,ULONG64 UserContext)495184255ffSAndreas Maier static BOOL CALLBACK SymRegisterCallback64Proc(
496184255ffSAndreas Maier HANDLE hProcess,
497184255ffSAndreas Maier ULONG ActionCode,
498184255ffSAndreas Maier ULONG64 CallbackData,
499184255ffSAndreas Maier ULONG64 UserContext)
500184255ffSAndreas Maier {
501184255ffSAndreas Maier symregcallback_context *ctx;
502184255ffSAndreas Maier ctx = (symregcallback_context*)(ULONG_PTR)UserContext;
503184255ffSAndreas Maier
504184255ffSAndreas Maier if (ctx->idx > sizeof(symregcallback_test_data))
505184255ffSAndreas Maier {
506184255ffSAndreas Maier ok(FALSE, "SymRegisterCallback64Proc: Too many calls.\n");
507184255ffSAndreas Maier }
508184255ffSAndreas Maier else
509184255ffSAndreas Maier {
510184255ffSAndreas Maier ok(ActionCode == symregcallback_test_data[ctx->idx].ActionCode,
511184255ffSAndreas Maier "ActionCode (idx %u) expected %u, got %u\n",
512184255ffSAndreas Maier ctx->idx, symregcallback_test_data[ctx->idx].ActionCode, ActionCode);
513184255ffSAndreas Maier }
514184255ffSAndreas Maier ctx->idx++;
515184255ffSAndreas Maier
516184255ffSAndreas Maier return FALSE;
517184255ffSAndreas Maier }
518184255ffSAndreas Maier
test_SymRegCallback(HANDLE hProc,const char * szModuleName,BOOL testANSI)519184255ffSAndreas Maier static void test_SymRegCallback(HANDLE hProc, const char* szModuleName, BOOL testANSI)
520184255ffSAndreas Maier {
521184255ffSAndreas Maier BOOL Ret;
522184255ffSAndreas Maier DWORD dwErr;
523184255ffSAndreas Maier ULONG64 BaseAddress;
524184255ffSAndreas Maier symregcallback_context ctx;
525184255ffSAndreas Maier
526184255ffSAndreas Maier ctx.idx = 0;
527184255ffSAndreas Maier ctx.isANSI = testANSI;
528184255ffSAndreas Maier
529b8a1a612SMark Jansen if (!init_sym(FALSE))
530184255ffSAndreas Maier return;
531184255ffSAndreas Maier
532184255ffSAndreas Maier if (testANSI)
533184255ffSAndreas Maier {
534184255ffSAndreas Maier Ret = SymRegisterCallback64(hProc, SymRegisterCallback64Proc, (ULONG_PTR)&ctx);
535184255ffSAndreas Maier }
536184255ffSAndreas Maier else
537184255ffSAndreas Maier {
538c296ee51SMark Jansen Ret = SymRegisterCallbackW64(hProc, SymRegisterCallback64Proc, (ULONG_PTR)&ctx);
539c296ee51SMark Jansen if (g_SymRegisterCallbackW64NotFound)
540184255ffSAndreas Maier {
541c296ee51SMark Jansen skip("SymRegisterCallbackW64 not found in dbghelp.dll\n");
542184255ffSAndreas Maier return;
543184255ffSAndreas Maier }
544184255ffSAndreas Maier }
545184255ffSAndreas Maier
546184255ffSAndreas Maier ok_int(Ret, TRUE);
547184255ffSAndreas Maier if (!Ret)
548184255ffSAndreas Maier return;
549184255ffSAndreas Maier
550184255ffSAndreas Maier SetLastError(ERROR_SUCCESS);
551184255ffSAndreas Maier BaseAddress = SymLoadModule64(hProc, NULL, szModuleName, NULL, 0x600000, 0);
552184255ffSAndreas Maier dwErr = GetLastError();
553184255ffSAndreas Maier
554184255ffSAndreas Maier ok_ulonglong(BaseAddress, 0x600000);
555184255ffSAndreas Maier ok_hex(dwErr, ERROR_SUCCESS);
556184255ffSAndreas Maier
557184255ffSAndreas Maier /* this is what we want to test ... we expect 5 calls */
558184255ffSAndreas Maier ok_int(ctx.idx, 5);
559184255ffSAndreas Maier
560184255ffSAndreas Maier deinit_sym();
561184255ffSAndreas Maier }
562c2c66affSColin Finck
START_TEST(pdb)563c2c66affSColin Finck START_TEST(pdb)
564c2c66affSColin Finck {
565c2c66affSColin Finck char szDllName[MAX_PATH];
566b8a1a612SMark Jansen char szDllPath[MAX_PATH], szOldDir[MAX_PATH];
567b8a1a612SMark Jansen HMODULE hMod;
568b8a1a612SMark Jansen DWORD64 BaseAddress;
569b8a1a612SMark Jansen DWORD dwErr, Options;
570c2c66affSColin Finck
571b8a1a612SMark Jansen Options = SymGetOptions();
572c2c66affSColin Finck Options &= ~(SYMOPT_UNDNAME);
573c2c66affSColin Finck //Options |= SYMOPT_DEBUG;
574c2c66affSColin Finck SymSetOptions(Options);
575c2c66affSColin Finck
576b8a1a612SMark Jansen if (!extract_msvc_dll(szDllName, szDllPath))
577c2c66affSColin Finck {
578c2c66affSColin Finck ok(0, "Failed extracting files\n");
579c2c66affSColin Finck return;
580c2c66affSColin Finck }
581c2c66affSColin Finck
582184255ffSAndreas Maier init_dbghelp_version();
583184255ffSAndreas Maier
584522e9f6dSVictor Perevertkin /* Register the failure hook using the magic name '__pfnDliFailureHook2'. */
585522e9f6dSVictor Perevertkin __pfnDliFailureHook2 = DliFailHook;
586522e9f6dSVictor Perevertkin
587b8a1a612SMark Jansen if (init_sym(FALSE))
588b8a1a612SMark Jansen {
589b8a1a612SMark Jansen SetLastError(ERROR_SUCCESS);
590b8a1a612SMark Jansen BaseAddress = SymLoadModule64(proc(), NULL, szDllName, NULL, 0x600000, 0);
591b8a1a612SMark Jansen dwErr = GetLastError();
592b8a1a612SMark Jansen
593b8a1a612SMark Jansen ok_ulonglong(BaseAddress, 0x600000);
594b8a1a612SMark Jansen ok_hex(dwErr, ERROR_SUCCESS);
595b8a1a612SMark Jansen
596b8a1a612SMark Jansen if (BaseAddress == 0x600000)
597b8a1a612SMark Jansen {
598b8a1a612SMark Jansen trace("Module loaded by SymLoadModule64\n");
599b8a1a612SMark Jansen test_SymFromName(proc(), BaseAddress);
600b8a1a612SMark Jansen test_SymFromAddr(proc(), BaseAddress);
601b8a1a612SMark Jansen test_SymEnumSymbols(proc(), BaseAddress);
602b8a1a612SMark Jansen }
603b8a1a612SMark Jansen
604b8a1a612SMark Jansen deinit_sym();
605b8a1a612SMark Jansen }
606b8a1a612SMark Jansen
607b8a1a612SMark Jansen /* This needs to load the module by itself */
608184255ffSAndreas Maier test_SymRegCallback(proc(), szDllName, TRUE);
609184255ffSAndreas Maier test_SymRegCallback(proc(), szDllName, FALSE);
610c2c66affSColin Finck
611b8a1a612SMark Jansen hMod = LoadLibraryA(szDllName);
612b8a1a612SMark Jansen if (hMod)
613b8a1a612SMark Jansen {
614b8a1a612SMark Jansen BaseAddress = (DWORD64)(DWORD_PTR)hMod;
615b8a1a612SMark Jansen /* Make sure we can find the pdb */
616b8a1a612SMark Jansen GetCurrentDirectoryA(_countof(szOldDir), szOldDir);
617b8a1a612SMark Jansen SetCurrentDirectoryA(szDllPath);
618b8a1a612SMark Jansen /* Invade process */
619b8a1a612SMark Jansen if (init_sym(TRUE))
620b8a1a612SMark Jansen {
621b8a1a612SMark Jansen trace("Module loaded by LoadLibraryA\n");
622b8a1a612SMark Jansen test_SymFromName(proc(), BaseAddress);
623b8a1a612SMark Jansen test_SymFromAddr(proc(), BaseAddress);
624b8a1a612SMark Jansen test_SymEnumSymbols(proc(), BaseAddress);
625184255ffSAndreas Maier
626b8a1a612SMark Jansen deinit_sym();
627b8a1a612SMark Jansen }
628b8a1a612SMark Jansen /* Restore working dir */
629b8a1a612SMark Jansen SetCurrentDirectoryA(szOldDir);
630b8a1a612SMark Jansen
631b8a1a612SMark Jansen FreeLibrary(hMod);
632b8a1a612SMark Jansen }
633b8a1a612SMark Jansen
634b8a1a612SMark Jansen cleanup_msvc_dll();
635c2c66affSColin Finck }
636