James Hawkins : msi: Reference count the custom action data to avoid freeing the data by another thread .

Alexandre Julliard julliard at wine.codeweavers.com
Wed Jun 27 09:11:36 CDT 2007


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

Author: James Hawkins <truiken at gmail.com>
Date:   Mon Jun 25 15:56:21 2007 -0700

msi: Reference count the custom action data to avoid freeing the data by another thread.

Based on a patch by Rob Shearman.

---

 dlls/msi/custom.c |   55 +++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 39 insertions(+), 16 deletions(-)

diff --git a/dlls/msi/custom.c b/dlls/msi/custom.c
index 2ea73f9..cd38af6 100644
--- a/dlls/msi/custom.c
+++ b/dlls/msi/custom.c
@@ -493,6 +493,7 @@ static UINT wait_process_handle(MSIPACKAGE* package, UINT type,
 
 typedef struct _msi_custom_action_info {
     struct list entry;
+    LONG refs;
     MSIPACKAGE *package;
     LPWSTR source;
     LPWSTR target;
@@ -502,20 +503,31 @@ typedef struct _msi_custom_action_info {
     GUID guid;
 } msi_custom_action_info;
 
-static void free_custom_action_data( msi_custom_action_info *info )
+static void release_custom_action_data( msi_custom_action_info *info )
 {
     EnterCriticalSection( &msi_custom_action_cs );
-    list_remove( &info->entry );
+
+    if (!--info->refs)
+    {
+        list_remove( &info->entry );
+        if (info->handle)
+            CloseHandle( info->handle );
+        msi_free( info->action );
+        msi_free( info->source );
+        msi_free( info->target );
+        msiobj_release( &info->package->hdr );
+        msi_free( info );
+    }
+
     LeaveCriticalSection( &msi_custom_action_cs );
-    if (info->handle)
-        CloseHandle( info->handle );
-    msi_free( info->action );
-    msi_free( info->source );
-    msi_free( info->target );
-    msiobj_release( &info->package->hdr );
-    msi_free( info );
 }
 
+/* must be called inside msi_custom_action_cs if info is in the pending custom actions list */
+static void addref_custom_action_data( msi_custom_action_info *info )
+{
+    info->refs++;
+ }
+
 static UINT wait_thread_handle( msi_custom_action_info *info )
 {
     UINT rc = ERROR_SUCCESS;
@@ -529,7 +541,7 @@ static UINT wait_thread_handle( msi_custom_action_info *info )
         if (!(info->type & msidbCustomActionTypeContinue))
             rc = custom_get_thread_return( info->package, info->handle );
 
-        free_custom_action_data( info );
+        release_custom_action_data( info );
     }
     else
     {
@@ -550,6 +562,7 @@ static msi_custom_action_info *find_action_by_guid( const GUID *guid )
     {
         if (IsEqualGUID( &info->guid, guid ))
         {
+            addref_custom_action_data( info );
             found = TRUE;
             break;
         }
@@ -657,7 +670,7 @@ static DWORD WINAPI ACTION_CallDllFunction( const GUID *guid )
 
     if (info->type & msidbCustomActionTypeAsync &&
         info->type & msidbCustomActionTypeContinue)
-        free_custom_action_data( info );
+        release_custom_action_data( info );
 
     return r;
 }
@@ -694,6 +707,8 @@ static DWORD WINAPI ACTION_CAInstallPackage(const GUID *guid)
     r = MsiInstallProductW(info->source, info->target);
     MsiSetInternalUI(old_level, NULL);
 
+    release_custom_action_data(info);
+
     return r;
 }
 
@@ -722,6 +737,7 @@ static msi_custom_action_info *do_msidbCustomActionTypeDll(
         return NULL;
 
     msiobj_addref( &package->hdr );
+    info->refs = 2; /* 1 for our caller and 1 for thread we created */
     info->package = package;
     info->type = type;
     info->target = strdupW( target );
@@ -736,7 +752,9 @@ static msi_custom_action_info *do_msidbCustomActionTypeDll(
     info->handle = CreateThread( NULL, 0, DllThread, &info->guid, 0, NULL );
     if (!info->handle)
     {
-        free_custom_action_data( info );
+        /* release both references */
+        release_custom_action_data( info );
+        release_custom_action_data( info );
         return NULL;
     }
 
@@ -753,6 +771,7 @@ static msi_custom_action_info *do_msidbCAConcurrentInstall(
         return NULL;
 
     msiobj_addref( &package->hdr );
+    info->refs = 2; /* 1 for our caller and 1 for thread we created */
     info->package = package;
     info->type = type;
     info->target = strdupW( target );
@@ -767,7 +786,9 @@ static msi_custom_action_info *do_msidbCAConcurrentInstall(
     info->handle = CreateThread( NULL, 0, ConcurrentInstallThread, &info->guid, 0, NULL );
     if (!info->handle)
     {
-        free_custom_action_data( info );
+        /* release both references */
+        release_custom_action_data( info );
+        release_custom_action_data( info );
         return NULL;
     }
 
@@ -1103,7 +1124,7 @@ static DWORD WINAPI ACTION_CallScript( const GUID *guid )
 
     if (info->type & msidbCustomActionTypeAsync &&
         info->type & msidbCustomActionTypeContinue)
-        free_custom_action_data( info );
+        release_custom_action_data( info );
 
     return S_OK;
 }
@@ -1133,6 +1154,7 @@ static msi_custom_action_info *do_msidbCustomActionTypeScript(
         return NULL;
 
     msiobj_addref( &package->hdr );
+    info->refs = 2; /* 1 for our caller and 1 for thread we created */
     info->package = package;
     info->type = type;
     info->target = strdupW( function );
@@ -1147,7 +1169,9 @@ static msi_custom_action_info *do_msidbCustomActionTypeScript(
     info->handle = CreateThread( NULL, 0, ScriptThread, &info->guid, 0, NULL );
     if (!info->handle)
     {
-        free_custom_action_data( info );
+        /* release both references */
+        release_custom_action_data( info );
+        release_custom_action_data( info );
         return NULL;
     }
 
@@ -1329,7 +1353,6 @@ void ACTION_FinishCustomActions(const MSIPACKAGE* package)
         {
             if (DuplicateHandle(GetCurrentProcess(), info->handle, GetCurrentProcess(), &wait_handles[handle_count], SYNCHRONIZE, FALSE, 0))
                 handle_count++;
-            free_custom_action_data( info );
         }
     }
 




More information about the wine-cvs mailing list