From 27a729d88d2c15be476ba12bca67f6796bfd5ee3 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Tue, 20 Jul 2004 16:48:18 +0000 Subject: [PATCH] Implemented ImageLoad, MapAndLoad, ImageRvaToVa, ImageRvaToSection, ImageDirectoryEntryToData, GetImageUnusedHeaderBytes and BindImageEx svn path=/trunk/; revision=10233 --- reactos/lib/imagehlp/access.c | 437 ++++++++++++---- reactos/lib/imagehlp/makefile | 3 +- reactos/lib/imagehlp/modify.c | 794 +++++++++++++++++++++++++++++- reactos/w32api/include/imagehlp.h | 10 +- 4 files changed, 1118 insertions(+), 126 deletions(-) diff --git a/reactos/lib/imagehlp/access.c b/reactos/lib/imagehlp/access.c index 9b3964e1476..181f59f41c9 100644 --- a/reactos/lib/imagehlp/access.c +++ b/reactos/lib/imagehlp/access.c @@ -35,6 +35,20 @@ extern inline DWORD WINAPI GetLastError(void) return ret; } +#define InitializeListHead(ListHead) (\ + (ListHead)->Flink = (ListHead)->Blink = (ListHead)) + +#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);\ + } + WINE_DEFAULT_DEBUG_CHANNEL(imagehlp); /*********************************************************************** @@ -60,6 +74,8 @@ static LOADED_IMAGE IMAGEHLP_EmptyLoadedImage = { }; extern HANDLE IMAGEHLP_hHeap; +BOOLEAN DllListInitialized; +LIST_ENTRY ImageLoadListHead; /*********************************************************************** * EnumerateLoadedModules (IMAGEHLP.@) @@ -103,55 +119,240 @@ BOOL WINAPI GetImageConfigInformation( /*********************************************************************** * GetImageUnusedHeaderBytes (IMAGEHLP.@) */ -DWORD WINAPI GetImageUnusedHeaderBytes( - PLOADED_IMAGE LoadedImage, - LPDWORD SizeUnusedHeaderBytes) +DWORD +WINAPI +GetImageUnusedHeaderBytes( + PLOADED_IMAGE LoadedImage, + LPDWORD SizeUnusedHeaderBytes + ) { - FIXME("(%p, %p): stub\n", - LoadedImage, SizeUnusedHeaderBytes - ); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; + DWORD FirstFreeByte; + PIMAGE_OPTIONAL_HEADER OptionalHeader32 = NULL; + PIMAGE_NT_HEADERS NtHeaders; + ULONG i; + + /* 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); + + /* Get the Optional Header */ + OptionalHeader32 = &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; iNumberOfRvaAndSizes; 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; + } + } + } + + /* Return the unused Header Bytes */ + *SizeUnusedHeaderBytes = OptionalHeader32->SizeOfHeaders - FirstFreeByte; + + /* And return the first free byte*/ + return FirstFreeByte; } /*********************************************************************** * ImageDirectoryEntryToData (IMAGEHLP.@) */ -PVOID WINAPI ImageDirectoryEntryToData( - PVOID Base, BOOLEAN MappedAsImage, USHORT DirectoryEntry, PULONG Size) +PVOID +WINAPI +ImageDirectoryEntryToData( + PVOID Base, + BOOLEAN MappedAsImage, + USHORT DirectoryEntry, + PULONG Size + ) { - FIXME("(%p, %d, %hd, %p): stub\n", - Base, MappedAsImage, DirectoryEntry, Size - ); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return NULL; + return ImageDirectoryEntryToDataEx(Base, MappedAsImage, DirectoryEntry, Size, NULL); } +/*********************************************************************** + * RosImageDirectoryEntryToDataEx (IMAGEHLP.@) + */ +PVOID +WINAPI +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; + + NtHeader = ImageNtHeader(Base); + FileHeader = &NtHeader->FileHeader; + OptionalHeader = &NtHeader->OptionalHeader; + + return (ImageDirectoryEntryToData32(Base, + MappedAsImage, + DirectoryEntry, + Size, + FoundSection, + FileHeader, + OptionalHeader)); +} + +/*********************************************************************** + * RosImageDirectoryEntryToDataEx (IMAGEHLP.@) + */ +PVOID +STDCALL +ImageDirectoryEntryToData32 ( + PVOID Base, + BOOLEAN MappedAsImage, + USHORT DirectoryEntry, + PULONG Size, + PIMAGE_SECTION_HEADER *FoundHeader OPTIONAL, + PIMAGE_FILE_HEADER FileHeader, + PIMAGE_OPTIONAL_HEADER OptionalHeader + ) +{ + 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; iNumberOfSections; 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) { - PLOADED_IMAGE pLoadedImage; + PLIST_ENTRY Head,Next; + PLOADED_IMAGE LoadedImage; - FIXME("(%s, %s): stub\n", DllName, DllPath); - - pLoadedImage = HeapAlloc(IMAGEHLP_hHeap, 0, sizeof(LOADED_IMAGE)); - if (pLoadedImage) - pLoadedImage->FileHeader = HeapAlloc(IMAGEHLP_hHeap, 0, sizeof(IMAGE_NT_HEADERS)); - - return pLoadedImage; + /* Initialize the List Head */ + if (!DllListInitialized) { + InitializeListHead(&ImageLoadListHead); + DllListInitialized = TRUE; + } + + /* Move to the Next DLL */ + Head = &ImageLoadListHead; + Next = Head->Flink; + + //FIXME("Trying to find library: %s in current ListHead \n", DllName); + + /* 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); + + /* Check if the Names Match */ + if (!lstrcmpi( DllName, LoadedImage->ModuleName )) { + //FIXME("Found it, returning it\n"); + return LoadedImage; + } + + /* 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 */ + LoadedImage = HeapAlloc(IMAGEHLP_hHeap, 0, sizeof(*LoadedImage) + lstrlen(DllName) + 1); + + /* Module Name will be after structure */ + LoadedImage->ModuleName = (LPSTR)LoadedImage + 1; + + /* 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; + return LoadedImage; } /*********************************************************************** * ImageRvaToSection (IMAGEHLP.@) */ -PIMAGE_SECTION_HEADER WINAPI ImageRvaToSection( - PIMAGE_NT_HEADERS NtHeaders, PVOID Base, ULONG Rva) +PIMAGE_SECTION_HEADER +WINAPI +ImageRvaToSection( + IN PIMAGE_NT_HEADERS NtHeaders, + IN PVOID Base, + IN ULONG Rva + ) { - FIXME("(%p, %p, %ld): stub\n", NtHeaders, Base, Rva); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return NULL; + PIMAGE_SECTION_HEADER Section; + ULONG i; + + /* 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) { + return Section; + } + ++Section; + } + + /* Not Found */ + return NULL; } /*********************************************************************** @@ -160,22 +361,35 @@ PIMAGE_SECTION_HEADER WINAPI ImageRvaToSection( PIMAGE_NT_HEADERS WINAPI ImageNtHeader(PVOID Base) { TRACE("(%p)\n", Base); - return (PIMAGE_NT_HEADERS) - ((LPBYTE) Base + ((PIMAGE_DOS_HEADER) Base)->e_lfanew); + + /* Just return the e_lfanew Offset VA */ + return (PIMAGE_NT_HEADERS)((LPBYTE)Base + + ((PIMAGE_DOS_HEADER)Base)->e_lfanew); } /*********************************************************************** * ImageRvaToVa (IMAGEHLP.@) */ -PVOID WINAPI ImageRvaToVa( - PIMAGE_NT_HEADERS NtHeaders, PVOID Base, ULONG Rva, - PIMAGE_SECTION_HEADER *LastRvaSection) +PVOID +WINAPI +ImageRvaToVa( + IN PIMAGE_NT_HEADERS NtHeaders, + IN PVOID Base, + IN ULONG Rva, + IN OUT PIMAGE_SECTION_HEADER *LastRvaSection OPTIONAL + ) { - FIXME("(%p, %p, %ld, %p): stub\n", - NtHeaders, Base, Rva, LastRvaSection - ); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return NULL; + PIMAGE_SECTION_HEADER Section; + + /* Get the Section Associated */ + Section = ImageRvaToSection(NtHeaders, Base, Rva); + + /* Return it, if specified */ + if (LastRvaSection) *LastRvaSection = Section; + + /* Return the VA */ + return (PVOID)((ULONG_PTR)Base + (Rva - Section->VirtualAddress) + + Section->PointerToRawData); } /*********************************************************************** @@ -225,97 +439,106 @@ BOOL WINAPI ImageUnload(PLOADED_IMAGE pLoadedImage) * MapAndLoad (IMAGEHLP.@) */ BOOL WINAPI MapAndLoad( - LPSTR pszImageName, LPSTR pszDllPath, PLOADED_IMAGE pLoadedImage, - BOOL bDotDll, BOOL bReadOnly) + LPSTR ImageName, + LPSTR DllPath, + PLOADED_IMAGE LoadedImage, + BOOL DotDll, + BOOL ReadOnly) { - CHAR szFileName[MAX_PATH]; HANDLE hFile = NULL; HANDLE hFileMapping = NULL; HMODULE hModule = NULL; - PIMAGE_NT_HEADERS pNtHeader = NULL; + PIMAGE_NT_HEADERS NtHeader = NULL; + ULONG Tried = 0; + UCHAR Buffer[MAX_PATH]; + LPSTR FilePart; + LPSTR FileToOpen; - TRACE("(%s, %s, %p, %d, %d)\n", pszImageName, pszDllPath, pLoadedImage, - bDotDll, bReadOnly); + /* So we can add the DLL Path later */ + FileToOpen = ImageName; - /* PathCombine(&szFileName, pszDllPath, pszImageName); */ - /* PathRenameExtension(&szFileName, bDotDll?:"dll":"exe"); */ - - /* FIXME: Check if the file already loaded (use IMAGEHLP_pFirstLoadedImage) */ - if(!(hFile = CreateFileA( - szFileName, GENERIC_READ, 1, /* FIXME: FILE_SHARE_READ not defined */ - NULL, OPEN_EXISTING, 0, NULL))) +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) { - SetLastError(ERROR_FILE_NOT_FOUND); - goto Error; + /* 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; + } + } + /* Fail */ + return FALSE; } - if(!(hFileMapping = CreateFileMappingA( - hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL))) + /* Create the File Mapping */ + if (!(hFileMapping = CreateFileMappingA (LoadedImage->hFile, + NULL, + ReadOnly ? PAGE_READONLY : PAGE_READWRITE, + 0, + 0, + NULL))) { DWORD dwLastError = GetLastError(); - WARN("CreateFileMapping: Error = %ld\n", dwLastError); - SetLastError(dwLastError); - goto Error; - } - CloseHandle(hFile); - hFile = NULL; - - if(!(hModule = (HMODULE) MapViewOfFile( - hFileMapping, FILE_MAP_READ, 0, 0, 0))) - { - DWORD dwLastError = GetLastError(); - WARN("MapViewOfFile: Error = %ld\n", dwLastError); SetLastError(dwLastError); goto Error; } - CloseHandle(hFileMapping); - hFileMapping=NULL; + /* Get a pointer to the file */ + if(!(LoadedImage->MappedAddress = MapViewOfFile(hFileMapping, + ReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE, + 0, + 0, + 0))) + { + DWORD dwLastError = GetLastError(); + SetLastError(dwLastError); + goto Error; + } - pLoadedImage = (PLOADED_IMAGE) HeapAlloc( - IMAGEHLP_hHeap, 0, sizeof(LOADED_IMAGE) - ); + /* Close the handle to the map, we don't need it anymore */ + CloseHandle(hFileMapping); + hFileMapping=NULL; - pNtHeader = ImageNtHeader((PVOID) hModule); + /* Get the Nt Header */ + NtHeader = ImageNtHeader(LoadedImage->MappedAddress); - pLoadedImage->ModuleName = HeapAlloc(IMAGEHLP_hHeap, 0, strlen(pszDllPath)+1); /* FIXME: Correct? */ - strcpy( pLoadedImage->ModuleName, pszDllPath ); - pLoadedImage->hFile = hFile; - pLoadedImage->MappedAddress = (PUCHAR) hModule; - pLoadedImage->FileHeader = pNtHeader; - pLoadedImage->Sections = (PIMAGE_SECTION_HEADER) - ((LPBYTE) &pNtHeader->OptionalHeader + - pNtHeader->FileHeader.SizeOfOptionalHeader); - pLoadedImage->NumberOfSections = - pNtHeader->FileHeader.NumberOfSections; - pLoadedImage->SizeOfImage = - pNtHeader->OptionalHeader.SizeOfImage; - pLoadedImage->Characteristics = - pNtHeader->FileHeader.Characteristics; - pLoadedImage->LastRvaSection = pLoadedImage->Sections; + /* 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 */ - pLoadedImage->fSystemImage = FALSE; /* FIXME */ - pLoadedImage->fDOSImage = FALSE; /* FIXME */ + /* Read only, so no sense in keeping the handle alive */ + if (ReadOnly) CloseHandle(LoadedImage->hFile); - /* FIXME: Make thread safe */ - pLoadedImage->Links.Flink = NULL; - pLoadedImage->Links.Blink = &IMAGEHLP_pLastLoadedImage->Links; - if(IMAGEHLP_pLastLoadedImage) - IMAGEHLP_pLastLoadedImage->Links.Flink = &pLoadedImage->Links; - IMAGEHLP_pLastLoadedImage = pLoadedImage; - if(!IMAGEHLP_pFirstLoadedImage) - IMAGEHLP_pFirstLoadedImage = pLoadedImage; - - return TRUE; + /* Return Success */ + return TRUE; Error: - if(hModule) - UnmapViewOfFile((PVOID) hModule); - if(hFileMapping) - CloseHandle(hFileMapping); - if(hFile) - CloseHandle(hFile); - return FALSE; + if(LoadedImage->MappedAddress) + UnmapViewOfFile(LoadedImage->MappedAddress); + if(hFileMapping) + CloseHandle(hFileMapping); + if(LoadedImage->hFile) + CloseHandle(LoadedImage->hFile); + return FALSE; } /*********************************************************************** diff --git a/reactos/lib/imagehlp/makefile b/reactos/lib/imagehlp/makefile index bf310baef35..513a85b67cb 100644 --- a/reactos/lib/imagehlp/makefile +++ b/reactos/lib/imagehlp/makefile @@ -28,7 +28,8 @@ DEFINES = \ TARGET_CFLAGS += \ $(DEFINES) \ -DDCX_USESTYLE=0x10000L \ - -I$(PATH_TO_TOP)/include/wine + -I$(PATH_TO_TOP)/include/wine + TARGET_RCFLAGS += -D__REACTOS__ -D_WIN32_IE=0x600 -D_WIN32_WINNT=0x501 diff --git a/reactos/lib/imagehlp/modify.c b/reactos/lib/imagehlp/modify.c index 64a7b9a5f26..4a3e2bd1ec5 100644 --- a/reactos/lib/imagehlp/modify.c +++ b/reactos/lib/imagehlp/modify.c @@ -31,19 +31,787 @@ WINE_DEFAULT_DEBUG_CHANNEL(imagehlp); static WORD CalcCheckSum(DWORD StartValue, LPVOID BaseAddress, DWORD WordCount); extern PIMAGE_NT_HEADERS WINAPI ImageNtHeader(PVOID Base); -/*********************************************************************** - * BindImageEx (IMAGEHLP.@) +/* Internal Structures we use to keep track of the Bound Imports */ +typedef struct _BOUND_FORWARDER_REFS { + ULONG TimeDateStamp; + LPSTR ModuleName; +} BOUND_FORWARDER_REFS, *PBOUND_FORWARDER_REFS; + +typedef struct _BOUND_IMPORT_DESCRIPTOR { + LPSTR ModuleName; + ULONG TimeDateStamp; + USHORT ForwaderReferences; + PBOUND_FORWARDER_REFS Forwarders; +} BOUND_IMPORT_DESCRIPTOR, *PBOUND_IMPORT_DESCRIPTOR; + + +VOID +STDCALL +BindpWalkAndBindImports( + PLOADED_IMAGE File, + LPSTR DllPath + ); + +PBOUND_IMPORT_DESCRIPTOR +STDCALL +BindpCreateBoundImportDescriptor( + LPSTR LibraryName, + PLOADED_IMAGE Library, + PULONG BoundImportDescriptor + ); + +BOOL +STDCALL +BindpBindThunk( + PIMAGE_THUNK_DATA Thunk, + PLOADED_IMAGE Image, + PIMAGE_THUNK_DATA BoundThunk, + PLOADED_IMAGE LoadedLibrary, + PIMAGE_EXPORT_DIRECTORY Exports, + PBOUND_IMPORT_DESCRIPTOR BoundImportDescriptor, + LPSTR DllPath + ); + +PIMAGE_BOUND_IMPORT_DESCRIPTOR +STDCALL +BindpCreateBoundImportSection( + PULONG BoundImportDescriptor, + PULONG BoundImportsSize + ); + +ULONG +STDCALL +BindpAddBoundForwarder( + PBOUND_IMPORT_DESCRIPTOR BoundImportDescriptor, + LPSTR DllPath, + PUCHAR ForwarderString + ); + +UCHAR BoundLibraries[4096]; +LPSTR BoundLibrariesPointer = BoundLibraries; +PULONG BoundImportDescriptors; + +/* + * BindImageEx + * + * FUNCTION: + * Binds a PE Image File to its imported Libraries + * ARGUMENTS: + * Flags - Caller Specified Flags + * ImageName - Name of Imagefile to Bind + * DllPath - Path to search DLL Files in, can be NULL to use Default + * SymbolPath - Path to search Symbol Files in, can be NULL to use Default + * StatusRoutine - Callback routine to notify of Bind Events, can be NULL to disable. + * + * RETURNS: + * TRUE if Success. */ -BOOL WINAPI BindImageEx( - DWORD Flags, LPSTR ImageName, LPSTR DllPath, LPSTR SymbolPath, - PIMAGEHLP_STATUS_ROUTINE StatusRoutine) +BOOL +WINAPI +BindImageEx( + IN DWORD Flags, + IN LPSTR ImageName, + IN LPSTR DllPath, + IN LPSTR SymbolPath, + IN PIMAGEHLP_STATUS_ROUTINE StatusRoutine + ) { - FIXME("(%ld, %s, %s, %s, %p): stub\n", - Flags, debugstr_a(ImageName), debugstr_a(DllPath), - debugstr_a(SymbolPath), StatusRoutine - ); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + LOADED_IMAGE FileData; + PLOADED_IMAGE File; + ULONG CheckSum, HeaderSum, OldChecksum; + SYSTEMTIME SystemTime; + FILETIME LastWriteTime; + + FIXME("BindImageEx Called for: %s \n", ImageName); + + /* Set and Clear Buffer */ + File = &FileData; + RtlZeroMemory(File, sizeof(*File)); + + /* Request Image Data */ + if (MapAndLoad(ImageName, DllPath, File, TRUE, FALSE)) { + + //FIXME("Image Mapped and Loaded\n"); + + /* Read Import Table */ + BindpWalkAndBindImports(File, DllPath); + + //FIXME("Binding Completed, getting Checksum\n"); + + /* Update Checksum */ + OldChecksum = File->FileHeader->OptionalHeader.CheckSum; + CheckSumMappedFile (File->MappedAddress, + GetFileSize(File->hFile, NULL), + &HeaderSum, + &CheckSum); + File->FileHeader->OptionalHeader.CheckSum = CheckSum; + + //FIXME("Saving Changes to file\n"); + + /* Save Changes */ + UnmapViewOfFile(File->MappedAddress); + + //FIXME("Setting time\n"); + + /* Save new Modified Time */ + GetSystemTime(&SystemTime); + SystemTimeToFileTime(&SystemTime, &LastWriteTime); + SetFileTime(File->hFile, NULL, NULL, &LastWriteTime); + + /* Close Handle */ + CloseHandle(File->hFile); + } + + FIXME("Done\n"); + return TRUE; +} + +/* + * BindpWalkAndBindImports + * + * FUNCTION: + * Does the actual Binding of the Imports and Forward-Referencing + * + * ARGUMENTS: + * File - Name of Imagefile to Bind + * DllPath - Path to search DLL Files in, can be NULL to use Default + * + * RETURNS: + * Nothing + */ +VOID +STDCALL +BindpWalkAndBindImports( + PLOADED_IMAGE File, + LPSTR DllPath + ) +{ + PIMAGE_IMPORT_DESCRIPTOR Imports; + PIMAGE_EXPORT_DIRECTORY Exports; + ULONG SizeOfImports; + ULONG SizeOfExports; + ULONG SizeOfThunks; + PIMAGE_OPTIONAL_HEADER OptionalHeader32 = NULL; + PIMAGE_FILE_HEADER FileHeader; + LPSTR ImportedLibrary; + PLOADED_IMAGE LoadedLibrary; + PBOUND_IMPORT_DESCRIPTOR BoundImportDescriptor = NULL; + PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportTable; + PIMAGE_THUNK_DATA Thunks, TempThunk; + PIMAGE_THUNK_DATA BoundThunks, TempBoundThunk; + ULONG ThunkCount = 0; + ULONG Thunk; + ULONG BoundImportTableSize; + ULONG VirtBytesFree, HeaderBytesFree, FirstFreeByte, PhysBytesFree; + + //FIXME("BindpWalkAndBindImports Called\n"); + + /* Load the Import Descriptor */ + Imports = ImageDirectoryEntryToData (File->MappedAddress, + FALSE, + IMAGE_DIRECTORY_ENTRY_IMPORT, + &SizeOfImports); + + /* Read the File Header */ + FileHeader = &File->FileHeader->FileHeader; + OptionalHeader32 = &File->FileHeader->OptionalHeader; + + /* Support for up to 32 imported DLLs */ + BoundImportDescriptors = GlobalAlloc(GMEM_ZEROINIT, 32* sizeof(*BoundImportDescriptor)); + + //FIXME("BoundImportDescriptors Allocated\n"); + + /* For each Import */ + for(; Imports->Name ; Imports++) { + + /* Which DLL is being Imported */ + ImportedLibrary = ImageRvaToVa (File->FileHeader, + File->MappedAddress, + Imports->Name, + &File->LastRvaSection); + + FIXME("Loading Imported DLL: %s \n", ImportedLibrary); + + /* Load the DLL */ + LoadedLibrary = ImageLoad(ImportedLibrary, DllPath); + + FIXME("DLL Loaded at: %p \n", LoadedLibrary->MappedAddress); + + /* Now load the Exports */ + Exports = ImageDirectoryEntryToData (LoadedLibrary->MappedAddress, + FALSE, + IMAGE_DIRECTORY_ENTRY_EXPORT, + &SizeOfExports); + + /* And load the Thunks */ + Thunks = ImageRvaToVa (File->FileHeader, + File->MappedAddress, + (ULONG)Imports->OriginalFirstThunk, + &File->LastRvaSection); + + /* No actual Exports (UPX Packer can do this */ + if (!Thunks) continue; + + //FIXME("Creating Bound Descriptor for this DLL\n"); + + /* Create Bound Import Descriptor */ + BoundImportDescriptor = BindpCreateBoundImportDescriptor (ImportedLibrary, + LoadedLibrary, + BoundImportDescriptors); + + /* Count how many Thunks we have */ + ThunkCount = 0; + TempThunk = Thunks; + while (TempThunk->u1.AddressOfData) { + ThunkCount++; + TempThunk++; + } + + /* Allocate Memory for the Thunks we will Bind */ + SizeOfThunks = ThunkCount * sizeof(*TempBoundThunk); + BoundThunks = GlobalAlloc(GMEM_ZEROINIT, SizeOfThunks); + + //FIXME("Binding Thunks\n"); + + /* Bind the Thunks */ + TempThunk = Thunks; + TempBoundThunk = BoundThunks; + for (Thunk=0; Thunk < ThunkCount; Thunk++) { + BindpBindThunk (TempThunk, + File, + TempBoundThunk, + LoadedLibrary, + Exports, + BoundImportDescriptor, + DllPath); + TempThunk++; + TempBoundThunk++; + } + + /* Load the Second Thunk Array */ + TempThunk = ImageRvaToVa (File->FileHeader, + File->MappedAddress, + (ULONG)Imports->FirstThunk, + &File->LastRvaSection); + + //FIXME("Copying Bound Thunks\n"); + + /* Copy the Pointers */ + if (memcmp(TempThunk, BoundThunks, SizeOfThunks)) { + RtlCopyMemory(TempThunk, BoundThunks, SizeOfThunks); + } + + /* Set the TimeStamp */ + if (Imports->TimeDateStamp != 0xFFFFFFFF) { + Imports->TimeDateStamp = 0xFFFFFFFF; + } + + /* Free the Allocated Memory */ + GlobalFree(BoundThunks); + + //FIXME("Moving to next File\n"); + } + + //FIXME("Creating Bound Import Section\n"); + + /* Create the Bound Import Table */ + BoundImportTable = BindpCreateBoundImportSection(BoundImportDescriptors, &BoundImportTableSize); + + /* Zero out the Bound Import Table */ + File->FileHeader->OptionalHeader.DataDirectory + [IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0; + File->FileHeader->OptionalHeader.DataDirectory + [IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0; + + /* Check if we have enough space */ + FirstFreeByte = GetImageUnusedHeaderBytes(File, &VirtBytesFree); + HeaderBytesFree = File->Sections->VirtualAddress - + File->FileHeader->OptionalHeader.SizeOfHeaders + VirtBytesFree; + PhysBytesFree = File->Sections->PointerToRawData - + File->FileHeader->OptionalHeader.SizeOfHeaders + VirtBytesFree; + + //FIXME("Calculating Space\n"); + + if (BoundImportTableSize > VirtBytesFree) { + if (BoundImportTableSize > HeaderBytesFree) { + FIXME("Not enough Space\n"); + return; /* Fail...not enough space */ + } + if (BoundImportTableSize <= PhysBytesFree) { + + FIXME("Header Recalculation\n"); + /* We have enough NULLs to add it, simply enlarge header data */ + File->FileHeader->OptionalHeader.SizeOfHeaders = File->FileHeader->OptionalHeader.SizeOfHeaders - + VirtBytesFree + + BoundImportTableSize + + ((File->FileHeader->OptionalHeader.FileAlignment - 1) + & ~(File->FileHeader->OptionalHeader.FileAlignment - 1)); + + } else { + + FIXME("Header Resizing\n"); + + /* Resize the Headers */ + //UNIMPLEMENTED + + /* Recalculate Headers */ + FileHeader = &File->FileHeader->FileHeader; + OptionalHeader32 = &File->FileHeader->OptionalHeader; + } + } + + /* Set Bound Import Table Data */ + File->FileHeader->OptionalHeader.DataDirectory + [IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = FirstFreeByte; + File->FileHeader->OptionalHeader.DataDirectory + [IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = BoundImportTableSize; + + //FIXME("Copying Bound Import Table\n"); + + /* Copy the Bound Import Table */ + RtlCopyMemory(File->MappedAddress + FirstFreeByte, BoundImportTable, BoundImportTableSize); + + /* Free out local copy */ + GlobalFree(BoundImportTable); +} + + +/* + * BindpCreateBoundImportSection + * + * FUNCTION: + * Creates a 32-bit PE Bound Import Table + * + * ARGUMENTS: + * BoundImportDescriptor - Pointer to the Bound Import Table + * BoundImportsSize - Size of the Bound Import Table + * + * RETURNS: + * PIMAGE_BOUND_IMPORT_DESCRIPTOR - The Bound Import Table + */ +PIMAGE_BOUND_IMPORT_DESCRIPTOR +STDCALL +BindpCreateBoundImportSection( + PULONG BoundImportDescriptor, + PULONG BoundImportsSize + ) +{ + ULONG BoundLibraryNamesSize, BoundImportTableSize; + PBOUND_FORWARDER_REFS BoundForwarder; + PBOUND_IMPORT_DESCRIPTOR CurrentBoundImportDescriptor; + PVOID BoundLibraryNames; + PIMAGE_BOUND_IMPORT_DESCRIPTOR CurrentBoundImportTableEntry, BoundImportTable; + PIMAGE_BOUND_FORWARDER_REF NewForwarder; + + /* Zero the Sizes */ + *BoundImportsSize = 0; + BoundLibraryNamesSize = 0; + BoundImportTableSize = 0; + + /* Start with the first Internal Descriptor */ + CurrentBoundImportDescriptor = (PBOUND_IMPORT_DESCRIPTOR)BoundImportDescriptor; + + /* Loop through every Descriptor we loaded */ + while (CurrentBoundImportDescriptor->ModuleName) { + + /* Add to the size of the Bound Import Table */ + BoundImportTableSize += sizeof(IMAGE_BOUND_IMPORT_DESCRIPTOR); + + /* Check Forwarders */ + BoundForwarder = CurrentBoundImportDescriptor->Forwarders; + while (BoundForwarder->ModuleName) { + + /* Add to size of Bound Import Table */ + BoundImportTableSize += sizeof(IMAGE_BOUND_FORWARDER_REF); + + /* Next Forwarder */ + BoundForwarder++; + } + + /* Read Next Internal Descriptor */ + CurrentBoundImportDescriptor++; + } + + /* Add Terminator for PE Loader*/ + BoundImportTableSize += sizeof(IMAGE_BOUND_IMPORT_DESCRIPTOR); + + /* Name of Libraries Bound in Bound Import Table */ + BoundLibraryNamesSize = ((ULONG)BoundLibrariesPointer - (ULONG)(&BoundLibraries)); + + /* Size of the whole table, dword aligned */ + *BoundImportsSize = BoundImportTableSize + + ((BoundLibraryNamesSize + sizeof(ULONG) - 1) & ~(sizeof(ULONG)-1)); + + /* Allocate it */ + BoundImportTable = GlobalAlloc(GMEM_ZEROINIT, *BoundImportsSize); + + /* Pointer Library Names inside the Bound Import Table */ + BoundLibraryNames = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)((ULONG_PTR)BoundImportTable + + BoundImportTableSize); + + /* Copy the Library Names */ + RtlCopyMemory(BoundLibraryNames, BoundLibraries, BoundLibraryNamesSize); + + /* Go back to first Internal Descriptor and load first entry in the Bound Import Table */ + CurrentBoundImportTableEntry = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)BoundImportTable; + CurrentBoundImportDescriptor = (PBOUND_IMPORT_DESCRIPTOR)BoundImportDescriptor; + + /* Copy the data from our Internal Structure to the Bound Import Table */ + while (CurrentBoundImportDescriptor->ModuleName) { + CurrentBoundImportTableEntry->TimeDateStamp = CurrentBoundImportDescriptor->TimeDateStamp; + CurrentBoundImportTableEntry->OffsetModuleName = (USHORT)(BoundImportTableSize + + (CurrentBoundImportDescriptor->ModuleName - + (LPSTR) BoundLibraries)); + CurrentBoundImportTableEntry->NumberOfModuleForwarderRefs = CurrentBoundImportDescriptor->ForwaderReferences; + + /* Copy the data from our Forwader Entries to the Bound Import Table */ + NewForwarder = (PIMAGE_BOUND_FORWARDER_REF)(CurrentBoundImportTableEntry+1); + BoundForwarder = CurrentBoundImportDescriptor->Forwarders; + while (BoundForwarder->ModuleName) { + NewForwarder->TimeDateStamp =BoundForwarder->TimeDateStamp; + NewForwarder->OffsetModuleName = (USHORT)(BoundImportTableSize + + (BoundForwarder->ModuleName - + (LPSTR) BoundLibraries)); + NewForwarder++; + BoundForwarder++; + } + + /* Move to next Bound Import Table Entry */ + CurrentBoundImportTableEntry = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)NewForwarder; + + /* move to next Internal Descriptor */ + CurrentBoundImportDescriptor++; + } + + /* Now put the pointer back at the beginning and clear the buffer */ + RtlZeroMemory(BoundLibraries, 4096); + BoundLibrariesPointer = BoundLibraries; + + return BoundImportTable; +} + +/* + * BindpBindThunk + * + * FUNCTION: + * Finds the pointer of the Imported function, and writes it into the Thunk, + * thus making the Thunk Bound. + * + * ARGUMENTS: + * Thunk - Current Thunk in Unbound File + * File - File containing the Thunk + * BoundThunk - Pointer to the corresponding Bound Thunk + * LoadedLibrary - Library containing the Exported Function + * Exports - Export Directory of LoadedLibrary + * BoundImportDescriptor - Internal Bound Import Descriptor of LoadedLibrary + * DllPath - DLL Search Path + * + * RETURNS: + * TRUE if Suceeded + */ +BOOL +STDCALL +BindpBindThunk( + PIMAGE_THUNK_DATA Thunk, + PLOADED_IMAGE File, + PIMAGE_THUNK_DATA BoundThunk, + PLOADED_IMAGE LoadedLibrary, + PIMAGE_EXPORT_DIRECTORY Exports, + PBOUND_IMPORT_DESCRIPTOR BoundImportDescriptor, + LPSTR DllPath + ) +{ + PULONG AddressOfNames; + PUSHORT AddressOfOrdinals; + PULONG AddressOfPointers; + PIMAGE_IMPORT_BY_NAME ImportName; + ULONG OrdinalNumber = 0; + USHORT HintIndex; + LPSTR ExportName; + ULONG ExportsBase; + ULONG ExportSize; + UCHAR NameBuffer[32]; + PIMAGE_OPTIONAL_HEADER OptionalHeader32 = NULL; + PIMAGE_OPTIONAL_HEADER LibraryOptionalHeader32 = NULL; + + /* Get the Pointers to the Tables */ + AddressOfNames = ImageRvaToVa (LoadedLibrary->FileHeader, + LoadedLibrary->MappedAddress, + Exports->AddressOfNames, + &LoadedLibrary->LastRvaSection); + AddressOfOrdinals = ImageRvaToVa (LoadedLibrary->FileHeader, + LoadedLibrary->MappedAddress, + Exports->AddressOfNameOrdinals, + &LoadedLibrary->LastRvaSection); + AddressOfPointers = ImageRvaToVa (LoadedLibrary->FileHeader, + LoadedLibrary->MappedAddress, + Exports->AddressOfFunctions, + &LoadedLibrary->LastRvaSection); + + //FIXME("Binding a Thunk\n"); + + /* Get the Optional Header */ + OptionalHeader32 = &File->FileHeader->OptionalHeader; + LibraryOptionalHeader32 = &LoadedLibrary->FileHeader->OptionalHeader; + + /* Import by Ordinal */ + if (IMAGE_SNAP_BY_ORDINAL(Thunk->u1.Ordinal) == TRUE) { + OrdinalNumber = (IMAGE_ORDINAL(Thunk->u1.Ordinal) - Exports->Base); + ImportName = (PIMAGE_IMPORT_BY_NAME)NameBuffer; + } else { + + /* Import by Name */ + ImportName = ImageRvaToVa (File->FileHeader, + File->MappedAddress, + (ULONG)Thunk->u1.AddressOfData, + &File->LastRvaSection); + + for (HintIndex = 0; HintIndex < Exports->NumberOfNames; HintIndex++) { + + /* Get the Export Name */ + ExportName = ImageRvaToVa (LoadedLibrary->FileHeader, + LoadedLibrary->MappedAddress, + (ULONG)AddressOfNames[HintIndex], + &LoadedLibrary->LastRvaSection); + + /* Check if it's the one we want */ + if (!strcmp(ImportName->Name, ExportName)) { + OrdinalNumber = AddressOfOrdinals[HintIndex]; + break; + } + } + } + + /* Fail if we still didn't find anything */ + if (!OrdinalNumber) return FALSE; + + /* Write the Pointer */ + (ULONG)BoundThunk->u1.Function = AddressOfPointers[OrdinalNumber] + LibraryOptionalHeader32->ImageBase; + + /* Load DLL's Exports */ + ExportsBase = (ULONG)ImageDirectoryEntryToData (LoadedLibrary->MappedAddress, + TRUE, + IMAGE_DIRECTORY_ENTRY_EXPORT, + &ExportSize) - + (ULONG_PTR)LoadedLibrary->MappedAddress; + /* RVA to VA */ + ExportsBase += LibraryOptionalHeader32->ImageBase; + + /* Check if the Export is forwarded (meaning that it's pointer is inside the Export Table) */ + if ((ULONG)BoundThunk->u1.Function > ExportsBase && (ULONG)BoundThunk->u1.Function < (ExportsBase + ExportSize)) { + + //FIXME("This Thunk is a forward...calling forward thunk bounder\n"); + + /* Replace the Forwarder String by the actual Pointer */ + (ULONG)BoundThunk->u1.Function = BindpAddBoundForwarder (BoundImportDescriptor, + DllPath, + ImageRvaToVa (LoadedLibrary->FileHeader, + LoadedLibrary->MappedAddress, + AddressOfPointers[OrdinalNumber], + &LoadedLibrary->LastRvaSection)); + + } + + /* Return Success */ + return TRUE; +} + +/* + * BindpAddBoundForwarder + * + * FUNCTION: + * Finds the pointer of the Forwarded function, and writes it into the Thunk, + * thus making the Thunk Bound. + * + * ARGUMENTS: + * BoundImportDescriptor - Internal Bound Import Descriptor of LoadedLibrary + * DllPath - DLL Search Path + * ForwarderString - Name of the Forwader String + * + * RETURNS: + * Pointer to the Forwaded Function. + */ +ULONG +STDCALL +BindpAddBoundForwarder( + PBOUND_IMPORT_DESCRIPTOR BoundImportDescriptor, + LPSTR DllPath, + PUCHAR ForwarderString + ) +{ + CHAR DllName[256]; + PUCHAR TempDllName; + PLOADED_IMAGE LoadedLibrary; + ULONG DllNameSize; + USHORT OrdinalNumber; + USHORT HintIndex; + ULONG ExportSize; + PIMAGE_EXPORT_DIRECTORY Exports; + ULONG ExportsBase; + PULONG AddressOfNames; + PUSHORT AddressOfOrdinals; + PULONG AddressOfPointers; + LPSTR ExportName; + ULONG ForwardedAddress; + PBOUND_FORWARDER_REFS BoundForwarder; + PIMAGE_OPTIONAL_HEADER OptionalHeader32 = NULL; + +NextForwarder: + + /* Get the DLL Name */ + TempDllName = ForwarderString; + while (*TempDllName && *TempDllName != '.') TempDllName++; + DllNameSize = (ULONG) (TempDllName - ForwarderString); + lstrcpyn(DllName, ForwarderString, DllNameSize + 1); + + /* Append .DLL extension */ + DllName[DllNameSize] = '\0'; + strcat(DllName, ".DLL" ); + + /* Load it */ + FIXME("Loading the Thunk Library: %s \n", DllName); + LoadedLibrary = ImageLoad(DllName, DllPath); + TempDllName += 1; + + /* Return whatever we got back in case of failure*/ + if (!LoadedLibrary) return (ULONG)ForwarderString; + FIXME("It Loaded at: %p \n", LoadedLibrary->MappedAddress); + + /* Load Exports */ + Exports = ImageDirectoryEntryToData(LoadedLibrary->MappedAddress, FALSE, IMAGE_DIRECTORY_ENTRY_EXPORT, &ExportSize); + + /* Get the Pointers to the Tables */ + AddressOfNames = ImageRvaToVa (LoadedLibrary->FileHeader, + LoadedLibrary->MappedAddress, + Exports->AddressOfNames, + &LoadedLibrary->LastRvaSection); + AddressOfOrdinals = ImageRvaToVa (LoadedLibrary->FileHeader, + LoadedLibrary->MappedAddress, + Exports->AddressOfNameOrdinals, + &LoadedLibrary->LastRvaSection); + AddressOfPointers = ImageRvaToVa (LoadedLibrary->FileHeader, + LoadedLibrary->MappedAddress, + Exports->AddressOfFunctions, + &LoadedLibrary->LastRvaSection); + + /* Get the Optional Header */ + OptionalHeader32 = &LoadedLibrary->FileHeader->OptionalHeader; + + /* Get the Ordinal Number */ + for (HintIndex = 0; HintIndex < Exports->NumberOfNames; HintIndex++) { + + /* Get the Export Name */ + ExportName = ImageRvaToVa (LoadedLibrary->FileHeader, + LoadedLibrary->MappedAddress, + AddressOfNames[HintIndex], + &LoadedLibrary->LastRvaSection); + + /* Check if it matches */ + if (!strcmp(TempDllName, ExportName)) { + OrdinalNumber = AddressOfOrdinals[HintIndex]; + break; + } + } + + do { + /* Get the Forwarded Address */ + ForwardedAddress = AddressOfPointers[OrdinalNumber] + OptionalHeader32->ImageBase; + + /* Load the First Bound Forward Structure */ + BoundForwarder = BoundImportDescriptor->Forwarders; + + /* Check if we already have the Module Name written */ + while (BoundForwarder->ModuleName) { + if (!lstrcmpi(DllName, BoundForwarder->ModuleName)) break; + BoundForwarder++; + } + + if (!BoundForwarder->ModuleName) { + + /* Save Library Name in Bound Libraries Buffer */ + strcat((char *)BoundLibrariesPointer, DllName); + + /* Set Data */ + BoundForwarder->ModuleName = BoundLibrariesPointer; + BoundForwarder->TimeDateStamp = LoadedLibrary->FileHeader->FileHeader.TimeDateStamp; + + /* Next String */ + BoundLibrariesPointer = BoundLibrariesPointer + strlen((char *)BoundLibrariesPointer) + 1; + BoundImportDescriptor->ForwaderReferences += 1; + } + + /* Load DLL's Exports */ + ExportsBase = (ULONG)ImageDirectoryEntryToData (LoadedLibrary->MappedAddress, + TRUE, + IMAGE_DIRECTORY_ENTRY_EXPORT, + &ExportSize) - + (ULONG_PTR)LoadedLibrary->MappedAddress; + ExportsBase += OptionalHeader32->ImageBase; + + //FIXME("I've thunked it\n"); + + /* Is this yet another Forward? */ + if (ForwardedAddress > ExportsBase && ForwardedAddress < (ExportsBase + ExportSize)) { + ForwarderString = ImageRvaToVa (LoadedLibrary->FileHeader, + LoadedLibrary->MappedAddress, + AddressOfPointers[OrdinalNumber], + &LoadedLibrary->LastRvaSection); + goto NextForwarder; + } + } + while (0); + return ForwardedAddress; +} + +/* + * BindpCreateBoundImportDescriptor + * + * FUNCTION: + * Creates an Internal Structure for the Bound Library + * + * ARGUMENTS: + * LibraryName - Name of the Library + * Library - Loaded Library + * BoundImportDescriptor - Internal Bound Import Descriptor of Library + * + * RETURNS: + * PBOUND_IMPORT_DESCRIPTOR - Pointer to the Internal Bind Structure + */ +PBOUND_IMPORT_DESCRIPTOR +STDCALL +BindpCreateBoundImportDescriptor( + LPSTR LibraryName, + PLOADED_IMAGE Library, + PULONG BoundImportDescriptor + ) +{ + PBOUND_IMPORT_DESCRIPTOR CurrentBoundImportDescriptor; + + /* Load the First Descriptor */ + CurrentBoundImportDescriptor = (PBOUND_IMPORT_DESCRIPTOR)BoundImportDescriptor; + + /* Check if we've already bound this library */ + while (CurrentBoundImportDescriptor->ModuleName) { + if (!lstrcmpi(CurrentBoundImportDescriptor->ModuleName, LibraryName)) { + return CurrentBoundImportDescriptor; + } + CurrentBoundImportDescriptor++; + } + + /* Save Library Name in Bound Libraries Buffer */ + strcat((char *)BoundLibrariesPointer, LibraryName); + + /* Set Data */ + CurrentBoundImportDescriptor->ModuleName = BoundLibrariesPointer; + CurrentBoundImportDescriptor->TimeDateStamp = Library->FileHeader->FileHeader.TimeDateStamp; + + /* Support for up to 32 Forwarded DLLs */ + CurrentBoundImportDescriptor->Forwarders = GlobalAlloc(GMEM_ZEROINIT, 32* sizeof(BOUND_FORWARDER_REFS)); + + /* Next String */ + BoundLibrariesPointer = BoundLibrariesPointer + strlen((char *)BoundLibrariesPointer) + 1; + + return CurrentBoundImportDescriptor; } /*********************************************************************** @@ -92,9 +860,7 @@ PIMAGE_NT_HEADERS WINAPI CheckSumMappedFile( DWORD CalcSum; DWORD HdrSum; - FIXME("(%p, %ld, %p, %p): stub\n", - BaseAddress, FileLength, HeaderSum, CheckSum - ); + FIXME("stub\n"); CalcSum = (DWORD)CalcCheckSum(0, BaseAddress, diff --git a/reactos/w32api/include/imagehlp.h b/reactos/w32api/include/imagehlp.h index 1f94533c10e..537a269f005 100644 --- a/reactos/w32api/include/imagehlp.h +++ b/reactos/w32api/include/imagehlp.h @@ -75,7 +75,7 @@ extern "C" { #define UNDNAME_NO_ARGUMENTS 8192 #define UNDNAME_NO_SPECIAL_SYMS 16384 -#define _IMAGEHLPAPI DECLSPEC_IMPORT WINAPI +#define _IMAGEHLPAPI WINAPI #ifndef RC_INVOKED @@ -258,6 +258,8 @@ PLOADED_IMAGE _IMAGEHLPAPI ImageLoad(LPSTR,LPSTR); BOOL _IMAGEHLPAPI ImageUnload(PLOADED_IMAGE); PIMAGE_NT_HEADERS _IMAGEHLPAPI ImageNtHeader(IN PVOID); PVOID _IMAGEHLPAPI ImageDirectoryEntryToData(IN PVOID,IN BOOLEAN,IN USHORT,OUT PULONG); +PVOID _IMAGEHLPAPI ImageDirectoryEntryToDataEx(IN PVOID Base, IN BOOLEAN MappedAsImage, IN USHORT DirectoryEntry, OUT PULONG Size, OUT PIMAGE_SECTION_HEADER *FoundSection OPTIONAL); +PVOID _IMAGEHLPAPI ImageDirectoryEntryToData32(PVOID Base, BOOLEAN MappedAsImage, USHORT DirectoryEntry, PULONG Size, PIMAGE_SECTION_HEADER *FoundHeader OPTIONAL, PIMAGE_FILE_HEADER FileHeader, PIMAGE_OPTIONAL_HEADER OptionalHeader); PIMAGE_SECTION_HEADER _IMAGEHLPAPI ImageRvaToSection(IN PIMAGE_NT_HEADERS,IN PVOID,IN ULONG); PVOID _IMAGEHLPAPI ImageRvaToVa(IN PIMAGE_NT_HEADERS,IN PVOID,IN ULONG,IN OUT PIMAGE_SECTION_HEADER*); BOOL _IMAGEHLPAPI MapAndLoad(LPSTR,LPSTR,PLOADED_IMAGE,BOOL,BOOL); @@ -305,11 +307,11 @@ BOOL _IMAGEHLPAPI SymUnloadModule(IN HANDLE,IN DWORD); BOOL _IMAGEHLPAPI SymUnDName(IN PIMAGEHLP_SYMBOL,OUT LPSTR,IN DWORD); BOOL _IMAGEHLPAPI SymRegisterCallback(IN HANDLE,IN PSYMBOL_REGISTERED_CALLBACK,IN PVOID); BOOL _IMAGEHLPAPI ImageGetDigestStream(IN HANDLE,IN DWORD,IN DIGEST_FUNCTION,IN DIGEST_HANDLE); -BOOL _IMAGEHLPAPI ImageAddCertificate(IN HANDLE,IN LPWIN_CERTIFICATE,OUT PDWORD); +//BOOL _IMAGEHLPAPI ImageAddCertificate(IN HANDLE,IN LPWIN_CERTIFICATE,OUT PDWORD); BOOL _IMAGEHLPAPI ImageRemoveCertificate(IN HANDLE,IN DWORD); BOOL _IMAGEHLPAPI ImageEnumerateCertificates(IN HANDLE,IN WORD,OUT PDWORD,IN OUT PDWORD OPTIONAL,IN OUT DWORD OPTIONAL); -BOOL _IMAGEHLPAPI ImageGetCertificateData(IN HANDLE,IN DWORD,OUT LPWIN_CERTIFICATE,IN OUT PDWORD); -BOOL _IMAGEHLPAPI ImageGetCertificateHeader(IN HANDLE,IN DWORD,IN OUT LPWIN_CERTIFICATE); +//BOOL _IMAGEHLPAPI ImageGetCertificateData(IN HANDLE,IN DWORD,OUT LPWIN_CERTIFICATE,IN OUT PDWORD); +//BOOL _IMAGEHLPAPI ImageGetCertificateHeader(IN HANDLE,IN DWORD,IN OUT LPWIN_CERTIFICATE); BOOL _IMAGEHLPAPI CopyPdb(CHAR const*,CHAR const*,BOOL); BOOL _IMAGEHLPAPI RemovePrivateCvSymbolicEx(PCHAR,ULONG,PCHAR*,ULONG*);