xref: /reactos/dll/win32/imagehlp/modify.c (revision bee818a2)
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