Skip to content

Commit

Permalink
Merge pull request #1 from JocelynBerrendonner/master
Browse files Browse the repository at this point in the history
Implementation of most of the WMI classes
  • Loading branch information
JocelynBerrendonner authored Feb 3, 2020
2 parents 01c5cbc + 7fe2146 commit cc8edeb
Show file tree
Hide file tree
Showing 89 changed files with 5,757 additions and 203 deletions.
27 changes: 27 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.
GOCMD=go
GOBUILD=$(GOCMD) build -v -mod=vendor
GOHOSTOS=$(strip $(shell $(GOCMD) env get GOHOSTOS))

TAG ?= $(shell git describe --tags)
COMMIT ?= $(shell git describe --always)
BUILD_DATE ?= $(shell date -u +%m/%d/%Y)

PKG :=

all: format library

.PHONY: vendor
vendor:
GO111MODULE=on go mod vendor -v
GO111MODULE=on go mod tidy

library:
GO111MODULE=on GOARCH=amd64 GOOS=windows $(GOBUILD) ./...

format:
gofmt -s -w go/cim/ go/wmi/

test:
GOOS=windows GO111MODULE=on GOARCH=amd64 go test -v ./go/...
9 changes: 9 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module github.com/microsoft/wmicodegen/go

go 1.13

require (
github.com/go-ole/go-ole v1.2.4
github.com/microsoft/wmicodegen v0.0.0-20190615015912-01c5cbc6013d
github.com/sirupsen/logrus v1.4.2
)
13 changes: 13 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/microsoft/wmicodegen v0.0.0-20190615015912-01c5cbc6013d h1:Kh4YxizgV2l1bfLvIZ5gENK++pxOQanld8uTemygAqQ=
github.com/microsoft/wmicodegen v0.0.0-20190615015912-01c5cbc6013d/go.mod h1:x55WMZd9Q64BopTkNWRgG3WoCAQZg4pnvUA9T049gDg=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
273 changes: 251 additions & 22 deletions go/cim/WmiClass.go
Original file line number Diff line number Diff line change
@@ -1,69 +1,298 @@
// 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/microsoft/wmicodegen/go/wmi"
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)

type WmiClass struct {
session *WmiSession
class *ole.IDispatch
classVar *ole.VARIANT
}

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) ClassName() string {
panic("not implemented")
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) SuperClassName() string {
func (c *WmiClass) GetSuperClassName() string {
superclass := c.mustGetSystemProperty("__SUPERCLASS")
defer superclass.Close()

panic("not implemented")
return superclass.Value().(string)
}

// ServerName
func (c WmiClass) ServerName() string {
panic("not implemented")
func (c *WmiClass) GetServerName() string {
server := c.mustGetSystemProperty("__SERVER")
defer server.Close()

return server.Value().(string)
}

// Namespace
func (c WmiClass) Namespace() string {
panic("not implemented")
func (c *WmiClass) GetNamespace() string {
namespace := c.mustGetSystemProperty("__NAMESPACE")
defer namespace.Close()

return namespace.Value().(string)
}

// SuperClass
func (c WmiClass) SuperClass() *wmi.Class {
panic("not implemented")
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) Properties() []string {
panic("not implemented")
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) Qualifiers() []string {
panic("not implemented")
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) Methods() []string {
panic("not implemented")
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 {
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
}
func (c WmiClass) InvokeMethod(methodName string, methodParams []string, inputOptions string) (error, string) {
func (c *WmiClass) InvokeMethod(methodName string, methodParams []string, inputOptions string) (error, string) {
panic("not implemented")
// TODO. Should theoretically be the same as WmiInstance InvokeMethod?
// both are SWbemObjects: https://docs.microsoft.com/en-us/windows/win32/wmisdk/swbemobject
}

// CloseAllClasses
func CloseAllClasses(classes []*WmiClass) {
for _, class := range classes {
class.Close()
}
}

func (c WmiClass) Dispose() {
panic("not implemented")
// Dispose
func (c *WmiClass) Close() error {
return c.classVar.Clear()
}
Loading

0 comments on commit cc8edeb

Please sign in to comment.