95 lines
2.2 KiB
Go
95 lines
2.2 KiB
Go
//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
|
|
}
|