Alexandre Julliard : ntdll: Implement RtlFindExportedRoutineByName().
Alexandre Julliard
julliard at winehq.org
Wed May 5 16:09:00 CDT 2021
Module: wine
Branch: master
Commit: 87b7132b37b733015a4a7db18571451f50683a32
URL: https://source.winehq.org/git/wine.git/?a=commit;h=87b7132b37b733015a4a7db18571451f50683a32
Author: Alexandre Julliard <julliard at winehq.org>
Date: Wed May 5 10:37:04 2021 +0200
ntdll: Implement RtlFindExportedRoutineByName().
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/ntdll/loader.c | 74 ++++++++++++++++++++++++++++++++--------------
dlls/ntdll/ntdll.spec | 1 +
dlls/ntdll/tests/virtual.c | 12 ++++++++
include/winternl.h | 1 +
4 files changed, 66 insertions(+), 22 deletions(-)
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index ee453700e51..c2dca4efc8e 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -723,6 +723,29 @@ static FARPROC find_ordinal_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY
}
+/*************************************************************************
+ * find_name_in_exports
+ *
+ * Helper for find_named_export.
+ */
+static int find_name_in_exports( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports, const char *name )
+{
+ const WORD *ordinals = get_rva( module, exports->AddressOfNameOrdinals );
+ const DWORD *names = get_rva( module, exports->AddressOfNames );
+ int min = 0, max = exports->NumberOfNames - 1;
+
+ while (min <= max)
+ {
+ int res, pos = (min + max) / 2;
+ char *ename = get_rva( module, names[pos] );
+ if (!(res = strcmp( ename, name ))) return ordinals[pos];
+ if (res > 0) max = pos - 1;
+ else min = pos + 1;
+ }
+ return -1;
+}
+
+
/*************************************************************************
* find_named_export
*
@@ -734,10 +757,10 @@ static FARPROC find_named_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY *
{
const WORD *ordinals = get_rva( module, exports->AddressOfNameOrdinals );
const DWORD *names = get_rva( module, exports->AddressOfNames );
- int min = 0, max = exports->NumberOfNames - 1;
+ int ordinal;
/* first check the hint */
- if (hint >= 0 && hint <= max)
+ if (hint >= 0 && hint < exports->NumberOfNames)
{
char *ename = get_rva( module, names[hint] );
if (!strcmp( ename, name ))
@@ -745,17 +768,30 @@ static FARPROC find_named_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY *
}
/* then do a binary search */
- while (min <= max)
- {
- int res, pos = (min + max) / 2;
- char *ename = get_rva( module, names[pos] );
- if (!(res = strcmp( ename, name )))
- return find_ordinal_export( module, exports, exp_size, ordinals[pos], load_path );
- if (res > 0) max = pos - 1;
- else min = pos + 1;
- }
- return NULL;
+ if ((ordinal = find_name_in_exports( module, exports, name )) == -1) return NULL;
+ return find_ordinal_export( module, exports, exp_size, ordinal, load_path );
+
+}
+
+
+/*************************************************************************
+ * RtlFindExportedRoutineByName
+ */
+void * WINAPI RtlFindExportedRoutineByName( HMODULE module, const char *name )
+{
+ const IMAGE_EXPORT_DIRECTORY *exports;
+ const DWORD *functions;
+ DWORD exp_size;
+ int ordinal;
+ exports = RtlImageDirectoryEntryToData( module, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size );
+ if (!exports || exp_size < sizeof(*exports)) return NULL;
+
+ if ((ordinal = find_name_in_exports( module, exports, name )) == -1) return NULL;
+ if (ordinal >= exports->NumberOfFunctions) return NULL;
+ functions = get_rva( module, exports->AddressOfFunctions );
+ if (!functions[ordinal]) return NULL;
+ return get_rva( module, functions[ordinal] );
}
@@ -1076,10 +1112,9 @@ static void free_tls_slot( LDR_DATA_TABLE_ENTRY *mod )
*/
static NTSTATUS fixup_imports_ilonly( WINE_MODREF *wm, LPCWSTR load_path, void **entry )
{
- IMAGE_EXPORT_DIRECTORY *exports;
- DWORD exp_size;
NTSTATUS status;
- void *proc = NULL;
+ void *proc;
+ const char *name;
WINE_MODREF *prev, *imp;
if (!(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS)) return STATUS_SUCCESS; /* already done */
@@ -1101,13 +1136,8 @@ static NTSTATUS fixup_imports_ilonly( WINE_MODREF *wm, LPCWSTR load_path, void *
TRACE( "loaded mscoree for %s\n", debugstr_w(wm->ldr.FullDllName.Buffer) );
- if ((exports = RtlImageDirectoryEntryToData( imp->ldr.DllBase, TRUE,
- IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size )))
- {
- const char *name = (wm->ldr.Flags & LDR_IMAGE_IS_DLL) ? "_CorDllMain" : "_CorExeMain";
- proc = find_named_export( imp->ldr.DllBase, exports, exp_size, name, -1, load_path );
- }
- if (!proc) return STATUS_PROCEDURE_NOT_FOUND;
+ name = (wm->ldr.Flags & LDR_IMAGE_IS_DLL) ? "_CorDllMain" : "_CorExeMain";
+ if (!(proc = RtlFindExportedRoutineByName( imp->ldr.DllBase, name ))) return STATUS_PROCEDURE_NOT_FOUND;
*entry = proc;
return STATUS_SUCCESS;
}
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index 94ebca02f35..0ccd06d351f 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -653,6 +653,7 @@
@ stdcall RtlFindClearBits(ptr long long)
@ stdcall RtlFindClearBitsAndSet(ptr long long)
@ stdcall RtlFindClearRuns(ptr ptr long long)
+@ stdcall RtlFindExportedRoutineByName(ptr str)
@ stdcall RtlFindLastBackwardRunClear(ptr long ptr)
@ stdcall RtlFindLastBackwardRunSet(ptr long ptr)
@ stdcall RtlFindLeastSignificantBit(int64)
diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c
index 112be80c01e..8f5b0092bea 100644
--- a/dlls/ntdll/tests/virtual.c
+++ b/dlls/ntdll/tests/virtual.c
@@ -33,6 +33,7 @@ static DWORD64 (WINAPI *pGetEnabledXStateFeatures)(void);
static NTSTATUS (WINAPI *pRtlCreateUserStack)(SIZE_T, SIZE_T, ULONG, SIZE_T, SIZE_T, INITIAL_TEB *);
static ULONG64 (WINAPI *pRtlGetEnabledExtendedFeatures)(ULONG64);
static NTSTATUS (WINAPI *pRtlFreeUserStack)(void *);
+static void * (WINAPI *pRtlFindExportedRoutineByName)(HMODULE,const char*);
static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
static NTSTATUS (WINAPI *pNtAllocateVirtualMemoryEx)(HANDLE, PVOID *, SIZE_T *, ULONG, ULONG,
MEM_EXTENDED_PARAMETER *, ULONG);
@@ -996,6 +997,16 @@ static void test_syscalls(void)
}
perform_relocations( ptr, delta );
pNtClose = (void *)GetProcAddress( module, "NtClose" );
+
+ if (pRtlFindExportedRoutineByName)
+ {
+ void *func = pRtlFindExportedRoutineByName( module, "NtClose" );
+ ok( func == (void *)pNtClose, "wrong ptr %p / %p\n", func, pNtClose );
+ func = pRtlFindExportedRoutineByName( ptr, "NtClose" );
+ ok( (char *)func - (char *)pNtClose == delta, "wrong ptr %p / %p\n", func, pNtClose );
+ }
+ else win_skip( "RtlFindExportedRoutineByName not supported\n" );
+
if (!memcmp( pNtClose, (char *)pNtClose + delta, 32 ))
{
pNtClose = (void *)((char *)pNtClose + delta);
@@ -1041,6 +1052,7 @@ START_TEST(virtual)
mod = GetModuleHandleA("ntdll.dll");
pRtlCreateUserStack = (void *)GetProcAddress(mod, "RtlCreateUserStack");
pRtlFreeUserStack = (void *)GetProcAddress(mod, "RtlFreeUserStack");
+ pRtlFindExportedRoutineByName = (void *)GetProcAddress(mod, "RtlFindExportedRoutineByName");
pRtlGetEnabledExtendedFeatures = (void *)GetProcAddress(mod, "RtlGetEnabledExtendedFeatures");
pNtAllocateVirtualMemoryEx = (void *)GetProcAddress(mod, "NtAllocateVirtualMemoryEx");
diff --git a/include/winternl.h b/include/winternl.h
index 69d0e32f1d4..4ccd68daa5f 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -4013,6 +4013,7 @@ NTSYSAPI NTSTATUS WINAPI RtlFindCharInUnicodeString(int,const UNICODE_STRING*,c
NTSYSAPI ULONG WINAPI RtlFindClearBits(PCRTL_BITMAP,ULONG,ULONG);
NTSYSAPI ULONG WINAPI RtlFindClearBitsAndSet(PRTL_BITMAP,ULONG,ULONG);
NTSYSAPI ULONG WINAPI RtlFindClearRuns(PCRTL_BITMAP,PRTL_BITMAP_RUN,ULONG,BOOLEAN);
+NTSYSAPI void * WINAPI RtlFindExportedRoutineByName(HMODULE,const char*);
NTSYSAPI ULONG WINAPI RtlFindLastBackwardRunSet(PCRTL_BITMAP,ULONG,PULONG);
NTSYSAPI ULONG WINAPI RtlFindLastBackwardRunClear(PCRTL_BITMAP,ULONG,PULONG);
NTSYSAPI CCHAR WINAPI RtlFindLeastSignificantBit(ULONGLONG);
More information about the wine-cvs
mailing list