Accessing 64 bit registry from 32 bit application - c++

I need to open a registry entry "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{26A24AE4-039D-4CA4-87B4-2F86416024FF}" in c++. It contains the java 64 bit application. The full path of that registry entry is "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{26A24AE4-039D-4CA4-87B4-2F86416024FF}".
We can view this path through regedit. I use
returnStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{26A24AE4-039D-4CA4-87B4-2F86416024FF}"),
0, KEY_ALL_ACCESS, &hKey)
for open the registry; But it returns error value (2).
returnStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall")...
returns a success result. What can i do?

The registry keys for 32 bit and 64 applications are separated, you can't access (directly) the 64 bit registry from your 32 bit application. In your case the required hive doesn't exist in the 32 bit part of the registry then you can access the parent folder only.
From MSDN:
On 64-bit Windows, portions of the registry entries are stored separately for 32-bit application and 64-bit applications and mapped into separate logical registry views using the registry redirector and registry reflection, because the 64-bit version of an application may use different registry keys and values than the 32-bit version. There are also shared registry keys that are not redirected or reflected.
You can read the list on MSDN: Registry Keys Affected by WOW64. Unfortunately the SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall is not mentioned but it's affected too.
Solution
What you have to do is to explicitly ask RegOpenKeyEx to access the 64 bit part of the registry. This can be done adding the KEY_WOW64_64KEY flag to your call (you can access the 32 bit registry from a 64 bit application using KEY_WOW64_32KEY). Please note that this flag is not supported on Windows 2000 then if your application must be compatible with that (old) version you have to manage the case.
See this link on MSDN for further details: Accessing an Alternate Registry View.
To make it easy, simply change your call from:
returnStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{26A24AE4-039D-4CA4-87B4-2F86416024FF}"),
0, KEY_ALL_ACCESS, &hKey);
to:
returnStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{26A24AE4-039D-4CA4-87B4-2F86416024FF}"),
0, KEY_ALL_ACCESS | KEY_WOW64_64KEY, &hKey);
Note
Note that you may access the key only via its path without any flags using this HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall.
Because the Wow6432 node is the virtualized node used by WOW64 but you shouldn't rely on this, it's stable but it should be considered an implementation detail subject to change.
References
- Registry Virtualization on MSDN.
- Readers my find interesting tips on this post: http://poshcode.org/2470, it's for the PowerShell but it explains how to access WMI data (relative to the 64 bit registry part) from a 32 bit application.

Error 2 means the registry path does not exist.
Make sure that the key {26A24AE4-039D-4CA4-87B4-2F86416024FF} actually exists under SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall

Related

Not able to read registry key for 64 bit Windows system with RegOpenKeyEx

I am trying to read a value from "SOFTWARE\\Company name\\Application\\Instance" as a Administrator on Windows 64 bit for my application.
(RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Company name\\Application\\Instance", 0,KEY_QUERY_VALUE, &hKey) NE ERROR_SUCCESS)
I tried with KEY_WOW64_64KEY along with KEY_QUERY_VALUE in OR condition and I used __TEXT in front of the path (SOFTWARE\\Company name\\Application\\Instance) even though It is failing with error code 2("File not found") on Windows 64 bit system.
Can anyone tell me what could cause the problem.
Thanks in advance

Delete key from registry HKEY_LOCAL_MACHINE

I want to make uninstaller which should delete registry key from HKEY_LOCAL_MACHINE. Problem is that every time when i try delete location get LASTERROR 2, which is usually wrong name.
HKEY hKey = HKEY_LOCAL_MACHINE;
LSTATUS deletes = SHDeleteKey(hKey, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\NameOfApp\\");
if (deletes == ERROR_SUCCESS)
{
return true;
}
I have same code in C# which work, but C++ not. Also try as administrator, still nothing (with C# didn't put any special privileges and work).
OS: Windows 7, 64 bit.
Do you have any idea, what is happening?
On 64-bit Windows there are two separated registry trees. One for 32-bit applications and the other for 64-bit ones. It depends on your application (32-bit vs 64-bit) which tree is used when calling SHDeleteKey and that could be why it is working with c# but not with c++.
You can use RegDeleteKeyEx to explicitly define the tree you want to access.

SetNamedSecurityInfo for a 64Bit registry key from a 32Bit Process

I am trying to use SetNamedSecurityInfo from a 32Bit application to set ACLs for a 64Bit registry key. Due to SetNamedSecurityInfo limitation that has only KEY_WOW64_32KEY flag this is not possible.
Copy paste from some post on MSDN:
No way to access 64-bit registry keys in WOW64
Note: When getting or setting the ACLs in the registry using SetNamedSecurityInfo or GetNamedSecurityInfo there is no way to access the 64-bit registry keys from a 32-bit DLL or EXE. A new SE_OBJECT_TYPE named SE_REGISTRY_WOW64_64KEY is needed that sets KEY_WOW64_64KEY in NTMARTA.DLL.
This means, for example, there is no way to create a 32/64bit agnostic SETUP.EXE that can adjust registry security settings during an installation. The workaround is to create a 64-bit DLL or EXE and distribute bot
My Question:
There is any workaround to solve this problem without creating a 64Bit application?
Use SetSecurityInfo instead:
HKEY hSecKey;
if( RegOpenKeyEx( hHive, Subkey.c_str(), 0, ACCESS_SYSTEM_SECURITY | KEY_WOW64_64KEY, &hSecKey ) != ERROR_SUCCESS )
return;
SetSecurityInfo(hSecKey, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION, NULL, NULL, &pDacl, NULL);
You have to obtain SE_SECURITY_NAME privilege first to open a key with ACCESS_SYSTEM_SECURITY.

Cannot read Registry entry in C++

I have a registry entry I can't seem to read in C++, but it shows up in Regedit.
Using the following C++ snippet:
openResult=RegOpenKeyEx( HKEY_LOCAL_MACHINE, _TEXT("SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full"), 0, KEY_READ, &root);
readResult1=RegQueryValueEx(root, _TEXT("InstallPath"), NULL, NULL, data1, &size);
readResult2=RegQueryValueEx(root, _TEXT("fake_entry"), NULL, NULL, data2, &size);
I get Error 2, ERROR_FILE_NOT_FOUND for my second RegQueryValueEx() call.
As you can see in the image below, my fake_entry exists.
I created this entry via Regedit.
Microsoft's Registry Keys Affected by WOW64 does not include the location I'm trying to read, and as you can see in the picture below, my fake_entry is not in the Wow6432Node location.
Yes, I understand this isn't a registry location I should be changing. I stumbled upon this as I was debugging my code and am curious why my added fake_entry doesn't work.
Yes, I've read about Registry Redirector.
Yes, I've read this question.
Yes, I tried reading fake_entry at SOFTWARE\\Wow6432Node\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full with the same error.
Running Windows 7, 64 bit, C++ in Visual Studio 2010, using ASCII character encoding.
Am I misunderstanding the Registry Redirector?
Is there a problem with my code?
Are there some sort of permission settings on certain portions of the Registry? I'm obviously missing something. Please point me in the right direction.
Try
openResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE, _TEXT("SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full"), 0, KEY_READ|KEY_WOW64_64KEY, &root);
according to MSDN you should use either KEY_WOW64_64KEY or KEY_WOW64_32KEY for WOW64 access
You are misreading the table of keys affected by WOW64. From the very top of that page:
The following table lists registry keys that are redirected, shared by both 32-bit and 64-bit applications, or redirected and reflected on 64-bit Windows. Subkeys of the keys in this table inherit the parent key's behavior unless otherwise specified. If a key has no parent listed in this table, the key is shared.
The parent of your key is HKLM\Software which is redirected. So your key is also redirected. It inherits that from its parent, as the documentation that I quoted explains.
You'll need to read the 64 bit view using KEY_WOW64_64KEY.

How to allow 32 bit apps on 64 bit windows to execute 64 bit apps provided in Windows\System32

Say you have an app, that you want to provide users ability to browse the system32 directory and execute programs in (like telnet).
What is the best method for supporting this when you need to support XP onwards as a client and 2k onwards for server?
Having written all this up I wonder if it's just too much time/effort in providing a browse to do this, where they could just copy it from explorer. Still requires ability to launch.
I have found some discussion on Nynaeve.
So far it seems there are the following options
Create a sysnative folder in windows which will allow you to browse/execute 64 bit. Issues are:
only available in Vista/Longhorn, so no support for XP 64
leads to different path naming, can't use same path on multiple versions.
will be active for whole of windows, not just our app
may not (probably is not) appropriate to do when installing the app
allows to specify explicitly through path only which version of the app to launch if there is a 32 bit and 64 bit version
Use the windows API to temporarily disable the redirection when showing file lists or executing users run commands. Issues are:
Only available on 64 bit - have to mess with GetProcAddress
available only under certain service packs
must individually identify all locations that this should be implemented
user will need to provide seperate information about whether this is a 64 bit app or 32 bit.
If anybody had some example code which displayed a Windows OpenFile dialog (say using MFC CFileDialog) showing nativly for XP/Vista and allowing the viewing of 64 bit system32 directory, that would be awesome.
If anybody had an example of launching the named app, that would also be great!
Edit:
Currently we use CreateProcess for launching the app (which is failing).
err = CreateProcess((wchar_t*)exeName.c_str(), (wchar_t*)cmdLine.c_str(), NULL, NULL, FALSE, CREATE_SEPARATE_WOW_VDM, NULL, workingDir.c_str(), &startupInfo, &processInfo);
I've gone with option 2,
For those who might be interested; here is my quick hack at a scoped version of managing the disabling of Wow64 redirection based on notes from MS. Will redirect if the API is available, expects that kernel32.dll is already available.
class Wow64RedirectOff {
typedef BOOL (WINAPI *FN_Wow64DisableWow64FsRedirection) ( __out PVOID *OldValue );
typedef BOOL (WINAPI *FN_Wow64RevertWow64FsRedirection) ( __in PVOID OldValue );
public:
Wow64RedirectOff() {
LPFN_Disable = (FN_Wow64DisableWow64FsRedirection)GetProcAddress(
GetModuleHandle(TEXT("kernel32")),"Wow64DisableWow64FsRedirection");
if( LPFN_Disable ) {
LPFN_Disable(&OldValue);
}
}
~Wow64RedirectOff() {
if( LPFN_Disable ) {
FN_Wow64RevertWow64FsRedirection LPFN_Revert = (FN_Wow64RevertWow64FsRedirection)GetProcAddress(
GetModuleHandle(TEXT("kernel32")),"Wow64RevertWow64FsRedirection");
if( LPFN_Revert ) {
LPFN_Revert(OldValue);
}
}
}
private:
FN_Wow64DisableWow64FsRedirection LPFN_Disable;
PVOID OldValue;
};
And thus usage would be
Wow64RedirectOff scopedRedirect;
//CFileOpen
//CreateProcess
Are you getting redirected to Windows/SysWoW64? I can launch 64-bit apps from Windows/System32 from an OpenFile in a 32-bit managed executable.