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
7#include "chrome/browser/policy/policy_path_parser.h"
8
9#include "base/logging.h"
10#include "base/memory/scoped_ptr.h"
11
12namespace policy {
13
14namespace path_parser {
15
16const WCHAR* kMachineNamePolicyVarName = L"${machine_name}";
17const WCHAR* kUserNamePolicyVarName = L"${user_name}";
18const WCHAR* kWinDocumentsFolderVarName = L"${documents}";
19const WCHAR* kWinLocalAppDataFolderVarName = L"${local_app_data}";
20const WCHAR* kWinRoamingAppDataFolderVarName = L"${roaming_app_data}";
21const WCHAR* kWinProfileFolderVarName = L"${profile}";
22const WCHAR* kWinProgramDataFolderVarName = L"${global_app_data}";
23const WCHAR* kWinProgramFilesFolderVarName = L"${program_files}";
24const WCHAR* kWinWindowsFolderVarName = L"${windows}";
25
26struct WinFolderNamesToCSIDLMapping {
27  const WCHAR* name;
28  int id;
29};
30
31// Mapping from variable names to Windows CSIDL ids.
32const WinFolderNamesToCSIDLMapping win_folder_mapping[] = {
33    { kWinWindowsFolderVarName,        CSIDL_WINDOWS},
34    { kWinProgramFilesFolderVarName,   CSIDL_PROGRAM_FILES},
35    { kWinProgramDataFolderVarName,    CSIDL_COMMON_APPDATA},
36    { kWinProfileFolderVarName,        CSIDL_PROFILE},
37    { kWinLocalAppDataFolderVarName,   CSIDL_LOCAL_APPDATA},
38    { kWinRoamingAppDataFolderVarName, CSIDL_APPDATA},
39    { kWinDocumentsFolderVarName,      CSIDL_PERSONAL}
40};
41
42// Replaces all variable occurances in the policy string with the respective
43// system settings values.
44FilePath::StringType ExpandPathVariables(
45    const FilePath::StringType& untranslated_string) {
46  FilePath::StringType result(untranslated_string);
47  // First translate all path variables we recognize.
48  for (int i = 0; i < arraysize(win_folder_mapping); ++i) {
49    size_t position = result.find(win_folder_mapping[i].name);
50    if (position != std::wstring::npos) {
51      WCHAR path[MAX_PATH];
52      ::SHGetSpecialFolderPath(0, path, win_folder_mapping[i].id, false);
53      std::wstring path_string(path);
54      result.replace(position, wcslen(win_folder_mapping[i].name), path_string);
55    }
56  }
57  // Next translate two speacial variables ${user_name} and ${machine_name}
58  size_t position = result.find(kUserNamePolicyVarName);
59  if (position != std::wstring::npos) {
60    DWORD return_length = 0;
61    ::GetUserName(NULL, &return_length);
62    if (return_length != 0) {
63      scoped_array<WCHAR> username(new WCHAR[return_length]);
64      ::GetUserName(username.get(), &return_length);
65      std::wstring username_string(username.get());
66      result.replace(position, wcslen(kUserNamePolicyVarName), username_string);
67    }
68  }
69  position = result.find(kMachineNamePolicyVarName);
70  if (position != std::wstring::npos) {
71    DWORD return_length = 0;
72    ::GetComputerNameEx(ComputerNamePhysicalDnsHostname, NULL, &return_length);
73    if (return_length != 0) {
74      scoped_array<WCHAR> machinename(new WCHAR[return_length]);
75      ::GetComputerNameEx(ComputerNamePhysicalDnsHostname,
76                          machinename.get(), &return_length);
77      std::wstring machinename_string(machinename.get());
78      result.replace(
79          position, wcslen(kMachineNamePolicyVarName), machinename_string);
80    }
81  }
82  return result;
83}
84
85}  // namespace path_parser
86
87}  // namespace policy
88