diff --git a/src/Magpie.App/HomePage.xaml b/src/Magpie.App/HomePage.xaml index ce843826..7f49c0b0 100644 --- a/src/Magpie.App/HomePage.xaml +++ b/src/Magpie.App/HomePage.xaml @@ -138,7 +138,8 @@ - + diff --git a/src/Magpie.App/HomeViewModel.cpp b/src/Magpie.App/HomeViewModel.cpp index dc058a0b..06983642 100644 --- a/src/Magpie.App/HomeViewModel.cpp +++ b/src/Magpie.App/HomeViewModel.cpp @@ -9,6 +9,7 @@ #include "StrUtils.h" #include "UpdateService.h" #include "CommonSharedConstants.h" +#include "Logger.h" namespace winrt::Magpie::App::implementation { @@ -185,6 +186,57 @@ void HomeViewModel::RemindMeLater() { ShowUpdateCard(false); } +bool HomeViewModel::IsTouchSupportEnabled() const noexcept { + wil::unique_cotaskmem_string system32Dir; + HRESULT hr = SHGetKnownFolderPath( + FOLDERID_System, KF_FLAG_DEFAULT, NULL, system32Dir.put()); + if (FAILED(hr)) { + Logger::Get().ComError("SHGetKnownFolderPath 失败", hr); + return false; + } + + std::wstring path = StrUtils::Concat(system32Dir.get(), + L"\\Magpie\\", CommonSharedConstants::TOUCH_HELPER_EXE_NAME); + if (!Win32Utils::FileExists(path.c_str())) { + return false; + } + + path += L".ver"; + + std::vector version; + if (!Win32Utils::ReadFile(path.c_str(), version) || version.size() != 4) { + Logger::Get().Error("读取版本号失败"); + return false; + } + + return *(uint32_t*)version.data() == CommonSharedConstants::TOUCH_HELPER_VERSION; +} + +void HomeViewModel::IsTouchSupportEnabled(bool value) { + if (IsTouchSupportEnabled() == value) { + return; + } + + SHELLEXECUTEINFO execInfo{ + .cbSize = sizeof(execInfo), + .fMask = SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS, + .lpVerb = L"runas", + .lpFile = Win32Utils::GetExePath().c_str(), + .lpParameters = value ? L" -r" : L" -ur" + }; + + if (ShellExecuteEx(&execInfo)) { + wil::unique_process_handle hProcess(execInfo.hProcess); + if (hProcess) { + wil::handle_wait(hProcess.get()); + } + } else { + Logger::Get().Win32Error("ShellExecuteEx 失败"); + } + + RaisePropertyChanged(L"IsTouchSupportEnabled"); +} + bool HomeViewModel::IsAllowScalingMaximized() const noexcept { return AppSettings::Get().IsAllowScalingMaximized(); } diff --git a/src/Magpie.App/HomeViewModel.h b/src/Magpie.App/HomeViewModel.h index 08759706..5ca8008d 100644 --- a/src/Magpie.App/HomeViewModel.h +++ b/src/Magpie.App/HomeViewModel.h @@ -50,6 +50,9 @@ struct HomeViewModel : HomeViewModelT, wil::notify_property_chang void RemindMeLater(); + bool IsTouchSupportEnabled() const noexcept; + void IsTouchSupportEnabled(bool value); + bool IsAllowScalingMaximized() const noexcept; void IsAllowScalingMaximized(bool value); diff --git a/src/Magpie.App/HomeViewModel.idl b/src/Magpie.App/HomeViewModel.idl index 4bbb235a..7e9fc33e 100644 --- a/src/Magpie.App/HomeViewModel.idl +++ b/src/Magpie.App/HomeViewModel.idl @@ -25,6 +25,7 @@ namespace Magpie.App { void ActivateRestore(); void ClearRestore(); + Boolean IsTouchSupportEnabled; Boolean IsAllowScalingMaximized; Boolean IsInlineParams; Boolean IsSimulateExclusiveFullscreen; diff --git a/src/Magpie/UIAccessHelper.cpp b/src/Magpie/UIAccessHelper.cpp index 50a6a8a4..323b8f95 100644 --- a/src/Magpie/UIAccessHelper.cpp +++ b/src/Magpie/UIAccessHelper.cpp @@ -7,6 +7,12 @@ namespace Magpie { +// 证书的 SHA1 哈希值,也是“指纹” +static constexpr std::array CERT_FINGERPRINT{ + 0xad, 0x5a, 0x50, 0x3d, 0xda, 0xec, 0x08, 0x5b, 0xf4, 0x48, + 0xd8, 0x63, 0xcf, 0x90, 0x3a, 0xb4, 0x72, 0x0e, 0x0b, 0x12 +}; + static std::vector GetCertificateDataFromPE(const wchar_t* fileName) noexcept { wil::unique_hfile hFile(CreateFile( fileName, FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)); @@ -40,12 +46,6 @@ using unique_cert_context = wil::unique_any; static bool InstallCertificateFromPE(const wchar_t* exePath) noexcept { - // 证书的 SHA1 哈希值,也是“指纹” - static constexpr std::array CERT_FINGERPRINT{ - 0xad, 0x5a, 0x50, 0x3d, 0xda, 0xec, 0x08, 0x5b, 0xf4, 0x48, - 0xd8, 0x63, 0xcf, 0x90, 0x3a, 0xb4, 0x72, 0x0e, 0x0b, 0x12 - }; - // 打开本地计算机的根证书存储区 unique_cert_store hRootCertStore(CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_OPEN_EXISTING_FLAG, L"ROOT")); @@ -182,4 +182,46 @@ bool UIAccessHelper::MakeExeUIAccess(const wchar_t* exePath, uint32_t version) n return true; } +bool UIAccessHelper::ClearUIAccess() noexcept { + if (!Win32Utils::IsProcessElevated()) { + Logger::Get().Error("没有管理员权限"); + return false; + } + + // 删除 system32\Magpie 文件夹 + + wil::unique_cotaskmem_string system32Dir; + HRESULT hr = SHGetKnownFolderPath( + FOLDERID_System, KF_FLAG_DEFAULT, NULL, system32Dir.put()); + if (FAILED(hr)) { + Logger::Get().ComError("SHGetKnownFolderPath 失败", hr); + return false; + } + + wil::RemoveDirectoryRecursiveNoThrow( + StrUtils::Concat(system32Dir.get(), L"\\Magpie").c_str()); + + // 删除证书 + + // 打开本地计算机的根证书存储区 + unique_cert_store hRootCertStore(CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, + CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_OPEN_EXISTING_FLAG, L"ROOT")); + if (!hRootCertStore) { + Logger::Get().Win32Error("CertOpenStore 失败"); + return false; + } + + const CRYPT_DATA_BLOB blob{ + .cbData = (DWORD)CERT_FINGERPRINT.size(), + .pbData = (BYTE*)CERT_FINGERPRINT.data() + }; + unique_cert_context context(CertFindCertificateInStore( + hRootCertStore.get(), PKCS_7_ASN_ENCODING, 0, CERT_FIND_SHA1_HASH, &blob, nullptr)); + if (context) { + CertDeleteCertificateFromStore(context.get()); + } + + return true; +} + } diff --git a/src/Magpie/UIAccessHelper.h b/src/Magpie/UIAccessHelper.h index 8429fcc8..8b317e1f 100644 --- a/src/Magpie/UIAccessHelper.h +++ b/src/Magpie/UIAccessHelper.h @@ -4,6 +4,7 @@ namespace Magpie { struct UIAccessHelper { static bool MakeExeUIAccess(const wchar_t* exePath, uint32_t version) noexcept; + static bool ClearUIAccess() noexcept; }; } diff --git a/src/Magpie/main.cpp b/src/Magpie/main.cpp index 9e21eccd..41bbe171 100644 --- a/src/Magpie/main.cpp +++ b/src/Magpie/main.cpp @@ -74,6 +74,9 @@ int APIENTRY wWinMain( CommonSharedConstants::TOUCH_HELPER_EXE_NAME, CommonSharedConstants::TOUCH_HELPER_VERSION ) ? 0 : 1; + } else if (lpCmdLine == L"-ur"sv) { + // TouchHelper 正在运行? + return Magpie::UIAccessHelper::ClearUIAccess() ? 0 : 1; } auto& app = Magpie::XamlApp::Get(); diff --git a/src/Shared/Win32Utils.cpp b/src/Shared/Win32Utils.cpp index 3685e0e5..33fdb396 100644 --- a/src/Shared/Win32Utils.cpp +++ b/src/Shared/Win32Utils.cpp @@ -151,7 +151,7 @@ bool Win32Utils::GetWindowFrameRect(HWND hWnd, RECT& rect) noexcept { return true; } -bool Win32Utils::ReadFile(const wchar_t* fileName, std::vector& result) noexcept { +bool Win32Utils::ReadFile(const wchar_t* fileName, std::vector& result) noexcept { Logger::Get().Info(StrUtils::Concat("读取文件: ", StrUtils::UTF16ToUTF8(fileName))); CREATEFILE2_EXTENDED_PARAMETERS extendedParams{ diff --git a/src/Shared/Win32Utils.h b/src/Shared/Win32Utils.h index 4ebdb230..5d03c3dd 100644 --- a/src/Shared/Win32Utils.h +++ b/src/Shared/Win32Utils.h @@ -22,7 +22,7 @@ struct Win32Utils { static bool GetWindowFrameRect(HWND hWnd, RECT& rect) noexcept; - static bool ReadFile(const wchar_t* fileName, std::vector& result) noexcept; + static bool ReadFile(const wchar_t* fileName, std::vector& result) noexcept; static bool ReadTextFile(const wchar_t* fileName, std::string& result) noexcept;