mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
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:
parent
7c6d6d777a
commit
7f3c5f0932
1 changed files with 64 additions and 64 deletions
|
@ -24,82 +24,82 @@ 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;
|
/*
|
||||||
|
* 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)
|
while (minn <= maxn)
|
||||||
{
|
{
|
||||||
LONG mid;
|
|
||||||
LONG res;
|
|
||||||
|
|
||||||
mid = (minn + maxn) / 2;
|
mid = (minn + maxn) / 2;
|
||||||
res = _strnicmp(Name->Buffer, (PCH)RVA((char*)BaseAddress, NamePtr[mid]),
|
CurrentNamePtr = (PCHAR)RVA(BaseAddress, NamePtr[mid]);
|
||||||
Name->Length);
|
res = strncmp(CurrentNamePtr, Name->Buffer, Name->Length);
|
||||||
if (res == 0)
|
if (res == 0)
|
||||||
{
|
{
|
||||||
*ProcedureAddress =
|
/*
|
||||||
(PVOID)RVA((char*)BaseAddress, AddressPtr[OrdinalPtr[mid]]);
|
* Check if the beginning of the name matched, but it's still
|
||||||
return(STATUS_SUCCESS);
|
* not the whole name.
|
||||||
}
|
*/
|
||||||
else if (res > 0)
|
if (CurrentNamePtr[Name->Length] != 0)
|
||||||
{
|
{
|
||||||
maxn = mid - 1;
|
res = -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
minn = mid + 1;
|
*ProcedureAddress = (PVOID)RVA(BaseAddress, AddressPtr[OrdinalPtr[mid]]);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (res > 0)
|
||||||
|
maxn = mid - 1;
|
||||||
|
else
|
||||||
|
minn = mid + 1;
|
||||||
|
}
|
||||||
|
|
||||||
CPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name);
|
CPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* by ordinal */
|
/* Search for export by ordinal */
|
||||||
|
|
||||||
Ordinal &= 0x0000FFFF;
|
Ordinal &= 0x0000FFFF;
|
||||||
if (Ordinal - ExportDir->Base < ExportDir->NumberOfFunctions)
|
if (Ordinal - ExportDir->Base < ExportDir->NumberOfFunctions)
|
||||||
{
|
{
|
||||||
*ProcedureAddress =
|
*ProcedureAddress = (PVOID)RVA(BaseAddress, AddressPtr[Ordinal - ExportDir->Base]);
|
||||||
(PVOID)((ULONG)BaseAddress +
|
|
||||||
(ULONG)AddressPtr[Ordinal - ExportDir->Base]);
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
CPRINT("LdrGetProcedureAddress: Can't resolve symbol @%d\n",
|
|
||||||
Ordinal);
|
CPRINT("LdrGetProcedureAddress: Can't resolve symbol @%d\n", Ordinal);
|
||||||
}
|
}
|
||||||
|
|
||||||
return STATUS_PROCEDURE_NOT_FOUND;
|
return STATUS_PROCEDURE_NOT_FOUND;
|
||||||
|
|
Loading…
Reference in a new issue