Eliminate the giant if.. else if block from ACTION_ProcessAction in

favor of a table of handlers.
Return code of the install should not depend on the return code of the
final action.
Update component installed states as they are installed so that
conditions based on component states are at least a little more
correct.
Add icon and argument when regestering clsids.
Add a stub for ResolveSource because we do that work just not in
ResolveSource like we should.
When quering a Component state return the correct state.
This commit is contained in:
Aric Stewart 2005-01-31 16:23:12 +00:00 committed by Alexandre Julliard
parent 5ca9d58491
commit 90c57396f4
1 changed files with 240 additions and 78 deletions

View File

@ -60,8 +60,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi);
*/ */
static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran); static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran);
static UINT ACTION_ProcessUISequence(MSIPACKAGE *package); static UINT ACTION_ProcessUISequence(MSIPACKAGE *package);
static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq); static UINT ACTION_PerformActionSequence(MSIPACKAGE *package, UINT seq);
static UINT build_icon_path(MSIPACKAGE *package, LPCWSTR icon_name,
LPWSTR *FilePath);
/*
* action handlers
*/
typedef UINT (*STANDARDACTIONHANDLER)(MSIPACKAGE*);
static UINT ACTION_LaunchConditions(MSIPACKAGE *package); static UINT ACTION_LaunchConditions(MSIPACKAGE *package);
static UINT ACTION_CostInitialize(MSIPACKAGE *package); static UINT ACTION_CostInitialize(MSIPACKAGE *package);
@ -86,10 +92,8 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package);
static UINT ACTION_InstallExecute(MSIPACKAGE *package); static UINT ACTION_InstallExecute(MSIPACKAGE *package);
static UINT ACTION_InstallFinalize(MSIPACKAGE *package); static UINT ACTION_InstallFinalize(MSIPACKAGE *package);
static UINT ACTION_ForceReboot(MSIPACKAGE *package); static UINT ACTION_ForceReboot(MSIPACKAGE *package);
static UINT ACTION_ResolveSource(MSIPACKAGE *package);
static UINT build_icon_path(MSIPACKAGE *package, LPCWSTR icon_name,
LPWSTR *FilePath);
/* /*
* consts and values used * consts and values used
@ -151,6 +155,43 @@ const static WCHAR szInstallFinalize[] =
{'I','n','s','t','a','l','l','F','i','n','a','l','i','z','e',0}; {'I','n','s','t','a','l','l','F','i','n','a','l','i','z','e',0};
const static WCHAR szForceReboot[] = const static WCHAR szForceReboot[] =
{'F','o','r','c','e','R','e','b','o','o','t',0}; {'F','o','r','c','e','R','e','b','o','o','t',0};
const static WCHAR szResolveSource[] =
{'R','e','s','o','l','v','e','S','o','u','r','c','e',0};
struct _actions {
LPCWSTR action;
STANDARDACTIONHANDLER handler;
};
struct _actions StandardActions[] = {
{ szCostFinalize, ACTION_CostFinalize },
{ szCostInitialize, ACTION_CostInitialize },
{ szCreateFolders, ACTION_CreateFolders },
{ szCreateShortcuts, ACTION_CreateShortcuts },
{ szDuplicateFiles, ACTION_DuplicateFiles},
{ szFileCost, ACTION_FileCost },
{ szForceReboot, ACTION_ForceReboot },
{ szInstallExecute, ACTION_InstallExecute },
{ szInstallExecuteAgain, ACTION_InstallExecute },
{ szInstallFiles, ACTION_InstallFiles},
{ szInstallFinalize, ACTION_InstallFinalize },
{ szInstallInitialize, ACTION_InstallInitialize },
{ szInstallValidate, ACTION_InstallValidate },
{ szLaunchConditions, ACTION_LaunchConditions },
{ szProcessComponents, ACTION_ProcessComponents },
{ szPublishFeatures, ACTION_PublishFeatures },
{ szPublishProduct, ACTION_PublishProduct },
{ szRegisterClassInfo, ACTION_RegisterClassInfo },
{ szRegisterProduct, ACTION_RegisterProduct },
{ szRegisterProgIdInfo, ACTION_RegisterProgIdInfo },
{ szRegisterTypeLibraries, ACTION_RegisterTypeLibraries },
{ szResolveSource, ACTION_ResolveSource},
{ szSelfRegModules, ACTION_SelfRegModules },
{ szWriteIniValues, ACTION_WriteIniValues },
{ szWriteRegistryValues, ACTION_WriteRegistryValues},
{ NULL, NULL},
};
/******************************************************** /********************************************************
* helper functions to get around current HACKS and such * helper functions to get around current HACKS and such
@ -720,13 +761,13 @@ UINT ACTION_DoTopLevelINSTALL(MSIPACKAGE *package, LPCWSTR szPackagePath,
/* process the ending type action */ /* process the ending type action */
if (rc == ERROR_SUCCESS) if (rc == ERROR_SUCCESS)
rc = ACTION_PerformActionSequence(package,-1); ACTION_PerformActionSequence(package,-1);
else if (rc == ERROR_INSTALL_USEREXIT) else if (rc == ERROR_INSTALL_USEREXIT)
rc = ACTION_PerformActionSequence(package,-2); ACTION_PerformActionSequence(package,-2);
else if (rc == ERROR_FUNCTION_FAILED) else if (rc == ERROR_FUNCTION_FAILED)
rc = ACTION_PerformActionSequence(package,-3); ACTION_PerformActionSequence(package,-3);
else if (rc == ERROR_INSTALL_SUSPEND) else if (rc == ERROR_INSTALL_SUSPEND)
rc = ACTION_PerformActionSequence(package,-4); ACTION_PerformActionSequence(package,-4);
/* finish up running custom actions */ /* finish up running custom actions */
ACTION_FinishCustomActions(package); ACTION_FinishCustomActions(package);
@ -1047,76 +1088,39 @@ end:
UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action) UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action)
{ {
UINT rc = ERROR_SUCCESS; UINT rc = ERROR_SUCCESS;
BOOL handled = FALSE;
int i;
TRACE("Performing action (%s)\n",debugstr_w(action)); TRACE("Performing action (%s)\n",debugstr_w(action));
ui_actioninfo(package, action, TRUE, 0);
ui_actionstart(package, action);
/* pre install, setup and configuration block */ i = 0;
if (strcmpW(action,szLaunchConditions)==0) while (StandardActions[i].action != NULL)
rc = ACTION_LaunchConditions(package); {
else if (strcmpW(action,szCostInitialize)==0) if (strcmpW(StandardActions[i].action, action)==0)
rc = ACTION_CostInitialize(package); {
else if (strcmpW(action,szFileCost)==0) ui_actioninfo(package, action, TRUE, 0);
rc = ACTION_FileCost(package); ui_actionstart(package, action);
else if (strcmpW(action,szCostFinalize)==0) rc = StandardActions[i].handler(package);
rc = ACTION_CostFinalize(package); ui_actioninfo(package, action, FALSE, rc);
else if (strcmpW(action,szInstallValidate)==0) handled =TRUE;
rc = ACTION_InstallValidate(package); break;
}
i++;
}
/* install block */ /* Try for Custom Actions */
else if (strcmpW(action,szProcessComponents)==0) if (!handled)
rc = ACTION_ProcessComponents(package); {
else if (strcmpW(action,szInstallInitialize)==0) rc = ACTION_CustomAction(package,action,FALSE);
rc = ACTION_InstallInitialize(package);
else if (strcmpW(action,szCreateFolders)==0)
rc = ACTION_CreateFolders(package);
else if (strcmpW(action,szInstallFiles)==0)
rc = ACTION_InstallFiles(package);
else if (strcmpW(action,szDuplicateFiles)==0)
rc = ACTION_DuplicateFiles(package);
else if (strcmpW(action,szWriteRegistryValues)==0)
rc = ACTION_WriteRegistryValues(package);
else if (strcmpW(action,szRegisterTypeLibraries)==0)
rc = ACTION_RegisterTypeLibraries(package);
else if (strcmpW(action,szRegisterClassInfo)==0)
rc = ACTION_RegisterClassInfo(package);
else if (strcmpW(action,szRegisterProgIdInfo)==0)
rc = ACTION_RegisterProgIdInfo(package);
else if (strcmpW(action,szCreateShortcuts)==0)
rc = ACTION_CreateShortcuts(package);
else if (strcmpW(action,szPublishProduct)==0)
rc = ACTION_PublishProduct(package);
else if (strcmpW(action,szWriteIniValues)==0)
rc = ACTION_WriteIniValues(package);
else if (strcmpW(action,szSelfRegModules)==0)
rc = ACTION_SelfRegModules(package);
else if (strcmpW(action,szPublishFeatures)==0)
rc = ACTION_PublishFeatures(package);
else if (strcmpW(action,szRegisterProduct)==0)
rc = ACTION_RegisterProduct(package);
else if (strcmpW(action,szInstallExecute)==0)
rc = ACTION_InstallExecute(package);
else if (strcmpW(action,szInstallExecuteAgain)==0)
rc = ACTION_InstallExecute(package);
else if (strcmpW(action,szInstallFinalize)==0)
rc = ACTION_InstallFinalize(package);
else if (strcmpW(action,szForceReboot)==0)
rc = ACTION_ForceReboot(package);
/* if (rc != ERROR_SUCCESS)
Called during iTunes but unimplemented and seem important {
FIXME("UNHANDLED MSI ACTION %s\n",debugstr_w(action));
ResolveSource (sets SourceDir) rc = ERROR_FUNCTION_NOT_CALLED;
*/ }
else if ((rc = ACTION_CustomAction(package,action,FALSE)) != ERROR_SUCCESS) }
{
FIXME("UNHANDLED MSI ACTION %s\n",debugstr_w(action));
rc = ERROR_FUNCTION_NOT_CALLED;
}
package->CurrentInstallState = rc; package->CurrentInstallState = rc;
ui_actioninfo(package, action, FALSE, rc);
return rc; return rc;
} }
@ -2794,10 +2798,18 @@ static UINT ACTION_DuplicateFiles(MSIPACKAGE *package)
INSTALLSTATE_LOCAL) INSTALLSTATE_LOCAL)
{ {
TRACE("Skipping copy due to disabled component\n"); TRACE("Skipping copy due to disabled component\n");
/* the action taken was the same as the current install state */
package->components[component_index].Action =
package->components[component_index].Installed;
msiobj_release(&row->hdr); msiobj_release(&row->hdr);
continue; continue;
} }
package->components[component_index].Action = INSTALLSTATE_LOCAL;
package->components[component_index].Installed = INSTALLSTATE_LOCAL;
sz=0x100; sz=0x100;
rc = MSI_RecordGetStringW(row,3,file_key,&sz); rc = MSI_RecordGetStringW(row,3,file_key,&sz);
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
@ -3029,9 +3041,16 @@ static UINT ACTION_WriteRegistryValues(MSIPACKAGE *package)
{ {
TRACE("Skipping write due to disabled component\n"); TRACE("Skipping write due to disabled component\n");
msiobj_release(&row->hdr); msiobj_release(&row->hdr);
package->components[component_index].Action =
package->components[component_index].Installed;
goto next; goto next;
} }
package->components[component_index].Action = INSTALLSTATE_LOCAL;
package->components[component_index].Installed = INSTALLSTATE_LOCAL;
/* null values have special meanings during uninstalls and such */ /* null values have special meanings during uninstalls and such */
if(MSI_RecordIsNull(row,5)) if(MSI_RecordIsNull(row,5))
@ -3460,9 +3479,16 @@ static UINT ACTION_RegisterTypeLibraries(MSIPACKAGE *package)
{ {
TRACE("Skipping typelib reg due to disabled component\n"); TRACE("Skipping typelib reg due to disabled component\n");
msiobj_release(&row->hdr); msiobj_release(&row->hdr);
package->components[index].Action =
package->components[index].Installed;
continue; continue;
} }
package->components[index].Action = INSTALLSTATE_LOCAL;
package->components[index].Installed = INSTALLSTATE_LOCAL;
index = get_loaded_file(package,package->components[index].KeyPath); index = get_loaded_file(package,package->components[index].KeyPath);
if (index < 0) if (index < 0)
@ -3650,7 +3676,9 @@ static UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
static const WCHAR szCLSID[] = { 'C','L','S','I','D',0 }; static const WCHAR szCLSID[] = { 'C','L','S','I','D',0 };
static const WCHAR szProgID[] = { 'P','r','o','g','I','D',0 }; static const WCHAR szProgID[] = { 'P','r','o','g','I','D',0 };
static const WCHAR szAppID[] = { 'A','p','p','I','D',0 }; static const WCHAR szAppID[] = { 'A','p','p','I','D',0 };
static const WCHAR szSpace[] = {' ',0};
HKEY hkey,hkey2,hkey3; HKEY hkey,hkey2,hkey3;
LPWSTR argument,deformated;
if (!package) if (!package)
return ERROR_INVALID_HANDLE; return ERROR_INVALID_HANDLE;
@ -3681,6 +3709,7 @@ static UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
WCHAR desc[0x100]; WCHAR desc[0x100];
DWORD sz; DWORD sz;
INT index; INT index;
DWORD size;
rc = MSI_ViewFetch(view,&row); rc = MSI_ViewFetch(view,&row);
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
@ -3704,9 +3733,16 @@ static UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
{ {
TRACE("Skipping class reg due to disabled component\n"); TRACE("Skipping class reg due to disabled component\n");
msiobj_release(&row->hdr); msiobj_release(&row->hdr);
package->components[index].Action =
package->components[index].Installed;
continue; continue;
} }
package->components[index].Action = INSTALLSTATE_LOCAL;
package->components[index].Installed = INSTALLSTATE_LOCAL;
sz=0x100; sz=0x100;
MSI_RecordGetStringW(row,1,clsid,&sz); MSI_RecordGetStringW(row,1,clsid,&sz);
RegCreateKeyW(hkey,clsid,&hkey2); RegCreateKeyW(hkey,clsid,&hkey2);
@ -3728,10 +3764,25 @@ static UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
RegCreateKeyW(hkey2,buffer,&hkey3); RegCreateKeyW(hkey2,buffer,&hkey3);
index = get_loaded_file(package,package->components[index].KeyPath); index = get_loaded_file(package,package->components[index].KeyPath);
RegSetValueExW(hkey3,NULL,0,REG_SZ,
(LPVOID)package->files[index].TargetPath, argument = load_dynamic_stringW(row,11);
(strlenW(package->files[index].TargetPath)+1) size = deformat_string(package,argument,&deformated);
*sizeof(WCHAR)); if (deformated)
size+=sizeof(WCHAR);
HeapFree(GetProcessHeap(),0,argument);
size += (strlenW(package->files[index].TargetPath))*sizeof(WCHAR);
argument = (LPWSTR)HeapAlloc(GetProcessHeap(),0,size+sizeof(WCHAR));
strcpyW(argument,package->files[index].TargetPath);
if (deformated)
{
strcatW(argument,szSpace);
strcatW(argument,deformated);
}
RegSetValueExW(hkey3,NULL,0,REG_SZ, (LPVOID)argument, size);
HeapFree(GetProcessHeap(),0,deformated);
HeapFree(GetProcessHeap(),0,argument);
RegCloseKey(hkey3); RegCloseKey(hkey3);
@ -3759,9 +3810,94 @@ static UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
register_appid(package,buffer,desc); register_appid(package,buffer,desc);
} }
RegCloseKey(hkey2);
FIXME("Process the rest of the fields >7\n"); if (!MSI_RecordIsNull(row,7))
{
FIXME("Process field 7\n");
}
if (!MSI_RecordIsNull(row,8))
{
static const WCHAR szDefaultIcon[] =
{'D','e','f','a','u','l','t','I','c','o','n',0};
LPWSTR FileName = load_dynamic_stringW(row,8);
LPWSTR FilePath;
INT index;
RegCreateKeyW(hkey2,szDefaultIcon,&hkey3);
build_icon_path(package,FileName,&FilePath);
if (!MSI_RecordIsNull(row,9))
{
static const WCHAR index_fmt[] = {',','%','i',0};
WCHAR index_buf[20];
index = MSI_RecordGetInteger(row,9);
sprintfW(index_buf,index_fmt,index);
size = strlenW(FilePath)+strlenW(index_buf)+1;
size *= sizeof(WCHAR);
HeapReAlloc(GetProcessHeap(),0,FilePath,size);
}
RegSetValueExW(hkey3,NULL,0,REG_SZ,(LPVOID)FilePath,
(strlenW(FilePath)+1) * sizeof(WCHAR));
HeapFree(GetProcessHeap(),0,FilePath);
HeapFree(GetProcessHeap(),0,FileName);
RegCloseKey(hkey3);
}
if (!MSI_RecordIsNull(row,10))
{
static const WCHAR szInproc32[] = {
'I','n','p','r','o','c','H','a','n','d','l','e','r','3','2',0};
static const WCHAR szInproc[] = {
'I','n','p','r','o','c','H','a','n','d','l','e','r',0};
INT i = MSI_RecordGetInteger(row,10);
if (i != MSI_NULL_INTEGER && i > 0 && i < 4)
{
static const WCHAR ole2[] = {'o','l','e','2','.','d','l','l',0};
static const WCHAR ole32[] = {
'o','l','e','3','2','.','d','l','l',0};
switch(i)
{
case 1:
size = strlenW(ole2) * sizeof(WCHAR);
RegCreateKeyW(hkey2,szInproc,&hkey3);
RegSetValueExW(hkey3,NULL,0,REG_SZ, (LPVOID)ole2, size);
RegCloseKey(hkey3);
break;
case 2:
size = strlenW(ole32) * sizeof(WCHAR);
RegCreateKeyW(hkey2,szInproc32,&hkey3);
RegSetValueExW(hkey3,NULL,0,REG_SZ, (LPVOID)ole32,size);
RegCloseKey(hkey3);
break;
case 3:
size = strlenW(ole2) * sizeof(WCHAR);
RegCreateKeyW(hkey2,szInproc,&hkey3);
RegSetValueExW(hkey3,NULL,0,REG_SZ, (LPVOID)ole2, size);
RegCloseKey(hkey3);
size = strlenW(ole32) * sizeof(WCHAR);
RegCreateKeyW(hkey2,szInproc32,&hkey3);
RegSetValueExW(hkey3,NULL,0,REG_SZ, (LPVOID)ole32,size);
RegCloseKey(hkey3);
break;
}
}
else
{
RegCreateKeyW(hkey2,szInproc32,&hkey3);
argument = load_dynamic_stringW(row,10);
reduce_to_longfilename(argument);
size = strlenW(argument)*sizeof(WCHAR);
RegSetValueExW(hkey3,NULL,0,REG_SZ, (LPVOID)argument, size);
HeapFree(GetProcessHeap(),0,argument);
RegCloseKey(hkey3);
}
}
RegCloseKey(hkey2);
ui_actiondata(package,szRegisterClassInfo,row); ui_actiondata(package,szRegisterClassInfo,row);
@ -4099,9 +4235,16 @@ static UINT ACTION_CreateShortcuts(MSIPACKAGE *package)
{ {
TRACE("Skipping shortcut creation due to disabled component\n"); TRACE("Skipping shortcut creation due to disabled component\n");
msiobj_release(&row->hdr); msiobj_release(&row->hdr);
package->components[index].Action =
package->components[index].Installed;
continue; continue;
} }
package->components[index].Action = INSTALLSTATE_LOCAL;
package->components[index].Installed = INSTALLSTATE_LOCAL;
ui_actiondata(package,szCreateShortcuts,row); ui_actiondata(package,szCreateShortcuts,row);
res = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, res = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
@ -4443,8 +4586,15 @@ static UINT ACTION_WriteIniValues(MSIPACKAGE *package)
{ {
TRACE("Skipping ini file due to disabled component\n"); TRACE("Skipping ini file due to disabled component\n");
msiobj_release(&row->hdr); msiobj_release(&row->hdr);
package->components[component_index].Action =
package->components[component_index].Installed;
continue; continue;
} }
package->components[component_index].Action = INSTALLSTATE_LOCAL;
package->components[component_index].Installed = INSTALLSTATE_LOCAL;
identifier = load_dynamic_stringW(row,1); identifier = load_dynamic_stringW(row,1);
filename = load_dynamic_stringW(row,2); filename = load_dynamic_stringW(row,2);
@ -4957,6 +5107,15 @@ static UINT ACTION_ForceReboot(MSIPACKAGE *package)
return ERROR_INSTALL_SUSPEND; return ERROR_INSTALL_SUSPEND;
} }
UINT ACTION_ResolveSource(MSIPACKAGE* package)
{
/*
* we are currently doing what should be done here in the top level Install
* however for Adminastrative and uninstalls this step will be needed
*/
return ERROR_SUCCESS;
}
/* Msi functions that seem appropriate here */ /* Msi functions that seem appropriate here */
UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction ) UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
{ {
@ -5408,7 +5567,10 @@ piAction);
*piInstalled = package->components[index].Installed; *piInstalled = package->components[index].Installed;
if (piAction) if (piAction)
*piInstalled = package->components[index].Action; *piAction = package->components[index].Action;
TRACE("states (%i, %i)\n",
(piInstalled)?*piInstalled:-1,(piAction)?*piAction:-1);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }