From 9c5f14278684957af67f08624a0dc8141b9c2425 Mon Sep 17 00:00:00 2001 From: yuyoyuppe Date: Fri, 20 Nov 2020 11:34:34 +0300 Subject: [PATCH] updating: split installer-related and github-related APIs, fix compilation error with latest VS --- .../bootstrapper/bootstrapper.cpp | 2 +- .../PowerToysBootstrapper/bootstrapper/pch.h | 4 + .../CustomAction.cpp | 2 +- .../PowerToysSetupCustomActions.vcxproj | 2 - src/action_runner/action_runner.cpp | 2 + src/common/updating/installer.cpp | 204 ++++++++++++++++++ src/common/updating/installer.h | 19 ++ src/common/updating/notifications.h | 2 + src/common/updating/updating.cpp | 183 +--------------- src/common/updating/updating.h | 8 - src/common/updating/updating.vcxproj | 2 + src/common/updating/updating.vcxproj.filters | 6 + src/runner/main.cpp | 3 +- src/runner/update_utils.cpp | 1 + 14 files changed, 247 insertions(+), 193 deletions(-) create mode 100644 src/common/updating/installer.cpp create mode 100644 src/common/updating/installer.h diff --git a/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp b/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp index a7ab40cb69..daffb571a4 100644 --- a/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp +++ b/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp @@ -4,8 +4,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/installer/PowerToysBootstrapper/bootstrapper/pch.h b/installer/PowerToysBootstrapper/bootstrapper/pch.h index b9367228c1..84ffdb89ed 100644 --- a/installer/PowerToysBootstrapper/bootstrapper/pch.h +++ b/installer/PowerToysBootstrapper/bootstrapper/pch.h @@ -20,4 +20,8 @@ #include #include +#include +#include +#include + #include diff --git a/installer/PowerToysSetupCustomActions/CustomAction.cpp b/installer/PowerToysSetupCustomActions/CustomAction.cpp index 8fd2d67f1a..9c90c19797 100644 --- a/installer/PowerToysSetupCustomActions/CustomAction.cpp +++ b/installer/PowerToysSetupCustomActions/CustomAction.cpp @@ -2,7 +2,7 @@ #include -#include "../../src/common/updating/updating.h" +#include "../../src/common/updating/installer.h" using namespace std; diff --git a/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj b/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj index dedb7601e1..a514bc8e06 100644 --- a/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj +++ b/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj @@ -97,8 +97,6 @@ Use stdafx.h - /await /Zc:twoPhase- %(AdditionalOptions) - /await /Zc:twoPhase- %(AdditionalOptions) diff --git a/src/action_runner/action_runner.cpp b/src/action_runner/action_runner.cpp index 99189b4f05..073e513496 100644 --- a/src/action_runner/action_runner.cpp +++ b/src/action_runner/action_runner.cpp @@ -4,10 +4,12 @@ #include #include +#include #include #include #include +#include #include #include diff --git a/src/common/updating/installer.cpp b/src/common/updating/installer.cpp new file mode 100644 index 0000000000..ab3e3c301a --- /dev/null +++ b/src/common/updating/installer.cpp @@ -0,0 +1,204 @@ +#include "pch.h" + +#include "installer.h" +#include "version.h" +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +namespace // Strings in this namespace should not be localized +{ + const wchar_t POWER_TOYS_UPGRADE_CODE[] = L"{42B84BF7-5FBF-473B-9C8B-049DC16F7708}"; + + const wchar_t DONT_SHOW_AGAIN_RECORD_REGISTRY_PATH[] = L"delete_previous_powertoys_confirm"; + + const wchar_t TOAST_TITLE[] = L"PowerToys"; + + const wchar_t MSIX_PACKAGE_NAME[] = L"Microsoft.PowerToys"; + const wchar_t MSIX_PACKAGE_PUBLISHER[] = L"CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"; + + const wchar_t POWERTOYS_EXE_COMPONENT[] = L"{A2C66D91-3485-4D00-B04D-91844E6B345B}"; +} + +namespace updating +{ + std::wstring get_msi_package_path() + { + std::wstring package_path; + wchar_t GUID_product_string[39]; + if (const bool found = ERROR_SUCCESS == MsiEnumRelatedProductsW(POWER_TOYS_UPGRADE_CODE, 0, 0, GUID_product_string); !found) + { + return package_path; + } + + if (const bool installed = INSTALLSTATE_DEFAULT == MsiQueryProductStateW(GUID_product_string); !installed) + { + return package_path; + } + + DWORD package_path_size = 0; + + if (const bool has_package_path = ERROR_SUCCESS == MsiGetProductInfoW(GUID_product_string, INSTALLPROPERTY_LOCALPACKAGE, nullptr, &package_path_size); !has_package_path) + { + return package_path; + } + + package_path = std::wstring(++package_path_size, L'\0'); + if (const bool got_package_path = ERROR_SUCCESS == MsiGetProductInfoW(GUID_product_string, INSTALLPROPERTY_LOCALPACKAGE, package_path.data(), &package_path_size); !got_package_path) + { + package_path = {}; + return package_path; + } + + package_path.resize(size(package_path) - 1); // trim additional \0 which we got from MsiGetProductInfoW + + return package_path; + } + + bool offer_msi_uninstallation(const notifications::strings& strings) + { + const auto selection = SHMessageBoxCheckW(nullptr, + strings.OFFER_UNINSTALL_MSI.c_str(), + strings.OFFER_UNINSTALL_MSI_TITLE.c_str(), + MB_ICONQUESTION | MB_YESNO, + IDNO, + DONT_SHOW_AGAIN_RECORD_REGISTRY_PATH); + return selection == IDYES; + } + + bool uninstall_msi_version(const std::wstring& package_path, const notifications::strings& strings) + { + const auto uninstall_result = MsiInstallProductW(package_path.c_str(), L"REMOVE=ALL"); + if (ERROR_SUCCESS == uninstall_result) + { + return true; + } + else if (auto system_message = get_last_error_message(uninstall_result); system_message.has_value()) + { + try + { + ::notifications::show_toast(*system_message, TOAST_TITLE); + } + catch (...) + { + updating::notifications::show_uninstallation_error(strings); + } + } + return false; + } + + std::optional get_msi_package_installed_path() + { + constexpr size_t guid_length = 39; + wchar_t product_ID[guid_length]; + if (const bool found = ERROR_SUCCESS == MsiEnumRelatedProductsW(POWER_TOYS_UPGRADE_CODE, 0, 0, product_ID); !found) + { + return std::nullopt; + } + + if (const bool installed = INSTALLSTATE_DEFAULT == MsiQueryProductStateW(product_ID); !installed) + { + return std::nullopt; + } + + DWORD buf_size = MAX_PATH; + wchar_t buf[MAX_PATH]; + if (ERROR_SUCCESS == MsiGetProductInfoW(product_ID, INSTALLPROPERTY_INSTALLLOCATION, buf, &buf_size) && buf_size) + { + return buf; + } + + DWORD package_path_size = 0; + + if (ERROR_SUCCESS != MsiGetProductInfoW(product_ID, INSTALLPROPERTY_LOCALPACKAGE, nullptr, &package_path_size)) + { + return std::nullopt; + } + std::wstring package_path(++package_path_size, L'\0'); + + if (ERROR_SUCCESS != MsiGetProductInfoW(product_ID, INSTALLPROPERTY_LOCALPACKAGE, package_path.data(), &package_path_size)) + { + return std::nullopt; + } + package_path.resize(size(package_path) - 1); // trim additional \0 which we got from MsiGetProductInfoW + + wchar_t path[MAX_PATH]; + DWORD path_size = MAX_PATH; + MsiGetComponentPathW(product_ID, POWERTOYS_EXE_COMPONENT, path, &path_size); + if (!path_size) + { + return std::nullopt; + } + PathCchRemoveFileSpec(path, path_size); + return path; + } + + std::optional get_installed_powertoys_version() + { + auto installed_path = get_msi_package_installed_path(); + if (!installed_path) + { + return std::nullopt; + } + *installed_path += L"\\PowerToys.exe"; + + // Get the version information for the file requested + const DWORD fvSize = GetFileVersionInfoSizeW(installed_path->c_str(), nullptr); + if (!fvSize) + { + return std::nullopt; + } + + auto pbVersionInfo = std::make_unique(fvSize); + + if (!GetFileVersionInfoW(installed_path->c_str(), 0, fvSize, pbVersionInfo.get())) + { + return std::nullopt; + } + + VS_FIXEDFILEINFO* fileInfo = nullptr; + UINT fileInfoLen = 0; + if (!VerQueryValueW(pbVersionInfo.get(), L"\\", reinterpret_cast(&fileInfo), &fileInfoLen)) + { + return std::nullopt; + } + return VersionHelper{ (fileInfo->dwFileVersionMS >> 16) & 0xffff, + (fileInfo->dwFileVersionMS >> 0) & 0xffff, + (fileInfo->dwFileVersionLS >> 16) & 0xffff }; + } + + std::future uninstall_previous_msix_version_async() + { + winrt::Windows::Management::Deployment::PackageManager package_manager; + + try + { + auto packages = package_manager.FindPackagesForUser({}, MSIX_PACKAGE_NAME, MSIX_PACKAGE_PUBLISHER); + VersionHelper current_version(VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION); + + for (auto package : packages) + { + VersionHelper msix_version(package.Id().Version().Major, package.Id().Version().Minor, package.Id().Version().Revision); + + if (msix_version < current_version) + { + co_await package_manager.RemovePackageAsync(package.Id().FullName()); + co_return true; + } + } + } + catch (...) + { + } + co_return false; + } + +} \ No newline at end of file diff --git a/src/common/updating/installer.h b/src/common/updating/installer.h new file mode 100644 index 0000000000..62e5da6fab --- /dev/null +++ b/src/common/updating/installer.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include +#include + +#include "notifications.h" +#include "../VersionHelper.h" + +namespace updating +{ + std::wstring get_msi_package_path(); + bool uninstall_msi_version(const std::wstring& package_path, const notifications::strings&); + bool offer_msi_uninstallation(const notifications::strings&); + std::optional get_msi_package_installed_path(); + + std::optional get_installed_powertoys_version(); + std::future uninstall_previous_msix_version_async(); +} \ No newline at end of file diff --git a/src/common/updating/notifications.h b/src/common/updating/notifications.h index eade6076a7..6b6f3ce445 100644 --- a/src/common/updating/notifications.h +++ b/src/common/updating/notifications.h @@ -1,5 +1,7 @@ #pragma once +#include + namespace updating { struct new_version_download_info; diff --git a/src/common/updating/updating.cpp b/src/common/updating/updating.cpp index 0160d4b0fc..7f1b53907b 100644 --- a/src/common/updating/updating.cpp +++ b/src/common/updating/updating.cpp @@ -6,99 +6,28 @@ #include "notifications.h" #include "updating.h" -#include #include #include #include #include #include -#include +#include +#include +#include #include #include "VersionHelper.h" -#include namespace // Strings in this namespace should not be localized { - const wchar_t POWER_TOYS_UPGRADE_CODE[] = L"{42B84BF7-5FBF-473B-9C8B-049DC16F7708}"; - const wchar_t POWERTOYS_EXE_COMPONENT[] = L"{A2C66D91-3485-4D00-B04D-91844E6B345B}"; - const wchar_t DONT_SHOW_AGAIN_RECORD_REGISTRY_PATH[] = L"delete_previous_powertoys_confirm"; const wchar_t LATEST_RELEASE_ENDPOINT[] = L"https://api.github.com/repos/microsoft/PowerToys/releases/latest"; - const wchar_t MSIX_PACKAGE_NAME[] = L"Microsoft.PowerToys"; - const wchar_t MSIX_PACKAGE_PUBLISHER[] = L"CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"; const size_t MAX_DOWNLOAD_ATTEMPTS = 3; - const wchar_t TOAST_TITLE[] = L"PowerToys"; } namespace updating { - std::wstring get_msi_package_path() - { - std::wstring package_path; - wchar_t GUID_product_string[39]; - if (const bool found = ERROR_SUCCESS == MsiEnumRelatedProductsW(POWER_TOYS_UPGRADE_CODE, 0, 0, GUID_product_string); !found) - { - return package_path; - } - - if (const bool installed = INSTALLSTATE_DEFAULT == MsiQueryProductStateW(GUID_product_string); !installed) - { - return package_path; - } - - DWORD package_path_size = 0; - - if (const bool has_package_path = ERROR_SUCCESS == MsiGetProductInfoW(GUID_product_string, INSTALLPROPERTY_LOCALPACKAGE, nullptr, &package_path_size); !has_package_path) - { - return package_path; - } - - package_path = std::wstring(++package_path_size, L'\0'); - if (const bool got_package_path = ERROR_SUCCESS == MsiGetProductInfoW(GUID_product_string, INSTALLPROPERTY_LOCALPACKAGE, package_path.data(), &package_path_size); !got_package_path) - { - package_path = {}; - return package_path; - } - - package_path.resize(size(package_path) - 1); // trim additional \0 which we got from MsiGetProductInfoW - - return package_path; - } - - bool offer_msi_uninstallation(const notifications::strings& strings) - { - const auto selection = SHMessageBoxCheckW(nullptr, - strings.OFFER_UNINSTALL_MSI.c_str(), - strings.OFFER_UNINSTALL_MSI_TITLE.c_str(), - MB_ICONQUESTION | MB_YESNO, - IDNO, - DONT_SHOW_AGAIN_RECORD_REGISTRY_PATH); - return selection == IDYES; - } - - bool uninstall_msi_version(const std::wstring& package_path, const notifications::strings& strings) - { - const auto uninstall_result = MsiInstallProductW(package_path.c_str(), L"REMOVE=ALL"); - if (ERROR_SUCCESS == uninstall_result) - { - return true; - } - else if (auto system_message = get_last_error_message(uninstall_result); system_message.has_value()) - { - try - { - ::notifications::show_toast(*system_message, TOAST_TITLE); - } - catch (...) - { - updating::notifications::show_uninstallation_error(strings); - } - } - return false; - } - std::future> get_new_github_version_info_async() { // If the current version starts with 0.0.*, it means we're on a local build from a farm and shouldn't check for updates. @@ -153,32 +82,6 @@ namespace updating } } - std::future uninstall_previous_msix_version_async() - { - winrt::Windows::Management::Deployment::PackageManager package_manager; - - try - { - auto packages = package_manager.FindPackagesForUser({}, MSIX_PACKAGE_NAME, MSIX_PACKAGE_PUBLISHER); - VersionHelper current_version(VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION); - - for (auto package : packages) - { - VersionHelper msix_version(package.Id().Version().Major, package.Id().Version().Minor, package.Id().Version().Revision); - - if (msix_version < current_version) - { - co_await package_manager.RemovePackageAsync(package.Id().FullName()); - co_return true; - } - } - } - catch (...) - { - } - co_return false; - } - bool could_be_costly_connection() { using namespace winrt::Windows::Networking::Connectivity; @@ -282,84 +185,4 @@ namespace updating co_return new_version->installer_filename; } - - std::optional get_msi_package_installed_path() - { - constexpr size_t guid_length = 39; - wchar_t product_ID[guid_length]; - if (const bool found = ERROR_SUCCESS == MsiEnumRelatedProductsW(POWER_TOYS_UPGRADE_CODE, 0, 0, product_ID); !found) - { - return std::nullopt; - } - - if (const bool installed = INSTALLSTATE_DEFAULT == MsiQueryProductStateW(product_ID); !installed) - { - return std::nullopt; - } - - DWORD buf_size = MAX_PATH; - wchar_t buf[MAX_PATH]; - if (ERROR_SUCCESS == MsiGetProductInfoW(product_ID, INSTALLPROPERTY_INSTALLLOCATION, buf, &buf_size) && buf_size) - { - return buf; - } - - DWORD package_path_size = 0; - - if (ERROR_SUCCESS != MsiGetProductInfoW(product_ID, INSTALLPROPERTY_LOCALPACKAGE, nullptr, &package_path_size)) - { - return std::nullopt; - } - std::wstring package_path(++package_path_size, L'\0'); - - if (ERROR_SUCCESS != MsiGetProductInfoW(product_ID, INSTALLPROPERTY_LOCALPACKAGE, package_path.data(), &package_path_size)) - { - return std::nullopt; - } - package_path.resize(size(package_path) - 1); // trim additional \0 which we got from MsiGetProductInfoW - - wchar_t path[MAX_PATH]; - DWORD path_size = MAX_PATH; - MsiGetComponentPathW(product_ID, POWERTOYS_EXE_COMPONENT, path, &path_size); - if (!path_size) - { - return std::nullopt; - } - PathCchRemoveFileSpec(path, path_size); - return path; - } - - std::optional get_installed_powertoys_version() - { - auto installed_path = get_msi_package_installed_path(); - if (!installed_path) - { - return std::nullopt; - } - *installed_path += L"\\PowerToys.exe"; - - // Get the version information for the file requested - const DWORD fvSize = GetFileVersionInfoSizeW(installed_path->c_str(), nullptr); - if (!fvSize) - { - return std::nullopt; - } - - auto pbVersionInfo = std::make_unique(fvSize); - - if (!GetFileVersionInfoW(installed_path->c_str(), 0, fvSize, pbVersionInfo.get())) - { - return std::nullopt; - } - - VS_FIXEDFILEINFO* fileInfo = nullptr; - UINT fileInfoLen = 0; - if (!VerQueryValueW(pbVersionInfo.get(), L"\\", reinterpret_cast(&fileInfo), &fileInfoLen)) - { - return std::nullopt; - } - return VersionHelper{ (fileInfo->dwFileVersionMS >> 16) & 0xffff, - (fileInfo->dwFileVersionMS >> 0) & 0xffff, - (fileInfo->dwFileVersionLS >> 16) & 0xffff }; - } } \ No newline at end of file diff --git a/src/common/updating/updating.h b/src/common/updating/updating.h index ea993f6d60..c5cace0587 100644 --- a/src/common/updating/updating.h +++ b/src/common/updating/updating.h @@ -11,14 +11,6 @@ namespace updating { - std::wstring get_msi_package_path(); - bool uninstall_msi_version(const std::wstring& package_path, const notifications::strings&); - bool offer_msi_uninstallation(const notifications::strings&); - std::optional get_msi_package_installed_path(); - std::optional get_installed_powertoys_version(); - - std::future uninstall_previous_msix_version_async(); - struct new_version_download_info { winrt::Windows::Foundation::Uri release_page_uri; diff --git a/src/common/updating/updating.vcxproj b/src/common/updating/updating.vcxproj index 48d6b3f01a..0a292bd97a 100644 --- a/src/common/updating/updating.vcxproj +++ b/src/common/updating/updating.vcxproj @@ -175,6 +175,7 @@ + @@ -182,6 +183,7 @@ + diff --git a/src/common/updating/updating.vcxproj.filters b/src/common/updating/updating.vcxproj.filters index bc72ef6795..9cbef007af 100644 --- a/src/common/updating/updating.vcxproj.filters +++ b/src/common/updating/updating.vcxproj.filters @@ -30,6 +30,9 @@ Header Files + + Header Files + @@ -47,6 +50,9 @@ Source Files + + Source Files + diff --git a/src/runner/main.cpp b/src/runner/main.cpp index aef500d230..a664c5246a 100644 --- a/src/runner/main.cpp +++ b/src/runner/main.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -33,7 +34,7 @@ #if _DEBUG && _WIN64 #include "unhandled_exception_handler.h" #endif -#include +#include #include extern "C" IMAGE_DOS_HEADER __ImageBase; diff --git a/src/runner/update_utils.cpp b/src/runner/update_utils.cpp index 4728fa21d0..6e5f97f338 100644 --- a/src/runner/update_utils.cpp +++ b/src/runner/update_utils.cpp @@ -8,6 +8,7 @@ #include "update_utils.h" #include +#include #include #include