Alexandre Julliard : kernel32: Move command line initialization to ntdll.

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


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Oct 22 10:17:14 2019 +0200

kernel32: Move command line initialization to ntdll.

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

---

 dlls/kernel32/process.c | 156 +-----------------------------------------------
 dlls/ntdll/env.c        |  86 ++++++++++++++++++++++++++
 2 files changed, 88 insertions(+), 154 deletions(-)

diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c
index cc76ad9d27..55630dc6dd 100644
--- a/dlls/kernel32/process.c
+++ b/dlls/kernel32/process.c
@@ -867,149 +867,6 @@ static void set_library_argv( WCHAR **wargv )
 }
 
 
-/***********************************************************************
- *           build_command_line
- *
- * Build the command line of a process from the argv array.
- *
- * Note that it does NOT necessarily include the file name.
- * Sometimes we don't even have any command line options at all.
- *
- * We must quote and escape characters so that the argv array can be rebuilt
- * from the command line:
- * - spaces and tabs must be quoted
- *   'a b'   -> '"a b"'
- * - quotes must be escaped
- *   '"'     -> '\"'
- * - if '\'s are followed by a '"', they must be doubled and followed by '\"',
- *   resulting in an odd number of '\' followed by a '"'
- *   '\"'    -> '\\\"'
- *   '\\"'   -> '\\\\\"'
- * - '\'s are followed by the closing '"' must be doubled,
- *   resulting in an even number of '\' followed by a '"'
- *   ' \'    -> '" \\"'
- *   ' \\'    -> '" \\\\"'
- * - '\'s that are not followed by a '"' can be left as is
- *   'a\b'   == 'a\b'
- *   'a\\b'  == 'a\\b'
- */
-static BOOL build_command_line( WCHAR **argv )
-{
-    int len;
-    WCHAR **arg;
-    LPWSTR p;
-    RTL_USER_PROCESS_PARAMETERS* rupp = NtCurrentTeb()->Peb->ProcessParameters;
-
-    if (rupp->CommandLine.Buffer) return TRUE; /* already got it from the server */
-
-    len = 0;
-    for (arg = argv; *arg; arg++)
-    {
-        BOOL has_space;
-        int bcount;
-        WCHAR* a;
-
-        has_space=FALSE;
-        bcount=0;
-        a=*arg;
-        if( arg == argv || !*a ) has_space=TRUE;
-        while (*a!='\0') {
-            if (*a=='\\') {
-                bcount++;
-            } else {
-                if (*a==' ' || *a=='\t') {
-                    has_space=TRUE;
-                } else if (*a=='"') {
-                    /* doubling of '\' preceding a '"',
-                     * plus escaping of said '"'
-                     */
-                    len+=2*bcount+1;
-                }
-                bcount=0;
-            }
-            a++;
-        }
-        len+=(a-*arg)+1 /* for the separating space */;
-        if (has_space)
-            len+=2+bcount; /* for the quotes and doubling of '\' preceding the closing quote */
-    }
-
-    if (!(rupp->CommandLine.Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR))))
-        return FALSE;
-
-    p = rupp->CommandLine.Buffer;
-    rupp->CommandLine.Length = (len - 1) * sizeof(WCHAR);
-    rupp->CommandLine.MaximumLength = len * sizeof(WCHAR);
-    for (arg = argv; *arg; arg++)
-    {
-        BOOL has_space,has_quote;
-        WCHAR* a;
-        int bcount;
-
-        /* Check for quotes and spaces in this argument */
-        has_space=has_quote=FALSE;
-        a=*arg;
-        if( arg == argv || !*a ) has_space=TRUE;
-        while (*a!='\0') {
-            if (*a==' ' || *a=='\t') {
-                has_space=TRUE;
-                if (has_quote)
-                    break;
-            } else if (*a=='"') {
-                has_quote=TRUE;
-                if (has_space)
-                    break;
-            }
-            a++;
-        }
-
-        /* Now transfer it to the command line */
-        if (has_space)
-            *p++='"';
-        if (has_quote || has_space) {
-            bcount=0;
-            a=*arg;
-            while (*a!='\0') {
-                if (*a=='\\') {
-                    *p++=*a;
-                    bcount++;
-                } else {
-                    if (*a=='"') {
-                        int i;
-
-                        /* Double all the '\\' preceding this '"', plus one */
-                        for (i=0;i<=bcount;i++)
-                            *p++='\\';
-                        *p++='"';
-                    } else {
-                        *p++=*a;
-                    }
-                    bcount=0;
-                }
-                a++;
-            }
-        } else {
-            WCHAR* x = *arg;
-            while ((*p=*x++)) p++;
-        }
-        if (has_space) {
-            int i;
-
-            /* Double all the '\' preceding the closing quote */
-            for (i=0;i<bcount;i++)
-                *p++='\\';
-            *p++='"';
-        }
-        *p++=' ';
-    }
-    if (p > rupp->CommandLine.Buffer)
-        p--;  /* remove last space */
-    *p = '\0';
-
-    return TRUE;
-}
-
-
 /***********************************************************************
  *           init_windows_dirs
  */
@@ -1182,20 +1039,14 @@ void * CDECL __wine_kernel_init(void)
     RtlSetUnhandledExceptionFilter( UnhandledExceptionFilter );
 
     LOCALE_Init();
+    init_windows_dirs();
+    boot_events[0] = boot_events[1] = 0;
 
     if (!peb->ProcessParameters->WindowTitle.Buffer)
     {
         /* convert old configuration to new format */
         convert_old_config();
         got_environment = has_registry_environment();
-    }
-
-    init_windows_dirs();
-    boot_events[0] = boot_events[1] = 0;
-
-    if (!peb->ProcessParameters->WindowTitle.Buffer)
-    {
-        if (!build_command_line( __wine_main_wargv )) goto error;
         start_wineboot( boot_events );
     }
 
@@ -1265,9 +1116,6 @@ void * CDECL __wine_kernel_init(void)
     if (!params->CurrentDirectory.Handle) chdir("/"); /* avoid locking removable devices */
 
     return start_process_wrapper;
-
- error:
-    ExitProcess( GetLastError() );
 }
 
 
diff --git a/dlls/ntdll/env.c b/dlls/ntdll/env.c
index 4fbe9a8411..ac0e2621ed 100644
--- a/dlls/ntdll/env.c
+++ b/dlls/ntdll/env.c
@@ -552,6 +552,91 @@ static void set_library_wargv( char **argv, const UNICODE_STRING *image )
 }
 
 
+/***********************************************************************
+ *           build_command_line
+ *
+ * Build the command line of a process from the argv array.
+ *
+ * Note that it does NOT necessarily include the file name.
+ * Sometimes we don't even have any command line options at all.
+ *
+ * We must quote and escape characters so that the argv array can be rebuilt
+ * from the command line:
+ * - spaces and tabs must be quoted
+ *   'a b'   -> '"a b"'
+ * - quotes must be escaped
+ *   '"'     -> '\"'
+ * - if '\'s are followed by a '"', they must be doubled and followed by '\"',
+ *   resulting in an odd number of '\' followed by a '"'
+ *   '\"'    -> '\\\"'
+ *   '\\"'   -> '\\\\\"'
+ * - '\'s are followed by the closing '"' must be doubled,
+ *   resulting in an even number of '\' followed by a '"'
+ *   ' \'    -> '" \\"'
+ *   ' \\'    -> '" \\\\"'
+ * - '\'s that are not followed by a '"' can be left as is
+ *   'a\b'   == 'a\b'
+ *   'a\\b'  == 'a\\b'
+ */
+static void build_command_line( WCHAR **argv, UNICODE_STRING *cmdline )
+{
+    int len;
+    WCHAR **arg;
+    LPWSTR p;
+
+    len = 1;
+    for (arg = argv; *arg; arg++) len += 3 + 2 * strlenW( *arg );
+    cmdline->MaximumLength = len * sizeof(WCHAR);
+    if (!(cmdline->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, cmdline->MaximumLength ))) return;
+
+    p = cmdline->Buffer;
+    for (arg = argv; *arg; arg++)
+    {
+        BOOL has_space, has_quote;
+        int i, bcount;
+        WCHAR *a;
+
+        /* check for quotes and spaces in this argument */
+        if (arg == argv || !**arg) has_space = TRUE;
+        else has_space = strchrW( *arg, ' ' ) || strchrW( *arg, '\t' );
+        has_quote = strchrW( *arg, '"' ) != NULL;
+
+        /* now transfer it to the command line */
+        if (has_space) *p++ = '"';
+        if (has_quote || has_space)
+        {
+            bcount = 0;
+            for (a = *arg; *a; a++)
+            {
+                if (*a == '\\') bcount++;
+                else
+                {
+                    if (*a == '"') /* double all the '\\' preceding this '"', plus one */
+                        for (i = 0; i <= bcount; i++) *p++ = '\\';
+                    bcount = 0;
+                }
+                *p++ = *a;
+            }
+        }
+        else
+        {
+            strcpyW( p, *arg );
+            p += strlenW( p );
+        }
+        if (has_space)
+        {
+            /* Double all the '\' preceding the closing quote */
+            for (i = 0; i < bcount; i++) *p++ = '\\';
+            *p++ = '"';
+        }
+        *p++ = ' ';
+    }
+    if (p > cmdline->Buffer) p--;  /* remove last space */
+    *p = 0;
+    cmdline->Length = (p - cmdline->Buffer) * sizeof(WCHAR);
+}
+
+
 /******************************************************************************
  *  NtQuerySystemEnvironmentValue		[NTDLL.@]
  */
@@ -1074,6 +1159,7 @@ void init_user_process_params( SIZE_T data_size )
         get_current_directory( &params->CurrentDirectory.DosPath );
         get_image_path( __wine_main_argv[0], &params->ImagePathName );
         set_library_wargv( __wine_main_argv, &params->ImagePathName );
+        build_command_line( __wine_main_wargv, &params->CommandLine );
 
         if (isatty(0) || isatty(1) || isatty(2))
             params->ConsoleHandle = (HANDLE)2; /* see kernel32/kernel_private.h */




More information about the wine-cvs mailing list