Solved

Edit Registry Code to show the whole key IE "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run"

Posted on 2008-09-29
3
1,061 Views
Last Modified: 2012-06-21
The object here is to help show the exact  key and full path "IE"
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run  
I will except a demo that will watch the registry and show me this info or help fix the current code posted here to do so.
unit RegMonitorThread;
 

interface
 

uses

  Classes, Windows, Messages, Registry, SysUtils;
 

  const

  WM_REGCHANGE  = WM_USER + 1973;
 

//Need to redeclare the API function - instead of BOOL is uses DWORD.

function RegNotifyChangeKeyValue(       hKey: HKEY;

                                        bWatchSubtree: DWORD;

                                        dwNotifyFilter: DWORD;

                                        hEvent: THandle;

                                        fAsynchronus: DWORD): Longint; stdcall;

external 'advapi32.dll' name 'RegNotifyChangeKeyValue';
 

type

  TChangeData = record

    Key : string;

    RootKey : HKey;

  end;
 

  TRegMonitorThread = class(TThread)
 

  private

    FReg: TRegistry;

    fChangeData : TChangeData;

    fKey: string;

    fRootKey: HKey;

    fWatchSub: boolean;

    fFilter: integer;

    fWnd: THandle;

    id: integer;

    procedure InitThread;

    procedure SetFilter(const Value: integer);

    function GetFilter: integer;

    function GetChangeData: TChangeData;
 

  public

    constructor Create;

    destructor Destroy; override;

    property Key: string        read fKey       write fKey;

    property RootKey: HKey      read fRootKey   write fRootKey;

    property WatchSub: boolean  read fWatchSub  write fWatchSub;

    property Filter: integer    read GetFilter  write SetFilter;

    property Wnd: THandle       read fWnd       write fWnd;

    property i: integer    read id  write id;

    property ChangeData : TChangeData read GetChangeData;
 

  protected

    procedure Execute; override;
 

  end;
 

implementation
 

{ TRegMonitorThread }

constructor TRegMonitorThread.Create;

begin

  // Execute wont be called until after Resume is called.

  inherited Create(True);
 

  FReg := TRegistry.Create;

end;
 

destructor TRegMonitorThread.Destroy;

begin

  FReg.Free;

  inherited;

end;
 

procedure TRegMonitorThread.InitThread;

begin

  FReg.RootKey := RootKey;

  if not FReg.OpenKeyReadOnly(Key) then

        MessageBox(     fwnd  ,

                        'Error accesing key',

                        'GetLastError',

                        MB_OK or MB_ICONINFORMATION )

  else

        RegNotifyChangeKeyValue(FReg.CurrentKey, 1, Filter, Cardinal(0), Cardinal(False));

end;
 
 

procedure TRegMonitorThread.Execute;

var

        tmp : Integer;

begin

  InitThread;
 

  while not Terminated do

  begin

      fChangeData.RootKey := RootKey;

      fChangeData.Key := Key;

      SendMessage(Wnd, WM_REGCHANGE, i, LongInt(PChar(Key)));
 

      tmp := RegNotifyChangeKeyValue(    FReg.CurrentKey,

                                        1,

                                        Filter,

                                        Cardinal(0),

                                        Cardinal(0));

      if tmp <> ERROR_SUCCESS then

      begin

                // Display the string.

        MessageBox(     fwnd,

                        'Error accesing key',

                        'GetLastError',

                        MB_OK or MB_ICONINFORMATION );

        fChangeData.RootKey := 0;

        fChangeData.Key := 'Terminated due to missing key.';

        SendMessage(Wnd, WM_REGCHANGE, i, LongInt(PChar(Key)));

        self.Terminate;

       end;

  end;

end;
 
 
 

procedure TRegMonitorThread.SetFilter(const Value: integer);

begin

  if fFilter <> Value then

  begin

    fFilter := Value;

  end;

end;
 
 

function TRegMonitorThread.GetFilter: integer;

begin

  if fFilter = 0 then begin

    fFilter:=

      REG_NOTIFY_CHANGE_NAME or

      REG_NOTIFY_CHANGE_ATTRIBUTES or

      REG_NOTIFY_CHANGE_LAST_SET or

      REG_NOTIFY_CHANGE_SECURITY;

  end;

  Result := fFilter;

end;
 
 

function TRegMonitorThread.GetChangeData: TChangeData;

begin

  Result := fChangeData;

end;
 

end.
 
 

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<FOrm1Code>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 

unit Unit1;
 

interface
 

uses

  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,

  Dialogs, StdCtrls, RegMonitorThread, MPlayer;
 

type

  TForm1 = class(TForm)

    Memo1: TMemo;

    Memo2: TMemo;

    Memo3: TMemo;

    Edit1: TEdit;

    Edit2: TEdit;

    Edit3: TEdit;

    Edit4: TEdit;

    CheckBox1: TCheckBox;

    CheckBox2: TCheckBox;

    CheckBox3: TCheckBox;

    CheckBox4: TCheckBox;

    Memo4: TMemo;

    Memo5: TMemo;

    Edit5: TEdit;

    CheckBox5: TCheckBox;

    soundPlayer1: TMediaPlayer;

    procedure FormCreate(Sender: TObject);

    procedure FormDestroy(Sender: TObject);

    procedure CheckBox1Click(Sender: TObject);

    procedure CheckBox3Click(Sender: TObject);

    procedure CheckBox2Click(Sender: TObject);

    procedure CheckBox4Click(Sender: TObject);

    procedure CheckBox5Click(Sender: TObject);

  private

    soundAvailable : BOOL;

    procedure WMREGCHANGE(var Msg : TMessage); message WM_REGCHANGE;

    procedure initSound;

  public

    { Public declarations }

  end;
 

var

  Form1: TForm1;

  RegMonitorThread1 : TRegMonitorThread;

  RegMonitorThread2 : TRegMonitorThread;

  RegMonitorThread3 : TRegMonitorThread;

  RegMonitorThread4 : TRegMonitorThread;

  RegMonitorThread5 : TRegMonitorThread;

  

implementation
 
 

{$R *.dfm}
 

procedure TForm1.FormCreate(Sender: TObject);

begin

        RegMonitorThread1 := TRegMonitorThread.Create;	//We create one thread per key to watch

        RegMonitorThread2 := TRegMonitorThread.Create;

        RegMonitorThread3 := TRegMonitorThread.Create;

        RegMonitorThread4 := TRegMonitorThread.Create;

        RegMonitorThread5 := TRegMonitorThread.Create;
 

  with RegMonitorThread1 do

  begin

    FreeOnTerminate:=True;

    Wnd := Form1.Handle;

    Key := '';

    RootKey := HKEY_CLASSES_ROOT ;

        i := 1;		// thread id

    WatchSub := True;

//    Resume;		Start only when signaled to do so

  end;
 

  with RegMonitorThread2 do

  begin

    FreeOnTerminate:=True;

    Wnd := Form1.Handle;

    Key := '';

    RootKey := HKEY_CURRENT_USER ;

        i := 2;

    WatchSub := True;

  end;
 

  with RegMonitorThread3 do

  begin

    FreeOnTerminate:=True;

    Wnd := Form1.Handle;

    Key := '';

    RootKey := HKEY_LOCAL_MACHINE ;

        i := 3;

    WatchSub := True;

  end;
 

  with RegMonitorThread4 do

  begin

    FreeOnTerminate:=True;

    Wnd := Form1.Handle;

    Key := '';

    RootKey := HKEY_USERS ;

        i := 4;

    WatchSub := True;

  end;
 

  with RegMonitorThread5 do

  begin

    FreeOnTerminate:=True;

    Wnd := Form1.Handle;

    Key := '';

    RootKey := HKEY_CURRENT_CONFIG ;

        i := 5;

    WatchSub := True;

  end;
 

    initSound;

end;
 

procedure TForm1.FormDestroy(Sender: TObject);

begin

        RegMonitorThread1.Terminate;

        RegMonitorThread2.Terminate;

        RegMonitorThread3.Terminate;

        RegMonitorThread4.Terminate;

        RegMonitorThread5.Terminate;

        if soundAvailable then	//if we were able to open the sound file

            soundPlayer1.Close;

end;
 

procedure TForm1.WMREGCHANGE(var Msg: TMessage);	//we put presentation code here

begin
 

        if Msg.WParam = 1 then

        begin

                Memo1.Lines.Add('-------------------------------------------');

                Memo1.Lines.Add('Registry change at ' + DateTimeToStr(Now));

                Memo1.Lines.Add(IntToStr(RegMonitorThread1.ChangeData.RootKey) +

                  ' - ' + RegMonitorThread1.ChangeData.Key);

        end

        else if Msg.WParam = 2 then

        begin

                Memo2.Lines.Add('-------------------------------------------');

                Memo2.Lines.Add('Registry change at ' + DateTimeToStr(Now));

                Memo2.Lines.Add(IntToStr(RegMonitorThread2.ChangeData.RootKey) +

                  ' - ' + RegMonitorThread2.ChangeData.Key);

        end

        else if Msg.WParam = 3 then

        begin

                Memo3.Lines.Add('-------------------------------------------');

                Memo3.Lines.Add('Registry change at ' + DateTimeToStr(Now));

                Memo3.Lines.Add(IntToStr(RegMonitorThread3.ChangeData.RootKey) +

                  ' - ' + RegMonitorThread3.ChangeData.Key);

        end

        else if Msg.WParam = 4 then

        begin

                Memo4.Lines.Add('-------------------------------------------');

                Memo4.Lines.Add('Registry change at ' + DateTimeToStr(Now));

                Memo4.Lines.Add(IntToStr(RegMonitorThread4.ChangeData.RootKey) +

                  ' - ' + RegMonitorThread4.ChangeData.Key);

        end

        else if Msg.WParam = 5 then

        begin

                Memo5.Lines.Add('-------------------------------------------');

                Memo5.Lines.Add('Registry change at ' + DateTimeToStr(Now));

                Memo5.Lines.Add(IntToStr(RegMonitorThread5.ChangeData.RootKey) +

                  ' - ' + RegMonitorThread5.ChangeData.Key);

        end;

        if soundAvailable then

            soundPlayer1.Play;

end;
 

procedure TForm1.CheckBox1Click(Sender: TObject);

begin

        if not CheckBox1.Checked then

        begin

            Edit1.Enabled := True;

            Edit1.Color := clWindow;

            TerminateThread(RegMonitorThread1.Handle,0);	//Stop the thread

        end

        else

        begin

            RegMonitorThread1 := TRegMonitorThread.Create;

            Edit1.Enabled := False;				//Run the thread again

            Edit1.Color := clInactiveCaptionText;

            with RegMonitorThread1 do

            begin

                FreeOnTerminate:=True;			// I know this code is repeated

                Wnd := Form1.Handle;			// I am leaving it so you can understand

                Key := Edit1.Text;			//everything. 

                RootKey := HKEY_CLASSES_ROOT ;

                i := 1;

                WatchSub := True;

                Resume;

            end;

        end;

end;

procedure TForm1.CheckBox2Click(Sender: TObject);

begin

        if not CheckBox2.Checked then

        begin

            Edit2.Enabled := True;

            Edit2.Color := clWindow;

            TerminateThread(RegMonitorThread2.Handle,0);

        end

        else

        begin

            RegMonitorThread2 := TRegMonitorThread.Create;

            Edit2.Enabled := False;

            Edit2.Color := clInactiveCaptionText;

            with RegMonitorThread2 do

            begin

                FreeOnTerminate:=True;

                Wnd := Form1.Handle;

                Key := Edit2.Text;

                RootKey := HKEY_CURRENT_USER ;

                i := 2;

                WatchSub := True;

                Resume;

            end;

        end;

end;

procedure TForm1.CheckBox3Click(Sender: TObject);

begin

        if not CheckBox3.Checked then

        begin

            Edit3.Enabled := True;

            Edit3.Color := clWindow;

            TerminateThread(RegMonitorThread3.Handle,0);

        end

        else

        begin

            RegMonitorThread3 := TRegMonitorThread.Create;

            Edit3.Enabled := False;

            Edit3.Color := clInactiveCaptionText;

            with RegMonitorThread3 do

            begin

                FreeOnTerminate:=True;

                Wnd := Form1.Handle;

                Key := Edit3.Text;

                RootKey := HKEY_LOCAL_MACHINE ;

                i := 3;

                WatchSub := True;

                Resume;

            end;

        end;

end;

procedure TForm1.CheckBox4Click(Sender: TObject);

begin

        if not CheckBox4.Checked then

        begin

            Edit4.Enabled := True;

            Edit4.Color := clWindow;

            TerminateThread(RegMonitorThread4.Handle,0);

        end

        else

        begin

            RegMonitorThread4 := TRegMonitorThread.Create;

            Edit4.Enabled := False;

            Edit4.Color := clInactiveCaptionText;

            with RegMonitorThread4 do

            begin

                FreeOnTerminate:=True;

                Wnd := Form1.Handle;

                Key := Edit4.Text;

                RootKey := HKEY_USERS;

                i := 4;

                WatchSub := True;

                Resume;

            end;

        end;

end;
 

procedure TForm1.CheckBox5Click(Sender: TObject);

begin

        if not CheckBox5.Checked then

        begin

            Edit5.Enabled := True;

            Edit5.Color := clWindow;

            TerminateThread(RegMonitorThread5.Handle,0);

        end

        else

        begin

            RegMonitorThread5 := TRegMonitorThread.Create;

            Edit5.Enabled := False;

            Edit5.Color := clInactiveCaptionText;

            with RegMonitorThread5 do

            begin

                FreeOnTerminate:=True;

                Wnd := Form1.Handle;

                Key := Edit5.Text;

                RootKey := HKEY_CURRENT_CONFIG;

                i := 5;

                WatchSub := True;

                Resume;

            end;

        end;

end;
 

procedure TForm1.initSound();

var sWinDir: String;

    iLength: Integer;

begin
 

    iLength := 255;

    setLength(sWinDir, iLength);

    iLength := GetWindowsDirectory(PChar(sWinDir), iLength);

    setLength(sWinDir, iLength);
 

    With soundPlayer1 do

    begin

         Filename := sWinDir + '\media\notify.wav'; //specify sound file

         try

            Open;	// this throws and exception. must catch it.

         except

            on EMCIDeviceError do ShowMessage('Could not open sound file');

         end;

         if Error = 0 then

            soundAvailable := True	//flag for use

         else

            soundAvailable := False;

    end;

end;
 
 

end.

Open in new window

0
Comment
Question by:Grant Fullen
  • 2
3 Comments
 
LVL 21

Accepted Solution

by:
ziolko earned 150 total points
ID: 22602995
not possible. RegNotifyChangeKeyValue signals only that change was made in specified registry key (or it's sub key if bWatchSubtree is true). there's no indication which values has been changed

ziolko.
0
 
LVL 21

Expert Comment

by:ziolko
ID: 22603025
... of course you can backup whole registry key to file set notification, once you get notification backup registry again and compare changes. but if you set notifications on all root keys this method will most likely completely kill preformance of your machine

ziolko.
0
 
LVL 26

Assisted Solution

by:EddieShipman
EddieShipman earned 100 total points
ID: 24310885
Per KB Q236570: http://support.microsoft.com/kb/236570

"As with the file change notification APIs, RegNotifyChangeKeyValue() does not return any indication as to what has changed in the registry key or its subkeys or values. The program must know the state of the keys or values prior to the notification, so that it can determine what has changed. "
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now