ntdll: Use the image info to check for fake dlls.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2019-02-09 15:29:54 +01:00
parent f244c3b5eb
commit 2062df7e6c
1 changed files with 17 additions and 51 deletions

View File

@ -1634,29 +1634,6 @@ NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE module, const ANSI_STRING *name,
} }
/***********************************************************************
* is_fake_dll
*
* Check if a loaded native dll is a Wine fake dll.
*/
static BOOL is_fake_dll( HANDLE handle )
{
static const char fakedll_signature[] = "Wine placeholder DLL";
char buffer[sizeof(IMAGE_DOS_HEADER) + sizeof(fakedll_signature)];
const IMAGE_DOS_HEADER *dos = (const IMAGE_DOS_HEADER *)buffer;
IO_STATUS_BLOCK io;
LARGE_INTEGER offset;
offset.QuadPart = 0;
if (NtReadFile( handle, 0, NULL, 0, &io, buffer, sizeof(buffer), &offset, NULL )) return FALSE;
if (io.Information < sizeof(buffer)) return FALSE;
if (dos->e_magic != IMAGE_DOS_SIGNATURE) return FALSE;
if (dos->e_lfanew >= sizeof(*dos) + sizeof(fakedll_signature) &&
!memcmp( dos + 1, fakedll_signature, sizeof(fakedll_signature) )) return TRUE;
return FALSE;
}
/*********************************************************************** /***********************************************************************
* get_builtin_fullname * get_builtin_fullname
* *
@ -2323,7 +2300,7 @@ 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 NTSTATUS open_dll_file( const WCHAR *name, UNICODE_STRING *nt_name, WINE_MODREF **pwm, static NTSTATUS open_dll_file( const WCHAR *name, UNICODE_STRING *nt_name, WINE_MODREF **pwm,
HANDLE *handle, void **module, pe_image_info_t *image_info, struct stat *st ) void **module, pe_image_info_t *image_info, struct stat *st )
{ {
FILE_BASIC_INFORMATION info; FILE_BASIC_INFORMATION info;
OBJECT_ATTRIBUTES attr; OBJECT_ATTRIBUTES attr;
@ -2331,7 +2308,7 @@ static NTSTATUS open_dll_file( const WCHAR *name, UNICODE_STRING *nt_name, WINE_
LARGE_INTEGER size; LARGE_INTEGER size;
SIZE_T len = 0; SIZE_T len = 0;
NTSTATUS status; NTSTATUS status;
HANDLE mapping; HANDLE handle, mapping;
int fd, needs_close; int fd, needs_close;
nt_name->Buffer = NULL; nt_name->Buffer = NULL;
@ -2345,7 +2322,7 @@ static NTSTATUS open_dll_file( const WCHAR *name, UNICODE_STRING *nt_name, WINE_
attr.ObjectName = nt_name; attr.ObjectName = nt_name;
attr.SecurityDescriptor = NULL; attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL; attr.SecurityQualityOfService = NULL;
if ((status = NtOpenFile( handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, if ((status = NtOpenFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &io,
FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_SHARE_READ | FILE_SHARE_DELETE,
FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE ))) FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE )))
{ {
@ -2360,7 +2337,7 @@ static NTSTATUS open_dll_file( const WCHAR *name, UNICODE_STRING *nt_name, WINE_
return STATUS_DLL_NOT_FOUND; return STATUS_DLL_NOT_FOUND;
} }
if (!server_get_unix_fd( *handle, 0, &fd, &needs_close, NULL, NULL )) if (!server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL ))
{ {
fstat( fd, st ); fstat( fd, st );
if (needs_close) close( fd ); if (needs_close) close( fd );
@ -2368,8 +2345,7 @@ static NTSTATUS open_dll_file( const WCHAR *name, UNICODE_STRING *nt_name, WINE_
{ {
TRACE( "%s is the same file as existing module %p %s\n", debugstr_w( nt_name->Buffer ), 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 )); (*pwm)->ldr.BaseAddress, debugstr_w( (*pwm)->ldr.FullDllName.Buffer ));
NtClose( *handle ); NtClose( handle );
*handle = 0;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
} }
@ -2377,7 +2353,9 @@ static NTSTATUS open_dll_file( const WCHAR *name, UNICODE_STRING *nt_name, WINE_
size.QuadPart = 0; size.QuadPart = 0;
status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY |
SECTION_MAP_READ | SECTION_MAP_EXECUTE, SECTION_MAP_READ | SECTION_MAP_EXECUTE,
NULL, &size, PAGE_EXECUTE_READ, SEC_IMAGE, *handle ); NULL, &size, PAGE_EXECUTE_READ, SEC_IMAGE, handle );
NtClose( handle );
if (!status) if (!status)
{ {
status = virtual_map_section( mapping, module, 0, 0, NULL, &len, status = virtual_map_section( mapping, module, 0, 0, NULL, &len,
@ -2385,11 +2363,6 @@ static NTSTATUS open_dll_file( const WCHAR *name, UNICODE_STRING *nt_name, WINE_
if (status == STATUS_IMAGE_NOT_AT_BASE) status = STATUS_SUCCESS; if (status == STATUS_IMAGE_NOT_AT_BASE) status = STATUS_SUCCESS;
NtClose( mapping ); NtClose( mapping );
} }
if (status)
{
NtClose( *handle );
*handle = 0;
}
return status; return status;
} }
@ -2400,8 +2373,8 @@ static NTSTATUS open_dll_file( const WCHAR *name, UNICODE_STRING *nt_name, WINE_
* Search for dll in the specified paths. * Search for dll in the specified paths.
*/ */
static NTSTATUS search_dll_file( LPCWSTR paths, LPCWSTR search, UNICODE_STRING *nt_name, static NTSTATUS search_dll_file( LPCWSTR paths, LPCWSTR search, UNICODE_STRING *nt_name,
WINE_MODREF **pwm, HANDLE *handle, void **module, WINE_MODREF **pwm, void **module, pe_image_info_t *image_info,
pe_image_info_t *image_info, struct stat *st ) struct stat *st )
{ {
WCHAR *name; WCHAR *name;
NTSTATUS status = STATUS_DLL_NOT_FOUND; NTSTATUS status = STATUS_DLL_NOT_FOUND;
@ -2423,7 +2396,7 @@ static NTSTATUS search_dll_file( LPCWSTR paths, LPCWSTR search, UNICODE_STRING *
memcpy( name, paths, len * sizeof(WCHAR) ); memcpy( name, paths, len * sizeof(WCHAR) );
if (len && name[len - 1] != '\\') name[len++] = '\\'; if (len && name[len - 1] != '\\') name[len++] = '\\';
strcpyW( name + len, search ); strcpyW( name + len, search );
status = open_dll_file( name, nt_name, pwm, handle, module, image_info, st ); status = open_dll_file( name, nt_name, pwm, module, image_info, st );
if (status != STATUS_DLL_NOT_FOUND) goto done; if (status != STATUS_DLL_NOT_FOUND) goto done;
RtlFreeUnicodeString( nt_name ); RtlFreeUnicodeString( nt_name );
paths = ptr; paths = ptr;
@ -2447,15 +2420,13 @@ done:
*/ */
static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname,
UNICODE_STRING *nt_name, WINE_MODREF **pwm, UNICODE_STRING *nt_name, WINE_MODREF **pwm,
HANDLE *handle, void **module, pe_image_info_t *image_info, void **module, pe_image_info_t *image_info, struct stat *st )
struct stat *st )
{ {
WCHAR *ext, *dllname; WCHAR *ext, *dllname;
NTSTATUS status = STATUS_SUCCESS; NTSTATUS status = STATUS_SUCCESS;
/* first append .dll if needed */ /* first append .dll if needed */
*handle = 0;
*pwm = NULL; *pwm = NULL;
*module = NULL; *module = NULL;
dllname = NULL; dllname = NULL;
@ -2488,9 +2459,9 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname,
} }
if (RtlDetermineDosPathNameType_U( libname ) == RELATIVE_PATH) if (RtlDetermineDosPathNameType_U( libname ) == RELATIVE_PATH)
status = search_dll_file( load_path, libname, nt_name, pwm, handle, module, image_info, st ); status = search_dll_file( load_path, libname, nt_name, pwm, module, image_info, st );
else else
status = open_dll_file( libname, nt_name, pwm, handle, module, image_info, st ); status = open_dll_file( libname, nt_name, pwm, module, image_info, st );
done: done:
RtlFreeHeap( GetProcessHeap(), 0, dllname ); RtlFreeHeap( GetProcessHeap(), 0, dllname );
@ -2510,14 +2481,13 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_
WINE_MODREF *main_exe; WINE_MODREF *main_exe;
UNICODE_STRING nt_name; UNICODE_STRING nt_name;
struct stat st; struct stat st;
HANDLE handle;
void *module; void *module;
pe_image_info_t image_info; pe_image_info_t image_info;
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) );
nts = find_dll_file( load_path, libname, &nt_name, pwm, &handle, &module, &image_info, &st ); nts = find_dll_file( load_path, libname, &nt_name, pwm, &module, &image_info, &st );
if (*pwm) /* found already loaded module */ if (*pwm) /* found already loaded module */
{ {
@ -2554,7 +2524,7 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_
break; break;
case STATUS_SUCCESS: /* valid PE file */ case STATUS_SUCCESS: /* valid PE file */
if (!is_fake_dll( handle )) if (!(image_info.image_flags & IMAGE_FLAGS_WineFakeDll))
{ {
switch (loadorder) switch (loadorder)
{ {
@ -2587,12 +2557,10 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_
nts = STATUS_DLL_NOT_FOUND; nts = STATUS_DLL_NOT_FOUND;
break; break;
} }
NtClose( handle );
if (module) NtUnmapViewOfSection( NtCurrentProcess(), module ); if (module) NtUnmapViewOfSection( NtCurrentProcess(), module );
break; break;
} }
TRACE( "%s is a fake Wine dll\n", debugstr_us(&nt_name) ); TRACE( "%s is a fake Wine dll\n", debugstr_us(&nt_name) );
NtClose( handle );
NtUnmapViewOfSection( NtCurrentProcess(), module ); NtUnmapViewOfSection( NtCurrentProcess(), module );
/* fall through */ /* fall through */
@ -2661,7 +2629,6 @@ NTSTATUS WINAPI LdrGetDllHandle( LPCWSTR load_path, ULONG flags, const UNICODE_S
NTSTATUS status; NTSTATUS status;
UNICODE_STRING nt_name; UNICODE_STRING nt_name;
WINE_MODREF *wm; WINE_MODREF *wm;
HANDLE handle;
void *module; void *module;
pe_image_info_t image_info; pe_image_info_t image_info;
struct stat st; struct stat st;
@ -2670,8 +2637,7 @@ NTSTATUS WINAPI LdrGetDllHandle( LPCWSTR load_path, ULONG flags, const UNICODE_S
if (!load_path) load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer; if (!load_path) load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
status = find_dll_file( load_path, name->Buffer, &nt_name, &wm, &handle, &module, &image_info, &st ); status = find_dll_file( load_path, name->Buffer, &nt_name, &wm, &module, &image_info, &st );
if (handle) NtClose( handle );
if (wm) *base = wm->ldr.BaseAddress; if (wm) *base = wm->ldr.BaseAddress;
else else