Sign in to follow this  
Followers 0
benners

Convert Reg Binary hex values to an integer

7 posts in this topic

I am trying to write a small program so I can hide user selected drives in an unattended Windows setup.

What I am trying to do is read the hex value from the registry, add the value that hides the drive and re write the key to the registry. I have monitored the registry changes made with TweakUI when I hide the individual drives and everything is fine until 100 is reached and then due to the Hex system the values change so 100 = a0, 101 = a1 and sometimes ff which should be 165 but I can't work out how knowing nothing about the hex system and can't understand what I am reading when I find something after searching :) what I need is a way to convert the numbers > 100 to an integer to add a new value then convert back to hex, is there a UDF or math function already in AutoIt that I could use or do I have to try and create one?.

My script is below with the commented lines at the end of the WriteKey function being where the conversion code should go.

Thanks

CODE
#include <Array.au3>

#NoTrayIcon

Dim $Key = 'HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer'

Dim $val = 'NoDrives'

; Arrays for drive letters

Dim $Hex1[8] = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']

Dim $Hex2[8] = ['i', 'j', 'k', 'l', 'm', 'n', 'o', 'p']

Dim $Hex3[8] = ['q', 'r', 's', 't', 'u', 'v', 'w', 'x']

Dim $Hex4[2] = ['y', 'z']

; Array for value to add for tweak.

Dim $HexInt[8] = ['1', '2', '4', '8', '10', '20', '40', '80']

Dim $HexVal[4]

If $cmdline[0] = 0 Then Exit ; Exit if no parameters.

Switch $cmdline[1] ; Get the drive letter from command line params.

Case 'a' To 'h'

WriteKey($Hex1, 0)

Case 'i' To 'p'

WriteKey($Hex2, 1)

Case 'q' To 'x'

WriteKey($Hex3, 2)

Case 'y' To 'z'

WriteKey($Hex4, 3)

EndSwitch

#cs

Function to write the registry key to hide the specified drive.

Read current 'NoDrives' value from registry, add the appropriate

value and re write the value to hide the drive in Windows Explorer.

$ATS = Array to search (Based on drive letter)

$AB = Array block ('NoDrives' Reg binary value split into 4 pairs)

#ce

Func WriteKey($ATS, $AB)

; Try to read the value, if nothing is returned assume key not found and write one.

If RegRead($key, $val) = '' Then RegWrite($key, $val, 'REG_BINARY', '00000000')

For $i = 1 To 8 Step 2 ; Read the 'NoDrives' value into the array in pairs.(givex 4 x 2 Hex pairs, i.e 00 00 00 00)

_ArrayPush($HexVal, StringMid(RegRead($Key, $val), $i, 2))

Next

; Find the drive letters position in the array.(Used to get the value to add to the Hex)

$pos = _ArraySearch($ATS, $cmdline[1])

; Convert the Hex value to an integer.

; requires code

; Add the value to hide the drive to the correct

; requires code

; Convert to hex and write the new value to the registry.

; requires code

EndFunc ;==>ReadKey

Share this post


Link to post
Share on other sites



Hi.

This should give you a start:

#include <array.au3>
Dim $HideValue = 0
$Paramstr1 = "AbFrUx" ; some drive letters, mixed UPPER and lower
$Paramstr1 = StringUpper($Paramstr1)
$HideArray = StringSplit($Paramstr1, "") ; "" will split the string into singletons
For $i = 1 To $HideArray[0]
    $Value = Asc($HideArray[$i]) - 65 ; ASC(A) = 65, this has to be reduced to 0 (zero), as  2^0=1, see table below.
    $HideValue += Exp(Log(2) * $Value) ; x ^ y = exp(log(x)*y)
    MsgBox(0, "Letter: " & $HideArray[$i], "Value: " & $Value & @LF & _
            "2^" & $Value & "=" & Exp(Log(2) * $Value) & @LF & _
            "HideValue=" & $HideValue)
Next
MsgBox(0, "Value in Dec and Hex:", $HideValue & @LF & Hex($HideValue))


#cs
    A: 1
    B: 2
    C: 4
    D: 8
    E: 16
    F: 32
    G: 64
    H: 128 
    I: 256
    J: 512
    K: 1024
    L: 2048
    M: 4096
    N: 8192
    O: 16384
    P: 32768
    Q: 65536
    R: 131072
    S: 262144
    T: 524288
    U: 1048576
    V: 2097152
    W: 4194304
    X: 8388608 
    Y: 16777216
    Z: 33554432
    All: 67108863
#ce

Regards, Rudi.


Earth is flat, pigs can fly, and Nuclear Power is SAFE!

Share this post


Link to post
Share on other sites

Hi.

This should give you a start:

#include <array.au3>
Dim $HideValue = 0
$Paramstr1 = "AbFrUx" ; some drive letters, mixed UPPER and lower
$Paramstr1 = StringUpper($Paramstr1)
$HideArray = StringSplit($Paramstr1, "") ; "" will split the string into singletons
For $i = 1 To $HideArray[0]
    $Value = Asc($HideArray[$i]) - 65 ; ASC(A) = 65, this has to be reduced to 0 (zero), as  2^0=1, see table below.
    $HideValue += Exp(Log(2) * $Value) ; x ^ y = exp(log(x)*y)
    MsgBox(0, "Letter: " & $HideArray[$i], "Value: " & $Value & @LF & _
            "2^" & $Value & "=" & Exp(Log(2) * $Value) & @LF & _
            "HideValue=" & $HideValue)
Next
MsgBox(0, "Value in Dec and Hex:", $HideValue & @LF & Hex($HideValue))


#cs
    A: 1
    B: 2
    C: 4
    D: 8
    E: 16
    F: 32
    G: 64
    H: 128 
    I: 256
    J: 512
    K: 1024
    L: 2048
    M: 4096
    N: 8192
    O: 16384
    P: 32768
    Q: 65536
    R: 131072
    S: 262144
    T: 524288
    U: 1048576
    V: 2097152
    W: 4194304
    X: 8388608 
    Y: 16777216
    Z: 33554432
    All: 67108863
#ce

Regards, Rudi.

Hi Rudi

Thanks for the reply. I have done some more testing and although the tweaks use the Hex format they do not seem to conform when calculating the result.

In Hex FF = 255 which is F (15) * 16 + F (15) * 1 but with these tweaks the number should be 165. For this tweak the first value is multiplied by 10 i.e FF = 165 which is F (15) * 10 + F (15) * 1, I made progress on the script and found a way to convert the Hex values to a number that could be added to but then found that the values also changed depending on which drives where previously hidden.

An example of this is hiding drives C, D and E gives a value of 22 which shouldn't need converting but with TweakUI the reg value is 1c which also works out to 22, so I found that when converting a new tweak value back to the Hex (type) format I would not know which variation would be the correct one. Their is obviously some pattern but I cannot see it so job stopped :)

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

Func _DriveHide($sDriveLetter, $fHide = True)
    Local $sKey = 'HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer', $sVal = 'NoDrives', $sOld, $iData, $iRet, $aDrives
    $sOld = RegRead($sKey, $sVal)
    If $sOld = "" Then $sOld = "00000000"
    $iData = Dec(Hex(Binary(BitOr('0x' & $sOld, 0))))
    $aDrives = StringSplit(StringUpper($sDriveLetter), "")
    For $i = 1 To $aDrives[0]
        If $fHide Then
            $iData = BitOr($iData, 2^(Asc($aDrives[$i])-65))
        Else
            $iData = BitAnd($iData, BitNOT(2^(Asc($aDrives[$i])-65)))
        EndIf
    Next
    $iRet = RegWrite($sKey, $sVal, "REG_BINARY", Hex(Binary($iData)))
    Return SetError(@error, 0, $iRet)
EndFunc

;Examples:

;hide B drive
_DriveHide("b")
MsgBox(0,'Test 1', RegRead('HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer', 'NoDrives'))
;hide K and Z drives
_DriveHide("kz")
MsgBox(0,'Test 2', RegRead('HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer', 'NoDrives'))
;show B, K and Z drives
_DriveHide("bkz", 0)
MsgBox(0,'Test 3', RegRead('HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer', 'NoDrives'))

Edited by Siao

"be smart, drink your wine"

Share this post


Link to post
Share on other sites

Func _DriveHide($sDriveLetter, $fHide = True)
    Local $sKey = 'HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer', $sVal = 'NoDrives', $sOld, $iData, $iRet, $aDrives
    $sOld = RegRead($sKey, $sVal)
    If $sOld = "" Then $sOld = "00000000"
    $iData = Dec(Hex(Binary(BitOr('0x' & $sOld, 0))))
    $aDrives = StringSplit(StringUpper($sDriveLetter), "")
    For $i = 1 To $aDrives[0]
        If $fHide Then
            $iData = BitOr($iData, 2^(Asc($aDrives[$i])-65))
        Else
            $iData = BitAnd($iData, BitNOT(2^(Asc($aDrives[$i])-65)))
        EndIf
    Next
    $iRet = RegWrite($sKey, $sVal, "REG_BINARY", Hex(Binary($iData)))
    Return SetError(@error, 0, $iRet)
EndFunc

;Examples:

;hide B drive
_DriveHide("b")
MsgBox(0,'Test 1', RegRead('HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer', 'NoDrives'))
;hide K and Z drives
_DriveHide("kz")
MsgBox(0,'Test 2', RegRead('HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer', 'NoDrives'))
;show B, K and Z drives
_DriveHide("bkz", 0)
MsgBox(0,'Test 3', RegRead('HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer', 'NoDrives'))
WOW!, thanks Siao

How do you even think of scripts like that, I don't think it would enter my head no matter how many times I read the manual, it makes mine laughable :) .

I like the multiple drives on the command line and the option to show them, I feel lazy now you have done all the work and cheated from all the sleep I have lost trying to get my script to do it. Was it obvious to you how the tweaks were applied?.

Share this post


Link to post
Share on other sites

Was it obvious to you how the tweaks were applied?.

Bitflag method is a pretty common practice to combine multiple options, it is used in some of the AutoIt functions too (see FileOpenDialog, FileOpen, etc.).

If you see that possible values are powers of 2, it's a safe bet.

If you're curious why it works the way it works, play with this little app.


"be smart, drink your wine"

Share this post


Link to post
Share on other sites

Updated:

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Compile_Both=y
#AutoIt3Wrapper_UseX64=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#RequireAdmin
#include <GuiListView.au3>
#include <GUIConstantsEx.au3>
#include <GuiListView.au3>
#include <String.au3>


Opt("GUIOnEventMode", 1)

Global $sKey = 'HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer'
Global $sVal = 'NoDrives'

MainGUI()

Func MainGUI()

    Global $listGUI = GUICreate("NoDrives", 280, 230, -1)
    Global $idListview = GUICtrlCreateListView("", 1, 1, 300, 200, $LVS_LIST, $LVS_EX_CHECKBOXES)
    Global $BtnId = 0

    local $drive_mask = RegRead($sKey, $sVal)

    If @error And @error <> -1 Then
        MsgBox($MB_SYSTEMMODAL, "Error " & @error, "Unable to read registry key" & @CRLF & $sKey & "\" & $sVal)
    EndIf
    ConsoleWrite($drive_mask & @CRLF)

    GUISetOnEvent($GUI_EVENT_CLOSE, "On_Close_Main")
    GUICtrlCreateLabel("Unchecked drives will be hidden", 5, 208)
    $BtnId = GUICtrlCreateButton("Save", 180, 205, 80, 20)
    GUICtrlSetOnEvent($BtnId, "_BtnSave")

    For $i = 0 To 25 ;A-Z
        local $lv_Cid = GUICtrlCreateListViewItem(Chr($i + 65) & ":\", $idListview)
        GUICtrlSetOnEvent($lv_Cid, "_LvClick")
        If(Not BitAnd($drive_mask, 2 ^ ($i))) Then
            _GUICtrlListView_SetItemChecked($idListview, $i, True)
        EndIf
    Next

    GUISetState()

    While 1
        Sleep(10)
    WEnd
EndFunc   ;==>MainGUI

Func _BtnSave()
    local $aItem
    local $bState = false
    local $sDrives = ""
    For $i = 0 To 25
        $aItem = _GUICtrlListView_GetItem($idListview, $i)
        $bState = _GUICtrlListView_GetItemChecked($idListview, $i)
        If(Not $bState) Then
            $sDrives &= StringLeft ($aItem[3],1)
        EndIf

        ConsoleWrite($aItem[3] & "Hide: " & NOT $bState & @CRLF)
    Next

    _DriveHide($sDrives, True)
    If @error Then
        MsgBox($MB_SYSTEMMODAL, "Error " & @error, "Unable to write registry key" & @CRLF & $sKey & "\" & $sVal)
    EndIf

    ;Reload regkey
    local $drive_mask = RegRead($sKey, $sVal)
    For $i = 0 To 25 ;A-Z
        If(Not BitAnd($drive_mask, 2 ^ ($i))) Then
            _GUICtrlListView_SetItemChecked($idListview, $i, True)
        EndIf
    Next
    ;Disable save button
    GUICtrlSetState(@GUI_CtrlId, $GUI_DISABLE)
EndFunc   ;==>_BtnSave

Func _LvClick()
    ;Enable save button
    GUICtrlSetState($BtnId, $GUI_ENABLE)
EndFunc   ;==>_LvClick

Func _DriveHide($sDriveLetter, $fHide = True) ;Siao
    local $iData, $iRet, $aDrives
    local $iData = RegRead($sKey, $sVal)
    local $aDrives = StringSplit(StringUpper($sDriveLetter), "")
    ConsoleWrite("0x" & Hex($iData) & @CRLF)
    For $i = 1 To $aDrives[0]
        ConsoleWrite($aDrives[$i] & ":\ 2^" & Asc($aDrives[$i]) - 65 & " => ")

        If $fHide Then
            $iData = BitOr($iData, 2 ^ (Asc($aDrives[$i]) - 65))
        Else
            $iData = BitAnd($iData, BitNOT(2 ^ (Asc($aDrives[$i]) - 65)))
        EndIf

        ConsoleWrite("0x" & Hex($iData) & "< " & @CRLF)
    Next

    $iRet = RegWrite($sKey, $sVal, "REG_DWORD", "0x" & Hex($iData))
    Return SetError(@error, 0, $iRet)
EndFunc   ;==>_DriveHide

Func On_Close_Main()
    Exit
EndFunc   ;==>On_Close_Main

 

NoDrives.png

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