1 /*
2 * IMAGEHLP library
3 *
4 * Copyright 1998 Patrik Stridvall
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include <stdarg.h>
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winternl.h"
26 #include "winerror.h"
27 #include "wine/debug.h"
28 #include "imagehlp.h"
29
30 WINE_DEFAULT_DEBUG_CHANNEL(imagehlp);
31
32 static WORD CalcCheckSum(DWORD StartValue, LPVOID BaseAddress, DWORD WordCount);
33
34 /***********************************************************************
35 * BindImage (IMAGEHLP.@)
36 *
37 * NOTES
38 * See BindImageEx
39 */
BindImage(PCSTR ImageName,PCSTR DllPath,PCSTR SymbolPath)40 BOOL WINAPI BindImage(
41 PCSTR ImageName, PCSTR DllPath, PCSTR SymbolPath)
42 {
43 return BindImageEx(0, ImageName, DllPath, SymbolPath, NULL);
44 }
45
46 /***********************************************************************
47 * BindImageEx (IMAGEHLP.@)
48 *
49 * Compute the virtual address of each function imported by a PE image
50 *
51 * PARAMS
52 *
53 * Flags [in] Bind options
54 * ImageName [in] File name of the image to be bound
55 * DllPath [in] Root of the fallback search path in case the ImageName file cannot be opened
56 * SymbolPath [in] Symbol file root search path
57 * StatusRoutine [in] Pointer to a status routine which will be called during the binding process
58 *
59 * RETURNS
60 * Success: TRUE
61 * Failure: FALSE
62 *
63 * NOTES
64 * Binding is not implemented yet, so far this function only enumerates
65 * all imported dlls/functions and returns TRUE.
66 */
BindImageEx(DWORD Flags,PCSTR ImageName,PCSTR DllPath,PCSTR SymbolPath,PIMAGEHLP_STATUS_ROUTINE StatusRoutine)67 BOOL WINAPI BindImageEx(
68 DWORD Flags, PCSTR ImageName, PCSTR DllPath, PCSTR SymbolPath,
69 PIMAGEHLP_STATUS_ROUTINE StatusRoutine)
70 {
71 LOADED_IMAGE loaded_image;
72 const IMAGE_IMPORT_DESCRIPTOR *import_desc;
73 ULONG size;
74
75 FIXME("(%d, %s, %s, %s, %p): semi-stub\n",
76 Flags, debugstr_a(ImageName), debugstr_a(DllPath),
77 debugstr_a(SymbolPath), StatusRoutine
78 );
79
80 if (!(MapAndLoad(ImageName, DllPath, &loaded_image, TRUE, TRUE))) return FALSE;
81
82 if (!(import_desc = RtlImageDirectoryEntryToData((HMODULE)loaded_image.MappedAddress, FALSE,
83 IMAGE_DIRECTORY_ENTRY_IMPORT, &size)))
84 {
85 UnMapAndLoad(&loaded_image);
86 return TRUE; /* No imported modules means nothing to bind, so we're done. */
87 }
88
89 /* FIXME: Does native imagehlp support both 32-bit and 64-bit PE executables? */
90 #ifdef _WIN64
91 if (loaded_image.FileHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC)
92 #else
93 if (loaded_image.FileHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
94 #endif
95 {
96 FIXME("Wrong architecture in PE header, unable to enumerate imports\n");
97 UnMapAndLoad(&loaded_image);
98 return TRUE;
99 }
100
101 for (; import_desc->Name && import_desc->FirstThunk; ++import_desc)
102 {
103 IMAGE_THUNK_DATA *thunk;
104 char dll_fullname[MAX_PATH];
105 const char *dll_name;
106
107 if (!(dll_name = ImageRvaToVa(loaded_image.FileHeader, loaded_image.MappedAddress,
108 import_desc->Name, 0)))
109 {
110 UnMapAndLoad(&loaded_image);
111 SetLastError(ERROR_INVALID_ACCESS); /* FIXME */
112 return FALSE;
113 }
114
115 if (StatusRoutine)
116 StatusRoutine(BindImportModule, ImageName, dll_name, 0, 0);
117
118 if (!SearchPathA(DllPath, dll_name, 0, sizeof(dll_fullname), dll_fullname, 0))
119 {
120 UnMapAndLoad(&loaded_image);
121 SetLastError(ERROR_FILE_NOT_FOUND);
122 return FALSE;
123 }
124
125 if (!(thunk = ImageRvaToVa(loaded_image.FileHeader, loaded_image.MappedAddress,
126 import_desc->OriginalFirstThunk ? import_desc->OriginalFirstThunk :
127 import_desc->FirstThunk, 0)))
128 {
129 ERR("Can't grab thunk data of %s, going to next imported DLL\n", dll_name);
130 continue;
131 }
132
133 for (; thunk->u1.Ordinal; ++thunk)
134 {
135 /* Ignoring ordinal imports for now */
136 if(!IMAGE_SNAP_BY_ORDINAL(thunk->u1.Ordinal))
137 {
138 IMAGE_IMPORT_BY_NAME *iibn;
139
140 if (!(iibn = ImageRvaToVa(loaded_image.FileHeader, loaded_image.MappedAddress,
141 thunk->u1.AddressOfData, 0)))
142 {
143 ERR("Can't grab import by name info, skipping to next ordinal\n");
144 continue;
145 }
146
147 if (StatusRoutine)
148 StatusRoutine(BindImportProcedure, ImageName, dll_fullname, 0, (ULONG_PTR)iibn->Name);
149 }
150 }
151 }
152
153 UnMapAndLoad(&loaded_image);
154 return TRUE;
155 }
156
157
158 /***********************************************************************
159 * CheckSum (internal)
160 */
CalcCheckSum(DWORD StartValue,LPVOID BaseAddress,DWORD WordCount)161 static WORD CalcCheckSum(
162 DWORD StartValue, LPVOID BaseAddress, DWORD WordCount)
163 {
164 LPWORD Ptr;
165 DWORD Sum;
166 DWORD i;
167
168 Sum = StartValue;
169 Ptr = (LPWORD)BaseAddress;
170 for (i = 0; i < WordCount; i++)
171 {
172 Sum += *Ptr;
173 if (HIWORD(Sum) != 0)
174 {
175 Sum = LOWORD(Sum) + HIWORD(Sum);
176 }
177 Ptr++;
178 }
179
180 return (WORD)(LOWORD(Sum) + HIWORD(Sum));
181 }
182
183
184 /***********************************************************************
185 * CheckSumMappedFile (IMAGEHLP.@)
186 */
CheckSumMappedFile(LPVOID BaseAddress,DWORD FileLength,LPDWORD HeaderSum,LPDWORD CheckSum)187 PIMAGE_NT_HEADERS WINAPI CheckSumMappedFile(
188 LPVOID BaseAddress, DWORD FileLength,
189 LPDWORD HeaderSum, LPDWORD CheckSum)
190 {
191 PIMAGE_NT_HEADERS header;
192 DWORD CalcSum;
193 DWORD HdrSum;
194
195 TRACE("(%p, %d, %p, %p)\n", BaseAddress, FileLength, HeaderSum, CheckSum);
196
197 CalcSum = CalcCheckSum(0, BaseAddress, (FileLength + 1) / sizeof(WORD));
198 header = RtlImageNtHeader(BaseAddress);
199
200 if (!header)
201 return NULL;
202
203 *HeaderSum = HdrSum = header->OptionalHeader.CheckSum;
204
205 /* Subtract image checksum from calculated checksum. */
206 /* fix low word of checksum */
207 if (LOWORD(CalcSum) >= LOWORD(HdrSum))
208 {
209 CalcSum -= LOWORD(HdrSum);
210 }
211 else
212 {
213 CalcSum = ((LOWORD(CalcSum) - LOWORD(HdrSum)) & 0xFFFF) - 1;
214 }
215
216 /* fix high word of checksum */
217 if (LOWORD(CalcSum) >= HIWORD(HdrSum))
218 {
219 CalcSum -= HIWORD(HdrSum);
220 }
221 else
222 {
223 CalcSum = ((LOWORD(CalcSum) - HIWORD(HdrSum)) & 0xFFFF) - 1;
224 }
225
226 /* add file length */
227 CalcSum += FileLength;
228
229 *CheckSum = CalcSum;
230
231 return header;
232 }
233
234 /***********************************************************************
235 * MapFileAndCheckSumA (IMAGEHLP.@)
236 */
MapFileAndCheckSumA(PCSTR Filename,PDWORD HeaderSum,PDWORD CheckSum)237 DWORD WINAPI MapFileAndCheckSumA(
238 PCSTR Filename, PDWORD HeaderSum, PDWORD CheckSum)
239 {
240 HANDLE hFile;
241 HANDLE hMapping;
242 LPVOID BaseAddress;
243 DWORD FileLength;
244
245 TRACE("(%s, %p, %p): stub\n",
246 debugstr_a(Filename), HeaderSum, CheckSum
247 );
248
249 hFile = CreateFileA(Filename,
250 GENERIC_READ,
251 FILE_SHARE_READ | FILE_SHARE_WRITE,
252 NULL,
253 OPEN_EXISTING,
254 FILE_ATTRIBUTE_NORMAL,
255 0);
256 if (hFile == INVALID_HANDLE_VALUE)
257 {
258 return CHECKSUM_OPEN_FAILURE;
259 }
260
261 hMapping = CreateFileMappingW(hFile,
262 NULL,
263 PAGE_READONLY,
264 0,
265 0,
266 NULL);
267 if (hMapping == 0)
268 {
269 CloseHandle(hFile);
270 return CHECKSUM_MAP_FAILURE;
271 }
272
273 BaseAddress = MapViewOfFile(hMapping,
274 FILE_MAP_READ,
275 0,
276 0,
277 0);
278 if (BaseAddress == 0)
279 {
280 CloseHandle(hMapping);
281 CloseHandle(hFile);
282 return CHECKSUM_MAPVIEW_FAILURE;
283 }
284
285 FileLength = GetFileSize(hFile,
286 NULL);
287
288 CheckSumMappedFile(BaseAddress,
289 FileLength,
290 HeaderSum,
291 CheckSum);
292
293 UnmapViewOfFile(BaseAddress);
294 CloseHandle(hMapping);
295 CloseHandle(hFile);
296
297 return 0;
298 }
299
300 /***********************************************************************
301 * MapFileAndCheckSumW (IMAGEHLP.@)
302 */
MapFileAndCheckSumW(PCWSTR Filename,PDWORD HeaderSum,PDWORD CheckSum)303 DWORD WINAPI MapFileAndCheckSumW(
304 PCWSTR Filename, PDWORD HeaderSum, PDWORD CheckSum)
305 {
306 HANDLE hFile;
307 HANDLE hMapping;
308 LPVOID BaseAddress;
309 DWORD FileLength;
310
311 TRACE("(%s, %p, %p): stub\n",
312 debugstr_w(Filename), HeaderSum, CheckSum
313 );
314
315 hFile = CreateFileW(Filename,
316 GENERIC_READ,
317 FILE_SHARE_READ | FILE_SHARE_WRITE,
318 NULL,
319 OPEN_EXISTING,
320 FILE_ATTRIBUTE_NORMAL,
321 0);
322 if (hFile == INVALID_HANDLE_VALUE)
323 {
324 return CHECKSUM_OPEN_FAILURE;
325 }
326
327 hMapping = CreateFileMappingW(hFile,
328 NULL,
329 PAGE_READONLY,
330 0,
331 0,
332 NULL);
333 if (hMapping == 0)
334 {
335 CloseHandle(hFile);
336 return CHECKSUM_MAP_FAILURE;
337 }
338
339 BaseAddress = MapViewOfFile(hMapping,
340 FILE_MAP_READ,
341 0,
342 0,
343 0);
344 if (BaseAddress == 0)
345 {
346 CloseHandle(hMapping);
347 CloseHandle(hFile);
348 return CHECKSUM_MAPVIEW_FAILURE;
349 }
350
351 FileLength = GetFileSize(hFile,
352 NULL);
353
354 CheckSumMappedFile(BaseAddress,
355 FileLength,
356 HeaderSum,
357 CheckSum);
358
359 UnmapViewOfFile(BaseAddress);
360 CloseHandle(hMapping);
361 CloseHandle(hFile);
362
363 return 0;
364 }
365
366 /***********************************************************************
367 * ReBaseImage (IMAGEHLP.@)
368 */
ReBaseImage(PCSTR CurrentImageName,PCSTR SymbolPath,BOOL fReBase,BOOL fRebaseSysfileOk,BOOL fGoingDown,ULONG CheckImageSize,ULONG * OldImageSize,ULONG_PTR * OldImageBase,ULONG * NewImageSize,ULONG_PTR * NewImageBase,ULONG TimeStamp)369 BOOL WINAPI ReBaseImage(
370 PCSTR CurrentImageName, PCSTR SymbolPath, BOOL fReBase,
371 BOOL fRebaseSysfileOk, BOOL fGoingDown, ULONG CheckImageSize,
372 ULONG *OldImageSize, ULONG_PTR *OldImageBase, ULONG *NewImageSize,
373 ULONG_PTR *NewImageBase, ULONG TimeStamp)
374 {
375 FIXME(
376 "(%s, %s, %d, %d, %d, %d, %p, %p, %p, %p, %d): stub\n",
377 debugstr_a(CurrentImageName),debugstr_a(SymbolPath), fReBase,
378 fRebaseSysfileOk, fGoingDown, CheckImageSize, OldImageSize,
379 OldImageBase, NewImageSize, NewImageBase, TimeStamp
380 );
381 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
382 return FALSE;
383 }
384
385 /***********************************************************************
386 * RemovePrivateCvSymbolic (IMAGEHLP.@)
387 */
RemovePrivateCvSymbolic(PCHAR DebugData,PCHAR * NewDebugData,ULONG * NewDebugSize)388 BOOL WINAPI RemovePrivateCvSymbolic(
389 PCHAR DebugData, PCHAR *NewDebugData, ULONG *NewDebugSize)
390 {
391 FIXME("(%p, %p, %p): stub\n",
392 DebugData, NewDebugData, NewDebugSize
393 );
394 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
395 return FALSE;
396 }
397
398 /***********************************************************************
399 * RemoveRelocations (IMAGEHLP.@)
400 */
RemoveRelocations(PCHAR ImageName)401 VOID WINAPI RemoveRelocations(PCHAR ImageName)
402 {
403 FIXME("(%p): stub\n", ImageName);
404 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
405 }
406
407 /***********************************************************************
408 * SplitSymbols (IMAGEHLP.@)
409 */
SplitSymbols(PSTR ImageName,PCSTR SymbolsPath,PSTR SymbolFilePath,ULONG Flags)410 BOOL WINAPI SplitSymbols(
411 PSTR ImageName, PCSTR SymbolsPath,
412 PSTR SymbolFilePath, ULONG Flags)
413 {
414 FIXME("(%s, %s, %s, %d): stub\n",
415 debugstr_a(ImageName), debugstr_a(SymbolsPath),
416 debugstr_a(SymbolFilePath), Flags
417 );
418 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
419 return FALSE;
420 }
421
422 /***********************************************************************
423 * UpdateDebugInfoFile (IMAGEHLP.@)
424 */
UpdateDebugInfoFile(PCSTR ImageFileName,PCSTR SymbolPath,PSTR DebugFilePath,PIMAGE_NT_HEADERS32 NtHeaders)425 BOOL WINAPI UpdateDebugInfoFile(
426 PCSTR ImageFileName, PCSTR SymbolPath,
427 PSTR DebugFilePath, PIMAGE_NT_HEADERS32 NtHeaders)
428 {
429 FIXME("(%s, %s, %s, %p): stub\n",
430 debugstr_a(ImageFileName), debugstr_a(SymbolPath),
431 debugstr_a(DebugFilePath), NtHeaders
432 );
433 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
434 return FALSE;
435 }
436
437 /***********************************************************************
438 * UpdateDebugInfoFileEx (IMAGEHLP.@)
439 */
UpdateDebugInfoFileEx(PCSTR ImageFileName,PCSTR SymbolPath,PSTR DebugFilePath,PIMAGE_NT_HEADERS32 NtHeaders,DWORD OldChecksum)440 BOOL WINAPI UpdateDebugInfoFileEx(
441 PCSTR ImageFileName, PCSTR SymbolPath, PSTR DebugFilePath,
442 PIMAGE_NT_HEADERS32 NtHeaders, DWORD OldChecksum)
443 {
444 FIXME("(%s, %s, %s, %p, %d): stub\n",
445 debugstr_a(ImageFileName), debugstr_a(SymbolPath),
446 debugstr_a(DebugFilePath), NtHeaders, OldChecksum
447 );
448 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
449 return FALSE;
450 }
451