* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#define WIN32_NO_STATUS
-#define _INC_WINDOWS
-#define COM_NO_WINDOWS_H
-#include <stdarg.h>
-#include <windef.h>
-#include <winbase.h>
+#include "precomp.h"
+
#include <winreg.h>
-#include <winsvc.h>
#include <winuser.h>
#include <msi.h>
#include <objbase.h>
-#include <stdio.h>
-#include <wine/debug.h>
#include <wine/unicode.h>
-WINE_DEFAULT_DEBUG_CHANNEL(msiexec);
-
typedef HRESULT (WINAPI *DLLREGISTERSERVER)(void);
typedef HRESULT (WINAPI *DLLUNREGISTERSERVER)(void);
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)
{
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, ignore;
-
- for( p = str, out = str; *p; p++ )
- {
- ignore = 1;
- switch( state )
- {
- case cs_whitespace:
- switch( *p )
- {
- case ' ':
- break;
- case '"':
- state = cs_quote;
- count++;
- break;
- default:
- count++;
- ignore = 0;
- state = cs_token;
- }
- break;
-
- case cs_token:
- switch( *p )
- {
- case '"':
- state = cs_quote;
- break;
- case ' ':
- state = cs_whitespace;
- *out++ = 0;
- break;
- default:
- ignore = 0;
- }
- break;
-
- case cs_quote:
- switch( *p )
- {
- case '"':
- state = cs_token;
- break;
- default:
- ignore = 0;
- }
- 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 )
WINE_TRACE("argvW[%d] = %s\n", i, wine_dbgstr_w(argvW[i]));
PackageName = argvW[i];
StringListAppend(&property_list, ActionAdmin);
+ WINE_FIXME("Administrative installs are not currently supported\n");
}
else if(msi_option_prefix(argvW[i], "f"))
{
ExitProcess(1);
}
}
- else if(msi_option_equal(argvW[i], "p"))
+ else if(msi_option_equal(argvW[i], "p") || msi_option_equal(argvW[i], "update"))
{
FunctionPatch = TRUE;
i++;
{
InstallUILevel = INSTALLUILEVEL_NONE;
}
- else if(msi_strequal(argvW[i]+2, "b"))
- {
- InstallUILevel = INSTALLUILEVEL_BASIC;
- }
else if(msi_strequal(argvW[i]+2, "r"))
{
InstallUILevel = INSTALLUILEVEL_REDUCED;
{
InstallUILevel = INSTALLUILEVEL_NONE|INSTALLUILEVEL_ENDDIALOG;
}
- else if(msi_strequal(argvW[i]+2, "b+"))
- {
- InstallUILevel = INSTALLUILEVEL_BASIC|INSTALLUILEVEL_ENDDIALOG;
- }
- else if(msi_strequal(argvW[i]+2, "b-"))
- {
- InstallUILevel = INSTALLUILEVEL_BASIC|INSTALLUILEVEL_PROGRESSONLY;
- }
- else if(msi_strequal(argvW[i]+2, "b+!"))
- {
- InstallUILevel = INSTALLUILEVEL_BASIC|INSTALLUILEVEL_ENDDIALOG;
- WINE_FIXME("Unknown modifier: !\n");
- }
- else if(msi_strequal(argvW[i]+2, "b!"))
+ else if(msi_strprefix(argvW[i]+2, "b"))
{
- InstallUILevel = INSTALLUILEVEL_BASIC;
- WINE_FIXME("Unknown modifier: !\n");
+ const WCHAR *ptr = argvW[i] + 3;
+
+ InstallUILevel = INSTALLUILEVEL_BASIC;
+
+ while (*ptr)
+ {
+ if (msi_strprefix(ptr, "+"))
+ InstallUILevel |= INSTALLUILEVEL_ENDDIALOG;
+ if (msi_strprefix(ptr, "-"))
+ InstallUILevel |= INSTALLUILEVEL_PROGRESSONLY;
+ if (msi_strprefix(ptr, "!"))
+ {
+ WINE_FIXME("Unhandled modifier: !\n");
+ InstallUILevel |= INSTALLUILEVEL_HIDECANCEL;
+ }
+ ptr++;
+ }
}
else
{
wine_dbgstr_w(argvW[i]+2));
}
}
+ else if(msi_option_equal(argvW[i], "passive"))
+ {
+ static const WCHAR rebootpromptW[] =
+ {'R','E','B','O','O','T','P','R','O','M','P','T','=','"','S','"',0};
+
+ InstallUILevel = INSTALLUILEVEL_BASIC|INSTALLUILEVEL_PROGRESSONLY|INSTALLUILEVEL_HIDECANCEL;
+ StringListAppend(&property_list, rebootpromptW);
+ }
else if(msi_option_equal(argvW[i], "y"))
{
FunctionDllRegisterServer = TRUE;