[NTOS:MM/PS] De-duplicate export name-to-ordinal functionality (#4918)

It was implemented in psmgr.c but in a recursive way. That implementation
is replaced, in the NameToOrdinal() helper, by the better non-recursive one
found in the MiLocateExportName() and MiFindExportedRoutineByName() functions.

This NameToOrdinal() helper is then called in lieu of the duplicated code
in MiLocateExportName() and MiFindExportedRoutineByName(). In addition,
one block of code in MiSnapThunk() is simplified in a similar manner.
This commit is contained in:
Hermès Bélusca-Maïto 2023-08-22 19:06:34 +02:00
parent e8b048a282
commit 4e55236662
No known key found for this signature in database
GPG Key ID: 3B2539C65E7B93D0
2 changed files with 80 additions and 130 deletions

View File

@ -213,6 +213,60 @@ MiLoadImageSection(_Inout_ PSECTION *SectionPtr,
return Status;
}
#ifndef RVA
#define RVA(m, b) ((PVOID)((ULONG_PTR)(b) + (ULONG_PTR)(m)))
#endif
USHORT
NTAPI
NameToOrdinal(
_In_ PCSTR ExportName,
_In_ PVOID ImageBase,
_In_ ULONG NumberOfNames,
_In_ PULONG NameTable,
_In_ PUSHORT OrdinalTable)
{
LONG Low, Mid, High, Ret;
/* Fail if no names */
if (!NumberOfNames)
return -1;
/* Do a binary search */
Low = Mid = 0;
High = NumberOfNames - 1;
while (High >= Low)
{
/* Get new middle value */
Mid = (Low + High) >> 1;
/* Compare name */
Ret = strcmp(ExportName, (PCHAR)RVA(ImageBase, NameTable[Mid]));
if (Ret < 0)
{
/* Update high */
High = Mid - 1;
}
else if (Ret > 0)
{
/* Update low */
Low = Mid + 1;
}
else
{
/* We got it */
break;
}
}
/* Check if we couldn't find it */
if (High < Low)
return -1;
/* Otherwise, this is the ordinal */
return OrdinalTable[Mid];
}
PVOID
NTAPI
MiLocateExportName(IN PVOID DllBase,
@ -221,7 +275,6 @@ MiLocateExportName(IN PVOID DllBase,
PULONG NameTable;
PUSHORT OrdinalTable;
PIMAGE_EXPORT_DIRECTORY ExportDirectory;
LONG Low = 0, Mid = 0, High, Ret;
USHORT Ordinal;
PVOID Function;
ULONG ExportSize;
@ -241,37 +294,15 @@ MiLocateExportName(IN PVOID DllBase,
OrdinalTable = (PUSHORT)((ULONG_PTR)DllBase +
ExportDirectory->AddressOfNameOrdinals);
/* Do a binary search */
High = ExportDirectory->NumberOfNames - 1;
while (High >= Low)
{
/* Get new middle value */
Mid = (Low + High) >> 1;
/* Compare name */
Ret = strcmp(ExportName, (PCHAR)DllBase + NameTable[Mid]);
if (Ret < 0)
{
/* Update high */
High = Mid - 1;
}
else if (Ret > 0)
{
/* Update low */
Low = Mid + 1;
}
else
{
/* We got it */
break;
}
}
/* Get the ordinal */
Ordinal = NameToOrdinal(ExportName,
DllBase,
ExportDirectory->NumberOfNames,
NameTable,
OrdinalTable);
/* Check if we couldn't find it */
if (High < Low) return NULL;
/* Otherwise, this is the ordinal */
Ordinal = OrdinalTable[Mid];
if (Ordinal == -1) return NULL;
/* Resolve the address and write it */
ExportTable = (PULONG)((ULONG_PTR)DllBase +
@ -486,7 +517,6 @@ MiFindExportedRoutineByName(IN PVOID DllBase,
PULONG NameTable;
PUSHORT OrdinalTable;
PIMAGE_EXPORT_DIRECTORY ExportDirectory;
LONG Low = 0, Mid = 0, High, Ret;
USHORT Ordinal;
PVOID Function;
ULONG ExportSize;
@ -506,37 +536,15 @@ MiFindExportedRoutineByName(IN PVOID DllBase,
OrdinalTable = (PUSHORT)((ULONG_PTR)DllBase +
ExportDirectory->AddressOfNameOrdinals);
/* Do a binary search */
High = ExportDirectory->NumberOfNames - 1;
while (High >= Low)
{
/* Get new middle value */
Mid = (Low + High) >> 1;
/* Compare name */
Ret = strcmp(ExportName->Buffer, (PCHAR)DllBase + NameTable[Mid]);
if (Ret < 0)
{
/* Update high */
High = Mid - 1;
}
else if (Ret > 0)
{
/* Update low */
Low = Mid + 1;
}
else
{
/* We got it */
break;
}
}
/* Get the ordinal */
Ordinal = NameToOrdinal(ExportName->Buffer,
DllBase,
ExportDirectory->NumberOfNames,
NameTable,
OrdinalTable);
/* Check if we couldn't find it */
if (High < Low) return NULL;
/* Otherwise, this is the ordinal */
Ordinal = OrdinalTable[Mid];
if (Ordinal == -1) return NULL;
/* Validate the ordinal */
if (Ordinal >= ExportDirectory->NumberOfFunctions) return NULL;
@ -696,8 +704,6 @@ MiSnapThunk(IN PVOID DllBase,
PUSHORT OrdinalTable;
PIMAGE_IMPORT_BY_NAME NameImport;
USHORT Hint;
ULONG Low = 0, Mid = 0, High;
LONG Ret;
NTSTATUS Status;
PCHAR MissingForwarder;
CHAR NameBuffer[MAXIMUM_FILENAME_LENGTH];
@ -751,40 +757,18 @@ MiSnapThunk(IN PVOID DllBase,
else
{
/* Do a binary search */
High = ExportDirectory->NumberOfNames - 1;
while (High >= Low)
{
/* Get new middle value */
Mid = (Low + High) >> 1;
/* Compare name */
Ret = strcmp((PCHAR)NameImport->Name, (PCHAR)DllBase + NameTable[Mid]);
if (Ret < 0)
{
/* Update high */
High = Mid - 1;
}
else if (Ret > 0)
{
/* Update low */
Low = Mid + 1;
}
else
{
/* We got it */
break;
}
}
Ordinal = NameToOrdinal((PCHAR)NameImport->Name,
DllBase,
ExportDirectory->NumberOfNames,
NameTable,
OrdinalTable);
/* Check if we couldn't find it */
if (High < Low)
if (Ordinal == -1)
{
DPRINT1("Warning: Driver failed to load, %s not found\n", NameImport->Name);
return STATUS_DRIVER_ENTRYPOINT_NOT_FOUND;
}
/* Otherwise, this is the ordinal */
Ordinal = OrdinalTable[Mid];
}
}

View File

@ -62,48 +62,14 @@ BOOLEAN PspDoingGiveBacks;
/* PRIVATE FUNCTIONS *********************************************************/
CODE_SEG("INIT")
USHORT
NTAPI
NameToOrdinal(IN PCHAR Name,
IN PVOID DllBase,
IN ULONG NumberOfNames,
IN PULONG NameTable,
IN PUSHORT OrdinalTable)
{
ULONG Mid;
LONG Ret;
/* Fail if no names */
if (!NumberOfNames) return -1;
/* Do binary search */
Mid = NumberOfNames >> 1;
Ret = strcmp(Name, (PCHAR)((ULONG_PTR)DllBase + NameTable[Mid]));
/* Check if we found it */
if (!Ret) return OrdinalTable[Mid];
/* We didn't. Check if we only had one name to check */
if (NumberOfNames == 1) return -1;
/* Check if we should look up or down */
if (Ret < 0)
{
/* Loop down */
NumberOfNames = Mid;
}
else
{
/* Look up, update tables */
NameTable = &NameTable[Mid + 1];
OrdinalTable = &OrdinalTable[Mid + 1];
NumberOfNames -= (Mid - 1);
}
/* Call us recursively */
return NameToOrdinal(Name, DllBase, NumberOfNames, NameTable, OrdinalTable);
}
NameToOrdinal(
_In_ PCSTR ExportName,
_In_ PVOID ImageBase,
_In_ ULONG NumberOfNames,
_In_ PULONG NameTable,
_In_ PUSHORT OrdinalTable);
CODE_SEG("INIT")
NTSTATUS