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;
}