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