Introduction

The registry redirector was added in x64/IA64 operating systems to support win32
(x86) applications on the new 64-bit platform. It is designed to smoothly support
"legacy" x86 applications without any modifications on these
applications. Because x86 and x64/IA64 are completely two different worlds, they
decided to make two different registry-views for old (x86) and new (x64/IA64)
applications. But a completely separate registry-view is not always what the app
wants. For example, the registry keys of COM servers (OutProc) should be visible
in both worlds. To address these issues, they indroduced the "Registry
Redirector". This redirector consists of the following three parts:

Two registry views

The location of the 32-bit view of the registry is inside the 64-bit view in a
special sub-node. This node is called Wow6432Node. The following
nodes contain the 32-bit view (and all sub-nodes):

HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Wow6432Node

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node

HKEY_USERS\*\SOFTWARE\Classes\Wow6432Node

The complete registry redirection is done in user-mode. The key-names are
translated in user-mode to the appropriate "kernel-mode" names. So in
general you can say: There is only one registry in windows x64,
but the redirector is sometimes converting the passed named to an other name.

Example

Here is a small example of the registry redirector:If you access the key
HKEY_LOCAL_MACHINE\SOFTWARE\MyApp\Settings from a 64-bit app, you
really opening this node. If you open this node from a 32-bit app, you are
transparently redirected to
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\MyApp\Setting.

There are several hard coded registry keys which will be shared by x86 and
x64/IA64 apps. These keys exists only in the 64-bit view of the registry but you
can open it in an x86 app. The list of these keys is available via KB article 896459 and here (by the way, the KB article has one misspelled
entry). Just for completeness, here is the current list:

Internals

This list can also be found in ADVAPI32!ExemptRedirectedKey by using windbg.

Every time a key is opened in an x86 app (this is done via
Wow64RegOpenKeyEx and Wow64pRegCreateKeyEx), it is
checked in ADVAPI32!IsExemptRedirectedKey if the key should be open
in the default-view or in the x64 view.

Side effect of shared registry keys

Because the keys exist only in the 64-bit view of the registry, there is
currently no way to find these keys in an x86 app via enumerating
(RegEnumKeyEx). You can simply verify this by opening the 32-bit
version of regedit.exe via %systemroot%\SysWOW64\regedit.exe
-m (-m to allow multiple instances of regedit.exe) and try to find these
keys.

Registry reflection is a really special part of the registry redirector. Like
shared registry keys, there is also a hard-coded list of keys which will be
reflected. Reflection means that two physical copies of a single key exist (in x86
view and x64/IA64 view), but these keys will be "reflected" if their
contents are changed and the key is closed. Because the reflection only occurs
with the closing of the key, the last close wins. Here is a list of relfected
keys:

Special handling of HKEY_LOCAL_MACHINE\Software\Classes\CLSID

This node contains all the COM components. Activating a COM component can be
done in two different ways: Either in-process or out-process. This is specified in
the registry under the CLSID of the component. There is either a sub-entry
InProcServer32 or LocalServer32. The registry reflector
is now 'intelligent' and only reflects keys which are bound to an out-process
("LocalServer32") server. It only makes sense for out-process to relfect
the keys, because in-proc COM-servers can either be 32-bit or
64-bit. There is no way to load a 64-bit DLL into a 32-bit process and vice versa.
So if you register an in-proc component, it is bound to the architecture of the
DLL (either 32-bit or 64-bit). So the affected registry keys must not be reflected
in the other world.

Disable / Enable reflection for particular keys

By default, reflection is enabled for all (sub-keys) of the hard-coded
reflection list. With the new APIs RegDisableReflection
Key and RegEnableReflectionK
ey it is possible to change the reflection state of these particular keys. Of
course, the current state of the key can be queried using the RegQueryReflectionKe
y function. But you should be aware that the out-parameter is named
bIsReflectionDisabled! This means, you must think outside the box.
For the sake of simplicity I have a list for you:

bIsReflectionDisabled == FALSE => Reflection is
enabled!

bIsReflectionDisabled != FALSE => Reflection is
disabled!

Limitations

It appears that this function can be used to enable reflection for any
particular key. But this is not true! By default, all keys will get reflected
which are on the hard-coded reflection list! You cannot add keys to this
hard-coded list! The only thing you can do, is disable reflection for a key which
would normally be reflected, because it is on the hard-coded reflection list.

The function RegDisableReflectionKey just sets a special
Tag to the specified key. The RegEnableReflectionKey
removes this Tag. So the functions will succeed on 'all' keys, but it
only will affect keys which are on the hard-coded reflection list.

You should also be aware, that subkeys are not affected by this function! Only
the specified key.

Example

In the follwoing example, I disable reflection for a key, which will never get
reflected (just to show that the function will succeed, even it has no affect,
because the key will never get reflected).

Internals

In general, Reflection is only done in x64/IA64 mode. So all functions are in
the x64 version of the ADVAPI32.DLL. Reflection is only done in
user-mode. No kernel-mode component needs to know about reflection, because every
kernel-mode component is x64/IA64 and threfore no reflection is needed.

What happens if a value is changed

If a value is changed the following will occur:

Test if Reflection is activated (BOOL ADVAPI32!bReflectorStatusOn)This
is interesting ... it seems that reflection can be disabled in some ways, or is
not always enabled (maybe at system startup).

Check if the registry key is on the "ReflectionList"
(ADVAPI32!IsOnReflectionListByToken)This list is fixed coded and stored in
x64-"ADVAPI32!ReflectList". Besides the already listed nodes, it also
contains the following nodes:

But I really cannot see that these keys are getting reflected ... maybe someone
can get it to work (it seems that the corresponding key without the
Wow6432Node is missing...)

If a value was changed, a "dirty"-flag is set.

On Closing the hKey, the function Wow64RegCloseKey will be called
and will do a NtSyncKey if the dirty flag is set. The function
Wow64RegCloseKey is called in x64 apps directly inside the
RegCloseKey, in x86 apps the function is called indirect through the
CpuSimulation in WOW64.

Handle list for dirty keys

The handle-list for open registry keys which contains the "dirty"
flags is restricted to 512? entries. So if you open more than 512 registry keys
(and keep them open) and all keys must be reflected, the latest keys will not be
reflected because of this restriction. Of course, you should never keep 512
registry keys open at the same time, so this should be no real-world restriction.

Writing REG_EXPAND_SZ strings from an x86 application (running under WOW64)
into the registry is something special. Because with REG_EXPAND_SZ, you can embed
environment variables into the string. And there might be a change where, some x64
application might read this string. Therefore, MS decided to change the value of
such strings "on-the-fly" if it contains environment variables which
might lead to the wrong directory. These environment varaibles are:

%ProgramFiles%

%commonprogramfiles%

If you write such a string then it will be replaced with the according x86
value (%ProgramFiles(x86)%,
%commonprogramfiles(x86)%).

There a new flags which can be used to access the alternate registry view in
your 32-bit or 64-bit application. With this flag, you can force
RegCreateKeyEx, RegDeleteKeyEx and
RegOpenKeyEx to explicitly access the 64-bit view
(KEY_WOW64_64KEY) or the 32-bit (KEY_WOW64_32KEY) view
of the registry, independent of your process' default view. Of course, this only
makes sense if you access some keys which will be redirected.

This flag is very special and is not associated with the returned handle!

If you want to delete a key and you have opened the node with
KEY_WOW64_64KEY, then you expect that the RegDeleteKeyEx
function will be performed on the 64-bit view. But this is not the case! It will
be performed on the default process view! If you want to delete a 64-bit key from
a 32-bit app, you need to explicitly pass the KEY_WOW64_64KEY flag to
the RegDeleteKeyEx. You do not need to open the node with
KEY_WOW64_64KEY (if the node exists in both views).

Here is a short example:

#include<windows.h>#include<tchar.h>#pragma comment(lib, "Advapi32.lib")
void _tmain()
{
LONG lRet;
HKEY hKey;
// Open the key on the default-view
lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\MyTest"),
0L, KEY_ALL_ACCESS, &hKey);
if(lRet == ERROR_SUCCESS)
{
// delete it on the other view...
#if _M_IX86
// The key will be deleted on the 64-bit view, even if the app is 32-bit
// and the key was opend on the 32-bit view!
lRet = RegDeleteKeyEx(hKey, _T("1"), KEY_WOW64_64KEY, 0);
#else// The key will be deleted on the 32-bit view, even if the app is 64-bit
// and the key was opend on the 64-bit view!
lRet = RegDeleteKeyEx(hKey, _T("1"), KEY_WOW64_32KEY, 0);
#endif
RegCloseKey(hKey);
}
}

The other way is also possible: You can open the key with
KEY_WOW64_xxKEY and if you do not specify this flag on
RegDeleteKeyEx, the key will be deleted on the default-view.

Side-Effect of KEY_WOW64_64KEY and the special node Wow6432Node

You should not open the following keys with KEY_WOW64_64KEY
because they will return the node of the key without the Wow6432Node.
I do not know if this is by design or a bug ...

SOFTWARE\Classes\Wow6432Node

SOFTWARE\Wow6432Node

So if you try to enumerate throw the registry with KEY_WOW64_64KEY
specified, you will end up in an endless loop!
Also if you open a subkey of the Wow6432Node such as
SOFTWARE\Wow6432Node\SubKey in an x86 app, the
Wow6432Node part is ignored. So if you specify
KEY_WOW64_64KEY, the x64-node SOFTWARE\SubKey is opened.
If you use the default view, also the node SOFTWARE\SubKey is opened
(in the accoring view!).

Also you should not create own sub-nodes with the name Wow6432Node, because this can lead to confusing when opening a key. So for example: opening SOFTWARE\Wow6432Node\SubKey\Wow6432Node will open the node SOFTWARE either in the default view (if no special flag is passed) or in the x64-view if KEY_WOW64_64KEY was passed.

In x86 apps it seems that the node Wow6432Node is just removed
from the path and the accoring to the flags either the x64 or the x86
registry-view is used.In x64 apps the node Wow6432Node is
removed if you specify the KEY_WOW64_64KEY flag.

In x64 apps, if you try to open a key with KEY_WOW64_32KEY and the
path contains a node named Wow6432Node, it always returns the
root-node! At least this is a bug I think.

Changes in Vista

New APIs

In Windows
Vista they introduced a new API function for changing the behavior of the
registry redirector for special keys. The functions are called RegSetKeyFlags and
RegQueryKeyFlags. It has three possible flags which can be set or cleared:

KEY_FLAG_DISABLE_REDIRECTIONI had not yet tested this flag;
so I will just quote the original documentation:

Disables registry redirection for operations that use this handle. (By
default, WOW64 redirects operations on handles opened in the 64-bit registry view
to the 32-bit registry view.)

KEY_FLAG_EXEMPT_REFLECTIONThis flag has the same effect as
using RegDisableReflectionKey, RegEnableReflectionKey
and RegQueryReflectionKey

KEY_FLAG_OWNERSHIP_REFLECTIONI had not yet tested this
flag; so I will just quote the original documentation:

Exempts the key from reflection if the key exists in an alternate
registry view and was not created by the caller.

It adds more control over redirection and reflection, but it also adds a more
complex mechanism to determine what exactly happens if these flags are set.

Internals

The new APIs use the same mechanism to store the settings as the current
available APIs (RegDisableReflectionKey,
RegEnableReflectionKey). The setting is stored using a key-tag (via
ADVAPI32!QueryKeyTag and ADVAPI32!UpdateKeyTag). So
using RegDisableReflectionKey or RegSetKeyFlags with
EY_FLAG_EXEMPT_REFLECTION has the same effect. The setting is stored
in the same tag, so you can also use the RegQueryKeyFlags or
RegQueryReflectionKey to query the reflection state.

Shared registry keys

It seems that the build 5365 has a bug in the
ADVAPI32!ExemptRedirectedKey list of shared keys. The key
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Time
Zones is misspelled and is now missing a "s" at the end (the same
confusion is in the two documentations about the list of shared keys (see above)).

History

23rd May, 2006

Initial revision.

07th Oct, 2006

Added "Transparent changes in values if written with REG_EXPAND_SZ"

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

I am developing a 32 bit application for 64 bit platform,
I need to export the registry keys related to active and non active profile to a file using RegCreateKeyEx and RegSaveKeyEx. In 32 bit application when I try to do RegCreteKeyEx for key
corresponding to
C:\Documents and Settings\\Local Settings\Application Data\Microsoft\Windows\Usrclass.dat *without* specifying key_wow64_64key, and use the handle returned by RegCreateKeyEx in RegSaveKeyEx, I get error "Invalid parameter" means key handle is invalid. With using key_wow64_64key, it works fine.
Once I do that, it sets the view of the process to 64 bit view of registry, later in same thread I try to create a COM component (disk quota control from microsoft ) using CoCreateInstance. cocreateinstance of any component will fail after that, this means, once a process switches to 64 bit registry view, it cannot reset its view to 32 bit view ?

Questions
Is the key I am trying to save specific to only 64 bit view? How do I know which Keys are specific to 64 bit view?
Can processing registry specific things in a different thread help? Will the process get back its 32 bit view after the thread is over?

On some site I read using ( key_wow64_64key | key_wow64_32key ), will that help?

The thread that was failing with CoCreateInstance had disabled FS redirection and was trying to create a 64 bit COM components from 32 bit APP running in WOW mode, Once I reverted the FS redirection, that problem is solved.

However I am facing an issue with registry redirection, In a 32 bit application running in WOW mode, if I try to do RegCreateKeyEx for HKEY_USERS and subkey "*_Classes" with KEY_WOW64_32KEY flag,
then RegSaveKeyEx fails with an error "Invalid Parameter".

As I understand, default registry view for 32 bit application is 32 bit view where HKEY_USERS\*_Classes should exist.
Hence if I dont specify KEY_WOW64_32KEY it should still succeed.
If I open the Key with KEY_WOW64_64KEY flag, it succeeds.

Following is the code snippet and the code runs with LOCAL_SYSTEM credentials:

the lRes value I receive is 87 : Invalid Parameter.
Can you suggest whats wrong with the code?

ours is a backup application wherein I need to backup 64 bit as well as 32 bit specific registry.
and As I understand if I open the reg key with KEY_WOW64_64KEY,
it will ignore WOW6432 subkey and RegSaveKey will not save 32 bit specific registry subkeys, is that right?

This article contains really valuable information which helped me find my path through the 64bit registry jungle.
In my case I always ran into an infinite loop when trying to walk all of hklm from a 32bit app. For some reason I have a node HKLM\SOFTWARE\Wow6432Node\Wow6432Node in the system registry of my 64bit Vista test system, so no matter I walked the tree with or without KEY_WOW64_64KEY, I ended up in an infinite loop. Thanks for pointing me into the right direction on how to work around this problem.
Gerd

Its really a nice article... but I have few questions as I am new to this.

1) I have a 32-bit application which is using the registry path to access some parameters. Now, can I use the same registry path which is used in 32-bit application? will it work on x64 OS?
As per my understanding, the redirection and reflection will take care of it and I need not change the registry path specified in my application . I dont have to change anything in my app and just use as it is regardless of x86 or x64.

2) Now, suppose I have a 32-bit application and I want to use the x64 registry. Can I do that? In you article you have mentioned the same in Side-Effect of KEY_WOW64_64KEY and the special node Wow6432Node topic but its not clear to me . Can you please clarify the same in detail? Also, if you can pass on the code that will be great .

1. Yes, you do not need to change anything. Your 32-Bit app will work on 64-Bit OS without modification.
2. What do you want to know? You can access the 64-Bit view if you use the KEY_WOW64_64_KEY flag.