github.com/hspan/go-ole@v0.0.0/idispatch_windows.go (about)

     1  // +build windows
     2  
     3  package ole
     4  
     5  import (
     6  	"math/big"
     7  	"syscall"
     8  	"time"
     9  	"unsafe"
    10  )
    11  
    12  func getIDsOfName(disp *IDispatch, names []string) (dispid []int32, err error) {
    13  	wnames := make([]*uint16, len(names))
    14  	for i := 0; i < len(names); i++ {
    15  		wnames[i] = syscall.StringToUTF16Ptr(names[i])
    16  	}
    17  	dispid = make([]int32, len(names))
    18  	namelen := uint32(len(names))
    19  	hr, _, _ := syscall.Syscall6(
    20  		disp.VTable().GetIDsOfNames,
    21  		6,
    22  		uintptr(unsafe.Pointer(disp)),
    23  		uintptr(unsafe.Pointer(IID_NULL)),
    24  		uintptr(unsafe.Pointer(&wnames[0])),
    25  		uintptr(namelen),
    26  		uintptr(GetUserDefaultLCID()),
    27  		uintptr(unsafe.Pointer(&dispid[0])))
    28  	if hr != 0 {
    29  		err = NewError(hr)
    30  	}
    31  	return
    32  }
    33  
    34  func getTypeInfoCount(disp *IDispatch) (c uint32, err error) {
    35  	hr, _, _ := syscall.Syscall(
    36  		disp.VTable().GetTypeInfoCount,
    37  		2,
    38  		uintptr(unsafe.Pointer(disp)),
    39  		uintptr(unsafe.Pointer(&c)),
    40  		0)
    41  	if hr != 0 {
    42  		err = NewError(hr)
    43  	}
    44  	return
    45  }
    46  
    47  func getTypeInfo(disp *IDispatch) (tinfo *ITypeInfo, err error) {
    48  	hr, _, _ := syscall.Syscall(
    49  		disp.VTable().GetTypeInfo,
    50  		3,
    51  		uintptr(unsafe.Pointer(disp)),
    52  		uintptr(GetUserDefaultLCID()),
    53  		uintptr(unsafe.Pointer(&tinfo)))
    54  	if hr != 0 {
    55  		err = NewError(hr)
    56  	}
    57  	return
    58  }
    59  
    60  func invoke(disp *IDispatch, dispid int32, dispatch int16, params ...interface{}) (result *VARIANT, err error) {
    61  	var dispparams DISPPARAMS
    62  
    63  	if dispatch&DISPATCH_PROPERTYPUT != 0 {
    64  		dispnames := [1]int32{DISPID_PROPERTYPUT}
    65  		dispparams.rgdispidNamedArgs = uintptr(unsafe.Pointer(&dispnames[0]))
    66  		dispparams.cNamedArgs = 1
    67  	} else if dispatch&DISPATCH_PROPERTYPUTREF != 0 {
    68  		dispnames := [1]int32{DISPID_PROPERTYPUT}
    69  		dispparams.rgdispidNamedArgs = uintptr(unsafe.Pointer(&dispnames[0]))
    70  		dispparams.cNamedArgs = 1
    71  	}
    72  	var vargs []VARIANT
    73  	if len(params) > 0 {
    74  		vargs = make([]VARIANT, len(params))
    75  		for i, v := range params {
    76  			//n := len(params)-i-1
    77  			n := len(params) - i - 1
    78  			VariantInit(&vargs[n])
    79  			switch vv := v.(type) {
    80  			case bool:
    81  				if vv {
    82  					vargs[n] = NewVariant(VT_BOOL, 0xffff)
    83  				} else {
    84  					vargs[n] = NewVariant(VT_BOOL, 0)
    85  				}
    86  			case *bool:
    87  				vargs[n] = NewVariant(VT_BOOL|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*bool)))))
    88  			case uint8:
    89  				vargs[n] = NewVariant(VT_I1, int64(v.(uint8)))
    90  			case *uint8:
    91  				vargs[n] = NewVariant(VT_I1|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint8)))))
    92  			case int8:
    93  				vargs[n] = NewVariant(VT_I1, int64(v.(int8)))
    94  			case *int8:
    95  				vargs[n] = NewVariant(VT_I1|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint8)))))
    96  			case int16:
    97  				vargs[n] = NewVariant(VT_I2, int64(v.(int16)))
    98  			case *int16:
    99  				vargs[n] = NewVariant(VT_I2|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int16)))))
   100  			case uint16:
   101  				vargs[n] = NewVariant(VT_UI2, int64(v.(uint16)))
   102  			case *uint16:
   103  				vargs[n] = NewVariant(VT_UI2|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint16)))))
   104  			case int32:
   105  				vargs[n] = NewVariant(VT_I4, int64(v.(int32)))
   106  			case *int32:
   107  				vargs[n] = NewVariant(VT_I4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int32)))))
   108  			case uint32:
   109  				vargs[n] = NewVariant(VT_UI4, int64(v.(uint32)))
   110  			case *uint32:
   111  				vargs[n] = NewVariant(VT_UI4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint32)))))
   112  			case int64:
   113  				vargs[n] = NewVariant(VT_I8, int64(v.(int64)))
   114  			case *int64:
   115  				vargs[n] = NewVariant(VT_I8|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int64)))))
   116  			case uint64:
   117  				vargs[n] = NewVariant(VT_UI8, int64(uintptr(v.(uint64))))
   118  			case *uint64:
   119  				vargs[n] = NewVariant(VT_UI8|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint64)))))
   120  			case int:
   121  				vargs[n] = NewVariant(VT_I4, int64(v.(int)))
   122  			case *int:
   123  				vargs[n] = NewVariant(VT_I4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*int)))))
   124  			case uint:
   125  				vargs[n] = NewVariant(VT_UI4, int64(v.(uint)))
   126  			case *uint:
   127  				vargs[n] = NewVariant(VT_UI4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*uint)))))
   128  			case float32:
   129  				vargs[n] = NewVariant(VT_R4, *(*int64)(unsafe.Pointer(&vv)))
   130  			case *float32:
   131  				vargs[n] = NewVariant(VT_R4|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*float32)))))
   132  			case float64:
   133  				vargs[n] = NewVariant(VT_R8, *(*int64)(unsafe.Pointer(&vv)))
   134  			case *float64:
   135  				vargs[n] = NewVariant(VT_R8|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*float64)))))
   136  			case *big.Int:
   137  				vargs[n] = NewVariant(VT_DECIMAL, v.(*big.Int).Int64())
   138  			case string:
   139  				vargs[n] = NewVariant(VT_BSTR, int64(uintptr(unsafe.Pointer(SysAllocStringLen(v.(string))))))
   140  			case *string:
   141  				vargs[n] = NewVariant(VT_BSTR|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*string)))))
   142  			case time.Time:
   143  				s := vv.Format("2006-01-02 15:04:05")
   144  				vargs[n] = NewVariant(VT_BSTR, int64(uintptr(unsafe.Pointer(SysAllocStringLen(s)))))
   145  			case *time.Time:
   146  				s := vv.Format("2006-01-02 15:04:05")
   147  				vargs[n] = NewVariant(VT_BSTR|VT_BYREF, int64(uintptr(unsafe.Pointer(&s))))
   148  			case *IDispatch:
   149  				vargs[n] = NewVariant(VT_DISPATCH, int64(uintptr(unsafe.Pointer(v.(*IDispatch)))))
   150  			case **IDispatch:
   151  				vargs[n] = NewVariant(VT_DISPATCH|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(**IDispatch)))))
   152  			case nil:
   153  				vargs[n] = NewVariant(VT_NULL, 0)
   154  			case *VARIANT:
   155  				vargs[n] = NewVariant(VT_VARIANT|VT_BYREF, int64(uintptr(unsafe.Pointer(v.(*VARIANT)))))
   156  			case []byte:
   157  				safeByteArray := safeArrayFromByteSlice(v.([]byte))
   158  				vargs[n] = NewVariant(VT_ARRAY|VT_UI1, int64(uintptr(unsafe.Pointer(safeByteArray))))
   159  				defer VariantClear(&vargs[n])
   160  			case []string:
   161  				safeByteArray := safeArrayFromStringSlice(v.([]string))
   162  				vargs[n] = NewVariant(VT_ARRAY|VT_BSTR, int64(uintptr(unsafe.Pointer(safeByteArray))))
   163  				defer VariantClear(&vargs[n])
   164  			case []int32:
   165  				safeByteArray := safeArrayFromInt32Slice(v.([]int32))
   166  				vargs[n] = NewVariant(VT_ARRAY|VT_I4, int64(uintptr(unsafe.Pointer(safeByteArray))))
   167  				defer VariantClear(&vargs[n])
   168  			default:
   169  				panic("unknown type")
   170  			}
   171  		}
   172  		dispparams.rgvarg = uintptr(unsafe.Pointer(&vargs[0]))
   173  		dispparams.cArgs = uint32(len(params))
   174  	}
   175  
   176  	result = new(VARIANT)
   177  	var excepInfo EXCEPINFO
   178  	VariantInit(result)
   179  	hr, _, _ := syscall.Syscall9(
   180  		disp.VTable().Invoke,
   181  		9,
   182  		uintptr(unsafe.Pointer(disp)),
   183  		uintptr(dispid),
   184  		uintptr(unsafe.Pointer(IID_NULL)),
   185  		uintptr(GetUserDefaultLCID()),
   186  		uintptr(dispatch),
   187  		uintptr(unsafe.Pointer(&dispparams)),
   188  		uintptr(unsafe.Pointer(result)),
   189  		uintptr(unsafe.Pointer(&excepInfo)),
   190  		0)
   191  	if hr != 0 {
   192  		err = NewErrorWithSubError(hr, BstrToString(excepInfo.bstrDescription), excepInfo)
   193  	}
   194  	for i, varg := range vargs {
   195  		n := len(params) - i - 1
   196  		if varg.VT == VT_BSTR && varg.Val != 0 {
   197  			SysFreeString(((*int16)(unsafe.Pointer(uintptr(varg.Val)))))
   198  		}
   199  		if varg.VT == (VT_BSTR|VT_BYREF) && varg.Val != 0 {
   200  			*(params[n].(*string)) = LpOleStrToString(*(**uint16)(unsafe.Pointer(uintptr(varg.Val))))
   201  		}
   202  	}
   203  	return
   204  }