From 7d1c92790eee04239729ffc419e93a5e277d225d Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Thu, 25 Feb 2016 15:09:06 -0800 Subject: [PATCH 1/3] Be way more careful for when we'll return true for shouldSilentInstall --- src/Setup/MachineInstaller.cpp | 56 +++++++++++++++------------------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/src/Setup/MachineInstaller.cpp b/src/Setup/MachineInstaller.cpp index 5220b330c..c54144e6a 100644 --- a/src/Setup/MachineInstaller.cpp +++ b/src/Setup/MachineInstaller.cpp @@ -49,6 +49,21 @@ bool findPackageFromEmbeddedZip(wchar_t* buf, DWORD cbSize) return ret; } +bool directoryExists(wchar_t* path) { + DWORD dwResult = GetFileAttributes(path); + + if (dwResult != INVALID_FILE_ATTRIBUTES) { + return true; + } + + // NB: The directory could exist but we can't access it, let's check + DWORD dwLastError = GetLastError(); + if (dwLastError == ERROR_FILE_NOT_FOUND) return false; + if (dwLastError == ERROR_PATH_NOT_FOUND) return false; + + return true; +} + int MachineInstaller::PerformMachineInstallSetup() { wchar_t packageName[512]; @@ -124,35 +139,29 @@ bool MachineInstaller::ShouldSilentInstall() HMODULE hMod = GetModuleHandle(NULL); GetModuleFileName(hMod, ourFile, _countof(ourFile)); + CString fullPath = CString(ourFile); CString pkgName = CString(ourFile + fullPath.ReverseFind(L'\\')); pkgName.Replace(L".exe", L""); wchar_t installFolder[MAX_PATH]; - // C:\Users\Username\AppData\Local\$pkgName\packages - SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, installFolder); - wcscat(installFolder, L"\\"); - wcscat(installFolder, pkgName); - wcscat(installFolder, L"\\"); - wcscat(installFolder, L"packages"); + // NB: Users often get into the sitch where they install the MSI, then try to + // install the standalone package on top of that. In previous versions we tried + // to detect if the app was properly installed, but now we're taking the much + // more conservative approach, that if the package dir exists in any way, we're + // bailing out - if (GetFileAttributes(installFolder) != INVALID_FILE_ATTRIBUTES) { - return false; - } - - // C:\Users\Username\AppData\Local\$pkgName\.dead (was machine-installed but user uninstalled) + // C:\Users\Username\AppData\Local\$pkgName SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, installFolder); wcscat(installFolder, L"\\"); wcscat(installFolder, pkgName); - wcscat(installFolder, L"\\"); - wcscat(installFolder, L".dead"); - if (GetFileAttributes(installFolder) != INVALID_FILE_ATTRIBUTES) { + if (directoryExists(installFolder)) { return false; } - // C:\ProgramData\$pkgName\$username\packages + // C:\ProgramData\$pkgName\$username wchar_t username[512]; DWORD unamesize = _countof(username); SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, installFolder); @@ -161,23 +170,8 @@ bool MachineInstaller::ShouldSilentInstall() wcscat(installFolder, pkgName); wcscat(installFolder, L"\\"); wcscat(installFolder, username); - wcscat(installFolder, L"\\"); - wcscat(installFolder, L"packages"); - - if (GetFileAttributes(installFolder) != INVALID_FILE_ATTRIBUTES) { - return false; - } - - // C:\ProgramData\$pkgName\$username\.dead - SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, installFolder); - wcscat(installFolder, L"\\"); - wcscat(installFolder, pkgName); - wcscat(installFolder, L"\\"); - wcscat(installFolder, username); - wcscat(installFolder, L"\\"); - wcscat(installFolder, L".dead"); - if (GetFileAttributes(installFolder) != INVALID_FILE_ATTRIBUTES) { + if (directoryExists(installFolder)) { return false; } From 449e5c52c494948be6ffd18893dc7cd43b7fcc4c Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Thu, 25 Feb 2016 16:30:18 -0800 Subject: [PATCH 2/3] Burn machine install --- src/Setup/MachineInstaller.cpp | 114 --------------------------------- src/Setup/MachineInstaller.h | 1 - 2 files changed, 115 deletions(-) diff --git a/src/Setup/MachineInstaller.cpp b/src/Setup/MachineInstaller.cpp index c54144e6a..b2bf38355 100644 --- a/src/Setup/MachineInstaller.cpp +++ b/src/Setup/MachineInstaller.cpp @@ -4,51 +4,6 @@ #include "resource.h" #include -bool findPackageFromEmbeddedZip(wchar_t* buf, DWORD cbSize) -{ - bool ret = false; - - CResource zipResource; - if (!zipResource.Load(L"DATA", IDR_UPDATE_ZIP)) { - return false; - } - - DWORD dwSize = zipResource.GetSize(); - if (dwSize < 0x100) { - return false; - } - - BYTE* pData = (BYTE*)zipResource.Lock(); - HZIP zipFile = OpenZip(pData, dwSize, NULL); - - ZRESULT zr; - int index = 0; - do { - ZIPENTRY zentry; - - zr = GetZipItem(zipFile, index, &zentry); - if (zr != ZR_OK && zr != ZR_MORE) { - break; - } - - if (wcsstr(zentry.name, L"nupkg")) { - ZeroMemory(buf, cbSize); - - int idx = wcscspn(zentry.name, L"-"); - memcpy(buf, zentry.name, sizeof(wchar_t) * idx); - ret = true; - break; - } - - index++; - } while (zr == ZR_MORE || zr == ZR_OK); - - CloseZip(zipFile); - zipResource.Release(); - - return ret; -} - bool directoryExists(wchar_t* path) { DWORD dwResult = GetFileAttributes(path); @@ -64,74 +19,6 @@ bool directoryExists(wchar_t* path) { return true; } -int MachineInstaller::PerformMachineInstallSetup() -{ - wchar_t packageName[512]; - - if (!findPackageFromEmbeddedZip(packageName, sizeof(packageName))) { - MessageBox(NULL, L"Corrupt installer", L"Cannot find package name for installer, is it created correctly?", MB_OK); - return ERROR_INVALID_PARAMETER; - } - - wchar_t machineInstallFolder[MAX_PATH]; - SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, machineInstallFolder); - wcscat(machineInstallFolder, L"\\SquirrelMachineInstalls"); - - // NB: This is the DACL for Program Files - wchar_t sddl[512] = L"D:PAI(A;;FA;;;S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464)(A;CIIO;GA;;;S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464)(A;;0x1301bf;;;SY)(A;OICIIO;GA;;;SY)(A;;0x1301bf;;;BA)(A;OICIIO;GA;;;BA)(A;;0x1200a9;;;BU)(A;OICIIO;GXGR;;;BU)(A;OICIIO;GA;;;CO)"; - - if (IsWindows8OrGreater()) { - // Add ALL APPLICATION PACKAGES account (Only available on Windows 8 and greater) - wcscat(sddl, L"(A;;0x1200a9;;;AC)(A;OICIIO;GXGR;;;AC)"); - } - - PSECURITY_DESCRIPTOR descriptor; - ConvertStringSecurityDescriptorToSecurityDescriptor( - sddl, - SDDL_REVISION_1, - &descriptor, NULL); - - SECURITY_ATTRIBUTES attrs; - attrs.nLength = sizeof(SECURITY_ATTRIBUTES); - attrs.bInheritHandle = false; - attrs.lpSecurityDescriptor = descriptor; - - if (!CreateDirectory(machineInstallFolder, &attrs) && GetLastError() != ERROR_ALREADY_EXISTS) { - LocalFree(descriptor); - return GetLastError(); - } - - LocalFree(descriptor); - - wcscat(machineInstallFolder, L"\\"); - wcscat(machineInstallFolder, packageName); - wcscat(machineInstallFolder, L".exe"); - - wchar_t ourFile[MAX_PATH]; - HMODULE hMod = GetModuleHandle(NULL); - GetModuleFileName(hMod, ourFile, _countof(ourFile)); - - if (!CopyFile(ourFile, machineInstallFolder, false)) { - return GetLastError(); - } - - HKEY runKey; - DWORD dontcare; - if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &runKey, &dontcare) != ERROR_SUCCESS) { - return GetLastError(); - } - - wcscat_s(machineInstallFolder, L" --checkInstall"); - - if (RegSetValueEx(runKey, packageName, 0, REG_SZ, (BYTE*)machineInstallFolder, (wcsnlen(machineInstallFolder, sizeof(machineInstallFolder)) + 1) * sizeof(wchar_t)) != ERROR_SUCCESS) { - return GetLastError(); - } - - RegCloseKey(runKey); - return 0; -} - - bool MachineInstaller::ShouldSilentInstall() { // Figure out the package name from our own EXE name @@ -139,7 +26,6 @@ bool MachineInstaller::ShouldSilentInstall() HMODULE hMod = GetModuleHandle(NULL); GetModuleFileName(hMod, ourFile, _countof(ourFile)); - CString fullPath = CString(ourFile); CString pkgName = CString(ourFile + fullPath.ReverseFind(L'\\')); pkgName.Replace(L".exe", L""); diff --git a/src/Setup/MachineInstaller.h b/src/Setup/MachineInstaller.h index eafd55812..cf1ef2ece 100644 --- a/src/Setup/MachineInstaller.h +++ b/src/Setup/MachineInstaller.h @@ -2,7 +2,6 @@ class MachineInstaller { public: - static int PerformMachineInstallSetup(); static bool ShouldSilentInstall(); }; From a8e16fbbcdbb9b5b97d8d6659830adaf6fd6ba31 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Thu, 25 Feb 2016 16:30:49 -0800 Subject: [PATCH 3/3] Really disallow us from running under elevated UAC --- src/Setup/winmain.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/Setup/winmain.cpp b/src/Setup/winmain.cpp index 05d76a078..7c89f6448 100644 --- a/src/Setup/winmain.cpp +++ b/src/Setup/winmain.cpp @@ -46,18 +46,12 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, bool isQuiet = (cmdLine.Find(L"-s") >= 0); bool weAreUACElevated = CUpdateRunner::AreWeUACElevated() == S_OK; - bool explicitMachineInstall = (cmdLine.Find(L"--machine") >= 0); + bool attemptingToRerun = (cmdLine.Find(L"--rerunningWithoutUAC") >= 0); - if (explicitMachineInstall || weAreUACElevated) { - exitCode = MachineInstaller::PerformMachineInstallSetup(); - if (exitCode != 0) goto out; - isQuiet = true; - - // Make sure update.exe gets silent - if (explicitMachineInstall) { - wcscat(lpCmdLine, L" --silent"); - printf("Machine-wide installation was successful! Users will see the app once they log out / log in again.\n"); - } + if (weAreUACElevated && attemptingToRerun) { + CUpdateRunner::DisplayErrorMessage(CString(L"Please re-run this installer as a normal user instead of \"Run as Administrator\"."), NULL); + exitCode = E_FAIL; + goto out; } if (!CFxHelper::CanInstallDotNet4_5()) { @@ -88,6 +82,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, wchar_t buf[4096]; HMODULE hMod = GetModuleHandle(NULL); GetModuleFileNameW(hMod, buf, 4096); + wcscat(lpCmdLine, L" --rerunningWithoutUAC"); CUpdateRunner::ShellExecuteFromExplorer(buf, lpCmdLine); exitCode = 0;