| Index: base/reg_key.cc
|
| diff --git a/base/reg_key.cc b/base/reg_key.cc
|
| deleted file mode 100644
|
| index 67abedfb28ddb61ae318eeacc0d03df9ca2e5282..0000000000000000000000000000000000000000
|
| --- a/base/reg_key.cc
|
| +++ /dev/null
|
| @@ -1,1277 +0,0 @@
|
| -// Copyright 2003-2009 Google Inc.
|
| -//
|
| -// Licensed under the Apache License, Version 2.0 (the "License");
|
| -// you may not use this file except in compliance with the License.
|
| -// You may obtain a copy of the License at
|
| -//
|
| -// http://www.apache.org/licenses/LICENSE-2.0
|
| -//
|
| -// Unless required by applicable law or agreed to in writing, software
|
| -// distributed under the License is distributed on an "AS IS" BASIS,
|
| -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| -// See the License for the specific language governing permissions and
|
| -// limitations under the License.
|
| -// ========================================================================
|
| -//
|
| -// Registry configuration wrapers class implementation
|
| -
|
| -#include <raserror.h>
|
| -#include "omaha/base/reg_key.h"
|
| -#include "omaha/base/logging.h"
|
| -#include "omaha/base/scoped_any.h"
|
| -#include "omaha/base/scoped_ptr_address.h"
|
| -#include "omaha/base/static_assert.h"
|
| -#include "omaha/base/string.h"
|
| -#include "omaha/base/synchronized.h"
|
| -#include "omaha/base/system.h"
|
| -#include "omaha/base/utils.h"
|
| -
|
| -namespace omaha {
|
| -
|
| -HRESULT RegKey::Close() {
|
| - HRESULT hr = S_OK;
|
| - if (h_key_ != NULL) {
|
| - LONG res = RegCloseKey(h_key_);
|
| - hr = HRESULT_FROM_WIN32(res);
|
| - h_key_ = NULL;
|
| - }
|
| - return hr;
|
| -}
|
| -
|
| -HRESULT RegKey::Create(HKEY hKeyParent,
|
| - const TCHAR * key_name,
|
| - TCHAR * lpszClass,
|
| - DWORD options,
|
| - REGSAM sam_desired,
|
| - LPSECURITY_ATTRIBUTES lpSecAttr,
|
| - LPDWORD lpdwDisposition) {
|
| - // lpszClass may be NULL
|
| - ASSERT1(key_name);
|
| - ASSERT1(hKeyParent != NULL);
|
| - DWORD dw;
|
| - HKEY hKey = NULL;
|
| - LONG res = ::RegCreateKeyEx(hKeyParent,
|
| - key_name,
|
| - 0,
|
| - lpszClass,
|
| - options,
|
| - sam_desired,
|
| - lpSecAttr,
|
| - &hKey,
|
| - &dw);
|
| - HRESULT hr = HRESULT_FROM_WIN32(res);
|
| -
|
| - if (lpdwDisposition != NULL)
|
| - *lpdwDisposition = dw;
|
| - // we have to close the currently opened key
|
| - // before replacing it with the new one
|
| - if (hr == S_OK) {
|
| - hr = Close();
|
| - ASSERT1(hr == S_OK);
|
| - h_key_ = hKey;
|
| - }
|
| - return hr;
|
| -}
|
| -
|
| -HRESULT RegKey::Create(const TCHAR * full_key_name,
|
| - TCHAR * lpszClass, DWORD options,
|
| - REGSAM sam_desired,
|
| - LPSECURITY_ATTRIBUTES lpSecAttr,
|
| - LPDWORD lpdwDisposition) {
|
| - // lpszClass may be NULL
|
| - ASSERT1(full_key_name);
|
| - CString key_name(full_key_name);
|
| -
|
| - HKEY parent_key = RegKey::GetRootKeyInfo(&key_name);
|
| - if (!parent_key) {
|
| - ASSERT(false, (_T("unable to get root key location %s"), full_key_name));
|
| - return HRESULT_FROM_WIN32(ERROR_KEY_NOT_FOUND);
|
| - }
|
| -
|
| - return Create(parent_key, key_name, lpszClass,
|
| - options, sam_desired, lpSecAttr, lpdwDisposition);
|
| -}
|
| -
|
| -HRESULT RegKey::CreateKeys(const TCHAR* keys_to_create[],
|
| - DWORD number_of_keys,
|
| - TCHAR* lpszClass,
|
| - DWORD options,
|
| - LPSECURITY_ATTRIBUTES lpSecAttr) {
|
| - ASSERT1(keys_to_create);
|
| - ASSERT1(number_of_keys);
|
| -
|
| - for (DWORD i = 0; i < number_of_keys; i++) {
|
| - HRESULT hr = CreateKey(keys_to_create[i], lpszClass, options, lpSecAttr);
|
| - if (FAILED(hr)) {
|
| - return hr;
|
| - }
|
| - }
|
| -
|
| - return S_OK;
|
| -}
|
| -
|
| -HRESULT RegKey::CreateKey(const TCHAR* full_key_name,
|
| - TCHAR* lpszClass,
|
| - DWORD options,
|
| - LPSECURITY_ATTRIBUTES lpSecAttr) {
|
| - ASSERT1(full_key_name);
|
| -
|
| - RegKey key;
|
| - HRESULT hr = key.Create(full_key_name,
|
| - lpszClass,
|
| - options,
|
| - KEY_ALL_ACCESS,
|
| - lpSecAttr,
|
| - NULL);
|
| - if (FAILED(hr)) {
|
| - UTIL_LOG(L3, (_T("[couldn't create %s reg key]"), full_key_name));
|
| - return hr;
|
| - }
|
| -
|
| - return S_OK;
|
| -}
|
| -
|
| -HRESULT RegKey::Open(HKEY hKeyParent,
|
| - const TCHAR * key_name,
|
| - REGSAM sam_desired) {
|
| - ASSERT1(key_name);
|
| - ASSERT1(hKeyParent != NULL);
|
| - HKEY hKey = NULL;
|
| - LONG res = ::RegOpenKeyEx(hKeyParent, key_name, 0, sam_desired, &hKey);
|
| - HRESULT hr = HRESULT_FROM_WIN32(res);
|
| -
|
| - // we have to close the currently opened key
|
| - // before replacing it with the new one
|
| - if (hr == S_OK) {
|
| - // close the currently opened key if any
|
| - hr = Close();
|
| - ASSERT1(hr == S_OK);
|
| - h_key_ = hKey;
|
| - }
|
| - return hr;
|
| -}
|
| -
|
| -HRESULT RegKey::Open(const TCHAR * full_key_name, REGSAM sam_desired) {
|
| - ASSERT1(full_key_name);
|
| - CString key_name(full_key_name);
|
| -
|
| - HKEY parent_key = RegKey::GetRootKeyInfo(&key_name);
|
| - if (!parent_key) {
|
| - ASSERT(false, (_T("unable to get root key for %s"), full_key_name));
|
| - return HRESULT_FROM_WIN32(ERROR_KEY_NOT_FOUND);
|
| - }
|
| -
|
| - return Open(parent_key, key_name, sam_desired);
|
| -}
|
| -
|
| -// save the key and all of its subkeys and values to a file
|
| -HRESULT RegKey::Save(const TCHAR* full_key_name, const TCHAR* file_name) {
|
| - ASSERT1(full_key_name);
|
| - ASSERT1(file_name);
|
| -
|
| - CString key_name(full_key_name);
|
| - HKEY h_key = GetRootKeyInfo(&key_name);
|
| - if (!h_key) {
|
| - return E_FAIL;
|
| - }
|
| -
|
| - RegKey key;
|
| - HRESULT hr = key.Open(h_key, key_name, KEY_READ);
|
| - if (FAILED(hr)) {
|
| - return hr;
|
| - }
|
| -
|
| - System::AdjustPrivilege(SE_BACKUP_NAME, true);
|
| - LONG res = ::RegSaveKey(key.h_key_, file_name, NULL);
|
| - System::AdjustPrivilege(SE_BACKUP_NAME, false);
|
| -
|
| - return HRESULT_FROM_WIN32(res);
|
| -}
|
| -
|
| -// restore the key and all of its subkeys and values which are saved into a file
|
| -HRESULT RegKey::Restore(const TCHAR* full_key_name, const TCHAR* file_name) {
|
| - ASSERT1(full_key_name);
|
| - ASSERT1(file_name);
|
| -
|
| - CString key_name(full_key_name);
|
| - HKEY h_key = GetRootKeyInfo(&key_name);
|
| - if (!h_key) {
|
| - return E_FAIL;
|
| - }
|
| -
|
| - RegKey key;
|
| - HRESULT hr = key.Open(h_key, key_name, KEY_WRITE);
|
| - if (FAILED(hr)) {
|
| - return hr;
|
| - }
|
| -
|
| - System::AdjustPrivilege(SE_RESTORE_NAME, true);
|
| - LONG res = ::RegRestoreKey(key.h_key_, file_name, REG_FORCE_RESTORE);
|
| - System::AdjustPrivilege(SE_RESTORE_NAME, false);
|
| -
|
| - return HRESULT_FROM_WIN32(res);
|
| -}
|
| -
|
| -// check if the current key has the specified subkey
|
| -bool RegKey::HasSubkey(const TCHAR * key_name) const {
|
| - ASSERT1(key_name);
|
| - ASSERT1(h_key_);
|
| -
|
| - RegKey key;
|
| - HRESULT hr = key.Open(h_key_, key_name, KEY_READ);
|
| - key.Close();
|
| - return S_OK == hr;
|
| -}
|
| -
|
| -// static flush key
|
| -HRESULT RegKey::FlushKey(const TCHAR * full_key_name) {
|
| - ASSERT1(full_key_name);
|
| -
|
| - HRESULT hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
|
| - // get the root HKEY
|
| - CString key_name(full_key_name);
|
| - HKEY h_key = GetRootKeyInfo(&key_name);
|
| -
|
| - if (h_key != NULL) {
|
| - LONG res = RegFlushKey(h_key);
|
| - hr = HRESULT_FROM_WIN32(res);
|
| - }
|
| - return hr;
|
| -}
|
| -
|
| -// static SET helper
|
| -HRESULT RegKey::SetValueStaticHelper(const TCHAR * full_key_name,
|
| - const TCHAR * value_name,
|
| - DWORD type,
|
| - LPVOID value,
|
| - DWORD byte_count) {
|
| - // value_name may be NULL
|
| - ASSERT1(full_key_name);
|
| -
|
| - HRESULT hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
|
| - // get the root HKEY
|
| - CString key_name(full_key_name);
|
| - HKEY h_key = GetRootKeyInfo(&key_name);
|
| -
|
| - if (h_key != NULL) {
|
| - RegKey key;
|
| - hr = key.Create(h_key, key_name.GetString());
|
| - if (hr == S_OK) {
|
| - switch (type) {
|
| - case REG_DWORD:
|
| - hr = key.SetValue(value_name, *reinterpret_cast<DWORD *>(value));
|
| - if (SUCCEEDED(hr)) {
|
| - UTIL_LOG(L6, (_T("[Wrote int32 value: %s:%s = %d]"),
|
| - full_key_name,
|
| - value_name,
|
| - *reinterpret_cast<DWORD*>(value)));
|
| - }
|
| - break;
|
| - case REG_QWORD:
|
| - hr = key.SetValue(value_name, *reinterpret_cast<DWORD64 *>(value));
|
| - if (SUCCEEDED(hr)) {
|
| - UTIL_LOG(L6, (_T("[Wrote int64 value: %s:%s = %s]"),
|
| - full_key_name,
|
| - value_name,
|
| - String_Int64ToString(
|
| - *reinterpret_cast<DWORD64*>(value), 10)));
|
| - }
|
| - break;
|
| - case REG_SZ:
|
| - hr = key.SetValue(value_name, reinterpret_cast<const TCHAR *>(value));
|
| - if (SUCCEEDED(hr)) {
|
| - UTIL_LOG(L6, (_T("[Wrote string value: %s:%s = %s]"),
|
| - full_key_name,
|
| - value_name,
|
| - reinterpret_cast<const TCHAR *>(value)));
|
| - }
|
| - break;
|
| - case REG_BINARY:
|
| - hr = key.SetValue(value_name,
|
| - reinterpret_cast<const byte *>(value),
|
| - byte_count);
|
| - if (SUCCEEDED(hr)) {
|
| - UTIL_LOG(L6, (_T("[Wrote binary value: %s:%s, len = %d]"),
|
| - full_key_name, value_name, byte_count));
|
| - }
|
| - break;
|
| - case REG_MULTI_SZ:
|
| - hr = key.SetValue(value_name,
|
| - reinterpret_cast<const byte *>(value),
|
| - byte_count,
|
| - type);
|
| - if (SUCCEEDED(hr)) {
|
| - UTIL_LOG(L6, (_T("[Wrote multi-sz value: %s:%s, len = %d]"),
|
| - full_key_name, value_name, byte_count));
|
| - }
|
| - break;
|
| - case REG_EXPAND_SZ:
|
| - hr = key.SetStringValue(value_name,
|
| - reinterpret_cast<const TCHAR *>(value),
|
| - type);
|
| - if (SUCCEEDED(hr)) {
|
| - UTIL_LOG(L6, (_T("[Wrote expandable string value: %s:%s = %s]"),
|
| - full_key_name, value_name, (const TCHAR *)value));
|
| - }
|
| - break;
|
| - default:
|
| - ASSERT(false, (_T("Unsupported Registry Type")));
|
| - hr = HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH);
|
| - break;
|
| - }
|
| - // close the key after writing
|
| - HRESULT temp_res = key.Close();
|
| - if (hr == S_OK) {
|
| - hr = temp_res;
|
| - } else {
|
| - ASSERT(false, (_T("Failed to write reg value: %s:%s (hr=0x%x)"),
|
| - full_key_name, value_name, hr));
|
| - }
|
| - } else {
|
| - UTIL_LOG(L3, (_T("[Failed to create reg key: %s]"), full_key_name));
|
| - }
|
| - }
|
| - return hr;
|
| -}
|
| -
|
| -// static GET helper
|
| -// byte_count may be NULL.
|
| -// value_name may be NULL.
|
| -HRESULT RegKey::GetValueStaticHelper(const TCHAR * full_key_name,
|
| - const TCHAR * value_name,
|
| - DWORD type,
|
| - LPVOID value,
|
| - DWORD * byte_count) {
|
| - ASSERT1(full_key_name);
|
| -
|
| - HRESULT hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
|
| - // get the root HKEY
|
| - CString key_name(full_key_name);
|
| - HKEY h_key = GetRootKeyInfo(&key_name);
|
| -
|
| - if (h_key != NULL) {
|
| - RegKey key;
|
| - hr = key.Open(h_key, key_name.GetString(), KEY_READ);
|
| - if (hr == S_OK) {
|
| - switch (type) {
|
| - case REG_DWORD:
|
| - hr = key.GetValue(value_name, reinterpret_cast<DWORD *>(value));
|
| - if (SUCCEEDED(hr)) {
|
| - UTIL_LOG(L6, (_T("[Read int32 value: %s:%s = %d]"),
|
| - full_key_name,
|
| - value_name,
|
| - *reinterpret_cast<DWORD*>(value)));
|
| - }
|
| - break;
|
| - case REG_QWORD:
|
| - hr = key.GetValue(value_name, reinterpret_cast<DWORD64 *>(value));
|
| - if (SUCCEEDED(hr)) {
|
| - UTIL_LOG(L6, (_T("[Read int64 value: %s:%s = %s]"),
|
| - full_key_name,
|
| - value_name,
|
| - String_Int64ToString(
|
| - *(reinterpret_cast<DWORD64*>(value)), 10)));
|
| - }
|
| - break;
|
| - case REG_SZ:
|
| - hr = key.GetValue(value_name, reinterpret_cast<TCHAR * *>(value));
|
| - if (SUCCEEDED(hr)) {
|
| - UTIL_LOG(L6, (_T("[Read string value: %s:%s = %s]"),
|
| - full_key_name,
|
| - value_name,
|
| - *reinterpret_cast<TCHAR * *>(value)));
|
| - }
|
| - break;
|
| - case REG_MULTI_SZ:
|
| - hr = key.GetValue(value_name,
|
| - reinterpret_cast<std::vector<CString> *>(value));
|
| - if (SUCCEEDED(hr)) {
|
| - UTIL_LOG(L6, (_T("[Read multi string value: %s:%s = %d]"),
|
| - full_key_name,
|
| - value_name,
|
| - reinterpret_cast<std::vector<CString>*>(value)->size()));
|
| - }
|
| - break;
|
| - case REG_BINARY:
|
| - hr = key.GetValue(value_name,
|
| - reinterpret_cast<byte * *>(value),
|
| - byte_count);
|
| - if (SUCCEEDED(hr)) {
|
| - UTIL_LOG(L6, (_T("[Read binary value: %s:%s, len = %d]"),
|
| - full_key_name, value_name, byte_count));
|
| - }
|
| - break;
|
| - default:
|
| - ASSERT(false, (_T("Unsupported Registry Type")));
|
| - hr = HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH);
|
| - break;
|
| - }
|
| - // close the key after writing
|
| - HRESULT temp_res = key.Close();
|
| - if (hr == S_OK) {
|
| - hr = temp_res;
|
| - } else {
|
| - UTIL_LOG(L5, (_T("[Failed to read reg value: %s:%s]"),
|
| - full_key_name, value_name));
|
| - }
|
| - } else {
|
| - UTIL_LOG(L5, (_T("[reg value does not exist: %s]"), key_name));
|
| - }
|
| - }
|
| - return hr;
|
| -}
|
| -
|
| -// GET helper
|
| -// value_name may be NULL.
|
| -HRESULT RegKey::GetValueHelper(const TCHAR * value_name,
|
| - DWORD * type,
|
| - byte * * value,
|
| - DWORD * byte_count) const {
|
| - ASSERT1(byte_count);
|
| - ASSERT1(value);
|
| - ASSERT1(type);
|
| - ASSERT1(h_key_);
|
| -
|
| - // init return buffer
|
| - *value = NULL;
|
| -
|
| - // get the size of the return data buffer
|
| - LONG res = ::SHQueryValueEx(h_key_, value_name, NULL, type, NULL, byte_count);
|
| - HRESULT hr = HRESULT_FROM_WIN32(res);
|
| -
|
| - if (hr == S_OK) {
|
| - // if the value length is 0, nothing to do
|
| - if (*byte_count != 0) {
|
| - // allocate the buffer
|
| - *value = new byte[*byte_count];
|
| - ASSERT1(*value);
|
| -
|
| - // make the call again to get the data
|
| - res = ::SHQueryValueEx(h_key_,
|
| - value_name,
|
| - NULL,
|
| - type,
|
| - *value,
|
| - byte_count);
|
| - hr = HRESULT_FROM_WIN32(res);
|
| - ASSERT1(S_OK == hr);
|
| - }
|
| - }
|
| - return hr;
|
| -}
|
| -
|
| -// value_name may be NULL
|
| -HRESULT RegKey::GetValueType(const TCHAR* value_name,
|
| - DWORD* value_type) const {
|
| - ASSERT1(value_type);
|
| -
|
| - *value_type = REG_NONE;
|
| -
|
| - LONG res = ::SHQueryValueEx(h_key_, value_name, NULL, value_type, NULL, NULL);
|
| - if (res != ERROR_SUCCESS) {
|
| - return HRESULT_FROM_WIN32(res);
|
| - }
|
| -
|
| - return S_OK;
|
| -}
|
| -
|
| -// Int32 Get
|
| -// value_name may be NULL.
|
| -HRESULT RegKey::GetValue(const TCHAR * value_name, DWORD * value) const {
|
| - ASSERT1(value);
|
| - ASSERT1(h_key_);
|
| -
|
| - DWORD type = 0;
|
| - DWORD byte_count = sizeof(DWORD);
|
| - LONG res = ::SHQueryValueEx(h_key_,
|
| - value_name,
|
| - NULL,
|
| - &type,
|
| - reinterpret_cast<byte*>(value),
|
| - &byte_count);
|
| - HRESULT hr = HRESULT_FROM_WIN32(res);
|
| - ASSERT1((hr != S_OK) || (type == REG_DWORD));
|
| - ASSERT1((hr != S_OK) || (byte_count == sizeof(DWORD)));
|
| - return hr;
|
| -}
|
| -
|
| -// Int64 Get
|
| -// value_name may be NULL.
|
| -HRESULT RegKey::GetValue(const TCHAR * value_name, DWORD64 * value) const {
|
| - ASSERT1(value);
|
| - ASSERT1(h_key_);
|
| -
|
| - DWORD type = 0;
|
| - DWORD byte_count = sizeof(DWORD64);
|
| - LONG res = ::SHQueryValueEx(h_key_,
|
| - value_name,
|
| - NULL,
|
| - &type,
|
| - reinterpret_cast<byte *>(value),
|
| - &byte_count);
|
| - HRESULT hr = HRESULT_FROM_WIN32(res);
|
| - ASSERT1((hr != S_OK) || (type == REG_QWORD));
|
| - ASSERT1((hr != S_OK) || (byte_count == sizeof(DWORD64)));
|
| - return hr;
|
| -}
|
| -
|
| -// String Get
|
| -// value_name may be NULL.
|
| -HRESULT RegKey::GetValue(const TCHAR * value_name, TCHAR * * value) const {
|
| - ASSERT1(value);
|
| - ASSERT1(h_key_);
|
| -
|
| - DWORD byte_count = 0;
|
| - DWORD type = 0;
|
| -
|
| - // first get the size of the string buffer
|
| - LONG res = ::SHQueryValueEx(h_key_,
|
| - value_name,
|
| - NULL,
|
| - &type,
|
| - NULL,
|
| - &byte_count);
|
| - HRESULT hr = HRESULT_FROM_WIN32(res);
|
| -
|
| - if (hr == S_OK) {
|
| - // allocate room for the string and a terminating \0
|
| - *value = new TCHAR[(byte_count / sizeof(TCHAR)) + 1];
|
| -
|
| - if ((*value) != NULL) {
|
| - if (byte_count != 0) {
|
| - // make the call again
|
| - res = ::SHQueryValueEx(h_key_, value_name, NULL, &type,
|
| - reinterpret_cast<byte*>(*value), &byte_count);
|
| - hr = HRESULT_FROM_WIN32(res);
|
| - } else {
|
| - (*value)[0] = _T('\0');
|
| - }
|
| -
|
| - ASSERT1((hr != S_OK) || (type == REG_SZ) ||
|
| - (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ));
|
| - } else {
|
| - hr = E_OUTOFMEMORY;
|
| - }
|
| - }
|
| -
|
| - return hr;
|
| -}
|
| -
|
| -// CString Get
|
| -// value_name may be NULL.
|
| -HRESULT RegKey::GetValue(const TCHAR* value_name, OUT CString* value) const {
|
| - ASSERT1(value);
|
| - ASSERT1(h_key_);
|
| -
|
| - DWORD byte_count = 0;
|
| - DWORD type = 0;
|
| -
|
| - // first get the size of the string buffer
|
| - LONG res = ::SHQueryValueEx(h_key_,
|
| - value_name,
|
| - NULL,
|
| - &type,
|
| - NULL,
|
| - &byte_count);
|
| - HRESULT hr = HRESULT_FROM_WIN32(res);
|
| -
|
| - if (hr == S_OK) {
|
| - if (byte_count != 0) {
|
| - // Allocate some memory and make the call again
|
| - TCHAR* buffer = value->GetBuffer(byte_count / sizeof(TCHAR) + 1);
|
| - if (buffer == NULL) {
|
| - hr = E_OUTOFMEMORY;
|
| - } else {
|
| - res = ::SHQueryValueEx(h_key_, value_name, NULL, &type,
|
| - reinterpret_cast<byte*>(buffer), &byte_count);
|
| - hr = HRESULT_FROM_WIN32(res);
|
| - }
|
| - value->ReleaseBuffer();
|
| - } else {
|
| - value->Empty();
|
| - }
|
| -
|
| - ASSERT1((hr != S_OK) || (type == REG_SZ) ||
|
| - (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ));
|
| - }
|
| -
|
| - return hr;
|
| -}
|
| -
|
| -// convert REG_MULTI_SZ bytes to string array
|
| -HRESULT RegKey::MultiSZBytesToStringArray(const byte * buffer,
|
| - DWORD byte_count,
|
| - std::vector<CString> * value) {
|
| - ASSERT1(buffer);
|
| - ASSERT1(value);
|
| -
|
| - const TCHAR* data = reinterpret_cast<const TCHAR*>(buffer);
|
| - DWORD data_len = byte_count / sizeof(TCHAR);
|
| - value->clear();
|
| - if (data_len > 1) {
|
| - // must be terminated by two null characters
|
| - if (data[data_len - 1] != 0 || data[data_len - 2] != 0) {
|
| - return E_INVALIDARG;
|
| - }
|
| -
|
| - // put null-terminated strings into arrays
|
| - while (*data) {
|
| - CString str(data);
|
| - value->push_back(str);
|
| - data += str.GetLength() + 1;
|
| - }
|
| - }
|
| - return S_OK;
|
| -}
|
| -
|
| -// get a vector<CString> value from REG_MULTI_SZ type
|
| -HRESULT RegKey::GetValue(const TCHAR * value_name,
|
| - std::vector<CString> * value) const {
|
| - ASSERT1(value);
|
| - // value_name may be NULL
|
| -
|
| - DWORD byte_count = 0;
|
| - DWORD type = 0;
|
| - byte* buffer = 0;
|
| -
|
| - // first get the size of the buffer
|
| - HRESULT hr = GetValueHelper(value_name, &type, &buffer, &byte_count);
|
| - ASSERT1((hr != S_OK) || (type == REG_MULTI_SZ));
|
| -
|
| - if (SUCCEEDED(hr)) {
|
| - hr = MultiSZBytesToStringArray(buffer, byte_count, value);
|
| - }
|
| -
|
| - return hr;
|
| -}
|
| -
|
| -// Binary data Get
|
| -HRESULT RegKey::GetValue(const TCHAR * value_name,
|
| - byte * * value,
|
| - DWORD * byte_count) const {
|
| - ASSERT1(byte_count);
|
| - ASSERT1(value);
|
| - // value_name may be NULL
|
| -
|
| - DWORD type = 0;
|
| - HRESULT hr = GetValueHelper(value_name, &type, value, byte_count);
|
| - ASSERT1((hr != S_OK) || (type == REG_MULTI_SZ) || (type == REG_BINARY));
|
| - return hr;
|
| -}
|
| -
|
| -// Raw data get
|
| -HRESULT RegKey::GetValue(const TCHAR * value_name,
|
| - byte * * value,
|
| - DWORD * byte_count,
|
| - DWORD *type) const {
|
| - ASSERT1(type);
|
| - ASSERT1(byte_count);
|
| - ASSERT1(value);
|
| -
|
| - return GetValueHelper(value_name, type, value, byte_count);
|
| -}
|
| -
|
| -// Int32 set
|
| -// value_name may be NULL
|
| -HRESULT RegKey::SetValue(const TCHAR * value_name, DWORD value) const {
|
| - ASSERT1(h_key_);
|
| - LONG res = RegSetValueEx(h_key_,
|
| - value_name,
|
| - NULL,
|
| - REG_DWORD,
|
| - reinterpret_cast<byte *>(&value),
|
| - sizeof(DWORD));
|
| - return HRESULT_FROM_WIN32(res);
|
| -}
|
| -
|
| -// Int64 set
|
| -// value_name may be NULL
|
| -HRESULT RegKey::SetValue(const TCHAR * value_name, DWORD64 value) const {
|
| - ASSERT1(h_key_);
|
| - LONG res = RegSetValueEx(h_key_,
|
| - value_name,
|
| - NULL,
|
| - REG_QWORD,
|
| - reinterpret_cast<byte *>(&value),
|
| - sizeof(DWORD64));
|
| - return HRESULT_FROM_WIN32(res);
|
| -}
|
| -
|
| -// String set
|
| -HRESULT RegKey::SetValue(const TCHAR * value_name, const TCHAR * value) const {
|
| - return SetStringValue(value_name, value, REG_SZ);
|
| -}
|
| -
|
| -// String set helper
|
| -// value_name may be NULL.
|
| -HRESULT RegKey::SetStringValue(const TCHAR * value_name,
|
| - const TCHAR * value,
|
| - DWORD type) const {
|
| - ASSERT1(value);
|
| - ASSERT1(h_key_);
|
| - ASSERT1(type == REG_SZ || type == REG_EXPAND_SZ);
|
| - LONG res = RegSetValueEx(h_key_,
|
| - value_name,
|
| - NULL,
|
| - type,
|
| - reinterpret_cast<const byte *>(value),
|
| - (lstrlen(value) + 1) * sizeof(TCHAR));
|
| - return HRESULT_FROM_WIN32(res);
|
| -}
|
| -
|
| -// Binary data set
|
| -// value may be NULL.
|
| -// value_name may be NULL.
|
| -HRESULT RegKey::SetValue(const TCHAR * value_name,
|
| - const byte * value,
|
| - DWORD byte_count) const {
|
| - ASSERT1(h_key_);
|
| -
|
| - // special case - if 'value' is NULL make sure byte_count is zero
|
| - if (value == NULL) {
|
| - byte_count = 0;
|
| - }
|
| -
|
| - LONG res = RegSetValueEx(h_key_,
|
| - value_name,
|
| - NULL,
|
| - REG_BINARY,
|
| - value,
|
| - byte_count);
|
| - return HRESULT_FROM_WIN32(res);
|
| -}
|
| -
|
| -// Raw data set
|
| -// value_name may be NULL.
|
| -HRESULT RegKey::SetValue(const TCHAR * value_name,
|
| - const byte * value,
|
| - DWORD byte_count,
|
| - DWORD type) const {
|
| - ASSERT1(value);
|
| - ASSERT1(h_key_);
|
| - LONG res = RegSetValueEx(h_key_, value_name, NULL, type, value, byte_count);
|
| - return HRESULT_FROM_WIN32(res);
|
| -}
|
| -
|
| -HRESULT RegKey::RenameValue(const TCHAR* old_value_name,
|
| - const TCHAR* new_value_name) const {
|
| - ASSERT1(h_key_);
|
| - ASSERT1(new_value_name);
|
| - ASSERT1(old_value_name);
|
| -
|
| - scoped_ptr<byte> value;
|
| - DWORD byte_count = 0;
|
| - DWORD type = 0;
|
| -
|
| - HRESULT hr = GetValue(old_value_name, address(value), &byte_count, &type);
|
| - if (FAILED(hr)) {
|
| - return hr;
|
| - }
|
| -
|
| - hr = SetValue(new_value_name, value.get(), byte_count, type);
|
| - if (FAILED(hr)) {
|
| - return hr;
|
| - }
|
| -
|
| - VERIFY1(SUCCEEDED(DeleteValue(old_value_name)));
|
| - return S_OK;
|
| -}
|
| -
|
| -bool RegKey::HasKey(const TCHAR * full_key_name) {
|
| - return HasKeyHelper(full_key_name, KEY_READ);
|
| -}
|
| -
|
| -bool RegKey::HasNativeKey(const TCHAR * full_key_name) {
|
| - return HasKeyHelper(full_key_name, KEY_READ | KEY_WOW64_64KEY);
|
| -}
|
| -
|
| -bool RegKey::HasKeyHelper(const TCHAR * full_key_name, DWORD sam_flags) {
|
| - ASSERT1(full_key_name);
|
| - ASSERT1(sam_flags & KEY_READ);
|
| -
|
| - // get the root HKEY
|
| - CString key_name(full_key_name);
|
| - HKEY h_key = GetRootKeyInfo(&key_name);
|
| -
|
| - if (h_key != NULL) {
|
| - RegKey key;
|
| - HRESULT hr = key.Open(h_key, key_name.GetString(), sam_flags);
|
| - key.Close();
|
| - return S_OK == hr;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -HRESULT RegKey::CopyValue(const TCHAR * full_from_key_name,
|
| - const TCHAR * from_value_name,
|
| - const TCHAR * full_to_key_name,
|
| - const TCHAR * to_value_name) {
|
| - ASSERT1(full_from_key_name);
|
| - ASSERT1(full_to_key_name);
|
| -
|
| - RegKey from_reg_key;
|
| - HRESULT hr = from_reg_key.Open(full_from_key_name, KEY_READ);
|
| - if (FAILED(hr)) {
|
| - return hr;
|
| - }
|
| -
|
| - scoped_ptr<byte> val;
|
| - DWORD byte_count = 0;
|
| - DWORD type = 0;
|
| - hr = from_reg_key.GetValue(from_value_name, address(val), &byte_count, &type);
|
| - if (FAILED(hr)) {
|
| - return hr;
|
| - }
|
| -
|
| - RegKey to_reg_key;
|
| - hr = to_reg_key.Open(full_to_key_name, KEY_WRITE);
|
| - if (FAILED(hr)) {
|
| - return hr;
|
| - }
|
| -
|
| - return to_reg_key.SetValue(to_value_name, val.get(), byte_count, type);
|
| -}
|
| -
|
| -// static version of HasValue
|
| -bool RegKey::HasValue(const TCHAR * full_key_name, const TCHAR * value_name) {
|
| - ASSERT1(full_key_name);
|
| -
|
| - bool has_value = false;
|
| - // get the root HKEY
|
| - CString key_name(full_key_name);
|
| - HKEY h_key = GetRootKeyInfo(&key_name);
|
| -
|
| - if (h_key != NULL) {
|
| - RegKey key;
|
| - if (key.Open(h_key, key_name.GetString(), KEY_READ) == S_OK) {
|
| - has_value = key.HasValue(value_name);
|
| - key.Close();
|
| - }
|
| - }
|
| - return has_value;
|
| -}
|
| -
|
| -HRESULT RegKey::GetValueType(const TCHAR* full_key_name,
|
| - const TCHAR* value_name,
|
| - DWORD* value_type) {
|
| - ASSERT1(full_key_name);
|
| - // value_name may be NULL
|
| - ASSERT1(value_type);
|
| -
|
| - *value_type = REG_NONE;
|
| -
|
| - CString key_name(full_key_name);
|
| - HKEY root_key = GetRootKeyInfo(&key_name);
|
| -
|
| - RegKey key;
|
| - HRESULT hr = key.Open(root_key, key_name, KEY_READ);
|
| - if (FAILED(hr)) {
|
| - return hr;
|
| - }
|
| - return key.GetValueType(value_name, value_type);
|
| -}
|
| -
|
| -HRESULT RegKey::DeleteKey(const TCHAR* full_key_name) {
|
| - ASSERT1(full_key_name);
|
| -
|
| - return DeleteKey(full_key_name, true);
|
| -}
|
| -
|
| -HRESULT RegKey::DeleteKey(const TCHAR* full_key_name, bool recursively) {
|
| - ASSERT1(full_key_name);
|
| -
|
| - // need to open the parent key first
|
| - // get the root HKEY
|
| - CString key_name(full_key_name);
|
| - HKEY h_key = GetRootKeyInfo(&key_name);
|
| -
|
| - // get the parent key
|
| - CString parent_key(GetParentKeyInfo(&key_name));
|
| -
|
| - RegKey key;
|
| - HRESULT hr = key.Open(h_key, parent_key);
|
| -
|
| - if (hr == S_OK) {
|
| - hr = recursively ? key.RecurseDeleteSubKey(key_name) :
|
| - key.DeleteSubKey(key_name);
|
| - } else if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) ||
|
| - hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)) {
|
| - hr = S_FALSE;
|
| - }
|
| -
|
| - key.Close();
|
| - return hr;
|
| -}
|
| -
|
| -HRESULT RegKey::DeleteValue(const TCHAR * full_key_name,
|
| - const TCHAR * value_name) {
|
| - ASSERT1(value_name);
|
| - ASSERT1(full_key_name);
|
| -
|
| - HRESULT hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
|
| - // get the root HKEY
|
| - CString key_name(full_key_name);
|
| - HKEY h_key = GetRootKeyInfo(&key_name);
|
| -
|
| - if (h_key != NULL) {
|
| - RegKey key;
|
| - hr = key.Open(h_key, key_name.GetString());
|
| - if (hr == S_OK) {
|
| - hr = key.DeleteValue(value_name);
|
| - key.Close();
|
| - }
|
| - }
|
| - return hr;
|
| -}
|
| -
|
| -HRESULT RegKey::RecurseDeleteSubKey(const TCHAR * key_name) {
|
| - ASSERT1(key_name);
|
| - ASSERT1(h_key_);
|
| -
|
| - RegKey key;
|
| - HRESULT hr = key.Open(h_key_, key_name);
|
| - if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) ||
|
| - hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)) {
|
| - hr = S_FALSE;
|
| - }
|
| - if (hr != S_OK) {
|
| - return hr;
|
| - }
|
| -
|
| - // enumerate all subkeys of this key
|
| - // and recursivelly delete them
|
| - FILETIME time;
|
| - TCHAR key_name_buf[kMaxKeyNameChars];
|
| - DWORD key_name_buf_size = kMaxKeyNameChars;
|
| - while (RegEnumKeyEx(key.h_key_,
|
| - 0,
|
| - key_name_buf,
|
| - &key_name_buf_size,
|
| - NULL,
|
| - NULL,
|
| - NULL,
|
| - &time) == ERROR_SUCCESS) {
|
| - hr = key.RecurseDeleteSubKey(key_name_buf);
|
| - // return if error deleting key
|
| - if (hr != S_OK)
|
| - return hr;
|
| - // restore the buffer size
|
| - key_name_buf_size = kMaxKeyNameChars;
|
| - }
|
| - // close the top key
|
| - key.Close();
|
| -
|
| - // the key has no more children keys
|
| - // delete the key and all of its values
|
| - return DeleteSubKey(key_name);
|
| -}
|
| -
|
| -HKEY RegKey::GetRootKeyInfo(CString * full_key_name) {
|
| - ASSERT1(full_key_name);
|
| -
|
| - HKEY h_key = NULL;
|
| - // get the root HKEY
|
| - int index = String_FindChar(*(full_key_name), '\\');
|
| - CString root_key;
|
| -
|
| - if (index == -1) {
|
| - root_key = *full_key_name;
|
| - *full_key_name = _T("");
|
| - } else {
|
| - root_key= full_key_name->Left(index);
|
| - *full_key_name =
|
| - full_key_name->Right(full_key_name->GetLength() - index - 1);
|
| - }
|
| -
|
| - if (!root_key.CompareNoCase(_T("HKLM")) ||
|
| - !root_key.CompareNoCase(_T("HKEY_LOCAL_MACHINE")))
|
| - h_key = HKEY_LOCAL_MACHINE;
|
| - else if (!root_key.CompareNoCase(_T("HKCU")) ||
|
| - !root_key.CompareNoCase(_T("HKEY_CURRENT_USER")))
|
| - h_key = HKEY_CURRENT_USER;
|
| - else if (!root_key.CompareNoCase(_T("HKU")) ||
|
| - !root_key.CompareNoCase(_T("HKEY_USERS")))
|
| - h_key = HKEY_USERS;
|
| - else if (!root_key.CompareNoCase(_T("HKCR")) ||
|
| - !root_key.CompareNoCase(_T("HKEY_CLASSES_ROOT")))
|
| - h_key = HKEY_CLASSES_ROOT;
|
| -
|
| - return h_key;
|
| -}
|
| -
|
| -
|
| -// Returns true if this key name is 'safe' for deletion (doesn't specify a
|
| -// key root)
|
| -bool RegKey::SafeKeyNameForDeletion(const wchar_t *key_name) {
|
| - ASSERT1(key_name);
|
| - CString key(key_name);
|
| -
|
| - HKEY root_key = GetRootKeyInfo(&key);
|
| -
|
| - if ( !root_key ) {
|
| - key = key_name;
|
| - }
|
| - if ( key.IsEmpty() ) {
|
| - return false;
|
| - }
|
| - bool found_subkey = false, backslash_found = false;
|
| - for (int i = 0 ; i < key.GetLength() ; ++i) {
|
| - if ( key[i] == L'\\' ) {
|
| - backslash_found = true;
|
| - } else if ( backslash_found ) {
|
| - found_subkey = true;
|
| - break;
|
| - }
|
| - }
|
| - return ( root_key == HKEY_USERS ) ? found_subkey : true;
|
| -}
|
| -
|
| -CString RegKey::GetParentKeyInfo(CString * key_name) {
|
| - ASSERT1(key_name);
|
| -
|
| - // get the parent key
|
| - int index = key_name->ReverseFind('\\');
|
| - CString parent_key;
|
| - if (index == -1) {
|
| - parent_key = _T("");
|
| - } else {
|
| - parent_key = key_name->Left(index);
|
| - *key_name = key_name->Right(key_name->GetLength() - index - 1);
|
| - }
|
| -
|
| - return parent_key;
|
| -}
|
| -
|
| -// get the number of values for this key
|
| -uint32 RegKey::GetValueCount() {
|
| - ASSERT1(h_key_);
|
| - // number of values for key
|
| - DWORD num_values = 0;
|
| -
|
| - LONG res = ::RegQueryInfoKey(h_key_, // key handle
|
| - NULL, // buffer for class name
|
| - NULL, // size of class string
|
| - NULL, // reserved
|
| - NULL, // number of subkeys
|
| - NULL, // longest subkey size
|
| - NULL, // longest class string
|
| - &num_values, // number of values for this key
|
| - NULL, // longest value name
|
| - NULL, // longest value data
|
| - NULL, // security descriptor
|
| - NULL); // last write time
|
| -
|
| - ASSERT1(res == ERROR_SUCCESS);
|
| - return num_values;
|
| -}
|
| -
|
| -// Enumerators for the value_names for this key
|
| -
|
| -// Called to get the value name for the given value name index
|
| -// Use GetValueCount() to get the total value_name count for this key
|
| -// Returns failure if no key at the specified index
|
| -// type may be NULL.
|
| -HRESULT RegKey::GetValueNameAt(int index, CString *value_name, DWORD *type) {
|
| - ASSERT1(value_name);
|
| - ASSERT1(h_key_);
|
| -
|
| - LONG res = ERROR_SUCCESS;
|
| - TCHAR value_name_buf[kMaxValueNameChars];
|
| - DWORD value_name_buf_size = kMaxValueNameChars;
|
| - res = ::RegEnumValue(h_key_,
|
| - index,
|
| - value_name_buf,
|
| - &value_name_buf_size,
|
| - NULL,
|
| - type,
|
| - NULL,
|
| - NULL);
|
| -
|
| - if (res == ERROR_SUCCESS) {
|
| - value_name->SetString(value_name_buf);
|
| - }
|
| -
|
| - return HRESULT_FROM_WIN32(res);
|
| -}
|
| -
|
| -uint32 RegKey::GetSubkeyCount() {
|
| - ASSERT1(h_key_);
|
| -
|
| - DWORD num_subkeys = 0; // number of values for key
|
| -
|
| - LONG res = ::RegQueryInfoKey(h_key_, // key handle
|
| - NULL, // buffer for class name
|
| - NULL, // size of class string
|
| - NULL, // reserved
|
| - &num_subkeys, // number of subkeys
|
| - NULL, // longest subkey size
|
| - NULL, // longest class string
|
| - NULL, // number of values for this key
|
| - NULL, // longest value name
|
| - NULL, // longest value data
|
| - NULL, // security descriptor
|
| - NULL); // last write time
|
| -
|
| - ASSERT1(res == ERROR_SUCCESS);
|
| - return num_subkeys;
|
| -}
|
| -
|
| -HRESULT RegKey::GetSubkeyNameAt(int index, CString * key_name) {
|
| - ASSERT1(key_name);
|
| - ASSERT1(h_key_);
|
| -
|
| - LONG res = ERROR_SUCCESS;
|
| - TCHAR key_name_buf[kMaxKeyNameChars];
|
| - DWORD key_name_buf_size = kMaxKeyNameChars;
|
| -
|
| - res = ::RegEnumKeyEx(h_key_,
|
| - index,
|
| - key_name_buf,
|
| - &key_name_buf_size,
|
| - NULL,
|
| - NULL,
|
| - NULL,
|
| - NULL);
|
| -
|
| - if (res == ERROR_SUCCESS) {
|
| - key_name->SetString(key_name_buf);
|
| - }
|
| -
|
| - return HRESULT_FROM_WIN32(res);
|
| -}
|
| -
|
| -// Is the key empty: having no sub-keys and values
|
| -bool RegKey::IsKeyEmpty(const TCHAR* full_key_name) {
|
| - ASSERT1(full_key_name);
|
| -
|
| - bool is_empty = true;
|
| -
|
| - // Get the root HKEY
|
| - CString key_name(full_key_name);
|
| - HKEY h_key = GetRootKeyInfo(&key_name);
|
| -
|
| - // Open the key to check
|
| - if (h_key != NULL) {
|
| - RegKey key;
|
| - HRESULT hr = key.Open(h_key, key_name.GetString(), KEY_READ);
|
| - if (SUCCEEDED(hr)) {
|
| - is_empty = key.GetSubkeyCount() == 0 && key.GetValueCount() == 0;
|
| - key.Close();
|
| - }
|
| - }
|
| -
|
| - return is_empty;
|
| -}
|
| -
|
| -// close this reg key and the event
|
| -HRESULT RegKeyWithChangeEvent::Close() {
|
| - reset(change_event_);
|
| - return RegKey::Close();
|
| -}
|
| -
|
| -// Called to create/reset the event that gets signaled
|
| -// any time the registry key changes
|
| -// Note:
|
| -// * reg key should have been opened using KEY_NOTIFY for the sam_desired
|
| -//
|
| -// See the documentation for RegNotifyChangeKeyValue
|
| -// for values for notify_filter.
|
| -HRESULT RegKeyWithChangeEvent::SetupEvent(bool watch_subtree,
|
| - DWORD notify_filter) {
|
| - // If the event exists, then it should be in the signaled state
|
| - // indicating a registry change took place. If not, then
|
| - // the caller is setting up the event a second time and this
|
| - // will create a memory leak.
|
| - ASSERT(!valid(change_event_) || HasChangeOccurred(),
|
| - (_T("Event is getting set-up for a second ")
|
| - _T("time without being signaled.")));
|
| -
|
| - if (!valid(change_event_)) {
|
| - reset(change_event_, ::CreateEvent(NULL, TRUE, FALSE, NULL));
|
| - if (!valid(change_event_)) {
|
| - ASSERT(false, (_T("create event failed")));
|
| - return HRESULT_FROM_WIN32(::GetLastError());
|
| - }
|
| - } else {
|
| - if (!::ResetEvent(get(change_event_))) {
|
| - ASSERT(false, (_T("reset event failed")));
|
| - return HRESULT_FROM_WIN32(::GetLastError());
|
| - }
|
| - }
|
| -
|
| - LONG res = ::RegNotifyChangeKeyValue(Key(), watch_subtree, notify_filter,
|
| - get(change_event_), TRUE);
|
| -
|
| - if (res != ERROR_SUCCESS) {
|
| - // You may get this failure if you didn't pass in KEY_NOTIFY
|
| - // as part of the sam_desired flags during Open or Create
|
| - ASSERT(false, (_T("setting up change notification for a reg key failed")));
|
| -
|
| - // Leave the event around so that it never changes once it has been set-up
|
| - // but in this case it will not get signaled again.
|
| - }
|
| -
|
| - return HRESULT_FROM_WIN32(res);
|
| -}
|
| -
|
| -// Indicates if any changes (that are being monitored have occured)
|
| -bool RegKeyWithChangeEvent::HasChangeOccurred() const {
|
| - return IsHandleSignaled(get(change_event_));
|
| -}
|
| -
|
| -
|
| -RegKeyWatcher::RegKeyWatcher(const TCHAR* reg_key, bool watch_subtree,
|
| - DWORD notify_filter, bool allow_creation)
|
| - : reg_key_string_(reg_key),
|
| - watch_subtree_(watch_subtree),
|
| - notify_filter_(notify_filter),
|
| - allow_creation_(allow_creation) {
|
| - UTIL_LOG(L3, (_T("[RegKeyWatcher::RegKeyWatcher][%s]"), reg_key));
|
| -}
|
| -
|
| -HRESULT RegKeyWatcher::EnsureEventSetup() {
|
| - UTIL_LOG(L3, (_T("[RegKeyWatcher::EnsureEventSetup]")));
|
| - if (!reg_key_with_change_event_.get()) {
|
| - scoped_ptr<RegKeyWithChangeEvent> local_reg_key(new RegKeyWithChangeEvent);
|
| - if (!local_reg_key.get()) {
|
| - ASSERT(false, (_T("unable to allocate local_reg_key")));
|
| - return E_FAIL;
|
| - }
|
| -
|
| - if (allow_creation_ && !RegKey::HasKey(reg_key_string_)) {
|
| - RegKey key;
|
| - VERIFY1(SUCCEEDED(key.Create(reg_key_string_)));
|
| - }
|
| -
|
| - HRESULT hr = local_reg_key->Open(reg_key_string_, KEY_NOTIFY);
|
| - if (FAILED(hr)) {
|
| - ASSERT(false, (_T("couldn't open %s reg key for notifications. ")
|
| - _T("Make sure you have pre-created the key!"),
|
| - reg_key_string_));
|
| - return hr;
|
| - }
|
| - reg_key_with_change_event_.reset(local_reg_key.release());
|
| - reg_key_string_.Empty();
|
| - }
|
| -
|
| - // if the event is set-up and no changes have occurred,
|
| - // then there is no need to re-setup the event.
|
| - if (reg_key_with_change_event_->change_event() && !HasChangeOccurred()) {
|
| - return S_OK;
|
| - }
|
| -
|
| - return reg_key_with_change_event_->SetupEvent(watch_subtree_,
|
| - notify_filter_);
|
| -}
|
| -
|
| -// Get the event that is signaled on registry changes.
|
| -HANDLE RegKeyWatcher::change_event() const {
|
| - if (!reg_key_with_change_event_.get()) {
|
| - ASSERT(false, (_T("call RegKeyWatcher::EnsureEventSetup first")));
|
| - return NULL;
|
| - }
|
| - return reg_key_with_change_event_->change_event();
|
| -}
|
| -
|
| -} // namespace omaha
|
| -
|
|
|