diff --git a/go.mod b/go.mod index d7ff921fe8..fc7f6e6df9 100644 --- a/go.mod +++ b/go.mod @@ -18,10 +18,8 @@ require ( github.com/kubernetes-csi/csi-lib-utils v0.14.1 github.com/kubernetes-csi/csi-proxy/client v1.0.1 github.com/kubernetes-csi/external-snapshotter/client/v4 v4.2.0 - github.com/microsoft/wmi v0.38.3 github.com/onsi/ginkgo/v2 v2.28.0 github.com/onsi/gomega v1.39.1 - github.com/pkg/errors v0.9.1 github.com/rubiojr/go-vhd v0.0.0-20200706105327-02e210299021 github.com/stretchr/testify v1.11.1 go.uber.org/goleak v1.3.0 @@ -103,6 +101,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/selinux v1.13.0 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.23.2 // indirect github.com/prometheus/client_model v0.6.2 // indirect diff --git a/go.sum b/go.sum index 90242e4026..034bedc110 100644 --- a/go.sum +++ b/go.sum @@ -305,8 +305,6 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3vE= github.com/mfridman/tparse v0.18.0/go.mod h1:gEvqZTuCgEhPbYk/2lS3Kcxg1GmTxxU7kTC8DvP0i/A= -github.com/microsoft/wmi v0.38.3 h1:RVbn+m2jlPRsB2fLADXqabJj/EhMXQbvKM7OYS8VOv0= -github.com/microsoft/wmi v0.38.3/go.mod h1:XF+cfluA15xGnSCYkJIYuj2vWzdm2YrNuvqlC+baWY0= github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU= github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= diff --git a/pkg/os/cim/wmi.go b/pkg/os/cim/wmi.go deleted file mode 100644 index bd40078e53..0000000000 --- a/pkg/os/cim/wmi.go +++ /dev/null @@ -1,205 +0,0 @@ -//go:build windows -// +build windows - -/* -Copyright 2025 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cim - -import ( - "errors" - "fmt" - "runtime" - - "github.com/go-ole/go-ole" - "github.com/microsoft/wmi/pkg/base/query" - wmierrors "github.com/microsoft/wmi/pkg/errors" - cim "github.com/microsoft/wmi/pkg/wmiinstance" - "golang.org/x/sys/windows" - "k8s.io/klog/v2" -) - -const ( - WMINamespaceCimV2 = "Root\\CimV2" - WMINamespaceStorage = "Root\\Microsoft\\Windows\\Storage" - WMINamespaceSmb = "Root\\Microsoft\\Windows\\Smb" -) - -type InstanceHandler func(instance *cim.WmiInstance) (bool, error) - -// NewWMISession creates a new local WMI session for the given namespace, defaulting -// to root namespace if none specified. -func NewWMISession(namespace string) (*cim.WmiSession, error) { - if namespace == "" { - namespace = WMINamespaceCimV2 - } - - sessionManager := cim.NewWmiSessionManager() - defer sessionManager.Dispose() - - session, err := sessionManager.GetLocalSession(namespace) - if err != nil { - return nil, fmt.Errorf("failed to get local WMI session for namespace %s. error: %w", namespace, err) - } - - connected, err := session.Connect() - if !connected || err != nil { - return nil, fmt.Errorf("failed to connect to WMI. error: %w", err) - } - - return session, nil -} - -// QueryFromWMI executes a WMI query in the specified namespace and processes each result -// through the provided handler function. Stops processing if handler returns false or encounters an error. -func QueryFromWMI(namespace string, query *query.WmiQuery, handler InstanceHandler) error { - session, err := NewWMISession(namespace) - if err != nil { - return err - } - - defer session.Close() - - instances, err := session.QueryInstances(query.String()) - if err != nil { - return fmt.Errorf("failed to query WMI class %s. error: %w", query.ClassName, err) - } - - if len(instances) == 0 { - return wmierrors.NotFound - } - - var cont bool - for _, instance := range instances { - cont, err = handler(instance) - if err != nil { - err = fmt.Errorf("failed to query WMI class %s instance (%s). error: %w", query.ClassName, instance.String(), err) - } - if !cont { - break - } - } - - return err -} - -// QueryInstances retrieves all WMI instances matching the given query in the specified namespace. -func QueryInstances(namespace string, query *query.WmiQuery) ([]*cim.WmiInstance, error) { - var instances []*cim.WmiInstance - err := QueryFromWMI(namespace, query, func(instance *cim.WmiInstance) (bool, error) { - instances = append(instances, instance) - return true, nil - }) - return instances, err -} - -// InvokeCimMethod calls a static method on a specific WMI class with given input parameters, -// returning the method's return value, output parameters, and any error encountered. -func InvokeCimMethod(namespace, class, methodName string, inputParameters map[string]interface{}) (int, map[string]interface{}, error) { - session, err := NewWMISession(namespace) - if err != nil { - return -1, nil, err - } - - defer session.Close() - - rawResult, err := session.Session.CallMethod("Get", class) - if err != nil { - return -1, nil, err - } - - classInst, err := cim.CreateWmiInstance(rawResult, session) - if err != nil { - return -1, nil, err - } - - method, err := cim.NewWmiMethod(methodName, classInst) - if err != nil { - return -1, nil, err - } - - var inParam cim.WmiMethodParamCollection - for k, v := range inputParameters { - inParam = append(inParam, &cim.WmiMethodParam{ - Name: k, - Value: v, - }) - } - - var outParam cim.WmiMethodParamCollection - var result *cim.WmiMethodResult - result, err = method.Execute(inParam, outParam) - if err != nil { - return -1, nil, err - } - - outputParameters := make(map[string]interface{}) - for _, v := range result.OutMethodParams { - outputParameters[v.Name] = v.Value - } - - return int(result.ReturnValue), outputParameters, nil -} - -// IsNotFound returns true if it's a "not found" error. -func IsNotFound(err error) bool { - return wmierrors.IsNotFound(err) -} - -// IgnoreNotFound returns nil if the error is nil or a "not found" error, -// otherwise returns the original error. -func IgnoreNotFound(err error) error { - if err == nil || IsNotFound(err) { - return nil - } - return err -} - -// WithCOMThread runs the given function `fn` on a locked OS thread -// with COM initialized using COINIT_MULTITHREADED. -// -// This is necessary for using COM/OLE APIs directly (e.g., via go-ole), -// because COM requires that initialization and usage occur on the same thread. -// -// It performs the following steps: -// - Locks the current goroutine to its OS thread -// - Calls ole.CoInitializeEx with COINIT_MULTITHREADED -// - Executes the user-provided function -// - Uninitializes COM -// - Unlocks the thread -// -// If COM initialization fails, or if the user's function returns an error, -// that error is returned by WithCOMThread. -func WithCOMThread(fn func() error) error { - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - if err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED); err != nil { - var oleError *ole.OleError - if errors.As(err, &oleError) && oleError != nil && oleError.Code() == uintptr(windows.S_FALSE) { - klog.V(10).Infof("COM library has been already initialized for the calling thread, proceeding to the function with no error") - err = nil - } - if err != nil { - return err - } - } else { - klog.V(10).Infof("COM library is initialized for the calling thread") - } - defer ole.CoUninitialize() - - return fn() -} diff --git a/pkg/os/filesystem/filesystem.go b/pkg/os/filesystem/filesystem.go index 84590ce306..f1040968bf 100644 --- a/pkg/os/filesystem/filesystem.go +++ b/pkg/os/filesystem/filesystem.go @@ -21,12 +21,12 @@ package filesystem import ( "context" + "errors" "fmt" "os" "regexp" "strings" - "github.com/pkg/errors" "golang.org/x/sys/windows" "k8s.io/klog/v2" "sigs.k8s.io/azurefile-csi-driver/pkg/util" diff --git a/pkg/os/smb/smb_cim.go b/pkg/os/smb/smb_cim.go index 74ab55f787..6f2ab6dde6 100644 --- a/pkg/os/smb/smb_cim.go +++ b/pkg/os/smb/smb_cim.go @@ -20,8 +20,10 @@ limitations under the License. package smb import ( + "fmt" + "k8s.io/klog/v2" - "sigs.k8s.io/azurefile-csi-driver/pkg/os/cim" + wmi "sigs.k8s.io/azurefile-csi-driver/pkg/os/wmi" ) var _ SMBAPI = &cimSMBAPI{} @@ -34,43 +36,48 @@ func NewCimSMBAPI() *cimSMBAPI { func (*cimSMBAPI) IsSmbMapped(remotePath string) (bool, error) { var isMapped bool - err := cim.WithCOMThread(func() error { - inst, err := cim.QuerySmbGlobalMappingByRemotePath(remotePath) - if err != nil { - klog.V(6).Infof("error querying smb mapping for remote path %s. err: %v", remotePath, err) - return err - } + err := wmi.WithCOMThread(func() error { + return wmi.WithScope(func(scope *wmi.Scope) error { + inst, err := wmi.QuerySmbGlobalMappingByRemotePath(scope, remotePath) + if err != nil { + klog.V(6).Infof("error querying smb mapping for remote path %s. err: %v", remotePath, err) + return err + } - status, err := cim.GetSmbGlobalMappingStatus(inst) - if err != nil { - klog.V(6).Infof("error getting smb mapping status for remote path %s. err: %v", remotePath, err) - return err - } + status, err := wmi.GetSmbGlobalMappingStatus(inst) + if err != nil { + klog.V(6).Infof("error getting smb mapping status for remote path %s. err: %v", remotePath, err) + return err + } - isMapped = status == cim.SmbMappingStatusOK - return nil + isMapped = status == wmi.SmbMappingStatusOK + return nil + }) }) - return isMapped, cim.IgnoreNotFound(err) + return isMapped, wmi.IgnoreNotFound(err) } func (*cimSMBAPI) NewSmbGlobalMapping(remotePath, username, password string) error { - return cim.WithCOMThread(func() error { - result, err := cim.NewSmbGlobalMapping(remotePath, username, password, true) + requirePrivacy := true + return wmi.WithCOMThread(func() error { + err := wmi.NewSmbGlobalMapping(remotePath, username, password, requirePrivacy) if err != nil { - klog.V(6).Infof("error creating smb mapping for remote path %s. result %d, err: %v", remotePath, result, err) - return err + klog.V(6).Infof("error creating smb mapping for remote path %s. err: %v", remotePath, err) + return fmt.Errorf("create SMB mapping failed for %s: %w", remotePath, err) } return nil }) } func (*cimSMBAPI) RemoveSmbGlobalMapping(remotePath string) error { - return cim.WithCOMThread(func() error { - err := cim.RemoveSmbGlobalMappingByRemotePath(remotePath) - if err != nil { - klog.V(6).Infof("error removing smb mapping for remote path %s. err: %v", remotePath, err) - return err - } - return nil + return wmi.WithCOMThread(func() error { + return wmi.WithScope(func(scope *wmi.Scope) error { + err := wmi.RemoveSmbGlobalMappingByRemotePath(scope, remotePath) + if err != nil { + klog.V(6).Infof("error removing smb mapping for remote path %s. err: %v", remotePath, err) + return fmt.Errorf("error remove smb mapping '%s'. err: %w", remotePath, err) + } + return nil + }) }) } diff --git a/pkg/os/cim/smb.go b/pkg/os/wmi/smb.go similarity index 61% rename from pkg/os/cim/smb.go rename to pkg/os/wmi/smb.go index 55a718d9b7..87e3eb903d 100644 --- a/pkg/os/cim/smb.go +++ b/pkg/os/wmi/smb.go @@ -17,35 +17,32 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cim +package wmi import ( + "fmt" "strings" +) - "github.com/microsoft/wmi/pkg/base/query" - cim "github.com/microsoft/wmi/pkg/wmiinstance" +const ( + MSFTSmbGlobalMappingClass = "MSFT_SmbGlobalMapping" ) // Refer to https://learn.microsoft.com/en-us/previous-versions/windows/desktop/smb/msft-smbmapping const ( - SmbMappingStatusOK int32 = iota + SmbMappingStatusOK uint32 = iota SmbMappingStatusPaused SmbMappingStatusDisconnected SmbMappingStatusNetworkError SmbMappingStatusConnecting SmbMappingStatusReconnecting SmbMappingStatusUnavailable +) +const ( credentialDelimiter = ":" ) -// escapeQueryParameter escapes a parameter for WMI Queries -func escapeQueryParameter(s string) string { - s = strings.ReplaceAll(s, "'", "''") - s = strings.ReplaceAll(s, "\\", "\\\\") - return s -} - func escapeUserName(userName string) string { // refer to https://github.com/PowerShell/PowerShell/blob/9303de597da55963a6e26a8fe164d0b256ca3d4d/src/Microsoft.PowerShell.Commands.Management/cimSupport/cmdletization/cim/cimConverter.cs#L169-L170 userName = strings.ReplaceAll(userName, "\\", "\\\\") @@ -61,46 +58,58 @@ func escapeUserName(userName string) string { // // Refer to https://pkg.go.dev/github.com/microsoft/wmi/server2019/root/microsoft/windows/smb#MSFT_SmbGlobalMapping // for the WMI class definition. -func QuerySmbGlobalMappingByRemotePath(remotePath string) (*cim.WmiInstance, error) { - smbQuery := query.NewWmiQuery("MSFT_SmbGlobalMapping", "RemotePath", escapeQueryParameter(remotePath)) - instances, err := QueryInstances(WMINamespaceSmb, smbQuery) +func QuerySmbGlobalMappingByRemotePath(scope *Scope, remotePath string) (*COMDispatchObject, error) { + q := NewQuery(MSFTSmbGlobalMappingClass). + WithNamespace(WMINamespaceSmb). + WithCondition("RemotePath", "=", remotePath) + + smb, err := QueryFirstObjectWithBuilder(scope, q) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to query SMB global mapping by remote path %s: %w", remotePath, err) } - return instances[0], err + return smb, nil } // GetSmbGlobalMappingStatus returns the status of an SMB global mapping. -func GetSmbGlobalMappingStatus(inst *cim.WmiInstance) (int32, error) { - statusProp, err := inst.GetProperty("Status") +func GetSmbGlobalMappingStatus(smb *COMDispatchObject) (uint32, error) { + statusProp, err := smb.GetProperty("Status") if err != nil { - return SmbMappingStatusUnavailable, err + return SmbMappingStatusUnavailable, fmt.Errorf("failed to get SMB global mapping status %v. error: %w", smb, err) } - return statusProp.(int32), nil + return NewSafeVariant(statusProp).Uint32(), nil } // RemoveSmbGlobalMappingByRemotePath removes an SMB global mapping matching to the remote path. // // Refer to https://pkg.go.dev/github.com/microsoft/wmi/server2019/root/microsoft/windows/smb#MSFT_SmbGlobalMapping // for the WMI class definition. -func RemoveSmbGlobalMappingByRemotePath(remotePath string) error { - smbQuery := query.NewWmiQuery("MSFT_SmbGlobalMapping", "RemotePath", escapeQueryParameter(remotePath)) - instances, err := QueryInstances(WMINamespaceSmb, smbQuery) +func RemoveSmbGlobalMappingByRemotePath(scope *Scope, remotePath string) error { + q := NewQuery(MSFTSmbGlobalMappingClass). + WithNamespace(WMINamespaceSmb). + WithCondition("RemotePath", "=", remotePath) + + smb, err := QueryFirstObjectWithBuilder(scope, q) if err != nil { - return err + return fmt.Errorf("failed to query SMB global mapping by remote path %s: %w", remotePath, err) } - _, err = instances[0].InvokeMethod("Remove", true) - return err + result, err := smb.CallUint32("Remove", true) + if err != nil { + return fmt.Errorf("failed to remove SMB global mapping by remote path %s: %w", remotePath, err) + } + if result != 0 { + return NewWMIError(MSFTSmbGlobalMappingClass, "Remove", smb.Dispatch(), result) + } + return nil } // NewSmbGlobalMapping creates a new SMB global mapping to the remote path. // // Refer to https://pkg.go.dev/github.com/microsoft/wmi/server2019/root/microsoft/windows/smb#MSFT_SmbGlobalMapping // for the WMI class definition. -func NewSmbGlobalMapping(remotePath, username, password string, requirePrivacy bool) (int, error) { +func NewSmbGlobalMapping(remotePath, username, password string, requirePrivacy bool) error { params := map[string]interface{}{ "RemotePath": remotePath, "RequirePrivacy": requirePrivacy, @@ -111,6 +120,12 @@ func NewSmbGlobalMapping(remotePath, username, password string, requirePrivacy b params["Credential"] = escapeUserName(username) + credentialDelimiter + password } - result, _, err := InvokeCimMethod(WMINamespaceSmb, "MSFT_SmbGlobalMapping", "Create", params) - return result, err + result, _, err := CallMethodOnWMIClass(WMINamespaceSmb, MSFTSmbGlobalMappingClass, "Create", params, DiscardOutputParameter) + if err != nil { + return fmt.Errorf("failed to create SMB global mapping: %w", err) + } + if result != 0 { + return NewWMIError(MSFTSmbGlobalMappingClass, "Create", nil, result) + } + return nil } diff --git a/pkg/os/wmi/wmi.go b/pkg/os/wmi/wmi.go new file mode 100644 index 0000000000..c6693025a6 --- /dev/null +++ b/pkg/os/wmi/wmi.go @@ -0,0 +1,802 @@ +//go:build windows +// +build windows + +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package wmi + +import ( + "errors" + "fmt" + "runtime" + "strings" + + "github.com/go-ole/go-ole" + "github.com/go-ole/go-ole/oleutil" + "golang.org/x/sys/windows" + "k8s.io/klog/v2" +) + +const ( + WMINamespaceCimV2 = "Root\\CimV2" + WMINamespaceStorage = "Root\\Microsoft\\Windows\\Storage" + WMINamespaceSmb = "Root\\Microsoft\\Windows\\Smb" +) + +var ( + ErrNotFound = errors.New("not found") + ErrStopIteration = errors.New("stop iteration") + + DiscardOutputParameter = func(_ string, _ *ole.VARIANT) (interface{}, error) { + return nil, nil + } + DiscardResult = func(_ *ole.VARIANT) error { + return nil + } +) + +// IsNotFound returns true if it's a "not found" error. +func IsNotFound(err error) bool { + return errors.Is(err, ErrNotFound) +} + +// IgnoreNotFound returns nil if the error is nil or a "not found" error, +// otherwise returns the original error. +func IgnoreNotFound(err error) error { + if err == nil || IsNotFound(err) { + return nil + } + return err +} + +// QueryBuilder is a builder for WMI queries. +type QueryBuilder struct { + Class string + Namespace string + Selectors []string + Conditions []Condition +} + +// Condition is a condition for a WMI query. +type Condition struct { + Field string + Operator string + Value any +} + +func (c Condition) String() string { + return fmt.Sprintf("%s %s %s", c.Field, c.Operator, formatValue(c.Value)) +} + +// WithCondition creates a new condition for a WMI query. +func WithCondition(field string, operator string, value any) Condition { + return Condition{Field: field, Operator: operator, Value: value} +} + +// NewQuery creates a new QueryBuilder for a WMI class. +func NewQuery(class string) *QueryBuilder { + return &QueryBuilder{ + Class: class, + Namespace: WMINamespaceCimV2, // default, override if needed + } +} + +func (q *QueryBuilder) WithNamespace(ns string) *QueryBuilder { + q.Namespace = ns + return q +} + +func (q *QueryBuilder) Select(selectors ...string) *QueryBuilder { + q.Selectors = append(q.Selectors, selectors...) + return q +} + +func (q *QueryBuilder) WithCondition(field string, operator string, value any) *QueryBuilder { + q.Conditions = append(q.Conditions, Condition{Field: field, Operator: operator, Value: value}) + return q +} + +func (q *QueryBuilder) WithConditions(conditions ...Condition) *QueryBuilder { + q.Conditions = append(q.Conditions, conditions...) + return q +} + +func (q *QueryBuilder) buildWhereClause() string { + if len(q.Conditions) == 0 { + return "" + } + + conditions := make([]string, len(q.Conditions)) + for i, condition := range q.Conditions { + conditions[i] = condition.String() + } + + return "WHERE " + strings.Join(conditions, " AND ") +} + +func (q *QueryBuilder) Build() string { + selectPart := "*" + + if len(q.Selectors) > 0 { + selectPart = "" + for i, s := range q.Selectors { + if i > 0 { + selectPart += ", " + } + selectPart += string(s) + } + } + + query := "SELECT " + selectPart + " FROM " + q.Class + + where := q.buildWhereClause() + if where != "" { + query += " " + where + } + + return query +} + +func formatValue(v any) string { + switch x := v.(type) { + + case string: + // WQL escaping: double single quotes and escape backslashes + escaped := strings.ReplaceAll(x, "'", "''") + escaped = strings.ReplaceAll(escaped, "\\", "\\\\") + return "'" + escaped + "'" + + case int, int32, int64, uint, uint32, uint64: + return fmt.Sprintf("%v", x) + + case bool: + if x { + return "TRUE" + } + return "FALSE" + + default: + return fmt.Sprintf("'%v'", x) + } +} + +// WithCOMThread runs the given function `fn` on a locked OS thread +// with COM initialized using COINIT_MULTITHREADED. +// +// This is necessary for using COM/OLE APIs directly (e.g., via go-ole), +// because COM requires that initialization and usage occur on the same thread. +// +// It performs the following steps: +// - Locks the current goroutine to its OS thread +// - Calls ole.CoInitializeEx with COINIT_MULTITHREADED +// - Executes the user-provided function +// - Uninitializes COM +// - Unlocks the thread + +// RPC_E_TOO_LATE is returned when CoInitializeSecurity has already been called. +const rpcETooLate = 0x80010119 + +var ( + modole32 = windows.NewLazySystemDLL("ole32.dll") + procCoInitializeSecurity = modole32.NewProc("CoInitializeSecurity") +) + +// initializeSecurity calls CoInitializeSecurity with default settings. +// It is safe to call multiple times; RPC_E_TOO_LATE is suppressed. +func initializeSecurity() error { + // Call CoInitializeSecurity with: + // pSecDesc=nil, cAuthSvc=-1(negotiate), asAuthSvc=nil, pReserved1=nil, + // dwAuthnLevel=DEFAULT(0), dwImpLevel=IMPERSONATE(3), + // pAuthList=nil, dwCapabilities=0, pReserved3=nil + hr, _, _ := procCoInitializeSecurity.Call( + 0, uintptr(0xFFFFFFFF), 0, 0, 0, 3, 0, 0, 0, + ) + if hr != 0 { + if hr == rpcETooLate { + return nil + } + return fmt.Errorf("CoInitializeSecurity failed: HRESULT 0x%08x", hr) + } + return nil +} + +// If COM initialization fails, or if the user's function returns an error, +// that error is returned by WithCOMThread. +func WithCOMThread(fn func() error) error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + if err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED); err != nil { + var oleError *ole.OleError + if errors.As(err, &oleError) && oleError != nil && oleError.Code() == uintptr(windows.S_FALSE) { + klog.V(10).Infof("COM library has been already initialized for the calling thread, proceeding to the function with no error") + err = nil + } + if err != nil { + return err + } + } else { + klog.V(10).Infof("COM library is initialized for the calling thread") + } + defer ole.CoUninitialize() + + // Initialize COM security. RPC_C_IMP_LEVEL_IMPERSONATE allows WMI + // to impersonate the caller, which is required for most WMI/DCOM operations. + // Ignore RPC_E_TOO_LATE (0x80010119) if security was already initialized. + if err := initializeSecurity(); err != nil { + klog.V(4).Infof("CoInitializeSecurity failed (non-fatal): %v", err) + } + + return fn() +} + +// WithWMIService runs the given function with a WMI service. +// +// It creates a new WMI service and calls the given function with it. +// It returns the error from the function. +func WithWMIService(namespace string, fn func(*ole.IDispatch) error) error { + locatorUnknown, err := oleutil.CreateObject("WbemScripting.SWbemLocator") + if err != nil { + return err + } + defer locatorUnknown.Release() + + locator, err := locatorUnknown.QueryInterface(ole.IID_IDispatch) + if err != nil { + return err + } + defer locator.Release() + + serviceRaw, err := oleutil.CallMethod(locator, "ConnectServer", nil, namespace) + if err != nil { + return err + } + defer serviceRaw.Clear() + service := serviceRaw.ToIDispatch() + + return fn(service) +} + +// Query queries the WMI objects with the given namespace and query. +func Query(namespace, query string, fn func(item *ole.IDispatch) error) error { + err := WithWMIService(namespace, func(service *ole.IDispatch) error { + resultRaw, err := oleutil.CallMethod(service, "ExecQuery", query) + if err != nil { + klog.V(4).Infof("ExecQuery: (namespace: %s, query: %s), error: %v", namespace, query, err) + return err + } + defer resultRaw.Clear() + result := resultRaw.ToIDispatch() + + countVar, err := oleutil.GetProperty(result, "Count") + if err != nil { + return err + } + defer countVar.Clear() + count := NewSafeVariant(countVar).Int() + klog.V(10).Infof("ExecQuery: (namespace: %s, query: %s) -> count: %d", namespace, query, count) + + if count == 0 { + return nil + } + + for i := 0; i < count; i++ { + itemRaw, err := oleutil.CallMethod(result, "ItemIndex", i) + if err != nil { + return fmt.Errorf("wmi query item retrieval failed (namespace: %s, query: %s, index: %d): %w", namespace, query, i, err) + } + + err = func() error { + defer itemRaw.Clear() + item := itemRaw.ToIDispatch() + + return fn(item) + }() + + if err != nil { + if errors.Is(err, ErrStopIteration) { + return nil // stop early + } + + return err + } + } + + return nil + }) + return err +} + +func QueryWithBuilder(builder *QueryBuilder, fn func(item *ole.IDispatch) error) error { + return Query(builder.Namespace, builder.Build(), fn) +} + +// GetProperty gets the property of the given name from the given object. +func GetProperty(item *ole.IDispatch, name string) (*ole.VARIANT, error) { + return oleutil.GetProperty(item, name) +} + +// Associators gets the associators of the given object. +func Associators(obj *ole.IDispatch, assocClass, resultClass, role, resultRole string, fn func(*ole.IDispatch) error) error { + klog.V(10).Infof("Associators: obj: %v, assocClass: %s, resultClass: %s, role: %s, resultRole: %s", obj, assocClass, resultClass, role, resultRole) + + // Associators_ is the key WMI COM method + result, err := oleutil.CallMethod( + obj, + "Associators_", + assocClass, // assocClass + resultClass, // resultClass + role, // role + resultRole, // resultRole + ) + if err != nil { + return fmt.Errorf("failed to list associators. error: %w", err) + } + + defer result.Clear() + + err = Enumerate(result.ToIDispatch(), func(item *ole.VARIANT) error { + return fn(item.ToIDispatch()) + }) + + return err +} + +// Enumerate enumerates the items of the given object. +// +// Doc: https://docs.microsoft.com/en-us/previous-versions/windows/desktop/automat/dispid-constants +func Enumerate(obj *ole.IDispatch, fn func(item *ole.VARIANT) error) error { + // --- Get _NewEnum --- + enumProp, err := obj.GetProperty("_NewEnum") + if err != nil { + return err + } + defer enumProp.Clear() + + // --- Get IEnumVARIANT --- + enum, err := enumProp.ToIUnknown().IEnumVARIANT(ole.IID_IEnumVariant) + if err != nil { + return err + } + if enum == nil { + return fmt.Errorf("enum is nil") + } + defer enum.Release() + + for { + item, length, err := enum.Next(1) + if length == 0 { + break + } + if err != nil { + return err + } + + err = func() error { + defer item.Clear() + return fn(&item) + }() + if err != nil { + return err + } + } + + return nil +} + +// CallMethodOnWMIClass calls a method on a WMI class and returns the return value. +func CallMethodOnWMIClass(namespace, class, methodName string, input map[string]interface{}, handler func(string, *ole.VARIANT) (interface{}, error)) (uint32, map[string]interface{}, error) { + var returnValue uint32 + var output map[string]interface{} + err := WithWMIService(namespace, func(service *ole.IDispatch) error { + classRaw, err := oleutil.CallMethod(service, "Get", class) + if err != nil { + return fmt.Errorf("get class %s failed: %w", class, err) + } + defer classRaw.Clear() + classInst := classRaw.ToIDispatch() + + methodsRaw, err := oleutil.GetProperty(classInst, "Methods_") + if err != nil { + return err + } + defer methodsRaw.Clear() + + methodRaw, err := methodsRaw.ToIDispatch().CallMethod("Item", methodName) + if err != nil { + return fmt.Errorf("method %s not found: %w", methodName, err) + } + defer methodRaw.Clear() + + params := []interface{}{methodName} + + if len(input) > 0 { + inParamsRaw, err := methodRaw.ToIDispatch().GetProperty("InParameters") + if err != nil { + return err + } + defer inParamsRaw.Clear() + + if inParamsRaw.Val != 0 { + inParamsInstRaw, err := oleutil.CallMethod(inParamsRaw.ToIDispatch(), "SpawnInstance_") + if err != nil { + return err + } + defer inParamsInstRaw.Clear() + + inParamsInst := inParamsInstRaw.ToIDispatch() + + for k, v := range input { + putResult, err := oleutil.PutProperty(inParamsInst, k, v) + if err != nil { + return fmt.Errorf("set param %s failed: %w", k, err) + } + putResult.Clear() + } + + params = append(params, inParamsInst) + } + } + + outParamsRaw, err := classInst.CallMethod("ExecMethod_", params...) + if err != nil { + return fmt.Errorf("ExecMethod_ failed: %w", err) + } + defer outParamsRaw.Clear() + + outParams := outParamsRaw.ToIDispatch() + + rv, err := outParams.GetProperty("ReturnValue") + if err != nil { + return fmt.Errorf("ReturnValue failed: %w", err) + } + defer rv.Clear() + returnValue = NewSafeVariant(rv).Uint32() + + propsRaw, err := outParams.GetProperty("Properties_") + if err != nil { + return err + } + defer propsRaw.Clear() + + props := propsRaw.ToIDispatch() + + output = make(map[string]interface{}) + err = Enumerate(props, func(item *ole.VARIANT) error { + prop := item.ToIDispatch() + + nameVar, err := prop.GetProperty("Name") + if err != nil { + return err + } + defer nameVar.Clear() + + name := fmt.Sprintf("%v", nameVar.Value()) + + valVar, err := prop.GetProperty("Value") + if err != nil { + return err + } + defer valVar.Clear() + + val, err := handler(name, valVar) + if err != nil { + return err + } + if val != nil { + output[name] = val + } + + return nil + }) + return err + }) + return returnValue, output, err +} + +// COMDispatchObject is a wrapper around an ole.IDispatch object. +type COMDispatchObject struct { + obj *ole.IDispatch +} + +// NewCOMDispatchObject clones an ole.IDispatch object and returns a COMDispatchObject. +// +// Ownership of the object is not transferred to the COMDispatchObject. +// Instead, it holds a new reference to the object. +func NewCOMDispatchObject(obj *ole.IDispatch) *COMDispatchObject { + if obj != nil { + obj.AddRef() + } + return &COMDispatchObject{obj: obj} +} + +func (c *COMDispatchObject) Dispatch() *ole.IDispatch { + return c.obj +} + +func (c *COMDispatchObject) GetProperty(name string) (*ole.VARIANT, error) { + return GetProperty(c.Dispatch(), name) +} + +func (c *COMDispatchObject) CallMethod(name string, fn func(*ole.VARIANT) error, params ...interface{}) error { + v, err := oleutil.CallMethod(c.Dispatch(), name, params...) + if err != nil { + return err + } + defer v.Clear() + + return fn(v) +} + +func (c *COMDispatchObject) CallVoid(name string, params ...interface{}) error { + return c.CallMethod(name, DiscardResult, params...) +} + +func (c *COMDispatchObject) CallUint32(name string, params ...interface{}) (uint32, error) { + var result uint32 + err := c.CallMethod(name, func(variant *ole.VARIANT) error { + result = NewSafeVariant(variant).Uint32() + return nil + }, params...) + return result, err +} + +func (c *COMDispatchObject) GetAssociated(scope *Scope, assocClass, resultClass, role, resultRole string) ([]*COMDispatchObject, error) { + results := make([]*COMDispatchObject, 0) + + err := Associators(c.Dispatch(), assocClass, resultClass, role, resultRole, func(item *ole.IDispatch) error { + obj := NewCOMDispatchObject(item) + results = append(results, scope.Track(obj)) + return nil + }) + if err != nil { + return nil, err + } + + return results, nil +} + +func (c *COMDispatchObject) Clone() *COMDispatchObject { + return NewCOMDispatchObject(c.obj) +} + +func (c *COMDispatchObject) release() { + if c.obj != nil { + c.obj.Release() + c.obj = nil + } +} + +// QueryObjectsWithBuilder queries WMI objects with the given query builder. +func QueryObjectsWithBuilder(scope *Scope, q *QueryBuilder) ([]*COMDispatchObject, error) { + results := make([]*COMDispatchObject, 0) + + err := Query(q.Namespace, q.Build(), func(item *ole.IDispatch) error { + obj := NewCOMDispatchObject(item) + results = append(results, scope.Track(obj)) + return nil + }) + if err != nil { + return nil, err + } + + return results, nil +} + +// QueryFirstObjectWithBuilder queries the first object with the given query builder. +// +// It returns the object and the error. +// +// If the object is not found, it returns ErrNotFound. +// +// If the query fails, it returns the error. +// +// If the query is successful, it returns the object. +func QueryFirstObjectWithBuilder(scope *Scope, q *QueryBuilder) (*COMDispatchObject, error) { + var result *COMDispatchObject + + err := Query(q.Namespace, q.Build(), func(item *ole.IDispatch) error { + result = scope.Track(NewCOMDispatchObject(item)) + + // stop early + return ErrStopIteration + }) + + if err != nil && !errors.Is(err, ErrStopIteration) { + return nil, err + } + + if result == nil { + return nil, ErrNotFound + } + + return result, nil +} + +func ForEach(items []*COMDispatchObject, fn func(*COMDispatchObject) error) error { + for _, item := range items { + if err := fn(item); err != nil { + if errors.Is(err, ErrStopIteration) { + return nil // stop early + } + return err + } + } + return nil +} + +// SafeVariant is a wrapper around an ole.VARIANT object. +type SafeVariant struct { + v *ole.VARIANT +} + +func NewSafeVariant(v *ole.VARIANT) SafeVariant { + return SafeVariant{v: v} +} + +func (s SafeVariant) Bool() bool { + if s.v == nil { + return false + } + if s.v.VT == ole.VT_BOOL { + return (s.v.Val & 0xffff) != 0 + } + return false +} + +func (s SafeVariant) String() string { + if s.v == nil { + return "" + } + return s.v.ToString() +} + +func isInteger(vt ole.VT) bool { + switch vt { + case ole.VT_I1, ole.VT_UI1, ole.VT_I2, ole.VT_UI2, ole.VT_I4, ole.VT_UI4, ole.VT_I8, ole.VT_UI8, ole.VT_INT, ole.VT_UINT: + return true + } + return false +} + +func (s SafeVariant) Int() int { + if s.v == nil || !isInteger(s.v.VT) { + return 0 + } + return int(s.v.Val) +} + +func (s SafeVariant) Int32() int32 { + if s.v == nil || !isInteger(s.v.VT) { + return 0 + } + return int32(s.v.Val) +} + +func (s SafeVariant) Int64() int64 { + if s.v == nil || !isInteger(s.v.VT) { + return 0 + } + return s.v.Val +} + +func (s SafeVariant) Uint16() uint16 { + if s.v == nil || !isInteger(s.v.VT) { + return 0 + } + return uint16(s.v.Val & 0xFFFF) +} + +func (s SafeVariant) Uint32() uint32 { + if s.v == nil || !isInteger(s.v.VT) { + return 0 + } + return uint32(s.v.Val & 0xFFFFFFFF) +} + +func (s SafeVariant) Uint64() uint64 { + if s.v == nil || !isInteger(s.v.VT) { + return 0 + } + return uint64(s.v.Val) +} + +func (s SafeVariant) Raw() (interface{}, bool) { + if s.v == nil { + return nil, false + } + return s.v.Value(), true +} + +func (s SafeVariant) Value() (interface{}, error) { + if s.v == nil { + return nil, fmt.Errorf("variant is nil") + } + return s.v.Value(), nil +} + +func (s SafeVariant) Clear() error { + if s.v == nil { + return nil + } + + return s.v.Clear() +} + +// Scope is a scope for a WMI operation to track the objects created during the operation. +// +// It is used to ensure that the objects are released when the scope is closed. +type Scope struct { + objs []*COMDispatchObject +} + +// Track tracks the given object in the scope. +// +// It returns the object itself. +func (s *Scope) Track(obj *COMDispatchObject) *COMDispatchObject { + if obj == nil { + return nil + } + + s.objs = append(s.objs, obj) + return obj +} + +// Close closes the scope and releases the objects. +func (s *Scope) Close() { + for i := len(s.objs) - 1; i >= 0; i-- { + if s.objs[i] != nil { + s.objs[i].release() + } + } + s.objs = nil +} + +// WithScope runs the given function with a new scope. +// It returns the error from the function. +func WithScope(fn func(*Scope) error) error { + scope := &Scope{} + defer scope.Close() + + return fn(scope) +} + +// WMIError is an error for a WMI operation. +type WMIError struct { + Method string + Class string + Target string + Code uint32 + Details string +} + +// NewWMIError creates a new WMIError. +func NewWMIError(class, method string, target *ole.IDispatch, code uint32) *WMIError { + return &WMIError{ + Class: class, + Method: method, + Target: fmt.Sprintf("%v", target), + Code: code, + } +} + +func (e *WMIError) Error() string { + if e.Details != "" { + return fmt.Sprintf("WMI %s.%s failed (target=%v): %s (code=%d)", e.Class, e.Method, e.Target, e.Details, e.Code) + } + return fmt.Sprintf("WMI %s.%s failed (target=%v): code=%d", e.Class, e.Method, e.Target, e.Code) +} diff --git a/pkg/os/wmi/wmi_test.go b/pkg/os/wmi/wmi_test.go new file mode 100644 index 0000000000..ccbf27a46b --- /dev/null +++ b/pkg/os/wmi/wmi_test.go @@ -0,0 +1,102 @@ +//go:build windows +// +build windows + +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package wmi + +import ( + "testing" +) + +func TestFormatValue(t *testing.T) { + tests := []struct { + name string + input any + expected string + }{ + {"string simple", "hello", "'hello'"}, + {"string with single quote", "it's", "'it''s'"}, + {"string with backslash", `c:\path`, `'c:\\path'`}, + {"string with both", `it's a\path`, `'it''s a\\path'`}, + {"int", 42, "42"}, + {"uint32", uint32(10), "10"}, + {"int64", int64(-1), "-1"}, + {"bool true", true, "TRUE"}, + {"bool false", false, "FALSE"}, + {"empty string", "", "''"}, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + got := formatValue(tc.input) + if got != tc.expected { + t.Errorf("formatValue(%v) = %s, want %s", tc.input, got, tc.expected) + } + }) + } +} + +func TestQueryBuilderBuild(t *testing.T) { + tests := []struct { + name string + builder *QueryBuilder + expected string + }{ + { + name: "simple select all", + builder: NewQuery("MSFT_Disk").WithNamespace("root/microsoft/windows/storage"), + expected: "SELECT * FROM MSFT_Disk", + }, + { + name: "select specific fields", + builder: NewQuery("MSFT_Disk").Select("Number", "Size"), + expected: "SELECT Number, Size FROM MSFT_Disk", + }, + { + name: "with condition string", + builder: NewQuery("MSFT_Volume").Select("UniqueId").WithCondition("UniqueId", "=", "vol-1"), + expected: "SELECT UniqueId FROM MSFT_Volume WHERE UniqueId = 'vol-1'", + }, + { + name: "with condition numeric", + builder: NewQuery("MSFT_Partition").WithCondition("DiskNumber", "=", uint32(1)), + expected: "SELECT * FROM MSFT_Partition WHERE DiskNumber = 1", + }, + { + name: "multiple conditions", + builder: NewQuery("MSFT_Partition"). + WithCondition("DiskNumber", "=", uint32(1)). + WithCondition("PartitionNumber", "=", uint32(2)), + expected: "SELECT * FROM MSFT_Partition WHERE DiskNumber = 1 AND PartitionNumber = 2", + }, + { + name: "condition with special chars", + builder: NewQuery("MSFT_SmbGlobalMapping").WithCondition("RemotePath", "=", `\\server\share`), + expected: `SELECT * FROM MSFT_SmbGlobalMapping WHERE RemotePath = '\\\\server\\share'`, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + got := tc.builder.Build() + if got != tc.expected { + t.Errorf("Build() = %s, want %s", got, tc.expected) + } + }) + } +} diff --git a/vendor/github.com/microsoft/wmi/LICENSE b/vendor/github.com/microsoft/wmi/LICENSE deleted file mode 100644 index 4b1ad51b2f..0000000000 --- a/vendor/github.com/microsoft/wmi/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE diff --git a/vendor/github.com/microsoft/wmi/go/wmi/Class.go b/vendor/github.com/microsoft/wmi/go/wmi/Class.go deleted file mode 100644 index e19f033275..0000000000 --- a/vendor/github.com/microsoft/wmi/go/wmi/Class.go +++ /dev/null @@ -1,16 +0,0 @@ -package wmi - -// Class -type Class interface { - ClassName() string - SuperClassName() string - ServerName() string - Namespace() string - SuperClass() *Class - Properties() []string - Qualifiers() []string - Methods() []string - MethodParameters(string) []string - InvokeMethod(string, []string, string) (error, string) - Dispose() -} diff --git a/vendor/github.com/microsoft/wmi/go/wmi/Credentials.go b/vendor/github.com/microsoft/wmi/go/wmi/Credentials.go deleted file mode 100644 index 1a77528843..0000000000 --- a/vendor/github.com/microsoft/wmi/go/wmi/Credentials.go +++ /dev/null @@ -1,13 +0,0 @@ -package wmi - -// Credentials -type Credentials struct { - UserName string - Password string - Domain string -} - -// GetSecureString -func (cred Credentials) GetSecureString() (string, error) { - panic("not implemented") -} diff --git a/vendor/github.com/microsoft/wmi/go/wmi/Instance.go b/vendor/github.com/microsoft/wmi/go/wmi/Instance.go deleted file mode 100644 index 7392038d3e..0000000000 --- a/vendor/github.com/microsoft/wmi/go/wmi/Instance.go +++ /dev/null @@ -1,24 +0,0 @@ -package wmi - -// Instance represents an interface for the wmi instance -type Instance interface { - GetInstance() (*Instance, error) - GetProperty(name string) (string, error) - SetProperty(name, value string) (string, error) - ResetProperty(name string) (string, error) - Class() *Class - EmbeddedInstance() (string, error) - InstanceManager() *InstanceManager - Equals(*Instance) bool - Refresh() error - Commit() error - Modify() error - Delete() error - InstancePath() (string, error) - InvokeMethod(namespaceName string, methodName string, methodParameters *[]MethodParameter) (MethodResult, error) - GetRelated(resultClassName string) (*[]Instance, error) - GetRelatedEx(resultClassName, associatedClassName, resultRole, sourceRole string) (*[]Instance, error) - GetAssociated(resultClassName, associatedClassName, resultRole, sourceRole string) (*[]Instance, error) - EnumerateReferencingInstances(associatedClassName, sourceRole string) (*[]Instance, error) - Dispose() -} diff --git a/vendor/github.com/microsoft/wmi/go/wmi/InstanceManager.go b/vendor/github.com/microsoft/wmi/go/wmi/InstanceManager.go deleted file mode 100644 index 9e2d45800f..0000000000 --- a/vendor/github.com/microsoft/wmi/go/wmi/InstanceManager.go +++ /dev/null @@ -1,17 +0,0 @@ -package wmi - -// InstanceManager interface -type InstanceManager interface { - ServerName() string - Namespace() string - Credentials() *Credentials - EnumerateInstances(className string) (*[]Instance, error) - QueryInstances(query string) (*[]Instance, error) - QueryInstancesEx(query Query) (*[]Instance, error) - - CreateInstance(className string, propertyValues map[string]string) (*Instance, error) - GetInstance(className string, propertyValues map[string]string) (*Instance, error) - GetClass(className string) (*Class, error) - EnumerateClasses() (*[]Class, error) - GetInstancesFromPaths(pathArray []string) (*[]Instance, error) -} diff --git a/vendor/github.com/microsoft/wmi/go/wmi/MethodDeclaration.go b/vendor/github.com/microsoft/wmi/go/wmi/MethodDeclaration.go deleted file mode 100644 index 16b0844462..0000000000 --- a/vendor/github.com/microsoft/wmi/go/wmi/MethodDeclaration.go +++ /dev/null @@ -1,7 +0,0 @@ -package wmi - -type MethodDeclaration struct { - Name string - Parameters *[]MethodParameter - Qualifiers *[]Qualifier -} diff --git a/vendor/github.com/microsoft/wmi/go/wmi/MethodParameter.go b/vendor/github.com/microsoft/wmi/go/wmi/MethodParameter.go deleted file mode 100644 index 897f50f6cc..0000000000 --- a/vendor/github.com/microsoft/wmi/go/wmi/MethodParameter.go +++ /dev/null @@ -1,66 +0,0 @@ -package wmi - -import ( - "errors" - "reflect" -) - -// MethodParameter -type MethodParameter struct { - Name string - Value interface{} - Type WmiType -} - -// MethodParameterCollection -type MethodParameterCollection []MethodParameter - -// GetValue -func (c MethodParameterCollection) GetValue(paramName string, value interface{}) error { - mval, err := c.Get(paramName) - if err != nil { - return errors.New("Not Found") - } - value = mval.Value - return nil -} - -// GetValueArray -func (c MethodParameterCollection) GetValueArray(paramName string, value interface{}) error { - mval, err := c.Get(paramName) - if err != nil { - return errors.New("Not Found") - } - if mval.Value != nil { - v := reflect.ValueOf(mval.Value) - - tmpValue := make([]interface{}, v.Len()) - for i := 0; i < v.Len(); i++ { - tmpValue[i] = v.Index(i).Interface() - value = tmpValue - } - } else { - value = make([]interface{}, 0) - } - return nil -} - -// Contains -func (c MethodParameterCollection) Contains(paramName string) bool { - for _, a := range c { - if a.Name == paramName { - return true - } - } - return false -} - -// Contains -func (c MethodParameterCollection) Get(paramName string) (val *MethodParameter, err error) { - for _, a := range c { - if a.Name == paramName { - return &a, nil - } - } - return nil, errors.New("Not Found") -} diff --git a/vendor/github.com/microsoft/wmi/go/wmi/MethodResult.go b/vendor/github.com/microsoft/wmi/go/wmi/MethodResult.go deleted file mode 100644 index 654cc0061b..0000000000 --- a/vendor/github.com/microsoft/wmi/go/wmi/MethodResult.go +++ /dev/null @@ -1,7 +0,0 @@ -package wmi - -// MethodResult -type MethodResult struct { - ReturnValue *MethodParameter - OutParameters *MethodParameterCollection -} diff --git a/vendor/github.com/microsoft/wmi/go/wmi/Property.go b/vendor/github.com/microsoft/wmi/go/wmi/Property.go deleted file mode 100644 index 1047d08a70..0000000000 --- a/vendor/github.com/microsoft/wmi/go/wmi/Property.go +++ /dev/null @@ -1,91 +0,0 @@ -package wmi - -type PropertyFlags int - -const ( - // None - None PropertyFlags = 0 - // Class - WClass PropertyFlags = 1 - // Method - Method PropertyFlags = 2 - // Property - WProperty PropertyFlags = 4 - // Parameter - Parameter PropertyFlags = 8 - // Association - Association PropertyFlags = 16 - // Indication - Indication PropertyFlags = 32 - // Reference - Reference PropertyFlags = 64 - // Any - Any PropertyFlags = 127 - // EnableOverride - EnableOverride PropertyFlags = 128 - // DisableOverride - DisableOverride PropertyFlags = 256 - // Restricted - Restricted PropertyFlags = 512 - // ToSubClass - ToSubclass PropertyFlags = 1024 - // Translatable - Translatable PropertyFlags = 2048 - // Key - Key PropertyFlags = 4096 - // In - In PropertyFlags = 8192 - // Out - Out PropertyFlags = 16384 - // Required - Required PropertyFlags = 32768 - // Static - Static PropertyFlags = 65536 - // Abstract - Abstract PropertyFlags = 131072 - // Terminal - Terminal PropertyFlags = 262144 - // Expensive - Expensive PropertyFlags = 524288 - // Stream - Stream PropertyFlags = 1048576 - // ReadOnly - ReadOnly PropertyFlags = 2097152 - // NotModified - NotModified PropertyFlags = 33554432 - // NullValue - NullValue PropertyFlags = 536870912 - // Borrow - Borrow PropertyFlags = 1073741824 - // Adopt - //Adopt PropertyFlags = 2147483648; -) - -type WmiType int - -const ( - WbemCimtypeSint8 WmiType = 16 - WbemCimtypeUint8 WmiType = 17 - WbemCimtypeSint16 WmiType = 2 - WbemCimtypeUint16 WmiType = 18 - WbemCimtypeSint32 WmiType = 3 - WbemCimtypeUint32 WmiType = 19 - WbemCimtypeSint64 WmiType = 20 - WbemCimtypeUint64 WmiType = 21 - WbemCimtypeReal32 WmiType = 4 - WbemCimtypeReal64 WmiType = 5 - WbemCimtypeBoolean WmiType = 11 - WbemCimtypeString WmiType = 8 - WbemCimtypeDatetime WmiType = 101 - WbemCimtypeReference WmiType = 102 - WbemCimtypeChar16 WmiType = 103 - WbemCimtypeObject WmiType = 13 -) - -// Property -type Property interface { - Name() string - Value() string - Type() WmiType - Flags() PropertyFlags -} diff --git a/vendor/github.com/microsoft/wmi/go/wmi/Qualifier.go b/vendor/github.com/microsoft/wmi/go/wmi/Qualifier.go deleted file mode 100644 index 1b8215c44f..0000000000 --- a/vendor/github.com/microsoft/wmi/go/wmi/Qualifier.go +++ /dev/null @@ -1,6 +0,0 @@ -package wmi - -type Qualifier interface { - Name() string - Value() string -} diff --git a/vendor/github.com/microsoft/wmi/go/wmi/Query.go b/vendor/github.com/microsoft/wmi/go/wmi/Query.go deleted file mode 100644 index 03d38ba5a8..0000000000 --- a/vendor/github.com/microsoft/wmi/go/wmi/Query.go +++ /dev/null @@ -1,51 +0,0 @@ -package wmi - -import "fmt" - -type WhereOperation int - -const ( - Equals WhereOperation = 0 - LessThan WhereOperation = 1 - GreaterThan WhereOperation = 2 - LessThanEquals WhereOperation = 3 - GreaterThenEquals WhereOperation = 4 - NotEqual WhereOperation = 5 - Like WhereOperation = 6 -) - -type QueryFilter struct { - Name string - Value string - Operation WhereOperation -} - -// GetFilter -func (q QueryFilter) GetFilter() string { - operator := "=" - switch q.Operation { - case Equals: - operator = "=" - case LessThan: - operator = "<" - case GreaterThan: - operator = ">" - case LessThanEquals: - operator = "<=" - case GreaterThenEquals: - operator = ">=" - case NotEqual: - operator = "!=" - case Like: - operator = "LIKE" - return fmt.Sprintf(" %s %s '%%%s%%'", q.Name, q.Value, operator) - default: - } - return fmt.Sprintf(" %s%s'%s'", q.Name, q.Value, operator) -} - -// Query -type Query interface { - ClassName() string - QueryString() string -} diff --git a/vendor/github.com/microsoft/wmi/go/wmi/Session.go b/vendor/github.com/microsoft/wmi/go/wmi/Session.go deleted file mode 100644 index 7f489c60b2..0000000000 --- a/vendor/github.com/microsoft/wmi/go/wmi/Session.go +++ /dev/null @@ -1,26 +0,0 @@ -package wmi - -type SessionStatus int - -const ( - Created SessionStatus = 0 - Connected SessionStatus = 1 - Disconnected SessionStatus = 2 - Disposed SessionStatus = 3 -) - -// Session -type Session interface { - Connect() (bool, error) - Dispose() - TestConnection() bool - GetProperty(name string) string - SetProperty(name, value string) string - ResetProperty(name string) string - GetClass(namespaceName, className string) (*Class, error) - GetInstance(namespaceName string, instance *Instance) (*Instance, error) - EnumerateClasses(namespaceName, className string) (*[]Class, error) - EnumerateInstances(namespaceName, className string) (*[]Instance, error) - QueryInstances(namespaceName, queryDislect, queryExpression string) (*[]Instance, error) - EnumerateReferencingInstances(namespaceName string, sourceInstance Instance, associationClassName, sourceRole string) (*[]Instance, error) -} diff --git a/vendor/github.com/microsoft/wmi/pkg/base/credential/credential.go b/vendor/github.com/microsoft/wmi/pkg/base/credential/credential.go deleted file mode 100644 index 150a297a89..0000000000 --- a/vendor/github.com/microsoft/wmi/pkg/base/credential/credential.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. -package credential - -type WmiCredential struct { - UserName string - Password string - Domain string -} - -// NewWmiCredential -func NewWmiCredential(username, password, domain string) *WmiCredential { - return &WmiCredential{UserName: username, Password: password, Domain: domain} -} diff --git a/vendor/github.com/microsoft/wmi/pkg/base/host/host.go b/vendor/github.com/microsoft/wmi/pkg/base/host/host.go deleted file mode 100644 index 71944e488f..0000000000 --- a/vendor/github.com/microsoft/wmi/pkg/base/host/host.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. -package host - -import ( - "github.com/microsoft/wmi/pkg/base/credential" -) - -type WmiHost struct { - HostName string - credential *credential.WmiCredential -} - -func NewWmiLocalHost() *WmiHost { - return NewWmiHost("localhost") -} - -// NewWmiHost -func NewWmiHost(hostname string) *WmiHost { - return NewWmiHostWithCredential(hostname, "", "", "") -} - -// NewWmiHostWithCredential -func NewWmiHostWithCredential(hostname, username, password, domain string) *WmiHost { - return &WmiHost{HostName: hostname, credential: credential.NewWmiCredential(username, password, domain)} -} - -// GetCredential -func (host *WmiHost) GetCredential() *credential.WmiCredential { - return host.credential -} diff --git a/vendor/github.com/microsoft/wmi/pkg/base/query/query.go b/vendor/github.com/microsoft/wmi/pkg/base/query/query.go deleted file mode 100644 index e7293c2412..0000000000 --- a/vendor/github.com/microsoft/wmi/pkg/base/query/query.go +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. -package query - -import ( - "fmt" - "log" - "strings" -) - -// https://docs.microsoft.com/en-us/windows/win32/wmisdk/wql-sql-for-wmi - -type CompareOperator string - -const ( - Equals CompareOperator = "=" - LessThan CompareOperator = "<" - GreaterThan CompareOperator = ">" - LessThanEquals CompareOperator = "<=" - GreaterThanEquals CompareOperator = ">=" - NotEquals CompareOperator = "<>" - Like CompareOperator = "LIKE" - Isa CompareOperator = "ISA" -) - -type WmiQueryFilter struct { - Name string - Value string - Operator CompareOperator -} - -type WmiQuery struct { - ClassName string - Filters []*WmiQueryFilter - SelectList []string -} - -func NewWmiQuery(className string, filters ...string) (wquery *WmiQuery) { - wquery = &WmiQuery{ClassName: className, Filters: []*WmiQueryFilter{}} - if len(filters) == 0 { - return - } - - wquery.BuildQueryFilter(filters) - return -} - -func NewWmiQueryWithSelectList(className string, selectList []string, filters ...string) (wquery *WmiQuery) { - wquery = &WmiQuery{ClassName: className, SelectList: selectList, Filters: []*WmiQueryFilter{}} - if len(filters) == 0 { - return - } - - wquery.BuildQueryFilter(filters) - return -} - -func (q *WmiQuery) BuildQueryFilter(filters []string) { - if len(filters)%2 == 1 { - log.Fatalf("Even number of strings is required to build key=value set of filters: [%+v]\n", filters) - } - - for i := 0; i < len(filters); i = i + 2 { - qfilter := NewWmiQueryFilter(filters[i], filters[i+1], Equals) - q.Filters = append(q.Filters, qfilter) - } - - return -} - -// NewWmiQueryFilter -func NewWmiQueryFilter(name, value string, oper CompareOperator) *WmiQueryFilter { - return &WmiQueryFilter{Name: name, Value: value, Operator: oper} -} - -func (q *WmiQueryFilter) String() string { - if q.Operator == Like { - return fmt.Sprintf("%s %s '%%%s%%'", q.Name, q.Operator, q.Value) - } else { - return fmt.Sprintf("%s %s '%s'", q.Name, q.Operator, q.Value) - } -} -func (q *WmiQuery) AddFilterWithComparer(propertyName, value string, oper CompareOperator) { - q.Filters = append(q.Filters, NewWmiQueryFilter(propertyName, value, oper)) - return -} -func (q *WmiQuery) AddFilter(propertyName, value string) { - q.Filters = append(q.Filters, NewWmiQueryFilter(propertyName, value, Equals)) - return -} - -// HasFilter -func (q *WmiQuery) HasFilter() bool { - return len(q.Filters) > 0 -} - -// String -func (q *WmiQuery) String() (queryString string) { - paramStr := "*" - if len(q.SelectList) > 0 { - paramStr = strings.Join(q.SelectList, ",") - } - queryString = fmt.Sprintf("SELECT %s FROM %s", paramStr, q.ClassName) - - if len(q.Filters) == 0 { - return - } - - queryString = fmt.Sprintf("%s WHERE ", queryString) - - for _, val := range q.Filters[:len(q.Filters)-1] { - queryString = queryString + fmt.Sprintf(" %s AND", val.String()) - } - - queryString = queryString + fmt.Sprintf(" %s ", q.Filters[len(q.Filters)-1].String()) - return -} - -type WmiQueryFilterCollection []*WmiQueryFilter - -func (c *WmiQueryFilterCollection) String() string { - queryString := "" - for _, query := range *c { - queryString = fmt.Sprintf("%s AND %s", queryString, query.String()) - } - return queryString -} diff --git a/vendor/github.com/microsoft/wmi/pkg/errors/errors.go b/vendor/github.com/microsoft/wmi/pkg/errors/errors.go deleted file mode 100644 index f74ffbf9f8..0000000000 --- a/vendor/github.com/microsoft/wmi/pkg/errors/errors.go +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. -package errors - -import ( - "errors" - "fmt" - "strings" - - perrors "github.com/pkg/errors" -) - -const ( - wmiError = "WMI Error 0x" -) - -var ( - NotFound error = errors.New("Not Found") - Timedout error = errors.New("Timedout") - InvalidInput error = errors.New("Invalid Input") - InvalidType error = errors.New("Invalid Type") - NotSupported error = errors.New("Not Supported") - AlreadyExists error = errors.New("Already Exists") - InvalidFilter error = errors.New("Invalid Filter") - Failed error = errors.New("Failed") - NotImplemented error = errors.New("Not Implemented") - Unknown error = errors.New("Unknown Reason") - DvdDriveNotFound error = errors.New("DVDDriveNotFound") -) - -func Wrap(cause error, message string) error { - return perrors.Wrap(cause, message) -} - -func Wrapf(err error, format string, args ...interface{}) error { - return perrors.Wrapf(err, format, args...) -} - -func IsNotFound(err error) bool { - return checkError(err, NotFound) -} -func IsAlreadyExists(err error) bool { - return checkError(err, AlreadyExists) -} -func IsTimedout(err error) bool { - return checkError(err, Timedout) -} -func IsInvalidInput(err error) bool { - return checkError(err, InvalidInput) -} -func IsInvalidType(err error) bool { - return checkError(err, InvalidType) -} -func IsNotSupported(err error) bool { - return checkError(err, NotSupported) -} -func IsInvalidFilter(err error) bool { - return checkError(err, InvalidFilter) -} -func IsFailed(err error) bool { - return checkError(err, Failed) -} -func IsNotImplemented(err error) bool { - return checkError(err, NotImplemented) -} -func IsUnknown(err error) bool { - return checkError(err, Unknown) -} -func IsDvdDriveNotFound(err error) bool { - return checkError(err, DvdDriveNotFound) -} - -func IsWMIError(err error) bool { - if err == nil { - return false - } - if strings.HasPrefix(err.Error(), wmiError) { - return true - } - cerr := perrors.Cause(err) - if strings.HasPrefix(cerr.Error(), wmiError) { - return true - } - - return false -} - -func checkError(wrappedError, err error) bool { - if wrappedError == nil { - return false - } - if wrappedError == err { - return true - } - cerr := perrors.Cause(wrappedError) - if cerr != nil && cerr == err { - return true - } - - return false - -} - -func New(errString string) error { - return errors.New(errString) -} - -func NewWMIError(errorCode uint16) error { - return fmt.Errorf(wmiError+"%08x", errorCode) -} diff --git a/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiClass.go b/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiClass.go deleted file mode 100644 index 3a5d730a7c..0000000000 --- a/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiClass.go +++ /dev/null @@ -1,314 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. - -// This class implement a wrapper of the SWbemObject class (from an instance perspective). -// Documentation: https://docs.microsoft.com/en-us/windows/win32/wmisdk/swbemobject - -package cim - -import ( - "github.com/go-ole/go-ole" - "github.com/go-ole/go-ole/oleutil" -) - -type WmiClass struct { - session *WmiSession - class *ole.IDispatch - classVar *ole.VARIANT -} - -// WmiInstanceCollection is a slice of WmiClass -type WmiClassCollection []*WmiClass - -// Close all class in a collection -func (wmic *WmiClassCollection) Close() { - for _, i := range *wmic { - i.Close() - } -} - -func CreateWmiClass(classVar *ole.VARIANT, session *WmiSession) (*WmiClass, error) { - return &WmiClass{ - classVar: classVar, - class: classVar.ToIDispatch(), - session: session, - }, nil -} - -// Makes a new instance of the class -func (c *WmiClass) MakeInstance() (*WmiInstance, error) { - rawResult, err := oleutil.CallMethod(c.class, "SpawnInstance_") - if err != nil { - return nil, err - } - - return CreateWmiInstance(rawResult, c.session) -} - -func (c *WmiClass) mustGetSystemProperty(name string) *WmiProperty { - wmiProperty, err := c.GetSystemProperty(name) - if err != nil { - panic("Couldn't retreive a system property. GetSystemProperty failed") - } - - return wmiProperty -} - -func (c *WmiClass) GetSystemProperty(name string) (*WmiProperty, error) { - // Documentation: https://docs.microsoft.com/en-us/windows/win32/wmisdk/swbemobjectex-systemproperties- - rawResult, err := oleutil.GetProperty(c.class, "SystemProperties_") - if err != nil { - return nil, err - } - - // SWbemObjectEx.SystemProperties_ returns - // an SWbemPropertySet object that contains the collection - // of sytem properties for the c class - sWbemObjectExAsIDispatch := rawResult.ToIDispatch() - defer rawResult.Clear() - - // Get the system property - sWbemProperty, err := oleutil.CallMethod(sWbemObjectExAsIDispatch, "Item", name) - if err != nil { - return nil, err - } - - return CreateWmiProperty(sWbemProperty, c.session) -} - -// ClassName -func (c *WmiClass) GetClassName() string { - class := c.mustGetSystemProperty("__CLASS") - defer class.Close() - - return class.Value().(string) -} - -// SetClassName -func (c *WmiClass) SetClassName(name string) error { - rawResult, err := oleutil.GetProperty(c.class, "Path_") - if err != nil { - return err - } - - pathIDispatch := rawResult.ToIDispatch() - defer rawResult.Clear() - - classRawResult, err := oleutil.PutProperty(pathIDispatch, "Class", name) - if err != nil { - return err - } - defer classRawResult.Clear() - - return nil -} - -// SuperClassName -func (c *WmiClass) GetSuperClassName() string { - superclass := c.mustGetSystemProperty("__SUPERCLASS") - defer superclass.Close() - - return superclass.Value().(string) -} - -// ServerName -func (c *WmiClass) GetServerName() string { - server := c.mustGetSystemProperty("__SERVER") - defer server.Close() - - return server.Value().(string) -} - -// Namespace -func (c *WmiClass) GetNamespace() string { - namespace := c.mustGetSystemProperty("__NAMESPACE") - defer namespace.Close() - - return namespace.Value().(string) -} - -// SuperClass -func (c *WmiClass) GetSuperClass() *WmiClass { - class, err := c.session.GetClass(c.GetSuperClassName()) - if err != nil { - panic("The class for this instance doesn't exist") - } - - return class -} - -// Derivation -func (c *WmiClass) GetDerivation() []string { - valueNameProperty, err := oleutil.GetProperty(c.class, "Derivation_") - if err != nil { - panic("GetDerivation() failed to get the Derivation_ name property") - } - defer valueNameProperty.Clear() - - derivations, err := GetVariantValues(valueNameProperty) - if len(derivations) < 1 { - panic("GetDerivation() failed to get the Derivation_ values") - } - - values := []string{} - for _, derivation := range derivations { - values = append(values, derivation.(string)) - } - - return values -} - -// Properties -func (c *WmiClass) GetPropertiesNames() []string { - values := c.getValueList("Properties_") - - valueNames := []string{} - for _, value := range values { - valueNames = append(valueNames, value.Name()) - } - CloseAllProperties(values) - - return valueNames -} - -// Qualifiers -func (c *WmiClass) GetQualifiersNames() []string { - values := c.getValueList("Qualifiers_") - - valueNames := []string{} - for _, value := range values { - valueNames = append(valueNames, value.Name()) - } - CloseAllProperties(values) - - return valueNames -} - -// Methods -func (c *WmiClass) GetMethodsNames() []string { - values := c.getValueList("Methods_") - - valueNames := []string{} - for _, value := range values { - valueNames = append(valueNames, value.Name()) - } - CloseAllProperties(values) - - return valueNames -} - -// GetProperty gets the property of the instance specified by name and returns in value -func (c *WmiClass) GetProperty(name string) (interface{}, error) { - rawResult, err := oleutil.GetProperty(c.class, name) - if err != nil { - return nil, err - } - - defer rawResult.Clear() - - if rawResult.VT == 0x1 { - return nil, err - } - - return GetVariantValue(rawResult) -} - -// SetProperty sets a value of property representation by name with value -func (c *WmiClass) SetProperty(name string, value interface{}) error { - rawResult, err := oleutil.PutProperty(c.class, name, value) - if err != nil { - return err - } - - defer rawResult.Clear() - return nil -} - -// Commit -func (c *WmiClass) Commit() error { - rawResult, err := oleutil.CallMethod(c.class, "Put_") - if err != nil { - return err - } - defer rawResult.Clear() - return nil - -} - -// Modify -func (c *WmiClass) Modify() error { - return c.Commit() -} - -func (c *WmiClass) getValueList(valuePropertyName string) []*WmiProperty { - valuesProperty, err := oleutil.GetProperty(c.class, valuePropertyName) - if err != nil { - panic("getValueList failed getting valuePropertyName") - } - defer valuesProperty.Clear() - - result := valuesProperty.ToIDispatch() - // Doc: https://docs.microsoft.com/en-us/previous-versions/windows/desktop/automat/dispid-constants - enum_property, err := result.GetProperty("_NewEnum") - if err != nil { - panic("getValueList() failed getting _NewEnum") - } - defer enum_property.Clear() - - // https://docs.microsoft.com/en-us/windows/win32/api/oaidl/nn-oaidl-ienumvariant - enum, err := enum_property.ToIUnknown().IEnumVARIANT(ole.IID_IEnumVariant) - if err != nil { - panic("getValueList() failed getting IID_IEnumVariant") - } - if enum == nil { - return []*WmiProperty{} - } - defer enum.Release() - - properties := []*WmiProperty{} - for valueVariant, length, err := enum.Next(1); length > 0; valueVariant, length, err = enum.Next(1) { - if err != nil { - panic("getValueList() failed to browse the value list") - } - - property, err := CreateWmiProperty(&valueVariant, c.session) - if err != nil { - panic("getValueList() failed to create the WMI property") - } - - properties = append(properties, property) - } - - return properties -} - -// MethodParameters -func (c *WmiClass) MethodParameters(methodName string) []string { - panic("not implemented") - // TODO. Relevant docs: - // https://docs.microsoft.com/en-us/windows/win32/wmisdk/swbemmethodset - // https://docs.microsoft.com/en-us/windows/win32/wmisdk/swbemmethod -} - -// Invoke static method on a wmi class -func (c *WmiClass) InvokeMethod(methodName string, params ...interface{}) ([]interface{}, error) { - rawResult, err := oleutil.CallMethod(c.class, methodName, params...) - if err != nil { - return nil, err - } - defer rawResult.Clear() - values, err := GetVariantValues(rawResult) - return values, err -} - -// CloseAllClasses -func CloseAllClasses(classes []*WmiClass) { - for _, class := range classes { - class.Close() - } -} - -// Dispose -func (c *WmiClass) Close() error { - return c.classVar.Clear() -} diff --git a/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiEventSink.go b/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiEventSink.go deleted file mode 100644 index 2d6c83e3f3..0000000000 --- a/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiEventSink.go +++ /dev/null @@ -1,248 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. - -// This class wraps a typicaly SWbemSink object. Its implementation is based on the -// SWbemSink documentation: https://docs.microsoft.com/en-us/windows/win32/wmisdk/receiving-asynchronous-event-notifications -// as well as the winsock example: https://github.com/go-ole/go-ole/blob/master/_example/winsock/winsock.go - -// Note: Please consider the security implications of makig asynchronous calls. -// Documentation: -// https://docs.microsoft.com/en-us/windows/win32/wmisdk/making-an-asynchronous-call-with-vbscript -// https://docs.microsoft.com/en-us/windows/win32/wmisdk/setting-security-on-an-asynchronous-call - -package cim - -import ( - "reflect" - "syscall" - "unsafe" - - ole "github.com/go-ole/go-ole" - "github.com/go-ole/go-ole/oleutil" -) - -var IID_ISWbemObjectPath = &ole.GUID{0x5791BC27, 0xCE9C, 0x11d1, [8]byte{0x97, 0xBF, 0x00, 0x00, 0xF8, 0x1E, 0x84, 0x9C}} -var IID_ISWbemSinkEvents = &ole.GUID{0x75718CA0, 0xF029, 0x11d1, [8]byte{0xA1, 0xAC, 0x00, 0xC0, 0x4F, 0xB6, 0xC2, 0x23}} - -const ( - eventSinkObjectName = "WbemScripting.SWbemSink" - iSWbemSinkEventsGuid = "{75718CA0-F029-11D1-A1AC-00C04FB6C223}" -) - -type WmiEventSink struct { - lpVtbl *WmiEventSinkVtbl - ref int32 - instance *ole.IDispatch - unknown *ole.IUnknown - closed bool - session *WmiSession - onObjectReady func(interface{}, []*WmiInstance) - onCompleted func(interface{}, []*WmiInstance) - onProgress func(interface{}, []*WmiInstance) - onObjectPut func(interface{}, []*WmiInstance) - callbackContext interface{} -} - -type WmiEventSinkVtbl struct { - pQueryInterface uintptr - pAddRef uintptr - pRelease uintptr - pGetTypeInfoCount uintptr - pGetTypeInfo uintptr - pGetIDsOfNames uintptr - pInvoke uintptr -} - -// DISPPARAMS are the arguments that passed to methods or property. -type DISPPARAMS struct { - rgvarg uintptr - rgdispidNamedArgs uintptr - cArgs uint32 - cNamedArgs uint32 -} - -func CreateWmiEventSink(session *WmiSession, callbackContext interface{}, onObjectReady func(interface{}, []*WmiInstance), onCompleted func(interface{}, []*WmiInstance), onProgress func(interface{}, []*WmiInstance), onObjectPut func(interface{}, []*WmiInstance)) (*WmiEventSink, error) { - eventSinkObject, err := oleutil.CreateObject(eventSinkObjectName) - if err != nil { - return nil, err - } - - eventSinkInstance, err := eventSinkObject.QueryInterface(ole.IID_IDispatch) - if err != nil { - return nil, err - } - - wmiEventSink := &WmiEventSink{} - wmiEventSink.lpVtbl = &WmiEventSinkVtbl{} - wmiEventSink.lpVtbl.pQueryInterface = syscall.NewCallback(queryInterface) - wmiEventSink.lpVtbl.pAddRef = syscall.NewCallback(addRef) - wmiEventSink.lpVtbl.pRelease = syscall.NewCallback(release) - wmiEventSink.lpVtbl.pGetTypeInfoCount = syscall.NewCallback(getTypeInfoCount) - wmiEventSink.lpVtbl.pGetTypeInfo = syscall.NewCallback(getTypeInfo) - wmiEventSink.lpVtbl.pGetIDsOfNames = syscall.NewCallback(getIDsOfNames) - wmiEventSink.lpVtbl.pInvoke = syscall.NewCallback(invoke) - wmiEventSink.onObjectReady = onObjectReady - wmiEventSink.onCompleted = onCompleted - wmiEventSink.onProgress = onProgress - wmiEventSink.onObjectPut = onObjectPut - wmiEventSink.callbackContext = callbackContext - wmiEventSink.instance = eventSinkInstance - wmiEventSink.unknown = eventSinkObject - wmiEventSink.session = session - - return wmiEventSink, nil -} - -func (c *WmiEventSink) Connect() (cookie uint32, err error) { - cookie = 0 - err = nil - - connectionPointContainer, err := c.instance.QueryInterface(ole.IID_IConnectionPointContainer) - if err != nil { - return - } - defer connectionPointContainer.Release() - - container := (*ole.IConnectionPointContainer)(unsafe.Pointer(connectionPointContainer)) - - var point *ole.IConnectionPoint - err = container.FindConnectionPoint(IID_ISWbemSinkEvents, &point) - if err != nil { - return - } - - return point.Advise((*ole.IUnknown)(unsafe.Pointer(c))) -} - -func (c *WmiEventSink) GetAndDispatchMessages() { - for c.ref != 0 { - var m ole.Msg - ole.GetMessage(&m, 0, 0, 0) - ole.DispatchMessage(&m) - } -} - -func (c *WmiEventSink) IsReadyToClose() bool { - return (c.ref == 0) -} - -func (c *WmiEventSink) PeekAndDispatchMessages() bool { - var m ole.Msg - msgAvailable, err := PeekMessage(&m, 0, 0, 0, PM_REMOVE) - if err != nil { - return false - } - - if msgAvailable { - ole.DispatchMessage(&m) - } - - return msgAvailable -} - -func (c *WmiEventSink) IsClosed() bool { - return c.closed -} -func (c *WmiEventSink) Close() { - if c.instance != nil { - c.instance.Release() - c.instance = nil - } - if c.unknown != nil { - c.unknown.Release() - c.unknown = nil - } - c.closed = true -} - -/////////////////////////////// Private methods and callbacks ///////////////////////////////////////////////////// - -func queryInterface(this *ole.IUnknown, iid *ole.GUID, punk **ole.IUnknown) uintptr { - s, _ := ole.StringFromCLSID(iid) - - *punk = nil - if ole.IsEqualGUID(iid, ole.IID_IUnknown) || - ole.IsEqualGUID(iid, ole.IID_IDispatch) { - addRef(this) - *punk = this - return ole.S_OK - } - if s == iSWbemSinkEventsGuid { - addRef(this) - *punk = this - return ole.S_OK - } - - return ole.E_NOINTERFACE -} - -func addRef(this *ole.IUnknown) uintptr { - pthis := (*WmiEventSink)(unsafe.Pointer(this)) - pthis.ref++ - return uintptr(pthis.ref) -} - -func release(this *ole.IUnknown) uintptr { - pthis := (*WmiEventSink)(unsafe.Pointer(this)) - pthis.ref-- - return uintptr(pthis.ref) -} - -func getIDsOfNames(this *ole.IUnknown, iid *ole.GUID, wnames **uint16, namelen int, lcid int, pdisp *int32) uintptr { - var pdispSlice []int32 - sliceHeader := (*reflect.SliceHeader)((unsafe.Pointer(&pdispSlice))) - sliceHeader.Cap = namelen - sliceHeader.Len = namelen - sliceHeader.Data = uintptr(unsafe.Pointer(pdisp)) - - var pwnamesSlice []*uint16 - sliceHeader2 := (*reflect.SliceHeader)((unsafe.Pointer(&pwnamesSlice))) - sliceHeader2.Cap = namelen - sliceHeader2.Len = namelen - sliceHeader2.Data = uintptr(unsafe.Pointer(wnames)) - - for n := 0; n < namelen; n++ { - pdispSlice[n] = int32(n) - } - return uintptr(ole.S_OK) -} - -func getTypeInfoCount(pcount *int) uintptr { - if pcount != nil { - *pcount = 0 - } - return uintptr(ole.S_OK) -} - -func getTypeInfo(ptypeif *uintptr) uintptr { - return uintptr(ole.E_NOTIMPL) -} - -func invoke(this *ole.IDispatch, dispid int, riid *ole.GUID, lcid int, flags int16, rawdispparams *DISPPARAMS, result *ole.VARIANT, pexcepinfo *ole.EXCEPINFO, nerr *uint) uintptr { - pthis := (*WmiEventSink)(unsafe.Pointer(this)) - if pthis.IsClosed() { - return ole.S_OK - } - - dispparams := GetDispParamsFromRaw(rawdispparams) - wmiEventInstances, err := GetVariantArrayAsWmiInstances(dispparams.rgvarg, pthis.session) - if err != nil { - return ole.S_OK - } - switch dispid { - case 1: - pthis.onObjectReady(pthis.callbackContext, wmiEventInstances) - return ole.S_OK - case 2: - pthis.onCompleted(pthis.callbackContext, wmiEventInstances) - return ole.S_OK - case 3: - pthis.onProgress(pthis.callbackContext, wmiEventInstances) - return ole.S_OK - case 4: - pthis.onObjectPut(pthis.callbackContext, wmiEventInstances) - return ole.S_OK - default: - } - return ole.E_NOTIMPL -} diff --git a/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiHelper.go b/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiHelper.go deleted file mode 100644 index 322fe9156d..0000000000 --- a/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiHelper.go +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. - -package cim - -import ( - "reflect" - "syscall" - "unsafe" - - "github.com/go-ole/go-ole" - "golang.org/x/sys/windows" - "strings" -) - -// Additional calls -var ( - modole32 = windows.NewLazySystemDLL("ole32.dll") - moduser32 = windows.NewLazySystemDLL("user32.dll") - - procCoInitializeSecurity = modole32.NewProc("CoInitializeSecurity") - procPeekMessageW = moduser32.NewProc("PeekMessageW") -) - -type RemoveMessageFlags uint32 - -const ( - PM_NOREMOVE RemoveMessageFlags = 0 - PM_REMOVE RemoveMessageFlags = 1 - PM_NOYIELD RemoveMessageFlags = 2 -) - -type RpcAuthenticationLevel uint32 - -const ( - RPC_C_AUTHN_LEVEL_DEFAULT RpcAuthenticationLevel = 0 - RPC_C_AUTHN_LEVEL_NONE RpcAuthenticationLevel = 1 - RPC_C_AUTHN_LEVEL_CONNECT RpcAuthenticationLevel = 2 - RPC_C_AUTHN_LEVEL_CALL RpcAuthenticationLevel = 3 - RPC_C_AUTHN_LEVEL_PKT RpcAuthenticationLevel = 4 - RPC_C_AUTHN_LEVEL_PKT_INTEGRITY RpcAuthenticationLevel = 5 - RPC_C_AUTHN_LEVEL_PKT_PRIVACY RpcAuthenticationLevel = 6 -) - -type RpcImpersonationLevel uint32 - -const ( - RPC_C_IMP_LEVEL_DEFAULT RpcImpersonationLevel = 0 - RPC_C_IMP_LEVEL_ANONYMOUS RpcImpersonationLevel = 1 - RPC_C_IMP_LEVEL_IDENTIFY RpcImpersonationLevel = 2 - RPC_C_IMP_LEVEL_IMPERSONATE RpcImpersonationLevel = 3 - RPC_C_IMP_LEVEL_DELEGATE RpcImpersonationLevel = 4 -) - -type tagEOLE_AUTHENTICATION_CAPABILITIES uint32 - -const ( - EOAC_NONE tagEOLE_AUTHENTICATION_CAPABILITIES = 0 - EOAC_MUTUAL_AUTH tagEOLE_AUTHENTICATION_CAPABILITIES = 0x1 - EOAC_STATIC_CLOAKING tagEOLE_AUTHENTICATION_CAPABILITIES = 0x20 - EOAC_DYNAMIC_CLOAKING tagEOLE_AUTHENTICATION_CAPABILITIES = 0x40 - EOAC_ANY_AUTHORITY tagEOLE_AUTHENTICATION_CAPABILITIES = 0x80 - EOAC_MAKE_FULLSIC tagEOLE_AUTHENTICATION_CAPABILITIES = 0x100 - EOAC_DEFAULT tagEOLE_AUTHENTICATION_CAPABILITIES = 0x800 - EOAC_SECURE_REFS tagEOLE_AUTHENTICATION_CAPABILITIES = 0x2 - EOAC_ACCESS_CONTROL tagEOLE_AUTHENTICATION_CAPABILITIES = 0x4 - EOAC_APPID tagEOLE_AUTHENTICATION_CAPABILITIES = 0x8 - EOAC_DYNAMIC tagEOLE_AUTHENTICATION_CAPABILITIES = 0x10 - EOAC_REQUIRE_FULLSIC tagEOLE_AUTHENTICATION_CAPABILITIES = 0x200 - EOAC_AUTO_IMPERSONATE tagEOLE_AUTHENTICATION_CAPABILITIES = 0x400 - EOAC_NO_CUSTOM_MARSHAL tagEOLE_AUTHENTICATION_CAPABILITIES = 0x2000 - EOAC_DISABLE_AAA tagEOLE_AUTHENTICATION_CAPABILITIES = 0x1000 -) - -const ( - RPC_E_TOO_LATE uint32 = 0x80010119 -) - -func GetVariantValue(rawValue *ole.VARIANT) (interface{}, error) { - array := rawValue.ToArray() - if array == nil { - return rawValue.Value(), nil - } - return array.ToValueArray(), nil -} - -func GetVariantValues(rawValue *ole.VARIANT) ([]interface{}, error) { - - var values []interface{} - array := rawValue.ToArray() - - if array == nil { - // Not an array - values = append(values, rawValue.Value()) - } else { - values = array.ToValueArray() - } - - return values, nil -} - -type DispParams struct { - rgvarg []ole.VARIANT - rgdispidNamedArgs []int32 -} - -func GetDispParamsFromRaw(dispparams *DISPPARAMS) *DispParams { - - // convert the DISPPARAMS to a slice header - params := DispParams{} - - var slice1 []ole.VARIANT - sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&slice1)) - sliceHeader.Data = dispparams.rgvarg - sliceHeader.Len = int(dispparams.cArgs) - sliceHeader.Cap = int(dispparams.cArgs) - params.rgvarg = make([]ole.VARIANT, dispparams.cArgs) - copy(params.rgvarg, slice1) - - var slice2 []int32 - sliceHeader = (*reflect.SliceHeader)(unsafe.Pointer(&slice2)) - sliceHeader.Data = dispparams.rgdispidNamedArgs - sliceHeader.Len = int(dispparams.cNamedArgs) - sliceHeader.Cap = int(dispparams.cNamedArgs) - params.rgdispidNamedArgs = make([]int32, dispparams.cNamedArgs) - copy(params.rgdispidNamedArgs, slice2) - - return ¶ms -} - -func GetVariantArrayAsWmiInstances(rawValues []ole.VARIANT, session *WmiSession) (WmiInstanceCollection, error) { - wcol := WmiInstanceCollection{} - for _, rawValue := range rawValues { - // skip wrong types and empty objects - if rawValue.VT != ole.VT_DISPATCH || rawValue.Val == 0 { - continue - } - - instance, err := CreateWmiInstance(&rawValue, session) - if err != nil { - return nil, err - } - wcol = append(wcol, instance) - } - - return wcol, nil -} - -func GetVariantArrayValues(rawValues []ole.VARIANT) ([]interface{}, error) { - var values []interface{} - - for _, rawValue := range rawValues { - array := rawValue.ToArray() - - if array == nil { - // Not an array - values = append(values, rawValue.Value()) - } else { - values = append(values, array.ToValueArray()) - } - } - - return values, nil -} - -func EscapeQueryValue(rawString string) string { - // Double the backslash character as per required by the "WHERE" WMI clause - // Documentation: https://docs.microsoft.com/en-us/windows/win32/wmisdk/where-clause - // Interestingly, double quotes don't seem to need escaping. - return strings.ReplaceAll(strings.ReplaceAll(rawString, "\\", "\\\\"), "'", "\\'") -} - -func FindStringInSlice(stringList []string, value string) (int, bool) { - for i, item := range stringList { - if item == value { - return i, true - } - } - return -1, false -} - -// PeekMessage in message queue from runtime. -// -// This function appears to block. PeekMessage does not block. -func PeekMessage(msg *ole.Msg, hwnd uint32, MsgFilterMin uint32, MsgFilterMax uint32, RemoveMsg RemoveMessageFlags) (ret bool, err error) { - r0, _, err := syscall.Syscall6(procPeekMessageW.Addr(), 5, uintptr(unsafe.Pointer(msg)), uintptr(hwnd), uintptr(MsgFilterMin), uintptr(MsgFilterMax), uintptr(RemoveMsg), 0) - ret = bool(r0 > 0) - return -} - -func CoInitializeSecurity(authLevel RpcAuthenticationLevel, impLevel RpcImpersonationLevel) (err error) { - // https://docs.microsoft.com/en-us/windows/win32/wmisdk/setting-the-default-process-security-level-using-c- - hr, _, _ := syscall.Syscall9(procCoInitializeSecurity.Addr(), 9, uintptr(0), ^uintptr(0), uintptr(0), uintptr(0), uintptr(authLevel), uintptr(impLevel), uintptr(0), uintptr(EOAC_NONE), uintptr(0)) - if hr != 0 { - err = ole.NewError(hr) - } - return -} diff --git a/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiInstance.go b/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiInstance.go deleted file mode 100644 index 4583fab569..0000000000 --- a/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiInstance.go +++ /dev/null @@ -1,527 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. - -// This class implement a wrapper of the SWbemObject class (from an instance perspective). -// Documentation: https://docs.microsoft.com/en-us/windows/win32/wmisdk/swbemobject - -package cim - -import ( - "fmt" - "log" - - "github.com/microsoft/wmi/pkg/base/host" - "github.com/microsoft/wmi/pkg/base/query" - "github.com/microsoft/wmi/pkg/errors" - - "github.com/go-ole/go-ole" - "github.com/go-ole/go-ole/oleutil" -) - -type UserAction uint32 - -const ( - None UserAction = 0 - Async UserAction = 1 - Wait UserAction = 2 - Cancel UserAction = 3 - Default UserAction = 4 -) - -// WmiInstance is a representation of a WMI instance -type WmiInstance struct { - class *WmiClass - session *WmiSession - instance *ole.IDispatch - instanceVar *ole.VARIANT -} - -// WmiInstanceCollection is a slice of WmiInstance -type WmiInstanceCollection []*WmiInstance - -func (wmic *WmiInstanceCollection) EmbeddedXMLInstances() (xmls []string, err error) { - for _, inst := range *wmic { - xml, err1 := inst.EmbeddedXMLInstance() - if err1 != nil { - err = err1 - return - } - xmls = append(xmls, xml) - } - return -} - -// Close all instances in a collection -func (wmic *WmiInstanceCollection) Close() { - for _, i := range *wmic { - i.Close() - } -} - -func CreateWmiInstance(instanceVar *ole.VARIANT, session *WmiSession) (*WmiInstance, error) { - return &WmiInstance{ - instanceVar: instanceVar, - instance: instanceVar.ToIDispatch(), - session: session, - }, nil -} - -// GetInstance returns the latest Instance -func (c *WmiInstance) GetInstance() (*WmiInstance, error) { - return c.session.GetInstance(c.InstancePath()) -} -func (c *WmiInstance) GetSession() *WmiSession { - return c.session -} -func (c *WmiInstance) GetWmiHost() *host.WmiHost { - return c.session.WMIHost -} - -func (c *WmiInstance) GetIDispatch() *ole.IDispatch { - return c.instance -} -func (c *WmiInstance) GetRawInstance() *ole.VARIANT { - return c.instanceVar -} - -func (c *WmiInstance) GetSystemProperty(name string) (*WmiProperty, error) { - // Documentation: https://docs.microsoft.com/en-us/windows/win32/wmisdk/swbemobjectex-systemproperties- - rawResult, err := oleutil.GetProperty(c.instance, "SystemProperties_") - if err != nil { - return nil, err - } - - // SWbemObjectEx.SystemProperties_ returns - // an SWbemPropertySet object that contains the collection - // of sytem properties for the c class - sWbemObjectExAsIDispatch := rawResult.ToIDispatch() - defer rawResult.Clear() - - // Get the system property - sWbemProperty, err := oleutil.CallMethod(sWbemObjectExAsIDispatch, "Item", name) - if err != nil { - return nil, err - } - - property, err := CreateWmiProperty(sWbemProperty, c.session) - if err != nil { - return nil, err - } - - return property, nil -} - -// GetProperty gets the property of the instance specified by name and returns in value -func (c *WmiInstance) GetProperty(name string) (interface{}, error) { - rawResult, err := oleutil.GetProperty(c.instance, name) - if err != nil { - return nil, err - } - - defer rawResult.Clear() - - if rawResult.VT == 0x1 { - return nil, err - } - - return GetVariantValue(rawResult) -} - -// SetProperty sets a value of property representation by name with value -func (c *WmiInstance) SetProperty(name string, value interface{}) error { - rawResult, err := oleutil.PutProperty(c.instance, name, value) - if err != nil { - log.Printf("[WMI] SetProperty Name[%s] Value[%+v] Err[%+v]\n", name, value, err) - return err - } - - defer rawResult.Clear() - return nil -} - -// ResetProperty resets a property -func (c *WmiInstance) ResetProperty(name string) error { - return c.SetProperty(name, nil) -} - -// GetClassName -func (c *WmiInstance) GetClassName() string { - className, err := c.GetSystemProperty("__CLASS") - if err != nil { - panic("The class doesn't have a __CLASS member " + err.Error()) - } - if className == nil { - panic("The __CLASS member doesn't contain one element, while it was expected to be") - } - defer className.Close() - - return className.Value().(string) -} - -// Class -func (c *WmiInstance) GetClass() *WmiClass { - class, err := c.session.GetClass(c.GetClassName()) - if err != nil { - panic("The class for this instance doesn't exist" + err.Error()) - } - - return class -} - -// EmbeddedXMLInstance -func (c *WmiInstance) EmbeddedXMLInstance() (string, error) { - rawResult, err := oleutil.CallMethod(c.instance, "GetText_", 1) - if err != nil { - return "", err - } - defer rawResult.Clear() - return rawResult.ToString(), err -} - -func (c *WmiInstance) String() string { - return c.InstancePath() -} - -// EmbeddedInstance -func (c *WmiInstance) EmbeddedInstance() (string, error) { - rawResult, err := oleutil.CallMethod(c.instance, "GetObjectText_") - if err != nil { - return "", err - } - defer rawResult.Clear() - return rawResult.ToString(), err -} - -// Equals -func (c *WmiInstance) Equals(instance *WmiInstance) bool { - rawResult, err := oleutil.CallMethod(c.instance, "CompareTo_", instance.instance) - if err != nil { - return false - } - defer rawResult.Clear() - value, err := GetVariantValue(rawResult) - if err != nil { - return false - } - - return value.(bool) -} - -// Clone -func (c *WmiInstance) Clone() (*WmiInstance, error) { - rawResult, err := oleutil.CallMethod(c.instance, "Clone_") - winstance, err := CreateWmiInstance(rawResult, c.session) - return winstance, err -} - -// Refresh -func (c *WmiInstance) Refresh() error { - rawResult, err := oleutil.CallMethod(c.instance, "Refresh_") - if err != nil { - return err - } - defer rawResult.Clear() - return nil -} - -// Commit -func (c *WmiInstance) Commit() error { - rawResult, err := oleutil.CallMethod(c.instance, "Put_") - if err != nil { - return err - } - defer rawResult.Clear() - return nil - -} - -// Modify -func (c *WmiInstance) Modify() error { - return c.Commit() -} - -// Delete -func (c *WmiInstance) Delete() error { - rawResult, err := oleutil.CallMethod(c.instance, "Delete_") - if err != nil { - return err - } - defer rawResult.Clear() - return nil -} - -// InstancePath -func (c *WmiInstance) InstancePath() string { - path, err := c.GetSystemProperty("__PATH") - if err != nil { - panic("The instance doesn't have a path " + err.Error()) - } - defer path.Close() - - return path.Value().(string) -} - -// RelativePath -func (c *WmiInstance) RelativePath() string { - path, err := c.GetSystemProperty("__RELPATH") - if err != nil { - panic("The instance doesn't have a path" + err.Error()) - } - defer path.Close() - - return path.Value().(string) -} - -// InvokeMethod -func (c *WmiInstance) InvokeMethod(methodName string, params ...interface{}) ([]interface{}, error) { - rawResult, err := oleutil.CallMethod(c.instance, methodName, params...) - if err != nil { - return nil, err - } - defer rawResult.Clear() - values, err := GetVariantValues(rawResult) - return values, err -} - -func (c *WmiInstance) GetWmiMethod(methodName string) (*WmiMethod, error) { - return NewWmiMethod(methodName, c) -} - -// InvokeMethodAsync -func (c *WmiInstance) InvokeMethodAsync(methodName string, action UserAction, percentComplete, timeoutSeconds uint32, params ...interface{}) ([]interface{}, error) { - rawResult, err := oleutil.CallMethod(c.instance, methodName, params...) - if err != nil { - return nil, err - } - defer rawResult.Clear() - return GetVariantValues(rawResult) -} - -// InvokeMethodWithReturn invokes a method with return -func (c *WmiInstance) InvokeMethodWithReturn(methodName string, params ...interface{}) (int32, error) { - results, err := c.InvokeMethod(methodName, params...) - if err != nil { - return 0, err - } - - // Does not have any results - if results == nil || len(results) == 0 || results[0] == nil { - return 0, nil - } - - return results[0].(int32), nil -} - -// GetAllRelatedWithQuery returns all related instances matching the query -func (c *WmiInstance) GetAllRelatedWithQuery(q *query.WmiQuery) (WmiInstanceCollection, error) { - winstances, err := c.GetAllRelated(q.ClassName) - if err != nil { - return nil, err - } - - if !q.HasFilter() { - return winstances, nil - } - - defer winstances.Close() - // For now, only Equals is implemented - filter := q.Filters[0] - filteredCollection := WmiInstanceCollection{} - for _, inst := range winstances { - propVal, err := inst.GetProperty(filter.Name) - if err != nil { - continue - } - propString := fmt.Sprintf("%v", propVal) - if propString == filter.Value { - clins, err := inst.Clone() - if err != nil { - return nil, err - } - filteredCollection = append(filteredCollection, clins) - continue - } - } - return filteredCollection, nil -} - -// GetAllRelated -func (c *WmiInstance) GetAllRelated(resultClassName string) (WmiInstanceCollection, error) { - return c.GetAssociated("", resultClassName, "", "") -} - -// GetRelated -func (c *WmiInstance) GetRelated(resultClassName string) (*WmiInstance, error) { - result, err := c.GetAllRelated(resultClassName) - if err != nil { - return nil, err - } - - if len(result) == 0 { - return nil, errors.Wrapf(errors.NotFound, "No Related Items were received for [%s]", resultClassName) - } - return result[0], nil -} - -// GetRelatedEx -func (c *WmiInstance) GetRelatedEx(associatedClassName, resultClassName, resultRole, sourceRole string) (WmiInstanceCollection, error) { - return c.GetAssociated(associatedClassName, resultClassName, resultRole, sourceRole) -} - -// GetFirstRelatedEx -func (c *WmiInstance) GetFirstRelatedEx(associatedClassName, resultClassName, resultRole, sourceRole string) (*WmiInstance, error) { - col, err := c.GetAssociated(associatedClassName, resultClassName, resultRole, sourceRole) - if err != nil { - return nil, err - } - defer col.Close() - - if len(col) == 0 { - return nil, errors.Wrapf(errors.NotFound, "No Related Items were received for [%s]", resultClassName) - } - - return col[0].Clone() -} - -func (c *WmiInstance) GetAssociatedEx(associatedClassName string) (WmiInstanceCollection, error) { - return c.GetAssociated(associatedClassName, "", "", "") -} - -// GetAssociated -func (c *WmiInstance) GetAssociated(associatedClassName, resultClassName, resultRole, sourceRole string) (WmiInstanceCollection, error) { - // Documentation here: https://docs.microsoft.com/en-us/windows/win32/wmisdk/swbemobject-associators- - rawResult, err := oleutil.CallMethod(c.instance, "Associators_", - associatedClassName, - resultClassName, - resultRole, - sourceRole, - ) - if err != nil { - return nil, err - } - - result := rawResult.ToIDispatch() - defer rawResult.Clear() - - // Doc: https://docs.microsoft.com/en-us/previous-versions/windows/desktop/automat/dispid-constants - enum_property, err := result.GetProperty("_NewEnum") - if err != nil { - return nil, err - } - defer enum_property.Clear() - - // https://docs.microsoft.com/en-us/windows/win32/api/oaidl/nn-oaidl-ienumvariant - enum, err := enum_property.ToIUnknown().IEnumVARIANT(ole.IID_IEnumVariant) - if err != nil { - return nil, err - } - if enum == nil { - return nil, fmt.Errorf("Enum is nil") - } - - defer enum.Release() - - wmiInstances := WmiInstanceCollection{} - for tmp, length, err := enum.Next(1); length > 0; tmp, length, err = enum.Next(1) { - //defer func() { - // if err != nil { - // wmiInstances.Close() - // } - //}() - if err != nil { - return nil, err - } - - wmiInstance, err := CreateWmiInstance(&tmp, c.session) - if err != nil { - // tmp.Clear() - return nil, err - } - - wmiInstances = append(wmiInstances, wmiInstance) - } - - //if len(wmiInstances) == 0 { - // return nil, errors.Wrapf(errors.NotFound, "GetAssociated [%s] [%s]", associatedClassName, resultClassName) - //} - - return wmiInstances, nil -} - -// GetReferences -func (c *WmiInstance) GetReferences(associatedClassName string) (WmiInstanceCollection, error) { - return c.EnumerateReferencingInstances(associatedClassName, "") -} - -// EnumerateReferencingInstances -func (c *WmiInstance) EnumerateReferencingInstances(resultClassName, sourceRole string) (WmiInstanceCollection, error) { - //Documentation: https://docs.microsoft.com/en-us/windows/win32/wmisdk/swbemobject-references- - rawResult, err := oleutil.CallMethod(c.instance, "References_", resultClassName, sourceRole) - if err != nil { - return nil, err - } - - result := rawResult.ToIDispatch() - defer rawResult.Clear() - - // Doc: https://docs.microsoft.com/en-us/previous-versions/windows/desktop/automat/dispid-constants - enum_property, err := result.GetProperty("_NewEnum") - if err != nil { - return nil, err - } - defer enum_property.Clear() - - // https://docs.microsoft.com/en-us/windows/win32/api/oaidl/nn-oaidl-ienumvariant - enum, err := enum_property.ToIUnknown().IEnumVARIANT(ole.IID_IEnumVariant) - if err != nil { - return nil, err - } - if enum == nil { - return nil, fmt.Errorf("Enum is nil") - } - - defer enum.Release() - - wmiInstances := WmiInstanceCollection{} - for tmp, length, err := enum.Next(1); length > 0; tmp, length, err = enum.Next(1) { - //defer func() { - // if err != nil { - // wmiInstances.Close() - // } - //}() - - if err != nil { - return nil, err - } - - wmiInstance, err := CreateWmiInstance(&tmp, c.session) - if err != nil { - //tmp.Clear() - return nil, err - } - - wmiInstances = append(wmiInstances, wmiInstance) - } - - return wmiInstances, nil -} - -// CloseAllInstances -func CloseAllInstances(instances []*WmiInstance) { - for _, instance := range instances { - instance.Close() - } -} - -// Close -func (c *WmiInstance) Close() (err error) { - if c.instanceVar != nil { - // https://docs.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-variantclear - // VariantClear would release the reference if its VT_DISPATCH. - // In our case, WmiInstance holds only VT_DISPATCH - c.instanceVar.Clear() - c.instanceVar = nil - } - - return -} diff --git a/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiJob.go b/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiJob.go deleted file mode 100644 index aab22d4c2d..0000000000 --- a/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiJob.go +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. - -// This class implements the swbemproperty class -// Documentation: https://docs.microsoft.com/en-us/windows/win32/wmisdk/swbemmethod - -package cim - -import ( - "fmt" - "time" - - "github.com/microsoft/wmi/pkg/errors" -) - -// JobState -type JobState int - -const ( - // New enum - JobState_Unknown JobState = 0 - // New enum - JobState_New JobState = 2 - // Starting enum - JobState_Starting JobState = 3 - // Running enum - JobState_Running JobState = 4 - // Suspended enum - JobState_Suspended JobState = 5 - // Shutting_Down enum - JobState_Shutting_Down JobState = 6 - // Completed enum - JobState_Completed JobState = 7 - // Terminated enum - JobState_Terminated JobState = 8 - // Killed enum - JobState_Killed JobState = 9 - // Exception enum - JobState_Exception JobState = 10 - // Service enum - JobState_Service JobState = 11 - // Query_Pending enum - JobState_Query_Pending JobState = 12 - // DMTF_Reserved enum - JobState_DMTF_Reserved JobState = 13 - // Vendor_Reserved enum - JobState_Vendor_Reserved JobState = 14 -) - -type WmiJob struct { - *WmiInstance -} - -func NewWmiJob(instance *WmiInstance) (*WmiJob, error) { - return &WmiJob{instance}, nil -} - -func (job *WmiJob) String() string { - jtype, err := job.JobType() - if err != nil { - return "" - } - return fmt.Sprintf("Type[%s] State[%s]", jtype, job.GetJobState()) -} - -// GetJobType gets the value of JobType for the instance -func (job *WmiJob) JobType() (value int32, err error) { - retValue, err := job.GetProperty("JobType") - if err != nil { - return - } - value, ok := retValue.(int32) - if !ok { - // TODO: Set an error - } - return -} - -// WaitForPercentComplete waits for the percentComplete or timeout -func (job *WmiJob) WaitForPercentComplete(percentComplete uint16, timeoutSeconds int16) error { - start := time.Now() - - // Run the loop, only if the job is actually running - for !job.IsComplete() { - pComplete, err := job.PercentComplete() - if err != nil { - return err - } - // Break if have achieved the target - if pComplete >= percentComplete { - break - } - time.Sleep(100 * time.Millisecond) - - // Infinite Loop - if timeoutSeconds < 0 { - continue - } - - // If we have waited enough time, return with a timeout error - if time.Since(start) > (time.Duration(timeoutSeconds) * time.Second) { - state := job.GetJobState() - exception := job.GetException() - return errors.Wrapf(errors.Timedout, "WaitForPercentComplete timeout. Current state: [%v], Exception: [%v]", state, exception) - } - } - - return job.GetException() -} - -// WaitForAction waits for the task based on the action type, percent complete and timeoutSeconds -func (job *WmiJob) WaitForAction(action UserAction, percentComplete uint16, timeoutSeconds int16) error { - switch action { - case Wait: - return job.WaitForPercentComplete(percentComplete, timeoutSeconds) - case Cancel: - return job.WaitForPercentComplete(percentComplete, timeoutSeconds) - case None: - fallthrough - case Default: - fallthrough - case Async: - break - } - return nil -} - -// PercentComplete -func (job *WmiJob) PercentComplete() (uint16, error) { - err := job.Refresh() - if err != nil { - return 0, err - } - retValue, err := job.GetProperty("PercentComplete") - if err != nil { - return 0, err - } - return uint16(retValue.(int32)), nil -} - -func (job *WmiJob) GetJobState() (js JobState) { - state, err := job.GetProperty("JobState") - if err != nil || state == nil { - return JobState_Unknown - } - if val, ok := state.(int32); ok { - js = JobState(val) - } else { - js = JobState_Unknown - } - return -} - -func (job *WmiJob) IsComplete() bool { - err := job.Refresh() - if err != nil { - - } - state := job.GetJobState() - switch state { - case JobState_New: - fallthrough - case JobState_Starting: - fallthrough - case JobState_Running: - fallthrough - case JobState_Suspended: - fallthrough - case JobState_Shutting_Down: - return false - case JobState_Completed: - fallthrough - case JobState_Terminated: - fallthrough - case JobState_Killed: - fallthrough - case JobState_Unknown: - fallthrough - case JobState_Exception: - return true - } - return false -} - -func (job *WmiJob) GetException() error { - job.Refresh() - state := job.GetJobState() - switch state { - case JobState_Terminated: - fallthrough - case JobState_Killed: - fallthrough - case JobState_Exception: - errorCodeVal, _ := job.GetProperty("ErrorCode") - errorCode := uint16(errorCodeVal.(int32)) - errorDescriptionVal, _ := job.GetProperty("ErrorDescription") - errorDescription, _ := errorDescriptionVal.(string) - errorSummaryDescriptionVal, _ := job.GetProperty("ErrorSummaryDescription") - errorSummaryDescription, _ := errorSummaryDescriptionVal.(string) - return errors.Wrapf(errors.NewWMIError(errorCode), - "ErrorCode[%d] ErrorDescription[%s] ErrorSummaryDescription [%s]", - errorCode, errorDescription, errorSummaryDescription) - case JobState_Unknown: - return errors.Wrapf(errors.Unknown, "Job is in Unknown state") - } - return nil -} - -func (job *WmiJob) WaitForJobCompletion(result int32, timeoutSeconds int16) error { - if result == 0 { - return nil - } else if result == 4096 { - return job.WaitForAction(Wait, 100, timeoutSeconds) - } else { - return errors.Wrapf(errors.Failed, "Unable to Wait for Job on Result[%d] ", result) - } - -} - -type WmiJobCollection []*WmiJob - -func (c *WmiJobCollection) Close() error { - var err error - for _, p := range *c { - err = p.Close() - } - return err -} diff --git a/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiMethod.go b/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiMethod.go deleted file mode 100644 index bae88ee8e0..0000000000 --- a/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiMethod.go +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. - -// This class implements the swbemproperty class -// Documentation: https://docs.microsoft.com/en-us/windows/win32/wmisdk/swbemmethod - -package cim - -import ( - "log" - - "github.com/go-ole/go-ole" - "github.com/go-ole/go-ole/oleutil" - "github.com/microsoft/wmi/pkg/errors" -) - -type WmiMethod struct { - Name string - // Reference - session *WmiSession - // Reference - classInstance *WmiInstance -} - -type WmiMethodResult struct { - ReturnValue int32 - OutMethodParams map[string]*WmiMethodParam -} - -// NewWmiMethod -func NewWmiMethod(methodName string, instance *WmiInstance) (*WmiMethod, error) { - return &WmiMethod{ - Name: methodName, - classInstance: instance, - session: instance.GetSession(), - }, nil -} - -func (c *WmiMethod) addInParam(inparamVariant *ole.VARIANT, paramName string, paramValue interface{}) error { - rawProperties, err := inparamVariant.ToIDispatch().GetProperty("Properties_") - if err != nil { - return err - } - defer rawProperties.Clear() - rawProperty, err := rawProperties.ToIDispatch().CallMethod("Item", paramName) - if err != nil { - return err - } - defer rawProperty.Clear() - - p, err := rawProperty.ToIDispatch().PutProperty("Value", paramValue) - if err != nil { - return err - } - defer p.Clear() - return nil -} - -func (c *WmiMethod) Execute(inParam, outParam WmiMethodParamCollection) (result *WmiMethodResult, err error) { - log.Printf("[WMI] - Executing Method [%s]\n", c.Name) - - iDispatchInstance := c.classInstance.GetIDispatch() - if iDispatchInstance == nil { - return nil, errors.Wrapf(errors.InvalidInput, "InvalidInstance") - } - rawResult, err := iDispatchInstance.GetProperty("Methods_") - if err != nil { - return nil, err - } - defer rawResult.Clear() - // Retrive the method - rawMethod, err := rawResult.ToIDispatch().CallMethod("Item", c.Name) - if err != nil { - return nil, err - } - defer rawMethod.Clear() - - params := []interface{}{c.Name} - - if len(inParam) > 0 { - inparamsRaw, err := rawMethod.ToIDispatch().GetProperty("InParameters") - if err != nil { - return nil, err - } - defer inparamsRaw.Clear() - - // Method with no parameters may return a VARIANT with nil IDispatch - if inparamsRaw.Val != 0 { - inparams, err := oleutil.CallMethod(inparamsRaw.ToIDispatch(), "SpawnInstance_") - if err != nil { - return nil, err - } - defer inparams.Clear() - - for _, inp := range inParam { - // log.Printf("InParam [%s]=>[%+v]\n", inp.Name, inp.Value) - c.addInParam(inparams, inp.Name, inp.Value) - } - - params = append(params, inparams) - } - } - - result = &WmiMethodResult{ - OutMethodParams: map[string]*WmiMethodParam{}, - } - outparams, err := c.classInstance.GetIDispatch().CallMethod("ExecMethod_", params...) - if err != nil { - return - } - defer outparams.Clear() - returnRaw, err := outparams.ToIDispatch().GetProperty("ReturnValue") - if err != nil { - return - } - defer returnRaw.Clear() - result.ReturnValue = returnRaw.Value().(int32) - log.Printf("[WMI] - Return [%d] ", result.ReturnValue) - - for _, outp := range outParam { - returnRawIn, err1 := outparams.ToIDispatch().GetProperty(outp.Name) - if err1 != nil { - err = err1 - return - } - defer returnRawIn.Clear() - - value, err1 := GetVariantValue(returnRawIn) - if err1 != nil { - err = err1 - return - } - // log.Printf("OutParam [%s]=> [%+v]\n", outp.Name, value) - - result.OutMethodParams[outp.Name] = NewWmiMethodParam(outp.Name, value) - } - return -} - -func (c *WmiMethod) Close() error { - return nil -} - -type WmiMethodCollection []*WmiMethod - -func (c *WmiMethodCollection) Close() error { - var err error - for _, p := range *c { - err = p.Close() - } - return err -} diff --git a/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiMethodParam.go b/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiMethodParam.go deleted file mode 100644 index b6a5b91f71..0000000000 --- a/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiMethodParam.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. - -// This class implements the swbemproperty class -// Documentation: https://docs.microsoft.com/en-us/windows/win32/wmisdk/swbemproperty - -package cim - -import ( -// "github.com/go-ole/go-ole" -) - -type WmiMethodParam struct { - Name string - Value interface{} - //session *WmiSession - //property *ole.IDispatch - //propertyVar *ole.VARIANT -} - -// func NewWmiMethodParam(name string, val interface{}, propertyVariant *ole.VARIANT, session *WmiSession) (*WmiMethodParam, error) { -func NewWmiMethodParam(name string, val interface{}) *WmiMethodParam { - return &WmiMethodParam{ - Name: name, - //propertyVar: propertyVariant, - //property: propertyVariant.ToIDispatch(), - //session: session, - Value: val, - } -} - -// Dispose -func (c *WmiMethodParam) Close() error { - return nil //c.propertyVar.Clear() -} - -type WmiMethodParamCollection []*WmiMethodParam - -func (c *WmiMethodParamCollection) Close() error { - var err error - for _, p := range *c { - err = p.Close() - } - return err -} diff --git a/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiProperty.go b/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiProperty.go deleted file mode 100644 index 09dff7907c..0000000000 --- a/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiProperty.go +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. - -// This class implements the swbemproperty class -// Documentation: https://docs.microsoft.com/en-us/windows/win32/wmisdk/swbemproperty - -package cim - -import ( - "github.com/go-ole/go-ole" - "github.com/go-ole/go-ole/oleutil" - - "github.com/microsoft/wmi/go/wmi" -) - -type WmiProperty struct { - session *WmiSession - property *ole.IDispatch - propertyVar *ole.VARIANT -} - -func CreateWmiProperty(propertyVariant *ole.VARIANT, session *WmiSession) (*WmiProperty, error) { - return &WmiProperty{ - propertyVar: propertyVariant, - property: propertyVariant.ToIDispatch(), - session: session, - }, nil -} - -// Name -func (c *WmiProperty) Name() string { - name, err := oleutil.GetProperty(c.property, "Name") - if err != nil { - panic("Error retrieving the property Name") - } - - value, err := GetVariantValue(name) - if err != nil { - panic("Error retrieving the property Name") - } - - return value.(string) -} - -// Value -func (c *WmiProperty) Value() interface{} { - rawSystemProperty, err := oleutil.GetProperty(c.property, "Value") - if err != nil { - panic("Error retrieving the property value") - } - - value, err := GetVariantValue(rawSystemProperty) - if err != nil { - panic("Error retrieving the property value") - } - - return value -} - -// Type -func (c *WmiProperty) Type() wmi.WmiType { - rawSystemProperty, err := oleutil.GetProperty(c.property, "CIMType") - if err != nil { - panic("Error retrieving the property type") - } - - value, err := GetVariantValue(rawSystemProperty) - if err != nil { - panic("Error retrieving the property type") - } - - return wmi.WmiType(value.(int)) -} - -func CloseAllProperties(properties []*WmiProperty) { - for _, property := range properties { - property.Close() - } -} - -// Dispose -func (c *WmiProperty) Close() error { - return c.propertyVar.Clear() -} diff --git a/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiQualifier.go b/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiQualifier.go deleted file mode 100644 index 242bfee1b1..0000000000 --- a/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiQualifier.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. - -package cim - -type WmiQualifier struct { -} - -// Name -func (c WmiQualifier) Name() string { - panic("not implemented") - -} - -// Value -func (c WmiQualifier) Value() string { - panic("not implemented") - -} diff --git a/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiSession.go b/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiSession.go deleted file mode 100644 index 35498e01b7..0000000000 --- a/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiSession.go +++ /dev/null @@ -1,307 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. - -// This class implements the SWbemServices object -// Documentation: https://docs.microsoft.com/en-us/windows/win32/wmisdk/swbemservices - -package cim - -import ( - "fmt" - "log" - "runtime/debug" - "strings" - - ole "github.com/go-ole/go-ole" - "github.com/go-ole/go-ole/oleutil" - "github.com/microsoft/wmi/go/wmi" - "github.com/microsoft/wmi/pkg/base/host" -) - -// WmiSession struct to hold the current session information -type WmiSession struct { - ServerName string - Namespace string - Username string - Password string - Domain string - WMIHost *host.WmiHost - Status wmi.SessionStatus - RawSession *ole.VARIANT - Session *ole.IDispatch - CimwmiService *ole.IDispatch -} - -// CreateSessionEx creates a session based on credentials -func CreateSessionEx(CimwmiService *ole.IDispatch, serverName, wmiNamespace string, credentials wmi.Credentials) (*WmiSession, error) { - return CreateSession(CimwmiService, wmiNamespace, serverName, credentials.Domain, credentials.UserName, credentials.Password) -} - -// CreateSession creates a new session with the server and namespace -func CreateSession(CimwmiService *ole.IDispatch, wmiNamespace, serverName, domain, userName, password string) (*WmiSession, error) { - return &WmiSession{ - CimwmiService: CimwmiService, - ServerName: serverName, - Namespace: wmiNamespace, - Username: userName, - Password: password, - Domain: domain, - Status: wmi.Created, - WMIHost: host.NewWmiHostWithCredential(serverName, userName, password, domain), - }, nil -} - -type WbemAuthenticationLevelEnum uint32 - -const ( - wbemAuthenticationLevelDefault WbemAuthenticationLevelEnum = 0 - wbemAuthenticationLevelNone WbemAuthenticationLevelEnum = 1 - wbemAuthenticationLevelConnect WbemAuthenticationLevelEnum = 2 - wbemAuthenticationLevelCall WbemAuthenticationLevelEnum = 3 - wbemAuthenticationLevelPkt WbemAuthenticationLevelEnum = 4 - wbemAuthenticationLevelPktIntegrity WbemAuthenticationLevelEnum = 5 - wbemAuthenticationLevelPktPrivacy WbemAuthenticationLevelEnum = 6 -) - -type WbemImpersonationLevel uint32 - -const ( - wbemImpersonationLevelAnonymous WbemImpersonationLevel = 1 - wbemImpersonationLevelIdentify WbemImpersonationLevel = 2 - wbemImpersonationLevelImpersonate WbemImpersonationLevel = 3 - wbemImpersonationLevelDelegate WbemImpersonationLevel = 4 -) - -// Connect the wmi session -func (c *WmiSession) Connect() (bool, error) { - var err error - // Node that we are connected through SWbemLocator, which uses the scripting language syntax for ConnectServer - // This means the first parameter of the call is the name of the server, and the second parameter is the name of the namespace - // (as opposed to C++ where these two are exposed as one parameter) - // See here for an example illustrating the scripting syntax: https://docs.microsoft.com/en-us/windows/win32/wmisdk/connecting-to-wmi-with-vbscript - c.RawSession, err = oleutil.CallMethod( - c.CimwmiService, "ConnectServer", strings.Join([]string{c.ServerName, c.Domain}, "."), c.Namespace, c.Username, c.Password, "MS_409") - if err != nil { - return false, err - } - c.Session = c.RawSession.ToIDispatch() - c.Status = wmi.Connected - - if c.Session == nil { - panic("Returned session is null") - } - - // Set the authentication level to packet privacy and impersonation to impersonate - // Relevant documentations: - // https://docs.microsoft.com/en-us/windows/win32/wmisdk/setting-security-on-an-asynchronous-call - // https://docs.microsoft.com/en-us/windows/win32/wmisdk/setting-the-default-process-security-level-using-vbscript - // https://docs.microsoft.com/en-us/windows/win32/wmisdk/swbemsecurity - // https://docs.microsoft.com/en-us/windows/win32/wmisdk/maintaining-wmi-security - // https://docs.microsoft.com/en-us/windows/win32/wmisdk/securing-scripting-clients - // https://docs.microsoft.com/en-us/windows/win32/wmisdk/providing-events-securely - rawSecurityObject, err := oleutil.GetProperty(c.Session, "Security_") - if err != nil { - debug.PrintStack() - return false, err - } - securityObject := rawSecurityObject.ToIDispatch() - defer rawSecurityObject.Clear() - - rawImpersonationLevel, err := oleutil.PutProperty(securityObject, "ImpersonationLevel", uint32(wbemImpersonationLevelImpersonate)) - if err != nil { - debug.PrintStack() - return false, err - } - defer rawImpersonationLevel.Clear() - - rawAuthenticationLevel, err := oleutil.PutProperty(securityObject, "AuthenticationLevel", uint32(wbemAuthenticationLevelPktPrivacy)) - if err != nil { - debug.PrintStack() - return false, err - } - defer rawAuthenticationLevel.Clear() - - return true, nil -} - -// Close the wmi session -func (c *WmiSession) Close() { - c.RawSession.Clear() - c.Status = wmi.Disconnected -} - -// Dispose the wmi session -func (c *WmiSession) Dispose() { - if c.Status != wmi.Disposed { - c.Close() - c.Status = wmi.Disposed - } -} - -// TestConnection -func (c *WmiSession) TestConnection() bool { - panic("not implemented") -} - -// Tells WMI to create a new class for us -func (c *WmiSession) CreateNewClass() (*WmiClass, error) { - rawResult, err := c.Session.CallMethod("Get") - if err != nil { - return nil, err - } - - return CreateWmiClass(rawResult, c) -} - -func (c *WmiSession) GetClass(classDefinition string) (*WmiClass, error) { - rawResult, err := c.Session.CallMethod("Get", classDefinition) - if err != nil { - return nil, err - } - - return CreateWmiClass(rawResult, c) -} - -// EnumerateClasses -func (c *WmiSession) EnumerateClasses(className string) ([]*WmiClass, error) { - return c.QueryClasses("SELECT * FROM meta_class") -} - -// QueryClasses -func (c *WmiSession) QueryClasses(queryString string) ([]*WmiClass, error) { - enum, err := c.PerformRawQuery(queryString) - if err != nil { - return nil, err - } - defer enum.Release() - - wmiClasses := []*WmiClass{} - for tmp, length, err := enum.Next(1); length > 0; tmp, length, err = enum.Next(1) { - if err != nil { - return nil, err - } - - wmiClass, err := CreateWmiClass(&tmp, c) - if err != nil { - return nil, err - } - - wmiClasses = append(wmiClasses, wmiClass) - } - - return wmiClasses, nil -} - -// GetInstance -func (c *WmiSession) GetInstance(path string) (*WmiInstance, error) { - rawResult, err := c.Session.CallMethod("Get", path) - if err != nil { - return nil, err - } - - return CreateWmiInstance(rawResult, c) -} - -// EnumerateInstances -func (c *WmiSession) EnumerateInstances(className string) ([]*WmiInstance, error) { - return c.QueryInstances("SELECT * FROM " + className) -} - -// QueryInstances -func (c *WmiSession) QueryInstances(queryExpression string) ([]*WmiInstance, error) { - enum, err := c.PerformRawQuery(queryExpression) - if err != nil { - return nil, err - } - defer enum.Release() - - wmiInstances := []*WmiInstance{} - for tmp, length, err := enum.Next(1); length > 0; tmp, length, err = enum.Next(1) { - if err != nil { - return nil, err - } - - wmiInstance, err := CreateWmiInstance(&tmp, c) - if err != nil { - return nil, err - } - - wmiInstances = append(wmiInstances, wmiInstance) - } - - log.Printf("[WMI] QueryInstances [%s]=> [%d]\n", queryExpression, len(wmiInstances)) - return wmiInstances, nil -} - -// QueryInstancesEx -func (c *WmiSession) QueryInstancesEx(query wmi.Query) (*[]wmi.Instance, error) { - panic("not implemented") -} - -// EnumerateReferencingInstances -func (c *WmiSession) EnumerateReferencingInstances(namespaceName string, sourceInstance WmiInstance, associationClassName, sourceRole string) (*[]WmiInstance, error) { - panic("not implemented") -} - -func (c *WmiSession) PerformRawQuery(queryExpression string) (*ole.IEnumVARIANT, error) { - rawResult, err := c.Session.CallMethod("ExecQuery", queryExpression) - if err != nil { - return nil, err - } - - result := rawResult.ToIDispatch() - defer rawResult.Clear() - - // Doc: https://docs.microsoft.com/en-us/previous-versions/windows/desktop/automat/dispid-constants - enum_property, err := result.GetProperty("_NewEnum") - if err != nil { - return nil, err - } - defer enum_property.Clear() - - // https://docs.microsoft.com/en-us/windows/win32/api/oaidl/nn-oaidl-ienumvariant - enum, err := enum_property.ToIUnknown().IEnumVARIANT(ole.IID_IEnumVariant) - if err != nil { - return nil, err - } - if enum == nil { - return nil, fmt.Errorf("Enum is nil") - } - - return enum, err -} - -// Credentials -func (c *WmiSession) Credentials() *wmi.Credentials { - credentials := wmi.Credentials{ - UserName: c.Username, - Password: c.Password, - Domain: c.Domain, - } - - return &credentials -} - -// Asynchronous approach to handling events -// Documentation: https://docs.microsoft.com/en-us/windows/win32/wmisdk/receiving-synchronous-and-semisynchronous-event-notifications -// Security considerations with Asynchronous calls: https://docs.microsoft.com/en-us/windows/win32/wmisdk/making-an-asynchronous-call-with-vbscript -func (c *WmiSession) ExecNotificationQueryAsync(eventSink *WmiEventSink, query string) (interface{}, error) { - rawResult, err := oleutil.CallMethod(c.Session, "ExecNotificationQueryAsync", eventSink.instance, query) - if err != nil { - return nil, err - } - defer rawResult.Clear() - - return GetVariantValue(rawResult) -} - -// Synchronous approach to handling events -// Documentation: https://docs.microsoft.com/en-us/windows/win32/wmisdk/receiving-synchronous-and-semisynchronous-event-notifications -func (c *WmiSession) ExecNotificationQuery(query string) (*WmiSynchronousEventsList, error) { - rawResult, err := oleutil.CallMethod(c.Session, "ExecNotificationQuery", query) - if err != nil { - return nil, err - } - - return CreateWmiSynchronousEventsList(rawResult, c), nil -} diff --git a/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiSessionManager.go b/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiSessionManager.go deleted file mode 100644 index 927f745494..0000000000 --- a/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiSessionManager.go +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. - -package cim - -import ( - "errors" - "fmt" - - ole "github.com/go-ole/go-ole" - "github.com/go-ole/go-ole/oleutil" -) - -const S_FALSE = 0x00000001 - -var IID_ISWbemLocator = &ole.GUID{0x76a6415b, 0xcb41, 0x11d1, [8]byte{0x8b, 0x02, 0x00, 0x60, 0x08, 0x06, 0xd9, 0xb6}} - -// Reference https://github.com/StackExchange/wmi -// Reference https://docs.microsoft.com/en-us/windows/desktop/WmiSdk/swbemlocator-connectserver - -type WmiSessionManager struct { - unknown *ole.IUnknown - wmi *ole.IDispatch - sessions map[string]*WmiSession -} - -func NewWmiSessionManager() *WmiSessionManager { - wsm := &WmiSessionManager{} - - err := wsm.init() - if err != nil { - panic("couldn't initialize the WmiSessionManager") - } - - return wsm -} - -func (c *WmiSessionManager) init() error { - err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED) - if err != nil { - oleCode := err.(*ole.OleError).Code() - if oleCode != ole.S_OK && oleCode != S_FALSE { - return err - } - } - - // Initialize COM security for the whole process - err = CoInitializeSecurity(RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE) - if err != nil { - oleCode := err.(*ole.OleError).Code() - - // Note: RPC_E_TOO_LATE means we have already initialized security. - if oleCode != ole.S_OK && oleCode != S_FALSE && oleCode != uintptr(RPC_E_TOO_LATE) { - panic(fmt.Sprintf("Couldn't initialize COM/DCOM security. Error: [%v]", err)) - } - } - - c.unknown, err = oleutil.CreateObject("WbemScripting.SWbemLocator") - if err != nil { - c.Dispose() - return err - } - if c.unknown == nil { - c.Dispose() - return errors.New("CreateObject failed") - } - - c.wmi, err = c.unknown.QueryInterface(IID_ISWbemLocator) - if err != nil { - c.Dispose() - return err - } - - return nil -} - -// Dispose clears the WmiSessionManager -func (c *WmiSessionManager) Dispose() { - c.Close() -} - -// Close -func (c *WmiSessionManager) Close() error { - // clear the Sessions - - if c.wmi != nil { - c.wmi.Release() - } - // clear ole object - if c.unknown != nil { - c.unknown.Release() - } - - // clear com - ole.CoUninitialize() - - return nil -} - -// GetSession -func (c *WmiSessionManager) GetSession(wmiNamespace, serverName, domain, userName, password string) (*WmiSession, error) { - return CreateSession(c.wmi, wmiNamespace, serverName, domain, userName, password) -} - -// GetLocalSession -func (c *WmiSessionManager) GetLocalSession(wmiNamespace string) (*WmiSession, error) { - return CreateSession(c.wmi, wmiNamespace, "", "", "", "") -} diff --git a/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiSynchronousEvents.go b/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiSynchronousEvents.go deleted file mode 100644 index 4017f2aa1c..0000000000 --- a/vendor/github.com/microsoft/wmi/pkg/wmiinstance/WmiSynchronousEvents.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. - -// This class wraps a typicaly SWbemEventSource object as returned by SWbemServices.ExecNotificationQuery. Its implementation is based on the -// Documentations: -// https://docs.microsoft.com/en-us/windows/win32/wmisdk/receiving-synchronous-and-semisynchronous-event-notifications -// https://docs.microsoft.com/en-us/windows/win32/wmisdk/swbemservices-execnotificationquery -// https://docs.microsoft.com/en-us/windows/win32/wmisdk/swbemeventsource - -package cim - -import ( - ole "github.com/go-ole/go-ole" - "github.com/go-ole/go-ole/oleutil" -) - -const ( - wbemTimeoutInfinite int32 = -1 -) - -type WmiSynchronousEventsList struct { - session *WmiSession - instance *ole.IDispatch - instanceVar *ole.VARIANT -} - -func CreateWmiSynchronousEventsList(instanceVar *ole.VARIANT, session *WmiSession) *WmiSynchronousEventsList { - return &WmiSynchronousEventsList{ - session: session, - instance: instanceVar.ToIDispatch(), - instanceVar: instanceVar, - } -} - -func (c *WmiSynchronousEventsList) Close() { - c.instanceVar.Clear() -} - -func (c *WmiSynchronousEventsList) WaitForNextEventUntil(timeout int32) (*WmiInstance, error) { - eventInstance, err := oleutil.CallMethod(c.instance, "NextEvent", timeout) - if err != nil { - return nil, err - } - - return CreateWmiInstance(eventInstance, c.session) -} - -func (c *WmiSynchronousEventsList) WaitForNextEvent() (*WmiInstance, error) { - return c.WaitForNextEventUntil(wbemTimeoutInfinite) -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 89768ba73d..79bdc0eafa 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -317,14 +317,6 @@ github.com/kylelemons/godebug/pretty github.com/mailru/easyjson/buffer github.com/mailru/easyjson/jlexer github.com/mailru/easyjson/jwriter -# github.com/microsoft/wmi v0.38.3 -## explicit; go 1.24.3 -github.com/microsoft/wmi/go/wmi -github.com/microsoft/wmi/pkg/base/credential -github.com/microsoft/wmi/pkg/base/host -github.com/microsoft/wmi/pkg/base/query -github.com/microsoft/wmi/pkg/errors -github.com/microsoft/wmi/pkg/wmiinstance # github.com/moby/spdystream v0.5.0 ## explicit; go 1.13 github.com/moby/spdystream