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

oldstable
Mike McCormack 2007-02-12 11:31:41 +09:00 committed by Alexandre Julliard
parent 5927015726
commit 63e554994a
3 changed files with 104 additions and 77 deletions

View File

@ -59,6 +59,7 @@ static UINT HANDLE_CustomType50(MSIPACKAGE *package, LPCWSTR source,
static UINT HANDLE_CustomType34(MSIPACKAGE *package, LPCWSTR source,
LPCWSTR target, const INT type, LPCWSTR action);
typedef UINT (WINAPI *MsiCustomActionEntryPoint)( MSIHANDLE );
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,
return rc;
}
static UINT wait_thread_handle(MSIPACKAGE* package, UINT type,
HANDLE ThreadHandle, LPCWSTR name)
typedef struct _msi_custom_action_info {
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;
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))
rc = custom_get_thread_return(ThreadHandle);
if (!(info->type & msidbCustomActionTypeContinue))
rc = custom_get_thread_return( info->handle );
CloseHandle(ThreadHandle);
free_custom_action_data( info );
}
else
{
TRACE("%s running in background\n", debugstr_w(name));
TRACE("%s running in background\n", debugstr_w( info->action ));
if (!(type & msidbCustomActionTypeContinue))
file_running_action(package, ThreadHandle, FALSE, name);
else
CloseHandle(ThreadHandle);
if (info->type & msidbCustomActionTypeContinue)
free_custom_action_data( info );
}
return rc;
}
typedef UINT __stdcall CustomEntry(MSIHANDLE);
typedef struct
{
MSIPACKAGE *package;
WCHAR *target;
WCHAR *source;
} thread_struct;
static DWORD WINAPI ACTION_CallDllFunction(thread_struct *stuff)
static DWORD WINAPI ACTION_CallDllFunction( msi_custom_action_info *info )
{
MsiCustomActionEntryPoint fn;
MSIHANDLE hPackage;
HANDLE hModule;
LPSTR proc;
CustomEntry *fn;
DWORD rc = ERROR_SUCCESS;
UINT r = ERROR_FUNCTION_FAILED;
TRACE("calling function (%s, %s)\n", debugstr_w(stuff->source),
debugstr_w(stuff->target));
TRACE("%s %s\n", debugstr_w( info->dllname ), debugstr_w( info->function ) );
hModule = LoadLibraryW(stuff->source);
if (hModule)
hModule = LoadLibraryW( info->dllname );
if (!hModule)
{
proc = strdupWtoA( stuff->target );
fn = (CustomEntry*)GetProcAddress(hModule,proc);
if (fn)
{
MSIHANDLE hPackage;
MSIPACKAGE *package = stuff->package;
ERR("failed to load dll %s\n", debugstr_w( info->dllname ) );
return r;
}
TRACE("Calling function %s\n", proc);
hPackage = alloc_msihandle( &package->hdr );
if (hPackage)
{
rc = fn( hPackage );
MsiCloseHandle( hPackage );
}
else
ERR("Handle for object %p not found\n", package );
proc = strdupWtoA( info->function );
fn = (MsiCustomActionEntryPoint) GetProcAddress( hModule, proc );
msi_free( proc );
if (fn)
{
hPackage = alloc_msihandle( &info->package->hdr );
if (hPackage)
{
TRACE("calling %s\n", debugstr_w( info->function ) );
r = fn( hPackage );
MsiCloseHandle( hPackage );
}
else
ERR("failed to resolve functon %s\n", debugstr_a(proc));
msi_free(proc);
FreeLibrary(hModule);
ERR("failed to create handle for %p\n", info->package );
}
else
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;
ERR("GetProcAddress(%s) failed\n", debugstr_w( info->function ) );
FreeLibrary(hModule);
return r;
}
static DWORD WINAPI DllThread(LPVOID info)
static DWORD WINAPI DllThread( LPVOID arg )
{
thread_struct *stuff;
msi_custom_action_info *info = arg;
DWORD rc = 0;
TRACE("MSI Thread (%x) started for custom action\n", GetCurrentThreadId());
TRACE("custom action (%x) started\n", GetCurrentThreadId() );
stuff = (thread_struct*)info;
rc = ACTION_CallDllFunction(stuff);
rc = ACTION_CallDllFunction( info );
TRACE("custom action (%x) returned %i\n", GetCurrentThreadId(), rc );
TRACE("MSI Thread (%x) finished (rc %i)\n",GetCurrentThreadId(), rc);
/* close all handles for this thread */
MsiCloseAllHandles();
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 );
info->package = package;
info->target = strdupW(target);
info->source = strdupW(dll);
info->type = type;
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,
LPCWSTR target, const INT type, LPCWSTR action)
{
msi_custom_action_info *info;
WCHAR tmp_file[MAX_PATH];
UINT r = ERROR_SUCCESS;
HANDLE ThreadHandle;
UINT r;
r = store_binary_to_temp(package, source, tmp_file);
if (r != ERROR_SUCCESS)
@ -529,11 +548,9 @@ static UINT HANDLE_CustomType1(MSIPACKAGE *package, LPCWSTR source,
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 r;
return wait_thread_handle( info );
}
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,
LPCWSTR target, const INT type, LPCWSTR action)
{
HANDLE hThread;
msi_custom_action_info *info;
MSIFILE *file;
TRACE("%s %s\n", debugstr_w(source), debugstr_w(target));
@ -606,9 +623,9 @@ static UINT HANDLE_CustomType17(MSIPACKAGE *package, LPCWSTR source,
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,
@ -735,7 +752,6 @@ static UINT HANDLE_CustomType50(MSIPACKAGE *package, LPCWSTR source,
rc = CreateProcessW(NULL, cmd, NULL, NULL, FALSE, 0, NULL,
c_collen, &si, &info);
if ( !rc )
{
ERR("Unable to execute command %s\n", debugstr_w(cmd));
@ -806,4 +822,13 @@ void ACTION_FinishCustomActions(MSIPACKAGE* package)
msi_free( action->name );
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 );
}
}

View File

@ -230,6 +230,7 @@ typedef struct tagMSIPACKAGE
struct tagMSISCRIPT *script;
struct list RunningActions;
struct list pending_custom_actions;
LPWSTR BaseURL;
LPWSTR PackagePath;

View File

@ -490,6 +490,7 @@ static MSIPACKAGE *msi_alloc_package( void )
list_init( &package->extensions );
list_init( &package->progids );
list_init( &package->RunningActions );
list_init( &package->pending_custom_actions );
for (i=0; i<PROPERTY_HASH_SIZE; i++)
list_init( &package->props[i] );