/* * Copyright (C) 2010-2016 JPEXS * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.sun.jna.platform.win32; /** * * @author JPEXS */ import com.sun.jna.Memory; import com.sun.jna.Native; import com.sun.jna.Pointer; import com.sun.jna.platform.win32.WinNT.EVENTLOGRECORD; import com.sun.jna.platform.win32.WinReg.HKEY; import com.sun.jna.platform.win32.WinReg.HKEYByReference; import com.sun.jna.ptr.IntByReference; import java.util.ArrayList; import java.util.Map; import java.util.Map.Entry; import java.util.TreeMap; /** * Advapi32 utility API. * * @author dblock[at]dblock.org */ public abstract class Advapi32Util { /** * An account. */ public static class Account { /** * Account name. */ public String name; /** * Account domain. */ public String domain; /** * Account SID. */ public byte[] sid; /** * String representation of the account SID. */ public String sidString; /** * Account type, one of SID_NAME_USE. */ public int accountType; /** * Fully qualified account name. */ public String fqn; } /** * Checks whether a registry key exists. * * @param root HKEY_LOCAL_MACHINE, etc. * @param key Path to the registry key. * @return True if the key exists. */ public static boolean registryKeyExists(HKEY root, String key) { HKEYByReference phkKey = new HKEYByReference(); int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, key, 0, WinNT.KEY_READ | WinNT.KEY_WOW64_32KEY, phkKey); switch (rc) { case W32Errors.ERROR_SUCCESS: Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); return true; case W32Errors.ERROR_FILE_NOT_FOUND: return false; default: throw new Win32Exception(rc); } } /** * Checks whether a registry value exists. * * @param root HKEY_LOCAL_MACHINE, etc. * @param key Registry key path. * @param value Value name. * @return True if the value exists. */ public static boolean registryValueExists(HKEY root, String key, String value) { HKEYByReference phkKey = new HKEYByReference(); int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, key, 0, WinNT.KEY_READ | WinNT.KEY_WOW64_32KEY, phkKey); try { switch (rc) { case W32Errors.ERROR_SUCCESS: break; case W32Errors.ERROR_FILE_NOT_FOUND: return false; default: throw new Win32Exception(rc); } IntByReference lpcbData = new IntByReference(); IntByReference lpType = new IntByReference(); rc = Advapi32.INSTANCE.RegQueryValueEx( phkKey.getValue(), value, 0, lpType, (char[]) null, lpcbData); switch (rc) { case W32Errors.ERROR_SUCCESS: case W32Errors.ERROR_INSUFFICIENT_BUFFER: return true; case W32Errors.ERROR_FILE_NOT_FOUND: return false; default: throw new Win32Exception(rc); } } finally { if (phkKey.getValue() != null && phkKey.getValue() != WinBase.INVALID_HANDLE_VALUE) { rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } } } } /** * Get a registry REG_SZ value. * * @param root Root key. * @param key Registry path. * @param value Name of the value to retrieve. * @return String value. */ public static String registryGetStringValue(HKEY root, String key, String value) { HKEYByReference phkKey = new HKEYByReference(); int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, key, 0, WinNT.KEY_READ | WinNT.KEY_WOW64_32KEY, phkKey); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } try { IntByReference lpcbData = new IntByReference(); IntByReference lpType = new IntByReference(); rc = Advapi32.INSTANCE.RegQueryValueEx( phkKey.getValue(), value, 0, lpType, (char[]) null, lpcbData); if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { throw new Win32Exception(rc); } if (lpType.getValue() != WinNT.REG_SZ) { throw new RuntimeException("Unexpected registry type " + lpType.getValue() + ", expected REG_SZ"); } char[] data = new char[lpcbData.getValue()]; rc = Advapi32.INSTANCE.RegQueryValueEx( phkKey.getValue(), value, 0, lpType, data, lpcbData); if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { throw new Win32Exception(rc); } return Native.toString(data); } finally { rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } } } /** * Get a registry REG_EXPAND_SZ value. * * @param root Root key. * @param key Registry path. * @param value Name of the value to retrieve. * @return String value. */ public static String registryGetExpandableStringValue(HKEY root, String key, String value) { HKEYByReference phkKey = new HKEYByReference(); int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, key, 0, WinNT.KEY_READ | WinNT.KEY_WOW64_32KEY, phkKey); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } try { IntByReference lpcbData = new IntByReference(); IntByReference lpType = new IntByReference(); rc = Advapi32.INSTANCE.RegQueryValueEx( phkKey.getValue(), value, 0, lpType, (char[]) null, lpcbData); if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { throw new Win32Exception(rc); } if (lpType.getValue() != WinNT.REG_EXPAND_SZ) { throw new RuntimeException("Unexpected registry type " + lpType.getValue() + ", expected REG_SZ"); } char[] data = new char[lpcbData.getValue()]; rc = Advapi32.INSTANCE.RegQueryValueEx( phkKey.getValue(), value, 0, lpType, data, lpcbData); if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { throw new Win32Exception(rc); } return Native.toString(data); } finally { rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } } } /** * Get a registry REG_MULTI_SZ value. * * @param root Root key. * @param key Registry path. * @param value Name of the value to retrieve. * @return String value. */ public static String[] registryGetStringArray(HKEY root, String key, String value) { HKEYByReference phkKey = new HKEYByReference(); int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, key, 0, WinNT.KEY_READ | WinNT.KEY_WOW64_32KEY, phkKey); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } try { IntByReference lpcbData = new IntByReference(); IntByReference lpType = new IntByReference(); rc = Advapi32.INSTANCE.RegQueryValueEx( phkKey.getValue(), value, 0, lpType, (char[]) null, lpcbData); if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { throw new Win32Exception(rc); } if (lpType.getValue() != WinNT.REG_MULTI_SZ) { throw new RuntimeException("Unexpected registry type " + lpType.getValue() + ", expected REG_SZ"); } Memory data = new Memory(lpcbData.getValue()); rc = Advapi32.INSTANCE.RegQueryValueEx( phkKey.getValue(), value, 0, lpType, data, lpcbData); if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { throw new Win32Exception(rc); } ArrayList<String> result = new ArrayList<>(); int offset = 0; while (offset < data.size()) { String s = data.getString(offset, true); offset += s.length() * Native.WCHAR_SIZE; offset += Native.WCHAR_SIZE; result.add(s); } return result.toArray(new String[result.size()]); } finally { rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } } } /** * Get a registry REG_BINARY value. * * @param root Root key. * @param key Registry path. * @param value Name of the value to retrieve. * @return String value. */ public static byte[] registryGetBinaryValue(HKEY root, String key, String value) { HKEYByReference phkKey = new HKEYByReference(); int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, key, 0, WinNT.KEY_READ | WinNT.KEY_WOW64_32KEY, phkKey); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } try { IntByReference lpcbData = new IntByReference(); IntByReference lpType = new IntByReference(); rc = Advapi32.INSTANCE.RegQueryValueEx( phkKey.getValue(), value, 0, lpType, (char[]) null, lpcbData); if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { throw new Win32Exception(rc); } if (lpType.getValue() != WinNT.REG_BINARY) { throw new RuntimeException("Unexpected registry type " + lpType.getValue() + ", expected REG_BINARY"); } byte[] data = new byte[lpcbData.getValue()]; rc = Advapi32.INSTANCE.RegQueryValueEx( phkKey.getValue(), value, 0, lpType, data, lpcbData); if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { throw new Win32Exception(rc); } return data; } finally { rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } } } /** * Get a registry DWORD value. * * @param root Root key. * @param key Registry key path. * @param value Name of the value to retrieve. * @return Integer value. */ public static int registryGetIntValue(HKEY root, String key, String value) { HKEYByReference phkKey = new HKEYByReference(); int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, key, 0, WinNT.KEY_READ | WinNT.KEY_WOW64_32KEY, phkKey); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } try { IntByReference lpcbData = new IntByReference(); IntByReference lpType = new IntByReference(); rc = Advapi32.INSTANCE.RegQueryValueEx( phkKey.getValue(), value, 0, lpType, (char[]) null, lpcbData); if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { throw new Win32Exception(rc); } if (lpType.getValue() != WinNT.REG_DWORD) { throw new RuntimeException("Unexpected registry type " + lpType.getValue() + ", expected REG_SZ"); } IntByReference data = new IntByReference(); rc = Advapi32.INSTANCE.RegQueryValueEx( phkKey.getValue(), value, 0, lpType, data, lpcbData); if (rc != W32Errors.ERROR_SUCCESS && rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { throw new Win32Exception(rc); } return data.getValue(); } finally { rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } } } /** * Create a registry key. * * @param hKey Parent key. * @param keyName Key name. * @return True if the key was created, false otherwise. */ public static boolean registryCreateKey(HKEY hKey, String keyName) { HKEYByReference phkResult = new HKEYByReference(); IntByReference lpdwDisposition = new IntByReference(); int rc = Advapi32.INSTANCE.RegCreateKeyEx(hKey, keyName, 0, null, WinNT.REG_OPTION_NON_VOLATILE, WinNT.KEY_READ, null, phkResult, lpdwDisposition); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } rc = Advapi32.INSTANCE.RegCloseKey(phkResult.getValue()); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } return WinNT.REG_CREATED_NEW_KEY == lpdwDisposition.getValue(); } /** * Create a registry key. * * @param root Root key. * @param parentPath Path to an existing registry key. * @param keyName Key name. * @return True if the key was created, false otherwise. */ public static boolean registryCreateKey(HKEY root, String parentPath, String keyName) { HKEYByReference phkKey = new HKEYByReference(); int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, parentPath, 0, WinNT.KEY_CREATE_SUB_KEY, phkKey); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } try { return registryCreateKey(phkKey.getValue(), keyName); } finally { rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } } } /** * Set an integer value in registry. * * @param hKey Parent key. * @param name Value name. * @param value Value to write to registry. */ public static void registrySetIntValue(HKEY hKey, String name, int value) { byte[] data = new byte[4]; data[0] = (byte) (value & 0xff); data[1] = (byte) ((value >> 8) & 0xff); data[2] = (byte) ((value >> 16) & 0xff); data[3] = (byte) ((value >> 24) & 0xff); int rc = Advapi32.INSTANCE.RegSetValueEx(hKey, name, 0, WinNT.REG_DWORD, data, 4); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } } /** * Set an integer value in registry. * * @param root Root key. * @param keyPath Path to an existing registry key. * @param name Value name. * @param value Value to write to registry. */ public static void registrySetIntValue(HKEY root, String keyPath, String name, int value) { HKEYByReference phkKey = new HKEYByReference(); int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ | WinNT.KEY_WRITE | WinNT.KEY_WOW64_32KEY, phkKey); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } try { registrySetIntValue(phkKey.getValue(), name, value); } finally { rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } } } /** * Set a string value in registry. * * @param hKey Parent key. * @param name Value name. * @param value Value to write to registry. */ public static void registrySetStringValue(HKEY hKey, String name, String value) { char[] data = Native.toCharArray(value); int rc = Advapi32.INSTANCE.RegSetValueEx(hKey, name, 0, WinNT.REG_SZ, data, data.length * Native.WCHAR_SIZE); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } } /** * Set a string value in registry. * * @param root Root key. * @param keyPath Path to an existing registry key. * @param name Value name. * @param value Value to write to registry. */ public static void registrySetStringValue(HKEY root, String keyPath, String name, String value) { HKEYByReference phkKey = new HKEYByReference(); int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ | WinNT.KEY_WRITE | WinNT.KEY_WOW64_32KEY, phkKey); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } try { registrySetStringValue(phkKey.getValue(), name, value); } finally { rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } } } /** * Set an expandable string value in registry. * * @param hKey Parent key. * @param name Value name. * @param value Value to write to registry. */ public static void registrySetExpandableStringValue(HKEY hKey, String name, String value) { char[] data = Native.toCharArray(value); int rc = Advapi32.INSTANCE.RegSetValueEx(hKey, name, 0, WinNT.REG_EXPAND_SZ, data, data.length * Native.WCHAR_SIZE); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } } /** * Set a string value in registry. * * @param root Root key. * @param keyPath Path to an existing registry key. * @param name Value name. * @param value Value to write to registry. */ public static void registrySetExpandableStringValue(HKEY root, String keyPath, String name, String value) { HKEYByReference phkKey = new HKEYByReference(); int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ | WinNT.KEY_WRITE | WinNT.KEY_WOW64_32KEY, phkKey); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } try { registrySetExpandableStringValue(phkKey.getValue(), name, value); } finally { rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } } } /** * Set a string array value in registry. * * @param hKey Parent key. * @param name Name. * @param arr Array of strings to write to registry. */ public static void registrySetStringArray(HKEY hKey, String name, String[] arr) { int size = 0; for (String s : arr) { size += s.length() * Native.WCHAR_SIZE; size += Native.WCHAR_SIZE; } int offset = 0; Memory data = new Memory(size); for (String s : arr) { data.setString(offset, s, true); offset += s.length() * Native.WCHAR_SIZE; offset += Native.WCHAR_SIZE; } int rc = Advapi32.INSTANCE.RegSetValueEx(hKey, name, 0, WinNT.REG_MULTI_SZ, data.getByteArray(0, size), size); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } } /** * Set a string array value in registry. * * @param root Root key. * @param keyPath Path to an existing registry key. * @param name Value name. * @param arr Array of strings to write to registry. */ public static void registrySetStringArray(HKEY root, String keyPath, String name, String[] arr) { HKEYByReference phkKey = new HKEYByReference(); int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ | WinNT.KEY_WRITE | WinNT.KEY_WOW64_32KEY, phkKey); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } try { registrySetStringArray(phkKey.getValue(), name, arr); } finally { rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } } } /** * Set a binary value in registry. * * @param hKey Parent key. * @param name Value name. * @param data Data to write to registry. */ public static void registrySetBinaryValue(HKEY hKey, String name, byte[] data) { int rc = Advapi32.INSTANCE.RegSetValueEx(hKey, name, 0, WinNT.REG_BINARY, data, data.length); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } } /** * Set a binary value in registry. * * @param root Root key. * @param keyPath Path to an existing registry key. * @param name Value name. * @param data Data to write to registry. */ public static void registrySetBinaryValue(HKEY root, String keyPath, String name, byte[] data) { HKEYByReference phkKey = new HKEYByReference(); int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ | WinNT.KEY_WRITE | WinNT.KEY_WOW64_32KEY, phkKey); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } try { registrySetBinaryValue(phkKey.getValue(), name, data); } finally { rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } } } /** * Delete a registry key. * * @param hKey Parent key. * @param keyName Name of the key to delete. */ public static void registryDeleteKey(HKEY hKey, String keyName) { int rc = Advapi32.INSTANCE.RegDeleteKey(hKey, keyName); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } } /** * Delete a registry key. * * @param root Root key. * @param keyPath Path to an existing registry key. * @param keyName Name of the key to delete. */ public static void registryDeleteKey(HKEY root, String keyPath, String keyName) { HKEYByReference phkKey = new HKEYByReference(); int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ | WinNT.KEY_WRITE | WinNT.KEY_WOW64_32KEY, phkKey); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } try { registryDeleteKey(phkKey.getValue(), keyName); } finally { rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } } } /** * Delete a registry value. * * @param hKey Parent key. * @param valueName Name of the value to delete. */ public static void registryDeleteValue(HKEY hKey, String valueName) { int rc = Advapi32.INSTANCE.RegDeleteValue(hKey, valueName); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } } /** * Delete a registry value. * * @param root Root key. * @param keyPath Path to an existing registry key. * @param valueName Name of the value to delete. */ public static void registryDeleteValue(HKEY root, String keyPath, String valueName) { HKEYByReference phkKey = new HKEYByReference(); int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ | WinNT.KEY_WRITE | WinNT.KEY_WOW64_32KEY, phkKey); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } try { registryDeleteValue(phkKey.getValue(), valueName); } finally { rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } } } /** * Get names of the registry key's sub-keys. * * @param hKey Registry key. * @return Array of registry key names. */ public static String[] registryGetKeys(HKEY hKey) { IntByReference lpcSubKeys = new IntByReference(); IntByReference lpcMaxSubKeyLen = new IntByReference(); int rc = Advapi32.INSTANCE.RegQueryInfoKey(hKey, null, null, null, lpcSubKeys, lpcMaxSubKeyLen, null, null, null, null, null, null); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } ArrayList<String> keys = new ArrayList<>(lpcSubKeys.getValue()); char[] name = new char[lpcMaxSubKeyLen.getValue() + 1]; for (int i = 0; i < lpcSubKeys.getValue(); i++) { IntByReference lpcchValueName = new IntByReference(lpcMaxSubKeyLen.getValue() + 1); rc = Advapi32.INSTANCE.RegEnumKeyEx(hKey, i, name, lpcchValueName, null, null, null, null); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } keys.add(Native.toString(name)); } return keys.toArray(new String[keys.size()]); } /** * Get names of the registry key's sub-keys. * * @param root Root key. * @param keyPath Path to a registry key. * @return Array of registry key names. */ public static String[] registryGetKeys(HKEY root, String keyPath) { HKEYByReference phkKey = new HKEYByReference(); int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ | WinNT.KEY_WOW64_32KEY, phkKey); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } try { return registryGetKeys(phkKey.getValue()); } finally { rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } } } /** * Get a table of registry values. * * @param hKey Registry key. * @return Table of values. */ public static TreeMap<String, Object> registryGetValues(HKEY hKey) { IntByReference lpcValues = new IntByReference(); IntByReference lpcMaxValueNameLen = new IntByReference(); IntByReference lpcMaxValueLen = new IntByReference(); int rc = Advapi32.INSTANCE.RegQueryInfoKey(hKey, null, null, null, null, null, null, lpcValues, lpcMaxValueNameLen, lpcMaxValueLen, null, null); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } TreeMap<String, Object> keyValues = new TreeMap<>(); char[] name = new char[lpcMaxValueNameLen.getValue() + 1]; byte[] data = new byte[lpcMaxValueLen.getValue()]; for (int i = 0; i < lpcValues.getValue(); i++) { IntByReference lpcchValueName = new IntByReference(lpcMaxValueNameLen.getValue() + 1); IntByReference lpcbData = new IntByReference(lpcMaxValueLen.getValue()); IntByReference lpType = new IntByReference(); rc = Advapi32.INSTANCE.RegEnumValue(hKey, i, name, lpcchValueName, null, lpType, data, lpcbData); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } String nameString = Native.toString(name); Memory byteData = new Memory(lpcbData.getValue()); byteData.write(0, data, 0, lpcbData.getValue()); switch (lpType.getValue()) { case WinNT.REG_DWORD: { keyValues.put(nameString, byteData.getInt(0)); break; } case WinNT.REG_SZ: case WinNT.REG_EXPAND_SZ: { keyValues.put(nameString, byteData.getString(0, true)); break; } case WinNT.REG_BINARY: { keyValues.put(nameString, byteData.getByteArray(0, lpcbData.getValue())); break; } case WinNT.REG_MULTI_SZ: { Memory stringData = new Memory(lpcbData.getValue()); stringData.write(0, data, 0, lpcbData.getValue()); ArrayList<String> result = new ArrayList<>(); int offset = 0; while (offset < stringData.size()) { String s = stringData.getString(offset, true); offset += s.length() * Native.WCHAR_SIZE; offset += Native.WCHAR_SIZE; result.add(s); } keyValues.put(nameString, result.toArray(new String[result.size()])); break; } default: throw new RuntimeException("Unsupported type: " + lpType.getValue()); } } return keyValues; } /** * Get a table of registry values. * * @param root Registry root. * @param keyPath Regitry key path. * @return Table of values. */ public static TreeMap<String, Object> registryGetValues(HKEY root, String keyPath) { HKEYByReference phkKey = new HKEYByReference(); int rc = Advapi32.INSTANCE.RegOpenKeyEx(root, keyPath, 0, WinNT.KEY_READ | WinNT.KEY_WOW64_32KEY, phkKey); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } try { return registryGetValues(phkKey.getValue()); } finally { rc = Advapi32.INSTANCE.RegCloseKey(phkKey.getValue()); if (rc != W32Errors.ERROR_SUCCESS) { throw new Win32Exception(rc); } } } /** * Converts a map of environment variables to an environment block suitable * for {@link Advapi32#CreateProcessAsUser}. This environment block consists * of null-terminated blocks of null-terminated strings. Each string is in * the following form: name=value\0 * * @param environment Environment variables * @return A environment block */ public static String getEnvironmentBlock(Map<String, String> environment) { StringBuilder out = new StringBuilder(); for (Entry<String, String> entry : environment.entrySet()) { if (entry.getValue() != null) { out.append(entry.getKey()).append("=").append(entry.getValue()).append("\0"); } } return out.toString() + "\0"; } /** * Event log types. */ public static enum EventLogType { Error, Warning, Informational, AuditSuccess, AuditFailure } /** * An event log record. */ public static class EventLogRecord { private EVENTLOGRECORD _record = null; private final String _source; private byte[] _data; private String[] _strings; /** * Raw record data. * * @return EVENTLOGRECORD. */ public EVENTLOGRECORD getRecord() { return _record; } /** * Event Id. * * @return Integer. */ public int getEventId() { return _record.EventID.intValue(); } /** * Event source. * * @return String. */ public String getSource() { return _source; } /** * Status code for the facility, part of the Event ID. * * @return Status code. */ public int getStatusCode() { return _record.EventID.intValue() & 0xFFFF; } /** * Record number of the record. This value can be used with the * EVENTLOG_SEEK_READ flag in the ReadEventLog function to begin reading * at a specified record. * * @return Integer. */ public int getRecordNumber() { return _record.RecordNumber.intValue(); } /** * Record length, with data. * * @return Number of bytes in the record including data. */ public int getLength() { return _record.Length.intValue(); } /** * Strings associated with this event. * * @return Array of strings or null. */ public String[] getStrings() { return _strings; } /** * Event log type. * * @return Event log type. */ public EventLogType getType() { switch (_record.EventType.intValue()) { case WinNT.EVENTLOG_SUCCESS: case WinNT.EVENTLOG_INFORMATION_TYPE: return EventLogType.Informational; case WinNT.EVENTLOG_AUDIT_FAILURE: return EventLogType.AuditFailure; case WinNT.EVENTLOG_AUDIT_SUCCESS: return EventLogType.AuditSuccess; case WinNT.EVENTLOG_ERROR_TYPE: return EventLogType.Error; case WinNT.EVENTLOG_WARNING_TYPE: return EventLogType.Warning; default: throw new RuntimeException("Invalid type: " + _record.EventType.intValue()); } } /** * Raw data associated with the record. * * @return Array of bytes or null. */ public byte[] getData() { return _data; } public EventLogRecord(Pointer pevlr) { _record = new EVENTLOGRECORD(pevlr); _source = pevlr.getString(_record.size(), true); // data if (_record.DataLength.intValue() > 0) { _data = pevlr.getByteArray(_record.DataOffset.intValue(), _record.DataLength.intValue()); } // strings if (_record.NumStrings.intValue() > 0) { ArrayList<String> strings = new ArrayList<>(); int count = _record.NumStrings.intValue(); long offset = _record.StringOffset.intValue(); while (count > 0) { String s = pevlr.getString(offset, true); strings.add(s); offset += s.length() * Native.WCHAR_SIZE; offset += Native.WCHAR_SIZE; count--; } _strings = strings.toArray(new String[strings.size()]); } } } }