diff --git a/Telegram/SourceFiles/platform/win/notifications_manager_win.cpp b/Telegram/SourceFiles/platform/win/notifications_manager_win.cpp index 0f2c05d74..8782aeb11 100644 --- a/Telegram/SourceFiles/platform/win/notifications_manager_win.cpp +++ b/Telegram/SourceFiles/platform/win/notifications_manager_win.cpp @@ -123,8 +123,16 @@ bool init() { return false; } - auto appUserModelId = AppUserModelId::getId(); - if (!SUCCEEDED(SetCurrentProcessExplicitAppUserModelID(appUserModelId))) { + PWSTR appUserModelId = {}; + if (!SUCCEEDED(GetCurrentProcessExplicitAppUserModelID(&appUserModelId))) { + return false; + } + + const auto appUserModelIdGuard = gsl::finally([&] { + CoTaskMemFree(appUserModelId); + }); + + if (AppUserModelId::getId() != appUserModelId) { return false; } return true; @@ -300,7 +308,7 @@ void QueryFocusAssist() { } return; } - const auto appUserModelId = std::wstring(AppUserModelId::getId()); + const auto appUserModelId = AppUserModelId::getId(); auto blocked = true; const auto guard = gsl::finally([&] { if (FocusAssistBlocks != blocked) { diff --git a/Telegram/SourceFiles/platform/win/specific_win.cpp b/Telegram/SourceFiles/platform/win/specific_win.cpp index 0da6adae9..056741ffb 100644 --- a/Telegram/SourceFiles/platform/win/specific_win.cpp +++ b/Telegram/SourceFiles/platform/win/specific_win.cpp @@ -209,7 +209,7 @@ bool ManageAppLink( if (const auto propertyStore = shellLink.try_as()) { PROPVARIANT appIdPropVar; - hr = InitPropVariantFromString(AppUserModelId::getId(), &appIdPropVar); + hr = InitPropVariantFromString(AppUserModelId::getId().c_str(), &appIdPropVar); if (SUCCEEDED(hr)) { hr = propertyStore->SetValue(AppUserModelId::getKey(), appIdPropVar); PropVariantClear(&appIdPropVar); @@ -370,6 +370,10 @@ void start() { void start() { // https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setlocale-wsetlocale#utf-8-support setlocale(LC_ALL, ".UTF8"); + + const auto appUserModelId = AppUserModelId::getId(); + SetCurrentProcessExplicitAppUserModelID(appUserModelId.c_str()); + LOG(("AppUserModelID: %1").arg(appUserModelId)); } void finish() { @@ -638,7 +642,7 @@ bool OpenSystemSettings(SystemSettingsType type) { } void NewVersionLaunched(int oldVersion) { - if (oldVersion < 8051) { + if (oldVersion <= 4009009) { AppUserModelId::checkPinned(); } if (oldVersion > 0 && oldVersion < 2008012) { diff --git a/Telegram/SourceFiles/platform/win/windows_app_user_model_id.cpp b/Telegram/SourceFiles/platform/win/windows_app_user_model_id.cpp index 1f5b8ad8d..e6a6c9204 100644 --- a/Telegram/SourceFiles/platform/win/windows_app_user_model_id.cpp +++ b/Telegram/SourceFiles/platform/win/windows_app_user_model_id.cpp @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "platform/win/windows_dlls.h" #include "platform/win/windows_toast_activator.h" #include "base/platform/win/base_windows_wrl.h" +#include "core/launcher.h" #include #include @@ -137,7 +138,7 @@ void checkPinned() { WCHAR already[MAX_PATH]; hr = PropVariantToString(appIdPropVar, already, MAX_PATH); if (SUCCEEDED(hr)) { - if (std::wstring(getId()) == already) { + if (getId() == already) { LOG(("Already!")); PropVariantClear(&appIdPropVar); return; @@ -149,7 +150,7 @@ void checkPinned() { } PropVariantClear(&appIdPropVar); - hr = InitPropVariantFromString(getId(), &appIdPropVar); + hr = InitPropVariantFromString(getId().c_str(), &appIdPropVar); if (!SUCCEEDED(hr)) return; hr = propertyStore->SetValue(getKey(), appIdPropVar); @@ -247,6 +248,20 @@ bool validateShortcutAt(const QString &path) { hr = persistFile->Load(p.c_str(), STGM_READWRITE); if (!SUCCEEDED(hr)) return false; + WCHAR szGotPath[MAX_PATH]; + WIN32_FIND_DATA wfd; + hr = shellLink->GetPath( + szGotPath, + MAX_PATH, + (WIN32_FIND_DATA*)&wfd, + SLGP_SHORTPATH); + if (!SUCCEEDED(hr)) return false; + + const auto full = cExeDir() + cExeName(); + if (QDir::toNativeSeparators(full).toStdWString() != szGotPath) { + return false; + } + ComPtr propertyStore; hr = shellLink.As(&propertyStore); if (!SUCCEEDED(hr)) return false; @@ -263,7 +278,7 @@ bool validateShortcutAt(const QString &path) { WCHAR already[MAX_PATH]; hr = PropVariantToString(appIdPropVar, already, MAX_PATH); - const auto good1 = SUCCEEDED(hr) && (std::wstring(getId()) == already); + const auto good1 = SUCCEEDED(hr) && (getId() == already); const auto bad1 = !good1 && (appIdPropVar.vt != VT_EMPTY); PropVariantClear(&appIdPropVar); @@ -279,7 +294,7 @@ bool validateShortcutAt(const QString &path) { return false; } - hr = InitPropVariantFromString(getId(), &appIdPropVar); + hr = InitPropVariantFromString(getId().c_str(), &appIdPropVar); if (!SUCCEEDED(hr)) return false; hr = propertyStore->SetValue(getKey(), appIdPropVar); @@ -309,6 +324,20 @@ bool validateShortcutAt(const QString &path) { return true; } +bool checkInstalled(QString path = {}) { + if (path.isEmpty()) { + path = systemShortcutPath(); + if (path.isEmpty()) { + return false; + } + } + + const auto installed = u"Telegram Desktop/Telegram.lnk"_q; + const auto old = u"Telegram Win (Unofficial)/Telegram.lnk"_q; + return validateShortcutAt(path + installed) + || validateShortcutAt(path + old); +} + bool validateShortcut() { QString path = systemShortcutPath(); if (path.isEmpty() || cExeName().isEmpty()) { @@ -321,10 +350,7 @@ bool validateShortcut() { return true; } } else { - const auto installed = u"Telegram Desktop/Telegram.lnk"_q; - const auto old = u"Telegram Win (Unofficial)/Telegram.lnk"_q; - if (validateShortcutAt(path + installed) - || validateShortcutAt(path + old)) { + if (checkInstalled(path)) { return true; } @@ -360,7 +386,7 @@ bool validateShortcut() { if (!SUCCEEDED(hr)) return false; PROPVARIANT appIdPropVar; - hr = InitPropVariantFromString(getId(), &appIdPropVar); + hr = InitPropVariantFromString(getId().c_str(), &appIdPropVar); if (!SUCCEEDED(hr)) return false; hr = propertyStore->SetValue(getKey(), appIdPropVar); @@ -407,8 +433,42 @@ bool validateShortcut() { return true; } -const WCHAR *getId() { - return cAlphaVersion() ? AppUserModelIdAlpha : AppUserModelIdRelease; +const std::wstring &getId() { + static const std::wstring BaseId(cAlphaVersion() + ? AppUserModelIdAlpha + : AppUserModelIdRelease); + static auto CheckingInstalled = false; + if (CheckingInstalled) { + return BaseId; + } + static const auto Installed = [] { + CheckingInstalled = true; + const auto guard = gsl::finally([] { + CheckingInstalled = false; + }); + if (!SUCCEEDED(CoInitialize(nullptr))) { + return false; + } + const auto coGuard = gsl::finally([] { + CoUninitialize(); + }); + return checkInstalled(); + }(); + if (Installed) { + return BaseId; + } + static const auto PortableId = [] { + std::string h(32, 0); + if (Core::Launcher::Instance().customWorkingDir()) { + const auto d = QFile::encodeName(QDir(cWorkingDir()).absolutePath()); + hashMd5Hex(d.constData(), d.size(), h.data()); + } else { + const auto exePath = QFile::encodeName(cExeDir() + cExeName()); + hashMd5Hex(exePath.constData(), exePath.size(), h.data()); + } + return BaseId + L'.' + std::wstring(h.begin(), h.end()); + }(); + return PortableId; } const PROPERTYKEY &getKey() { diff --git a/Telegram/SourceFiles/platform/win/windows_app_user_model_id.h b/Telegram/SourceFiles/platform/win/windows_app_user_model_id.h index 464e44041..5be435cb9 100644 --- a/Telegram/SourceFiles/platform/win/windows_app_user_model_id.h +++ b/Telegram/SourceFiles/platform/win/windows_app_user_model_id.h @@ -15,7 +15,7 @@ namespace AppUserModelId { void cleanupShortcut(); void checkPinned(); -const WCHAR *getId(); +const std::wstring &getId(); bool validateShortcut(); const PROPERTYKEY &getKey();