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
9ec7ab3f
Commit
9ec7ab3f
authored
Oct 04, 2012
by
Francois Gouget
Committed by
Alexandre Julliard
Oct 04, 2012
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
shell32/tests: Write proper tests for CommandLineToArgvW().
parent
da6b02ce
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
232 additions
and
106 deletions
+232
-106
process.c
dlls/kernel32/tests/process.c
+0
-12
shlexec.c
dlls/shell32/tests/shlexec.c
+232
-94
No files found.
dlls/kernel32/tests/process.c
View file @
9ec7ab3f
...
...
@@ -298,18 +298,6 @@ static void doChild(const char* file, const char* option)
childPrintf
(
hFile
,
"argvA%d=%s
\n
"
,
i
,
encodeA
(
myARGV
[
i
]));
}
childPrintf
(
hFile
,
"CommandLineA=%s
\n
"
,
encodeA
(
GetCommandLineA
()));
#if 0
int argcW;
WCHAR** argvW;
/* this is part of shell32... and should be tested there */
argvW = CommandLineToArgvW(GetCommandLineW(), &argcW);
for (i = 0; i < argcW; i++)
{
childPrintf(hFile, "argvW%d=%s\n", i, encodeW(argvW[i]));
}
#endif
childPrintf
(
hFile
,
"CommandLineW=%s
\n\n
"
,
encodeW
(
GetCommandLineW
()));
/* output of environment (Ansi) */
...
...
dlls/shell32/tests/shlexec.c
View file @
9ec7ab3f
...
...
@@ -953,6 +953,237 @@ static void test_lpFile_parsed(void)
"%s failed: rc=%lu
\n
"
,
shell_call
,
rc
);
}
typedef
struct
{
const
char
*
cmd
;
const
char
*
args
[
11
];
int
todo
;
}
cmdline_tests_t
;
static
const
cmdline_tests_t
cmdline_tests
[]
=
{
{
"exe arg1 arg2
\"
arg three
\"
'four five` six
\\
$even)"
,
{
"exe"
,
"arg1"
,
"arg2"
,
"arg three"
,
"'four"
,
"five`"
,
"six
\\
"
,
"$even)"
,
NULL
},
0
},
{
"exe arg=1 arg-2 three
\t
four
\r
four
\n
four "
,
{
"exe"
,
"arg=1"
,
"arg-2"
,
"three"
,
"four
\r
four
\n
four"
,
NULL
},
0
},
{
"exe arg
\"
one
\"
\"
second
\"
arg thirdarg "
,
{
"exe"
,
"argone"
,
"secondarg"
,
"thirdarg"
,
NULL
},
0
},
/* cmd's metacharacters have no special meaning */
{
"exe
\"
one^
\"
\"
arg
\"
&two three|four"
,
{
"exe"
,
"one^"
,
"arg&two"
,
"three|four"
,
NULL
},
0
},
/* Environment variables are not interpreted either */
{
"exe %TMPDIR% %2"
,
{
"exe"
,
"%TMPDIR%"
,
"%2"
,
NULL
},
0
},
/* If not followed by a quote, backslashes go through as is */
{
"exe o
\\
ne t
\\\\
wo t
\\\\\\
ree f
\\\\\\\\
our "
,
{
"exe"
,
"o
\\
ne"
,
"t
\\\\
wo"
,
"t
\\\\\\
ree"
,
"f
\\\\\\\\
our"
,
NULL
},
0
},
{
"exe
\"
o
\\
ne
\"
\"
t
\\\\
wo
\"
\"
t
\\\\\\
ree
\"
\"
f
\\\\\\\\
our
\"
"
,
{
"exe"
,
"o
\\
ne"
,
"t
\\\\
wo"
,
"t
\\\\\\
ree"
,
"f
\\\\\\\\
our"
,
NULL
},
0
},
/* When followed by a quote their number is halved and the remainder
* escapes the quote
*/
{
"exe
\\\"
one
\\\\\"
two
\"
\\\\\\\"
three
\\\\\\\\\"
four
\"
end"
,
{
"exe"
,
"
\"
one"
,
"
\\
two"
,
"
\\\"
three"
,
"
\\\\
four"
,
"end"
,
NULL
},
0
},
{
"exe
\"
one
\\\"
still
\"
\"
two
\\\\\"
\"
three
\\\\\\\"
still
\"
\"
four
\\\\\\\\\"
end"
,
{
"exe"
,
"one
\"
still"
,
"two
\\
"
,
"three
\\\"
still"
,
"four
\\\\
"
,
"end"
,
NULL
},
0
},
/* One can put a quote in an unquoted string by tripling it, that is in
* effect quoting it like so """ -> ". The general rule is as follows:
* 3n quotes -> n quotes
* 3n+1 quotes -> n quotes plus start of a quoted string
* 3n+2 quotes -> n quotes (plus an empty string from the remaining pair)
* Nicely, when n is 0 we get the standard rules back.
*/
{
"exe two
\"\"
quotes next"
,
{
"exe"
,
"twoquotes"
,
"next"
,
NULL
},
0
},
{
"exe three
\"\"\"
quotes next"
,
{
"exe"
,
"three
\"
quotes"
,
"next"
,
NULL
},
0x21
},
{
"exe four
\"\"\"\"
quotes
\"
next 4%3=1"
,
{
"exe"
,
"four
\"
quotes"
,
"next"
,
"4%3=1"
,
NULL
},
0x61
},
{
"exe five
\"\"\"\"\"
quotes next"
,
{
"exe"
,
"five
\"
quotes"
,
"next"
,
NULL
},
0x21
},
{
"exe six
\"\"\"\"\"\"
quotes next"
,
{
"exe"
,
"six
\"\"
quotes"
,
"next"
,
NULL
},
0x20
},
{
"exe seven
\"\"\"\"\"\"\"
quotes
\"
next 7%3=1"
,
{
"exe"
,
"seven
\"\"
quotes"
,
"next"
,
"7%3=1"
,
NULL
},
0x20
},
{
"exe twelve
\"\"\"\"\"\"\"\"\"\"\"\"
quotes next"
,
{
"exe"
,
"twelve
\"\"\"\"
quotes"
,
"next"
,
NULL
},
0x20
},
{
"exe thirteen
\"\"\"\"\"\"\"\"\"\"\"\"\"
quotes
\"
next 13%3=1"
,
{
"exe"
,
"thirteen
\"\"\"\"
quotes"
,
"next"
,
"13%3=1"
,
NULL
},
0x20
},
/* Inside a quoted string the opening quote is added to the set of
* consecutive quotes to get the effective quotes count. This gives:
* 1+3n quotes -> n quotes
* 1+3n+1 quotes -> n quotes plus closes the quoted string
* 1+3n+2 quotes -> n+1 quotes plus closes the quoted string
*/
{
"exe
\"
two
\"\"
quotes next"
,
{
"exe"
,
"two
\"
quotes"
,
"next"
,
NULL
},
0x21
},
{
"exe
\"
two
\"\"
next"
,
{
"exe"
,
"two
\"
"
,
"next"
,
NULL
},
0x21
},
{
"exe
\"
three
\"\"\"
quotes
\"
next 4%3=1"
,
{
"exe"
,
"three
\"
quotes"
,
"next"
,
"4%3=1"
,
NULL
},
0x61
},
{
"exe
\"
four
\"\"\"\"
quotes next"
,
{
"exe"
,
"four
\"
quotes"
,
"next"
,
NULL
},
0x21
},
{
"exe
\"
five
\"\"\"\"\"
quotes next"
,
{
"exe"
,
"five
\"\"
quotes"
,
"next"
,
NULL
},
0x20
},
{
"exe
\"
six
\"\"\"\"\"\"
quotes
\"
next 7%3=1"
,
{
"exe"
,
"six
\"\"
quotes"
,
"next"
,
"7%3=1"
,
NULL
},
0x20
},
{
"exe
\"
eleven
\"\"\"\"\"\"\"\"\"\"\"
quotes next"
,
{
"exe"
,
"eleven
\"\"\"\"
quotes"
,
"next"
,
NULL
},
0x20
},
{
"exe
\"
twelve
\"\"\"\"\"\"\"\"\"\"\"\"
quotes
\"
next 13%3=1"
,
{
"exe"
,
"twelve
\"\"\"\"
quotes"
,
"next"
,
"13%3=1"
,
NULL
},
0x20
},
/* The executable path has its own rules!!!
* - Backslashes have no special meaning.
* - If the first character is a quote, then the second quote ends the
* executable path.
* - The previous rule holds even if the next character is not a space!
* - If the first character is not a quote, then quotes have no special
* meaning either and the executable path stops at the first space.
* - The consecutive quotes rules don't apply either.
* - Even if there is no space between the executable path and the first
* argument, the latter is parsed using the regular rules.
*/
{
"exe
\"
file
\"
path arg1"
,
{
"exe
\"
file
\"
path"
,
"arg1"
,
NULL
},
0x30
},
{
"exe
\"
path
\\
arg1"
,
{
"exe
\"
path
\\
"
,
"arg1"
,
NULL
},
0x31
},
{
"
\\\"
exe
\"
arg one
\"
"
,
{
"
\\\"
exe"
,
"arg one"
,
NULL
},
0x10
},
{
"
\"
spaced exe
\"
\"
next arg
\"
"
,
{
"spaced exe"
,
"next arg"
,
NULL
},
0
},
{
"
\"
exe
\"
arg
\"
one
\"
argtwo"
,
{
"exe"
,
"arg one"
,
"argtwo"
,
NULL
},
0x31
},
{
"
\"
spaced exe
\\\"
arg1 arg2"
,
{
"spaced exe
\\
"
,
"arg1"
,
"arg2"
,
NULL
},
0x11
},
{
"
\"
two
\"\"
arg1 "
,
{
"two"
,
" arg1 "
,
NULL
},
0x21
},
{
"
\"
three
\"\"\"
arg2"
,
{
"three"
,
""
,
"arg2"
,
NULL
},
0x61
},
{
"
\"
four
\"\"\"\"
arg1"
,
{
"four"
,
"
\"
arg1"
,
NULL
},
0x21
},
/* If the first character is a space then the executable path is empty */
{
"
\"
arg
\"
one argtwo"
,
{
""
,
"argone"
,
"argtwo"
,
NULL
},
0
},
{
NULL
,
{
NULL
},
0
}
};
static
BOOL
test_one_cmdline
(
const
cmdline_tests_t
*
test
)
{
WCHAR
cmdW
[
MAX_PATH
],
argW
[
MAX_PATH
];
LPWSTR
*
cl2a
;
int
cl2a_count
;
LPWSTR
*
argsW
;
int
i
,
count
;
/* trace("----- cmd='%s'\n", test->cmd); */
MultiByteToWideChar
(
CP_ACP
,
0
,
test
->
cmd
,
-
1
,
cmdW
,
sizeof
(
cmdW
)
/
sizeof
(
*
cmdW
));
argsW
=
cl2a
=
CommandLineToArgvW
(
cmdW
,
&
cl2a_count
);
if
(
argsW
==
NULL
&&
cl2a_count
==
-
1
)
{
win_skip
(
"CommandLineToArgvW not implemented, skipping
\n
"
);
return
FALSE
;
}
count
=
0
;
while
(
test
->
args
[
count
])
count
++
;
if
((
test
->
todo
&
0x1
)
==
0
)
ok
(
cl2a_count
==
count
,
"%s: expected %d arguments, but got %d
\n
"
,
test
->
cmd
,
count
,
cl2a_count
);
else
todo_wine
ok
(
cl2a_count
==
count
,
"%s: expected %d arguments, but got %d
\n
"
,
test
->
cmd
,
count
,
cl2a_count
);
for
(
i
=
0
;
i
<
cl2a_count
-
1
;
i
++
)
{
if
(
test
->
args
[
i
])
{
MultiByteToWideChar
(
CP_ACP
,
0
,
test
->
args
[
i
],
-
1
,
argW
,
sizeof
(
argW
)
/
sizeof
(
*
argW
));
if
((
test
->
todo
&
(
1
<<
(
i
+
4
)))
==
0
)
ok
(
!
lstrcmpW
(
*
argsW
,
argW
),
"%s: arg[%d] expected %s but got %s
\n
"
,
test
->
cmd
,
i
,
wine_dbgstr_w
(
argW
),
wine_dbgstr_w
(
*
argsW
));
else
todo_wine
ok
(
!
lstrcmpW
(
*
argsW
,
argW
),
"%s: arg[%d] expected %s but got %s
\n
"
,
test
->
cmd
,
i
,
wine_dbgstr_w
(
argW
),
wine_dbgstr_w
(
*
argsW
));
}
else
if
((
test
->
todo
&
0x1
)
==
0
)
ok
(
0
,
"%s: got extra arg[%d]=%s
\n
"
,
test
->
cmd
,
i
,
wine_dbgstr_w
(
*
argsW
));
else
todo_wine
ok
(
0
,
"%s: got extra arg[%d]=%s
\n
"
,
test
->
cmd
,
i
,
wine_dbgstr_w
(
*
argsW
));
argsW
++
;
}
LocalFree
(
cl2a
);
return
TRUE
;
}
static
void
test_commandline2argv
(
void
)
{
static
const
WCHAR
exeW
[]
=
{
'e'
,
'x'
,
'e'
,
0
};
const
cmdline_tests_t
*
test
;
WCHAR
strW
[
MAX_PATH
];
LPWSTR
*
args
;
int
numargs
;
DWORD
le
;
test
=
cmdline_tests
;
while
(
test
->
cmd
)
{
if
(
!
test_one_cmdline
(
test
))
return
;
test
++
;
}
SetLastError
(
0xdeadbeef
);
args
=
CommandLineToArgvW
(
exeW
,
NULL
);
le
=
GetLastError
();
ok
(
args
==
NULL
&&
le
==
ERROR_INVALID_PARAMETER
,
"expected NULL with ERROR_INVALID_PARAMETER got %p with %u
\n
"
,
args
,
le
);
SetLastError
(
0xdeadbeef
);
args
=
CommandLineToArgvW
(
NULL
,
NULL
);
le
=
GetLastError
();
ok
(
args
==
NULL
&&
le
==
ERROR_INVALID_PARAMETER
,
"expected NULL with ERROR_INVALID_PARAMETER got %p with %u
\n
"
,
args
,
le
);
*
strW
=
0
;
args
=
CommandLineToArgvW
(
strW
,
&
numargs
);
ok
(
numargs
==
1
,
"expected 1 args, got %d
\n
"
,
numargs
);
if
(
numargs
==
1
)
{
GetModuleFileNameW
(
NULL
,
strW
,
sizeof
(
strW
)
/
sizeof
(
*
strW
));
ok
(
!
lstrcmpW
(
args
[
0
],
strW
),
"wrong path to the current executable: %s instead of %s
\n
"
,
wine_dbgstr_w
(
args
[
0
]),
wine_dbgstr_w
(
strW
));
}
if
(
args
)
LocalFree
(
args
);
}
static
void
test_argify
(
void
)
{
char
fileA
[
MAX_PATH
];
...
...
@@ -2210,99 +2441,6 @@ static void cleanup_test(void)
CoUninitialize
();
}
static
void
test_commandline
(
void
)
{
static
const
WCHAR
one
[]
=
{
'o'
,
'n'
,
'e'
,
0
};
static
const
WCHAR
two
[]
=
{
't'
,
'w'
,
'o'
,
0
};
static
const
WCHAR
three
[]
=
{
't'
,
'h'
,
'r'
,
'e'
,
'e'
,
0
};
static
const
WCHAR
four
[]
=
{
'f'
,
'o'
,
'u'
,
'r'
,
0
};
static
const
WCHAR
fmt1
[]
=
{
'%'
,
's'
,
' '
,
'%'
,
's'
,
' '
,
'%'
,
's'
,
' '
,
'%'
,
's'
,
0
};
static
const
WCHAR
fmt2
[]
=
{
' '
,
'%'
,
's'
,
' '
,
'%'
,
's'
,
' '
,
'%'
,
's'
,
' '
,
'%'
,
's'
,
0
};
static
const
WCHAR
fmt3
[]
=
{
'%'
,
's'
,
'='
,
'%'
,
's'
,
' '
,
'%'
,
's'
,
'='
,
'\"'
,
'%'
,
's'
,
'\"'
,
0
};
static
const
WCHAR
fmt4
[]
=
{
'\"'
,
'%'
,
's'
,
'\"'
,
' '
,
'\"'
,
'%'
,
's'
,
' '
,
'%'
,
's'
,
'\"'
,
' '
,
'%'
,
's'
,
0
};
static
const
WCHAR
fmt5
[]
=
{
'\\'
,
'\"'
,
'%'
,
's'
,
'\"'
,
' '
,
'%'
,
's'
,
'='
,
'\"'
,
'%'
,
's'
,
'\\'
,
'\"'
,
' '
,
'\"'
,
'%'
,
's'
,
'\\'
,
'\"'
,
0
};
static
const
WCHAR
fmt6
[]
=
{
0
};
static
const
WCHAR
chkfmt1
[]
=
{
'%'
,
's'
,
'='
,
'%'
,
's'
,
0
};
static
const
WCHAR
chkfmt2
[]
=
{
'%'
,
's'
,
' '
,
'%'
,
's'
,
0
};
static
const
WCHAR
chkfmt3
[]
=
{
'\\'
,
'\"'
,
'%'
,
's'
,
'\"'
,
0
};
static
const
WCHAR
chkfmt4
[]
=
{
'%'
,
's'
,
'='
,
'%'
,
's'
,
'\"'
,
' '
,
'%'
,
's'
,
'\"'
,
0
};
WCHAR
cmdline
[
255
];
LPWSTR
*
args
=
(
LPWSTR
*
)
0xdeadcafe
,
pbuf
;
INT
numargs
=
-
1
;
size_t
buflen
;
DWORD
lerror
;
wsprintfW
(
cmdline
,
fmt1
,
one
,
two
,
three
,
four
);
args
=
CommandLineToArgvW
(
cmdline
,
&
numargs
);
if
(
args
==
NULL
&&
numargs
==
-
1
)
{
win_skip
(
"CommandLineToArgvW not implemented, skipping
\n
"
);
return
;
}
ok
(
numargs
==
4
,
"expected 4 args, got %i
\n
"
,
numargs
);
ok
(
lstrcmpW
(
args
[
0
],
one
)
==
0
,
"arg0 is not as expected
\n
"
);
ok
(
lstrcmpW
(
args
[
1
],
two
)
==
0
,
"arg1 is not as expected
\n
"
);
ok
(
lstrcmpW
(
args
[
2
],
three
)
==
0
,
"arg2 is not as expected
\n
"
);
ok
(
lstrcmpW
(
args
[
3
],
four
)
==
0
,
"arg3 is not as expected
\n
"
);
SetLastError
(
0xdeadbeef
);
args
=
CommandLineToArgvW
(
cmdline
,
NULL
);
lerror
=
GetLastError
();
ok
(
args
==
NULL
&&
lerror
==
ERROR_INVALID_PARAMETER
,
"expected NULL with ERROR_INVALID_PARAMETER got %p with %u
\n
"
,
args
,
lerror
);
SetLastError
(
0xdeadbeef
);
args
=
CommandLineToArgvW
(
NULL
,
NULL
);
lerror
=
GetLastError
();
ok
(
args
==
NULL
&&
lerror
==
ERROR_INVALID_PARAMETER
,
"expected NULL with ERROR_INVALID_PARAMETER got %p with %u
\n
"
,
args
,
lerror
);
wsprintfW
(
cmdline
,
fmt2
,
one
,
two
,
three
,
four
);
args
=
CommandLineToArgvW
(
cmdline
,
&
numargs
);
ok
(
numargs
==
5
,
"expected 5 args, got %i
\n
"
,
numargs
);
ok
(
args
[
0
][
0
]
==
0
,
"arg0 is not as expected
\n
"
);
ok
(
lstrcmpW
(
args
[
1
],
one
)
==
0
,
"arg1 is not as expected
\n
"
);
ok
(
lstrcmpW
(
args
[
2
],
two
)
==
0
,
"arg2 is not as expected
\n
"
);
ok
(
lstrcmpW
(
args
[
3
],
three
)
==
0
,
"arg3 is not as expected
\n
"
);
ok
(
lstrcmpW
(
args
[
4
],
four
)
==
0
,
"arg4 is not as expected
\n
"
);
wsprintfW
(
cmdline
,
fmt3
,
one
,
two
,
three
,
four
);
args
=
CommandLineToArgvW
(
cmdline
,
&
numargs
);
ok
(
numargs
==
2
,
"expected 2 args, got %i
\n
"
,
numargs
);
wsprintfW
(
cmdline
,
chkfmt1
,
one
,
two
);
ok
(
lstrcmpW
(
args
[
0
],
cmdline
)
==
0
,
"arg0 is not as expected
\n
"
);
wsprintfW
(
cmdline
,
chkfmt1
,
three
,
four
);
ok
(
lstrcmpW
(
args
[
1
],
cmdline
)
==
0
,
"arg1 is not as expected
\n
"
);
wsprintfW
(
cmdline
,
fmt4
,
one
,
two
,
three
,
four
);
args
=
CommandLineToArgvW
(
cmdline
,
&
numargs
);
ok
(
numargs
==
3
,
"expected 3 args, got %i
\n
"
,
numargs
);
ok
(
lstrcmpW
(
args
[
0
],
one
)
==
0
,
"arg0 is not as expected
\n
"
);
wsprintfW
(
cmdline
,
chkfmt2
,
two
,
three
);
ok
(
lstrcmpW
(
args
[
1
],
cmdline
)
==
0
,
"arg1 is not as expected
\n
"
);
ok
(
lstrcmpW
(
args
[
2
],
four
)
==
0
,
"arg2 is not as expected
\n
"
);
wsprintfW
(
cmdline
,
fmt5
,
one
,
two
,
three
,
four
);
args
=
CommandLineToArgvW
(
cmdline
,
&
numargs
);
ok
(
numargs
==
2
,
"expected 2 args, got %i
\n
"
,
numargs
);
wsprintfW
(
cmdline
,
chkfmt3
,
one
);
todo_wine
ok
(
lstrcmpW
(
args
[
0
],
cmdline
)
==
0
,
"arg0 is not as expected
\n
"
);
wsprintfW
(
cmdline
,
chkfmt4
,
two
,
three
,
four
);
todo_wine
ok
(
lstrcmpW
(
args
[
1
],
cmdline
)
==
0
,
"arg1 is not as expected
\n
"
);
wsprintfW
(
cmdline
,
fmt6
);
args
=
CommandLineToArgvW
(
cmdline
,
&
numargs
);
ok
(
numargs
==
1
,
"expected 1 args, got %i
\n
"
,
numargs
);
if
(
numargs
==
1
)
{
buflen
=
max
(
lstrlenW
(
args
[
0
])
+
1
,
256
);
pbuf
=
HeapAlloc
(
GetProcessHeap
(),
0
,
buflen
*
sizeof
(
pbuf
[
0
]));
GetModuleFileNameW
(
NULL
,
pbuf
,
buflen
);
pbuf
[
buflen
-
1
]
=
0
;
/* check args[0] is module file name */
ok
(
lstrcmpW
(
args
[
0
],
pbuf
)
==
0
,
"wrong path to the current executable
\n
"
);
HeapFree
(
GetProcessHeap
(),
0
,
pbuf
);
}
}
static
void
test_directory
(
void
)
{
char
path
[
MAX_PATH
],
newdir
[
MAX_PATH
];
...
...
@@ -2346,6 +2484,7 @@ START_TEST(shlexec)
init_test
();
test_commandline2argv
();
test_argify
();
test_lpFile_parsed
();
test_filename
();
...
...
@@ -2356,7 +2495,6 @@ START_TEST(shlexec)
test_exes_long
();
test_dde
();
test_dde_default_app
();
test_commandline
();
test_directory
();
cleanup_test
();
...
...
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