Home | History | Annotate | Download | only in policy
      1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/policy/configuration_policy_provider_delegate_win.h"
      6 
      7 #include "base/string_number_conversions.h"
      8 #include "base/utf_string_conversions.h"
      9 #include "base/win/registry.h"
     10 #include "policy/policy_constants.h"
     11 
     12 using base::win::RegKey;
     13 
     14 namespace {
     15 
     16 bool ReadRegistryStringValue(RegKey* key, const string16& name,
     17                              string16* result) {
     18   DWORD value_size = 0;
     19   DWORD key_type = 0;
     20   scoped_array<uint8> buffer;
     21 
     22   if (key->ReadValue(name.c_str(), 0, &value_size, &key_type) != ERROR_SUCCESS)
     23     return false;
     24   if (key_type != REG_SZ)
     25     return false;
     26 
     27   // According to the Microsoft documentation, the string
     28   // buffer may not be explicitly 0-terminated. Allocate a
     29   // slightly larger buffer and pre-fill to zeros to guarantee
     30   // the 0-termination.
     31   buffer.reset(new uint8[value_size + 2]);
     32   memset(buffer.get(), 0, value_size + 2);
     33   key->ReadValue(name.c_str(), buffer.get(), &value_size, NULL);
     34   result->assign(reinterpret_cast<const wchar_t*>(buffer.get()));
     35   return true;
     36 }
     37 
     38 }  // namespace
     39 
     40 namespace policy {
     41 
     42 ConfigurationPolicyProviderDelegateWin::ConfigurationPolicyProviderDelegateWin(
     43     const ConfigurationPolicyProvider::PolicyDefinitionList*
     44         policy_definition_list)
     45     : policy_definition_list_(policy_definition_list) {
     46 }
     47 
     48 DictionaryValue* ConfigurationPolicyProviderDelegateWin::Load() {
     49   DictionaryValue* result = new DictionaryValue();
     50   const ConfigurationPolicyProvider::PolicyDefinitionList::Entry* current;
     51   for (current = policy_definition_list_->begin;
     52        current != policy_definition_list_->end;
     53        ++current) {
     54     const string16 name(ASCIIToUTF16(current->name));
     55     switch (current->value_type) {
     56       case Value::TYPE_STRING: {
     57         string16 string_value;
     58         if (GetRegistryPolicyString(name, &string_value)) {
     59           result->SetString(current->name, string_value);
     60         }
     61         break;
     62       }
     63       case Value::TYPE_LIST: {
     64         scoped_ptr<ListValue> list_value(new ListValue);
     65         if (GetRegistryPolicyStringList(name, list_value.get()))
     66           result->Set(current->name, list_value.release());
     67         break;
     68       }
     69       case Value::TYPE_BOOLEAN: {
     70         bool bool_value;
     71         if (GetRegistryPolicyBoolean(name, &bool_value)) {
     72           result->SetBoolean(current->name, bool_value);
     73         }
     74         break;
     75       }
     76       case Value::TYPE_INTEGER: {
     77         uint32 int_value;
     78         if (GetRegistryPolicyInteger(name, &int_value)) {
     79           result->SetInteger(current->name, int_value);
     80         }
     81         break;
     82       }
     83       default:
     84         NOTREACHED();
     85     }
     86   }
     87   return result;
     88 }
     89 
     90 bool ConfigurationPolicyProviderDelegateWin::GetRegistryPolicyString(
     91     const string16& name, string16* result) const {
     92   RegKey policy_key(HKEY_LOCAL_MACHINE, kRegistrySubKey, KEY_READ);
     93   // First try the global policy.
     94   if (ReadRegistryStringValue(&policy_key, name, result))
     95     return true;
     96 
     97   // Fall back on user-specific policy.
     98   if (policy_key.Open(HKEY_CURRENT_USER, kRegistrySubKey,
     99                       KEY_READ) != ERROR_SUCCESS)
    100     return false;
    101   return ReadRegistryStringValue(&policy_key, name, result);
    102 }
    103 
    104 bool ConfigurationPolicyProviderDelegateWin::GetRegistryPolicyStringList(
    105     const string16& key, ListValue* result) const {
    106   string16 path = string16(kRegistrySubKey);
    107   path += ASCIIToUTF16("\\") + key;
    108   RegKey policy_key;
    109   if (policy_key.Open(HKEY_LOCAL_MACHINE, path.c_str(), KEY_READ) !=
    110       ERROR_SUCCESS) {
    111     // Fall back on user-specific policy.
    112     if (policy_key.Open(HKEY_CURRENT_USER, path.c_str(), KEY_READ) !=
    113         ERROR_SUCCESS)
    114       return false;
    115   }
    116   string16 policy_string;
    117   int index = 0;
    118   while (ReadRegistryStringValue(&policy_key, base::IntToString16(++index),
    119                                  &policy_string)) {
    120     result->Append(Value::CreateStringValue(policy_string));
    121   }
    122   return true;
    123 }
    124 
    125 bool ConfigurationPolicyProviderDelegateWin::GetRegistryPolicyBoolean(
    126     const string16& value_name, bool* result) const {
    127   uint32 local_result = 0;
    128   bool ret = GetRegistryPolicyInteger(value_name, &local_result);
    129   if (ret)
    130     *result = local_result != 0;
    131   return ret;
    132 }
    133 
    134 bool ConfigurationPolicyProviderDelegateWin::GetRegistryPolicyInteger(
    135     const string16& value_name, uint32* result) const {
    136   DWORD value = 0;
    137   RegKey policy_key(HKEY_LOCAL_MACHINE, kRegistrySubKey, KEY_READ);
    138   if (policy_key.ReadValueDW(value_name.c_str(), &value) == ERROR_SUCCESS) {
    139     *result = value;
    140     return true;
    141   }
    142 
    143   if (policy_key.Open(HKEY_CURRENT_USER, kRegistrySubKey, KEY_READ) ==
    144       ERROR_SUCCESS) {
    145     if (policy_key.ReadValueDW(value_name.c_str(), &value) == ERROR_SUCCESS) {
    146       *result = value;
    147       return true;
    148     }
    149   }
    150   return false;
    151 }
    152 
    153 }  // namespace policy
    154