diff --git a/dlls/msi/action.c b/dlls/msi/action.c index 16652000ee5..e016b43a8c1 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -30,7 +30,6 @@ #include "odbcinst.h" #include "wine/debug.h" #include "msidefs.h" -#include "msipriv.h" #include "winuser.h" #include "shlobj.h" #include "objbase.h" @@ -40,6 +39,9 @@ #include "wine/unicode.h" #include "winver.h" +#include "msipriv.h" +#include "resource.h" + #define REG_PROGRESS_VALUE 13200 #define COMPONENT_PROGRESS_VALUE 24000 @@ -156,18 +158,13 @@ static const WCHAR szValidateProductID[] = static const WCHAR szWriteEnvironmentStrings[] = {'W','r','i','t','e','E','n','v','i','r','o','n','m','e','n','t','S','t','r','i','n','g','s',0}; -static void ui_actionstart(MSIPACKAGE *package, LPCWSTR action) +static void ui_actionstart(MSIPACKAGE *package, LPCWSTR action, LPCWSTR description, LPCWSTR template) { - static const WCHAR Query_t[] = - {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', - '`','A','c','t','i','o', 'n','T','e','x','t','`',' ', - 'W','H','E','R','E', ' ','`','A','c','t','i','o','n','`',' ','=', - ' ','\'','%','s','\'',0}; - MSIRECORD * row; - - row = MSI_QueryGetRecord( package->db, Query_t, action ); - if (!row) - return; + MSIRECORD *row = MSI_CreateRecord(3); + if (!row) return; + MSI_RecordSetStringW(row, 1, action); + MSI_RecordSetStringW(row, 2, description); + MSI_RecordSetStringW(row, 3, template); MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONSTART, row); msiobj_release(&row->hdr); } @@ -175,28 +172,22 @@ static void ui_actionstart(MSIPACKAGE *package, LPCWSTR action) static void ui_actioninfo(MSIPACKAGE *package, LPCWSTR action, BOOL start, UINT rc) { - MSIRECORD * row; - static const WCHAR template_s[]= - {'A','c','t','i','o','n',' ','s','t','a','r','t',' ','%','s',':',' ', - '%','s', '.',0}; - static const WCHAR template_e[]= - {'A','c','t','i','o','n',' ','e','n','d','e','d',' ','%','s',':',' ', - '%','s', '.',' ','R','e','t','u','r','n',' ','v','a','l','u','e',' ', - '%','i','.',0}; + MSIRECORD *row; + WCHAR template[1024]; static const WCHAR format[] = {'H','H','\'',':','\'','m','m','\'',':','\'','s','s',0}; WCHAR message[1024]; WCHAR timet[0x100]; GetTimeFormatW(LOCALE_USER_DEFAULT, 0, NULL, format, timet, 0x100); - if (start) - sprintfW(message,template_s,timet,action); - else - sprintfW(message,template_e,timet,action,rc); - - row = MSI_CreateRecord(1); - MSI_RecordSetStringW(row,1,message); - + LoadStringW(msi_hInstance, start ? IDS_INFO_ACTIONSTART : IDS_INFO_ACTIONENDED, template, 1024); + sprintfW(message, template, timet); + + row = MSI_CreateRecord(2); + if (!row) return; + MSI_RecordSetStringW(row, 0, message); + MSI_RecordSetStringW(row, 1, action); + MSI_RecordSetInteger(row, 2, !rc); MSI_ProcessMessage(package, INSTALLMESSAGE_INFO, row); msiobj_release(&row->hdr); } @@ -622,7 +613,11 @@ static BOOL ACTION_HandleCustomAction( MSIPACKAGE *package, LPCWSTR action, UINT BOOL ret=FALSE; UINT arc; + ui_actionstart(package, action, NULL, NULL); + ui_actioninfo(package, action, TRUE, 0); arc = ACTION_CustomAction( package, action, script ); + ui_actioninfo(package, action, FALSE, arc); + if (arc != ERROR_CALL_NOT_IMPLEMENTED) { *rc = arc; @@ -1567,7 +1562,7 @@ static UINT ACTION_CostInitialize(MSIPACKAGE *package) static UINT execute_script_action( MSIPACKAGE *package, UINT script, UINT index ) { const WCHAR *action = package->script->Actions[script][index]; - ui_actionstart( package, action ); + ui_actionstart( package, action, NULL, NULL ); TRACE("executing %s\n", debugstr_w(action)); return ACTION_PerformAction( package, action, script ); } @@ -7690,88 +7685,90 @@ static UINT ACTION_InstallSFPCatalogFile( MSIPACKAGE *package ) static const struct { const WCHAR *action; + const UINT description; + const UINT template; UINT (*handler)(MSIPACKAGE *); const WCHAR *action_rollback; } StandardActions[] = { - { szAllocateRegistrySpace, ACTION_AllocateRegistrySpace, NULL }, - { szAppSearch, ACTION_AppSearch, NULL }, - { szBindImage, ACTION_BindImage, NULL }, - { szCCPSearch, ACTION_CCPSearch, NULL }, - { szCostFinalize, ACTION_CostFinalize, NULL }, - { szCostInitialize, ACTION_CostInitialize, NULL }, - { szCreateFolders, ACTION_CreateFolders, szRemoveFolders }, - { szCreateShortcuts, ACTION_CreateShortcuts, szRemoveShortcuts }, - { szDeleteServices, ACTION_DeleteServices, szInstallServices }, - { szDisableRollback, ACTION_DisableRollback, NULL }, - { szDuplicateFiles, ACTION_DuplicateFiles, szRemoveDuplicateFiles }, - { szExecuteAction, ACTION_ExecuteAction, NULL }, - { szFileCost, ACTION_FileCost, NULL }, - { szFindRelatedProducts, ACTION_FindRelatedProducts, NULL }, - { szForceReboot, ACTION_ForceReboot, NULL }, - { szInstallAdminPackage, ACTION_InstallAdminPackage, NULL }, - { szInstallExecute, ACTION_InstallExecute, NULL }, - { szInstallExecuteAgain, ACTION_InstallExecute, NULL }, - { szInstallFiles, ACTION_InstallFiles, szRemoveFiles }, - { szInstallFinalize, ACTION_InstallFinalize, NULL }, - { szInstallInitialize, ACTION_InstallInitialize, NULL }, - { szInstallODBC, ACTION_InstallODBC, szRemoveODBC }, - { szInstallServices, ACTION_InstallServices, szDeleteServices }, - { szInstallSFPCatalogFile, ACTION_InstallSFPCatalogFile, NULL }, - { szInstallValidate, ACTION_InstallValidate, NULL }, - { szIsolateComponents, ACTION_IsolateComponents, NULL }, - { szLaunchConditions, ACTION_LaunchConditions, NULL }, - { szMigrateFeatureStates, ACTION_MigrateFeatureStates, NULL }, - { szMoveFiles, ACTION_MoveFiles, NULL }, - { szMsiPublishAssemblies, ACTION_MsiPublishAssemblies, szMsiUnpublishAssemblies }, - { szMsiUnpublishAssemblies, ACTION_MsiUnpublishAssemblies, szMsiPublishAssemblies }, - { szPatchFiles, ACTION_PatchFiles, NULL }, - { szProcessComponents, ACTION_ProcessComponents, szProcessComponents }, - { szPublishComponents, ACTION_PublishComponents, szUnpublishComponents }, - { szPublishFeatures, ACTION_PublishFeatures, szUnpublishFeatures }, - { szPublishProduct, ACTION_PublishProduct, szUnpublishProduct }, - { szRegisterClassInfo, ACTION_RegisterClassInfo, szUnregisterClassInfo }, - { szRegisterComPlus, ACTION_RegisterComPlus, szUnregisterComPlus }, - { szRegisterExtensionInfo, ACTION_RegisterExtensionInfo, szUnregisterExtensionInfo }, - { szRegisterFonts, ACTION_RegisterFonts, szUnregisterFonts }, - { szRegisterMIMEInfo, ACTION_RegisterMIMEInfo, szUnregisterMIMEInfo }, - { szRegisterProduct, ACTION_RegisterProduct, NULL }, - { szRegisterProgIdInfo, ACTION_RegisterProgIdInfo, szUnregisterProgIdInfo }, - { szRegisterTypeLibraries, ACTION_RegisterTypeLibraries, szUnregisterTypeLibraries }, - { szRegisterUser, ACTION_RegisterUser, NULL }, - { szRemoveDuplicateFiles, ACTION_RemoveDuplicateFiles, szDuplicateFiles }, - { szRemoveEnvironmentStrings, ACTION_RemoveEnvironmentStrings, szWriteEnvironmentStrings }, - { szRemoveExistingProducts, ACTION_RemoveExistingProducts, NULL }, - { szRemoveFiles, ACTION_RemoveFiles, szInstallFiles }, - { szRemoveFolders, ACTION_RemoveFolders, szCreateFolders }, - { szRemoveIniValues, ACTION_RemoveIniValues, szWriteIniValues }, - { szRemoveODBC, ACTION_RemoveODBC, szInstallODBC }, - { szRemoveRegistryValues, ACTION_RemoveRegistryValues, szWriteRegistryValues }, - { szRemoveShortcuts, ACTION_RemoveShortcuts, szCreateShortcuts }, - { szResolveSource, ACTION_ResolveSource, NULL }, - { szRMCCPSearch, ACTION_RMCCPSearch, NULL }, - { szScheduleReboot, ACTION_ScheduleReboot, NULL }, - { szSelfRegModules, ACTION_SelfRegModules, szSelfUnregModules }, - { szSelfUnregModules, ACTION_SelfUnregModules, szSelfRegModules }, - { szSetODBCFolders, ACTION_SetODBCFolders, NULL }, - { szStartServices, ACTION_StartServices, szStopServices }, - { szStopServices, ACTION_StopServices, szStartServices }, - { szUnpublishComponents, ACTION_UnpublishComponents, szPublishComponents }, - { szUnpublishFeatures, ACTION_UnpublishFeatures, szPublishFeatures }, - { szUnpublishProduct, ACTION_UnpublishProduct, NULL }, /* for rollback only */ - { szUnregisterClassInfo, ACTION_UnregisterClassInfo, szRegisterClassInfo }, - { szUnregisterComPlus, ACTION_UnregisterComPlus, szRegisterComPlus }, - { szUnregisterExtensionInfo, ACTION_UnregisterExtensionInfo, szRegisterExtensionInfo }, - { szUnregisterFonts, ACTION_UnregisterFonts, szRegisterFonts }, - { szUnregisterMIMEInfo, ACTION_UnregisterMIMEInfo, szRegisterMIMEInfo }, - { szUnregisterProgIdInfo, ACTION_UnregisterProgIdInfo, szRegisterProgIdInfo }, - { szUnregisterTypeLibraries, ACTION_UnregisterTypeLibraries, szRegisterTypeLibraries }, - { szValidateProductID, ACTION_ValidateProductID, NULL }, - { szWriteEnvironmentStrings, ACTION_WriteEnvironmentStrings, szRemoveEnvironmentStrings }, - { szWriteIniValues, ACTION_WriteIniValues, szRemoveIniValues }, - { szWriteRegistryValues, ACTION_WriteRegistryValues, szRemoveRegistryValues }, - { NULL, NULL, NULL } + { szAllocateRegistrySpace, IDS_DESC_ALLOCATEREGISTRYSPACE, IDS_TEMP_ALLOCATEREGISTRYSPACE, ACTION_AllocateRegistrySpace, NULL }, + { szAppSearch, IDS_DESC_APPSEARCH, IDS_TEMP_APPSEARCH, ACTION_AppSearch, NULL }, + { szBindImage, IDS_DESC_BINDIMAGE, IDS_TEMP_BINDIMAGE, ACTION_BindImage, NULL }, + { szCCPSearch, IDS_DESC_CCPSEARCH, 0, ACTION_CCPSearch, NULL }, + { szCostFinalize, IDS_DESC_COSTFINALIZE, 0, ACTION_CostFinalize, NULL }, + { szCostInitialize, IDS_DESC_COSTINITIALIZE, 0, ACTION_CostInitialize, NULL }, + { szCreateFolders, IDS_DESC_CREATEFOLDERS, IDS_TEMP_CREATEFOLDERS, ACTION_CreateFolders, szRemoveFolders }, + { szCreateShortcuts, IDS_DESC_CREATESHORTCUTS, IDS_TEMP_CREATESHORTCUTS, ACTION_CreateShortcuts, szRemoveShortcuts }, + { szDeleteServices, IDS_DESC_DELETESERVICES, IDS_TEMP_DELETESERVICES, ACTION_DeleteServices, szInstallServices }, + { szDisableRollback, 0, 0, ACTION_DisableRollback, NULL }, + { szDuplicateFiles, IDS_DESC_DUPLICATEFILES, IDS_TEMP_DUPLICATEFILES, ACTION_DuplicateFiles, szRemoveDuplicateFiles }, + { szExecuteAction, 0, 0, ACTION_ExecuteAction, NULL }, + { szFileCost, IDS_DESC_FILECOST, 0, ACTION_FileCost, NULL }, + { szFindRelatedProducts, IDS_DESC_FINDRELATEDPRODUCTS, IDS_TEMP_FINDRELATEDPRODUCTS, ACTION_FindRelatedProducts, NULL }, + { szForceReboot, 0, 0, ACTION_ForceReboot, NULL }, + { szInstallAdminPackage, IDS_DESC_INSTALLADMINPACKAGE, IDS_TEMP_INSTALLADMINPACKAGE, ACTION_InstallAdminPackage, NULL }, + { szInstallExecute, 0, 0, ACTION_InstallExecute, NULL }, + { szInstallExecuteAgain, 0, 0, ACTION_InstallExecute, NULL }, + { szInstallFiles, IDS_DESC_INSTALLFILES, IDS_TEMP_INSTALLFILES, ACTION_InstallFiles, szRemoveFiles }, + { szInstallFinalize, 0, 0, ACTION_InstallFinalize, NULL }, + { szInstallInitialize, 0, 0, ACTION_InstallInitialize, NULL }, + { szInstallODBC, IDS_DESC_INSTALLODBC, 0, ACTION_InstallODBC, szRemoveODBC }, + { szInstallServices, IDS_DESC_INSTALLSERVICES, IDS_TEMP_INSTALLSERVICES, ACTION_InstallServices, szDeleteServices }, + { szInstallSFPCatalogFile, IDS_DESC_INSTALLSFPCATALOGFILE, IDS_TEMP_INSTALLSFPCATALOGFILE, ACTION_InstallSFPCatalogFile, NULL }, + { szInstallValidate, IDS_DESC_INSTALLVALIDATE, 0, ACTION_InstallValidate, NULL }, + { szIsolateComponents, 0, 0, ACTION_IsolateComponents, NULL }, + { szLaunchConditions, IDS_DESC_LAUNCHCONDITIONS, 0, ACTION_LaunchConditions, NULL }, + { szMigrateFeatureStates, IDS_DESC_MIGRATEFEATURESTATES, IDS_TEMP_MIGRATEFEATURESTATES, ACTION_MigrateFeatureStates, NULL }, + { szMoveFiles, IDS_DESC_MOVEFILES, IDS_TEMP_MOVEFILES, ACTION_MoveFiles, NULL }, + { szMsiPublishAssemblies, IDS_DESC_MSIPUBLISHASSEMBLIES, IDS_TEMP_MSIPUBLISHASSEMBLIES, ACTION_MsiPublishAssemblies, szMsiUnpublishAssemblies }, + { szMsiUnpublishAssemblies, IDS_DESC_MSIUNPUBLISHASSEMBLIES, IDS_TEMP_MSIUNPUBLISHASSEMBLIES, ACTION_MsiUnpublishAssemblies, szMsiPublishAssemblies }, + { szPatchFiles, IDS_DESC_PATCHFILES, IDS_TEMP_PATCHFILES, ACTION_PatchFiles, NULL }, + { szProcessComponents, IDS_DESC_PROCESSCOMPONENTS, 0, ACTION_ProcessComponents, szProcessComponents }, + { szPublishComponents, IDS_DESC_PUBLISHCOMPONENTS, IDS_TEMP_PUBLISHCOMPONENTS, ACTION_PublishComponents, szUnpublishComponents }, + { szPublishFeatures, IDS_DESC_PUBLISHFEATURES, IDS_TEMP_PUBLISHFEATURES, ACTION_PublishFeatures, szUnpublishFeatures }, + { szPublishProduct, IDS_DESC_PUBLISHPRODUCT, 0, ACTION_PublishProduct, szUnpublishProduct }, + { szRegisterClassInfo, IDS_DESC_REGISTERCLASSINFO, IDS_TEMP_REGISTERCLASSINFO, ACTION_RegisterClassInfo, szUnregisterClassInfo }, + { szRegisterComPlus, IDS_DESC_REGISTERCOMPLUS, IDS_TEMP_REGISTERCOMPLUS, ACTION_RegisterComPlus, szUnregisterComPlus }, + { szRegisterExtensionInfo, IDS_DESC_REGISTEREXTENSIONINFO, 0, ACTION_RegisterExtensionInfo, szUnregisterExtensionInfo }, + { szRegisterFonts, IDS_DESC_REGISTERFONTS, IDS_TEMP_REGISTERFONTS, ACTION_RegisterFonts, szUnregisterFonts }, + { szRegisterMIMEInfo, IDS_DESC_REGISTERMIMEINFO, IDS_TEMP_REGISTERMIMEINFO, ACTION_RegisterMIMEInfo, szUnregisterMIMEInfo }, + { szRegisterProduct, IDS_DESC_REGISTERPRODUCT, 0, ACTION_RegisterProduct, NULL }, + { szRegisterProgIdInfo, IDS_DESC_REGISTERPROGIDINFO, IDS_TEMP_REGISTERPROGIDINFO, ACTION_RegisterProgIdInfo, szUnregisterProgIdInfo }, + { szRegisterTypeLibraries, IDS_DESC_REGISTERTYPELIBRARIES, IDS_TEMP_REGISTERTYPELIBRARIES, ACTION_RegisterTypeLibraries, szUnregisterTypeLibraries }, + { szRegisterUser, IDS_DESC_REGISTERUSER, 0, ACTION_RegisterUser, NULL }, + { szRemoveDuplicateFiles, IDS_DESC_REMOVEDUPLICATEFILES, IDS_TEMP_REMOVEDUPLICATEFILES, ACTION_RemoveDuplicateFiles, szDuplicateFiles }, + { szRemoveEnvironmentStrings, IDS_DESC_REMOVEENVIRONMENTSTRINGS, IDS_TEMP_REMOVEENVIRONMENTSTRINGS, ACTION_RemoveEnvironmentStrings, szWriteEnvironmentStrings }, + { szRemoveExistingProducts, IDS_DESC_REMOVEEXISTINGPRODUCTS, IDS_TEMP_REMOVEEXISTINGPRODUCTS, ACTION_RemoveExistingProducts, NULL }, + { szRemoveFiles, IDS_DESC_REMOVEFILES, IDS_TEMP_REMOVEFILES, ACTION_RemoveFiles, szInstallFiles }, + { szRemoveFolders, IDS_DESC_REMOVEFOLDERS, IDS_TEMP_REMOVEFOLDERS, ACTION_RemoveFolders, szCreateFolders }, + { szRemoveIniValues, IDS_DESC_REMOVEINIVALUES, IDS_TEMP_REMOVEINIVALUES, ACTION_RemoveIniValues, szWriteIniValues }, + { szRemoveODBC, IDS_DESC_REMOVEODBC, 0, ACTION_RemoveODBC, szInstallODBC }, + { szRemoveRegistryValues, IDS_DESC_REMOVEREGISTRYVALUES, IDS_TEMP_REMOVEREGISTRYVALUES, ACTION_RemoveRegistryValues, szWriteRegistryValues }, + { szRemoveShortcuts, IDS_DESC_REMOVESHORTCUTS, IDS_TEMP_REMOVESHORTCUTS, ACTION_RemoveShortcuts, szCreateShortcuts }, + { szResolveSource, 0, 0, ACTION_ResolveSource, NULL }, + { szRMCCPSearch, IDS_DESC_RMCCPSEARCH, 0, ACTION_RMCCPSearch, NULL }, + { szScheduleReboot, 0, 0, ACTION_ScheduleReboot, NULL }, + { szSelfRegModules, IDS_DESC_SELFREGMODULES, IDS_TEMP_SELFREGMODULES, ACTION_SelfRegModules, szSelfUnregModules }, + { szSelfUnregModules, IDS_DESC_SELFUNREGMODULES, IDS_TEMP_SELFUNREGMODULES, ACTION_SelfUnregModules, szSelfRegModules }, + { szSetODBCFolders, IDS_DESC_SETODBCFOLDERS, 0, ACTION_SetODBCFolders, NULL }, + { szStartServices, IDS_DESC_STARTSERVICES, IDS_TEMP_STARTSERVICES, ACTION_StartServices, szStopServices }, + { szStopServices, IDS_DESC_STOPSERVICES, IDS_TEMP_STOPSERVICES, ACTION_StopServices, szStartServices }, + { szUnpublishComponents, IDS_DESC_UNPUBLISHCOMPONENTS, IDS_TEMP_UNPUBLISHCOMPONENTS, ACTION_UnpublishComponents, szPublishComponents }, + { szUnpublishFeatures, IDS_DESC_UNPUBLISHFEATURES, IDS_TEMP_UNPUBLISHFEATURES, ACTION_UnpublishFeatures, szPublishFeatures }, + { szUnpublishProduct, IDS_DESC_UNPUBLISHPRODUCT, 0, ACTION_UnpublishProduct, NULL }, /* for rollback only */ + { szUnregisterClassInfo, IDS_DESC_UNREGISTERCLASSINFO, IDS_TEMP_UNREGISTERCLASSINFO, ACTION_UnregisterClassInfo, szRegisterClassInfo }, + { szUnregisterComPlus, IDS_DESC_UNREGISTERCOMPLUS, IDS_TEMP_UNREGISTERCOMPLUS, ACTION_UnregisterComPlus, szRegisterComPlus }, + { szUnregisterExtensionInfo, IDS_DESC_UNREGISTEREXTENSIONINFO, IDS_TEMP_UNREGISTEREXTENSIONINFO, ACTION_UnregisterExtensionInfo, szRegisterExtensionInfo }, + { szUnregisterFonts, IDS_DESC_UNREGISTERFONTS, IDS_TEMP_UNREGISTERFONTS, ACTION_UnregisterFonts, szRegisterFonts }, + { szUnregisterMIMEInfo, IDS_DESC_UNREGISTERMIMEINFO, IDS_TEMP_UNREGISTERMIMEINFO, ACTION_UnregisterMIMEInfo, szRegisterMIMEInfo }, + { szUnregisterProgIdInfo, IDS_DESC_UNREGISTERPROGIDINFO, IDS_TEMP_UNREGISTERPROGIDINFO, ACTION_UnregisterProgIdInfo, szRegisterProgIdInfo }, + { szUnregisterTypeLibraries, IDS_DESC_UNREGISTERTYPELIBRARIES, IDS_TEMP_UNREGISTERTYPELIBRARIES, ACTION_UnregisterTypeLibraries, szRegisterTypeLibraries }, + { szValidateProductID, 0, 0, ACTION_ValidateProductID, NULL }, + { szWriteEnvironmentStrings, IDS_DESC_WRITEENVIRONMENTSTRINGS, IDS_TEMP_WRITEENVIRONMENTSTRINGS, ACTION_WriteEnvironmentStrings, szRemoveEnvironmentStrings }, + { szWriteIniValues, IDS_DESC_WRITEINIVALUES, IDS_TEMP_WRITEINIVALUES, ACTION_WriteIniValues, szRemoveIniValues }, + { szWriteRegistryValues, IDS_DESC_WRITEREGISTRYVALUES, IDS_TEMP_WRITEREGISTRYVALUES, ACTION_WriteRegistryValues, szRemoveRegistryValues }, + { 0 } }; static BOOL ACTION_HandleStandardAction( MSIPACKAGE *package, LPCWSTR action, UINT *rc ) @@ -7784,7 +7781,14 @@ static BOOL ACTION_HandleStandardAction( MSIPACKAGE *package, LPCWSTR action, UI { if (!strcmpW( StandardActions[i].action, action )) { - ui_actionstart( package, action ); + WCHAR description[100] = {0}, template[100] = {0}; + + if (StandardActions[i].description != 0) + LoadStringW(msi_hInstance, StandardActions[i].description, (LPWSTR)&description, 100); + if (StandardActions[i].template != 0) + LoadStringW(msi_hInstance, StandardActions[i].template, (LPWSTR)&template, 100); + + ui_actionstart(package, action, description, template); if (StandardActions[i].handler) { ui_actioninfo( package, action, TRUE, 0 ); diff --git a/dlls/msi/msi.rc b/dlls/msi/msi.rc index e52fac5ea00..4904a2d5e14 100644 --- a/dlls/msi/msi.rc +++ b/dlls/msi/msi.rc @@ -19,6 +19,7 @@ */ #include "windef.h" +#include "resource.h" #pragma makedep po @@ -63,6 +64,145 @@ STRINGTABLE 15 "choose which folder contains %s" } +/* Install message format strings */ +STRINGTABLE +{ + IDS_ACTIONSTART "Action %s: [1]. [2]" + IDS_INFO "Info [1]. " +} + +/* INSTALLMESSAGE_INFO strings */ +STRINGTABLE +{ + IDS_INFO_ACTIONSTART "Action start %s: [1]." + IDS_INFO_ACTIONENDED "Action ended %s: [1]. Return value [2]." +} + +/* Standard action description strings */ +STRINGTABLE +{ + IDS_DESC_ALLOCATEREGISTRYSPACE "Allocating registry space" + IDS_DESC_APPSEARCH "Searching for installed applications" + IDS_DESC_BINDIMAGE "Binding executables" + IDS_DESC_CCPSEARCH "Searching for qualifying products" + IDS_DESC_COSTFINALIZE "Computing space requirements" + IDS_DESC_COSTINITIALIZE "Computing space requirements" + IDS_DESC_CREATEFOLDERS "Creating folders" + IDS_DESC_CREATESHORTCUTS "Creating shortcuts" + IDS_DESC_DELETESERVICES "Deleting services" + IDS_DESC_DUPLICATEFILES "Creating duplicate files" + IDS_DESC_FILECOST "Computing space requirements" + IDS_DESC_FINDRELATEDPRODUCTS "Searching for related applications" + IDS_DESC_INSTALLADMINPACKAGE "Copying network install files" + IDS_DESC_INSTALLFILES "Copying new files" + IDS_DESC_INSTALLODBC "Installing ODBC components" + IDS_DESC_INSTALLSERVICES "Installing new services" + IDS_DESC_INSTALLSFPCATALOGFILE "Installing system catalog" + IDS_DESC_INSTALLVALIDATE "Validating install" + IDS_DESC_LAUNCHCONDITIONS "Evaluating launch conditions" + IDS_DESC_MIGRATEFEATURESTATES "Migrating feature states from related applications" + IDS_DESC_MOVEFILES "Moving files" + IDS_DESC_MSIPUBLISHASSEMBLIES "Publishing assembly information" + IDS_DESC_MSIUNPUBLISHASSEMBLIES "Unpublishing assembly information" + IDS_DESC_PATCHFILES "Patching files" + IDS_DESC_PROCESSCOMPONENTS "Updating component registration" + IDS_DESC_PUBLISHCOMPONENTS "Publishing Qualified Components" + IDS_DESC_PUBLISHFEATURES "Publishing Product Features" + IDS_DESC_PUBLISHPRODUCT "Publishing product information" + IDS_DESC_REGISTERCLASSINFO "Registering Class servers" + IDS_DESC_REGISTERCOMPLUS "Registering COM+ Applications and Components" + IDS_DESC_REGISTEREXTENSIONINFO "Registering extension servers" + IDS_DESC_REGISTERFONTS "Registering fonts" + IDS_DESC_REGISTERMIMEINFO "Registering MIME info" + IDS_DESC_REGISTERPRODUCT "Registering product" + IDS_DESC_REGISTERPROGIDINFO "Registering program identifiers" + IDS_DESC_REGISTERTYPELIBRARIES "Registering type libraries" + IDS_DESC_REGISTERUSER "Registering user" + IDS_DESC_REMOVEDUPLICATEFILES "Removing duplicated files" + IDS_DESC_REMOVEENVIRONMENTSTRINGS "Updating environment strings" + IDS_DESC_REMOVEEXISTINGPRODUCTS "Removing applications" + IDS_DESC_REMOVEFILES "Removing files" + IDS_DESC_REMOVEFOLDERS "Removing folders" + IDS_DESC_REMOVEINIVALUES "Removing INI files entries" + IDS_DESC_REMOVEODBC "Removing ODBC components" + IDS_DESC_REMOVEREGISTRYVALUES "Removing system registry values" + IDS_DESC_REMOVESHORTCUTS "Removing shortcuts" + IDS_DESC_RMCCPSEARCH "Searching for qualifying products" + IDS_DESC_SELFREGMODULES "Registering modules" + IDS_DESC_SELFUNREGMODULES "Unregistering modules" + IDS_DESC_SETODBCFOLDERS "Initializing ODBC directories" + IDS_DESC_STARTSERVICES "Starting services" + IDS_DESC_STOPSERVICES "Stopping services" + IDS_DESC_UNPUBLISHCOMPONENTS "Unpublishing Qualified Components" + IDS_DESC_UNPUBLISHFEATURES "Unpublishing Product Features" + IDS_DESC_UNPUBLISHPRODUCT "Unpublishing product information" + IDS_DESC_UNREGISTERCLASSINFO "Unregister Class servers" + IDS_DESC_UNREGISTERCOMPLUS "Unregistering COM+ Applications and Components" + IDS_DESC_UNREGISTEREXTENSIONINFO "Unregistering extension servers" + IDS_DESC_UNREGISTERFONTS "Unregistering fonts" + IDS_DESC_UNREGISTERMIMEINFO "Unregistering MIME info" + IDS_DESC_UNREGISTERPROGIDINFO "Unregistering program identifiers" + IDS_DESC_UNREGISTERTYPELIBRARIES "Unregistering type libraries" + IDS_DESC_WRITEENVIRONMENTSTRINGS "Updating environment strings" + IDS_DESC_WRITEINIVALUES "Writing INI files values" + IDS_DESC_WRITEREGISTRYVALUES "Writing system registry values" +} + +/* Standard action template strings */ +STRINGTABLE +{ + IDS_TEMP_ALLOCATEREGISTRYSPACE "Free space: [1]" + IDS_TEMP_APPSEARCH "Property: [1], Signature: [2]" + IDS_TEMP_BINDIMAGE "File: [1]" + IDS_TEMP_CREATEFOLDERS "Folder: [1]" + IDS_TEMP_CREATESHORTCUTS "Shortcut: [1]" + IDS_TEMP_DELETESERVICES "Service: [1]" + IDS_TEMP_DUPLICATEFILES "File: [1], Directory: [9], Size: [6]" + IDS_TEMP_FINDRELATEDPRODUCTS "Found application: [1]" + IDS_TEMP_INSTALLADMINPACKAGE "File: [1], Directory: [9], Size: [6]" + IDS_TEMP_INSTALLFILES "File: [1], Directory: [9], Size: [6]" + IDS_TEMP_INSTALLSERVICES "Service: [2]" + IDS_TEMP_INSTALLSFPCATALOGFILE "File: [1], Dependencies: [2]" + IDS_TEMP_MIGRATEFEATURESTATES "Application: [1]" + IDS_TEMP_MOVEFILES "File: [1], Directory: [9], Size: [6]" + IDS_TEMP_MSIPUBLISHASSEMBLIES "Application Context:[1], Assembly Name:[2]" + IDS_TEMP_MSIUNPUBLISHASSEMBLIES "Application Context:[1], Assembly Name:[2]" + IDS_TEMP_PATCHFILES "File: [1], Directory: [2], Size: [3]" + IDS_TEMP_PUBLISHCOMPONENTS "Component ID: [1], Qualifier: [2]" + IDS_TEMP_PUBLISHFEATURES "Feature: [1]" + IDS_TEMP_REGISTERCLASSINFO "Class Id: [1]" + IDS_TEMP_REGISTERCOMPLUS "AppId: [1]{{, AppType: [2], Users: [3], RSN: [4]}}" + IDS_TEMP_REGISTEREXTENSIONINFO "Extension: [1]" + IDS_TEMP_REGISTERFONTS "Font: [1]" + IDS_TEMP_REGISTERMIMEINFO "MIME Content Type: [1], Extension: [2]" + IDS_TEMP_REGISTERPROGIDINFO "ProgId: [1]" + IDS_TEMP_REGISTERTYPELIBRARIES "LibID: [1]" + IDS_TEMP_REMOVEDUPLICATEFILES "File: [1], Directory: [9]" + IDS_TEMP_REMOVEENVIRONMENTSTRINGS "Name: [1], Value: [2], Action [3]" + IDS_TEMP_REMOVEEXISTINGPRODUCTS "Application: [1], Command line: [2]" + IDS_TEMP_REMOVEFILES "File: [1], Directory: [9]" + IDS_TEMP_REMOVEFOLDERS "Folder: [1]" + IDS_TEMP_REMOVEINIVALUES "File: [1], Section: [2], Key: [3], Value: [4]" + IDS_TEMP_REMOVEREGISTRYVALUES "Key: [1], Name: [2]" + IDS_TEMP_REMOVESHORTCUTS "Shortcut: [1]" + IDS_TEMP_SELFREGMODULES "File: [1], Folder: [2]" + IDS_TEMP_SELFUNREGMODULES "File: [1], Folder: [2]" + IDS_TEMP_STARTSERVICES "Service: [1]" + IDS_TEMP_STOPSERVICES "Service: [1]" + IDS_TEMP_UNPUBLISHCOMPONENTS "Component ID: [1], Qualifier: [2]" + IDS_TEMP_UNPUBLISHFEATURES "Feature: [1]" + IDS_TEMP_UNREGISTERCLASSINFO "Class Id: [1]" + IDS_TEMP_UNREGISTERCOMPLUS "AppId: [1]{{, AppType: [2]}}" + IDS_TEMP_UNREGISTEREXTENSIONINFO "Extension: [1]" + IDS_TEMP_UNREGISTERFONTS "Font: [1]" + IDS_TEMP_UNREGISTERMIMEINFO "MIME Content Type: [1], Extension: [2]" + IDS_TEMP_UNREGISTERPROGIDINFO "ProgId: [1]" + IDS_TEMP_UNREGISTERTYPELIBRARIES "LibID: [1]" + IDS_TEMP_WRITEENVIRONMENTSTRINGS "Name: [1], Value: [2], Action [3]" + IDS_TEMP_WRITEINIVALUES "File: [1], Section: [2], Key: [3], Value: [4]" + IDS_TEMP_WRITEREGISTRYVALUES "Key: [1], Name: [2], Value: [3]" +} + LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL /* @makedep: msiserver.rgs */ diff --git a/dlls/msi/package.c b/dlls/msi/package.c index de1cdf2e02e..7c537d4b5a6 100644 --- a/dlls/msi/package.c +++ b/dlls/msi/package.c @@ -46,6 +46,7 @@ #include "msipriv.h" #include "msiserver.h" +#include "resource.h" WINE_DEFAULT_DEBUG_CHANNEL(msi); @@ -1711,6 +1712,7 @@ INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIREC MSIRECORD *uirow; LPWSTR deformated, message = {0}; DWORD len, log_type = 0; + UINT res; INT rc = 0; char *msg; @@ -1747,44 +1749,52 @@ INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIREC if ((eMessageType & 0xff000000) == INSTALLMESSAGE_ACTIONSTART) { - static const WCHAR template_s[]= - {'A','c','t','i','o','n',' ','%','s',':',' ','%','s','.',' ',0}; - static const WCHAR format[] = + WCHAR template_s[1024]; + static const WCHAR time_format[] = {'H','H','\'',':','\'','m','m','\'',':','\'','s','s',0}; - WCHAR timet[0x100]; - LPCWSTR action_text, action; - LPWSTR deformatted = NULL; + WCHAR timet[100], template[1024]; - 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); + LoadStringW(msi_hInstance, IDS_ACTIONSTART, template_s, 1024); + GetTimeFormatW(LOCALE_USER_DEFAULT, 0, NULL, time_format, timet, 100); + sprintfW(template, template_s, timet); + MSI_RecordSetStringW(record, 0, template); } - else + else if ((eMessageType & 0xff000000) == INSTALLMESSAGE_INFO && + MSI_RecordGetInteger(record, 1) != MSI_NULL_INTEGER) { - UINT res = MSI_FormatRecordW(package, record, message, &len); + WCHAR template_s[1024]; + WCHAR *template_rec, *template; + DWORD length; + + LoadStringW(msi_hInstance, IDS_INFO, template_s, 1024); + + res = MSI_RecordGetStringW(record, 0, NULL, &length); 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); + template_rec = msi_alloc(len * sizeof(WCHAR)); + if (!template_rec) return ERROR_OUTOFMEMORY; + MSI_RecordGetStringW(record, 0, template_rec, &length); + + template = msi_alloc((len + strlenW(template_s)) * sizeof(WCHAR)); + if (!template) return ERROR_OUTOFMEMORY; + + strcpyW(template, template_s); + strcatW(template, template_rec); + MSI_RecordSetStringW(record, 0, template); + + msi_free(template_rec); + msi_free(template); } + 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); + /* convert it to ASCII */ len = WideCharToMultiByte( CP_ACP, 0, message, -1, NULL, 0, NULL, NULL ); msg = msi_alloc( len ); @@ -1858,6 +1868,11 @@ INT MSI_ProcessMessage( MSIPACKAGE *package, INSTALLMESSAGE eMessageType, MSIREC break; } + if (package && (package->ui_level & INSTALLUILEVEL_MASK) != INSTALLUILEVEL_NONE) + { + FIXME("Internal UI not yet handled (UILevel == %x)\n", package->ui_level); + } + return rc; } diff --git a/dlls/msi/resource.h b/dlls/msi/resource.h new file mode 100644 index 00000000000..4d349e685ef --- /dev/null +++ b/dlls/msi/resource.h @@ -0,0 +1,140 @@ +/* + * Copyright 2017 Zebediah Figura + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define IDS_ACTIONSTART 1000 +#define IDS_INFO 1001 + +#define IDS_INFO_ACTIONSTART 1050 +#define IDS_INFO_ACTIONENDED 1051 + +#define IDS_DESC_ALLOCATEREGISTRYSPACE 1100 +#define IDS_DESC_APPSEARCH 1101 +#define IDS_DESC_BINDIMAGE 1102 +#define IDS_DESC_CCPSEARCH 1103 +#define IDS_DESC_COSTFINALIZE 1104 +#define IDS_DESC_COSTINITIALIZE 1105 +#define IDS_DESC_CREATEFOLDERS 1106 +#define IDS_DESC_CREATESHORTCUTS 1107 +#define IDS_DESC_DELETESERVICES 1108 +#define IDS_DESC_DUPLICATEFILES 1109 +#define IDS_DESC_FILECOST 1110 +#define IDS_DESC_FINDRELATEDPRODUCTS 1111 +#define IDS_DESC_INSTALLADMINPACKAGE 1112 +#define IDS_DESC_INSTALLFILES 1113 +#define IDS_DESC_INSTALLODBC 1114 +#define IDS_DESC_INSTALLSERVICES 1115 +#define IDS_DESC_INSTALLSFPCATALOGFILE 1116 +#define IDS_DESC_INSTALLVALIDATE 1117 +#define IDS_DESC_LAUNCHCONDITIONS 1118 +#define IDS_DESC_MIGRATEFEATURESTATES 1119 +#define IDS_DESC_MOVEFILES 1120 +#define IDS_DESC_MSIPUBLISHASSEMBLIES 1121 +#define IDS_DESC_MSIUNPUBLISHASSEMBLIES 1122 +#define IDS_DESC_PATCHFILES 1123 +#define IDS_DESC_PROCESSCOMPONENTS 1124 +#define IDS_DESC_PUBLISHCOMPONENTS 1125 +#define IDS_DESC_PUBLISHFEATURES 1126 +#define IDS_DESC_PUBLISHPRODUCT 1127 +#define IDS_DESC_REGISTERCLASSINFO 1128 +#define IDS_DESC_REGISTERCOMPLUS 1129 +#define IDS_DESC_REGISTEREXTENSIONINFO 1130 +#define IDS_DESC_REGISTERFONTS 1131 +#define IDS_DESC_REGISTERMIMEINFO 1132 +#define IDS_DESC_REGISTERPRODUCT 1133 +#define IDS_DESC_REGISTERPROGIDINFO 1134 +#define IDS_DESC_REGISTERTYPELIBRARIES 1135 +#define IDS_DESC_REGISTERUSER 1136 +#define IDS_DESC_REMOVEDUPLICATEFILES 1137 +#define IDS_DESC_REMOVEENVIRONMENTSTRINGS 1138 +#define IDS_DESC_REMOVEEXISTINGPRODUCTS 1139 +#define IDS_DESC_REMOVEFILES 1140 +#define IDS_DESC_REMOVEFOLDERS 1141 +#define IDS_DESC_REMOVEINIVALUES 1142 +#define IDS_DESC_REMOVEODBC 1143 +#define IDS_DESC_REMOVEREGISTRYVALUES 1144 +#define IDS_DESC_REMOVESHORTCUTS 1145 +#define IDS_DESC_RMCCPSEARCH 1146 +#define IDS_DESC_SELFREGMODULES 1147 +#define IDS_DESC_SELFUNREGMODULES 1148 +#define IDS_DESC_SETODBCFOLDERS 1149 +#define IDS_DESC_STARTSERVICES 1150 +#define IDS_DESC_STOPSERVICES 1151 +#define IDS_DESC_UNPUBLISHCOMPONENTS 1152 +#define IDS_DESC_UNPUBLISHFEATURES 1153 +#define IDS_DESC_UNPUBLISHPRODUCT 1154 +#define IDS_DESC_UNREGISTERCLASSINFO 1155 +#define IDS_DESC_UNREGISTERCOMPLUS 1156 +#define IDS_DESC_UNREGISTEREXTENSIONINFO 1157 +#define IDS_DESC_UNREGISTERFONTS 1158 +#define IDS_DESC_UNREGISTERMIMEINFO 1159 +#define IDS_DESC_UNREGISTERPROGIDINFO 1160 +#define IDS_DESC_UNREGISTERTYPELIBRARIES 1161 +#define IDS_DESC_WRITEENVIRONMENTSTRINGS 1162 +#define IDS_DESC_WRITEINIVALUES 1163 +#define IDS_DESC_WRITEREGISTRYVALUES 1164 + +#define IDS_TEMP_ALLOCATEREGISTRYSPACE 1200 +#define IDS_TEMP_APPSEARCH 1201 +#define IDS_TEMP_BINDIMAGE 1202 +#define IDS_TEMP_CREATEFOLDERS 1203 +#define IDS_TEMP_CREATESHORTCUTS 1204 +#define IDS_TEMP_DELETESERVICES 1205 +#define IDS_TEMP_DUPLICATEFILES 1206 +#define IDS_TEMP_FINDRELATEDPRODUCTS 1207 +#define IDS_TEMP_INSTALLADMINPACKAGE 1208 +#define IDS_TEMP_INSTALLFILES 1209 +#define IDS_TEMP_INSTALLSERVICES 1210 +#define IDS_TEMP_INSTALLSFPCATALOGFILE 1211 +#define IDS_TEMP_MIGRATEFEATURESTATES 1212 +#define IDS_TEMP_MOVEFILES 1213 +#define IDS_TEMP_MSIPUBLISHASSEMBLIES 1214 +#define IDS_TEMP_MSIUNPUBLISHASSEMBLIES 1215 +#define IDS_TEMP_PATCHFILES 1216 +#define IDS_TEMP_PUBLISHCOMPONENTS 1217 +#define IDS_TEMP_PUBLISHFEATURES 1218 +#define IDS_TEMP_REGISTERCLASSINFO 1219 +#define IDS_TEMP_REGISTERCOMPLUS 1220 +#define IDS_TEMP_REGISTEREXTENSIONINFO 1221 +#define IDS_TEMP_REGISTERFONTS 1222 +#define IDS_TEMP_REGISTERMIMEINFO 1223 +#define IDS_TEMP_REGISTERPROGIDINFO 1224 +#define IDS_TEMP_REGISTERTYPELIBRARIES 1225 +#define IDS_TEMP_REMOVEDUPLICATEFILES 1226 +#define IDS_TEMP_REMOVEENVIRONMENTSTRINGS 1227 +#define IDS_TEMP_REMOVEEXISTINGPRODUCTS 1228 +#define IDS_TEMP_REMOVEFILES 1229 +#define IDS_TEMP_REMOVEFOLDERS 1230 +#define IDS_TEMP_REMOVEINIVALUES 1231 +#define IDS_TEMP_REMOVEREGISTRYVALUES 1232 +#define IDS_TEMP_REMOVESHORTCUTS 1233 +#define IDS_TEMP_SELFREGMODULES 1234 +#define IDS_TEMP_SELFUNREGMODULES 1235 +#define IDS_TEMP_STARTSERVICES 1236 +#define IDS_TEMP_STOPSERVICES 1237 +#define IDS_TEMP_UNPUBLISHCOMPONENTS 1238 +#define IDS_TEMP_UNPUBLISHFEATURES 1239 +#define IDS_TEMP_UNREGISTERCLASSINFO 1240 +#define IDS_TEMP_UNREGISTERCOMPLUS 1241 +#define IDS_TEMP_UNREGISTEREXTENSIONINFO 1242 +#define IDS_TEMP_UNREGISTERFONTS 1243 +#define IDS_TEMP_UNREGISTERMIMEINFO 1244 +#define IDS_TEMP_UNREGISTERPROGIDINFO 1245 +#define IDS_TEMP_UNREGISTERTYPELIBRARIES 1246 +#define IDS_TEMP_WRITEENVIRONMENTSTRINGS 1247 +#define IDS_TEMP_WRITEINIVALUES 1248 +#define IDS_TEMP_WRITEREGISTRYVALUES 1249 diff --git a/dlls/msi/tests/format.c b/dlls/msi/tests/format.c index da586b2622a..b035cfa08bf 100644 --- a/dlls/msi/tests/format.c +++ b/dlls/msi/tests/format.c @@ -2775,6 +2775,7 @@ static void test_processmessage(void) ok( r == ERROR_SUCCESS, "set string failed\n"); r = MsiProcessMessage(package, INSTALLMESSAGE_ACTIONSTART, hrec); + todo_wine ok( r == IDOK, "expected IDOK, got %i\n", r); r = MsiProcessMessage(package, INSTALLMESSAGE_PROGRESS, hrec); diff --git a/dlls/msi/tests/package.c b/dlls/msi/tests/package.c index 119641242b2..9934c00a29e 100644 --- a/dlls/msi/tests/package.c +++ b/dlls/msi/tests/package.c @@ -9404,7 +9404,7 @@ static void test_externalui_message(void) /* Test a standard action */ r = MsiDoActionA(hpkg, "custom"); ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r); - ok_sequence(doaction_custom_sequence, "MsiDoAction(\"custom\")", TRUE); + ok_sequence(doaction_custom_sequence, "MsiDoAction(\"custom\")", FALSE); /* close the package */ MsiCloseHandle(hpkg);