Bas Weelinck : cmd: Detect and handle start console title.

Alexandre Julliard julliard at winehq.org
Wed May 17 15:58:30 CDT 2017


Module: wine
Branch: master
Commit: 9baceabb88e2aeb90a32bb5f6923107904ed58ea
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=9baceabb88e2aeb90a32bb5f6923107904ed58ea

Author: Bas Weelinck <bas.weelinck at gmail.com>
Date:   Mon May  8 18:28:28 2017 +0200

cmd: Detect and handle start console title.

Signed-off-by: Bas Weelinck <bas.weelinck at gmail.com>
Signed-off-by: Vincent Povirk <vincent at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 programs/cmd/builtins.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++--
 programs/cmd/wcmd.h     |  2 +-
 2 files changed, 89 insertions(+), 4 deletions(-)

diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c
index 7301f54..1da1f67 100644
--- a/programs/cmd/builtins.c
+++ b/programs/cmd/builtins.c
@@ -4311,10 +4311,15 @@ void WCMD_shift (const WCHAR *args) {
 /****************************************************************************
  * WCMD_start
  */
-void WCMD_start(const WCHAR *args)
+void WCMD_start(WCHAR *args)
 {
     static const WCHAR exeW[] = {'\\','c','o','m','m','a','n','d',
                                  '\\','s','t','a','r','t','.','e','x','e',0};
+    static const WCHAR startDelims[] = { ' ', '\t', '/', '\0' };
+    static const WCHAR prefixQuote[] = {'"','\\','"','\0'};
+    static const WCHAR postfixQuote[] = {'\\','"','"','\0'};
+    int argno;
+    int have_title;
     WCHAR file[MAX_PATH];
     WCHAR *cmdline;
     STARTUPINFOW st;
@@ -4322,10 +4327,90 @@ void WCMD_start(const WCHAR *args)
 
     GetWindowsDirectoryW( file, MAX_PATH );
     strcatW( file, exeW );
-    cmdline = heap_alloc( (strlenW(file) + strlenW(args) + 2) * sizeof(WCHAR) );
+    cmdline = heap_alloc( (strlenW(file) + strlenW(args) + 8) * sizeof(WCHAR) );
     strcpyW( cmdline, file );
     strcatW( cmdline, spaceW );
-    strcatW( cmdline, args );
+
+    /* The start built-in has some special command-line parsing properties
+     * which will be outlined here.
+     *
+     * both '\t' and ' ' are argument separators
+     * '/' has a special double role as both separator and switch prefix, e.g.
+     *
+     * > start /low/i
+     * or
+     * > start "title"/i
+     *
+     * are valid ways to pass multiple options to start. In the latter case
+     * '/i' is not a part of the title but parsed as a switch.
+     *
+     * However, '=', ';' and ',' are not separators:
+     * > start "deus"=ex,machina
+     *
+     * will in fact open a console titled 'deus=ex,machina'
+     *
+     * The title argument parsing code is only interested in quotes themselves,
+     * it does not respect escaping of any kind and all quotes are dropped
+     * from the resulting title, therefore:
+     *
+     * > start "\"" hello"/low
+     *
+     * actually opens a console titled '\ hello' with low priorities.
+     *
+     * To not break compatibility with wine programs relying on
+     * wine's separate 'start.exe', this program's peculiar console
+     * title parsing is actually implemented in 'cmd.exe' which is the
+     * application native Windows programs will use to invoke 'start'.
+     *
+     * WCMD_parameter_with_delims will take care of everything for us.
+     */
+    have_title = FALSE;
+    for (argno=0; ; argno++) {
+        WCHAR *thisArg, *argN;
+
+        argN = NULL;
+        thisArg = WCMD_parameter_with_delims(args, argno, &argN, FALSE, FALSE, startDelims);
+
+        /* No more parameters */
+        if (!argN)
+            break;
+
+        /* Found the title */
+        if (argN[0] == '"') {
+            TRACE("detected console title: %s\n", wine_dbgstr_w(thisArg));
+            have_title = TRUE;
+
+            /* Copy all of the cmdline processed */
+            memcpy(cmdline, args, sizeof(WCHAR) * (argN - args));
+            cmdline[argN - args] = '\0';
+
+            /* Add quoted title */
+            strcatW(cmdline, prefixQuote);
+            strcatW(cmdline, thisArg);
+            strcatW(cmdline, postfixQuote);
+
+            /* Concatenate remaining command-line */
+            thisArg = WCMD_parameter_with_delims(args, argno, &argN, TRUE, FALSE, startDelims);
+            strcatW(cmdline, argN + strlenW(thisArg));
+
+            break;
+        }
+
+        /* Skipping a regular argument? */
+        else if (argN != args && argN[-1] == '/') {
+            continue;
+
+        /* Not an argument nor the title, start of program arguments,
+         * stop looking for title.
+         */
+        } else
+            break;
+    }
+
+    /* build command-line if not built yet */
+    if (!have_title) {
+        strcatW( cmdline, args );
+    }
 
     memset( &st, 0, sizeof(STARTUPINFOW) );
     st.cb = sizeof(STARTUPINFOW);
diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h
index c135621..1180251 100644
--- a/programs/cmd/wcmd.h
+++ b/programs/cmd/wcmd.h
@@ -95,7 +95,7 @@ void WCMD_setshow_path (const WCHAR *args);
 void WCMD_setshow_prompt (void);
 void WCMD_setshow_time (void);
 void WCMD_shift (const WCHAR *args);
-void WCMD_start (const WCHAR *args);
+void WCMD_start (WCHAR *args);
 void WCMD_title (const WCHAR *);
 void WCMD_type (WCHAR *);
 void WCMD_verify (const WCHAR *args);




More information about the wine-cvs mailing list