Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added GetMethod, Put, SpawnInstance, and ExecMethod functions #1534

Merged
merged 1 commit into from
Aug 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Next Release (5.14.0)

Features
--------
* [#1534](https://github.com/java-native-access/jna/pull/1534): Add `GetMethod`, `Put`, `SpawnInstance` to `c.s.j.p.win32.COM.WbemCli#IWbemClassObject` and `ExecMethod` to `c.s.j.p.win32.COM.WbemCli#IWbemServices` - [@faddom](https://github.com/faddom).

Bug Fixes
---------
Expand Down
78 changes: 78 additions & 0 deletions contrib/platform/src/com/sun/jna/platform/win32/COM/Wbemcli.java
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,23 @@ public HRESULT Get(String wszName, int lFlags, VARIANT.ByReference pVal, IntByRe
return Get(wszName == null ? null : new WString(wszName), lFlags, pVal, pType, plFlavor);
}

public HRESULT GetMethod(String wszName, int lFlags, PointerByReference ppInSignature, PointerByReference ppOutSignature) {
return GetMethod(wszName == null ? null : new WString(wszName), lFlags, ppInSignature, ppOutSignature);
}

public HRESULT GetMethod(WString wszName, int lFlags, PointerByReference ppInSignature, PointerByReference ppOutSignature) {
// 20th method in IWbemClassObjectVtbl
return (HRESULT) _invokeNativeObject(19,
new Object[]{ getPointer(), wszName, lFlags, ppInSignature, ppOutSignature}, HRESULT.class);
}

public IWbemClassObject GetMethod(String wszName) {
PointerByReference ppInSignature = new PointerByReference();
HRESULT res = GetMethod(wszName, 0, ppInSignature, null);
COMUtils.checkRC(res);
return new IWbemClassObject(ppInSignature.getValue());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to return IWbemClassObject[2] and assert in the documentation, that that is an array with exactly two elements, where the first is the in and the second is the out signature?

This would also be required as the method description states (https://learn.microsoft.com/de-de/windows/win32/api/wbemcli/nf-wbemcli-iwbemclassobject-getmethod):

Note The caller must call IWbemClassObject::Release on the ppInSignature and ppOutSignature pointers when these objects are no longer required.

Essentially you are leaking the inSignature object.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume you meant that I am leaking the outSignature object?
This overload was meant to be make the library easier to use for the common use case where usually what you would be interested in is the inSignature so I don't think we would want to return the array of IWbemClassObject.
I updated this to send NULL for the outSignature so we don't leak it.

}

public HRESULT GetNames(String wszQualifierName, int lFlags, VARIANT.ByReference pQualifierVal, PointerByReference pNames) {
return GetNames(wszQualifierName == null ? null : new WString(wszQualifierName), lFlags, pQualifierVal, pNames);
}
Expand Down Expand Up @@ -194,6 +211,42 @@ public IWbemQualifierSet GetPropertyQualifierSet(String strProperty) {
IWbemQualifierSet qualifier = new IWbemQualifierSet(ppQualSet.getValue());
return qualifier;
}

public HRESULT Put(String wszName, int lFlags, Variant.VARIANT pVal, int Type) {
return Put(wszName == null ? null : new WString(wszName), lFlags, pVal, Type);
}

public HRESULT Put(WString wszName, int lFlags, Variant.VARIANT pVal, int Type) {
// 6th method in IWbemClassObjectVtbl
return (HRESULT) _invokeNativeObject(5,
new Object[]{ getPointer(), wszName, lFlags, pVal, Type}, HRESULT.class);
}

public void Put(String wszName, String pValue) {
Variant.VARIANT aVariant = new Variant.VARIANT();
BSTR strValue = OleAuto.INSTANCE.SysAllocString(pValue);
try {
aVariant.setValue(Variant.VT_BSTR, strValue);
HRESULT res = Put(wszName, 0, aVariant, 0);
COMUtils.checkRC(res);
}
finally {
OleAuto.INSTANCE.VariantClear(aVariant);
}
}

public HRESULT SpawnInstance(int lFlags, PointerByReference ppNewInstance) {
// 16th method in IWbemClassObjectVtbl
return (HRESULT) _invokeNativeObject(15,
new Object[]{ getPointer(), lFlags, ppNewInstance}, HRESULT.class);
}

public IWbemClassObject SpawnInstance() {
PointerByReference ppNewInstance = new PointerByReference();
HRESULT res = SpawnInstance(0, ppNewInstance);
COMUtils.checkRC(res);
return new IWbemClassObject(ppNewInstance.getValue());
}
}

class IWbemQualifierSet extends Unknown {
Expand Down Expand Up @@ -348,6 +401,31 @@ public IWbemServices(Pointer pvInstance) {
super(pvInstance);
}

public HRESULT ExecMethod(BSTR strObjectPath, BSTR strMethodName, int lFlags, IWbemContext pCtx,
Pointer pInParams, PointerByReference ppOutParams, PointerByReference ppCallResult) {
// ExecMethod is 25st method of IWbemServicesVtbl in WbemCli.h
return (HRESULT) _invokeNativeObject(24,
new Object[] { getPointer(), strObjectPath, strMethodName, lFlags, pCtx, pInParams, ppOutParams, ppCallResult }, HRESULT.class);
}

public IWbemClassObject ExecMethod(String strObjectPath, String strMethodName, int lFlags, IWbemContext pCtx,
IWbemClassObject inParams) {
BSTR strObjectPathBSTR = OleAuto.INSTANCE.SysAllocString(strObjectPath);
BSTR strMethodNameBSTR = OleAuto.INSTANCE.SysAllocString(strMethodName);
try {
PointerByReference ppOutParams = new PointerByReference();

HRESULT res = ExecMethod(strObjectPathBSTR, strMethodNameBSTR, lFlags, pCtx, inParams.getPointer(), ppOutParams, null);

COMUtils.checkRC(res);

return new IWbemClassObject(ppOutParams.getValue());
} finally {
OleAuto.INSTANCE.SysFreeString(strObjectPathBSTR);
OleAuto.INSTANCE.SysFreeString(strMethodNameBSTR);
}
}

public HRESULT ExecQuery(BSTR strQueryLanguage, BSTR strQuery, int lFlags, IWbemContext pCtx,
PointerByReference ppEnum) {
// ExecQuery is 21st method of IWbemServicesVtbl in WbemCli.h
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,44 @@ public void testIWbemContextSetValue() {
assertEquals(currentPid, pVal.longValue());
}

@Test
public void testWmiObject() {
Wbemcli.IWbemServices svc = null;
Variant.VARIANT.ByReference pVal = new Variant.VARIANT.ByReference();

String className = "StdRegProv";
String methodName = "GetStringValue";

IWbemClassObject regClass = null;
IWbemClassObject method = null;
IWbemClassObject instance = null;
IWbemClassObject result = null;

try {
svc = WbemcliUtil.connectServer("ROOT\\Default");

regClass = svc.GetObject(className, 0, null);
method = regClass.GetMethod(methodName);
instance = method.SpawnInstance();

instance.Put("sSubKeyName", "SOFTWARE\\Microsoft\\Windows\\CurrentVersion");
instance.Put("sValueName", "CommonFilesDir");

result = svc.ExecMethod(className, methodName, 0, null, instance);

result.Get("sValue", 0, pVal, null, null);
assertEquals(Variant.VT_BSTR, pVal.getVarType().intValue());
assertTrue(!pVal.stringValue().isEmpty());
OleAuto.INSTANCE.VariantClear(pVal);
} finally {
if (svc != null) svc.Release();
if (result != null) result.Release();
if (method != null) method.Release();
if (instance != null) instance.Release();
if (regClass != null) regClass.Release();
}
}

/**
* Copy from WbemcliUtil#connectServer with American English selected as
* locale.
Expand Down