Switch remote deploy to vendored source builds
Move remote deployment to a vendored source bundle built on the target host via Docker so redeploys no longer require local cross-compilation or host Go installation. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
179
vendor/git.sr.ht/~jackmordaunt/go-toast/v2/wintoast/impl.go
vendored
Normal file
179
vendor/git.sr.ht/~jackmordaunt/go-toast/v2/wintoast/impl.go
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
//go:build windows
|
||||
|
||||
// This file contains our pure-Go implementations of two COM objects that we need
|
||||
// to render toast notifications: IClassFactory and INotificationActivationCallback.
|
||||
//
|
||||
// More specifically we allocate the C callable functions that can be used to populate
|
||||
// the vtable at runtime.
|
||||
//
|
||||
// Unfortunately these functions have to be declared as var not const because the callbacks
|
||||
// are built at runtime. They are declared globally because `syscall.NewCallback` never
|
||||
// releases the memory it allocates for the functions thus causing an unsolvable memory
|
||||
// leak if we were to allocate these per-notification.
|
||||
//
|
||||
// The other COM interfaces we are interacting with are auto-generated from metadata.
|
||||
// However the INotificationActivationCallback is undocumented, so we have to define
|
||||
// it entirely ourselves.
|
||||
//
|
||||
// The definitions are derived from:
|
||||
// - <combase.h>
|
||||
// - <NotificationActivationCallback.h>
|
||||
package wintoast
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/go-ole/go-ole"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// Interface GUIDS. These GUIDS are predefined by the Windows Runtime, identifying the various
|
||||
// interfaces we want to make use of.
|
||||
var (
|
||||
IID_IClassFactory = ole.NewGUID("{00000001-0000-0000-C000-000000000046}")
|
||||
IID_INotificationActivationCallback = ole.NewGUID("{53E31837-6600-4A81-9395-75CFFE746F94}")
|
||||
)
|
||||
|
||||
// This default GUID is for our implementation.
|
||||
// This was generated and should not collide with any other GUID.
|
||||
// It's preferable for the application to override this value with its own generated GUID.
|
||||
var GUID_ImplNotificationActivationCallback = ole.NewGUID("{0F82E845-CB89-4039-BDBF-67CA33254C76}")
|
||||
|
||||
type (
|
||||
// IClassFactory defines the factory that builds our INotificationActivationCallback instance.
|
||||
// Windows Runtime loves factories.
|
||||
IClassFactory struct {
|
||||
VTable *IClassFactoryVtbl
|
||||
}
|
||||
|
||||
IClassFactoryVtbl struct {
|
||||
ole.IUnknownVtbl
|
||||
CreateInstance uintptr
|
||||
LockServer uintptr
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
// INotificationActivationCallback receives activations from toast notifications.
|
||||
INotificationActivationCallback struct {
|
||||
VTable *INotificationActivationCallbackVtbl
|
||||
}
|
||||
|
||||
INotificationActivationCallbackVtbl struct {
|
||||
ole.IUnknownVtbl
|
||||
Activate uintptr
|
||||
}
|
||||
)
|
||||
|
||||
/*
|
||||
Strictly speaking we shouldn't need to pin the static objects. They
|
||||
are package-globals and wont be garabge collected. No harm in being
|
||||
extra careful, though.
|
||||
*/
|
||||
|
||||
var pinner runtime.Pinner
|
||||
|
||||
func init() {
|
||||
pinner.Pin(ClassFactory)
|
||||
pinner.Pin(ClassFactory.VTable)
|
||||
pinner.Pin(NotificationActivationCallback)
|
||||
pinner.Pin(NotificationActivationCallback.VTable)
|
||||
}
|
||||
|
||||
// Static implementations for the IClassFactory.
|
||||
var (
|
||||
ClassFactory = &IClassFactory{
|
||||
VTable: &IClassFactoryVtbl{
|
||||
IUnknownVtbl: ole.IUnknownVtbl{
|
||||
QueryInterface: IClassFactory_QueryInterface,
|
||||
AddRef: IClassFactory_AddRef,
|
||||
Release: IClassFactory_Release,
|
||||
},
|
||||
LockServer: IClassFactory_LockServer,
|
||||
CreateInstance: IClassFactory_CreateInstance,
|
||||
},
|
||||
}
|
||||
|
||||
IClassFactory_AddRef = syscall.NewCallback(func(this *IClassFactory) (re uintptr) {
|
||||
return uintptr(1)
|
||||
})
|
||||
|
||||
IClassFactory_Release = syscall.NewCallback(func(this *IClassFactory) (re uintptr) {
|
||||
return uintptr(1)
|
||||
})
|
||||
|
||||
IClassFactory_QueryInterface = syscall.NewCallback(func(this *IClassFactory, riid *ole.GUID, out unsafe.Pointer) (re uintptr) {
|
||||
if !ole.IsEqualGUID(riid, IID_IClassFactory) &&
|
||||
!ole.IsEqualGUID(riid, ole.IID_IUnknown) {
|
||||
return ole.E_NOINTERFACE
|
||||
}
|
||||
*(**IClassFactory)(out) = this
|
||||
return ole.S_OK
|
||||
})
|
||||
|
||||
IClassFactory_LockServer = syscall.NewCallback(func(this *IClassFactory, flock uintptr) (ret uintptr) {
|
||||
return ole.S_OK
|
||||
})
|
||||
|
||||
IClassFactory_CreateInstance = syscall.NewCallback(func(this *IClassFactory, punkOuter *ole.IUnknown, riid *ole.GUID, out unsafe.Pointer) (re uintptr) {
|
||||
if punkOuter != nil {
|
||||
// Should be CLASS_E_NOAGGREGATION but ole doesn't define this.
|
||||
return ole.E_NOINTERFACE
|
||||
}
|
||||
if !ole.IsEqualGUID(riid, IID_INotificationActivationCallback) &&
|
||||
!ole.IsEqualGUID(riid, ole.IID_IUnknown) {
|
||||
return ole.E_NOINTERFACE
|
||||
}
|
||||
*(**INotificationActivationCallback)(out) = NotificationActivationCallback
|
||||
return ole.S_OK
|
||||
})
|
||||
)
|
||||
|
||||
// Static implementations for the INotificationActivationCallback.
|
||||
var (
|
||||
NotificationActivationCallback = &INotificationActivationCallback{
|
||||
VTable: &INotificationActivationCallbackVtbl{
|
||||
IUnknownVtbl: ole.IUnknownVtbl{
|
||||
QueryInterface: INotificationActivationCallback_QueryInterface,
|
||||
AddRef: INotificationActivationCallback_AddRef,
|
||||
Release: INotificationActivationCallback_Release,
|
||||
},
|
||||
Activate: INotificationActivationCallback_Activate,
|
||||
},
|
||||
}
|
||||
|
||||
INotificationActivationCallback_AddRef = syscall.NewCallback(func(this *INotificationActivationCallback) (re uintptr) {
|
||||
return uintptr(1)
|
||||
})
|
||||
|
||||
INotificationActivationCallback_Release = syscall.NewCallback(func(this *INotificationActivationCallback) (re uintptr) {
|
||||
return uintptr(1)
|
||||
})
|
||||
|
||||
INotificationActivationCallback_QueryInterface = syscall.NewCallback(func(this *INotificationActivationCallback, riid *ole.GUID, out unsafe.Pointer) (re uintptr) {
|
||||
if !ole.IsEqualGUID(riid, IID_INotificationActivationCallback) &&
|
||||
!ole.IsEqualGUID(riid, ole.IID_IUnknown) {
|
||||
return ole.E_NOINTERFACE
|
||||
}
|
||||
*(**INotificationActivationCallback)(out) = this
|
||||
return ole.S_OK
|
||||
})
|
||||
|
||||
// Activate is our re-entrance into Go from Windows. This is the magic.
|
||||
INotificationActivationCallback_Activate = syscall.NewCallback(func(
|
||||
this unsafe.Pointer,
|
||||
appUserModelId unsafe.Pointer,
|
||||
invokedArgs unsafe.Pointer,
|
||||
data unsafe.Pointer,
|
||||
count uint32,
|
||||
) (ret uintptr) {
|
||||
callback(
|
||||
windows.UTF16PtrToString((*uint16)(appUserModelId)),
|
||||
windows.UTF16PtrToString((*uint16)(invokedArgs)),
|
||||
sliceUserDataFromUnsafe(data, int(count)),
|
||||
)
|
||||
return
|
||||
})
|
||||
)
|
||||
Reference in New Issue
Block a user