mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
[NTOS:MM/PS] Remove code duplication between LookupEntryPoint/MiLocateExportName/MiFindExportedRoutineByName. (#4918)
As it turns out, those three functions were duplicating the same code between each other. Reimplement these in terms of a common helper, RtlFindExportedRoutineByName(). Indeed: MiFindExportedRoutineByName() was just MiLocateExportName() but taking a PANSI_STRING instead of a NULL-terminated string. A similar state of affairs also existed in Windows <= 2003, and the MS guys also noticed it. Both routines have been then merged and renamed to MiFindExportedRoutineByName() on Windows 8 (taking a PCSTR instead), and finally renamed and exported as RtlFindExportedRoutineByName() on Windows 10.
This commit is contained in:
parent
d8695eee1e
commit
86e0d5e9b8
4 changed files with 168 additions and 163 deletions
|
@ -1490,16 +1490,15 @@ VOID
|
|||
NTAPI
|
||||
MmFreeSectionSegments(PFILE_OBJECT FileObject);
|
||||
|
||||
/* Exported from NT 6.2 Onward. We keep it internal. */
|
||||
/* Exported from NT 6.2 onward. We keep it internal. */
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MmMapViewInSystemSpaceEx (
|
||||
MmMapViewInSystemSpaceEx(
|
||||
_In_ PVOID Section,
|
||||
_Outptr_result_bytebuffer_ (*ViewSize) PVOID *MappedBase,
|
||||
_Inout_ PSIZE_T ViewSize,
|
||||
_Inout_ PLARGE_INTEGER SectionOffset,
|
||||
_In_ ULONG_PTR Flags
|
||||
);
|
||||
_In_ ULONG_PTR Flags);
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
|
@ -1661,6 +1660,23 @@ NTAPI
|
|||
MmFreeDriverInitialization(
|
||||
IN PLDR_DATA_TABLE_ENTRY LdrEntry);
|
||||
|
||||
/* ReactOS-only, used by psmgr.c PspLookupSystemDllEntryPoint() as well */
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
RtlpFindExportedRoutineByName(
|
||||
_In_ PVOID ImageBase,
|
||||
_In_ PCSTR ExportName,
|
||||
_Out_ PVOID* Function,
|
||||
_Out_opt_ PBOOLEAN IsForwarder,
|
||||
_In_ NTSTATUS NotFoundStatus);
|
||||
|
||||
/* Exported from NT 10.0 onward. We keep it internal. */
|
||||
PVOID
|
||||
NTAPI
|
||||
RtlFindExportedRoutineByName(
|
||||
_In_ PVOID ImageBase,
|
||||
_In_ PCSTR ExportName);
|
||||
|
||||
/* procsup.c *****************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
|
|
|
@ -134,12 +134,6 @@ PsLocateSystemDll(
|
|||
VOID
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PspGetSystemDllEntryPoints(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
PsChangeQuantumTable(
|
||||
|
|
|
@ -267,60 +267,163 @@ NameToOrdinal(
|
|||
return OrdinalTable[Mid];
|
||||
}
|
||||
|
||||
PVOID
|
||||
/**
|
||||
* @brief
|
||||
* ReactOS-only helper routine for RtlFindExportedRoutineByName(),
|
||||
* that provides a finer granularity regarding the nature of the
|
||||
* export, and the failure reasons.
|
||||
*
|
||||
* @param[in] ImageBase
|
||||
* The base address of the loaded image.
|
||||
*
|
||||
* @param[in] ExportName
|
||||
* The name of the export, given as an ANSI NULL-terminated string.
|
||||
*
|
||||
* @param[out] Function
|
||||
* The address of the named exported routine, or NULL if not found.
|
||||
* If the export is a forwarder (see @p IsForwarder below), this
|
||||
* address points to the forwarder name.
|
||||
*
|
||||
* @param[out] IsForwarder
|
||||
* An optional pointer to a BOOLEAN variable, that is set to TRUE
|
||||
* if the found export is a forwarder, and FALSE otherwise.
|
||||
*
|
||||
* @param[in] NotFoundStatus
|
||||
* The status code to return in case the export could not be found
|
||||
* (examples: STATUS_ENTRYPOINT_NOT_FOUND, STATUS_PROCEDURE_NOT_FOUND).
|
||||
*
|
||||
* @return
|
||||
* A status code as follows:
|
||||
* - STATUS_SUCCESS if the named exported routine is found;
|
||||
* - The custom @p NotFoundStatus if the export could not be found;
|
||||
* - STATUS_INVALID_PARAMETER if the image is invalid or does not
|
||||
* contain an Export Directory.
|
||||
*
|
||||
* @note
|
||||
* See RtlFindExportedRoutineByName() for more remarks.
|
||||
* Used by psmgr.c PspLookupSystemDllEntryPoint() as well.
|
||||
**/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiLocateExportName(IN PVOID DllBase,
|
||||
IN PCHAR ExportName)
|
||||
RtlpFindExportedRoutineByName(
|
||||
_In_ PVOID ImageBase,
|
||||
_In_ PCSTR ExportName,
|
||||
_Out_ PVOID* Function,
|
||||
_Out_opt_ PBOOLEAN IsForwarder,
|
||||
_In_ NTSTATUS NotFoundStatus)
|
||||
{
|
||||
PIMAGE_EXPORT_DIRECTORY ExportDirectory;
|
||||
PULONG NameTable;
|
||||
PUSHORT OrdinalTable;
|
||||
PIMAGE_EXPORT_DIRECTORY ExportDirectory;
|
||||
USHORT Ordinal;
|
||||
PVOID Function;
|
||||
ULONG ExportSize;
|
||||
USHORT Ordinal;
|
||||
PULONG ExportTable;
|
||||
ULONG_PTR FunctionAddress;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
/* Get the export directory */
|
||||
ExportDirectory = RtlImageDirectoryEntryToData(DllBase,
|
||||
ExportDirectory = RtlImageDirectoryEntryToData(ImageBase,
|
||||
TRUE,
|
||||
IMAGE_DIRECTORY_ENTRY_EXPORT,
|
||||
&ExportSize);
|
||||
if (!ExportDirectory) return NULL;
|
||||
if (!ExportDirectory)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* Setup name tables */
|
||||
NameTable = (PULONG)((ULONG_PTR)DllBase +
|
||||
ExportDirectory->AddressOfNames);
|
||||
OrdinalTable = (PUSHORT)((ULONG_PTR)DllBase +
|
||||
ExportDirectory->AddressOfNameOrdinals);
|
||||
NameTable = (PULONG)RVA(ImageBase, ExportDirectory->AddressOfNames);
|
||||
OrdinalTable = (PUSHORT)RVA(ImageBase, ExportDirectory->AddressOfNameOrdinals);
|
||||
|
||||
/* Get the ordinal */
|
||||
Ordinal = NameToOrdinal(ExportName,
|
||||
DllBase,
|
||||
ImageBase,
|
||||
ExportDirectory->NumberOfNames,
|
||||
NameTable,
|
||||
OrdinalTable);
|
||||
|
||||
/* Check if we couldn't find it */
|
||||
if (Ordinal == -1) return NULL;
|
||||
if (Ordinal == -1)
|
||||
return NotFoundStatus;
|
||||
|
||||
/* Validate the ordinal */
|
||||
if (Ordinal >= ExportDirectory->NumberOfFunctions) return NULL;
|
||||
if (Ordinal >= ExportDirectory->NumberOfFunctions)
|
||||
return NotFoundStatus;
|
||||
|
||||
/* Resolve the address and write it */
|
||||
ExportTable = (PULONG)((ULONG_PTR)DllBase +
|
||||
ExportDirectory->AddressOfFunctions);
|
||||
Function = (PVOID)((ULONG_PTR)DllBase + ExportTable[Ordinal]);
|
||||
/* Resolve the function's address */
|
||||
ExportTable = (PULONG)RVA(ImageBase, ExportDirectory->AddressOfFunctions);
|
||||
FunctionAddress = (ULONG_PTR)RVA(ImageBase, ExportTable[Ordinal]);
|
||||
|
||||
/* Check if the function is actually a forwarder */
|
||||
if (((ULONG_PTR)Function > (ULONG_PTR)ExportDirectory) &&
|
||||
((ULONG_PTR)Function < ((ULONG_PTR)ExportDirectory + ExportSize)))
|
||||
if (IsForwarder)
|
||||
{
|
||||
/* It is, fail */
|
||||
*IsForwarder = FALSE;
|
||||
if ((FunctionAddress > (ULONG_PTR)ExportDirectory) &&
|
||||
(FunctionAddress < (ULONG_PTR)ExportDirectory + ExportSize))
|
||||
{
|
||||
/* It is, and points to the forwarder name */
|
||||
*IsForwarder = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* We've found it */
|
||||
*Function = (PVOID)FunctionAddress;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Finds the address of a given named exported routine in a loaded image.
|
||||
* Note that this function does not support forwarders.
|
||||
*
|
||||
* @param[in] ImageBase
|
||||
* The base address of the loaded image.
|
||||
*
|
||||
* @param[in] ExportName
|
||||
* The name of the export, given as an ANSI NULL-terminated string.
|
||||
*
|
||||
* @return
|
||||
* The address of the named exported routine, or NULL if not found.
|
||||
* If the export is a forwarder, this function returns NULL as well.
|
||||
*
|
||||
* @note
|
||||
* This routine was originally named MiLocateExportName(), with a separate
|
||||
* duplicated MiFindExportedRoutineByName() one (taking a PANSI_STRING)
|
||||
* on Windows <= 2003. Both routines have been then merged and renamed
|
||||
* to MiFindExportedRoutineByName() on Windows 8 (taking a PCSTR instead),
|
||||
* and finally renamed and exported as RtlFindExportedRoutineByName() on
|
||||
* Windows 10.
|
||||
*
|
||||
* @see https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/sysload/mmgetsystemroutineaddress.htm
|
||||
**/
|
||||
PVOID
|
||||
NTAPI
|
||||
RtlFindExportedRoutineByName(
|
||||
_In_ PVOID ImageBase,
|
||||
_In_ PCSTR ExportName)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
BOOLEAN IsForwarder = FALSE;
|
||||
PVOID Function;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
/* Call the internal API */
|
||||
Status = RtlpFindExportedRoutineByName(ImageBase,
|
||||
ExportName,
|
||||
&Function,
|
||||
&IsForwarder,
|
||||
STATUS_ENTRYPOINT_NOT_FOUND);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return NULL;
|
||||
|
||||
/* If the export is actually a forwarder, log the error and fail */
|
||||
if (IsForwarder)
|
||||
{
|
||||
DPRINT1("RtlFindExportedRoutineByName does not support forwarders!\n", FALSE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We found it */
|
||||
/* We've found the export */
|
||||
return Function;
|
||||
}
|
||||
|
||||
|
@ -340,8 +443,8 @@ MmCallDllInitialize(
|
|||
PAGED_CODE();
|
||||
|
||||
/* Try to see if the image exports a DllInitialize routine */
|
||||
DllInit = (PMM_DLL_INITIALIZE)MiLocateExportName(LdrEntry->DllBase,
|
||||
"DllInitialize");
|
||||
DllInit = (PMM_DLL_INITIALIZE)
|
||||
RtlFindExportedRoutineByName(LdrEntry->DllBase, "DllInitialize");
|
||||
if (!DllInit)
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
|
@ -399,7 +502,8 @@ MiCallDllUnloadAndUnloadDll(
|
|||
PAGED_CODE();
|
||||
|
||||
/* Retrieve the DllUnload routine */
|
||||
DllUnload = (PMM_DLL_UNLOAD)MiLocateExportName(LdrEntry->DllBase, "DllUnload");
|
||||
DllUnload = (PMM_DLL_UNLOAD)
|
||||
RtlFindExportedRoutineByName(LdrEntry->DllBase, "DllUnload");
|
||||
if (!DllUnload)
|
||||
return FALSE;
|
||||
|
||||
|
@ -512,58 +616,6 @@ MiClearImports(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
|
|||
LdrEntry->LoadedImports = MM_SYSLDR_BOOT_LOADED;
|
||||
}
|
||||
|
||||
PVOID
|
||||
NTAPI
|
||||
MiFindExportedRoutineByName(IN PVOID DllBase,
|
||||
IN PANSI_STRING ExportName)
|
||||
{
|
||||
PULONG NameTable;
|
||||
PUSHORT OrdinalTable;
|
||||
PIMAGE_EXPORT_DIRECTORY ExportDirectory;
|
||||
USHORT Ordinal;
|
||||
PVOID Function;
|
||||
ULONG ExportSize;
|
||||
PULONG ExportTable;
|
||||
PAGED_CODE();
|
||||
|
||||
/* Get the export directory */
|
||||
ExportDirectory = RtlImageDirectoryEntryToData(DllBase,
|
||||
TRUE,
|
||||
IMAGE_DIRECTORY_ENTRY_EXPORT,
|
||||
&ExportSize);
|
||||
if (!ExportDirectory) return NULL;
|
||||
|
||||
/* Setup name tables */
|
||||
NameTable = (PULONG)((ULONG_PTR)DllBase +
|
||||
ExportDirectory->AddressOfNames);
|
||||
OrdinalTable = (PUSHORT)((ULONG_PTR)DllBase +
|
||||
ExportDirectory->AddressOfNameOrdinals);
|
||||
|
||||
/* Get the ordinal */
|
||||
Ordinal = NameToOrdinal(ExportName->Buffer,
|
||||
DllBase,
|
||||
ExportDirectory->NumberOfNames,
|
||||
NameTable,
|
||||
OrdinalTable);
|
||||
|
||||
/* Check if we couldn't find it */
|
||||
if (Ordinal == -1) return NULL;
|
||||
|
||||
/* Validate the ordinal */
|
||||
if (Ordinal >= ExportDirectory->NumberOfFunctions) return NULL;
|
||||
|
||||
/* Resolve the address and write it */
|
||||
ExportTable = (PULONG)((ULONG_PTR)DllBase +
|
||||
ExportDirectory->AddressOfFunctions);
|
||||
Function = (PVOID)((ULONG_PTR)DllBase + ExportTable[Ordinal]);
|
||||
|
||||
/* We found it! */
|
||||
ASSERT((Function < (PVOID)ExportDirectory) ||
|
||||
(Function > (PVOID)((ULONG_PTR)ExportDirectory + ExportSize)));
|
||||
|
||||
return Function;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
MiProcessLoaderEntry(IN PLDR_DATA_TABLE_ENTRY LdrEntry,
|
||||
|
@ -720,6 +772,7 @@ MiSnapThunk(IN PVOID DllBase,
|
|||
PIMAGE_IMPORT_BY_NAME ForwardName;
|
||||
SIZE_T ForwardLength;
|
||||
IMAGE_THUNK_DATA ForwardThunk;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
/* Check if this is an ordinal */
|
||||
|
@ -740,7 +793,7 @@ MiSnapThunk(IN PVOID DllBase,
|
|||
/* Copy the procedure name */
|
||||
RtlStringCbCopyA(*MissingApi,
|
||||
MAXIMUM_FILENAME_LENGTH,
|
||||
(PCHAR)&NameImport->Name[0]);
|
||||
(PCHAR)NameImport->Name);
|
||||
|
||||
/* Setup name tables */
|
||||
DPRINT("Import name: %s\n", NameImport->Name);
|
||||
|
@ -775,10 +828,10 @@ MiSnapThunk(IN PVOID DllBase,
|
|||
}
|
||||
}
|
||||
|
||||
/* Check if the ordinal is invalid */
|
||||
/* Check if the ordinal is valid */
|
||||
if (Ordinal >= ExportDirectory->NumberOfFunctions)
|
||||
{
|
||||
/* Fail */
|
||||
/* It's not, fail */
|
||||
Status = STATUS_DRIVER_ORDINAL_NOT_FOUND;
|
||||
}
|
||||
else
|
||||
|
@ -796,7 +849,7 @@ MiSnapThunk(IN PVOID DllBase,
|
|||
|
||||
/* Check if the function is actually a forwarder */
|
||||
if ((Address->u1.Function > (ULONG_PTR)ExportDirectory) &&
|
||||
(Address->u1.Function < ((ULONG_PTR)ExportDirectory + ExportSize)))
|
||||
(Address->u1.Function < (ULONG_PTR)ExportDirectory + ExportSize))
|
||||
{
|
||||
/* Now assume failure in case the forwarder doesn't exist */
|
||||
Status = STATUS_DRIVER_ENTRYPOINT_NOT_FOUND;
|
||||
|
@ -3594,8 +3647,8 @@ MmGetSystemRoutineAddress(IN PUNICODE_STRING SystemRoutineName)
|
|||
if (Found)
|
||||
{
|
||||
/* Find the procedure name */
|
||||
ProcAddress = MiFindExportedRoutineByName(LdrEntry->DllBase,
|
||||
&AnsiRoutineName);
|
||||
ProcAddress = RtlFindExportedRoutineByName(LdrEntry->DllBase,
|
||||
AnsiRoutineName.Buffer);
|
||||
|
||||
/* Break out if we found it or if we already tried both modules */
|
||||
if (ProcAddress) break;
|
||||
|
|
|
@ -62,80 +62,22 @@ BOOLEAN PspDoingGiveBacks;
|
|||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
USHORT
|
||||
NTAPI
|
||||
NameToOrdinal(
|
||||
_In_ PCSTR ExportName,
|
||||
_In_ PVOID ImageBase,
|
||||
_In_ ULONG NumberOfNames,
|
||||
_In_ PULONG NameTable,
|
||||
_In_ PUSHORT OrdinalTable);
|
||||
|
||||
CODE_SEG("INIT")
|
||||
static CODE_SEG("INIT")
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
LookupEntryPoint(IN PVOID DllBase,
|
||||
IN PCHAR Name,
|
||||
OUT PVOID *EntryPoint)
|
||||
PspLookupSystemDllEntryPoint(
|
||||
_In_ PCSTR Name,
|
||||
_Out_ PVOID* EntryPoint)
|
||||
{
|
||||
PULONG NameTable;
|
||||
PUSHORT OrdinalTable;
|
||||
PIMAGE_EXPORT_DIRECTORY ExportDirectory;
|
||||
ULONG ExportSize;
|
||||
CHAR Buffer[64];
|
||||
USHORT Ordinal;
|
||||
PULONG ExportTable;
|
||||
|
||||
/* Get the export directory */
|
||||
ExportDirectory = RtlImageDirectoryEntryToData(DllBase,
|
||||
TRUE,
|
||||
IMAGE_DIRECTORY_ENTRY_EXPORT,
|
||||
&ExportSize);
|
||||
|
||||
/* Validate the name and copy it */
|
||||
if (strlen(Name) > sizeof(Buffer) - 2) return STATUS_INVALID_PARAMETER;
|
||||
strcpy(Buffer, Name);
|
||||
|
||||
/* Setup name tables */
|
||||
NameTable = (PULONG)((ULONG_PTR)DllBase +
|
||||
ExportDirectory->AddressOfNames);
|
||||
OrdinalTable = (PUSHORT)((ULONG_PTR)DllBase +
|
||||
ExportDirectory->AddressOfNameOrdinals);
|
||||
|
||||
/* Get the ordinal */
|
||||
Ordinal = NameToOrdinal(Buffer,
|
||||
DllBase,
|
||||
ExportDirectory->NumberOfNames,
|
||||
NameTable,
|
||||
OrdinalTable);
|
||||
|
||||
/* Make sure the ordinal is valid */
|
||||
if (Ordinal >= ExportDirectory->NumberOfFunctions)
|
||||
{
|
||||
/* It's not, fail */
|
||||
return STATUS_PROCEDURE_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* Resolve the address and write it */
|
||||
ExportTable = (PULONG)((ULONG_PTR)DllBase +
|
||||
ExportDirectory->AddressOfFunctions);
|
||||
*EntryPoint = (PVOID)((ULONG_PTR)DllBase + ExportTable[Ordinal]);
|
||||
return STATUS_SUCCESS;
|
||||
/* Call the internal API */
|
||||
return RtlpFindExportedRoutineByName(PspSystemDllBase,
|
||||
Name,
|
||||
EntryPoint,
|
||||
NULL,
|
||||
STATUS_PROCEDURE_NOT_FOUND);
|
||||
}
|
||||
|
||||
CODE_SEG("INIT")
|
||||
static CODE_SEG("INIT")
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PspLookupSystemDllEntryPoint(IN PCHAR Name,
|
||||
IN PVOID *EntryPoint)
|
||||
{
|
||||
/* Call the LDR Routine */
|
||||
return LookupEntryPoint(PspSystemDllBase, Name, EntryPoint);
|
||||
}
|
||||
|
||||
CODE_SEG("INIT")
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PspLookupKernelUserEntryPoints(VOID)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
|
Loading…
Reference in a new issue