Module: wine Branch: master Commit: d73c38fe9ab18900eb7f1e1a30570a3139501466 URL: http://source.winehq.org/git/wine.git/?a=commit;h=d73c38fe9ab18900eb7f1e1a30...
Author: Hans Leidekker hans@codeweavers.com Date: Tue Jun 6 09:20:16 2017 +0200
msiexec: Fix parsing of command lines where quoted strings and properties are not separated by whitespace.
Signed-off-by: Hans Leidekker hans@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
programs/msiexec/msiexec.c | 169 +++++++++++++++++++++++---------------------- 1 file changed, 87 insertions(+), 82 deletions(-)
diff --git a/programs/msiexec/msiexec.c b/programs/msiexec/msiexec.c index b7999d1..8dcd216 100644 --- a/programs/msiexec/msiexec.c +++ b/programs/msiexec/msiexec.c @@ -216,14 +216,6 @@ static DWORD msi_atou(LPCWSTR str) return ret; }
-static LPWSTR msi_strdup(LPCWSTR str) -{ - DWORD len = lstrlenW(str)+1; - LPWSTR ret = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*len); - lstrcpyW(ret, str); - return ret; -} - /* str1 is the same as str2, ignoring case */ static BOOL msi_strequal(LPCWSTR str1, LPCSTR str2) { @@ -413,90 +405,103 @@ static INT DoEmbedding( LPWSTR key )
enum chomp_state { - cs_whitespace, - cs_token, - cs_quote + CS_WHITESPACE, + CS_TOKEN, + CS_QUOTE };
-static int chomp( WCHAR *str ) +static int chomp( const WCHAR *in, WCHAR *out ) { - enum chomp_state state = cs_token; - WCHAR *p, *out; - int count = 1; - BOOL ignore; - - for( p = str, out = str; *p; p++ ) - { - ignore = TRUE; - switch( state ) - { - case cs_whitespace: - switch( *p ) - { - case ' ': - break; - case '"': - state = cs_quote; - count++; - break; - default: - count++; - ignore = FALSE; - state = cs_token; - } - break; - - case cs_token: - switch( *p ) - { - case '"': - state = cs_quote; - break; - case ' ': - state = cs_whitespace; - *out++ = 0; - break; - default: - ignore = FALSE; - } - break; - - case cs_quote: - switch( *p ) - { - case '"': - state = cs_token; - break; - default: - ignore = FALSE; - } - break; - } - if( !ignore ) - *out++ = *p; - } - - *out = 0; + enum chomp_state state = CS_TOKEN; + const WCHAR *p; + int count = 1; + BOOL ignore;
- return count; + for (p = in; *p; p++) + { + ignore = TRUE; + switch (state) + { + case CS_WHITESPACE: + switch (*p) + { + case ' ': + break; + case '"': + state = CS_QUOTE; + count++; + break; + default: + count++; + ignore = FALSE; + state = CS_TOKEN; + } + break; + + case CS_TOKEN: + switch (*p) + { + case '"': + state = CS_QUOTE; + break; + case ' ': + state = CS_WHITESPACE; + if (out) *out++ = 0; + break; + default: + if (p > in && p[-1] == '"') + { + if (out) *out++ = 0; + count++; + } + ignore = FALSE; + } + break; + + case CS_QUOTE: + switch (*p) + { + case '"': + state = CS_TOKEN; + break; + default: + ignore = FALSE; + } + break; + } + if (!ignore && out) *out++ = *p; + } + if (out) *out = 0; + return count; }
static void process_args( WCHAR *cmdline, int *pargc, WCHAR ***pargv ) { - WCHAR **argv, *p = msi_strdup(cmdline); - int i, n; + WCHAR **argv, *p; + int i, count;
- n = chomp( p ); - argv = HeapAlloc(GetProcessHeap(), 0, sizeof (WCHAR*)*(n+1)); - for( i=0; i<n; i++ ) - { - argv[i] = p; - p += lstrlenW(p) + 1; - } - argv[i] = NULL; + *pargc = 0; + *pargv = NULL; + + count = chomp( cmdline, NULL ); + if (!(p = HeapAlloc( GetProcessHeap(), 0, (lstrlenW(cmdline) + count + 1) * sizeof(WCHAR) ))) + return; + + count = chomp( cmdline, p ); + if (!(argv = HeapAlloc( GetProcessHeap(), 0, (count + 1) * sizeof(WCHAR *) ))) + { + HeapFree( GetProcessHeap(), 0, p ); + return; + } + for (i = 0; i < count; i++) + { + argv[i] = p; + p += lstrlenW( p ) + 1; + } + argv[i] = NULL;
- *pargc = n; - *pargv = argv; + *pargc = count; + *pargv = argv; }
static BOOL process_args_from_reg( const WCHAR *ident, int *pargc, WCHAR ***pargv )