summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/msvs/msi/custom_actions.c52
-rw-r--r--tools/msvs/msi/custom_actions.def3
-rwxr-xr-xtools/msvs/msi/product.wxs17
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>