You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
903 lines
27 KiB
903 lines
27 KiB
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
blbind.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the code that implements the funtions required
|
|
to relocate an image and bind DLL entry points.
|
|
|
|
Author:
|
|
|
|
David N. Cutler (davec) 21-May-1991
|
|
|
|
Revision History:
|
|
|
|
Forrest Foltz (forrestf) 10-Jun-2000
|
|
|
|
Broke out x86 32/64 code into this module
|
|
|
|
--*/
|
|
|
|
#if defined(_X86AMD64_)
|
|
//
|
|
// warning 4305 is "typecast truncation"
|
|
// right now, the amd64 code grabs certain 64 bit definitions,
|
|
// but is compiled for 32 bit. as a result, a pointer here
|
|
// is only 32 bits, but there are definitions for 64 bit
|
|
// structures. ignore these for now, but amd64 should really
|
|
// have it's own headers for these structures
|
|
//
|
|
#pragma warning(disable:4305)
|
|
#endif
|
|
|
|
//
|
|
// Define local procedure prototypes.
|
|
//
|
|
|
|
ARC_STATUS
|
|
BlpScanImportAddressTable(
|
|
IN PVOID DllBase,
|
|
IN PVOID ImageBase,
|
|
IN PIMAGE_THUNK_DATA ThunkNameTable,
|
|
IN PIMAGE_THUNK_DATA ThunkAddressTable
|
|
);
|
|
|
|
ARC_STATUS
|
|
BlpBindImportName (
|
|
IN PVOID DllBase,
|
|
IN PVOID ImageBase,
|
|
IN PIMAGE_THUNK_DATA ThunkNameEntry,
|
|
IN PIMAGE_THUNK_DATA ThunkAddressEntry,
|
|
IN PIMAGE_EXPORT_DIRECTORY ExportDirectory,
|
|
IN ULONG ExportSize,
|
|
IN BOOLEAN SnapForwarder
|
|
);
|
|
|
|
|
|
ARC_STATUS
|
|
BlAllocateDataTableEntry (
|
|
IN PCHAR BaseDllName,
|
|
IN PCHAR FullDllName,
|
|
IN PVOID Base,
|
|
OUT PKLDR_DATA_TABLE_ENTRY *AllocatedEntry
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine allocates a data table entry for the specified image
|
|
and inserts the entry in the loaded module list.
|
|
|
|
Arguments:
|
|
|
|
BaseDllName - Supplies a pointer to a zero terminated base DLL name.
|
|
|
|
FullDllName - Supplies a pointer to a zero terminated full DLL name.
|
|
|
|
Base - Supplies a pointer to the base of the DLL image.
|
|
|
|
AllocatedEntry - Supplies a pointer to a variable that receives a
|
|
pointer to the allocated data table entry.
|
|
|
|
Return Value:
|
|
|
|
ESUCCESS is returned if a data table entry is allocated. Otherwise,
|
|
return a unsuccessful status.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PWSTR Buffer;
|
|
PKLDR_DATA_TABLE_ENTRY DataTableEntry;
|
|
PIMAGE_NT_HEADERS NtHeaders;
|
|
USHORT Length;
|
|
|
|
//
|
|
// Allocate a data table entry.
|
|
//
|
|
|
|
DataTableEntry =
|
|
(PKLDR_DATA_TABLE_ENTRY)BlAllocateHeap(sizeof(KLDR_DATA_TABLE_ENTRY));
|
|
|
|
if (DataTableEntry == NULL) {
|
|
return ENOMEM;
|
|
}
|
|
|
|
//
|
|
// Initialize the address of the DLL image file header and the entry
|
|
// point address.
|
|
//
|
|
|
|
NtHeaders = IMAGE_NT_HEADER(Base);
|
|
DataTableEntry->DllBase = Base;
|
|
DataTableEntry->SizeOfImage = NtHeaders->OptionalHeader.SizeOfImage;
|
|
DataTableEntry->EntryPoint = (PVOID)((ULONG_PTR)Base +
|
|
NtHeaders->OptionalHeader.AddressOfEntryPoint);
|
|
DataTableEntry->SectionPointer = 0;
|
|
DataTableEntry->CheckSum = NtHeaders->OptionalHeader.CheckSum;
|
|
|
|
//
|
|
// Compute the length of the base DLL name, allocate a buffer to hold
|
|
// the name, copy the name into the buffer, and initialize the base
|
|
// DLL string descriptor.
|
|
//
|
|
|
|
Length = (USHORT)(strlen(BaseDllName) * sizeof(WCHAR));
|
|
Buffer = (PWSTR)BlAllocateHeap(Length);
|
|
if (Buffer == NULL) {
|
|
return ENOMEM;
|
|
}
|
|
|
|
DataTableEntry->BaseDllName.Length = Length;
|
|
DataTableEntry->BaseDllName.MaximumLength = Length;
|
|
DataTableEntry->BaseDllName.Buffer = Buffer;
|
|
while (*BaseDllName != 0) {
|
|
*Buffer++ = *BaseDllName++;
|
|
}
|
|
|
|
//
|
|
// Compute the length of the full DLL name, allocate a buffer to hold
|
|
// the name, copy the name into the buffer, and initialize the full
|
|
// DLL string descriptor.
|
|
//
|
|
|
|
Length = (USHORT)(strlen(FullDllName) * sizeof(WCHAR));
|
|
Buffer = (PWSTR)BlAllocateHeap(Length);
|
|
if (Buffer == NULL) {
|
|
return ENOMEM;
|
|
}
|
|
|
|
DataTableEntry->FullDllName.Length = Length;
|
|
DataTableEntry->FullDllName.MaximumLength = Length;
|
|
DataTableEntry->FullDllName.Buffer = Buffer;
|
|
while (*FullDllName != 0) {
|
|
*Buffer++ = *FullDllName++;
|
|
}
|
|
|
|
//
|
|
// Initialize the flags, load count, and insert the data table entry
|
|
// in the loaded module list.
|
|
//
|
|
|
|
DataTableEntry->Flags = LDRP_ENTRY_PROCESSED;
|
|
DataTableEntry->LoadCount = 1;
|
|
InsertTailList(&BlLoaderBlock->LoadOrderListHead,
|
|
&DataTableEntry->InLoadOrderLinks);
|
|
|
|
*AllocatedEntry = DataTableEntry;
|
|
return ESUCCESS;
|
|
}
|
|
|
|
ARC_STATUS
|
|
BlAllocateFirmwareTableEntry (
|
|
IN PCHAR BaseDllName,
|
|
IN PCHAR FullDllName,
|
|
IN PVOID Base,
|
|
IN ULONG Size,
|
|
OUT PKLDR_DATA_TABLE_ENTRY *AllocatedEntry
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine allocates a firmware table entry for the specified image
|
|
and inserts the entry in the loaded module list.
|
|
|
|
Arguments:
|
|
|
|
BaseDllName - Supplies a pointer to a zero terminated base DLL name.
|
|
|
|
FullDllName - Supplies a pointer to a zero terminated full DLL name.
|
|
|
|
Base - Supplies a pointer to the base of the DLL image.
|
|
|
|
Size - Supplies how big the image is.
|
|
|
|
AllocatedEntry - Supplies a pointer to a variable that receives a
|
|
pointer to the allocated data table entry.
|
|
|
|
Return Value:
|
|
|
|
ESUCCESS is returned if a data table entry is allocated. Otherwise,
|
|
return a unsuccessful status.
|
|
|
|
--*/
|
|
{
|
|
PWSTR Buffer;
|
|
PKLDR_DATA_TABLE_ENTRY DataTableEntry;
|
|
USHORT Length;
|
|
|
|
//
|
|
// Allocate a data table entry.
|
|
//
|
|
|
|
DataTableEntry =
|
|
(PKLDR_DATA_TABLE_ENTRY)BlAllocateHeap(sizeof(KLDR_DATA_TABLE_ENTRY));
|
|
|
|
if (DataTableEntry == NULL) {
|
|
return ENOMEM;
|
|
}
|
|
|
|
//
|
|
// Initialize the address of the firmware image
|
|
//
|
|
DataTableEntry->DllBase = Base;
|
|
DataTableEntry->SizeOfImage = Size;
|
|
DataTableEntry->EntryPoint = Base;
|
|
DataTableEntry->SectionPointer = 0;
|
|
DataTableEntry->CheckSum = 0;
|
|
|
|
//
|
|
// Compute the length of the base DLL name, allocate a buffer to hold
|
|
// the name, copy the name into the buffer, and initialize the base
|
|
// DLL string descriptor.
|
|
//
|
|
Length = (USHORT)(strlen(BaseDllName) * sizeof(WCHAR));
|
|
Buffer = (PWSTR)BlAllocateHeap(Length);
|
|
if (Buffer == NULL) {
|
|
return ENOMEM;
|
|
}
|
|
|
|
DataTableEntry->BaseDllName.Length = Length;
|
|
DataTableEntry->BaseDllName.MaximumLength = Length;
|
|
DataTableEntry->BaseDllName.Buffer = Buffer;
|
|
while (*BaseDllName != 0) {
|
|
*Buffer++ = *BaseDllName++;
|
|
}
|
|
|
|
//
|
|
// Compute the length of the full DLL name, allocate a buffer to hold
|
|
// the name, copy the name into the buffer, and initialize the full
|
|
// DLL string descriptor.
|
|
//
|
|
|
|
Length = (USHORT)(strlen(FullDllName) * sizeof(WCHAR));
|
|
Buffer = (PWSTR)BlAllocateHeap(Length);
|
|
if (Buffer == NULL) {
|
|
return ENOMEM;
|
|
}
|
|
|
|
DataTableEntry->FullDllName.Length = Length;
|
|
DataTableEntry->FullDllName.MaximumLength = Length;
|
|
DataTableEntry->FullDllName.Buffer = Buffer;
|
|
while (*FullDllName != 0) {
|
|
*Buffer++ = *FullDllName++;
|
|
}
|
|
|
|
//
|
|
// Initialize the flags, load count, and insert the data table entry
|
|
// in the loaded module list.
|
|
//
|
|
|
|
DataTableEntry->Flags = LDRP_ENTRY_PROCESSED;
|
|
DataTableEntry->LoadCount = 1;
|
|
InsertTailList(&BlLoaderBlock->Extension->FirmwareDescriptorListHead,
|
|
&DataTableEntry->InLoadOrderLinks);
|
|
|
|
*AllocatedEntry = DataTableEntry;
|
|
return ESUCCESS;
|
|
}
|
|
|
|
ARC_STATUS
|
|
BlpBindImportName (
|
|
IN PVOID DllBase,
|
|
IN PVOID ImageBase,
|
|
IN PIMAGE_THUNK_DATA ThunkNameEntry,
|
|
IN PIMAGE_THUNK_DATA ThunkAddressEntry,
|
|
IN PIMAGE_EXPORT_DIRECTORY ExportDirectory,
|
|
IN ULONG ExportSize,
|
|
IN BOOLEAN SnapForwarder
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine binds an import table reference with an exported entry
|
|
point and fills in the thunk data.
|
|
|
|
Arguments:
|
|
|
|
DllBase - Supplies the base address of the DLL image that contains
|
|
the export directory. On x86 systems, a NULL DllBase binds the
|
|
import table reference to the OsLoader's exported entry points.
|
|
|
|
ImageBase - Supplies the base address of the image that contains
|
|
the import thunk table.
|
|
|
|
ThunkNameEntry - Supplies a pointer to a thunk table name entry.
|
|
|
|
ThunkAddressEntry - Supplies a pointer to a thunk table address entry.
|
|
|
|
ExportDirectory - Supplies a pointer to the export directory of the
|
|
DLL from which references are to be resolved.
|
|
|
|
SnapForwarder - determine if the snap is for a forwarder, and therefore
|
|
Address of Data is already setup.
|
|
|
|
Return Value:
|
|
|
|
ESUCCESS is returned if the specified thunk is bound. Otherwise, an
|
|
return an unsuccessful status.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PULONG FunctionTable;
|
|
LONG High;
|
|
ULONG HintIndex;
|
|
LONG Low;
|
|
LONG Middle = 0;
|
|
PULONG NameTable;
|
|
ULONG Ordinal;
|
|
PUSHORT OrdinalTable;
|
|
LONG Result;
|
|
PCHAR Temp;
|
|
|
|
#if defined(_X86_)
|
|
|
|
if(DllBase == NULL) {
|
|
DllBase = (PVOID)OsLoaderBase;
|
|
}
|
|
|
|
#endif
|
|
|
|
//
|
|
// If the reference is by ordinal, then compute the ordinal number.
|
|
// Otherwise, lookup the import name in the export directory.
|
|
//
|
|
|
|
if (IMAGE_SNAP_BY_ORDINAL(ThunkNameEntry->u1.Ordinal) && !SnapForwarder) {
|
|
|
|
//
|
|
// Compute the ordinal.
|
|
//
|
|
|
|
Ordinal = (ULONG)(IMAGE_ORDINAL(ThunkNameEntry->u1.Ordinal) - ExportDirectory->Base);
|
|
|
|
} else {
|
|
|
|
if (!SnapForwarder) {
|
|
//
|
|
// Change AddressOfData from an RVA to a VA.
|
|
//
|
|
|
|
ThunkNameEntry->u1.AddressOfData = ((ULONG_PTR)ImageBase + ThunkNameEntry->u1.AddressOfData);
|
|
}
|
|
|
|
//
|
|
// Lookup the import name in the export table to determine the
|
|
// ordinal.
|
|
//
|
|
|
|
NameTable = (PULONG)((ULONG_PTR)DllBase +
|
|
ExportDirectory->AddressOfNames);
|
|
|
|
OrdinalTable = (PUSHORT)((ULONG_PTR)DllBase +
|
|
ExportDirectory->AddressOfNameOrdinals);
|
|
|
|
//
|
|
// If the hint index is within the limits of the name table and the
|
|
// import and export names match, then the ordinal number can be
|
|
// obtained directly from the ordinal table. Otherwise, the name
|
|
// table must be searched for the specified name.
|
|
//
|
|
|
|
HintIndex = ((PIMAGE_IMPORT_BY_NAME)ThunkNameEntry->u1.AddressOfData)->Hint;
|
|
if ((HintIndex < ExportDirectory->NumberOfNames) &&
|
|
(strcmp((PCHAR)(&((PIMAGE_IMPORT_BY_NAME)ThunkNameEntry->u1.AddressOfData)->Name[0]),
|
|
(PCHAR)((ULONG_PTR)DllBase + NameTable[HintIndex])) == 0)) {
|
|
|
|
//
|
|
// Get the ordinal number from the ordinal table.
|
|
//
|
|
|
|
Ordinal = OrdinalTable[HintIndex];
|
|
|
|
} else {
|
|
|
|
//
|
|
// Lookup the import name in the name table using a binary search.
|
|
//
|
|
|
|
Low = 0;
|
|
High = ExportDirectory->NumberOfNames - 1;
|
|
while (High >= Low) {
|
|
|
|
//
|
|
// Compute the next probe index and compare the import name
|
|
// with the export name entry.
|
|
//
|
|
|
|
Middle = (Low + High) >> 1;
|
|
Result = strcmp((PCHAR)(&((PIMAGE_IMPORT_BY_NAME)ThunkNameEntry->u1.AddressOfData)->Name[0]),
|
|
(PCHAR)((ULONG_PTR)DllBase + NameTable[Middle]));
|
|
|
|
if (Result < 0) {
|
|
High = Middle - 1;
|
|
|
|
} else if (Result > 0) {
|
|
Low = Middle + 1;
|
|
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If the high index is less than the low index, then a matching
|
|
// table entry was not found. Otherwise, get the ordinal number
|
|
// from the ordinal table.
|
|
//
|
|
|
|
if (High < Low) {
|
|
return EINVAL;
|
|
|
|
} else {
|
|
Ordinal = OrdinalTable[Middle];
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// If the ordinal number is valid, then bind the import reference and
|
|
// return success. Otherwise, return an unsuccessful status.
|
|
//
|
|
|
|
if (Ordinal >= ExportDirectory->NumberOfFunctions) {
|
|
return EINVAL;
|
|
}
|
|
|
|
FunctionTable = (PULONG)((ULONG_PTR)DllBase + ExportDirectory->AddressOfFunctions);
|
|
ThunkAddressEntry->u1.Function = ((ULONG_PTR)DllBase + FunctionTable[Ordinal]);
|
|
|
|
//
|
|
// Check for a forwarder.
|
|
//
|
|
if ( ((ULONG_PTR)ThunkAddressEntry->u1.Function > (ULONG_PTR)ExportDirectory) &&
|
|
((ULONG_PTR)ThunkAddressEntry->u1.Function < ((ULONG_PTR)ExportDirectory + ExportSize)) ) {
|
|
CHAR ForwardDllName[10];
|
|
PKLDR_DATA_TABLE_ENTRY DataTableEntry;
|
|
ULONG TargetExportSize;
|
|
PIMAGE_EXPORT_DIRECTORY TargetExportDirectory;
|
|
|
|
RtlCopyMemory(ForwardDllName,
|
|
(PCHAR)ThunkAddressEntry->u1.Function,
|
|
sizeof(ForwardDllName));
|
|
Temp = strchr(ForwardDllName,'.');
|
|
|
|
ASSERT(Temp != NULL); // Malformed name, stop here and debug why.
|
|
|
|
if (Temp != NULL) {
|
|
*Temp = '\0';
|
|
}
|
|
|
|
if (!BlCheckForLoadedDll(ForwardDllName,&DataTableEntry)) {
|
|
//
|
|
// Should load the referenced DLL here, just return failure for now.
|
|
//
|
|
|
|
return(EINVAL);
|
|
}
|
|
TargetExportDirectory = (PIMAGE_EXPORT_DIRECTORY)
|
|
RtlImageDirectoryEntryToData(DataTableEntry->DllBase,
|
|
TRUE,
|
|
IMAGE_DIRECTORY_ENTRY_EXPORT,
|
|
&TargetExportSize);
|
|
if (TargetExportDirectory) {
|
|
|
|
IMAGE_THUNK_DATA thunkData;
|
|
PIMAGE_IMPORT_BY_NAME addressOfData;
|
|
UCHAR Buffer[128];
|
|
PCHAR ImportName;
|
|
ARC_STATUS Status;
|
|
|
|
ImportName = strchr((PCHAR)ThunkAddressEntry->u1.Function, '.') + 1;
|
|
addressOfData = (PIMAGE_IMPORT_BY_NAME)Buffer;
|
|
RtlCopyMemory(&addressOfData->Name[0], ImportName, strlen(ImportName)+1);
|
|
addressOfData->Hint = 0;
|
|
thunkData.u1.AddressOfData = (ULONG_PTR)addressOfData;
|
|
Status = BlpBindImportName(DataTableEntry->DllBase,
|
|
ImageBase,
|
|
&thunkData,
|
|
&thunkData,
|
|
TargetExportDirectory,
|
|
TargetExportSize,
|
|
TRUE);
|
|
ThunkAddressEntry->u1 = thunkData.u1;
|
|
return(Status);
|
|
} else {
|
|
return(EINVAL);
|
|
}
|
|
}
|
|
|
|
#if IMAGE_DEFINITIONS == 64
|
|
|
|
//
|
|
// The import is relative to KSEG0_BASE_X86. Adjust it so that it is
|
|
// relative to KSEG0_BASE_AMD64.
|
|
//
|
|
|
|
ThunkAddressEntry->u1.Function +=
|
|
((ULONG64)KSEG0_BASE_AMD64 - (ULONG)KSEG0_BASE_X86);
|
|
|
|
#endif
|
|
|
|
return ESUCCESS;
|
|
}
|
|
|
|
ARC_STATUS
|
|
BlpScanImportAddressTable(
|
|
IN PVOID DllBase,
|
|
IN PVOID ImageBase,
|
|
IN PIMAGE_THUNK_DATA ThunkNameTable,
|
|
IN PIMAGE_THUNK_DATA ThunkAddressTable
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine scans the import address table for the specified image
|
|
file and snaps each reference.
|
|
|
|
Arguments:
|
|
|
|
DllBase - Supplies the base address of the specified DLL.
|
|
If NULL, then references in the image's import table are to
|
|
be resolved against the osloader's export table.
|
|
|
|
ImageBase - Supplies the base address of the image.
|
|
|
|
ThunkNameTable - Supplies a pointer to the import thunk name table.
|
|
|
|
ThunkAddressTable - Supplies a pointer to the import thunk address table.
|
|
|
|
Return Value:
|
|
|
|
ESUCCESS is returned in the scan is successful. Otherwise, return an
|
|
unsuccessful status.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PIMAGE_EXPORT_DIRECTORY ExportDirectory;
|
|
ULONG ExportTableSize;
|
|
ARC_STATUS Status;
|
|
|
|
//
|
|
// Locate the export table in the image specified by the DLL base
|
|
// address.
|
|
//
|
|
|
|
#if i386
|
|
if (DllBase == NULL) {
|
|
ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)OsLoaderExports;
|
|
ExportTableSize = 0; // this is OK as this is only used to bind forwarded exports and osloader does not have any
|
|
} else {
|
|
ExportDirectory =
|
|
(PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(DllBase,
|
|
TRUE,
|
|
IMAGE_DIRECTORY_ENTRY_EXPORT,
|
|
&ExportTableSize);
|
|
}
|
|
#else
|
|
ExportDirectory =
|
|
(PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(DllBase,
|
|
TRUE,
|
|
IMAGE_DIRECTORY_ENTRY_EXPORT,
|
|
&ExportTableSize);
|
|
#endif
|
|
if (ExportDirectory == NULL) {
|
|
return EBADF;
|
|
}
|
|
|
|
//
|
|
// Scan the thunk table and bind each import reference.
|
|
//
|
|
|
|
while (ThunkNameTable->u1.AddressOfData) {
|
|
Status = BlpBindImportName(DllBase,
|
|
ImageBase,
|
|
ThunkNameTable,
|
|
ThunkAddressTable,
|
|
ExportDirectory,
|
|
ExportTableSize,
|
|
FALSE);
|
|
if (Status != ESUCCESS) {
|
|
#if defined(_X86AMD64_)
|
|
ICEBP;
|
|
#endif
|
|
return Status;
|
|
}
|
|
ThunkNameTable++;
|
|
ThunkAddressTable++;
|
|
}
|
|
|
|
return ESUCCESS;
|
|
}
|
|
|
|
ARC_STATUS
|
|
BlScanImportDescriptorTable(
|
|
IN PPATH_SET PathSet,
|
|
IN PKLDR_DATA_TABLE_ENTRY ScanEntry,
|
|
IN TYPE_OF_MEMORY MemoryType
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine scans the import descriptor table for the specified image
|
|
file and loads each DLL that is referenced.
|
|
|
|
Arguments:
|
|
|
|
PathSet - Supplies a pointer to a set of paths to scan when searching
|
|
for DLL's.
|
|
|
|
ScanEntry - Supplies a pointer to the data table entry for the
|
|
image whose import table is to be scanned.
|
|
|
|
MemoryType - Supplies the type of memory to to be assigned to any DLL's
|
|
referenced.
|
|
|
|
Return Value:
|
|
|
|
ESUCCESS is returned in the scan is successful. Otherwise, return an
|
|
unsuccessful status.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PKLDR_DATA_TABLE_ENTRY DataTableEntry;
|
|
CHAR FullDllName[256];
|
|
PVOID Base = NULL;
|
|
PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor;
|
|
ULONG ImportTableSize;
|
|
ARC_STATUS Status;
|
|
PSZ ImportName;
|
|
ULONG Index;
|
|
PPATH_SOURCE PathSource;
|
|
|
|
//
|
|
// Locate the import table in the image specified by the data table entry.
|
|
//
|
|
|
|
ImportDescriptor =
|
|
(PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(ScanEntry->DllBase,
|
|
TRUE,
|
|
IMAGE_DIRECTORY_ENTRY_IMPORT,
|
|
&ImportTableSize);
|
|
|
|
//
|
|
// If the image has an import directory, then scan the import table and
|
|
// load the specified DLLs.
|
|
//
|
|
|
|
if (ImportDescriptor != NULL) {
|
|
while ((ImportDescriptor->Name != 0) &&
|
|
(ImportDescriptor->OriginalFirstThunk != 0)) {
|
|
|
|
//
|
|
// Change the name from an RVA to a VA.
|
|
//
|
|
|
|
ImportName = (PSZ)((ULONG_PTR)ScanEntry->DllBase + ImportDescriptor->Name);
|
|
|
|
//
|
|
// If the DLL references itself, then skip the import entry.
|
|
//
|
|
|
|
if (BlpCompareDllName((PCHAR)ImportName,
|
|
&ScanEntry->BaseDllName) == FALSE) {
|
|
|
|
//
|
|
// If the DLL is not already loaded, then load the DLL and
|
|
// scan its import table.
|
|
//
|
|
|
|
if (BlCheckForLoadedDll((PCHAR)ImportName,
|
|
&DataTableEntry) == FALSE) {
|
|
|
|
//
|
|
// Start walking our list of DevicePaths. If the list is
|
|
// empty (bad caller!) we fail with ENOENT.
|
|
//
|
|
Status = ENOENT;
|
|
for(Index=0; Index < PathSet->PathCount; Index++) {
|
|
|
|
PathSource = &PathSet->Source[Index];
|
|
|
|
strcpy(&FullDllName[0], PathSource->DirectoryPath);
|
|
strcat(&FullDllName[0], PathSet->PathOffset);
|
|
strcat(&FullDllName[0], (PCHAR)ImportName);
|
|
|
|
Status = BlLoadImage(
|
|
PathSource->DeviceId,
|
|
MemoryType,
|
|
&FullDllName[0],
|
|
TARGET_IMAGE,
|
|
&Base
|
|
);
|
|
|
|
if (Status == ESUCCESS) {
|
|
|
|
BlOutputLoadMessage(
|
|
(PCHAR) PathSource->DeviceName,
|
|
&FullDllName[0],
|
|
NULL
|
|
);
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (Status != ESUCCESS) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// ISSUE - 2000/29/03 - ADRIAO: Existant namespace polution
|
|
// For the FullDllName field We should really be passing
|
|
// in AliasName\PathOffset\ImportName.
|
|
//
|
|
Status = BlAllocateDataTableEntry((PCHAR)ImportName,
|
|
&FullDllName[0],
|
|
Base,
|
|
&DataTableEntry);
|
|
|
|
if (Status != ESUCCESS) {
|
|
return Status;
|
|
}
|
|
|
|
DataTableEntry->Flags |= (ScanEntry->Flags & LDRP_DRIVER_DEPENDENT_DLL);
|
|
|
|
Status = BlScanImportDescriptorTable(PathSet,
|
|
DataTableEntry,
|
|
MemoryType);
|
|
|
|
if (Status != ESUCCESS) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// BlAllocateDataTableEntry inserts the data table entry into the load order
|
|
// linked list in the order the dlls were found. We want the order to be the
|
|
// order of dependency. For example if driver A needed Dll B which needed Dll C
|
|
// we want the order to be ACB and not ABC. So here we remove this DLLs entry
|
|
// and add it at the end. This way when IoInitializeBootDrivers calls DllInitialize
|
|
// it will call them in the right order.
|
|
//
|
|
if (DataTableEntry->Flags &LDRP_DRIVER_DEPENDENT_DLL) {
|
|
RemoveEntryList(&(DataTableEntry)->InLoadOrderLinks);
|
|
InsertTailList(&BlLoaderBlock->LoadOrderListHead,
|
|
&DataTableEntry->InLoadOrderLinks);
|
|
}
|
|
|
|
} else {
|
|
//
|
|
// Dll already exists but it might not be marked as a driver dependent DLL.
|
|
// For example it might be a driver. So mark it now.
|
|
//
|
|
DataTableEntry->Flags |= (ScanEntry->Flags & LDRP_DRIVER_DEPENDENT_DLL);
|
|
}
|
|
|
|
//
|
|
// Scan the import address table and snap links.
|
|
//
|
|
|
|
Status = BlpScanImportAddressTable(DataTableEntry->DllBase,
|
|
ScanEntry->DllBase,
|
|
(PIMAGE_THUNK_DATA)((ULONG_PTR)ScanEntry->DllBase +
|
|
ImportDescriptor->OriginalFirstThunk),
|
|
(PIMAGE_THUNK_DATA)((ULONG_PTR)ScanEntry->DllBase +
|
|
ImportDescriptor->FirstThunk));
|
|
|
|
if (Status != ESUCCESS) {
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
ImportDescriptor += 1;
|
|
}
|
|
}
|
|
|
|
return ESUCCESS;
|
|
}
|
|
|
|
ARC_STATUS
|
|
BlScanOsloaderBoundImportTable (
|
|
IN PKLDR_DATA_TABLE_ENTRY ScanEntry
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine scans the import descriptor table for the specified image
|
|
file and loads each DLL that is referenced.
|
|
|
|
Arguments:
|
|
|
|
DataTableEntry - Supplies a pointer to the data table entry for the
|
|
image whose import table is to be scanned.
|
|
|
|
Return Value:
|
|
|
|
ESUCCESS is returned in the scan is successful. Otherwise, return an
|
|
unsuccessful status.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor;
|
|
ULONG ImportTableSize;
|
|
ARC_STATUS Status;
|
|
PSZ ImportName;
|
|
|
|
//
|
|
// Locate the import table in the image specified by the data table entry.
|
|
//
|
|
|
|
ImportDescriptor =
|
|
(PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(ScanEntry->DllBase,
|
|
TRUE,
|
|
IMAGE_DIRECTORY_ENTRY_IMPORT,
|
|
&ImportTableSize);
|
|
|
|
//
|
|
// If the image has an import directory, then scan the import table.
|
|
//
|
|
|
|
if (ImportDescriptor != NULL) {
|
|
while ((ImportDescriptor->Name != 0) &&
|
|
(ImportDescriptor->OriginalFirstThunk != 0)) {
|
|
|
|
//
|
|
// Change the name from an RVA to a VA.
|
|
//
|
|
|
|
ImportName = (PSZ)((ULONG_PTR)ScanEntry->DllBase + ImportDescriptor->Name);
|
|
|
|
//
|
|
// If the DLL references itself, then skip the import entry.
|
|
//
|
|
|
|
if (BlpCompareDllName((PCHAR)ImportName,
|
|
&ScanEntry->BaseDllName) == FALSE) {
|
|
|
|
//
|
|
// Scan the import address table and snap links.
|
|
//
|
|
|
|
Status = BlpScanImportAddressTable(NULL,
|
|
ScanEntry->DllBase,
|
|
(PIMAGE_THUNK_DATA)((ULONG_PTR)ScanEntry->DllBase +
|
|
ImportDescriptor->OriginalFirstThunk),
|
|
(PIMAGE_THUNK_DATA)((ULONG_PTR)ScanEntry->DllBase +
|
|
ImportDescriptor->FirstThunk));
|
|
|
|
if (Status != ESUCCESS) {
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
ImportDescriptor += 1;
|
|
}
|
|
}
|
|
|
|
return ESUCCESS;
|
|
}
|