static bool WriteUninstallerRegistryInfo(HKEY hkey) { bool ok = true; ScopedMem<WCHAR> installedExePath(GetInstalledExePath()); ScopedMem<WCHAR> installDate(GetInstallDate()); ScopedMem<WCHAR> installDir(path::GetDir(installedExePath)); ScopedMem<WCHAR> uninstallCmdLine(str::Format(L"\"%s\"", ScopedMem<WCHAR>(GetUninstallerPath()))); ok &= WriteRegStr(hkey, REG_PATH_UNINST, DISPLAY_ICON, installedExePath); ok &= WriteRegStr(hkey, REG_PATH_UNINST, DISPLAY_NAME, APP_NAME_STR); ok &= WriteRegStr(hkey, REG_PATH_UNINST, DISPLAY_VERSION, CURR_VERSION_STR); // Windows XP doesn't allow to view the version number at a glance, // so include it in the DisplayName if (!IsVistaOrGreater()) ok &= WriteRegStr(hkey, REG_PATH_UNINST, DISPLAY_NAME, APP_NAME_STR L" " CURR_VERSION_STR); DWORD size = GetDirSize(gGlobalData.installDir) / 1024; ok &= WriteRegDWORD(hkey, REG_PATH_UNINST, ESTIMATED_SIZE, size); ok &= WriteRegStr(hkey, REG_PATH_UNINST, INSTALL_DATE, installDate); ok &= WriteRegStr(hkey, REG_PATH_UNINST, INSTALL_LOCATION, installDir); ok &= WriteRegDWORD(hkey, REG_PATH_UNINST, NO_MODIFY, 1); ok &= WriteRegDWORD(hkey, REG_PATH_UNINST, NO_REPAIR, 1); ok &= WriteRegStr(hkey, REG_PATH_UNINST, PUBLISHER, TEXT(PUBLISHER_STR)); ok &= WriteRegStr(hkey, REG_PATH_UNINST, UNINSTALL_STRING, uninstallCmdLine); ok &= WriteRegStr(hkey, REG_PATH_UNINST, URL_INFO_ABOUT, L"http://www.sumatrapdfreader.org/"); ok &= WriteRegStr(hkey, REG_PATH_UNINST, URL_UPDATE_INFO, L"http://www.sumatrapdfreader.org/news.html"); return ok; }
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; }
// cf. http://msdn.microsoft.com/en-us/library/cc144148(v=vs.85).aspx static bool WriteExtendedFileExtensionInfo(HKEY hkey) { bool success = true; ScopedMem<WCHAR> exePath(GetInstalledExePath()); if (HKEY_LOCAL_MACHINE == hkey) success &= WriteRegStr(hkey, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\" EXENAME, NULL, exePath); // mirroring some of what DoAssociateExeWithPdfExtension() does (cf. AppTools.cpp) ScopedMem<WCHAR> iconPath(str::Join(exePath, L",1")); success &= WriteRegStr(hkey, REG_CLASSES_APPS L"\\DefaultIcon", NULL, iconPath); ScopedMem<WCHAR> cmdPath(str::Format(L"\"%s\" \"%%1\" %%*", exePath)); success &= WriteRegStr(hkey, REG_CLASSES_APPS L"\\Shell\\Open\\Command", NULL, cmdPath); ScopedMem<WCHAR> printPath(str::Format(L"\"%s\" -print-to-default \"%%1\"", exePath)); success &= WriteRegStr(hkey, REG_CLASSES_APPS L"\\Shell\\Print\\Command", NULL, printPath); ScopedMem<WCHAR> printToPath(str::Format(L"\"%s\" -print-to \"%%2\" \"%%1\"", exePath)); success &= WriteRegStr(hkey, REG_CLASSES_APPS L"\\Shell\\PrintTo\\Command", NULL, printToPath); // don't add REG_CLASSES_APPS L"\\SupportedTypes", as that prevents SumatraPDF.exe to // potentially appear in the Open With lists for other filetypes (such as single images) // add the installed SumatraPDF.exe to the Open With lists of the supported file extensions for (int i = 0; NULL != gSupportedExts[i]; i++) { ScopedMem<WCHAR> keyname(str::Join(L"Software\\Classes\\", gSupportedExts[i], L"\\OpenWithList\\" EXENAME)); success &= CreateRegKey(hkey, keyname); // TODO: stop removing this after version 1.8 (was wrongly created for version 1.6) keyname.Set(str::Join(L"Software\\Classes\\", gSupportedExts[i], L"\\OpenWithList\\" APP_NAME_STR)); DeleteRegKey(hkey, keyname); } // in case these values don't exist yet (we won't delete these at uninstallation) success &= WriteRegStr(hkey, REG_CLASSES_PDF, L"Content Type", L"application/pdf"); success &= WriteRegStr(hkey, L"Software\\Classes\\MIME\\Database\\Content Type\\application/pdf", L"Extension", L".pdf"); return success; }
static bool WriteUninstallerRegistryInfo(HKEY hkey) { bool success = true; ScopedMem<WCHAR> uninstallerPath(GetUninstallerPath()); ScopedMem<WCHAR> installedExePath(GetInstalledExePath()); ScopedMem<WCHAR> installDate(GetInstallDate()); ScopedMem<WCHAR> installDir(path::GetDir(installedExePath)); success &= WriteRegStr(hkey, REG_PATH_UNINST, DISPLAY_ICON, installedExePath); success &= WriteRegStr(hkey, REG_PATH_UNINST, DISPLAY_NAME, TAPP); success &= WriteRegStr(hkey, REG_PATH_UNINST, DISPLAY_VERSION, CURR_VERSION_STR); // Windows XP doesn't allow to view the version number at a glance, // so include it in the DisplayName if (!IsVistaOrGreater()) success &= WriteRegStr(hkey, REG_PATH_UNINST, DISPLAY_NAME, TAPP L" " CURR_VERSION_STR); DWORD size = GetDirSize(gGlobalData.installDir) / 1024; success &= WriteRegDWORD(hkey, REG_PATH_UNINST, ESTIMATED_SIZE, size); success &= WriteRegStr(hkey, REG_PATH_UNINST, INSTALL_DATE, installDate); success &= WriteRegStr(hkey, REG_PATH_UNINST, INSTALL_LOCATION, installDir); success &= WriteRegDWORD(hkey, REG_PATH_UNINST, NO_MODIFY, 1); success &= WriteRegDWORD(hkey, REG_PATH_UNINST, NO_REPAIR, 1); success &= WriteRegStr(hkey, REG_PATH_UNINST, PUBLISHER, TEXT(PUBLISHER_STR)); success &= WriteRegStr(hkey, REG_PATH_UNINST, UNINSTALL_STRING, uninstallerPath); success &= WriteRegStr(hkey, REG_PATH_UNINST, URL_INFO_ABOUT, L"http://blog.kowalczyk.info/software/sumatrapdf/"); success &= WriteRegStr(hkey, REG_PATH_UNINST, URL_UPDATE_INFO, L"http://blog.kowalczyk.info/software/sumatrapdf/news.html"); return success; }
static bool CreateAppShortcut(bool allUsers) { ScopedMem<WCHAR> shortcutPath(GetShortcutPath(allUsers)); if (!shortcutPath.Get()) return false; ScopedMem<WCHAR> installedExePath(GetInstalledExePath()); return CreateShortcut(shortcutPath, installedExePath); }
// cf. http://msdn.microsoft.com/en-us/library/cc144148(v=vs.85).aspx static bool WriteExtendedFileExtensionInfo(HKEY hkey) { bool ok = true; ScopedMem<WCHAR> exePath(GetInstalledExePath()); if (HKEY_LOCAL_MACHINE == hkey) ok &= WriteRegStr(hkey, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\" EXENAME, nullptr, exePath); // mirroring some of what DoAssociateExeWithPdfExtension() does (cf. AppTools.cpp) ScopedMem<WCHAR> iconPath(str::Join(exePath, L",1")); ok &= WriteRegStr(hkey, REG_CLASSES_APPS L"\\DefaultIcon", nullptr, iconPath); ScopedMem<WCHAR> cmdPath(str::Format(L"\"%s\" \"%%1\" %%*", exePath)); ok &= WriteRegStr(hkey, REG_CLASSES_APPS L"\\Shell\\Open\\Command", nullptr, cmdPath); ScopedMem<WCHAR> printPath(str::Format(L"\"%s\" -print-to-default \"%%1\"", exePath)); ok &= WriteRegStr(hkey, REG_CLASSES_APPS L"\\Shell\\Print\\Command", nullptr, printPath); ScopedMem<WCHAR> printToPath(str::Format(L"\"%s\" -print-to \"%%2\" \"%%1\"", exePath)); ok &= WriteRegStr(hkey, REG_CLASSES_APPS L"\\Shell\\PrintTo\\Command", nullptr, printToPath); // don't add REG_CLASSES_APPS L"\\SupportedTypes", as that prevents SumatraPDF.exe to // potentially appear in the Open With lists for other filetypes (such as single images) // add the installed SumatraPDF.exe to the Open With lists of the supported file extensions // TODO: per http://msdn.microsoft.com/en-us/library/cc144148(v=vs.85).aspx we shouldn't be // using OpenWithList but OpenWithProgIds. Also, it doesn't seem to work on my win7 32bit // (HKLM\Software\Classes\.mobi\OpenWithList\SumatraPDF.exe key is present but "Open With" // menu item doesn't even exist for .mobi files // It's not so easy, though, because if we just set it to SumatraPDF, // all gSupportedExts will be reported as "PDF Document" by Explorer, so this needs // to be more intelligent. We should probably mimic Windows Media Player scheme i.e. // set OpenWithProgIds to SumatraPDF.AssocFile.Mobi etc. and create apropriate // \SOFTWARE\Classes\CLSID\{GUID}\ProgID etc. entries // Also, if Sumatra is the only program handling those docs, our // PDF icon will be shown (we need icons and properly configure them) for (int i = 0; nullptr != gSupportedExts[i]; i++) { ScopedMem<WCHAR> keyname(str::Join(L"Software\\Classes\\", gSupportedExts[i], L"\\OpenWithList\\" EXENAME)); ok &= CreateRegKey(hkey, keyname); } // in case these values don't exist yet (we won't delete these at uninstallation) ok &= WriteRegStr(hkey, REG_CLASSES_PDF, L"Content Type", L"application/pdf"); ok &= WriteRegStr(hkey, L"Software\\Classes\\MIME\\Database\\Content Type\\application/pdf", L"Extension", L".pdf"); return ok; }
static void OnButtonStartSumatra() { ScopedMem<WCHAR> exePath(GetInstalledExePath()); RunNonElevated(exePath); OnButtonExit(); }
BOOL IsUninstallerNeeded() { ScopedMem<WCHAR> exePath(GetInstalledExePath()); return file::Exists(exePath); }