zemf4you

Rearranged Apache code for working with the Windows registry

Feb 22nd, 2021 (edited)
120
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 12.97 KB | None | 0 0
  1. package ru.zemf4you.windows
  2.  
  3. import java.lang.reflect.InvocationTargetException
  4. import java.util.*
  5. import java.util.prefs.Preferences
  6. import kotlin.collections.HashMap
  7. import kotlin.collections.set
  8. import kotlin.jvm.Throws
  9.  
  10.  
  11. object WinRegistry {
  12.     const val HKEY_CURRENT_USER = -0x7fffffff
  13.     const val HKEY_LOCAL_MACHINE = -0x7ffffffe
  14.     const val REG_SUCCESS = 0
  15.     const val REG_NOTFOUND = 2
  16.     const val REG_ACCESSDENIED = 5
  17.     const val KEY_ALL_ACCESS = 0xf003f
  18.     const val KEY_READ = 0x20019
  19.     private val userRoot = Preferences.userRoot()
  20.     private val systemRoot = Preferences.systemRoot()
  21.     private val userClass: Class<out Preferences> = userRoot.javaClass
  22.     private val regOpenKey = userClass.getDeclaredMethod(
  23.         "WindowsRegOpenKey",
  24.         Int::class.javaPrimitiveType, ByteArray::class.java, Int::class.javaPrimitiveType
  25.     )
  26.     private val regCloseKey = userClass.getDeclaredMethod(
  27.         "WindowsRegCloseKey",
  28.         Int::class.javaPrimitiveType
  29.     )
  30.     private val regQueryValueEx = userClass.getDeclaredMethod(
  31.         "WindowsRegQueryValueEx",
  32.         Int::class.javaPrimitiveType, ByteArray::class.java
  33.     )
  34.     private val regEnumValue = userClass.getDeclaredMethod(
  35.         "WindowsRegEnumValue",
  36.         Int::class.javaPrimitiveType, Int::class.javaPrimitiveType, Int::class.javaPrimitiveType
  37.     )
  38.     private val regQueryInfoKey = userClass.getDeclaredMethod(
  39.         "WindowsRegQueryInfoKey1",
  40.         Int::class.javaPrimitiveType
  41.     )
  42.     private val regEnumKeyEx = userClass.getDeclaredMethod(
  43.         "WindowsRegEnumKeyEx", Int::class.javaPrimitiveType, Int::class.javaPrimitiveType, Int::class.javaPrimitiveType
  44.     )
  45.     private val regCreateKeyEx = userClass.getDeclaredMethod(
  46.         "WindowsRegCreateKeyEx", Int::class.javaPrimitiveType, ByteArray::class.java
  47.     )
  48.     private val regSetValueEx = userClass.getDeclaredMethod(
  49.         "WindowsRegSetValueEx", Int::class.javaPrimitiveType, ByteArray::class.java, ByteArray::class.java
  50.     )
  51.     private val regDeleteValue = userClass.getDeclaredMethod(
  52.         "WindowsRegDeleteValue", Int::class.javaPrimitiveType, ByteArray::class.java
  53.     )
  54.     private val regDeleteKey = userClass.getDeclaredMethod(
  55.         "WindowsRegDeleteKey", Int::class.javaPrimitiveType, ByteArray::class.java
  56.     )
  57.  
  58.     init {
  59.         regCreateKeyEx.isAccessible = true
  60.         regEnumKeyEx.isAccessible = true
  61.         regQueryInfoKey.isAccessible = true
  62.         regEnumValue.isAccessible = true
  63.         regQueryValueEx.isAccessible = true
  64.         regCloseKey.isAccessible = true
  65.         regOpenKey.isAccessible = true
  66.         regSetValueEx.isAccessible = true
  67.         regDeleteValue.isAccessible = true
  68.         regDeleteKey.isAccessible = true
  69.     }
  70.  
  71.     /**
  72.      * Read a value from key and value name
  73.      * @param hkey   HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
  74.      * @param key
  75.      * @param valueName
  76.      * @return the value
  77.      * @throws IllegalArgumentException
  78.      * @throws IllegalAccessException
  79.      * @throws InvocationTargetException
  80.      */
  81.     @Throws(IllegalArgumentException::class, IllegalAccessException::class, InvocationTargetException::class)
  82.     fun readString(hkey: Int, key: String, valueName: String): String? {
  83.         return when (hkey) {
  84.             HKEY_LOCAL_MACHINE -> {
  85.                 readString(systemRoot, hkey, key, valueName)
  86.             }
  87.             HKEY_CURRENT_USER -> {
  88.                 readString(userRoot, hkey, key, valueName)
  89.             }
  90.             else -> {
  91.                 throw IllegalArgumentException("hkey=$hkey")
  92.             }
  93.         }
  94.     }
  95.  
  96.     /**
  97.      * Read value(s) and value name(s) form given key
  98.      * @param hkey  HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
  99.      * @param key
  100.      * @return the value name(s) plus the value(s)
  101.      * @throws IllegalArgumentException
  102.      * @throws IllegalAccessException
  103.      * @throws InvocationTargetException
  104.      */
  105.     @Throws(IllegalArgumentException::class, IllegalAccessException::class, InvocationTargetException::class)
  106.     fun readStringValues(hkey: Int, key: String): Map<String, String?>? {
  107.         return when (hkey) {
  108.             HKEY_LOCAL_MACHINE -> {
  109.                 readStringValues(systemRoot, hkey, key)
  110.             }
  111.             HKEY_CURRENT_USER -> {
  112.                 readStringValues(userRoot, hkey, key)
  113.             }
  114.             else -> {
  115.                 throw IllegalArgumentException("hkey=$hkey")
  116.             }
  117.         }
  118.     }
  119.  
  120.     /**
  121.      * Read the value name(s) from a given key
  122.      * @param hkey  HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
  123.      * @param key
  124.      * @return the value name(s)
  125.      * @throws IllegalArgumentException
  126.      * @throws IllegalAccessException
  127.      * @throws InvocationTargetException
  128.      */
  129.     @Throws(IllegalArgumentException::class, IllegalAccessException::class, InvocationTargetException::class)
  130.     fun readStringSubKeys(hkey: Int, key: String): List<String>? {
  131.         return when (hkey) {
  132.             HKEY_LOCAL_MACHINE -> {
  133.                 readStringSubKeys(systemRoot, hkey, key)
  134.             }
  135.             HKEY_CURRENT_USER -> {
  136.                 readStringSubKeys(userRoot, hkey, key)
  137.             }
  138.             else -> {
  139.                 throw IllegalArgumentException("hkey=$hkey")
  140.             }
  141.         }
  142.     }
  143.  
  144.     /**
  145.      * Create a key
  146.      * @param hkey  HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
  147.      * @param key
  148.      * @throws IllegalArgumentException
  149.      * @throws IllegalAccessException
  150.      * @throws InvocationTargetException
  151.      */
  152.     @Throws(IllegalArgumentException::class, IllegalAccessException::class, InvocationTargetException::class)
  153.     fun createKey(hkey: Int, key: String) {
  154.         val ret: IntArray
  155.         when (hkey) {
  156.             HKEY_LOCAL_MACHINE -> {
  157.                 ret = createKey(systemRoot, hkey, key)
  158.                 regCloseKey.invoke(systemRoot, ret[0])
  159.             }
  160.             HKEY_CURRENT_USER -> {
  161.                 ret = createKey(userRoot, hkey, key)
  162.                 regCloseKey.invoke(userRoot, ret[0])
  163.             }
  164.             else -> {
  165.                 throw IllegalArgumentException("hkey=$hkey")
  166.             }
  167.         }
  168.         require(ret[1] == REG_SUCCESS) { "rc=" + ret[1] + "  key=" + key }
  169.     }
  170.  
  171.     /**
  172.      * Write a value in a given key/value name
  173.      * @param hkey
  174.      * @param key
  175.      * @param valueName
  176.      * @param value
  177.      * @throws IllegalArgumentException
  178.      * @throws IllegalAccessException
  179.      * @throws InvocationTargetException
  180.      */
  181.     @Throws(IllegalArgumentException::class, IllegalAccessException::class, InvocationTargetException::class)
  182.     fun writeStringValue(hkey: Int, key: String, valueName: String, value: String) {
  183.         when (hkey) {
  184.             HKEY_LOCAL_MACHINE -> {
  185.                 writeStringValue(systemRoot, hkey, key, valueName, value)
  186.             }
  187.             HKEY_CURRENT_USER -> {
  188.                 writeStringValue(userRoot, hkey, key, valueName, value)
  189.             }
  190.             else -> {
  191.                 throw IllegalArgumentException("hkey=$hkey")
  192.             }
  193.         }
  194.     }
  195.  
  196.     /**
  197.      * Delete a given key
  198.      * @param hkey
  199.      * @param key
  200.      * @throws IllegalArgumentException
  201.      * @throws IllegalAccessException
  202.      * @throws InvocationTargetException
  203.      */
  204.     @Throws(IllegalArgumentException::class, IllegalAccessException::class, InvocationTargetException::class)
  205.     fun deleteKey(hkey: Int, key: String) {
  206.         var rc = -1
  207.         if (hkey == HKEY_LOCAL_MACHINE) {
  208.             rc = deleteKey(systemRoot, hkey, key)
  209.         } else if (hkey == HKEY_CURRENT_USER) {
  210.             rc = deleteKey(userRoot, hkey, key)
  211.         }
  212.         require(rc == REG_SUCCESS) { "rc=$rc  key=$key" }
  213.     }
  214.  
  215.     /**
  216.      * delete a value from a given key/value name
  217.      * @param hkey
  218.      * @param key
  219.      * @param value
  220.      * @throws IllegalArgumentException
  221.      * @throws IllegalAccessException
  222.      * @throws InvocationTargetException
  223.      */
  224.     @Throws(IllegalArgumentException::class, IllegalAccessException::class, InvocationTargetException::class)
  225.     fun deleteValue(hkey: Int, key: String, value: String) {
  226.         var rc = -1
  227.         if (hkey == HKEY_LOCAL_MACHINE) {
  228.             rc = deleteValue(systemRoot, hkey, key, value)
  229.         } else if (hkey == HKEY_CURRENT_USER) {
  230.             rc = deleteValue(userRoot, hkey, key, value)
  231.         }
  232.         require(rc == REG_SUCCESS) { "rc=$rc  key=$key  value=$value" }
  233.     }
  234.  
  235.     // =====================
  236.     @Throws(IllegalArgumentException::class, IllegalAccessException::class, InvocationTargetException::class)
  237.     private fun deleteValue(root: Preferences, hkey: Int, key: String, value: String): Int {
  238.         val handles = regOpenKey.invoke(root, hkey, toCstr(key), KEY_ALL_ACCESS) as IntArray
  239.         if (handles[1] != REG_SUCCESS) {
  240.             return handles[1] // can be REG_NOTFOUND, REG_ACCESSDENIED
  241.         }
  242.         val rc = (regDeleteValue.invoke(
  243.             root,
  244.             handles[0], toCstr(value)
  245.         ) as Int).toInt()
  246.         regCloseKey.invoke(root, handles[0])
  247.         return rc
  248.     }
  249.  
  250.     @Throws(IllegalArgumentException::class, IllegalAccessException::class, InvocationTargetException::class)
  251.     private fun deleteKey(root: Preferences, hkey: Int, key: String): Int {
  252.         return (regDeleteKey.invoke(
  253.             root,
  254.             hkey, toCstr(key)
  255.         ) as Int).toInt() // can REG_NOTFOUND, REG_ACCESSDENIED, REG_SUCCESS
  256.     }
  257.  
  258.     @Throws(IllegalArgumentException::class, IllegalAccessException::class, InvocationTargetException::class)
  259.     private fun readString(root: Preferences, hkey: Int, key: String, value: String): String? {
  260.         val handles = regOpenKey.invoke(root, hkey, toCstr(key), KEY_READ) as IntArray
  261.         if (handles[1] != REG_SUCCESS) {
  262.             return null
  263.         }
  264.         val valb = regQueryValueEx.invoke(root, handles[0], toCstr(value)) as ByteArray
  265.         regCloseKey.invoke(root, handles[0])
  266.         return String(valb).trim { it <= ' ' }
  267.     }
  268.  
  269.     @Throws(IllegalArgumentException::class, IllegalAccessException::class, InvocationTargetException::class)
  270.     private fun readStringValues(root: Preferences, hkey: Int, key: String): Map<String, String?>? {
  271.         val results = HashMap<String, String?>()
  272.         val handles = regOpenKey.invoke(root, hkey, toCstr(key), KEY_READ) as IntArray
  273.         if (handles[1] != REG_SUCCESS) {
  274.             return null
  275.         }
  276.         val info = regQueryInfoKey.invoke(
  277.             root,
  278.             handles[0]
  279.         ) as IntArray
  280.         val count = info[0] // count  
  281.         val maxlen = info[3] // value length max
  282.         for (index in 0 until count) {
  283.             val name = regEnumValue.invoke(root, handles[0], index, maxlen + 1) as ByteArray
  284.             val value = readString(hkey, key, String(name))
  285.             results[String(name).trim { it <= ' ' }] = value
  286.         }
  287.         regCloseKey.invoke(root, handles[0])
  288.         return results
  289.     }
  290.  
  291.     @Throws(IllegalArgumentException::class, IllegalAccessException::class, InvocationTargetException::class)
  292.     private fun readStringSubKeys(root: Preferences, hkey: Int, key: String): List<String>? {
  293.         val results: MutableList<String> = ArrayList()
  294.         val handles = regOpenKey.invoke(root, hkey, toCstr(key), KEY_READ) as IntArray
  295.         if (handles[1] != REG_SUCCESS) {
  296.             return null
  297.         }
  298.         val info = regQueryInfoKey.invoke(
  299.             root,
  300.             handles[0]
  301.         ) as IntArray
  302.         val count =
  303.             info[0] // Fix: info[2] was being used here with wrong results. Suggested by davenpcj, confirmed by Petrucio
  304.         val maxlen = info[3] // value length max
  305.         for (index in 0 until count) {
  306.             val name = regEnumKeyEx.invoke(root, handles[0], index, maxlen + 1) as ByteArray
  307.             results.add(String(name).trim { it <= ' ' })
  308.         }
  309.         regCloseKey.invoke(root, handles[0])
  310.         return results
  311.     }
  312.  
  313.     @Throws(IllegalArgumentException::class, IllegalAccessException::class, InvocationTargetException::class)
  314.     private fun createKey(root: Preferences, hkey: Int, key: String): IntArray {
  315.         return regCreateKeyEx.invoke(
  316.             root,
  317.             hkey, toCstr(key)
  318.         ) as IntArray
  319.     }
  320.  
  321.     @Throws(IllegalArgumentException::class, IllegalAccessException::class, InvocationTargetException::class)
  322.     private fun writeStringValue(root: Preferences, hkey: Int, key: String, valueName: String, value: String) {
  323.         val handles = regOpenKey.invoke(root, hkey, toCstr(key), KEY_ALL_ACCESS) as IntArray
  324.         regSetValueEx.invoke(
  325.             root,
  326.             handles[0], toCstr(valueName), toCstr(value)
  327.         )
  328.         regCloseKey.invoke(root, handles[0])
  329.     }
  330.  
  331.     // utility
  332.     private fun toCstr(str: String): ByteArray {
  333.         val result = ByteArray(str.length + 1)
  334.         for (i in str.indices) {
  335.             result[i] = str[i].toByte()
  336.         }
  337.         result[str.length] = 0
  338.         return result
  339.     }
  340.  
  341. }
Add Comment
Please, Sign In to add comment