mirror of
https://github.com/reactos/reactos.git
synced 2025-01-02 20:43:18 +00:00
1cc5bd55b6
svn path=/trunk/; revision=2610
235 lines
5.4 KiB
C
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 */
|