Of course, I forgot to commit the new file in revision 22049...
[reactos.git] / reactos / ntoskrnl / ldr / rtl.c
index 90c0ac4..02e9e5a 100644 (file)
-/* $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 */