From: Piotr Caban piotr@codeweavers.com
--- programs/xcopy/xcopy.c | 67 +++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 31 deletions(-)
diff --git a/programs/xcopy/xcopy.c b/programs/xcopy/xcopy.c index 072d44728a3..715fd8f167b 100644 --- a/programs/xcopy/xcopy.c +++ b/programs/xcopy/xcopy.c @@ -647,7 +647,7 @@ static inline BOOL is_whitespace(WCHAR c) return c == ' ' || c == '\t'; }
-static WCHAR *skip_whitespace(WCHAR *p) +static const WCHAR *skip_whitespace(const WCHAR *p) { for (; *p && is_whitespace(*p); p++); return p; @@ -662,10 +662,12 @@ static inline BOOL is_digit(WCHAR c) that lacks the escaped-quote logic of build_argv(), because literal double quotes are illegal in any of its arguments. Example: 'XCOPY "c:\DIR A" "c:DIR B"' is OK. */ -static int find_end_of_word(const WCHAR *word, WCHAR **end) +static int get_arg(const WCHAR **cmdline, WCHAR **arg) { + const WCHAR *ptr = *cmdline; BOOL in_quotes = FALSE; - const WCHAR *ptr = word; + int len; + for (;;) { for (; *ptr != '\0' && *ptr != '"' && (in_quotes || !is_whitespace(*ptr)); ptr++); @@ -679,7 +681,15 @@ static int find_end_of_word(const WCHAR *word, WCHAR **end) if (*ptr == '\0' || (!in_quotes && is_whitespace(*ptr))) break; } - *end = (WCHAR*)ptr; + + len = ptr - *cmdline; + *arg = malloc((len + 1) * sizeof(WCHAR)); + if (!*arg) + return RC_INITERROR; + memcpy(*arg, *cmdline, len * sizeof(WCHAR)); + (*arg)[len] = 0; + + *cmdline = skip_whitespace(ptr); return RC_OK; }
@@ -701,25 +711,20 @@ static int XCOPY_ParseCommandLine(WCHAR *suppliedsource, WCHAR *supplieddestination, DWORD *pflags) { DWORD flags = *pflags; - WCHAR *cmdline, *word, *end, *next; + const WCHAR *cmdline; + WCHAR *word; int rc;
- cmdline = _wcsdup(GetCommandLineW()); - if (cmdline == NULL) - exit(RC_INITERROR); - + cmdline = GetCommandLineW(); /* Skip first arg, which is the program name */ - if ((rc = find_end_of_word(cmdline, &word)) != RC_OK) + if ((rc = get_arg(&cmdline, &word)) != RC_OK) exit(rc); - word = skip_whitespace(word); + free(word);
- while (*word) + while (*cmdline) { - if ((rc = find_end_of_word(word, &end)) != RC_OK) + if ((rc = get_arg(&cmdline, &word)) != RC_OK) exit(rc); - - next = skip_whitespace(end); - *end = '\0'; WINE_TRACE("Processing Arg: '%s'\n", wine_dbgstr_w(word));
/* First non-switch parameter is source, second is destination */ @@ -739,12 +744,12 @@ static int XCOPY_ParseCommandLine(WCHAR *suppliedsource, but tests show it is done for each src file regardless of the destination */ int skip=0; - WCHAR *rest; + WCHAR *p = word, *rest;
- while (word[0]) { + while (*p) { rest = NULL;
- switch (toupper(word[1])) { + switch (toupper(p[1])) { case 'I': flags |= OPT_ASSUMEDIR; break; case 'S': flags |= OPT_RECURSIVE; break; case 'Q': flags |= OPT_QUIET; break; @@ -766,15 +771,15 @@ static int XCOPY_ParseCommandLine(WCHAR *suppliedsource,
/* E can be /E or /EXCLUDE */ case 'E': if (CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, - &word[1], 8, L"EXCLUDE:", -1) == CSTR_EQUAL) { - if (XCOPY_ProcessExcludeList(&word[9])) { + &p[1], 8, L"EXCLUDE:", -1) == CSTR_EQUAL) { + if (XCOPY_ProcessExcludeList(&p[9])) { XCOPY_FailMessage(ERROR_INVALID_PARAMETER); exit(RC_INITERROR); } else { flags |= OPT_EXCLUDELIST;
/* Do not support concatenated switches onto exclude lists yet */ - rest = end; + rest = p + wcslen(p); } } else { flags |= OPT_EMPTYDIR | OPT_RECURSIVE; @@ -782,9 +787,9 @@ static int XCOPY_ParseCommandLine(WCHAR *suppliedsource, break;
/* D can be /D or /D: */ - case 'D': if (word[2]==':' && is_digit(word[3])) { + case 'D': if (p[2]==':' && is_digit(p[3])) { SYSTEMTIME st; - WCHAR *pos = &word[3]; + WCHAR *pos = &p[3]; BOOL isError = FALSE; memset(&st, 0x00, sizeof(st));
@@ -835,9 +840,9 @@ static int XCOPY_ParseCommandLine(WCHAR *suppliedsource, } break;
- case '-': if (toupper(word[2])=='Y') { + case '-': if (toupper(p[2])=='Y') { flags &= ~OPT_NOPROMPT; - rest = &word[3]; /* Skip over 3 characters */ + rest = &p[3]; /* Skip over 3 characters */ } break; case '?': XCOPY_wprintf(XCOPY_LoadMessage(STRING_HELP)); @@ -846,13 +851,13 @@ static int XCOPY_ParseCommandLine(WCHAR *suppliedsource, WINE_FIXME("ignoring /V\n"); break; default: - WINE_TRACE("Unhandled parameter '%s'\n", wine_dbgstr_w(word)); - XCOPY_wprintf(XCOPY_LoadMessage(STRING_INVPARM), word); + WINE_TRACE("Unhandled parameter '%s'\n", wine_dbgstr_w(p)); + XCOPY_wprintf(XCOPY_LoadMessage(STRING_INVPARM), p); exit(RC_INITERROR); }
/* Unless overridden above, skip over the '/' and the first character */ - if (rest == NULL) rest = &word[2]; + if (rest == NULL) rest = &p[2];
/* By now, rest should point either to the null after the switch, or the beginning of the next switch if there @@ -861,11 +866,11 @@ static int XCOPY_ParseCommandLine(WCHAR *suppliedsource, WINE_FIXME("Unexpected characters found and ignored '%s'\n", wine_dbgstr_w(rest)); skip=1; } else { - word = rest; + p = rest; } } } - word = next; + free(word); }
/* Default the destination if not supplied */