func getFriendlyName(portname string) string {

	// this method panics a lot and i'm not sure why, just catch
	// the panic and return empty list
	defer func() {
		if e := recover(); e != nil {
			// e is the interface{} typed-value we passed to panic()
			log.Println("Got panic: ", e) // Prints "Whoops: boom!"
		}
	}()

	var friendlyName string

	// init COM, oh yeah
	ole.CoInitialize(0)
	defer ole.CoUninitialize()

	unknown, _ := oleutil.CreateObject("WbemScripting.SWbemLocator")
	defer unknown.Release()

	wmi, _ := unknown.QueryInterface(ole.IID_IDispatch)
	defer wmi.Release()

	// service is a SWbemServices
	serviceRaw, _ := oleutil.CallMethod(wmi, "ConnectServer")
	service := serviceRaw.ToIDispatch()
	defer service.Release()

	// result is a SWBemObjectSet
	//pname := syscall.StringToUTF16("SELECT * FROM Win32_PnPEntity where Name like '%" + "COM35" + "%'")
	pname := "SELECT * FROM Win32_PnPEntity where Name like '%" + portname + "%'"
	resultRaw, _ := oleutil.CallMethod(service, "ExecQuery", pname)
	result := resultRaw.ToIDispatch()
	defer result.Release()

	countVar, _ := oleutil.GetProperty(result, "Count")
	count := int(countVar.Val)

	for i := 0; i < count; i++ {
		// item is a SWbemObject, but really a Win32_Process
		itemRaw, _ := oleutil.CallMethod(result, "ItemIndex", i)
		item := itemRaw.ToIDispatch()
		defer item.Release()

		asString, _ := oleutil.GetProperty(item, "Name")

		println(asString.ToString())
		friendlyName = asString.ToString()
	}

	return friendlyName
}
Exemple #2
0
func readExample(fileName string, excel, workbooks *ole.IDispatch) {
	workbook, err := oleutil.CallMethod(workbooks, "Open", fileName)

	if err != nil {
		log.Fatalln(err)
	}
	defer workbook.ToIDispatch().Release()

	sheets := oleutil.MustGetProperty(excel, "Sheets").ToIDispatch()
	sheetCount := (int)(oleutil.MustGetProperty(sheets, "Count").Val)
	fmt.Println("sheet count=", sheetCount)
	sheets.Release()

	worksheet := oleutil.MustGetProperty(workbook.ToIDispatch(), "Worksheets", 1).ToIDispatch()
	defer worksheet.Release()
	for row := 1; row <= 2; row++ {
		for col := 1; col <= 5; col++ {
			cell := oleutil.MustGetProperty(worksheet, "Cells", row, col).ToIDispatch()
			val, err := oleutil.GetProperty(cell, "Value")
			if err != nil {
				break
			}
			fmt.Printf("(%d,%d)=%+v toString=%s\n", col, row, val.Value(), val.ToString())
			cell.Release()
		}
	}
}
Exemple #3
0
func (c *AdodbConn) prepare(ctx context.Context, query string) (driver.Stmt, error) {
	unknown, err := oleutil.CreateObject("ADODB.Command")
	if err != nil {
		return nil, err
	}
	s, err := unknown.QueryInterface(ole.IID_IDispatch)
	if err != nil {
		return nil, err
	}
	_, err = oleutil.PutProperty(s, "ActiveConnection", c.db)
	if err != nil {
		return nil, err
	}
	_, err = oleutil.PutProperty(s, "CommandText", query)
	if err != nil {
		return nil, err
	}
	_, err = oleutil.PutProperty(s, "CommandType", 1)
	if err != nil {
		return nil, err
	}
	_, err = oleutil.PutProperty(s, "Prepared", true)
	if err != nil {
		return nil, err
	}
	val, err := oleutil.GetProperty(s, "Parameters")
	if err != nil {
		return nil, err
	}
	return &AdodbStmt{c, s, val.ToIDispatch(), nil}, nil
}
Exemple #4
0
func main() {
	ole.CoInitialize(0)
	unknown, _ := oleutil.CreateObject("Outlook.Application")
	outlook, _ := unknown.QueryInterface(ole.IID_IDispatch)
	ns := oleutil.MustCallMethod(outlook, "GetNamespace", "MAPI").ToIDispatch()
	folder := oleutil.MustCallMethod(ns, "GetDefaultFolder", 10).ToIDispatch()
	contacts := oleutil.MustCallMethod(folder, "Items").ToIDispatch()
	count := oleutil.MustGetProperty(contacts, "Count").Value().(int32)
	for i := 1; i <= int(count); i++ {
		item, err := oleutil.GetProperty(contacts, "Item", i)
		if err == nil && item.VT == ole.VT_DISPATCH {
			if value, err := oleutil.GetProperty(item.ToIDispatch(), "FullName"); err == nil {
				fmt.Println(value.Value())
			}
		}
	}
	oleutil.MustCallMethod(outlook, "Quit")
}
Exemple #5
0
func oleInt64(item *ole.IDispatch, prop string) (int64, error) {
	v, err := oleutil.GetProperty(item, prop)
	if err != nil {
		return 0, err
	}
	defer v.Clear()

	i := int64(v.Val)
	return i, nil
}
Exemple #6
0
func (rc *AdodbRows) Columns() []string {
	if rc.nc != len(rc.cols) {
		unknown, err := oleutil.GetProperty(rc.rc, "Fields")
		if err != nil {
			return []string{}
		}
		fields := unknown.ToIDispatch()
		defer fields.Release()
		val, err := oleutil.GetProperty(fields, "Count")
		if err != nil {
			return []string{}
		}
		rc.nc = int(val.Val)
		rc.cols = make([]string, rc.nc)
		for i := 0; i < rc.nc; i++ {
			var varval ole.VARIANT
			varval.VT = ole.VT_I4
			varval.Val = int64(i)
			val, err := oleutil.CallMethod(fields, "Item", &varval)
			if err != nil {
				return []string{}
			}
			item := val.ToIDispatch()
			if err != nil {
				return []string{}
			}
			name, err := oleutil.GetProperty(item, "Name")
			if err != nil {
				return []string{}
			}
			rc.cols[i] = name.ToString()
			item.Release()
		}
	}
	return rc.cols
}
Exemple #7
0
func (s *AdodbStmt) NumInput() int {
	if s.b != nil {
		return len(s.b)
	}
	_, err := oleutil.CallMethod(s.ps, "Refresh")
	if err != nil {
		return -1
	}
	val, err := oleutil.GetProperty(s.ps, "Count")
	if err != nil {
		return -1
	}
	c := int(val.Val)
	return c
}
Exemple #8
0
// NOTE:  This function will panic if called with high frequency (we should throttle the polling - probably caused by slow OLE calls that can't be parallel.. sigh ;))
func GetSerialPortList() ([]CommPort, error) {
	err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED)
	if err != nil {
		log.Fatal("Init error: ", err)
	}
	defer ole.CoUninitialize()

	unknown, _ := oleutil.CreateObject("WbemScripting.SWbemLocator")
	defer unknown.Release()

	wmi, _ := unknown.QueryInterface(ole.IID_IDispatch)
	defer wmi.Release()

	serviceRaw, _ := oleutil.CallMethod(wmi, "ConnectServer")
	service := serviceRaw.ToIDispatch()
	defer service.Release()

	query := "SELECT * FROM Win32_PnPEntity WHERE ConfigManagerErrorCode = 0 and Name like '%(COM%'"
	queryResult, err2 := oleutil.CallMethod(service, "ExecQuery", query)

	commPorts := []CommPort{}

	if err2 != nil {
		log.Printf("Error from oleutil.CallMethod: ", err2)
		return nil, err2
	}

	result := queryResult.ToIDispatch()
	defer result.Release()

	countVar, _ := oleutil.GetProperty(result, "Count")
	count := int(countVar.Val)

	// Should we filter on VID/PID here or later?
	for i := 0; i < count; i++ {
		itemRaw, _ := oleutil.CallMethod(result, "ItemIndex", i)
		item := itemRaw.ToIDispatch()
		defer item.Release()

		displayName, _ := oleutil.GetProperty(item, "Name")

		fmt.Printf("Port found: %s\n", displayName.ToString())

		re := regexp.MustCompile("\\((COM[0-9]+)\\)").FindAllStringSubmatch(displayName.ToString(), 1)

		var path string = ""

		if re != nil && len(re[0]) > 1 {
			path = re[0][1]
		}

		fmt.Printf("Path: %v\n", path)

		deviceId, _ := oleutil.GetProperty(item, "DeviceID")

		re = regexp.MustCompile("ID_(....)").FindAllStringSubmatch(deviceId.ToString(), 2)

		var VID, PID uint16 = 0, 0

		if re != nil && len(re) == 2 {
			if len(re[0]) > 1 {
				val, _ := strconv.ParseUint(re[0][1], 16, 16)
				VID = uint16(val)
			}
			if len(re[1]) > 1 {
				val, _ := strconv.ParseUint(re[1][1], 16, 16)
				PID = uint16(val)
			}
			fmt.Printf("VID: %v, PID: %v\n", VID, PID)
		}

		commPorts = append(commPorts, CommPort{Path: path, VendorId: VID, ProductId: PID, DisplayName: displayName.ToString()})

	}

	return commPorts, err
}
Exemple #9
0
func listComPorts() {
	// init COM
	ole.CoInitialize(0)
	defer ole.CoUninitialize()

	locator, err := oleutil.CreateObject("WbemScripting.SWbemLocator")
	if err != nil {
		log.Fatal(err)
	}
	defer locator.Release()

	wmi, err := locator.QueryInterface(ole.IID_IDispatch)
	if err != nil {
		log.Fatal(err)
	}
	defer wmi.Release()

	// service is a SWbemServices
	serviceRaw, err := oleutil.CallMethod(wmi, "ConnectServer")
	if err != nil {
		log.Fatal(err)
	}
	service := serviceRaw.ToIDispatch()
	defer service.Release()

	// result is a SWBemObjectSet
	resultRaw, err := oleutil.CallMethod(service, "ExecQuery", "SELECT * FROM Win32_PnPEntity WHERE Name LIKE '%(COM%)'")
	if err != nil {
		log.Fatal(err)
	}
	result := resultRaw.ToIDispatch()
	defer result.Release()

	countVar, err := oleutil.GetProperty(result, "Count")
	if err != nil {
		log.Fatal(err)
	}
	count := int(countVar.Val)

	var ports Ports
	re := regexp.MustCompile(`(.*) \(COM(\d+)\)$`)
	for i := 0; i < count; i++ {
		// item is a SWbemObject, but really a Win32_Process
		itemRaw, err := oleutil.CallMethod(result, "ItemIndex", i)
		if err != nil {
			continue
		}
		item := itemRaw.ToIDispatch()
		defer item.Release()

		property, err := oleutil.GetProperty(item, "Name")
		if err != nil {
			continue
		}
		port := re.FindAllStringSubmatch(property.ToString(), -1)
		num, _ := strconv.Atoi(port[0][2])
		ports = append(ports, Port{num, port[0][1]})
	}

	sort.Sort(ports)

	digit := getDigit(ports[len(ports)-1].Number)
	for i := 0; i < len(ports); i++ {
		fmt.Println("COM" + strconv.Itoa(ports[i].Number) + strings.Repeat(" ", digit-getDigit(ports[i].Number)) + " : " + ports[i].Name)
	}
}
func getListViaWmiPnpEntity() ([]OsSerialPort, os.SyscallError) {

	//log.Println("Doing getListViaWmiPnpEntity()")

	// this method panics a lot and i'm not sure why, just catch
	// the panic and return empty list
	defer func() {
		if e := recover(); e != nil {
			// e is the interface{} typed-value we passed to panic()
			log.Println("Got panic: ", e) // Prints "Whoops: boom!"
		}
	}()

	var err os.SyscallError

	//var friendlyName string

	// init COM, oh yeah
	ole.CoInitialize(0)
	defer ole.CoUninitialize()

	unknown, _ := oleutil.CreateObject("WbemScripting.SWbemLocator")
	defer unknown.Release()

	wmi, _ := unknown.QueryInterface(ole.IID_IDispatch)
	defer wmi.Release()

	// service is a SWbemServices
	serviceRaw, _ := oleutil.CallMethod(wmi, "ConnectServer")
	service := serviceRaw.ToIDispatch()
	defer service.Release()

	// result is a SWBemObjectSet
	//pname := syscall.StringToUTF16("SELECT * FROM Win32_PnPEntity where Name like '%" + "COM35" + "%'")
	pname := "SELECT * FROM Win32_PnPEntity WHERE ConfigManagerErrorCode = 0 and Name like '%(COM%'"
	//pname := "SELECT * FROM Win32_PnPEntity WHERE ConfigManagerErrorCode = 0"
	resultRaw, err2 := oleutil.CallMethod(service, "ExecQuery", pname)
	//log.Println("Got result from oleutil.CallMethod")
	if err2 != nil {
		// we got back an error or empty list
		log.Printf("Got an error back from oleutil.CallMethod. err:%v", err2)
		return nil, err
	}

	result := resultRaw.ToIDispatch()
	defer result.Release()

	countVar, _ := oleutil.GetProperty(result, "Count")
	count := int(countVar.Val)

	list := make([]OsSerialPort, count)

	for i := 0; i < count; i++ {

		// items we're looping thru look like below and
		// thus we can query for any of these names
		/*
					__GENUS                     : 2
			__CLASS                     : Win32_PnPEntity
			__SUPERCLASS                : CIM_LogicalDevice
			__DYNASTY                   : CIM_ManagedSystemElement
			__RELPATH                   : Win32_PnPEntity.DeviceID="USB\\VID_1D50&PID_606D&MI_02\\6&2F09EA14&0&0002"
			__PROPERTY_COUNT            : 24
			__DERIVATION                : {CIM_LogicalDevice, CIM_LogicalElement, CIM_ManagedSystemElement}
			__SERVER                    : JOHN-ATIV
			__NAMESPACE                 : root\cimv2
			__PATH                      : \\JOHN-ATIV\root\cimv2:Win32_PnPEntity.DeviceID="USB\\VID_1D50&PID_606D&MI_02\\6&2F09EA14
			                              &0&0002"
			Availability                :
			Caption                     : TinyG v2 (Data Channel) (COM12)
			ClassGuid                   : {4d36e978-e325-11ce-bfc1-08002be10318}
			CompatibleID                : {USB\Class_02&SubClass_02&Prot_01, USB\Class_02&SubClass_02, USB\Class_02}
			ConfigManagerErrorCode      : 0
			ConfigManagerUserConfig     : False
			CreationClassName           : Win32_PnPEntity
			Description                 : TinyG v2 (Data Channel)
			DeviceID                    : USB\VID_1D50&PID_606D&MI_02\6&2F09EA14&0&0002
			ErrorCleared                :
			ErrorDescription            :
			HardwareID                  : {USB\VID_1D50&PID_606D&REV_0097&MI_02, USB\VID_1D50&PID_606D&MI_02}
			InstallDate                 :
			LastErrorCode               :
			Manufacturer                : Synthetos (www.synthetos.com)
			Name                        : TinyG v2 (Data Channel) (COM12)
			PNPDeviceID                 : USB\VID_1D50&PID_606D&MI_02\6&2F09EA14&0&0002
			PowerManagementCapabilities :
			PowerManagementSupported    :
			Service                     : usbser
			Status                      : OK
			StatusInfo                  :
			SystemCreationClassName     : Win32_ComputerSystem
			SystemName                  : JOHN-ATIV
			PSComputerName              : JOHN-ATIV
		*/

		// item is a SWbemObject, but really a Win32_Process
		itemRaw, _ := oleutil.CallMethod(result, "ItemIndex", i)
		item := itemRaw.ToIDispatch()
		defer item.Release()

		asString, _ := oleutil.GetProperty(item, "Name")

		//log.Println(asString.ToString())

		// get the com port
		//if false {
		s := strings.Split(asString.ToString(), "(COM")[1]
		s = "COM" + s
		s = strings.Split(s, ")")[0]
		list[i].Name = s
		list[i].FriendlyName = asString.ToString()
		//}

		// get the deviceid so we can figure out related ports
		// it will look similar to
		// USB\VID_1D50&PID_606D&MI_00\6&2F09EA14&0&0000
		deviceIdStr, _ := oleutil.GetProperty(item, "DeviceID")
		devIdItems := strings.Split(deviceIdStr.ToString(), "&")
		log.Printf("DeviceId elements:%v", devIdItems)
		if len(devIdItems) > 3 {
			list[i].SerialNumber = devIdItems[3]
			//list[i].IdProduct = strings.Replace(devIdItems[1], "PID_", "", 1)
			//list[i].IdVendor = strings.Replace(devIdItems[0], "USB\\VID_", "", 1)
		} else {
			list[i].SerialNumber = deviceIdStr.ToString()
		}

		pidMatch := regexp.MustCompile("PID_(....)").FindAllStringSubmatch(deviceIdStr.ToString(), -1)
		if len(pidMatch) > 0 {
			if len(pidMatch[0]) > 1 {
				list[i].IdProduct = pidMatch[0][1]
			}
		}
		vidMatch := regexp.MustCompile("VID_(....)").FindAllStringSubmatch(deviceIdStr.ToString(), -1)
		if len(vidMatch) > 0 {
			if len(vidMatch[0]) > 1 {
				list[i].IdVendor = vidMatch[0][1]
			}
		}

		manufStr, _ := oleutil.GetProperty(item, "Manufacturer")
		list[i].Manufacturer = manufStr.ToString()
		descStr, _ := oleutil.GetProperty(item, "Description")
		list[i].Product = descStr.ToString()
		//classStr, _ := oleutil.GetProperty(item, "CreationClassName")
		//list[i].DeviceClass = classStr.ToString()

	}

	for index, element := range list {

		log.Printf("index:%v, name:%v, friendly:%v ", index, element.Name, element.FriendlyName)
		log.Printf("pid:%v, vid:%v", element.IdProduct, element.IdVendor)

		for index2, element2 := range list {
			if index == index2 {
				continue
			}
			if element.SerialNumber == element2.SerialNumber {
				log.Printf("Found related element1:%v, element2:%v", element, element2)
				list[index].RelatedNames = append(list[index].RelatedNames, element2.Name)
			}
		}

	}

	return list, err
}
Exemple #11
0
// loadEntity loads a SWbemObject into a struct pointer.
func (c *Client) loadEntity(dst interface{}, src *ole.IDispatch) (errFieldMismatch error) {
	v := reflect.ValueOf(dst).Elem()
	for i := 0; i < v.NumField(); i++ {
		f := v.Field(i)
		of := f
		isPtr := f.Kind() == reflect.Ptr
		if isPtr {
			ptr := reflect.New(f.Type().Elem())
			f.Set(ptr)
			f = f.Elem()
		}
		n := v.Type().Field(i).Name
		if !f.CanSet() {
			return &ErrFieldMismatch{
				StructType: of.Type(),
				FieldName:  n,
				Reason:     "CanSet() is false",
			}
		}
		prop, err := oleutil.GetProperty(src, n)
		if err != nil {
			if !c.AllowMissingFields {
				errFieldMismatch = &ErrFieldMismatch{
					StructType: of.Type(),
					FieldName:  n,
					Reason:     "no such struct field",
				}
			}
			continue
		}
		defer prop.Clear()

		switch val := prop.Value().(type) {
		case int8, int16, int32, int64, int:
			v := reflect.ValueOf(val).Int()
			switch f.Kind() {
			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
				f.SetInt(v)
			case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
				f.SetUint(uint64(v))
			default:
				return &ErrFieldMismatch{
					StructType: of.Type(),
					FieldName:  n,
					Reason:     "not an integer class",
				}
			}
		case uint8, uint16, uint32, uint64:
			v := reflect.ValueOf(val).Uint()
			switch f.Kind() {
			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
				f.SetInt(int64(v))
			case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
				f.SetUint(v)
			default:
				return &ErrFieldMismatch{
					StructType: of.Type(),
					FieldName:  n,
					Reason:     "not an integer class",
				}
			}
		case string:
			switch f.Kind() {
			case reflect.String:
				f.SetString(val)
			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
				iv, err := strconv.ParseInt(val, 10, 64)
				if err != nil {
					return err
				}
				f.SetInt(iv)
			case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
				uv, err := strconv.ParseUint(val, 10, 64)
				if err != nil {
					return err
				}
				f.SetUint(uv)
			case reflect.Struct:
				switch f.Type() {
				case timeType:
					if len(val) == 25 {
						mins, err := strconv.Atoi(val[22:])
						if err != nil {
							return err
						}
						val = val[:22] + fmt.Sprintf("%02d%02d", mins/60, mins%60)
					}
					t, err := time.Parse("20060102150405.000000-0700", val)
					if err != nil {
						return err
					}
					f.Set(reflect.ValueOf(t))
				}
			}
		case bool:
			switch f.Kind() {
			case reflect.Bool:
				f.SetBool(val)
			default:
				return &ErrFieldMismatch{
					StructType: of.Type(),
					FieldName:  n,
					Reason:     "not a bool",
				}
			}
		default:
			typeof := reflect.TypeOf(val)
			if typeof == nil && (isPtr || c.NonePtrZero) {
				if (isPtr && c.PtrNil) || (!isPtr && c.NonePtrZero) {
					of.Set(reflect.Zero(of.Type()))
				}
				break
			}
			return &ErrFieldMismatch{
				StructType: of.Type(),
				FieldName:  n,
				Reason:     fmt.Sprintf("unsupported type (%T)", val),
			}
		}
	}
	return errFieldMismatch
}
Exemple #12
0
//get cell pointer.
func (sheet Sheet) Cell(r int, c int) (cell Cell, err error) {
	defer Except("Sheet.Cell", &err)
	_cell, err := oleutil.GetProperty(sheet.Idisp, "Cells", r, c)
	cell = Cell{_cell.ToIDispatch()}
	return
}
Exemple #13
0
func (mso *MSO) ActiveWorkBook() (WorkBook, error) {
	_wb, err := oleutil.GetProperty(mso.IdExcel, "ActiveWorkBook")
	return WorkBook{_wb.ToIDispatch(), mso}, err
}
Exemple #14
0
func (rc *AdodbRows) Next(dest []driver.Value) error {
	unknown, err := oleutil.GetProperty(rc.rc, "EOF")
	if err != nil {
		return io.EOF
	}
	if unknown.Val != 0 {
		return io.EOF
	}
	unknown, err = oleutil.GetProperty(rc.rc, "Fields")
	if err != nil {
		return err
	}
	fields := unknown.ToIDispatch()
	defer fields.Release()
	for i := range dest {
		var varval ole.VARIANT
		varval.VT = ole.VT_I4
		varval.Val = int64(i)
		val, err := oleutil.CallMethod(fields, "Item", &varval)
		if err != nil {
			return err
		}
		field := val.ToIDispatch()
		defer field.Release()
		typ, err := oleutil.GetProperty(field, "Type")
		if err != nil {
			return err
		}
		val, err = oleutil.GetProperty(field, "Value")
		if err != nil {
			return err
		}
		sc, err := oleutil.GetProperty(field, "NumericScale")
		field.Release()
		if val.VT == 1 /* VT_NULL */ {
			dest[i] = nil
			continue
		}
		switch typ.Val {
		case 0: // ADEMPTY
			dest[i] = nil
		case 2: // ADSMALLINT
			dest[i] = int64(int16(val.Val))
		case 3: // ADINTEGER
			dest[i] = int64(int32(val.Val))
		case 4: // ADSINGLE
			dest[i] = float64(math.Float32frombits(uint32(val.Val)))
		case 5: // ADDOUBLE
			dest[i] = math.Float64frombits(uint64(val.Val))
		case 6: // ADCURRENCY
			dest[i] = float64(val.Val) / 10000
		case 7: // ADDATE
			// see http://blogs.msdn.com/b/ericlippert/archive/2003/09/16/eric-s-complete-guide-to-vt-date.aspx
			d, t := math.Modf(math.Float64frombits(uint64(val.Val)))
			t = math.Abs(t)
			dest[i] = time.Date(1899, 12, 30+int(d), 0, 0, int(t*86400), 0, time.Local)
		case 8: // ADBSTR
			dest[i] = val.ToString()
		case 9: // ADIDISPATCH
			dest[i] = val.ToIDispatch()
		case 10: // ADERROR
			// TODO
		case 11: // ADBOOLEAN
			dest[i] = val.Val != 0
		case 12: // ADVARIANT
			dest[i] = val
		case 13: // ADIUNKNOWN
			dest[i] = val.ToIUnknown()
		case 14: // ADDECIMAL
			sub := math.Pow(10, float64(sc.Val))
			dest[i] = float64(float64(val.Val) / sub)
		case 16: // ADTINYINT
			dest[i] = int8(val.Val)
		case 17: // ADUNSIGNEDTINYINT
			dest[i] = uint8(val.Val)
		case 18: // ADUNSIGNEDSMALLINT
			dest[i] = uint16(val.Val)
		case 19: // ADUNSIGNEDINT
			dest[i] = uint32(val.Val)
		case 20: // ADBIGINT
			dest[i] = big.NewInt(val.Val)
		case 21: // ADUNSIGNEDBIGINT
			// TODO
		case 72: // ADGUID
			dest[i] = val.ToString()
		case 128: // ADBINARY
			sa := (*ole.SafeArray)(unsafe.Pointer(uintptr(val.Val)))
			conv := &ole.SafeArrayConversion{sa}
			elems, err := conv.TotalElements(0)
			if err != nil {
				return err
			}
			dest[i] = (*[1 << 30]byte)(unsafe.Pointer(uintptr(sa.Data)))[0:elems]
		case 129: // ADCHAR
			dest[i] = val.ToString() //uint8(val.Val)
		case 130: // ADWCHAR
			dest[i] = val.ToString() //uint16(val.Val)
		case 131: // ADNUMERIC
			sub := math.Pow(10, float64(sc.Val))
			dest[i] = float64(float64(val.Val) / sub)
		case 132: // ADUSERDEFINED
			dest[i] = uintptr(val.Val)
		case 133: // ADDBDATE
			// see http://blogs.msdn.com/b/ericlippert/archive/2003/09/16/eric-s-complete-guide-to-vt-date.aspx
			d := math.Float64frombits(uint64(val.Val))
			dest[i] = time.Date(1899, 12, 30+int(d), 0, 0, 0, 0, time.Local)
		case 134: // ADDBTIME
			t := math.Float64frombits(uint64(val.Val))
			dest[i] = time.Date(0, 1, 1, 0, 0, int(t*86400), 0, time.Local)
		case 135: // ADDBTIMESTAMP
			d, t := math.Modf(math.Float64frombits(uint64(val.Val)))
			t = math.Abs(t)
			dest[i] = time.Date(1899, 12, 30+int(d), 0, 0, int(t*86400), 0, time.Local)
		case 136: // ADCHAPTER
			dest[i] = val.ToString()
		case 200: // ADVARCHAR
			dest[i] = val.ToString()
		case 201: // ADLONGVARCHAR
			dest[i] = val.ToString()
		case 202: // ADVARWCHAR
			dest[i] = val.ToString()
		case 203: // ADLONGVARWCHAR
			dest[i] = val.ToString()
		case 204: // ADVARBINARY
			// TODO
		case 205: // ADLONGVARBINARY
			sa := (*ole.SafeArray)(unsafe.Pointer(uintptr(val.Val)))
			conv := &ole.SafeArrayConversion{sa}
			elems, err := conv.TotalElements(0)
			if err != nil {
				return err
			}
			dest[i] = (*[1 << 30]byte)(unsafe.Pointer(uintptr(sa.Data)))[0:elems]
		}
	}
	_, err = oleutil.CallMethod(rc.rc, "MoveNext")
	if err != nil {
		return err
	}
	return nil
}