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