commit c818d2a22a2a0439f8d45352d90bfc940486e717
parent 637ac233934ae98c9e6c5c93f233012131364118
Author: Jack Mordaunt <jackmordaunt.dev@gmail.com>
Date: Mon, 28 Oct 2024 12:07:19 +0800
wintoast.pushCOM: disable notifications when unsupported
Windows 7 can have WinRT apis stubbed out, such as RoActivateInstance.
Rather than erroring like they should, they silently succeed, such that
we panic when we attempt to use the resulting COM object.
To avoid this we recover the panic and transform it into an error value
for the caller. In the above case of E_NOINTERFACE we permanently
disable the api to avoid spurious unrecoverable errors. pushCOM becomes
a noop function.
Signed-off-by: Jack Mordaunt <jackmordaunt.dev@gmail.com>
Diffstat:
1 file changed, 30 insertions(+), 1 deletion(-)
diff --git a/wintoast/bind_windows.go b/wintoast/bind_windows.go
@@ -58,7 +58,36 @@ func buildPowershell(xml string, w io.Writer) error {
return tmpl.ScriptTemplate.Execute(w, scriptData{AppID: appData.AppID, XML: xml})
}
-func pushCOM(appID, xml string) error {
+// HRESULT E_NOINTERFACE
+const errNoInterface = 0x80004002
+
+var comDisabled atomic.Bool
+
+func pushCOM(appID, xml string) (err error) {
+ if comDisabled.Load() {
+ return nil
+ }
+
+ defer func() {
+ // On Windows 7 WinRT interfaces can be stubbed out, and fail to produce
+ // error values. This leads to a panic when trying to use the interface.
+ // This recover transforms such panics back into an error value for the
+ // caller.
+ //
+ // If the error is "interface not supported" we will permanently disable
+ // this API henceforth.
+ if v := recover(); v != nil {
+ if verr, ok := v.(error); ok {
+ err = verr
+ }
+ if oleErr, ok := v.(*ole.OleError); ok {
+ if oleErr.Code() == errNoInterface {
+ comDisabled.Store(true)
+ }
+ }
+ }
+ }()
+
if err := initialize(); err != nil {
return err
}