MSI: various registry related fixes

Aric Stewart aric at codeweavers.com
Tue May 31 12:31:13 CDT 2005


A few changes
write the skipped actions for ExecSequence as well as ExecUISequence
Further refind Class and ProgId registration to include FileType masks and the VersionIndependentProgIds
handled install_on_demand processing, even if it is a constant right now.
Dont use short filenames for InprocServer32
Respect features that report that they cannot be installed ADVERTISED

-------------- next part --------------
Index: dlls/msi/action.c
===================================================================
RCS file: /home/wine/wine/dlls/msi/action.c,v
retrieving revision 1.126
diff -u -r1.126 action.c
--- dlls/msi/action.c	31 May 2005 13:20:09 -0000	1.126
+++ dlls/msi/action.c	31 May 2005 17:07:53 -0000
@@ -1268,6 +1268,15 @@
                 break;
             }
 
+            sz=0x100;
+            rc =  MSI_RecordGetStringW(row,1,buffer,&sz);
+            if (rc != ERROR_SUCCESS)
+            {
+                ERR("Error is %x\n",rc);
+                msiobj_release(&row->hdr);
+                break;
+            }
+
             /* check conditions */
             if (!MSI_RecordIsNull(row,2))
             {
@@ -1282,6 +1291,8 @@
                     {
                         HeapFree(GetProcessHeap(),0,cond);
                         msiobj_release(&row->hdr);
+                        TRACE("Skipping action: %s (condition is false)\n",
+                                    debugstr_w(buffer));
                         continue; 
                     }
                     else
@@ -1289,15 +1300,6 @@
                 }
             }
 
-            sz=0x100;
-            rc =  MSI_RecordGetStringW(row,1,buffer,&sz);
-            if (rc != ERROR_SUCCESS)
-            {
-                ERR("Error is %x\n",rc);
-                msiobj_release(&row->hdr);
-                break;
-            }
-
             rc = ACTION_PerformAction(package,buffer, FALSE);
 
             if (rc == ERROR_FUNCTION_NOT_CALLED)
@@ -4395,8 +4397,13 @@
     sz = strlenW(tl_struct->source)+4;
     sz *= sizeof(WCHAR);
 
-    tl_struct->path = HeapAlloc(GetProcessHeap(),0,sz);
-    sprintfW(tl_struct->path,fmt,tl_struct->source, lpszName);
+    if ((INT)lpszName == 1)
+        tl_struct->path = strdupW(tl_struct->source);
+    else
+    {
+        tl_struct->path = HeapAlloc(GetProcessHeap(),0,sz);
+        sprintfW(tl_struct->path,fmt,tl_struct->source, lpszName);
+    }
 
     TRACE("trying %s\n", debugstr_w(tl_struct->path));
     res = LoadTypeLib(tl_struct->path,&tl_struct->ptLib);
@@ -4706,6 +4713,7 @@
     }
 
     package->progids[index].CurVerIndex = -1;
+    package->progids[index].VersionIndIndex = -1;
 
     /* if we have a parent then we may be that parents CurVer */
     if (package->progids[index].ParentIndex >= 0)
@@ -4717,6 +4725,7 @@
         FIXME("BAD BAD need to determing if we are really the CurVer\n");
 
         package->progids[index].CurVerIndex = pindex;
+        package->progids[pindex].VersionIndIndex = index;
     }
     
     return index;
@@ -5519,7 +5528,10 @@
     static const WCHAR szVIProgID[] = { 'V','e','r','s','i','o','n','I','n','d','e','p','e','n','d','e','n','t','P','r','o','g','I','D',0 };
     static const WCHAR szAppID[] = { 'A','p','p','I','D',0 };
     static const WCHAR szSpace[] = {' ',0};
+    static const WCHAR szInprocServer32[] = {'I','n','p','r','o','c','S','e','r','v','e','r','3','2',0};
+    static const WCHAR szFileType_fmt[] = {'F','i','l','e','T','y','p','e','\\','%','s','\\','%','i',0};
     HKEY hkey,hkey2,hkey3;
+    BOOL install_on_demand = FALSE;
     int i;
 
     if (!package)
@@ -5530,6 +5542,11 @@
     if (rc != ERROR_SUCCESS)
         return ERROR_FUNCTION_FAILED;
 
+    /* install_on_demand should be set if OLE supports install on demand OLE
+     * servers. For now i am defaulting to FALSE because i do not know how to
+     * check, and i am told our builtin OLE does not support it
+     */
+    
     for (i = 0; i < package->loaded_classes; i++)
     {
         INT index,f_index;
@@ -5550,8 +5567,8 @@
          */
         if ((!ACTION_VerifyFeatureForAction(package, f_index,
                                 INSTALLSTATE_LOCAL)) &&
-            (!ACTION_VerifyFeatureForAction(package, f_index,
-                                INSTALLSTATE_ADVERTISED)))
+             !(install_on_demand && ACTION_VerifyFeatureForAction(package,
+                             f_index, INSTALLSTATE_ADVERTISED)))
         {
             TRACE("Skipping class %s reg due to disabled feature %s\n", 
                             debugstr_w(package->classes[i].CLSID), 
@@ -5578,16 +5595,43 @@
         index = get_loaded_file(package,package->components[index].KeyPath);
 
 
-        /* the context server is a short path name */
-        sz = 0;
-        sz = GetShortPathNameW(package->files[index].TargetPath, NULL, 0);
-        if (sz == 0)
+        /* the context server is a short path name 
+         * except for if it is InprocServer32... 
+         */
+        if (strcmpiW(package->classes[i].Context,szInprocServer32)!=0)
         {
-            ERR("Unable to find short path for CLSID COM Server\n");
+            sz = 0;
+            sz = GetShortPathNameW(package->files[index].TargetPath, NULL, 0);
+            if (sz == 0)
+            {
+                ERR("Unable to find short path for CLSID COM Server\n");
+                argument = NULL;
+            }
+            else
+            {
+                size = sz * sizeof(WCHAR);
+
+                if (package->classes[i].Argument)
+                {
+                    size += strlenW(package->classes[i].Argument) * 
+                            sizeof(WCHAR);
+                    size += sizeof(WCHAR);
+                }
+
+                argument = HeapAlloc(GetProcessHeap(), 0, size + sizeof(WCHAR));
+                GetShortPathNameW(package->files[index].TargetPath, argument, 
+                                sz);
+
+                if (package->classes[i].Argument)
+                {
+                    strcatW(argument,szSpace);
+                    strcatW(argument,package->classes[i].Argument);
+                }
+            }
         }
         else
         {
-             size = sz * sizeof(WCHAR);
+            size = lstrlenW(package->files[index].TargetPath) * sizeof(WCHAR);
 
             if (package->classes[i].Argument)
             {
@@ -5596,14 +5640,17 @@
             }
 
             argument = HeapAlloc(GetProcessHeap(), 0, size + sizeof(WCHAR));
-            GetShortPathNameW(package->files[index].TargetPath, argument, sz);
+            strcpyW(argument, package->files[index].TargetPath);
 
             if (package->classes[i].Argument)
             {
                 strcatW(argument,szSpace);
                 strcatW(argument,package->classes[i].Argument);
             }
+        }
 
+        if (argument)
+        {
             RegSetValueExW(hkey3,NULL,0,REG_SZ, (LPVOID)argument, size);
             HeapFree(GetProcessHeap(),0,argument);
         }
@@ -5627,12 +5674,12 @@
             RegCloseKey(hkey3);
 
             if (package->classes[i].ProgIDIndex >= 0 &&
-                package->progids[package->classes[i].ProgIDIndex].ParentIndex 
-                            >= 0)
+                package->progids[package->classes[i].ProgIDIndex].
+                                VersionIndIndex >= 0)
             {
-                progid = package->progids[package->progids[
-                        package->classes[i].ProgIDIndex].ParentIndex].ProgID;
-
+                progid = strdupW(package->progids[package->progids[
+                        package->classes[i].ProgIDIndex].VersionIndIndex].
+                        ProgID);
                 RegCreateKeyW(hkey2,szVIProgID,&hkey3);
                 RegSetValueExW(hkey3,NULL,0,REG_SZ,(LPVOID)progid,
                             (strlenW(progid)+1) *sizeof(WCHAR));
@@ -5700,6 +5747,37 @@
         
         RegCloseKey(hkey2);
 
+        /* if there is a FileTypeMask, register the FileType */
+        if (package->classes[i].FileTypeMask)
+        {
+            LPWSTR ptr, ptr2;
+            LPWSTR keyname;
+            INT index = 0;
+            ptr = package->classes[i].FileTypeMask;
+            while (ptr && *ptr)
+            {
+                ptr2 = strchrW(ptr,';');
+                if (ptr2)
+                    *ptr2 = 0;
+                keyname = HeapAlloc(GetProcessHeap(),0,(strlenW(szFileType_fmt)+
+                                        strlenW(package->classes[i].CLSID) + 4)
+                                * sizeof(WCHAR));
+                sprintfW(keyname,szFileType_fmt, package->classes[i].CLSID, 
+                        index);
+
+                RegCreateKeyW(HKEY_CLASSES_ROOT,keyname,&hkey2);
+                RegSetValueExW(hkey2,NULL,0,REG_SZ, (LPVOID)ptr,
+                        strlenW(ptr)*sizeof(WCHAR));
+
+                if (ptr2)
+                    ptr = ptr2+1;
+                else
+                    ptr = NULL;
+
+                index ++;
+            }
+        }
+        
         uirow = MSI_CreateRecord(1);
 
         MSI_RecordSetStringW(uirow,1,package->classes[i].CLSID);
@@ -5844,6 +5922,9 @@
         WCHAR clsid[0x1000];
 
         /* check if this progid is to be installed */
+        package->progids[i].InstallMe =  ((package->progids[i].InstallMe) ||
+              (package->progids[i].ClassIndex >= 0 &&
+              package->classes[package->progids[i].ClassIndex].Installed));
 
         if (!package->progids[i].InstallMe)
         {
@@ -6995,12 +7076,18 @@
     HKEY hkey;
     INT i;
     MSIRECORD *uirow;
+    BOOL install_on_demand = TRUE;
 
     if (!package)
         return ERROR_INVALID_HANDLE;
 
     load_classes_and_such(package);
 
+    /* We need to set install_on_demand based on if the shell handles advertised
+     * shortcuts and the like. Because Mike McCormack is working on this i am
+     * going to default to TRUE
+     */
+    
     for (i = 0; i < package->loaded_extensions; i++)
     {
         WCHAR extension[257];
@@ -7018,8 +7105,8 @@
          */
         if ((!ACTION_VerifyFeatureForAction(package, f_index,
                                 INSTALLSTATE_LOCAL)) &&
-            (!ACTION_VerifyFeatureForAction(package, f_index,
-                                INSTALLSTATE_ADVERTISED)))
+             !(install_on_demand && ACTION_VerifyFeatureForAction(package,
+                             f_index, INSTALLSTATE_ADVERTISED)))
         {
             TRACE("Skipping extension  %s reg due to disabled feature %s\n",
                             debugstr_w(package->extensions[i].Extension),
@@ -7033,7 +7120,11 @@
 
         package->extensions[i].Installed = TRUE;
 
-        if (package->extensions[i].ProgIDIndex >= 0)
+        /* this is only registered if the extension has at least 1 verb
+         * according to MSDN
+         */
+        if (package->extensions[i].ProgIDIndex >= 0 &&
+                package->extensions[i].VerbCount > 0)
            mark_progid_for_install(package, package->extensions[i].ProgIDIndex);
 
         if (package->extensions[i].MIMEIndex >= 0)
@@ -7948,6 +8039,11 @@
     index = get_loaded_feature(package,szFeature);
     if (index < 0)
         return ERROR_UNKNOWN_FEATURE;
+
+    if (iState == INSTALLSTATE_ADVERTISED && 
+        package->features[index].Attributes & 
+            msidbFeatureAttributesDisallowAdvertise)
+        return ERROR_FUNCTION_FAILED;
 
     package->features[index].ActionRequest= iState;
     package->features[index].Action= iState;
Index: dlls/msi/action.h
===================================================================
RCS file: /home/wine/wine/dlls/msi/action.h,v
retrieving revision 1.12
diff -u -r1.12 action.h
--- dlls/msi/action.h	30 May 2005 09:56:56 -0000	1.12
+++ dlls/msi/action.h	31 May 2005 17:07:53 -0000
@@ -147,6 +147,7 @@
     /* not in the table, set during installation */
     BOOL InstallMe;
     INT CurVerIndex;
+    INT VersionIndIndex;
 } MSIPROGID;
 
 typedef struct tagMSIVERB


More information about the wine-patches mailing list