I used RegCreateKeyEx from a win32 application(VisualStudio 2008) in 64 bit windows(Project built with target x64). It was able to create a registry entry. Now I have a dll file (Project built with target x64) which too wanna create registry entry but my dll is returning error code 5(Yeah! its a sign of access denied). My samDesired flag have KEY_ALL_Access + In linker->manifestfile->run as administrator chosen which still fails with error code 5. Whereas it works perfectly in 32bit windows(Project built with target x86). Am i missing something?
NOTE: I'm trying to create an entry at HKEY_LOCAL_MACHINE.
You can't create a registry key in HKEY_LOCAL_MACHINE because this isn't a hive. You need to put your key in HKEY_LOCAL_MACHINE\Software or (less probably) one of the other hives.
I don't know why this appeared to work when you were running 32-bit code in WOW64, perhaps this is a side-effect of the way the 32-bit view of the registry is presented.
Related
I have a batch file that copies a directory to a new location, creates 2 other .bat files, 2 .json files, and Inserts Registry Keys. When running the batch script for the command line, I get no errors and all desired outcomes. While running it from the post-build event command-line, I get no errors, but I'm missing the Registry entries. Co-worker suggested that this could be due to Visual Studio not having Admin permissions whereas the command line can. My question is: is there a way (without running Visual Studio as an admin) to elevate permissions for a post-build event? If you're wondering why not just run VS as admin, it's because this solution is shared via TFS, and not all my co-workers will know to run their instance of VS as admin for this one particular solution. I've Googled away with nothing to show for it. Thanks in advance for help! Here's the Post-build event command line I'm using. Again I know it works... it just doesn't plop the Registry values. CMD does. PS. Using VS 2013 on Windows 7
if $(ConfigurationName) == Debug call "$(ProjectDir)BatchFiles\DebugHelper.bat" "$(TargetDir)" C:\CEC\Batch\Test\
This is from Windows SDK about redirection (there is also reflected and shared)
Registry Redirector
The registry redirector isolates 32-bit and 64-bit applications by providing separate logical views of key portions of the registry on WOW64. The registry redirector intercepts 32-bit registry calls to each logical registry view and maps them to the corresponding physical registry location. The redirection process is transparent to the application. Therefore, a 32-bit application can access registry data as if it were running on 32-bit Windows even if the data is stored in a different location on 64-bit Windows.
Redirection is enabled for the following registry keys:
HKEY_LOCAL_MACHINE\Software
HKEY_USERS\*\Software\Classes
HKEY_USERS\*_Classes
Note * indicates a match for all user security IDs (SID).
The following scenario illustrates the use of these logical views:
A 32-bit application checks for the existance of the following registry key: HKEY_LOCAL_MACHINE\Software\Hello. If the key does not exist, it creates it with a default value of "Hello 32-bit world"; otherwise, it reads and displays the value.
The same application is modified to write "Hello 64-bit world" instead of "Hello 32-bit world" and recompiled as a 64-bit application.
When the 32-bit application is run on 64-bit Windows, it displays "Hello 32-bit world". When the 64-bit application is run, it displays "Hello 64-bit world". Both applications call the same registry functions with the same predefined handle and the same key name; the difference is that each application operates on its logical view of registry, and each view is mapped to a separate physical location of the registry, which keeps both versions of the string intact.
To help applications that write REG_EXPAND_SZ keys containing %ProgramFiles% to the registry, WOW64 intercepts these writes and replaces them with "%ProgramFiles(x86)%". This environment variable is defined for all processes. For example, if the Program Files directory is on the C drive, then "%ProgramFiles(x86)%" expands to "C:\Program Files (x86)".
To enable application interoperability through COM and other mechanisms, WOW64 uses registry reflection, which copies specific registry keys and values between the two registry views to keep them in synch. The reflector is intelligent and copies COM activation data for Local servers between the views, but not in-process data, because 32/64 in-process data mixing is not permitted on 64-bit Windows.
What to do
In a program
KEY_WOW64_64KEY 0x0100 Access a 64-bit key from either a 32-bit or 64-bit application.
Windows 2000: This flag is not supported.
KEY_WOW64_32KEY 0x0200 Access a 32-bit key from either a 32-bit or 64-bit application.
Windows 2000: This flag is not supported.
From command prompt see reg flags /? allowing your key to opt out of redirection.
And a reminder that UAC also may be virtualising it. As it redirects some writes to HKLM to HKCU. Giving permission for users to write to your key will overcome that.
Can I set up a 64-bit registry key to refer to a 32-bit program files path using WiX?
I'm writing a plugin for another piece of software. I want my plugin dll to go in C:\Program Files (x86)\MyPlugin\MyPlugin.dll not in C:\Program Files\MyPlugin\MyPlugin.dll because the dll is 32-bit, not 64-bit.
However, I need the registry key to go in HKLM/Software/Company/Product/Etc.... not in HKLM/Wow6432Node/Software/Company/Product/Etc.... because the process that actually reads the registry key is 64-bit. That 64-bit process reads the registry and launches a 32-bit process to sandbox the dll.
Is there any way to do this? I've tried using different components with different Win64 attribute values, and even putting them in separate component groups. However, I keep getting these build errors (not warnings):
ICE80: This 64BitComponent RegistryComponent uses 32BitDirectory INSTALLFOLDER
A somewhat poor solution, but you could just a custom action to add registry entries, if you don't mind them sticking around after an uninstall.
If you write a custom action in C# you can just do something like this:
using (var hklm = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
{
// do it
}
If you support 32-bit and 64-bit machines you need two separate MSI setups:
http://blogs.msdn.com/b/heaths/archive/2008/01/15/different-packages-are-required-for-different-processor-architectures.aspx
So your 32-bit install creates any COM entries for any 32-bit Clients and the 64-bit setup has 32-bit and 64-bit components that write to the registry.
http://msdn.microsoft.com/en-us/library/aa367451(v=vs.85).aspx
A rather easy solution to only have one installer version for 32 and 64 bit is to export a .reg file with the keys you want to add (from regedit) and then run a custom action during install, ie:
<CustomAction Id='Add_Registry_Keys' Execute='deferred' Directory='DriverDir' Impersonate='no' ExeCommand='regedit.exe /s "[DriverDir]default.reg' Return='ignore' />
You can suppress ICE errors also, not just warnings. This means you can use Win64 attributes in your x86 msi.
The setting to ignore ICE validations is found in the Project Properties under the Tool Settings tab.
It might not be recommended, but if it works its still better than the alternative of a custom action.
I set up the registry key, HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps as described on MSDN.
I have a test program - a console program, compiled with Visual C++, that tries to dereference a NULL pointer before printing a message and exiting. The test program used to exit and dump a core file, but now it just exits. I get no core.
I'm running Windows Server 2008 R2 Enterprise, SP1 on physical hardware.
I don't know what changed. What could have changed that prevents WER from dumping cores now?
The following may go wrong:
Permissions of the folder to write to
Looking at the permissions of the folder C:\ProgramData\Microsoft\Windows\WER it has
Read & execute
List folder contents
Read
Creating a subfolder LocalDumps will inherit the permissions.
So you should either modify the permissions of that folder or use a different folder with write permissions.
Permissions of the Registry key
Windows might not be able to read the Registry settings if the permissions do not allow it. E.g. the following (really silly) permissions will prevent a LocalDump as well:
32 vs. 64 bit
Windows Error Reporting is executed by Windows and only uses the registry key with the bitness of the OS. You said you set up both. If that's true, it`s fine. If you only set up the 32 bit Registry key, it won't work.
AeDebug
If you have a setting for AeDebug HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug, those are executed before WER.
Note that this entry may exist in 32 bit (WOW6432Node) and 64 bit.
Usually that should result in starting a debugger, but who knows ... it might do nothing and just exit.
LocalDumps is disabled
Make sure that there is no DWORD Disabled with a value of 1 in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps
Use of REG_SZ instead of REG_EXPAND_SZ
I have seen people using a REG_SZ for DumpFolder in combination with %APPDATA%. Only REG_EXPAND_SZ will expand environment variables.
Make sure you've added a key on the LocalDumps node like "LocalDumps\MyApplication.exe". Then, update the values that are explained in that link. At the time of a crash, WER looks for a key with the matching application name to decide how to handle the dump.
I am clueless about a recent issue that I encountered while making an MSI installer for Windows XP 64 bit platform.
In the Launch condition of the installer I am trying to read from registry, but the installer is not fetching the correct value. I tried checking for a different Value name, to confirm that its not just one particular Value name, and found it's behaving in the same manner.
I tried to print the fetched registry value data in the error message and realized that in some cases it gets no value at all and in other cases, it fails to get any number that is a part of the complete value data.
For example if try reading the data for:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework
Value Name : InstallRoot
Value Data: C:\Windows\Microsoft.NET\Framework64\
The data that installer fetched is: C:\Windows\Microsoft.NET\Framework\. And in some other instances it gets an empty string.
Registry searches use the 32-bit registry hive by default and the 64-bit hive only if msidbLocatorType64bit flag is set.
So the solution is to use 2 searches with the same property:
one for the 32-bit hive
one for the 64-bit hive (with msidbLocatorType64bit flag)
Please note that Visual Studio setup projects do not support this. Other setup authoring tools do.
My boss just got Windows 7 and he tried running one of our installers which runs perfectly fine under XP. On Windows 7, the installer runs without giving any errors. However, it does not create registry keys under HKEY_LOCAL_MACHINE\SOFTWARE{Company}{product}. These keys get created correctly under XP.
Has anyone encountered this issue? I suspect it is a rights/security issue but I'm not sure and I don't have Windows 7 to experiment with.
EDIT
The computer in question is a 64-bit machine running 64-bit Windows. It turns out Windows 7 redirects 32-bit applications to HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node{Company}{product}. The problem is my application code tries to access the registry using a hardcoded value like this:
var t = Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\..., "ValueName", DefaultValue);
So, my new question is how do I access the registry such that the Windows 9 registry redirection will just work?
If you're using .NET 4, you can specifically request that your 32-bit (or 64-bit) process access the 64-bit view of the registry using the RegistryKey.OpenBaseKey method.
Cf. http://msdn.microsoft.com/en-us/library/microsoft.win32.registrykey.openbasekey.aspx
Here's an example that reads a value from the 64-bit view of the registry, even if it runs as part of a 32-bit process:
var hklm64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
var key = hklm.OpenSubKey(#"SOFTWARE\AcmeSoft\AnvilMaker 1.0");
var value = (string) key.GetValue("Blacksmith Name");
The RegistryKey.OpenBaseKey method also allows you to explicitly open a 32-bit view of the registry. This is useful if you're trying to go the other way around and access the 32-bit view of the registry from a 64-bit process and you don't want to explicitly add "Wow6432Node" to the registry path.
For example, today I needed to delete a sub-key tree in both the 32-bit and 64-bit views of the registry. Doing this in .NET 4 with a single registry path was easy:
foreach(var view in new[] {RegistryView.Registry32, RegistryView.Registry64})
{
var hklm = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, view);
hklm.DeleteSubKeyTree(#"SOFTWARE\AcmeSoft\SomeKeyWeNoLongerWant", throwOnMissingSubKey: false);
}
On a 64-bit version of windows, the above code will remove the following sub-key trees from the registry:
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\AcmeSoft\SomeKeyWeNoLongerWant
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\AcmeSoft\SomeKeyWeNoLongerWant
-Adam
After more digging I came across this link which describes the registry access rules for .NET applications. My program had initially been targeted for "AnyCpu" which causes the app to target the 64-bit registry even though Windows installed it under the Wow6432Node. By setting the target to "x86" my program "magically" started accessing the registry under the Wow6432Node. Go figure!
In the C Windows API this is done by setting the samDesired parameter in the RegOpenKeyEx call to KEY_WOW64_64KEY. This means that the lookup of the registry value will map onto the regular 64-bit entry, rather than the WOW32Node one. I can't see how you would achieve this in .Net though as the Registry class doesn't appear to support these operations, but maybe it's provided through a newer class?
Registry Reflection
Code Sample