Commit c9802931 authored by Aric Stewart's avatar Aric Stewart Committed by Alexandre Julliard

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.
parent 8ee142a1
......@@ -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);
......
......@@ -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, ... );
......
......@@ -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)
{
......
......@@ -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};
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment