Various LdrGetProcedureAddress fixes:
- Fix the binary search limits.
- Fix the comparsion of names (previously "XXX" and "XXXyyy" would be considered identical) and make it case sensitive.
- Remove non-binary search, it's not needed.
- Don't use ULONG to store pointers.
Modified: trunk/reactos/ntoskrnl/ldr/rtl.c

Modified: trunk/reactos/ntoskrnl/ldr/rtl.c
--- trunk/reactos/ntoskrnl/ldr/rtl.c	2005-08-01 13:34:33 UTC (rev 16954)
+++ trunk/reactos/ntoskrnl/ldr/rtl.c	2005-08-01 13:50:07 UTC (rev 16955)
@@ -24,84 +24,84 @@
                         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);
+   ExportDir = RtlImageDirectoryEntryToData(BaseAddress, TRUE,
+				            IMAGE_DIRECTORY_ENTRY_EXPORT,
+				            &ExportDirSize);
 
-   if (!ExportDir || !i || !ProcedureAddress)
-     {
-	return(STATUS_INVALID_PARAMETER);
-     }
+   if (ExportDir == NULL || ExportDirSize == 0)
+      return STATUS_INVALID_PARAMETER;
 
-   AddressPtr = (PULONG)RVA((char*)BaseAddress, ExportDir->AddressOfFunctions);
+   AddressPtr = (PULONG)RVA(BaseAddress, ExportDir->AddressOfFunctions);
+
    if (Name && Name->Length)
-     {
-       LONG minn, maxn;
+   {
+      LONG minn, maxn, mid, res;
 
-	/* by name */
-       OrdinalPtr =
-	 (PUSHORT)RVA((char*)BaseAddress, ExportDir->AddressOfNameOrdinals);
-       NamePtr = (PULONG)RVA((char*)BaseAddress, ExportDir->AddressOfNames);
+      /* Search for export by name */
 
-	minn = 0; maxn = ExportDir->NumberOfNames;
-	while (minn <= maxn)
-	  {
-	    LONG mid;
-	    LONG res;
+      /*
+       * 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
+       */
 
-	    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;
-	      }
-	  }
+      OrdinalPtr = (PUSHORT)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals);
+      NamePtr = (PULONG)RVA(BaseAddress, ExportDir->AddressOfNames);
 
-	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);
-     }
+      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;
 }