Sign in to follow this  
Followers 0
wraithdu

Custom _RegWrite() and _RegRead()

21 posts in this topic

#1 ·  Posted (edited)

Well, this was just kinda random. I came across the REG_NONE type while doing some research, noticed AutoIt didn't support it, and couldn't find anyone who had posted a solution yet. Here are custom _RegWrite() and _RegRead() functions to write and read any registry keys / value types. It can also create VOLATILE registry keys.

#include-once
#include <Constants.au3>

;; REG_* constants for value types are located in <Constants.au3>
;; except REG_QWORD which is defined below

Global Const $HKEY_CLASSES_ROOT = 0x80000000
Global Const $HKEY_CURRENT_USER = 0x80000001
Global Const $HKEY_LOCAL_MACHINE = 0x80000002
Global Const $HKEY_USERS = 0x80000003
Global Const $HKEY_PERFORMANCE_DATA = 0x80000004
Global Const $HKEY_PERFORMANCE_TEXT = 0x80000050
Global Const $HKEY_PERFORMANCE_NLSTEXT = 0x80000060
Global Const $HKEY_CURRENT_CONFIG = 0x80000005
Global Const $HKEY_DYN_DATA = 0x80000006
Global Const $KEY_QUERY_VALUE = 0x0001
Global Const $KEY_SET_VALUE = 0x0002
Global Const $KEY_WRITE = 0x20006
Global Const $REG_OPTION_NON_VOLATILE = 0x0000
Global Const $REG_OPTION_VOLATILE = 0x0001
Global Const $REG_QWORD = 11

Func _RegWrite($szKey, $szValue = "", $iType = -1, $bData = Default, $dwOptions = $REG_OPTION_NON_VOLATILE)
    Local $hRoot = StringLeft($szKey, StringInStr($szKey, "\") - 1)
    If $hRoot = "" Then $hRoot = $szKey ; passed a root key
    Switch $hRoot
        Case "HKEY_LOCAL_MACHINE", "HKLM"
            $hRoot = $HKEY_LOCAL_MACHINE
        Case "HKEY_USERS", "HKU"
            $hRoot = $HKEY_USERS
        Case "HKEY_CURRENT_USER", "HKCU"
            $hRoot = $HKEY_CURRENT_USER
        Case "HKEY_CLASSES_ROOT", "HKCR"
            $hRoot = $HKEY_CLASSES_ROOT
        Case "HKEY_CURRENT_CONFIG", "HKCC"
            $hRoot = $HKEY_CURRENT_CONFIG
        Case Else
    Return SetError(1, 0, 0)
    EndSwitch

    Local $szSubkey = StringTrimLeft($szKey, StringInStr($szKey, "\"))

    Local $ret = DllCall("advapi32.dll", "long", "RegCreateKeyExW", "ulong_ptr", $hRoot, "wstr", $szSubkey, "dword", 0, "ptr", 0, "dword", $dwOptions, _
                                            "dword", $KEY_WRITE, "ptr", 0, "ulong_ptr*", 0, "ptr*", 0)
    If $ret[0] <> 0 Then Return SetError(2, $ret[0], 0)
    Local $hKey = $ret[8]
    If $iType >= 0 And $bData <> Default Then
        Switch $iType
            Case $REG_SZ, $REG_EXPAND_SZ
                $bData &= Chr(0) ; add terminating null
                Local $lpData = DllStructCreate("wchar[" & StringLen($bData) & "]")
            Case $REG_MULTI_SZ
                $bData &= Chr(0) & Chr(0) ; add 2 terminating nulls
                Local $lpData = DllStructCreate("wchar[" & StringLen($bData) & "]")
            Case Else
                Local $lpData = DllStructCreate("byte[" & BinaryLen($bData) & "]")
        EndSwitch
        DllStructSetData($lpData, 1, $bData)
        $ret = DllCall("advapi32.dll", "long", "RegSetValueExW", "ulong_ptr", $hKey, "wstr", $szValue, "dword", 0, _
                                        "dword", $iType, "ptr", DllStructGetPtr($lpData), "dword", DllStructGetSize($lpData))
    EndIf
    DllCall("advapi32.dll", "long", "RegCloseKey", "ulong_ptr", $hKey)

    If $ret[0] <> 0 Then Return SetError(3, $ret[0], 0)
    Return 1
EndFunc

Func _RegRead($szKey, $szValue)
    Local $hRoot = StringLeft($szKey, StringInStr($szKey, "\") - 1)
    If $hRoot = "" Then $hRoot = $szKey ; passed a root key
    Switch $hRoot
        Case "HKEY_LOCAL_MACHINE", "HKLM"
            $hRoot = $HKEY_LOCAL_MACHINE
        Case "HKEY_USERS", "HKU"
            $hRoot = $HKEY_USERS
        Case "HKEY_CURRENT_USER", "HKCU"
            $hRoot = $HKEY_CURRENT_USER
        Case "HKEY_CLASSES_ROOT", "HKCR"
            $hRoot = $HKEY_CLASSES_ROOT
        Case "HKEY_CURRENT_CONFIG", "HKCC"
            $hRoot = $HKEY_CURRENT_CONFIG
        Case Else
            Return SetError(1, 0, 0)
    EndSwitch

    Local $szSubkey = StringTrimLeft($szKey, StringInStr($szKey, "\"))

    Local $ret = DllCall("advapi32.dll", "long", "RegOpenKeyExW", "ulong_ptr", $hRoot, "wstr", $szSubkey, "dword", 0, "dword", $KEY_QUERY_VALUE, "ulong_ptr*", 0)
    If $ret[0] <> 0 Then Return SetError(2, $ret[0], 0)
    $hKey = $ret[5]
    $ret = DllCall("advapi32.dll", "long", "RegQueryValueExW", "ulong_ptr", $hKey, "wstr", $szValue, "ptr", 0, _
                                    "dword*", 0, "ptr", 0, "dword*", 0)
    If $ret[0] <> 0 Then Return SetError(3, $ret[0], 0)

    Local $iType = $ret[4], $iLen = $ret[6], $sType
    Switch $iType ; set type of value
        Case $REG_SZ, $REG_EXPAND_SZ, $REG_MULTI_SZ
            $sType = "wchar"
            ; iLen is byte length, if unicode string divide by 2
            ; add 2 terminating nulls for possibly incorrectly stored strings
            $iLen = ($iLen / 2) + 2
        Case $REG_BINARY, $REG_NONE
            $sType = "byte"
        Case $REG_QWORD
            $sType = "int64"
            $iLen = $iLen / 8 ; int64 = 8 bytes
        Case Else
            $sType = "int"
            $iLen = $iLen / 4 ; int = 4 bytes
    EndSwitch
    Local $lpData = DllStructCreate($sType & "[" & $iLen & "]")
    $ret = DllCall("advapi32.dll", "long", "RegQueryValueExW", "ulong_ptr", $hKey, "wstr", $szValue, "ptr", 0, _
                                    "dword*", 0, "ptr", DllStructGetPtr($lpData), "dword*", DllStructGetSize($lpData))
    DllCall("advapi32.dll", "long", "RegCloseKey", "ulong_ptr", $hKey)

    If $ret[0] <> 0 Then Return SetError(3, $ret[0], 0)
    Return SetError(0, $iType, DllStructGetData($lpData, 1))
EndFunc

Func _TypeToString($iType)
    Local $sType
    Switch $iType
        Case $REG_NONE
            $sType = "REG_NONE"
        Case $REG_SZ
            $sType = "REG_SZ"
        Case $REG_EXPAND_SZ
            $sType = "REG_EXPAND_SZ"
        Case $REG_BINARY
            $sType = "REG_BINARY"
        Case $REG_DWORD
            $sType = "REG_DWORD"
        Case $REG_DWORD_BIG_ENDIAN
            $sType = "REG_DWORD_BIG_ENDIAN"
        Case $REG_LINK
            $sType = "REG_LINK"
        Case $REG_MULTI_SZ
            $sType = "REG_MULTI_SZ"
        Case $REG_RESOURCE_LIST
            $sType = "REG_RESOURCE_LIST"
        Case $REG_FULL_RESOURCE_DESCRIPTOR
            $sType = "REG_FULL_RESOURCE_DESCRIPTOR"
        Case $REG_RESOURCE_REQUIREMENTS_LIST
            $sType = "REG_RESOURCE_REQUIREMENTS_LIST"
        Case $REG_QWORD
            $sType = "REG_QWORD"
        Case Else
            $sType = ""
    EndSwitch
    Return $sType
EndFunc

;; EXAMPLE
; just create a key
_RegWrite("HKCU\Software\AAB Test")
; sets the default value
_RegWrite("HKCU\Software\AAA Test", "", $REG_SZ, "default value")
$read = _RegRead("HKCU\Software\AAA Test", "")
ConsoleWrite("Type:  " & _TypeToString(@extended) & @CRLF)
ConsoleWrite("Data:  " & $read & @CRLF)
; writes an empty reg_none value
_RegWrite("HKCU\Software\AAA Test", "value1", $REG_NONE, "")
$read = _RegRead("HKCU\Software\AAA Test", "value1")
ConsoleWrite("Type:  " & _TypeToString(@extended) & @CRLF)
ConsoleWrite("Data:  " & $read & @CRLF)
; writes some string data as binary
_RegWrite("HKCU\Software\AAA Test", "value2", $REG_BINARY, "test data")
$read = _RegRead("HKCU\Software\AAA Test", "value2")
ConsoleWrite("Type:  " & _TypeToString(@extended) & @CRLF)
ConsoleWrite("Data:  " & $read & @CRLF)
; writes some binary data
_RegWrite("HKCU\Software\AAA Test", "value3", $REG_BINARY, Binary("0x02000000"))
$read = _RegRead("HKCU\Software\AAA Test", "value3")
ConsoleWrite("Type:  " & _TypeToString(@extended) & @CRLF)
ConsoleWrite("Data:  " & $read & @CRLF)
; write a string
_RegWrite("HKCU\Software\AAA Test", "value4", $REG_SZ, "here is a string")
$read = _RegRead("HKCU\Software\AAA Test", "value4")
ConsoleWrite("Type:  " & _TypeToString(@extended) & @CRLF)
ConsoleWrite("Data:  " & $read & @CRLF)
; write an integer
_RegWrite("HKCU\Software\AAA Test", "value5", $REG_DWORD, 123456)
$read = _RegRead("HKCU\Software\AAA Test", "value5")
ConsoleWrite("Type:  " & _TypeToString(@extended) & @CRLF)
ConsoleWrite("Data:  " & $read & @CRLF)
Edited by wraithdu

Share this post


Link to post
Share on other sites



Hey Cool! Thanks for sharing.I just need too figure out how to include this in my reg to au3 converter.

Share this post


Link to post
Share on other sites

It is the reg type for values under file type keys 'OpenWithProgIDs'

Share this post


Link to post
Share on other sites

Thanks , i needed this.

I'll try & reply.

:D

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

Great Work.

It works.

REG_NONE key is created.

I tried this:-

$var = RegRead("HKCU\Software\AAA Test", "value_none")

MsgBox(64, "Data: ", $var)

; $var comes as ""

As it is not supported.

Now, How do i write data?

I need REG_NONE for IconUnderline ( Data = 02 00 00 00 )

i.e -> Try This code

EX:-

; Single Click Without Icon Underline With Default Menu

RegWrite("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer","ShellState","REG_BINARY",Binary("0x2400000013a80000000000000000000000000000010000000d0000000000000002000000"))

;RegWrite("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer","IconUnderline","REG_NONE",Binary("0x02000000"))

;"IconUnderline"=hex(0):02,00,00,00

( Restart Explorer ) or Start some start menu programs for changing to Default menu

Also regread of reg_none will make things very easier to handle.

:D

Edited by ZNote

Share this post


Link to post
Share on other sites

Ok, didn't think anyone would need to write actual data to a REG_NONE value, since the point of the type is that the data doesn't matter. Anyway, I've updated the first post to allow writing of data, and a function to read it back. The data returned is binary, and the size is returned in @extended.

Share this post


Link to post
Share on other sites

Ok, didn't think anyone would need to write actual data to a REG_NONE value, since the point of the type is that the data doesn't matter. Anyway, I've updated the first post to allow writing of data, and a function to read it back. The data returned is binary, and the size is returned in @extended.

Thanks, Both the functions work very well.

:D

Share this post


Link to post
Share on other sites

Updated to be totally generic. Can create VOLATILE reg keys as well.

Share this post


Link to post
Share on other sites

Very nice, thanks !

I remember I wondered about REG_NONE at some point, but never needed it. Now I feel more "secure" :D

Share this post


Link to post
Share on other sites

Volatileness sounds interesting. Tested on HKCU by anyone?

Thanks wraithdu. Nice one.


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

Yep, tested. I created just a key and a key with a value (same operation), and both were gone after a reboot. If you load a HIVE, then create a volatile key in it, it will be gone after it is unmounted as well.

But if the base key exists, ex HKCU\Software\SomeCrap, trying to create a volatile key of the same name with a value will not cause the value to disappear after reboot. Only keys have the volatile attribute, and only if they are created with it by the write operation. That option is ignored for keys that already exist.

Edited by wraithdu

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

Yep, tested. I created just a key and a key with a value (same operation), and both were gone after a reboot. If you load a HIVE, then create a volatile key in it, it will be gone after it is unmounted as well.

But if the base key exists, ex HKCU\Software\SomeCrap, trying to create a volatile key of the same name with a value will not cause the value to disappear after reboot. Only keys have the volatile attribute, and only if they are created with it by the write operation. That option is ignored for keys that already exist.

And behaviour with log off/log on action?

It's a great way to detect reboot then (at least re-logon, depending on the answer to the question).

edit:

This is important for when writing to HKLM requires #RequireAdmin. To avoid that obviously.

Edited by trancexx

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

#15 ·  Posted (edited)

Unfortunately not, at least not on Win7. I tried a logoff/on first but the keys were still there. The registry hive needs to be unloaded for the keys to disappear, and I thought that was supposed to happen during logoff. Not sure why it needed a reboot.

The keys I added were in HKCU\Software, if it makes a difference.

Edited by wraithdu

Share this post


Link to post
Share on other sites

Unfortunately not, at least not on Win7. I tried a logoff/on first but the keys were still there. The registry hive needs to be unloaded for the keys to disappear, and I thought that was supposed to happen during logoff. Not sure why it needed a reboot.

The keys I added were in HKCU\Software, if it makes a difference.

I find that to be the good news. And it kind of make a sense. HKU should be affected by switching users.

Anyway, some time ago I wrote a little function to determine if the system is/was restarted since the last run of the script. It required writing to HKLM and that is the problem with Vista/Win7 since it requires #RequireAdmin. And that move scares people.

It could be like this now (could you test on Win7?):

#include <Constants.au3>

Global Const $HKEY_CLASSES_ROOT = 0x80000000
Global Const $HKEY_CURRENT_USER = 0x80000001
Global Const $HKEY_LOCAL_MACHINE = 0x80000002
Global Const $HKEY_USERS = 0x80000003
Global Const $HKEY_PERFORMANCE_DATA = 0x80000004
Global Const $HKEY_PERFORMANCE_TEXT = 0x80000050
Global Const $HKEY_PERFORMANCE_NLSTEXT = 0x80000060
Global Const $HKEY_CURRENT_CONFIG = 0x80000005
Global Const $HKEY_DYN_DATA = 0x80000006
Global Const $KEY_QUERY_VALUE = 0x0001
Global Const $KEY_SET_VALUE = 0x0002
Global Const $KEY_WRITE = 0x20006
Global Const $REG_OPTION_NON_VOLATILE = 0x0000
Global Const $REG_OPTION_VOLATILE = 0x0001
Global Const $REG_QWORD = 11

Global $iCheck = _CheckIfSystemRestartedSinceLastRun()

If @error Then
    MsgBox(48, "Error", "Function failed")
Else
    If $iCheck Then
        MsgBox(64, "Info", "You are running this script for the first time since last system restart")
    Else
        MsgBox(64, "Info", "System was not restarted since last time you run this script")
    EndIf
EndIf



Func _CheckIfSystemRestartedSinceLastRun()

    Local $sRegRead = RegRead("HKCU\Software\Restart Test", "{C5B8D2FF-301F-42EB-BA4F-6CC7933EA6E6}"); Random valuename. Make sure that it's unique.
;Local $sRegRead = _RegRead("HKCU\Software\Restart Test", "{C5B8D2FF-301F-42EB-BA4F-6CC7933EA6E6}")

    If $sRegRead Then
        Return 0; System was not restarted.
    EndIf

    _RegWrite("HKCU\Software\Restart Test", "{C5B8D2FF-301F-42EB-BA4F-6CC7933EA6E6}", $REG_DWORD, 1, $REG_OPTION_VOLATILE)

    If @error Then
        Return SetError(1)
    EndIf

    Return 1; First run after restart.

EndFunc  ;==>_CheckIfSystemRestartedSinceLastRun




;wraithdu wrote this
Func _RegWrite($szKey, $szValue = "", $iType = -1, $bData = Default, $dwOptions = $REG_OPTION_NON_VOLATILE)
    Local $hRoot = StringLeft($szKey, StringInStr($szKey, "\") - 1)
    If $hRoot = "" Then $hRoot = $szKey; passed a root key
    Switch $hRoot
        Case "HKEY_LOCAL_MACHINE", "HKLM"
            $hRoot = $HKEY_LOCAL_MACHINE
        Case "HKEY_USERS", "HKU"
            $hRoot = $HKEY_USERS
        Case "HKEY_CURRENT_USER", "HKCU"
            $hRoot = $HKEY_CURRENT_USER
        Case "HKEY_CLASSES_ROOT", "HKCR"
            $hRoot = $HKEY_CLASSES_ROOT
        Case "HKEY_CURRENT_CONFIG", "HKCC"
            $hRoot = $HKEY_CURRENT_CONFIG
        Case Else
            Return SetError(1, 0, 0)
    EndSwitch

    Local $szSubkey = StringTrimLeft($szKey, StringInStr($szKey, "\"))

    Local $ret = DllCall("advapi32.dll", "long", "RegCreateKeyExW", "ulong_ptr", $hRoot, "wstr", $szSubkey, "dword", 0, "ptr", 0, "dword", $dwOptions, _
            "dword", $KEY_WRITE, "ptr", 0, "ulong_ptr*", 0, "ptr*", 0)
    If $ret[0] <> 0 Then Return SetError(2, $ret[0], 0)
    Local $hKey = $ret[8]
    If $iType >= 0 And $bData <> Default Then
        Switch $iType
            Case $REG_SZ, $REG_EXPAND_SZ
                $bData &= Chr(0); add terminating null
                Local $lpData = DllStructCreate("wchar[" & StringLen($bData) & "]")
            Case $REG_MULTI_SZ
                $bData &= Chr(0) & Chr(0); add 2 terminating nulls
                Local $lpData = DllStructCreate("wchar[" & StringLen($bData) & "]")
            Case Else
                Local $lpData = DllStructCreate("byte[" & BinaryLen($bData) & "]")
        EndSwitch
        DllStructSetData($lpData, 1, $bData)
        $ret = DllCall("advapi32.dll", "long", "RegSetValueExW", "ulong_ptr", $hKey, "wstr", $szValue, "dword", 0, _
                "dword", $iType, "ptr", DllStructGetPtr($lpData), "dword", DllStructGetSize($lpData))
    EndIf
    DllCall("advapi32.dll", "long", "RegCloseKey", "ulong_ptr", $hKey)

    If $ret[0] <> 0 Then Return SetError(3, $ret[0], 0)
    Return 1
EndFunc  ;==>_RegWrite


;wraithdu wrote this
Func _RegRead($szKey, $szValue)
    Local $hRoot = StringLeft($szKey, StringInStr($szKey, "\") - 1)
    If $hRoot = "" Then $hRoot = $szKey; passed a root key
    Switch $hRoot
        Case "HKEY_LOCAL_MACHINE", "HKLM"
            $hRoot = $HKEY_LOCAL_MACHINE
        Case "HKEY_USERS", "HKU"
            $hRoot = $HKEY_USERS
        Case "HKEY_CURRENT_USER", "HKCU"
            $hRoot = $HKEY_CURRENT_USER
        Case "HKEY_CLASSES_ROOT", "HKCR"
            $hRoot = $HKEY_CLASSES_ROOT
        Case "HKEY_CURRENT_CONFIG", "HKCC"
            $hRoot = $HKEY_CURRENT_CONFIG
        Case Else
            Return SetError(1, 0, 0)
    EndSwitch

    Local $szSubkey = StringTrimLeft($szKey, StringInStr($szKey, "\"))

    Local $ret = DllCall("advapi32.dll", "long", "RegOpenKeyExW", "ulong_ptr", $hRoot, "wstr", $szSubkey, "dword", 0, "dword", $KEY_QUERY_VALUE, "ulong_ptr*", 0)
    If $ret[0] <> 0 Then Return SetError(2, $ret[0], 0)
    $hKey = $ret[5]
    $ret = DllCall("advapi32.dll", "long", "RegQueryValueExW", "ulong_ptr", $hKey, "wstr", $szValue, "ptr", 0, _
            "dword*", 0, "ptr", 0, "dword*", 0)
    If $ret[0] <> 0 Then Return SetError(3, $ret[0], 0)

    Local $iType = $ret[4], $iLen = $ret[6], $sType
    Switch $iType; set type of value
        Case $REG_SZ, $REG_EXPAND_SZ, $REG_MULTI_SZ
            $sType = "wchar"
        ; iLen is byte length, if unicode string divide by 2
        ; add 2 terminating nulls for possibly incorrectly stored strings
            $iLen = ($iLen / 2) + 2
        Case $REG_BINARY, $REG_NONE
            $sType = "byte"
        Case $REG_QWORD
            $sType = "int64"
            $iLen = $iLen / 8; int64 = 8 bytes
        Case Else
            $sType = "int"
            $iLen = $iLen / 4; int = 4 bytes
    EndSwitch
    Local $lpData = DllStructCreate($sType & "[" & $iLen & "]")
    $ret = DllCall("advapi32.dll", "long", "RegQueryValueExW", "ulong_ptr", $hKey, "wstr", $szValue, "ptr", 0, _
            "dword*", 0, "ptr", DllStructGetPtr($lpData), "dword*", DllStructGetSize($lpData))
    DllCall("advapi32.dll", "long", "RegCloseKey", "ulong_ptr", $hKey)

    If $ret[0] <> 0 Then Return SetError(3, $ret[0], 0)
    Return SetError(0, $iType, DllStructGetData($lpData, 1))
EndFunc  ;==>_RegRead

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

Yep, works a treat.

Share this post


Link to post
Share on other sites

Very Nice.

Because Of Your Work, Reg things have become very easy to handle.

:D

Share this post


Link to post
Share on other sites

Thanks :D

But in reality, these functions are only a superset of the AutoIt internal functions, such as a few more registry value types and volatile keys.

Share this post


Link to post
Share on other sites

is it possible to know the modification date of the registry key?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0