- Corrected processing import directories to handle case when executable imports the same DLL more times.

svn path=/trunk/; revision=8549
This commit is contained in:
Filip Navara 2004-03-06 20:32:06 +00:00
parent fa714393ca
commit c3d3178f3e

View file

@ -1,4 +1,4 @@
/* $Id: utils.c,v 1.82 2004/01/31 23:53:45 gvg Exp $ /* $Id: utils.c,v 1.83 2004/03/06 20:32:06 navaraf Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -1416,118 +1416,125 @@ LdrpGetOrLoadModule(PWCHAR SerachPath,
} }
static NTSTATUS static NTSTATUS
LdrpProcessImportDirectory(PLDR_MODULE Module, LdrpProcessImportDirectory(
PLDR_MODULE ImportedModule, PLDR_MODULE Module,
PCHAR ImportedName) PLDR_MODULE ImportedModule,
PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory,
PCHAR ImportedName)
{ {
PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
NTSTATUS Status; NTSTATUS Status;
PVOID* ImportAddressList; PVOID* ImportAddressList;
PULONG FunctionNameList; PULONG FunctionNameList;
DWORD pName;
WORD pHint;
PVOID IATBase; PVOID IATBase;
ULONG OldProtect; ULONG OldProtect;
ULONG Ordinal; ULONG Ordinal;
ULONG IATSize; ULONG IATSize;
PCHAR Name;
DPRINT("LdrpProcessImportDirectory(%x '%wZ', %x '%wZ', %x '%s')\n", DPRINT("LdrpProcessImportDirectory(%x '%wZ', '%s')\n",
Module, &Module->BaseDllName, ImportedModule, Module, &Module->BaseDllName, ImportedName);
&ImportedModule->BaseDllName, ImportedName, ImportedName);
ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
RtlImageDirectoryEntryToData(Module->BaseAddress,
TRUE,
IMAGE_DIRECTORY_ENTRY_IMPORT,
NULL);
if (ImportModuleDirectory == NULL) if (ImportModuleDirectory == NULL)
{ {
return STATUS_UNSUCCESSFUL; PCHAR Name;
ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
RtlImageDirectoryEntryToData(Module->BaseAddress,
TRUE,
IMAGE_DIRECTORY_ENTRY_IMPORT,
NULL);
if (ImportModuleDirectory == NULL)
{
return STATUS_UNSUCCESSFUL;
}
while (ImportModuleDirectory->dwRVAModuleName)
{
Name = (PCHAR)Module->BaseAddress + ImportModuleDirectory->dwRVAModuleName;
if (0 == _stricmp(Name, ImportedName))
{
break;
}
ImportModuleDirectory++;
}
if (ImportModuleDirectory->dwRVAModuleName == 0)
{
return STATUS_UNSUCCESSFUL;
}
} }
while (ImportModuleDirectory->dwRVAModuleName) /* Get the import address list. */
ImportAddressList = (PVOID *)(Module->BaseAddress + ImportModuleDirectory->dwRVAFunctionAddressList);
/* Get the list of functions to import. */
if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
{ {
Name = (PCHAR)Module->BaseAddress + ImportModuleDirectory->dwRVAModuleName; FunctionNameList = (PULONG) (Module->BaseAddress + ImportModuleDirectory->dwRVAFunctionNameList);
if (0 == _stricmp(Name, ImportedName)) }
{ else
{
FunctionNameList = (PULONG)(Module->BaseAddress + ImportModuleDirectory->dwRVAFunctionAddressList);
}
/* Get the import address list. */ /* Get the size of IAT. */
ImportAddressList = (PVOID *)(Module->BaseAddress + ImportModuleDirectory->dwRVAFunctionAddressList); IATSize = 0;
while (FunctionNameList[IATSize] != 0L)
{
IATSize++;
}
/* Get the list of functions to import. */ /* Unprotect the region we are about to write into. */
if (ImportModuleDirectory->dwRVAFunctionNameList != 0) IATBase = (PVOID)ImportAddressList;
{ Status = NtProtectVirtualMemory(NtCurrentProcess(),
FunctionNameList = (PULONG) (Module->BaseAddress + ImportModuleDirectory->dwRVAFunctionNameList); IATBase,
} IATSize * sizeof(PVOID*),
else PAGE_READWRITE,
{ &OldProtect);
FunctionNameList = (PULONG)(Module->BaseAddress + ImportModuleDirectory->dwRVAFunctionAddressList); if (!NT_SUCCESS(Status))
} {
DPRINT1("Failed to unprotect IAT.\n");
/* Get the size of IAT. */ return(Status);
IATSize = 0; }
while (FunctionNameList[IATSize] != 0L)
{ /* Walk through function list and fixup addresses. */
IATSize++; while (*FunctionNameList != 0L)
} {
if ((*FunctionNameList) & 0x80000000)
/* Unprotect the region we are about to write into. */ {
IATBase = (PVOID)ImportAddressList; Ordinal = (*FunctionNameList) & 0x7fffffff;
Status = NtProtectVirtualMemory(NtCurrentProcess(), *ImportAddressList = LdrGetExportByOrdinal(ImportedModule->BaseAddress, Ordinal);
IATBase, }
IATSize * sizeof(PVOID*), else
PAGE_READWRITE, {
&OldProtect); IMAGE_IMPORT_BY_NAME *pe_name;
if (!NT_SUCCESS(Status)) pe_name = RVA(Module->BaseAddress, *FunctionNameList);
*ImportAddressList = LdrGetExportByName(ImportedModule->BaseAddress, pe_name->Name, pe_name->Hint);
if ((*ImportAddressList) == NULL)
{ {
DPRINT1("Failed to unprotect IAT.\n"); DPRINT1("Failed to import %s\n", pe_name->Name);
return(Status); return STATUS_UNSUCCESSFUL;
} }
}
/* Walk through function list and fixup addresses. */ ImportAddressList++;
FunctionNameList++;
while (*FunctionNameList != 0L) }
{
if ((*FunctionNameList) & 0x80000000)
{
Ordinal = (*FunctionNameList) & 0x7fffffff;
*ImportAddressList = LdrGetExportByOrdinal(ImportedModule->BaseAddress, Ordinal);
}
else
{
pName = (DWORD) (Module->BaseAddress + *FunctionNameList + 2);
pHint = *(PWORD)(Module->BaseAddress + *FunctionNameList);
*ImportAddressList = LdrGetExportByName(ImportedModule->BaseAddress, (PUCHAR)pName, pHint); /* Protect the region we are about to write into. */
if ((*ImportAddressList) == NULL) Status = NtProtectVirtualMemory(NtCurrentProcess(),
{ IATBase,
DPRINT1("Failed to import %s\n", pName); IATSize * sizeof(PVOID*),
return STATUS_UNSUCCESSFUL; OldProtect,
} &OldProtect);
} if (!NT_SUCCESS(Status))
ImportAddressList++; {
FunctionNameList++; DPRINT1("Failed to protect IAT.\n");
} return(Status);
/* Protect the region we are about to write into. */
Status = NtProtectVirtualMemory(NtCurrentProcess(),
IATBase,
IATSize * sizeof(PVOID*),
OldProtect,
&OldProtect);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to protect IAT.\n");
return(Status);
}
}
ImportModuleDirectory++;
} }
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
NTSTATUS LdrpAdjustImportDirectory(PLDR_MODULE Module, NTSTATUS LdrpAdjustImportDirectory(PLDR_MODULE Module,
PLDR_MODULE ImportedModule, PLDR_MODULE ImportedModule,
PUCHAR ImportedName) PUCHAR ImportedName)
@ -1726,7 +1733,7 @@ LdrFixupImports(IN PWSTR SearchPath OPTIONAL,
{ {
TRACE_LDR("%wZ has stale binding to %wZ\n", TRACE_LDR("%wZ has stale binding to %wZ\n",
&Module->BaseDllName, &ImportedModule->BaseDllName); &Module->BaseDllName, &ImportedModule->BaseDllName);
Status = LdrpProcessImportDirectory(Module, ImportedModule, ImportedName); Status = LdrpProcessImportDirectory(Module, ImportedModule, NULL, ImportedName);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("failed to import %s\n", ImportedName); DPRINT1("failed to import %s\n", ImportedName);
@ -1787,7 +1794,7 @@ LdrFixupImports(IN PWSTR SearchPath OPTIONAL,
if (WrongForwarder || if (WrongForwarder ||
ImportedModule->Flags & IMAGE_NOT_AT_BASE) ImportedModule->Flags & IMAGE_NOT_AT_BASE)
{ {
Status = LdrpProcessImportDirectory(Module, ImportedModule, ImportedName); Status = LdrpProcessImportDirectory(Module, ImportedModule, NULL, ImportedName);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("failed to import %s\n", ImportedName); DPRINT1("failed to import %s\n", ImportedName);
@ -1813,7 +1820,7 @@ LdrFixupImports(IN PWSTR SearchPath OPTIONAL,
*/ */
TRACE_LDR("Stale BIND %s from %wZ\n", TRACE_LDR("Stale BIND %s from %wZ\n",
ImportedName, &Module->BaseDllName); ImportedName, &Module->BaseDllName);
Status = LdrpProcessImportDirectory(Module, ImportedModule, ImportedName); Status = LdrpProcessImportDirectory(Module, ImportedModule, NULL, ImportedName);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("faild to import %s\n", ImportedName); DPRINT1("faild to import %s\n", ImportedName);
@ -1844,13 +1851,14 @@ LdrFixupImports(IN PWSTR SearchPath OPTIONAL,
DPRINT1("failed to load %s\n", ImportedName); DPRINT1("failed to load %s\n", ImportedName);
return Status; return Status;
} }
if (Module == ImportedModule) if (Module == ImportedModule)
{ {
LdrpDecrementLoadCount(Module, FALSE); LdrpDecrementLoadCount(Module, FALSE);
} }
TRACE_LDR("Initializing imports for %wZ from %s\n", TRACE_LDR("Initializing imports for %wZ from %s\n",
&Module->BaseDllName, ImportedName); &Module->BaseDllName, ImportedName);
Status = LdrpProcessImportDirectory(Module, ImportedModule, ImportedName); Status = LdrpProcessImportDirectory(Module, ImportedModule, ImportModuleDirectoryCurrent, ImportedName);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("failed to import %s\n", ImportedName); DPRINT1("failed to import %s\n", ImportedName);
@ -1859,6 +1867,7 @@ LdrFixupImports(IN PWSTR SearchPath OPTIONAL,
ImportModuleDirectoryCurrent++; ImportModuleDirectoryCurrent++;
} }
} }
if (TlsDirectory && TlsSize > 0) if (TlsDirectory && TlsSize > 0)
{ {
LdrpAcquireTlsSlot(Module, TlsSize, FALSE); LdrpAcquireTlsSlot(Module, TlsSize, FALSE);