// Copyright (C) 2012 jOVAL.org. All rights reserved. // This software is licensed under the AGPL 3.0 license available at http://www.joval.org/agpl_v3.txt package jwsmv.cim; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilder; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.dmtf.wsman.AttributableDuration; import org.dmtf.wsman.AttributableURI; import org.dmtf.wsman.OptionSet; import org.dmtf.wsman.OptionType; import jwsmv.Constants; import jwsmv.wsman.FaultException; import jwsmv.wsman.Port; /** * A WSMV-based implementation of the WMI StdRegProv class. * * @author David A. Solin * @version %I% %G% */ public class StdRegProv implements Constants { public static final long HKEY_CLASSES_ROOT = 0x80000000L; public static final long HKEY_CURRENT_USER = 0x80000001L; public static final long HKEY_LOCAL_MACHINE = 0x80000002L; public static final long HKEY_USERS = 0x80000003L; public static final long HKEY_CURRENT_CONFIG= 0x80000005L; public static final long HKEY_DYN_DATA = 0x80000006L; public static final int REG_NONE = 0; public static final int REG_SZ = 1; public static final int REG_EXPAND_SZ = 2; public static final int REG_BINARY = 3; public static final int REG_DWORD = 4; public static final int REG_MULTI_SZ = 7; public static final int REG_QWORD = 11; static final String CLASS_URI = "http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/StdRegProv"; static final DocumentBuilder BUILDER; static { try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); BUILDER = dbf.newDocumentBuilder(); } catch (Exception e) { throw new RuntimeException(e); } } private Port port; private Document doc; private String arch = null; /** * Create a new Registry, using the default provider architecture. */ public StdRegProv(Port port) { this.port = port; doc = BUILDER.newDocument(); } /** * Create a new Registry using the specified provider architecture. * * @param view Use 32 or 64. // // DAS: One cannot select the provider architecture via MS-WSMV, on account of Microsoft internal defect // ID #SR112120710065406, so for now, I have commented out this constructor. // public StdRegProv(Port port, int view) throws IllegalArgumentException { this(port); switch(view) { case 32: arch = "32"; break; case 64: arch = "64"; break; default: throw new IllegalArgumentException(Integer.toString(view)); } } */ /** * List all the subkeys under a registry key. * * @param hive one of the HKEY_* constants * @param subkey the path of the subkey to enumerate */ public String[] enumKey(long hive, String subkey) throws Exception { Element defKey = doc.createElementNS(CLASS_URI, "hDefKey"); defKey.setTextContent(Long.toString(hive)); Element subKeyName = doc.createElementNS(CLASS_URI, "sSubKeyName"); subKeyName.setTextContent(subkey); Element params = doc.createElementNS(CLASS_URI, "EnumKey_INPUT"); params.appendChild(defKey); params.appendChild(subKeyName); Object result = port.dispatch(CLASS_URI + "/EnumKey", getDispatchHeaders(), params); if (result instanceof Element) { Element elt = (Element)result; if ("EnumKey_OUTPUT".equals(elt.getLocalName())) { int hResult = (int)getHResult(elt); switch(hResult) { case 0: NodeList nodes = elt.getElementsByTagNameNS(CLASS_URI, "sNames"); int len = nodes.getLength(); ArrayList<String> subkeys = new ArrayList<String>(len); for (int i=0; i < len; i++) { subkeys.add(nodes.item(i).getTextContent()); } return subkeys.toArray(new String[len]); case 2: throw new NoSuchElementException(subkey); default: throw new Exception("Unexpected result code: " + hResult); } } else { throw new Exception("Unexpected element: " + elt.getLocalName()); } } else { throw new Exception("Unexpected return type: " + result.getClass().getName()); } } /** * List all the values (and their types) stored under a registry key. * * @param hive one of the HKEY_* constants * @param subkey the path of the subkey whose values will be enumerated */ public Value[] enumValues(long hive, String subkey) throws Exception { Element defKey = doc.createElementNS(CLASS_URI, "hDefKey"); defKey.setTextContent(Long.toString(hive)); Element subKeyName = doc.createElementNS(CLASS_URI, "sSubKeyName"); subKeyName.setTextContent(subkey); Element params = doc.createElementNS(CLASS_URI, "EnumValues_INPUT"); params.appendChild(defKey); params.appendChild(subKeyName); Object result = port.dispatch(CLASS_URI + "/EnumValues", getDispatchHeaders(), params); if (result instanceof Element) { Element elt = (Element)result; if ("EnumValues_OUTPUT".equals(elt.getLocalName())) { int hResult = (int)getHResult(elt); switch(hResult) { case 0: NodeList nodes = elt.getElementsByTagNameNS(CLASS_URI, "sNames"); int len = nodes.getLength(); ArrayList<Value> values = new ArrayList<Value>(len); for (int i=0; i < len; i++) { Value value = new Value(); value.name = nodes.item(i).getTextContent(); values.add(value); } nodes = elt.getElementsByTagNameNS(CLASS_URI, "Types"); for (int i=0; i < len; i++) { values.get(i).type = Integer.parseInt(nodes.item(i).getTextContent()); } return values.toArray(new Value[len]); default: throw new Exception("Unexpected result code: " + hResult); } } else { throw new Exception("Unexpected element: " + elt.getLocalName()); } } else { throw new Exception("Unexpected return type: " + result.getClass().getName()); } } /** * Get a REG_BINARY value from the registry. */ public byte[] getBinaryValue(long hive, String subkey, String value) throws Exception { Element defKey = doc.createElementNS(CLASS_URI, "hDefKey"); defKey.setTextContent(Long.toString(hive)); Element subKeyName = doc.createElementNS(CLASS_URI, "sSubKeyName"); subKeyName.setTextContent(subkey); Element valueName = doc.createElementNS(CLASS_URI, "sValueName"); valueName.setTextContent(value); Element params = doc.createElementNS(CLASS_URI, "GetBinaryValue_INPUT"); params.appendChild(defKey); params.appendChild(subKeyName); params.appendChild(valueName); Object result = port.dispatch(CLASS_URI + "/GetBinaryValue", getDispatchHeaders(), params); if (result instanceof Element) { Element elt = (Element)result; if ("GetBinaryValue_OUTPUT".equals(elt.getLocalName())) { int hResult = (int)getHResult(elt); switch(hResult) { case 0: NodeList nodes = elt.getElementsByTagNameNS(CLASS_URI, "uValue"); int len = nodes.getLength(); byte[] data = new byte[len]; for (int i=0; i < len; i++) { data[i] = (byte)(0xFF & Short.parseShort(nodes.item(i).getTextContent())); } return data; case 2: throw new NoSuchElementException(value); default: throw new Exception("Unexpected result code: " + hResult); } } else { throw new Exception("Unexpected element: " + elt.getLocalName()); } } else { throw new Exception("Unexpected return type: " + result.getClass().getName()); } } /** * Get a REG_DWORD value from the registry. */ public int getDwordValue(long hive, String subkey, String value) throws Exception { Element defKey = doc.createElementNS(CLASS_URI, "hDefKey"); defKey.setTextContent(Long.toString(hive)); Element subKeyName = doc.createElementNS(CLASS_URI, "sSubKeyName"); subKeyName.setTextContent(subkey); Element valueName = doc.createElementNS(CLASS_URI, "sValueName"); valueName.setTextContent(value); Element params = doc.createElementNS(CLASS_URI, "GetDWORDValue_INPUT"); params.appendChild(defKey); params.appendChild(subKeyName); params.appendChild(valueName); Object result = port.dispatch(CLASS_URI + "/GetDWORDValue", getDispatchHeaders(), params); if (result instanceof Element) { Element elt = (Element)result; if ("GetDWORDValue_OUTPUT".equals(elt.getLocalName())) { int hResult = (int)getHResult(elt); switch(hResult) { case 0: NodeList nodes = elt.getElementsByTagNameNS(CLASS_URI, "uValue"); int len = nodes.getLength(); if (len == 1) { return Integer.parseInt(nodes.item(0).getTextContent()); } else { throw new Exception("Unexpected return value quantity: " + len); } case 2: throw new NoSuchElementException(value); default: throw new Exception("Unexpected result code: " + hResult); } } else { throw new Exception("Unexpected element: " + elt.getLocalName()); } } else { throw new Exception("Unexpected return type: " + result.getClass().getName()); } } /** * Get a REG_EXPAND_SZ value from the registry. The returned value will be expanded. */ public String getExpandedStringValue(long hive, String subkey, String value) throws Exception { Element defKey = doc.createElementNS(CLASS_URI, "hDefKey"); defKey.setTextContent(Long.toString(hive)); Element subKeyName = doc.createElementNS(CLASS_URI, "sSubKeyName"); subKeyName.setTextContent(subkey); Element valueName = doc.createElementNS(CLASS_URI, "sValueName"); valueName.setTextContent(value); Element params = doc.createElementNS(CLASS_URI, "GetExpandedStringValue_INPUT"); params.appendChild(defKey); params.appendChild(subKeyName); params.appendChild(valueName); Object result = port.dispatch(CLASS_URI + "/GetExpandedStringValue", getDispatchHeaders(), params); if (result instanceof Element) { Element elt = (Element)result; if ("GetExpandedStringValue_OUTPUT".equals(elt.getLocalName())) { int hResult = (int)getHResult(elt); switch(hResult) { case 0: NodeList nodes = elt.getElementsByTagNameNS(CLASS_URI, "sValue"); int len = nodes.getLength(); if (len == 1) { return nodes.item(0).getTextContent(); } else { throw new Exception("Unexpected return value quantity: " + len); } case 2: throw new NoSuchElementException(value); default: throw new Exception("Unexpected result code: " + hResult); } } else { throw new Exception("Unexpected element: " + elt.getLocalName()); } } else { throw new Exception("Unexpected return type: " + result.getClass().getName()); } } /** * Get a REG_MULTI_SZ value from the registry. */ public String[] getMultiStringValue(long hive, String subkey, String value) throws Exception { Element defKey = doc.createElementNS(CLASS_URI, "hDefKey"); defKey.setTextContent(Long.toString(hive)); Element subKeyName = doc.createElementNS(CLASS_URI, "sSubKeyName"); subKeyName.setTextContent(subkey); Element valueName = doc.createElementNS(CLASS_URI, "sValueName"); valueName.setTextContent(value); Element params = doc.createElementNS(CLASS_URI, "GetMultiStringValue_INPUT"); params.appendChild(defKey); params.appendChild(subKeyName); params.appendChild(valueName); Object result = port.dispatch(CLASS_URI + "/GetMultiStringValue", getDispatchHeaders(), params); if (result instanceof Element) { Element elt = (Element)result; if ("GetMultiStringValue_OUTPUT".equals(elt.getLocalName())) { int hResult = (int)getHResult(elt); switch(hResult) { case 0: NodeList nodes = elt.getElementsByTagNameNS(CLASS_URI, "sValue"); int len = nodes.getLength(); if (len == 0) { return null; } else { String[] data = new String[len]; for (int i=0; i < len; i++) { data[i] = nodes.item(i).getTextContent(); } return data; } case 2: throw new NoSuchElementException(value); default: throw new Exception("Unexpected result code: " + hResult); } } else { throw new Exception("Unexpected element: " + elt.getLocalName()); } } else { throw new Exception("Unexpected return type: " + result.getClass().getName()); } } /** * Get a REG_SZ value from the registry. */ public String getStringValue(long hive, String subkey, String value) throws Exception { Element defKey = doc.createElementNS(CLASS_URI, "hDefKey"); defKey.setTextContent(Long.toString(hive)); Element subKeyName = doc.createElementNS(CLASS_URI, "sSubKeyName"); subKeyName.setTextContent(subkey); Element valueName = doc.createElementNS(CLASS_URI, "sValueName"); valueName.setTextContent(value); Element params = doc.createElementNS(CLASS_URI, "GetStringValue_INPUT"); params.appendChild(defKey); params.appendChild(subKeyName); params.appendChild(valueName); Object result = port.dispatch(CLASS_URI + "/GetStringValue", getDispatchHeaders(), params); if (result instanceof Element) { Element elt = (Element)result; if ("GetStringValue_OUTPUT".equals(elt.getLocalName())) { int hResult = (int)getHResult(elt); switch(hResult) { case 0: NodeList nodes = elt.getElementsByTagNameNS(CLASS_URI, "sValue"); int len = nodes.getLength(); if (len == 1) { return nodes.item(0).getTextContent(); } else { throw new Exception("Unexpected return value quantity: " + len); } case 2: throw new NoSuchElementException(value); default: throw new Exception("Unexpected result code: " + hResult); } } else { throw new Exception("Unexpected element: " + elt.getLocalName()); } } else { throw new Exception("Unexpected return type: " + result.getClass().getName()); } } /** * Get a REG_QWORD value from the registry. */ public long getQwordValue(long hive, String subkey, String value) throws Exception { Element defKey = doc.createElementNS(CLASS_URI, "hDefKey"); defKey.setTextContent(Long.toString(hive)); Element subKeyName = doc.createElementNS(CLASS_URI, "sSubKeyName"); subKeyName.setTextContent(subkey); Element valueName = doc.createElementNS(CLASS_URI, "sValueName"); valueName.setTextContent(value); Element params = doc.createElementNS(CLASS_URI, "GetQWORDValue_INPUT"); params.appendChild(defKey); params.appendChild(subKeyName); params.appendChild(valueName); Object result = port.dispatch(CLASS_URI + "/GetQWORDValue", getDispatchHeaders(), params); if (result instanceof Element) { Element elt = (Element)result; if ("GetQWORDValue_OUTPUT".equals(elt.getLocalName())) { int hResult = (int)getHResult(elt); switch(hResult) { case 0: NodeList nodes = elt.getElementsByTagNameNS(CLASS_URI, "uValue"); int len = nodes.getLength(); if (len == 1) { return Long.parseLong(nodes.item(0).getTextContent()); } else { throw new Exception("Unexpected return value quantity: " + len); } case 2: throw new NoSuchElementException(value); default: throw new Exception("Unexpected result code: " + hResult); } } else { throw new Exception("Unexpected element: " + elt.getLocalName()); } } else { throw new Exception("Unexpected return type: " + result.getClass().getName()); } } /** * Container for information about a registry value. */ public class Value { private int type; private String name; private Value() {} public String getName() { return name; } /** * The REG_* constant corresponding to the type of this value. */ public int getType() { return type; } @Override public String toString() { String sType = null; switch(type) { case StdRegProv.REG_NONE: sType = "REG_NONE "; break; case StdRegProv.REG_DWORD: sType = "REG_DWORD "; break; case StdRegProv.REG_BINARY: sType = "REG_BINARY "; break; case StdRegProv.REG_SZ: sType = "REG_SZ "; break; case StdRegProv.REG_EXPAND_SZ: sType = "REG_EXPAND_SZ "; break; case StdRegProv.REG_MULTI_SZ: sType = "REG_MULTI_SZ "; break; case StdRegProv.REG_QWORD: sType = "REG_QWORD "; break; } return new StringBuffer(sType).append(name).toString(); } } // Private /** * Get the call result code from the element. */ private long getHResult(Element elt) throws IllegalArgumentException { NodeList nodes = elt.getElementsByTagNameNS(CLASS_URI, "ReturnValue"); int len = nodes.getLength(); if (len == 1) { return Long.parseLong(nodes.item(0).getTextContent()); } else { throw new IllegalArgumentException("Unexpected return value quantity: " + len); } } /** * Get dispatch headers for invoking methods of the StdRegProv WMI class. */ private List<Object> getDispatchHeaders() { List<Object> headers = new ArrayList<Object>(); AttributableURI uri = Factories.WSMAN.createAttributableURI(); uri.setValue(CLASS_URI); uri.getOtherAttributes().put(MUST_UNDERSTAND, "true"); headers.add(Factories.WSMAN.createResourceURI(uri)); // // Set the appropriate provider architecture using an OptionSet, if one was specified. // if (arch != null) { OptionSet options = Factories.WSMAN.createOptionSet(); headers.add(options); OptionType architecture = Factories.WSMAN.createOptionType(); architecture.setName("wmi:__ProviderArchitecture"); architecture.setType(new QName(XMLNS, "int")); architecture.setValue(arch); options.getOption().add(architecture); } AttributableDuration duration = Factories.WSMAN.createAttributableDuration(); duration.setValue(Factories.XMLDT.newDuration(60000)); headers.add(Factories.WSMAN.createOperationTimeout(duration)); return headers; } }