[PATCH] ntdll: Don't fail if LDR_MODULE.Flags is modified during load
Myah Caron
qsniyg at mail.com
Thu Mar 26 09:22:04 CDT 2020
Modifications to EntryPoint are respected, which is why it uses the
original wm->ldr instead of ldr.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48817
Signed-off-by: Myah Caron <qsniyg at mail.com>
---
dlls/ntdll/loader.c | 46 +++++++++++++++++++++++++++------------------
1 file changed, 28 insertions(+), 18 deletions(-)
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 1b641f1b9d..c54ef24c97 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -696,7 +696,7 @@ static FARPROC find_ordinal_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY
proc = get_rva( module, functions[ordinal] );
/* if the address falls into the export dir, it's a forward */
- if (((const char *)proc >= (const char *)exports) &&
+ if (((const char *)proc >= (const char *)exports) &&
((const char *)proc < (const char *)exports + exp_size))
return find_forwarded_export( module, (const char *)proc, load_path );
@@ -1301,7 +1301,7 @@ static void call_tls_callbacks( HMODULE module, UINT reason )
/*************************************************************************
* MODULE_InitDLL
*/
-static NTSTATUS MODULE_InitDLL( WINE_MODREF *wm, UINT reason, LPVOID lpReserved )
+static NTSTATUS MODULE_InitDLL( WINE_MODREF *wm, LDR_MODULE ldr, UINT reason, LPVOID lpReserved )
{
WCHAR mod_name[32];
NTSTATUS status = STATUS_SUCCESS;
@@ -1311,19 +1311,19 @@ static NTSTATUS MODULE_InitDLL( WINE_MODREF *wm, UINT reason, LPVOID lpReserved
/* Skip calls for modules loaded with special load flags */
- if (wm->ldr.Flags & LDR_DONT_RESOLVE_REFS) return STATUS_SUCCESS;
- if (wm->ldr.TlsIndex != -1) call_tls_callbacks( wm->ldr.BaseAddress, reason );
- if (!entry || !(wm->ldr.Flags & LDR_IMAGE_IS_DLL)) return STATUS_SUCCESS;
+ if (ldr.Flags & LDR_DONT_RESOLVE_REFS) return STATUS_SUCCESS;
+ if (ldr.TlsIndex != -1) call_tls_callbacks( wm->ldr.BaseAddress, reason );
+ if (!entry || !(ldr.Flags & LDR_IMAGE_IS_DLL)) return STATUS_SUCCESS;
if (TRACE_ON(relay))
{
- size_t len = min( wm->ldr.BaseDllName.Length, sizeof(mod_name)-sizeof(WCHAR) );
- memcpy( mod_name, wm->ldr.BaseDllName.Buffer, len );
+ size_t len = min( ldr.BaseDllName.Length, sizeof(mod_name)-sizeof(WCHAR) );
+ memcpy( mod_name, ldr.BaseDllName.Buffer, len );
mod_name[len / sizeof(WCHAR)] = 0;
TRACE_(relay)("\1Call PE DLL (proc=%p,module=%p %s,reason=%s,res=%p)\n",
entry, module, debugstr_w(mod_name), reason_names[reason], lpReserved );
}
- else TRACE("(%p %s,%s,%p) - CALL\n", module, debugstr_w(wm->ldr.BaseDllName.Buffer),
+ else TRACE("(%p %s,%s,%p) - CALL\n", module, debugstr_w(ldr.BaseDllName.Buffer),
reason_names[reason], lpReserved );
__TRY
@@ -1389,6 +1389,7 @@ static NTSTATUS process_attach( WINE_MODREF *wm, LPVOID lpReserved )
NTSTATUS status = STATUS_SUCCESS;
ULONG_PTR cookie;
int i;
+ LDR_MODULE ldr_backup;
if (process_detaching) return status;
@@ -1404,6 +1405,9 @@ static NTSTATUS process_attach( WINE_MODREF *wm, LPVOID lpReserved )
if (lpReserved) wm->ldr.LoadCount = -1; /* pin it if imported by the main exe */
if (wm->ldr.ActivationContext) RtlActivateActivationContext( 0, wm->ldr.ActivationContext, &cookie );
+ /* The flags can be modified by DLL dependencies */
+ ldr_backup = wm->ldr;
+
/* Recursively attach all DLLs this one depends on */
for ( i = 0; i < wm->nDeps; i++ )
{
@@ -1422,14 +1426,14 @@ static NTSTATUS process_attach( WINE_MODREF *wm, LPVOID lpReserved )
current_modref = wm;
call_ldr_notifications( LDR_DLL_NOTIFICATION_REASON_LOADED, &wm->ldr );
- status = MODULE_InitDLL( wm, DLL_PROCESS_ATTACH, lpReserved );
+ status = MODULE_InitDLL( wm, ldr_backup, DLL_PROCESS_ATTACH, lpReserved );
if (status == STATUS_SUCCESS)
{
wm->ldr.Flags |= LDR_PROCESS_ATTACHED;
}
else
{
- MODULE_InitDLL( wm, DLL_PROCESS_DETACH, lpReserved );
+ MODULE_InitDLL( wm, ldr_backup, DLL_PROCESS_DETACH, lpReserved );
call_ldr_notifications( LDR_DLL_NOTIFICATION_REASON_UNLOADED, &wm->ldr );
/* point to the name so LdrInitializeThunk can print it */
@@ -1486,13 +1490,14 @@ static void process_detach(void)
{
PLIST_ENTRY mark, entry;
PLDR_MODULE mod;
+ WINE_MODREF *wm;
mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
do
{
for (entry = mark->Blink; entry != mark; entry = entry->Blink)
{
- mod = CONTAINING_RECORD(entry, LDR_MODULE,
+ mod = CONTAINING_RECORD(entry, LDR_MODULE,
InInitializationOrderModuleList);
/* Check whether to detach this DLL */
if ( !(mod->Flags & LDR_PROCESS_ATTACHED) )
@@ -1502,7 +1507,8 @@ static void process_detach(void)
/* Call detach notification */
mod->Flags &= ~LDR_PROCESS_ATTACHED;
- MODULE_InitDLL( CONTAINING_RECORD(mod, WINE_MODREF, ldr),
+ wm = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
+ MODULE_InitDLL( wm, wm->ldr,
DLL_PROCESS_DETACH, ULongToPtr(process_detaching) );
call_ldr_notifications( LDR_DLL_NOTIFICATION_REASON_UNLOADED, mod );
@@ -1524,18 +1530,20 @@ static void thread_attach(void)
{
PLIST_ENTRY mark, entry;
PLDR_MODULE mod;
+ WINE_MODREF *wm;
mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
for (entry = mark->Flink; entry != mark; entry = entry->Flink)
{
- mod = CONTAINING_RECORD(entry, LDR_MODULE,
+ mod = CONTAINING_RECORD(entry, LDR_MODULE,
InInitializationOrderModuleList);
if ( !(mod->Flags & LDR_PROCESS_ATTACHED) )
continue;
if ( mod->Flags & LDR_NO_DLL_CALLS )
continue;
- MODULE_InitDLL( CONTAINING_RECORD(mod, WINE_MODREF, ldr), DLL_THREAD_ATTACH, NULL );
+ wm = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
+ MODULE_InitDLL( wm, wm->ldr, DLL_THREAD_ATTACH, NULL );
}
}
@@ -3032,7 +3040,7 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC
case LO_DEFAULT:
nts = load_builtin_dll( load_path, &nt_name, &module, flags, pwm );
if (nts == STATUS_SUCCESS && loadorder == LO_DEFAULT &&
- (MODULE_InitDLL( *pwm, DLL_WINE_PREATTACH, NULL ) != STATUS_SUCCESS))
+ (MODULE_InitDLL( *pwm, (*pwm)->ldr, DLL_WINE_PREATTACH, NULL ) != STATUS_SUCCESS))
{
/* stub-only dll, try native */
TRACE( "%s pre-attach returned FALSE, preferring native\n", debugstr_us(&nt_name) );
@@ -3252,7 +3260,7 @@ IMAGE_BASE_RELOCATION * WINAPI LdrProcessRelocationBlock( void *page, UINT count
* LdrQueryProcessModuleInformation
*
*/
-NTSTATUS WINAPI LdrQueryProcessModuleInformation(PSYSTEM_MODULE_INFORMATION smi,
+NTSTATUS WINAPI LdrQueryProcessModuleInformation(PSYSTEM_MODULE_INFORMATION smi,
ULONG buf_size, ULONG* req_size)
{
SYSTEM_MODULE* sm = &smi->Modules[0];
@@ -3522,6 +3530,7 @@ void WINAPI LdrShutdownThread(void)
{
PLIST_ENTRY mark, entry;
PLDR_MODULE mod;
+ WINE_MODREF *wm;
UINT i;
void **pointers;
@@ -3535,14 +3544,15 @@ void WINAPI LdrShutdownThread(void)
mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
for (entry = mark->Blink; entry != mark; entry = entry->Blink)
{
- mod = CONTAINING_RECORD(entry, LDR_MODULE,
+ mod = CONTAINING_RECORD(entry, LDR_MODULE,
InInitializationOrderModuleList);
if ( !(mod->Flags & LDR_PROCESS_ATTACHED) )
continue;
if ( mod->Flags & LDR_NO_DLL_CALLS )
continue;
- MODULE_InitDLL( CONTAINING_RECORD(mod, WINE_MODREF, ldr),
+ wm = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
+ MODULE_InitDLL( wm, wm->ldr,
DLL_THREAD_DETACH, NULL );
}
--
2.25.1
More information about the wine-devel
mailing list