3

I'm trying to use RegNotifyChangeKeyValue to monitor changes of a 64-bit registry key. To open this key from a 32-bit application, we must add the access flag KEY_WOW64_64KEY.

Unfortunately I can't seem to be able to monitor changes to this key, only it's 32-bit counterpart.

I'm including a demo project along with the unit I'm using to implement registry monitoring. Download it here: RegMonitor

Steps to reproduce the problem:

  1. Compile the program. Run it as administrator. Click the Start button.

  2. Open regedit and navigate to

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run

  3. Add a new value there. RegMonitor will not detect any change.

  4. Navigate to

    HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run

  5. Add a new value there. RegMonitor will detect this change.

I've added the KEY_WOW64_64KEY access flag when opening the registry, but it still does not notify of any changes to correct key, only the Wow6432Node redirect.

Any idea if it's possible to use RegNotifyChangeKeyValue to monitor such key?

3
  • 1
    OK, I built the sample app from here: msdn.microsoft.com/en-us/library/windows/desktop/… Then I modified it to use KEY_WOW64_64KEY when opening the key. And then the code successfully notified me of a change in the 64 bit part of the registry. So no, the API does work fine with KEY_WOW64_64KEY from the emulator. Commented Jan 15, 2012 at 19:21
  • As an aside, you have hard-coded Wow6432Node into your app. That is always a bad idea. I trust that this was done purely for the purposes of testing this app. Commented Jan 15, 2012 at 19:40
  • The demo app is just for testing purposes, that's why I hard coded the flag into it. Commented Jan 15, 2012 at 19:57

1 Answer 1

2

The following minimal example detects changes in the 64 bit view of the registry, from a 32 bit process. I don't know what's different about your program, but this code proves that a 32 bit program can indeed detect changes in both views.

I know this doesn't solve you problem, but I hope it helps steer you in the right direction.

program RegMonitor;

{$APPTYPE CONSOLE}

uses
  SysUtils, Windows;

procedure Main;
const
  dwFilter: DWORD =
    REG_NOTIFY_CHANGE_NAME or
    REG_NOTIFY_CHANGE_ATTRIBUTES or
    REG_NOTIFY_CHANGE_LAST_SET or
    REG_NOTIFY_CHANGE_SECURITY;
var
  Error: Integer;
  key: HKEY;
begin
  Error := RegOpenKeyEx(
    HKEY_LOCAL_MACHINE,
    'Software\Microsoft\Windows\CurrentVersion\RunOnce',
    0,
    KEY_NOTIFY or KEY_WOW64_64KEY,
    key
  );
  if Error<>ERROR_SUCCESS then
    RaiseLastOSError(Error);
  try
    Error := RegNotifyChangeKeyValue(
      key,
      True,
      dwFilter,
      0,
      False
    );
    if Error<>ERROR_SUCCESS then
      RaiseLastOSError(Error);
    Writeln('Change detected');
    Readln;
  finally
    RegCloseKey(key);
  end;
end;

begin
  Main;
end.

Now, as for your program, it looks like there are lots of problems with it. But the fundamental problem, the one that means you are not notified of changes, is that your event is created incorrectly. You create it like this:

CreateEvent(Nil, True, False, 'RegistryChangeMonitorEvent')

but you need to create it like this

CreateEvent(nil, True, False, nil)

I've not delved into what the requirements are for this event, the documentation does not offer any clues. All I did was look for differences between your code and the code in the MSDN example.

Make that change to the event creation and you have enough to start receiving notifications. However, when I did that change, your program still did not work and failed with an AV. One of your objects was not created. However, I think those are pretty routine bugs that you can sort out for yourself.


I wonder why you are using KEY_ALL_ACCESS. Why don't you use KEY_NOTIFY when you open the key to be passed to RegNotifyChangeKeyValue? And when you try to build a report of what has changed in a key, why don't you use KEY_READ? Since you are not attempting to write ever, KEY_ALL_ACCESS is not appropriate. If you make these changes then you won't need to run as admin.

Sign up to request clarification or add additional context in comments.

7 Comments

David, thanks for the answer and all the investigation you did so far. The usage of KEY_ALL_ACCESS was just for testing purposes. I've also just tried your demo program, but on my system it does not notify of changes on HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce, only on HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\RunOnce On your system it correctly detects changes on the 64 bit view of that registry key?
yes, on my system my sample program detects changes in 64 bit view. I'm running win 7 x64 with UAC and not elevating. No need to run as admin.
I may be missing something, but this code doesn't seem to use KEY_WOW64_64KEY, so surely as-is it is only looking at the 32 bit view?
@Harry oh dear you are right. Looks like I pasted the wrong version if the code. I've added the flag now.
I can confirm that adding the KEY_WOW64_64KEY flag does indeed notify the correct registry area. I have modified my existing code to use RegOpenKeyEx instead of Delphi's TRegistry and it has fixed the issue. Guess it has something to do with the access flags not being correctly passed to RegNotifyChangeKeyValue when using TRegistry to open the key.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.