mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +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,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);
|
||||
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(BaseAddress, ExportDir->AddressOfFunctions);
|
||||
|
||||
AddressPtr = (PULONG)RVA((char*)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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue