ntdll: Use FSCTL_GET_OBJECT_ID to compare file identities.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2020-06-21 16:56:05 +02:00
parent 251335cdf3
commit 9e3893cc29
5 changed files with 47 additions and 50 deletions

View File

@ -37,6 +37,7 @@
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winnt.h"
#include "winioctl.h"
#include "winternl.h"
#include "delayloadhandler.h"
@ -122,12 +123,16 @@ static const char * const reason_names[] =
static const WCHAR dllW[] = {'.','d','l','l',0};
/* internal representation of 32bit modules. per process. */
struct file_id
{
BYTE ObjectId[16];
};
/* internal representation of loaded modules */
typedef struct _wine_modref
{
LDR_DATA_TABLE_ENTRY ldr;
dev_t dev;
ino_t ino;
struct file_id id;
void *so_handle;
int alloc_deps;
int nDeps;
@ -554,12 +559,11 @@ static WINE_MODREF *find_fullname_module( const UNICODE_STRING *nt_name )
* Find a module from its file id.
* The loader_section must be locked while calling this function
*/
static WINE_MODREF *find_fileid_module( struct stat *st )
static WINE_MODREF *find_fileid_module( const struct file_id *id )
{
LIST_ENTRY *mark, *entry;
if (cached_modref && cached_modref->dev == st->st_dev && cached_modref->ino == st->st_ino)
return cached_modref;
if (cached_modref && !memcmp( &cached_modref->id, id, sizeof(*id) )) return cached_modref;
mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
for (entry = mark->Flink; entry != mark; entry = entry->Flink)
@ -567,7 +571,7 @@ static WINE_MODREF *find_fileid_module( struct stat *st )
LDR_DATA_TABLE_ENTRY *mod = CONTAINING_RECORD( entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks );
WINE_MODREF *wm = CONTAINING_RECORD( mod, WINE_MODREF, ldr );
if (wm->dev == st->st_dev && wm->ino == st->st_ino)
if (!memcmp( &wm->id, id, sizeof(*id) ))
{
cached_modref = wm;
return wm;
@ -2303,16 +2307,16 @@ static NTSTATUS get_dll_load_path_search_flags( LPCWSTR module, DWORD flags, WCH
* Open a file for a new dll. Helper for find_dll_file.
*/
static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm,
void **module, pe_image_info_t *image_info, struct stat *st )
void **module, pe_image_info_t *image_info, struct file_id *id )
{
FILE_BASIC_INFORMATION info;
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
LARGE_INTEGER size;
FILE_OBJECTID_BUFFER fid;
SIZE_T len = 0;
NTSTATUS status;
HANDLE handle, mapping;
int fd, needs_close;
if ((*pwm = find_fullname_module( nt_name )))
{
@ -2342,11 +2346,10 @@ static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm,
return STATUS_DLL_NOT_FOUND;
}
if (!unix_funcs->server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL ))
if (!NtFsControlFile( handle, 0, NULL, NULL, &io, FSCTL_GET_OBJECT_ID, NULL, 0, &fid, sizeof(fid) ))
{
fstat( fd, st );
if (needs_close) close( fd );
if ((*pwm = find_fileid_module( st )))
memcpy( id, fid.ObjectId, sizeof(*id) );
if ((*pwm = find_fileid_module( id )))
{
TRACE( "%s is the same file as existing module %p %s\n", debugstr_w( nt_name->Buffer ),
(*pwm)->ldr.DllBase, debugstr_w( (*pwm)->ldr.FullDllName.Buffer ));
@ -2390,8 +2393,8 @@ static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm,
* load_native_dll (internal)
*/
static NTSTATUS load_native_dll( LPCWSTR load_path, const UNICODE_STRING *nt_name, void **module,
const pe_image_info_t *image_info, DWORD flags, WINE_MODREF** pwm,
struct stat *st )
const pe_image_info_t *image_info, const struct file_id *id,
DWORD flags, WINE_MODREF** pwm )
{
IMAGE_NT_HEADERS *nt = RtlImageNtHeader( *module );
WINE_MODREF *wm;
@ -2409,8 +2412,7 @@ static NTSTATUS load_native_dll( LPCWSTR load_path, const UNICODE_STRING *nt_nam
if (!(wm = alloc_module( *module, nt_name, (image_info->image_flags & IMAGE_FLAGS_WineBuiltin) )))
return STATUS_NO_MEMORY;
wm->dev = st->st_dev;
wm->ino = st->st_ino;
wm->id = *id;
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;
@ -2521,7 +2523,7 @@ static inline char *prepend( char *buffer, const char *str, size_t len )
* open_builtin_file
*/
static NTSTATUS open_builtin_file( char *name, WINE_MODREF **pwm, void **module,
pe_image_info_t *image_info, struct stat *st, char **so_name )
pe_image_info_t *image_info, struct file_id *id, char **so_name )
{
ANSI_STRING strA;
UNICODE_STRING nt_name;
@ -2532,7 +2534,7 @@ static NTSTATUS open_builtin_file( char *name, WINE_MODREF **pwm, void **module,
RtlInitString( &strA, name );
if ((status = wine_unix_to_nt_file_name( &strA, &nt_name ))) return status;
status = open_dll_file( &nt_name, pwm, module, image_info, st );
status = open_dll_file( &nt_name, pwm, module, image_info, id );
RtlFreeUnicodeString( &nt_name );
/* ignore non-builtins */
@ -2569,9 +2571,8 @@ static NTSTATUS open_builtin_file( char *name, WINE_MODREF **pwm, void **module,
/***********************************************************************
* find_builtin_dll
*/
static NTSTATUS find_builtin_dll( const WCHAR *name, WINE_MODREF **pwm,
void **module, pe_image_info_t *image_info, struct stat *st,
char **so_name )
static NTSTATUS find_builtin_dll( const WCHAR *name, WINE_MODREF **pwm, void **module,
pe_image_info_t *image_info, struct file_id *id, char **so_name )
{
unsigned int i, pos, len, namelen, maxlen = 0;
char *ptr, *file;
@ -2608,7 +2609,7 @@ static NTSTATUS find_builtin_dll( const WCHAR *name, WINE_MODREF **pwm,
ptr = prepend( ptr, ptr, namelen );
ptr = prepend( ptr, "/dlls", sizeof("/dlls") - 1 );
ptr = prepend( ptr, build_dir, strlen(build_dir) );
status = open_builtin_file( ptr, pwm, module, image_info, st, so_name );
status = open_builtin_file( ptr, pwm, module, image_info, id, so_name );
if (status != STATUS_DLL_NOT_FOUND) goto done;
/* now as a program */
@ -2619,7 +2620,7 @@ static NTSTATUS find_builtin_dll( const WCHAR *name, WINE_MODREF **pwm,
ptr = prepend( ptr, ptr, namelen );
ptr = prepend( ptr, "/programs", sizeof("/programs") - 1 );
ptr = prepend( ptr, build_dir, strlen(build_dir) );
status = open_builtin_file( ptr, pwm, module, image_info, st, so_name );
status = open_builtin_file( ptr, pwm, module, image_info, id, so_name );
if (status != STATUS_DLL_NOT_FOUND) goto done;
}
@ -2627,7 +2628,7 @@ static NTSTATUS find_builtin_dll( const WCHAR *name, WINE_MODREF **pwm,
{
file[pos + len + 1] = 0;
ptr = prepend( file + pos, dll_paths[i], strlen(dll_paths[i]) );
status = open_builtin_file( ptr, pwm, module, image_info, st, so_name );
status = open_builtin_file( ptr, pwm, module, image_info, id, so_name );
if (status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) found_image = TRUE;
else if (status != STATUS_DLL_NOT_FOUND) goto done;
}
@ -2760,7 +2761,7 @@ static NTSTATUS load_builtin_dll( LPCWSTR load_path, const UNICODE_STRING *nt_na
NTSTATUS status;
void *module = NULL;
pe_image_info_t image_info;
struct stat st;
struct file_id id;
char *so_name;
/* Fix the name in case we have a full path and extension */
@ -2772,7 +2773,7 @@ static NTSTATUS load_builtin_dll( LPCWSTR load_path, const UNICODE_STRING *nt_na
if (!module_ptr) module_ptr = &module;
status = find_builtin_dll( name, pwm, module_ptr, &image_info, &st, &so_name );
status = find_builtin_dll( name, pwm, module_ptr, &image_info, &id, &so_name );
if (status) return status;
if (*pwm)
@ -2787,7 +2788,7 @@ static NTSTATUS load_builtin_dll( LPCWSTR load_path, const UNICODE_STRING *nt_na
if (*module_ptr)
{
TRACE( "loading %s from PE builtin %s\n", debugstr_w(name), debugstr_us(nt_name) );
return load_native_dll( load_path, nt_name, module_ptr, &image_info, flags, pwm, &st );
return load_native_dll( load_path, nt_name, module_ptr, &image_info, &id, flags, pwm );
}
status = load_so_dll( load_path, nt_name, so_name, flags, pwm );
@ -2904,7 +2905,7 @@ done:
*/
static NTSTATUS search_dll_file( LPCWSTR paths, LPCWSTR search, UNICODE_STRING *nt_name,
WINE_MODREF **pwm, void **module, pe_image_info_t *image_info,
struct stat *st )
struct file_id *id )
{
WCHAR *name;
BOOL found_image = FALSE;
@ -2931,7 +2932,7 @@ static NTSTATUS search_dll_file( LPCWSTR paths, LPCWSTR search, UNICODE_STRING *
nt_name->Buffer = NULL;
if ((status = RtlDosPathNameToNtPathName_U_WithStatus( name, nt_name, NULL, NULL ))) goto done;
status = open_dll_file( nt_name, pwm, module, image_info, st );
status = open_dll_file( nt_name, pwm, module, image_info, id );
if (status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) found_image = TRUE;
else if (status != STATUS_DLL_NOT_FOUND) goto done;
RtlFreeUnicodeString( nt_name );
@ -2960,7 +2961,7 @@ done:
*/
static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, const WCHAR *default_ext,
UNICODE_STRING *nt_name, WINE_MODREF **pwm,
void **module, pe_image_info_t *image_info, struct stat *st )
void **module, pe_image_info_t *image_info, struct file_id *id )
{
WCHAR *ext, *dllname;
NTSTATUS status;
@ -3011,9 +3012,9 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, con
}
if (RtlDetermineDosPathNameType_U( libname ) == RELATIVE_PATH)
status = search_dll_file( load_path, libname, nt_name, pwm, module, image_info, st );
status = search_dll_file( load_path, libname, nt_name, pwm, module, image_info, id );
else if (!(status = RtlDosPathNameToNtPathName_U_WithStatus( libname, nt_name, NULL, NULL )))
status = open_dll_file( nt_name, pwm, module, image_info, st );
status = open_dll_file( nt_name, pwm, module, image_info, id );
if (status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) status = STATUS_INVALID_IMAGE_FORMAT;
@ -3036,14 +3037,14 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC
enum loadorder loadorder;
WINE_MODREF *main_exe;
UNICODE_STRING nt_name;
struct stat st;
struct file_id id;
void *module;
pe_image_info_t image_info;
NTSTATUS nts;
TRACE( "looking for %s in %s\n", debugstr_w(libname), debugstr_w(load_path) );
nts = find_dll_file( load_path, libname, default_ext, &nt_name, pwm, &module, &image_info, &st );
nts = find_dll_file( load_path, libname, default_ext, &nt_name, pwm, &module, &image_info, &id );
if (*pwm) /* found already loaded module */
{
@ -3090,7 +3091,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_DLL_NOT_FOUND)
nts = load_native_dll( load_path, &nt_name, &module, &image_info, flags, pwm, &st );
nts = load_native_dll( load_path, &nt_name, &module, &image_info, &id, flags, pwm );
break;
default:
nts = STATUS_DLL_NOT_FOUND;
@ -3105,7 +3106,7 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC
{
case LO_NATIVE:
case LO_NATIVE_BUILTIN:
nts = load_native_dll( load_path, &nt_name, &module, &image_info, flags, pwm, &st );
nts = load_native_dll( load_path, &nt_name, &module, &image_info, &id, flags, pwm );
break;
case LO_BUILTIN:
nts = load_builtin_dll( load_path, &nt_name, &module, flags, pwm );
@ -3121,10 +3122,10 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC
LdrUnloadDll( (*pwm)->ldr.DllBase );
nts = STATUS_DLL_NOT_FOUND;
/* map the dll again if it was unmapped */
if (!module && open_dll_file( &nt_name, pwm, &module, &image_info, &st )) break;
if (!module && open_dll_file( &nt_name, pwm, &module, &image_info, &id )) break;
}
if (nts == STATUS_DLL_NOT_FOUND)
nts = load_native_dll( load_path, &nt_name, &module, &image_info, flags, pwm, &st );
nts = load_native_dll( load_path, &nt_name, &module, &image_info, &id, flags, pwm );
break;
default:
nts = STATUS_DLL_NOT_FOUND;
@ -3203,13 +3204,13 @@ NTSTATUS WINAPI LdrGetDllHandle( LPCWSTR load_path, ULONG flags, const UNICODE_S
WINE_MODREF *wm;
void *module;
pe_image_info_t image_info;
struct stat st;
struct file_id id;
RtlEnterCriticalSection( &loader_section );
if (!load_path) load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
status = find_dll_file( load_path, name->Buffer, dllW, &nt_name, &wm, &module, &image_info, &st );
status = find_dll_file( load_path, name->Buffer, dllW, &nt_name, &wm, &module, &image_info, &id );
if (wm) *base = wm->ldr.DllBase;
else

View File

@ -1024,7 +1024,6 @@ static struct unix_funcs unix_funcs =
exec_process,
wine_server_call,
server_send_fd,
server_get_unix_fd,
server_fd_to_handle,
server_handle_to_fd,
server_release_fd,

View File

@ -999,7 +999,7 @@ static int remove_fd_from_cache( HANDLE handle )
*
* The returned unix_fd should be closed iff needs_close is non-zero.
*/
int CDECL server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd,
int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd,
int *needs_close, enum server_fd_type *type, unsigned int *options )
{
sigset_t sigset;

View File

@ -101,9 +101,6 @@ extern void CDECL virtual_release_address_space(void) DECLSPEC_HIDDEN;
extern void CDECL virtual_set_large_address_space(void) DECLSPEC_HIDDEN;
extern void CDECL server_send_fd( int fd ) DECLSPEC_HIDDEN;
extern int CDECL server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd,
int *needs_close, enum server_fd_type *type,
unsigned int *options ) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL server_fd_to_handle( int fd, unsigned int access, unsigned int attributes,
HANDLE *handle ) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL server_handle_to_fd( HANDLE handle, unsigned int access, int *unix_fd,
@ -155,6 +152,8 @@ extern unsigned int server_wait( const select_op_t *select_op, data_size_t size,
const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN;
extern unsigned int server_queue_process_apc( HANDLE process, const apc_call_t *call,
apc_result_t *result ) DECLSPEC_HIDDEN;
extern int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd,
int *needs_close, enum server_fd_type *type, unsigned int *options ) DECLSPEC_HIDDEN;
extern void server_init_process(void) DECLSPEC_HIDDEN;
extern size_t server_init_thread( void *entry_point, BOOL *suspend ) DECLSPEC_HIDDEN;
extern int server_pipe( int fd[2] ) DECLSPEC_HIDDEN;

View File

@ -28,7 +28,7 @@ struct ldt_copy;
struct msghdr;
/* increment this when you change the function table */
#define NTDLL_UNIXLIB_VERSION 56
#define NTDLL_UNIXLIB_VERSION 57
struct unix_funcs
{
@ -310,8 +310,6 @@ struct unix_funcs
/* server functions */
unsigned int (CDECL *server_call)( void *req_ptr );
void (CDECL *server_send_fd)( int fd );
int (CDECL *server_get_unix_fd)( HANDLE handle, unsigned int wanted_access, int *unix_fd,
int *needs_close, enum server_fd_type *type, unsigned int *options );
NTSTATUS (CDECL *server_fd_to_handle)( int fd, unsigned int access, unsigned int attributes,
HANDLE *handle );
NTSTATUS (CDECL *server_handle_to_fd)( HANDLE handle, unsigned int access, int *unix_fd,