From 98eafa870c619dbf78ae28feb8f5abc904de5cb9 Mon Sep 17 00:00:00 2001 From: James Hawkins Date: Sun, 15 Apr 2007 03:12:23 -0500 Subject: [PATCH] msi: Add handling for the concurrent install custom action. --- dlls/msi/custom.c | 98 ++++++++++++++++++++++++++++++++++++++++ dlls/msi/tests/install.c | 11 ++--- 2 files changed, 102 insertions(+), 7 deletions(-) diff --git a/dlls/msi/custom.c b/dlls/msi/custom.c index c1c7e960ec9..c38ea9888d3 100644 --- a/dlls/msi/custom.c +++ b/dlls/msi/custom.c @@ -54,6 +54,8 @@ static UINT HANDLE_CustomType18(MSIPACKAGE *package, LPCWSTR source, LPCWSTR target, const INT type, LPCWSTR action); static UINT HANDLE_CustomType19(MSIPACKAGE *package, LPCWSTR source, LPCWSTR target, const INT type, LPCWSTR action); +static UINT HANDLE_CustomType23(MSIPACKAGE *package, LPCWSTR source, + LPCWSTR target, const INT type, LPCWSTR action); static UINT HANDLE_CustomType50(MSIPACKAGE *package, LPCWSTR source, LPCWSTR target, const INT type, LPCWSTR action); static UINT HANDLE_CustomType34(MSIPACKAGE *package, LPCWSTR source, @@ -250,6 +252,10 @@ UINT ACTION_CustomAction(MSIPACKAGE *package,LPCWSTR action, BOOL execute) case 17: rc = HANDLE_CustomType17(package,source,target,type,action); break; + case 23: /* installs another package in the source tree */ + deformat_string(package,target,&deformated); + rc = HANDLE_CustomType23(package,source,deformated,type,action); + break; case 50: /*EXE file specified by a property value */ rc = HANDLE_CustomType50(package,source,target,type,action); break; @@ -548,6 +554,41 @@ static DWORD WINAPI DllThread( LPVOID arg ) return rc; } +static DWORD WINAPI ACTION_CAInstallPackage(const GUID *guid) +{ + msi_custom_action_info *info; + UINT r = ERROR_FUNCTION_FAILED; + INSTALLUILEVEL old_level; + + info = find_action_by_guid(guid); + if (!info) + { + ERR("failed to find action %s\n", debugstr_guid(guid)); + return r; + } + + old_level = MsiSetInternalUI(INSTALLUILEVEL_BASIC, NULL); + r = MsiInstallProductW(info->source, info->target); + MsiSetInternalUI(old_level, NULL); + + return r; +} + +static DWORD WINAPI ConcurrentInstallThread(LPVOID arg) +{ + LPGUID guid = arg; + DWORD rc; + + TRACE("concurrent installation (%x) started\n", GetCurrentThreadId()); + + rc = ACTION_CAInstallPackage(guid); + + TRACE("concurrent installation (%x) returned %i\n", GetCurrentThreadId(), rc); + + MsiCloseAllHandles(); + return rc; +} + static msi_custom_action_info *do_msidbCustomActionTypeDll( MSIPACKAGE *package, INT type, LPCWSTR source, LPCWSTR target, LPCWSTR action ) { @@ -579,6 +620,63 @@ static msi_custom_action_info *do_msidbCustomActionTypeDll( return info; } +static msi_custom_action_info *do_msidbCAConcurrentInstall( + MSIPACKAGE *package, INT type, LPCWSTR source, LPCWSTR target, LPCWSTR action) +{ + msi_custom_action_info *info; + + info = msi_alloc( sizeof *info ); + if (!info) + return NULL; + + msiobj_addref( &package->hdr ); + info->package = package; + info->type = type; + info->target = strdupW( target ); + info->source = strdupW( source ); + info->action = strdupW( action ); + CoCreateGuid( &info->guid ); + + EnterCriticalSection( &msi_custom_action_cs ); + list_add_tail( &msi_pending_custom_actions, &info->entry ); + LeaveCriticalSection( &msi_custom_action_cs ); + + info->handle = CreateThread( NULL, 0, ConcurrentInstallThread, &info->guid, 0, NULL ); + if (!info->handle) + { + free_custom_action_data( info ); + return NULL; + } + + return info; +} + +static UINT HANDLE_CustomType23(MSIPACKAGE *package, LPCWSTR source, + LPCWSTR target, const INT type, LPCWSTR action) +{ + msi_custom_action_info *info; + WCHAR package_path[MAX_PATH]; + DWORD size; + + static const WCHAR backslash[] = {'\\',0}; + + MSI_GetPropertyW(package, cszSourceDir, package_path, &size); + lstrcatW(package_path, backslash); + lstrcatW(package_path, source); + + if (GetFileAttributesW(package_path) == INVALID_FILE_ATTRIBUTES) + { + ERR("Source package does not exist: %s\n", debugstr_w(package_path)); + return ERROR_FUNCTION_FAILED; + } + + TRACE("Installing package %s concurrently\n", debugstr_w(package_path)); + + info = do_msidbCAConcurrentInstall(package, type, package_path, target, action); + + return wait_thread_handle(info); +} + static UINT HANDLE_CustomType1(MSIPACKAGE *package, LPCWSTR source, LPCWSTR target, const INT type, LPCWSTR action) { diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c index 6c8b0789d2e..5b7050f6575 100644 --- a/dlls/msi/tests/install.c +++ b/dlls/msi/tests/install.c @@ -1417,13 +1417,10 @@ static void test_concurrentinstall(void) MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL); r = MsiInstallProductA(msifile, NULL); - todo_wine - { - ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); - ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n"); - ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n"); - ok(delete_pf("msitest", FALSE), "File not installed\n"); - } + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n"); + ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n"); + ok(delete_pf("msitest", FALSE), "File not installed\n"); DeleteFile(msifile); }