Home | History | Annotate | Download | only in policy
      1 // Copyright (c) 2011 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 <shlobj.h>
      6 #include <wtsapi32.h>
      7 #pragma comment(lib, "wtsapi32.lib")
      8 
      9 #include "chrome/browser/policy/policy_path_parser.h"
     10 
     11 #include "base/memory/scoped_ptr.h"
     12 #include "base/strings/utf_string_conversions.h"
     13 #include "base/win/registry.h"
     14 #include "chrome/common/chrome_switches.h"
     15 #include "policy/policy_constants.h"
     16 
     17 namespace {
     18 
     19 // Checks if the key exists in the given hive and expands any string variables.
     20 bool LoadUserDataDirPolicyFromRegistry(HKEY hive, base::FilePath* dir) {
     21   std::wstring value;
     22   std::wstring key_name(base::ASCIIToWide(policy::key::kUserDataDir));
     23   base::win::RegKey key(hive, policy::kRegistryChromePolicyKey, KEY_READ);
     24   if (key.ReadValue(key_name.c_str(), &value) == ERROR_SUCCESS) {
     25     *dir = base::FilePath(policy::path_parser::ExpandPathVariables(value));
     26     return true;
     27   }
     28   return false;
     29 }
     30 
     31 const WCHAR* kMachineNamePolicyVarName = L"${machine_name}";
     32 const WCHAR* kUserNamePolicyVarName = L"${user_name}";
     33 const WCHAR* kWinDocumentsFolderVarName = L"${documents}";
     34 const WCHAR* kWinLocalAppDataFolderVarName = L"${local_app_data}";
     35 const WCHAR* kWinRoamingAppDataFolderVarName = L"${roaming_app_data}";
     36 const WCHAR* kWinProfileFolderVarName = L"${profile}";
     37 const WCHAR* kWinProgramDataFolderVarName = L"${global_app_data}";
     38 const WCHAR* kWinProgramFilesFolderVarName = L"${program_files}";
     39 const WCHAR* kWinWindowsFolderVarName = L"${windows}";
     40 const WCHAR* kWinClientName = L"${client_name}";
     41 
     42 struct WinFolderNamesToCSIDLMapping {
     43   const WCHAR* name;
     44   int id;
     45 };
     46 
     47 // Mapping from variable names to Windows CSIDL ids.
     48 const WinFolderNamesToCSIDLMapping win_folder_mapping[] = {
     49     { kWinWindowsFolderVarName,        CSIDL_WINDOWS},
     50     { kWinProgramFilesFolderVarName,   CSIDL_PROGRAM_FILES},
     51     { kWinProgramDataFolderVarName,    CSIDL_COMMON_APPDATA},
     52     { kWinProfileFolderVarName,        CSIDL_PROFILE},
     53     { kWinLocalAppDataFolderVarName,   CSIDL_LOCAL_APPDATA},
     54     { kWinRoamingAppDataFolderVarName, CSIDL_APPDATA},
     55     { kWinDocumentsFolderVarName,      CSIDL_PERSONAL}
     56 };
     57 
     58 }  // namespace
     59 
     60 namespace policy {
     61 
     62 namespace path_parser {
     63 
     64 // Replaces all variable occurances in the policy string with the respective
     65 // system settings values.
     66 base::FilePath::StringType ExpandPathVariables(
     67     const base::FilePath::StringType& untranslated_string) {
     68   base::FilePath::StringType result(untranslated_string);
     69   if (result.length() == 0)
     70     return result;
     71   // Sanitize quotes in case of any around the whole string.
     72   if (result.length() > 1 &&
     73       ((result[0] == L'"' && result[result.length() - 1] == L'"') ||
     74        (result[0] == L'\'' && result[result.length() - 1] == L'\''))) {
     75     // Strip first and last char which should be matching quotes now.
     76     result = result.substr(1, result.length() - 2);
     77   }
     78   // First translate all path variables we recognize.
     79   for (int i = 0; i < arraysize(win_folder_mapping); ++i) {
     80     size_t position = result.find(win_folder_mapping[i].name);
     81     if (position != std::wstring::npos) {
     82       WCHAR path[MAX_PATH];
     83       ::SHGetSpecialFolderPath(0, path, win_folder_mapping[i].id, false);
     84       std::wstring path_string(path);
     85       result.replace(position, wcslen(win_folder_mapping[i].name), path_string);
     86     }
     87   }
     88   // Next translate other windows specific variables.
     89   size_t position = result.find(kUserNamePolicyVarName);
     90   if (position != std::wstring::npos) {
     91     DWORD return_length = 0;
     92     ::GetUserName(NULL, &return_length);
     93     if (return_length != 0) {
     94       scoped_ptr<WCHAR[]> username(new WCHAR[return_length]);
     95       ::GetUserName(username.get(), &return_length);
     96       std::wstring username_string(username.get());
     97       result.replace(position, wcslen(kUserNamePolicyVarName), username_string);
     98     }
     99   }
    100   position = result.find(kMachineNamePolicyVarName);
    101   if (position != std::wstring::npos) {
    102     DWORD return_length = 0;
    103     ::GetComputerNameEx(ComputerNamePhysicalDnsHostname, NULL, &return_length);
    104     if (return_length != 0) {
    105       scoped_ptr<WCHAR[]> machinename(new WCHAR[return_length]);
    106       ::GetComputerNameEx(ComputerNamePhysicalDnsHostname,
    107                           machinename.get(), &return_length);
    108       std::wstring machinename_string(machinename.get());
    109       result.replace(
    110           position, wcslen(kMachineNamePolicyVarName), machinename_string);
    111     }
    112   }
    113   position = result.find(kWinClientName);
    114   if (position != std::wstring::npos) {
    115     LPWSTR buffer = NULL;
    116     DWORD buffer_length = 0;
    117     if (::WTSQuerySessionInformation(WTS_CURRENT_SERVER, WTS_CURRENT_SESSION,
    118                                      WTSClientName,
    119                                      &buffer, &buffer_length)) {
    120       std::wstring clientname_string(buffer);
    121       result.replace(position, wcslen(kWinClientName), clientname_string);
    122       ::WTSFreeMemory(buffer);
    123     }
    124   }
    125 
    126   return result;
    127 }
    128 
    129 void CheckUserDataDirPolicy(base::FilePath* user_data_dir) {
    130   DCHECK(user_data_dir);
    131   // Policy from the HKLM hive has precedence over HKCU.
    132   if (!LoadUserDataDirPolicyFromRegistry(HKEY_LOCAL_MACHINE, user_data_dir))
    133     LoadUserDataDirPolicyFromRegistry(HKEY_CURRENT_USER, user_data_dir);
    134 }
    135 
    136 }  // namespace path_parser
    137 
    138 }  // namespace policy
    139