Update dependencies
This commit is contained in:
140
vendor/github.com/dblohm7/wingoes/com/api.go
generated
vendored
Normal file
140
vendor/github.com/dblohm7/wingoes/com/api.go
generated
vendored
Normal 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)
|
||||
}
|
||||
7
vendor/github.com/dblohm7/wingoes/com/automation/automation.go
generated
vendored
Normal file
7
vendor/github.com/dblohm7/wingoes/com/automation/automation.go
generated
vendored
Normal 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
|
||||
14
vendor/github.com/dblohm7/wingoes/com/automation/mksyscall.go
generated
vendored
Normal file
14
vendor/github.com/dblohm7/wingoes/com/automation/mksyscall.go
generated
vendored
Normal 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
|
||||
93
vendor/github.com/dblohm7/wingoes/com/automation/types.go
generated
vendored
Normal file
93
vendor/github.com/dblohm7/wingoes/com/automation/types.go
generated
vendored
Normal 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
|
||||
}
|
||||
70
vendor/github.com/dblohm7/wingoes/com/automation/zsyscall_windows.go
generated
vendored
Normal file
70
vendor/github.com/dblohm7/wingoes/com/automation/zsyscall_windows.go
generated
vendored
Normal 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
9
vendor/github.com/dblohm7/wingoes/com/com.go
generated
vendored
Normal 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
120
vendor/github.com/dblohm7/wingoes/com/globalopts.go
generated
vendored
Normal 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
22
vendor/github.com/dblohm7/wingoes/com/guid.go
generated
vendored
Normal 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
112
vendor/github.com/dblohm7/wingoes/com/interface.go
generated
vendored
Normal 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
25
vendor/github.com/dblohm7/wingoes/com/mksyscall.go
generated
vendored
Normal 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
89
vendor/github.com/dblohm7/wingoes/com/object.go
generated
vendored
Normal 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
268
vendor/github.com/dblohm7/wingoes/com/process.go
generated
vendored
Normal 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
556
vendor/github.com/dblohm7/wingoes/com/stream.go
generated
vendored
Normal 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
13
vendor/github.com/dblohm7/wingoes/com/stream_not386.go
generated
vendored
Normal 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
|
||||
11
vendor/github.com/dblohm7/wingoes/com/stream_windows_386.go
generated
vendored
Normal file
11
vendor/github.com/dblohm7/wingoes/com/stream_windows_386.go
generated
vendored
Normal 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
150
vendor/github.com/dblohm7/wingoes/com/types.go
generated
vendored
Normal 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
44
vendor/github.com/dblohm7/wingoes/com/unknown.go
generated
vendored
Normal 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)
|
||||
}
|
||||
106
vendor/github.com/dblohm7/wingoes/com/zsyscall_windows.go
generated
vendored
Normal file
106
vendor/github.com/dblohm7/wingoes/com/zsyscall_windows.go
generated
vendored
Normal 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
|
||||
}
|
||||
Reference in New Issue
Block a user