-
Jan 8th, 2013, 07:44 AM
#1
Thread Starter
Addicted Member
access 64 bit registry from 32 bit app
I have a 32 bit VB6 application which checks a registry path of a 64 bit application installed in a 64 bit machine.So if try to access HKEY_LOCAL_MACHINE\SOFTWARE then it will be redirected to HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node. So this problem is by nature of the windows registry that 32 bit application will be accessing wow6432node. So how can avoid redirecting to wow6432node and instead access HKEY_LOCAL_MACHINE\SOFTWARE.
-
Jan 8th, 2013, 07:51 AM
#2
Re: access 64 bit registry from 32 bit app
Should be several threads on this here if you search. Sample code too.
Also see Accessing an Alternate Registry View (Windows)
-
Jun 15th, 2015, 11:11 AM
#3
New Member
Re: access 64 bit registry from 32 bit app
I know this thread is old but I have been trying to figure this out for several months now and am even having trouble finding some good examples. I need to force my application to read and write to HKLM regardless of if it's 64 bit or 32 bit.
Could someone please provide me with some links to valid examples? At this point I will gladly pay for help as well.
Thanks
-
Jun 15th, 2015, 02:34 PM
#4
Re: access 64 bit registry from 32 bit app
Originally Posted by Mike VB
I need to force my application to read and write to HKLM regardless of if it's 64 bit or 32 bit.
dilettante already gave a link to the MSDN topic that discusses how it can be done. Here's an excerpt of the relevant parts:
Originally Posted by MSDN
Accessing an Alternate Registry View
By default, a 32-bit application running on WOW64 accesses the 32-bit registry view and a 64-bit application accesses the 64-bit registry view. The following flags enable 32-bit applications to access redirected keys in the 64-bit registry view and 64-bit applications to access redirected keys in the 32-bit registry view. These flags have no effect on shared registry keys. For more information, see Registry Keys Affected by WOW64.
Flag name |
Value |
Description |
KEY_WOW64_64KEY |
0x0100 |
Access a 64-bit key from either a 32-bit or 64-bit application. |
KEY_WOW64_32KEY |
0x0200 |
Access a 32-bit key from either a 32-bit or 64-bit application. |
Originally Posted by Mike VB
Could someone please provide me with some links to valid examples?
The example here shows how to open and delete a 64-bit key and its subkeys that are under HKLM.
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)
-
Jun 15th, 2015, 02:49 PM
#5
New Member
Re: access 64 bit registry from 32 bit app
Originally Posted by Bonnie West
dilettante already gave a link to the MSDN topic that discusses how it can be done. Here's an excerpt of the relevant parts:
The example here shows how to open and delete a 64-bit key and its subkeys that are under HKLM.
Thanks, Bonnie. Do you know of any examples for writing to HKLM in 64 bit?
-
Jun 15th, 2015, 03:05 PM
#6
Re: access 64 bit registry from 32 bit app
Originally Posted by Mike VB
Do you know of any examples for writing to HKLM in 64 bit?
Well, I could search for examples, ... or I could make one for you. Can you describe the specific details of your problem?
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)
-
Jun 15th, 2015, 03:14 PM
#7
New Member
Re: access 64 bit registry from 32 bit app
Originally Posted by Bonnie West
Well, I could search for examples, ... or I could make one for you. Can you describe the specific details of your problem?
Thanks, Bonnie. I wrote an application that is a companion application to another application (not written by me). The application not written by me was designed specifically to write values to HKLM and not Wow6432Node despite being on a 64 bit or 32 bit machine (for his own reasons, IDK why). Basically I need to read and write registry values to HKLM\Software\x\x regardless of if my application is being run on a 64 bit or 32 bit machine. My application is used by thousands of people around the world (literally) and is offered for free, but is not working properly anymore since the other application's developer changed the registry structure.
Thanks very much for your help.
-
Jun 15th, 2015, 07:51 PM
#8
Re: access 64 bit registry from 32 bit app
OK, the following example might help you get going:
Code:
Option Explicit 'In a standard (.BAS) module
Private Const ERROR_SUCCESS As Long = 0
Private Const HKEY_LOCAL_MACHINE As Long = &H80000002
Private Const KEY_ALL_ACCESS As Long = &HF003F
Private Const KEY_WOW64_32KEY As Long = &H200
Private Const KEY_WOW64_64KEY As Long = &H100
Private Const REG_OPTION_NON_VOLATILE As Long = &H0
Private Const REG_SZ As Long = 1
Private Const DUMMY_SUBKEY As String = "SOFTWARE\0 Dummy Subkey"
Private Const DUMMY_VALUE_NAME As String = "Dummy Value Name"
Private Const DUMMY_DATA As String = "Dummy Data"
Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long
Private Declare Function RegCreateKeyExW Lib "advapi32.dll" (ByVal hKey As Long, ByVal lpSubKey As Long, ByVal Reserved As Long, ByVal lpClass As Long, ByVal dwOptions As Long, ByVal samDesired As Long, ByVal lpSecurityAttributes As Long, ByRef phkResult As Long, Optional ByRef lpdwDisposition As Long) As Long
Private Declare Function RegDeleteKeyExW Lib "advapi32.dll" (ByVal hKey As Long, ByVal lpSubKey As Long, ByVal samDesired As Long, Optional ByVal Reserved As Long) As Long
Private Declare Function RegDeleteValueW Lib "advapi32.dll" (ByVal hKey As Long, Optional ByVal lpValueName As Long) As Long
Private Declare Function RegQueryValueExW Lib "advapi32.dll" (ByVal hKey As Long, Optional ByVal lpValueName As Long, Optional ByVal lpReserved As Long, Optional ByRef lpType As Long, Optional ByVal lpData As Long, Optional ByRef lpcbData As Long) As Long
Private Declare Function RegSetValueExW Lib "advapi32.dll" (ByVal hKey As Long, ByVal lpValueName As Long, ByVal Reserved As Long, ByVal dwType As Long, ByRef lpData As Any, ByVal cbData As Long) As Long
Private Declare Function SysReAllocStringLen Lib "oleaut32.dll" (ByVal pBSTR As Long, Optional ByVal pszStrPtr As Long, Optional ByVal Length As Long) As Long
Private Sub Main()
Dim hKey As Long, nSize As Long, RV As Long, sBuffer As String
'Create a registry key (or open it if it already exists).
'KEY_WOW64_64KEY indicates that all operations on a 64-bit OS should be
'done on the 64-bit registry view. That flag is ignored on a 32-bit OS.
'The app must be running elevated if it's going to modify/delete keys under HKLM,
'else the operation(s) will be redirected to HKCU\Software\Classes\VirtualStore.
If RegCreateKeyExW(HKEY_LOCAL_MACHINE, StrPtr(DUMMY_SUBKEY), 0&, 0&, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS Or KEY_WOW64_64KEY, 0&, hKey) = ERROR_SUCCESS Then
'Create/write a value and its corresponding data
nSize = LenB(DUMMY_DATA) + 2& '<-- Include size of terminating Unicode null char
If RegSetValueExW(hKey, StrPtr(DUMMY_VALUE_NAME), 0&, REG_SZ, ByVal StrPtr(DUMMY_DATA), nSize) = ERROR_SUCCESS Then
'Retrieve/read the previously written value
'Request the required buffer size first
If RegQueryValueExW(hKey, StrPtr(DUMMY_VALUE_NAME), , , , nSize) = ERROR_SUCCESS Then
'Allocate the exact buffer size required
SysReAllocStringLen VarPtr(sBuffer), , nSize \ 2& - 1& 'nSize is in Bytes & includes the terminating Unicode null char
'Retrieve the value and see whether it is indeed the same data
RV = RegQueryValueExW(hKey, StrPtr(DUMMY_VALUE_NAME), , , StrPtr(sBuffer), nSize): Debug.Assert RV = ERROR_SUCCESS
Debug.Assert sBuffer = DUMMY_DATA
End If
'Delete the value and its corresponding data
RV = RegDeleteValueW(hKey, StrPtr(DUMMY_VALUE_NAME)): Debug.Assert RV = ERROR_SUCCESS
End If
RV = RegCloseKey(hKey): Debug.Assert RV = ERROR_SUCCESS
'Remove the subkey from the 64-bit view of the registry. KEY_WOW64_64KEY is ignored on a 32-bit OS.
RV = RegDeleteKeyExW(HKEY_LOCAL_MACHINE, StrPtr(DUMMY_SUBKEY), KEY_WOW64_64KEY): Debug.Assert RV = ERROR_SUCCESS
End If
End Sub
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)
-
Jun 16th, 2015, 11:48 AM
#9
New Member
Re: access 64 bit registry from 32 bit app
Originally Posted by Bonnie West
OK, the following example might help you get going:
Code:
Option Explicit 'In a standard (.BAS) module
Private Const ERROR_SUCCESS As Long = 0
Private Const HKEY_LOCAL_MACHINE As Long = &H80000002
Private Const KEY_ALL_ACCESS As Long = &HF003F
Private Const KEY_WOW64_32KEY As Long = &H200
Private Const KEY_WOW64_64KEY As Long = &H100
Private Const REG_OPTION_NON_VOLATILE As Long = &H0
Private Const REG_SZ As Long = 1
Private Const DUMMY_SUBKEY As String = "SOFTWARE\0 Dummy Subkey"
Private Const DUMMY_VALUE_NAME As String = "Dummy Value Name"
Private Const DUMMY_DATA As String = "Dummy Data"
Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long
Private Declare Function RegCreateKeyExW Lib "advapi32.dll" (ByVal hKey As Long, ByVal lpSubKey As Long, ByVal Reserved As Long, ByVal lpClass As Long, ByVal dwOptions As Long, ByVal samDesired As Long, ByVal lpSecurityAttributes As Long, ByRef phkResult As Long, Optional ByRef lpdwDisposition As Long) As Long
Private Declare Function RegDeleteKeyExW Lib "advapi32.dll" (ByVal hKey As Long, ByVal lpSubKey As Long, ByVal samDesired As Long, Optional ByVal Reserved As Long) As Long
Private Declare Function RegDeleteValueW Lib "advapi32.dll" (ByVal hKey As Long, Optional ByVal lpValueName As Long) As Long
Private Declare Function RegQueryValueExW Lib "advapi32.dll" (ByVal hKey As Long, Optional ByVal lpValueName As Long, Optional ByVal lpReserved As Long, Optional ByRef lpType As Long, Optional ByVal lpData As Long, Optional ByRef lpcbData As Long) As Long
Private Declare Function RegSetValueExW Lib "advapi32.dll" (ByVal hKey As Long, ByVal lpValueName As Long, ByVal Reserved As Long, ByVal dwType As Long, ByRef lpData As Any, ByVal cbData As Long) As Long
Private Declare Function SysReAllocStringLen Lib "oleaut32.dll" (ByVal pBSTR As Long, Optional ByVal pszStrPtr As Long, Optional ByVal Length As Long) As Long
Private Sub Main()
Dim hKey As Long, nSize As Long, RV As Long, sBuffer As String
'Create a registry key (or open it if it already exists).
'KEY_WOW64_64KEY indicates that all operations on a 64-bit OS should be
'done on the 64-bit registry view. That flag is ignored on a 32-bit OS.
'The app must be running elevated if it's going to modify/delete keys under HKLM,
'else the operation(s) will be redirected to HKCU\Software\Classes\VirtualStore.
If RegCreateKeyExW(HKEY_LOCAL_MACHINE, StrPtr(DUMMY_SUBKEY), 0&, 0&, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS Or KEY_WOW64_64KEY, 0&, hKey) = ERROR_SUCCESS Then
'Create/write a value and its corresponding data
nSize = LenB(DUMMY_DATA) + 2& '<-- Include size of terminating Unicode null char
If RegSetValueExW(hKey, StrPtr(DUMMY_VALUE_NAME), 0&, REG_SZ, ByVal StrPtr(DUMMY_DATA), nSize) = ERROR_SUCCESS Then
'Retrieve/read the previously written value
'Request the required buffer size first
If RegQueryValueExW(hKey, StrPtr(DUMMY_VALUE_NAME), , , , nSize) = ERROR_SUCCESS Then
'Allocate the exact buffer size required
SysReAllocStringLen VarPtr(sBuffer), , nSize \ 2& - 1& 'nSize is in Bytes & includes the terminating Unicode null char
'Retrieve the value and see whether it is indeed the same data
RV = RegQueryValueExW(hKey, StrPtr(DUMMY_VALUE_NAME), , , StrPtr(sBuffer), nSize): Debug.Assert RV = ERROR_SUCCESS
Debug.Assert sBuffer = DUMMY_DATA
End If
'Delete the value and its corresponding data
RV = RegDeleteValueW(hKey, StrPtr(DUMMY_VALUE_NAME)): Debug.Assert RV = ERROR_SUCCESS
End If
RV = RegCloseKey(hKey): Debug.Assert RV = ERROR_SUCCESS
'Remove the subkey from the 64-bit view of the registry. KEY_WOW64_64KEY is ignored on a 32-bit OS.
RV = RegDeleteKeyExW(HKEY_LOCAL_MACHINE, StrPtr(DUMMY_SUBKEY), KEY_WOW64_64KEY): Debug.Assert RV = ERROR_SUCCESS
End If
End Sub
Thank you VERY much! I am playing around with it now and it looks like this will be a huge help.
Thanks again.
-
Aug 3rd, 2016, 02:35 PM
#10
New Member
Re: access 64 bit registry from 32 bit app
This solution is great, except for one small part at the end:
'Remove the subkey from the 64-bit view of the registry. KEY_WOW64_64KEY is ignored on a 32-bit OS.
RV = RegDeleteKeyExW(HKEY_LOCAL_MACHINE, StrPtr(DUMMY_SUBKEY), KEY_WOW64_64KEY): Debug.Assert RV = ERROR_SUCCESS
On XP 32-bit, RegDeleteKeyEx doesn't exist in advapi32.dll. It was introduced in XP-64 and newer OSes (newer versions of advapi32.dll, specifically from the 5.1.x versions that didn't have it, to the 6.1.x version that do). So I came up with this alternative:
'Remove the subkey from the 64-bit view of the registry. KEY_WOW64_64KEY is ignored on a 32-bit OS.
On Error Resume Next
RV = RegDeleteKeyExW(HKEY_LOCAL_MACHINE, StrPtr(DUMMY_SUBKEY), KEY_WOW64_64KEY): Debug.Assert RV = ERROR_SUCCESS
If Err Then
'On older OS, RegDeleteKeyEx doesn't exist. Use regular RegDeleteKey()
RV = RegDeleteKey(HKEY_LOCAL_MACHINE, DUMMY_SUBKEY): Debug.Assert RV = ERROR_SUCCESS
End If
Is there an easier / better way? (In case it wasn't clear, I intend to run this code on everything from XP 32-bit to Windows 10 64-bit, and also the servers from Server 2003 to Server 2012 R2.)
Last edited by MickeyF; Aug 3rd, 2016 at 04:10 PM.
-
Aug 4th, 2016, 09:48 AM
#11
Re: access 64 bit registry from 32 bit app
Originally Posted by MickeyF
On XP 32-bit, RegDeleteKeyEx doesn't exist in advapi32.dll. It was introduced in XP-64 and newer OSes (newer versions of advapi32.dll, specifically from the 5.1.x versions that didn't have it, to the 6.1.x version that do). So I came up with this alternative:
Thanks for the bug report and the suggested fix!
Originally Posted by MickeyF
Is there an easier / better way?
I think it's already the best solution. I couldn't find a better Registry API function than those 2 functions.
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)
-
Aug 4th, 2016, 11:37 AM
#12
New Member
Re: access 64 bit registry from 32 bit app
I was really thinking along the lines of using GetProcAddress to see if the function exists, which is a little cleaner, but this is quicker and does have one other major advantage - it already works!
-
Aug 4th, 2016, 12:40 PM
#13
Re: access 64 bit registry from 32 bit app
Originally Posted by MickeyF
I was really thinking along the lines of using GetProcAddress to see if the function exists, which is a little cleaner, ...
It is my understanding that VB6 already internally calls GetProcAddress the 1st time that a Declare'd API function is called (VB6 caches the return value and uses it the next time the function is called). Personally, I prefer the OERN approach because it is less code, GetProcAddress is called only once per API function and EXE size is slightly reduced because there is at least 1 less Unicode string instance of the API function's name in the EXE.
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|