Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / base / win / registry.cc
index a6cb9ae..23ad12c 100644 (file)
@@ -34,23 +34,67 @@ const REGSAM kWow64AccessMask = KEY_WOW64_32KEY | KEY_WOW64_64KEY;
 
 }  // 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))
@@ -150,7 +194,6 @@ LONG RegKey::OpenKey(const wchar_t* relative_key_name, REGSAM access) {
 }
 
 void RegKey::Close() {
-  StopWatching();
   if (key_) {
     ::RegCloseKey(key_);
     key_ = NULL;
@@ -168,7 +211,6 @@ void RegKey::Set(HKEY key) {
 
 HKEY RegKey::Take() {
   DCHECK(wow64access_ == 0);
-  StopWatching();
   HKEY key = key_;
   key_ = NULL;
   return key;
@@ -367,44 +409,14 @@ LONG RegKey::WriteValue(const wchar_t* name,
   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
@@ -487,10 +499,26 @@ LONG RegKey::RegDelRecurse(HKEY root_key,
 // 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 {
@@ -577,23 +605,13 @@ bool RegistryValueIterator::Read() {
 
 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() {
@@ -634,5 +652,29 @@ bool RegistryKeyIterator::Read() {
   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