} // namespace
+// Watches for modifications to a key.
+class RegKey::Watcher : public ObjectWatcher::Delegate {
+ public:
+ explicit Watcher(RegKey* owner) : owner_(owner) {}
+ ~Watcher() {}
+
+ bool StartWatching(HKEY key, const ChangeCallback& callback);
+
+ // Implementation of ObjectWatcher::Delegate.
+ void OnObjectSignaled(HANDLE object) override {
+ DCHECK(watch_event_.IsValid() && watch_event_.Get() == object);
+ ChangeCallback callback = callback_;
+ callback_.Reset();
+ callback.Run();
+ }
+
+ private:
+ RegKey* owner_;
+ ScopedHandle watch_event_;
+ ObjectWatcher object_watcher_;
+ ChangeCallback callback_;
+ DISALLOW_COPY_AND_ASSIGN(Watcher);
+};
+
+bool RegKey::Watcher::StartWatching(HKEY key, const ChangeCallback& callback) {
+ DCHECK(key);
+ DCHECK(callback_.is_null());
+
+ if (!watch_event_.IsValid())
+ watch_event_.Set(CreateEvent(NULL, TRUE, FALSE, NULL));
+
+ if (!watch_event_.IsValid())
+ return false;
+
+ DWORD filter = REG_NOTIFY_CHANGE_NAME |
+ REG_NOTIFY_CHANGE_ATTRIBUTES |
+ REG_NOTIFY_CHANGE_LAST_SET |
+ REG_NOTIFY_CHANGE_SECURITY;
+
+ // Watch the registry key for a change of value.
+ LONG result = RegNotifyChangeKeyValue(key, TRUE, filter, watch_event_.Get(),
+ TRUE);
+ if (result != ERROR_SUCCESS) {
+ watch_event_.Close();
+ return false;
+ }
+
+ callback_ = callback;
+ return object_watcher_.StartWatching(watch_event_.Get(), this);
+}
+
// RegKey ----------------------------------------------------------------------
-RegKey::RegKey()
- : key_(NULL),
- watch_event_(0),
- wow64access_(0) {
+RegKey::RegKey() : key_(NULL), wow64access_(0) {
}
-RegKey::RegKey(HKEY key)
- : key_(key),
- watch_event_(0),
- wow64access_(0) {
+RegKey::RegKey(HKEY key) : key_(key), wow64access_(0) {
}
RegKey::RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access)
: key_(NULL),
- watch_event_(0),
wow64access_(0) {
if (rootkey) {
if (access & (KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_CREATE_LINK))
}
void RegKey::Close() {
- StopWatching();
if (key_) {
::RegCloseKey(key_);
key_ = NULL;
HKEY RegKey::Take() {
DCHECK(wow64access_ == 0);
- StopWatching();
HKEY key = key_;
key_ = NULL;
return key;
return result;
}
-LONG RegKey::StartWatching() {
- DCHECK(key_);
- if (!watch_event_)
- watch_event_ = CreateEvent(NULL, TRUE, FALSE, NULL);
-
- DWORD filter = REG_NOTIFY_CHANGE_NAME |
- REG_NOTIFY_CHANGE_ATTRIBUTES |
- REG_NOTIFY_CHANGE_LAST_SET |
- REG_NOTIFY_CHANGE_SECURITY;
+bool RegKey::StartWatching(const ChangeCallback& callback) {
+ if (!key_watcher_)
+ key_watcher_.reset(new Watcher(this));
- // Watch the registry key for a change of value.
- LONG result = RegNotifyChangeKeyValue(key_, TRUE, filter, watch_event_, TRUE);
- if (result != ERROR_SUCCESS) {
- CloseHandle(watch_event_);
- watch_event_ = 0;
- }
+ if (!key_watcher_.get()->StartWatching(key_, callback))
+ return false;
- return result;
-}
-
-bool RegKey::HasChanged() {
- if (watch_event_) {
- if (WaitForSingleObject(watch_event_, 0) == WAIT_OBJECT_0) {
- StartWatching();
- return true;
- }
- }
- return false;
-}
-
-LONG RegKey::StopWatching() {
- LONG result = ERROR_INVALID_HANDLE;
- if (watch_event_) {
- CloseHandle(watch_event_);
- watch_event_ = 0;
- result = ERROR_SUCCESS;
- }
- return result;
+ return true;
}
// static
// RegistryValueIterator ------------------------------------------------------
RegistryValueIterator::RegistryValueIterator(HKEY root_key,
+ const wchar_t* folder_key,
+ REGSAM wow64access)
+ : name_(MAX_PATH, L'\0'),
+ value_(MAX_PATH, L'\0') {
+ Initialize(root_key, folder_key, wow64access);
+}
+
+RegistryValueIterator::RegistryValueIterator(HKEY root_key,
const wchar_t* folder_key)
: name_(MAX_PATH, L'\0'),
value_(MAX_PATH, L'\0') {
- LONG result = RegOpenKeyEx(root_key, folder_key, 0, KEY_READ, &key_);
+ Initialize(root_key, folder_key, 0);
+}
+
+void RegistryValueIterator::Initialize(HKEY root_key,
+ const wchar_t* folder_key,
+ REGSAM wow64access) {
+ DCHECK_EQ(wow64access & ~kWow64AccessMask, static_cast<REGSAM>(0));
+ LONG result =
+ RegOpenKeyEx(root_key, folder_key, 0, KEY_READ | wow64access, &key_);
if (result != ERROR_SUCCESS) {
key_ = NULL;
} else {
RegistryKeyIterator::RegistryKeyIterator(HKEY root_key,
const wchar_t* folder_key) {
- LONG result = RegOpenKeyEx(root_key, folder_key, 0, KEY_READ, &key_);
- if (result != ERROR_SUCCESS) {
- key_ = NULL;
- } else {
- DWORD count = 0;
- LONG result = ::RegQueryInfoKey(key_, NULL, 0, NULL, &count, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL);
-
- if (result != ERROR_SUCCESS) {
- ::RegCloseKey(key_);
- key_ = NULL;
- } else {
- index_ = count - 1;
- }
- }
+ Initialize(root_key, folder_key, 0);
+}
- Read();
+RegistryKeyIterator::RegistryKeyIterator(HKEY root_key,
+ const wchar_t* folder_key,
+ REGSAM wow64access) {
+ Initialize(root_key, folder_key, wow64access);
}
RegistryKeyIterator::~RegistryKeyIterator() {
return false;
}
+void RegistryKeyIterator::Initialize(HKEY root_key,
+ const wchar_t* folder_key,
+ REGSAM wow64access) {
+ DCHECK_EQ(wow64access & ~kWow64AccessMask, static_cast<REGSAM>(0));
+ LONG result =
+ RegOpenKeyEx(root_key, folder_key, 0, KEY_READ | wow64access, &key_);
+ if (result != ERROR_SUCCESS) {
+ key_ = NULL;
+ } else {
+ DWORD count = 0;
+ LONG result = ::RegQueryInfoKey(key_, NULL, 0, NULL, &count, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+
+ if (result != ERROR_SUCCESS) {
+ ::RegCloseKey(key_);
+ key_ = NULL;
+ } else {
+ index_ = count - 1;
+ }
+ }
+
+ Read();
+}
+
} // namespace win
} // namespace base