Reading and Writing 64-bit Registry from 32-bit.

written by Tomas Johansson
11 · 09 · 30

Have recently had a problem when I had to read and write 64-bit registry. One scenario I had was that we wanted to create a unique key under HKEY_LOCAL_MACHINE \ Software \ and then via GPO and a VMI filter, turn off offline folders about who logged in was who was managedBy in Active Directory. The WMI filter runs as 64-bit but the script that created the keys in the registry went as 32-bit.

I had to create and read 64-bit registry but the program was run in 32-bit and then you can not normally read / write in 64-bit registry. After some research online, I realized that I can solve this via VMI. Using the StdRegProv class containing methods that you can manipulate the system registry keys and values. StdRegProv is too installed in WMI namespaces root \ default and root \ cimv2.

Worth noting is that the X64 version of Windows can not run correctly 32-bit code. Since most programs are 32-bit, the x64 version of Windows will use emulator called WOW64, to allow 32-bit applications to run. One of the problems of running 32-bit code on a 64-bit operating system is that the OS should maintain full code separation. Microsoft has created a new folder named \ Windows \ SysWOW64 that is used to store 32-bit DLL files. In the 32-bit version of Windows, DLL files are normally stored in the \ windows \ system32 folder. However, the x64 version of Windows uses the \ Windows \ System32 folder folder for 64-bit DLL files.

By default, a program or script gets data from the corresponding provider when there are two versions of the provider. 32-bit provider returns data to a 32-bit application, including all scripts, and 64-bit provider returns data to 64-bit compiled applications. However, a program or script may request non-standard provider data, if available, by notifying WMI through methodological flags.

By using the __ProviderArchitecture flag, you can request access to 32-bit records in a 64-bit computer. The caller connects to 32-bit hive, whether it’s a 32- or 64-bit program.

The problem I received was that I could not access a 64-bit registry value when the script I was running was executed as 32-bit via the sccm client. But using __ProviderArchitecture and StdRegProv I came around this.
Naturally, one can reverse and read and write the 32-bit registry from a 64-bit session.

Option Explicit

'---------------------------------------------------
' Declared Constants 
'---------------------------------------------------

Const wbemFlagReturnImmediately = &h10 
Const wbemFlagForwardOnly = &h20
Const Success = 0
Const Failure = 1
Const HKEY_LOCAL_MACHINE = &H80000002
Const Read_REG_SZ = "GetStringValue"
Const Write_REG_SZ = "SetStringValue"
Const Read_REG_DWORD = "GetDWORDValue"
Const Write_REG_DWORD = "SetDWORDValue"

'---------------------------------------------------
' Declared Variables 
'---------------------------------------------------

Dim strResult, TextString1, TextString2

'---------------------------------------------------
' Parameters for Funktions ReadRegStr and WriteRegStr
'---------------------------------------------------

' Reads a REG_SZ and REG_DWORD value from the local computer's registry using WMI. 
' Parameters:
' Method - What type of value going to write (GetStringValue, SetStringValue, GetDWORDValue, SetDWORDValue)
' RootKey - The registry hive (HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CURRENT_CONFIG
' Key - The key that contains the desired value. 
' Value - The value that you want to get. 
' RegType - The registry bitness: 32 or 64

'---------------------------------------------------
' Create _TEST registry key in 64-bit Registry
'---------------------------------------------------

WScript.Echo "---------------------------------------------------"
WScript.Echo " Creating _TEST key in 64-bit Registry "
WScript.Echo "---------------------------------------------------"

strResult = CreateRegKey (HKEY_LOCAL_MACHINE, "Software\_TEST", 64)

If strResult = 0 Then
WScript.Echo "Able to Create Key : " & "HKEY_LOCAL_MACHINE\Software\_TEST"
Else
WScript.Echo "Not able to Create Key"
'WScript.Quit
End If

'---------------------------------------------------
' Set _TEST registry values in 64-bit Registry
'---------------------------------------------------

WScript.Echo "---------------------------------------------------"
WScript.Echo " Writing in 64-bit Registry "
WScript.Echo "---------------------------------------------------"

' Writing Testvalue1
TextString1 = "Test of writing value 1"
strResult = WriteRegStr (Write_REG_SZ, HKEY_LOCAL_MACHINE, "Software\_TEST", "SubKey1", TextString1, 64)

If strResult = 0 and debug =  1 Then
WScript.Echo "Able to Write Value : " & "SubKey1" & " = "& TextString1
Else
WScript.Echo "Not able to Write Value"
'WScript.Quit
End If

' Writing Testvalue2
TextString2 = "Test of writing value 2"
strResult = WriteRegStr (Write_REG_SZ, HKEY_LOCAL_MACHINE, "Software\_TEST", "SubKey2", TextString2, 64)

If strResult = 0 Then
WScript.Echo "Able to Write Value : " & "SubKey2" & " = "& TextString2
Else
WScript.Echo "Not able to Write Value"
'WScript.Quit
End If

'---------------------------------------------------
' Delete a SubKey value in 64-bit Registry
'---------------------------------------------------

strResult = DeleteSubKeyValue (HKEY_LOCAL_MACHINE, "Software\_TEST", "SubKey1", 64)

If strResult = 0 Then
WScript.Echo "Able to Delete SubKey value : " & "HKEY_LOCAL_MACHINE\Software\_TEST\SubKey1"  
Else
WScript.Echo "Not able to Delete SubKey value"
'WScript.Quit
End If

'---------------------------------------------------
' Delete _TEST registry key in 64-bit Registry
'---------------------------------------------------

WScript.Echo "---------------------------------------------------"
WScript.Echo " Delete _TEST key in 64-bit Registry "
WScript.Echo "---------------------------------------------------"

strResult = DeleteRegKey (HKEY_LOCAL_MACHINE, "Software\_TEST", 64)

If strResult = 0 Then
WScript.Echo "Able to Delete Key : " & "HKEY_LOCAL_MACHINE\Software\_TEST"
Else
WScript.Echo "Not able to Delete Key"
'WScript.Quit
End If

'---------------------------------------------------
' Function Create Registry Key
'---------------------------------------------------

Function CreateRegKey(RootKey, KeyPath, RegType)

Dim oCtx, oLocator, oReg, oInParams, oOutParams 
Dim strKeyPath, Return

Set oCtx = CreateObject("WbemScripting.SWbemNamedValueSet") 
oCtx.Add "__ProviderArchitecture", RegType

Set oLocator = CreateObject("Wbemscripting.SWbemLocator") 
Set oReg = oLocator.ConnectServer("", "root\default", "", "", , , , oCtx).Get("StdRegProv")

Set oInParams = oReg.Methods_("CreateKey").InParameters 
oInParams.hDefKey = RootKey 
oInParams.sSubKeyName = KeyPath 

Set oOutParams = oReg.ExecMethod_("CreateKey", oInParams, , oCtx)

CreateRegKey = oOutParams.ReturnValue

set oCtx = Nothing 
set oLocator = Nothing 

End Function

'---------------------------------------------------
' Function Delete Registry Key
'---------------------------------------------------

Function DeleteRegKey(RootKey, KeyPath, RegType)

Dim oCtx, oLocator, oReg, oInParams, oOutParams 
Dim strKeyPath, Return

Set oCtx = CreateObject("WbemScripting.SWbemNamedValueSet") 
oCtx.Add "__ProviderArchitecture", RegType

Set oLocator = CreateObject("Wbemscripting.SWbemLocator") 
Set oReg = oLocator.ConnectServer("", "root\default", "", "", , , , oCtx).Get("StdRegProv")

Set oInParams = oReg.Methods_("DeleteKey").InParameters 
oInParams.hDefKey = RootKey 
oInParams.sSubKeyName = KeyPath 

Set oOutParams = oReg.ExecMethod_("DeleteKey", oInParams, , oCtx)

DeleteRegKey = oOutParams.ReturnValue

wscript.echo 

set oCtx = Nothing 
set oLocator = Nothing 

End Function

'---------------------------------------------------
' Function Read Registry String
'---------------------------------------------------

Function ReadRegStr (Method, RootKey, Key, Value, RegType) 
Dim oCtx, oLocator, oReg, oInParams, oOutParams 

Set oCtx = CreateObject("WbemScripting.SWbemNamedValueSet") 
oCtx.Add "__ProviderArchitecture", RegType 

Set oLocator = CreateObject("Wbemscripting.SWbemLocator") 
Set oReg = oLocator.ConnectServer("", "root\default", "", "", , , , oCtx).Get("StdRegProv") 

Set oInParams = oReg.Methods_(Method).InParameters 
oInParams.hDefKey = RootKey 
oInParams.sSubKeyName = Key 
oInParams.sValueName = Value 

Set oOutParams = oReg.ExecMethod_(Method, oInParams, , oCtx) 

ReadRegStr = oOutParams.sValue 

set oCtx = Nothing 
set oLocator = Nothing 
End Function

'---------------------------------------------------
' Function Write Registry String
'---------------------------------------------------

Function WriteRegStr (Method, RootKey, Key, ValueName, Value, RegType) 

Dim oCtx, oLocator, oReg, oInParams, oOutParams 

Set oCtx = CreateObject("WbemScripting.SWbemNamedValueSet") 
oCtx.Add "__ProviderArchitecture", RegType 

Set oLocator = CreateObject("Wbemscripting.SWbemLocator") 
Set oReg = oLocator.ConnectServer("", "root\default", "", "", , , , oCtx).Get("StdRegProv") 

Set oInParams = oReg.Methods_(Method).InParameters 
oInParams.hDefKey = RootKey 
oInParams.sSubKeyName = Key 
oInParams.sValueName = ValueName 
oInParams.sValue = Value 

Set oOutParams = oReg.ExecMethod_(Method, oInParams, , oCtx) 

WriteRegStr = oOutParams.ReturnValue

Set oCtx = Nothing 
Set oLocator = Nothing 

End Function

'---------------------------------------------------
' Function Delete Registry value
'---------------------------------------------------

Function DeleteSubKeyValue (RootKey, KeyPath, ValueName, RegType) 

Dim oCtx, oLocator, oReg, oInParams, oOutParams 

Set oCtx = CreateObject("WbemScripting.SWbemNamedValueSet") 
oCtx.Add "__ProviderArchitecture", RegType 

Set oLocator = CreateObject("Wbemscripting.SWbemLocator") 
Set oReg = oLocator.ConnectServer("", "root\default", "", "", , , , oCtx).Get("StdRegProv") 

Set oInParams = oReg.Methods_("DeleteValue").InParameters 
oInParams.hDefKey = RootKey
oInParams.sSubKeyName = KeyPath
oInParams.sValueName = ValueName

Set oOutParams = oReg.ExecMethod_("DeleteValue", oInParams, , oCtx) 

DeleteSubKeyValue = oOutParams.ReturnValue

Set oCtx = Nothing 
Set oLocator = Nothing 

End Function
Author

Tomas Johansson

I have worked in IT for more than 25 years, as a consultant, system administrator and technician. As a consultant, I have worked with system integration and development. I have also managed Windows client deployment for Swedish Armed Forces. Has a broad experience of most things in IT and still has a burning interest in learning new technologies and how to best use the technology.

Related Posts

Copy files to and from Hyper-V Guest

Using the PowerShell cmdlet Copy-VMFile To copy files to a VM using the Copy-VMFile cmdlet, we first have to enable Guest Services under Integration Services for a VM. Luckily, there is a PowerShell one-liner for...

Create NetNat Switch for Hyper-V

 In the latest versions in the Windows 10 client operating system, Microsoft already includes a “Default Virtual Switch”, which allows you to use Hyper-V NAT Networking, without doing any configuration changes. If you want to create an additional VM Switch which uses...

Powershell GUI to encrypt string

I’ve often found myself with tasks eligible for automation. Automating is great with PowerShell until you need to pass credentials into a script. I have seen many administrators put passwords into the body of their script. For testing purposes, this could considered a...

Copy files to and from Hyper-V Guest

Using the PowerShell cmdlet Copy-VMFile To copy files to a VM using the Copy-VMFile cmdlet, we first have to enable Guest Services under Integration Services for a VM. Luckily, there is a PowerShell one-liner for...

Create NetNat Switch for Hyper-V

 In the latest versions in the Windows 10 client operating system, Microsoft already includes a “Default Virtual Switch”, which allows you to use Hyper-V NAT Networking, without doing any configuration changes. If you want to create an additional VM Switch which uses...

Powershell GUI to encrypt string

I’ve often found myself with tasks eligible for automation. Automating is great with PowerShell until you need to pass credentials into a script. I have seen many administrators put passwords into the body of their script. For testing purposes, this could considered a...

Hyper-V GUI in Powershell

A small powershell script that i make to test powershell script with gui. In this gui a can see all my hyper-v guest i have. I can start/stop, connect and delete machines in this...

Comments

0 Comments

Follow Us