reactos/lib/imagehlp
diff -N winehq2ros.patch
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ winehq2ros.patch 12 Nov 2004 03:55:15 -0000 1.1
@@ -0,0 +1,1064 @@
+
+Index: dlls/imagehlp/access.c
+===================================================================
+RCS file: /home/wine/wine/dlls/imagehlp/access.c,v
+retrieving revision 1.20
+diff -u -r1.20 access.c
+--- dlls/imagehlp/access.c 5 Apr 2004 22:50:45 -0000 1.20
++++ dlls/imagehlp/access.c 29 Sep 2004 17:17:35 -0000
+@@ -54,6 +54,8 @@
+ };
+
+ extern HANDLE IMAGEHLP_hHeap;
++BOOLEAN DllListInitialized;
++LIST_ENTRY ImageLoadListHead;
+
+ /***********************************************************************
+ * GetImageConfigInformation (IMAGEHLP.@)
+@@ -76,11 +78,45 @@
+ 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; 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;
++ }
++ }
++ }
++
++ /* Return the unused Header Bytes */
++ *SizeUnusedHeaderBytes = OptionalHeader32->SizeOfHeaders - FirstFreeByte;
++
++ /* And return the first free byte*/
++ return FirstFreeByte;
+ }
+
+ /***********************************************************************
+@@ -88,15 +124,58 @@
+ */
+ PLOADED_IMAGE WINAPI ImageLoad(LPSTR DllName, LPSTR DllPath)
+ {
+- PLOADED_IMAGE pLoadedImage;
++ PLIST_ENTRY Head,Next;
++ PLOADED_IMAGE LoadedImage;
++
++ /* Initialize the List Head */
++ if (!DllListInitialized) {
++ InitializeListHead(&ImageLoadListHead);
++ DllListInitialized = TRUE;
++ }
++
++ /* Move to the Next DLL */
++ Head = &ImageLoadListHead;
++ Next = Head->Flink;
++
++ TRACE("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);
++ TRACE("Found: %s in current ListHead \n", LoadedImage->ModuleName);
++
++ /* Check if the Names Match */
++ if (!lstrcmpiA( DllName, LoadedImage->ModuleName )) {
++ TRACE("Found: %s\n the names match",DllName);
++ return LoadedImage;
++ }
++
++ /* Move to next Entry */
++ Next = Next->Flink;
++ TRACE("Moving to next List Entry\n");
++ }
++
++ /* Allocate memory for the Structure, and write the Module Name under */
++ LoadedImage = HeapAlloc(IMAGEHLP_hHeap, 0, sizeof(*LoadedImage) + lstrlenA(DllName) + 1);
+
+- FIXME("(%s, %s): stub\n", DllName, DllPath);
++ /* Module Name will be after structure */
++ LoadedImage->ModuleName = (LPSTR)LoadedImage + 1;
+
+- pLoadedImage = HeapAlloc(IMAGEHLP_hHeap, 0, sizeof(LOADED_IMAGE));
+- if (pLoadedImage)
+- pLoadedImage->FileHeader = HeapAlloc(IMAGEHLP_hHeap, 0, sizeof(IMAGE_NT_HEADERS));
++ /* Copy the Moduel Name */
++ lstrcpyA(LoadedImage->ModuleName, DllName);
+
+- return pLoadedImage;
++ /* 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;
+ }
+
+ /***********************************************************************
+@@ -149,40 +228,62 @@
+ LPSTR pszImageName, LPSTR pszDllPath, PLOADED_IMAGE pLoadedImage,
+ BOOL bDotDll, BOOL bReadOnly)
+ {
+- 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 = pszImageName;
+
+- /* 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 ((pLoadedImage->hFile = CreateFileA (FileToOpen,
++ bReadOnly ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
++ bReadOnly ? 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 = SearchPathA(pszDllPath, pszImageName, bDotDll ? ".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 (pLoadedImage->hFile,
++ NULL,
++ bReadOnly ? 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)))
++ /* Get a pointer to the file */
++ if(!(pLoadedImage->MappedAddress = MapViewOfFile(hFileMapping,
++ bReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE,
++ 0,
++ 0,
++ 0)))
+ {
+ DWORD dwLastError = GetLastError();
+ WARN("MapViewOfFile: Error = %ld\n", dwLastError);
+@@ -190,52 +291,43 @@
+ goto Error;
+ }
+
++
++ /* Close the handle to the map, we don't need it anymore */
+ CloseHandle(hFileMapping);
+ hFileMapping=NULL;
+
+- pLoadedImage = (PLOADED_IMAGE) HeapAlloc(
+- IMAGEHLP_hHeap, 0, sizeof(LOADED_IMAGE)
+- );
++ /* Get the Nt Header */
++ NtHeader = ImageNtHeader(pLoadedImage->MappedAddress);
+
+- pNtHeader = RtlImageNtHeader(hModule);
+-
+- 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;
++ /* Write data */
++ pLoadedImage->ModuleName = HeapAlloc(IMAGEHLP_hHeap, 0, lstrlenA(pszImageName) + 1);
++ lstrcpyA(pLoadedImage->ModuleName, pszImageName);
++ pLoadedImage->FileHeader = NtHeader;
+ 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;
++ ((LPBYTE)&NtHeader->OptionalHeader +
++ NtHeader->FileHeader.SizeOfOptionalHeader);
++ pLoadedImage->NumberOfSections = NtHeader->FileHeader.NumberOfSections;
++ pLoadedImage->SizeOfImage = NtHeader->OptionalHeader.SizeOfImage;
++ pLoadedImage->Characteristics = NtHeader->FileHeader.Characteristics;
+ pLoadedImage->LastRvaSection = pLoadedImage->Sections;
+-
+ pLoadedImage->fSystemImage = FALSE; /* FIXME */
+ pLoadedImage->fDOSImage = FALSE; /* FIXME */
+
+- /* 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;
+
++ /* Read only, so no sense in keeping the handle alive */
++ if (bReadOnly) CloseHandle(pLoadedImage->hFile);
++
++
++ /* Return Success */
+ return TRUE;
+
+ Error:
+- if(hModule)
+- UnmapViewOfFile((PVOID) hModule);
++ if(pLoadedImage->MappedAddress)
++ UnmapViewOfFile(pLoadedImage->MappedAddress);
+ if(hFileMapping)
+ CloseHandle(hFileMapping);
+- if(hFile)
+- CloseHandle(hFile);
++ if(pLoadedImage->hFile)
++ CloseHandle(pLoadedImage->hFile);
+ return FALSE;
+ }
+
+Index: dlls/imagehlp/modify.c
+===================================================================
+RCS file: /home/wine/wine/dlls/imagehlp/modify.c,v
+retrieving revision 1.13
+diff -u -r1.13 modify.c
+--- dlls/imagehlp/modify.c 21 Nov 2003 21:31:35 -0000 1.13
++++ dlls/imagehlp/modify.c 29 Sep 2004 17:17:37 -0000
+@@ -30,8 +30,669 @@
+
+ WINE_DEFAULT_DEBUG_CHANNEL(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;
++
++UCHAR BoundLibraries[4096];
++LPSTR BoundLibrariesPointer = BoundLibraries;
++PULONG BoundImportDescriptors;
++
+ static WORD CalcCheckSum(DWORD StartValue, LPVOID BaseAddress, DWORD WordCount);
+
++/*
++ * 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
++WINAPI
++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 (!lstrcmpiA(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;
++}
++
++/*
++ * 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
++WINAPI
++BindpAddBoundForwarder(
++ PBOUND_IMPORT_DESCRIPTOR BoundImportDescriptor,
++ LPSTR DllPath,
++ PUCHAR ForwarderString
++ )
++{
++ CHAR DllName[256];
++ PUCHAR TempDllName;
++ PLOADED_IMAGE LoadedLibrary;
++ ULONG DllNameSize;
++ USHORT OrdinalNumber = 0;
++ 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);
++ lstrcpynA(DllName, ForwarderString, DllNameSize + 1);
++
++ /* Append .DLL extension */
++ DllName[DllNameSize] = '\0';
++ strcat(DllName, ".DLL" );
++
++ /* Load it */
++ TRACE("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;
++ TRACE("It Loaded at: %p \n", LoadedLibrary->MappedAddress);
++
++ /* Load Exports */
++ Exports = RtlImageDirectoryEntryToData((HMODULE)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 (!lstrcmpiA(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)RtlImageDirectoryEntryToData ((HMODULE)LoadedLibrary->MappedAddress,
++ TRUE,
++ IMAGE_DIRECTORY_ENTRY_EXPORT,
++ &ExportSize) -
++ (ULONG_PTR)LoadedLibrary->MappedAddress;
++ ExportsBase += OptionalHeader32->ImageBase;
++
++ TRACE("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;
++}
++
++/*
++ * 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
++WINAPI
++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);
++
++ TRACE("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)RtlImageDirectoryEntryToData ((HMODULE)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)) {
++
++ TRACE("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;
++}
++
++/*
++ * 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
++WINAPI
++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;
++}
++
++/*
++ * 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
++WINAPI
++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;
++
++ TRACE("BindpWalkAndBindImports Called\n");
++
++ /* Load the Import Descriptor */
++ Imports = RtlImageDirectoryEntryToData ((HMODULE)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));
++
++ TRACE("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);
++
++ TRACE("Loading Imported DLL: %s \n", ImportedLibrary);
++
++ /* Load the DLL */
++ LoadedLibrary = ImageLoad(ImportedLibrary, DllPath);
++
++ TRACE("DLL Loaded at: %p \n", LoadedLibrary->MappedAddress);
++
++ /* Now load the Exports */
++ Exports = RtlImageDirectoryEntryToData ((HMODULE)LoadedLibrary->MappedAddress,
++ FALSE,
++ IMAGE_DIRECTORY_ENTRY_EXPORT,
++ &SizeOfExports);
++
++ /* And load the Thunks */
++ Thunks = ImageRvaToVa (File->FileHeader,
++ File->MappedAddress,
++ (ULONG)Imports->u.OriginalFirstThunk,
++ &File->LastRvaSection);
++
++ /* No actual Exports (UPX Packer can do this */
++ if (!Thunks) continue;
++
++ TRACE("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);
++
++ TRACE("Binding Thunks %p\n",BoundThunks);
++
++ /* 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);
++
++ TRACE("Copying Bound Thunks %p\n",TempThunk);
++
++ /* 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);
++
++ TRACE("Moving to next File\n");
++ }
++
++ TRACE("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;
++
++ TRACE("Calculating Space, %lx bytes free\n",PhysBytesFree);
++
++ if (BoundImportTableSize > VirtBytesFree) {
++ if (BoundImportTableSize > HeaderBytesFree) {
++ TRACE("Only %lx bytes free. Not enough Space\n",HeaderBytesFree);
++ return; /* Fail...not enough space */
++ }
++ if (BoundImportTableSize <= PhysBytesFree) {
++
++ TRACE("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 {
++
++ /* Resize the Headers */
++ FIXME("Add support for Header Resizing\n");
++
++ /* 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;
++
++ TRACE("Copying Bound Import Table\n");
++
++ /* Copy the Bound Import Table */
++ RtlCopyMemory(File->MappedAddress + FirstFreeByte, BoundImportTable, BoundImportTableSize);
++
++ /* Free out local copy */
++ GlobalFree(BoundImportTable);
++}
+
+ /***********************************************************************
+ * BindImage (IMAGEHLP.@)
+@@ -42,21 +703,80 @@
+ return BindImageEx(0, ImageName, DllPath, SymbolPath, NULL);
+ }
+
+-/***********************************************************************
+- * BindImageEx (IMAGEHLP.@)
++/*
++ * 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)
+-{
+- FIXME("(%ld, %s, %s, %s, %p): stub\n",
+- Flags, debugstr_a(ImageName), debugstr_a(DllPath),
+- debugstr_a(SymbolPath), StatusRoutine
[truncated at 1000 lines; 68 more skipped]