Alexandre Julliard : kernel32: Move exe path functions to ntdll.

Alexandre Julliard julliard at winehq.org
Thu Oct 3 16:44:00 CDT 2019


Module: wine
Branch: master
Commit: a5d45e9ae5a6a88f859c1ca1f05b4c93a0817103
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=a5d45e9ae5a6a88f859c1ca1f05b4c93a0817103

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Oct  3 19:26:01 2019 +0200

kernel32: Move exe path functions to ntdll.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/kernel32/process.c    | 19 ++++++++----
 dlls/kernel32/tests/path.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++
 dlls/ntdll/loader.c        | 25 ++++++++++++++++
 dlls/ntdll/ntdll.spec      |  1 +
 include/winternl.h         |  1 +
 5 files changed, 116 insertions(+), 5 deletions(-)

diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c
index 3aae3d129e..d2682ac83e 100644
--- a/dlls/kernel32/process.c
+++ b/dlls/kernel32/process.c
@@ -438,11 +438,18 @@ static HANDLE open_exe_file( const WCHAR *name, BOOL *is_64bit )
  */
 static BOOL find_exe_file( const WCHAR *name, WCHAR *buffer, int buflen, HANDLE *handle )
 {
-    TRACE("looking for %s\n", debugstr_w(name) );
+    WCHAR *load_path;
+    BOOL ret;
+
+    if (!set_ntstatus( RtlGetExePath( name, &load_path ))) return FALSE;
+
+    TRACE("looking for %s in %s\n", debugstr_w(name), debugstr_w(load_path) );
 
-    if (!SearchPathW( NULL, name, exeW, buflen, buffer, NULL ) &&
-        /* no builtin found, try native without extension in case it is a Unix app */
-        !SearchPathW( NULL, name, NULL, buflen, buffer, NULL )) return FALSE;
+    ret = (SearchPathW( load_path, name, exeW, buflen, buffer, NULL ) ||
+           /* no builtin found, try native without extension in case it is a Unix app */
+           SearchPathW( load_path, name, NULL, buflen, buffer, NULL ));
+    RtlReleasePath( load_path );
+    if (!ret) return FALSE;
 
     TRACE( "Trying native exe %s\n", debugstr_w(buffer) );
     *handle = CreateFileW( buffer, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE,
@@ -1412,12 +1419,14 @@ void * CDECL __wine_kernel_init(void)
     {
         BOOL is_64bit;
 
-        if (!SearchPathW( NULL, __wine_main_wargv[0], exeW, MAX_PATH, main_exe_name, NULL ) &&
+        RtlGetExePath( __wine_main_wargv[0], &load_path );
+        if (!SearchPathW( load_path, __wine_main_wargv[0], exeW, MAX_PATH, main_exe_name, NULL ) &&
             !get_builtin_path( __wine_main_wargv[0], exeW, main_exe_name, MAX_PATH, &is_64bit ))
         {
             MESSAGE( "wine: cannot find '%s'\n", __wine_main_argv[0] );
             ExitProcess( GetLastError() );
         }
+        RtlReleasePath( load_path );
         update_library_argv0( main_exe_name );
         if (!build_command_line( __wine_main_wargv )) goto error;
         start_wineboot( boot_events );
diff --git a/dlls/kernel32/tests/path.c b/dlls/kernel32/tests/path.c
index 1610370064..71577793b0 100644
--- a/dlls/kernel32/tests/path.c
+++ b/dlls/kernel32/tests/path.c
@@ -78,6 +78,7 @@ static BOOL     (WINAPI *pRemoveDllDirectory)(DLL_DIRECTORY_COOKIE);
 static BOOL     (WINAPI *pSetSearchPathMode)(DWORD);
 static BOOL     (WINAPI *pSetDllDirectoryW)(LPCWSTR);
 static BOOL     (WINAPI *pSetDefaultDllDirectories)(DWORD);
+static NTSTATUS (WINAPI *pRtlGetExePath)(LPCWSTR,LPWSTR*);
 static NTSTATUS (WINAPI *pRtlGetSearchPath)(LPWSTR*);
 static void     (WINAPI *pRtlReleasePath)(LPWSTR);
 static NTSTATUS (WINAPI *pLdrGetDllPath)(LPCWSTR,ULONG,LPWSTR*,LPWSTR*);
@@ -2218,6 +2219,7 @@ static void init_pointers(void)
     MAKEFUNC(CheckNameLegalDOS8Dot3A);
     mod = GetModuleHandleA("ntdll.dll");
     MAKEFUNC(LdrGetDllPath);
+    MAKEFUNC(RtlGetExePath);
     MAKEFUNC(RtlGetSearchPath);
     MAKEFUNC(RtlReleasePath);
 #undef MAKEFUNC
@@ -2570,6 +2572,78 @@ static void test_RtlGetSearchPath(void)
     SetEnvironmentVariableW( pathW, old_path );
 }
 
+static void test_RtlGetExePath(void)
+{
+    static const WCHAR fooW[] = {'\\','f','o','o',0};
+    static const WCHAR emptyW[1];
+    NTSTATUS ret;
+    WCHAR *path;
+    WCHAR buffer[2048], old_path[2048], dlldir[4];
+
+    if (!pRtlGetExePath)
+    {
+        win_skip( "RtlGetExePath isn't available\n" );
+        return;
+    }
+
+    GetEnvironmentVariableW( pathW, old_path, ARRAY_SIZE(old_path) );
+    GetWindowsDirectoryW( buffer, ARRAY_SIZE(buffer) );
+    lstrcpynW( dlldir, buffer, ARRAY_SIZE(dlldir) );
+    SetEnvironmentVariableA( "NoDefaultCurrentDirectoryInExePath", NULL );
+
+    build_search_path( buffer, ARRAY_SIZE(buffer), NULL, FALSE );
+    path = (WCHAR *)0xdeadbeef;
+    ret = pRtlGetExePath( fooW, &path );
+    ok( !ret, "RtlGetExePath failed %x\n", ret );
+    ok( path_equal( path, buffer ), "got %s expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(buffer));
+    pRtlReleasePath( path );
+
+    build_search_path( buffer, ARRAY_SIZE(buffer), NULL, FALSE );
+    path = (WCHAR *)0xdeadbeef;
+    ret = pRtlGetExePath( fooW + 1, &path );
+    ok( !ret, "RtlGetExePath failed %x\n", ret );
+    ok( path_equal( path, buffer ), "got %s expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(buffer));
+    pRtlReleasePath( path );
+
+    SetEnvironmentVariableA( "NoDefaultCurrentDirectoryInExePath", "yes" );
+
+    build_search_path( buffer, ARRAY_SIZE(buffer), NULL, FALSE );
+    path = (WCHAR *)0xdeadbeef;
+    ret = pRtlGetExePath( fooW, &path );
+    ok( !ret, "RtlGetExePath failed %x\n", ret );
+    ok( path_equal( path, buffer ), "got %s expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(buffer));
+    pRtlReleasePath( path );
+
+    build_search_path( buffer, ARRAY_SIZE(buffer), emptyW, TRUE );
+    path = (WCHAR *)0xdeadbeef;
+    ret = pRtlGetExePath( fooW + 1, &path );
+    ok( !ret, "RtlGetExePath failed %x\n", ret );
+    ok( path_equal( path, buffer ), "got %s expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(buffer));
+    pRtlReleasePath( path );
+
+    SetEnvironmentVariableA( "PATH", "foo" );
+    build_search_path( buffer, ARRAY_SIZE(buffer), NULL, FALSE );
+    path = (WCHAR *)0xdeadbeef;
+    ret = pRtlGetExePath( fooW, &path );
+    ok( !ret, "RtlGetExePath failed %x\n", ret );
+    ok( path_equal( path, buffer ), "got %s expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(buffer));
+    pRtlReleasePath( path );
+
+    if (pSetDllDirectoryW)
+    {
+        ok( pSetDllDirectoryW( dlldir ), "SetDllDirectoryW failed\n" );
+        build_search_path( buffer, ARRAY_SIZE(buffer), NULL, FALSE );
+        path = (WCHAR *)0xdeadbeef;
+        ret = pRtlGetExePath( fooW, &path );
+        ok( !ret, "RtlGetExePath failed %x\n", ret );
+        ok( path_equal( path, buffer ), "got %s expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(buffer));
+        pRtlReleasePath( path );
+        pSetDllDirectoryW( NULL );
+    }
+
+    SetEnvironmentVariableW( pathW, old_path );
+}
+
 static void test_LdrGetDllPath(void)
 {
     static const WCHAR fooW[] = {'f','o','o',0};
@@ -2705,5 +2779,6 @@ START_TEST(path)
     test_CheckNameLegalDOS8Dot3();
     test_SetSearchPathMode();
     test_RtlGetSearchPath();
+    test_RtlGetExePath();
     test_LdrGetDllPath();
 }
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 4b528b5ea8..5eacc5a23c 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -4132,6 +4132,31 @@ NTSTATUS WINAPI RtlSetSearchPathMode( ULONG flags )
 }
 
 
+/******************************************************************
+ *           RtlGetExePath   (NTDLL.@)
+ */
+NTSTATUS WINAPI RtlGetExePath( PCWSTR name, PWSTR *path )
+{
+    static const WCHAR emptyW[1];
+    const WCHAR *dlldir = dotW;
+    const WCHAR *module = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer;
+
+    /* same check as NeedCurrentDirectoryForExePathW */
+    if (!strchrW( name, '\\' ))
+    {
+        static const WCHAR env_name[] = {'N','o','D','e','f','a','u','l','t','C','u','r','r','e','n','t',
+                                         'D','i','r','e','c','t','o','r','y','I','n',
+                                         'E','x','e','P','a','t','h',0};
+        UNICODE_STRING name, value = { 0 };
+
+        RtlInitUnicodeString( &name, env_name );
+        if (RtlQueryEnvironmentVariable_U( NULL, &name, &value ) != STATUS_VARIABLE_NOT_FOUND)
+            dlldir = emptyW;
+    }
+    return get_dll_load_path( module, dlldir, FALSE, path );
+}
+
+
 /******************************************************************
  *           RtlGetSearchPath   (NTDLL.@)
  */
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index c33f12121b..3dd184d8c7 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -687,6 +687,7 @@
 @ stdcall RtlGetDaclSecurityDescriptor(ptr ptr ptr ptr)
 @ stub RtlGetElementGenericTable
 # @ stub RtlGetElementGenericTableAvl
+@ stdcall RtlGetExePath(wstr ptr)
 # @ stub RtlGetFirstRange
 @ stdcall RtlGetFrame()
 @ stdcall RtlGetFullPathName_U(wstr long ptr ptr)
diff --git a/include/winternl.h b/include/winternl.h
index 95105c67b4..16df963770 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -2724,6 +2724,7 @@ NTSYSAPI NTSTATUS  WINAPI RtlGetControlSecurityDescriptor(PSECURITY_DESCRIPTOR,
 NTSYSAPI ULONG     WINAPI RtlGetCurrentDirectory_U(ULONG, LPWSTR);
 NTSYSAPI PEB *     WINAPI RtlGetCurrentPeb(void);
 NTSYSAPI NTSTATUS  WINAPI RtlGetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR,PBOOLEAN,PACL *,PBOOLEAN);
+NTSYSAPI NTSTATUS  WINAPI RtlGetExePath(PCWSTR,PWSTR*);
 NTSYSAPI TEB_ACTIVE_FRAME * WINAPI RtlGetFrame(void);
 NTSYSAPI ULONG     WINAPI RtlGetFullPathName_U(PCWSTR,ULONG,PWSTR,PWSTR*);
 NTSYSAPI NTSTATUS  WINAPI RtlGetGroupSecurityDescriptor(PSECURITY_DESCRIPTOR,PSID *,PBOOLEAN);




More information about the wine-cvs mailing list