* 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 )
{
msi_free( feature );
}
+static void free_folder( MSIFOLDER *folder )
+{
+ struct list *item, *cursor;
+
+ LIST_FOR_EACH_SAFE( item, cursor, &folder->children )
+ {
+ FolderList *fl = LIST_ENTRY( item, FolderList, entry );
+ list_remove( &fl->entry );
+ msi_free( fl );
+ }
+ msi_free( folder->Parent );
+ msi_free( folder->Directory );
+ msi_free( folder->TargetDefault );
+ msi_free( folder->SourceLongPath );
+ msi_free( folder->SourceShortPath );
+ msi_free( folder->ResolvedTarget );
+ msi_free( folder->ResolvedSource );
+ msi_free( folder );
+}
+
static void free_extension( MSIEXTENSION *ext )
{
struct list *item, *cursor;
msi_free( assembly );
}
-static void free_package_structures( MSIPACKAGE *package )
+void msi_free_action_script( MSIPACKAGE *package, UINT script )
{
- INT i;
- struct list *item, *cursor;
+ UINT i;
+ for (i = 0; i < package->script->ActionCount[script]; i++)
+ msi_free( package->script->Actions[script][i] );
- TRACE("Freeing package action data\n");
+ msi_free( package->script->Actions[script] );
+ package->script->Actions[script] = NULL;
+ package->script->ActionCount[script] = 0;
+}
- remove_tracked_tempfiles(package);
+static void free_package_structures( MSIPACKAGE *package )
+{
+ struct list *item, *cursor;
LIST_FOR_EACH_SAFE( item, cursor, &package->features )
{
LIST_FOR_EACH_SAFE( item, cursor, &package->folders )
{
MSIFOLDER *folder = LIST_ENTRY( item, MSIFOLDER, entry );
-
list_remove( &folder->entry );
- msi_free( folder->Parent );
- msi_free( folder->Directory );
- msi_free( folder->TargetDefault );
- msi_free( folder->SourceLongPath );
- msi_free( folder->SourceShortPath );
- msi_free( folder->ResolvedTarget );
- msi_free( folder->ResolvedSource );
- msi_free( folder->Property );
- msi_free( folder );
+ 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 )
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 */
if (package->script)
{
- for (i = 0; i < TOTAL_SCRIPTS; i++)
+ 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 );
}
- LIST_FOR_EACH_SAFE( item, cursor, &package->patches )
- {
- MSIPATCHINFO *patch = LIST_ENTRY( item, MSIPATCHINFO, entry );
-
- list_remove( &patch->entry );
- msi_free( patch->patchcode );
- msi_free( patch->transforms );
- msi_free( patch->localfile );
- msi_free( patch );
- }
-
LIST_FOR_EACH_SAFE( item, cursor, &package->binaries )
{
MSIBINARY *binary = LIST_ENTRY( item, MSIBINARY, entry );
msi_free( binary );
}
+ LIST_FOR_EACH_SAFE( item, cursor, &package->cabinet_streams )
+ {
+ MSICABINETSTREAM *cab = LIST_ENTRY( item, MSICABINETSTREAM, entry );
+
+ list_remove( &cab->entry );
+ IStorage_Release( cab->storage );
+ msi_free( cab->stream );
+ msi_free( cab );
+ }
+
+ LIST_FOR_EACH_SAFE( item, cursor, &package->patches )
+ {
+ MSIPATCHINFO *patch = LIST_ENTRY( item, MSIPATCHINFO, entry );
+
+ list_remove( &patch->entry );
+ if (patch->delete_on_close && !DeleteFileW( patch->localfile ))
+ {
+ ERR("failed to delete %s (%u)\n", debugstr_w(patch->localfile), GetLastError());
+ }
+ msi_free_patchinfo( patch );
+ }
+
msi_free( package->BaseURL );
msi_free( package->PackagePath );
msi_free( package->ProductCode );
msi_free( package->ActionFormat );
msi_free( package->LastAction );
+ msi_free( package->LastActionTemplate );
msi_free( package->langids );
/* cleanup control event subscriptions */
- ControlEvent_CleanupSubscriptions( package );
+ msi_event_cleanup_all_subscriptions( package );
}
static void MSI_FreePackage( MSIOBJECTHDR *arg)
{
- UINT i;
MSIPACKAGE *package = (MSIPACKAGE *)arg;
+ msi_destroy_assembly_caches( package );
+
if( package->dialog )
msi_dialog_destroy( package->dialog );
free_package_structures(package);
CloseHandle( package->log_file );
- for (i = 0; i < CLR_VERSION_MAX; i++)
- if (package->cache_net[i]) IAssemblyCache_Release( package->cache_net[i] );
- if (package->cache_sxs) IAssemblyCache_Release( package->cache_sxs );
+ 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)
{
- MSIQUERY *view = NULL;
+ static const WCHAR query[] = {
+ 'C','R','E','A','T','E',' ','T','A','B','L','E',' ',
+ '`','_','P','r','o','p','e','r','t','y','`',' ','(',' ',
+ '`','_','P','r','o','p','e','r','t','y','`',' ',
+ 'C','H','A','R','(','5','6',')',' ','N','O','T',' ','N','U','L','L',' ',
+ 'T','E','M','P','O','R','A','R','Y',',',' ',
+ '`','V','a','l','u','e','`',' ','C','H','A','R','(','9','8',')',' ',
+ 'N','O','T',' ','N','U','L','L',' ','T','E','M','P','O','R','A','R','Y',
+ ' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ',
+ '`','_','P','r','o','p','e','r','t','y','`',')',' ','H','O','L','D',0};
+ MSIQUERY *view;
UINT rc;
- static const WCHAR CreateSql[] = {
- 'C','R','E','A','T','E',' ','T','A','B','L','E',' ',
- '`','_','P','r','o','p','e','r','t','y','`',' ','(',' ',
- '`','_','P','r','o','p','e','r','t','y','`',' ',
- 'C','H','A','R','(','5','6',')',' ','N','O','T',' ','N','U','L','L',' ',
- 'T','E','M','P','O','R','A','R','Y',',',' ',
- '`','V','a','l','u','e','`',' ','C','H','A','R','(','9','8',')',' ',
- 'N','O','T',' ','N','U','L','L',' ','T','E','M','P','O','R','A','R','Y',
- ' ','P','R','I','M','A','R','Y',' ','K','E','Y',' ',
- '`','_','P','r','o','p','e','r','t','y','`',')',' ','H','O','L','D',0};
-
- rc = MSI_DatabaseOpenViewW(package->db, CreateSql, &view);
+ rc = MSI_DatabaseOpenViewW(package->db, query, &view);
if (rc != ERROR_SUCCESS)
return rc;
return rc;
}
-UINT msi_clone_properties(MSIPACKAGE *package)
+UINT msi_clone_properties( MSIDATABASE *db )
{
- MSIQUERY *view_select = NULL;
- UINT rc;
-
static const WCHAR query_select[] = {
- 'S','E','L','E','C','T',' ','*',' ',
- 'F','R','O','M',' ','`','P','r','o','p','e','r','t','y','`',0};
+ 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
+ '`','P','r','o','p','e','r','t','y','`',0};
static const WCHAR query_insert[] = {
- 'I','N','S','E','R','T',' ','i','n','t','o',' ',
- '`','_','P','r','o','p','e','r','t','y','`',' ',
- '(','`','_','P','r','o','p','e','r','t','y','`',',',
- '`','V','a','l','u','e','`',')',' ',
- 'V','A','L','U','E','S',' ','(','?',',','?',')',0};
+ 'I','N','S','E','R','T',' ','I','N','T','O',' ',
+ '`','_','P','r','o','p','e','r','t','y','`',' ',
+ '(','`','_','P','r','o','p','e','r','t','y','`',',','`','V','a','l','u','e','`',')',' ',
+ 'V','A','L','U','E','S',' ','(','?',',','?',')',0};
static const WCHAR query_update[] = {
'U','P','D','A','T','E',' ','`','_','P','r','o','p','e','r','t','y','`',' ',
'S','E','T',' ','`','V','a','l','u','e','`',' ','=',' ','?',' ',
'W','H','E','R','E',' ','`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','?',0};
+ 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;
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 );
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);
*/
static UINT set_installed_prop( MSIPACKAGE *package )
{
- HKEY hkey = 0;
+ HKEY hkey;
UINT r;
- r = MSIREG_OpenUninstallKey( package, &hkey, FALSE );
+ if (!package->ProductCode) return ERROR_FUNCTION_FAILED;
+
+ r = MSIREG_OpenUninstallKey( package->ProductCode, package->platform, &hkey, FALSE );
if (r == ERROR_SUCCESS)
{
RegCloseKey( hkey );
- msi_set_property( package->db, szInstalled, szOne );
+ msi_set_property( package->db, szInstalled, szOne, -1 );
}
-
return r;
}
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 );
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;
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);
static VOID set_installer_properties(MSIPACKAGE *package)
{
- WCHAR pth[MAX_PATH];
WCHAR *ptr;
OSVERSIONINFOEXW OSVersion;
MEMORYSTATUSEX msex;
DWORD verval, len;
- WCHAR verstr[10], bufstr[20];
+ WCHAR pth[MAX_PATH], verstr[11], bufstr[22];
HDC dc;
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};
static const WCHAR szDesktopFolder[] = {'D','e','s','k','t','o','p','F','o','l','d','e','r',0};
static const WCHAR szProgramMenuFolder[] = {'P','r','o','g','r','a','m','M','e','n','u','F','o','l','d','e','r',0};
static const WCHAR szAdminToolsFolder[] = {'A','d','m','i','n','T','o','o','l','s','F','o','l','d','e','r',0};
- static const WCHAR szAppDataFolder[] = {'A','p','p','D','a','t','a','F','o','l','d','e','r',0};
static const WCHAR szSystemFolder[] = {'S','y','s','t','e','m','F','o','l','d','e','r',0};
static const WCHAR szSystem16Folder[] = {'S','y','s','t','e','m','1','6','F','o','l','d','e','r',0};
static const WCHAR szLocalAppDataFolder[] = {'L','o','c','a','l','A','p','p','D','a','t','a','F','o','l','d','e','r',0};
static const WCHAR szMyPicturesFolder[] = {'M','y','P','i','c','t','u','r','e','s','F','o','l','d','e','r',0};
static const WCHAR szPersonalFolder[] = {'P','e','r','s','o','n','a','l','F','o','l','d','e','r',0};
- static const WCHAR szWindowsFolder[] = {'W','i','n','d','o','w','s','F','o','l','d','e','r',0};
static const WCHAR szWindowsVolume[] = {'W','i','n','d','o','w','s','V','o','l','u','m','e',0};
- static const WCHAR szTempFolder[]= {'T','e','m','p','F','o','l','d','e','r',0};
static const WCHAR szPrivileged[] = {'P','r','i','v','i','l','e','g','e','d',0};
static const WCHAR szVersion9x[] = {'V','e','r','s','i','o','n','9','X',0};
static const WCHAR szVersionNT[] = {'V','e','r','s','i','o','n','N','T',0};
static const WCHAR szMsiNTProductType[] = {'M','s','i','N','T','P','r','o','d','u','c','t','T','y','p','e',0};
- static const WCHAR szFormat[] = {'%','l','i',0};
+ static const WCHAR szFormat[] = {'%','u',0};
+ static const WCHAR szFormat2[] = {'%','u','.','%','u',0};
static const WCHAR szWindowsBuild[] = {'W','i','n','d','o','w','s','B','u','i','l','d',0};
static const WCHAR szServicePackLevel[] = {'S','e','r','v','i','c','e','P','a','c','k','L','e','v','e','l',0};
- static const WCHAR szSix[] = {'6',0 };
static const WCHAR szVersionMsi[] = { 'V','e','r','s','i','o','n','M','s','i',0 };
static const WCHAR szVersionDatabase[] = { 'V','e','r','s','i','o','n','D','a','t','a','b','a','s','e',0 };
static const WCHAR szPhysicalMemory[] = { 'P','h','y','s','i','c','a','l','M','e','m','o','r','y',0 };
- static const WCHAR szFormat2[] = {'%','l','i','.','%','l','i',0};
static const WCHAR szScreenX[] = {'S','c','r','e','e','n','X',0};
static const WCHAR szScreenY[] = {'S','c','r','e','e','n','Y',0};
static const WCHAR szColorBits[] = {'C','o','l','o','r','B','i','t','s',0};
};
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};
static const WCHAR szNetHoodFolder[] = {'N','e','t','H','o','o','d','F','o','l','d','e','r',0};
static const WCHAR szPrintHoodFolder[] = {'P','r','i','n','t','H','o','o','d','F','o','l','d','e','r',0};
static const WCHAR szRecentFolder[] = {'R','e','c','e','n','t','F','o','l','d','e','r',0};
+ static const WCHAR szComputerName[] = {'C','o','m','p','u','t','e','r','N','a','m','e',0};
/*
* Other things that probably should be set:
*
- * ComputerName VirtualMemory
- * ShellAdvSupport DefaultUIFont PackagecodeChanging
- * CaptionHeight BorderTop BorderSide TextHeight
- * RedirectedDllSupport
+ * VirtualMemory ShellAdvSupport DefaultUIFont PackagecodeChanging
+ * CaptionHeight BorderTop BorderSide TextHeight RedirectedDllSupport
*/
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);
- /* just fudge this */
- msi_set_property(package->db, szServicePackLevel, szSix);
+ 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 );
+ len = sprintfW( bufstr, szIntFormat, sys_info.wProcessorLevel );
+ msi_set_property( package->db, szIntel, bufstr, len );
if (sys_info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
{
- msi_set_property( package->db, szIntel, bufstr );
-
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 */
{
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) &&
{
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 );
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_MORE_DATA)
+ if (!GetUserNameW( NULL, &len ) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
WCHAR *username;
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 );
}
}
-}
-
-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)
+ if (!GetComputerNameW( NULL, &len ) && GetLastError() == ERROR_BUFFER_OVERFLOW)
{
- 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;
+ WCHAR *computername;
+ if ((computername = msi_alloc( len * sizeof(WCHAR) )))
+ {
+ if (GetComputerNameW( computername, &len ))
+ msi_set_property( package->db, szComputerName, computername, len );
+ msi_free( computername );
+ }
}
-
- 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 )
list_init( &package->components );
list_init( &package->features );
list_init( &package->files );
+ list_init( &package->filepatches );
list_init( &package->tempfiles );
list_init( &package->folders );
list_init( &package->subscriptions );
list_init( &package->sourcelist_media );
list_init( &package->patches );
list_init( &package->binaries );
+ list_init( &package->cabinet_streams );
}
return 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 )
{
- static const WCHAR szLevel[] = { 'U','I','L','e','v','e','l',0 };
- static const WCHAR szpi[] = {'%','i',0};
+ static const WCHAR fmtW[] = {'%','u',0};
MSIPACKAGE *package;
- WCHAR uilevel[10];
+ WCHAR uilevel[11];
+ int len;
UINT r;
TRACE("%p\n", db);
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 );
- sprintfW(uilevel,szpi,gUILevel);
- msi_set_property(package->db, szLevel, uilevel);
+ package->ui_level = gUILevel;
+ 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 );
package->log_file = INVALID_HANDLE_VALUE;
}
-
return package;
}
-/*
- * copy_package_to_temp [internal]
- *
- * copy the msi file to a temp file to prevent locking a CD
- * with a multi disc install
- *
- * FIXME: I think this is wrong, and instead of copying the package,
- * we should read all the tables to memory, then open the
- * database to read binary streams on demand.
- */
-static UINT copy_package_to_temp( LPCWSTR szPackage, LPWSTR filename )
-{
- WCHAR path[MAX_PATH];
-
- GetTempPathW( MAX_PATH, path );
- GetTempFileNameW( path, szMsi, 0, filename );
-
- if( !CopyFileW( szPackage, filename, FALSE ) )
- {
- UINT error = GetLastError();
- if ( error == ERROR_FILE_NOT_FOUND )
- ERR("can't find %s\n", debugstr_w(szPackage));
- else
- ERR("failed to copy package %s to %s (%u)\n", debugstr_w(szPackage), debugstr_w(filename), error);
- DeleteFileW( filename );
- return error;
- }
-
- return ERROR_SUCCESS;
-}
-
UINT msi_download_file( LPCWSTR szUrl, LPWSTR filename )
{
LPINTERNET_CACHE_ENTRY_INFOW cache_entry;
DWORD size = 0;
HRESULT hr;
- /* call will always fail, becase size is 0,
+ /* call will always fail, because size is 0,
* but will return ERROR_FILE_NOT_FOUND first
* if the file doesn't exist
*/
return ERROR_SUCCESS;
}
-UINT msi_get_local_package_name( LPWSTR path, LPCWSTR suffix )
+UINT msi_create_empty_local_file( LPWSTR path, LPCWSTR suffix )
{
static const WCHAR szInstaller[] = {
'\\','I','n','s','t','a','l','l','e','r','\\',0};
return ERROR_SUCCESS;
}
-static UINT apply_registered_patch( MSIPACKAGE *package, LPCWSTR patch_code )
+static enum platform parse_platform( const WCHAR *str )
{
- UINT r;
- DWORD len;
- WCHAR patch_file[MAX_PATH];
- MSIDATABASE *patch_db;
- MSIPATCHINFO *patch_info;
- MSISUMMARYINFO *si;
-
- len = sizeof(patch_file) / sizeof(WCHAR);
- r = MsiGetPatchInfoExW( patch_code, package->ProductCode, NULL, package->Context,
- INSTALLPROPERTY_LOCALPACKAGEW, patch_file, &len );
- if (r != ERROR_SUCCESS)
- {
- ERR("failed to get patch filename %u\n", r);
- return r;
- }
-
- r = MSI_OpenDatabaseW( patch_file, MSIDBOPEN_READONLY + MSIDBOPEN_PATCHFILE, &patch_db );
- if (r != ERROR_SUCCESS)
- {
- ERR("failed to open patch database %s\n", debugstr_w( patch_file ));
- return r;
- }
-
- si = MSI_GetSummaryInformationW( patch_db->storage, 0 );
- if (!si)
- {
- msiobj_release( &patch_db->hdr );
- return ERROR_FUNCTION_FAILED;
- }
-
- r = msi_parse_patch_summary( si, &patch_info );
- msiobj_release( &si->hdr );
- if (r != ERROR_SUCCESS)
- {
- ERR("failed to parse patch summary %u\n", r);
- msiobj_release( &patch_db->hdr );
- return r;
- }
-
- patch_info->localfile = strdupW( patch_file );
- if (!patch_info->localfile)
- {
- msiobj_release( &patch_db->hdr );
- return ERROR_OUTOFMEMORY;
- }
-
- r = msi_apply_patch_db( package, patch_db, patch_info );
- msiobj_release( &patch_db->hdr );
- if (r != ERROR_SUCCESS)
- {
- ERR("failed to apply patch %u\n", r);
- msi_free( patch_info->patchcode );
- msi_free( patch_info->transforms );
- msi_free( patch_info->localfile );
- msi_free( patch_info );
- }
- return r;
+ 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 msi_parse_summary( MSISUMMARYINFO *si, MSIPACKAGE *package )
+static UINT parse_suminfo( MSISUMMARYINFO *si, MSIPACKAGE *package )
{
- WCHAR *template, *p, *q;
+ WCHAR *template, *p, *q, *platform;
DWORD i, count;
package->version = msi_suminfo_get_int32( si, PID_PAGECOUNT );
return ERROR_PATCH_PACKAGE_INVALID;
}
*p = 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
+ 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 );
static UINT validate_package( MSIPACKAGE *package )
{
- BOOL is_wow64;
UINT i;
- IsWow64Process( GetCurrentProcess(), &is_wow64 );
+ if (package->platform == PLATFORM_INTEL64)
+ return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
+#ifndef __arm__
+ if (package->platform == PLATFORM_ARM)
+ return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
+#endif
if (package->platform == PLATFORM_X64)
{
if (!is_64bit && !is_wow64)
return ERROR_INSTALL_LANGUAGE_UNSUPPORTED;
}
+static WCHAR *get_product_code( MSIDATABASE *db )
+{
+ static const WCHAR query[] = {
+ 'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ',
+ 'F','R','O','M',' ','`','P','r','o','p','e','r','t','y','`',' ',
+ 'W','H','E','R','E',' ','`','P','r','o','p','e','r','t','y','`','=',
+ '\'','P','r','o','d','u','c','t','C','o','d','e','\'',0};
+ MSIQUERY *view;
+ MSIRECORD *rec;
+ WCHAR *ret = NULL;
+
+ if (MSI_DatabaseOpenViewW( db, query, &view ) != ERROR_SUCCESS)
+ {
+ return NULL;
+ }
+ if (MSI_ViewExecute( view, 0 ) != ERROR_SUCCESS)
+ {
+ MSI_ViewClose( view );
+ msiobj_release( &view->hdr );
+ return NULL;
+ }
+ if (MSI_ViewFetch( view, &rec ) == ERROR_SUCCESS)
+ {
+ ret = strdupW( MSI_RecordGetString( rec, 1 ) );
+ msiobj_release( &rec->hdr );
+ }
+ MSI_ViewClose( view );
+ msiobj_release( &view->hdr );
+ return ret;
+}
+
+static UINT get_registered_local_package( const WCHAR *product, const WCHAR *package, WCHAR *localfile )
+{
+ MSIINSTALLCONTEXT context;
+ HKEY product_key, props_key;
+ WCHAR *registered_package = NULL, unsquashed[GUID_SIZE];
+ UINT r;
+
+ r = msi_locate_product( product, &context );
+ if (r != ERROR_SUCCESS)
+ return r;
+
+ r = MSIREG_OpenProductKey( product, NULL, context, &product_key, FALSE );
+ if (r != ERROR_SUCCESS)
+ return r;
+
+ r = MSIREG_OpenInstallProps( product, context, NULL, &props_key, FALSE );
+ if (r != ERROR_SUCCESS)
+ {
+ RegCloseKey( product_key );
+ return r;
+ }
+ r = ERROR_FUNCTION_FAILED;
+ registered_package = msi_reg_get_val_str( product_key, INSTALLPROPERTY_PACKAGECODEW );
+ if (!registered_package)
+ goto done;
+
+ unsquash_guid( registered_package, unsquashed );
+ if (!strcmpiW( package, unsquashed ))
+ {
+ WCHAR *filename = msi_reg_get_val_str( props_key, INSTALLPROPERTY_LOCALPACKAGEW );
+ if (!filename)
+ goto done;
+
+ strcpyW( localfile, filename );
+ msi_free( filename );
+ r = ERROR_SUCCESS;
+ }
+done:
+ msi_free( registered_package );
+ RegCloseKey( props_key );
+ RegCloseKey( product_key );
+ return r;
+}
+
+static WCHAR *get_package_code( MSIDATABASE *db )
+{
+ WCHAR *ret;
+ MSISUMMARYINFO *si;
+ UINT r;
+
+ r = msi_get_suminfo( db->storage, 0, &si );
+ if (r != ERROR_SUCCESS)
+ {
+ 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 );
+ return ret;
+}
+
+static UINT get_local_package( const WCHAR *filename, WCHAR *localfile )
+{
+ WCHAR *product_code, *package_code;
+ MSIDATABASE *db;
+ UINT r;
+
+ if ((r = MSI_OpenDatabaseW( filename, MSIDBOPEN_READONLY, &db )) != ERROR_SUCCESS)
+ {
+ if (GetFileAttributesW( filename ) == INVALID_FILE_ATTRIBUTES)
+ return ERROR_FILE_NOT_FOUND;
+ return r;
+ }
+ if (!(product_code = get_product_code( db )))
+ {
+ msiobj_release( &db->hdr );
+ return ERROR_INSTALL_PACKAGE_INVALID;
+ }
+ if (!(package_code = get_package_code( db )))
+ {
+ msi_free( product_code );
+ msiobj_release( &db->hdr );
+ return ERROR_INSTALL_PACKAGE_INVALID;
+ }
+ r = get_registered_local_package( product_code, package_code, localfile );
+ msi_free( package_code );
+ msi_free( product_code );
+ msiobj_release( &db->hdr );
+ 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 Database[] = {'D','A','T','A','B','A','S','E',0};
static const WCHAR dotmsi[] = {'.','m','s','i',0};
- MSIDATABASE *db = NULL;
+ MSIDATABASE *db;
MSIPACKAGE *package;
MSIHANDLE handle;
+ MSIRECORD *data_row, *info_row;
LPWSTR ptr, base_url = NULL;
UINT r;
- WCHAR temppath[MAX_PATH], localfile[MAX_PATH], cachefile[MAX_PATH];
+ WCHAR localfile[MAX_PATH], cachefile[MAX_PATH];
LPCWSTR file = szPackage;
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] == '#' )
{
handle = atoiW(&szPackage[1]);
if ( UrlIsW( szPackage, URLIS_URL ) )
{
r = msi_download_file( szPackage, cachefile );
- if ( r != ERROR_SUCCESS )
- return r;
-
- r = copy_package_to_temp( cachefile, temppath );
- if ( r != ERROR_SUCCESS )
+ if (r != ERROR_SUCCESS)
return r;
- file = temppath;
+ file = cachefile;
base_url = strdupW( szPackage );
- if ( !base_url )
+ if (!base_url)
return ERROR_OUTOFMEMORY;
ptr = strrchrW( base_url, '/' );
if (ptr) *(ptr + 1) = '\0';
}
- else
+ r = get_local_package( file, localfile );
+ if (r != ERROR_SUCCESS || GetFileAttributesW( localfile ) == INVALID_FILE_ATTRIBUTES)
{
- r = copy_package_to_temp( szPackage, temppath );
- if ( r != ERROR_SUCCESS )
+ r = msi_create_empty_local_file( localfile, dotmsi );
+ if (r != ERROR_SUCCESS)
+ {
+ msi_free ( base_url );
return r;
+ }
- file = temppath;
+ 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;
}
-
- r = msi_get_local_package_name( localfile, dotmsi );
+ TRACE("opening package %s\n", debugstr_w( localfile ));
+ r = MSI_OpenDatabaseW( localfile, MSIDBOPEN_TRANSACT, &db );
if (r != ERROR_SUCCESS)
- return r;
-
- TRACE("Copying to local package %s\n", debugstr_w(localfile));
-
- if (!CopyFileW( file, localfile, FALSE ))
- {
- ERR("Unable to copy package (%s -> %s) (error %u)\n",
- debugstr_w(file), debugstr_w(localfile), GetLastError());
- return GetLastError();
- }
-
- TRACE("Opening relocated package %s\n", debugstr_w( file ));
-
- /* transforms that add binary streams require that we open the database
- * read/write, which is safe because we always create a copy that is thrown
- * away when we're done.
- */
- r = MSI_OpenDatabaseW( file, MSIDBOPEN_TRANSACT, &db );
- if( r != ERROR_SUCCESS )
{
- if (file != szPackage)
- DeleteFileW( file );
-
- if (GetFileAttributesW(szPackage) == INVALID_FILE_ATTRIBUTES)
- return ERROR_FILE_NOT_FOUND;
-
+ msi_free ( base_url );
return r;
}
-
- db->localfile = strdupW( localfile );
}
-
package = MSI_CreatePackage( db, base_url );
msi_free( base_url );
msiobj_release( &db->hdr );
- if( !package )
- {
- if (file != szPackage)
- DeleteFileW( file );
-
- return ERROR_INSTALL_PACKAGE_INVALID;
- }
+ if (!package) return ERROR_INSTALL_PACKAGE_INVALID;
+ package->localfile = strdupW( localfile );
+ package->delete_on_close = delete_on_close;
- if( file != szPackage )
- track_tempfile( package, file );
-
- 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 %u\n", r);
- 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)
{
msiobj_release( &package->hdr );
return r;
}
-
r = validate_package( package );
if (r != ERROR_SUCCESS)
{
msiobj_release( &package->hdr );
return r;
}
- msi_set_property( package->db, Database, 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)
TRACE("found registered patch %s\n", debugstr_w(patch_code));
- r = apply_registered_patch( package, patch_code );
+ r = msi_apply_registered_patch( package, patch_code );
if (r != ERROR_SUCCESS)
{
ERR("registered patch failed to apply %u\n", r);
msiobj_release( &package->hdr );
return r;
}
-
index++;
}
+ if (index) msi_adjust_privilege_properties( package );
- if (index)
+ 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;
}
ret = ERROR_NOT_ENOUGH_MEMORY;
msiobj_release( &package->hdr );
}
+ else
+ MSI_ProcessMessage(NULL, INSTALLMESSAGE_TERMINATE, 0);
return ret;
}
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 szActionText[] = {'A','c','t','i','o','n','T','e','x','t',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)
{
- 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};
- LPWSTR message;
- DWORD sz, total_size = 0, log_type = 0;
- INT i, rc = 0;
+ LPWSTR message = {0};
+ DWORD len, log_type = 0;
+ UINT res;
+ INT rc = 0;
char *msg;
- int len;
TRACE("%x\n", eMessageType);
+ if (TRACE_ON(msi)) dump_record(record);
+ if ((eMessageType & 0xff000000) == INSTALLMESSAGE_FATALEXIT)
+ log_type |= INSTALLLOGMODE_FATALEXIT;
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ERROR)
log_type |= INSTALLLOGMODE_ERROR;
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_WARNING)
log_type |= INSTALLLOGMODE_USER;
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INFO)
log_type |= INSTALLLOGMODE_INFO;
+ if ((eMessageType & 0xff000000) == INSTALLMESSAGE_RESOLVESOURCE)
+ log_type |= INSTALLLOGMODE_RESOLVESOURCE;
+ if ((eMessageType & 0xff000000) == INSTALLMESSAGE_OUTOFDISKSPACE)
+ log_type |= INSTALLLOGMODE_OUTOFDISKSPACE;
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_COMMONDATA)
log_type |= INSTALLLOGMODE_COMMONDATA;
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART)
log_type |= INSTALLLOGMODE_ACTIONSTART;
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONDATA)
log_type |= INSTALLLOGMODE_ACTIONDATA;
- /* just a guess */
if ((eMessageType & 0xff000000) == INSTALLMESSAGE_PROGRESS)
- log_type |= 0x800;
-
- 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
- {
- INT msg_field=1;
- message = msi_alloc(1*sizeof (WCHAR));
- message[0]=0;
- msg_field = MSI_RecordGetFieldCount(record);
- for (i = 1; i <= msg_field; i++)
- {
- LPWSTR tmp;
- WCHAR number[3];
- static const WCHAR format[] = { '%','i',':',' ',0};
- sz = 0;
- MSI_RecordGetStringW(record,i,NULL,&sz);
- sz+=4;
- total_size+=sz*sizeof(WCHAR);
- tmp = msi_alloc(sz*sizeof(WCHAR));
- message = msi_realloc(message,total_size*sizeof (WCHAR));
-
- MSI_RecordGetStringW(record,i,tmp,&sz);
-
- if (msg_field > 1)
- {
- sprintfW(number,format,i);
- strcatW(message,number);
- }
- strcatW(message,tmp);
- if (msg_field > 1)
- strcatW(message, szSpace);
-
- msi_free(tmp);
- }
+ log_type |= INSTALLLOGMODE_PROGRESS;
+ if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INITIALIZE)
+ log_type |= INSTALLLOGMODE_INITIALIZE;
+ if ((eMessageType & 0xff000000) == INSTALLMESSAGE_TERMINATE)
+ log_type |= INSTALLLOGMODE_TERMINATE;
+ if ((eMessageType & 0xff000000) == INSTALLMESSAGE_SHOWDIALOG)
+ log_type |= INSTALLLOGMODE_SHOWDIALOG;
+
+ 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;
msi_free( msg );
msi_free( message );
+ return rc;
+}
+
+INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIRECORD *record )
+{
switch (eMessageType & 0xff000000)
{
- case INSTALLMESSAGE_ACTIONDATA:
- /* FIXME: format record here instead of in ui_actiondata to get the
- * correct action data for external scripts */
- ControlEvent_FireSubscribedEvent(package, szActionData, record);
+ 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 */
+
+ LPWSTR template;
+ LPWSTR template_rec = NULL, template_prefix = NULL;
+ int error = MSI_RecordGetInteger(record, 1);
+
+ 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);
+
+ template_prefix = msi_get_error_message(package->db, eMessageType >> 24);
+ if (!template_prefix) template_prefix = strdupW(szEmpty);
+
+ if (!template_rec)
+ {
+ /* always returns 0 */
+ MSI_RecordSetStringW(record, 0, template_prefix);
+ MSI_ProcessMessageVerbatim(package, eMessageType, record);
+ msi_free(template_prefix);
+ return 0;
+ }
+
+ 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:
{
- MSIRECORD *uirow;
- LPWSTR deformated;
- LPCWSTR action_text = MSI_RecordGetString(record, 2);
+ WCHAR *template = msi_get_error_message(package->db, MSIERR_ACTIONSTART);
+ MSI_RecordSetStringW(record, 0, template);
+ msi_free(template);
- deformat_string(package, action_text, &deformated);
- uirow = MSI_CreateRecord(1);
- MSI_RecordSetStringW(uirow, 1, deformated);
- TRACE("INSTALLMESSAGE_ACTIONSTART: %s\n", debugstr_w(deformated));
- msi_free(deformated);
-
- ControlEvent_FireSubscribedEvent(package, szActionText, uirow);
-
- msiobj_release(&uirow->hdr);
+ 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_PROGRESS:
- ControlEvent_FireSubscribedEvent(package, szSetProgress, record);
+ 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,
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 )
{
}
}
-UINT msi_set_property( MSIDATABASE *db, LPCWSTR szName, LPCWSTR szValue )
+UINT msi_set_property( MSIDATABASE *db, const WCHAR *name, const WCHAR *value, int len )
{
- MSIQUERY *view;
- MSIRECORD *row = NULL;
- UINT rc;
- DWORD sz = 0;
- WCHAR Query[1024];
-
- static const WCHAR Insert[] = {
- 'I','N','S','E','R','T',' ','i','n','t','o',' ',
- '`','_','P','r','o','p','e','r','t','y','`',' ','(',
- '`','_','P','r','o','p','e','r','t','y','`',',',
- '`','V','a','l','u','e','`',')',' ','V','A','L','U','E','S'
- ,' ','(','?',',','?',')',0};
- static const WCHAR Update[] = {
- 'U','P','D','A','T','E',' ','`','_','P','r','o','p','e','r','t','y','`',
- ' ','s','e','t',' ','`','V','a','l','u','e','`',' ','=',' ','?',' ',
- 'w','h','e','r','e',' ','`','_','P','r','o','p','e','r','t','y','`',
- ' ','=',' ','\'','%','s','\'',0};
- static const WCHAR Delete[] = {
+ static const WCHAR insert_query[] = {
+ 'I','N','S','E','R','T',' ','I','N','T','O',' ',
+ '`','_','P','r','o','p','e','r','t','y','`',' ',
+ '(','`','_','P','r','o','p','e','r','t','y','`',',','`','V','a','l','u','e','`',')',' ',
+ 'V','A','L','U','E','S',' ','(','?',',','?',')',0};
+ static const WCHAR update_query[] = {
+ 'U','P','D','A','T','E',' ','`','_','P','r','o','p','e','r','t','y','`',' ',
+ 'S','E','T',' ','`','V','a','l','u','e','`',' ','=',' ','?',' ','W','H','E','R','E',' ',
+ '`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',0};
+ static const WCHAR delete_query[] = {
'D','E','L','E','T','E',' ','F','R','O','M',' ',
'`','_','P','r','o','p','e','r','t','y','`',' ','W','H','E','R','E',' ',
'`','_','P','r','o','p','e','r','t','y','`',' ','=',' ','\'','%','s','\'',0};
+ MSIQUERY *view;
+ MSIRECORD *row = NULL;
+ DWORD sz = 0;
+ 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, szName);
+ sprintfW( query, delete_query, name );
}
else if (rc == ERROR_MORE_DATA || rc == ERROR_SUCCESS)
{
- sprintfW(Query, Update, 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);
-
+ 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);
+ rc = MSI_DatabaseOpenViewW(db, query, &view);
if (rc == ERROR_SUCCESS)
{
rc = MSI_ViewExecute(view, row);
MSI_ViewClose(view);
msiobj_release(&view->hdr);
}
-
- if (row)
- msiobj_release(&row->hdr);
-
+ if (row) msiobj_release(&row->hdr);
return rc;
}
return ERROR_SUCCESS;
}
- ret = msi_set_property( package->db, szName, szValue );
- if (ret == ERROR_SUCCESS && !strcmpW( szName, cszSourceDir ))
+ ret = msi_set_property( package->db, szName, szValue, -1 );
+ if (ret == ERROR_SUCCESS && !strcmpW( szName, szSourceDir ))
msi_reset_folders( package, TRUE );
msiobj_release( &package->hdr );
static MSIRECORD *msi_get_property_row( MSIDATABASE *db, LPCWSTR name )
{
- MSIQUERY *view;
+ static const WCHAR query[]= {
+ 'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ',
+ 'F','R','O','M',' ' ,'`','_','P','r','o','p','e','r','t','y','`',' ',
+ 'W','H','E','R','E',' ' ,'`','_','P','r','o','p','e','r','t','y','`','=','?',0};
MSIRECORD *rec, *row = NULL;
+ MSIQUERY *view;
UINT r;
- static const WCHAR query[]= {
- 'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ',
- 'F','R','O','M',' ' ,'`','_','P','r','o','p','e','r','t','y','`',
- ' ','W','H','E','R','E',' ' ,'`','_','P','r','o','p','e','r','t','y','`',
- '=','?',0};
+ 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;
MSI_ViewClose(view);
msiobj_release(&view->hdr);
}
-
msiobj_release(&rec->hdr);
return row;
}
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)
}
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,
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 );
IWineMsiRemotePackage *remote_package;
LPWSTR value = NULL;
BSTR bname;
- DWORD len;
remote_package = (IWineMsiRemotePackage *)msi_get_remote( handle );
if (!remote_package)
return ERROR_OUTOFMEMORY;
}
- len = 0;
hr = IWineMsiRemotePackage_GetProperty( remote_package, bname, NULL, &len );
if (FAILED(hr))
goto done;
goto done;
}
- hr = IWineMsiRemotePackage_GetProperty( remote_package, bname, (BSTR *)value, &len );
+ hr = IWineMsiRemotePackage_GetProperty( remote_package, bname, value, &len );
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)
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 );
if( IsEqualCLSID( riid, &IID_IUnknown ) ||
IsEqualCLSID( riid, &IID_IWineMsiRemotePackage ) )
{
- IUnknown_AddRef( iface );
+ IWineMsiRemotePackage_AddRef( iface );
*ppobj = iface;
return S_OK;
}
return S_OK;
}
-static HRESULT WINAPI mrp_GetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR *value, DWORD *size )
+static HRESULT WINAPI mrp_GetProperty( IWineMsiRemotePackage *iface, BSTR property, BSTR value, DWORD *size )
{
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
- UINT r;
-
- r = MsiGetPropertyW(This->package, (LPWSTR)property, (LPWSTR)value, size);
- if (r != ERROR_SUCCESS)
- return HRESULT_FROM_WIN32(r);
-
+ UINT r = MsiGetPropertyW(This->package, property, value, size);
+ if (r != ERROR_SUCCESS) return HRESULT_FROM_WIN32(r);
return S_OK;
}
return HRESULT_FROM_WIN32(r);
}
-static HRESULT WINAPI mrp_GetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR *value, DWORD *size )
+static HRESULT WINAPI mrp_GetTargetPath( IWineMsiRemotePackage *iface, BSTR folder, BSTR value, DWORD *size )
{
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
- UINT r = MsiGetTargetPathW(This->package, (LPWSTR)folder, (LPWSTR)value, size);
+ UINT r = MsiGetTargetPathW(This->package, folder, value, size);
return HRESULT_FROM_WIN32(r);
}
return HRESULT_FROM_WIN32(r);
}
-static HRESULT WINAPI mrp_GetSourcePath( IWineMsiRemotePackage *iface, BSTR folder, BSTR *value, DWORD *size )
+static HRESULT WINAPI mrp_GetSourcePath( IWineMsiRemotePackage *iface, BSTR folder, BSTR value, DWORD *size )
{
msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
- UINT r = MsiGetSourcePathW(This->package, (LPWSTR)folder, (LPWSTR)value, size);
+ UINT r = MsiGetSourcePathW(This->package, folder, value, size);
return HRESULT_FROM_WIN32(r);
}
return HRESULT_FROM_WIN32(r);
}
+static HRESULT WINAPI mrp_EnumComponentCosts( IWineMsiRemotePackage *iface, BSTR component,
+ DWORD index, INSTALLSTATE state, BSTR drive,
+ DWORD *buflen, INT *cost, INT *temp )
+{
+ msi_remote_package_impl* This = impl_from_IWineMsiRemotePackage( iface );
+ UINT r = MsiEnumComponentCostsW(This->package, component, index, state, drive, buflen, cost, temp);
+ return HRESULT_FROM_WIN32(r);
+}
+
static const IWineMsiRemotePackageVtbl msi_remote_package_vtbl =
{
mrp_QueryInterface,
mrp_FormatRecord,
mrp_EvaluateCondition,
mrp_GetFeatureCost,
+ mrp_EnumComponentCosts
};
HRESULT create_msi_remote_package( IUnknown *pOuter, LPVOID *ppObj )
This->package = 0;
This->refs = 1;
- *ppObj = This;
+ *ppObj = &This->IWineMsiRemotePackage_iface;
return S_OK;
}