[MSIEXEC] Sync with Wine Staging 2.16. CORE-13762
authorAmine Khaldi <amine.khaldi@reactos.org>
Sun, 8 Oct 2017 08:33:23 +0000 (09:33 +0100)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sun, 8 Oct 2017 11:08:41 +0000 (12:08 +0100)
d73c38f msiexec: Fix parsing of command lines where quoted strings and properties are not separated by whitespace.

base/system/msiexec/msiexec.c
media/doc/README.WINE

index 44f1f28..f215562 100644 (file)
@@ -212,14 +212,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)
 {
@@ -409,90 +401,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 )
index 778f42f..1eca9ef 100644 (file)
@@ -243,7 +243,7 @@ reactos/base/applications/wordpad           # Synced to WineStaging-1.9.16
 reactos/base/applications/write             # Synced to WineStaging-2.9
 reactos/base/services/rpcss                 # Synced to WineStaging-1.9.16
 reactos/base/system/expand                  # Synced to WineStaging-2.9
-reactos/base/system/msiexec                 # Synced to WineStaging-2.9
+reactos/base/system/msiexec                 # Synced to WineStaging-2.16
 reactos/modules/rosapps/winfile             # Autosync
 
 In addition the following libs, dlls and source files are mostly based on code ported