// 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) {
  std::wstring value;
  std::wstring key_name(base::ASCIIToWide(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}";

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);
    }
  }

  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
