Alexandre Julliard : kernel32: Move current directory initialization to ntdll.

Alexandre Julliard julliard at winehq.org
Tue Oct 22 16:57:00 CDT 2019


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Oct 22 09:58:32 2019 +0200

kernel32: Move current directory initialization to ntdll.

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

---

 dlls/kernel32/process.c | 73 ---------------------------------------
 dlls/ntdll/env.c        | 92 +++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 89 insertions(+), 76 deletions(-)

diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c
index 5cb470e0c7..a60aad6721 100644
--- a/dlls/kernel32/process.c
+++ b/dlls/kernel32/process.c
@@ -1085,78 +1085,6 @@ static BOOL build_command_line( WCHAR **argv )
 }
 
 
-/***********************************************************************
- *           init_current_directory
- *
- * Initialize the current directory from the Unix cwd or the parent info.
- */
-static void init_current_directory( CURDIR *cur_dir )
-{
-    UNICODE_STRING dir_str;
-    const char *pwd;
-    char *cwd;
-    int size;
-
-    /* if we received a cur dir from the parent, try this first */
-
-    if (cur_dir->DosPath.Length)
-    {
-        if (RtlSetCurrentDirectory_U( &cur_dir->DosPath ) == STATUS_SUCCESS) goto done;
-    }
-
-    /* now try to get it from the Unix cwd */
-
-    for (size = 256; ; size *= 2)
-    {
-        if (!(cwd = HeapAlloc( GetProcessHeap(), 0, size ))) break;
-        if (getcwd( cwd, size )) break;
-        HeapFree( GetProcessHeap(), 0, cwd );
-        if (errno == ERANGE) continue;
-        cwd = NULL;
-        break;
-    }
-
-    /* try to use PWD if it is valid, so that we don't resolve symlinks */
-
-    pwd = getenv( "PWD" );
-    if (cwd)
-    {
-        struct stat st1, st2;
-
-        if (!pwd || stat( pwd, &st1 ) == -1 ||
-            (!stat( cwd, &st2 ) && (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)))
-            pwd = cwd;
-    }
-
-    if (pwd)
-    {
-        ANSI_STRING unix_name;
-        UNICODE_STRING nt_name;
-        RtlInitAnsiString( &unix_name, pwd );
-        if (!wine_unix_to_nt_file_name( &unix_name, &nt_name ))
-        {
-            UNICODE_STRING dos_path;
-            /* skip the \??\ prefix, nt_name is 0 terminated */
-            RtlInitUnicodeString( &dos_path, nt_name.Buffer + 4 );
-            RtlSetCurrentDirectory_U( &dos_path );
-            RtlFreeUnicodeString( &nt_name );
-        }
-    }
-
-    if (!cur_dir->DosPath.Length)  /* still not initialized */
-    {
-        MESSAGE("Warning: could not find DOS drive for current working directory '%s', "
-                "starting in the Windows directory.\n", cwd ? cwd : "" );
-        RtlInitUnicodeString( &dir_str, DIR_Windows );
-        RtlSetCurrentDirectory_U( &dir_str );
-    }
-    HeapFree( GetProcessHeap(), 0, cwd );
-
-done:
-    TRACE( "starting in %s %p\n", debugstr_w( cur_dir->DosPath.Buffer ), cur_dir->Handle );
-}
-
-
 /***********************************************************************
  *           init_windows_dirs
  */
@@ -1405,7 +1333,6 @@ void * CDECL __wine_kernel_init(void)
     }
 
     init_windows_dirs();
-    init_current_directory( &params->CurrentDirectory );
 
     set_process_name( __wine_main_argc, __wine_main_argv );
     set_library_wargv( __wine_main_argv );
diff --git a/dlls/ntdll/env.c b/dlls/ntdll/env.c
index 724faf0b8f..7b5f370083 100644
--- a/dlls/ntdll/env.c
+++ b/dlls/ntdll/env.c
@@ -21,7 +21,12 @@
 #include "config.h"
 
 #include <assert.h>
+#include <errno.h>
 #include <stdarg.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
 #endif
@@ -41,6 +46,8 @@ static WCHAR empty[] = {0};
 static const UNICODE_STRING empty_str = { 0, sizeof(empty), empty };
 static const UNICODE_STRING null_str = { 0, 0, NULL };
 
+static const WCHAR windows_dir[] = {'C',':','\\','w','i','n','d','o','w','s',0};
+
 static inline SIZE_T get_env_length( const WCHAR *env )
 {
     const WCHAR *end = env;
@@ -48,6 +55,77 @@ static inline SIZE_T get_env_length( const WCHAR *env )
     return end + 1 - env;
 }
 
+/***********************************************************************
+ *           get_current_directory
+ *
+ * Initialize the current directory from the Unix cwd.
+ */
+static void get_current_directory( UNICODE_STRING *dir )
+{
+    const char *pwd;
+    char *cwd;
+    int size;
+
+    dir->Length = 0;
+
+    /* try to get it from the Unix cwd */
+
+    for (size = 1024; ; size *= 2)
+    {
+        if (!(cwd = RtlAllocateHeap( GetProcessHeap(), 0, size ))) break;
+        if (getcwd( cwd, size )) break;
+        RtlFreeHeap( GetProcessHeap(), 0, cwd );
+        if (errno == ERANGE) continue;
+        cwd = NULL;
+        break;
+    }
+
+    /* try to use PWD if it is valid, so that we don't resolve symlinks */
+
+    pwd = getenv( "PWD" );
+    if (cwd)
+    {
+        struct stat st1, st2;
+
+        if (!pwd || stat( pwd, &st1 ) == -1 ||
+            (!stat( cwd, &st2 ) && (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)))
+            pwd = cwd;
+    }
+
+    if (pwd)
+    {
+        ANSI_STRING unix_name;
+        UNICODE_STRING nt_name;
+
+        RtlInitAnsiString( &unix_name, pwd );
+        if (!wine_unix_to_nt_file_name( &unix_name, &nt_name ))
+        {
+            /* skip the \??\ prefix */
+            dir->Length = nt_name.Length - 4 * sizeof(WCHAR);
+            memcpy( dir->Buffer, nt_name.Buffer + 4, dir->Length );
+            RtlFreeUnicodeString( &nt_name );
+        }
+    }
+
+    if (!dir->Length)  /* still not initialized */
+    {
+        MESSAGE("Warning: could not find DOS drive for current working directory '%s', "
+                "starting in the Windows directory.\n", cwd ? cwd : "" );
+        dir->Length = strlenW( windows_dir ) * sizeof(WCHAR);
+        memcpy( dir->Buffer, windows_dir, dir->Length );
+    }
+    RtlFreeHeap( GetProcessHeap(), 0, cwd );
+
+    /* add trailing backslash */
+    if (dir->Buffer[dir->Length / sizeof(WCHAR) - 1] != '\\')
+    {
+        dir->Buffer[dir->Length / sizeof(WCHAR)] = '\\';
+        dir->Length += sizeof(WCHAR);
+    }
+    dir->Buffer[dir->Length / sizeof(WCHAR)] = 0;
+}
+
+
 /******************************************************************************
  *  NtQuerySystemEnvironmentValue		[NTDLL.@]
  */
@@ -554,7 +632,7 @@ void init_user_process_params( SIZE_T data_size )
     WCHAR *src;
     SIZE_T info_size, env_size;
     NTSTATUS status;
-    startup_info_t *info;
+    startup_info_t *info = NULL;
     RTL_USER_PROCESS_PARAMETERS *params = NULL;
     UNICODE_STRING curdir, dllpath, imagepath, cmdline, title, desktop, shellinfo, runtime;
 
@@ -566,6 +644,8 @@ void init_user_process_params( SIZE_T data_size )
             return;
 
         NtCurrentTeb()->Peb->ProcessParameters = params;
+        get_current_directory( &params->CurrentDirectory.DosPath );
+
         if (isatty(0) || isatty(1) || isatty(2))
             params->ConsoleHandle = (HANDLE)2; /* see kernel32/kernel_private.h */
         if (!isatty(0))
@@ -575,7 +655,7 @@ void init_user_process_params( SIZE_T data_size )
         if (!isatty(2))
             wine_server_fd_to_handle( 2, GENERIC_WRITE|SYNCHRONIZE, OBJ_INHERIT, &params->hStdError );
         params->wShowWindow = 1; /* SW_SHOWNORMAL */
-        return;
+        goto done;
     }
 
     if (!(info = RtlAllocateHeap( GetProcessHeap(), 0, data_size ))) return;
@@ -603,7 +683,6 @@ void init_user_process_params( SIZE_T data_size )
     get_unicode_string( &shellinfo, &src, info->shellinfo_len );
     get_unicode_string( &runtime, &src, info->runtime_len );
 
-    curdir.MaximumLength = MAX_PATH * sizeof(WCHAR);  /* current directory needs more space */
     runtime.MaximumLength = runtime.Length;  /* runtime info isn't a real string */
 
     if (RtlCreateProcessParametersEx( &params, &imagepath, &dllpath, &curdir, &cmdline, NULL,
@@ -637,6 +716,13 @@ void init_user_process_params( SIZE_T data_size )
 
 done:
     RtlFreeHeap( GetProcessHeap(), 0, info );
+    if (RtlSetCurrentDirectory_U( &params->CurrentDirectory.DosPath ))
+    {
+        MESSAGE("wine: could not open working directory %s, starting in the Windows directory.\n",
+                debugstr_w( params->CurrentDirectory.DosPath.Buffer ));
+        RtlInitUnicodeString( &curdir, windows_dir );
+        RtlSetCurrentDirectory_U( &curdir );
+    }
 }
 
 




More information about the wine-cvs mailing list