package at.jta;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.ArrayList;
import java.io.File;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import java.io.FileOutputStream;
/********************************************************************************************************************************
*
* <p>Title: Class is 100% pur Java Registry handle</p>
*
* <p>Description: You can read, delete or create any key in the registry (when you have access rights).
* But you just can read/write and set string values! The java.dll doesnt provide any other feature.<br>
* <b>ATTENTION: Since version 3 you can also read/write dword, binary, expand and multi data - but this is implemented by calling
* the regedit executeable with parameters and temporary files - so it might not success or have a deadlock!!!</b></p>
*
* <p>Copyright: Copyright (c) 2008 - class is under GPL and LGPL</p>
*
* <p>Company: Taschek Joerg</p>
*
* @author <a href="mailto:joerg_t_p@gmx.at">Taschek Joerg</a>
* @version 2.0 22.03.2007 Methods are renamed and now called by the function they are implementing and the document is now in
* english, instead of german<br><br>
* @version 3.0 03.06.2008 Replaced all int Key values with Key class for storing the path and added new methods for
* reading/writing dword, binary, multi and expand values (these new methods are tested under XP SP2 and
* Vista Ultimate x64 with admin privliges and UCL turned off, so if there are any bugs with other windows
* version please submit it to me - or just to say thank you or to donate ;-))<br>
* All OLD methods are stil here and the start with _<br>
* @version 3.1 15.10.2008 extractAnyValue had a bug,when reading out items which goes over more lines (JTA)<br>
* @version 3.2 17.10.2008 added caching methods for caching many registry entries + values<br>
* @version 3.3 20.10.2008 found major bug in the method extractAnyValue - the method returned and value found with the name, not only
* for the right key<br>
* @version 3.4 21.10.2008 bug in the parseHexString method when you want to replace the 0 signs! It removed every 0 sign
* @released 21.10.2008 (internal release)
*******************************************************************************************************************************/
final public class Regor
{
/**
* the old handle to the HKEY_CLASSES_ROOT registry root node
*/
public static final int _HKEY_CLASSES_ROOT = 0x80000000;
/**
* the old handle to the HEKY_CURRENT_USER registry root node
*/
public static final int _HKEY_CURRENT_USER = 0x80000001;
/**
* the old handle to the HKEY_LOCAL_MACHINE registry root node
*/
public static final int _HKEY_LOCAL_MACHINE = 0x80000002;
/**
* the NEW handle to the HKEY_CLASSES_ROOT registry root node
*/
public static final Key HKEY_CLASSES_ROOT = new Key(_HKEY_CLASSES_ROOT, "HKEY_CLASSES_ROOT");
/**
* the NEW handle to the HEKY_CURRENT_USER registry root node
*/
public static final Key HKEY_CURRENT_USER = new Key(_HKEY_CURRENT_USER, "HKEY_CURRENT_USER");
/**
* the NEW handle to the HKEY_LOCAL_MACHINE registry root node
*/
public static final Key HKEY_LOCAL_MACHINE = new Key(_HKEY_LOCAL_MACHINE, "HKEY_LOCAL_MACHINE");
public static final int ERROR_SUCCESS = 0;
public static final int ERROR_FILE_NOT_FOUND = 2;
public static final int ERROR_ACCESS_DENIED = 5;
/* Constants used to interpret returns of native functions */
public static final int NATIVE_HANDLE = 0;
public static final int ERROR_CODE = 1;
public static final int SUBKEYS_NUMBER = 0;
public static final int VALUES_NUMBER = 2;
public static final int MAX_KEY_LENGTH = 3;
public static final int MAX_VALUE_NAME_LENGTH = 4;
/* Windows security masks */
/**
* Security Mask need by openKey - just for delete
*/
public static final int DELETE = 0x10000;
/**
* Security Mask need by openKey - just for querying values
*/
public static final int KEY_QUERY_VALUE = 1;
/**
* Security Mask need by openKey - just for setting values
*/
public static final int KEY_SET_VALUE = 2;
/**
* Security Mask need by openKey - for creating sub keys
*/
public static final int KEY_CREATE_SUB_KEY = 4;
/**
* Security Mask need by openKey - for enum sub keys
*/
public static final int KEY_ENUMERATE_SUB_KEYS = 8;
/**
* Security Mask need by openKey - for key reading
*/
public static final int KEY_READ = 0x20019;
/**
* Security Mask need by openKey - for writing keys
*/
public static final int KEY_WRITE = 0x20006;
/**
* Security Mask need by openKey - highest access to do everything (default access by openkey without security mask)
*/
public static final int KEY_ALL_ACCESS = 0xf003f;
private Method openKey = null;
private Method closeKey = null;
private Method delKey = null;
private Method createKey = null;
private Method flushKey = null;
private Method queryValue = null;
private Method setValue = null;
private Method delValue = null;
private Method queryInfoKey = null;
private Method enumKey = null;
private Method enumValue = null;
/**
* Needed to replace the entries in exported tmp registry file
*/
private static final String NULL_STRING = new String(new char[]{0});
/**
* Standard text for inserting in the registry - used for import dword, binary, multi and expand
*/
private static final String INIT_WINDOWS_STRING = "Windows Registry Editor Version 5.00";
/**
* Every binary entry starts with this (when exported or for the import)
*/
private static final String BINARY_KEY = "hex:";
/**
* Every dword entry starts with this, also used for import
*/
private static final String DWORD_KEY = "dword:";
/**
* Every multi string entry starts with this, also used for import
*/
private static final String MULTI_KEY = "hex(7):";
/**
* Every expand string entry starts with this, also used for import
*/
private static final String EXPAND_KEY = "hex(2):";
/**
* Time (milliseconds) for waiting for a file to grow (needed for caching and reading dword, binary, multi and expand values)
*/
public static int WAIT_FOR_FILE = 250;
/**
* List for cached registry entires
*/
private ArrayList caches;
/**
* If you want to use cached entries. The method readBinary, readDword, readExpand and readMulti just use caches (not readValue)
*/
private boolean useCache = false;
/******************************************************************************************************************************
* Constructor to handle with windows registry
* @throws RegistryErrorException throws an registryerrorException when its not able to get a handle to the registry methods
* @throws NotSupportedOSException throws an notSupportedOSException if the registry is not used in windows
*****************************************************************************************************************************/
public Regor() throws RegistryErrorException
{
checkOS();
initMethods();
}
/******************************************************************************************************************************
* Method checks either if its windows or anohter system (if not windows an exception is thrown) - just needed for internal checks
*****************************************************************************************************************************/
private void checkOS()
{
String str = System.getProperty("os.name");
if(str == null || str.toLowerCase().indexOf("windows") == -1)
throw new NotSupportedOSException("Operating system: " + str + " is not supported!");
}
////// DIRTY METHODS START HERE - THE METHODS DONT USE A DLL TO READ/WRITE ENTRIES, NO THE USE RUNTIME AND THE REGEDIT EXECUTABLE///
/**********************************************************************************************************************************
* Method saves any variable to the registry via the regedit.exe and runtime - because its java 1.4 compatbile (otherwhise
* it would be the processbuilder)
* @param path String the registy path (without [])
* @param valueName String the valuename to set
* @param type String the type (BINARY, DWORD, MULTI, EXPAND)
* @param data String the data which should be stored in the registry (it must be converted into the right format for the given type)
* @return boolean returns always true (otherwhise exceptio is thrown) - maybe better use in future
* @throws RegistryErrorException
*********************************************************************************************************************************/
private boolean saveAnyValue(String path, String valueName, String type, String data) throws RegistryErrorException
{
try{
File f = File.createTempFile("regorexp",".jta"); //creates tmp File for storing the registry key
//now writing the file for registry import
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f)));
bw.write(INIT_WINDOWS_STRING);
bw.newLine();
bw.newLine();
bw.write("[");
bw.write(path);
bw.write("]");
bw.newLine();
bw.write("\"");
bw.write(valueName);
bw.write("\"=");
bw.write(type);
bw.write(data);
bw.newLine();
bw.close();
//ATTENTION!! THESE COULD BE A DEADLOCK BECAUSE I WAITFOR THE END OF PROCESS HERE
Runtime.getRuntime().exec("regedit /s /i " + f.getAbsolutePath()).waitFor(); //<-- Waiting for END of Process
if(!f.delete()) //if delete has no success
f.deleteOnExit(); //mark it, for delete on exit
}
catch(Exception ex)
{
System.err.println(ex.getLocalizedMessage());
// ex.printStackTrace(System.out);
throw new RegistryErrorException(ex.getLocalizedMessage());
}
return true;
}
/**********************************************************************************************************************************
* Method extracts any variable from the registry via the regedit.exe and runtime - because its java 1.4 compatbile (otherwhise
* it would be the processbuilder)
* @param path String the registry path to the parent key
* @param valueName String the valuename which should be read from the registry key
* @return String null if the valuename is not found or the path could not be exported - otherwhise the data from the registry
* @throws RegistryErrorException
*********************************************************************************************************************************/
private String extractAnyValue(String path, String valueName) throws RegistryErrorException
{
try{
String tmp = getCachedValue(path, valueName);
if (tmp != null)
return tmp;
else if (useCache)
System.out.println("CACHED KEY: " + path + " AND VALUE NOT FOUND: " + valueName);
}
catch(NoEntryException nee) //has not this children
{
if(isCachingActive()) //only if caching is active
return null;
}
StringBuffer strRet = new StringBuffer(); //stringbuffer for appending, if an entry has multiplie lines
try{
File f = File.createTempFile("regorexp",".jta"); //creates tmp File for storing the registry key
//ATTENTION!! THESE COULD BE A DEADLOCK BECAUSE I WAITFOR THE END OF PROCESS HERE
Runtime.getRuntime().exec("regedit /e " + f.getAbsolutePath() + " \"" + path + "\"").waitFor(); //<-- WAITING FOR END OF PROCESS
_waitForFile(f); //wait until the file size is not increasing anymore
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
String line = "";
boolean lineFound = false, keyFound = false;
while ( ( line = br.readLine() ) != null)
{
line = line.replaceAll(NULL_STRING,"");
if(line.length() > 0)
{
if (keyFound || (line.startsWith("[") && line.endsWith("]")) )
{
if(line.startsWith("[") && line.endsWith("]"))
{
if(keyFound) //abort if new key starts
break;
else{
if(line.equals("[" + path + "]")) //if the line is the same then start searching for your value
keyFound = true;
}
}
else if(keyFound && ( lineFound || line.startsWith("\"" + valueName) && line.indexOf("=") != -1 ))
{
if(lineFound) //when line found, just append
{
if(line.length() > 0)
{
if (line.indexOf("=") != -1) //if = is found, this is a new item so abort
{
break;
}
//and append the line, if its for the same item
strRet.append(line.trim().replaceAll("\\\\", "")); //eliminate every \
if(!line.endsWith("\\")) //if line doesnt ends with \ the registry entry has no more lines
{
break;
}
}
}
else
{
line = line.substring(line.indexOf("=") + 1);
strRet.append(line.replaceAll("\\\\","")); //eliminate every \ also if there is none
lineFound = true;
if (line.indexOf("\\") == -1) //if no \\ is found, there is no new line in the string, so abort
{
break; //abort if no \ is found
}
}
}
}
}
}
br.close(); //close reader, so that you can delete the file
if(!f.delete()) //if delete has no success
f.deleteOnExit(); //mark it, for delete on exit
}
catch(Exception ex)
{
System.err.println(ex.getLocalizedMessage());
// ex.printStackTrace(System.out);
throw new RegistryErrorException(ex.getLocalizedMessage());
}
//if the buffer length is zero, return null
return strRet.length() == 0 ? null : strRet.toString();
}
/***********************************************************************************************************************************
* Method saves a binary entry for the given key, valuename and data
* @since version 3 (03.06.2008)
* @see <code>saveAnyValue</code> - method could have a deadlock
* @param key Key The parent key handle obtained by openKey
* @param valueName String the binary value name in the registry
* @param hexCommaData String the string converted in hexadecimal signs separated with commas.
* Use <code>String convertStringToHexComma(String plainString, false)</code> to get the hex comma separated data
* @throws RegistryErrorException
**********************************************************************************************************************************/
public void saveBinary(Key key, String valueName, String hexCommaData) throws RegistryErrorException
{
saveAnyValue(key.getPath(), valueName, BINARY_KEY, hexCommaData);
}
/**********************************************************************************************************************************
* Method reads from the registry a BINARY value - this is made via Runtime.getRuntime().exec(regedit) and is not one
* of the best methods, but at least it doesnt need a dll
* @since version 3 (03.06.2008 - guess who has birthday ;))
* @see <code>extractAnyValue</code> - method could have a deadlock
* @param key Key the obtained key from the registry
* @param valueName String the valueName of the binary entry which you want to read
* @return String null or the binary data separated by comma
* @throws RegistryErrorException
*********************************************************************************************************************************/
public String readBinary(Key key, String valueName) throws RegistryErrorException
{
if(key == null)
throw new NullPointerException("Registry key cannot be null");
if(valueName == null)
throw new NullPointerException("Valuename cannot be null, because the default value is always a STRING! If you want to read a String use readValue");
String ret = extractAnyValue(key.getPath(), valueName);
//if it is not null and it starts with hex: it is hopefully a binary entry
if(ret != null && ret.startsWith(BINARY_KEY))
{
return ret.substring(4);
}
return null;
}
/**********************************************************************************************************************************
* Method saves a dword entry in the registry
* @since version 3 (03.06.2008)
* @see <code>saveAnyValue</code> - method could have a deadlock
* @param key Key the parent key handle obtained by openKey
* @param valueName String the valuename of the dword entry
* @param hexData String a hexadecimal String withouth comma or spaces (use <code>Integer.toHexString()</code> to get a hex string)
* @throws RegistryErrorException
*********************************************************************************************************************************/
public void saveDword(Key key, String valueName, String hexData) throws RegistryErrorException
{
saveAnyValue(key.getPath(), valueName, DWORD_KEY, hexData);
}
/**********************************************************************************************************************************
* Method reads the dword entry from the registry
* @since version 3 (03.06.2008 - dont know who has birthday?)
* @see <code>extractAnyValue</code> - method could have a deadlock
* @param key Key the parent key handle obtained by openKey
* @param valueName String the dword value
* @return String the dword entry in a hex string
* @throws RegistryErrorException
*********************************************************************************************************************************/
public String readDword(Key key, String valueName) throws RegistryErrorException
{
if(key == null)
throw new NullPointerException("Registry key cannot be null");
if(valueName == null)
throw new NullPointerException("Valuename cannot be null, because the default value is always a STRING! If you want to read a String use readValue");
String ret = extractAnyValue(key.getPath(), valueName);
//if it is not null and it starts with hex: it is hopefully a binary entry
if(ret != null && ret.startsWith(DWORD_KEY))
{
return ret.substring(6);
}
return null;
}
/***********************************************************************************************************************************
* Method saves a multi string entry in the registry
* @since version 3 (03.06.2008)
* @see <code>saveAnyValue</code> - method could have a deadlock
* @param key Key the parent key handle obtained by openKey
* @param valueName String the multi value name
* @param hexCommaZeroData String the data to write converted in hex string separated by a comma with trailing zeros
* Use <code>String convertStringToHexComma(String plainString, true)</code> to get the hex comma separated data with 0 signs between
* @throws RegistryErrorException
**********************************************************************************************************************************/
public void saveMulti(Key key, String valueName, String hexCommaZeroData) throws RegistryErrorException
{
saveAnyValue(key.getPath(), valueName, MULTI_KEY, hexCommaZeroData);
}
/**********************************************************************************************************************************
* Method reads a multi string entry from the registry
* @since version 3 (03.06.2008 - my dad has birthday ;))
* @see <code>extractAnyValue</code> - method could have a deadlock
* @param key Key the parent key handle obtained by openKey
* @param valueName String the multi value name
* @return String the HEXADECIMAL values separated by comma (use <code>String parseHexString(String)</code> to convert it
* the line seperator is also a hex null! You have to parse it out
* @throws RegistryErrorException
*********************************************************************************************************************************/
public String readMulti(Key key, String valueName) throws RegistryErrorException
{
if(key == null)
throw new NullPointerException("Registry key cannot be null");
if(valueName == null)
throw new NullPointerException("Valuename cannot be null, because the default value is always a STRING! If you want to read a String use readValue");
String ret = extractAnyValue(key.getPath(), valueName);
//if it is not null and it starts with hex: it is hopefully a binary entry
if(ret != null && ret.startsWith(MULTI_KEY))
{
return ret.substring(7);
}
return null;
}
/**********************************************************************************************************************************
* Method saves an expand string entry
* @since version 3 (03.06.2008)
* @see <code>saveAnyValue</code> - method could have a deadlock
* @param key Key the parent key handle obtained by openKey
* @param valueName String the expand value name
* @param hexCommaZeroData String the data to write converted in hex string separated by a comma with trailing zeros
* Use <code>String convertStringToHexComma(String plainString, true)</code> to get the hex comma separated data with 0 signs between
* @throws RegistryErrorException
*********************************************************************************************************************************/
public void saveExpand(Key key, String valueName, String hexCommaZeroData) throws RegistryErrorException
{
saveAnyValue(key.getPath(), valueName, EXPAND_KEY, hexCommaZeroData);
}
/**********************************************************************************************************************************
* Method reads an expand string entry
* @since version 3 (03.06.2008)
* @see <code>extractAnyValue</code> - method could have a deadlock
* @param key Key the parent key handle obtained by openKey
* @param valueName String the expand value name
* @return String the HEXADECIMAL values separated by comma (use <code>String parseHexString(String)</code> to convert it
* @throws RegistryErrorException
*********************************************************************************************************************************/
public String readExpand(Key key, String valueName) throws RegistryErrorException
{
if(key == null)
throw new NullPointerException("Registry key cannot be null");
if(valueName == null)
throw new NullPointerException("Valuename cannot be null, because the default value is always a STRING! If you want to read a String use readValue");
String ret = extractAnyValue(key.getPath(), valueName);
//if it is not null and it starts with hex: it is hopefully a binary entry
if(ret != null && ret.startsWith(EXPAND_KEY))
{
return ret.substring(7);
}
return null;
}
////// DIRTY METHODS STOP HERE - THE METHODS DONT USE A DLL TO READ/WRITE ENTRIES, NO THE USE RUNTIME AND THE REGEDIT EXECUTABLE///
/******************************************************************************************************************************
* Reading every valueName (not only the string value) out of the registry handle (for maximum value index and maxValueNameLength
* use the getChildInformation method
* @param key the handle to the parent key obtained from openKey
* @param valueNameIndex the index of the valueName name - starting from 0 going to the maximum count from the getChildInformation
* stored in array index 2
* @param maxValueNameLength maximum length of valueName name (used because for memory allocating in the java.dll - if you obtain
* the size from getChildInformation increase the [4] int array by 1)
* @return byte[] either the name of the valueName or null if not found or an error occurs or if the maxValueNameLength is to short
* @throws RegistryErrorException
*****************************************************************************************************************************/
public byte[] enumValueName(Key key, int valueNameIndex, int maxValueNameLength) throws RegistryErrorException
{
return _enumValueName(key.getKey(), valueNameIndex, maxValueNameLength);
}
/******************************************************************************************************************************
* Reading every valueName (not only the string value) out of the registry handle (for maximum value index and maxValueNameLength
* use the getChildInformation method
* @param key the handle to the parent key obtained from openKey
* @param valueNameIndex the index of the valueName name - starting from 0 going to the maximum count from the getChildInformation
* stored in array index 2
* @param maxValueNameLength maximum length of valueName name (used because for memory allocating in the java.dll - if you obtain
* the size from getChildInformation increase the [4] int array by 1)
* @return byte[] either the name of the valueName or null if not found or an error occurs or if the maxValueNameLength is to short
* @throws RegistryErrorException
* @deprecated use <code>byte[] enumValueName(Key key, int valueNameIndex, int maxValueNameLength)</code> instead of
*****************************************************************************************************************************/
public byte[] _enumValueName(int key, int valueNameIndex, int maxValueNameLength) throws RegistryErrorException
{
try
{
return (byte[])enumValue.invoke(null, new Object[] {new Integer(key), new Integer(valueNameIndex), new Integer(maxValueNameLength)});
}
catch (InvocationTargetException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
catch (IllegalArgumentException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
catch (IllegalAccessException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
}
/*****************************************************************************************************************************
* Returns every valueName (not only the String value names)
* @param key either one of the root nodes or a key obtained from openKey
* @param subkey a string to a subkey - if the subkey is empty or null the information will be obtained from the given key
* @return List on success and found a filled list with strings will be returned - on error or nothing found null will be returned
* @throws RegistryErrorException
****************************************************************************************************************************/
public List listValueNames(Key key, String subkey) throws RegistryErrorException
{
return _listValueNames(key.getKey(), subkey);
}
/*****************************************************************************************************************************
* Returns every valueName (not only the String value names)
* @param key either one of the root nodes or a key obtained from openKey
* @return List on success and found a filled list with strings will be returned - on error or nothing found null will be returned
* @throws RegistryErrorException
****************************************************************************************************************************/
public List listValueNames(Key key) throws RegistryErrorException
{
return listValueNames(key,null);
}
/*****************************************************************************************************************************
* Returns every valueName (not only the String value names)
* @param key either one of the root nodes or a key obtained from openKey
* @param subkey a string to a subkey - if the subkey is empty or null the information will be obtained from the given key
* @return List on success and found a filled list with strings will be returned - on error or nothing found null will be returned
* @throws RegistryErrorException
* @deprecated use <code>List listValueNames(Key key, String subkey)</code> instead of
****************************************************************************************************************************/
public List _listValueNames(int key, String subkey) throws RegistryErrorException
{
int handle = -1;
try{
handle = _openKey(key, subkey, KEY_READ); //just reading priv
if(handle != -1)
{
int info[] = _getChildInformation(handle); //obtain the informations
if(info != null && info[0] != -1)
{
List ret = new ArrayList();
for(int x = 0; x != info[2]; x++)
{
String tmp = parseValue(_enumValueName(handle,x,info[4] + 1));
if(tmp != null) //just if not null, maybe there are no valueNames
ret.add(tmp);
}
return ret.isEmpty() ? null : ret;
}
}
}
catch(RegistryErrorException ex)
{
throw ex;
}
catch(Exception ex)
{
throw new RegistryErrorException(ex.getMessage());
}
finally{
_closeKey(handle);
}
return null;
}
/*****************************************************************************************************************************
* Returns every valueName (not only the String value names)
* @param key either one of the root nodes or a key obtained from openKey
* @return List on success and found a filled list with strings will be returned - on error or nothing found null will be returned
* @throws RegistryErrorException
* @deprecated use <code>List listValueNames(Key key)</code> instead of
****************************************************************************************************************************/
public List _listValueNames(int key) throws RegistryErrorException
{
return _listValueNames(key,null);
}
/******************************************************************************************************************************
* Reading the subkey name out of the registry (to obtain the count and the maxKeyNameLength use <code>getChildInformation</code>
* method
* @param key the handle to the key obtained by openKey
* @param subkeyIndex index from the subkey from which you want to obtain the name (start with 0 - the maximum count you get from
* getChildInformation method in array [0])
* @param maxKeyNameLength the maximum length of a subkey name (used because for memory allocating in the java.dll - if you obtain
* the size from getChildInformation increase the [3] int array by 1 )
* @return byte[] on error or not found or the maxKeyNameLength is to short it will returns null, on success the name of the subkey
* @throws RegistryErrorException
*****************************************************************************************************************************/
public byte[] enumKeys(Key key, int subkeyIndex, int maxKeyNameLength) throws RegistryErrorException
{
return _enumKeys(key.getKey(), subkeyIndex, maxKeyNameLength);
}
/******************************************************************************************************************************
* Reading the subkey name out of the registry (to obtain the count and the maxKeyNameLength use <code>getChildInformation</code>
* method
* @param key the handle to the key obtained by openKey
* @param subkeyIndex index from the subkey from which you want to obtain the name (start with 0 - the maximum count you get from
* getChildInformation method in array [0])
* @param maxKeyNameLength the maximum length of a subkey name (used because for memory allocating in the java.dll - if you obtain
* the size from getChildInformation increase the [3] int array by 1 )
* @return byte[] on error or not found or the maxKeyNameLength is to short it will returns null, on success the name of the subkey
* @throws RegistryErrorException
* @deprecated use <code>byte[] enumKeys(Key key, int subkexindex, int maxKeyNameLength)</code> instead of
*****************************************************************************************************************************/
public byte[] _enumKeys(int key, int subkeyIndex, int maxKeyNameLength) throws RegistryErrorException
{
try
{
return (byte[])enumKey.invoke(null, new Object[] {new Integer(key), new Integer(subkeyIndex), new Integer(maxKeyNameLength)});
}
catch (InvocationTargetException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
catch (IllegalArgumentException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
catch (IllegalAccessException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
}
/******************************************************************************************************************************
* Returns all subkeys from the given key and subkey
* @param key either one of the root nodes or a key obtained from openKey
* @param subkey a string to a subkey - if the subkey is empty or null the information will be obtained from the given key
* @return List on success and found a filled list with strings will be returned - on error or nothing found null will be returned
* @throws RegistryErrorException
*****************************************************************************************************************************/
public List listKeys(Key key, String subkey) throws RegistryErrorException
{
return _listKeys(key.getKey(), subkey);
}
/*****************************************************************************************************************************
* Returns all subkeys from the given key
* @param key either one of the root nodes or a key obtained from openKey
* @return List on success and found a filled list with strings will be returned - on error or nothing found null will be returned
* @throws RegistryErrorException
****************************************************************************************************************************/
public List listKeys(Key key) throws RegistryErrorException
{
return listKeys(key,null);
}
/******************************************************************************************************************************
* Returns all subkeys from the given key and subkey
* @param key either one of the root nodes or a key obtained from openKey
* @param subkey a string to a subkey - if the subkey is empty or null the information will be obtained from the given key
* @return List on success and found a filled list with strings will be returned - on error or nothing found null will be returned
* @throws RegistryErrorException
* @deprecated use <code>List listKeys(Key key, String subkey)</code> instead of
*****************************************************************************************************************************/
public List _listKeys(int key, String subkey) throws RegistryErrorException
{
int handle = -1;
try{
handle = _openKey(key, subkey, KEY_READ); //just reading priv
if(handle != -1)
{
int info[] = _getChildInformation(handle); //obtain the informations
if(info != null && info[0] != -1)
{
List ret = new ArrayList();
for(int x = 0; x != info[0]; x++)
{
String tmp = parseValue(_enumKeys(handle,x,info[3] + 1));
if(tmp != null) //just if not null, maybe there are no valueNames
ret.add(tmp);
}
return ret.isEmpty() ? null : ret;
}
}
}
catch(RegistryErrorException ex)
{
throw ex;
}
catch(Exception ex)
{
throw new RegistryErrorException(ex.getMessage());
}
finally{
_closeKey(handle);
}
return null;
}
/*****************************************************************************************************************************
* Returns all subkeys from the given key
* @param key either one of the root nodes or a key obtained from openKey
* @return List on success and found a filled list with strings will be returned - on error or nothing found null will be returned
* @throws RegistryErrorException
* @deprecated use <code>List listKeys(Key key)</code> instead of
****************************************************************************************************************************/
public List _listKeys(int key) throws RegistryErrorException
{
return _listKeys(key,null);
}
/******************************************************************************************************************************
* Reads information about the current opened key (use it when you want to enumKey or enumValueName to determine the maximum
* key length and the count of keys)
* @param key the key which you obtained from openKey
* @return int[0] the count of the subkeys,[2] count of valuenames,
* [3] the maximum length of a subkey! the maximum length of valuename is stored in[4]
* (for other operations you should increase the [3] or [4] value by 1 because of the terminating \0 in C - because you handle
* with the java.dll)
* if nothing found or illegal key, the values are -1 of the array (at index 1 the value would be 6 the other -1)
* @throws RegistryErrorException
*****************************************************************************************************************************/
public int[] getChildInformation(Key key) throws RegistryErrorException
{
return _getChildInformation(key.getKey());
}
/******************************************************************************************************************************
* Reads information about the current opened key (use it when you want to enumKey or enumValueName to determine the maximum
* key length and the count of keys)
* @param key the key which you obtained from openKey
* @return int[0] the count of the subkeys,[2] count of valuenames,
* [3] the maximum length of a subkey! the maximum length of valuename is stored in[4]
* (for other operations you should increase the [3] or [4] value by 1 because of the terminating \0 in C - because you handle
* with the java.dll)
* if nothing found or illegal key, the values are -1 of the array (at index 1 the value would be 6 the other -1)
* @throws RegistryErrorException
* @deprecated use <code>int[] getChildInformation(Key key)</code> instead of
*****************************************************************************************************************************/
public int[] _getChildInformation(int key) throws RegistryErrorException
{
try
{
return (int[])queryInfoKey.invoke(null, new Object[] {new Integer(key)});
}
catch (InvocationTargetException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
catch (IllegalArgumentException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
catch (IllegalAccessException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
}
/******************************************************************************************************************************
* Method deletes the specified value (YOU CAN ALSO DELETE BINARY, DWORD, MULTI OR EXPAND ENTRIES!!!)
* @param key the key obtained by openKey
* @param valueName name of String value you want to delete (if the string is empty or null the default entry will be
* deleted)
* @return int
* @throws RegistryErrorException
*****************************************************************************************************************************/
public int delValue(Key key, String valueName) throws RegistryErrorException
{
return _delValue(key.getKey(), valueName);
}
/******************************************************************************************************************************
* Method deletes the specified value (YOU CAN ALSO DELETE BINARY, DWORD, MULTI OR EXPAND ENTRIES!!!)
* @param key the key obtained by openKey
* @param valueName name of String value you want to delete (if the string is empty or null the default entry will be
* deleted)
* @return int
* @throws RegistryErrorException
* @deprecated use <code>int delValue(Key key, String valueName)</code> instead of
*****************************************************************************************************************************/
public int _delValue(int key, String valueName) throws RegistryErrorException
{
try
{
Integer ret = (Integer)delValue.invoke(null, new Object[] {new Integer(key), getString(valueName)});
if(ret != null)
return ret.intValue();
else
return -1;
}
catch (InvocationTargetException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
catch (IllegalArgumentException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
catch (IllegalAccessException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
}
/******************************************************************************************************************************
* Method set the specified string value (DO NOT USE THIS METHOD FOR READING BINARY, DWORD, MULTI OR EXPAND ENTRIES - JUST
* FOR SZ - STRING ENTRIES!!!)
* Methode setzt (oder erstellt) einen Wert auf eine Zeichenfolge
* Will man den defaulteintrag ndern, so muss man valueName "" ergeben
* @param key obtained by openKey
* @param valueName the string value name in the registry you want to set
* @param value the new value you want to set
* @return on success, return is ERROR_SUCCESS if not -1 or sth else will be returned
* @throws RegistryErrorException
*****************************************************************************************************************************/
public int setValue(Key key,String valueName, String value) throws RegistryErrorException
{
return _setValue(key.getKey(), valueName, value);
}
/******************************************************************************************************************************
* Method set the specified string value (DO NOT USE THIS METHOD FOR READING BINARY, DWORD, MULTI OR EXPAND ENTRIES - JUST
* FOR SZ - STRING ENTRIES!!!)
* Methode setzt (oder erstellt) einen Wert auf eine Zeichenfolge
* Will man den defaulteintrag ndern, so muss man valueName "" bergeben
* @param key obtained by openKey
* @param valueName the string value name in the registry you want to set
* @param value the new value you want to set
* @return on success, return is ERROR_SUCCESS if not -1 or sth else will be returned
* @throws RegistryErrorException
* @deprecated use <code>int setValue(Key key, String valueName, String value)</code> instead of
*****************************************************************************************************************************/
public int _setValue(int key,String valueName, String value) throws RegistryErrorException
{
try
{
Integer ret = (Integer)setValue.invoke(null, new Object[] {new Integer(key), getString(valueName), getString(value)});
if(ret != null)
return ret.intValue();
else
return -1;
}
catch (InvocationTargetException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
catch (IllegalArgumentException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
catch (IllegalAccessException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
}
/******************************************************************************************************************************
* Reads the value of a string value (DO NOT USE THIS METHOD FOR READING BINARY, DWORD, MULTI OR EXPAND ENTRIES - JUST
* FOR SZ - STRING ENTRIES!!!)
* @param key obtained from openKey
* @param valueName the string value which you want to read (if you want to obtain the default entry the valueName should be
* empty or NULL)
* @return byte[] if found the data in the string value will be returned (to get a string use the class method parseValue(byte[]))
* on error NULL will be returned
* @throws RegistryErrorException
*****************************************************************************************************************************/
public byte[] readValue(Key key, String valueName) throws RegistryErrorException
{
return _readValue(key.getKey(), valueName);
}
/******************************************************************************************************************************
* Reads the value of a string value (DO NOT USE THIS METHOD FOR READING BINARY, DWORD, MULTI OR EXPAND ENTRIES - JUST
* FOR SZ - STRING ENTRIES!!!)
* @param key obtained from openKey
* @param valueName the string value which you want to read (if you want to obtain the default entry the valueName should be
* empty or NULL)
* @return byte[] if found the data in the string value will be returned (to get a string use the class method parseValue(byte[]))
* on error NULL will be returned
* @throws RegistryErrorException
* @deprecated use <code>byte[] readValue(Key key, String valueName)</code> instead of
*****************************************************************************************************************************/
public byte[] _readValue(int key, String valueName) throws RegistryErrorException
{
try
{
byte ret[] = (byte[])queryValue.invoke(null, new Object[] {new Integer(key), getString(valueName)});
return ret;
}
catch (InvocationTargetException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
catch (IllegalArgumentException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
catch (IllegalAccessException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
}
/******************************************************************************************************************************
* Flush method - dont know what the method exactly does just implemented because i found it in the java sun source
* @param key obtained the key from openKey
* @return on success, ERROR_SUCESS will be returned! on error -1 or sth else
* @throws RegistryErrorException
*****************************************************************************************************************************/
public int flushKey(Key key) throws RegistryErrorException
{
return _flushKey(key.getKey());
}
/******************************************************************************************************************************
* Flush method - dont know what the method exactly does just implemented because i found it in the java sun source
* @param key obtained the key from openKey
* @return on success, ERROR_SUCESS will be returned! on error -1 or sth else
* @throws RegistryErrorException
* @deprecated use <code>int flushKey(Key key)</code> instead of
*****************************************************************************************************************************/
public int _flushKey(int key) throws RegistryErrorException
{
try
{
Integer ret = (Integer)flushKey.invoke(null, new Object[] {new Integer(key)});
if(ret != null)
return ret.intValue();
else
return -1;
}
catch (InvocationTargetException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
catch (IllegalArgumentException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
catch (IllegalAccessException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
}
/******************************************************************************************************************************
* deletes a key/subkey from the registry
* @param key the parent key obtained by openKey
* @param subkey the key name you want to delete
* @return int ERROR_SUCCESS wenn erfolgreich
* @throws RegistryErrorException if subkey is empty or null or any other exception occurs
*****************************************************************************************************************************/
public int delKey(Key key, String subkey) throws RegistryErrorException
{
return _delKey(key.getKey(), subkey);
}
/******************************************************************************************************************************
* deletes a key/subkey from the registry
* @param key the parent key obtained by openKey
* @param subkey the key name you want to delete
* @return int ERROR_SUCCESS wenn erfolgreich
* @throws RegistryErrorException if subkey is empty or null or any other exception occurs
* @deprecated use <code>int delKey(Key key, String subkey)</code> instead of
*****************************************************************************************************************************/
public int _delKey(int key, String subkey) throws RegistryErrorException
{
if(subkey == null || subkey.length() == 0)
throw new RegistryErrorException("subkey cannot be null");
try
{
Integer ret = (Integer)delKey.invoke(null, new Object[] {new Integer(key), getString(subkey)});
if(ret != null)
return ret.intValue();
else
return -1;
}
catch (InvocationTargetException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
catch (IllegalArgumentException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
catch (IllegalAccessException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
}
/******************************************************************************************************************************
* Create new key/subkey in the registry with the specified name
* Attentition: if the key is successfully returned, you should close and open the key again, because the obtained key
* doesnt have a high access level (so maybe creating or deleting a key/value wouldn't be successful)
* @param key handle to parent key obtained from openKey
* @param subkey name of the key/subkey you want to create
* @return on success the handle to the new key will be returned, otherwhise it will be null
* @throws RegistryErrorException
*****************************************************************************************************************************/
public Key createKey(Key key, String subkey) throws RegistryErrorException
{
int tmpKey = _createKey(key.getKey(), subkey);
if(tmpKey == -1)
return null;
else
return new Key(key, tmpKey, subkey);
}
/******************************************************************************************************************************
* Create new key/subkey in the registry with the specified name
* Attentition: if the key is successfully returned, you should close and open the key again, because the obtained key
* doesnt have a high access level (so maybe creating or deleting a key/value wouldn't be successful)
* @param key handle to parent key obtained from openKey
* @param subkey name of the key/subkey you want to create
* @return on success the handle to the new key will be returned, otherwhise it will be -1
* @throws RegistryErrorException
* @deprecated use <code>Key createKey(Key key, String subkey)</code> instead of
*****************************************************************************************************************************/
public int _createKey(int key, String subkey) throws RegistryErrorException
{
try
{
int result[] = (int[])createKey.invoke(null, new Object[] {new Integer(key), getString(subkey)});
if(result[ERROR_CODE] == ERROR_SUCCESS)
return result[NATIVE_HANDLE];
else
return -1;
}
catch (InvocationTargetException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
catch (IllegalArgumentException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
catch (IllegalAccessException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
}
/*****************************************************************************************************************************
* Close an obtained key for right usage
* @param key the key handle
* @return int on error it will be -1
* @throws RegistryErrorException
****************************************************************************************************************************/
public int closeKey(Key key) throws RegistryErrorException
{
return _closeKey(key.getKey());
}
/*****************************************************************************************************************************
* Close an obtained key for right usage
* @param key the key handle
* @return int on error it will be -1
* @throws RegistryErrorException
* @deprecated use <code>closeKey(Key key)</code> instead of
****************************************************************************************************************************/
public int _closeKey(int key) throws RegistryErrorException
{
try
{
Integer ret = (Integer)closeKey.invoke(null, new Object[] {new Integer(key)});
if(ret != null)
return ret.intValue();
else
return -1;
}
catch (InvocationTargetException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
catch (IllegalArgumentException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
catch (IllegalAccessException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
}
/******************************************************************************************************************************
* Opens a registry key
* @param key one of the registry root nodes - either HKEY_CLASSES_ROOT, HKEY_CURRENT_USER or HKEY_LOCAL_MACHINE
* @param subkey the name of the key/subkey like SOFTWARE or HARDWARE - for subkeys use the \\ as delimiter f.e. : SOFTWARE\\MICROSOFT
* if subkey name is "" or null it returns the handle to the root node
* @param security_mask the security mask to handle with the opened key (see security mask doc at the begin for detailed information)
* @return Key on NULL (when not found or not allowed) otherwhise the handle to the obtained key (in the Key Object)
* @throws RegistryErrorException
*****************************************************************************************************************************/
public Key openKey(Key key, String subkey, int security_mask) throws RegistryErrorException
{
int tmpKey = _openKey(key.getKey(), subkey, security_mask);
if(tmpKey == -1)
return null;
else
return new Key(key, tmpKey, subkey);
}
/******************************************************************************************************************************
* Opens a registry key
* @param key one of the registry root nodes - either HKEY_CLASSES_ROOT, HKEY_CURRENT_USER or HKEY_LOCAL_MACHINE
* @param subkey the name of the key/subkey like SOFTWARE or HARDWARE - for subkeys use the \\ as delimiter f.e. : SOFTWARE\\MICROSOFT
* if subkey name is "" or null it returns the handle to the root node
* @return Key null if not found or not allowed (attention here this methods allways uses the KEY_ALL_ACCESS security mask)
* on success the handle to key will be returned
* @throws RegistryErrorException
*****************************************************************************************************************************/
public Key openKey(Key key, String subkey) throws RegistryErrorException
{
return openKey(key,subkey,KEY_ALL_ACCESS);
}
/******************************************************************************************************************************
* Opens a registry key
* @param key one of the registry root nodes - either HKEY_CLASSES_ROOT, HKEY_CURRENT_USER or HKEY_LOCAL_MACHINE
* @param subkey the name of the key/subkey like SOFTWARE or HARDWARE - for subkeys use the \\ as delimiter f.e. : SOFTWARE\\MICROSOFT
* if subkey name is "" or null it returns the handle to the root node
* @param security_mask the security mask to handle with the opened key (see security mask doc at the begin for detailed information)
* @return int on error -1 (when not found or not allowed) otherwhise the handle to the obtained key
* @throws RegistryErrorException
* @deprecated use <code>openKey(Key key, String subkey, int security_mask)</code> instead of
*****************************************************************************************************************************/
public int _openKey(int key, String subkey, int security_mask) throws RegistryErrorException
{
try
{
int[] result = (int[])openKey.invoke(null, new Object[]{new Integer(key),getString(subkey),new Integer(security_mask)});
if(result == null || result[ERROR_CODE] != ERROR_SUCCESS)
return -1;
else
return result[NATIVE_HANDLE];
}
catch (InvocationTargetException ex1)
{
throw new RegistryErrorException(ex1.getMessage());
}
catch (IllegalArgumentException ex1)
{
throw new RegistryErrorException(ex1.getMessage());
}
catch (IllegalAccessException ex1)
{
throw new RegistryErrorException(ex1.getMessage());
}
}
/******************************************************************************************************************************
* Opens a registry key
* @param key one of the registry root nodes - either HKEY_CLASSES_ROOT, HKEY_CURRENT_USER or HKEY_LOCAL_MACHINE
* @param subkey the name of the key/subkey like SOFTWARE or HARDWARE - for subkeys use the \\ as delimiter f.e. : SOFTWARE\\MICROSOFT
* if subkey name is "" or null it returns the handle to the root node
* @return int -1 if not found or not allowed (attention here this methods allways uses the KEY_ALL_ACCESS security mask)
* on success the handle to key will be returned
* @throws RegistryErrorException
* @deprecated use <code>openKey(Key key, String subkey)</code> instead of
*****************************************************************************************************************************/
public int _openKey(int key, String subkey) throws RegistryErrorException
{
return _openKey(key,subkey,KEY_ALL_ACCESS);
}
/******************************************************************************************************************************
* Intern method which adds the trailing \0 for the handle with java.dll
* @param str String
* @return byte[]
*****************************************************************************************************************************/
private byte[] getString(String str)
{
if(str == null)
str = "";
return (str += "\0").getBytes();
}
/******************************************************************************************************************************
* Method removes the trailing \0 which is returned from the java.dll (just if the last sign is a \0)
* @param buf the byte[] buffer which every read method returns
* @return String a parsed string without the trailing \0
*****************************************************************************************************************************/
public static String parseValue(byte buf[])
{
if(buf == null)
return null;
String ret = new String(buf);
if(ret.charAt(ret.length() - 1) == '\0')
return ret.substring(0,ret.length() - 1);
return ret;
}
/**********************************************************************************************************************************
* Method converts a hex given String (separated by comma) into a string
* For Multi entries, every entry ends with HEX 0 so you can split the lines
* @param hexCommaString String
* @param deleteNullSigns boolean if you want to remove every 0 sign (delete null signs is needed for multi and expand entries,
* but not for binary
* @return String
*********************************************************************************************************************************/
public static String parseHexString(String hexCommaString, boolean deleteNullSigns)
{
if(hexCommaString == null || hexCommaString.trim().length() == 0)
return hexCommaString;
String items[] = hexCommaString.split(",");
//if no comma was found, return the given string
if(items == null || items.length == 0)
return hexCommaString;
StringBuffer strRet = new StringBuffer();
for(int x = 0; items != null && x != items.length; x++)
{
char sign = (char)Integer.parseInt(items[x], 16);
if(!deleteNullSigns || (deleteNullSigns && sign != 0) || x % 2 == 0) //dont delete every 0, just every 2nd step
strRet.append(sign);
}
//if i should delete 0 sign and the last sign is a hex 0 remove it!
if(deleteNullSigns && strRet.charAt(strRet.length() - 1) == 0)
strRet.deleteCharAt(strRet.length() - 1);
return strRet.toString();
}
/***********************************************************************************************************************************
* Method converts a plain String into a hex comma separated String with 0's between
* @param plain String
* @param appendNullSigns boolean if you want to add null signs (needed for multi and expand entries, but not for binary entry)
* @return String the converted string
**********************************************************************************************************************************/
public static String convertStringToHexComma(String plain, boolean appendNullSigns)
{
if(plain == null || plain.trim().length() == 0)
return plain;
StringBuffer strBuf = new StringBuffer();
for(int x = 0; x != plain.length(); x++)
{
if(x > 0)
strBuf.append(",");
strBuf.append(Integer.toHexString(plain.charAt(x)));
if(appendNullSigns)
strBuf.append(",00"); //this is needed, dunno why by the multi and expand string entries, but not for the binary
}
return strBuf.toString();
}
/******************************************************************************************************************************
* intern method which obtain the methods via reflection from the java.util.prefs.WindowPreferences (tested with java 1.4, 1.5
* and java 1.6)
* @throws RegistryErrorException exception is thrown if any method is not found or if the class is not found
*****************************************************************************************************************************/
private void initMethods() throws RegistryErrorException
{
Class clazz = null;
try
{
clazz = Class.forName("java.util.prefs.WindowsPreferences"); //you cannot access the class directly, cause its private
Method ms[] = clazz.getDeclaredMethods();
if(ms == null)
throw new RegistryErrorException("Cannot access java.util.prefs.WindowsPreferences class!");
//researching all methods to load it into the reflection methods
for(int x = 0; x != ms.length; x++)
{
if(ms[x] != null)
{
if(ms[x].getName().equals("WindowsRegOpenKey"))
{
openKey = ms[x];
openKey.setAccessible(true); //set Access for private
}
else if(ms[x].getName().equals("WindowsRegCloseKey"))
{
closeKey = ms[x];
closeKey.setAccessible(true);
}
else if(ms[x].getName().equals("WindowsRegCreateKeyEx"))
{
createKey = ms[x];
createKey.setAccessible(true);
}
else if(ms[x].getName().equals("WindowsRegDeleteKey"))
{
delKey = ms[x];
delKey.setAccessible(true);
}
else if(ms[x].getName().equals("WindowsRegFlushKey"))
{
flushKey = ms[x];
flushKey.setAccessible(true);
}
else if(ms[x].getName().equals("WindowsRegQueryValueEx"))
{
queryValue = ms[x];
queryValue.setAccessible(true);
}
else if(ms[x].getName().equals("WindowsRegSetValueEx"))
{
setValue = ms[x];
setValue.setAccessible(true);
}
else if(ms[x].getName().equals("WindowsRegDeleteValue"))
{
delValue = ms[x];
delValue.setAccessible(true);
}
else if(ms[x].getName().equals("WindowsRegQueryInfoKey"))
{
queryInfoKey = ms[x];
queryInfoKey.setAccessible(true);
}
else if(ms[x].getName().equals("WindowsRegEnumKeyEx"))
{
enumKey = ms[x];
enumKey.setAccessible(true);
}
else if(ms[x].getName().equals("WindowsRegEnumValue"))
{
enumValue = ms[x];
enumValue.setAccessible(true);
}
}
}
}
catch (ClassNotFoundException ex)
{
throw new RegistryErrorException(ex.getMessage());
}
}
///// caching methods starting here ////
/**********************************************************************************************************************************
* Method caches a complete key + 1 subkey
* @param key Key the registry key which should be cached + subchildren
* @throws RegistryErrorException
*********************************************************************************************************************************/
public void cacheKeys(Key key) throws RegistryErrorException
{
cacheKeys(key, 1);
}
/**********************************************************************************************************************************
* Method caches a complete key tree (so the key + subchildren)
* @param key Key the registry key which should be cached + subchildren
* @param maximumChildren int amount of the subchildren which should be cached (attention, this may create a java.lang.OutofMemory
* Error if you have not enoguth memory use -Xmx512M or sth)
* @throws RegistryErrorException
*********************************************************************************************************************************/
public void cacheKeys(Key key, int maximumChildren) throws RegistryErrorException
{
if(key == null)
throw new NullPointerException("Registry key cannot be null");
cacheKeys(key.getPath(), maximumChildren);
}
/**********************************************************************************************************************************
* Method caches a complete key tree (so the key + subchildren)
* @param key String the registry key which should be cached + subchildren
* @param maximumChildren int amount of the subchildren which should be cached (attention, this may create a java.lang.OutofMemory
* Error if you have not enoguth memory use -Xmx512M or sth)
* @throws RegistryErrorException
*********************************************************************************************************************************/
private void cacheKeys(String key, int maximumChildren) throws RegistryErrorException
{
StringBuffer strRet = new StringBuffer(); //stringbuffer for appending, if an entry has multiplie lines
try{
File f = File.createTempFile("regorexp",".jta"); //creates tmp File for storing the registry key
// long stamp1 = System.currentTimeMillis();
//ATTENTION!! THESE COULD BE A DEADLOCK BECAUSE I WAITFOR THE END OF PROCESS HERE
Runtime.getRuntime().exec("regedit /e " + f.getAbsolutePath() + " \"" + key + "\"").waitFor(); //<-- WAITING FOR END OF PROCESS
_waitForFile(f); //wait until the file size is not increasing anymore
// System.out.println(">>> NEEDED: " + (System.currentTimeMillis() - stamp1) + " " + f.getAbsolutePath());
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
String line = "";
CachedEntry entry = new CachedEntry(), currentEntry = null;
CachedValue currentValue = null;
entry.setKey(key);
while ( ( line = br.readLine() ) != null)
{
line = line.replaceAll(NULL_STRING,""); //remove illegale signs
if(line != null && line.length() > 0)
{
if(line.startsWith("[") && line.endsWith("]")) //
{
if(currentEntry != null) //if there was a key
{
Object tmp[] = entry.getSub(currentEntry.getKey());
if(tmp != null)
{
//just append the data if the maximumchildren is not higher as given
if ( ( (Integer) tmp[1]).intValue() < maximumChildren)
((CachedEntry)tmp[0]).appendChildren(currentEntry);
}
currentEntry = null;
}
String currentKey = line.substring(1, line.length() - 1); //gets the current key
//if not null and bigger than 0 and if is not the main key
if(currentKey != null && currentKey.length() > 0)
{
//when it is the main key, then you should store it settings at the main key
if (currentKey.equals(entry.getKey()))
currentEntry = entry;
else
{
currentEntry = new CachedEntry();
currentEntry.setKey(currentKey);
}
}
}
//if currentEntry is opened and either equals is in the line or it is more than one line
else if(currentEntry != null && (line.indexOf("=") != -1 || currentValue != null))
{
if(currentValue != null) //when line found, just append
{
if(line.length() > 0)
{
if (line.indexOf("=") != -1) //if = is found, this is a new item so abort
{
currentValue.setData(strRet.toString());
// currentValue.setData(parseData(strRet.toString()));
strRet.delete(0, strRet.length());
currentEntry.appendEntry(currentValue);
currentValue = null;
}
else //and append the line, if its for the same item
{
line = line.trim();
if(line.endsWith("\\"))
strRet.append(line.substring(0, line.length() - 1));
else
{
strRet.append(line.trim());
// }
// if (!line.endsWith("\\")) //if line doesnt ends with \ the registry entry has no more lines
// {
currentValue.setData(strRet.toString());
// currentValue.setData(parseData(strRet.toString()));
strRet.delete(0, strRet.length());
currentEntry.appendEntry(currentValue);
currentValue = null;
}
}
}
}
else
{
String currentName = line.substring(0,line.indexOf("="));
//default name
if(currentName.equals("@"))
currentName = "";
currentValue = new CachedValue();
currentValue.setName(currentName.replaceAll("\"",""));
line = line.substring(line.indexOf("=") + 1);
if(line.endsWith("\\"))
strRet.append(line.substring(0, line.length() - 1));
else
{
strRet.append(line);
// }
// if (line.indexOf("\\") == -1) //if no \\ is found, there is no new line in the string, so abort
// {
currentValue.setData(strRet.toString());
// currentValue.setData(parseData(strRet.toString()));
strRet.delete(0, strRet.length());
currentEntry.appendEntry(currentValue);
currentValue = null;
}
}
}
}
}
if(currentEntry != null) //if there was a key
{
Object tmp[] = entry.getSub(currentEntry.getKey());
if(tmp != null)
{
//just append the data if the maximumchildren is not higher as given
if ( ( (Integer) tmp[1]).intValue() < maximumChildren)
( (CachedEntry) tmp[0]).appendChildren(currentEntry);
}
}
br.close(); //close reader, so that you can delete the file
if(!f.delete()) //if delete has no success
f.deleteOnExit(); //mark it, for delete on exit
if(caches == null)
caches = new ArrayList();
caches.add(entry);
}
catch(Exception ex)
{
// ex.printStackTrace(System.out);
System.err.println(ex.getLocalizedMessage());
throw new RegistryErrorException(ex.getLocalizedMessage());
}
}
/***********************************************************************************************************************************
* Enables the caching method for dword, expand, multi and binary for the cacheKeys method and then for reading it
* @param aValue boolean true or false
**********************************************************************************************************************************/
public void setCaching(boolean aValue)
{
if(useCache != aValue)
useCache = aValue;
}
/***********************************************************************************************************************************
* Returns if the caching for dword, expand, multi and binary is enabled (you have to use cacheKeys method)
* @return boolean true or false (default = false)
**********************************************************************************************************************************/
public boolean isCachingActive()
{
return useCache;
}
/***********************************************************************************************************************************
* Method returns all cached Keys
* @return List a list of string of the cached key names
**********************************************************************************************************************************/
public List getCachingKeys()
{
List ret = null;
if(isCachingActive() && caches != null && caches.size() > 0)
{
ret = new ArrayList();
for(int x = 0; x != caches.size(); x++)
{
CachedEntry entry = (CachedEntry) caches.get(x);
if(entry != null)
ret.add(entry.getKey());
}
}
return ret;
}
/**********************************************************************************************************************************
* Method refreshes the cached entries
* @todo implement 100% funtionality - i dont know the deepth search of the subkinds
* @throws RegistryErrorException
*********************************************************************************************************************************/
public void refreshCaches() throws RegistryErrorException
{
if(isCachingActive())
{
if(caches != null && caches.size() > 0)
{
List tmpCache = (List) caches.clone();
caches = new ArrayList();
for (int x = 0; tmpCache != null && x != tmpCache.size(); x++)
{
CachedEntry entry = (CachedEntry) tmpCache.get(x);
if (entry != null)
{
String key = entry.getKey();
cacheKeys(key, 1);
}
}
}
}
}
/**********************************************************************************************************************************
* Method deletes all caching values
*********************************************************************************************************************************/
public void deleteCaches()
{
if(isCachingActive())
{
for (int x = 0; caches != null && x != caches.size(); x++)
{
CachedEntry entry = (CachedEntry) caches.get(x);
if (entry != null)
{
List children = entry.getChildren();
if (children != null)
children.clear();
List entries = entry.getEntries();
if (entries != null)
entries.clear();
}
}
caches.clear();
caches = null;
}
}
/***********************************************************************************************************************************
* Method searches for the key in the cache entry - just for private usage
* @param key String
* @param name String
* @return String
* @throws NoEntryException throws this exception if there is no such entry - returns null if it is not cached or caching is disabled
**********************************************************************************************************************************/
private String getCachedValue(String key, String name) throws NoEntryException
{
if(isCachingActive())
{
for(int x = 0; caches != null && x != caches.size(); x++)
{
CachedEntry entry = (CachedEntry) caches.get(x);
CachedEntry child = entry.findSub(key);
if(child != null)
{
List list = child.getEntries();
if(list == null)
throw new NoEntryException(key + " @ " + name + " not found in registry");
for(int y = 0; list != null && y != list.size(); y++)
{
CachedValue val = (CachedValue)list.get(y);
if(val != null)
{
if(val.getName().equals(name))
return val.getData();
}
}
if(list.size() > 0) //when the list has entries and the name is not found, then there is no such entry
throw new NoEntryException(key + " @ " + name + " not found in registry");
}
}
}
return null;
}
/**********************************************************************************************************************************
* Method parses the data for caching - not used anymore
* @param data String
* @return String
*********************************************************************************************************************************/
private static String parseData(String data)
{
if(data == null || data.length() == 0)
return data;
if(data.startsWith(BINARY_KEY))
return data.substring(4);
// return parseHexString(data.substring(4), false);
else if(data.startsWith(DWORD_KEY))
return data.substring(6);
// return parseHexString(data.substring(6), false);
else if(data.startsWith(MULTI_KEY))
return data.substring(7);
// return parseHexString(data.substring(7), true);
else if(data.startsWith(EXPAND_KEY))
return data.substring(7);
// return parseHexString(data.substring(7), true);
else if(data.startsWith("\""))
return data.replaceAll("\"", "");
return data;
}
/**********************************************************************************************************************************
* Method looks if the filesize becomes bigger after waiting some ms (which can be defined at WAIT_FOR_FILE)
* @param file File
*********************************************************************************************************************************/
private static void _waitForFile(File file)
{
try{
long size = file.length();
Thread.currentThread().sleep(WAIT_FOR_FILE);
if(size != file.length())
_waitForFile(file);
}
catch(Exception ex)
{
System.err.println("ERROR WAITING FOR FILE: " + file);
}
}
/******************************************************************************************************************************
* main for testing and some examples are stored here
* @param args String[]
* @throws Exception
*****************************************************************************************************************************/
public static void main(String[] args) throws Exception
{
Regor regor = new Regor();
Key _key = regor.openKey(HKEY_LOCAL_MACHINE, "SYSTEM\\ControlSet001\\Services");
// regor.setCaching(true);
// Key _key = regor.openKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\debis");
regor.cacheKeys(_key, 2);
Key __key = regor.openKey(_key, "xmlprov");
System.out.println("KEY:: " + __key);
// System.out.println(">> " + regor.readExpand(__key, "ServiceDll"));
// System.out.println(">>> " + Regor.parseHexString(regor.readExpand(__key, "ServiceDll"), true));
System.out.println(">>>> " + regor.readMulti(__key,"DependOnService"));
System.out.println(">>> " + Regor.parseHexString(regor.readMulti(__key, "DependOnService"), true));
System.out.println(">>>> " + regor.readExpand(__key,"ImagePath"));
System.out.println(">>> " + Regor.parseHexString(regor.readExpand(__key, "ImagePath"), true));
regor.closeKey(__key);
regor.closeKey(_key);
if(true)
return;
if(false) //testing the new methods
{
Key key = regor.openKey(HKEY_LOCAL_MACHINE, "Software\\AVS3");
// regor.saveAnyValue("HKEY_LOCAL_MACHINE\\Software\\AVS3", "MULTI", MULTI_KEY,convertStringToHexComma("Das ist ein langer Test, mal schauen was da nachher rauskommt \n dumdidum!", true));
// System.out.println(">>> " + Regor.parseHexString(regor.readMulti(key,"MULTI"), true));
// System.out.println(">>> " + regor.readMulti(key, "MULTI"));
// regor.saveDword(key, "DWOR1D", Integer.toHexString(23));
regor.saveBinary(key, "BIN1", Regor.convertStringToHexComma("HALLO", false));
System.out.println(">> " + regor.readBinary(key, "BIN1"));
System.out.println(">>DW: " +regor.readDword(key, "DWORD"));
regor.saveExpand(key, "MULTI3", Regor.convertStringToHexComma("DUMDIDUM", true));
regor.closeKey(key);
return;
}
//AT FIRST THE OLD WAY IS USED!!
{
System.out.println("NOW USING DEPRECATED REGOR!");
//opening dhe LOCAL_MACHINE entry and software\microsoft - the delimiter is the \\
int key = regor._openKey(_HKEY_LOCAL_MACHINE, "Software\\Microsoft"), key2 = -1;
//listing the subkeys
List l = regor._listKeys(key);
System.out.println("SOME KEYS....");
for (int x = 0; l != null && x != l.size(); x++) //printing out the keys
System.out.println(x + " == " + l.get(x));
if (l.size() > 0) //if keys found, use first key to get valueNames
key2 = regor._openKey(key, (String) l.get(0));
l = regor._listValueNames(key2); //read the valueNames
System.out.println("SOME VALUENAMES.....");
for (int x = 0; l != null && x != l.size(); x++) //printing it
System.out.println(x + " == " + l.get(x));
System.out.println("SOME STRING VALUES....");
for (int x = 0; l != null && x != l.size(); x++) //getting the String value from the valueNames
{
byte buf[] = regor._readValue(key2, (String) l.get(x)); //get the information - if is not a string value, null will be returned
System.out.println(x + ": " + l.get(x) + " == " + Regor.parseValue(buf)); //parses the byte buffer to String
}
//example to access the default valueName - either null or ""
System.out.println("default entry == " + Regor.parseValue(regor._readValue(key, null)));
//accessing a root node
l = regor._listKeys(_HKEY_LOCAL_MACHINE);
System.out.println("KEYS FROM LOCAL_MACHINE....");
for (int x = 0; l != null && x != l.size(); x++) //printing out the keys
System.out.println(x + " == " + l.get(x));
regor._closeKey(key2);
regor._closeKey(key);
}
//HERE THE NEW METHOD IS USED
{
System.out.println("NOW USING NEW REGOR!");
Key key = regor.openKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft"), key2 = null;
//listing the subkeys
List l = regor.listKeys(key);
System.out.println("SOME KEYS....");
for (int x = 0; l != null && x != l.size(); x++) //printing out the keys
System.out.println(x + " == " + l.get(x));
if (l.size() > 0) //if keys found, use first key to get valueNames
key2 = regor.openKey(key, (String) l.get(0));
l = regor.listValueNames(key2); //read the valueNames
System.out.println("SOME VALUENAMES.....");
for (int x = 0; l != null && x != l.size(); x++) //printing it
System.out.println(x + " == " + l.get(x));
System.out.println("SOME STRING VALUES....");
for (int x = 0; l != null && x != l.size(); x++) //getting the String value from the valueNames
{
byte buf[] = regor.readValue(key2, (String) l.get(x)); //get the information - if is not a string value, null will be returned
System.out.println(x + ": " + l.get(x) + " == " + Regor.parseValue(buf)); //parses the byte buffer to String
}
//example to access the default valueName - either null or ""
System.out.println("default entry == " + Regor.parseValue(regor.readValue(key, null)));
//accessing a root node
l = regor.listKeys(HKEY_LOCAL_MACHINE);
System.out.println("KEYS FROM LOCAL_MACHINE....");
for (int x = 0; l != null && x != l.size(); x++) //printing out the keys
System.out.println(x + " == " + l.get(x));
regor.closeKey(key2);
regor.closeKey(key);
}
}
//
//Exception is used when searching with cached values and the cached values has no entries
private static class NoEntryException extends Exception
{
public NoEntryException(String str)
{
super(str);
}
}
}