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

Based on a patch by Rob Shearman.
This commit is contained in:
James Hawkins 2007-06-25 15:56:21 -07:00 committed by Alexandre Julliard
parent bb8ba38f98
commit 4c3e4ba029
1 changed files with 39 additions and 16 deletions

View File

@ -493,6 +493,7 @@ static UINT wait_process_handle(MSIPACKAGE* package, UINT type,
typedef struct _msi_custom_action_info { typedef struct _msi_custom_action_info {
struct list entry; struct list entry;
LONG refs;
MSIPACKAGE *package; MSIPACKAGE *package;
LPWSTR source; LPWSTR source;
LPWSTR target; LPWSTR target;
@ -502,20 +503,31 @@ typedef struct _msi_custom_action_info {
GUID guid; GUID guid;
} msi_custom_action_info; } 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 ); 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 ); 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 ) static UINT wait_thread_handle( msi_custom_action_info *info )
{ {
UINT rc = ERROR_SUCCESS; UINT rc = ERROR_SUCCESS;
@ -529,7 +541,7 @@ static UINT wait_thread_handle( msi_custom_action_info *info )
if (!(info->type & msidbCustomActionTypeContinue)) if (!(info->type & msidbCustomActionTypeContinue))
rc = custom_get_thread_return( info->package, info->handle ); rc = custom_get_thread_return( info->package, info->handle );
free_custom_action_data( info ); release_custom_action_data( info );
} }
else else
{ {
@ -550,6 +562,7 @@ static msi_custom_action_info *find_action_by_guid( const GUID *guid )
{ {
if (IsEqualGUID( &info->guid, guid )) if (IsEqualGUID( &info->guid, guid ))
{ {
addref_custom_action_data( info );
found = TRUE; found = TRUE;
break; break;
} }
@ -657,7 +670,7 @@ static DWORD WINAPI ACTION_CallDllFunction( const GUID *guid )
if (info->type & msidbCustomActionTypeAsync && if (info->type & msidbCustomActionTypeAsync &&
info->type & msidbCustomActionTypeContinue) info->type & msidbCustomActionTypeContinue)
free_custom_action_data( info ); release_custom_action_data( info );
return r; return r;
} }
@ -694,6 +707,8 @@ static DWORD WINAPI ACTION_CAInstallPackage(const GUID *guid)
r = MsiInstallProductW(info->source, info->target); r = MsiInstallProductW(info->source, info->target);
MsiSetInternalUI(old_level, NULL); MsiSetInternalUI(old_level, NULL);
release_custom_action_data(info);
return r; return r;
} }
@ -722,6 +737,7 @@ static msi_custom_action_info *do_msidbCustomActionTypeDll(
return NULL; return NULL;
msiobj_addref( &package->hdr ); msiobj_addref( &package->hdr );
info->refs = 2; /* 1 for our caller and 1 for thread we created */
info->package = package; info->package = package;
info->type = type; info->type = type;
info->target = strdupW( target ); 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 ); info->handle = CreateThread( NULL, 0, DllThread, &info->guid, 0, NULL );
if (!info->handle) if (!info->handle)
{ {
free_custom_action_data( info ); /* release both references */
release_custom_action_data( info );
release_custom_action_data( info );
return NULL; return NULL;
} }
@ -753,6 +771,7 @@ static msi_custom_action_info *do_msidbCAConcurrentInstall(
return NULL; return NULL;
msiobj_addref( &package->hdr ); msiobj_addref( &package->hdr );
info->refs = 2; /* 1 for our caller and 1 for thread we created */
info->package = package; info->package = package;
info->type = type; info->type = type;
info->target = strdupW( target ); 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 ); info->handle = CreateThread( NULL, 0, ConcurrentInstallThread, &info->guid, 0, NULL );
if (!info->handle) if (!info->handle)
{ {
free_custom_action_data( info ); /* release both references */
release_custom_action_data( info );
release_custom_action_data( info );
return NULL; return NULL;
} }
@ -1103,7 +1124,7 @@ static DWORD WINAPI ACTION_CallScript( const GUID *guid )
if (info->type & msidbCustomActionTypeAsync && if (info->type & msidbCustomActionTypeAsync &&
info->type & msidbCustomActionTypeContinue) info->type & msidbCustomActionTypeContinue)
free_custom_action_data( info ); release_custom_action_data( info );
return S_OK; return S_OK;
} }
@ -1133,6 +1154,7 @@ static msi_custom_action_info *do_msidbCustomActionTypeScript(
return NULL; return NULL;
msiobj_addref( &package->hdr ); msiobj_addref( &package->hdr );
info->refs = 2; /* 1 for our caller and 1 for thread we created */
info->package = package; info->package = package;
info->type = type; info->type = type;
info->target = strdupW( function ); 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 ); info->handle = CreateThread( NULL, 0, ScriptThread, &info->guid, 0, NULL );
if (!info->handle) if (!info->handle)
{ {
free_custom_action_data( info ); /* release both references */
release_custom_action_data( info );
release_custom_action_data( info );
return NULL; 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)) if (DuplicateHandle(GetCurrentProcess(), info->handle, GetCurrentProcess(), &wait_handles[handle_count], SYNCHRONIZE, FALSE, 0))
handle_count++; handle_count++;
free_custom_action_data( info );
} }
} }