]> repos.lx-s.de Git - winmute.git/commitdiff
Retry WTSRegisterSessionNotification for about half a minute.. Disable lock-on-mute...
authorlx-s <lx-s@users.noreply.github.com>
Tue, 18 Aug 2026 06:06:53 +0000 (08:06 +0200)
committerlx-s <lx-s@users.noreply.github.com>
Tue, 18 Aug 2026 06:06:53 +0000 (08:06 +0200)
Translations/lang-de.json
Translations/lang-en.json
WinMute/WinMute.cpp
WinMute/WinMute.h

index b6bbc6ae703bb13c45ca80eb66627c1ea1e2abbf..b57257db2dc684f59d367a1cf706adb546757e50 100644 (file)
@@ -16,6 +16,8 @@
   "general.error.audio-service-shutdown.text": "WinMute kann diese Situation nicht Beheben. Bitte starten Sie das Programm neu.",
   "popup.remote-session-detected.title": "Remote Session festgestellt",
   "popup.remote-session-detected.text": "Alle Audiogeräte wurden stumm geschaltet",
+  "popup.session-notification-failed.title": "Stummschalten bei Arbeitsplatz-Sperre deaktiviert",
+  "popup.session-notification-failed.text": "WinMute konnte sich nicht für Sperr-Benachrichtigungen registrieren.\nBitte prüfen Sie das Protokoll für weitere Details.",
   "popup.bluetooth-muting-disabled.title": "Bluetooth-Stummschalten deaktiviert",
   "popup.bluetooth-muting-disabled.text": "Bluetooth ist nicht verfügbar oder deaktiviert.\nDas Bluetooth-abhängige Stummschalten wurde deaktiviert.",
   "popup.wlan-muting-disabled.title": "WLAN-Stummschalten deaktiviert",
index 1883abaf466bf298416169fd5eadf21a75225c03..4299fc0f3a5865c35257670a8bc8d83a5b4da87e 100644 (file)
@@ -22,6 +22,8 @@
   "pupup.error.update-check-failed.text": "Unable to check for a new version.\nPlease check/enable logging for further details.",
   "popup.remote-session-detected.title": "Remote Session detected",
   "popup.remote-session-detected.text": "All audio devices have been muted",
+  "popup.session-notification-failed.title": "Muting on workstation lock disabled",
+  "popup.session-notification-failed.text": "WinMute could not register for session notifications.\nPlease check the log for further details.",
   "popup.bluetooth-muting-disabled.title": "Bluetooth muting disabled",
   "popup.bluetooth-muting-disabled.text": "Bluetooth is not available or disabled.\nBluetooth muting will be disabled on this computer.",
   "popup.wlan-muting-disabled.title": "WLAN muting disabled",
index 494f10a98474967428f72e62ae273f177a61a0ca..b2b190e9c85f376a2a03a0297ce84e0bcb5dc1cb 100644 (file)
@@ -46,6 +46,14 @@ static const wchar_t* TERMINAL_SERVER_KEY =
     L"SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\";
 static const wchar_t* GLASS_SESSION_ID = L"GlassSessionId";
 
+static constexpr UINT_PTR WTS_RETRY_TIMER_ID = 190503;
+// When WinMute is started from autostart, the services Remote Desktop
+// Services depends on can still be coming up, which makes
+// WTSRegisterSessionNotification fail with RPC_S_INVALID_BINDING. Retry for
+// roughly half a minute before giving up.
+static constexpr UINT WTS_RETRY_INTERVAL_MS = 1000;
+static constexpr int WTS_RETRY_MAX_ATTEMPTS = 30;
+
 static LRESULT CALLBACK WinMuteWndProc(HWND hWnd, UINT msg, WPARAM wParam,
                                        LPARAM lParam)
 {
@@ -64,6 +72,15 @@ static LRESULT CALLBACK WinMuteWndProc(HWND hWnd, UINT msg, WPARAM wParam,
                 : DefWindowProcW(hWnd, msg, wParam, lParam);
 }
 
+static void CALLBACK WtsRetryTimerProc(HWND hWnd, UINT, UINT_PTR, DWORD)
+{
+    auto wm =
+        reinterpret_cast<WinMute*>(GetWindowLongPtrW(hWnd, GWLP_USERDATA));
+    if (wm != nullptr) {
+        wm->RetrySessionNotification();
+    }
+}
+
 static bool IsCurrentSessionRemoteable() noexcept
 {
     bool isRemoteable = false;
@@ -202,6 +219,72 @@ bool WinMute::InitTrayMenu()
 }
 #undef CHECK_MENU_ITEM
 
+bool WinMute::TryRegisterSessionNotification()
+{
+    if (wtsSessionNotificationRegistered_) {
+        return true;
+    }
+    if (!WTSRegisterSessionNotification(hWnd_, NOTIFY_FOR_THIS_SESSION)) {
+        WMLog::GetInstance().LogWinError(L"WTSRegisterSessionNotification",
+                                         GetLastError());
+        return false;
+    }
+    wtsSessionNotificationRegistered_ = true;
+    return true;
+}
+
+void WinMute::StartSessionNotificationRetry()
+{
+    WMLog& log = WMLog::GetInstance();
+
+    if (wtsRetryTimerId_ != 0) {
+        return;
+    }
+    if (SetTimer(hWnd_, WTS_RETRY_TIMER_ID, WTS_RETRY_INTERVAL_MS,
+                 WtsRetryTimerProc) == 0)
+    {
+        log.LogWinError(L"SetTimer (session notification retry)",
+                        GetLastError());
+        log.LogError(L"Muting on workstation lock is not available");
+        return;
+    }
+    wtsRetryTimerId_ = WTS_RETRY_TIMER_ID;
+    wtsRetryAttempts_ = 0;
+    log.LogInfo(L"Retrying to register for session notifications every {} ms",
+                WTS_RETRY_INTERVAL_MS);
+}
+
+void WinMute::StopSessionNotificationRetry() noexcept
+{
+    if (wtsRetryTimerId_ != 0) {
+        KillTimer(hWnd_, wtsRetryTimerId_);
+        wtsRetryTimerId_ = 0;
+    }
+}
+
+void WinMute::RetrySessionNotification()
+{
+    WMLog& log = WMLog::GetInstance();
+
+    ++wtsRetryAttempts_;
+    if (TryRegisterSessionNotification()) {
+        StopSessionNotificationRetry();
+        log.LogInfo(L"Registered for session notifications after {} attempts",
+                    wtsRetryAttempts_);
+        return;
+    }
+    if (wtsRetryAttempts_ >= WTS_RETRY_MAX_ATTEMPTS) {
+        StopSessionNotificationRetry();
+        log.LogError(
+            L"Giving up on registering for session notifications after {} "
+            L"attempts. Muting on workstation lock is not available",
+            wtsRetryAttempts_);
+        wmTray_.ShowPopup(
+            i18n_.GetTranslationW("popup.session-notification-failed.title"),
+            i18n_.GetTranslationW("popup.session-notification-failed.text"));
+    }
+}
+
 bool WinMute::Init()
 {
     WMLog& log = WMLog::GetInstance();
@@ -232,13 +315,12 @@ bool WinMute::Init()
         return false;
     }
 
-    if (!WTSRegisterSessionNotification(hWnd_, NOTIFY_FOR_THIS_SESSION)) {
-        const DWORD lastError = GetLastError();
-        ShowWindowsError(L"WTSRegisterSessionNotification");
-        log.LogWinError(L"WTSRegisterSessionNotification", lastError);
-        return false;
+    // Try to register session notification. This is needed for mute-on-lock
+    // to work. If it fails, try again for a few times in the background,
+    // but don't block startup on it.
+    if (!TryRegisterSessionNotification()) {
+        StartSessionNotificationRetry();
     }
-    wtsSessionNotificationRegistered_ = true;
 
     hPowerNotify_ = RegisterPowerSettingNotification(
         hWnd_, &GUID_CONSOLE_DISPLAY_STATE, DEVICE_NOTIFY_WINDOW_HANDLE);
@@ -878,6 +960,7 @@ void WinMute::Unload() noexcept
         UnregisterPowerSettingNotification(hLidCloseNotify_);
         hLidCloseNotify_ = nullptr;
     }
+    StopSessionNotificationRetry();
     if (wtsSessionNotificationRegistered_) {
         WTSUnRegisterSessionNotification(hWnd_);
         wtsSessionNotificationRegistered_ = false;
index 4d78612ded29b9a3603be541bd43538d1864b61a..f993ef6757c8beb022270a5c7469a148d8d0b5bc 100644 (file)
@@ -51,6 +51,7 @@ public:
 
    // for internal use
    LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+   void RetrySessionNotification();
 private:
    HWND hWnd_;
    HMENU hTrayMenu_;
@@ -66,6 +67,8 @@ private:
    } muteConfig_;
 
    bool wtsSessionNotificationRegistered_ = false;
+   UINT_PTR wtsRetryTimerId_ = 0;
+   int wtsRetryAttempts_ = 0;
    HPOWERNOTIFY hPowerNotify_ = nullptr;
    HPOWERNOTIFY hLidCloseNotify_ = nullptr;
 
@@ -86,6 +89,10 @@ private:
    bool InitTrayMenu();
    bool LoadSettings();
 
+   bool TryRegisterSessionNotification();
+   void StartSessionNotificationRetry();
+   void StopSessionNotificationRetry() noexcept;
+
    void Unload() noexcept;
 
    void ToggleMenuCheck(UINT item, bool* setting) noexcept;