/*
 *  Copyright 2003 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

// Registry configuration wrapers class implementation
//
// Change made by S. Ganesh - ganesh@google.com:
//   Use SHQueryValueEx instead of RegQueryValueEx throughout.
//   A call to the SHLWAPI function is essentially a call to the standard
//   function but with post-processing:
//   * to fix REG_SZ or REG_EXPAND_SZ data that is not properly null-terminated;
//   * to expand REG_EXPAND_SZ data.

#include "webrtc/base/win32regkey.h"

#include <shlwapi.h>

#include "webrtc/base/common.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/scoped_ptr.h"

namespace rtc {

RegKey::RegKey() {
  h_key_ = NULL;
}

RegKey::~RegKey() {
  Close();
}

HRESULT RegKey::Create(HKEY parent_key, const wchar_t* key_name) {
  return Create(parent_key,
                key_name,
                REG_NONE,
                REG_OPTION_NON_VOLATILE,
                KEY_ALL_ACCESS,
                NULL,
                NULL);
}

HRESULT RegKey::Open(HKEY parent_key, const wchar_t* key_name) {
  return Open(parent_key, key_name, KEY_ALL_ACCESS);
}

bool RegKey::HasValue(const TCHAR* value_name) const {
  return (ERROR_SUCCESS == ::RegQueryValueEx(h_key_, value_name, NULL,
                                             NULL, NULL, NULL));
}

HRESULT RegKey::SetValue(const wchar_t* full_key_name,
                         const wchar_t* value_name,
                         DWORD value) {
  ASSERT(full_key_name != NULL);

  return SetValueStaticHelper(full_key_name, value_name, REG_DWORD, &value);
}

HRESULT RegKey::SetValue(const wchar_t* full_key_name,
                         const wchar_t* value_name,
                         DWORD64 value) {
  ASSERT(full_key_name != NULL);

  return SetValueStaticHelper(full_key_name, value_name, REG_QWORD, &value);
}

HRESULT RegKey::SetValue(const wchar_t* full_key_name,
                         const wchar_t* value_name,
                         float value) {
  ASSERT(full_key_name != NULL);

  return SetValueStaticHelper(full_key_name, value_name,
                              REG_BINARY, &value, sizeof(value));
}

HRESULT RegKey::SetValue(const wchar_t* full_key_name,
                         const wchar_t* value_name,
                         double value) {
  ASSERT(full_key_name != NULL);

  return SetValueStaticHelper(full_key_name, value_name,
                              REG_BINARY, &value, sizeof(value));
}

HRESULT RegKey::SetValue(const wchar_t* full_key_name,
                         const wchar_t* value_name,
                         const TCHAR* value) {
  ASSERT(full_key_name != NULL);
  ASSERT(value != NULL);

  return SetValueStaticHelper(full_key_name, value_name,
                              REG_SZ, const_cast<wchar_t*>(value));
}

HRESULT RegKey::SetValue(const wchar_t* full_key_name,
                         const wchar_t* value_name,
                         const uint8_t* value,
                         DWORD byte_count) {
  ASSERT(full_key_name != NULL);

  return SetValueStaticHelper(full_key_name, value_name, REG_BINARY,
                              const_cast<uint8_t*>(value), byte_count);
}

HRESULT RegKey::SetValueMultiSZ(const wchar_t* full_key_name,
                                const wchar_t* value_name,
                                const uint8_t* value,
                                DWORD byte_count) {
  ASSERT(full_key_name != NULL);

  return SetValueStaticHelper(full_key_name, value_name, REG_MULTI_SZ,
                              const_cast<uint8_t*>(value), byte_count);
}

HRESULT RegKey::GetValue(const wchar_t* full_key_name,
                         const wchar_t* value_name,
                         DWORD* value) {
  ASSERT(full_key_name != NULL);
  ASSERT(value != NULL);

  return GetValueStaticHelper(full_key_name, value_name, REG_DWORD, value);
}

HRESULT RegKey::GetValue(const wchar_t* full_key_name,
                         const wchar_t* value_name,
                         DWORD64* value) {
  ASSERT(full_key_name != NULL);
  ASSERT(value != NULL);

  return GetValueStaticHelper(full_key_name, value_name, REG_QWORD, value);
}

HRESULT RegKey::GetValue(const wchar_t* full_key_name,
                         const wchar_t* value_name,
                         float* value) {
  ASSERT(value != NULL);
  ASSERT(full_key_name != NULL);

  DWORD byte_count = 0;
  scoped_ptr<byte[]> buffer;
  HRESULT hr = GetValueStaticHelper(full_key_name, value_name,
                                    REG_BINARY, buffer.accept(), &byte_count);
  if (SUCCEEDED(hr)) {
    ASSERT(byte_count == sizeof(*value));
    if (byte_count == sizeof(*value)) {
      *value = *reinterpret_cast<float*>(buffer.get());
    }
  }
  return hr;
}

HRESULT RegKey::GetValue(const wchar_t* full_key_name,
                         const wchar_t* value_name,
                         double* value) {
  ASSERT(value != NULL);
  ASSERT(full_key_name != NULL);

  DWORD byte_count = 0;
  scoped_ptr<byte[]> buffer;
  HRESULT hr = GetValueStaticHelper(full_key_name, value_name,
                                    REG_BINARY, buffer.accept(), &byte_count);
  if (SUCCEEDED(hr)) {
    ASSERT(byte_count == sizeof(*value));
    if (byte_count == sizeof(*value)) {
      *value = *reinterpret_cast<double*>(buffer.get());
    }
  }
  return hr;
}

HRESULT RegKey::GetValue(const wchar_t* full_key_name,
                         const wchar_t* value_name,
                         wchar_t** value) {
  ASSERT(full_key_name != NULL);
  ASSERT(value != NULL);

  return GetValueStaticHelper(full_key_name, value_name, REG_SZ, value);
}

HRESULT RegKey::GetValue(const wchar_t* full_key_name,
                         const wchar_t* value_name,
                         std::wstring* value) {
  ASSERT(full_key_name != NULL);
  ASSERT(value != NULL);

  scoped_ptr<wchar_t[]> buffer;
  HRESULT hr = RegKey::GetValue(full_key_name, value_name, buffer.accept());
  if (SUCCEEDED(hr)) {
    value->assign(buffer.get());
  }
  return hr;
}

HRESULT RegKey::GetValue(const wchar_t* full_key_name,
                         const wchar_t* value_name,
                         std::vector<std::wstring>* value) {
  ASSERT(full_key_name != NULL);
  ASSERT(value != NULL);

  return GetValueStaticHelper(full_key_name, value_name, REG_MULTI_SZ, value);
}

HRESULT RegKey::GetValue(const wchar_t* full_key_name,
                         const wchar_t* value_name,
                         uint8_t** value,
                         DWORD* byte_count) {
  ASSERT(full_key_name != NULL);
  ASSERT(value != NULL);
  ASSERT(byte_count != NULL);

  return GetValueStaticHelper(full_key_name, value_name,
                              REG_BINARY, value, byte_count);
}

HRESULT RegKey::DeleteSubKey(const wchar_t* key_name) {
  ASSERT(key_name != NULL);
  ASSERT(h_key_ != NULL);

  LONG res = ::RegDeleteKey(h_key_, key_name);
  HRESULT hr = HRESULT_FROM_WIN32(res);
  if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) ||
      hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)) {
    hr = S_FALSE;
  }
  return hr;
}

HRESULT RegKey::DeleteValue(const wchar_t* value_name) {
  ASSERT(h_key_ != NULL);

  LONG res = ::RegDeleteValue(h_key_, value_name);
  HRESULT hr = HRESULT_FROM_WIN32(res);
  if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) ||
      hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)) {
    hr = S_FALSE;
  }
  return hr;
}

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 parent_key,
                       const wchar_t* key_name,
                       wchar_t* lpszClass,
                       DWORD options,
                       REGSAM sam_desired,
                       LPSECURITY_ATTRIBUTES lpSecAttr,
                       LPDWORD lpdwDisposition) {
  ASSERT(key_name != NULL);
  ASSERT(parent_key != NULL);

  DWORD dw = 0;
  HKEY h_key = NULL;
  LONG res = ::RegCreateKeyEx(parent_key, key_name, 0, lpszClass, options,
                              sam_desired, lpSecAttr, &h_key, &dw);
  HRESULT hr = HRESULT_FROM_WIN32(res);

  if (lpdwDisposition) {
    *lpdwDisposition = dw;
  }

  // we have to close the currently opened key
  // before replacing it with the new one
  if (hr == S_OK) {
    hr = Close();
    ASSERT(hr == S_OK);
    h_key_ = h_key;
  }
  return hr;
}

HRESULT RegKey::Open(HKEY parent_key,
                     const wchar_t* key_name,
                     REGSAM sam_desired) {
  ASSERT(key_name != NULL);
  ASSERT(parent_key != NULL);

  HKEY h_key = NULL;
  LONG res = ::RegOpenKeyEx(parent_key, key_name, 0, sam_desired, &h_key);
  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();
    ASSERT(hr == S_OK);
    h_key_ = h_key;
  }
  return hr;
}

// save the key and all of its subkeys and values to a file
HRESULT RegKey::Save(const wchar_t* full_key_name, const wchar_t* file_name) {
  ASSERT(full_key_name != NULL);
  ASSERT(file_name != NULL);

  std::wstring 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.c_str(), KEY_READ);
  if (FAILED(hr)) {
    return hr;
  }

  AdjustCurrentProcessPrivilege(SE_BACKUP_NAME, true);
  LONG res = ::RegSaveKey(key.h_key_, file_name, NULL);
  AdjustCurrentProcessPrivilege(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 wchar_t* full_key_name,
                        const wchar_t* file_name) {
  ASSERT(full_key_name != NULL);
  ASSERT(file_name != NULL);

  std::wstring 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.c_str(), KEY_WRITE);
  if (FAILED(hr)) {
    return hr;
  }

  AdjustCurrentProcessPrivilege(SE_RESTORE_NAME, true);
  LONG res = ::RegRestoreKey(key.h_key_, file_name, REG_FORCE_RESTORE);
  AdjustCurrentProcessPrivilege(SE_RESTORE_NAME, false);

  return HRESULT_FROM_WIN32(res);
}

// check if the current key has the specified subkey
bool RegKey::HasSubkey(const wchar_t* key_name) const {
  ASSERT(key_name != NULL);

  RegKey key;
  HRESULT hr = key.Open(h_key_, key_name, KEY_READ);
  key.Close();
  return hr == S_OK;
}

// static flush key
HRESULT RegKey::FlushKey(const wchar_t* full_key_name) {
  ASSERT(full_key_name != NULL);

  HRESULT hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
  // get the root HKEY
  std::wstring 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 wchar_t* full_key_name,
                                     const wchar_t* value_name,
                                     DWORD type,
                                     LPVOID value,
                                     DWORD byte_count) {
  ASSERT(full_key_name != NULL);

  HRESULT hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
  // get the root HKEY
  std::wstring key_name(full_key_name);
  HKEY h_key = GetRootKeyInfo(&key_name);

  if (h_key != NULL) {
    RegKey key;
    hr = key.Create(h_key, key_name.c_str());
    if (hr == S_OK) {
      switch (type) {
        case REG_DWORD:
          hr = key.SetValue(value_name, *(static_cast<DWORD*>(value)));
          break;
        case REG_QWORD:
          hr = key.SetValue(value_name, *(static_cast<DWORD64*>(value)));
          break;
        case REG_SZ:
          hr = key.SetValue(value_name, static_cast<const wchar_t*>(value));
          break;
        case REG_BINARY:
          hr = key.SetValue(value_name, static_cast<const uint8_t*>(value),
                            byte_count);
          break;
        case REG_MULTI_SZ:
          hr = key.SetValue(value_name, static_cast<const uint8_t*>(value),
                            byte_count, type);
          break;
        default:
          ASSERT(false);
          hr = HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH);
          break;
      }
      // close the key after writing
      HRESULT temp_hr = key.Close();
      if (hr == S_OK) {
        hr = temp_hr;
      }
    }
  }
  return hr;
}

// static GET helper
HRESULT RegKey::GetValueStaticHelper(const wchar_t* full_key_name,
                                     const wchar_t* value_name,
                                     DWORD type,
                                     LPVOID value,
                                     DWORD* byte_count) {
  ASSERT(full_key_name != NULL);

  HRESULT hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
  // get the root HKEY
  std::wstring key_name(full_key_name);
  HKEY h_key = GetRootKeyInfo(&key_name);

  if (h_key != NULL) {
    RegKey key;
    hr = key.Open(h_key, key_name.c_str(), KEY_READ);
    if (hr == S_OK) {
      switch (type) {
        case REG_DWORD:
          hr = key.GetValue(value_name, reinterpret_cast<DWORD*>(value));
          break;
        case REG_QWORD:
          hr = key.GetValue(value_name, reinterpret_cast<DWORD64*>(value));
          break;
        case REG_SZ:
          hr = key.GetValue(value_name, reinterpret_cast<wchar_t**>(value));
          break;
        case REG_MULTI_SZ:
          hr = key.GetValue(value_name, reinterpret_cast<
                                            std::vector<std::wstring>*>(value));
          break;
        case REG_BINARY:
          hr = key.GetValue(value_name, reinterpret_cast<uint8_t**>(value),
                            byte_count);
          break;
        default:
          ASSERT(false);
          hr = HRESULT_FROM_WIN32(ERROR_DATATYPE_MISMATCH);
          break;
      }
      // close the key after writing
      HRESULT temp_hr = key.Close();
      if (hr == S_OK) {
        hr = temp_hr;
      }
    }
  }
  return hr;
}

// GET helper
HRESULT RegKey::GetValueHelper(const wchar_t* value_name,
                               DWORD* type,
                               uint8_t** value,
                               DWORD* byte_count) const {
  ASSERT(byte_count != NULL);
  ASSERT(value != NULL);
  ASSERT(type != NULL);

  // 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];
      ASSERT(*value != NULL);

      // make the call again to get the data
      res = ::SHQueryValueEx(h_key_, value_name, NULL,
                             type, *value, byte_count);
      hr = HRESULT_FROM_WIN32(res);
      ASSERT(hr == S_OK);
    }
  }
  return hr;
}

// Int32 Get
HRESULT RegKey::GetValue(const wchar_t* value_name, DWORD* value) const {
  ASSERT(value != NULL);

  DWORD type = 0;
  DWORD byte_count = sizeof(DWORD);
  LONG res = ::SHQueryValueEx(h_key_, value_name, NULL, &type,
                              value, &byte_count);
  HRESULT hr = HRESULT_FROM_WIN32(res);
  ASSERT((hr != S_OK) || (type == REG_DWORD));
  ASSERT((hr != S_OK) || (byte_count == sizeof(DWORD)));
  return hr;
}

// Int64 Get
HRESULT RegKey::GetValue(const wchar_t* value_name, DWORD64* value) const {
  ASSERT(value != NULL);

  DWORD type = 0;
  DWORD byte_count = sizeof(DWORD64);
  LONG res = ::SHQueryValueEx(h_key_, value_name, NULL, &type,
                              value, &byte_count);
  HRESULT hr = HRESULT_FROM_WIN32(res);
  ASSERT((hr != S_OK) || (type == REG_QWORD));
  ASSERT((hr != S_OK) || (byte_count == sizeof(DWORD64)));
  return hr;
}

// String Get
HRESULT RegKey::GetValue(const wchar_t* value_name, wchar_t** value) const {
  ASSERT(value != NULL);

  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 wchar_t[(byte_count / sizeof(wchar_t)) + 1];

    if ((*value) != NULL) {
      if (byte_count != 0) {
        // make the call again
        res = ::SHQueryValueEx(h_key_, value_name, NULL, &type,
                               *value, &byte_count);
        hr = HRESULT_FROM_WIN32(res);
      } else {
        (*value)[0] = L'\0';
      }

      ASSERT((hr != S_OK) || (type == REG_SZ) ||
             (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ));
    } else {
      hr = E_OUTOFMEMORY;
    }
  }

  return hr;
}

// get a string value
HRESULT RegKey::GetValue(const wchar_t* value_name, std::wstring* value) const {
  ASSERT(value != NULL);

  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
      value->resize(byte_count / sizeof(wchar_t) + 1);
      res = ::SHQueryValueEx(h_key_, value_name, NULL, &type,
                             &value->at(0), &byte_count);
      hr = HRESULT_FROM_WIN32(res);
      value->resize(wcslen(value->data()));
    } else {
      value->clear();
    }

    ASSERT((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 uint8_t* buffer,
                                          DWORD byte_count,
                                          std::vector<std::wstring>* value) {
  ASSERT(buffer != NULL);
  ASSERT(value != NULL);

  const wchar_t* data = reinterpret_cast<const wchar_t*>(buffer);
  DWORD data_len = byte_count / sizeof(wchar_t);
  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) {
      std::wstring str(data);
      value->push_back(str);
      data += str.length() + 1;
    }
  }
  return S_OK;
}

// get a std::vector<std::wstring> value from REG_MULTI_SZ type
HRESULT RegKey::GetValue(const wchar_t* value_name,
                         std::vector<std::wstring>* value) const {
  ASSERT(value != NULL);

  DWORD byte_count = 0;
  DWORD type = 0;
  uint8_t* buffer = 0;

  // first get the size of the buffer
  HRESULT hr = GetValueHelper(value_name, &type, &buffer, &byte_count);
  ASSERT((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 wchar_t* value_name,
                         uint8_t** value,
                         DWORD* byte_count) const {
  ASSERT(byte_count != NULL);
  ASSERT(value != NULL);

  DWORD type = 0;
  HRESULT hr = GetValueHelper(value_name, &type, value, byte_count);
  ASSERT((hr != S_OK) || (type == REG_MULTI_SZ) || (type == REG_BINARY));
  return hr;
}

// Raw data get
HRESULT RegKey::GetValue(const wchar_t* value_name,
                         uint8_t** value,
                         DWORD* byte_count,
                         DWORD* type) const {
  ASSERT(type != NULL);
  ASSERT(byte_count != NULL);
  ASSERT(value != NULL);

  return GetValueHelper(value_name, type, value, byte_count);
}

// Int32 set
HRESULT RegKey::SetValue(const wchar_t* value_name, DWORD value) const {
  ASSERT(h_key_ != NULL);

  LONG res =
      ::RegSetValueEx(h_key_, value_name, NULL, REG_DWORD,
                      reinterpret_cast<const uint8_t*>(&value), sizeof(DWORD));
  return HRESULT_FROM_WIN32(res);
}

// Int64 set
HRESULT RegKey::SetValue(const wchar_t* value_name, DWORD64 value) const {
  ASSERT(h_key_ != NULL);

  LONG res = ::RegSetValueEx(h_key_, value_name, NULL, REG_QWORD,
                             reinterpret_cast<const uint8_t*>(&value),
                             sizeof(DWORD64));
  return HRESULT_FROM_WIN32(res);
}

// String set
HRESULT RegKey::SetValue(const wchar_t* value_name,
                         const wchar_t* value) const {
  ASSERT(value != NULL);
  ASSERT(h_key_ != NULL);

  LONG res = ::RegSetValueEx(h_key_, value_name, NULL, REG_SZ,
                             reinterpret_cast<const uint8_t*>(value),
                             (lstrlen(value) + 1) * sizeof(wchar_t));
  return HRESULT_FROM_WIN32(res);
}

// Binary data set
HRESULT RegKey::SetValue(const wchar_t* value_name,
                         const uint8_t* value,
                         DWORD byte_count) const {
  ASSERT(h_key_ != NULL);

  // 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
HRESULT RegKey::SetValue(const wchar_t* value_name,
                         const uint8_t* value,
                         DWORD byte_count,
                         DWORD type) const {
  ASSERT(value != NULL);
  ASSERT(h_key_ != NULL);

  LONG res = ::RegSetValueEx(h_key_, value_name, NULL, type, value, byte_count);
  return HRESULT_FROM_WIN32(res);
}

bool RegKey::HasKey(const wchar_t* full_key_name) {
  ASSERT(full_key_name != NULL);

  // get the root HKEY
  std::wstring 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.c_str(), KEY_READ);
    key.Close();
    return S_OK == hr;
  }
  return false;
}

// static version of HasValue
bool RegKey::HasValue(const wchar_t* full_key_name, const wchar_t* value_name) {
  ASSERT(full_key_name != NULL);

  bool has_value = false;
  // get the root HKEY
  std::wstring key_name(full_key_name);
  HKEY h_key = GetRootKeyInfo(&key_name);

  if (h_key != NULL) {
    RegKey key;
    if (key.Open(h_key, key_name.c_str(), KEY_READ) == S_OK) {
      has_value = key.HasValue(value_name);
      key.Close();
    }
  }
  return has_value;
}

HRESULT RegKey::GetValueType(const wchar_t* full_key_name,
                             const wchar_t* value_name,
                             DWORD* value_type) {
  ASSERT(full_key_name != NULL);
  ASSERT(value_type != NULL);

  *value_type = REG_NONE;

  std::wstring key_name(full_key_name);
  HKEY h_key = GetRootKeyInfo(&key_name);

  RegKey key;
  HRESULT hr = key.Open(h_key, key_name.c_str(), KEY_READ);
  if (SUCCEEDED(hr)) {
    LONG res = ::SHQueryValueEx(key.h_key_, value_name, NULL, value_type,
                                NULL, NULL);
    if (res != ERROR_SUCCESS) {
      hr = HRESULT_FROM_WIN32(res);
    }
  }

  return hr;
}

HRESULT RegKey::DeleteKey(const wchar_t* full_key_name) {
  ASSERT(full_key_name != NULL);

  return DeleteKey(full_key_name, true);
}

HRESULT RegKey::DeleteKey(const wchar_t* full_key_name, bool recursively) {
  ASSERT(full_key_name != NULL);

  // need to open the parent key first
  // get the root HKEY
  std::wstring key_name(full_key_name);
  HKEY h_key = GetRootKeyInfo(&key_name);

  // get the parent key
  std::wstring parent_key(GetParentKeyInfo(&key_name));

  RegKey key;
  HRESULT hr = key.Open(h_key, parent_key.c_str());

  if (hr == S_OK) {
    hr = recursively ? key.RecurseDeleteSubKey(key_name.c_str())
                     : key.DeleteSubKey(key_name.c_str());
  } 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 wchar_t* full_key_name,
                            const wchar_t* value_name) {
  ASSERT(full_key_name != NULL);

  HRESULT hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
  // get the root HKEY
  std::wstring key_name(full_key_name);
  HKEY h_key = GetRootKeyInfo(&key_name);

  if (h_key != NULL) {
    RegKey key;
    hr = key.Open(h_key, key_name.c_str());
    if (hr == S_OK) {
      hr = key.DeleteValue(value_name);
      key.Close();
    }
  }
  return hr;
}

HRESULT RegKey::RecurseDeleteSubKey(const wchar_t* key_name) {
  ASSERT(key_name != NULL);

  RegKey key;
  HRESULT hr = key.Open(h_key_, key_name);

  if (hr == S_OK) {
    // enumerate all subkeys of this key and recursivelly delete them
    FILETIME time = {0};
    wchar_t key_name_buf[kMaxKeyNameChars] = {0};
    DWORD key_name_buf_size = kMaxKeyNameChars;
    while (hr == S_OK &&
        ::RegEnumKeyEx(key.h_key_, 0, key_name_buf, &key_name_buf_size,
                       NULL, NULL, NULL,  &time) == ERROR_SUCCESS) {
      hr = key.RecurseDeleteSubKey(key_name_buf);

      // restore the buffer size
      key_name_buf_size = kMaxKeyNameChars;
    }
    // close the top key
    key.Close();
  }

  if (hr == S_OK) {
    // the key has no more children keys
    // delete the key and all of its values
    hr = DeleteSubKey(key_name);
  }

  return hr;
}

HKEY RegKey::GetRootKeyInfo(std::wstring* full_key_name) {
  ASSERT(full_key_name != NULL);

  HKEY h_key = NULL;
  // get the root HKEY
  size_t index = full_key_name->find(L'\\');
  std::wstring root_key;

  if (index == -1) {
    root_key = *full_key_name;
    *full_key_name = L"";
  } else {
    root_key = full_key_name->substr(0, index);
    *full_key_name = full_key_name->substr(index + 1,
                                           full_key_name->length() - index - 1);
  }

  for (std::wstring::iterator iter = root_key.begin();
       iter != root_key.end(); ++iter) {
    *iter = toupper(*iter);
  }

  if (!root_key.compare(L"HKLM") ||
      !root_key.compare(L"HKEY_LOCAL_MACHINE")) {
    h_key = HKEY_LOCAL_MACHINE;
  } else if (!root_key.compare(L"HKCU") ||
             !root_key.compare(L"HKEY_CURRENT_USER")) {
    h_key = HKEY_CURRENT_USER;
  } else if (!root_key.compare(L"HKU") ||
             !root_key.compare(L"HKEY_USERS")) {
    h_key = HKEY_USERS;
  } else if (!root_key.compare(L"HKCR") ||
             !root_key.compare(L"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) {
  ASSERT(key_name != NULL);
  std::wstring key(key_name);

  HKEY root_key = GetRootKeyInfo(&key);

  if (!root_key) {
    key = key_name;
  }
  if (key.empty()) {
    return false;
  }
  bool found_subkey = false, backslash_found = false;
  for (size_t i = 0 ; i < key.length() ; ++i) {
    if (key[i] == L'\\') {
      backslash_found = true;
    } else if (backslash_found) {
      found_subkey = true;
      break;
    }
  }
  return (root_key == HKEY_USERS) ? found_subkey : true;
}

std::wstring RegKey::GetParentKeyInfo(std::wstring* key_name) {
  ASSERT(key_name != NULL);

  // get the parent key
  size_t index = key_name->rfind(L'\\');
  std::wstring parent_key;
  if (index == -1) {
    parent_key = L"";
  } else {
    parent_key = key_name->substr(0, index);
    *key_name = key_name->substr(index + 1, key_name->length() - index - 1);
  }

  return parent_key;
}

// get the number of values for this key
uint32_t RegKey::GetValueCount() {
  DWORD num_values = 0;

  if (ERROR_SUCCESS != ::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
    ASSERT(false);
  }
  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
HRESULT RegKey::GetValueNameAt(int index, std::wstring* value_name,
                               DWORD* type) {
  ASSERT(value_name != NULL);

  LONG res = ERROR_SUCCESS;
  wchar_t value_name_buf[kMaxValueNameChars] = {0};
  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->assign(value_name_buf);
  }

  return HRESULT_FROM_WIN32(res);
}

uint32_t RegKey::GetSubkeyCount() {
  // number of values for key
  DWORD num_subkeys = 0;

  if (ERROR_SUCCESS != ::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
    ASSERT(false);
  }
  return num_subkeys;
}

HRESULT RegKey::GetSubkeyNameAt(int index, std::wstring* key_name) {
  ASSERT(key_name != NULL);

  LONG res = ERROR_SUCCESS;
  wchar_t key_name_buf[kMaxKeyNameChars] = {0};
  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->assign(key_name_buf);
  }

  return HRESULT_FROM_WIN32(res);
}

// Is the key empty: having no sub-keys and values
bool RegKey::IsKeyEmpty(const wchar_t* full_key_name) {
  ASSERT(full_key_name != NULL);

  bool is_empty = true;

  // Get the root HKEY
  std::wstring 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.c_str(), KEY_READ);
    if (SUCCEEDED(hr)) {
      is_empty = key.GetSubkeyCount() == 0 && key.GetValueCount() == 0;
      key.Close();
    }
  }

  return is_empty;
}

bool AdjustCurrentProcessPrivilege(const TCHAR* privilege, bool to_enable) {
  ASSERT(privilege != NULL);

  bool ret = false;
  HANDLE token;
  if (::OpenProcessToken(::GetCurrentProcess(),
                         TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) {
    LUID luid;
    memset(&luid, 0, sizeof(luid));
    if (::LookupPrivilegeValue(NULL, privilege, &luid)) {
      TOKEN_PRIVILEGES privs;
      privs.PrivilegeCount = 1;
      privs.Privileges[0].Luid = luid;
      privs.Privileges[0].Attributes = to_enable ? SE_PRIVILEGE_ENABLED : 0;
      if (::AdjustTokenPrivileges(token, FALSE, &privs, 0, NULL, 0)) {
        ret = true;
      } else {
        LOG_GLE(LS_ERROR) << "AdjustTokenPrivileges failed";
      }
    } else {
      LOG_GLE(LS_ERROR) << "LookupPrivilegeValue failed";
    }
    CloseHandle(token);
  } else {
    LOG_GLE(LS_ERROR) << "OpenProcessToken(GetCurrentProcess) failed";
  }

  return ret;
}

}  // namespace rtc
