Hans Leidekker : msi: Only remove a component if the number of clients drops to zero.

Alexandre Julliard julliard at winehq.org
Tue Sep 11 16:59:07 CDT 2012


Module: wine
Branch: master
Commit: 1ee3be6e8092af933d5a4e09fc3503fc1bea4001
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=1ee3be6e8092af933d5a4e09fc3503fc1bea4001

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Tue Sep 11 16:20:59 2012 +0200

msi: Only remove a component if the number of clients drops to zero.

---

 dlls/msi/action.c  |   47 +++++++++++++++++++++++++++++++++++++++++------
 dlls/msi/msipriv.h |    1 +
 2 files changed, 42 insertions(+), 6 deletions(-)

diff --git a/dlls/msi/action.c b/dlls/msi/action.c
index f874528..845a0fd 100644
--- a/dlls/msi/action.c
+++ b/dlls/msi/action.c
@@ -809,6 +809,11 @@ INSTALLSTATE msi_get_component_action( MSIPACKAGE *package, MSICOMPONENT *comp )
         return INSTALLSTATE_UNKNOWN;
     }
     if (package->need_rollback) return comp->Installed;
+    if (comp->num_clients > 0 && comp->ActionRequest == INSTALLSTATE_ABSENT)
+    {
+        TRACE("%s has %u clients left\n", debugstr_w(comp->Component), comp->num_clients);
+        return comp->Installed;
+    }
     return comp->ActionRequest;
 }
 
@@ -1620,6 +1625,27 @@ static UINT ACTION_FileCost(MSIPACKAGE *package)
     return ERROR_SUCCESS;
 }
 
+static void get_client_counts( MSIPACKAGE *package )
+{
+    MSICOMPONENT *comp;
+    HKEY hkey;
+
+    LIST_FOR_EACH_ENTRY( comp, &package->components, MSICOMPONENT, entry )
+    {
+        if (!comp->ComponentId) continue;
+
+        if (MSIREG_OpenUserDataComponentKey( comp->ComponentId, szLocalSid, &hkey, FALSE ) &&
+            MSIREG_OpenUserDataComponentKey( comp->ComponentId, NULL, &hkey, FALSE ))
+        {
+            comp->num_clients = 0;
+            continue;
+        }
+        RegQueryInfoKeyW( hkey, NULL, NULL, NULL, NULL, NULL, NULL, (DWORD *)&comp->num_clients,
+                          NULL, NULL, NULL, NULL );
+        RegCloseKey( hkey );
+    }
+}
+
 static void ACTION_GetComponentInstallStates(MSIPACKAGE *package)
 {
     MSICOMPONENT *comp;
@@ -1983,6 +2009,11 @@ UINT MSI_SetFeatureStates(MSIPACKAGE *package)
 
         TRACE("component %s (installed %d request %d action %d)\n",
               debugstr_w(component->Component), component->Installed, component->ActionRequest, component->Action);
+
+        if (component->Action == INSTALLSTATE_LOCAL || component->Action == INSTALLSTATE_SOURCE)
+            component->num_clients++;
+        else if (component->Action == INSTALLSTATE_ABSENT)
+            component->num_clients--;
     }
 
     return ERROR_SUCCESS;
@@ -2368,6 +2399,7 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
         else
             comp->Enabled = TRUE;
     }
+    get_client_counts( package );
 
     /* read components states from the registry */
     ACTION_GetComponentInstallStates(package);
@@ -3307,9 +3339,9 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
         if (package->need_rollback) action = comp->Installed;
         else action = comp->ActionRequest;
 
-        TRACE("Component %s (%s), Keypath=%s, RefCount=%u Action=%u\n",
+        TRACE("Component %s (%s) Keypath=%s RefCount=%u Clients=%u Action=%u\n",
                             debugstr_w(comp->Component), debugstr_w(squished_cc),
-                            debugstr_w(comp->FullKeypath), comp->RefCount, action);
+                            debugstr_w(comp->FullKeypath), comp->RefCount, comp->num_clients, action);
 
         if (action == INSTALLSTATE_LOCAL || action == INSTALLSTATE_SOURCE)
         {
@@ -3372,10 +3404,13 @@ static UINT ACTION_ProcessComponents(MSIPACKAGE *package)
         }
         else if (action == INSTALLSTATE_ABSENT)
         {
-            if (package->Context == MSIINSTALLCONTEXT_MACHINE)
-                MSIREG_DeleteUserDataComponentKey(comp->ComponentId, szLocalSid);
-            else
-                MSIREG_DeleteUserDataComponentKey(comp->ComponentId, NULL);
+            if (comp->num_clients <= 0)
+            {
+                if (package->Context == MSIINSTALLCONTEXT_MACHINE)
+                    MSIREG_DeleteUserDataComponentKey( comp->ComponentId, szLocalSid );
+                else
+                    MSIREG_DeleteUserDataComponentKey( comp->ComponentId, NULL );
+            }
         }
 
         /* UI stuff */
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index 43ac194..73bccecd 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -481,6 +481,7 @@ typedef struct tagMSICOMPONENT
     LPWSTR FullKeypath;
     LPWSTR AdvertiseString;
     MSIASSEMBLY *assembly;
+    int num_clients;
 
     unsigned int anyAbsent:1;
     unsigned int hasAdvertiseFeature:1;




More information about the wine-cvs mailing list