Commit 63e55499 authored by Mike McCormack's avatar Mike McCormack Committed by Alexandre Julliard

msi: Store dll based custom actions in a separate list.

parent 59270157
...@@ -59,6 +59,7 @@ static UINT HANDLE_CustomType50(MSIPACKAGE *package, LPCWSTR source, ...@@ -59,6 +59,7 @@ static UINT HANDLE_CustomType50(MSIPACKAGE *package, LPCWSTR source,
static UINT HANDLE_CustomType34(MSIPACKAGE *package, LPCWSTR source, static UINT HANDLE_CustomType34(MSIPACKAGE *package, LPCWSTR source,
LPCWSTR target, const INT type, LPCWSTR action); LPCWSTR target, const INT type, LPCWSTR action);
typedef UINT (WINAPI *MsiCustomActionEntryPoint)( MSIHANDLE );
static BOOL check_execution_scheduling_options(MSIPACKAGE *package, LPCWSTR action, UINT options) static BOOL check_execution_scheduling_options(MSIPACKAGE *package, LPCWSTR action, UINT options)
{ {
...@@ -396,125 +397,143 @@ static UINT wait_process_handle(MSIPACKAGE* package, UINT type, ...@@ -396,125 +397,143 @@ static UINT wait_process_handle(MSIPACKAGE* package, UINT type,
return rc; return rc;
} }
static UINT wait_thread_handle(MSIPACKAGE* package, UINT type, typedef struct _msi_custom_action_info {
HANDLE ThreadHandle, LPCWSTR name) struct list entry;
MSIPACKAGE *package;
LPWSTR dllname;
LPWSTR function;
HANDLE handle;
LPWSTR action;
INT type;
} msi_custom_action_info;
static void free_custom_action_data( msi_custom_action_info *info )
{
list_remove( &info->entry );
if (info->handle)
CloseHandle( info->handle );
msi_free( info->action );
msi_free( info->dllname );
msi_free( info->function );
msiobj_release( &info->package->hdr );
msi_free( info );
}
static UINT wait_thread_handle( msi_custom_action_info *info )
{ {
UINT rc = ERROR_SUCCESS; UINT rc = ERROR_SUCCESS;
if (!(type & msidbCustomActionTypeAsync)) if (!(info->type & msidbCustomActionTypeAsync))
{ {
TRACE("waiting for %s\n", debugstr_w(name)); TRACE("waiting for %s\n", debugstr_w( info->action ));
msi_dialog_check_messages(ThreadHandle); msi_dialog_check_messages( info->handle );
if (!(type & msidbCustomActionTypeContinue)) if (!(info->type & msidbCustomActionTypeContinue))
rc = custom_get_thread_return(ThreadHandle); rc = custom_get_thread_return( info->handle );
CloseHandle(ThreadHandle); free_custom_action_data( info );
} }
else else
{ {
TRACE("%s running in background\n", debugstr_w(name)); TRACE("%s running in background\n", debugstr_w( info->action ));
if (!(type & msidbCustomActionTypeContinue)) if (info->type & msidbCustomActionTypeContinue)
file_running_action(package, ThreadHandle, FALSE, name); free_custom_action_data( info );
else
CloseHandle(ThreadHandle);
} }
return rc; return rc;
} }
typedef UINT __stdcall CustomEntry(MSIHANDLE); static DWORD WINAPI ACTION_CallDllFunction( msi_custom_action_info *info )
typedef struct
{
MSIPACKAGE *package;
WCHAR *target;
WCHAR *source;
} thread_struct;
static DWORD WINAPI ACTION_CallDllFunction(thread_struct *stuff)
{ {
MsiCustomActionEntryPoint fn;
MSIHANDLE hPackage;
HANDLE hModule; HANDLE hModule;
LPSTR proc; LPSTR proc;
CustomEntry *fn; UINT r = ERROR_FUNCTION_FAILED;
DWORD rc = ERROR_SUCCESS;
TRACE("calling function (%s, %s)\n", debugstr_w(stuff->source), TRACE("%s %s\n", debugstr_w( info->dllname ), debugstr_w( info->function ) );
debugstr_w(stuff->target));
hModule = LoadLibraryW(stuff->source); hModule = LoadLibraryW( info->dllname );
if (hModule) if (!hModule)
{ {
proc = strdupWtoA( stuff->target ); ERR("failed to load dll %s\n", debugstr_w( info->dllname ) );
fn = (CustomEntry*)GetProcAddress(hModule,proc); return r;
}
proc = strdupWtoA( info->function );
fn = (MsiCustomActionEntryPoint) GetProcAddress( hModule, proc );
msi_free( proc );
if (fn) if (fn)
{ {
MSIHANDLE hPackage; hPackage = alloc_msihandle( &info->package->hdr );
MSIPACKAGE *package = stuff->package;
TRACE("Calling function %s\n", proc);
hPackage = alloc_msihandle( &package->hdr );
if (hPackage) if (hPackage)
{ {
rc = fn( hPackage ); TRACE("calling %s\n", debugstr_w( info->function ) );
r = fn( hPackage );
MsiCloseHandle( hPackage ); MsiCloseHandle( hPackage );
} }
else else
ERR("Handle for object %p not found\n", package ); ERR("failed to create handle for %p\n", info->package );
} }
else else
ERR("failed to resolve functon %s\n", debugstr_a(proc)); ERR("GetProcAddress(%s) failed\n", debugstr_w( info->function ) );
msi_free(proc);
FreeLibrary(hModule); FreeLibrary(hModule);
}
else return r;
ERR("failed to load dll %s\n", debugstr_w(stuff->source));
msiobj_release( &stuff->package->hdr );
msi_free(stuff->source);
msi_free(stuff->target);
msi_free(stuff);
return rc;
} }
static DWORD WINAPI DllThread(LPVOID info) static DWORD WINAPI DllThread( LPVOID arg )
{ {
thread_struct *stuff; msi_custom_action_info *info = arg;
DWORD rc = 0; DWORD rc = 0;
TRACE("MSI Thread (%x) started for custom action\n", GetCurrentThreadId()); TRACE("custom action (%x) started\n", GetCurrentThreadId() );
rc = ACTION_CallDllFunction( info );
stuff = (thread_struct*)info; TRACE("custom action (%x) returned %i\n", GetCurrentThreadId(), rc );
rc = ACTION_CallDllFunction(stuff);
TRACE("MSI Thread (%x) finished (rc %i)\n",GetCurrentThreadId(), rc);
/* close all handles for this thread */
MsiCloseAllHandles(); MsiCloseAllHandles();
return rc; return rc;
} }
static HANDLE do_msidbCustomActionTypeDll(MSIPACKAGE *package, LPCWSTR dll, LPCWSTR target) static msi_custom_action_info *do_msidbCustomActionTypeDll(
MSIPACKAGE *package, INT type, LPCWSTR dllname, LPCWSTR function, LPCWSTR action )
{ {
thread_struct *info; msi_custom_action_info *info;
info = msi_alloc( sizeof *info );
if (!info)
return NULL;
info = msi_alloc( sizeof(*info) );
msiobj_addref( &package->hdr ); msiobj_addref( &package->hdr );
info->package = package; info->package = package;
info->target = strdupW(target); info->type = type;
info->source = strdupW(dll); info->function = strdupW( function );
info->dllname = strdupW( dllname );
info->action = strdupW( action );
list_add_tail( &package->pending_custom_actions, &info->entry );
return CreateThread(NULL, 0, DllThread, info, 0, NULL); info->handle = CreateThread( NULL, 0, DllThread, info, 0, NULL );
if (!info->handle)
{
free_custom_action_data( info );
return NULL;
}
return info;
} }
static UINT HANDLE_CustomType1(MSIPACKAGE *package, LPCWSTR source, static UINT HANDLE_CustomType1(MSIPACKAGE *package, LPCWSTR source,
LPCWSTR target, const INT type, LPCWSTR action) LPCWSTR target, const INT type, LPCWSTR action)
{ {
msi_custom_action_info *info;
WCHAR tmp_file[MAX_PATH]; WCHAR tmp_file[MAX_PATH];
UINT r = ERROR_SUCCESS; UINT r;
HANDLE ThreadHandle;
r = store_binary_to_temp(package, source, tmp_file); r = store_binary_to_temp(package, source, tmp_file);
if (r != ERROR_SUCCESS) if (r != ERROR_SUCCESS)
...@@ -529,11 +548,9 @@ static UINT HANDLE_CustomType1(MSIPACKAGE *package, LPCWSTR source, ...@@ -529,11 +548,9 @@ static UINT HANDLE_CustomType1(MSIPACKAGE *package, LPCWSTR source,
strcatW(tmp_file,dot); strcatW(tmp_file,dot);
} }
ThreadHandle = do_msidbCustomActionTypeDll( package, tmp_file, target ); info = do_msidbCustomActionTypeDll( package, type, tmp_file, target, action );
r = wait_thread_handle( package, type, ThreadHandle, action ); return wait_thread_handle( info );
return r;
} }
static UINT HANDLE_CustomType2(MSIPACKAGE *package, LPCWSTR source, static UINT HANDLE_CustomType2(MSIPACKAGE *package, LPCWSTR source,
...@@ -594,7 +611,7 @@ static UINT HANDLE_CustomType2(MSIPACKAGE *package, LPCWSTR source, ...@@ -594,7 +611,7 @@ static UINT HANDLE_CustomType2(MSIPACKAGE *package, LPCWSTR source,
static UINT HANDLE_CustomType17(MSIPACKAGE *package, LPCWSTR source, static UINT HANDLE_CustomType17(MSIPACKAGE *package, LPCWSTR source,
LPCWSTR target, const INT type, LPCWSTR action) LPCWSTR target, const INT type, LPCWSTR action)
{ {
HANDLE hThread; msi_custom_action_info *info;
MSIFILE *file; MSIFILE *file;
TRACE("%s %s\n", debugstr_w(source), debugstr_w(target)); TRACE("%s %s\n", debugstr_w(source), debugstr_w(target));
...@@ -606,9 +623,9 @@ static UINT HANDLE_CustomType17(MSIPACKAGE *package, LPCWSTR source, ...@@ -606,9 +623,9 @@ static UINT HANDLE_CustomType17(MSIPACKAGE *package, LPCWSTR source,
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
} }
hThread = do_msidbCustomActionTypeDll( package, file->TargetPath, target ); info = do_msidbCustomActionTypeDll( package, type, file->TargetPath, target, action );
return wait_thread_handle(package, type, hThread, action); return wait_thread_handle( info );
} }
static UINT HANDLE_CustomType18(MSIPACKAGE *package, LPCWSTR source, static UINT HANDLE_CustomType18(MSIPACKAGE *package, LPCWSTR source,
...@@ -735,7 +752,6 @@ static UINT HANDLE_CustomType50(MSIPACKAGE *package, LPCWSTR source, ...@@ -735,7 +752,6 @@ static UINT HANDLE_CustomType50(MSIPACKAGE *package, LPCWSTR source,
rc = CreateProcessW(NULL, cmd, NULL, NULL, FALSE, 0, NULL, rc = CreateProcessW(NULL, cmd, NULL, NULL, FALSE, 0, NULL,
c_collen, &si, &info); c_collen, &si, &info);
if ( !rc ) if ( !rc )
{ {
ERR("Unable to execute command %s\n", debugstr_w(cmd)); ERR("Unable to execute command %s\n", debugstr_w(cmd));
...@@ -806,4 +822,13 @@ void ACTION_FinishCustomActions(MSIPACKAGE* package) ...@@ -806,4 +822,13 @@ void ACTION_FinishCustomActions(MSIPACKAGE* package)
msi_free( action->name ); msi_free( action->name );
msi_free( action ); msi_free( action );
} }
while ((item = list_head( &package->pending_custom_actions )))
{
msi_custom_action_info *info;
info = LIST_ENTRY( item, msi_custom_action_info, entry );
msi_dialog_check_messages( info->handle );
free_custom_action_data( info );
}
} }
...@@ -230,6 +230,7 @@ typedef struct tagMSIPACKAGE ...@@ -230,6 +230,7 @@ typedef struct tagMSIPACKAGE
struct tagMSISCRIPT *script; struct tagMSISCRIPT *script;
struct list RunningActions; struct list RunningActions;
struct list pending_custom_actions;
LPWSTR BaseURL; LPWSTR BaseURL;
LPWSTR PackagePath; LPWSTR PackagePath;
......
...@@ -490,6 +490,7 @@ static MSIPACKAGE *msi_alloc_package( void ) ...@@ -490,6 +490,7 @@ static MSIPACKAGE *msi_alloc_package( void )
list_init( &package->extensions ); list_init( &package->extensions );
list_init( &package->progids ); list_init( &package->progids );
list_init( &package->RunningActions ); list_init( &package->RunningActions );
list_init( &package->pending_custom_actions );
for (i=0; i<PROPERTY_HASH_SIZE; i++) for (i=0; i<PROPERTY_HASH_SIZE; i++)
list_init( &package->props[i] ); list_init( &package->props[i] );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment