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 12extern "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 75LExit: 76 // Always succeed. This should not block the installation. 77 return WcaFinalize(ERROR_SUCCESS); 78} 79 80 81extern "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 96LExit: 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 103extern "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 125LExit: 126 er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; 127 LocalFree(sid); 128 return WcaFinalize(er); 129} 130 131extern "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