SetNamedSecurityInfo for a 64Bit registry key from a 32Bit Process - c++

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.

Related

C++ read a Registry entry in SOFTWARE\WOW6432 from a 64-bit app

I've got some 32-bit C++ code to read a Key/Value pair from the Registry as follows:
// Get a handle to the required key
HKEY hKey;
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\MyKey", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
// Look up the value for the key
bOK = (RegQueryValueEx(hKey, szKey, NULL, NULL, (PBYTE)szValue, &dwMax) == ERROR_SUCCESS);
// Release the handle
RegCloseKey(hKey);
}
As it's a 32-bit app it reads from SOFTWARE\WOW6432Node\MyKey
This was working fine until I ported the app to 64-bit, so it now reads from SOFTWARE\MyKey.
My installer won't let me put entries into both the 32-bit and 64-bit parts of the Registry, so I need the 64-bit app to go on getting its data from WOW6432Node.
Does anyone know how to do this?
Many thanks
Tony Reynolds
As documented under 32-bit and 64-bit Application Data in the Registry:
The KEY_WOW64_64KEY and KEY_WOW64_32KEY flags enable explicit access to the 64-bit registry view and the 32-bit view, respectively. For more information, see Accessing an Alternate Registry View.
The latter link explains that
These flags can be specified in the samDesired parameter of the following registry functions:
RegCreateKeyEx
RegDeleteKeyEx
RegOpenKeyEx
The following code accomplishes what you are asking for:
// Get a handle to the required key
HKEY hKey;
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\MyKey", 0, KEY_READ | KEY_WOW64_32KEY, &hKey) == ERROR_SUCCESS)
{
// ...
}

Reading the Windows registry key "SOFTWARE\Microsoft\Windows\CurrentVersion\Run" using RegGetValue() returns error code 2

Reading the Windows registry key "SOFTWARE\Microsoft\Windows\CurrentVersion\Run" using RegGetValue() returns error code 2.
I've been sitting for hours debugging this problem, but haven't found a solution.
Here is the code that I use to retrieve the registry value named "test":
long result = RegGetValue(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"), TEXT("test"), RRF_RT_ANY, &dwType, (PVOID)&buff, &size);
Below is a picture that I've added the registry value "test" to the Run key (mentioned above).
The error code I get is 2 which represents an invalid file.
It should be mentioned that the local host is running Windows 10 Pro x64.
What could be the source of this confusion?
Modified code:
I still get the error code 2 after using the KEY_WOW64_64KEY flag.
RegCreateKeyEx(
HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"),
NULL,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS | KEY_WOW64_64KEY,
NULL,
&hKey,
&dwStatus)
long result = RegGetValue(hKey, NULL, TEXT("test"), RRF_RT_ANY, &dwType, (PVOID)&buff, &size);
Problem
You are most probably trying to access the 64-bit registry view from a 32-bit application.
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.
Solution
You can rebuild your application in x64 mode or you can specify which view of the registry you require.
HKEY key;
RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"), 0, KEY_ALL_ACCESS | KEY_WOW64_64KEY, &key);
long result = RegGetValue(key, nullptr, TEXT("test"), RRF_RT_ANY, &dwType, (PVOID)&buff, &size);
For more info: Accessing an Alternate Registry View

RegOpenKeyEx access denied reading HKEY_LOCAL_MACHINE

In Windows 7 (32 bit), I consistently get error 5 (access denied) when I call ::RegOpenKeyEx on HKEY_LOCAL_MACHINE if I am not running in Administrator mode.
This is my code:
result = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\MyCompany\\MyApp"), 0, KEY_QUERY_VALUE, &keySoftware)
I am trying to build an app that can be installed for an entire machine as opposed to a specific user. Therefore my installer (which does run in Administrator mode) writes to HKEY_LOCAL_MACHINE, and the installer works fine.
I'd like my app to be able to read the data that my installer has put into the registry. I don't want to change any of the registry data. I have also tried using KEY_READ and KEY_EXECUTE instead of KEY_QUERY_VALUE. But it seems that no matter what I do, I cannot read from HKEY_LOCAL_MACHINE without using an elevated status. What am I missing here?
Your installer needs to adjust the security permissions on your Registry key so that non-admin users are allowed to access it. Have a look at RegSetKeySecurity(), or your installer's equivalent, or any number of command-line tools that are available. You can create a DACL that enables read-only access for the Everyone user group, or for specific user accounts.
Update: since you are using Inno Setup, try this in your Registry setup:
[Registry]
Root: HKLM; Subkey: "Software\MyCompany\MyApp"; Permissions: everyone-read
Or:
[Registry]
Root: HKLM; Subkey: "Software\MyCompany\MyApp"; Permissions: users-read
Your code as I was writing this answer:
result = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\MyCompany\\MyApp"), 0, KEY_QUERY_VALUE, &keySoftware)
RegOpenKeyEx doesn't support general paths, just direct key names.
To use it you would have to iterate your way down the hierarchy.
SHRegOpenUSKey is one alternative that does support general paths:
HUSKEY keySoftware;
LSTATUS const result = ::SHRegOpenUSKey(
L"Software\\Microsoft\\MediaPlayer", KEY_QUERY_VALUE, 0, &keySoftware, TRUE
);

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.

Accessing 64 bit registry from 32 bit application

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