• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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