Attribute VB_Name = "modRegistry"
    
    'For working with the Windows Registry
    Declare Function RegDeleteValue Lib "advapi32.dll" Alias "RegDeleteValueA" (ByVal hkey As Long, ByVal lpValueName As String) As Long
    Declare Function RegOpenKey Lib "advapi32.dll" Alias "RegOpenKeyA" (ByVal hkey As Long, ByVal lpSubKey As String, phkResult As Long) As Long
    Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" (ByVal hkey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long, ByVal samDesired As Long, phkResult As Long) As Long
    Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hkey As Long) As Long
    Declare Function RegCreateKey Lib "advapi32.dll" Alias "RegCreateKeyA" (ByVal hkey As Long, ByVal lpSubKey As String, phkResult As Long) As Long
    Declare Function RegDeleteKey Lib "advapi32.dll" Alias "RegDeleteKeyA" (ByVal hkey As Long, ByVal lpSubKey As String) As Long
    Declare Function RegQueryValueEx Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hkey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, lpType As Long, ByVal lpData As String, lpcbData As Long) As Long
    Declare Function RegQueryValueExA Lib "advapi32.dll" (ByVal hkey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, lpType As Long, ByRef lpData As Long, lpcbData As Long) As Long
    Declare Function RegSetValueEx Lib "advapi32.dll" Alias "RegSetValueExA" (ByVal hkey As Long, ByVal lpValueName As String, ByVal Reserved As Long, ByVal dwType As Long, ByVal lpData As String, ByVal cbData As Long) As Long
    Declare Function RegSetValueExA Lib "advapi32.dll" (ByVal hkey As Long, ByVal lpValueName As String, ByVal Reserved As Long, ByVal dwType As Long, ByRef lpData As Long, ByVal cbData As Long) As Long
    Declare Function RegSetValueExB Lib "advapi32.dll" Alias "RegSetValueExA" (ByVal hkey As Long, ByVal lpValueName As String, ByVal Reserved As Long, ByVal dwType As Long, ByRef lpData As Byte, ByVal cbData As Long) As Long
    Declare Function RegEnumKeyEx Lib "advapi32.dll" Alias "RegEnumKeyExA" (ByVal hkey As Long, ByVal dwIndex As Long, ByVal lpName As String, lpcbName As Long, ByVal lpReserved As Long, ByVal lpClass As String, lpcbClass As Long, lpftLastWriteTime As Any) As Long
    Declare Function RegEnumValue Lib "advapi32.dll" Alias "RegEnumValueA" (ByVal hkey As Long, ByVal dwIndex As Long, ByVal lpValueName As String, lpcbValueName As Long, ByVal lpReserved As Long, lpType As Long, lpData As Byte, lpcbData As Long) As Long

    Const ERROR_SUCCESS = 0&
    Const ERROR_BADDB = 1009&
    Const ERROR_BADKEY = 1010&
    Const ERROR_CANTOPEN = 1011&
    Const ERROR_CANTREAD = 1012&
    Const ERROR_CANTWRITE = 1013&
    Const ERROR_OUTOFMEMORY = 14&
    Const ERROR_INVALID_PARAMETER = 87&
    Const ERROR_ACCESS_DENIED = 5&
    Const ERROR_NO_MORE_ITEMS = 259&
    Const ERROR_MORE_DATA = 234&
    
    Const REG_NONE = 0&
    Const REG_SZ = 1&
    Const REG_EXPAND_SZ = 2&
    Const REG_BINARY = 3&
    Const REG_DWORD = 4&
    Const REG_DWORD_LITTLE_ENDIAN = 4&
    Const REG_DWORD_BIG_ENDIAN = 5&
    Const REG_LINK = 6&
    Const REG_MULTI_SZ = 7&
    Const REG_RESOURCE_LIST = 8&
    Const REG_FULL_RESOURCE_DESCRIPTOR = 9&
    Const REG_RESOURCE_REQUIREMENTS_LIST = 10&
    
    Const KEY_QUERY_VALUE = &H1&
    Const KEY_SET_VALUE = &H2&
    Const KEY_CREATE_SUB_KEY = &H4&
    Const KEY_ENUMERATE_SUB_KEYS = &H8&
    Const KEY_NOTIFY = &H10&
    Const KEY_CREATE_LINK = &H20&
    Const READ_CONTROL = &H20000
    Const WRITE_DAC = &H40000
    Const WRITE_OWNER = &H80000
    Const SYNCHRONIZE = &H100000
    Const STANDARD_RIGHTS_REQUIRED = &HF0000
    Const STANDARD_RIGHTS_READ = READ_CONTROL
    Const STANDARD_RIGHTS_WRITE = READ_CONTROL
    Const STANDARD_RIGHTS_EXECUTE = READ_CONTROL
    Const KEY_READ = STANDARD_RIGHTS_READ Or KEY_QUERY_VALUE Or KEY_ENUMERATE_SUB_KEYS Or KEY_NOTIFY
    Const KEY_WRITE = STANDARD_RIGHTS_WRITE Or KEY_SET_VALUE Or KEY_CREATE_SUB_KEY
    Const KEY_EXECUTE = KEY_READ
    
    Dim hkey As Long, MainKeyHandle As Long
    Dim rtn As Long, lBuffer As Long, sBuffer As String
    Dim lBufferSize As Long
    Dim lDataSize As Long
    Dim ByteArray() As Byte
        
    'This constant determins wether or not to display error messages to the
    'user. I have set the default value to False as an error message can and
    'does become irritating after a while. Turn this value to true if you want
    'to debug your programming code when reading and writing to your system
    'registry, as any errors will be displayed in a message box.
    Const DisplayErrorMsg = False
            
    Public Function EnumRegKey(SubKey As String) As String()
        Dim hkey As Long
        Dim Cnt As Long
        Dim sSave As String
        Dim strKeys() As String
        
        Call ParseKey(SubKey, MainKeyHandle)
        
        '   Open a registry key
        RegOpenKey MainKeyHandle, SubKey, hkey
    
        Do
            '   Create a buffer
            sSave = String(255, 0)
            '   Enumerate the keys
            If RegEnumKeyEx(hkey, Cnt, sSave, 255, 0, vbNullString, ByVal 0&, ByVal 0&) <> 0 Then
                ReDim Preserve strKeys(Cnt)
                Exit Do
            Else
                '   Add the Keys to the array.
                ReDim Preserve strKeys(Cnt)
                strKeys(Cnt) = StripTerminator(sSave)
                Cnt = Cnt + 1
            End If
        Loop
    
        RegCloseKey hkey
        
        EnumRegKey = strKeys
    End Function
        
    Public Sub EnumValues(SubKey As String, ListToAddTo As ListView)
        Dim hkey As Long, Cnt As Long, sSave As String
        
        Call ParseKey(SubKey, MainKeyHandle)
        'Open a new key
        RegOpenKey MainKeyHandle, SubKey, hkey
        Cnt = 0
        Do
            'Create a buffer
            sSave = String(255, 0)
            'enumerate the values
            If RegEnumValue(hkey, Cnt, sSave, 255, 0, ByVal 0&, ByVal 0&, ByVal 0&) <> 0 Then Exit Do
            'pritn the results to the form
            If StripTerminator(sSave) <> "" Then
                ListToAddTo.ListItems.Add , , StripTerminator(sSave)
            End If
            Cnt = Cnt + 1
            DoEvents
            'If InProcess = False Then Exit Do
        Loop
        'Close the registry
        RegCloseKey hkey
    End Sub
        
    Private Function StripTerminator(sInput As String) As String
        'This function is used to stripoff all the unnecessary chr$(0)'s
        Dim ZeroPos As Integer
        'Search the first chr$(0)
        ZeroPos = InStr(1, sInput, vbNullChar)
        If ZeroPos > 0 Then
            StripTerminator = Left$(sInput, ZeroPos - 1)
        Else
            StripTerminator = sInput
        End If
    End Function
        
    Function DeleteKey(ByVal Keyname As String) As Boolean
        Call ParseKey(Keyname, MainKeyHandle)
        
        rtn = RegDeleteKey(MainKeyHandle, Keyname) 'delete the key
        If rtn = 0 Then
            DeleteKey = True
        Else
            DeleteKey = False
        End If
    End Function
    
    Public Function DeleteValue(ByVal strPath As String, ByVal strValue As String)
        Dim keyhand As Long
        
        Call ParseKey(strPath, MainKeyHandle)
        
        rtn = RegOpenKey(MainKeyHandle, strPath, keyhand)
        rtn = RegDeleteValue(keyhand, strValue)
        rtn = RegCloseKey(keyhand)
    End Function
    
    Function SetDWORDValue(SubKey As String, Entry As String, Value As Long)
        Call ParseKey(SubKey, MainKeyHandle)
        
        If MainKeyHandle Then
           rtn = RegOpenKeyEx(MainKeyHandle, SubKey, 0, KEY_WRITE, hkey) 'open the key
           If rtn = ERROR_SUCCESS Then 'if the key was open successfully then
              rtn = RegSetValueExA(hkey, Entry, 0, REG_DWORD, Value, 4) 'write the value
              If Not rtn = ERROR_SUCCESS Then   'if there was an error writting the value
                 If DisplayErrorMsg = True Then 'if the user want errors displayed
                    MsgBox ErrorMsg(rtn)        'display the error
                 End If
              End If
              rtn = RegCloseKey(hkey) 'close the key
           Else 'if there was an error opening the key
              If DisplayErrorMsg = True Then 'if the user want errors displayed
                 MsgBox ErrorMsg(rtn) 'display the error
              End If
           End If
        End If
    End Function
    
    Function GetDWORDValue(SubKey As String, Entry As String)
        Call ParseKey(SubKey, MainKeyHandle)
        
        If MainKeyHandle Then
           rtn = RegOpenKeyEx(MainKeyHandle, SubKey, 0, KEY_READ, hkey) 'open the key
           If rtn = ERROR_SUCCESS Then 'if the key could be opened then
              rtn = RegQueryValueExA(hkey, Entry, 0, REG_DWORD, lBuffer, 4) 'get the value from the registry
              If rtn = ERROR_SUCCESS Then 'if the value could be retreived then
                 rtn = RegCloseKey(hkey)  'close the key
                 GetDWORDValue = lBuffer  'return the value
              Else                        'otherwise, if the value couldnt be retreived
                 GetDWORDValue = "Error"  'return Error to the user
                 If DisplayErrorMsg = True Then 'if the user wants errors displayed
                    MsgBox ErrorMsg(rtn)        'tell the user what was wrong
                 End If
              End If
           Else 'otherwise, if the key couldnt be opened
              GetDWORDValue = "Error"        'return Error to the user
              If DisplayErrorMsg = True Then 'if the user wants errors displayed
                 MsgBox ErrorMsg(rtn)        'tell the user what was wrong
              End If
           End If
        End If
    End Function
    
    Function SetBinaryValue(SubKey As String, Entry As String, Value As String)
        Dim I       As Integer
        
        Call ParseKey(SubKey, MainKeyHandle)
        
        If MainKeyHandle Then
           rtn = RegOpenKeyEx(MainKeyHandle, SubKey, 0, KEY_WRITE, hkey) 'open the key
           If rtn = ERROR_SUCCESS Then 'if the key was open successfully then
              lDataSize = Len(Value)
              ReDim ByteArray(lDataSize)
              For I = 1 To lDataSize
              ByteArray(I) = Asc(Mid$(Value, I, 1))
              Next
              rtn = RegSetValueExB(hkey, Entry, 0, REG_BINARY, ByteArray(1), lDataSize) 'write the value
              If Not rtn = ERROR_SUCCESS Then   'if the was an error writting the value
                 If DisplayErrorMsg = True Then 'if the user want errors displayed
                    MsgBox ErrorMsg(rtn)        'display the error
                 End If
              End If
              rtn = RegCloseKey(hkey) 'close the key
           Else 'if there was an error opening the key
              If DisplayErrorMsg = True Then 'if the user wants errors displayed
                 MsgBox ErrorMsg(rtn) 'display the error
              End If
           End If
        End If
    End Function
    
    Function GetBinaryValue(SubKey As String, Entry As String)
        Call ParseKey(SubKey, MainKeyHandle)
        
        If MainKeyHandle Then
           rtn = RegOpenKeyEx(MainKeyHandle, SubKey, 0, KEY_READ, hkey) 'open the key
           If rtn = ERROR_SUCCESS Then 'if the key could be opened
              lBufferSize = 1
              rtn = RegQueryValueEx(hkey, Entry, 0, REG_BINARY, 0, lBufferSize) 'get the value from the registry
              sBuffer = Space(lBufferSize)
              rtn = RegQueryValueEx(hkey, Entry, 0, REG_BINARY, sBuffer, lBufferSize) 'get the value from the registry
              If rtn = ERROR_SUCCESS Then 'if the value could be retreived then
                 rtn = RegCloseKey(hkey)  'close the key
                 GetBinaryValue = sBuffer 'return the value to the user
              Else                        'otherwise, if the value couldnt be retreived
                 GetBinaryValue = "Error" 'return Error to the user
                 If DisplayErrorMsg = True Then 'if the user wants to errors displayed
                    MsgBox ErrorMsg(rtn)  'display the error to the user
                 End If
              End If
           Else 'otherwise, if the key couldnt be opened
              GetBinaryValue = "Error" 'return Error to the user
              If DisplayErrorMsg = True Then 'if the user wants to errors displayed
                 MsgBox ErrorMsg(rtn)  'display the error to the user
              End If
           End If
        End If
    End Function
    
    Public Function GetMainKeyHandle(MainKeyName As String) As Long
        Const HKEY_CLASSES_ROOT = &H80000000
        Const HKEY_CURRENT_USER = &H80000001
        Const HKEY_LOCAL_MACHINE = &H80000002
        Const HKEY_USERS = &H80000003
        Const HKEY_PERFORMANCE_DATA = &H80000004
        Const HKEY_CURRENT_CONFIG = &H80000005
        Const HKEY_DYN_DATA = &H80000006
           
        Select Case MainKeyName
               Case "HKEY_CLASSES_ROOT"
                    GetMainKeyHandle = HKEY_CLASSES_ROOT
               Case "HKEY_CURRENT_USER"
                    GetMainKeyHandle = HKEY_CURRENT_USER
               Case "HKEY_LOCAL_MACHINE"
                    GetMainKeyHandle = HKEY_LOCAL_MACHINE
               Case "HKEY_USERS"
                    GetMainKeyHandle = HKEY_USERS
               Case "HKEY_PERFORMANCE_DATA"
                    GetMainKeyHandle = HKEY_PERFORMANCE_DATA
               Case "HKEY_CURRENT_CONFIG"
                    GetMainKeyHandle = HKEY_CURRENT_CONFIG
               Case "HKEY_DYN_DATA"
                    GetMainKeyHandle = HKEY_DYN_DATA
        End Select
    End Function
    
    Function ErrorMsg(lErrorCode As Long) As String
        'If an error does accurr, and the user wants error messages displayed, then
        'display one of the following error messages
        Select Case lErrorCode
               Case 1009, 1015
                    GetErrorMsg = "The Registry Database is corrupt!"
               Case 2, 1010
                    GetErrorMsg = "Bad Key Name"
               Case 1011
                    GetErrorMsg = "Can't Open Key"
               Case 4, 1012
                    GetErrorMsg = "Can't Read Key"
               Case 5
                    GetErrorMsg = "Access to this key is denied"
               Case 1013
                    GetErrorMsg = "Can't Write Key"
               Case 8, 14
                    GetErrorMsg = "Out of memory"
               Case 87
                    GetErrorMsg = "Invalid Parameter"
               Case 234
                    GetErrorMsg = "There is more data than the buffer has been allocated to hold."
               Case Else
                    GetErrorMsg = "Undefined Error Code:  " & Str$(lErrorCode)
        End Select
    End Function
    
    Function GetStringValue(SubKey As String, Entry As String) As String
        On Error Resume Next
        Call ParseKey(SubKey, MainKeyHandle)
        
        If MainKeyHandle Then
           rtn = RegOpenKeyEx(MainKeyHandle, SubKey, 0, KEY_READ, hkey) 'open the key
           If rtn = ERROR_SUCCESS Then 'if the key could be opened then
              sBuffer = Space(255)     'make a buffer
              lBufferSize = Len(sBuffer)
              rtn = RegQueryValueEx(hkey, Entry, 0, REG_SZ, sBuffer, lBufferSize) 'get the value from the registry
              If rtn = ERROR_SUCCESS Then 'if the value could be retreived then
                 rtn = RegCloseKey(hkey)  'close the key
                 sBuffer = Trim(sBuffer)
                 GetStringValue = Left(sBuffer, Len(sBuffer) - 1) 'return the value to the user
              Else                        'otherwise, if the value couldnt be retreived
                 GetStringValue = "Error" 'return Error to the user
                 If DisplayErrorMsg = True Then 'if the user wants errors displayed then
                    MsgBox ErrorMsg(rtn)  'tell the user what was wrong
                 End If
              End If
           Else 'otherwise, if the key couldnt be opened
              GetStringValue = "Error"       'return Error to the user
              If DisplayErrorMsg = True Then 'if the user wants errors displayed then
                 MsgBox ErrorMsg(rtn)        'tell the user what was wrong
              End If
           End If
        End If
    End Function
    
    Private Sub ParseKey(Keyname As String, Keyhandle As Long)
        rtn = InStr(Keyname, "\") 'return if "\" is contained in the Keyname
        
        If Left(Keyname, 5) <> "HKEY_" Or Right(Keyname, 1) = "\" Then 'if the is a "\" at the end of the Keyname then
           MsgBox "Incorrect Format:" + Chr(10) + Chr(10) + Keyname 'display error to the user
           Exit Sub 'exit the procedure
        ElseIf rtn = 0 Then 'if the Keyname contains no "\"
           Keyhandle = GetMainKeyHandle(Keyname)
           Keyname = "" 'leave Keyname blank
        Else 'otherwise, Keyname contains "\"
           Keyhandle = GetMainKeyHandle(Left(Keyname, rtn - 1)) 'seperate the Keyname
           Keyname = Right(Keyname, Len(Keyname) - rtn)
        End If
    End Sub
    
    Function CreateKey(SubKey As String)
        Call ParseKey(SubKey, MainKeyHandle)
        
        If MainKeyHandle Then
           rtn = RegCreateKey(MainKeyHandle, SubKey, hkey) 'create the key
           If rtn = ERROR_SUCCESS Then 'if the key was created then
              rtn = RegCloseKey(hkey)  'close the key
           End If
        End If
    End Function
    
    Function SetStringValue(SubKey As String, Entry As String, Value As String)
        Call ParseKey(SubKey, MainKeyHandle)
        
        If MainKeyHandle Then
           rtn = RegOpenKeyEx(MainKeyHandle, SubKey, 0, KEY_WRITE, hkey) 'open the key
           If rtn = ERROR_SUCCESS Then 'if the key was open successfully then
              rtn = RegSetValueEx(hkey, Entry, 0, REG_SZ, ByVal Value, Len(Value)) 'write the value
              If Not rtn = ERROR_SUCCESS Then   'if there was an error writting the value
                 If DisplayErrorMsg = True Then 'if the user wants errors displayed
                    MsgBox ErrorMsg(rtn)        'display the error
                 End If
              End If
              rtn = RegCloseKey(hkey) 'close the key
           Else 'if there was an error opening the key
              If DisplayErrorMsg = True Then 'if the user wants errors displayed
                 MsgBox ErrorMsg(rtn)        'display the error
              End If
           End If
        End If
    End Function
