Skip to content

Commit

Permalink
Merge pull request #614 from Squirrel/machine-install-fixes
Browse files Browse the repository at this point in the history
Remove machine install as a Thing
  • Loading branch information
anaisbetts committed Feb 27, 2016
2 parents 22751c9 + a8e16fb commit 3a208fc
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 150 deletions.
156 changes: 18 additions & 138 deletions src/Setup/MachineInstaller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,119 +4,21 @@
#include "resource.h"
#include <sddl.h>

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;
}

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");
bool directoryExists(wchar_t* path) {
DWORD dwResult = GetFileAttributes(path);

// 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)");
if (dwResult != INVALID_FILE_ATTRIBUTES) {
return true;
}

PSECURITY_DESCRIPTOR descriptor;
ConvertStringSecurityDescriptorToSecurityDescriptor(
sddl,
SDDL_REVISION_1,
&descriptor, NULL);

SECURITY_ATTRIBUTES attrs;
attrs.nLength = sizeof(SECURITY_ATTRIBUTES);
attrs.bInheritHandle = false;
attrs.lpSecurityDescriptor = descriptor;
// 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;

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;
return true;
}


bool MachineInstaller::ShouldSilentInstall()
{
// Figure out the package name from our own EXE name
Expand All @@ -130,29 +32,22 @@ bool MachineInstaller::ShouldSilentInstall()

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);
Expand All @@ -161,23 +56,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;
}

Expand Down
1 change: 0 additions & 1 deletion src/Setup/MachineInstaller.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
class MachineInstaller
{
public:
static int PerformMachineInstallSetup();
static bool ShouldSilentInstall();
};

17 changes: 6 additions & 11 deletions src/Setup/winmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 3a208fc

Please sign in to comment.