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 WBEM methods and a class. #1474

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 @@ -10,6 +10,7 @@ Features
* [#1454](https://github.com/java-native-access/jna/pull/1454): Add `c.s.j.p.win32.Psapi.QueryWorkingSetEx` and associated Types - [@crain-32](https://github.com/Crain-32).
* [#1459](https://github.com/java-native-access/jna/pull/1459): Add `VirtualLock` and `VirtualUnlock` in `c.s.j.p.win32.Kernel32` - [@matthiasblaesing](https://github.com/matthiasblaesing).
* [#1471](https://github.com/java-native-access/jna/pull/1471): Add `c.s.j.p.win32.Advapi32Util#isCurrentProcessElevated` and associated Types - [@dbwiddis](https://github.com/dbwiddis).
* [#1474](https://github.com/java-native-access/jna/pull/1474): Add `c.s.j.p.win32.WbemCli#IWbemClassObject.IWbemQualifierSet`, `IWbemServices.GetObject`, `IWbemContext.SetValue` and associated methods - [@rchateauneu](https://github.com/rchateauneu).

Bug Fixes
---------
Expand Down
157 changes: 157 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 @@ -25,6 +25,9 @@

import com.sun.jna.Pointer;
import com.sun.jna.WString;
import com.sun.jna.platform.win32.*;
import com.sun.jna.platform.win32.COM.COMUtils;
import com.sun.jna.platform.win32.COM.Unknown;
import com.sun.jna.platform.win32.Guid.CLSID;
import com.sun.jna.platform.win32.Guid.GUID;
import com.sun.jna.platform.win32.OaIdl.SAFEARRAY;
Expand All @@ -45,8 +48,16 @@
*/
public interface Wbemcli {

public static final int WBEM_FLAG_RETURN_WBEM_COMPLETE = 0x00000000;
public static final int WBEM_FLAG_RETURN_IMMEDIATELY = 0x00000010;
public static final int WBEM_FLAG_FORWARD_ONLY = 0x00000020;
public static final int WBEM_FLAG_NO_ERROR_OBJECT = 0x00000040;
public static final int WBEM_FLAG_SEND_STATUS = 0x00000080;
public static final int WBEM_FLAG_ENSURE_LOCATABLE = 0x00000100;
public static final int WBEM_FLAG_DIRECT_READ = 0x00000200;
public static final int WBEM_MASK_RESERVED_FLAGS = 0x0001F000;
public static final int WBEM_FLAG_USE_AMENDED_QUALIFIERS = 0x00020000;
public static final int WBEM_FLAG_STRONG_VALIDATION = 0x00100000;
public static final int WBEM_INFINITE = 0xFFFFFFFF;

// Non-error constants
Expand Down Expand Up @@ -146,6 +157,88 @@ public String[] GetNames(String wszQualifierName, int lFlags, VARIANT.ByReferenc
}
return names;
}

public HRESULT GetQualifierSet(PointerByReference ppQualSet) {
// Get is the fourth method of IWbemClassObjectVtbl in WbemCli.h :
return (HRESULT) _invokeNativeObject(3,
new Object[] { getPointer(), ppQualSet }, HRESULT.class);
}

public IWbemQualifierSet GetQualifierSet() {
PointerByReference ppQualSet = new PointerByReference();
HRESULT hr = GetQualifierSet(ppQualSet);
COMUtils.checkRC(hr);
IWbemQualifierSet qualifier = new IWbemQualifierSet(ppQualSet.getValue());

return qualifier;
}

/*
// https://docs.microsoft.com/en-us/windows/win32/api/wbemcli/nf-wbemcli-iwbemclassobject-getpropertyqualifierset
HRESULT GetPropertyQualifierSet(
[in] LPCWSTR wszProperty,
[out] IWbemQualifierSet **ppQualSet
);
*/
public HRESULT GetPropertyQualifierSet(WString wszProperty, PointerByReference ppQualSet) {
// Get is 12th method of IWbemClassObjectVtbl in WbemCli.h :
return (HRESULT) _invokeNativeObject(11,
new Object[] { getPointer(), wszProperty, ppQualSet }, HRESULT.class);
}

public IWbemQualifierSet GetPropertyQualifierSet(String strProperty) {
WString wszProperty = new WString(strProperty);
PointerByReference ppQualSet = new PointerByReference();

COMUtils.checkRC(GetPropertyQualifierSet(wszProperty, ppQualSet));
IWbemQualifierSet qualifier = new IWbemQualifierSet(ppQualSet.getValue());
return qualifier;
}
}

class IWbemQualifierSet extends Unknown {
public IWbemQualifierSet(Pointer pvInstance) {
super(pvInstance);
}

public HRESULT Get(WString wszName, int lFlags, VARIANT.ByReference pVal, IntByReference plFlavor) {
return (HRESULT) _invokeNativeObject(3,
new Object[] { getPointer(), wszName, lFlags, pVal, plFlavor }, HRESULT.class);
}

public String Get(String wszName) {
WString wszNameStr = new WString(wszName);
Variant.VARIANT.ByReference pQualifierVal = new Variant.VARIANT.ByReference();
HRESULT hres = Get(wszNameStr, 0, pQualifierVal, null);
if(hres.intValue() == 0x80041002) {
// This error for some classes only.
return null;
}
int qualifierInt = pQualifierVal.getVarType().intValue();
switch(qualifierInt) {
case Wbemcli.CIM_BOOLEAN:
return String.valueOf(pQualifierVal.booleanValue());
case Wbemcli.CIM_STRING:
return pQualifierVal.stringValue();
}
return null;
}

public HRESULT GetNames(int lFlags, PointerByReference pNames) {
return (HRESULT) _invokeNativeObject(6,
new Object[] { getPointer(), lFlags, pNames }, HRESULT.class);
rchateauneu marked this conversation as resolved.
Show resolved Hide resolved
}

public String[] GetNames() {
PointerByReference pbr = new PointerByReference();
COMUtils.checkRC(GetNames(0, pbr));
Object[] nameObjects = (Object[]) OaIdlUtil.toPrimitiveArray(new SAFEARRAY(pbr.getValue()), true);
String[] qualifierNames = new String[nameObjects.length];
for(int i = 0; i < nameObjects.length; i++) {
qualifierNames[i] = (String) nameObjects[i];
}
return qualifierNames;
}
}

/**
Expand Down Expand Up @@ -278,19 +371,83 @@ public IEnumWbemClassObject ExecQuery(String strQueryLanguage, String strQuery,
OleAuto.INSTANCE.SysFreeString(strQueryBSTR);
}
}

public HRESULT GetObject(BSTR strObjectPath, int lFlags, IWbemContext pCtx,
PointerByReference ppObject, PointerByReference ppCallResult) {
// GetObject is the 7th method of IWbemServicesVtbl in WbemCli.h
return (HRESULT) _invokeNativeObject(6,
new Object[] { getPointer(), strObjectPath, lFlags, pCtx, ppObject, ppCallResult}, HRESULT.class);
}

public IWbemClassObject GetObject(String strObjectPath, int lFlags, IWbemContext pCtx) {
BSTR strObjectPathBSTR = OleAuto.INSTANCE.SysAllocString(strObjectPath);
try {
PointerByReference ppObject = new PointerByReference();
HRESULT res = GetObject(strObjectPathBSTR, lFlags, pCtx, ppObject, null);
COMUtils.checkRC(res);
return new IWbemClassObject(ppObject.getValue());
} finally {
OleAuto.INSTANCE.SysFreeString(strObjectPathBSTR);
}
}
}

/**
* Optionally used to communicate additional context information to
* providers when submitting IWbemServices calls to WMI
*/
class IWbemContext extends Unknown {
public static final CLSID CLSID_WbemContext = new CLSID("674B6698-EE92-11D0-AD71-00C04FD8FDFF");
public static final GUID IID_IWbemContext = new GUID("44aca674-e8fc-11d0-a07c-00c04fb68820");

public IWbemContext() {
}

public static IWbemContext create() {
PointerByReference pbr = new PointerByReference();

HRESULT hres = Ole32.INSTANCE.CoCreateInstance(CLSID_WbemContext, null, WTypes.CLSCTX_INPROC_SERVER,
IID_IWbemContext, pbr);
if (COMUtils.FAILED(hres)) {
return null;
}

return new IWbemContext(pbr.getValue());
}

public IWbemContext(Pointer pvInstance) {
super(pvInstance);
}

public void SetValue(String wszName, int lFlag, Variant.VARIANT pValue) {
BSTR wszNameBSTR = OleAuto.INSTANCE.SysAllocString(wszName);
try {
// SetValue is the 9th method of IWbemContextVtbl in WbemCli.h
HRESULT res = (HRESULT) _invokeNativeObject(8,
new Object[] { getPointer(), wszNameBSTR, lFlag, pValue}, HRESULT.class);
COMUtils.checkRC(res);
} finally {
OleAuto.INSTANCE.SysFreeString(wszNameBSTR);
}
}

public void SetValue(String wszName, int lFlag, boolean pValue) {
Variant.VARIANT aVariant = new Variant.VARIANT();
aVariant.setValue(Variant.VT_BOOL, pValue ? Variant.VARIANT_TRUE : Variant.VARIANT_FALSE);
SetValue(wszName, lFlag, aVariant);
OleAuto.INSTANCE.VariantClear(aVariant);
}

public void SetValue(String wszName, int lFlag, String pValue) {
Variant.VARIANT aVariant = new Variant.VARIANT();
BSTR strValue = OleAuto.INSTANCE.SysAllocString(pValue);
try {
aVariant.setValue(Variant.VT_LPSTR, strValue);
SetValue(wszName, lFlag, aVariant);
}
finally {
OleAuto.INSTANCE.SysFreeString(strValue);
}
}
}
}
141 changes: 141 additions & 0 deletions contrib/platform/test/com/sun/jna/platform/win32/COM/WbemcliTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,20 @@
import org.junit.Before;
import org.junit.Test;

import static com.sun.jna.platform.win32.Variant.VT_ARRAY;
import static com.sun.jna.platform.win32.Variant.VT_BSTR;

import com.sun.jna.platform.win32.Ole32;
import com.sun.jna.platform.win32.Variant;
import com.sun.jna.platform.win32.COM.Wbemcli.IEnumWbemClassObject;
import com.sun.jna.platform.win32.COM.Wbemcli.IWbemClassObject;
import com.sun.jna.platform.win32.COM.WbemcliUtil.WmiQuery;
import com.sun.jna.platform.win32.COM.WbemcliUtil.WmiResult;
import com.sun.jna.platform.win32.OleAuto;
import com.sun.jna.platform.win32.OaIdl.SAFEARRAY;
import com.sun.jna.platform.win32.WTypes;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.ptr.IntByReference;
import java.util.Arrays;
import java.util.HashSet;
Expand Down Expand Up @@ -309,4 +316,138 @@ public void testUnsupportedValues() {
assertNull(result.getValue(Win32_DiskDrive_Values.CAPABILITIES, i));
}
}

@Test
public void testIWbemClassObjectGetQualifierSet() {

Wbemcli.IWbemServices svc = null;
Wbemcli.IEnumWbemClassObject enumRes = null;
Variant.VARIANT.ByReference pVal = new Variant.VARIANT.ByReference();
IntByReference pType = new IntByReference();
IntByReference plFlavor = new IntByReference();

boolean foundWin32_Process = false;
try {
svc = connectServerEnglishLocale(WbemcliUtil.DEFAULT_NAMESPACE);
enumRes = svc.ExecQuery(
"WQL",
"SELECT * FROM meta_class",
Wbemcli.WBEM_FLAG_FORWARD_ONLY | Wbemcli.WBEM_FLAG_USE_AMENDED_QUALIFIERS, null);

while (true) {
Wbemcli.IWbemClassObject[] results = enumRes.Next(Wbemcli.WBEM_INFINITE, 1);
if (results.length == 0) {
break;
}

Wbemcli.IWbemClassObject classObject = results[0];
Variant.VARIANT.ByReference pQualifierVal = new Variant.VARIANT.ByReference();

COMUtils.checkRC(classObject.Get("__CLASS", 0, pVal, pType, plFlavor));
String className = pVal.stringValue();
if(! className.equals("Win32_Process")) {
continue;
}
foundWin32_Process = true;
OleAuto.INSTANCE.VariantClear(pVal);

COMUtils.checkRC(classObject.Get("__SUPERCLASS", 0, pVal, pType, plFlavor));
Object baseClass = pVal.getValue();
OleAuto.INSTANCE.VariantClear(pVal);
assertEquals("CIM_Process", baseClass.toString());

String[] propertyNames = classObject.GetNames(null, 0, pQualifierVal);
assertTrue(Arrays.asList(propertyNames).contains("ProcessId"));

Wbemcli.IWbemQualifierSet classQualifiersSet = classObject.GetQualifierSet();
String[] classQualifiersNames = classQualifiersSet.GetNames();
assertTrue(Arrays.asList(classQualifiersNames).contains("DisplayName"));
String classDisplayName = classQualifiersSet.Get("DisplayName");
assertEquals("Processes", classDisplayName);

Wbemcli.IWbemQualifierSet propertyQualifiersSet = classObject.GetPropertyQualifierSet("ProcessId");
String[] propertyQualifierNames = propertyQualifiersSet.GetNames();

assertTrue(Arrays.asList(propertyQualifierNames).contains("DisplayName"));
String propertyDisplayName = propertyQualifiersSet.Get("DisplayName");
assertEquals("Process Id", propertyDisplayName);

assertTrue(Arrays.asList(propertyQualifierNames).contains("CIMTYPE"));
String propertyCIMTYPE = propertyQualifiersSet.Get("CIMTYPE");
assertEquals("uint32", propertyCIMTYPE);

classObject.Release();
}
} finally {
if (svc != null) svc.Release();
if (enumRes != null) enumRes.Release();
}
assertTrue(foundWin32_Process);
}

@Test
public void testIWbemContextSetValue() {
long currentPid = Kernel32.INSTANCE.GetCurrentProcessId();
String objectPath = String.format("\\\\.\\%s:Win32_Process.Handle=\"%d\"", WbemcliUtil.DEFAULT_NAMESPACE, currentPid);

// This context object retrieves only parts of a WMI instance.
Wbemcli.IWbemContext pctxDrive = new Wbemcli.IWbemContext().create();
pctxDrive.SetValue("__GET_EXTENSIONS", 0, true);
pctxDrive.SetValue("__GET_EXT_CLIENT_REQUEST", 0, true);

// Create a safe array of just one property to retrieve.
SAFEARRAY psaProperties = SAFEARRAY.createSafeArray(new WTypes.VARTYPE(VT_BSTR), 1);
OleAuto.INSTANCE.SafeArrayLock(psaProperties);
try {
WTypes.BSTR strPropertyBSTR = OleAuto.INSTANCE.SysAllocString("ProcessId");
try {
psaProperties.putElement(strPropertyBSTR, 0);
} finally {
OleAuto.INSTANCE.SysFreeString(strPropertyBSTR);
}
} finally {
OleAuto.INSTANCE.SafeArrayUnlock(psaProperties);
}

Variant.VARIANT.ByReference vPropertyList = new Variant.VARIANT.ByReference();
vPropertyList.setVarType((short) (VT_ARRAY | VT_BSTR));
vPropertyList.setValue(psaProperties);
pctxDrive.SetValue("__GET_EXT_PROPERTIES", 0, vPropertyList);
psaProperties.destroy();

Variant.VARIANT.ByReference pVal = new Variant.VARIANT.ByReference();
Wbemcli.IWbemServices svc = null;
try {
svc = WbemcliUtil.connectServer(WbemcliUtil.DEFAULT_NAMESPACE);
Wbemcli.IWbemClassObject classObject = svc.GetObject(objectPath, Wbemcli.WBEM_FLAG_RETURN_WBEM_COMPLETE, pctxDrive);
// The properties "Handle" and "PropertyId" must have the same values with different types.
COMUtils.checkRC(classObject.Get("ProcessId", 0, pVal, null, null));
}
finally {
if (svc != null) svc.Release();
}
assertEquals(currentPid, pVal.longValue());
}

/**
* Copy from WbemcliUtil#connectServer with American English selected as
* locale.
*/
private static Wbemcli.IWbemServices connectServerEnglishLocale(String namespace) {
Wbemcli.IWbemLocator loc = Wbemcli.IWbemLocator.create();
if (loc == null) {
throw new COMException("Failed to create WbemLocator object.");
}

Wbemcli.IWbemServices services = loc.ConnectServer(namespace, null, null, "MS_409", 0, null, null);
loc.Release();

WinNT.HRESULT hres = Ole32.INSTANCE.CoSetProxyBlanket(services, Ole32.RPC_C_AUTHN_WINNT, Ole32.RPC_C_AUTHZ_NONE, null,
Ole32.RPC_C_AUTHN_LEVEL_CALL, Ole32.RPC_C_IMP_LEVEL_IMPERSONATE, null, Ole32.EOAC_NONE);
if (COMUtils.FAILED(hres)) {
services.Release();
throw new COMException("Could not set proxy blanket.", hres);
}
return services;
}
}