reactos/reactos/ntoskrnl/ldr/rtl.c
Casper Hornstrup 1cc5bd55b6 Removed or changed debug prints printed at boot.
svn path=/trunk/; revision=2610
2002-02-08 02:57:10 +00:00

235 lines
5.4 KiB
C

/* $Id: rtl.c,v 1.13 2002/02/08 02:57:07 chorns Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ldr/loader.c
* PURPOSE: Loader utilities
* PROGRAMMERS: Jean Michault
* Rex Jolliff (rex@lvcablemodem.com)
*/
/* INCLUDES *****************************************************************/
#include <ddk/ntddk.h>
#include <internal/module.h>
#include <internal/ntoskrnl.h>
#include <internal/ob.h>
#include <internal/ps.h>
#include <internal/ldr.h>
#define NDEBUG
#include <internal/debug.h>
/* FUNCTIONS ****************************************************************/
PIMAGE_NT_HEADERS STDCALL
RtlImageNtHeader (IN PVOID BaseAddress)
{
PIMAGE_DOS_HEADER DosHeader;
PIMAGE_NT_HEADERS NTHeaders;
DosHeader = (PIMAGE_DOS_HEADER)BaseAddress;
NTHeaders = (PIMAGE_NT_HEADERS)(BaseAddress + DosHeader->e_lfanew);
if ((DosHeader->e_magic != IMAGE_DOS_MAGIC)
|| (DosHeader->e_lfanew == 0L)
|| (*(PULONG) NTHeaders != IMAGE_PE_MAGIC))
{
return(NULL);
}
return(NTHeaders);
}
PVOID STDCALL
RtlImageDirectoryEntryToData (IN PVOID BaseAddress,
IN BOOLEAN ImageLoaded,
IN ULONG Directory,
OUT PULONG Size)
{
PIMAGE_NT_HEADERS NtHeader;
PIMAGE_SECTION_HEADER SectionHeader;
ULONG Va;
ULONG Count;
NtHeader = RtlImageNtHeader (BaseAddress);
if (NtHeader == NULL)
return NULL;
if (Directory >= NtHeader->OptionalHeader.NumberOfRvaAndSizes)
return NULL;
Va = NtHeader->OptionalHeader.DataDirectory[Directory].VirtualAddress;
if (Va == 0)
return NULL;
if (Size)
*Size = NtHeader->OptionalHeader.DataDirectory[Directory].Size;
if (ImageLoaded)
return (PVOID)(BaseAddress + Va);
/* image mapped as ordinary file, we must find raw pointer */
SectionHeader = (PIMAGE_SECTION_HEADER)(NtHeader + 1);
Count = NtHeader->FileHeader.NumberOfSections;
while (Count--)
{
if (SectionHeader->VirtualAddress == Va)
return (PVOID)(BaseAddress + SectionHeader->PointerToRawData);
SectionHeader++;
}
return NULL;
}
PIMAGE_SECTION_HEADER
STDCALL
RtlImageRvaToSection (
PIMAGE_NT_HEADERS NtHeader,
PVOID BaseAddress,
ULONG Rva
)
{
PIMAGE_SECTION_HEADER Section;
ULONG Va;
ULONG Count;
Count = NtHeader->FileHeader.NumberOfSections;
Section = (PIMAGE_SECTION_HEADER)((ULONG)&NtHeader->OptionalHeader +
NtHeader->FileHeader.SizeOfOptionalHeader);
while (Count)
{
Va = Section->VirtualAddress;
if ((Va <= Rva) &&
(Rva < Va + Section->SizeOfRawData))
return Section;
Section++;
}
return NULL;
}
ULONG
STDCALL
RtlImageRvaToVa (
PIMAGE_NT_HEADERS NtHeader,
PVOID BaseAddress,
ULONG Rva,
PIMAGE_SECTION_HEADER *SectionHeader
)
{
PIMAGE_SECTION_HEADER Section = NULL;
if (SectionHeader)
Section = *SectionHeader;
if (Section == NULL ||
Rva < Section->VirtualAddress ||
Rva >= Section->VirtualAddress + Section->SizeOfRawData)
{
Section = RtlImageRvaToSection (NtHeader, BaseAddress, Rva);
if (Section == NULL)
return 0;
if (SectionHeader)
*SectionHeader = Section;
}
return (ULONG)(BaseAddress +
Rva +
Section->PointerToRawData -
Section->VirtualAddress);
}
#define RVA(m, b) ((ULONG)b + m)
NTSTATUS STDCALL
LdrGetProcedureAddress (IN PVOID BaseAddress,
IN PANSI_STRING Name,
IN ULONG Ordinal,
OUT PVOID *ProcedureAddress)
{
PIMAGE_EXPORT_DIRECTORY ExportDir;
PUSHORT OrdinalPtr;
PULONG NamePtr;
PULONG AddressPtr;
ULONG i = 0;
/* get the pointer to the export directory */
ExportDir = (PIMAGE_EXPORT_DIRECTORY)
RtlImageDirectoryEntryToData (BaseAddress, TRUE,
IMAGE_DIRECTORY_ENTRY_EXPORT, &i);
if (!ExportDir || !i || !ProcedureAddress)
{
return(STATUS_INVALID_PARAMETER);
}
AddressPtr = (PULONG)RVA(BaseAddress, ExportDir->AddressOfFunctions);
if (Name && Name->Length)
{
ULONG minn, maxn;
/* by name */
OrdinalPtr =
(PUSHORT)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals);
NamePtr = (PULONG)RVA(BaseAddress, ExportDir->AddressOfNames);
minn = 0; maxn = ExportDir->NumberOfNames;
while (minn <= maxn)
{
ULONG mid;
LONG res;
mid = (minn + maxn) / 2;
res = _strnicmp(Name->Buffer, (PCH)RVA(BaseAddress, NamePtr[mid]),
Name->Length);
if (res == 0)
{
*ProcedureAddress =
(PVOID)RVA(BaseAddress, AddressPtr[OrdinalPtr[mid]]);
return(STATUS_SUCCESS);
}
else if (res > 0)
{
maxn = mid - 1;
}
else
{
minn = mid + 1;
}
}
for (i = 0; i < ExportDir->NumberOfNames; i++, NamePtr++, OrdinalPtr++)
{
if (!_strnicmp(Name->Buffer,
(char*)(BaseAddress + *NamePtr), Name->Length))
{
*ProcedureAddress =
(PVOID)((ULONG)BaseAddress +
(ULONG)AddressPtr[*OrdinalPtr]);
return STATUS_SUCCESS;
}
}
CPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name);
}
else
{
/* by ordinal */
Ordinal &= 0x0000FFFF;
if (Ordinal - ExportDir->Base < ExportDir->NumberOfFunctions)
{
*ProcedureAddress =
(PVOID)((ULONG)BaseAddress +
(ULONG)AddressPtr[Ordinal - ExportDir->Base]);
return STATUS_SUCCESS;
}
CPRINT("LdrGetProcedureAddress: Can't resolve symbol @%d\n",
Ordinal);
}
return STATUS_PROCEDURE_NOT_FOUND;
}
/* EOF */