mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-02 12:23:31 +00:00
Implemented ImageLoad, MapAndLoad, ImageRvaToVa, ImageRvaToSection, ImageDirectoryEntryToData, GetImageUnusedHeaderBytes and BindImageEx
svn path=/trunk/; revision=10233
This commit is contained in:
+330
-107
@@ -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; 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;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* 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; 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
+780
-14
@@ -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,
|
||||
|
||||
@@ -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*);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user