You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
203 lines
5.8 KiB
203 lines
5.8 KiB
// Copyright 2010-2012 The W32 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 w32 |
|
|
|
import ( |
|
"syscall" |
|
"unicode/utf16" |
|
"unsafe" |
|
) |
|
|
|
func MakeIntResource(id uint16) *uint16 { |
|
return (*uint16)(unsafe.Pointer(uintptr(id))) |
|
} |
|
|
|
func LOWORD(dw uint32) uint16 { |
|
return uint16(dw) |
|
} |
|
|
|
func HIWORD(dw uint32) uint16 { |
|
return uint16(dw >> 16 & 0xffff) |
|
} |
|
|
|
func BoolToBOOL(value bool) BOOL { |
|
if value { |
|
return 1 |
|
} |
|
|
|
return 0 |
|
} |
|
|
|
func UTF16PtrToString(cstr *uint16) string { |
|
if cstr != nil { |
|
us := make([]uint16, 0, 256) |
|
for p := uintptr(unsafe.Pointer(cstr)); ; p += 2 { |
|
u := *(*uint16)(unsafe.Pointer(p)) |
|
if u == 0 { |
|
return string(utf16.Decode(us)) |
|
} |
|
us = append(us, u) |
|
} |
|
} |
|
|
|
return "" |
|
} |
|
|
|
func ComAddRef(unknown *IUnknown) int32 { |
|
ret, _, _ := syscall.Syscall(unknown.lpVtbl.pAddRef, 1, |
|
uintptr(unsafe.Pointer(unknown)), |
|
0, |
|
0) |
|
return int32(ret) |
|
} |
|
|
|
func ComRelease(unknown *IUnknown) int32 { |
|
ret, _, _ := syscall.Syscall(unknown.lpVtbl.pRelease, 1, |
|
uintptr(unsafe.Pointer(unknown)), |
|
0, |
|
0) |
|
return int32(ret) |
|
} |
|
|
|
func ComQueryInterface(unknown *IUnknown, id *GUID) *IDispatch { |
|
var disp *IDispatch |
|
hr, _, _ := syscall.Syscall(unknown.lpVtbl.pQueryInterface, 3, |
|
uintptr(unsafe.Pointer(unknown)), |
|
uintptr(unsafe.Pointer(id)), |
|
uintptr(unsafe.Pointer(&disp))) |
|
if hr != 0 { |
|
panic("Invoke QieryInterface error.") |
|
} |
|
return disp |
|
} |
|
|
|
func ComGetIDsOfName(disp *IDispatch, names []string) []int32 { |
|
wnames := make([]*uint16, len(names)) |
|
dispid := make([]int32, len(names)) |
|
for i := 0; i < len(names); i++ { |
|
wnames[i] = syscall.StringToUTF16Ptr(names[i]) |
|
} |
|
hr, _, _ := syscall.Syscall6(disp.lpVtbl.pGetIDsOfNames, 6, |
|
uintptr(unsafe.Pointer(disp)), |
|
uintptr(unsafe.Pointer(IID_NULL)), |
|
uintptr(unsafe.Pointer(&wnames[0])), |
|
uintptr(len(names)), |
|
uintptr(GetUserDefaultLCID()), |
|
uintptr(unsafe.Pointer(&dispid[0]))) |
|
if hr != 0 { |
|
panic("Invoke GetIDsOfName error.") |
|
} |
|
return dispid |
|
} |
|
|
|
func ComInvoke(disp *IDispatch, dispid int32, dispatch int16, params ...interface{}) (result *VARIANT) { |
|
var dispparams DISPPARAMS |
|
|
|
if dispatch&DISPATCH_PROPERTYPUT != 0 { |
|
dispnames := [1]int32{DISPID_PROPERTYPUT} |
|
dispparams.RgdispidNamedArgs = uintptr(unsafe.Pointer(&dispnames[0])) |
|
dispparams.CNamedArgs = 1 |
|
} |
|
var vargs []VARIANT |
|
if len(params) > 0 { |
|
vargs = make([]VARIANT, len(params)) |
|
for i, v := range params { |
|
//n := len(params)-i-1 |
|
n := len(params) - i - 1 |
|
VariantInit(&vargs[n]) |
|
switch v.(type) { |
|
case bool: |
|
if v.(bool) { |
|
vargs[n] = VARIANT{VT_BOOL, 0, 0, 0, 0xffff} |
|
} else { |
|
vargs[n] = VARIANT{VT_BOOL, 0, 0, 0, 0} |
|
} |
|
case *bool: |
|
vargs[n] = VARIANT{VT_BOOL | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*bool))))} |
|
case byte: |
|
vargs[n] = VARIANT{VT_I1, 0, 0, 0, int64(v.(byte))} |
|
case *byte: |
|
vargs[n] = VARIANT{VT_I1 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*byte))))} |
|
case int16: |
|
vargs[n] = VARIANT{VT_I2, 0, 0, 0, int64(v.(int16))} |
|
case *int16: |
|
vargs[n] = VARIANT{VT_I2 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int16))))} |
|
case uint16: |
|
vargs[n] = VARIANT{VT_UI2, 0, 0, 0, int64(v.(int16))} |
|
case *uint16: |
|
vargs[n] = VARIANT{VT_UI2 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint16))))} |
|
case int, int32: |
|
vargs[n] = VARIANT{VT_UI4, 0, 0, 0, int64(v.(int))} |
|
case *int, *int32: |
|
vargs[n] = VARIANT{VT_I4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int))))} |
|
case uint, uint32: |
|
vargs[n] = VARIANT{VT_UI4, 0, 0, 0, int64(v.(uint))} |
|
case *uint, *uint32: |
|
vargs[n] = VARIANT{VT_UI4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint))))} |
|
case int64: |
|
vargs[n] = VARIANT{VT_I8, 0, 0, 0, v.(int64)} |
|
case *int64: |
|
vargs[n] = VARIANT{VT_I8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int64))))} |
|
case uint64: |
|
vargs[n] = VARIANT{VT_UI8, 0, 0, 0, int64(v.(uint64))} |
|
case *uint64: |
|
vargs[n] = VARIANT{VT_UI8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint64))))} |
|
case float32: |
|
vargs[n] = VARIANT{VT_R4, 0, 0, 0, int64(v.(float32))} |
|
case *float32: |
|
vargs[n] = VARIANT{VT_R4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*float32))))} |
|
case float64: |
|
vargs[n] = VARIANT{VT_R8, 0, 0, 0, int64(v.(float64))} |
|
case *float64: |
|
vargs[n] = VARIANT{VT_R8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*float64))))} |
|
case string: |
|
vargs[n] = VARIANT{VT_BSTR, 0, 0, 0, int64(uintptr(unsafe.Pointer(SysAllocString(v.(string)))))} |
|
case *string: |
|
vargs[n] = VARIANT{VT_BSTR | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*string))))} |
|
case *IDispatch: |
|
vargs[n] = VARIANT{VT_DISPATCH, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*IDispatch))))} |
|
case **IDispatch: |
|
vargs[n] = VARIANT{VT_DISPATCH | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(**IDispatch))))} |
|
case nil: |
|
vargs[n] = VARIANT{VT_NULL, 0, 0, 0, 0} |
|
case *VARIANT: |
|
vargs[n] = VARIANT{VT_VARIANT | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*VARIANT))))} |
|
default: |
|
panic("unknown type") |
|
} |
|
} |
|
dispparams.Rgvarg = uintptr(unsafe.Pointer(&vargs[0])) |
|
dispparams.CArgs = uint32(len(params)) |
|
} |
|
|
|
var ret VARIANT |
|
var excepInfo EXCEPINFO |
|
VariantInit(&ret) |
|
hr, _, _ := syscall.Syscall9(disp.lpVtbl.pInvoke, 8, |
|
uintptr(unsafe.Pointer(disp)), |
|
uintptr(dispid), |
|
uintptr(unsafe.Pointer(IID_NULL)), |
|
uintptr(GetUserDefaultLCID()), |
|
uintptr(dispatch), |
|
uintptr(unsafe.Pointer(&dispparams)), |
|
uintptr(unsafe.Pointer(&ret)), |
|
uintptr(unsafe.Pointer(&excepInfo)), |
|
0) |
|
if hr != 0 { |
|
if excepInfo.BstrDescription != nil { |
|
bs := UTF16PtrToString(excepInfo.BstrDescription) |
|
panic(bs) |
|
} |
|
} |
|
for _, varg := range vargs { |
|
if varg.VT == VT_BSTR && varg.Val != 0 { |
|
SysFreeString(((*int16)(unsafe.Pointer(uintptr(varg.Val))))) |
|
} |
|
} |
|
result = &ret |
|
return |
|
}
|
|
|