/* * IMAGEHLP library * * Copyright 1998 Patrik Stridvall * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include "windef.h" #include "winbase.h" #include "winternl.h" #include "winerror.h" #include "wine/debug.h" #include "imagehlp.h" WINE_DEFAULT_DEBUG_CHANNEL(imagehlp); static WORD CalcCheckSum(DWORD StartValue, LPVOID BaseAddress, DWORD WordCount); /*********************************************************************** * BindImage (IMAGEHLP.@) */ BOOL WINAPI BindImage( PCSTR ImageName, PCSTR DllPath, PCSTR SymbolPath) { return BindImageEx(0, ImageName, DllPath, SymbolPath, NULL); } /*********************************************************************** * BindImageEx (IMAGEHLP.@) */ BOOL WINAPI BindImageEx(DWORD flags, const char *module, const char *dll_path, const char *symbol_path, PIMAGEHLP_STATUS_ROUTINE cb) { const IMAGE_IMPORT_DESCRIPTOR *import; LOADED_IMAGE image; ULONG size; TRACE("flags %#x, module %s, dll_path %s, symbol_path %s, cb %p.\n", flags, debugstr_a(module), debugstr_a(dll_path), debugstr_a(symbol_path), cb); if (!(flags & BIND_NO_UPDATE)) FIXME("Image modification is not implemented.\n"); if (flags & ~BIND_NO_UPDATE) FIXME("Ignoring flags %#x.\n", flags); if (!MapAndLoad(module, dll_path, &image, TRUE, TRUE)) return FALSE; if (!(import = ImageDirectoryEntryToData(image.MappedAddress, FALSE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size))) { UnMapAndLoad(&image); return TRUE; /* no imports */ } if (image.FileHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC) { FIXME("Unhandled architecture %#x.\n", image.FileHeader->OptionalHeader.Magic); UnMapAndLoad(&image); return TRUE; } for (; import->Name && import->FirstThunk; ++import) { char full_path[MAX_PATH]; IMAGE_THUNK_DATA *thunk; const char *dll_name; DWORD thunk_rva; if (!(dll_name = ImageRvaToVa(image.FileHeader, image.MappedAddress, import->Name, 0))) { ERR("Failed to get VA for import name RVA %#x.\n", import->Name); continue; } if (cb) cb(BindImportModule, module, dll_name, 0, 0); if (!SearchPathA(dll_path, dll_name, 0, sizeof(full_path), full_path, 0)) { ERR("Import %s was not found.\n", debugstr_a(dll_path)); continue; } thunk_rva = import->OriginalFirstThunk ? import->OriginalFirstThunk : import->FirstThunk; if (!(thunk = ImageRvaToVa(image.FileHeader, image.MappedAddress, thunk_rva, 0))) { ERR("Failed to get VA for import thunk RVA %#x.\n", thunk_rva); continue; } for (; thunk->u1.Ordinal; ++thunk) { if (IMAGE_SNAP_BY_ORDINAL(thunk->u1.Ordinal)) { /* FIXME: We apparently need to subtract the actual module's * ordinal base. */ FIXME("Ordinal imports are not implemented.\n"); } else { IMAGE_IMPORT_BY_NAME *name; if (!(name = ImageRvaToVa(image.FileHeader, image.MappedAddress, thunk->u1.AddressOfData, 0))) { ERR("Failed to get VA for name RVA %#x.\n", thunk->u1.AddressOfData); continue; } if (cb) cb(BindImportProcedure, module, full_path, 0, (ULONG_PTR)name->Name); } } } UnMapAndLoad(&image); return TRUE; } /*********************************************************************** * CheckSum (internal) */ static WORD CalcCheckSum( DWORD StartValue, LPVOID BaseAddress, DWORD WordCount) { LPWORD Ptr; DWORD Sum; DWORD i; Sum = StartValue; Ptr = (LPWORD)BaseAddress; for (i = 0; i < WordCount; i++) { Sum += *Ptr; if (HIWORD(Sum) != 0) { Sum = LOWORD(Sum) + HIWORD(Sum); } Ptr++; } return (WORD)(LOWORD(Sum) + HIWORD(Sum)); } /*********************************************************************** * CheckSumMappedFile (IMAGEHLP.@) */ PIMAGE_NT_HEADERS WINAPI CheckSumMappedFile( LPVOID BaseAddress, DWORD FileLength, LPDWORD HeaderSum, LPDWORD CheckSum) { PIMAGE_NT_HEADERS header; DWORD CalcSum; DWORD HdrSum; TRACE("(%p, %d, %p, %p)\n", BaseAddress, FileLength, HeaderSum, CheckSum); CalcSum = CalcCheckSum(0, BaseAddress, (FileLength + 1) / sizeof(WORD)); header = RtlImageNtHeader(BaseAddress); if (!header) return NULL; *HeaderSum = HdrSum = header->OptionalHeader.CheckSum; /* Subtract image checksum from calculated checksum. */ /* fix low word of checksum */ if (LOWORD(CalcSum) >= LOWORD(HdrSum)) { CalcSum -= LOWORD(HdrSum); } else { CalcSum = ((LOWORD(CalcSum) - LOWORD(HdrSum)) & 0xFFFF) - 1; } /* fix high word of checksum */ if (LOWORD(CalcSum) >= HIWORD(HdrSum)) { CalcSum -= HIWORD(HdrSum); } else { CalcSum = ((LOWORD(CalcSum) - HIWORD(HdrSum)) & 0xFFFF) - 1; } /* add file length */ CalcSum += FileLength; *CheckSum = CalcSum; return header; } /*********************************************************************** * MapFileAndCheckSumA (IMAGEHLP.@) */ DWORD WINAPI MapFileAndCheckSumA( PCSTR Filename, PDWORD HeaderSum, PDWORD CheckSum) { HANDLE hFile; HANDLE hMapping; LPVOID BaseAddress; DWORD FileLength; TRACE("(%s, %p, %p): stub\n", debugstr_a(Filename), HeaderSum, CheckSum ); hFile = CreateFileA(Filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (hFile == INVALID_HANDLE_VALUE) { return CHECKSUM_OPEN_FAILURE; } hMapping = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); if (hMapping == 0) { CloseHandle(hFile); return CHECKSUM_MAP_FAILURE; } BaseAddress = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0); if (BaseAddress == 0) { CloseHandle(hMapping); CloseHandle(hFile); return CHECKSUM_MAPVIEW_FAILURE; } FileLength = GetFileSize(hFile, NULL); CheckSumMappedFile(BaseAddress, FileLength, HeaderSum, CheckSum); UnmapViewOfFile(BaseAddress); CloseHandle(hMapping); CloseHandle(hFile); return 0; } /*********************************************************************** * MapFileAndCheckSumW (IMAGEHLP.@) */ DWORD WINAPI MapFileAndCheckSumW( PCWSTR Filename, PDWORD HeaderSum, PDWORD CheckSum) { HANDLE hFile; HANDLE hMapping; LPVOID BaseAddress; DWORD FileLength; TRACE("(%s, %p, %p): stub\n", debugstr_w(Filename), HeaderSum, CheckSum ); hFile = CreateFileW(Filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (hFile == INVALID_HANDLE_VALUE) { return CHECKSUM_OPEN_FAILURE; } hMapping = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); if (hMapping == 0) { CloseHandle(hFile); return CHECKSUM_MAP_FAILURE; } BaseAddress = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0); if (BaseAddress == 0) { CloseHandle(hMapping); CloseHandle(hFile); return CHECKSUM_MAPVIEW_FAILURE; } FileLength = GetFileSize(hFile, NULL); CheckSumMappedFile(BaseAddress, FileLength, HeaderSum, CheckSum); UnmapViewOfFile(BaseAddress); CloseHandle(hMapping); CloseHandle(hFile); return 0; } /*********************************************************************** * ReBaseImage (IMAGEHLP.@) */ BOOL WINAPI 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) { FIXME( "(%s, %s, %d, %d, %d, %d, %p, %p, %p, %p, %d): stub\n", debugstr_a(CurrentImageName),debugstr_a(SymbolPath), fReBase, fRebaseSysfileOk, fGoingDown, CheckImageSize, OldImageSize, OldImageBase, NewImageSize, NewImageBase, TimeStamp ); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } /*********************************************************************** * RemovePrivateCvSymbolic (IMAGEHLP.@) */ BOOL WINAPI RemovePrivateCvSymbolic( PCHAR DebugData, PCHAR *NewDebugData, ULONG *NewDebugSize) { FIXME("(%p, %p, %p): stub\n", DebugData, NewDebugData, NewDebugSize ); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } /*********************************************************************** * RemoveRelocations (IMAGEHLP.@) */ VOID WINAPI RemoveRelocations(PCHAR ImageName) { FIXME("(%p): stub\n", ImageName); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); } /*********************************************************************** * SplitSymbols (IMAGEHLP.@) */ BOOL WINAPI SplitSymbols( PSTR ImageName, PCSTR SymbolsPath, PSTR SymbolFilePath, ULONG Flags) { FIXME("(%s, %s, %s, %d): stub\n", debugstr_a(ImageName), debugstr_a(SymbolsPath), debugstr_a(SymbolFilePath), Flags ); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } /*********************************************************************** * UpdateDebugInfoFile (IMAGEHLP.@) */ BOOL WINAPI UpdateDebugInfoFile( PCSTR ImageFileName, PCSTR SymbolPath, PSTR DebugFilePath, PIMAGE_NT_HEADERS32 NtHeaders) { FIXME("(%s, %s, %s, %p): stub\n", debugstr_a(ImageFileName), debugstr_a(SymbolPath), debugstr_a(DebugFilePath), NtHeaders ); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } /*********************************************************************** * UpdateDebugInfoFileEx (IMAGEHLP.@) */ BOOL WINAPI UpdateDebugInfoFileEx( PCSTR ImageFileName, PCSTR SymbolPath, PSTR DebugFilePath, PIMAGE_NT_HEADERS32 NtHeaders, DWORD OldChecksum) { FIXME("(%s, %s, %s, %p, %d): stub\n", debugstr_a(ImageFileName), debugstr_a(SymbolPath), debugstr_a(DebugFilePath), NtHeaders, OldChecksum ); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; }