[cmd] Fix parameterization around delimiters

Ann and Jason Edmeades jason at edmeades.me.uk
Tue Sep 25 05:07:31 CDT 2012


Prior to this patch, cmd.exe is seriously broke anywhere around the use of a
parameter with mixed quotes, e.g. c:\"program files"\filename, as well as in
various other ways.

[Fixes bug 22431, passed as full testbot job 21780]

FYI:

Investigations into a number of the remaining todos and bugs raised against
the
cmd shell shows how rubbish the parameter parsing currently is. In fact,
reading
the cmd.exe 'help' from windows 7 makes it much simpler, as it lists the
special
characters we therefore need to be careful of, and simple tests can show
which act
as delimiters.

Fixing the parameter parsing routine itself is quite simple (and as a side
effect,
probably makes it suitable for the 'for /f delims= support now when I get
there).

This patch:

- Ensures parameter parsing is on the delimiters windows uses for the
command shell
  which fixes various things like now supporting c:\"a b"\c type syntax,
fixing a
  number of to-do's

- Adds some tests specifically around parameterization (one todo as ^ isnt
implemented
  yet)

- Adds some tests specifically around parameters with mixed quote and
non-quotes

- Changes some for /f tests to todo's, as they previously only passed as a
side effect
  of the poor parameterization by nature of the way the tests are coded.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.winehq.org/pipermail/wine-patches/attachments/20120925/414afc0b/attachment-0001.html>
-------------- next part --------------
From 161ced8629ab2968b9782fec17d3b7df3f51bb92 Mon Sep 17 00:00:00 2001
From: Jason Edmeades <jason at edmeades.me.uk>
Date: Tue, 25 Sep 2012 11:01:27 +0100
Subject: [PATCH] [cmd] Fix parameterization around delimiters

Prior to this patch, cmd.exe is seriously broke anywhere around the use of a
parameter with mixed quotes, e.g. c:\"program files"\filename, as well as in
various other ways.

[Fixes bug 22431]

FYI:

Investigations into a number of the remaining todos and bugs raised against the
cmd shell shows how rubbish the parameter parsing currently is. In fact, reading
the cmd.exe 'help' from windows 7 makes it much simpler, as it lists the special
characters we therefore need to be careful of, and simple tests can show which act
as delimiters.

Fixing the parameter parsing routine itself is quite simple (and as a side effect,
probably makes it suitable for the 'for /f delims= support now when I get there).

This patch:

- Ensures parameter parsing is on the delimiters windows uses for the command shell
  which fixes various things like now supporting c:\"a b"\c type syntax, fixing a
  number of to-do's

- Adds some tests specifically around parameterization (one todo as ^ isnt implemented
  yet)

- Adds some tests specifically around parameters with mixed quote and non-quotes

- Changes some for /f tests to todo's, as they previously only passed as a side effect
  of the poor parameterization by nature of the way the tests are coded.
---
 programs/cmd/batch.c                     |   63 ++++++++++++++++++++++--------
 programs/cmd/builtins.c                  |   36 +++++++++--------
 programs/cmd/directory.c                 |    2 +-
 programs/cmd/tests/test_builtins.cmd     |   44 +++++++++++++++++++--
 programs/cmd/tests/test_builtins.cmd.exp |   59 ++++++++++++++++++++--------
 programs/cmd/wcmd.h                      |    2 +-
 programs/cmd/wcmdmain.c                  |    8 ++--
 7 files changed, 154 insertions(+), 60 deletions(-)

diff --git a/programs/cmd/batch.c b/programs/cmd/batch.c
index 7a735cf..d24b11e 100644
--- a/programs/cmd/batch.c
+++ b/programs/cmd/batch.c
@@ -117,9 +117,11 @@ void WCMD_batch (WCHAR *file, WCHAR *command, BOOL called, WCHAR *startLabel, HA
  *  n     [I] # of the parameter to return, counted from 0
  *  start [O] Optional. Pointer to the first char of param n in s
  *  end   [O] Optional. Pointer to the last char of param n in s
+ *  raw   [I] True to return the parameter in raw format (quotes maintainted)
+ *            False returns the parameter with quotes stripped
  *
  * RETURNS
- *  Success: The nth delimited parameter found in s, with any surrounding quotes removed
+ *  Success: The nth delimited parameter found in s
  *           if start != NULL, *start points to the start of the param
  *           if end != NULL, *end points to the end of the param
  *  Failure: An empty string if the param is not found.
@@ -128,40 +130,67 @@ void WCMD_batch (WCHAR *file, WCHAR *command, BOOL called, WCHAR *startLabel, HA
  * NOTES
  *  Return value is stored in static storage (i.e. overwritten after each call).
  *  Specify 'start' and/or 'end' to include delimiting double quotes as well, if any.
+ *  By default, the parameter is returned with quotes removed, ready for use with
+ *  other API calls, e.g. c:\"a b"\c is returned as c:\a b\c. However, some commands
+ *  need to preserve the exact syntax (echo, for, etc) hence the raw option.
  */
-WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **start, WCHAR **end)
+WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **start, WCHAR **end, BOOL raw)
 {
+    static const WCHAR defaultDelims[] = { ' ', '\t', ',', '=', ';', '\0' };
     int curParamNb = 0;
     static WCHAR param[MAX_PATH];
-    WCHAR *p = s, *q;
-    BOOL quotesDelimited;
+    WCHAR *p = s, *begin;
 
     if (start != NULL) *start = NULL;
     if (end != NULL) *end = NULL;
     param[0] = '\0';
+
     while (TRUE) {
-        while (*p && ((*p == ' ') || (*p == ',') || (*p == '=') || (*p == '\t')))
+
+        /* Absorb repeated word delimiters until we get to the next token (or the end!) */
+        while (*p && (strchrW(defaultDelims, *p) != NULL))
             p++;
         if (*p == '\0') return param;
 
-        quotesDelimited = (*p == '"');
+        /* If we have reached the token number we want, remember the beginning of it if it */
         if (start != NULL && curParamNb == n) *start = p;
 
-        if (quotesDelimited) {
-            q = ++p;
-            while (*p && *p != '"') p++;
-        } else {
-            q = p;
-            while (*p && (*p != ' ') && (*p != ',') && (*p != '=') && (*p != '\t'))
+        /* Return the whole word up to the next delimiter, handling quotes in the middle
+           of it, e.g. a"\b c\"d is a single parameter.                                  */
+        begin = p;
+
+        /* Loop character by character, but just need to special case quotes */
+        while (*p) {
+            /* Once we have found a delimiter, break */
+            if (strchrW(defaultDelims, *p) != NULL) break;
+
+            /* If we find a quote, copy until we get the end quote */
+            if (*p == '"') {
                 p++;
+                while (*p && *p != '"') p++;
+            }
+
+            /* Now skip the character / quote */
+            if (*p) p++;
         }
+
         if (curParamNb == n) {
-            memcpy(param, q, (p - q) * sizeof(WCHAR));
-            param[p-q] = '\0';
-            if (end) *end = p - 1 + quotesDelimited;
+            /* Return the parameter in static storage either as-is (raw) or
+               suitable for use with other win32 api calls (quotes stripped) */
+            if (raw) {
+                memcpy(param, begin, (p - begin) * sizeof(WCHAR));
+                param[p-begin] = '\0';
+            } else {
+                int i=0;
+                while (begin < p) {
+                  if (*begin != '"') param[i++] = *begin;
+                  begin++;
+                }
+                param[i] = '\0';
+            }
+            if (end) *end = p - 1;
             return param;
         }
-        if (quotesDelimited && *p == '"') p++;
         curParamNb++;
     }
 }
@@ -381,7 +410,7 @@ void WCMD_HandleTildaModifiers(WCHAR **start, const WCHAR *forVariable,
   } else if ((*lastModifier >= '1' && *lastModifier <= '9')) {
     strcpyW(outputparam,
             WCMD_parameter (context -> command, *lastModifier-'0' + context -> shift_count[*lastModifier-'0'],
-                            NULL, NULL));
+                            NULL, NULL, FALSE));
   } else {
     strcpyW(outputparam, forValue);
   }
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c
index 94c7171..ad9d40c 100644
--- a/programs/cmd/builtins.c
+++ b/programs/cmd/builtins.c
@@ -564,7 +564,7 @@ void WCMD_create_dir (WCHAR *command) {
     }
     /* Loop through all args */
     while (TRUE) {
-        WCHAR *thisArg = WCMD_parameter(command, argno++, &argN, NULL);
+        WCHAR *thisArg = WCMD_parameter(command, argno++, &argN, NULL, FALSE);
         if (!argN) break;
         if (!create_full_path(thisArg)) {
             WCMD_print_error ();
@@ -869,7 +869,7 @@ BOOL WCMD_delete (WCHAR *command) {
         WCHAR *thisArg;
 
         argN = NULL;
-        thisArg = WCMD_parameter (command, argno, &argN, NULL);
+        thisArg = WCMD_parameter (command, argno, &argN, NULL, FALSE);
         if (!argN)
             break;       /* no more parameters */
         if (argN[0] == '/')
@@ -1206,7 +1206,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
 
     WINE_TRACE("Processing for set %p\n", thisSet);
     i = 0;
-    while (*(item = WCMD_parameter (thisSet->command, i, &itemStart, NULL))) {
+    while (*(item = WCMD_parameter (thisSet->command, i, &itemStart, NULL, TRUE))) {
 
       /*
        * If the parameter within the set has a wildcard then search for matching files
@@ -1305,7 +1305,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
             while (WCMD_fgets(buffer, sizeof(buffer)/sizeof(WCHAR), input)) {
 
               /* Skip blank lines*/
-              parm = WCMD_parameter (buffer, 0, &where, NULL);
+              parm = WCMD_parameter (buffer, 0, &where, NULL, FALSE);
               WINE_TRACE("Parsed parameter: %s from %s\n", wine_dbgstr_w(parm),
                          wine_dbgstr_w(buffer));
 
@@ -1336,7 +1336,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
 
           /* Skip blank lines, and re-extract parameter now string has quotes removed */
           strcpyW(buffer, item);
-          parm = WCMD_parameter (buffer, 0, &where, NULL);
+          parm = WCMD_parameter (buffer, 0, &where, NULL, FALSE);
           WINE_TRACE("Parsed parameter: %s from %s\n", wine_dbgstr_w(parm),
                        wine_dbgstr_w(buffer));
 
@@ -1596,7 +1596,7 @@ void WCMD_if (WCHAR *p, CMD_LIST **cmdList) {
   WINE_TRACE("Condition: %s\n", wine_dbgstr_w(condition));
 
   if (!lstrcmpiW (condition, errlvlW)) {
-    WCHAR *param = WCMD_parameter(p, 1+negate, NULL, NULL);
+    WCHAR *param = WCMD_parameter(p, 1+negate, NULL, NULL, FALSE);
     WCHAR *endptr;
     long int param_int = strtolW(param, &endptr, 10);
     if (*endptr) {
@@ -1604,22 +1604,24 @@ void WCMD_if (WCHAR *p, CMD_LIST **cmdList) {
       return;
     }
     test = ((long int)errorlevel >= param_int);
-    WCMD_parameter(p, 2+negate, &command, NULL);
+    WCMD_parameter(p, 2+negate, &command, NULL, FALSE);
   }
   else if (!lstrcmpiW (condition, existW)) {
-    test = (GetFileAttributesW(WCMD_parameter(p, 1+negate, NULL, NULL)) != INVALID_FILE_ATTRIBUTES);
-    WCMD_parameter(p, 2+negate, &command, NULL);
+    test = (GetFileAttributesW(WCMD_parameter(p, 1+negate, NULL, NULL, FALSE))
+             != INVALID_FILE_ATTRIBUTES);
+    WCMD_parameter(p, 2+negate, &command, NULL, FALSE);
   }
   else if (!lstrcmpiW (condition, defdW)) {
-    test = (GetEnvironmentVariableW(WCMD_parameter(p, 1+negate, NULL, NULL), NULL, 0) > 0);
-    WCMD_parameter(p, 2+negate, &command, NULL);
+    test = (GetEnvironmentVariableW(WCMD_parameter(p, 1+negate, NULL, NULL, FALSE),
+                                    NULL, 0) > 0);
+    WCMD_parameter(p, 2+negate, &command, NULL, FALSE);
   }
   else if ((s = strstrW (p, eqeqW))) {
     /* We need to get potential surrounding double quotes, so param1/2 can't be used */
     WCHAR *leftPart, *leftPartEnd, *rightPart, *rightPartEnd;
     s += 2;
-    WCMD_parameter(p, 0+negate+caseInsensitive, &leftPart, &leftPartEnd);
-    WCMD_parameter(p, 1+negate+caseInsensitive, &rightPart, &rightPartEnd);
+    WCMD_parameter(p, 0+negate+caseInsensitive, &leftPart, &leftPartEnd, FALSE);
+    WCMD_parameter(p, 1+negate+caseInsensitive, &rightPart, &rightPartEnd, FALSE);
     test = caseInsensitive
             ? (CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
                               leftPart, leftPartEnd-leftPart+1,
@@ -1627,7 +1629,7 @@ void WCMD_if (WCHAR *p, CMD_LIST **cmdList) {
             : (CompareStringW(LOCALE_SYSTEM_DEFAULT, 0,
                               leftPart, leftPartEnd-leftPart+1,
                               rightPart, rightPartEnd-rightPart+1) == CSTR_EQUAL);
-    WCMD_parameter(s, 1, &command, NULL);
+    WCMD_parameter(s, 1, &command, NULL, FALSE);
   }
   else {
     WCMD_output_stderr(WCMD_LoadMessage(WCMD_SYNTAXERR));
@@ -1802,7 +1804,7 @@ void WCMD_remove_dir (WCHAR *command) {
 
   /* Loop through all args */
   while (argN) {
-    WCHAR *thisArg = WCMD_parameter (command, argno++, &argN, NULL);
+    WCHAR *thisArg = WCMD_parameter (command, argno++, &argN, NULL, FALSE);
     if (argN && argN[0] != '/') {
       WINE_TRACE("rd: Processing arg %s (quals:%s)\n", wine_dbgstr_w(thisArg),
                  wine_dbgstr_w(quals));
@@ -2564,7 +2566,7 @@ void WCMD_type (WCHAR *command) {
   /* Loop through all args */
   errorlevel = 0;
   while (argN) {
-    WCHAR *thisArg = WCMD_parameter (command, argno++, &argN, NULL);
+    WCHAR *thisArg = WCMD_parameter (command, argno++, &argN, NULL, FALSE);
 
     HANDLE h;
     WCHAR buffer[512];
@@ -2658,7 +2660,7 @@ void WCMD_more (WCHAR *command) {
     WCMD_enter_paged_mode(moreStrPage);
 
     while (argN) {
-      WCHAR *thisArg = WCMD_parameter (command, argno++, &argN, NULL);
+      WCHAR *thisArg = WCMD_parameter (command, argno++, &argN, NULL, FALSE);
       HANDLE h;
 
       if (!argN) break;
diff --git a/programs/cmd/directory.c b/programs/cmd/directory.c
index 52b998c..5f7746d 100644
--- a/programs/cmd/directory.c
+++ b/programs/cmd/directory.c
@@ -803,7 +803,7 @@ void WCMD_directory (WCHAR *cmd)
   prevEntry = NULL;
   while (argN) {
     WCHAR fullname[MAXSTRING];
-    WCHAR *thisArg = WCMD_parameter(cmd, argno++, &argN, NULL);
+    WCHAR *thisArg = WCMD_parameter(cmd, argno++, &argN, NULL, FALSE);
     if (argN && argN[0] != '/') {
 
       WINE_TRACE("Found parm '%s'\n", wine_dbgstr_w(thisArg));
diff --git a/programs/cmd/tests/test_builtins.cmd b/programs/cmd/tests/test_builtins.cmd
index 77086ed..444b6e6 100644
--- a/programs/cmd/tests/test_builtins.cmd
+++ b/programs/cmd/tests/test_builtins.cmd
@@ -67,6 +67,26 @@ type mixedEchoModes.cmd
 cmd /c mixedEchoModes.cmd
 del mixedEchoModes.cmd
 
+echo ------------ Testing parameterization ------------
+call :TestParm a b c
+call :TestParm "a b c"
+call :TestParm "a b"\c
+call :TestParm a=~`+,.{}!+b
+call :TestParm a;b
+call :TestParm "a;b"
+call :TestParm a^;b
+call :TestParm a[b]{c}(d)e
+call :TestParm a&echo second line
+call :TestParm a   b,,,c
+call :TestParm a==b;;c
+call :TestParm       a,,,  b
+goto :TestRem
+
+:TestParm
+echo '%1', '%2', '%3'
+goto :eof
+
+:TestRem
 echo ------------ Testing rem ------------
 rem Hello
 rem  Hello
@@ -110,6 +130,12 @@ echo foo11> foo
 type foo
 echo foo12> foo
 type foo
+echo foo13>"foo"
+type foo
+echo foo14>."\foo"
+type foo
+echo foo15>."\f"oo
+type foo
 del foo
 echo1>foo
 type foo
@@ -124,7 +150,7 @@ echo fooc 1>>foo
 type foo
 echo food1>>foo
 type foo
-echo food2>>foo
+echo food2>>"foo"
 type foo
 del foo
 echo food21>>foo
@@ -502,6 +528,12 @@ mkdir "bar bak"
 cd "bar bak"
 cd
 cd ..
+cd ".\bar bak"
+cd
+cd ..
+cd .\"bar bak"
+cd
+cd ..
 cd bar bak
 cd
 cd "bar bak at space@"@tab@@space@
@@ -522,7 +554,11 @@ type foobaz
 echo ---
 @echo off
 type foobaz at tab@
-echo ---
+echo ---1
+type ."\foobaz"
+echo ---2
+type ".\foobaz"
+echo ---3
 del foobaz
 
 echo ------------ Testing NUL ------------
@@ -1125,11 +1161,13 @@ if not exist foo (
 )
 echo --- multiple directories at once
 mkdir foobaz & cd foobaz
-mkdir foo bar\baz foobar
+mkdir foo bar\baz foobar "bazbaz" .\"zabzab"
 if exist foo (echo foo created) else echo foo not created!
 if exist bar (echo bar created) else echo bar not created!
 if exist foobar (echo foobar created) else echo foobar not created!
 if exist bar\baz (echo bar\baz created) else echo bar\baz not created!
+if exist bazbaz (echo bazbaz created) else echo bazbaz not created!
+if exist zabzab (echo zabzab created) else echo zabzab not created!
 cd .. & rd /s/q foobaz
 call :setError 0
 mkdir foo\*
diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp
index d0a4e1f..a4f874c 100644
--- a/programs/cmd/tests/test_builtins.cmd.exp
+++ b/programs/cmd/tests/test_builtins.cmd.exp
@@ -116,6 +116,20 @@ foo
 bar
 foo2
 bar2
+------------ Testing parameterization ------------
+'a', 'b', 'c'
+'"a b c"', '', ''
+'"a b"\c', '', ''
+'a', '~`+', '.{}!+b'
+'a', 'b', ''
+'"a;b"', '', ''
+ at todo_wine@'a', 'b', ''
+'a[b]{c}(d)e', '', ''
+'a', '', ''
+second line
+'a', 'b', 'c'
+'a', 'b', 'c'
+'a', 'b', ''
 ------------ Testing rem ------------
 
 @pwd@>rem Hello at space@
@@ -145,6 +159,9 @@ foo9 at space@@or_broken at foo@tab@
 foo1
 foo11
 foo12
+foo13
+foo14
+foo15
 --- stdout appending
 foo
 foo at space@
@@ -257,7 +274,7 @@ e at or_broken@qwerty
 r at or_broken@qwerty
 ------------ Testing variable substitution ------------
 --- in FOR variables
- at todo_wine@"A B"
+"A B"
 C
 'A B'@or_broken@''
 'C'@or_broken@''
@@ -291,19 +308,19 @@ N
 ''
 '.eh'
 --- in parameters
- at todo_wine@"A B"
+"A B"
 C
- at todo_wine@'A B'@or_broken@''
+'A B'@or_broken@''
 'C'@or_broken@''
- at todo_wine@@pwd@\C D
+ at pwd@\C D
 @pwd@\E
 @drive@
 @drive@
 @path@
 @path@
- at todo_wine@L M
+L M
 N
- at todo_wine@'.OOL'
+'.OOL'
 '.TABC'
 ''
 @todo_wine@'@drive@@shortpath at R S'@or_broken@''
@@ -364,6 +381,8 @@ Current dir: @pwd@\foobar at or_broken@Current dir:@space@
 @pwd@\foobar\bar bak
 @pwd@\foobar\bar bak
 @pwd@\foobar\bar bak
+ at pwd@\foobar\bar bak
+ at pwd@\foobar\bar bak
 @pwd@
 @pwd@\foobar
 ------------ Testing type ------------
@@ -374,7 +393,11 @@ bar
 @pwd@>echo --- at space@
 ---
 bar
----
+---1
+bar
+---2
+bar
+---3
 ------------ Testing NUL ------------
 bar
 bar
@@ -438,8 +461,8 @@ B`
 'echo
 A
 B'
- at todo_wine@"echo A B"
- at todo_wine@"A B"
+"echo A B"
+"A B"
 C
 --- imbricated FORs
 @todo_wine at X Y
@@ -565,11 +588,11 @@ ErrorLevel 0
 
 --- for /F
 ------ string argument
+ at todo_wine@a
+ at todo_wine@a
 a
-a
-a
-a
-a
+ at todo_wine@a
+ at todo_wine@a
 ------ fileset argument
 --------- basic blank handling
 a
@@ -682,6 +705,8 @@ foo created
 bar created
 foobar created
 bar\baz created
+bazbaz created
+zabzab created
 mkdir foo\* errorlevel 1
 ok, foo created
 ------------ Testing rmdir ------------
@@ -764,16 +789,16 @@ foo at space@
 foo 8
 foo at space@@space@
 foo bar at space@
- at todo_wine@foo ""@space@
- at todo_wine@"" bar at space@
+foo ""@space@
+"" bar at space@
 foo ''@space@
 '' bar at space@
 --- internal routines
 bar :testRoutine
 foo at space@
 foo bar
- at todo_wine@foo ""
- at todo_wine@"" bar
+foo ""
+"" bar
 foo ''
 '' bar
 --- with builtins
diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h
index 4e021d9..451c49b 100644
--- a/programs/cmd/wcmd.h
+++ b/programs/cmd/wcmd.h
@@ -107,7 +107,7 @@ static inline BOOL WCMD_is_console_handle(HANDLE h)
     return (((DWORD_PTR)h) & 3) == 3;
 }
 WCHAR *WCMD_fgets (WCHAR *buf, DWORD n, HANDLE stream);
-WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **start, WCHAR **end);
+WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **start, WCHAR **end, BOOL raw);
 WCHAR *WCMD_skip_leading_spaces (WCHAR *string);
 BOOL WCMD_keyword_ws_found(const WCHAR *keyword, int len, const WCHAR *ptr);
 void WCMD_HandleTildaModifiers(WCHAR **start, const WCHAR *forVariable, const WCHAR *forValue, BOOL justFors);
diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c
index f762b70..94d2b76 100644
--- a/programs/cmd/wcmdmain.c
+++ b/programs/cmd/wcmdmain.c
@@ -831,13 +831,13 @@ static void handleExpansion(WCHAR *cmd, BOOL justFors,
 
     /* Replace use of %0...%9 if in batch program*/
     } else if (!justFors && context && (i >= 0) && (i <= 9)) {
-      t = WCMD_parameter(context -> command, i + context -> shift_count[i], NULL, NULL);
+      t = WCMD_parameter(context -> command, i + context -> shift_count[i], NULL, NULL, TRUE);
       WCMD_strsubstW(p, p+2, t, -1);
 
     /* Replace use of %* if in batch program*/
     } else if (!justFors && context && *(p+1)=='*') {
       WCHAR *startOfParms = NULL;
-      WCMD_parameter(context -> command, 1, &startOfParms, NULL);
+      WCMD_parameter(context -> command, 1, &startOfParms, NULL, TRUE);
       if (startOfParms != NULL)
         WCMD_strsubstW(p, p+2, startOfParms, -1);
       else
@@ -1356,7 +1356,7 @@ void WCMD_execute (const WCHAR *command, const WCHAR *redirects,
 
     /* Otherwise STDIN could come from a '<' redirect */
     } else if ((p = strchrW(new_redir,'<')) != NULL) {
-      h = CreateFileW(WCMD_parameter(++p, 0, NULL, NULL), GENERIC_READ, FILE_SHARE_READ,
+      h = CreateFileW(WCMD_parameter(++p, 0, NULL, NULL, FALSE), GENERIC_READ, FILE_SHARE_READ,
                       &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
       if (h == INVALID_HANDLE_VALUE) {
 	WCMD_print_error ();
@@ -1401,7 +1401,7 @@ void WCMD_execute (const WCHAR *command, const WCHAR *redirects,
         WINE_TRACE("Redirect %d (%p) to %d (%p)\n", handle, GetStdHandle(idx_stdhandles[idx]), idx, h);
 
       } else {
-        WCHAR *param = WCMD_parameter(p, 0, NULL, NULL);
+        WCHAR *param = WCMD_parameter(p, 0, NULL, NULL, FALSE);
         h = CreateFileW(param, GENERIC_WRITE, 0, &sa, creationDisposition,
                         FILE_ATTRIBUTE_NORMAL, NULL);
         if (h == INVALID_HANDLE_VALUE) {
-- 
1.7.9.5


More information about the wine-patches mailing list