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;