msi: action.c restructure. and fixes

Aric Stewart aric at codeweavers.com
Sun Jan 30 18:54:51 CST 2005


the biggest change is to eliminate the giant if.. else if block from 
ACTION_ProcessAction in favor of a table of handlers.

also:
   return code of the install should not depend on the return code of 
the final action, this was causing failures to report if a handler was 
not present.

   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.
-------------- next part --------------
Index: dlls/msi/action.c
===================================================================
RCS file: /home/wine/wine/dlls/msi/action.c,v
retrieving revision 1.76
diff -u -u -r1.76 action.c
--- dlls/msi/action.c	27 Jan 2005 11:12:56 -0000	1.76
+++ dlls/msi/action.c	31 Jan 2005 00:52:00 -0000
@@ -60,8 +60,14 @@
  */
 static UINT ACTION_ProcessExecSequence(MSIPACKAGE *package, BOOL UIran);
 static UINT ACTION_ProcessUISequence(MSIPACKAGE *package);
-
 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_CostInitialize(MSIPACKAGE *package);
@@ -86,10 +92,8 @@
 static UINT ACTION_InstallExecute(MSIPACKAGE *package);
 static UINT ACTION_InstallFinalize(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
@@ -151,6 +155,43 @@
 {'I','n','s','t','a','l','l','F','i','n','a','l','i','z','e',0};
 const static WCHAR szForceReboot[] = 
 {'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
@@ -720,13 +761,13 @@
 
     /* process the ending type action */
     if (rc == ERROR_SUCCESS)
-        rc = ACTION_PerformActionSequence(package,-1);
+        ACTION_PerformActionSequence(package,-1);
     else if (rc == ERROR_INSTALL_USEREXIT) 
-        rc = ACTION_PerformActionSequence(package,-2);
+        ACTION_PerformActionSequence(package,-2);
     else if (rc == ERROR_FUNCTION_FAILED) 
-        rc = ACTION_PerformActionSequence(package,-3);
+        ACTION_PerformActionSequence(package,-3);
     else if (rc == ERROR_INSTALL_SUSPEND) 
-        rc = ACTION_PerformActionSequence(package,-4);
+        ACTION_PerformActionSequence(package,-4);
 
     /* finish up running custom actions */
     ACTION_FinishCustomActions(package);
@@ -1047,76 +1088,39 @@
 UINT ACTION_PerformAction(MSIPACKAGE *package, const WCHAR *action)
 {
     UINT rc = ERROR_SUCCESS; 
+    BOOL handled = FALSE;
+    int i;
 
     TRACE("Performing action (%s)\n",debugstr_w(action));
-    ui_actioninfo(package, action, TRUE, 0);
-    ui_actionstart(package, action);
 
-    /* pre install, setup and configuration block */
-    if (strcmpW(action,szLaunchConditions)==0)
-        rc = ACTION_LaunchConditions(package);
-    else if (strcmpW(action,szCostInitialize)==0)
-        rc = ACTION_CostInitialize(package);
-    else if (strcmpW(action,szFileCost)==0)
-        rc = ACTION_FileCost(package);
-    else if (strcmpW(action,szCostFinalize)==0)
-        rc = ACTION_CostFinalize(package);
-    else if (strcmpW(action,szInstallValidate)==0)
-        rc = ACTION_InstallValidate(package);
-
-    /* install block */
-    else if (strcmpW(action,szProcessComponents)==0)
-        rc = ACTION_ProcessComponents(package);
-    else if (strcmpW(action,szInstallInitialize)==0)
-        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);
+    i = 0;
+    while (StandardActions[i].action != NULL)
+    {
+        if (strcmpW(StandardActions[i].action, action)==0)
+        {
+            ui_actioninfo(package, action, TRUE, 0);
+            ui_actionstart(package, action);
+            rc = StandardActions[i].handler(package);
+            ui_actioninfo(package, action, FALSE, rc);
+            handled =TRUE;
+            break;
+        }
+        i++;
+    }
 
-    /*
-     Called during iTunes but unimplemented and seem important
+    /* Try for Custom Actions */
+    if (!handled)
+    {
+        rc = ACTION_CustomAction(package,action,FALSE);
 
-     ResolveSource  (sets SourceDir)
-     */
-     else if ((rc = ACTION_CustomAction(package,action,FALSE)) != ERROR_SUCCESS)
-     {
-        FIXME("UNHANDLED MSI ACTION %s\n",debugstr_w(action));
-        rc = ERROR_FUNCTION_NOT_CALLED;
-     }
+        if (rc != ERROR_SUCCESS)
+        {
+            FIXME("UNHANDLED MSI ACTION %s\n",debugstr_w(action));
+            rc = ERROR_FUNCTION_NOT_CALLED;
+        }
+    }
 
     package->CurrentInstallState = rc;
-    ui_actioninfo(package, action, FALSE, rc);
     return rc;
 }
 
@@ -2794,10 +2798,18 @@
              INSTALLSTATE_LOCAL)
         {
             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);
             continue;
         }
 
+        package->components[component_index].Action = INSTALLSTATE_LOCAL;
+        package->components[component_index].Installed = INSTALLSTATE_LOCAL;
+
         sz=0x100;
         rc = MSI_RecordGetStringW(row,3,file_key,&sz);
         if (rc != ERROR_SUCCESS)
@@ -3029,9 +3041,16 @@
         {
             TRACE("Skipping write due to disabled component\n");
             msiobj_release(&row->hdr);
+
+            package->components[component_index].Action =
+                package->components[component_index].Installed;
+
             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 */
         
         if(MSI_RecordIsNull(row,5))
@@ -3460,9 +3479,16 @@
         {
             TRACE("Skipping typelib reg due to disabled component\n");
             msiobj_release(&row->hdr);
+
+            package->components[index].Action =
+                package->components[index].Installed;
+
             continue;
         }
 
+        package->components[index].Action = INSTALLSTATE_LOCAL;
+        package->components[index].Installed = INSTALLSTATE_LOCAL;
+
         index = get_loaded_file(package,package->components[index].KeyPath); 
    
         if (index < 0)
@@ -3650,7 +3676,9 @@
     static const WCHAR szCLSID[] = { 'C','L','S','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 szSpace[] = {' ',0};
     HKEY hkey,hkey2,hkey3;
+    LPWSTR argument,deformated;
 
     if (!package)
         return ERROR_INVALID_HANDLE;
@@ -3681,6 +3709,7 @@
         WCHAR desc[0x100];
         DWORD sz;
         INT index;
+        DWORD size;
      
         rc = MSI_ViewFetch(view,&row);
         if (rc != ERROR_SUCCESS)
@@ -3704,9 +3733,16 @@
         {
             TRACE("Skipping class reg due to disabled component\n");
             msiobj_release(&row->hdr);
+
+            package->components[index].Action =
+                package->components[index].Installed;
+
             continue;
         }
 
+        package->components[index].Action = INSTALLSTATE_LOCAL;
+        package->components[index].Installed = INSTALLSTATE_LOCAL;
+
         sz=0x100;
         MSI_RecordGetStringW(row,1,clsid,&sz);
         RegCreateKeyW(hkey,clsid,&hkey2);
@@ -3728,10 +3764,25 @@
         RegCreateKeyW(hkey2,buffer,&hkey3);
 
         index = get_loaded_file(package,package->components[index].KeyPath);
-        RegSetValueExW(hkey3,NULL,0,REG_SZ,
-                       (LPVOID)package->files[index].TargetPath,
-                       (strlenW(package->files[index].TargetPath)+1)
-                        *sizeof(WCHAR));
+
+        argument = load_dynamic_stringW(row,11); 
+        size = deformat_string(package,argument,&deformated);
+        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);
 
@@ -3759,9 +3810,94 @@
             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);
 
@@ -4099,9 +4235,16 @@
         {
             TRACE("Skipping shortcut creation due to disabled component\n");
             msiobj_release(&row->hdr);
+
+            package->components[index].Action =
+                package->components[index].Installed;
+
             continue;
         }
 
+        package->components[index].Action = INSTALLSTATE_LOCAL;
+        package->components[index].Installed = INSTALLSTATE_LOCAL;
+
         ui_actiondata(package,szCreateShortcuts,row);
 
         res = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
@@ -4443,8 +4586,15 @@
         {
             TRACE("Skipping ini file due to disabled component\n");
             msiobj_release(&row->hdr);
+
+            package->components[component_index].Action =
+                package->components[component_index].Installed;
+
             continue;
         }
+
+        package->components[component_index].Action = INSTALLSTATE_LOCAL;
+        package->components[component_index].Installed = INSTALLSTATE_LOCAL;
    
         identifier = load_dynamic_stringW(row,1); 
         filename = load_dynamic_stringW(row,2);
@@ -4957,6 +5107,15 @@
     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 */
 UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
 {
@@ -5408,7 +5567,10 @@
         *piInstalled = package->components[index].Installed;
 
     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;
 }


More information about the wine-patches mailing list