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