-/* $Id: rtl.c,v 1.8 2000/06/29 23:35:40 dwelch Exp $
+/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
- * FILE: ntoskrnl/ldr/loader.c
+ * FILE: ntoskrnl/ldr/rtl.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 <string.h>
-#include <internal/string.h>
-#include <internal/ldr.h>
-
+#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
/* FUNCTIONS ****************************************************************/
-#if 0
-static PVOID LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
- PUCHAR Name,
- USHORT Hint)
+NTSTATUS STDCALL
+LdrGetProcedureAddress (IN PVOID BaseAddress,
+ IN PANSI_STRING Name,
+ IN ULONG Ordinal,
+ OUT PVOID *ProcedureAddress)
{
- WORD Idx;
- DWORD ExportsStartRVA, ExportsEndRVA;
- PVOID ExportAddress;
- PWORD OrdinalList;
- PDWORD FunctionList, NameList;
- PIMAGE_SECTION_HEADER SectionHeader;
- PIMAGE_EXPORT_DIRECTORY ExportDirectory;
-
- ExportsStartRVA = ModuleObject->Image.PE.OptionalHeader->DataDirectory
- [IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
- ExportsEndRVA = ExportsStartRVA +
- ModuleObject->Image.PE.OptionalHeader->DataDirectory
- [IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
-
- /* Get the IMAGE_SECTION_HEADER that contains the exports. This is
- usually the .edata section, but doesn't have to be. */
- SectionHeader = LdrPEGetEnclosingSectionHeader(ExportsStartRVA, ModuleObject);
-
- if (!SectionHeader)
- {
- return 0;
- }
-
- ExportDirectory = MakePtr(PIMAGE_EXPORT_DIRECTORY,
- ModuleObject->Base,
- SectionHeader->VirtualAddress);
-
- FunctionList = (PDWORD)((DWORD)ExportDirectory->AddressOfFunctions + ModuleObject->Base);
- NameList = (PDWORD)((DWORD)ExportDirectory->AddressOfNames + ModuleObject->Base);
- OrdinalList = (PWORD)((DWORD)ExportDirectory->AddressOfNameOrdinals + ModuleObject->Base);
-
- ExportAddress = 0;
-
- if (Name != NULL)
- {
- for (Idx = 0; Idx < ExportDirectory->NumberOfNames; Idx++)
- {
-#if 0
- DPRINT(" Name:%s NameList[%d]:%s\n",
- Name,
- Idx,
- (DWORD) ModuleObject->Base + NameList[Idx]);
-
-#endif
- if (!strcmp(Name, (PCHAR) ((DWORD)ModuleObject->Base + NameList[Idx])))
+ PIMAGE_EXPORT_DIRECTORY ExportDir;
+ ULONG ExportDirSize = 0;
+ PUSHORT OrdinalPtr;
+ PULONG NamePtr;
+ PCHAR CurrentNamePtr;
+ PULONG AddressPtr;
+
+ if (ProcedureAddress == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ /* get the pointer to the export directory */
+ ExportDir = RtlImageDirectoryEntryToData(BaseAddress, TRUE,
+ IMAGE_DIRECTORY_ENTRY_EXPORT,
+ &ExportDirSize);
+
+ if (ExportDir == NULL || ExportDirSize == 0)
+ return STATUS_INVALID_PARAMETER;
+
+ AddressPtr = (PULONG)RVA(BaseAddress, ExportDir->AddressOfFunctions);
+
+ if (Name && Name->Length)
+ {
+ LONG minn, maxn, mid, res;
+
+ /* Search for export by name */
+
+ /*
+ * NOTE: Exports are always sorted and so we can apply binary search.
+ * Also the function names are _case sensitive_, so respect that.
+ * -- Filip Navara, August 1st, 2005
+ */
+
+ OrdinalPtr = (PUSHORT)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals);
+ NamePtr = (PULONG)RVA(BaseAddress, ExportDir->AddressOfNames);
+
+ minn = 0; maxn = ExportDir->NumberOfNames - 1;
+ while (minn <= maxn)
+ {
+ mid = (minn + maxn) / 2;
+ CurrentNamePtr = (PCHAR)RVA(BaseAddress, NamePtr[mid]);
+ res = strncmp(CurrentNamePtr, Name->Buffer, Name->Length);
+ if (res == 0)
+ {
+ /*
+ * Check if the beginning of the name matched, but it's still
+ * not the whole name.
+ */
+ if (CurrentNamePtr[Name->Length] != 0)
{
- ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
- FunctionList[OrdinalList[Idx]]);
- break;
+ res = -1;
}
- }
- }
- else /* use hint */
- {
- ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
- FunctionList[Hint - ExportDirectory->Base]);
- }
- if (ExportAddress == 0)
- {
- DbgPrint("Export not found for %d:%s\n", Hint,
- Name != NULL ? Name : "(Ordinal)");
- KeBugCheck(0);
- }
-
- return ExportAddress;
-}
-#endif
-
-PIMAGE_NT_HEADERS STDCALL RtlImageNtHeader (IN PVOID BaseAddress)
-{
- PIMAGE_DOS_HEADER DosHeader;
- PIMAGE_NT_HEADERS NTHeaders;
-
- DPRINT("BaseAddress %x\n", BaseAddress);
- DosHeader = (PIMAGE_DOS_HEADER)BaseAddress;
- DPRINT("DosHeader %x\n", DosHeader);
- NTHeaders = (PIMAGE_NT_HEADERS)(BaseAddress + DosHeader->e_lfanew);
- DPRINT("NTHeaders %x\n", NTHeaders);
- DPRINT("DosHeader->e_magic %x DosHeader->e_lfanew %x\n",
- DosHeader->e_magic, DosHeader->e_lfanew);
- DPRINT("*NTHeaders %x\n", *(PULONG)NTHeaders);
- if ((DosHeader->e_magic != IMAGE_DOS_MAGIC)
- || (DosHeader->e_lfanew == 0L)
- || (*(PULONG) NTHeaders != IMAGE_PE_MAGIC))
- {
- return(NULL);
- }
- return(NTHeaders);
+ else
+ {
+ *ProcedureAddress = (PVOID)RVA(BaseAddress, AddressPtr[OrdinalPtr[mid]]);
+ return STATUS_SUCCESS;
+ }
+ }
+ if (res > 0)
+ maxn = mid - 1;
+ else
+ minn = mid + 1;
+ }
+
+ CPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name);
+ }
+ else
+ {
+ /* Search for export by ordinal */
+
+ Ordinal &= 0x0000FFFF;
+ if (Ordinal - ExportDir->Base < ExportDir->NumberOfFunctions)
+ {
+ *ProcedureAddress = (PVOID)RVA(BaseAddress, AddressPtr[Ordinal - ExportDir->Base]);
+ return STATUS_SUCCESS;
+ }
+
+ CPRINT("LdrGetProcedureAddress: Can't resolve symbol @%d\n", Ordinal);
+ }
+
+ return STATUS_PROCEDURE_NOT_FOUND;
}
-
/* EOF */