Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/ntdll/loader.c | 59 +++++++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 21 deletions(-)
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 9397c927c3e..a8222ec30df 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -206,7 +206,9 @@ static RTL_SRWLOCK ldr_data_srw_lock; static RTL_BITMAP tls_bitmap; static RTL_BITMAP tls_expansion_bitmap;
-static WINE_MODREF *cached_modref; +static WINE_MODREF * volatile cached_modref; + +/* Used with exclusive loader lock only. */ static WINE_MODREF *current_modref; static WINE_MODREF *last_failed_modref;
@@ -470,6 +472,26 @@ static void lock_loader_restore_exclusive(void) locked_exclusive = TRUE; }
+/************************************************************************* + * get_cached_modref + * + */ +static WINE_MODREF *get_cached_modref(void) +{ + return cached_modref; +} + +/************************************************************************* + * put_cached_modref + * + * Returns the new argument regardless of whether it was actually cached or not. + */ +static WINE_MODREF *put_cached_modref( WINE_MODREF *old, WINE_MODREF *new ) +{ + InterlockedCompareExchangePointer( (void **)&cached_modref, new, old ); + return new; +} + #define RTL_UNLOAD_EVENT_TRACE_NUMBER 64
typedef struct _RTL_UNLOAD_EVENT_TRACE @@ -753,17 +775,18 @@ static void call_ldr_notifications( ULONG reason, LDR_DATA_TABLE_ENTRY *module ) */ static WINE_MODREF *get_modref( HMODULE hmod ) { + WINE_MODREF *cached = get_cached_modref(); PLIST_ENTRY mark, entry; PLDR_DATA_TABLE_ENTRY mod;
- if (cached_modref && cached_modref->ldr.DllBase == hmod) return cached_modref; + if (cached && cached->ldr.DllBase == hmod) return cached;
mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList; for (entry = mark->Flink; entry != mark; entry = entry->Flink) { mod = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks); if (mod->DllBase == hmod) - return cached_modref = CONTAINING_RECORD(mod, WINE_MODREF, ldr); + return put_cached_modref( cached, CONTAINING_RECORD(mod, WINE_MODREF, ldr) ); } return NULL; } @@ -777,23 +800,21 @@ static WINE_MODREF *get_modref( HMODULE hmod ) */ static WINE_MODREF *find_basename_module( LPCWSTR name ) { + WINE_MODREF *cached = get_cached_modref(); PLIST_ENTRY mark, entry; UNICODE_STRING name_str;
RtlInitUnicodeString( &name_str, name );
- if (cached_modref && RtlEqualUnicodeString( &name_str, &cached_modref->ldr.BaseDllName, TRUE )) - return cached_modref; + if (cached && RtlEqualUnicodeString( &name_str, &cached->ldr.BaseDllName, TRUE )) + return cached;
mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList; for (entry = mark->Flink; entry != mark; entry = entry->Flink) { LDR_DATA_TABLE_ENTRY *mod = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); if (RtlEqualUnicodeString( &name_str, &mod->BaseDllName, TRUE )) - { - cached_modref = CONTAINING_RECORD(mod, WINE_MODREF, ldr); - return cached_modref; - } + return put_cached_modref( cached, CONTAINING_RECORD(mod, WINE_MODREF, ldr) ); } return NULL; } @@ -807,6 +828,7 @@ static WINE_MODREF *find_basename_module( LPCWSTR name ) */ static WINE_MODREF *find_fullname_module( const UNICODE_STRING *nt_name ) { + WINE_MODREF *cached = get_cached_modref(); PLIST_ENTRY mark, entry; UNICODE_STRING name = *nt_name;
@@ -814,18 +836,15 @@ static WINE_MODREF *find_fullname_module( const UNICODE_STRING *nt_name ) name.Length -= 4 * sizeof(WCHAR); /* for ??\ prefix */ name.Buffer += 4;
- if (cached_modref && RtlEqualUnicodeString( &name, &cached_modref->ldr.FullDllName, TRUE )) - return cached_modref; + if (cached && RtlEqualUnicodeString( &name, &cached->ldr.FullDllName, TRUE )) + return cached;
mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList; for (entry = mark->Flink; entry != mark; entry = entry->Flink) { LDR_DATA_TABLE_ENTRY *mod = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); if (RtlEqualUnicodeString( &name, &mod->FullDllName, TRUE )) - { - cached_modref = CONTAINING_RECORD(mod, WINE_MODREF, ldr); - return cached_modref; - } + return put_cached_modref( cached, CONTAINING_RECORD(mod, WINE_MODREF, ldr) ); } return NULL; } @@ -839,9 +858,10 @@ static WINE_MODREF *find_fullname_module( const UNICODE_STRING *nt_name ) */ static WINE_MODREF *find_fileid_module( const struct file_id *id ) { + WINE_MODREF *cached = get_cached_modref(); LIST_ENTRY *mark, *entry;
- if (cached_modref && !memcmp( &cached_modref->id, id, sizeof(*id) )) return cached_modref; + if (cached && !memcmp( &cached->id, id, sizeof(*id) )) return cached;
mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList; for (entry = mark->Flink; entry != mark; entry = entry->Flink) @@ -850,10 +870,7 @@ static WINE_MODREF *find_fileid_module( const struct file_id *id ) WINE_MODREF *wm = CONTAINING_RECORD( mod, WINE_MODREF, ldr );
if (!memcmp( &wm->id, id, sizeof(*id) )) - { - cached_modref = wm; - return wm; - } + return put_cached_modref( cached, wm ); } return NULL; } @@ -3821,7 +3838,7 @@ static void free_modref( WINE_MODREF *wm ) free_tls_slot( &wm->ldr ); RtlReleaseActivationContext( wm->ldr.ActivationContext ); NtUnmapViewOfSection( NtCurrentProcess(), wm->ldr.DllBase ); - if (cached_modref == wm) cached_modref = NULL; + if (get_cached_modref() == wm) put_cached_modref( wm, NULL ); RtlFreeUnicodeString( &wm->ldr.FullDllName ); RtlFreeHeap( GetProcessHeap(), 0, wm->deps ); RtlFreeHeap( GetProcessHeap(), 0, wm );