Alexandre Julliard : ntdll: Directly try to open the dll file instead of checking for existence first.
Alexandre Julliard
julliard at winehq.org
Mon Feb 11 16:12:11 CST 2019
Module: wine
Branch: master
Commit: c946922a9cc17929dc121b0d4c0895cf57010753
URL: https://source.winehq.org/git/wine.git/?a=commit;h=c946922a9cc17929dc121b0d4c0895cf57010753
Author: Alexandre Julliard <julliard at 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 at 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);
More information about the wine-cvs
mailing list