Commit 1cee60d0 authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Check file identity in addition to file name to find a loaded module.

parent 97b09074
...@@ -1282,14 +1282,11 @@ static void test_filenames(void) ...@@ -1282,14 +1282,11 @@ static void test_filenames(void)
mod2 = GetModuleHandleA( short_path ); mod2 = GetModuleHandleA( short_path );
ok( mod == mod2, "wrong module %p for %s\n", mod2, short_path ); ok( mod == mod2, "wrong module %p for %s\n", mod2, short_path );
mod2 = GetModuleHandleA( long_path ); mod2 = GetModuleHandleA( long_path );
todo_wine
ok( mod == mod2, "wrong module %p for %s\n", mod2, long_path ); ok( mod == mod2, "wrong module %p for %s\n", mod2, long_path );
mod2 = LoadLibraryA( long_path ); mod2 = LoadLibraryA( long_path );
ok( mod2 != NULL, "loading failed err %u\n", GetLastError() ); ok( mod2 != NULL, "loading failed err %u\n", GetLastError() );
todo_wine
ok( mod == mod2, "library loaded twice\n" ); ok( mod == mod2, "library loaded twice\n" );
GetModuleFileNameA( mod2, buffer, MAX_PATH ); GetModuleFileNameA( mod2, buffer, MAX_PATH );
todo_wine
ok( !lstrcmpiA( buffer, short_path ), "got wrong path %s / %s\n", buffer, short_path ); ok( !lstrcmpiA( buffer, short_path ), "got wrong path %s / %s\n", buffer, short_path );
FreeLibrary( mod2 ); FreeLibrary( mod2 );
FreeLibrary( mod ); FreeLibrary( mod );
...@@ -1299,16 +1296,13 @@ static void test_filenames(void) ...@@ -1299,16 +1296,13 @@ static void test_filenames(void)
GetModuleFileNameA( mod, buffer, MAX_PATH ); GetModuleFileNameA( mod, buffer, MAX_PATH );
ok( !lstrcmpiA( buffer, long_path ), "got wrong path %s / %s\n", buffer, long_path ); ok( !lstrcmpiA( buffer, long_path ), "got wrong path %s / %s\n", buffer, long_path );
mod2 = GetModuleHandleA( short_path ); mod2 = GetModuleHandleA( short_path );
todo_wine
ok( mod == mod2, "wrong module %p for %s\n", mod2, short_path ); ok( mod == mod2, "wrong module %p for %s\n", mod2, short_path );
mod2 = GetModuleHandleA( long_path ); mod2 = GetModuleHandleA( long_path );
ok( mod == mod2, "wrong module %p for %s\n", mod2, long_path ); ok( mod == mod2, "wrong module %p for %s\n", mod2, long_path );
mod2 = LoadLibraryA( short_path ); mod2 = LoadLibraryA( short_path );
ok( mod2 != NULL, "loading failed err %u\n", GetLastError() ); ok( mod2 != NULL, "loading failed err %u\n", GetLastError() );
todo_wine
ok( mod == mod2, "library loaded twice\n" ); ok( mod == mod2, "library loaded twice\n" );
GetModuleFileNameA( mod2, buffer, MAX_PATH ); GetModuleFileNameA( mod2, buffer, MAX_PATH );
todo_wine
ok( !lstrcmpiA( buffer, long_path ), "got wrong path %s / %s\n", buffer, long_path ); ok( !lstrcmpiA( buffer, long_path ), "got wrong path %s / %s\n", buffer, long_path );
FreeLibrary( mod2 ); FreeLibrary( mod2 );
FreeLibrary( mod ); FreeLibrary( mod );
...@@ -1324,14 +1318,11 @@ static void test_filenames(void) ...@@ -1324,14 +1318,11 @@ static void test_filenames(void)
GetModuleFileNameA( mod, buffer, MAX_PATH ); GetModuleFileNameA( mod, buffer, MAX_PATH );
ok( !lstrcmpiA( buffer, dll_name ), "got wrong path %s / %s\n", buffer, dll_name ); ok( !lstrcmpiA( buffer, dll_name ), "got wrong path %s / %s\n", buffer, dll_name );
mod2 = GetModuleHandleA( long_path ); mod2 = GetModuleHandleA( long_path );
todo_wine
ok( mod == mod2, "wrong module %p for %s\n", mod2, long_path ); ok( mod == mod2, "wrong module %p for %s\n", mod2, long_path );
mod2 = LoadLibraryA( long_path ); mod2 = LoadLibraryA( long_path );
ok( mod2 != NULL, "loading failed err %u\n", GetLastError() ); ok( mod2 != NULL, "loading failed err %u\n", GetLastError() );
todo_wine
ok( mod == mod2, "library loaded twice\n" ); ok( mod == mod2, "library loaded twice\n" );
GetModuleFileNameA( mod2, buffer, MAX_PATH ); GetModuleFileNameA( mod2, buffer, MAX_PATH );
todo_wine
ok( !lstrcmpiA( buffer, dll_name ), "got wrong path %s / %s\n", buffer, short_path ); ok( !lstrcmpiA( buffer, dll_name ), "got wrong path %s / %s\n", buffer, short_path );
FreeLibrary( mod2 ); FreeLibrary( mod2 );
FreeLibrary( mod ); FreeLibrary( mod );
......
...@@ -87,6 +87,8 @@ static const WCHAR dllW[] = {'.','d','l','l',0}; ...@@ -87,6 +87,8 @@ static const WCHAR dllW[] = {'.','d','l','l',0};
typedef struct _wine_modref typedef struct _wine_modref
{ {
LDR_MODULE ldr; LDR_MODULE ldr;
dev_t dev;
ino_t ino;
int nDeps; int nDeps;
struct _wine_modref **deps; struct _wine_modref **deps;
} WINE_MODREF; } WINE_MODREF;
...@@ -418,6 +420,35 @@ static WINE_MODREF *find_fullname_module( LPCWSTR name ) ...@@ -418,6 +420,35 @@ static WINE_MODREF *find_fullname_module( LPCWSTR name )
} }
/**********************************************************************
* find_fileid_module
*
* Find a module from its file id.
* The loader_section must be locked while calling this function
*/
static WINE_MODREF *find_fileid_module( HANDLE handle, struct stat *st )
{
LIST_ENTRY *mark, *entry;
if (cached_modref && cached_modref->dev == st->st_dev && cached_modref->ino == st->st_ino)
return cached_modref;
mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
for (entry = mark->Flink; entry != mark; entry = entry->Flink)
{
LDR_MODULE *mod = CONTAINING_RECORD( entry, LDR_MODULE, InLoadOrderModuleList );
WINE_MODREF *wm = CONTAINING_RECORD( mod, WINE_MODREF, ldr );
if (wm->dev == st->st_dev && wm->ino == st->st_ino)
{
cached_modref = wm;
return wm;
}
}
return NULL;
}
/************************************************************************* /*************************************************************************
* find_forwarded_export * find_forwarded_export
* *
...@@ -998,21 +1029,13 @@ static WINE_MODREF *alloc_module( HMODULE hModule, LPCWSTR filename ) ...@@ -998,21 +1029,13 @@ static WINE_MODREF *alloc_module( HMODULE hModule, LPCWSTR filename )
const WCHAR *p; const WCHAR *p;
const IMAGE_NT_HEADERS *nt = RtlImageNtHeader(hModule); const IMAGE_NT_HEADERS *nt = RtlImageNtHeader(hModule);
if (!(wm = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*wm) ))) return NULL; if (!(wm = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wm) ))) return NULL;
wm->nDeps = 0;
wm->deps = NULL;
wm->ldr.BaseAddress = hModule; wm->ldr.BaseAddress = hModule;
wm->ldr.EntryPoint = NULL;
wm->ldr.SizeOfImage = nt->OptionalHeader.SizeOfImage; wm->ldr.SizeOfImage = nt->OptionalHeader.SizeOfImage;
wm->ldr.Flags = LDR_DONT_RESOLVE_REFS; wm->ldr.Flags = LDR_DONT_RESOLVE_REFS;
wm->ldr.TlsIndex = -1; wm->ldr.TlsIndex = -1;
wm->ldr.LoadCount = 1; wm->ldr.LoadCount = 1;
wm->ldr.SectionHandle = NULL;
wm->ldr.CheckSum = 0;
wm->ldr.TimeDateStamp = 0;
wm->ldr.ActivationContext = 0;
RtlCreateUnicodeString( &wm->ldr.FullDllName, filename ); RtlCreateUnicodeString( &wm->ldr.FullDllName, filename );
if ((p = strrchrW( wm->ldr.FullDllName.Buffer, '\\' ))) p++; if ((p = strrchrW( wm->ldr.FullDllName.Buffer, '\\' ))) p++;
...@@ -1031,10 +1054,7 @@ static WINE_MODREF *alloc_module( HMODULE hModule, LPCWSTR filename ) ...@@ -1031,10 +1054,7 @@ static WINE_MODREF *alloc_module( HMODULE hModule, LPCWSTR filename )
&wm->ldr.InLoadOrderModuleList); &wm->ldr.InLoadOrderModuleList);
InsertTailList(&NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList, InsertTailList(&NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList,
&wm->ldr.InMemoryOrderModuleList); &wm->ldr.InMemoryOrderModuleList);
/* wait until init is called for inserting into InInitializationOrderModuleList */
/* wait until init is called for inserting into this list */
wm->ldr.InInitializationOrderModuleList.Flink = NULL;
wm->ldr.InInitializationOrderModuleList.Blink = NULL;
if (!(nt->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NX_COMPAT)) if (!(nt->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NX_COMPAT))
{ {
...@@ -1840,7 +1860,7 @@ static BOOL is_valid_binary( HMODULE module, const pe_image_info_t *info ) ...@@ -1840,7 +1860,7 @@ static BOOL is_valid_binary( HMODULE module, const pe_image_info_t *info )
* load_native_dll (internal) * load_native_dll (internal)
*/ */
static NTSTATUS load_native_dll( LPCWSTR load_path, LPCWSTR name, HANDLE file, static NTSTATUS load_native_dll( LPCWSTR load_path, LPCWSTR name, HANDLE file,
DWORD flags, WINE_MODREF** pwm ) DWORD flags, WINE_MODREF** pwm, struct stat *st )
{ {
void *module; void *module;
HANDLE mapping; HANDLE mapping;
...@@ -1889,6 +1909,8 @@ static NTSTATUS load_native_dll( LPCWSTR load_path, LPCWSTR name, HANDLE file, ...@@ -1889,6 +1909,8 @@ static NTSTATUS load_native_dll( LPCWSTR load_path, LPCWSTR name, HANDLE file,
return STATUS_NO_MEMORY; return STATUS_NO_MEMORY;
} }
wm->dev = st->st_dev;
wm->ino = st->st_ino;
if (image_info.loader_flags) wm->ldr.Flags |= LDR_COR_IMAGE; if (image_info.loader_flags) wm->ldr.Flags |= LDR_COR_IMAGE;
if (image_info.image_flags & IMAGE_FLAGS_ComPlusILOnly) wm->ldr.Flags |= LDR_COR_ILONLY; if (image_info.image_flags & IMAGE_FLAGS_ComPlusILOnly) wm->ldr.Flags |= LDR_COR_ILONLY;
...@@ -2170,11 +2192,12 @@ done: ...@@ -2170,11 +2192,12 @@ done:
* *
* Open a file for a new dll. Helper for find_dll_file. * Open a file for a new dll. Helper for find_dll_file.
*/ */
static HANDLE open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm ) static HANDLE open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, struct stat *st )
{ {
OBJECT_ATTRIBUTES attr; OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io; IO_STATUS_BLOCK io;
HANDLE handle; HANDLE handle;
int fd, needs_close;
attr.Length = sizeof(attr); attr.Length = sizeof(attr);
attr.RootDirectory = 0; attr.RootDirectory = 0;
...@@ -2186,6 +2209,18 @@ static HANDLE open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm ) ...@@ -2186,6 +2209,18 @@ static HANDLE open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm )
FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE )) FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE ))
return 0; return 0;
if (!server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL ))
{
fstat( fd, st );
if (needs_close) close( fd );
if ((*pwm = find_fileid_module( handle, st )))
{
TRACE( "%s is the same file as existing module %p %s\n", debugstr_w( nt_name->Buffer ),
(*pwm)->ldr.BaseAddress, debugstr_w( (*pwm)->ldr.FullDllName.Buffer ));
NtClose( handle );
return 0;
}
}
return handle; return handle;
} }
...@@ -2196,7 +2231,8 @@ static HANDLE open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm ) ...@@ -2196,7 +2231,8 @@ static HANDLE open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm )
* Find the file (or already loaded module) for a given dll name. * Find the file (or already loaded module) for a given dll name.
*/ */
static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname,
WCHAR *filename, ULONG *size, WINE_MODREF **pwm, HANDLE *handle ) WCHAR *filename, ULONG *size, WINE_MODREF **pwm,
HANDLE *handle, struct stat *st )
{ {
UNICODE_STRING nt_name; UNICODE_STRING nt_name;
WCHAR *file_part, *ext, *dllname; WCHAR *file_part, *ext, *dllname;
...@@ -2204,6 +2240,7 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, ...@@ -2204,6 +2240,7 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname,
/* first append .dll if needed */ /* first append .dll if needed */
*handle = 0;
dllname = NULL; dllname = NULL;
if (!(ext = strrchrW( libname, '.')) || strchrW( ext, '/' ) || strchrW( ext, '\\')) if (!(ext = strrchrW( libname, '.')) || strchrW( ext, '/' ) || strchrW( ext, '\\'))
{ {
...@@ -2245,14 +2282,14 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, ...@@ -2245,14 +2282,14 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname,
if (len) if (len)
{ {
if (len >= *size) goto overflow; if (len >= *size) goto overflow;
if ((*pwm = find_fullname_module( filename )) || !handle) goto found; if ((*pwm = find_fullname_module( filename ))) goto found;
if (!RtlDosPathNameToNtPathName_U( filename, &nt_name, NULL, NULL )) if (!RtlDosPathNameToNtPathName_U( filename, &nt_name, NULL, NULL ))
{ {
RtlFreeHeap( GetProcessHeap(), 0, dllname ); RtlFreeHeap( GetProcessHeap(), 0, dllname );
return STATUS_NO_MEMORY; return STATUS_NO_MEMORY;
} }
*handle = open_dll_file( &nt_name, pwm ); *handle = open_dll_file( &nt_name, pwm, st );
goto found; goto found;
} }
...@@ -2279,8 +2316,8 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, ...@@ -2279,8 +2316,8 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname,
len = nt_name.Length - 4*sizeof(WCHAR); /* for \??\ prefix */ len = nt_name.Length - 4*sizeof(WCHAR); /* for \??\ prefix */
if (len >= *size) goto overflow; if (len >= *size) goto overflow;
memcpy( filename, nt_name.Buffer + 4, len + sizeof(WCHAR) ); memcpy( filename, nt_name.Buffer + 4, len + sizeof(WCHAR) );
if (!(*pwm = find_fullname_module( filename )) && handle) if (!(*pwm = find_fullname_module( filename )))
*handle = open_dll_file( &nt_name, pwm ); *handle = open_dll_file( &nt_name, pwm, st );
found: found:
RtlFreeUnicodeString( &nt_name ); RtlFreeUnicodeString( &nt_name );
...@@ -2308,7 +2345,8 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_ ...@@ -2308,7 +2345,8 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_
WCHAR *filename; WCHAR *filename;
ULONG size; ULONG size;
WINE_MODREF *main_exe; WINE_MODREF *main_exe;
HANDLE handle = 0; struct stat st;
HANDLE handle;
NTSTATUS nts; NTSTATUS nts;
TRACE( "looking for %s in %s\n", debugstr_w(libname), debugstr_w(load_path) ); TRACE( "looking for %s in %s\n", debugstr_w(libname), debugstr_w(load_path) );
...@@ -2318,7 +2356,7 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_ ...@@ -2318,7 +2356,7 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_
size = sizeof(buffer); size = sizeof(buffer);
for (;;) for (;;)
{ {
nts = find_dll_file( load_path, libname, filename, &size, pwm, &handle ); nts = find_dll_file( load_path, libname, filename, &size, pwm, &handle, &st );
if (nts == STATUS_SUCCESS) break; if (nts == STATUS_SUCCESS) break;
if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename ); if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename );
if (nts != STATUS_BUFFER_TOO_SMALL) return nts; if (nts != STATUS_BUFFER_TOO_SMALL) return nts;
...@@ -2360,7 +2398,7 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_ ...@@ -2360,7 +2398,7 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_
if (!handle) nts = STATUS_DLL_NOT_FOUND; if (!handle) nts = STATUS_DLL_NOT_FOUND;
else else
{ {
nts = load_native_dll( load_path, filename, handle, flags, pwm ); nts = load_native_dll( load_path, filename, handle, flags, pwm, &st );
if (nts == STATUS_INVALID_IMAGE_NOT_MZ) if (nts == STATUS_INVALID_IMAGE_NOT_MZ)
/* not in PE format, maybe it's a builtin */ /* not in PE format, maybe it's a builtin */
nts = load_builtin_dll( load_path, filename, handle, flags, pwm ); nts = load_builtin_dll( load_path, filename, handle, flags, pwm );
...@@ -2385,7 +2423,7 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_ ...@@ -2385,7 +2423,7 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_
nts = STATUS_DLL_NOT_FOUND; nts = STATUS_DLL_NOT_FOUND;
} }
if (nts == STATUS_DLL_NOT_FOUND && loadorder != LO_BUILTIN) if (nts == STATUS_DLL_NOT_FOUND && loadorder != LO_BUILTIN)
nts = load_native_dll( load_path, filename, handle, flags, pwm ); nts = load_native_dll( load_path, filename, handle, flags, pwm, &st );
break; break;
} }
...@@ -2446,6 +2484,8 @@ NTSTATUS WINAPI LdrGetDllHandle( LPCWSTR load_path, ULONG flags, const UNICODE_S ...@@ -2446,6 +2484,8 @@ NTSTATUS WINAPI LdrGetDllHandle( LPCWSTR load_path, ULONG flags, const UNICODE_S
WCHAR *filename; WCHAR *filename;
ULONG size; ULONG size;
WINE_MODREF *wm; WINE_MODREF *wm;
HANDLE handle;
struct stat st;
RtlEnterCriticalSection( &loader_section ); RtlEnterCriticalSection( &loader_section );
...@@ -2455,7 +2495,8 @@ NTSTATUS WINAPI LdrGetDllHandle( LPCWSTR load_path, ULONG flags, const UNICODE_S ...@@ -2455,7 +2495,8 @@ NTSTATUS WINAPI LdrGetDllHandle( LPCWSTR load_path, ULONG flags, const UNICODE_S
size = sizeof(buffer); size = sizeof(buffer);
for (;;) for (;;)
{ {
status = find_dll_file( load_path, name->Buffer, filename, &size, &wm, NULL ); status = find_dll_file( load_path, name->Buffer, filename, &size, &wm, &handle, &st );
if (handle) NtClose( handle );
if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename ); if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename );
if (status != STATUS_BUFFER_TOO_SMALL) break; if (status != STATUS_BUFFER_TOO_SMALL) break;
/* grow the buffer and retry */ /* grow the buffer and retry */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment