github.com/scalingdata/go-ole@v1.2.0/idispatch_windows.go (about)

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