- Silence TCPIP.
[reactos.git] / reactos / ntoskrnl / ldr / rtl.c
index 19346b2..02e9e5a 100644 (file)
-/* $Id: rtl.c,v 1.19 2004/06/27 14:15:33 navaraf 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 <internal/ldr.h>
-
+#include <ntoskrnl.h>
 #define NDEBUG
 #include <internal/debug.h>
 
 /* FUNCTIONS ****************************************************************/
 
-
-/*
- * @implemented
- */
-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)((char*)BaseAddress + DosHeader->e_lfanew);
-   if ((DosHeader->e_magic != IMAGE_DOS_MAGIC)
-       || (DosHeader->e_lfanew == 0L)
-       || (*(PULONG) NTHeaders != IMAGE_PE_MAGIC))
-     {
-       return(NULL);
-     }
-   return(NTHeaders);
-}
-
-
-/*
- * @implemented
- */
-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)((char*)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)((char*)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)((char*)BaseAddress +
-                      Rva +
-                      Section->PointerToRawData -
-                      Section->VirtualAddress);
-}
-
-#define RVA(m, b) ((ULONG)b + m)
-
 NTSTATUS STDCALL
 LdrGetProcedureAddress (IN PVOID BaseAddress,
                         IN PANSI_STRING Name,
@@ -157,83 +24,83 @@ LdrGetProcedureAddress (IN PVOID BaseAddress,
                         OUT PVOID *ProcedureAddress)
 {
    PIMAGE_EXPORT_DIRECTORY ExportDir;
+   ULONG ExportDirSize = 0;
    PUSHORT OrdinalPtr;
    PULONG NamePtr;
+   PCHAR CurrentNamePtr;
    PULONG AddressPtr;
-   ULONG i = 0;
+
+   if (ProcedureAddress == NULL)
+      return STATUS_INVALID_PARAMETER;
 
    /* 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((char*)BaseAddress, ExportDir->AddressOfFunctions);
+   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;
-
-       /* by name */
-       OrdinalPtr = 
-        (PUSHORT)RVA((char*)BaseAddress, ExportDir->AddressOfNameOrdinals);
-       NamePtr = (PULONG)RVA((char*)BaseAddress, ExportDir->AddressOfNames);
-
-       minn = 0; maxn = ExportDir->NumberOfNames;
-       while (minn <= maxn)
-         {
-           LONG mid;
-           LONG res;
-
-           mid = (minn + maxn) / 2;
-           res = _strnicmp(Name->Buffer, (PCH)RVA((char*)BaseAddress, NamePtr[mid]),
-                           Name->Length);
-           if (res == 0)
-             {
-               *ProcedureAddress = 
-                 (PVOID)RVA((char*)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*)((char*)BaseAddress + *NamePtr), Name->Length))
-              {
-                 *ProcedureAddress = 
-                   (PVOID)((ULONG)BaseAddress + 
-                           (ULONG)AddressPtr[*OrdinalPtr]);
-                 return STATUS_SUCCESS;
-              }
-         }
-       CPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name);
-     }
+   {
+      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)
+            {
+               res = -1;
+            }
+            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
-     {
-       /* 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);
-  }
+   {
+      /* 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;
 }