291 lines
13 KiB
C++
291 lines
13 KiB
C++
// ==========================================================================
|
|
// Class Specification : COXRegistryWatcher
|
|
// ==========================================================================
|
|
|
|
// Header file : OXRegistryWatcher.h
|
|
|
|
// Version: 9.3
|
|
|
|
// //////////////////////////////////////////////////////////////////////////
|
|
|
|
// Properties :
|
|
// NO Abstract class (does not have any objects)
|
|
// YES Derived from CObject
|
|
|
|
// NO Is a Cwnd.
|
|
// NO Two stage creation (constructor & Create())
|
|
// NO Has a message map
|
|
// NO Needs a resource (template)
|
|
|
|
// NO Persistent objects (saveable on disk)
|
|
// NO Uses exceptions
|
|
|
|
// //////////////////////////////////////////////////////////////////////////
|
|
|
|
// Description :
|
|
// This class can be used to organize Registry change notifications.
|
|
// It notifies the caller about changes to the attributes or contents of a specified Registry key.
|
|
// All notifications are handled by virtual function, which can be overridden in derived classes.
|
|
// COXRegistryWatcher class can also convert notifications to a window message. This message
|
|
// can be sent to a specified window and translated there (e.g. by PreTranslateMessage()).
|
|
// Note that COXRegistryWatcher doesn't notify the caller if the specified key is deleted.
|
|
|
|
// Example :
|
|
// COXRegistryWatcher RegWatch;
|
|
// if ( ::RegOpenKeyEx(hKey, sKeyName, 0, KEY_NOTIFY, &hKeyAdd) == ERROR_SUCCESS && hKeyAdd )
|
|
// {
|
|
// if ( RegWatch.EnableWindowNotification(RegWatch.AddWatch(hKeyAdd, TRUE), this) )
|
|
// TRACE1("Watched Key : %s\n", sKeyName);
|
|
// }
|
|
|
|
// Remark :
|
|
// Registry watch is carried out by the separate worker thread.
|
|
// Therefore COXRegistryWatcher's Registry watching doesn't "hung" your programs.
|
|
|
|
// Prerequisites (necessary conditions):
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef __OXREGISTRYWATCHER_H__
|
|
#define __OXREGISTRYWATCHER_H__
|
|
|
|
#if _MSC_VER >= 1000
|
|
#pragma once
|
|
#endif // _MSC_VER >= 1000
|
|
|
|
#include "OXDllExt.h"
|
|
#include "OXMainRes.h"
|
|
|
|
#include "OXRegistryWatchNotifier.h"
|
|
|
|
|
|
|
|
// //////////////////////////////////////////////////////////////////////////
|
|
// Definitions of error codes.
|
|
#define OX_FACILITY_REGISTRY_WATCHER 0x221
|
|
#define OX_STATUS_SEVERITY_SUCCESS 0x0
|
|
#define OX_STATUS_SEVERITY_ERROR 0x3
|
|
#define OX_CODE_REGISTRY_WATCHER_ERROR_SUCCESS 1
|
|
#define OX_CODE_REGISTRY_WATCHER_NO_HKEY 2
|
|
#define OX_CODE_REGISTRY_WATCHER_THREAD_FAILURE 3
|
|
#define OX_CODE_REGISTRY_WATCHER_EVENT_FAILURE 4
|
|
#define OX_CODE_REGISTRY_WATCHER_EMPTY_WATCHER 5
|
|
#define OX_CODE_REGISTRY_WATCHER_INCORRECT_HKEY 6
|
|
#define OX_CODE_REGISTRY_WATCHER_ALREADY_STARTED 7
|
|
#define OX_CODE_REGISTRY_WATCHER_ALREADY_STOPPED 8
|
|
#define OX_CODE_REGISTRY_WATCHER_VERSION_FAILURE 9
|
|
#define OX_CODE_REGISTRY_WATCHER_NO_NOTIFIER 10
|
|
#define OX_CODE_REGISTRY_WATCHER_INCORRECT_ID 11
|
|
#define OX_CODE_REGISTRY_WATCHER_SYNCHRO_FAILURE 12
|
|
|
|
// The operation completed successfully.
|
|
#define OX_REGISTRY_WATCHER_ERROR_SUCCESS MAKE_HRESULT(OX_STATUS_SEVERITY_SUCCESS,\
|
|
OX_FACILITY_REGISTRY_WATCHER, OX_CODE_REGISTRY_WATCHER_ERROR_SUCCESS)
|
|
|
|
// Registry key is not specifying.
|
|
#define OX_REGISTRY_WATCHER_NO_HKEY MAKE_HRESULT(OX_STATUS_SEVERITY_ERROR,\
|
|
OX_FACILITY_REGISTRY_WATCHER, OX_CODE_REGISTRY_WATCHER_NO_HKEY)
|
|
|
|
// Failure to start or process the worker thread.
|
|
#define OX_REGISTRY_WATCHER_THREAD_FAILURE MAKE_HRESULT(OX_STATUS_SEVERITY_ERROR,\
|
|
OX_FACILITY_REGISTRY_WATCHER, OX_CODE_REGISTRY_WATCHER_THREAD_FAILURE)
|
|
|
|
// Failure of notification event initialization.
|
|
#define OX_REGISTRY_WATCHER_EVENT_FAILURE MAKE_HRESULT(OX_STATUS_SEVERITY_ERROR,\
|
|
OX_FACILITY_REGISTRY_WATCHER, OX_CODE_REGISTRY_WATCHER_EVENT_FAILURE)
|
|
|
|
// No watched keys (empty "watch queue").
|
|
#define OX_REGISTRY_WATCHER_EMPTY_WATCHER MAKE_HRESULT(OX_STATUS_SEVERITY_ERROR,\
|
|
OX_FACILITY_REGISTRY_WATCHER, OX_CODE_REGISTRY_WATCHER_EMPTY_WATCHER)
|
|
|
|
// Registry key is not watched by this COXRegistryWatcher object.
|
|
#define OX_REGISTRY_WATCHER_INCORRECT_HKEY MAKE_HRESULT(OX_STATUS_SEVERITY_ERROR,\
|
|
OX_FACILITY_REGISTRY_WATCHER, OX_CODE_REGISTRY_WATCHER_INCORRECT_HKEY)
|
|
|
|
// Starting thread is already started.
|
|
#define OX_REGISTRY_WATCHER_ALREADY_STARTED MAKE_HRESULT(OX_STATUS_SEVERITY_ERROR,\
|
|
OX_FACILITY_REGISTRY_WATCHER, OX_CODE_REGISTRY_WATCHER_ALREADY_STARTED)
|
|
|
|
// Stoping thread is already stoped.
|
|
#define OX_REGISTRY_WATCHER_ALREADY_STOPPED MAKE_HRESULT(OX_STATUS_SEVERITY_ERROR,\
|
|
OX_FACILITY_REGISTRY_WATCHER, OX_CODE_REGISTRY_WATCHER_ALREADY_STOPPED)
|
|
|
|
// Failure to retrieve the Windows version.
|
|
#define OX_REGISTRY_WATCHER_VERSION_FAILURE MAKE_HRESULT(OX_STATUS_SEVERITY_ERROR,\
|
|
OX_FACILITY_REGISTRY_WATCHER, OX_CODE_REGISTRY_WATCHER_VERSION_FAILURE)
|
|
|
|
// Can't to find specified notifier.
|
|
#define OX_REGISTRY_WATCHER_NO_NOTIFIER MAKE_HRESULT(OX_STATUS_SEVERITY_ERROR,\
|
|
OX_FACILITY_REGISTRY_WATCHER, OX_CODE_REGISTRY_WATCHER_NO_NOTIFIER)
|
|
|
|
// Incorrect notifier ID.
|
|
#define OX_REGISTRY_WATCHER_INCORRECT_ID MAKE_HRESULT(OX_STATUS_SEVERITY_ERROR,\
|
|
OX_FACILITY_REGISTRY_WATCHER, OX_CODE_REGISTRY_WATCHER_INCORRECT_ID)
|
|
|
|
// Failure of synchronization event setting.
|
|
#define OX_REGISTRY_WATCHER_SYNCHRO_FAILURE MAKE_HRESULT(OX_STATUS_SEVERITY_ERROR,\
|
|
OX_FACILITY_REGISTRY_WATCHER, OX_CODE_REGISTRY_WATCHER_SYNCHRO_FAILURE)
|
|
|
|
// //////////////////////////////////////////////////////////////////////////
|
|
|
|
class OX_CLASS_DECL COXRegistryWatcher : public CObject
|
|
{
|
|
// Data members -------------------------------------------------------------
|
|
public:
|
|
// Flags to specify which type of changes should be reported (for AddWatch()).
|
|
const static DWORD OXRegistryWatchChangeName; // Subkey was added or deleted.
|
|
const static DWORD OXRegistryWatchChangeAttributes; // Changes to the attributes of the key.
|
|
const static DWORD OXRegistryWatchChangeLastSet; // Changes to a value of the key.
|
|
const static DWORD OXRegistryWatchChangeSecurity; // Changes to the security descriptor of the key.
|
|
|
|
protected:
|
|
CEvent m_EventWatchLoop;
|
|
CEvent m_EventWatchRestart;
|
|
CEvent m_EventWatchBuildBegin;
|
|
CEvent m_EventWatchBuildEnd;
|
|
HRESULT m_hResultError;
|
|
DWORD m_dwWatchesNumber;
|
|
CWinThread* m_pNotificationThread;
|
|
COXRegistryWatchNotifier* m_pRegistryWatchNotifier;
|
|
|
|
private:
|
|
|
|
// Member functions ---------------------------------------------------------
|
|
public:
|
|
COXRegistryWatcher();
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : Constructs the COXRegistryWatcher object.
|
|
|
|
virtual ~COXRegistryWatcher();
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : Removes all watched keys and destroys the COXRegistryWatcher object.
|
|
|
|
BOOL IsWatchingSupported();
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns : TRUE - if Registry key watching is supported, FALSE - otherwise.
|
|
// --- Effect : This function returns whether Registry key watching is supported.
|
|
// This is only supported on Windows NT version 4.0 and higher.
|
|
|
|
DWORD AddWatch(HKEY hRegKey, BOOL bWatchSubtree = FALSE,
|
|
DWORD dwWatchFilter = OXRegistryWatchChangeName | OXRegistryWatchChangeLastSet);
|
|
// --- In : hRegKey : Registry key to be watched.
|
|
// bWatchSubtree : Flag that indicates whether to report changes in the specified key
|
|
// and all of its subkeys or only in the specified key. If this parameter
|
|
// is TRUE, the class reports changes in the key and its subkeys.
|
|
// If the parameter is FALSE, the class reports changes only in the key.
|
|
// dwWatchFilter : Specifies a combination of flags that control which changes should be
|
|
// reported. Flags are described above in the "Data members - public:"
|
|
// section of COXRegistryWatcher Class Specification.
|
|
// --- Out :
|
|
// --- Returns : If the function succeeds - ID of added notifier; if the function fails - 0.
|
|
// To get extended error information, call GetLastError() method of this class.
|
|
// --- Effect : Adds Registry key watch. When hRegKey changes, class calls virtual function
|
|
// OnNotify(), which can be overridden in your derived class.
|
|
// You can add unlimited number of keys to watch.
|
|
|
|
virtual BOOL OnNotify(COXRegistryWatchNotifier* pRegWatchNotifier);
|
|
// --- In : pRegWatchNotifier : Copy of the received parameters in the form of a
|
|
// pointer to COXRegistryWatchNotifier object.
|
|
// --- Out :
|
|
// --- Returns : Indicates whether this notification should be ignored (TRUE) or whether the
|
|
// object may continue handling the event (FALSE). The last option (FALSE) is
|
|
// necessary if the event is to be translated into a window message.
|
|
// --- Effect : This function is called when a Registry change notification is received by
|
|
// specified Registry watch object. It can be overriden in derived classes.
|
|
|
|
BOOL GetWatchIDsFromKey(HKEY hRegKey, CDWordArray& IDs);
|
|
// --- In : hRegKey : Watched Registry key.
|
|
// IDs : Array to store indexes of notifiers linked with specified key.
|
|
// --- Out : IDs : Array of indexes of notifiers linked with specified key.
|
|
// --- Returns : FALSE, if IDs array is empty; TRUE otherwise.
|
|
// --- Effect : Retrieves indexes of notifiers (COXRegistryWatchNotifier objects) that
|
|
// linked to specified Registry key.
|
|
|
|
DWORD COXRegistryWatcher::GetNotifCount();
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns : Number of notifiers. If no notifiers added, returns 0.
|
|
// --- Effect : Returns number of successfully added by AddWatch() function notifiers
|
|
// (COXRegistryWatchNotifier objects), in other words - returns number of
|
|
// watched Registry keys.
|
|
|
|
BOOL RemoveWatch(DWORD dwID);
|
|
// --- In : dwID : Notifier ID (watched Registry key, that was added by AddWatch()).
|
|
// --- Out :
|
|
// --- Returns : TRUE - if the function succeeds, FALSE - if the function fails.
|
|
// To get extended error information, call GetLastError() method of this class.
|
|
// --- Effect : Removes the specified notifier (watch of linked Registry key).
|
|
|
|
BOOL RemoveAllWatches();
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns : TRUE - if the function succeeds, FALSE - if the function fails.
|
|
// To get extended error information, call GetLastError() method of this class.
|
|
// --- Effect : Removes all notifiers (watches on all current watched keys).
|
|
|
|
BOOL EnableWindowNotification(DWORD dwID, CWnd* pWnd, BOOL bPost = TRUE);
|
|
// --- In : dwID : ID of notifier (watched Registry key, that was added by AddWatch()).
|
|
// pWnd : Points to the CWnd class object, that represents window,
|
|
// which will receive the notification message when Registry key changes.
|
|
// bPost : If TRUE, message posts (by default), if FALSE, message sends.
|
|
// --- Out :
|
|
// --- Returns : TRUE - if the function succeeds, FALSE - if the function fails.
|
|
// To get extended error information, call GetLastError() method of this class.
|
|
// --- Effect : Connects a future notification of a Registry watch to a message
|
|
// to a particular window. When a notification is received for that
|
|
// particular key, a specific message is posted/sent to the specified window.
|
|
// This message is WM_OX_REGISTRY_NOTIFY, wParam is index of received
|
|
// notification object (object can be retrieved by GetWatchNotifier()),
|
|
// and lParam is a handle of watched Registry key (HKEY).
|
|
|
|
BOOL DisableWindowNotification(DWORD dwID);
|
|
// --- In : dwID : ID of notifier (watched Registry key, that was added by AddWatch()).
|
|
// --- Out :
|
|
// --- Returns : TRUE - if the function succeeds, FALSE - if the function fails.
|
|
// To get extended error information, call GetLastError() method of this class.
|
|
// --- Effect : Removes connection between specified notification and window.
|
|
|
|
BOOL DisableAllWindowNotifications();
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns : TRUE - if the function succeeds, FALSE - if the function fails.
|
|
// To get extended error information, call GetLastError() method of this class.
|
|
// --- Effect : Removes all connections between notifications of Registry keys and windows.
|
|
|
|
COXRegistryWatchNotifier* GetWatchNotifier(DWORD dwID, DWORD* pdwQueueIndex = NULL);
|
|
// --- In : dwID : ID of notification object (COXRegistryWatchNotifier).
|
|
// pdwQueueIndex : Address of buffer for index of this object in "watch queue".
|
|
// This parameter can be NULL (default).
|
|
// --- Out : pdwQueueIndex : Index of this object in "watch queue" (if pdwQueueIndex != NULL).
|
|
// --- Returns : Pointer to COXRegistryWatchNotifier object.
|
|
// When no object is linked to specified ID, NULL is returned.
|
|
// --- Effect : Returns a specific Registry watch notifier object.
|
|
// This function can be used for notifier ID validity check.
|
|
|
|
HRESULT GetLastError() const;
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns : Code of the last error. Codes are described above in the
|
|
// "Definitions of error codes" section of Class Specification.
|
|
// --- Effect : Returns the error code of the last error that has occurred.
|
|
|
|
protected:
|
|
void AfterNotify(COXRegistryWatchNotifier* pRegWatchNotifier);
|
|
static UINT RegistryWatchThreadFunction(LPVOID pParam);
|
|
BOOL StartWatchThread();
|
|
BOOL StopWatchThread();
|
|
BOOL IsWatchStarted();
|
|
DWORD FindNewID();
|
|
|
|
private:
|
|
|
|
};
|
|
|
|
#endif // __OXREGISTRYWATCHER_H__
|
|
// ==========================================================================
|