普通文本  |  154行  |  4.84 KB

// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/policy/configuration_policy_provider_delegate_win.h"

#include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h"
#include "base/win/registry.h"
#include "policy/policy_constants.h"

using base::win::RegKey;

namespace {

bool ReadRegistryStringValue(RegKey* key, const string16& name,
                             string16* result) {
  DWORD value_size = 0;
  DWORD key_type = 0;
  scoped_array<uint8> buffer;

  if (key->ReadValue(name.c_str(), 0, &value_size, &key_type) != ERROR_SUCCESS)
    return false;
  if (key_type != REG_SZ)
    return false;

  // According to the Microsoft documentation, the string
  // buffer may not be explicitly 0-terminated. Allocate a
  // slightly larger buffer and pre-fill to zeros to guarantee
  // the 0-termination.
  buffer.reset(new uint8[value_size + 2]);
  memset(buffer.get(), 0, value_size + 2);
  key->ReadValue(name.c_str(), buffer.get(), &value_size, NULL);
  result->assign(reinterpret_cast<const wchar_t*>(buffer.get()));
  return true;
}

}  // namespace

namespace policy {

ConfigurationPolicyProviderDelegateWin::ConfigurationPolicyProviderDelegateWin(
    const ConfigurationPolicyProvider::PolicyDefinitionList*
        policy_definition_list)
    : policy_definition_list_(policy_definition_list) {
}

DictionaryValue* ConfigurationPolicyProviderDelegateWin::Load() {
  DictionaryValue* result = new DictionaryValue();
  const ConfigurationPolicyProvider::PolicyDefinitionList::Entry* current;
  for (current = policy_definition_list_->begin;
       current != policy_definition_list_->end;
       ++current) {
    const string16 name(ASCIIToUTF16(current->name));
    switch (current->value_type) {
      case Value::TYPE_STRING: {
        string16 string_value;
        if (GetRegistryPolicyString(name, &string_value)) {
          result->SetString(current->name, string_value);
        }
        break;
      }
      case Value::TYPE_LIST: {
        scoped_ptr<ListValue> list_value(new ListValue);
        if (GetRegistryPolicyStringList(name, list_value.get()))
          result->Set(current->name, list_value.release());
        break;
      }
      case Value::TYPE_BOOLEAN: {
        bool bool_value;
        if (GetRegistryPolicyBoolean(name, &bool_value)) {
          result->SetBoolean(current->name, bool_value);
        }
        break;
      }
      case Value::TYPE_INTEGER: {
        uint32 int_value;
        if (GetRegistryPolicyInteger(name, &int_value)) {
          result->SetInteger(current->name, int_value);
        }
        break;
      }
      default:
        NOTREACHED();
    }
  }
  return result;
}

bool ConfigurationPolicyProviderDelegateWin::GetRegistryPolicyString(
    const string16& name, string16* result) const {
  RegKey policy_key(HKEY_LOCAL_MACHINE, kRegistrySubKey, KEY_READ);
  // First try the global policy.
  if (ReadRegistryStringValue(&policy_key, name, result))
    return true;

  // Fall back on user-specific policy.
  if (policy_key.Open(HKEY_CURRENT_USER, kRegistrySubKey,
                      KEY_READ) != ERROR_SUCCESS)
    return false;
  return ReadRegistryStringValue(&policy_key, name, result);
}

bool ConfigurationPolicyProviderDelegateWin::GetRegistryPolicyStringList(
    const string16& key, ListValue* result) const {
  string16 path = string16(kRegistrySubKey);
  path += ASCIIToUTF16("\\") + key;
  RegKey policy_key;
  if (policy_key.Open(HKEY_LOCAL_MACHINE, path.c_str(), KEY_READ) !=
      ERROR_SUCCESS) {
    // Fall back on user-specific policy.
    if (policy_key.Open(HKEY_CURRENT_USER, path.c_str(), KEY_READ) !=
        ERROR_SUCCESS)
      return false;
  }
  string16 policy_string;
  int index = 0;
  while (ReadRegistryStringValue(&policy_key, base::IntToString16(++index),
                                 &policy_string)) {
    result->Append(Value::CreateStringValue(policy_string));
  }
  return true;
}

bool ConfigurationPolicyProviderDelegateWin::GetRegistryPolicyBoolean(
    const string16& value_name, bool* result) const {
  uint32 local_result = 0;
  bool ret = GetRegistryPolicyInteger(value_name, &local_result);
  if (ret)
    *result = local_result != 0;
  return ret;
}

bool ConfigurationPolicyProviderDelegateWin::GetRegistryPolicyInteger(
    const string16& value_name, uint32* result) const {
  DWORD value = 0;
  RegKey policy_key(HKEY_LOCAL_MACHINE, kRegistrySubKey, KEY_READ);
  if (policy_key.ReadValueDW(value_name.c_str(), &value) == ERROR_SUCCESS) {
    *result = value;
    return true;
  }

  if (policy_key.Open(HKEY_CURRENT_USER, kRegistrySubKey, KEY_READ) ==
      ERROR_SUCCESS) {
    if (policy_key.ReadValueDW(value_name.c_str(), &value) == ERROR_SUCCESS) {
      *result = value;
      return true;
    }
  }
  return false;
}

}  // namespace policy