1 #define WIN32_LEAN_AND_MEAN
2
3 #include <windows.h>
4 #include <msiquery.h>
5 #include <wcautil.h>
6 #include <sddl.h>
7 #include <Lmcons.h>
8
9 #define GUID_BUFFER_SIZE 39 // {8-4-4-4-12}\0
10
11
SetInstallScope(MSIHANDLE hInstall)12 extern "C" UINT WINAPI SetInstallScope(MSIHANDLE hInstall) {
13 HRESULT hr = S_OK;
14 UINT er = ERROR_SUCCESS;
15 PMSIHANDLE hDB;
16 PMSIHANDLE hView;
17 PMSIHANDLE hRecord;
18
19 hr = WcaInitialize(hInstall, "SetInstallScope");
20 ExitOnFailure(hr, "Failed to initialize");
21
22 hDB = MsiGetActiveDatabase(hInstall);
23 ExitOnNull(hDB, hr, S_FALSE, "Failed to get active database");
24
25 LPCTSTR query = TEXT("SELECT DISTINCT UpgradeCode FROM Upgrade");
26 er = MsiDatabaseOpenView(hDB, query, &hView);
27 ExitOnWin32Error(er, hr, "Failed MsiDatabaseOpenView");
28
29 er = MsiViewExecute(hView, 0);
30 ExitOnWin32Error(er, hr, "Failed MsiViewExecute");
31
32 for (;;) {
33 er = MsiViewFetch(hView, &hRecord);
34 if (er == ERROR_NO_MORE_ITEMS) break;
35 ExitOnWin32Error(er, hr, "Failed MsiViewFetch");
36
37 TCHAR upgrade_code[GUID_BUFFER_SIZE];
38 DWORD upgrade_code_len = GUID_BUFFER_SIZE;
39 er = MsiRecordGetString(hRecord, 1, upgrade_code, &upgrade_code_len);
40 ExitOnWin32Error(er, hr, "Failed to read UpgradeCode");
41
42 DWORD iProductIndex;
43 for (iProductIndex = 0;; iProductIndex++) {
44 TCHAR product_code[GUID_BUFFER_SIZE];
45 er = MsiEnumRelatedProducts(upgrade_code, 0, iProductIndex,
46 product_code);
47 if (er == ERROR_NO_MORE_ITEMS) break;
48 ExitOnWin32Error(er, hr, "Failed to get related product code");
49
50 TCHAR assignment_type[2];
51 DWORD assignment_type_len = 2;
52 er = MsiGetProductInfo(product_code, INSTALLPROPERTY_ASSIGNMENTTYPE,
53 assignment_type, &assignment_type_len);
54 ExitOnWin32Error(er, hr, "Failed to get the assignment type property "
55 "from related product");
56
57 // '0' = per-user; '1' = per-machine
58 if (assignment_type[0] == '0') {
59 /* When old versions which were installed as per-user are detected,
60 * the installation scope has to be set to per-user to be able to do
61 * an upgrade. If not, two versions will be installed side-by-side:
62 * one as per-user and the other as per-machine.
63 *
64 * If we wanted to disable backward compatibility, the installer
65 * should abort here, and request the previous version to be manually
66 * uninstalled before installing this one.
67 */
68 er = MsiSetProperty(hInstall, TEXT("ALLUSERS"), TEXT(""));
69 ExitOnWin32Error(er, hr, "Failed to set the install scope to per-user");
70 goto LExit;
71 }
72 }
73 }
74
75 LExit:
76 // Always succeed. This should not block the installation.
77 return WcaFinalize(ERROR_SUCCESS);
78 }
79
80
BroadcastEnvironmentUpdate(MSIHANDLE hInstall)81 extern "C" UINT WINAPI BroadcastEnvironmentUpdate(MSIHANDLE hInstall) {
82 HRESULT hr = S_OK;
83 UINT er = ERROR_SUCCESS;
84
85 hr = WcaInitialize(hInstall, "BroadcastEnvironmentUpdate");
86 ExitOnFailure(hr, "Failed to initialize");
87
88 SendMessageTimeoutW(HWND_BROADCAST,
89 WM_SETTINGCHANGE,
90 0,
91 (LPARAM) L"Environment",
92 SMTO_ABORTIFHUNG,
93 5000,
94 NULL);
95
96 LExit:
97 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
98 return WcaFinalize(er);
99 }
100
101 #define AUTHENTICATED_USERS_SID L"S-1-5-11"
102
GetLocalizedUserNames(MSIHANDLE hInstall)103 extern "C" UINT WINAPI GetLocalizedUserNames(MSIHANDLE hInstall) {
104 HRESULT hr = S_OK;
105 UINT er = ERROR_SUCCESS;
106 TCHAR userName[UNLEN + 1] = {0};
107 DWORD userNameSize = UNLEN + 1;
108 TCHAR domain[DNLEN + 1] = {0};
109 DWORD domainSize = DNLEN + 1;
110 PSID sid;
111 SID_NAME_USE nameUse;
112
113 hr = WcaInitialize(hInstall, "GetLocalizedUserNames");
114 ExitOnFailure(hr, "Failed to initialize");
115
116 er = ConvertStringSidToSidW(AUTHENTICATED_USERS_SID, &sid);
117 ExitOnLastError(er, "Failed to convert security identifier");
118
119 er = LookupAccountSidW(NULL, sid, userName, &userNameSize, domain, &domainSize, &nameUse);
120 ExitOnLastError(er, "Failed to lookup security identifier");
121
122 MsiSetProperty(hInstall, L"AUTHENTICATED_USERS", userName);
123 ExitOnWin32Error(er, hr, "Failed to set localized Authenticated User name");
124
125 LExit:
126 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
127 LocalFree(sid);
128 return WcaFinalize(er);
129 }
130
DllMain(HINSTANCE hInst,ULONG ulReason,VOID * dummy)131 extern "C" BOOL WINAPI DllMain(HINSTANCE hInst, ULONG ulReason, VOID* dummy) {
132 switch (ulReason) {
133 case DLL_PROCESS_ATTACH:
134 WcaGlobalInitialize(hInst);
135 break;
136
137 case DLL_PROCESS_DETACH:
138 WcaGlobalFinalize();
139 break;
140 }
141
142 return TRUE;
143 }
144