From c9802931c191b1070bb058ae6d5519ea138f398a Mon Sep 17 00:00:00 2001 From: Aric Stewart Date: Thu, 30 Jun 2005 20:45:43 +0000 Subject: [PATCH] Keep track of what sequence we are in and register unique actions. This allows us to make sure actions and custom actions flagged to run only once, actually run only once. Also clean up some of the numeric constants in custom.c using the defined values from msidefs.h. --- dlls/msi/action.c | 7 ++++++ dlls/msi/action.h | 10 ++++++++- dlls/msi/custom.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++------ dlls/msi/helpers.c | 44 ++++++++++++++++++++++++++++++++++++++ dlls/msi/upgrade.c | 10 +++++---- 5 files changed, 123 insertions(+), 11 deletions(-) diff --git a/dlls/msi/action.c b/dlls/msi/action.c index 1dafcef1170..3c4d1243458 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -447,6 +447,8 @@ UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath, package->script = HeapAlloc(GetProcessHeap(),0,sizeof(MSISCRIPT)); memset(package->script,0,sizeof(MSISCRIPT)); + package->script->InWhatSequence = SEQUENCE_INSTALL; + package->msiFilePath= strdupW(msiFilePath); if (szPackagePath) @@ -540,10 +542,14 @@ UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath, { if (atoiW(buffer) >= INSTALLUILEVEL_REDUCED) { + package->script->InWhatSequence |= SEQUENCE_UI; rc = ACTION_ProcessUISequence(package); ui = TRUE; if (rc == ERROR_SUCCESS) + { + package->script->InWhatSequence |= SEQUENCE_EXEC; rc = ACTION_ProcessExecSequence(package,TRUE); + } } else rc = ACTION_ProcessExecSequence(package,FALSE); @@ -3847,6 +3853,7 @@ static UINT ACTION_ExecuteAction(MSIPACKAGE *package) level = load_dynamic_property(package,szUILevel,NULL); MSI_SetPropertyW(package,szUILevel,szTwo); + package->script->InWhatSequence |= SEQUENCE_EXEC; rc = ACTION_ProcessExecSequence(package,FALSE); MSI_SetPropertyW(package,szUILevel,level); HeapFree(GetProcessHeap(),0,level); diff --git a/dlls/msi/action.h b/dlls/msi/action.h index 5fb25c9c303..b8914074b9c 100644 --- a/dlls/msi/action.h +++ b/dlls/msi/action.h @@ -187,13 +187,19 @@ enum SCRIPTS { TOTAL_SCRIPTS = 3 }; +#define SEQUENCE_UI 0x1 +#define SEQUENCE_EXEC 0x2 +#define SEQUENCE_INSTALL 0x10 + typedef struct tagMSISCRIPT { LPWSTR *Actions[TOTAL_SCRIPTS]; UINT ActionCount[TOTAL_SCRIPTS]; BOOL ExecuteSequenceRun; - BOOL FindRelatedProductsRun; BOOL CurrentlyScripting; + UINT InWhatSequence; + LPWSTR *UniqueActions; + UINT UniqueActionsCount; }MSISCRIPT; @@ -234,6 +240,8 @@ void reduce_to_longfilename(WCHAR*); void reduce_to_shortfilename(WCHAR*); LPWSTR create_component_advertise_string(MSIPACKAGE*, MSICOMPONENT*, LPCWSTR); void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature); +UINT register_unique_action(MSIPACKAGE *, LPCWSTR); +BOOL check_unique_action(MSIPACKAGE *, LPCWSTR); WCHAR* generate_error_string(MSIPACKAGE *, UINT, DWORD, ... ); diff --git a/dlls/msi/custom.c b/dlls/msi/custom.c index 08b0aed1ab3..bccd6bb76d7 100644 --- a/dlls/msi/custom.c +++ b/dlls/msi/custom.c @@ -36,6 +36,7 @@ http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/summa #include "wine/debug.h" #include "fdi.h" #include "msi.h" +#include "msidefs.h" #include "msiquery.h" #include "msvcrt/fcntl.h" #include "objbase.h" @@ -74,6 +75,45 @@ static UINT HANDLE_CustomType50(MSIPACKAGE *package, LPCWSTR source, static UINT HANDLE_CustomType34(MSIPACKAGE *package, LPCWSTR source, LPCWSTR target, const INT type, LPCWSTR action); + +static BOOL check_execution_scheduling_options(MSIPACKAGE *package, LPCWSTR action, UINT options) +{ + if (!package->script) + return TRUE; + + if ((options & msidbCustomActionTypeClientRepeat) == + msidbCustomActionTypeClientRepeat) + { + if (!(package->script->InWhatSequence & SEQUENCE_UI && + package->script->InWhatSequence & SEQUENCE_EXEC)) + { + TRACE("Skipping action due to dbCustomActionTypeClientRepeat option.\n"); + return FALSE; + } + } + else if (options & msidbCustomActionTypeFirstSequence) + { + if (package->script->InWhatSequence & SEQUENCE_UI && + package->script->InWhatSequence & SEQUENCE_EXEC ) + { + TRACE("Skipping action due to msidbCustomActionTypeFirstSequence option.\n"); + return FALSE; + } + } + else if (options & msidbCustomActionTypeOncePerProcess) + { + if (check_unique_action(package,action)) + { + TRACE("Skipping action due to msidbCustomActionTypeOncePerProcess option.\n"); + return FALSE; + } + else + register_unique_action(package,action); + } + + return TRUE; +} + UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute) { UINT rc = ERROR_SUCCESS; @@ -101,9 +141,15 @@ UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute) debugstr_w(source), debugstr_w(target)); /* handle some of the deferred actions */ - if (type & 0x400) + if (type & msidbCustomActionTypeTSAware) + FIXME("msidbCustomActionTypeTSAware not handled\n"); + + if (type & msidbCustomActionTypeInScript) { - if (type & 0x100) + if (type & msidbCustomActionTypeNoImpersonate) + FIXME("msidbCustomActionTypeNoImpersonate not handled\n"); + + if (type & msidbCustomActionTypeRollback) { FIXME("Rollback only action... rollbacks not supported yet\n"); schedule_action(package, ROLLBACK_SCRIPT, action); @@ -114,7 +160,7 @@ UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute) } if (!execute) { - if (type & 0x200) + if (type & msidbCustomActionTypeCommit) { TRACE("Deferring Commit Action!\n"); schedule_action(package, COMMIT_SCRIPT, action); @@ -136,11 +182,16 @@ UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute) static const WCHAR szActionData[] = { 'C','u','s','t','o','m','A','c','t','i','o','n','D','a','t','a',0}; + static const WCHAR szBlank[] = {' ',0}; LPWSTR actiondata = load_dynamic_property(package,action,NULL); if (actiondata) MSI_SetPropertyW(package,szActionData,actiondata); + else + MSI_SetPropertyW(package,szActionData,szBlank); } } + else if (!check_execution_scheduling_options(package,action,type)) + return ERROR_SUCCESS; switch (type & CUSTOM_ACTION_TYPE_MASK) { @@ -304,7 +355,7 @@ static UINT process_handle(MSIPACKAGE* package, UINT type, { UINT rc = ERROR_SUCCESS; - if (!(type & 0x80)) + if (!(type & msidbCustomActionTypeAsync)) { /* synchronous */ TRACE("Synchronous Execution of action %s\n",debugstr_w(Name)); @@ -313,7 +364,7 @@ static UINT process_handle(MSIPACKAGE* package, UINT type, else msi_dialog_check_messages(ThreadHandle); - if (!(type & 0x40)) + if (!(type & msidbCustomActionTypeContinue)) { if (ProcessHandle) rc = process_action_return_value(2,ProcessHandle); @@ -331,7 +382,7 @@ static UINT process_handle(MSIPACKAGE* package, UINT type, { TRACE("Asynchronous Execution of action %s\n",debugstr_w(Name)); /* asynchronous */ - if (type & 0x40) + if (type & msidbCustomActionTypeContinue) { if (ProcessHandle) { diff --git a/dlls/msi/helpers.c b/dlls/msi/helpers.c index 7cf7c536201..a234a4c1881 100644 --- a/dlls/msi/helpers.c +++ b/dlls/msi/helpers.c @@ -576,6 +576,11 @@ void ACTION_free_package_structures( MSIPACKAGE* package) HeapFree(GetProcessHeap(),0,package->script->Actions[i]); } + + for (i = 0; i < package->script->UniqueActionsCount; i++) + HeapFree(GetProcessHeap(),0,package->script->UniqueActions[i]); + + HeapFree(GetProcessHeap(),0,package->script->UniqueActions); HeapFree(GetProcessHeap(),0,package->script); } @@ -913,6 +918,45 @@ void ACTION_UpdateComponentStates(MSIPACKAGE *package, LPCWSTR szFeature) } } +UINT register_unique_action(MSIPACKAGE *package, LPCWSTR action) +{ + UINT count; + LPWSTR *newbuf = NULL; + + if (!package || !package->script) + return FALSE; + + TRACE("Registering Action %s as having fun\n",debugstr_w(action)); + + count = package->script->UniqueActionsCount; + package->script->UniqueActionsCount++; + if (count != 0) + newbuf = HeapReAlloc(GetProcessHeap(),0, + package->script->UniqueActions, + package->script->UniqueActionsCount* sizeof(LPWSTR)); + else + newbuf = HeapAlloc(GetProcessHeap(),0, sizeof(LPWSTR)); + + newbuf[count] = strdupW(action); + package->script->UniqueActions = newbuf; + + return ERROR_SUCCESS; +} + +BOOL check_unique_action(MSIPACKAGE *package, LPCWSTR action) +{ + INT i; + + if (!package || !package->script) + return FALSE; + + for (i = 0; i < package->script->UniqueActionsCount; i++) + if (!strcmpW(package->script->UniqueActions[i],action)) + return TRUE; + + return FALSE; +} + WCHAR* generate_error_string(MSIPACKAGE *package, UINT error, DWORD count, ... ) { 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}; diff --git a/dlls/msi/upgrade.c b/dlls/msi/upgrade.c index 7a066ca621a..a0a762bc7c1 100644 --- a/dlls/msi/upgrade.c +++ b/dlls/msi/upgrade.c @@ -211,12 +211,14 @@ UINT ACTION_FindRelatedProducts(MSIPACKAGE *package) UINT rc = ERROR_SUCCESS; MSIQUERY *view; - if (package->script && package->script->FindRelatedProductsRun) + if (check_unique_action(package,szFindRelatedProducts)) + { + TRACE("Skipping FindRelatedProducts action: already done on client side\n"); return ERROR_SUCCESS; + } + else + register_unique_action(package,szFindRelatedProducts); - if (package->script) - package->script->FindRelatedProductsRun = TRUE; - rc = MSI_DatabaseOpenViewW(package->db, Query, &view); if (rc != ERROR_SUCCESS) return ERROR_SUCCESS; -- 2.11.4.GIT