This one is for Steven... 18 months later, I kept my promise ;) - BindImage & friends refactoring of my original code. Fixed two or three dozen bugs, stopped making assumptions about everything, actually checked for failure, used dynamic allocation instead of 32 static structures, fixed a lot of broken code, fixed some helper functions, made the code as 64-bit compatible as I could (checked with msvc WP64 + prefast). - Remove internal.c and use NDK instead - Remove debug.c and symbol.c like WINE have done - Rewrite the entire exports file to update it for XP. Forward almost all the functions to dbghelp, like WINE have done (note: windows DLL used delayed imports instead). - Cleanup source to add implemented/unimplemented tags, source header, and precompiled header. - Sync with latest code from WINE.
Tested with Quicken 2004 & its patches (which make extensive use of BindImage) as well as random bindings of some applications on my disk. Worked perfectly in Windows. Modified: trunk/reactos/lib/imagehlp/access.c Deleted: trunk/reactos/lib/imagehlp/debug.c Modified: trunk/reactos/lib/imagehlp/imagehlp.def Modified: trunk/reactos/lib/imagehlp/imagehlp.xml Modified: trunk/reactos/lib/imagehlp/imagehlp_main.c Modified: trunk/reactos/lib/imagehlp/integrity.c Deleted: trunk/reactos/lib/imagehlp/internal.c Modified: trunk/reactos/lib/imagehlp/modify.c Added: trunk/reactos/lib/imagehlp/precomp.h Deleted: trunk/reactos/lib/imagehlp/symbol.c Deleted: trunk/reactos/lib/imagehlp/winehq2ros.patch Modified: trunk/reactos/w32api/include/imagehlp.h Modified: trunk/reactos/w32api/include/winnt.h _____
Modified: trunk/reactos/lib/imagehlp/access.c --- trunk/reactos/lib/imagehlp/access.c 2005-11-06 01:24:21 UTC (rev 19024) +++ trunk/reactos/lib/imagehlp/access.c 2005-11-06 10:48:14 UTC (rev 19025) @@ -1,564 +1,634 @@
/* - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: Imagehlp Libary + * FILE: lib/imagehlp/access.c + * PURPOSE: Image (un)load/mapping and data directory/section access + * PROGRAMMER: Patrik Stridvall */
-#include <stdarg.h> -#include <string.h> -#include "windef.h" -#include "winbase.h" -#include "winnt.h" -#include "winerror.h" -#include "wine/debug.h" -#include "imagehlp.h" +/* INCLUDES ******************************************************************/
-/* Couple of Hacks */ -extern inline DWORD WINAPI GetLastError(void) +#include "precomp.h" + +//#define NDEBUG +#include <debug.h> + +/* DATA **********************************************************************/ + +BOOLEAN DllListInitialized; +LIST_ENTRY ImageLoadListHead; + +/* FUNCTIONS *****************************************************************/ + +PVOID +IMAGEAPI +ImageDirectoryEntryToData32(PVOID Base, + BOOLEAN MappedAsImage, + USHORT DirectoryEntry, + PULONG Size, + PIMAGE_SECTION_HEADER *FoundHeader OPTIONAL, + PIMAGE_FILE_HEADER FileHeader, + PIMAGE_OPTIONAL_HEADER OptionalHeader) { - DWORD ret; - __asm__ __volatile__( ".byte 0x64\n\tmovl 0x60,%0" : "=r" (ret) ); - return ret; -} + ULONG i; + PIMAGE_SECTION_HEADER CurrentSection; + ULONG DirectoryEntryVA;
-#define InitializeListHead(ListHead) (\ - (ListHead)->Flink = (ListHead)->Blink = (ListHead)) + /* Check if this entry is invalid */ + if (DirectoryEntry >= OptionalHeader->NumberOfRvaAndSizes) + { + /* Nothing found */ + *Size = 0; + return NULL; + }
-#define InsertTailList(ListHead,Entry) {\ - PLIST_ENTRY _EX_Blink;\ - PLIST_ENTRY _EX_ListHead;\ - _EX_ListHead = (ListHead);\ - _EX_Blink = _EX_ListHead->Blink;\ - (Entry)->Flink = _EX_ListHead;\ - (Entry)->Blink = _EX_Blink;\ - _EX_Blink->Flink = (Entry);\ - _EX_ListHead->Blink = (Entry);\ + /* Get the VA of the Directory Requested */ + DirectoryEntryVA = OptionalHeader->DataDirectory[DirectoryEntry].VirtualAddress; + if (!DirectoryEntryVA) + { + /* It doesn't exist */ + *Size = 0; + return NULL; }
-WINE_DEFAULT_DEBUG_CHANNEL(imagehlp); + /* Get the size of the Directory Requested */ + *Size = OptionalHeader->DataDirectory[DirectoryEntry].Size;
-/********************************************************************** * - * Data - */ + /* Check if it was mapped as an image or if the entry is within the headers */ + if ((MappedAsImage) || (DirectoryEntryVA < OptionalHeader->SizeOfHeaders)) + { + /* No header found */ + if (FoundHeader) *FoundHeader = NULL; + + /* And simply return the VA */ + return (PVOID)((ULONG_PTR)Base + DirectoryEntryVA); + }
-static PLOADED_IMAGE IMAGEHLP_pFirstLoadedImage=NULL; -static PLOADED_IMAGE IMAGEHLP_pLastLoadedImage=NULL; + /* Read the first Section */ + CurrentSection = (PIMAGE_SECTION_HEADER)((ULONG_PTR)OptionalHeader + + FileHeader->SizeOfOptionalHeader); + + /* Loop through every section*/ + for (i = 0; i < FileHeader->NumberOfSections; i++) + { + /* If the Directory VA is located inside this section's VA, then this section belongs to this Directory */ + if ((DirectoryEntryVA >= CurrentSection->VirtualAddress) && + (DirectoryEntryVA < (CurrentSection->VirtualAddress + + CurrentSection->SizeOfRawData))) + { + /* Return the section header */ + if (FoundHeader) *FoundHeader = CurrentSection; + return ((PVOID)((ULONG_PTR)Base + + (DirectoryEntryVA - CurrentSection->VirtualAddress) + + CurrentSection->PointerToRawData)); + }
-static LOADED_IMAGE IMAGEHLP_EmptyLoadedImage = { - NULL, /* ModuleName */ - 0, /* hFile */ - NULL, /* MappedAddress */ - NULL, /* FileHeader */ - NULL, /* LastRvaSection */ - 0, /* NumberOfSections */ - NULL, /* Sections */ - 1, /* Characteristics */ - FALSE, /* fSystemImage */ - FALSE, /* fDOSImage */ - { &IMAGEHLP_EmptyLoadedImage.Links, &IMAGEHLP_EmptyLoadedImage.Links }, /* Links */ - 148, /* SizeOfImage; */ -}; + /* Move to the next section */ + CurrentSection++; + }
-extern HANDLE IMAGEHLP_hHeap; -BOOLEAN DllListInitialized; -LIST_ENTRY ImageLoadListHead; - -/********************************************************************** * - * EnumerateLoadedModules (IMAGEHLP.@) - */ -BOOL WINAPI EnumerateLoadedModules( - HANDLE hProcess, - PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback, - PVOID UserContext) -{ - FIXME("(%p, %p, %p): stub\n", - hProcess, EnumLoadedModulesCallback, UserContext - ); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + /* If we got here, then we didn't find anything */ + return NULL; }
-/********************************************************************** * - * GetTimestampForLoadedLibrary (IMAGEHLP.@) +/* + * @unimplemented */ -DWORD WINAPI GetTimestampForLoadedLibrary(HMODULE Module) +DWORD +IMAGEAPI +GetTimestampForLoadedLibrary(HMODULE Module) { - FIXME("(%p): stub\n", Module); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; + UNIMPLEMENTED; + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; }
-/********************************************************************** * - * GetImageConfigInformation (IMAGEHLP.@) +/* + * @unimplemented */ -BOOL WINAPI GetImageConfigInformation( - PLOADED_IMAGE LoadedImage, - PIMAGE_LOAD_CONFIG_DIRECTORY ImageConfigInformation) +BOOL +IMAGEAPI +GetImageConfigInformation(PLOADED_IMAGE LoadedImage, + PIMAGE_LOAD_CONFIG_DIRECTORY ImageConfigInformation) { - FIXME("(%p, %p): stub\n", - LoadedImage, ImageConfigInformation - ); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + UNIMPLEMENTED; + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; }
-/********************************************************************** * - * GetImageUnusedHeaderBytes (IMAGEHLP.@) +/* + * @implemented */ DWORD -WINAPI -GetImageUnusedHeaderBytes( - PLOADED_IMAGE LoadedImage, - LPDWORD SizeUnusedHeaderBytes - ) +IMAGEAPI +GetImageUnusedHeaderBytes(PLOADED_IMAGE LoadedImage, + LPDWORD SizeUnusedHeaderBytes) { - DWORD FirstFreeByte; - PIMAGE_OPTIONAL_HEADER OptionalHeader32 = NULL; - PIMAGE_NT_HEADERS NtHeaders; - ULONG i; + SIZE_T FirstFreeByte; + PIMAGE_OPTIONAL_HEADER OptionalHeader = NULL; + PIMAGE_NT_HEADERS NtHeaders; + ULONG i;
- /* Read the NT Headers */ + /* Read the NT Headers */ NtHeaders = LoadedImage->FileHeader;
- /* Find the first free byte, which is after all the headers and sections */ - FirstFreeByte = (ULONG_PTR)NtHeaders - (ULONG_PTR)LoadedImage->MappedAddress + - FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + - NtHeaders->FileHeader.SizeOfOptionalHeader + - NtHeaders->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER); + /* Find the first free byte, which is after all the headers and sections */ + FirstFreeByte = (ULONG_PTR)NtHeaders - + (ULONG_PTR)LoadedImage->MappedAddress + + FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + + NtHeaders->FileHeader.SizeOfOptionalHeader + + NtHeaders->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
- /* Get the Optional Header */ - OptionalHeader32 = &LoadedImage->FileHeader->OptionalHeader; + /* Get the Optional Header */ + OptionalHeader = &LoadedImage->FileHeader->OptionalHeader;
- /* There is the possibilty that one of the Data Directories is in the PE Header - itself, so we'll need to find such a case and add it to our PE used space */ - for ( i = 0; i<OptionalHeader32->NumberOfRvaAndSizes; i++ ) { - - /* If the VA is less then the size of headers, then the data is inside the PE header */ - if (OptionalHeader32->DataDirectory[i].VirtualAddress < OptionalHeader32->SizeOfHeaders) { - - /* However, make sure it's not 0, which means it doesnt actually exist */ - if (OptionalHeader32->DataDirectory[i].VirtualAddress >= FirstFreeByte) { - - /* Our first empty byte is after this Directory Data then */ - FirstFreeByte = OptionalHeader32->DataDirectory[i].VirtualAddress + - OptionalHeader32->DataDirectory[i].Size; - } + /* + * There is the possibilty that one of the Data Directories is in the PE Header + * itself, so we'll need to find such a case and add it to our PE used space + */ + for (i = 0; i < OptionalHeader->NumberOfRvaAndSizes; i++) + { + /* If the VA is less then the size of headers, then the data is inside the PE header */ + if (OptionalHeader->DataDirectory[i].VirtualAddress < + OptionalHeader->SizeOfHeaders) + { + /* However, make sure it's not 0, which means it doesnt actually exist */ + if (OptionalHeader->DataDirectory[i].VirtualAddress >= + FirstFreeByte) + { + /* Our first empty byte is after this Directory Data then */ + FirstFreeByte = OptionalHeader->DataDirectory[i].VirtualAddress + + OptionalHeader->DataDirectory[i].Size; } } + }
- /* Return the unused Header Bytes */ - *SizeUnusedHeaderBytes = OptionalHeader32->SizeOfHeaders - FirstFreeByte; + /* Return the unused Header Bytes */ + *SizeUnusedHeaderBytes = OptionalHeader->SizeOfHeaders - (DWORD)FirstFreeByte;
- /* And return the first free byte*/ - return FirstFreeByte; + /* And return the first free byte*/ + return (DWORD)FirstFreeByte; }
-/********************************************************************** * - * ImageDirectoryEntryToData (IMAGEHLP.@) +/* + * @implemented */ PVOID -WINAPI -ImageDirectoryEntryToData( - PVOID Base, - BOOLEAN MappedAsImage, - USHORT DirectoryEntry, - PULONG Size - ) +IMAGEAPI +ImageDirectoryEntryToData(PVOID Base, + BOOLEAN MappedAsImage, + USHORT DirectoryEntry, + PULONG Size) { - return ImageDirectoryEntryToDataEx(Base, MappedAsImage, DirectoryEntry, Size, NULL); + /* Let the extended function handle it */ + return ImageDirectoryEntryToDataEx(Base, + MappedAsImage, + DirectoryEntry, + Size, + NULL); }
-/********************************************************************** * - * RosImageDirectoryEntryToDataEx (IMAGEHLP.@) +/* + * @implemented */ PVOID -WINAPI -ImageDirectoryEntryToDataEx ( - IN PVOID Base, - IN BOOLEAN MappedAsImage, - IN USHORT DirectoryEntry, - OUT PULONG Size, - OUT PIMAGE_SECTION_HEADER *FoundSection OPTIONAL - ) +IMAGEAPI +ImageDirectoryEntryToDataEx(IN PVOID Base, + IN BOOLEAN MappedAsImage, + IN USHORT DirectoryEntry, + OUT PULONG Size, + OUT PIMAGE_SECTION_HEADER *FoundSection OPTIONAL) { - PIMAGE_NT_HEADERS NtHeader; - PIMAGE_FILE_HEADER FileHeader; - PIMAGE_OPTIONAL_HEADER OptionalHeader; + PIMAGE_NT_HEADERS NtHeader; + PIMAGE_FILE_HEADER FileHeader; + PIMAGE_OPTIONAL_HEADER OptionalHeader;
+ /* Get the optional header ourselves */ NtHeader = ImageNtHeader(Base); FileHeader = &NtHeader->FileHeader; OptionalHeader = &NtHeader->OptionalHeader;
- return (ImageDirectoryEntryToData32(Base, - MappedAsImage, - DirectoryEntry, - Size, - FoundSection, - FileHeader, - OptionalHeader)); + /* FIXME: Read image type and call appropriate function (32, 64, ROM) */ + return ImageDirectoryEntryToData32(Base, + MappedAsImage, + DirectoryEntry, + Size, + FoundSection, + FileHeader, + OptionalHeader); }
-/********************************************************************** * - * RosImageDirectoryEntryToDataEx (IMAGEHLP.@) +/* + * @implemented */ -PVOID -STDCALL -ImageDirectoryEntryToData32 ( - PVOID Base, - BOOLEAN MappedAsImage, - USHORT DirectoryEntry, - PULONG Size, - PIMAGE_SECTION_HEADER *FoundHeader OPTIONAL, - PIMAGE_FILE_HEADER FileHeader, - PIMAGE_OPTIONAL_HEADER OptionalHeader - ) +PLOADED_IMAGE +IMAGEAPI +ImageLoad(LPSTR DllName, + LPSTR DllPath) { - ULONG i; - PIMAGE_SECTION_HEADER CurrentSection; - ULONG DirectoryEntryVA; - - /* Get the VA of the Directory Requested */ - DirectoryEntryVA = OptionalHeader->DataDirectory[DirectoryEntry].VirtualAddress; - - /* Get the size of the Directory Requested */ - *Size = OptionalHeader->DataDirectory[DirectoryEntry].Size; - - /* Return VA if Mapped as Image*/ - if (MappedAsImage || DirectoryEntryVA < OptionalHeader->SizeOfHeaders) { - if (FoundHeader) { - *FoundHeader = NULL; - } - return (PVOID)((ULONG_PTR)Base + DirectoryEntryVA); - } - - /* Read the first Section */ - CurrentSection = (PIMAGE_SECTION_HEADER)((ULONG_PTR)OptionalHeader + FileHeader->SizeOfOptionalHeader); - - /* Loop through every section*/ - for (i=0; i<FileHeader->NumberOfSections; i++) { - - /* If the Directory VA is located inside this section's VA, then this section belongs to this Directory */ - if (DirectoryEntryVA >= CurrentSection->VirtualAddress && - DirectoryEntryVA < CurrentSection->VirtualAddress + CurrentSection->SizeOfRawData) { - if (FoundHeader) { - *FoundHeader = CurrentSection; - } - //return( (PVOID)((ULONG_PTR)Base + (DirectoryAddress - NtSection->VirtualAddress) + NtSection->PointerToRawData) ); - return ((PVOID)((ULONG_PTR)Base + (DirectoryEntryVA - CurrentSection->VirtualAddress) + CurrentSection->PointerToRawData)); - } - ++CurrentSection; - } - return(NULL); -} -/********************************************************************** * - * ImageLoad (IMAGEHLP.@) - */ -PLOADED_IMAGE WINAPI ImageLoad(LPSTR DllName, LPSTR DllPath) -{ - PLIST_ENTRY Head,Next; + PLIST_ENTRY Head, Next; PLOADED_IMAGE LoadedImage; + CHAR Drive[_MAX_DRIVE], Dir[_MAX_DIR], Filename[_MAX_FNAME], Ext[_MAX_EXT]; + BOOL CompleteName = TRUE; + CHAR FullName[MAX_PATH];
- /* Initialize the List Head */ - if (!DllListInitialized) { + /* Initialize the List Head */ + if (!DllListInitialized) + { InitializeListHead(&ImageLoadListHead); DllListInitialized = TRUE; }
- /* Move to the Next DLL */ + /* Move to the Next DLL */ Head = &ImageLoadListHead; Next = Head->Flink; + DPRINT("Trying to find library: %s in current ListHead \n", DllName);
- //FIXME("Trying to find library: %s in current ListHead \n", DllName); + /* Split the path */ + _splitpath(DllName, Drive, Dir, Filename, Ext);
- /* Check if we already Loaded it */ - while (Next != Head) { + /* Check if we only got a name */ + if (!strlen(Drive) && !strlen(Dir)) CompleteName = FALSE;
- /* Get the Loaded Image Structure */ + /* Check if we already Loaded it */ + while (Next != Head) + { + /* Get the Loaded Image Structure */ LoadedImage = CONTAINING_RECORD(Next, LOADED_IMAGE, Links); - //FIXME("Found: %s in current ListHead \n", LoadedImage->ModuleName); + DPRINT("Found: %s in current ListHead \n", LoadedImage->ModuleName);
- /* Check if the Names Match */ - if (!lstrcmpi( DllName, LoadedImage->ModuleName )) { - //FIXME("Found it, returning it\n"); + /* Check if we didn't have a complete name */ + if (!CompleteName) + { + /* Split this module's name */ + _splitpath(LoadedImage->ModuleName, NULL, NULL, Filename, Ext); + + /* Use only the name and extension */ + strcpy(FullName, Filename); + strcat(FullName, Ext); + } + else + { + /* Use the full untouched name */ + strcpy(FullName, LoadedImage->ModuleName); + } + + /* Check if the Names Match */ + if (!_stricmp(DllName, FullName)) + { + DPRINT("Found it, returning it\n"); return LoadedImage; }
- /* Move to next Entry */ + /* Move to next Entry */ Next = Next->Flink; - //FIXME("Moving to next List Entry\n"); }
- //FIXME("Didn't find it...allocating it for you now\n"); + /* Allocate memory for the Structure, and write the Module Name under */ + DPRINT("Didn't find it...allocating it for you now\n"); + LoadedImage = HeapAlloc(IMAGEHLP_hHeap, + 0, + sizeof(*LoadedImage) + strlen(DllName) + 1); + if (LoadedImage) + { + /* Module Name will be after structure */ + LoadedImage->ModuleName = (LPSTR)(LoadedImage + 1);
- /* Allocate memory for the Structure, and write the Module Name under */ - LoadedImage = HeapAlloc(IMAGEHLP_hHeap, 0, sizeof(*LoadedImage) + lstrlen(DllName) + 1); + /* Copy the Module Name */ + strcpy(LoadedImage->ModuleName, DllName);
- /* Module Name will be after structure */ - LoadedImage->ModuleName = (LPSTR)LoadedImage + 1; + /* Now Load it */ + if (MapAndLoad(DllName, DllPath, LoadedImage, TRUE, TRUE)) + { + /* Add it to our list and return it */ + InsertTailList(&ImageLoadListHead, &LoadedImage->Links); + return LoadedImage; + }
- /* Copy the Moduel Name */ - lstrcpy(LoadedImage->ModuleName, DllName); - - /* Now Load it and add it to our list*/ - if (MapAndLoad(DllName, DllPath, LoadedImage, TRUE, TRUE)) { - InsertTailList(&ImageLoadListHead, &LoadedImage->Links); - return LoadedImage; + /* If we're here...there's been a failure */ + HeapFree(IMAGEHLP_hHeap, 0, LoadedImage); + LoadedImage = NULL; } - - /* If we're here...there's been a failure */ - HeapFree(IMAGEHLP_hHeap, 0, LoadedImage); - LoadedImage = NULL; return LoadedImage; }
-/********************************************************************** * - * ImageRvaToSection (IMAGEHLP.@) +/* + * @implemented */ PIMAGE_SECTION_HEADER -WINAPI -ImageRvaToSection( - IN PIMAGE_NT_HEADERS NtHeaders, - IN PVOID Base, - IN ULONG Rva - ) +IMAGEAPI +ImageRvaToSection(IN PIMAGE_NT_HEADERS NtHeaders, + IN PVOID Base, + IN ULONG Rva) { - PIMAGE_SECTION_HEADER Section; + PIMAGE_SECTION_HEADER Section; ULONG i;
- /* Get the First Section */ + /* Get the First Section */ Section = IMAGE_FIRST_SECTION(NtHeaders);
- /* Look through each section and check if the RVA is in between */ - for (i=0; i < NtHeaders->FileHeader.NumberOfSections; i++) { - if (Rva >= Section->VirtualAddress && Rva < Section->VirtualAddress + - Section->SizeOfRawData) { + /* Look through each section */ + for (i = 0; i < NtHeaders->FileHeader.NumberOfSections; i++) + { + /* Check if the RVA is in between */ + if ((Rva >= Section->VirtualAddress) && + (Rva < (Section->VirtualAddress + Section->SizeOfRawData))) + { + /* Return this section */ return Section; - } - ++Section; }
- /* Not Found */ + /* Move to the next section */ + Section++; + } + + /* Not Found */ return NULL; }
-/********************************************************************** * - * ImageNtHeader (IMAGEHLP.@) +/* + * @implemented */ -PIMAGE_NT_HEADERS WINAPI ImageNtHeader(PVOID Base) +PIMAGE_NT_HEADERS +IMAGEAPI +ImageNtHeader(PVOID Base) { - TRACE("(%p)\n", Base); - - /* Just return the e_lfanew Offset VA */ - return (PIMAGE_NT_HEADERS)((LPBYTE)Base + - ((PIMAGE_DOS_HEADER)Base)->e_lfanew); + /* Let RTL do it */ + return RtlImageNtHeader(Base); }
-/********************************************************************** * - * ImageRvaToVa (IMAGEHLP.@) +/* + * @implemented */ PVOID -WINAPI -ImageRvaToVa( - IN PIMAGE_NT_HEADERS NtHeaders, - IN PVOID Base, - IN ULONG Rva, - IN OUT PIMAGE_SECTION_HEADER *LastRvaSection OPTIONAL - ) +IMAGEAPI +ImageRvaToVa(IN PIMAGE_NT_HEADERS NtHeaders, + IN PVOID Base, + IN ULONG Rva, + IN OUT PIMAGE_SECTION_HEADER *LastRvaSection OPTIONAL) { PIMAGE_SECTION_HEADER Section;
- /* Get the Section Associated */ - Section = ImageRvaToSection(NtHeaders, Base, Rva); + /* Get the Section Associated */ + Section = ImageRvaToSection(NtHeaders, Base, Rva);
- /* Return it, if specified */ + /* Return it, if specified */ if (LastRvaSection) *LastRvaSection = Section;
- /* Return the VA */ + /* Return the VA */ return (PVOID)((ULONG_PTR)Base + (Rva - Section->VirtualAddress) + - Section->PointerToRawData); + Section->PointerToRawData); }
-/********************************************************************** * - * ImageUnload (IMAGEHLP.@) +/* + * @implemented */ -BOOL WINAPI ImageUnload(PLOADED_IMAGE pLoadedImage) +BOOL +IMAGEAPI +ImageUnload(PLOADED_IMAGE LoadedImage) { - LIST_ENTRY *pCurrent, *pFind; + /* If the image list isn't empty, remove this entry */ + if (!IsListEmpty(&LoadedImage->Links)) RemoveEntryList(&LoadedImage->Links);
- TRACE("(%p)\n", pLoadedImage); - - if(!IMAGEHLP_pFirstLoadedImage || !pLoadedImage) - { - /* No image loaded or null pointer */ - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } + /* Unmap and unload it */ + UnMapAndLoad(LoadedImage);
- pFind=&pLoadedImage->Links; - pCurrent=&IMAGEHLP_pFirstLoadedImage->Links; - while((pCurrent != pFind) && - (pCurrent != NULL)) - pCurrent = pCurrent->Flink; - if(!pCurrent) - { - /* Not found */ - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } + /* Free the structure */ + HeapFree(IMAGEHLP_hHeap, 0, LoadedImage);
- if(pCurrent->Blink) - pCurrent->Blink->Flink = pCurrent->Flink; - else - IMAGEHLP_pFirstLoadedImage = pCurrent->Flink?CONTAINING_RECORD( - pCurrent->Flink, LOADED_IMAGE, Links):NULL; - - if(pCurrent->Flink) - pCurrent->Flink->Blink = pCurrent->Blink; - else - IMAGEHLP_pLastLoadedImage = pCurrent->Blink?CONTAINING_RECORD( - pCurrent->Blink, LOADED_IMAGE, Links):NULL; - - return FALSE; + /* Return success */ + return TRUE; }
-/********************************************************************** * - * MapAndLoad (IMAGEHLP.@) +/* + * @implemented */ -BOOL WINAPI MapAndLoad( - LPSTR ImageName, - LPSTR DllPath, - PLOADED_IMAGE LoadedImage, - BOOL DotDll, - BOOL ReadOnly) +BOOL +IMAGEAPI +MapAndLoad(LPSTR ImageName, + LPSTR DllPath, + PLOADED_IMAGE LoadedImage, + BOOL DotDll, + BOOL ReadOnly) { - HANDLE hFileMapping = NULL; - PIMAGE_NT_HEADERS NtHeader = NULL; - ULONG Tried = 0; - UCHAR Buffer[MAX_PATH]; - LPSTR FilePart; - LPSTR FileToOpen; + HANDLE hFile; + HANDLE hFileMapping; + ULONG Tried = 0; + UCHAR Buffer[MAX_PATH]; + LPSTR FilePart; + LPSTR FileToOpen; + PIMAGE_NT_HEADERS NtHeader;
- /* So we can add the DLL Path later */ - FileToOpen = ImageName; + /* So we can add the DLL Path later */ + FileToOpen = ImageName; + + /* Assume failure */ + LoadedImage->hFile = INVALID_HANDLE_VALUE;
-TryAgain: - /* Get a handle to the file */ - if ((LoadedImage->hFile = CreateFileA (FileToOpen, - ReadOnly ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE, - ReadOnly ? FILE_SHARE_READ : FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - 0, - NULL)) == INVALID_HANDLE_VALUE) + /* Start open loop */ + while (TRUE) { - /* It Failed, use the DLL Search Path then (make sure we haven't already) */ - if (!Tried) { - Tried = SearchPath(DllPath, ImageName, DotDll ? ".dll" : ".exe", MAX_PATH, Buffer, &FilePart); - if (Tried) { - FileToOpen = Buffer; - goto TryAgain; + /* Get a handle to the file */ + hFile = CreateFileA(FileToOpen, + ReadOnly ? GENERIC_READ : + GENERIC_READ | GENERIC_WRITE, + ReadOnly ? FILE_SHARE_READ : + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + /* Check if we already tried this once */ + if (!Tried) + { + /* We didn't do do a path search now */ + Tried = SearchPath(DllPath, + ImageName, + DotDll ? ".dll" : ".exe", + MAX_PATH, + Buffer, + &FilePart); + + /* Check if it was successful */ + if (Tried && (Tried < MAX_PATH)) + { + /* Change the filename to use, and try again */ + FileToOpen = Buffer; + continue; + } } + + /* Fail */ + return FALSE; } - /* Fail */ - return FALSE; - }
- /* Create the File Mapping */ - if (!(hFileMapping = CreateFileMappingA (LoadedImage->hFile, - NULL, - ReadOnly ? PAGE_READONLY : PAGE_READWRITE, - 0, - 0, - NULL))) - { - DWORD dwLastError = GetLastError(); - SetLastError(dwLastError); - goto Error; + /* Success, break out */ + break; }
- /* Get a pointer to the file */ - if(!(LoadedImage->MappedAddress = MapViewOfFile(hFileMapping, - ReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE, - 0, - 0, - 0))) + /* Create the File Mapping */ + hFileMapping = CreateFileMappingA(hFile, + NULL, + ReadOnly ? PAGE_READONLY : + PAGE_READWRITE, + 0, + 0, + NULL); + if (!hFileMapping) { - DWORD dwLastError = GetLastError(); - SetLastError(dwLastError); - goto Error; + /* Fail */ + SetLastError(GetLastError()); + CloseHandle(hFile); + return FALSE; }
- /* Close the handle to the map, we don't need it anymore */ - CloseHandle(hFileMapping); - hFileMapping=NULL; + /* Get a pointer to the file */ + LoadedImage->MappedAddress = MapViewOfFile(hFileMapping, + ReadOnly ? FILE_MAP_READ : + FILE_MAP_WRITE, + 0, + 0, + 0);
- /* Get the Nt Header */ - NtHeader = ImageNtHeader(LoadedImage->MappedAddress); + /* Close the handle to the map, we don't need it anymore */ + CloseHandle(hFileMapping);
- /* Write data */ - LoadedImage->ModuleName = HeapAlloc(IMAGEHLP_hHeap, 0, lstrlen(ImageName) + 1); - lstrcpy(LoadedImage->ModuleName, ImageName); - LoadedImage->FileHeader = NtHeader; - LoadedImage->Sections = (PIMAGE_SECTION_HEADER) - ((LPBYTE)&NtHeader->OptionalHeader + - NtHeader->FileHeader.SizeOfOptionalHeader); - LoadedImage->NumberOfSections = NtHeader->FileHeader.NumberOfSections; - LoadedImage->SizeOfImage = NtHeader->OptionalHeader.SizeOfImage; - LoadedImage->Characteristics = NtHeader->FileHeader.Characteristics; - LoadedImage->LastRvaSection = LoadedImage->Sections; - LoadedImage->fSystemImage = FALSE; /* FIXME */ - LoadedImage->fDOSImage = FALSE; /* FIXME */ + /* Write the image size */ + LoadedImage->SizeOfImage = GetFileSize(hFile, NULL);
- /* Read only, so no sense in keeping the handle alive */ - if (ReadOnly) CloseHandle(LoadedImage->hFile); + /* Get the Nt Header */ + NtHeader = ImageNtHeader(LoadedImage->MappedAddress);
- /* Return Success */ - return TRUE; + /* Allocate memory for the name and save it */ + LoadedImage->ModuleName = HeapAlloc(IMAGEHLP_hHeap, + 0, + strlen(FileToOpen) + 16); + strcpy(LoadedImage->ModuleName, FileToOpen);
-Error: - if(LoadedImage->MappedAddress) - UnmapViewOfFile(LoadedImage->MappedAddress); - if(hFileMapping) - CloseHandle(hFileMapping); - if(LoadedImage->hFile) - CloseHandle(LoadedImage->hFile); - return FALSE; + /* Save the NT Header */ + LoadedImage->FileHeader = NtHeader; + + /* Save the section data */ + LoadedImage->Sections = IMAGE_FIRST_SECTION(NtHeader); + LoadedImage->NumberOfSections = NtHeader->FileHeader.NumberOfSections; + + /* Setup other data */ + LoadedImage->SizeOfImage = NtHeader->OptionalHeader.SizeOfImage; + LoadedImage->Characteristics = NtHeader->FileHeader.Characteristics; + LoadedImage->LastRvaSection = LoadedImage->Sections; + LoadedImage->fSystemImage = FALSE; /* FIXME */ + LoadedImage->fDOSImage = FALSE; /* FIXME */ + InitializeListHead(&LoadedImage->Links); + + /* Check if it was read-only */ + if (ReadOnly) + { + /* It was, so close our handle and write it as invalid */ + CloseHandle(hFile); + LoadedImage->hFile = INVALID_HANDLE_VALUE; + } + else + { + /* Write our file handle */ + LoadedImage->hFile = hFile; + } + + /* Return Success */ + return TRUE; }
-/********************************************************************** * - * SetImageConfigInformation (IMAGEHLP.@) +/* + * @unimplemented */ -BOOL WINAPI SetImageConfigInformation( - PLOADED_IMAGE LoadedImage, - PIMAGE_LOAD_CONFIG_DIRECTORY ImageConfigInformation) +BOOL +IMAGEAPI +SetImageConfigInformation(PLOADED_IMAGE LoadedImage, + PIMAGE_LOAD_CONFIG_DIRECTORY ImageConfigInformation) { - FIXME("(%p, %p): stub\n", - LoadedImage, ImageConfigInformation - ); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + UNIMPLEMENTED; + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; }
-/********************************************************************** * - * UnMapAndLoad (IMAGEHLP.@) +/* + * @implemented */ -BOOL WINAPI UnMapAndLoad(PLOADED_IMAGE LoadedImage) +BOOL +IMAGEAPI +UnMapAndLoad(PLOADED_IMAGE Image) { - FIXME("(%p): stub\n", LoadedImage); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + PIMAGE_NT_HEADERS NtHeader; + DWORD HeaderCheckSum, CheckSum; + + /* Check if the image was read-only */ + if (Image->hFile == INVALID_HANDLE_VALUE) + { + /* We'll only unmap the view */ + UnmapViewOfFile(Image->MappedAddress); + } + else + { [truncated at 1000 lines; 4883 more skipped]