Update dependencies

This commit is contained in:
bluepython508
2024-11-01 17:33:34 +00:00
parent 033ac0b400
commit 5cdfab398d
3596 changed files with 1033483 additions and 259 deletions

140
vendor/github.com/dblohm7/wingoes/com/api.go generated vendored Normal file
View File

@@ -0,0 +1,140 @@
// Copyright (c) 2022 Tailscale Inc & AUTHORS. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build windows
package com
import (
"unsafe"
"github.com/dblohm7/wingoes"
)
// MustGetAppID parses s, a string containing an app ID and returns a pointer to the
// parsed AppID. s must be specified in the format "{XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}".
// If there is an error parsing s, MustGetAppID panics.
func MustGetAppID(s string) *AppID {
return (*AppID)(unsafe.Pointer(wingoes.MustGetGUID(s)))
}
// MustGetCLSID parses s, a string containing a CLSID and returns a pointer to the
// parsed CLSID. s must be specified in the format "{XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}".
// If there is an error parsing s, MustGetCLSID panics.
func MustGetCLSID(s string) *CLSID {
return (*CLSID)(unsafe.Pointer(wingoes.MustGetGUID(s)))
}
// MustGetIID parses s, a string containing an IID and returns a pointer to the
// parsed IID. s must be specified in the format "{XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}".
// If there is an error parsing s, MustGetIID panics.
func MustGetIID(s string) *IID {
return (*IID)(unsafe.Pointer(wingoes.MustGetGUID(s)))
}
// MustGetServiceID parses s, a string containing a service ID and returns a pointer to the
// parsed ServiceID. s must be specified in the format "{XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}".
// If there is an error parsing s, MustGetServiceID panics.
func MustGetServiceID(s string) *ServiceID {
return (*ServiceID)(unsafe.Pointer(wingoes.MustGetGUID(s)))
}
func getCurrentApartmentInfo() (aptInfo, error) {
var info aptInfo
hr := coGetApartmentType(&info.apt, &info.qualifier)
if err := wingoes.ErrorFromHRESULT(hr); err.Failed() {
return info, err
}
return info, nil
}
// aptChecker is a function that applies an arbitrary predicate to an OS thread's
// apartment information, returning true if the input satisifes that predicate.
type aptChecker func(*aptInfo) bool
// checkCurrentApartment obtains information about the COM apartment that the
// current OS thread resides in, and then passes that information to chk,
// which evaluates that information and determines the return value.
func checkCurrentApartment(chk aptChecker) bool {
info, err := getCurrentApartmentInfo()
if err != nil {
return false
}
return chk(&info)
}
// AssertCurrentOSThreadSTA checks if the current OS thread resides in a
// single-threaded apartment, and if not, panics.
func AssertCurrentOSThreadSTA() {
if IsCurrentOSThreadSTA() {
return
}
panic("current OS thread does not reside in a single-threaded apartment")
}
// IsCurrentOSThreadSTA checks if the current OS thread resides in a
// single-threaded apartment and returns true if so.
func IsCurrentOSThreadSTA() bool {
chk := func(i *aptInfo) bool {
return i.apt == coAPTTYPE_STA || i.apt == coAPTTYPE_MAINSTA
}
return checkCurrentApartment(chk)
}
// AssertCurrentOSThreadMTA checks if the current OS thread resides in the
// multi-threaded apartment, and if not, panics.
func AssertCurrentOSThreadMTA() {
if IsCurrentOSThreadMTA() {
return
}
panic("current OS thread does not reside in the multi-threaded apartment")
}
// IsCurrentOSThreadMTA checks if the current OS thread resides in the
// multi-threaded apartment and returns true if so.
func IsCurrentOSThreadMTA() bool {
chk := func(i *aptInfo) bool {
return i.apt == coAPTTYPE_MTA
}
return checkCurrentApartment(chk)
}
// createInstanceWithCLSCTX creates a new garbage-collected COM object of type T
// using class clsid. clsctx determines the acceptable location for hosting the
// COM object (in-process, local but out-of-process, or remote).
func createInstanceWithCLSCTX[T Object](clsid *CLSID, clsctx coCLSCTX) (T, error) {
var t T
iid := t.IID()
ppunk := NewABIReceiver()
hr := coCreateInstance(
clsid,
nil,
clsctx,
iid,
ppunk,
)
if err := wingoes.ErrorFromHRESULT(hr); err.Failed() {
return t, err
}
return t.Make(ppunk).(T), nil
}
// CreateInstance instantiates a new in-process COM object of type T
// using class clsid.
func CreateInstance[T Object](clsid *CLSID) (T, error) {
return createInstanceWithCLSCTX[T](clsid, coCLSCTX_INPROC_SERVER)
}
// CreateInstance instantiates a new local, out-of-process COM object of type T
// using class clsid.
func CreateOutOfProcessInstance[T Object](clsid *CLSID) (T, error) {
return createInstanceWithCLSCTX[T](clsid, coCLSCTX_LOCAL_SERVER)
}

View File

@@ -0,0 +1,7 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
//go:build windows
// Package automation provides essential types for interacting with COM Automation (IDispatch).
package automation

View File

@@ -0,0 +1,14 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
//go:build windows
package automation
//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go mksyscall.go
//go:generate go run golang.org/x/tools/cmd/goimports -w zsyscall_windows.go
//sys sysAllocString(str *uint16) (ret BSTR) = oleaut32.SysAllocString
//sys sysAllocStringLen(str *uint16, strLen uint32) (ret BSTR) = oleaut32.SysAllocStringLen
//sys sysFreeString(bstr BSTR) = oleaut32.SysFreeString
//sys sysStringLen(bstr BSTR) (ret uint32) = oleaut32.SysStringLen

View File

@@ -0,0 +1,93 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
//go:build windows
package automation
import (
"unsafe"
"golang.org/x/sys/windows"
)
// BSTR is the string format used by COM Automation. They are not garbage
// collected and must be explicitly closed when no longer needed.
type BSTR uintptr
// NewBSTR creates a new BSTR from string s.
func NewBSTR(s string) BSTR {
buf, err := windows.UTF16FromString(s)
if err != nil {
return 0
}
return NewBSTRFromUTF16(buf)
}
// NewBSTR creates a new BSTR from slice us, which contains UTF-16 code units.
func NewBSTRFromUTF16(us []uint16) BSTR {
if len(us) == 0 {
return 0
}
return sysAllocStringLen(unsafe.SliceData(us), uint32(len(us)))
}
// NewBSTR creates a new BSTR from up, a C-style string pointer to UTF-16 code units.
func NewBSTRFromUTF16Ptr(up *uint16) BSTR {
if up == nil {
return 0
}
return sysAllocString(up)
}
// Len returns the length of bs in code units.
func (bs *BSTR) Len() uint32 {
return sysStringLen(*bs)
}
// String returns the contents of bs as a Go string.
func (bs *BSTR) String() string {
return windows.UTF16ToString(bs.toUTF16())
}
// toUTF16 is unsafe for general use because it returns a pointer that is
// not managed by the Go GC.
func (bs *BSTR) toUTF16() []uint16 {
return unsafe.Slice(bs.toUTF16Ptr(), bs.Len())
}
// ToUTF16 returns the contents of bs as a slice of UTF-16 code units.
func (bs *BSTR) ToUTF16() []uint16 {
return append([]uint16{}, bs.toUTF16()...)
}
// toUTF16Ptr is unsafe for general use because it returns a pointer that is
// not managed by the Go GC.
func (bs *BSTR) toUTF16Ptr() *uint16 {
return (*uint16)(unsafe.Pointer(*bs))
}
// ToUTF16 returns the contents of bs as C-style string pointer to UTF-16 code units.
func (bs *BSTR) ToUTF16Ptr() *uint16 {
return unsafe.SliceData(bs.ToUTF16())
}
// Clone creates a clone of bs whose lifetime becomes independent of the original.
// It must be explicitly closed when no longer needed.
func (bs *BSTR) Clone() BSTR {
return sysAllocStringLen(bs.toUTF16Ptr(), bs.Len())
}
// IsNil returns true if bs holds a nil value.
func (bs *BSTR) IsNil() bool {
return *bs == 0
}
// Close frees bs.
func (bs *BSTR) Close() error {
if *bs != 0 {
sysFreeString(*bs)
*bs = 0
}
return nil
}

View File

@@ -0,0 +1,70 @@
// Code generated by 'go generate'; DO NOT EDIT.
package automation
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
var _ unsafe.Pointer
// Do the interface allocations only once for common
// Errno values.
const (
errnoERROR_IO_PENDING = 997
)
var (
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
errERROR_EINVAL error = syscall.EINVAL
)
// errnoErr returns common boxed Errno values, to prevent
// allocations at runtime.
func errnoErr(e syscall.Errno) error {
switch e {
case 0:
return errERROR_EINVAL
case errnoERROR_IO_PENDING:
return errERROR_IO_PENDING
}
// TODO: add more here, after collecting data on the common
// error values see on Windows. (perhaps when running
// all.bat?)
return e
}
var (
modoleaut32 = windows.NewLazySystemDLL("oleaut32.dll")
procSysAllocString = modoleaut32.NewProc("SysAllocString")
procSysAllocStringLen = modoleaut32.NewProc("SysAllocStringLen")
procSysFreeString = modoleaut32.NewProc("SysFreeString")
procSysStringLen = modoleaut32.NewProc("SysStringLen")
)
func sysAllocString(str *uint16) (ret BSTR) {
r0, _, _ := syscall.Syscall(procSysAllocString.Addr(), 1, uintptr(unsafe.Pointer(str)), 0, 0)
ret = BSTR(r0)
return
}
func sysAllocStringLen(str *uint16, strLen uint32) (ret BSTR) {
r0, _, _ := syscall.Syscall(procSysAllocStringLen.Addr(), 2, uintptr(unsafe.Pointer(str)), uintptr(strLen), 0)
ret = BSTR(r0)
return
}
func sysFreeString(bstr BSTR) {
syscall.Syscall(procSysFreeString.Addr(), 1, uintptr(bstr), 0, 0)
return
}
func sysStringLen(bstr BSTR) (ret uint32) {
r0, _, _ := syscall.Syscall(procSysStringLen.Addr(), 1, uintptr(bstr), 0, 0)
ret = uint32(r0)
return
}

9
vendor/github.com/dblohm7/wingoes/com/com.go generated vendored Normal file
View File

@@ -0,0 +1,9 @@
// Copyright (c) 2022 Tailscale Inc & AUTHORS. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build windows
// Package com provides an idiomatic foundation for instantiating and invoking
// COM objects.
package com

120
vendor/github.com/dblohm7/wingoes/com/globalopts.go generated vendored Normal file
View File

@@ -0,0 +1,120 @@
// Copyright (c) 2022 Tailscale Inc & AUTHORS. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build windows
package com
import (
"runtime"
"syscall"
"unsafe"
"github.com/dblohm7/wingoes"
)
var (
CLSID_GlobalOptions = &CLSID{0x0000034B, 0x0000, 0x0000, [8]byte{0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}
)
var (
IID_IGlobalOptions = &IID{0x0000015B, 0x0000, 0x0000, [8]byte{0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}
)
type GLOBALOPT_PROPERTIES int32
const (
COMGLB_EXCEPTION_HANDLING = GLOBALOPT_PROPERTIES(1)
COMGLB_APPID = GLOBALOPT_PROPERTIES(2)
COMGLB_RPC_THREADPOOL_SETTING = GLOBALOPT_PROPERTIES(3)
COMGLB_RO_SETTINGS = GLOBALOPT_PROPERTIES(4)
COMGLB_UNMARSHALING_POLICY = GLOBALOPT_PROPERTIES(5)
)
const (
COMGLB_EXCEPTION_HANDLE = 0
COMGLB_EXCEPTION_DONOT_HANDLE_FATAL = 1
COMGLB_EXCEPTION_DONOT_HANDLE = 1
COMGLB_EXCEPTION_DONOT_HANDLE_ANY = 2
)
// IGlobalOptionsABI represents the COM ABI for the IGlobalOptions interface.
type IGlobalOptionsABI struct {
IUnknownABI
}
// GlobalOptions is the COM object used for setting global configuration settings
// on the COM runtime. It must be called after COM runtime security has been
// initialized, but before anything else "significant" is done using COM.
type GlobalOptions struct {
GenericObject[IGlobalOptionsABI]
}
func (abi *IGlobalOptionsABI) Set(prop GLOBALOPT_PROPERTIES, value uintptr) error {
method := unsafe.Slice(abi.Vtbl, 5)[3]
rc, _, _ := syscall.Syscall(
method,
3,
uintptr(unsafe.Pointer(abi)),
uintptr(prop),
value,
)
if e := wingoes.ErrorFromHRESULT(wingoes.HRESULT(rc)); e.Failed() {
return e
}
return nil
}
func (abi *IGlobalOptionsABI) Query(prop GLOBALOPT_PROPERTIES) (uintptr, error) {
var result uintptr
method := unsafe.Slice(abi.Vtbl, 5)[4]
rc, _, _ := syscall.Syscall(
method,
3,
uintptr(unsafe.Pointer(abi)),
uintptr(prop),
uintptr(unsafe.Pointer(&result)),
)
if e := wingoes.ErrorFromHRESULT(wingoes.HRESULT(rc)); e.Failed() {
return 0, e
}
return result, nil
}
func (o GlobalOptions) IID() *IID {
return IID_IGlobalOptions
}
func (o GlobalOptions) Make(r ABIReceiver) any {
if r == nil {
return GlobalOptions{}
}
runtime.SetFinalizer(r, ReleaseABI)
pp := (**IGlobalOptionsABI)(unsafe.Pointer(r))
return GlobalOptions{GenericObject[IGlobalOptionsABI]{Pp: pp}}
}
// UnsafeUnwrap returns the underlying IGlobalOptionsABI of the object. As the
// name implies, this is unsafe -- you had better know what you are doing!
func (o GlobalOptions) UnsafeUnwrap() *IGlobalOptionsABI {
return *(o.Pp)
}
// Set sets the global property prop to value.
func (o GlobalOptions) Set(prop GLOBALOPT_PROPERTIES, value uintptr) error {
p := *(o.Pp)
return p.Set(prop, value)
}
// Query returns the value of global property prop.
func (o GlobalOptions) Query(prop GLOBALOPT_PROPERTIES) (uintptr, error) {
p := *(o.Pp)
return p.Query(prop)
}

22
vendor/github.com/dblohm7/wingoes/com/guid.go generated vendored Normal file
View File

@@ -0,0 +1,22 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
package com
import (
"github.com/dblohm7/wingoes"
)
// We intentionally export these types across all GOOSes
// IID is a GUID that represents an interface ID.
type IID wingoes.GUID
// CLSID is a GUID that represents a class ID.
type CLSID wingoes.GUID
// AppID is a GUID that represents an application ID.
type AppID wingoes.GUID
// ServiceID is a GUID that represents a service ID.
type ServiceID wingoes.GUID

112
vendor/github.com/dblohm7/wingoes/com/interface.go generated vendored Normal file
View File

@@ -0,0 +1,112 @@
// Copyright (c) 2022 Tailscale Inc & AUTHORS. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build windows
package com
import (
"syscall"
"unsafe"
"github.com/dblohm7/wingoes"
)
// IUnknown is the base COM interface.
type IUnknown interface {
QueryInterface(iid *IID) (IUnknown, error)
AddRef() int32
Release() int32
}
// This is a sentinel that indicates that a struct implements the COM ABI.
// Only IUnknownABI should implement this.
type hasVTable interface {
vtable() *uintptr
}
// IUnknownABI describes the ABI of the IUnknown interface (ie, a vtable).
type IUnknownABI struct {
Vtbl *uintptr
}
func (abi IUnknownABI) vtable() *uintptr {
return abi.Vtbl
}
// ABI is a type constraint allowing the COM ABI, or any struct that embeds it.
type ABI interface {
hasVTable
}
// PUnknown is a type constraint for types that both implement IUnknown and
// are also pointers to a COM ABI.
type PUnknown[A ABI] interface {
IUnknown
*A
}
// ABIReceiver is the type that receives COM interface pointers from COM
// method outparams.
type ABIReceiver **IUnknownABI
// NewABIReceiver instantiates a new ABIReceiver.
func NewABIReceiver() ABIReceiver {
return ABIReceiver(new(*IUnknownABI))
}
// ReleaseABI releases a COM object. Finalizers must always invoke this function
// when destroying COM interfaces.
func ReleaseABI(p **IUnknownABI) {
(*p).Release()
}
// QueryInterface implements the QueryInterface call for a COM interface pointer.
// iid is the desired interface ID.
func (abi *IUnknownABI) QueryInterface(iid *IID) (IUnknown, error) {
var punk *IUnknownABI
r, _, _ := syscall.Syscall(
*(abi.Vtbl),
3,
uintptr(unsafe.Pointer(abi)),
uintptr(unsafe.Pointer(iid)),
uintptr(unsafe.Pointer(&punk)),
)
if e := wingoes.ErrorFromHRESULT(wingoes.HRESULT(r)); e.Failed() {
return nil, e
}
return punk, nil
}
// AddRef implements the AddRef call for a COM interface pointer.
func (abi *IUnknownABI) AddRef() int32 {
method := unsafe.Slice(abi.Vtbl, 3)[1]
r, _, _ := syscall.Syscall(
method,
1,
uintptr(unsafe.Pointer(abi)),
0,
0,
)
return int32(r)
}
// Release implements the Release call for a COM interface pointer.
func (abi *IUnknownABI) Release() int32 {
method := unsafe.Slice(abi.Vtbl, 3)[2]
r, _, _ := syscall.Syscall(
method,
1,
uintptr(unsafe.Pointer(abi)),
0,
0,
)
return int32(r)
}

25
vendor/github.com/dblohm7/wingoes/com/mksyscall.go generated vendored Normal file
View File

@@ -0,0 +1,25 @@
// Copyright (c) 2022 Tailscale Inc & AUTHORS. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build windows
package com
//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go mksyscall.go
//go:generate go run golang.org/x/tools/cmd/goimports -w zsyscall_windows.go
//sys coCreateInstance(clsid *CLSID, unkOuter *IUnknownABI, clsctx coCLSCTX, iid *IID, ppv **IUnknownABI) (hr wingoes.HRESULT) = ole32.CoCreateInstance
//sys coGetApartmentType(aptType *coAPTTYPE, qual *coAPTTYPEQUALIFIER) (hr wingoes.HRESULT) = ole32.CoGetApartmentType
//sys coInitializeEx(reserved uintptr, flags uint32) (hr wingoes.HRESULT) = ole32.CoInitializeEx
//sys coInitializeSecurity(sd *windows.SECURITY_DESCRIPTOR, authSvcLen int32, authSvc *soleAuthenticationService, reserved1 uintptr, authnLevel rpcAuthnLevel, impLevel rpcImpersonationLevel, authList *soleAuthenticationList, capabilities authCapabilities, reserved2 uintptr) (hr wingoes.HRESULT) = ole32.CoInitializeSecurity
// We don't use '?' on coIncrementMTAUsage because that doesn't play nicely with HRESULTs. We manually check for its presence in process.go
//sys coIncrementMTAUsage(cookie *coMTAUsageCookie) (hr wingoes.HRESULT) = ole32.CoIncrementMTAUsage
// Technically this proc is __cdecl, but since it has 0 args this doesn't matter
//sys setOaNoCache() = oleaut32.SetOaNoCache
// For the following two functions we use IUnknownABI instead of IStreamABI because it makes the callsites cleaner.
//sys shCreateMemStream(pInit *byte, cbInit uint32) (stream *IUnknownABI) = shlwapi.SHCreateMemStream
//sys createStreamOnHGlobal(hglobal internal.HGLOBAL, deleteOnRelease bool, stream **IUnknownABI) (hr wingoes.HRESULT) = ole32.CreateStreamOnHGlobal

89
vendor/github.com/dblohm7/wingoes/com/object.go generated vendored Normal file
View File

@@ -0,0 +1,89 @@
// Copyright (c) 2022 Tailscale Inc & AUTHORS. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build windows
package com
import (
"fmt"
"unsafe"
)
// GenericObject is a struct that wraps any interface that implements the COM ABI.
type GenericObject[A ABI] struct {
Pp **A
}
func (o GenericObject[A]) pp() **A {
return o.Pp
}
// Object is the interface that all garbage-collected instances of COM interfaces
// must implement.
type Object interface {
// IID returns the interface ID for the object. This method may be called
// on Objects containing the zero value, so its return value must not depend
// on the value of the method's receiver.
IID() *IID
// Make converts r to an instance of a garbage-collected COM object. The type
// of its return value must always match the type of the method's receiver.
Make(r ABIReceiver) any
}
// EmbedsGenericObject is a type constraint matching any struct that embeds
// a GenericObject[A].
type EmbedsGenericObject[A ABI] interface {
Object
~struct{ GenericObject[A] }
pp() **A
}
// As casts obj to an object of type O, or panics if obj cannot be converted to O.
func As[O Object, A ABI, PU PUnknown[A], E EmbedsGenericObject[A]](obj E) O {
o, err := TryAs[O, A, PU](obj)
if err != nil {
panic(fmt.Sprintf("wingoes.com.As error: %v", err))
}
return o
}
// TryAs casts obj to an object of type O, or returns an error if obj cannot be
// converted to O.
func TryAs[O Object, A ABI, PU PUnknown[A], E EmbedsGenericObject[A]](obj E) (O, error) {
var o O
iid := o.IID()
p := (PU)(unsafe.Pointer(*(obj.pp())))
i, err := p.QueryInterface(iid)
if err != nil {
return o, err
}
r := NewABIReceiver()
*r = i.(*IUnknownABI)
return o.Make(r).(O), nil
}
// IsSameObject returns true when both l and r refer to the same underlying object.
func IsSameObject[AL, AR ABI, PL PUnknown[AL], PR PUnknown[AR], EL EmbedsGenericObject[AL], ER EmbedsGenericObject[AR]](l EL, r ER) bool {
pl := (PL)(unsafe.Pointer(*(l.pp())))
ul, err := pl.QueryInterface(IID_IUnknown)
if err != nil {
return false
}
defer ul.Release()
pr := (PR)(unsafe.Pointer(*(r.pp())))
ur, err := pr.QueryInterface(IID_IUnknown)
if err != nil {
return false
}
defer ur.Release()
return ul.(*IUnknownABI) == ur.(*IUnknownABI)
}

268
vendor/github.com/dblohm7/wingoes/com/process.go generated vendored Normal file
View File

@@ -0,0 +1,268 @@
// Copyright (c) 2022 Tailscale Inc & AUTHORS. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build windows
package com
import (
"os"
"runtime"
"github.com/dblohm7/wingoes"
"golang.org/x/sys/windows"
)
// ProcessType is an enumeration that specifies the type of the current process
// when calling StartRuntime.
type ProcessType uint
const (
// ConsoleApp is a text-mode Windows program.
ConsoleApp = ProcessType(iota)
// Service is a Windows service.
Service
// GUIApp is a GUI-mode Windows program.
GUIApp
// Note: Even though this implementation is not yet internally distinguishing
// between console apps and services, this distinction may be useful in the
// future. For example, a service could receive more restrictive default
// security settings than a console app.
// Having this as part of the API now avoids future breakage.
)
// StartRuntime permanently initializes COM for the remaining lifetime of the
// current process. To avoid errors, it should be called as early as possible
// during program initialization. When processType == GUIApp, the current
// OS thread becomes permanently locked to the current goroutine; any subsequent
// GUI *must* be created on the same OS thread.
// An excellent location to call StartRuntime is in the init function of the
// main package.
func StartRuntime(processType ProcessType) error {
return StartRuntimeWithDACL(processType, nil)
}
// StartRuntimeWithDACL permanently initializes COM for the remaining lifetime
// of the current process. To avoid errors, it should be called as early as
// possible during program initialization. When processType == GUIApp, the
// current OS thread becomes permanently locked to the current goroutine; any
// subsequent GUI *must* be created on the same OS thread. dacl is an ACL that
// controls access of other processes connecting to the current process over COM.
// For further information about COM access control, look up the COM_RIGHTS_*
// access flags in the Windows developer documentation.
// An excellent location to call StartRuntimeWithDACL is in the init function of
// the main package.
func StartRuntimeWithDACL(processType ProcessType, dacl *windows.ACL) error {
runtime.LockOSThread()
defer func() {
// When initializing for non-GUI processes, the OS thread may be unlocked
// upon return from this function.
if processType != GUIApp {
runtime.UnlockOSThread()
}
}()
switch processType {
case ConsoleApp, Service:
// Just start the MTA implicitly.
if err := startMTAImplicitly(); err != nil {
return err
}
case GUIApp:
// For GUIApp, we want the current OS thread to enter a single-threaded
// apartment (STA). However, we want all other OS threads to reside inside
// a multi-threaded apartment (MTA). The way to so this is to first start
// the MTA implicitly, affecting all OS threads who have not yet explicitly
// entered a COM apartment...
if err := startMTAImplicitly(); err != nil {
runtime.UnlockOSThread()
return err
}
// ...and then subsequently explicitly enter a STA on this OS thread, which
// automatically removes this OS thread from the MTA.
if err := enterSTA(); err != nil {
runtime.UnlockOSThread()
return err
}
// From this point forward, we must never unlock the OS thread.
default:
return os.ErrInvalid
}
// Order is extremely important here: initSecurity must be called immediately
// after apartments are set up, but before doing anything else.
if err := initSecurity(dacl); err != nil {
return err
}
// By default, for compatibility reasons, COM internally sets a catch-all
// exception handler at its API boundary. This is dangerous, so we override it.
// This work must happen after security settings are initialized, but before
// anything "significant" is done with COM.
globalOpts, err := CreateInstance[GlobalOptions](CLSID_GlobalOptions)
if err != nil {
return err
}
err = globalOpts.Set(COMGLB_EXCEPTION_HANDLING, COMGLB_EXCEPTION_DONOT_HANDLE_ANY)
// The BSTR cache never invalidates itself, so we disable it unconditionally.
// We do this here to ensure that the BSTR cache is off before anything
// can possibly start using oleaut32.dll.
setOaNoCache()
return err
}
// startMTAImplicitly creates an implicit multi-threaded apartment (MTA) for
// all threads in a process that do not otherwise explicitly enter a COM apartment.
func startMTAImplicitly() error {
// CoIncrementMTAUsage is the modern API to use for creating the MTA implicitly,
// however we may fall back to a legacy mechanism when the former API is unavailable.
if err := procCoIncrementMTAUsage.Find(); err != nil {
return startMTAImplicitlyLegacy()
}
// We do not retain cookie beyond this function, as we have no intention of
// tearing any of this back down.
var cookie coMTAUsageCookie
hr := coIncrementMTAUsage(&cookie)
if e := wingoes.ErrorFromHRESULT(hr); e.Failed() {
return e
}
return nil
}
// startMTAImplicitlyLegacy works by having a background OS thread explicitly enter
// the multi-threaded apartment. All other OS threads that have not explicitly
// entered an apartment will become implicit members of that MTA. This function is
// written assuming that the current OS thread has already been locked.
func startMTAImplicitlyLegacy() error {
// We need to start the MTA on a background OS thread, HOWEVER we also want this
// to happen synchronously, so we wait on c for MTA initialization to complete.
c := make(chan error)
go bgMTASustainer(c)
return <-c
}
// bgMTASustainer locks the current goroutine to the current OS thread, enters
// the COM multi-threaded apartment, and then blocks for the remainder of the
// process's lifetime. It sends its result to c so that startMTAImplicitlyLegacy
// can wait for the MTA to be ready before proceeding.
func bgMTASustainer(c chan error) {
runtime.LockOSThread()
err := enterMTA()
c <- err
if err != nil {
// We didn't enter the MTA, so just unlock and bail.
runtime.UnlockOSThread()
return
}
select {}
}
// enterMTA causes the current OS thread to explicitly declare itself to be a
// member of COM's multi-threaded apartment. Note that this function affects
// thread-local state, so use carefully!
func enterMTA() error {
return coInit(windows.COINIT_MULTITHREADED)
}
// enterSTA causes the current OS thread to create and enter a single-threaded
// apartment. The current OS thread must be locked and remain locked for the
// duration of the thread's time in the apartment. For our purposes, the calling
// OS thread never leaves the STA, so it must effectively remain locked for
// the remaining lifetime of the process. A single-threaded apartment should be
// used if and only if an OS thread is going to be creating windows and pumping
// messages; STAs are NOT generic containers for single-threaded COM code,
// contrary to popular belief. Note that this function affects thread-local
// state, so use carefully!
func enterSTA() error {
return coInit(windows.COINIT_APARTMENTTHREADED)
}
// coInit is a wrapper for CoInitializeEx that properly handles the S_FALSE
// error code (x/sys/windows.CoInitializeEx does not).
func coInit(apartment uint32) error {
hr := coInitializeEx(0, apartment)
if e := wingoes.ErrorFromHRESULT(hr); e.Failed() {
return e
}
return nil
}
const (
authSvcCOMChooses = -1
)
// initSecurity initializes COM security using the ACL specified by dacl.
// A nil dacl implies that a default ACL should be used instead.
func initSecurity(dacl *windows.ACL) error {
sd, err := buildSecurityDescriptor(dacl)
if err != nil {
return err
}
caps := authCapNone
if sd == nil {
// For COM to fall back to system-wide defaults, we need to set this bit.
caps |= authCapAppID
}
hr := coInitializeSecurity(
sd,
authSvcCOMChooses,
nil, // authSvc (not used because previous arg is authSvcCOMChooses)
0, // Reserved, must be 0
rpcAuthnLevelDefault,
rpcImpLevelIdentify,
nil, // authlist: use defaults
caps,
0, // Reserved, must be 0
)
if e := wingoes.ErrorFromHRESULT(hr); e.Failed() {
return e
}
return nil
}
// buildSecurityDescriptor inserts dacl into a valid security descriptor for use
// with CoInitializeSecurity. A nil dacl results in a nil security descriptor,
// which we consider to be a valid "use defaults" sentinel.
func buildSecurityDescriptor(dacl *windows.ACL) (*windows.SECURITY_DESCRIPTOR, error) {
if dacl == nil {
// Not an error, just use defaults.
return nil, nil
}
sd, err := windows.NewSecurityDescriptor()
if err != nil {
return nil, err
}
if err := sd.SetDACL(dacl, true, false); err != nil {
return nil, err
}
// CoInitializeSecurity will fail unless the SD's owner and group are both set.
userSIDs, err := wingoes.CurrentProcessUserSIDs()
if err != nil {
return nil, err
}
if err := sd.SetOwner(userSIDs.User, false); err != nil {
return nil, err
}
if err := sd.SetGroup(userSIDs.PrimaryGroup, false); err != nil {
return nil, err
}
return sd, nil
}

556
vendor/github.com/dblohm7/wingoes/com/stream.go generated vendored Normal file
View File

@@ -0,0 +1,556 @@
// Copyright (c) 2023 Tailscale Inc & AUTHORS. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build windows
package com
import (
"io"
"runtime"
"syscall"
"unsafe"
"github.com/dblohm7/wingoes"
"github.com/dblohm7/wingoes/internal"
"golang.org/x/sys/windows"
)
var (
IID_ISequentialStream = &IID{0x0C733A30, 0x2A1C, 0x11CE, [8]byte{0xAD, 0xE5, 0x00, 0xAA, 0x00, 0x44, 0x77, 0x3D}}
IID_IStream = &IID{0x0000000C, 0x0000, 0x0000, [8]byte{0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}
)
type STGC uint32
const (
STGC_DEFAULT = STGC(0)
STGC_OVERWRITE = STGC(1)
STGC_ONLYIFCURRENT = STGC(2)
STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE = STGC(4)
STGC_CONSOLIDATE = STGC(8)
)
type LOCKTYPE uint32
const (
LOCK_WRITE = LOCKTYPE(1)
LOCK_EXCLUSIVE = LOCKTYPE(2)
LOCK_ONLYONCE = LOCKTYPE(4)
)
type STGTY uint32
const (
STGTY_STORAGE = STGTY(1)
STGTY_STREAM = STGTY(2)
STGTY_LOCKBYTES = STGTY(3)
STGTY_PROPERTY = STGTY(4)
)
type STATFLAG uint32
const (
STATFLAG_DEFAULT = STATFLAG(0)
STATFLAG_NONAME = STATFLAG(1)
STATFLAG_NOOPEN = STATFLAG(2)
)
type STATSTG struct {
Name COMAllocatedString
Type STGTY
Size uint64
MTime windows.Filetime
CTime windows.Filetime
ATime windows.Filetime
Mode uint32
LocksSupported LOCKTYPE
ClsID CLSID
_ uint32 // StateBits
_ uint32 // reserved
}
func (st *STATSTG) Close() error {
return st.Name.Close()
}
type ISequentialStreamABI struct {
IUnknownABI
}
type IStreamABI struct {
ISequentialStreamABI
}
type SequentialStream struct {
GenericObject[ISequentialStreamABI]
}
type Stream struct {
GenericObject[IStreamABI]
}
func (abi *ISequentialStreamABI) Read(p []byte) (int, error) {
if len(p) > maxStreamRWLen {
p = p[:maxStreamRWLen]
}
var cbRead uint32
method := unsafe.Slice(abi.Vtbl, 5)[3]
rc, _, _ := syscall.SyscallN(
method,
uintptr(unsafe.Pointer(abi)),
uintptr(unsafe.Pointer(unsafe.SliceData(p))),
uintptr(uint32(len(p))),
uintptr(unsafe.Pointer(&cbRead)),
)
n := int(cbRead)
e := wingoes.ErrorFromHRESULT(wingoes.HRESULT(rc))
if e.Failed() {
return n, e
}
// Various implementations of IStream handle EOF differently. We need to
// deal with both.
if e.AsHRESULT() == wingoes.S_FALSE || (n == 0 && len(p) > 0) {
return n, io.EOF
}
return n, nil
}
func (abi *ISequentialStreamABI) Write(p []byte) (int, error) {
w := p
if len(w) > maxStreamRWLen {
w = w[:maxStreamRWLen]
}
var cbWritten uint32
method := unsafe.Slice(abi.Vtbl, 5)[4]
rc, _, _ := syscall.SyscallN(
method,
uintptr(unsafe.Pointer(abi)),
uintptr(unsafe.Pointer(unsafe.SliceData(w))),
uintptr(uint32(len(w))),
uintptr(unsafe.Pointer(&cbWritten)),
)
n := int(cbWritten)
if e := wingoes.ErrorFromHRESULT(wingoes.HRESULT(rc)); e.Failed() {
return n, e
}
// Need this to satisfy Writer.
if n < len(p) {
return n, io.ErrShortWrite
}
return n, nil
}
func (o SequentialStream) IID() *IID {
return IID_ISequentialStream
}
func (o SequentialStream) Make(r ABIReceiver) any {
if r == nil {
return SequentialStream{}
}
runtime.SetFinalizer(r, ReleaseABI)
pp := (**ISequentialStreamABI)(unsafe.Pointer(r))
return SequentialStream{GenericObject[ISequentialStreamABI]{Pp: pp}}
}
func (o SequentialStream) UnsafeUnwrap() *ISequentialStreamABI {
return *(o.Pp)
}
func (o SequentialStream) Read(b []byte) (n int, err error) {
p := *(o.Pp)
return p.Read(b)
}
func (o SequentialStream) Write(b []byte) (int, error) {
p := *(o.Pp)
return p.Write(b)
}
func (abi *IStreamABI) Seek(offset int64, whence int) (n int64, _ error) {
var hr wingoes.HRESULT
method := unsafe.Slice(abi.Vtbl, 14)[5]
if runtime.GOARCH == "386" {
words := (*[2]uintptr)(unsafe.Pointer(&offset))
rc, _, _ := syscall.SyscallN(
method,
uintptr(unsafe.Pointer(abi)),
words[0],
words[1],
uintptr(uint32(whence)),
uintptr(unsafe.Pointer(&n)),
)
hr = wingoes.HRESULT(rc)
} else {
rc, _, _ := syscall.SyscallN(
method,
uintptr(unsafe.Pointer(abi)),
uintptr(offset),
uintptr(uint32(whence)),
uintptr(unsafe.Pointer(&n)),
)
hr = wingoes.HRESULT(rc)
}
if e := wingoes.ErrorFromHRESULT(hr); e.Failed() {
return 0, e
}
return n, nil
}
func (abi *IStreamABI) SetSize(newSize uint64) error {
var hr wingoes.HRESULT
method := unsafe.Slice(abi.Vtbl, 14)[6]
if runtime.GOARCH == "386" {
words := (*[2]uintptr)(unsafe.Pointer(&newSize))
rc, _, _ := syscall.SyscallN(
method,
uintptr(unsafe.Pointer(abi)),
words[0],
words[1],
)
hr = wingoes.HRESULT(rc)
} else {
rc, _, _ := syscall.SyscallN(
method,
uintptr(unsafe.Pointer(abi)),
uintptr(newSize),
)
hr = wingoes.HRESULT(rc)
}
if e := wingoes.ErrorFromHRESULT(hr); e.Failed() {
return e
}
return nil
}
func (abi *IStreamABI) CopyTo(dest *IStreamABI, numBytesToCopy uint64) (bytesRead, bytesWritten uint64, _ error) {
var hr wingoes.HRESULT
method := unsafe.Slice(abi.Vtbl, 14)[7]
if runtime.GOARCH == "386" {
words := (*[2]uintptr)(unsafe.Pointer(&numBytesToCopy))
rc, _, _ := syscall.SyscallN(
method,
uintptr(unsafe.Pointer(abi)),
uintptr(unsafe.Pointer(dest)),
words[0],
words[1],
uintptr(unsafe.Pointer(&bytesRead)),
uintptr(unsafe.Pointer(&bytesWritten)),
)
hr = wingoes.HRESULT(rc)
} else {
rc, _, _ := syscall.SyscallN(
method,
uintptr(unsafe.Pointer(abi)),
uintptr(unsafe.Pointer(dest)),
uintptr(numBytesToCopy),
uintptr(unsafe.Pointer(&bytesRead)),
uintptr(unsafe.Pointer(&bytesWritten)),
)
hr = wingoes.HRESULT(rc)
}
if e := wingoes.ErrorFromHRESULT(hr); e.Failed() {
return bytesRead, bytesWritten, e
}
return bytesRead, bytesWritten, nil
}
func (abi *IStreamABI) Commit(flags STGC) error {
method := unsafe.Slice(abi.Vtbl, 14)[8]
rc, _, _ := syscall.SyscallN(
method,
uintptr(unsafe.Pointer(abi)),
uintptr(flags),
)
if e := wingoes.ErrorFromHRESULT(wingoes.HRESULT(rc)); e.Failed() {
return e
}
return nil
}
func (abi *IStreamABI) Revert() error {
method := unsafe.Slice(abi.Vtbl, 14)[9]
rc, _, _ := syscall.SyscallN(
method,
uintptr(unsafe.Pointer(abi)),
)
if e := wingoes.ErrorFromHRESULT(wingoes.HRESULT(rc)); e.Failed() {
return e
}
return nil
}
func (abi *IStreamABI) LockRegion(offset, numBytes uint64, lockType LOCKTYPE) error {
var hr wingoes.HRESULT
method := unsafe.Slice(abi.Vtbl, 14)[10]
if runtime.GOARCH == "386" {
oWords := (*[2]uintptr)(unsafe.Pointer(&offset))
nWords := (*[2]uintptr)(unsafe.Pointer(&numBytes))
rc, _, _ := syscall.SyscallN(
method,
uintptr(unsafe.Pointer(abi)),
oWords[0],
oWords[1],
nWords[0],
nWords[1],
uintptr(lockType),
)
hr = wingoes.HRESULT(rc)
} else {
rc, _, _ := syscall.SyscallN(
method,
uintptr(unsafe.Pointer(abi)),
uintptr(offset),
uintptr(numBytes),
uintptr(lockType),
)
hr = wingoes.HRESULT(rc)
}
if e := wingoes.ErrorFromHRESULT(hr); e.Failed() {
return e
}
return nil
}
func (abi *IStreamABI) UnlockRegion(offset, numBytes uint64, lockType LOCKTYPE) error {
var hr wingoes.HRESULT
method := unsafe.Slice(abi.Vtbl, 14)[11]
if runtime.GOARCH == "386" {
oWords := (*[2]uintptr)(unsafe.Pointer(&offset))
nWords := (*[2]uintptr)(unsafe.Pointer(&numBytes))
rc, _, _ := syscall.SyscallN(
method,
uintptr(unsafe.Pointer(abi)),
oWords[0],
oWords[1],
nWords[0],
nWords[1],
uintptr(lockType),
)
hr = wingoes.HRESULT(rc)
} else {
rc, _, _ := syscall.SyscallN(
method,
uintptr(unsafe.Pointer(abi)),
uintptr(offset),
uintptr(numBytes),
uintptr(lockType),
)
hr = wingoes.HRESULT(rc)
}
if e := wingoes.ErrorFromHRESULT(hr); e.Failed() {
return e
}
return nil
}
func (abi *IStreamABI) Stat(flags STATFLAG) (*STATSTG, error) {
result := new(STATSTG)
method := unsafe.Slice(abi.Vtbl, 14)[12]
rc, _, _ := syscall.SyscallN(
method,
uintptr(unsafe.Pointer(abi)),
uintptr(unsafe.Pointer(result)),
uintptr(flags),
)
if e := wingoes.ErrorFromHRESULT(wingoes.HRESULT(rc)); e.Failed() {
return nil, e
}
return result, nil
}
func (abi *IStreamABI) Clone() (result *IUnknownABI, _ error) {
method := unsafe.Slice(abi.Vtbl, 14)[13]
rc, _, _ := syscall.SyscallN(
method,
uintptr(unsafe.Pointer(abi)),
uintptr(unsafe.Pointer(&result)),
)
if e := wingoes.ErrorFromHRESULT(wingoes.HRESULT(rc)); e.Failed() {
return nil, e
}
return result, nil
}
func (o Stream) IID() *IID {
return IID_IStream
}
func (o Stream) Make(r ABIReceiver) any {
if r == nil {
return Stream{}
}
runtime.SetFinalizer(r, ReleaseABI)
pp := (**IStreamABI)(unsafe.Pointer(r))
return Stream{GenericObject[IStreamABI]{Pp: pp}}
}
func (o Stream) UnsafeUnwrap() *IStreamABI {
return *(o.Pp)
}
func (o Stream) Read(buf []byte) (int, error) {
p := *(o.Pp)
return p.Read(buf)
}
func (o Stream) Write(buf []byte) (int, error) {
p := *(o.Pp)
return p.Write(buf)
}
func (o Stream) Seek(offset int64, whence int) (n int64, _ error) {
p := *(o.Pp)
return p.Seek(offset, whence)
}
func (o Stream) SetSize(newSize uint64) error {
p := *(o.Pp)
return p.SetSize(newSize)
}
func (o Stream) CopyTo(dest Stream, numBytesToCopy uint64) (bytesRead, bytesWritten uint64, _ error) {
p := *(o.Pp)
return p.CopyTo(dest.UnsafeUnwrap(), numBytesToCopy)
}
func (o Stream) Commit(flags STGC) error {
p := *(o.Pp)
return p.Commit(flags)
}
func (o Stream) Revert() error {
p := *(o.Pp)
return p.Revert()
}
func (o Stream) LockRegion(offset, numBytes uint64, lockType LOCKTYPE) error {
p := *(o.Pp)
return p.LockRegion(offset, numBytes, lockType)
}
func (o Stream) UnlockRegion(offset, numBytes uint64, lockType LOCKTYPE) error {
p := *(o.Pp)
return p.UnlockRegion(offset, numBytes, lockType)
}
func (o Stream) Stat(flags STATFLAG) (*STATSTG, error) {
p := *(o.Pp)
return p.Stat(flags)
}
func (o Stream) Clone() (result Stream, _ error) {
p := *(o.Pp)
punk, err := p.Clone()
if err != nil {
return result, err
}
return result.Make(&punk).(Stream), nil
}
const hrE_OUTOFMEMORY = wingoes.HRESULT(-((0x8007000E ^ 0xFFFFFFFF) + 1))
// NewMemoryStream creates a new in-memory Stream object initially containing a
// copy of initialBytes. Its seek pointer is guaranteed to reference the
// beginning of the stream.
func NewMemoryStream(initialBytes []byte) (result Stream, _ error) {
return newMemoryStreamInternal(initialBytes, false)
}
func newMemoryStreamInternal(initialBytes []byte, forceLegacy bool) (result Stream, _ error) {
if len(initialBytes) > maxStreamRWLen {
return result, wingoes.ErrorFromHRESULT(hrE_OUTOFMEMORY)
}
// SHCreateMemStream exists on Win7 but is not safe for us to use until Win8.
if forceLegacy || !wingoes.IsWin8OrGreater() {
return newMemoryStreamLegacy(initialBytes)
}
var base *byte
var length uint32
if l := uint32(len(initialBytes)); l > 0 {
base = unsafe.SliceData(initialBytes)
length = l
}
punk := shCreateMemStream(base, length)
if punk == nil {
return result, wingoes.ErrorFromHRESULT(hrE_OUTOFMEMORY)
}
obj := result.Make(&punk).(Stream)
if _, err := obj.Seek(0, io.SeekStart); err != nil {
return result, err
}
return obj, nil
}
func newMemoryStreamLegacy(initialBytes []byte) (result Stream, _ error) {
ppstream := NewABIReceiver()
hr := createStreamOnHGlobal(internal.HGLOBAL(0), true, ppstream)
if e := wingoes.ErrorFromHRESULT(hr); e.Failed() {
return result, e
}
obj := result.Make(ppstream).(Stream)
if err := obj.SetSize(uint64(len(initialBytes))); err != nil {
return result, err
}
if len(initialBytes) == 0 {
return obj, nil
}
_, err := obj.Write(initialBytes)
if err != nil {
return result, err
}
if _, err := obj.Seek(0, io.SeekStart); err != nil {
return result, err
}
return obj, nil
}

13
vendor/github.com/dblohm7/wingoes/com/stream_not386.go generated vendored Normal file
View File

@@ -0,0 +1,13 @@
// Copyright (c) 2023 Tailscale Inc & AUTHORS. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build windows && !386
package com
import (
"math"
)
const maxStreamRWLen = math.MaxUint32

View File

@@ -0,0 +1,11 @@
// Copyright (c) 2023 Tailscale Inc & AUTHORS. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package com
import (
"math"
)
const maxStreamRWLen = math.MaxInt32

150
vendor/github.com/dblohm7/wingoes/com/types.go generated vendored Normal file
View File

@@ -0,0 +1,150 @@
// Copyright (c) 2022 Tailscale Inc & AUTHORS. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build windows
package com
import (
"unsafe"
"github.com/dblohm7/wingoes"
"golang.org/x/sys/windows"
)
type coMTAUsageCookie windows.Handle
type coCLSCTX uint32
const (
// We intentionally do not define combinations of these values, as in my experience
// people don't realize what they're doing when they use those.
coCLSCTX_INPROC_SERVER = coCLSCTX(0x1)
coCLSCTX_LOCAL_SERVER = coCLSCTX(0x4)
coCLSCTX_REMOTE_SERVER = coCLSCTX(0x10)
)
type coAPTTYPE int32
const (
coAPTTYPE_CURRENT = coAPTTYPE(-1)
coAPTTYPE_STA = coAPTTYPE(0)
coAPTTYPE_MTA = coAPTTYPE(1)
coAPTTYPE_NA = coAPTTYPE(2)
coAPTTYPE_MAINSTA = coAPTTYPE(3)
)
type coAPTTYPEQUALIFIER int32
const (
coAPTTYPEQUALIFIER_NONE = coAPTTYPEQUALIFIER(0)
coAPTTYPEQUALIFIER_IMPLICIT_MTA = coAPTTYPEQUALIFIER(1)
coAPTTYPEQUALIFIER_NA_ON_MTA = coAPTTYPEQUALIFIER(2)
coAPTTYPEQUALIFIER_NA_ON_STA = coAPTTYPEQUALIFIER(3)
coAPTTYPEQUALIFIER_NA_ON_IMPLICIT_MTA = coAPTTYPEQUALIFIER(4)
coAPTTYPEQUALIFIER_NA_ON_MAINSTA = coAPTTYPEQUALIFIER(5)
coAPTTYPEQUALIFIER_APPLICATION_STA = coAPTTYPEQUALIFIER(6)
)
type aptInfo struct {
apt coAPTTYPE
qualifier coAPTTYPEQUALIFIER
}
type soleAuthenticationInfo struct {
authnSvc uint32
authzSvc uint32
authInfo uintptr
}
type soleAuthenticationList struct {
count uint32
authInfo *soleAuthenticationInfo
}
type soleAuthenticationService struct {
authnSvc uint32
authzSvc uint32
principalName *uint16
hr wingoes.HRESULT
}
type authCapabilities uint32
const (
authCapNone = authCapabilities(0)
authCapMutualAuth = authCapabilities(1)
authCapSecureRefs = authCapabilities(2)
authCapAccessControl = authCapabilities(4)
authCapAppID = authCapabilities(8)
authCapDynamic = authCapabilities(0x10)
authCapStaticCloaking = authCapabilities(0x20)
authCapDynamicCloaking = authCapabilities(0x40)
authCapAnyAuthority = authCapabilities(0x80)
authCapMakeFullsic = authCapabilities(0x100)
authCapRequireFullsic = authCapabilities(0x200)
authCapAutoImpersonate = authCapabilities(0x400)
authCapDefault = authCapabilities(0x800)
authCapDisableAAA = authCapabilities(0x1000)
authCapNoCustomMarshal = authCapabilities(0x2000)
)
type rpcAuthnLevel uint32
const (
rpcAuthnLevelDefault = rpcAuthnLevel(0)
rpcAuthnLevelNone = rpcAuthnLevel(1)
rpcAuthnLevelConnect = rpcAuthnLevel(2)
rpcAuthnLevelCall = rpcAuthnLevel(3)
rpcAuthnLevelPkt = rpcAuthnLevel(4)
rpcAuthnLevelPktIntegrity = rpcAuthnLevel(5)
rpcAuthnLevelPkgPrivacy = rpcAuthnLevel(6)
)
type rpcImpersonationLevel uint32
const (
rpcImpLevelDefault = rpcImpersonationLevel(0)
rpcImpLevelAnonymous = rpcImpersonationLevel(1)
rpcImpLevelIdentify = rpcImpersonationLevel(2)
rpcImpLevelImpersonate = rpcImpersonationLevel(3)
rpcImpLevelDelegate = rpcImpersonationLevel(4)
)
// COMAllocatedString encapsulates a UTF-16 string that was allocated by COM
// using its internal heap.
type COMAllocatedString uintptr
// Close frees the memory held by the string.
func (s *COMAllocatedString) Close() error {
windows.CoTaskMemFree(unsafe.Pointer(*s))
*s = 0
return nil
}
func (s *COMAllocatedString) String() string {
return windows.UTF16PtrToString((*uint16)(unsafe.Pointer(*s)))
}
// UTF16 returns a slice containing a copy of the UTF-16 string, including a
// NUL terminator.
func (s *COMAllocatedString) UTF16() []uint16 {
p := (*uint16)(unsafe.Pointer(*s))
if p == nil {
return nil
}
n := 0
for ptr := unsafe.Pointer(p); *(*uint16)(ptr) != 0; n++ {
ptr = unsafe.Pointer(uintptr(ptr) + unsafe.Sizeof(*p))
}
// Make a copy, including the NUL terminator.
return append([]uint16{}, unsafe.Slice(p, n+1)...)
}
// UTF16Ptr returns a pointer to a NUL-terminated copy of the UTF-16 string.
func (s *COMAllocatedString) UTF16Ptr() *uint16 {
return unsafe.SliceData(s.UTF16())
}

44
vendor/github.com/dblohm7/wingoes/com/unknown.go generated vendored Normal file
View File

@@ -0,0 +1,44 @@
// Copyright (c) 2022 Tailscale Inc & AUTHORS. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build windows
package com
import (
"runtime"
)
var (
IID_IUnknown = &IID{0x00000000, 0x0000, 0x0000, [8]byte{0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}
)
// ObjectBase is a garbage-collected instance of any COM object's base interface.
type ObjectBase struct {
GenericObject[IUnknownABI]
}
// IID always returns IID_IUnknown.
func (o ObjectBase) IID() *IID {
return IID_IUnknown
}
// Make produces a new instance of ObjectBase that wraps r. Its return type is
// always ObjectBase.
func (o ObjectBase) Make(r ABIReceiver) any {
if r == nil {
return ObjectBase{}
}
runtime.SetFinalizer(r, ReleaseABI)
pp := (**IUnknownABI)(r)
return ObjectBase{GenericObject[IUnknownABI]{Pp: pp}}
}
// UnsafeUnwrap returns the underlying IUnknownABI of the object. As the name
// implies, this is unsafe -- you had better know what you are doing!
func (o ObjectBase) UnsafeUnwrap() *IUnknownABI {
return *(o.Pp)
}

View File

@@ -0,0 +1,106 @@
// Code generated by 'go generate'; DO NOT EDIT.
package com
import (
"syscall"
"unsafe"
"github.com/dblohm7/wingoes"
"github.com/dblohm7/wingoes/internal"
"golang.org/x/sys/windows"
)
var _ unsafe.Pointer
// Do the interface allocations only once for common
// Errno values.
const (
errnoERROR_IO_PENDING = 997
)
var (
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
errERROR_EINVAL error = syscall.EINVAL
)
// errnoErr returns common boxed Errno values, to prevent
// allocations at runtime.
func errnoErr(e syscall.Errno) error {
switch e {
case 0:
return errERROR_EINVAL
case errnoERROR_IO_PENDING:
return errERROR_IO_PENDING
}
// TODO: add more here, after collecting data on the common
// error values see on Windows. (perhaps when running
// all.bat?)
return e
}
var (
modole32 = windows.NewLazySystemDLL("ole32.dll")
modoleaut32 = windows.NewLazySystemDLL("oleaut32.dll")
modshlwapi = windows.NewLazySystemDLL("shlwapi.dll")
procCoCreateInstance = modole32.NewProc("CoCreateInstance")
procCoGetApartmentType = modole32.NewProc("CoGetApartmentType")
procCoIncrementMTAUsage = modole32.NewProc("CoIncrementMTAUsage")
procCoInitializeEx = modole32.NewProc("CoInitializeEx")
procCoInitializeSecurity = modole32.NewProc("CoInitializeSecurity")
procCreateStreamOnHGlobal = modole32.NewProc("CreateStreamOnHGlobal")
procSetOaNoCache = modoleaut32.NewProc("SetOaNoCache")
procSHCreateMemStream = modshlwapi.NewProc("SHCreateMemStream")
)
func coCreateInstance(clsid *CLSID, unkOuter *IUnknownABI, clsctx coCLSCTX, iid *IID, ppv **IUnknownABI) (hr wingoes.HRESULT) {
r0, _, _ := syscall.Syscall6(procCoCreateInstance.Addr(), 5, uintptr(unsafe.Pointer(clsid)), uintptr(unsafe.Pointer(unkOuter)), uintptr(clsctx), uintptr(unsafe.Pointer(iid)), uintptr(unsafe.Pointer(ppv)), 0)
hr = wingoes.HRESULT(r0)
return
}
func coGetApartmentType(aptType *coAPTTYPE, qual *coAPTTYPEQUALIFIER) (hr wingoes.HRESULT) {
r0, _, _ := syscall.Syscall(procCoGetApartmentType.Addr(), 2, uintptr(unsafe.Pointer(aptType)), uintptr(unsafe.Pointer(qual)), 0)
hr = wingoes.HRESULT(r0)
return
}
func coIncrementMTAUsage(cookie *coMTAUsageCookie) (hr wingoes.HRESULT) {
r0, _, _ := syscall.Syscall(procCoIncrementMTAUsage.Addr(), 1, uintptr(unsafe.Pointer(cookie)), 0, 0)
hr = wingoes.HRESULT(r0)
return
}
func coInitializeEx(reserved uintptr, flags uint32) (hr wingoes.HRESULT) {
r0, _, _ := syscall.Syscall(procCoInitializeEx.Addr(), 2, uintptr(reserved), uintptr(flags), 0)
hr = wingoes.HRESULT(r0)
return
}
func coInitializeSecurity(sd *windows.SECURITY_DESCRIPTOR, authSvcLen int32, authSvc *soleAuthenticationService, reserved1 uintptr, authnLevel rpcAuthnLevel, impLevel rpcImpersonationLevel, authList *soleAuthenticationList, capabilities authCapabilities, reserved2 uintptr) (hr wingoes.HRESULT) {
r0, _, _ := syscall.Syscall9(procCoInitializeSecurity.Addr(), 9, uintptr(unsafe.Pointer(sd)), uintptr(authSvcLen), uintptr(unsafe.Pointer(authSvc)), uintptr(reserved1), uintptr(authnLevel), uintptr(impLevel), uintptr(unsafe.Pointer(authList)), uintptr(capabilities), uintptr(reserved2))
hr = wingoes.HRESULT(r0)
return
}
func createStreamOnHGlobal(hglobal internal.HGLOBAL, deleteOnRelease bool, stream **IUnknownABI) (hr wingoes.HRESULT) {
var _p0 uint32
if deleteOnRelease {
_p0 = 1
}
r0, _, _ := syscall.Syscall(procCreateStreamOnHGlobal.Addr(), 3, uintptr(hglobal), uintptr(_p0), uintptr(unsafe.Pointer(stream)))
hr = wingoes.HRESULT(r0)
return
}
func setOaNoCache() {
syscall.Syscall(procSetOaNoCache.Addr(), 0, 0, 0, 0)
return
}
func shCreateMemStream(pInit *byte, cbInit uint32) (stream *IUnknownABI) {
r0, _, _ := syscall.Syscall(procSHCreateMemStream.Addr(), 2, uintptr(unsafe.Pointer(pInit)), uintptr(cbInit), 0)
stream = (*IUnknownABI)(unsafe.Pointer(r0))
return
}