//go:build windows // +build windows package wmiext import ( "fmt" "syscall" "unsafe" "github.com/go-ole/go-ole" ) type IEnumWbemClassObjectVtbl struct { QueryInterface uintptr AddRef uintptr Release uintptr Reset uintptr Next uintptr NextAsync uintptr Clone uintptr Skip uintptr } type Enum struct { enum *ole.IUnknown vTable *IEnumWbemClassObjectVtbl service *Service } func (e *Enum) Close() { if e != nil && e.enum != nil { e.enum.Release() } } func newEnum(enumerator *ole.IUnknown, service *Service) *Enum { return &Enum{ enum: enumerator, vTable: (*IEnumWbemClassObjectVtbl)(unsafe.Pointer(enumerator.RawVTable)), service: service, } } // NextObject obtains the next instance in an enumeration and sets all fields // of the struct pointer passed through the target parameter. Otherwise, if // the target parameter is not a struct pointer type, an error will be // returned. func NextObject(enum *Enum, target interface{}) (bool, error) { var err error var instance *Instance if instance, err = enum.Next(); err != nil { return false, err } if instance == nil { return true, nil } defer instance.Close() return false, instance.GetAll(target) } // Next returns the next object instance in this iteration func (e *Enum) Next() (instance *Instance, err error) { var res uintptr var apObjects *ole.IUnknown var uReturned uint32 res, _, _ = syscall.SyscallN( e.vTable.Next, // IEnumWbemClassObject::Next() uintptr(unsafe.Pointer(e.enum)), // IEnumWbemClassObject ptr uintptr(WBEM_INFINITE), // [in] long lTimeout, uintptr(1), // [in] ULONG uCount, uintptr(unsafe.Pointer(&apObjects)), // [out] IWbemClassObject **apObjects, uintptr(unsafe.Pointer(&uReturned))) // [out] ULONG *puReturned) if int(res) < 0 { return nil, NewWmiError(res) } if uReturned < 1 { switch res { case WBEM_S_NO_ERROR, WBEM_S_FALSE: // No more elements return nil, nil default: return nil, fmt.Errorf("failure advancing enumeration (%d)", res) } } return newInstance(apObjects, e.service), nil }