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.
7 #pragma comment(lib, "wtsapi32.lib")
9 #include "chrome/browser/policy/policy_path_parser.h"
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"
19 // Checks if the key exists in the given hive and expands any string variables.
20 bool LoadUserDataDirPolicyFromRegistry(HKEY hive
, base::FilePath
* dir
) {
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
));
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}";
42 struct WinFolderNamesToCSIDLMapping
{
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
}
62 namespace path_parser
{
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)
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);
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
) {
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
);
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
);
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());
110 position
, wcslen(kMachineNamePolicyVarName
), machinename_string
);
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
,
119 &buffer
, &buffer_length
)) {
120 std::wstring
clientname_string(buffer
);
121 result
.replace(position
, wcslen(kWinClientName
), clientname_string
);
122 ::WTSFreeMemory(buffer
);
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
);
136 } // namespace path_parser
138 } // namespace policy