DWORD WINAPI InstallerThread(LPVOID data) { gGlobalData.success = false; if (!CreateInstallationDirectory()) goto Error; ProgressStep(); if (!InstallCopyFiles()) goto Error; if (gGlobalData.registerAsDefault) { // need to sublaunch SumatraPDF.exe instead of replicating the code // because registration uses translated strings ScopedMem<WCHAR> installedExePath(GetInstalledExePath()); CreateProcessHelper(installedExePath, L"-register-for-pdf"); } if (gGlobalData.installBrowserPlugin) InstallBrowserPlugin(); else if (IsBrowserPluginInstalled()) UninstallBrowserPlugin(); if (gGlobalData.installPdfFilter) InstallPdfFilter(); else if (IsPdfFilterInstalled()) UninstallPdfFilter(); if (gGlobalData.installPdfPreviewer) InstallPdfPreviewer(); else if (IsPdfPreviewerInstalled()) UninstallPdfPreviewer(); if (!CreateAppShortcut(true) && !CreateAppShortcut(false)) { NotifyFailed(_TR("Failed to create a shortcut")); goto Error; } // consider installation a success from here on // (still warn, if we've failed to create the uninstaller, though) gGlobalData.success = true; if (!WriteUninstallerRegistryInfo(HKEY_LOCAL_MACHINE) && !WriteUninstallerRegistryInfo(HKEY_CURRENT_USER)) { NotifyFailed(_TR("Failed to write the uninstallation information to the registry")); } if (!WriteExtendedFileExtensionInfo(HKEY_LOCAL_MACHINE) && !WriteExtendedFileExtensionInfo(HKEY_CURRENT_USER)) { NotifyFailed(_TR("Failed to write the extended file extension information to the registry")); } ProgressStep(); Error: // TODO: roll back installation on failure (restore previous installation!) if (gHwndFrame && !gGlobalData.silent) { Sleep(500); // allow a glimpse of the completed progress bar before hiding it PostMessage(gHwndFrame, WM_APP_INSTALLATION_FINISHED, 0, 0); } return 0; }
// If this is uninstaller and we're running from installation directory, // copy uninstaller to temp directory and execute from there, exiting // ourselves. This is needed so that uninstaller can delete itself // from installation directory and remove installation directory // If returns TRUE, this is an installer and we sublaunched ourselves, // so the caller needs to exit bool ExecuteUninstallerFromTempDir() { // only need to sublaunch if running from installation dir ScopedMem<WCHAR> ownDir(path::GetDir(GetOwnPath())); ScopedMem<WCHAR> tempPath(GetTempUninstallerPath()); // no temp directory available? if (!tempPath) return false; // not running from the installation directory? // (likely a test uninstaller that shouldn't be removed anyway) if (!path::IsSame(ownDir, gGlobalData.installDir)) return false; // already running from temp directory? if (path::IsSame(GetOwnPath(), tempPath)) return false; if (!CopyFile(GetOwnPath(), tempPath, FALSE)) { NotifyFailed(L"Failed to copy uninstaller to temp directory"); return false; } ScopedMem<WCHAR> args(str::Format(L"/d \"%s\" %s", gGlobalData.installDir, gGlobalData.silent ? L"/s" : L"")); bool ok = CreateProcessHelper(tempPath, args); // mark the uninstaller for removal at shutdown (note: works only for administrators) MoveFileEx(tempPath, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); return ok; }