// Copyright 2010 The win Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build windows package win import ( "fmt" "golang.org/x/sys/windows" "syscall" "unsafe" ) type DISPID int32 const ( DISPID_BEFORENAVIGATE DISPID = 100 DISPID_NAVIGATECOMPLETE DISPID = 101 DISPID_STATUSTEXTCHANGE DISPID = 102 DISPID_QUIT DISPID = 103 DISPID_DOWNLOADCOMPLETE DISPID = 104 DISPID_COMMANDSTATECHANGE DISPID = 105 DISPID_DOWNLOADBEGIN DISPID = 106 DISPID_NEWWINDOW DISPID = 107 DISPID_PROGRESSCHANGE DISPID = 108 DISPID_WINDOWMOVE DISPID = 109 DISPID_WINDOWRESIZE DISPID = 110 DISPID_WINDOWACTIVATE DISPID = 111 DISPID_PROPERTYCHANGE DISPID = 112 DISPID_TITLECHANGE DISPID = 113 DISPID_TITLEICONCHANGE DISPID = 114 DISPID_FRAMEBEFORENAVIGATE DISPID = 200 DISPID_FRAMENAVIGATECOMPLETE DISPID = 201 DISPID_FRAMENEWWINDOW DISPID = 204 DISPID_BEFORENAVIGATE2 DISPID = 250 DISPID_NEWWINDOW2 DISPID = 251 DISPID_NAVIGATECOMPLETE2 DISPID = 252 DISPID_ONQUIT DISPID = 253 DISPID_ONVISIBLE DISPID = 254 DISPID_ONTOOLBAR DISPID = 255 DISPID_ONMENUBAR DISPID = 256 DISPID_ONSTATUSBAR DISPID = 257 DISPID_ONFULLSCREEN DISPID = 258 DISPID_DOCUMENTCOMPLETE DISPID = 259 DISPID_ONTHEATERMODE DISPID = 260 DISPID_ONADDRESSBAR DISPID = 261 DISPID_WINDOWSETRESIZABLE DISPID = 262 DISPID_WINDOWCLOSING DISPID = 263 DISPID_WINDOWSETLEFT DISPID = 264 DISPID_WINDOWSETTOP DISPID = 265 DISPID_WINDOWSETWIDTH DISPID = 266 DISPID_WINDOWSETHEIGHT DISPID = 267 DISPID_CLIENTTOHOSTWINDOW DISPID = 268 DISPID_SETSECURELOCKICON DISPID = 269 DISPID_FILEDOWNLOAD DISPID = 270 DISPID_NAVIGATEERROR DISPID = 271 DISPID_PRIVACYIMPACTEDSTATECHANGE DISPID = 272 DISPID_NEWWINDOW3 DISPID = 273 ) var ( IID_IDispatch = IID{0x00020400, 0x0000, 0x0000, [8]byte{0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}} ) const ( DISP_E_MEMBERNOTFOUND = 0x80020003 ) const ( CSC_UPDATECOMMANDS = ^0x0 CSC_NAVIGATEFORWARD = 0x1 CSC_NAVIGATEBACK = 0x2 ) type IDispatchVtbl struct { QueryInterface uintptr AddRef uintptr Release uintptr GetTypeInfoCount uintptr GetTypeInfo uintptr GetIDsOfNames uintptr Invoke uintptr } type IDispatch struct { LpVtbl *IDispatchVtbl } type VARTYPE uint16 const ( VT_EMPTY VARTYPE = 0 VT_NULL VARTYPE = 1 VT_I2 VARTYPE = 2 VT_I4 VARTYPE = 3 VT_R4 VARTYPE = 4 VT_R8 VARTYPE = 5 VT_CY VARTYPE = 6 VT_DATE VARTYPE = 7 VT_BSTR VARTYPE = 8 VT_DISPATCH VARTYPE = 9 VT_ERROR VARTYPE = 10 VT_BOOL VARTYPE = 11 VT_VARIANT VARTYPE = 12 VT_UNKNOWN VARTYPE = 13 VT_DECIMAL VARTYPE = 14 VT_I1 VARTYPE = 16 VT_UI1 VARTYPE = 17 VT_UI2 VARTYPE = 18 VT_UI4 VARTYPE = 19 VT_I8 VARTYPE = 20 VT_UI8 VARTYPE = 21 VT_INT VARTYPE = 22 VT_UINT VARTYPE = 23 VT_VOID VARTYPE = 24 VT_HRESULT VARTYPE = 25 VT_PTR VARTYPE = 26 VT_SAFEARRAY VARTYPE = 27 VT_CARRAY VARTYPE = 28 VT_USERDEFINED VARTYPE = 29 VT_LPSTR VARTYPE = 30 VT_LPWSTR VARTYPE = 31 VT_RECORD VARTYPE = 36 VT_INT_PTR VARTYPE = 37 VT_UINT_PTR VARTYPE = 38 VT_FILETIME VARTYPE = 64 VT_BLOB VARTYPE = 65 VT_STREAM VARTYPE = 66 VT_STORAGE VARTYPE = 67 VT_STREAMED_OBJECT VARTYPE = 68 VT_STORED_OBJECT VARTYPE = 69 VT_BLOB_OBJECT VARTYPE = 70 VT_CF VARTYPE = 71 VT_CLSID VARTYPE = 72 VT_VERSIONED_STREAM VARTYPE = 73 VT_BSTR_BLOB VARTYPE = 0xfff VT_VECTOR VARTYPE = 0x1000 VT_ARRAY VARTYPE = 0x2000 VT_BYREF VARTYPE = 0x4000 VT_RESERVED VARTYPE = 0x8000 VT_ILLEGAL VARTYPE = 0xffff VT_ILLEGALMASKED VARTYPE = 0xfff VT_TYPEMASK VARTYPE = 0xfff ) type VARIANTARG struct { VARIANT } type VARIANT_BOOL int16 const ( VARIANT_TRUE VARIANT_BOOL = -1 VARIANT_FALSE VARIANT_BOOL = 0 ) type SAFEARRAYBOUND struct { CElements uint32 LLbound int32 } type SAFEARRAY struct { CDims uint16 FFeatures uint16 CbElements uint32 CLocks uint32 PvData uintptr Rgsabound [1]SAFEARRAYBOUND } //type BSTR *uint16 func StringToBSTR(value string) *uint16 /*BSTR*/ { // IMPORTANT: Don't forget to free the BSTR value when no longer needed! return SysAllocString(value) } func BSTRToString(value *uint16 /*BSTR*/) string { // ISSUE: Is this really ok? bstrArrPtr := (*[200000000]uint16)(unsafe.Pointer(value)) bstrSlice := make([]uint16, SysStringLen(value)) copy(bstrSlice, bstrArrPtr[:]) return syscall.UTF16ToString(bstrSlice) } func IntToVariantI4(value int32) *VAR_I4 { return &VAR_I4{vt: VT_I4, lVal: value} } func VariantI4ToInt(value *VAR_I4) int32 { return value.lVal } func BoolToVariantBool(value bool) *VAR_BOOL { return &VAR_BOOL{vt: VT_BOOL, boolVal: VARIANT_BOOL(BoolToBOOL(value))} } func VariantBoolToBool(value *VAR_BOOL) bool { return value.boolVal != 0 } func StringToVariantBSTR(value string) *VAR_BSTR { // IMPORTANT: Don't forget to free the BSTR value when no longer needed! return &VAR_BSTR{vt: VT_BSTR, bstrVal: StringToBSTR(value)} } func VariantBSTRToString(value *VAR_BSTR) string { return BSTRToString(value.bstrVal) } func (v *VARIANT) MustLong() int32 { value, err := v.Long() if err != nil { panic(err) } return value } func (v *VARIANT) Long() (int32, error) { if v.Vt != VT_I4 { return 0, fmt.Errorf("Error: Long() v.Vt != VT_I4, ptr=%p, value=%+v", v, v) } p := (*VAR_I4)(unsafe.Pointer(v)) return p.lVal, nil } func (v *VARIANT) SetLong(value int32) { v.Vt = VT_I4 p := (*VAR_I4)(unsafe.Pointer(v)) p.lVal = value } func (v *VARIANT) MustULong() uint32 { value, err := v.ULong() if err != nil { panic(err) } return value } func (v *VARIANT) ULong() (uint32, error) { if v.Vt != VT_UI4 { return 0, fmt.Errorf("Error: ULong() v.Vt != VT_UI4, ptr=%p, value=%+v", v, v) } p := (*VAR_UI4)(unsafe.Pointer(v)) return p.ulVal, nil } func (v *VARIANT) SetULong(value uint32) { v.Vt = VT_UI4 p := (*VAR_UI4)(unsafe.Pointer(v)) p.ulVal = value } func (v *VARIANT) MustBool() VARIANT_BOOL { value, err := v.Bool() if err != nil { panic(err) } return value } func (v *VARIANT) Bool() (VARIANT_BOOL, error) { if v.Vt != VT_BOOL { return VARIANT_FALSE, fmt.Errorf("Error: Bool() v.Vt != VT_BOOL, ptr=%p, value=%+v", v, v) } p := (*VAR_BOOL)(unsafe.Pointer(v)) return p.boolVal, nil } func (v *VARIANT) SetBool(value VARIANT_BOOL) { v.Vt = VT_BOOL p := (*VAR_BOOL)(unsafe.Pointer(v)) p.boolVal = value } func (v *VARIANT) MustBSTR() *uint16 { value, err := v.BSTR() if err != nil { panic(err) } return value } func (v *VARIANT) BSTR() (*uint16, error) { if v.Vt != VT_BSTR { return nil, fmt.Errorf("Error: BSTR() v.Vt != VT_BSTR, ptr=%p, value=%+v", v, v) } p := (*VAR_BSTR)(unsafe.Pointer(v)) return p.bstrVal, nil } func (v *VARIANT) SetBSTR(value *uint16) { v.Vt = VT_BSTR p := (*VAR_BSTR)(unsafe.Pointer(v)) p.bstrVal = value } func (v *VARIANT) MustPDispatch() *IDispatch { value, err := v.PDispatch() if err != nil { panic(err) } return value } func (v *VARIANT) PDispatch() (*IDispatch, error) { if v.Vt != VT_DISPATCH { return nil, fmt.Errorf("Error: PDispatch() v.Vt != VT_DISPATCH, ptr=%p, value=%+v", v, v) } p := (*VAR_PDISP)(unsafe.Pointer(v)) return p.pdispVal, nil } func (v *VARIANT) SetPDispatch(value *IDispatch) { v.Vt = VT_DISPATCH p := (*VAR_PDISP)(unsafe.Pointer(v)) p.pdispVal = value } func (v *VARIANT) MustPVariant() *VARIANT { value, err := v.PVariant() if err != nil { panic(err) } return value } func (v *VARIANT) PVariant() (*VARIANT, error) { if v.Vt != VT_BYREF|VT_VARIANT { return nil, fmt.Errorf("Error: PVariant() v.Vt != VT_BYREF|VT_VARIANT, ptr=%p, value=%+v", v, v) } p := (*VAR_PVAR)(unsafe.Pointer(v)) return p.pvarVal, nil } func (v *VARIANT) SetPVariant(value *VARIANT) { v.Vt = VT_BYREF | VT_VARIANT p := (*VAR_PVAR)(unsafe.Pointer(v)) p.pvarVal = value } func (v *VARIANT) MustPBool() *VARIANT_BOOL { value, err := v.PBool() if err != nil { panic(err) } return value } func (v *VARIANT) PBool() (*VARIANT_BOOL, error) { if v.Vt != VT_BYREF|VT_BOOL { return nil, fmt.Errorf("Error: PBool() v.Vt != VT_BYREF|VT_BOOL, ptr=%p, value=%+v", v, v) } p := (*VAR_PBOOL)(unsafe.Pointer(v)) return p.pboolVal, nil } func (v *VARIANT) SetPBool(value *VARIANT_BOOL) { v.Vt = VT_BYREF | VT_BOOL p := (*VAR_PBOOL)(unsafe.Pointer(v)) p.pboolVal = value } func (v *VARIANT) MustPPDispatch() **IDispatch { value, err := v.PPDispatch() if err != nil { panic(err) } return value } func (v *VARIANT) PPDispatch() (**IDispatch, error) { if v.Vt != VT_BYREF|VT_DISPATCH { return nil, fmt.Errorf("PPDispatch() v.Vt != VT_BYREF|VT_DISPATCH, ptr=%p, value=%+v", v, v) } p := (*VAR_PPDISP)(unsafe.Pointer(v)) return p.ppdispVal, nil } func (v *VARIANT) SetPPDispatch(value **IDispatch) { v.Vt = VT_BYREF | VT_DISPATCH p := (*VAR_PPDISP)(unsafe.Pointer(v)) p.ppdispVal = value } func (v *VARIANT) MustPSafeArray() *SAFEARRAY { value, err := v.PSafeArray() if err != nil { panic(err) } return value } func (v *VARIANT) PSafeArray() (*SAFEARRAY, error) { if (v.Vt & VT_ARRAY) != VT_ARRAY { return nil, fmt.Errorf("Error: PSafeArray() (v.Vt & VT_ARRAY) != VT_ARRAY, ptr=%p, value=%+v", v, v) } p := (*VAR_PSAFEARRAY)(unsafe.Pointer(v)) return p.parray, nil } func (v *VARIANT) SetPSafeArray(value *SAFEARRAY, elementVt VARTYPE) { v.Vt = VT_ARRAY | elementVt p := (*VAR_PSAFEARRAY)(unsafe.Pointer(v)) p.parray = value } type DISPPARAMS struct { Rgvarg *VARIANTARG RgdispidNamedArgs *DISPID CArgs int32 CNamedArgs int32 } var ( // Library liboleaut32 *windows.LazyDLL // Functions sysAllocString *windows.LazyProc sysFreeString *windows.LazyProc sysStringLen *windows.LazyProc ) func init() { // Library liboleaut32 = windows.NewLazySystemDLL("oleaut32.dll") // Functions sysAllocString = liboleaut32.NewProc("SysAllocString") sysFreeString = liboleaut32.NewProc("SysFreeString") sysStringLen = liboleaut32.NewProc("SysStringLen") } func SysAllocString(s string) *uint16 /*BSTR*/ { ret, _, _ := syscall.Syscall(sysAllocString.Addr(), 1, uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(s))), 0, 0) return (*uint16) /*BSTR*/ (unsafe.Pointer(ret)) } func SysFreeString(bstr *uint16 /*BSTR*/) { syscall.Syscall(sysFreeString.Addr(), 1, uintptr(unsafe.Pointer(bstr)), 0, 0) } func SysStringLen(bstr *uint16 /*BSTR*/) uint32 { ret, _, _ := syscall.Syscall(sysStringLen.Addr(), 1, uintptr(unsafe.Pointer(bstr)), 0, 0) return uint32(ret) }