Skip to content

Commit 8e80528

Browse files
joaocgreisorangemocha
authored andcommitted
win,msi: change InstallScope to perMachine
The MSI install scope was set to the WiX default, which is per-user. However, with UAC, it could not be installed by a standard user because InstallPrivileges is elevated by default, hence the install scope should be set to per-machine. Furthermore, the default install path is a per-machine location and setting the system path requires administrator privileges. By changing the InstallScope to perMachine, Start Menu shortcuts are placed in ProgramData and not the installing user's AppData folder, making the shortcuts available to other users. This also fixes the installation when AppData is a network folder. The custom action is necessary to allow upgrades. Since a per-machine MSI cannot upgrade an application installed per-user, the custom action checks if there is going to be an upgrade to a previous version installed per-user and sets the installation as per-user to allow upgrading. Hence, the advantages of installing per-machine will only apply in fresh installations. Fixes #5849 Fixes #7629 PR-URL: nodejs/node-v0.x-archive#25640 Reviewed-By: Alexis Campailla <alexis@janeasystems.com> Reviewed-By: Bert Belder <bertbelder@gmail.com>
1 parent b8d47a7 commit 8e80528

File tree

3 files changed

+67
-5
lines changed

3 files changed

+67
-5
lines changed

tools/msvs/msi/custom_actions.c

+51-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,60 @@
1-
21
#define WIN32_LEAN_AND_MEAN
32

43
#include <windows.h>
54
#include <msiquery.h>
65
#include <wcautil.h>
76

7+
#define GUID_BUFFER_SIZE 39 // {8-4-4-4-12}\0
8+
9+
10+
UINT WINAPI SetInstallScope(MSIHANDLE hInstall) {
11+
HRESULT hr = S_OK;
12+
UINT er = ERROR_SUCCESS;
13+
TCHAR upgrade_code[GUID_BUFFER_SIZE];
14+
DWORD upgrade_code_len = GUID_BUFFER_SIZE;
15+
DWORD iProductIndex;
16+
TCHAR product_code[GUID_BUFFER_SIZE];
17+
TCHAR assignment_type[2];
18+
DWORD assignment_type_len = 2;
19+
20+
hr = WcaInitialize(hInstall, "SetInstallScope");
21+
ExitOnFailure(hr, "Failed to initialize");
22+
23+
er = MsiGetProperty(hInstall, TEXT("UpgradeCode"), upgrade_code,
24+
&upgrade_code_len);
25+
ExitOnWin32Error(er, hr, "Failed to get UpgradeCode property");
26+
27+
for (iProductIndex = 0;; iProductIndex++) {
28+
er = MsiEnumRelatedProducts(upgrade_code, 0, iProductIndex, product_code);
29+
if (er == ERROR_NO_MORE_ITEMS) break;
30+
ExitOnWin32Error(er, hr, "Failed to get related product code");
31+
32+
er = MsiGetProductInfo(product_code, INSTALLPROPERTY_ASSIGNMENTTYPE,
33+
assignment_type, &assignment_type_len);
34+
ExitOnWin32Error(er, hr, "Failed to get the assignment type property "
35+
"from related product");
36+
37+
// '0' = per-user; '1' = per-machine
38+
if (assignment_type[0] == '0') {
39+
/* When old versions which were installed as per-user are detected, the
40+
* installation scope has to be set to per-user to be able to do an
41+
* upgrade. If not, two versions will be installed side-by-side: one as
42+
* per-user and the other as per-machine.
43+
*
44+
* If we wanted to disable backward compatibility, the installer should
45+
* abort here, and request the previous version to be manually
46+
* uninstalled before installing this one.
47+
*/
48+
er = MsiSetProperty(hInstall, TEXT("ALLUSERS"), TEXT(""));
49+
ExitOnWin32Error(er, hr, "Failed to set the install scope to per-user");
50+
break;
51+
}
52+
}
53+
54+
LExit:
55+
return WcaFinalize(ERROR_SUCCESS);
56+
}
57+
858

959
UINT WINAPI BroadcastEnvironmentUpdate(MSIHANDLE hInstall) {
1060
HRESULT hr = S_OK;

tools/msvs/msi/custom_actions.def

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
LIBRARY "custom_actions"
22

33
EXPORTS
4-
BroadcastEnvironmentUpdate
4+
SetInstallScope
5+
BroadcastEnvironmentUpdate

tools/msvs/msi/product.wxs

+14-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
Manufacturer="$(var.ProductAuthor)"
1919
UpgradeCode="1d60944c-b9ce-4a71-a7c0-0384eb884baa">
2020

21-
<Package InstallerVersion="200" Compressed="yes"/>
21+
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine"/>
2222

2323
<Media Id="1" Cabinet="media1.cab" EmbedCab="yes"/>
2424

@@ -249,16 +249,27 @@
249249
</Component>
250250
</DirectoryRef>
251251

252-
<Binary Id='BroadcastEnvironmentUpdate'
252+
<Binary Id='CustomActionsDLL'
253253
SourceFile='$(var.custom_actions.TargetDir)$(var.custom_actions.TargetName).dll' />
254254

255+
<CustomAction Id="SetInstallScope"
256+
BinaryKey="CustomActionsDLL"
257+
DllEntry="SetInstallScope"
258+
Execute="immediate"
259+
Return="check" />
260+
255261
<CustomAction Id="BroadcastEnvironmentUpdate"
256-
BinaryKey="BroadcastEnvironmentUpdate"
262+
BinaryKey="CustomActionsDLL"
257263
DllEntry="BroadcastEnvironmentUpdate"
258264
Execute="immediate"
259265
Return="check" />
260266

267+
<InstallUISequence>
268+
<Custom Action='SetInstallScope' Before='FindRelatedProducts'/>
269+
</InstallUISequence>
270+
261271
<InstallExecuteSequence>
272+
<Custom Action='SetInstallScope' Before='FindRelatedProducts'/>
262273
<Custom Action='BroadcastEnvironmentUpdate' After='InstallFinalize'/>
263274
</InstallExecuteSequence>
264275

0 commit comments

Comments
 (0)