[MSI] Apply Wine commit fdac39f by Hans Leidekker: Pass correct length to GetDateForm...
[reactos.git] / dll / win32 / msi / package.c
index a050b2e..3e0ae71 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#define NONAMELESSUNION
-#define NONAMELESSSTRUCT
-#define COBJMACROS
-
-#include <stdarg.h>
-#include "windef.h"
-#include "winbase.h"
-#include "winreg.h"
-#include "winnls.h"
-#include "shlwapi.h"
-#include "wingdi.h"
-#include "wine/debug.h"
-#include "msi.h"
-#include "msiquery.h"
-#include "objidl.h"
-#include "wincrypt.h"
-#include "winuser.h"
-#include "wininet.h"
-#include "winver.h"
-#include "urlmon.h"
-#include "shlobj.h"
-#include "wine/unicode.h"
-#include "objbase.h"
-#include "msidefs.h"
-#include "sddl.h"
-
 #include "msipriv.h"
-#include "msiserver.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(msi);
-
-static void remove_tracked_tempfiles( MSIPACKAGE *package )
-{
-    struct list *item, *cursor;
 
-    LIST_FOR_EACH_SAFE( item, cursor, &package->tempfiles )
-    {
-        MSITEMPFILE *temp = LIST_ENTRY( item, MSITEMPFILE, entry );
+#include <wininet.h>
 
-        list_remove( &temp->entry );
-        TRACE("deleting temp file %s\n", debugstr_w( temp->Path ));
-        DeleteFileW( temp->Path );
-        msi_free( temp->Path );
-        msi_free( temp );
-    }
-}
+WINE_DEFAULT_DEBUG_CHANNEL(msi);
 
 static void free_feature( MSIFEATURE *feature )
 {
@@ -154,7 +113,6 @@ void msi_free_action_script( MSIPACKAGE *package, UINT script )
 
 static void free_package_structures( MSIPACKAGE *package )
 {
-    INT i;
     struct list *item, *cursor;
 
     LIST_FOR_EACH_SAFE( item, cursor, &package->features )
@@ -171,6 +129,22 @@ static void free_package_structures( MSIPACKAGE *package )
         free_folder( folder );
     }
 
+    LIST_FOR_EACH_SAFE( item, cursor, &package->files )
+    {
+        MSIFILE *file = LIST_ENTRY( item, MSIFILE, entry );
+
+        list_remove( &file->entry );
+        msi_free( file->File );
+        msi_free( file->FileName );
+        msi_free( file->ShortName );
+        msi_free( file->LongName );
+        msi_free( file->Version );
+        msi_free( file->Language );
+        if (msi_is_global_assembly( file->Component )) DeleteFileW( file->TargetPath );
+        msi_free( file->TargetPath );
+        msi_free( file );
+    }
+
     LIST_FOR_EACH_SAFE( item, cursor, &package->components )
     {
         MSICOMPONENT *comp = LIST_ENTRY( item, MSICOMPONENT, entry );
@@ -186,19 +160,13 @@ static void free_package_structures( MSIPACKAGE *package )
         msi_free( comp );
     }
 
-    LIST_FOR_EACH_SAFE( item, cursor, &package->files )
+    LIST_FOR_EACH_SAFE( item, cursor, &package->filepatches )
     {
-        MSIFILE *file = LIST_ENTRY( item, MSIFILE, entry );
+        MSIFILEPATCH *patch = LIST_ENTRY( item, MSIFILEPATCH, entry );
 
-        list_remove( &file->entry );
-        msi_free( file->File );
-        msi_free( file->FileName );
-        msi_free( file->ShortName );
-        msi_free( file->LongName );
-        msi_free( file->Version );
-        msi_free( file->Language );
-        msi_free( file->TargetPath );
-        msi_free( file );
+        list_remove( &patch->entry );
+        msi_free( patch->path );
+        msi_free( patch );
     }
 
     /* clean up extension, progid, class and verb structures */
@@ -283,11 +251,14 @@ static void free_package_structures( MSIPACKAGE *package )
 
     if (package->script)
     {
+        INT i;
+        UINT j;
+
         for (i = 0; i < SCRIPT_MAX; i++)
             msi_free_action_script( package, i );
 
-        for (i = 0; i < package->script->UniqueActionsCount; i++)
-            msi_free( package->script->UniqueActions[i] );
+        for (j = 0; j < package->script->UniqueActionsCount; j++)
+            msi_free( package->script->UniqueActions[j] );
 
         msi_free( package->script->UniqueActions );
         msi_free( package->script );
@@ -334,12 +305,11 @@ static void free_package_structures( MSIPACKAGE *package )
     msi_free( package->ProductCode );
     msi_free( package->ActionFormat );
     msi_free( package->LastAction );
+    msi_free( package->LastActionTemplate );
     msi_free( package->langids );
 
-    remove_tracked_tempfiles(package);
-
     /* cleanup control event subscriptions */
-    ControlEvent_CleanupSubscriptions( package );
+    msi_event_cleanup_all_subscriptions( package );
 }
 
 static void MSI_FreePackage( MSIOBJECTHDR *arg)
@@ -357,6 +327,7 @@ static void MSI_FreePackage( MSIOBJECTHDR *arg)
 
     if (package->delete_on_close) DeleteFileW( package->localfile );
     msi_free( package->localfile );
+    MSI_ProcessMessage(NULL, INSTALLMESSAGE_TERMINATE, 0);
 }
 
 static UINT create_temp_property_table(MSIPACKAGE *package)
@@ -384,7 +355,7 @@ static UINT create_temp_property_table(MSIPACKAGE *package)
     return rc;
 }
 
-UINT msi_clone_properties(MSIPACKAGE *package)
+UINT msi_clone_properties( MSIDATABASE *db )
 {
     static const WCHAR query_select[] = {
         'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
@@ -401,7 +372,7 @@ UINT msi_clone_properties(MSIPACKAGE *package)
     MSIQUERY *view_select;
     UINT rc;
 
-    rc = MSI_DatabaseOpenViewW( package->db, query_select, &view_select );
+    rc = MSI_DatabaseOpenViewW( db, query_select, &view_select );
     if (rc != ERROR_SUCCESS)
         return rc;
 
@@ -422,7 +393,7 @@ UINT msi_clone_properties(MSIPACKAGE *package)
         if (rc != ERROR_SUCCESS)
             break;
 
-        rc = MSI_DatabaseOpenViewW( package->db, query_insert, &view_insert );
+        rc = MSI_DatabaseOpenViewW( db, query_insert, &view_insert );
         if (rc != ERROR_SUCCESS)
         {
             msiobj_release( &rec_select->hdr );
@@ -438,7 +409,7 @@ UINT msi_clone_properties(MSIPACKAGE *package)
 
             TRACE("insert failed, trying update\n");
 
-            rc = MSI_DatabaseOpenViewW( package->db, query_update, &view_update );
+            rc = MSI_DatabaseOpenViewW( db, query_update, &view_update );
             if (rc != ERROR_SUCCESS)
             {
                 WARN("open view failed %u\n", rc);
@@ -483,7 +454,7 @@ static UINT set_installed_prop( MSIPACKAGE *package )
     if (r == ERROR_SUCCESS)
     {
         RegCloseKey( hkey );
-        msi_set_property( package->db, szInstalled, szOne );
+        msi_set_property( package->db, szInstalled, szOne, -1 );
     }
     return r;
 }
@@ -525,7 +496,7 @@ static UINT set_user_sid_prop( MSIPACKAGE *package )
     if (!ConvertSidToStringSidW( psid, &sid_str ))
         goto done;
 
-    r = msi_set_property( package->db, szUserSID, sid_str );
+    r = msi_set_property( package->db, szUserSID, sid_str, -1 );
 
 done:
     LocalFree( sid_str );
@@ -638,10 +609,12 @@ static void set_msi_assembly_prop(MSIPACKAGE *package)
         return;
 
     size = GetFileVersionInfoSizeW(fusion, &handle);
-    if (!size) return;
+    if (!size)
+        goto done;
 
     version = msi_alloc(size);
-    if (!version) return;
+    if (!version)
+        goto done;
 
     if (!GetFileVersionInfoW(fusion, handle, size, version))
         goto done;
@@ -657,7 +630,7 @@ static void set_msi_assembly_prop(MSIPACKAGE *package)
     if (!val_len || !verstr)
         goto done;
 
-    msi_set_property(package->db, netasm, verstr);
+    msi_set_property( package->db, netasm, verstr, -1 );
 
 done:
     msi_free(fusion);
@@ -675,7 +648,6 @@ static VOID set_installer_properties(MSIPACKAGE *package)
     HKEY hkey;
     LPWSTR username, companyname;
     SYSTEM_INFO sys_info;
-    SYSTEMTIME systemtime;
     LANGID langid;
 
     static const WCHAR szCommonFilesFolder[] = {'C','o','m','m','o','n','F','i','l','e','s','F','o','l','d','e','r',0};
@@ -737,8 +709,6 @@ static VOID set_installer_properties(MSIPACKAGE *package)
     };
     static const WCHAR szUSERNAME[] = {'U','S','E','R','N','A','M','E',0};
     static const WCHAR szCOMPANYNAME[] = {'C','O','M','P','A','N','Y','N','A','M','E',0};
-    static const WCHAR szDate[] = {'D','a','t','e',0};
-    static const WCHAR szTime[] = {'T','i','m','e',0};
     static const WCHAR szUserLanguageID[] = {'U','s','e','r','L','a','n','g','u','a','g','e','I','D',0};
     static const WCHAR szSystemLangID[] = {'S','y','s','t','e','m','L','a','n','g','u','a','g','e','I','D',0};
     static const WCHAR szProductState[] = {'P','r','o','d','u','c','t','S','t','a','t','e',0};
@@ -757,182 +727,182 @@ static VOID set_installer_properties(MSIPACKAGE *package)
 
     SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szCommonAppDataFolder, pth);
+    msi_set_property( package->db, szCommonAppDataFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_FAVORITES, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szFavoritesFolder, pth);
+    msi_set_property( package->db, szFavoritesFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_FONTS, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szFontsFolder, pth);
+    msi_set_property( package->db, szFontsFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_SENDTO, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szSendToFolder, pth);
+    msi_set_property( package->db, szSendToFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_STARTMENU, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szStartMenuFolder, pth);
+    msi_set_property( package->db, szStartMenuFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_STARTUP, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szStartupFolder, pth);
+    msi_set_property( package->db, szStartupFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_TEMPLATES, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szTemplateFolder, pth);
+    msi_set_property( package->db, szTemplateFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szDesktopFolder, pth);
+    msi_set_property( package->db, szDesktopFolder, pth, -1 );
 
     /* FIXME: set to AllUsers profile path if ALLUSERS is set */
     SHGetFolderPathW(NULL, CSIDL_PROGRAMS, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szProgramMenuFolder, pth);
+    msi_set_property( package->db, szProgramMenuFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_ADMINTOOLS, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szAdminToolsFolder, pth);
+    msi_set_property( package->db, szAdminToolsFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szAppDataFolder, pth);
+    msi_set_property( package->db, szAppDataFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_SYSTEM, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szSystemFolder, pth);
-    msi_set_property(package->db, szSystem16Folder, pth);
+    msi_set_property( package->db, szSystemFolder, pth, -1 );
+    msi_set_property( package->db, szSystem16Folder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szLocalAppDataFolder, pth);
+    msi_set_property( package->db, szLocalAppDataFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_MYPICTURES, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szMyPicturesFolder, pth);
+    msi_set_property( package->db, szMyPicturesFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szPersonalFolder, pth);
+    msi_set_property( package->db, szPersonalFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szWindowsFolder, pth);
+    msi_set_property( package->db, szWindowsFolder, pth, -1 );
     
     SHGetFolderPathW(NULL, CSIDL_PRINTHOOD, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szPrintHoodFolder, pth);
+    msi_set_property( package->db, szPrintHoodFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_NETHOOD, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szNetHoodFolder, pth);
+    msi_set_property( package->db, szNetHoodFolder, pth, -1 );
 
     SHGetFolderPathW(NULL, CSIDL_RECENT, NULL, 0, pth);
     strcatW(pth, szBackSlash);
-    msi_set_property(package->db, szRecentFolder, pth);
+    msi_set_property( package->db, szRecentFolder, pth, -1 );
 
     /* Physical Memory is specified in MB. Using total amount. */
     msex.dwLength = sizeof(msex);
     GlobalMemoryStatusEx( &msex );
-    sprintfW( bufstr, szIntFormat, (int)(msex.ullTotalPhys / 1024 / 1024) );
-    msi_set_property(package->db, szPhysicalMemory, bufstr);
+    len = sprintfW( bufstr, szIntFormat, (int)(msex.ullTotalPhys / 1024 / 1024) );
+    msi_set_property( package->db, szPhysicalMemory, bufstr, len );
 
     SHGetFolderPathW(NULL, CSIDL_WINDOWS, NULL, 0, pth);
     ptr = strchrW(pth,'\\');
     if (ptr) *(ptr + 1) = 0;
-    msi_set_property(package->db, szWindowsVolume, pth);
+    msi_set_property( package->db, szWindowsVolume, pth, -1 );
     
-    GetTempPathW(MAX_PATH,pth);
-    msi_set_property(package->db, szTempFolder, pth);
+    len = GetTempPathW(MAX_PATH, pth);
+    msi_set_property( package->db, szTempFolder, pth, len );
 
     /* in a wine environment the user is always admin and privileged */
-    msi_set_property(package->db, szAdminUser, szOne);
-    msi_set_property(package->db, szPrivileged, szOne);
+    msi_set_property( package->db, szAdminUser, szOne, -1 );
+    msi_set_property( package->db, szPrivileged, szOne, -1 );
 
     /* set the os things */
     OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
     GetVersionExW((OSVERSIONINFOW *)&OSVersion);
     verval = OSVersion.dwMinorVersion + OSVersion.dwMajorVersion * 100;
-    sprintfW(verstr, szFormat, verval);
+    len = sprintfW( verstr, szFormat, verval );
     switch (OSVersion.dwPlatformId)
     {
         case VER_PLATFORM_WIN32_WINDOWS:    
-            msi_set_property(package->db, szVersion9x, verstr);
+            msi_set_property( package->db, szVersion9x, verstr, len );
             break;
         case VER_PLATFORM_WIN32_NT:
-            msi_set_property(package->db, szVersionNT, verstr);
-            sprintfW(verstr, szFormat,OSVersion.wProductType);
-            msi_set_property(package->db, szMsiNTProductType, verstr);
+            msi_set_property( package->db, szVersionNT, verstr, len );
+            len = sprintfW( bufstr, szFormat,OSVersion.wProductType );
+            msi_set_property( package->db, szMsiNTProductType, bufstr, len );
             break;
     }
-    sprintfW(verstr, szFormat, OSVersion.dwBuildNumber);
-    msi_set_property(package->db, szWindowsBuild, verstr);
-    sprintfW(verstr, szFormat, OSVersion.wServicePackMajor);
-    msi_set_property(package->db, szServicePackLevel, verstr);
+    len = sprintfW( bufstr, szFormat, OSVersion.dwBuildNumber );
+    msi_set_property( package->db, szWindowsBuild, bufstr, len );
+    len = sprintfW( bufstr, szFormat, OSVersion.wServicePackMajor );
+    msi_set_property( package->db, szServicePackLevel, bufstr, len );
 
-    sprintfW( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION);
-    msi_set_property( package->db, szVersionMsi, bufstr );
-    sprintfW( bufstr, szFormat, MSI_MAJORVERSION * 100);
-    msi_set_property( package->db, szVersionDatabase, bufstr );
+    len = sprintfW( bufstr, szFormat2, MSI_MAJORVERSION, MSI_MINORVERSION );
+    msi_set_property( package->db, szVersionMsi, bufstr, len );
+    len = sprintfW( bufstr, szFormat, MSI_MAJORVERSION * 100 );
+    msi_set_property( package->db, szVersionDatabase, bufstr, len );
 
     GetNativeSystemInfo( &sys_info );
-    sprintfW( bufstr, szIntFormat, sys_info.wProcessorLevel );
-    msi_set_property( package->db, szIntel, bufstr );
+    len = sprintfW( bufstr, szIntFormat, sys_info.wProcessorLevel );
+    msi_set_property( package->db, szIntel, bufstr, len );
     if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
     {
         GetSystemDirectoryW( pth, MAX_PATH );
         PathAddBackslashW( pth );
-        msi_set_property( package->db, szSystemFolder, pth );
+        msi_set_property( package->db, szSystemFolder, pth, -1 );
 
         SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES, NULL, 0, pth );
         PathAddBackslashW( pth );
-        msi_set_property( package->db, szProgramFilesFolder, pth );
+        msi_set_property( package->db, szProgramFilesFolder, pth, -1 );
 
         SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, pth );
         PathAddBackslashW( pth );
-        msi_set_property( package->db, szCommonFilesFolder, pth );
+        msi_set_property( package->db, szCommonFilesFolder, pth, -1 );
     }
     else if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
     {
-        msi_set_property( package->db, szMsiAMD64, bufstr );
-        msi_set_property( package->db, szMsix64, bufstr );
-        msi_set_property( package->db, szVersionNT64, verstr );
+        msi_set_property( package->db, szMsiAMD64, bufstr, -1 );
+        msi_set_property( package->db, szMsix64, bufstr, -1 );
+        msi_set_property( package->db, szVersionNT64, verstr, -1 );
 
         GetSystemDirectoryW( pth, MAX_PATH );
         PathAddBackslashW( pth );
-        msi_set_property( package->db, szSystem64Folder, pth );
+        msi_set_property( package->db, szSystem64Folder, pth, -1 );
 
         GetSystemWow64DirectoryW( pth, MAX_PATH );
         PathAddBackslashW( pth );
-        msi_set_property( package->db, szSystemFolder, pth );
+        msi_set_property( package->db, szSystemFolder, pth, -1 );
 
         SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES, NULL, 0, pth );
         PathAddBackslashW( pth );
-        msi_set_property( package->db, szProgramFiles64Folder, pth );
+        msi_set_property( package->db, szProgramFiles64Folder, pth, -1 );
 
         SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILESX86, NULL, 0, pth );
         PathAddBackslashW( pth );
-        msi_set_property( package->db, szProgramFilesFolder, pth );
+        msi_set_property( package->db, szProgramFilesFolder, pth, -1 );
 
         SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, pth );
         PathAddBackslashW( pth );
-        msi_set_property( package->db, szCommonFiles64Folder, pth );
+        msi_set_property( package->db, szCommonFiles64Folder, pth, -1 );
 
         SHGetFolderPathW( NULL, CSIDL_PROGRAM_FILES_COMMONX86, NULL, 0, pth );
         PathAddBackslashW( pth );
-        msi_set_property( package->db, szCommonFilesFolder, pth );
+        msi_set_property( package->db, szCommonFilesFolder, pth, -1 );
     }
 
     /* Screen properties. */
     dc = GetDC(0);
-    sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, HORZRES ) );
-    msi_set_property( package->db, szScreenX, bufstr );
-    sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, VERTRES ));
-    msi_set_property( package->db, szScreenY, bufstr );
-    sprintfW( bufstr, szIntFormat, GetDeviceCaps( dc, BITSPIXEL ));
-    msi_set_property( package->db, szColorBits, bufstr );
+    len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, HORZRES) );
+    msi_set_property( package->db, szScreenX, bufstr, len );
+    len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, VERTRES) );
+    msi_set_property( package->db, szScreenY, bufstr, len );
+    len = sprintfW( bufstr, szIntFormat, GetDeviceCaps(dc, BITSPIXEL) );
+    msi_set_property( package->db, szColorBits, bufstr, len );
     ReleaseDC(0, dc);
 
     /* USERNAME and COMPANYNAME */
@@ -944,10 +914,10 @@ static VOID set_installer_properties(MSIPACKAGE *package)
     {
         if (!username &&
             (username = msi_reg_get_val_str( hkey, szDefName )))
-            msi_set_property( package->db, szUSERNAME, username );
+            msi_set_property( package->db, szUSERNAME, username, -1 );
         if (!companyname &&
             (companyname = msi_reg_get_val_str( hkey, szDefCompany )))
-            msi_set_property( package->db, szCOMPANYNAME, companyname );
+            msi_set_property( package->db, szCOMPANYNAME, companyname, -1 );
         CloseHandle( hkey );
     }
     if ((!username || !companyname) &&
@@ -955,10 +925,10 @@ static VOID set_installer_properties(MSIPACKAGE *package)
     {
         if (!username &&
             (username = msi_reg_get_val_str( hkey, szRegisteredUser )))
-            msi_set_property( package->db, szUSERNAME, username );
+            msi_set_property( package->db, szUSERNAME, username, -1 );
         if (!companyname &&
             (companyname = msi_reg_get_val_str( hkey, szRegisteredOrganization )))
-            msi_set_property( package->db, szCOMPANYNAME, companyname );
+            msi_set_property( package->db, szCOMPANYNAME, companyname, -1 );
         CloseHandle( hkey );
     }
     msi_free( username );
@@ -967,34 +937,18 @@ static VOID set_installer_properties(MSIPACKAGE *package)
     if ( set_user_sid_prop( package ) != ERROR_SUCCESS)
         ERR("Failed to set the UserSID property\n");
 
-    /* Date and time properties */
-    GetSystemTime( &systemtime );
-    if (GetDateFormatW( LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systemtime,
-                        NULL, bufstr, sizeof(bufstr)/sizeof(bufstr[0]) ))
-        msi_set_property( package->db, szDate, bufstr );
-    else
-        ERR("Couldn't set Date property: GetDateFormat failed with error %d\n", GetLastError());
-
-    if (GetTimeFormatW( LOCALE_USER_DEFAULT,
-                        TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER,
-                        &systemtime, NULL, bufstr,
-                        sizeof(bufstr)/sizeof(bufstr[0]) ))
-        msi_set_property( package->db, szTime, bufstr );
-    else
-        ERR("Couldn't set Time property: GetTimeFormat failed with error %d\n", GetLastError());
-
     set_msi_assembly_prop( package );
 
     langid = GetUserDefaultLangID();
-    sprintfW(bufstr, szIntFormat, langid);
-    msi_set_property( package->db, szUserLanguageID, bufstr );
+    len = sprintfW( bufstr, szIntFormat, langid );
+    msi_set_property( package->db, szUserLanguageID, bufstr, len );
 
     langid = GetSystemDefaultLangID();
-    sprintfW(bufstr, szIntFormat, langid);
-    msi_set_property( package->db, szSystemLangID, bufstr );
+    len = sprintfW( bufstr, szIntFormat, langid );
+    msi_set_property( package->db, szSystemLangID, bufstr, len );
 
-    sprintfW(bufstr, szIntFormat, MsiQueryProductStateW(package->ProductCode));
-    msi_set_property( package->db, szProductState, bufstr );
+    len = sprintfW( bufstr, szIntFormat, MsiQueryProductStateW(package->ProductCode) );
+    msi_set_property( package->db, szProductState, bufstr, len );
 
     len = 0;
     if (!GetUserNameW( NULL, &len ) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
@@ -1003,7 +957,7 @@ static VOID set_installer_properties(MSIPACKAGE *package)
         if ((username = msi_alloc( len * sizeof(WCHAR) )))
         {
             if (GetUserNameW( username, &len ))
-                msi_set_property( package->db, szLogonUser, username );
+                msi_set_property( package->db, szLogonUser, username, len - 1 );
             msi_free( username );
         }
     }
@@ -1014,79 +968,12 @@ static VOID set_installer_properties(MSIPACKAGE *package)
         if ((computername = msi_alloc( len * sizeof(WCHAR) )))
         {
             if (GetComputerNameW( computername, &len ))
-                msi_set_property( package->db, szComputerName, computername );
+                msi_set_property( package->db, szComputerName, computername, len );
             msi_free( computername );
         }
     }
 }
 
-static UINT msi_load_summary_properties( MSIPACKAGE *package )
-{
-    UINT rc;
-    MSIHANDLE suminfo;
-    MSIHANDLE hdb = alloc_msihandle( &package->db->hdr );
-    INT count;
-    DWORD len;
-    LPWSTR package_code;
-    static const WCHAR szPackageCode[] = {
-        'P','a','c','k','a','g','e','C','o','d','e',0};
-
-    if (!hdb) {
-        ERR("Unable to allocate handle\n");
-        return ERROR_OUTOFMEMORY;
-    }
-
-    rc = MsiGetSummaryInformationW( hdb, NULL, 0, &suminfo );
-    MsiCloseHandle(hdb);
-    if (rc != ERROR_SUCCESS)
-    {
-        ERR("Unable to open Summary Information\n");
-        return rc;
-    }
-
-    rc = MsiSummaryInfoGetPropertyW( suminfo, PID_PAGECOUNT, NULL,
-                                     &count, NULL, NULL, NULL );
-    if (rc != ERROR_SUCCESS)
-    {
-        WARN("Unable to query page count: %d\n", rc);
-        goto done;
-    }
-
-    /* load package code property */
-    len = 0;
-    rc = MsiSummaryInfoGetPropertyW( suminfo, PID_REVNUMBER, NULL,
-                                     NULL, NULL, NULL, &len );
-    if (rc != ERROR_MORE_DATA)
-    {
-        WARN("Unable to query revision number: %d\n", rc);
-        rc = ERROR_FUNCTION_FAILED;
-        goto done;
-    }
-
-    len++;
-    package_code = msi_alloc( len * sizeof(WCHAR) );
-    rc = MsiSummaryInfoGetPropertyW( suminfo, PID_REVNUMBER, NULL,
-                                     NULL, NULL, package_code, &len );
-    if (rc != ERROR_SUCCESS)
-    {
-        WARN("Unable to query rev number: %d\n", rc);
-        goto done;
-    }
-
-    msi_set_property( package->db, szPackageCode, package_code );
-    msi_free( package_code );
-
-    /* load package attributes */
-    count = 0;
-    MsiSummaryInfoGetPropertyW( suminfo, PID_WORDCOUNT, NULL,
-                                &count, NULL, NULL, NULL );
-    package->WordCount = count;
-
-done:
-    MsiCloseHandle(suminfo);
-    return rc;
-}
-
 static MSIPACKAGE *msi_alloc_package( void )
 {
     MSIPACKAGE *package;
@@ -1141,9 +1028,9 @@ void msi_adjust_privilege_properties( MSIPACKAGE *package )
     if (msi_get_property_int( package->db, szAllUsers, 0 ) == 2)
     {
         TRACE("resetting ALLUSERS property from 2 to 1\n");
-        msi_set_property( package->db, szAllUsers, szOne );
+        msi_set_property( package->db, szAllUsers, szOne, -1 );
     }
-    msi_set_property( package->db, szAdminUser, szOne );
+    msi_set_property( package->db, szAdminUser, szOne, -1 );
 }
 
 MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url )
@@ -1151,6 +1038,7 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url )
     static const WCHAR fmtW[] = {'%','u',0};
     MSIPACKAGE *package;
     WCHAR uilevel[11];
+    int len;
     UINT r;
 
     TRACE("%p\n", db);
@@ -1161,25 +1049,27 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url )
         msiobj_addref( &db->hdr );
         package->db = db;
 
+        package->LastAction = NULL;
+        package->LastActionTemplate = NULL;
+        package->LastActionResult = MSI_NULL_INTEGER;
         package->WordCount = 0;
         package->PackagePath = strdupW( db->path );
         package->BaseURL = strdupW( base_url );
 
         create_temp_property_table( package );
-        msi_clone_properties( package );
+        msi_clone_properties( package->db );
         msi_adjust_privilege_properties( package );
 
         package->ProductCode = msi_dup_property( package->db, szProductCode );
         package->script = msi_alloc_zero( sizeof(MSISCRIPT) );
 
-        set_installed_prop( package );
         set_installer_properties( package );
 
         package->ui_level = gUILevel;
-        sprintfW( uilevel, fmtW, gUILevel & INSTALLUILEVEL_MASK );
-        msi_set_property(package->db, szUILevel, uilevel);
+        len = sprintfW( uilevel, fmtW, gUILevel & INSTALLUILEVEL_MASK );
+        msi_set_property( package->db, szUILevel, uilevel, len );
 
-        r = msi_load_summary_properties( package );
+        r = msi_load_suminfo_properties( package );
         if (r != ERROR_SUCCESS)
         {
             msiobj_release( &package->hdr );
@@ -1263,9 +1153,18 @@ UINT msi_create_empty_local_file( LPWSTR path, LPCWSTR suffix )
     return ERROR_SUCCESS;
 }
 
-static UINT msi_parse_summary( MSISUMMARYINFO *si, MSIPACKAGE *package )
+static enum platform parse_platform( const WCHAR *str )
 {
-    WCHAR *template, *p, *q;
+    if (!str[0] || !strcmpW( str, szIntel )) return PLATFORM_INTEL;
+    else if (!strcmpW( str, szIntel64 )) return PLATFORM_INTEL64;
+    else if (!strcmpW( str, szX64 ) || !strcmpW( str, szAMD64 )) return PLATFORM_X64;
+    else if (!strcmpW( str, szARM )) return PLATFORM_ARM;
+    return PLATFORM_UNKNOWN;
+}
+
+static UINT parse_suminfo( MSISUMMARYINFO *si, MSIPACKAGE *package )
+{
+    WCHAR *template, *p, *q, *platform;
     DWORD i, count;
 
     package->version = msi_suminfo_get_int32( si, PID_PAGECOUNT );
@@ -1285,16 +1184,16 @@ static UINT msi_parse_summary( MSISUMMARYINFO *si, MSIPACKAGE *package )
         return ERROR_PATCH_PACKAGE_INVALID;
     }
     *p = 0;
-    if ((q = strchrW( template, ',' ))) *q = 0;
-    if (!template[0] || !strcmpW( template, szIntel ))
-        package->platform = PLATFORM_INTEL;
-    else if (!strcmpW( template, szIntel64 ))
-        package->platform = PLATFORM_INTEL64;
-    else if (!strcmpW( template, szX64 ) || !strcmpW( template, szAMD64 ))
-        package->platform = PLATFORM_X64;
-    else if (!strcmpW( template, szARM ))
-        package->platform = PLATFORM_ARM;
-    else
+    platform = template;
+    if ((q = strchrW( platform, ',' ))) *q = 0;
+    package->platform = parse_platform( platform );
+    while (package->platform == PLATFORM_UNKNOWN && q)
+    {
+        platform = q + 1;
+        if ((q = strchrW( platform, ',' ))) *q = 0;
+        package->platform = parse_platform( platform );
+    }
+    if (package->platform == PLATFORM_UNKNOWN)
     {
         WARN("unknown platform %s\n", debugstr_w(template));
         msi_free( template );
@@ -1371,22 +1270,6 @@ static UINT validate_package( MSIPACKAGE *package )
     return ERROR_INSTALL_LANGUAGE_UNSUPPORTED;
 }
 
-int msi_track_tempfile( MSIPACKAGE *package, const WCHAR *path )
-{
-    MSITEMPFILE *temp;
-
-    TRACE("%s\n", debugstr_w(path));
-
-    LIST_FOR_EACH_ENTRY( temp, &package->tempfiles, MSITEMPFILE, entry )
-    {
-        if (!strcmpW( path, temp->Path )) return 0;
-    }
-    if (!(temp = msi_alloc_zero( sizeof (MSITEMPFILE) ))) return -1;
-    list_add_head( &package->tempfiles, &temp->entry );
-    temp->Path = strdupW( path );
-    return 0;
-}
-
 static WCHAR *get_product_code( MSIDATABASE *db )
 {
     static const WCHAR query[] = {
@@ -1466,11 +1349,17 @@ static WCHAR *get_package_code( MSIDATABASE *db )
 {
     WCHAR *ret;
     MSISUMMARYINFO *si;
+    UINT r;
 
-    if (!(si = MSI_GetSummaryInformationW( db->storage, 0 )))
+    r = msi_get_suminfo( db->storage, 0, &si );
+    if (r != ERROR_SUCCESS)
     {
-        WARN("failed to load summary info\n");
-        return NULL;
+        r = msi_get_db_suminfo( db, 0, &si );
+        if (r != ERROR_SUCCESS)
+        {
+            WARN("failed to load summary info %u\n", r);
+            return NULL;
+        }
     }
     ret = msi_suminfo_dup_string( si, PID_REVNUMBER );
     msiobj_release( &si->hdr );
@@ -1507,12 +1396,35 @@ static UINT get_local_package( const WCHAR *filename, WCHAR *localfile )
     return r;
 }
 
+UINT msi_set_original_database_property( MSIDATABASE *db, const WCHAR *package )
+{
+    UINT r;
+
+    if (UrlIsW( package, URLIS_URL ))
+        r = msi_set_property( db, szOriginalDatabase, package, -1 );
+    else if (package[0] == '#')
+        r = msi_set_property( db, szOriginalDatabase, db->path, -1 );
+    else
+    {
+        DWORD len;
+        WCHAR *path;
+
+        if (!(len = GetFullPathNameW( package, 0, NULL, NULL ))) return GetLastError();
+        if (!(path = msi_alloc( len * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY;
+        len = GetFullPathNameW( package, len, path, NULL );
+        r = msi_set_property( db, szOriginalDatabase, path, len );
+        msi_free( path );
+    }
+    return r;
+}
+
 UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
 {
     static const WCHAR dotmsi[] = {'.','m','s','i',0};
     MSIDATABASE *db;
     MSIPACKAGE *package;
     MSIHANDLE handle;
+    MSIRECORD *data_row, *info_row;
     LPWSTR ptr, base_url = NULL;
     UINT r;
     WCHAR localfile[MAX_PATH], cachefile[MAX_PATH];
@@ -1520,9 +1432,13 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
     DWORD index = 0;
     MSISUMMARYINFO *si;
     BOOL delete_on_close = FALSE;
+    LPWSTR productname;
+    WCHAR *info_template;
 
     TRACE("%s %p\n", debugstr_w(szPackage), pPackage);
 
+    MSI_ProcessMessage(NULL, INSTALLMESSAGE_INITIALIZE, 0);
+
     localfile[0] = 0;
     if( szPackage[0] == '#' )
     {
@@ -1564,13 +1480,17 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
         {
             r = msi_create_empty_local_file( localfile, dotmsi );
             if (r != ERROR_SUCCESS)
+            {
+                msi_free ( base_url );
                 return r;
+            }
 
             if (!CopyFileW( file, localfile, FALSE ))
             {
                 r = GetLastError();
                 WARN("unable to copy package %s to %s (%u)\n", debugstr_w(file), debugstr_w(localfile), r);
                 DeleteFileW( localfile );
+                msi_free ( base_url );
                 return r;
             }
             delete_on_close = TRUE;
@@ -1578,7 +1498,10 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
         TRACE("opening package %s\n", debugstr_w( localfile ));
         r = MSI_OpenDatabaseW( localfile, MSIDBOPEN_TRANSACT, &db );
         if (r != ERROR_SUCCESS)
+        {
+            msi_free ( base_url );
             return r;
+        }
     }
     package = MSI_CreatePackage( db, base_url );
     msi_free( base_url );
@@ -1587,14 +1510,18 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
     package->localfile = strdupW( localfile );
     package->delete_on_close = delete_on_close;
 
-    si = MSI_GetSummaryInformationW( db->storage, 0 );
-    if (!si)
+    r = msi_get_suminfo( db->storage, 0, &si );
+    if (r != ERROR_SUCCESS)
     {
-        WARN("failed to load summary info\n");
-        msiobj_release( &package->hdr );
-        return ERROR_INSTALL_PACKAGE_INVALID;
+        r = msi_get_db_suminfo( db, 0, &si );
+        if (r != ERROR_SUCCESS)
+        {
+            WARN("failed to load summary info\n");
+            msiobj_release( &package->hdr );
+            return ERROR_INSTALL_PACKAGE_INVALID;
+        }
     }
-    r = msi_parse_summary( si, package );
+    r = parse_suminfo( si, package );
     msiobj_release( &si->hdr );
     if (r != ERROR_SUCCESS)
     {
@@ -1608,19 +1535,8 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
         msiobj_release( &package->hdr );
         return r;
     }
-    msi_set_property( package->db, szDatabase, db->path );
-
-    if( UrlIsW( szPackage, URLIS_URL ) )
-        msi_set_property( package->db, szOriginalDatabase, szPackage );
-    else if( szPackage[0] == '#' )
-        msi_set_property( package->db, szOriginalDatabase, db->path );
-    else
-    {
-        WCHAR fullpath[MAX_PATH];
-
-        GetFullPathNameW( szPackage, MAX_PATH, fullpath, NULL );
-        msi_set_property( package->db, szOriginalDatabase, fullpath );
-    }
+    msi_set_property( package->db, szDatabase, db->path, -1 );
+    set_installed_prop( package );
     msi_set_context( package );
 
     while (1)
@@ -1642,14 +1558,51 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
         }
         index++;
     }
-    if (index)
+    if (index) msi_adjust_privilege_properties( package );
+
+    r = msi_set_original_database_property( package->db, szPackage );
+    if (r != ERROR_SUCCESS)
     {
-        msi_clone_properties( package );
-        msi_adjust_privilege_properties( package );
+        msiobj_release( &package->hdr );
+        return r;
     }
     if (gszLogFile)
         package->log_file = CreateFileW( gszLogFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
                                          OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
+
+    /* FIXME: when should these messages be sent? */
+    data_row = MSI_CreateRecord(3);
+    if (!data_row)
+       return ERROR_OUTOFMEMORY;
+    MSI_RecordSetStringW(data_row, 0, NULL);
+    MSI_RecordSetInteger(data_row, 1, 0);
+    MSI_RecordSetInteger(data_row, 2, package->num_langids ? package->langids[0] : 0);
+    MSI_RecordSetInteger(data_row, 3, msi_get_string_table_codepage(package->db->strings));
+    MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_COMMONDATA, data_row);
+
+    info_row = MSI_CreateRecord(0);
+    if (!info_row)
+    {
+       msiobj_release(&data_row->hdr);
+       return ERROR_OUTOFMEMORY;
+    }
+    info_template = msi_get_error_message(package->db, MSIERR_INFO_LOGGINGSTART);
+    MSI_RecordSetStringW(info_row, 0, info_template);
+    msi_free(info_template);
+    MSI_ProcessMessage(package, INSTALLMESSAGE_INFO|MB_ICONHAND, info_row);
+
+    MSI_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, data_row);
+
+    productname = msi_dup_property(package->db, INSTALLPROPERTY_PRODUCTNAMEW);
+    MSI_RecordSetInteger(data_row, 1, 1);
+    MSI_RecordSetStringW(data_row, 2, productname);
+    MSI_RecordSetStringW(data_row, 3, NULL);
+    MSI_ProcessMessage(package, INSTALLMESSAGE_COMMONDATA, data_row);
+
+    msi_free(productname);
+    msiobj_release(&info_row->hdr);
+    msiobj_release(&data_row->hdr);
+
     *pPackage = package;
     return ERROR_SUCCESS;
 }
@@ -1681,6 +1634,8 @@ UINT WINAPI MsiOpenPackageExW(LPCWSTR szPackage, DWORD dwOptions, MSIHANDLE *phP
             ret = ERROR_NOT_ENOUGH_MEMORY;
         msiobj_release( &package->hdr );
     }
+    else
+        MSI_ProcessMessage(NULL, INSTALLMESSAGE_TERMINATE, 0);
 
     return ret;
 }
@@ -1747,18 +1702,169 @@ MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
     return handle;
 }
 
-INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record )
+static INT internal_ui_handler(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record, LPCWSTR message)
 {
     static const WCHAR szActionData[] = {'A','c','t','i','o','n','D','a','t','a',0};
-    static const WCHAR szSetProgress[] = {'S','e','t','P','r','o','g','r','e','s','s',0};
     static const WCHAR szActionText[] = {'A','c','t','i','o','n','T','e','x','t',0};
-    MSIRECORD *uirow;
-    LPWSTR deformated, message;
-    DWORD i, len, total_len, log_type = 0;
+    static const WCHAR szSetProgress[] = {'S','e','t','P','r','o','g','r','e','s','s',0};
+    static const WCHAR szWindows_Installer[] =
+        {'W','i','n','d','o','w','s',' ','I','n','s','t','a','l','l','e','r',0};
+
+    if (!package || (package->ui_level & INSTALLUILEVEL_MASK) == INSTALLUILEVEL_NONE)
+        return 0;
+
+    /* todo: check if message needs additional styles (topmost/foreground/modality?) */
+
+    switch (eMessageType & 0xff000000)
+    {
+    case INSTALLMESSAGE_FATALEXIT:
+    case INSTALLMESSAGE_ERROR:
+    case INSTALLMESSAGE_OUTOFDISKSPACE:
+        if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0;
+        if (!(eMessageType & MB_ICONMASK))
+            eMessageType |= MB_ICONEXCLAMATION;
+        return MessageBoxW(gUIhwnd, message, szWindows_Installer, eMessageType & 0x00ffffff);
+    case INSTALLMESSAGE_WARNING:
+        if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0;
+        if (!(eMessageType & MB_ICONMASK))
+            eMessageType |= MB_ICONASTERISK;
+        return MessageBoxW(gUIhwnd, message, szWindows_Installer, eMessageType & 0x00ffffff);
+    case INSTALLMESSAGE_USER:
+        if (package->ui_level & INSTALLUILEVEL_PROGRESSONLY) return 0;
+        if (!(eMessageType & MB_ICONMASK))
+            eMessageType |= MB_USERICON;
+        return MessageBoxW(gUIhwnd, message, szWindows_Installer, eMessageType & 0x00ffffff);
+    case INSTALLMESSAGE_INFO:
+    case INSTALLMESSAGE_INITIALIZE:
+    case INSTALLMESSAGE_TERMINATE:
+        return 0;
+    case INSTALLMESSAGE_SHOWDIALOG:
+    {
+        LPWSTR dialog = msi_dup_record_field(record, 0);
+        INT rc = ACTION_DialogBox(package, dialog);
+        msi_free(dialog);
+        return rc;
+    }
+    case INSTALLMESSAGE_ACTIONSTART:
+    {
+        LPWSTR deformatted;
+        MSIRECORD *uirow = MSI_CreateRecord(1);
+        if (!uirow) return -1;
+        deformat_string(package, MSI_RecordGetString(record, 2), &deformatted);
+        MSI_RecordSetStringW(uirow, 1, deformatted);
+        msi_event_fire(package, szActionText, uirow);
+
+        msi_free(deformatted);
+        msiobj_release(&uirow->hdr);
+        return 1;
+    }
+    case INSTALLMESSAGE_ACTIONDATA:
+    {
+        MSIRECORD *uirow = MSI_CreateRecord(1);
+        if (!uirow) return -1;
+        MSI_RecordSetStringW(uirow, 1, message);
+        msi_event_fire(package, szActionData, uirow);
+        msiobj_release(&uirow->hdr);
+
+        if (package->action_progress_increment)
+        {
+            uirow = MSI_CreateRecord(2);
+            if (!uirow) return -1;
+            MSI_RecordSetInteger(uirow, 1, 2);
+            MSI_RecordSetInteger(uirow, 2, package->action_progress_increment);
+            msi_event_fire(package, szSetProgress, uirow);
+            msiobj_release(&uirow->hdr);
+        }
+        return 1;
+    }
+    case INSTALLMESSAGE_PROGRESS:
+        msi_event_fire(package, szSetProgress, record);
+        return 1;
+    case INSTALLMESSAGE_COMMONDATA:
+        switch (MSI_RecordGetInteger(record, 1))
+        {
+        case 0:
+        case 1:
+            /* do nothing */
+            return 0;
+        default:
+            /* fall through */
+            ;
+        }
+    default:
+        FIXME("internal UI not implemented for message 0x%08x (UI level = %x)\n", eMessageType, package->ui_level);
+        return 0;
+    }
+}
+
+static const WCHAR szActionNotFound[] = {'D','E','B','U','G',':',' ','E','r','r','o','r',' ','[','1',']',':',' ',' ','A','c','t','i','o','n',' ','n','o','t',' ','f','o','u','n','d',':',' ','[','2',']',0};
+
+static const struct
+{
+    int id;
+    const WCHAR *text;
+}
+internal_errors[] =
+{
+    {2726, szActionNotFound},
+    {0}
+};
+
+static LPCWSTR get_internal_error_message(int error)
+{
+    int i = 0;
+
+    while (internal_errors[i].id != 0)
+    {
+        if (internal_errors[i].id == error)
+            return internal_errors[i].text;
+        i++;
+    }
+
+    FIXME("missing error message %d\n", error);
+    return NULL;
+}
+
+/* Returned string must be freed */
+LPWSTR msi_get_error_message(MSIDATABASE *db, int error)
+{
+    static const WCHAR query[] =
+        {'S','E','L','E','C','T',' ','`','M','e','s','s','a','g','e','`',' ',
+         'F','R','O','M',' ','`','E','r','r','o','r','`',' ','W','H','E','R','E',' ',
+         '`','E','r','r','o','r','`',' ','=',' ','%','i',0};
+    MSIRECORD *record;
+    LPWSTR ret = NULL;
+
+    if ((record = MSI_QueryGetRecord(db, query, error)))
+    {
+        ret = msi_dup_record_field(record, 1);
+        msiobj_release(&record->hdr);
+    }
+    else if (error < 2000)
+    {
+        int len = LoadStringW(msi_hInstance, IDS_ERROR_BASE + error, (LPWSTR) &ret, 0);
+        if (len)
+        {
+            ret = msi_alloc((len + 1) * sizeof(WCHAR));
+            LoadStringW(msi_hInstance, IDS_ERROR_BASE + error, ret, len + 1);
+        }
+        else
+            ret = NULL;
+    }
+
+    return ret;
+}
+
+INT MSI_ProcessMessageVerbatim(MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record)
+{
+    LPWSTR message = {0};
+    DWORD len, log_type = 0;
+    UINT res;
     INT rc = 0;
     char *msg;
 
     TRACE("%x\n", eMessageType);
+    if (TRACE_ON(msi)) dump_record(record);
 
     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_FATALEXIT)
         log_type |= INSTALLLOGMODE_FATALEXIT;
@@ -1789,97 +1895,48 @@ INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIREC
     if ((eMessageType & 0xff000000) == INSTALLMESSAGE_SHOWDIALOG)
         log_type |= INSTALLLOGMODE_SHOWDIALOG;
 
-    if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART)
-    {
-        static const WCHAR template_s[]=
-            {'A','c','t','i','o','n',' ','%','s',':',' ','%','s','.',' ',0};
-        static const WCHAR format[] = 
-            {'H','H','\'',':','\'','m','m','\'',':','\'','s','s',0};
-        WCHAR timet[0x100];
-        LPCWSTR action_text, action;
-        LPWSTR deformatted = NULL;
-
-        GetTimeFormatW(LOCALE_USER_DEFAULT, 0, NULL, format, timet, 0x100);
-
-        action = MSI_RecordGetString(record, 1);
-        action_text = MSI_RecordGetString(record, 2);
-
-        if (!action || !action_text)
-            return IDOK;
-
-        deformat_string(package, action_text, &deformatted);
-
-        len = strlenW(timet) + strlenW(action) + strlenW(template_s);
-        if (deformatted)
-            len += strlenW(deformatted);
-        message = msi_alloc(len*sizeof(WCHAR));
-        sprintfW(message, template_s, timet, action);
-        if (deformatted)
-            strcatW(message, deformatted);
-        msi_free(deformatted);
-    }
-    else
-    {
-        static const WCHAR format[] = {'%','u',':',' ',0};
-        UINT count = MSI_RecordGetFieldCount( record );
-        WCHAR *p;
-
-        total_len = 1;
-        for (i = 1; i <= count; i++)
-        {
-            len = 0;
-            MSI_RecordGetStringW( record, i, NULL, &len );
-            total_len += len + 13;
-        }
-        p = message = msi_alloc( total_len * sizeof(WCHAR) );
-        if (!p) return ERROR_OUTOFMEMORY;
-
-        for (i = 1; i <= count; i++)
-        {
-            if (count > 1)
-            {
-                len = sprintfW( p, format, i );
-                total_len -= len;
-                p += len;
-            }
-            len = total_len;
-            MSI_RecordGetStringW( record, i, p, &len );
-            total_len -= len;
-            p += len;
-            if (count > 1 && total_len)
-            {
-                *p++ = ' ';
-                total_len--;
-            }
-        }
-        p[0] = 0;
+    if (!package || !record)
+        message = NULL;
+    else {
+        res = MSI_FormatRecordW(package, record, message, &len);
+        if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
+            return res;
+        len++;
+        message = msi_alloc(len * sizeof(WCHAR));
+        if (!message) return ERROR_OUTOFMEMORY;
+        MSI_FormatRecordW(package, record, message, &len);
     }
 
-    TRACE("%p %p %p %x %x %s\n", gUIHandlerA, gUIHandlerW, gUIHandlerRecord,
-          gUIFilter, log_type, debugstr_w(message));
-
     /* convert it to ASCII */
     len = WideCharToMultiByte( CP_ACP, 0, message, -1, NULL, 0, NULL, NULL );
     msg = msi_alloc( len );
     WideCharToMultiByte( CP_ACP, 0, message, -1, msg, len, NULL, NULL );
 
-    if (gUIHandlerW && (gUIFilter & log_type))
+    if (gUIHandlerRecord && (gUIFilterRecord & log_type))
     {
-        rc = gUIHandlerW( gUIContext, eMessageType, message );
+        MSIHANDLE rec = alloc_msihandle(&record->hdr);
+        TRACE("Calling UI handler %p(pvContext=%p, iMessageType=%08x, hRecord=%u)\n",
+              gUIHandlerRecord, gUIContextRecord, eMessageType, rec);
+        rc = gUIHandlerRecord( gUIContextRecord, eMessageType, rec );
+        MsiCloseHandle( rec );
     }
-    else if (gUIHandlerA && (gUIFilter & log_type))
+    if (!rc && gUIHandlerW && (gUIFilter & log_type))
     {
-        rc = gUIHandlerA( gUIContext, eMessageType, msg );
+        TRACE("Calling UI handler %p(pvContext=%p, iMessageType=%08x, szMessage=%s)\n",
+              gUIHandlerW, gUIContext, eMessageType, debugstr_w(message));
+        rc = gUIHandlerW( gUIContext, eMessageType, message );
     }
-    else if (gUIHandlerRecord && (gUIFilter & log_type))
+    else if (!rc && gUIHandlerA && (gUIFilter & log_type))
     {
-        MSIHANDLE rec = MsiCreateRecord( 1 );
-        MsiRecordSetStringW( rec, 0, message );
-        rc = gUIHandlerRecord( gUIContext, eMessageType, rec );
-        MsiCloseHandle( rec );
+        TRACE("Calling UI handler %p(pvContext=%p, iMessageType=%08x, szMessage=%s)\n",
+              gUIHandlerA, gUIContext, eMessageType, debugstr_a(msg));
+        rc = gUIHandlerA( gUIContext, eMessageType, msg );
     }
 
-    if (!rc && package->log_file != INVALID_HANDLE_VALUE &&
+    if (!rc)
+        rc = internal_ui_handler(package, eMessageType, record, message);
+
+    if (!rc && package && package->log_file != INVALID_HANDLE_VALUE &&
         (eMessageType & 0xff000000) != INSTALLMESSAGE_PROGRESS)
     {
         DWORD written;
@@ -1889,44 +1946,113 @@ INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIREC
     msi_free( msg );
     msi_free( message );
 
+    return rc;
+}
+
+INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record )
+{
     switch (eMessageType & 0xff000000)
     {
-    case INSTALLMESSAGE_ACTIONDATA:
-        deformat_string(package, MSI_RecordGetString(record, 2), &deformated);
-        uirow = MSI_CreateRecord(1);
-        MSI_RecordSetStringW(uirow, 1, deformated);
-        msi_free(deformated);
+    case INSTALLMESSAGE_FATALEXIT:
+    case INSTALLMESSAGE_ERROR:
+    case INSTALLMESSAGE_WARNING:
+    case INSTALLMESSAGE_USER:
+    case INSTALLMESSAGE_INFO:
+    case INSTALLMESSAGE_OUTOFDISKSPACE:
+        if (MSI_RecordGetInteger(record, 1) != MSI_NULL_INTEGER)
+        {
+            /* error message */
 
-        ControlEvent_FireSubscribedEvent(package, szActionData, uirow);
-        msiobj_release(&uirow->hdr);
+            LPWSTR template;
+            LPWSTR template_rec = NULL, template_prefix = NULL;
+            int error = MSI_RecordGetInteger(record, 1);
 
-        if (package->action_progress_increment)
-        {
-            uirow = MSI_CreateRecord(2);
-            MSI_RecordSetInteger(uirow, 1, 2);
-            MSI_RecordSetInteger(uirow, 2, package->action_progress_increment);
-            ControlEvent_FireSubscribedEvent(package, szSetProgress, uirow);
-            msiobj_release(&uirow->hdr);
-        }
-        break;
+            if (MSI_RecordIsNull(record, 0))
+            {
+                if (error >= 32)
+                {
+                    template_rec = msi_get_error_message(package->db, error);
+
+                    if (!template_rec && error >= 2000)
+                    {
+                        /* internal error, not localized */
+                        if ((template_rec = (LPWSTR) get_internal_error_message(error)))
+                        {
+                            MSI_RecordSetStringW(record, 0, template_rec);
+                            MSI_ProcessMessageVerbatim(package, INSTALLMESSAGE_INFO, record);
+                        }
+                        template_rec = msi_get_error_message(package->db, MSIERR_INSTALLERROR);
+                        MSI_RecordSetStringW(record, 0, template_rec);
+                        MSI_ProcessMessageVerbatim(package, eMessageType, record);
+                        msi_free(template_rec);
+                        return 0;
+                    }
+                }
+            }
+            else
+                template_rec = msi_dup_record_field(record, 0);
 
-    case INSTALLMESSAGE_ACTIONSTART:
-        deformat_string(package, MSI_RecordGetString(record, 2), &deformated);
-        uirow = MSI_CreateRecord(1);
-        MSI_RecordSetStringW(uirow, 1, deformated);
-        msi_free(deformated);
+            template_prefix = msi_get_error_message(package->db, eMessageType >> 24);
+            if (!template_prefix) template_prefix = strdupW(szEmpty);
 
-        ControlEvent_FireSubscribedEvent(package, szActionText, uirow);
+            if (!template_rec)
+            {
+                /* always returns 0 */
+                MSI_RecordSetStringW(record, 0, template_prefix);
+                MSI_ProcessMessageVerbatim(package, eMessageType, record);
+                msi_free(template_prefix);
+                return 0;
+            }
 
-        msiobj_release(&uirow->hdr);
+            template = msi_alloc((strlenW(template_rec) + strlenW(template_prefix) + 1) * sizeof(WCHAR));
+            if (!template) return ERROR_OUTOFMEMORY;
+
+            strcpyW(template, template_prefix);
+            strcatW(template, template_rec);
+            MSI_RecordSetStringW(record, 0, template);
+
+            msi_free(template_prefix);
+            msi_free(template_rec);
+            msi_free(template);
+        }
         break;
+    case INSTALLMESSAGE_ACTIONSTART:
+    {
+        WCHAR *template = msi_get_error_message(package->db, MSIERR_ACTIONSTART);
+        MSI_RecordSetStringW(record, 0, template);
+        msi_free(template);
 
-    case INSTALLMESSAGE_PROGRESS:
-        ControlEvent_FireSubscribedEvent(package, szSetProgress, record);
+        msi_free(package->LastAction);
+        msi_free(package->LastActionTemplate);
+        package->LastAction = msi_dup_record_field(record, 1);
+        if (!package->LastAction) package->LastAction = strdupW(szEmpty);
+        package->LastActionTemplate = msi_dup_record_field(record, 3);
+        break;
+    }
+    case INSTALLMESSAGE_ACTIONDATA:
+        if (package->LastAction && package->LastActionTemplate)
+        {
+            static const WCHAR template_s[] =
+                {'{','{','%','s',':',' ','}','}','%','s',0};
+            WCHAR *template;
+
+            template = msi_alloc((strlenW(package->LastAction) + strlenW(package->LastActionTemplate) + 7) * sizeof(WCHAR));
+            if (!template) return ERROR_OUTOFMEMORY;
+            sprintfW(template, template_s, package->LastAction, package->LastActionTemplate);
+            MSI_RecordSetStringW(record, 0, template);
+            msi_free(template);
+        }
         break;
+    case INSTALLMESSAGE_COMMONDATA:
+    {
+        WCHAR *template = msi_get_error_message(package->db, MSIERR_COMMONDATA);
+        MSI_RecordSetStringW(record, 0, template);
+        msi_free(template);
+    }
+    break;
     }
 
-    return ERROR_SUCCESS;
+    return MSI_ProcessMessageVerbatim(package, eMessageType, record);
 }
 
 INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
@@ -1936,6 +2062,14 @@ INT WINAPI MsiProcessMessage( MSIHANDLE hInstall, INSTALLMESSAGE eMessageType,
     MSIPACKAGE *package = NULL;
     MSIRECORD *record = NULL;
 
+    if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INITIALIZE ||
+        (eMessageType & 0xff000000) == INSTALLMESSAGE_TERMINATE)
+        return -1;
+
+    if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA &&
+        MsiRecordGetInteger(hRecord, 1) != 2)
+        return -1;
+
     package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
     if( !package )
     {
@@ -2018,7 +2152,7 @@ void msi_reset_folders( MSIPACKAGE *package, BOOL source )
     }
 }
 
-UINT msi_set_property( MSIDATABASE *db, LPCWSTR szName, LPCWSTR szValue )
+UINT msi_set_property( MSIDATABASE *db, const WCHAR *name, const WCHAR *value, int len )
 {
     static const WCHAR insert_query[] = {
         'I','N','S','E','R','T',' ','I','N','T','O',' ',
@@ -2039,34 +2173,34 @@ UINT msi_set_property( MSIDATABASE *db, LPCWSTR szName, LPCWSTR szValue )
     WCHAR query[1024];
     UINT rc;
 
-    TRACE("%p %s %s\n", db, debugstr_w(szName), debugstr_w(szValue));
+    TRACE("%p %s %s %d\n", db, debugstr_w(name), debugstr_wn(value, len), len);
 
-    if (!szName)
+    if (!name)
         return ERROR_INVALID_PARAMETER;
 
     /* this one is weird... */
-    if (!szName[0])
-        return szValue ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS;
+    if (!name[0])
+        return value ? ERROR_FUNCTION_FAILED : ERROR_SUCCESS;
+
+    if (value && len < 0) len = strlenW( value );
 
-    rc = msi_get_property(db, szName, 0, &sz);
-    if (!szValue || !*szValue)
+    rc = msi_get_property( db, name, 0, &sz );
+    if (!value || (!*value && !len))
     {
-        sprintfW(query, delete_query, szName);
+        sprintfW( query, delete_query, name );
     }
     else if (rc == ERROR_MORE_DATA || rc == ERROR_SUCCESS)
     {
-        sprintfW(query, update_query, szName);
-
+        sprintfW( query, update_query, name );
         row = MSI_CreateRecord(1);
-        MSI_RecordSetStringW(row, 1, szValue);
+        msi_record_set_string( row, 1, value, len );
     }
     else
     {
-        strcpyW(query, insert_query);
-
+        strcpyW( query, insert_query );
         row = MSI_CreateRecord(2);
-        MSI_RecordSetStringW(row, 1, szName);
-        MSI_RecordSetStringW(row, 2, szValue);
+        msi_record_set_string( row, 1, name, -1 );
+        msi_record_set_string( row, 2, value, len );
     }
 
     rc = MSI_DatabaseOpenViewW(db, query, &view);
@@ -2123,7 +2257,7 @@ UINT WINAPI MsiSetPropertyW( MSIHANDLE hInstall, LPCWSTR szName, LPCWSTR szValue
         return ERROR_SUCCESS;
     }
 
-    ret = msi_set_property( package->db, szName, szValue );
+    ret = msi_set_property( package->db, szName, szValue, -1 );
     if (ret == ERROR_SUCCESS && !strcmpW( szName, szSourceDir ))
         msi_reset_folders( package, TRUE );
 
@@ -2141,9 +2275,45 @@ static MSIRECORD *msi_get_property_row( MSIDATABASE *db, LPCWSTR name )
     MSIQUERY *view;
     UINT r;
 
+    static const WCHAR szDate[] = {'D','a','t','e',0};
+    static const WCHAR szTime[] = {'T','i','m','e',0};
+    WCHAR *buffer;
+    int length;
+
     if (!name || !*name)
         return NULL;
 
+    if (!strcmpW(name, szDate))
+    {
+        length = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, NULL, 0);
+        if (!length)
+            return NULL;
+        buffer = msi_alloc(length * sizeof(WCHAR));
+        GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, buffer, length);
+
+        row = MSI_CreateRecord(1);
+        if (!row)
+            return NULL;
+        MSI_RecordSetStringW(row, 1, buffer);
+        msi_free(buffer);
+        return row;
+    }
+    else if (!strcmpW(name, szTime))
+    {
+        length = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER, NULL, NULL, NULL, 0);
+        if (!length)
+            return NULL;
+        buffer = msi_alloc(length * sizeof(WCHAR));
+        GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER, NULL, NULL, buffer, length);
+
+        row = MSI_CreateRecord(1);
+        if (!row)
+            return NULL;
+        MSI_RecordSetStringW(row, 1, buffer);
+        msi_free(buffer);
+        return row;
+    }
+
     rec = MSI_CreateRecord(1);
     if (!rec)
         return NULL;
@@ -2169,6 +2339,8 @@ UINT msi_get_property( MSIDATABASE *db, LPCWSTR szName,
     MSIRECORD *row;
     UINT rc = ERROR_FUNCTION_FAILED;
 
+    TRACE("%p %s %p %p\n", db, debugstr_w(szName), szValueBuf, pchValueBuf);
+
     row = msi_get_property_row( db, szName );
 
     if (*pchValueBuf > 0)
@@ -2181,7 +2353,7 @@ UINT msi_get_property( MSIDATABASE *db, LPCWSTR szName,
     }
 
     if (rc == ERROR_SUCCESS)
-        TRACE("returning %s for property %s\n", debugstr_w(szValueBuf),
+        TRACE("returning %s for property %s\n", debugstr_wn(szValueBuf, *pchValueBuf),
             debugstr_w(szName));
     else if (rc == ERROR_MORE_DATA)
         TRACE("need %d sized buffer for %s\n", *pchValueBuf,
@@ -2232,6 +2404,7 @@ static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name,
     MSIRECORD *row = NULL;
     UINT r = ERROR_FUNCTION_FAILED;
     LPCWSTR val = NULL;
+    DWORD len = 0;
 
     TRACE("%u %s %p %p\n", handle, debugstr_w(name),
           szValueBuf->str.w, pchValueBuf );
@@ -2246,7 +2419,6 @@ static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name,
         IWineMsiRemotePackage *remote_package;
         LPWSTR value = NULL;
         BSTR bname;
-        DWORD len;
 
         remote_package = (IWineMsiRemotePackage *)msi_get_remote( handle );
         if (!remote_package)
@@ -2259,7 +2431,6 @@ static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name,
             return ERROR_OUTOFMEMORY;
         }
 
-        len = 0;
         hr = IWineMsiRemotePackage_GetProperty( remote_package, bname, NULL, &len );
         if (FAILED(hr))
             goto done;
@@ -2276,7 +2447,7 @@ static UINT MSI_GetProperty( MSIHANDLE handle, LPCWSTR name,
         if (FAILED(hr))
             goto done;
 
-        r = msi_strcpy_to_awstring( value, szValueBuf, pchValueBuf );
+        r = msi_strcpy_to_awstring( value, len, szValueBuf, pchValueBuf );
 
         /* Bug required by Adobe installers */
         if (!szValueBuf->unicode && !szValueBuf->str.a)
@@ -2300,12 +2471,12 @@ done:
 
     row = msi_get_property_row( package->db, name );
     if (row)
-        val = MSI_RecordGetString( row, 1 );
+        val = msi_record_get_string( row, 1, (int *)&len );
 
     if (!val)
         val = szEmpty;
 
-    r = msi_strcpy_to_awstring( val, szValueBuf, pchValueBuf );
+    r = msi_strcpy_to_awstring( val, len, szValueBuf, pchValueBuf );
 
     if (row)
         msiobj_release( &row->hdr );
@@ -2621,7 +2792,7 @@ HRESULT create_msi_remote_package( IUnknown *pOuter, LPVOID *ppObj )
     This->package = 0;
     This->refs = 1;
 
-    *ppObj = This;
+    *ppObj = &This->IWineMsiRemotePackage_iface;
 
     return S_OK;
 }