Module: wine Branch: master Commit: 87b7132b37b733015a4a7db18571451f50683a32 URL: https://source.winehq.org/git/wine.git/?a=commit;h=87b7132b37b733015a4a7db18...
Author: Alexandre Julliard julliard@winehq.org Date: Wed May 5 10:37:04 2021 +0200
ntdll: Implement RtlFindExportedRoutineByName().
Signed-off-by: Alexandre Julliard julliard@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);