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.

svn path=/trunk/; revision=16955
This commit is contained in:
Filip Navara 2005-08-01 13:50:07 +00:00
parent 7c6d6d777a
commit 7f3c5f0932

View file

@ -24,83 +24,83 @@ LdrGetProcedureAddress (IN PVOID BaseAddress,
OUT PVOID *ProcedureAddress) OUT PVOID *ProcedureAddress)
{ {
PIMAGE_EXPORT_DIRECTORY ExportDir; PIMAGE_EXPORT_DIRECTORY ExportDir;
ULONG ExportDirSize = 0;
PUSHORT OrdinalPtr; PUSHORT OrdinalPtr;
PULONG NamePtr; PULONG NamePtr;
PCHAR CurrentNamePtr;
PULONG AddressPtr; PULONG AddressPtr;
ULONG i = 0;
if (ProcedureAddress == NULL)
return STATUS_INVALID_PARAMETER;
/* get the pointer to the export directory */ /* get the pointer to the export directory */
ExportDir = (PIMAGE_EXPORT_DIRECTORY) ExportDir = RtlImageDirectoryEntryToData(BaseAddress, TRUE,
RtlImageDirectoryEntryToData (BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT,
IMAGE_DIRECTORY_ENTRY_EXPORT, &i); &ExportDirSize);
if (!ExportDir || !i || !ProcedureAddress) if (ExportDir == NULL || ExportDirSize == 0)
{ return STATUS_INVALID_PARAMETER;
return(STATUS_INVALID_PARAMETER);
} AddressPtr = (PULONG)RVA(BaseAddress, ExportDir->AddressOfFunctions);
AddressPtr = (PULONG)RVA((char*)BaseAddress, ExportDir->AddressOfFunctions);
if (Name && Name->Length) if (Name && Name->Length)
{ {
LONG minn, maxn; LONG minn, maxn, mid, res;
/* by name */ /* Search for export by name */
OrdinalPtr =
(PUSHORT)RVA((char*)BaseAddress, ExportDir->AddressOfNameOrdinals);
NamePtr = (PULONG)RVA((char*)BaseAddress, ExportDir->AddressOfNames);
minn = 0; maxn = ExportDir->NumberOfNames; /*
while (minn <= maxn) * NOTE: Exports are always sorted and so we can apply binary search.
{ * Also the function names are _case sensitive_, so respect that.
LONG mid; * -- Filip Navara, August 1st, 2005
LONG res; */
mid = (minn + maxn) / 2; OrdinalPtr = (PUSHORT)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals);
res = _strnicmp(Name->Buffer, (PCH)RVA((char*)BaseAddress, NamePtr[mid]), NamePtr = (PULONG)RVA(BaseAddress, ExportDir->AddressOfNames);
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++) minn = 0; maxn = ExportDir->NumberOfNames - 1;
{ while (minn <= maxn)
if (!_strnicmp(Name->Buffer, {
(char*)((char*)BaseAddress + *NamePtr), Name->Length)) mid = (minn + maxn) / 2;
{ CurrentNamePtr = (PCHAR)RVA(BaseAddress, NamePtr[mid]);
*ProcedureAddress = res = strncmp(CurrentNamePtr, Name->Buffer, Name->Length);
(PVOID)((ULONG)BaseAddress + if (res == 0)
(ULONG)AddressPtr[*OrdinalPtr]); {
return STATUS_SUCCESS; /*
} * Check if the beginning of the name matched, but it's still
} * not the whole name.
CPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", 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 else
{ {
/* by ordinal */ /* Search for export by ordinal */
Ordinal &= 0x0000FFFF;
if (Ordinal - ExportDir->Base < ExportDir->NumberOfFunctions) Ordinal &= 0x0000FFFF;
{ if (Ordinal - ExportDir->Base < ExportDir->NumberOfFunctions)
*ProcedureAddress = {
(PVOID)((ULONG)BaseAddress + *ProcedureAddress = (PVOID)RVA(BaseAddress, AddressPtr[Ordinal - ExportDir->Base]);
(ULONG)AddressPtr[Ordinal - ExportDir->Base]); return STATUS_SUCCESS;
return STATUS_SUCCESS; }
}
CPRINT("LdrGetProcedureAddress: Can't resolve symbol @%d\n", CPRINT("LdrGetProcedureAddress: Can't resolve symbol @%d\n", Ordinal);
Ordinal); }
}
return STATUS_PROCEDURE_NOT_FOUND; return STATUS_PROCEDURE_NOT_FOUND;
} }