Module: wine Branch: master Commit: c946922a9cc17929dc121b0d4c0895cf57010753 URL: https://source.winehq.org/git/wine.git/?a=commit;h=c946922a9cc17929dc121b0d4...
Author: Alexandre Julliard julliard@winehq.org Date: Fri Feb 8 19:58:40 2019 +0100
ntdll: Directly try to open the dll file instead of checking for existence first.
Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/kernel32/tests/module.c | 25 ++++-------- dlls/ntdll/loader.c | 94 ++++++++++++++++++++------------------------ 2 files changed, 50 insertions(+), 69 deletions(-)
diff --git a/dlls/kernel32/tests/module.c b/dlls/kernel32/tests/module.c index 2314c84..3e077f3 100644 --- a/dlls/kernel32/tests/module.c +++ b/dlls/kernel32/tests/module.c @@ -336,32 +336,23 @@ static void testLoadLibraryEx(void) SetLastError(0xdeadbeef); hmodule = LoadLibraryExA("testfile.dll", hfile, 0); ok(hmodule == 0, "Expected 0, got %p\n", hmodule); - todo_wine - { - ok(GetLastError() == ERROR_SHARING_VIOLATION || - GetLastError() == ERROR_INVALID_PARAMETER, /* win2k3 */ - "Unexpected last error, got %d\n", GetLastError()); - } + ok(GetLastError() == ERROR_SHARING_VIOLATION || + GetLastError() == ERROR_INVALID_PARAMETER, /* win2k3 */ + "Unexpected last error, got %d\n", GetLastError());
SetLastError(0xdeadbeef); hmodule = LoadLibraryExA("testfile.dll", (HANDLE)0xdeadbeef, 0); ok(hmodule == 0, "Expected 0, got %p\n", hmodule); - todo_wine - { - ok(GetLastError() == ERROR_SHARING_VIOLATION || - GetLastError() == ERROR_INVALID_PARAMETER, /* win2k3 */ - "Unexpected last error, got %d\n", GetLastError()); - } + ok(GetLastError() == ERROR_SHARING_VIOLATION || + GetLastError() == ERROR_INVALID_PARAMETER, /* win2k3 */ + "Unexpected last error, got %d\n", GetLastError());
/* try to open a file that is locked */ SetLastError(0xdeadbeef); hmodule = LoadLibraryExA("testfile.dll", NULL, 0); ok(hmodule == 0, "Expected 0, got %p\n", hmodule); - todo_wine - { - ok(GetLastError() == ERROR_SHARING_VIOLATION, - "Expected ERROR_SHARING_VIOLATION, got %d\n", GetLastError()); - } + ok(GetLastError() == ERROR_SHARING_VIOLATION, + "Expected ERROR_SHARING_VIOLATION, got %d\n", GetLastError());
/* lpFileName does not matter */ if (is_unicode_enabled) diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 701692a..2c93b02 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -2345,14 +2345,19 @@ done: * * Open a file for a new dll. Helper for find_dll_file. */ -static HANDLE open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, struct stat *st ) +static NTSTATUS open_dll_file( const WCHAR *name, UNICODE_STRING *nt_name, + WINE_MODREF **pwm, HANDLE *handle, struct stat *st ) { + FILE_BASIC_INFORMATION info; OBJECT_ATTRIBUTES attr; IO_STATUS_BLOCK io; - HANDLE handle; + NTSTATUS status; int fd, needs_close;
- if ((*pwm = find_fullname_module( nt_name ))) return 0; + nt_name->Buffer = NULL; + if ((status = RtlDosPathNameToNtPathName_U_WithStatus( name, nt_name, NULL, NULL ))) return status; + + if ((*pwm = find_fullname_module( nt_name ))) return STATUS_SUCCESS;
attr.Length = sizeof(attr); attr.RootDirectory = 0; @@ -2360,11 +2365,22 @@ static HANDLE open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, struct attr.ObjectName = nt_name; attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL; - if (NtOpenFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_DELETE, - FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE )) - return 0; + if ((status = NtOpenFile( handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, + FILE_SHARE_READ | FILE_SHARE_DELETE, + FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE ))) + { + if (status != STATUS_OBJECT_PATH_NOT_FOUND && + status != STATUS_OBJECT_NAME_NOT_FOUND && + !NtQueryAttributesFile( &attr, &info )) + { + /* if the file exists but failed to open, report the error */ + return status; + } + /* otherwise continue searching */ + 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 ); if (needs_close) close( fd ); @@ -2372,11 +2388,11 @@ static HANDLE open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, struct { 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; + NtClose( *handle ); + *handle = 0; } } - return handle; + return STATUS_SUCCESS; }
@@ -2385,7 +2401,8 @@ static HANDLE open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, struct * * 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, struct stat *st ) { WCHAR *name; NTSTATUS status = STATUS_DLL_NOT_FOUND; @@ -2407,14 +2424,9 @@ static NTSTATUS search_dll_file( LPCWSTR paths, LPCWSTR search, UNICODE_STRING * memcpy( name, paths, len * sizeof(WCHAR) ); if (len && name[len - 1] != '\') name[len++] = '\'; strcpyW( name + len, search ); - if (RtlDoesFileExists_U( name )) - { - if (!RtlDosPathNameToNtPathName_U( name, nt_name, NULL, NULL )) - status = STATUS_NO_MEMORY; - else - status = STATUS_SUCCESS; - goto done; - } + status = open_dll_file( name, nt_name, pwm, handle, st ); + if (status != STATUS_DLL_NOT_FOUND) goto done; + RtlFreeUnicodeString( nt_name ); paths = ptr; }
@@ -2439,11 +2451,12 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, HANDLE *handle, struct stat *st ) { WCHAR *ext, *dllname; - NTSTATUS status; + NTSTATUS status = STATUS_SUCCESS;
/* first append .dll if needed */
*handle = 0; + *pwm = NULL; dllname = NULL; if (!(ext = strrchrW( libname, '.')) || strchrW( ext, '/' ) || strchrW( ext, '\')) { @@ -2461,7 +2474,7 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, { WCHAR *fullname = NULL;
- if ((*pwm = find_basename_module( libname )) != NULL) goto found; + if ((*pwm = find_basename_module( libname )) != NULL) goto done;
status = find_actctx_dll( libname, &fullname ); if (status == STATUS_SUCCESS) @@ -2470,40 +2483,17 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, RtlFreeHeap( GetProcessHeap(), 0, dllname ); libname = dllname = fullname; } - else if (status != STATUS_SXS_KEY_NOT_FOUND) - { - RtlFreeHeap( GetProcessHeap(), 0, dllname ); - return status; - } + else if (status != STATUS_SXS_KEY_NOT_FOUND) goto done; }
if (RtlDetermineDosPathNameType_U( libname ) == RELATIVE_PATH) - { - /* we need to search for it */ - if (!(status = search_dll_file( load_path, libname, nt_name ))) - { - *handle = open_dll_file( nt_name, pwm, st ); - } - else if (status != STATUS_DLL_NOT_FOUND) - { - RtlFreeHeap( GetProcessHeap(), 0, dllname ); - return status; - } - goto found; - } - - /* absolute path name */ - - if (!RtlDosPathNameToNtPathName_U( libname, nt_name, NULL, NULL )) - { - RtlFreeHeap( GetProcessHeap(), 0, dllname ); - return STATUS_NO_MEMORY; - } - *handle = open_dll_file( nt_name, pwm, st ); + status = search_dll_file( load_path, libname, nt_name, pwm, handle, st ); + else + status = open_dll_file( libname, nt_name, pwm, handle, st );
-found: +done: RtlFreeHeap( GetProcessHeap(), 0, dllname ); - return STATUS_SUCCESS; + return status; }
@@ -2524,9 +2514,8 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_
TRACE( "looking for %s in %s\n", debugstr_w(libname), debugstr_w(load_path) );
- *pwm = NULL; nts = find_dll_file( load_path, libname, &nt_name, pwm, &handle, &st ); - if (nts) return nts; + if (nts && nts != STATUS_DLL_NOT_FOUND) goto done;
if (*pwm) /* found already loaded module */ { @@ -2591,6 +2580,7 @@ static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_ break; }
+done: if (nts == STATUS_SUCCESS) TRACE("Loaded module %s (%s) at %p\n", debugstr_us(&nt_name), ((*pwm)->ldr.Flags & LDR_WINE_INTERNAL) ? "builtin" : "native", (*pwm)->ldr.BaseAddress);