extrac32: Use own parser for command line.
This commit is contained in:
parent
69008be65d
commit
c7d2b1d5cc
|
@ -82,6 +82,98 @@ static void copy_file(LPCWSTR source, LPCWSTR destination)
|
||||||
CopyFileW(source, destination, FALSE);
|
CopyFileW(source, destination, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static LPWSTR *get_extrac_args(LPWSTR cmdline, int *pargc)
|
||||||
|
{
|
||||||
|
enum {OUTSIDE_ARG, INSIDE_ARG, INSIDE_QUOTED_ARG} state;
|
||||||
|
LPWSTR str;
|
||||||
|
int argc;
|
||||||
|
LPWSTR *argv;
|
||||||
|
int max_argc = 16;
|
||||||
|
BOOL new_arg;
|
||||||
|
|
||||||
|
WINE_TRACE("cmdline: %s\n", wine_dbgstr_w(cmdline));
|
||||||
|
str = HeapAlloc(GetProcessHeap(), 0, (strlenW(cmdline) + 1) * sizeof(WCHAR));
|
||||||
|
if(!str) return NULL;
|
||||||
|
strcpyW(str, cmdline);
|
||||||
|
argv = HeapAlloc(GetProcessHeap(), 0, (max_argc + 1) * sizeof(LPWSTR));
|
||||||
|
if(!argv)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, str);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Split command line to separate arg-strings and fill argv */
|
||||||
|
state = OUTSIDE_ARG;
|
||||||
|
argc = 0;
|
||||||
|
while(*str)
|
||||||
|
{
|
||||||
|
new_arg = FALSE;
|
||||||
|
/* Check character */
|
||||||
|
if(isspaceW(*str)) /* white space */
|
||||||
|
{
|
||||||
|
if(state == INSIDE_ARG)
|
||||||
|
{
|
||||||
|
state = OUTSIDE_ARG;
|
||||||
|
*str = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(*str == '"') /* double quote */
|
||||||
|
switch(state)
|
||||||
|
{
|
||||||
|
case INSIDE_QUOTED_ARG:
|
||||||
|
state = OUTSIDE_ARG;
|
||||||
|
*str = 0;
|
||||||
|
break;
|
||||||
|
case INSIDE_ARG:
|
||||||
|
*str = 0;
|
||||||
|
/* Fall through */
|
||||||
|
case OUTSIDE_ARG:
|
||||||
|
if(!*++str) continue;
|
||||||
|
state = INSIDE_QUOTED_ARG;
|
||||||
|
new_arg = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else /* regular character */
|
||||||
|
if(state == OUTSIDE_ARG)
|
||||||
|
{
|
||||||
|
state = INSIDE_ARG;
|
||||||
|
new_arg = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add new argv entry, if need */
|
||||||
|
if(new_arg)
|
||||||
|
{
|
||||||
|
if(argc >= max_argc - 1)
|
||||||
|
{
|
||||||
|
/* Realloc argv here because there always should be
|
||||||
|
at least one reserved cell for terminating NULL */
|
||||||
|
max_argc *= 2;
|
||||||
|
argv = HeapReAlloc(GetProcessHeap(), 0, argv,
|
||||||
|
(max_argc + 1) * sizeof(LPWSTR));
|
||||||
|
if(!argv)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, str);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
argv[argc++] = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
argv[argc] = NULL;
|
||||||
|
*pargc = argc;
|
||||||
|
|
||||||
|
if(TRACE_ON(extrac32))
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < argc; i++)
|
||||||
|
WINE_TRACE("arg %d: %s\n", i, wine_dbgstr_w(argv[i]));
|
||||||
|
}
|
||||||
|
return argv;
|
||||||
|
}
|
||||||
|
|
||||||
int PASCAL wWinMain(HINSTANCE hInstance, HINSTANCE prev, LPWSTR cmdline, int show)
|
int PASCAL wWinMain(HINSTANCE hInstance, HINSTANCE prev, LPWSTR cmdline, int show)
|
||||||
{
|
{
|
||||||
LPWSTR *argv;
|
LPWSTR *argv;
|
||||||
|
@ -93,11 +185,17 @@ int PASCAL wWinMain(HINSTANCE hInstance, HINSTANCE prev, LPWSTR cmdline, int sho
|
||||||
LPCWSTR cabfile = NULL;
|
LPCWSTR cabfile = NULL;
|
||||||
|
|
||||||
path[0] = 0;
|
path[0] = 0;
|
||||||
argv = CommandLineToArgvW(cmdline, &argc);
|
|
||||||
|
/* Do not use CommandLineToArgvW() or __wgetmainargs() to parse
|
||||||
|
* command line for this program. It should treat each quote as argument
|
||||||
|
* delimiter. This doesn't match with behavior of mentioned functions.
|
||||||
|
* Do not use args provided by wmain() for the same reason.
|
||||||
|
*/
|
||||||
|
argv = get_extrac_args(cmdline, &argc);
|
||||||
|
|
||||||
if(!argv)
|
if(!argv)
|
||||||
{
|
{
|
||||||
WINE_ERR("Bad command line arguments\n");
|
WINE_ERR("Command line parsing failed\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue