3
votes

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?

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. - David Heffernan
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. - David Heffernan
The demo app is just for testing purposes, that's why I hard coded the flag into it. - smartins

1 Answers

2
votes

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.