From eb6b4d427bd2938bb0ef80cb9c5c614327e382d0 Mon Sep 17 00:00:00 2001 From: Greg Bray Date: Tue, 26 Jul 2016 14:53:07 -0600 Subject: [PATCH 1/2] vendor: update github.com/stackexchange/wmi package with 2 PRs --- vendor/github.com/StackExchange/wmi/wmi.go | 51 ++++++++++++++-------- vendor/vendor.json | 5 +++ 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/vendor/github.com/StackExchange/wmi/wmi.go b/vendor/github.com/StackExchange/wmi/wmi.go index b931ca57af..c7f4fad00c 100644 --- a/vendor/github.com/StackExchange/wmi/wmi.go +++ b/vendor/github.com/StackExchange/wmi/wmi.go @@ -34,7 +34,6 @@ import ( "runtime" "strconv" "strings" - "sync" "time" "github.com/go-ole/go-ole" @@ -45,9 +44,14 @@ var l = log.New(os.Stdout, "", log.LstdFlags) var ( ErrInvalidEntityType = errors.New("wmi: invalid entity type") - lock sync.Mutex + // ErrNilCreateObject is the error returned if CreateObject returns nil even + // if the error was nil. + ErrNilCreateObject = errors.New("wmi: create object returned nil") ) +// S_FALSE is returned by CoInitializeEx if it was already called on this thread. +const S_FALSE = 0x00000001 + // QueryNamespace invokes Query with the given namespace on the local machine. func QueryNamespace(query string, dst interface{}, namespace string) error { return Query(query, dst, nil, namespace) @@ -119,28 +123,23 @@ func (c *Client) Query(query string, dst interface{}, connectServerArgs ...inter return ErrInvalidEntityType } - lock.Lock() - defer lock.Unlock() runtime.LockOSThread() defer runtime.UnlockOSThread() - err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED) + err := ole.CoInitializeEx(0, ole.COINIT_APARTMENTTHREADED) if err != nil { - oleerr := err.(*ole.OleError) - // S_FALSE = 0x00000001 // CoInitializeEx was already called on this thread - if oleerr.Code() != ole.S_OK && oleerr.Code() != 0x00000001 { + oleCode := err.(*ole.OleError).Code() + if oleCode != ole.S_OK && oleCode != S_FALSE { return err } - } else { - // Only invoke CoUninitialize if the thread was not initizlied before. - // This will allow other go packages based on go-ole play along - // with this library. - defer ole.CoUninitialize() } + defer ole.CoUninitialize() unknown, err := oleutil.CreateObject("WbemScripting.SWbemLocator") if err != nil { return err + } else if unknown == nil { + return ErrNilCreateObject } defer unknown.Release() @@ -171,19 +170,33 @@ func (c *Client) Query(query string, dst interface{}, connectServerArgs ...inter return err } + enumProperty, err := result.GetProperty("_NewEnum") + if err != nil { + return err + } + defer enumProperty.Clear() + + enum, err := enumProperty.ToIUnknown().IEnumVARIANT(ole.IID_IEnumVariant) + if err != nil { + return err + } + if enum == nil { + return fmt.Errorf("can't get IEnumVARIANT, enum is nil") + } + // Initialize a slice with Count capacity dv.Set(reflect.MakeSlice(dv.Type(), 0, int(count))) var errFieldMismatch error - for i := int64(0); i < count; i++ { + for itemRaw, length, err := enum.Next(1); length > 0; itemRaw, length, err = enum.Next(1) { + if err != nil { + return err + } + err := func() error { // item is a SWbemObject, but really a Win32_Process - itemRaw, err := oleutil.CallMethod(result, "ItemIndex", i) - if err != nil { - return err - } item := itemRaw.ToIDispatch() - defer itemRaw.Clear() + defer item.Release() ev := reflect.New(elemType) if err = c.loadEntity(ev.Interface(), item); err != nil { diff --git a/vendor/vendor.json b/vendor/vendor.json index 07f673d51f..a0a56da453 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -624,6 +624,11 @@ "revision": "fc89ed2e418d27e3ea76e708e54276d2b44ae9cf", "revisionTime": "2015-03-07T10:11:20+08:00" }, + { + "path": "github.com/stackexchange/wmi", + "revision": "04850ec8cb7d7abe649e84596e564910521c22b4", + "revisionTime": "2016-05-26T11:44:21Z" + }, { "path": "github.com/syndtr/goleveldb/leveldb", "revision": "1a9d62f03ea92815b46fcaab357cfd4df264b1a0", From 856c544983cea143130b77797aca9dc6b12e0f11 Mon Sep 17 00:00:00 2001 From: Greg Bray Date: Tue, 26 Jul 2016 19:09:03 -0600 Subject: [PATCH 2/2] vendor: change wmi back to COINIT_MULTITHREADED see https://github.com/StackExchange/wmi/pull/16 --- vendor/github.com/StackExchange/wmi/wmi.go | 6 +++++- vendor/vendor.json | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/vendor/github.com/StackExchange/wmi/wmi.go b/vendor/github.com/StackExchange/wmi/wmi.go index c7f4fad00c..fc62377a96 100644 --- a/vendor/github.com/StackExchange/wmi/wmi.go +++ b/vendor/github.com/StackExchange/wmi/wmi.go @@ -34,6 +34,7 @@ import ( "runtime" "strconv" "strings" + "sync" "time" "github.com/go-ole/go-ole" @@ -47,6 +48,7 @@ var ( // ErrNilCreateObject is the error returned if CreateObject returns nil even // if the error was nil. ErrNilCreateObject = errors.New("wmi: create object returned nil") + lock sync.Mutex ) // S_FALSE is returned by CoInitializeEx if it was already called on this thread. @@ -123,10 +125,12 @@ func (c *Client) Query(query string, dst interface{}, connectServerArgs ...inter return ErrInvalidEntityType } + lock.Lock() + defer lock.Unlock() runtime.LockOSThread() defer runtime.UnlockOSThread() - err := ole.CoInitializeEx(0, ole.COINIT_APARTMENTTHREADED) + err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED) if err != nil { oleCode := err.(*ole.OleError).Code() if oleCode != ole.S_OK && oleCode != S_FALSE { diff --git a/vendor/vendor.json b/vendor/vendor.json index a0a56da453..474b5f077e 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -626,8 +626,8 @@ }, { "path": "github.com/stackexchange/wmi", - "revision": "04850ec8cb7d7abe649e84596e564910521c22b4", - "revisionTime": "2016-05-26T11:44:21Z" + "revision": "d4ae5b448be53329ab38edcbc8aa1d196fc87f21", + "revisionTime": "2016-07-26T18:57:16-06:00" }, { "path": "github.com/syndtr/goleveldb/leveldb",