| OLD | NEW |
| (Empty) |
| 1 // Copyright 2008-2009 Google Inc. | |
| 2 // | |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
| 4 // you may not use this file except in compliance with the License. | |
| 5 // You may obtain a copy of the License at | |
| 6 // | |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | |
| 8 // | |
| 9 // Unless required by applicable law or agreed to in writing, software | |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 12 // See the License for the specific language governing permissions and | |
| 13 // limitations under the License. | |
| 14 // ======================================================================== | |
| 15 // | |
| 16 // RegistryMonitor creates a KeyWatcher for every unique registry key that | |
| 17 // contains a value registered by MonitorValue. Each KeyWatcher is responsible | |
| 18 // for monitoring one or more values in a single registry key but not its | |
| 19 // subkeys. RegistryMonitor manages a thread which waits on event objects. | |
| 20 // The events are signaled when the corresponding monitored key changes. | |
| 21 | |
| 22 #include "omaha/base/registry_monitor_manager.h" | |
| 23 #include <atlbase.h> | |
| 24 #include <utility> | |
| 25 #include <vector> | |
| 26 #include "omaha/base/debug.h" | |
| 27 #include "omaha/base/error.h" | |
| 28 #include "omaha/base/logging.h" | |
| 29 #include "omaha/base/reg_key.h" | |
| 30 #include "omaha/base/scoped_any.h" | |
| 31 #include "omaha/base/synchronized.h" | |
| 32 #include "omaha/base/thread.h" | |
| 33 | |
| 34 namespace omaha { | |
| 35 | |
| 36 namespace detail { | |
| 37 | |
| 38 // converts a registry change type value to a string for logging purposes. | |
| 39 CString RegistryChangeTypeToString(RegistryChangeType registry_change_type) { | |
| 40 switch (registry_change_type) { | |
| 41 case REGISTRY_CHANGE_TYPE_CREATE: | |
| 42 return _T("create"); | |
| 43 case REGISTRY_CHANGE_TYPE_UPDATE: | |
| 44 return _T("update"); | |
| 45 case REGISTRY_CHANGE_TYPE_DELETE: | |
| 46 return _T("delete"); | |
| 47 default: | |
| 48 ASSERT1(false); | |
| 49 return _T("unknown"); | |
| 50 } | |
| 51 }; | |
| 52 | |
| 53 // Holds a pair of root key and sub key, as monitoring must be unique for | |
| 54 // each pair. | |
| 55 class KeyId { | |
| 56 public: | |
| 57 KeyId(HKEY parent_key, const CString& key_name) | |
| 58 : parent_key_(parent_key), key_name_(key_name) {} | |
| 59 | |
| 60 HKEY parent_key() const { return parent_key_; } | |
| 61 CString key_name() const { return key_name_; } | |
| 62 | |
| 63 static bool IsEqual(const KeyId& id1, const KeyId& id2) { | |
| 64 return id1.parent_key_ == id2.parent_key_ && | |
| 65 id1.key_name_ == id2.key_name_; | |
| 66 } | |
| 67 private: | |
| 68 HKEY parent_key_; | |
| 69 CString key_name_; | |
| 70 }; | |
| 71 | |
| 72 class KeyWatcher; | |
| 73 | |
| 74 // ValueWatcher represents a single monitored registry value. | |
| 75 // It is used by KeyWatcher to determine which registry value has changed when | |
| 76 // it detects a change in its key. | |
| 77 class ValueWatcher { | |
| 78 public: | |
| 79 ValueWatcher(KeyWatcher* key_watcher, | |
| 80 const CString& value_name, | |
| 81 int value_type, | |
| 82 RegistryValueChangeCallback callback, | |
| 83 void* user_data); | |
| 84 ~ValueWatcher(); | |
| 85 | |
| 86 // Returns true if the initial value has changed. | |
| 87 bool HasChanged(); | |
| 88 | |
| 89 // Calls the callback function to do the notification of the change. | |
| 90 void DoCallback(); | |
| 91 | |
| 92 private: | |
| 93 CString GetCurrentValueString(); | |
| 94 DWORD GetCurrentValueDword(); | |
| 95 | |
| 96 CString last_known_value_string_; | |
| 97 DWORD last_known_value_dword_; | |
| 98 bool value_is_valid_; | |
| 99 RegistryChangeType change_type_; | |
| 100 CString value_name_; | |
| 101 int value_type_; | |
| 102 KeyWatcher* key_watcher_; | |
| 103 RegistryValueChangeCallback callback_; | |
| 104 void* callback_param_; | |
| 105 }; | |
| 106 | |
| 107 | |
| 108 // KeyWatcher is responsible for monitoring changes to a single key in the | |
| 109 // Windows registry. RegistryMonitor keeps a container of KeyWatcher objects, | |
| 110 // one object for each key that contains a value to be monitored. | |
| 111 class KeyWatcher { | |
| 112 public: | |
| 113 explicit KeyWatcher(const KeyId& key_id); | |
| 114 | |
| 115 ~KeyWatcher(); | |
| 116 | |
| 117 // Adds a new registry value to monitor. | |
| 118 HRESULT AddValue(const CString& value_name, | |
| 119 int value_type, | |
| 120 RegistryValueChangeCallback callback, | |
| 121 void* user_data); | |
| 122 | |
| 123 // Registers the key watcher with the OS and gets ready to receive events. | |
| 124 HRESULT StartWatching(); | |
| 125 | |
| 126 // Returns true if the underlying registry handle corresponds to a valid key. | |
| 127 bool IsKeyValid(); | |
| 128 | |
| 129 HANDLE notification_event() const { return get(notification_event_); } | |
| 130 | |
| 131 RegKey& key() { return key_; } | |
| 132 | |
| 133 CString key_name() const { return key_id_.key_name(); } | |
| 134 | |
| 135 void set_callback(RegistryKeyChangeCallback callback, void* callback_param) { | |
| 136 callback_ = callback; | |
| 137 callback_param_ = callback_param; | |
| 138 } | |
| 139 | |
| 140 // Callback called when the notification event is signaled by the OS | |
| 141 // as a result of a change in the monitored key. | |
| 142 void HandleEvent(HANDLE handle); | |
| 143 | |
| 144 private: | |
| 145 // Ensures the key to monitor is always open. | |
| 146 HRESULT EnsureOpen(); | |
| 147 | |
| 148 std::vector<ValueWatcher*> values_; | |
| 149 RegKey key_; | |
| 150 const KeyId key_id_; | |
| 151 scoped_event notification_event_; | |
| 152 | |
| 153 RegistryKeyChangeCallback callback_; | |
| 154 void* callback_param_; | |
| 155 | |
| 156 DISALLOW_EVIL_CONSTRUCTORS(KeyWatcher); | |
| 157 }; | |
| 158 | |
| 159 class RegistryMonitorImpl : public Runnable { | |
| 160 public: | |
| 161 RegistryMonitorImpl(); | |
| 162 ~RegistryMonitorImpl(); | |
| 163 | |
| 164 HRESULT MonitorKey(HKEY root_key, | |
| 165 const CString& sub_key, | |
| 166 RegistryKeyChangeCallback callback, | |
| 167 void* user_data); | |
| 168 | |
| 169 HRESULT MonitorValue(HKEY root_key, | |
| 170 const CString& sub_key, | |
| 171 const CString& value_name, | |
| 172 int value_type, | |
| 173 RegistryValueChangeCallback callback, | |
| 174 void* user_data); | |
| 175 | |
| 176 HRESULT Initialize(); | |
| 177 | |
| 178 HRESULT StartMonitoring(); | |
| 179 | |
| 180 private: | |
| 181 | |
| 182 // Runnable. | |
| 183 virtual void Run(); | |
| 184 | |
| 185 typedef std::pair<KeyId, KeyWatcher*> Watcher; | |
| 186 std::vector<Watcher> watchers_; | |
| 187 | |
| 188 Thread thread_; | |
| 189 scoped_ptr<Gate> start_monitoring_gate_; | |
| 190 scoped_event stop_monitoring_; | |
| 191 DISALLOW_EVIL_CONSTRUCTORS(RegistryMonitorImpl); | |
| 192 }; | |
| 193 | |
| 194 | |
| 195 ValueWatcher::ValueWatcher(KeyWatcher* key_watcher, | |
| 196 const CString &value_name, | |
| 197 int value_type, | |
| 198 RegistryValueChangeCallback callback, | |
| 199 void* user_data) | |
| 200 : key_watcher_(key_watcher), | |
| 201 value_is_valid_(false), | |
| 202 change_type_(REGISTRY_CHANGE_TYPE_CREATE), | |
| 203 callback_(callback), | |
| 204 callback_param_(user_data), | |
| 205 value_name_(value_name), | |
| 206 value_type_(value_type), | |
| 207 last_known_value_dword_(0) { | |
| 208 ASSERT1(key_watcher); | |
| 209 ASSERT1(callback); | |
| 210 if (value_type_ == REG_SZ) { | |
| 211 last_known_value_string_ = GetCurrentValueString(); | |
| 212 } else if (value_type_ == REG_DWORD) { | |
| 213 last_known_value_dword_ = GetCurrentValueDword(); | |
| 214 } else { | |
| 215 ASSERT(false, (_T("value type not supported"))); | |
| 216 } | |
| 217 } | |
| 218 | |
| 219 ValueWatcher::~ValueWatcher() { | |
| 220 } | |
| 221 | |
| 222 bool ValueWatcher::HasChanged() { | |
| 223 UTIL_LOG(L3, (_T("[ValueWatcher::HasChanged]") | |
| 224 _T("[key name '%s'][value '%s'][valid %d]"), | |
| 225 key_watcher_->key_name(), value_name_, value_is_valid_)); | |
| 226 | |
| 227 const bool value_was_valid = value_is_valid_; | |
| 228 | |
| 229 bool has_changed = false; | |
| 230 if (value_type_ == REG_SZ) { | |
| 231 CString new_value = GetCurrentValueString(); | |
| 232 has_changed = last_known_value_string_ != new_value; | |
| 233 | |
| 234 UTIL_LOG(L3, (_T("[ValueWatcher::HasChanged][old value %s][new value %s]"), | |
| 235 last_known_value_string_, new_value)); | |
| 236 | |
| 237 last_known_value_string_ = new_value; | |
| 238 } else if (value_type_ == REG_DWORD) { | |
| 239 DWORD new_value = GetCurrentValueDword(); | |
| 240 has_changed = last_known_value_dword_ != new_value; | |
| 241 | |
| 242 UTIL_LOG(L3, (_T("[ValueWatcher::HasChanged][old value %d][new value %d]"), | |
| 243 last_known_value_dword_, new_value)); | |
| 244 | |
| 245 last_known_value_dword_ = new_value; | |
| 246 } else { | |
| 247 ASSERT(false, (_T("value type not supported"))); | |
| 248 } | |
| 249 | |
| 250 // Detect the type of the change based on previous and current value state. | |
| 251 if (value_was_valid && value_is_valid_) { | |
| 252 change_type_ = REGISTRY_CHANGE_TYPE_UPDATE; | |
| 253 } else if (value_was_valid && !value_is_valid_) { | |
| 254 change_type_ = REGISTRY_CHANGE_TYPE_DELETE; | |
| 255 } else if (!value_was_valid && value_is_valid_) { | |
| 256 change_type_ = REGISTRY_CHANGE_TYPE_CREATE; | |
| 257 } else { | |
| 258 ASSERT1(!value_was_valid && !value_is_valid_); | |
| 259 } | |
| 260 | |
| 261 if (has_changed) { | |
| 262 UTIL_LOG(L3, (_T("[ValueWatcher::HasChanged]") | |
| 263 _T("[key name '%s'][value '%s' has changed][%s]"), | |
| 264 key_watcher_->key_name(), value_name_, | |
| 265 RegistryChangeTypeToString(change_type_))); | |
| 266 } else { | |
| 267 UTIL_LOG(L3, (_T("[ValueWatcher::HasChanged]") | |
| 268 _T("[key name '%s'][value '%s' is the same]"), | |
| 269 key_watcher_->key_name(), value_name_)); | |
| 270 } | |
| 271 | |
| 272 return has_changed; | |
| 273 } | |
| 274 | |
| 275 CString ValueWatcher::GetCurrentValueString() { | |
| 276 CString value_data; | |
| 277 RegKey& key = key_watcher_->key(); | |
| 278 ASSERT1(key.Key()); | |
| 279 value_is_valid_ = SUCCEEDED(key.GetValue(value_name_, &value_data)); | |
| 280 return value_is_valid_ ? value_data : CString(); | |
| 281 } | |
| 282 | |
| 283 DWORD ValueWatcher::GetCurrentValueDword() { | |
| 284 DWORD value_data = 0; | |
| 285 RegKey& key = key_watcher_->key(); | |
| 286 ASSERT1(key.Key()); | |
| 287 value_is_valid_ = SUCCEEDED(key.GetValue(value_name_, &value_data)); | |
| 288 return value_is_valid_ ? value_data : static_cast<DWORD>(-1); | |
| 289 } | |
| 290 | |
| 291 void ValueWatcher::DoCallback() { | |
| 292 ASSERT1(callback_ != NULL); | |
| 293 | |
| 294 const void* value = NULL; | |
| 295 if (value_type_ == REG_SZ) { | |
| 296 value = static_cast<const TCHAR*>(last_known_value_string_); | |
| 297 } else if (value_type_ == REG_DWORD) { | |
| 298 value = reinterpret_cast<void*>(last_known_value_dword_); | |
| 299 } | |
| 300 | |
| 301 callback_(key_watcher_->key_name(), value_name_, change_type_, | |
| 302 value, callback_param_); | |
| 303 | |
| 304 // If value was not valid, for example, the key was deleted or renamed, and | |
| 305 // it is valid after callback, update last known with the current value. | |
| 306 if (!value_is_valid_) { | |
| 307 if (value_type_ == REG_SZ) { | |
| 308 CString new_value = GetCurrentValueString(); | |
| 309 if (value_is_valid_) { | |
| 310 last_known_value_string_ = new_value; | |
| 311 } | |
| 312 } else if (value_type_ == REG_DWORD) { | |
| 313 DWORD new_value = GetCurrentValueDword(); | |
| 314 if (value_is_valid_) { | |
| 315 last_known_value_dword_ = new_value; | |
| 316 } | |
| 317 } | |
| 318 } | |
| 319 } | |
| 320 | |
| 321 KeyWatcher::KeyWatcher(const KeyId& key_id) | |
| 322 : key_id_(key_id), | |
| 323 notification_event_(::CreateEvent(NULL, false, false, NULL)), | |
| 324 callback_(NULL), | |
| 325 callback_param_(NULL) { | |
| 326 } | |
| 327 | |
| 328 KeyWatcher::~KeyWatcher() { | |
| 329 for (size_t i = 0; i != values_.size(); ++i) { | |
| 330 delete values_[i]; | |
| 331 } | |
| 332 } | |
| 333 | |
| 334 HRESULT KeyWatcher::StartWatching() { | |
| 335 // By this time the key could be deleted or renamed. Check if the handle | |
| 336 // is still valid and reopen the key if needed. | |
| 337 HRESULT hr = EnsureOpen(); | |
| 338 if (FAILED(hr)) { | |
| 339 return hr; | |
| 340 } | |
| 341 ASSERT1(key_.Key()); | |
| 342 const DWORD kNotifyFilter = REG_NOTIFY_CHANGE_NAME | | |
| 343 REG_NOTIFY_CHANGE_ATTRIBUTES | | |
| 344 REG_NOTIFY_CHANGE_LAST_SET | | |
| 345 REG_NOTIFY_CHANGE_SECURITY; | |
| 346 LONG result = ::RegNotifyChangeKeyValue(key_.Key(), false, kNotifyFilter, | |
| 347 get(notification_event_), true); | |
| 348 UTIL_LOG(L3, (_T("[KeyWatcher::StartWatching][key '%s' %s]"), | |
| 349 key_id_.key_name(), | |
| 350 result == ERROR_SUCCESS ? _T("ok") : _T("failed"))); | |
| 351 return HRESULT_FROM_WIN32(result); | |
| 352 } | |
| 353 | |
| 354 HRESULT KeyWatcher::AddValue(const CString& value_name, | |
| 355 int value_type, | |
| 356 RegistryValueChangeCallback callback, | |
| 357 void* user_data) { | |
| 358 ASSERT1(callback); | |
| 359 HRESULT hr = EnsureOpen(); | |
| 360 if (FAILED(hr)) { | |
| 361 return hr; | |
| 362 } | |
| 363 values_.push_back( | |
| 364 new ValueWatcher(this, value_name, value_type, callback, user_data)); | |
| 365 return S_OK; | |
| 366 } | |
| 367 | |
| 368 void KeyWatcher::HandleEvent(HANDLE handle) { | |
| 369 UTIL_LOG(L3, (_T("[KeyWatcher::HandleEvent][key '%s']"), key_id_.key_name())); | |
| 370 | |
| 371 ASSERT1(handle); | |
| 372 ASSERT1(handle == get(notification_event_)); | |
| 373 UNREFERENCED_PARAMETER(handle); | |
| 374 | |
| 375 // Although not documented, it seems the OS pulses the event so the event | |
| 376 // is never signaled at this point. | |
| 377 ASSERT1(::WaitForSingleObject(handle, 0) == WAIT_TIMEOUT); | |
| 378 | |
| 379 // Notify the key has changed. | |
| 380 if (callback_) { | |
| 381 callback_(key_name(), callback_param_); | |
| 382 } | |
| 383 | |
| 384 // Notify the values have changed. | |
| 385 for (size_t i = 0; i != values_.size(); ++i) { | |
| 386 ValueWatcher* value = values_[i]; | |
| 387 if (value != NULL) { | |
| 388 if (value->HasChanged()) { | |
| 389 value->DoCallback(); | |
| 390 } | |
| 391 } | |
| 392 } | |
| 393 | |
| 394 VERIFY1(SUCCEEDED(StartWatching())); | |
| 395 } | |
| 396 | |
| 397 HRESULT KeyWatcher::EnsureOpen() { | |
| 398 // Close the key if it is not valid for whatever reasons, such as it was | |
| 399 // deleted and recreated back. | |
| 400 if (!IsKeyValid()) { | |
| 401 UTIL_LOG(L3, (_T("[key '%s' is not valid]"), key_id_.key_name())); | |
| 402 VERIFY1(SUCCEEDED(key_.Close())); | |
| 403 } | |
| 404 | |
| 405 // Open the key if not already open or create the key if needed. | |
| 406 HRESULT hr = S_OK; | |
| 407 if (!key_.Key()) { | |
| 408 hr = key_.Create(key_id_.parent_key(), key_id_.key_name()); | |
| 409 if (SUCCEEDED(hr)) { | |
| 410 UTIL_LOG(L3, (_T("[key '%s' has been created]"), key_id_.key_name())); | |
| 411 } | |
| 412 } | |
| 413 return hr; | |
| 414 } | |
| 415 | |
| 416 bool KeyWatcher::IsKeyValid() { | |
| 417 if (!key_.Key()) { | |
| 418 return false; | |
| 419 } | |
| 420 LONG ret = RegQueryInfoKey(key_.Key(), | |
| 421 NULL, NULL, NULL, NULL, NULL, | |
| 422 NULL, NULL, NULL, NULL, NULL, NULL); | |
| 423 return ret == ERROR_SUCCESS; | |
| 424 } | |
| 425 | |
| 426 RegistryMonitorImpl::RegistryMonitorImpl() { | |
| 427 } | |
| 428 | |
| 429 RegistryMonitorImpl::~RegistryMonitorImpl() { | |
| 430 if (stop_monitoring_) { | |
| 431 VERIFY1(::SetEvent(get(stop_monitoring_))); | |
| 432 } | |
| 433 VERIFY1(thread_.WaitTillExit(INFINITE)); | |
| 434 | |
| 435 for (size_t i = 0; i != watchers_.size(); ++i) { | |
| 436 ASSERT1(watchers_[i].second); | |
| 437 delete watchers_[i].second; | |
| 438 } | |
| 439 } | |
| 440 | |
| 441 HRESULT RegistryMonitorImpl::Initialize() { | |
| 442 reset(stop_monitoring_, ::CreateEvent(NULL, true, false, NULL)); | |
| 443 if (!stop_monitoring_) { | |
| 444 return HRESULTFromLastError(); | |
| 445 } | |
| 446 return S_OK; | |
| 447 } | |
| 448 | |
| 449 HRESULT RegistryMonitorImpl::MonitorKey(HKEY root_key, | |
| 450 const CString& sub_key, | |
| 451 RegistryKeyChangeCallback callback, | |
| 452 void* user_data) { | |
| 453 ASSERT1(callback); | |
| 454 ASSERT1(!thread_.Running()); | |
| 455 | |
| 456 KeyId key_id(root_key, sub_key); | |
| 457 for (size_t i = 0; i != watchers_.size(); ++i) { | |
| 458 if (KeyId::IsEqual(watchers_[i].first, key_id)) { | |
| 459 watchers_[i].second->set_callback(callback, user_data); | |
| 460 return S_OK; | |
| 461 } | |
| 462 } | |
| 463 scoped_ptr<KeyWatcher> key_watcher(new KeyWatcher(key_id)); | |
| 464 key_watcher->set_callback(callback, user_data); | |
| 465 Watcher watcher(key_id, key_watcher.release()); | |
| 466 watchers_.push_back(watcher); | |
| 467 return S_OK; | |
| 468 } | |
| 469 | |
| 470 HRESULT RegistryMonitorImpl::MonitorValue( | |
| 471 HKEY root_key, const CString& sub_key, const CString& value_name, | |
| 472 int value_type, RegistryValueChangeCallback callback, void* user_data) { | |
| 473 ASSERT1(callback); | |
| 474 ASSERT1(!thread_.Running()); | |
| 475 | |
| 476 // Reuse an existing key watcher if there is a value already registered | |
| 477 // for monitoring under the respective registry key. | |
| 478 KeyId key_id(root_key, sub_key); | |
| 479 for (size_t i = 0; i != watchers_.size(); ++i) { | |
| 480 if (KeyId::IsEqual(watchers_[i].first, key_id)) { | |
| 481 return watchers_[i].second->AddValue(value_name, value_type, | |
| 482 callback, user_data); | |
| 483 } | |
| 484 } | |
| 485 scoped_ptr<KeyWatcher> key_watcher(new KeyWatcher(key_id)); | |
| 486 HRESULT hr = key_watcher->AddValue(value_name, value_type, | |
| 487 callback, user_data); | |
| 488 if (FAILED(hr)) { | |
| 489 UTIL_LOG(LE, (_T("[RegistryMonitorImpl::RegisterValue failed]") | |
| 490 _T("[key %s][value %s][0x%x]"), sub_key, value_name, hr)); | |
| 491 return hr; | |
| 492 } | |
| 493 Watcher watcher(key_id, key_watcher.release()); | |
| 494 watchers_.push_back(watcher); | |
| 495 return S_OK; | |
| 496 } | |
| 497 | |
| 498 HRESULT RegistryMonitorImpl::StartMonitoring() { | |
| 499 // Starts the thread and waits on the gate for the thread to open after | |
| 500 // it has registered all watchers for notifications and it is ready to | |
| 501 // handle notification events. The gate is only needed to synchronize the | |
| 502 // caller and the monitoring threads. | |
| 503 start_monitoring_gate_.reset(new Gate); | |
| 504 if (!thread_.Start(this)) { | |
| 505 return E_FAIL; | |
| 506 } | |
| 507 bool wait_result = start_monitoring_gate_->Wait(INFINITE); | |
| 508 start_monitoring_gate_.reset(); | |
| 509 ASSERT1(wait_result); | |
| 510 return wait_result ? S_OK : HRESULTFromLastError(); | |
| 511 } | |
| 512 | |
| 513 void RegistryMonitorImpl::Run() { | |
| 514 UTIL_LOG(L3, (_T("[started monitoring registry]"))); | |
| 515 | |
| 516 const size_t kNumNotificationHandles = watchers_.size(); | |
| 517 const size_t kNumHandles = kNumNotificationHandles + 1; | |
| 518 const size_t kStopMonitoringHandleIndex = kNumNotificationHandles; | |
| 519 | |
| 520 scoped_array<HANDLE> handles(new HANDLE[kNumHandles]); | |
| 521 for (size_t i = 0; i != watchers_.size(); ++i) { | |
| 522 handles[i] = watchers_[i].second->notification_event(); | |
| 523 VERIFY1(SUCCEEDED(watchers_[i].second->StartWatching())); | |
| 524 } | |
| 525 handles[kStopMonitoringHandleIndex] = get(stop_monitoring_); | |
| 526 | |
| 527 // Open the gate and allow the RegistryMonitor::StartMonitoring call to | |
| 528 // to return to the caller. | |
| 529 ASSERT1(start_monitoring_gate_.get()); | |
| 530 VERIFY1(start_monitoring_gate_->Open()); | |
| 531 | |
| 532 for (;;) { | |
| 533 DWORD result = ::WaitForMultipleObjects(kNumHandles, | |
| 534 handles.get(), | |
| 535 false, | |
| 536 INFINITE); | |
| 537 COMPILE_ASSERT(0 == WAIT_OBJECT_0, invalid_wait_object_0); | |
| 538 ASSERT1(result < kNumHandles); | |
| 539 if (result < kNumHandles) { | |
| 540 if (result == kStopMonitoringHandleIndex) { | |
| 541 break; | |
| 542 } else { | |
| 543 size_t i = result - WAIT_OBJECT_0; | |
| 544 watchers_[i].second->HandleEvent(handles[i]); | |
| 545 } | |
| 546 } | |
| 547 } | |
| 548 UTIL_LOG(L3, (_T("[stopped monitoring registry]"))); | |
| 549 } | |
| 550 | |
| 551 } // namespace detail | |
| 552 | |
| 553 RegistryMonitor::RegistryMonitor() | |
| 554 : impl_(new detail::RegistryMonitorImpl) { | |
| 555 } | |
| 556 | |
| 557 RegistryMonitor::~RegistryMonitor() { | |
| 558 } | |
| 559 | |
| 560 HRESULT RegistryMonitor::MonitorKey(HKEY root_key, | |
| 561 const CString& sub_key, | |
| 562 RegistryKeyChangeCallback callback, | |
| 563 void* user_data) { | |
| 564 return impl_->MonitorKey(root_key, sub_key, callback, user_data); | |
| 565 } | |
| 566 | |
| 567 HRESULT RegistryMonitor::MonitorValue(HKEY root_key, | |
| 568 const CString& sub_key, | |
| 569 const CString& value_name, | |
| 570 int value_type, | |
| 571 RegistryValueChangeCallback callback, | |
| 572 void* user_data) { | |
| 573 return impl_->MonitorValue(root_key, sub_key, value_name, value_type, | |
| 574 callback, user_data); | |
| 575 } | |
| 576 | |
| 577 HRESULT RegistryMonitor::Initialize() { | |
| 578 return impl_->Initialize(); | |
| 579 } | |
| 580 | |
| 581 HRESULT RegistryMonitor::StartMonitoring() { | |
| 582 return impl_->StartMonitoring(); | |
| 583 } | |
| 584 | |
| 585 } // namespace omaha | |
| 586 | |
| OLD | NEW |