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.

1Option Explicit
2
3'---------------------------------------------------
4' Declared Constants
5'---------------------------------------------------
6
7Const wbemFlagReturnImmediately = &h10
8Const wbemFlagForwardOnly = &h20
9Const Success = 0
10Const Failure = 1
11Const HKEY_LOCAL_MACHINE = &H80000002
12Const Read_REG_SZ = "GetStringValue"
13Const Write_REG_SZ = "SetStringValue"
14Const Read_REG_DWORD = "GetDWORDValue"
15Const Write_REG_DWORD = "SetDWORDValue"
16
17'---------------------------------------------------
18' Declared Variables
19'---------------------------------------------------
20
21Dim strResult, TextString1, TextString2
22
23'---------------------------------------------------
24' Parameters for Funktions ReadRegStr and WriteRegStr
25'---------------------------------------------------
26
27' Reads a REG_SZ and REG_DWORD value from the local computer's registry using WMI.
28' Parameters:
29' Method - What type of value going to write (GetStringValue, SetStringValue, GetDWORDValue, SetDWORDValue)
30' RootKey - The registry hive (HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CURRENT_CONFIG
31' Key - The key that contains the desired value.
32' Value - The value that you want to get.
33' RegType - The registry bitness: 32 or 64
34
35'---------------------------------------------------
36' Create _TEST registry key in 64-bit Registry
37'---------------------------------------------------
38
39WScript.Echo "---------------------------------------------------"
40WScript.Echo " Creating _TEST key in 64-bit Registry "
41WScript.Echo "---------------------------------------------------"
42
43strResult = CreateRegKey (HKEY_LOCAL_MACHINE, "Software\_TEST", 64)
44
45If strResult = 0 Then
46WScript.Echo "Able to Create Key : " & "HKEY_LOCAL_MACHINE\Software\_TEST"
47Else
48WScript.Echo "Not able to Create Key"
49'WScript.Quit
50End If
51
52'---------------------------------------------------
53' Set _TEST registry values in 64-bit Registry
54'---------------------------------------------------
55
56WScript.Echo "---------------------------------------------------"
57WScript.Echo " Writing in 64-bit Registry "
58WScript.Echo "---------------------------------------------------"
59
60' Writing Testvalue1
61TextString1 = "Test of writing value 1"
62strResult = WriteRegStr (Write_REG_SZ, HKEY_LOCAL_MACHINE, "Software\_TEST", "SubKey1", TextString1, 64)
63
64If strResult = 0 and debug = 1 Then
65WScript.Echo "Able to Write Value : " & "SubKey1" & " = "& TextString1
66Else
67WScript.Echo "Not able to Write Value"
68'WScript.Quit
69End If
70
71' Writing Testvalue2
72TextString2 = "Test of writing value 2"
73strResult = WriteRegStr (Write_REG_SZ, HKEY_LOCAL_MACHINE, "Software\_TEST", "SubKey2", TextString2, 64)
74
75If strResult = 0 Then
76WScript.Echo "Able to Write Value : " & "SubKey2" & " = "& TextString2
77Else
78WScript.Echo "Not able to Write Value"
79'WScript.Quit
80End If
81
82'---------------------------------------------------
83' Delete a SubKey value in 64-bit Registry
84'---------------------------------------------------
85
86strResult = DeleteSubKeyValue (HKEY_LOCAL_MACHINE, "Software\_TEST", "SubKey1", 64)
87
88If strResult = 0 Then
89WScript.Echo "Able to Delete SubKey value : " & "HKEY_LOCAL_MACHINE\Software\_TEST\SubKey1"
90Else
91WScript.Echo "Not able to Delete SubKey value"
92'WScript.Quit
93End If
94
95'---------------------------------------------------
96' Delete _TEST registry key in 64-bit Registry
97'---------------------------------------------------
98
99WScript.Echo "---------------------------------------------------"
100WScript.Echo " Delete _TEST key in 64-bit Registry "
101WScript.Echo "---------------------------------------------------"
102
103strResult = DeleteRegKey (HKEY_LOCAL_MACHINE, "Software\_TEST", 64)
104
105If strResult = 0 Then
106WScript.Echo "Able to Delete Key : " & "HKEY_LOCAL_MACHINE\Software\_TEST"
107Else
108WScript.Echo "Not able to Delete Key"
109'WScript.Quit
110End If
111
112'---------------------------------------------------
113' Function Create Registry Key
114'---------------------------------------------------
115
116Function CreateRegKey(RootKey, KeyPath, RegType)
117
118Dim oCtx, oLocator, oReg, oInParams, oOutParams
119Dim strKeyPath, Return
120
121Set oCtx = CreateObject("WbemScripting.SWbemNamedValueSet")
122oCtx.Add "__ProviderArchitecture", RegType
123
124Set oLocator = CreateObject("Wbemscripting.SWbemLocator")
125Set oReg = oLocator.ConnectServer("", "root\default", "", "", , , , oCtx).Get("StdRegProv")
126
127Set oInParams = oReg.Methods_("CreateKey").InParameters
128oInParams.hDefKey = RootKey
129oInParams.sSubKeyName = KeyPath
130
131Set oOutParams = oReg.ExecMethod_("CreateKey", oInParams, , oCtx)
132
133CreateRegKey = oOutParams.ReturnValue
134
135set oCtx = Nothing
136set oLocator = Nothing
137
138End Function
139
140'---------------------------------------------------
141' Function Delete Registry Key
142'---------------------------------------------------
143
144Function DeleteRegKey(RootKey, KeyPath, RegType)
145
146Dim oCtx, oLocator, oReg, oInParams, oOutParams
147Dim strKeyPath, Return
148
149Set oCtx = CreateObject("WbemScripting.SWbemNamedValueSet")
150oCtx.Add "__ProviderArchitecture", RegType
151
152Set oLocator = CreateObject("Wbemscripting.SWbemLocator")
153Set oReg = oLocator.ConnectServer("", "root\default", "", "", , , , oCtx).Get("StdRegProv")
154
155Set oInParams = oReg.Methods_("DeleteKey").InParameters
156oInParams.hDefKey = RootKey
157oInParams.sSubKeyName = KeyPath
158
159Set oOutParams = oReg.ExecMethod_("DeleteKey", oInParams, , oCtx)
160
161DeleteRegKey = oOutParams.ReturnValue
162
163wscript.echo
164
165set oCtx = Nothing
166set oLocator = Nothing
167
168End Function
169
170'---------------------------------------------------
171' Function Read Registry String
172'---------------------------------------------------
173
174Function ReadRegStr (Method, RootKey, Key, Value, RegType)
175Dim oCtx, oLocator, oReg, oInParams, oOutParams
176
177Set oCtx = CreateObject("WbemScripting.SWbemNamedValueSet")
178oCtx.Add "__ProviderArchitecture", RegType
179
180Set oLocator = CreateObject("Wbemscripting.SWbemLocator")
181Set oReg = oLocator.ConnectServer("", "root\default", "", "", , , , oCtx).Get("StdRegProv")
182
183Set oInParams = oReg.Methods_(Method).InParameters
184oInParams.hDefKey = RootKey
185oInParams.sSubKeyName = Key
186oInParams.sValueName = Value
187
188Set oOutParams = oReg.ExecMethod_(Method, oInParams, , oCtx)
189
190ReadRegStr = oOutParams.sValue
191
192set oCtx = Nothing
193set oLocator = Nothing
194End Function
195
196'---------------------------------------------------
197' Function Write Registry String
198'---------------------------------------------------
199
200Function WriteRegStr (Method, RootKey, Key, ValueName, Value, RegType)
201
202Dim oCtx, oLocator, oReg, oInParams, oOutParams
203
204Set oCtx = CreateObject("WbemScripting.SWbemNamedValueSet")
205oCtx.Add "__ProviderArchitecture", RegType
206
207Set oLocator = CreateObject("Wbemscripting.SWbemLocator")
208Set oReg = oLocator.ConnectServer("", "root\default", "", "", , , , oCtx).Get("StdRegProv")
209
210Set oInParams = oReg.Methods_(Method).InParameters
211oInParams.hDefKey = RootKey
212oInParams.sSubKeyName = Key
213oInParams.sValueName = ValueName
214oInParams.sValue = Value
215
216Set oOutParams = oReg.ExecMethod_(Method, oInParams, , oCtx)
217
218WriteRegStr = oOutParams.ReturnValue
219
220Set oCtx = Nothing
221Set oLocator = Nothing
222
223End Function
224
225'---------------------------------------------------
226' Function Delete Registry value
227'---------------------------------------------------
228
229Function DeleteSubKeyValue (RootKey, KeyPath, ValueName, RegType)
230
231Dim oCtx, oLocator, oReg, oInParams, oOutParams
232
233Set oCtx = CreateObject("WbemScripting.SWbemNamedValueSet")
234oCtx.Add "__ProviderArchitecture", RegType
235
236Set oLocator = CreateObject("Wbemscripting.SWbemLocator")
237Set oReg = oLocator.ConnectServer("", "root\default", "", "", , , , oCtx).Get("StdRegProv")
238
239Set oInParams = oReg.Methods_("DeleteValue").InParameters
240oInParams.hDefKey = RootKey
241oInParams.sSubKeyName = KeyPath
242oInParams.sValueName = ValueName
243
244Set oOutParams = oReg.ExecMethod_("DeleteValue", oInParams, , oCtx)
245
246DeleteSubKeyValue = oOutParams.ReturnValue
247
248Set oCtx = Nothing
249Set oLocator = Nothing
250
251End Function