Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
5ee3879c
Commit
5ee3879c
authored
Sep 20, 2001
by
Francois Gouget
Committed by
Alexandre Julliard
Sep 20, 2001
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix the conversions of a command line to/from an argv array.
parent
45e9cea3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
332 additions
and
97 deletions
+332
-97
shell32_main.c
dlls/shell32/shell32_main.c
+142
-40
environ.c
memory/environ.c
+106
-19
process.c
scheduler/process.c
+84
-38
No files found.
dlls/shell32/shell32_main.c
View file @
5ee3879c
...
...
@@ -34,50 +34,152 @@ DEFAULT_DEBUG_CHANNEL(shell);
#define MORE_DEBUG 1
/*************************************************************************
* CommandLineToArgvW [SHELL32.@]
*
* We must interpret the quotes in the command line to rebuild the argv
* array correctly:
* - arguments are separated by spaces or tabs
* - quotes serve as optional argument delimiters
* '"a b"' -> 'a b'
* - escaped quotes must be converted back to '"'
* '\"' -> '"'
* - an odd number of '\'s followed by '"' correspond to half that number
* of '\' followed by a '"' (extension of the above)
* '\\\"' -> '\"'
* '\\\\\"' -> '\\"'
* - an even number of '\'s followed by a '"' correspond to half that number
* of '\', plus a regular quote serving as an argument delimiter (which
* means it does not appear in the result)
* 'a\\"b c"' -> 'a\b c'
* 'a\\\\"b c"' -> 'a\\b c'
* - '\' that are not followed by a '"' are copied literally
* 'a\b' -> 'a\b'
* 'a\\b' -> 'a\\b'
*
* Note:
* '\t' == 0x0009
* ' ' == 0x0020
* '"' == 0x0022
* '\\' == 0x005c
*/
LPWSTR
*
WINAPI
CommandLineToArgvW
(
LPCWSTR
lpCmdline
,
int
*
numargs
)
{
LPWSTR
*
argv
,
s
,
t
;
LPWSTR
cmdline
;
int
i
;
TRACE
(
"
\n
"
);
/* to get writeable copy */
if
(
!
(
cmdline
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
strlenW
(
lpCmdline
)
+
1
)
*
sizeof
(
WCHAR
)
)))
return
NULL
;
strcpyW
(
cmdline
,
lpCmdline
);
s
=
cmdline
;
i
=
0
;
while
(
*
s
)
{
/* space */
if
(
*
s
==
0x0020
)
{
i
++
;
s
++
;
while
(
*
s
&&
*
s
==
0x0020
)
s
++
;
continue
;
}
s
++
;
}
argv
=
(
LPWSTR
*
)
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
LPWSTR
)
*
(
i
+
1
)
);
s
=
t
=
cmdline
;
i
=
0
;
while
(
*
s
)
{
if
(
*
s
==
0x0020
)
{
argv
[
i
++
]
=
t
;
while
(
*
s
==
0x0020
)
*
s
++
=
0
;
t
=
s
;
continue
;
{
DWORD
argc
;
LPWSTR
*
argv
;
LPWSTR
arg
,
s
,
d
;
LPWSTR
cmdline
;
int
in_quotes
,
bcount
;
/* FIXME: same thing if we only have spaces */
if
(
*
lpCmdline
==
0
)
{
/* Return the path to the executable */
DWORD
size
;
argv
=
HeapAlloc
(
GetProcessHeap
(),
0
,
2
*
sizeof
(
LPWSTR
));
argv
[
0
]
=
NULL
;
size
=
16
;
do
{
size
*=
2
;
argv
[
0
]
=
HeapReAlloc
(
GetProcessHeap
(),
0
,
argv
[
0
],
size
);
}
while
(
GetModuleFileNameW
((
HMODULE
)
0
,
argv
[
0
],
size
)
==
0
);
argv
[
1
]
=
NULL
;
if
(
numargs
)
*
numargs
=
2
;
return
argv
;
}
/* to get a writeable copy */
cmdline
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
strlenW
(
lpCmdline
)
+
1
)
*
sizeof
(
WCHAR
));
if
(
!
cmdline
)
return
NULL
;
strcpyW
(
cmdline
,
lpCmdline
);
argc
=
0
;
bcount
=
0
;
in_quotes
=
0
;
s
=
cmdline
;
while
(
1
)
{
if
(
*
s
==
0
||
((
*
s
==
0x0009
||
*
s
==
0x0020
)
&&
!
in_quotes
))
{
/* space */
argc
++
;
/* skip the remaining spaces */
while
(
*
s
==
0x0009
||
*
s
==
0x0020
)
{
s
++
;
}
s
++
;
}
if
(
*
t
)
argv
[
i
++
]
=
t
;
if
(
*
s
==
0
)
break
;
bcount
=
0
;
continue
;
}
else
if
(
*
s
==
0x005c
)
{
/* '\', count them */
bcount
++
;
}
else
if
((
*
s
==
0x0022
)
&&
((
bcount
&
1
)
==
0
))
{
/* unescaped '"' */
in_quotes
=!
in_quotes
;
bcount
=
0
;
}
else
{
/* a regular character */
bcount
=
0
;
}
s
++
;
}
argv
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
argc
+
1
)
*
sizeof
(
LPWSTR
));
argc
=
0
;
bcount
=
0
;
in_quotes
=
0
;
arg
=
d
=
s
=
cmdline
;
while
(
*
s
)
{
if
((
*
s
==
0x0009
||
*
s
==
0x0020
)
&&
!
in_quotes
)
{
/* Close the argument and copy it */
*
d
=
0
;
argv
[
argc
++
]
=
arg
;
/* skip the remaining spaces */
do
{
s
++
;
}
while
(
*
s
==
0x0009
||
*
s
==
0x0020
);
/* Start with a new argument */
arg
=
d
=
s
;
bcount
=
0
;
}
else
if
(
*
s
==
0x005c
)
{
/* '\\' */
*
d
++=*
s
++
;
bcount
++
;
}
else
if
(
*
s
==
0x0022
)
{
/* '"' */
if
((
bcount
&
1
)
==
0
)
{
/* Preceeded by an even number of '\', this is half that
* number of '\', plus a quote which we erase.
*/
d
-=
bcount
/
2
;
in_quotes
=!
in_quotes
;
s
++
;
}
else
{
/* Preceeded by an odd number of '\', this is half that
* number of '\' followed by a '"'
*/
d
=
d
-
bcount
/
2
-
1
;
*
d
++=
'"'
;
s
++
;
}
bcount
=
0
;
}
else
{
/* a regular character */
*
d
++=*
s
++
;
bcount
=
0
;
}
}
if
(
*
arg
)
{
*
d
=
'\0'
;
argv
[
argc
++
]
=
arg
;
}
argv
[
argc
]
=
NULL
;
if
(
numargs
)
*
numargs
=
argc
;
argv
[
i
]
=
NULL
;
*
numargs
=
i
;
return
argv
;
HeapFree
(
GetProcessHeap
(),
0
,
cmdline
);
return
argv
;
}
/*************************************************************************
...
...
memory/environ.c
View file @
5ee3879c
...
...
@@ -174,34 +174,121 @@ ENVDB *ENV_BuildEnvironment(void)
*
* 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 that are not followed by a '"' can be left as is
* 'a\b' == 'a\b'
* 'a\\b' == 'a\\b'
*/
BOOL
ENV_BuildCommandLine
(
char
**
argv
)
{
int
len
,
quote
=
0
;
int
len
;
char
*
p
,
**
arg
;
for
(
arg
=
argv
,
len
=
0
;
*
arg
;
arg
++
)
len
+=
strlen
(
*
arg
)
+
1
;
if
((
argv
[
0
])
&&
(
quote
=
(
strchr
(
argv
[
0
],
' '
)
!=
NULL
)))
len
+=
2
;
if
(
!
(
p
=
current_envdb
.
cmd_line
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
)))
return
FALSE
;
arg
=
argv
;
if
(
quote
)
len
=
0
;
for
(
arg
=
argv
;
*
arg
;
arg
++
)
{
*
p
++
=
'\"'
;
strcpy
(
p
,
*
arg
);
p
+=
strlen
(
p
);
*
p
++
=
'\"'
;
*
p
++
=
' '
;
arg
++
;
int
has_space
,
bcount
;
char
*
a
;
has_space
=
0
;
bcount
=
0
;
a
=*
arg
;
while
(
*
a
!=
'\0'
)
{
if
(
*
a
==
'\\'
)
{
bcount
++
;
}
else
{
if
(
*
a
==
' '
||
*
a
==
'\t'
)
{
has_space
=
1
;
}
else
if
(
*
a
==
'"'
)
{
/* doubling of '\' preceeding 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
;
/* for the quotes */
}
while
(
*
arg
)
if
(
!
(
current_envdb
.
cmd_line
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
)))
return
FALSE
;
p
=
current_envdb
.
cmd_line
;
for
(
arg
=
argv
;
*
arg
;
arg
++
)
{
strcpy
(
p
,
*
arg
);
p
+=
strlen
(
p
);
*
p
++
=
' '
;
arg
++
;
int
has_space
,
has_quote
;
char
*
a
;
/* Check for quotes and spaces in this argument */
has_space
=
has_quote
=
0
;
a
=*
arg
;
while
(
*
a
!=
'\0'
)
{
if
(
*
a
==
' '
||
*
a
==
'\t'
)
{
has_space
=
1
;
if
(
has_quote
)
break
;
}
else
if
(
*
a
==
'"'
)
{
has_quote
=
1
;
if
(
has_space
)
break
;
}
a
++
;
}
/* Now transfer it to the command line */
if
(
has_space
)
*
p
++=
'"'
;
if
(
has_quote
)
{
int
bcount
;
char
*
a
;
bcount
=
0
;
a
=*
arg
;
while
(
*
a
!=
'\0'
)
{
if
(
*
a
==
'\\'
)
{
*
p
++=*
a
;
bcount
++
;
}
else
{
if
(
*
a
==
'"'
)
{
int
i
;
/* Double all the '\\' preceeding this '"', plus one */
for
(
i
=
0
;
i
<=
bcount
;
i
++
)
*
p
++=
'\\'
;
*
p
++=
'"'
;
}
else
{
*
p
++=*
a
;
}
bcount
=
0
;
}
a
++
;
}
}
else
{
strcpy
(
p
,
*
arg
);
p
+=
strlen
(
*
arg
);
}
if
(
has_space
)
*
p
++=
'"'
;
*
p
++=
' '
;
}
if
(
p
>
current_envdb
.
cmd_line
)
p
--
;
/* remove last space */
*
p
=
0
;
if
(
p
>
current_envdb
.
cmd_line
)
p
--
;
/* remove last space */
*
p
=
'\0'
;
/* now allocate the Unicode version */
len
=
MultiByteToWideChar
(
CP_ACP
,
0
,
current_envdb
.
cmd_line
,
-
1
,
NULL
,
0
);
if
(
!
(
cmdlineW
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
*
sizeof
(
WCHAR
)
)))
...
...
scheduler/process.c
View file @
5ee3879c
...
...
@@ -531,50 +531,96 @@ void PROCESS_InitWine( int argc, char *argv[], LPSTR win16_exe_name, HANDLE *win
*/
static
char
**
build_argv
(
char
*
cmdline
,
int
reserved
)
{
char
**
argv
;
int
count
=
reserved
+
1
;
char
*
p
=
cmdline
;
/* if first word is quoted store it as a single arg */
if
(
*
cmdline
==
'\"'
)
{
if
((
p
=
strchr
(
cmdline
+
1
,
'\"'
)))
{
p
++
;
count
++
;
int
argc
;
char
**
argv
;
char
*
arg
,
*
s
,
*
d
;
int
in_quotes
,
bcount
;
argc
=
reserved
+
1
;
bcount
=
0
;
in_quotes
=
0
;
s
=
cmdline
;
while
(
1
)
{
if
(
*
s
==
'\0'
||
((
*
s
==
' '
||
*
s
==
'\t'
)
&&
!
in_quotes
))
{
/* space */
argc
++
;
/* skip the remaining spaces */
while
(
*
s
==
' '
||
*
s
==
'\t'
)
{
s
++
;
}
if
(
*
s
==
'\0'
)
break
;
bcount
=
0
;
continue
;
}
else
if
(
*
s
==
'\\'
)
{
/* '\', count them */
bcount
++
;
}
else
if
((
*
s
==
'"'
)
&&
((
bcount
&
1
)
==
0
))
{
/* unescaped '"' */
in_quotes
=!
in_quotes
;
bcount
=
0
;
}
else
{
/* a regular character */
bcount
=
0
;
}
else
p
=
cmdline
;
}
while
(
*
p
)
{
while
(
*
p
&&
isspace
(
*
p
))
p
++
;
if
(
!*
p
)
break
;
count
++
;
while
(
*
p
&&
!
isspace
(
*
p
))
p
++
;
s
++
;
}
argv
=
malloc
(
argc
*
sizeof
(
*
argv
));
if
(
!
argv
)
return
NULL
;
if
((
argv
=
malloc
(
count
*
sizeof
(
*
argv
)
)))
{
char
**
argvptr
=
argv
+
reserved
;
p
=
cmdline
;
if
(
*
cmdline
==
'\"'
)
{
if
((
p
=
strchr
(
cmdline
+
1
,
'\"'
)))
{
*
argvptr
++
=
cmdline
+
1
;
*
p
++
=
0
;
arg
=
d
=
s
=
cmdline
;
bcount
=
0
;
in_quotes
=
0
;
argc
=
reserved
;
while
(
*
s
)
{
if
((
*
s
==
' '
||
*
s
==
'\t'
)
&&
!
in_quotes
)
{
/* Close the argument and copy it */
*
d
=
0
;
argv
[
argc
++
]
=
arg
;
/* skip the remaining spaces */
do
{
s
++
;
}
while
(
*
s
==
' '
||
*
s
==
'\t'
);
/* Start with a new argument */
arg
=
d
=
s
;
bcount
=
0
;
}
else
if
(
*
s
==
'\\'
)
{
/* '\\' */
*
d
++=*
s
++
;
bcount
++
;
}
else
if
(
*
s
==
'"'
)
{
/* '"' */
if
((
bcount
&
1
)
==
0
)
{
/* Preceeded by an even number of '\', this is half that
* number of '\', plus a '"' which we discard.
*/
d
-=
bcount
/
2
;
s
++
;
in_quotes
=!
in_quotes
;
}
else
{
/* Preceeded by an odd number of '\', this is half that
* number of '\' followed by a '"'
*/
d
=
d
-
bcount
/
2
-
1
;
*
d
++=
'"'
;
s
++
;
}
else
p
=
cmdline
;
bcount
=
0
;
}
else
{
/* a regular character */
*
d
++=*
s
++
;
bcount
=
0
;
}
while
(
*
p
)
{
while
(
*
p
&&
isspace
(
*
p
))
*
p
++
=
0
;
if
(
!*
p
)
break
;
*
argvptr
++
=
p
;
while
(
*
p
&&
!
isspace
(
*
p
))
p
++
;
}
*
argvptr
=
0
;
}
if
(
*
arg
)
{
*
d
=
'\0'
;
argv
[
argc
++
]
=
arg
;
}
argv
[
argc
]
=
NULL
;
return
argv
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment