Skip to content

Commit

Permalink
Added methods to IWbemContext, IWbemServices and IWbemClassObject. Ad…
Browse files Browse the repository at this point in the history
…ded IWbemQualifierSet.
  • Loading branch information
rchateauneu committed Oct 28, 2022
1 parent 673079f commit cc92ed6
Show file tree
Hide file tree
Showing 3 changed files with 299 additions and 0 deletions.
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);
}

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;
}
}

0 comments on commit cc92ed6

Please sign in to comment.