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>
This commit is contained in:
Hans Leidekker 2017-06-06 09:20:16 +02:00 committed by Alexandre Julliard
parent 20c627d58c
commit d73c38fe9a
1 changed files with 85 additions and 80 deletions

View File

@ -216,14 +216,6 @@ static DWORD msi_atou(LPCWSTR str)
return ret; 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 */ /* str1 is the same as str2, ignoring case */
static BOOL msi_strequal(LPCWSTR str1, LPCSTR str2) static BOOL msi_strequal(LPCWSTR str1, LPCSTR str2)
{ {
@ -413,90 +405,103 @@ static INT DoEmbedding( LPWSTR key )
enum chomp_state enum chomp_state
{ {
cs_whitespace, CS_WHITESPACE,
cs_token, CS_TOKEN,
cs_quote CS_QUOTE
}; };
static int chomp( WCHAR *str ) static int chomp( const WCHAR *in, WCHAR *out )
{ {
enum chomp_state state = cs_token; enum chomp_state state = CS_TOKEN;
WCHAR *p, *out; const WCHAR *p;
int count = 1; int count = 1;
BOOL ignore; BOOL ignore;
for( p = str, out = str; *p; p++ ) for (p = in; *p; p++)
{ {
ignore = TRUE; ignore = TRUE;
switch( state ) switch (state)
{ {
case cs_whitespace: case CS_WHITESPACE:
switch( *p ) switch (*p)
{ {
case ' ': case ' ':
break; break;
case '"': case '"':
state = cs_quote; state = CS_QUOTE;
count++; count++;
break; break;
default: default:
count++; count++;
ignore = FALSE; ignore = FALSE;
state = cs_token; state = CS_TOKEN;
} }
break; break;
case cs_token: case CS_TOKEN:
switch( *p ) switch (*p)
{ {
case '"': case '"':
state = cs_quote; state = CS_QUOTE;
break; break;
case ' ': case ' ':
state = cs_whitespace; state = CS_WHITESPACE;
*out++ = 0; if (out) *out++ = 0;
break; break;
default: default:
ignore = FALSE; if (p > in && p[-1] == '"')
} {
break; if (out) *out++ = 0;
count++;
}
ignore = FALSE;
}
break;
case cs_quote: case CS_QUOTE:
switch( *p ) switch (*p)
{ {
case '"': case '"':
state = cs_token; state = CS_TOKEN;
break; break;
default: default:
ignore = FALSE; ignore = FALSE;
} }
break; break;
} }
if( !ignore ) if (!ignore && out) *out++ = *p;
*out++ = *p; }
} if (out) *out = 0;
return count;
*out = 0;
return count;
} }
static void process_args( WCHAR *cmdline, int *pargc, WCHAR ***pargv ) static void process_args( WCHAR *cmdline, int *pargc, WCHAR ***pargv )
{ {
WCHAR **argv, *p = msi_strdup(cmdline); WCHAR **argv, *p;
int i, n; int i, count;
n = chomp( p ); *pargc = 0;
argv = HeapAlloc(GetProcessHeap(), 0, sizeof (WCHAR*)*(n+1)); *pargv = NULL;
for( i=0; i<n; i++ )
{
argv[i] = p;
p += lstrlenW(p) + 1;
}
argv[i] = NULL;
*pargc = n; count = chomp( cmdline, NULL );
*pargv = argv; 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 = count;
*pargv = argv;
} }
static BOOL process_args_from_reg( const WCHAR *ident, int *pargc, WCHAR ***pargv ) static BOOL process_args_from_reg( const WCHAR *ident, int *pargc, WCHAR ***pargv )