diff options
-rw-r--r-- | tools/msvs/msi/custom_actions.c | 52 | ||||
-rw-r--r-- | tools/msvs/msi/custom_actions.def | 3 | ||||
-rwxr-xr-x | tools/msvs/msi/product.wxs | 17 |
3 files changed, 67 insertions, 5 deletions
diff --git a/tools/msvs/msi/custom_actions.c b/tools/msvs/msi/custom_actions.c index 5e7d617f3..bf36edc73 100644 --- a/tools/msvs/msi/custom_actions.c +++ b/tools/msvs/msi/custom_actions.c @@ -1,10 +1,60 @@ - #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <msiquery.h> #include <wcautil.h> +#define GUID_BUFFER_SIZE 39 // {8-4-4-4-12}\0 + + +UINT WINAPI SetInstallScope(MSIHANDLE hInstall) { + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + TCHAR upgrade_code[GUID_BUFFER_SIZE]; + DWORD upgrade_code_len = GUID_BUFFER_SIZE; + DWORD iProductIndex; + TCHAR product_code[GUID_BUFFER_SIZE]; + TCHAR assignment_type[2]; + DWORD assignment_type_len = 2; + + hr = WcaInitialize(hInstall, "SetInstallScope"); + ExitOnFailure(hr, "Failed to initialize"); + + er = MsiGetProperty(hInstall, TEXT("UpgradeCode"), upgrade_code, + &upgrade_code_len); + ExitOnWin32Error(er, hr, "Failed to get UpgradeCode property"); + + for (iProductIndex = 0;; iProductIndex++) { + er = MsiEnumRelatedProducts(upgrade_code, 0, iProductIndex, product_code); + if (er == ERROR_NO_MORE_ITEMS) break; + ExitOnWin32Error(er, hr, "Failed to get related product code"); + + er = MsiGetProductInfo(product_code, INSTALLPROPERTY_ASSIGNMENTTYPE, + assignment_type, &assignment_type_len); + ExitOnWin32Error(er, hr, "Failed to get the assignment type property " + "from related product"); + + // '0' = per-user; '1' = per-machine + if (assignment_type[0] == '0') { + /* When old versions which were installed as per-user are detected, the + * installation scope has to be set to per-user to be able to do an + * upgrade. If not, two versions will be installed side-by-side: one as + * per-user and the other as per-machine. + * + * If we wanted to disable backward compatibility, the installer should + * abort here, and request the previous version to be manually + * uninstalled before installing this one. + */ + er = MsiSetProperty(hInstall, TEXT("ALLUSERS"), TEXT("")); + ExitOnWin32Error(er, hr, "Failed to set the install scope to per-user"); + break; + } + } + +LExit: + return WcaFinalize(ERROR_SUCCESS); +} + UINT WINAPI BroadcastEnvironmentUpdate(MSIHANDLE hInstall) { HRESULT hr = S_OK; diff --git a/tools/msvs/msi/custom_actions.def b/tools/msvs/msi/custom_actions.def index 29e0933e3..5f6b25fc4 100644 --- a/tools/msvs/msi/custom_actions.def +++ b/tools/msvs/msi/custom_actions.def @@ -1,4 +1,5 @@ LIBRARY "custom_actions" EXPORTS -BroadcastEnvironmentUpdate
\ No newline at end of file +SetInstallScope +BroadcastEnvironmentUpdate diff --git a/tools/msvs/msi/product.wxs b/tools/msvs/msi/product.wxs index 6ff0d4b14..2ce00a44b 100755 --- a/tools/msvs/msi/product.wxs +++ b/tools/msvs/msi/product.wxs @@ -18,7 +18,7 @@ Manufacturer="$(var.ProductAuthor)" UpgradeCode="1d60944c-b9ce-4a71-a7c0-0384eb884baa"> - <Package InstallerVersion="200" Compressed="yes"/> + <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine"/> <Media Id="1" Cabinet="media1.cab" EmbedCab="yes"/> @@ -249,16 +249,27 @@ </Component> </DirectoryRef> - <Binary Id='BroadcastEnvironmentUpdate' + <Binary Id='CustomActionsDLL' SourceFile='$(var.custom_actions.TargetDir)$(var.custom_actions.TargetName).dll' /> + <CustomAction Id="SetInstallScope" + BinaryKey="CustomActionsDLL" + DllEntry="SetInstallScope" + Execute="immediate" + Return="check" /> + <CustomAction Id="BroadcastEnvironmentUpdate" - BinaryKey="BroadcastEnvironmentUpdate" + BinaryKey="CustomActionsDLL" DllEntry="BroadcastEnvironmentUpdate" Execute="immediate" Return="check" /> + <InstallUISequence> + <Custom Action='SetInstallScope' Before='FindRelatedProducts'/> + </InstallUISequence> + <InstallExecuteSequence> + <Custom Action='SetInstallScope' Before='FindRelatedProducts'/> <Custom Action='BroadcastEnvironmentUpdate' After='InstallFinalize'/> </InstallExecuteSequence> |