// Copyright 2010-2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "win32/base/uninstall_helper.h"

#define _ATL_NO_AUTOMATIC_NAMESPACE
#define _WTL_NO_AUTOMATIC_NAMESPACE
#include <atlbase.h>
#include <atlcom.h>
#include <msctf.h>
#include <strsafe.h>
#include <objbase.h>

#include <iomanip>
#include <map>
#include <memory>
#include <sstream>

#include "base/logging.h"
#include "base/scoped_handle.h"
#include "base/system_util.h"
#include "base/win_util.h"
#include "win32/base/imm_registrar.h"
#include "win32/base/imm_util.h"
#include "win32/base/immdev.h"
#include "win32/base/tsf_profile.h"

namespace mozc {
namespace win32 {
using ATL::CComPtr;
using ATL::CRegKey;
using std::unique_ptr;

namespace {

typedef map<int, DWORD> PreloadOrderToKLIDMap;

// Windows NT 6.0, 6.1 and 6.2
const CLSID CLSID_IMJPTIP = {
    0x03b5835f, 0xf03c, 0x411b, {0x9c, 0xe2, 0xaa, 0x23, 0xe1, 0x17, 0x1e, 0x36}
};
const GUID GUID_IMJPTIP = {
    0xa76c93d9, 0x5523, 0x4e90, {0xaa, 0xfa, 0x4d, 0xb1, 0x12, 0xf9, 0xac, 0x76}
};

const LANGID kLANGJaJP = MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN);

const wchar_t kRegKeyboardLayouts[] =
    L"SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts";
const wchar_t kPreloadKeyName[] = L"Keyboard Layout\\Preload";

// Registry element size limits are described in the link below.
// http://msdn.microsoft.com/en-us/library/ms724872(VS.85).aspx
const DWORD kMaxValueNameLength = 16383;


// Converts an unsigned integer to a wide string.
wstring utow(unsigned int i) {
  wstringstream ss;
  ss << i;
  return ss.str();
}

wstring GetIMEFileNameFromKeyboardLayout(
    const CRegKey &key, const KeyboardLayoutID &klid) {
  CRegKey subkey;
  LONG result = subkey.Open(key, klid.ToString().c_str(), KEY_READ);
  if (ERROR_SUCCESS != result) {
    return L"";
  }

  wchar_t filename_buffer[kMaxValueNameLength];
  ULONG filename_length_including_null = kMaxValueNameLength;
  result = subkey.QueryStringValue(
      L"Ime File", filename_buffer, &filename_length_including_null);

  // Note that |filename_length_including_null| contains NUL terminator.
  if ((ERROR_SUCCESS != result) || (filename_length_including_null <= 1)) {
    return L"";
  }

  const ULONG filename_length = (filename_length_including_null - 1);
  const wstring filename(filename_buffer);

  // Note that |filename_length| does not contain NUL character.
  DCHECK_EQ(filename_length, filename.size());
  return filename;
}

bool GenerateKeyboardLayoutList(vector<KeyboardLayoutInfo> *keyboard_layouts) {
  if (keyboard_layouts == nullptr) {
    return false;
  }
  keyboard_layouts->clear();

  CRegKey key;
  LONG result = key.Open(
      HKEY_LOCAL_MACHINE, kRegKeyboardLayouts, KEY_READ);
  if (ERROR_SUCCESS != result) {
    return false;
  }

  wchar_t value_name[kMaxValueNameLength];
  for (DWORD enum_reg_index = 0;; ++enum_reg_index) {
    DWORD value_name_length = kMaxValueNameLength;
    result = key.EnumKey(
        enum_reg_index,
        value_name,
        &value_name_length);
    if (ERROR_NO_MORE_ITEMS == result) {
      return true;
    }
    if (ERROR_SUCCESS != result) {
      return true;
    }

    // Note that |value_name_length| does not contain NUL character.
    const KeyboardLayoutID klid(
        wstring(value_name, value_name + value_name_length));

    if (!klid.has_id()) {
      continue;
    }

    KeyboardLayoutInfo info;
    info.klid = klid.id();
    info.ime_filename = GetIMEFileNameFromKeyboardLayout(key, klid);
    keyboard_layouts->push_back(info);
  }
  return true;
}

bool GenerateKeyboardLayoutMap(map<DWORD, wstring> *keyboard_layouts) {
  if (keyboard_layouts == nullptr) {
    return false;
  }
  vector<KeyboardLayoutInfo> keyboard_layout_list;
  if (!GenerateKeyboardLayoutList(&keyboard_layout_list)) {
    return false;
  }

  for (size_t i = 0; i < keyboard_layout_list.size(); ++i) {
    const KeyboardLayoutInfo &layout = keyboard_layout_list[i];
    (*keyboard_layouts)[layout.klid] = layout.ime_filename;
  }

  return true;
}

wstring GetIMEFileName(HKL hkl) {
  const UINT num_chars_without_null = ::ImmGetIMEFileName(hkl, nullptr, 0);
  const size_t num_chars_with_null = num_chars_without_null + 1;
  unique_ptr<wchar_t[]> buffer(new wchar_t[num_chars_with_null]);
  const UINT num_copied =
      ::ImmGetIMEFileName(hkl, buffer.get(), num_chars_with_null);

  // |num_copied| does not include terminating null character.
  return wstring(buffer.get(), buffer.get() + num_copied);
}

bool GetInstalledProfilesByLanguageForTSF(
    LANGID langid,
    vector<LayoutProfileInfo> *installed_profiles) {
  ScopedCOMInitializer com_initializer;
  if (FAILED(com_initializer.error_code())) {
    return false;
  }

  HRESULT hr = S_OK;

  CComPtr<ITfInputProcessorProfiles> profiles;
  hr = profiles.CoCreateInstance(CLSID_TF_InputProcessorProfiles);
  if (FAILED(hr)) {
    return false;
  }

  CComPtr<IEnumTfLanguageProfiles> enum_profiles;
  hr = profiles->EnumLanguageProfiles(langid, &enum_profiles);
  if (FAILED(hr)) {
    return false;
  }

  while (true) {
    ULONG num_fetched = 0;
    TF_LANGUAGEPROFILE src = {0};
    hr = enum_profiles->Next(1, &src, &num_fetched);
    if (FAILED(hr)) {
      return false;
    }
    if ((hr == S_FALSE) || (num_fetched != 1)) {
      break;
    }

    if (src.catid != GUID_TFCAT_TIP_KEYBOARD) {
      continue;
    }
    LayoutProfileInfo profile;
    profile.langid = src.langid;
    profile.is_default = (src.fActive != FALSE);
    BOOL enabled = FALSE;
    hr = profiles->IsEnabledLanguageProfile(
        src.clsid, langid, src.guidProfile, &enabled);
    if (SUCCEEDED(hr)) {
      profile.is_enabled = (enabled != FALSE);
    }
    profile.clsid = src.clsid;
    profile.profile_guid = src.guidProfile;
    profile.is_tip = true;
    installed_profiles->push_back(profile);
  }

  return true;
}

bool GetInstalledProfilesByLanguageForIMM32(
    LANGID langid,
    vector<LayoutProfileInfo> *installed_profiles) {
  vector<KeyboardLayoutInfo> keyboard_layouts;
  if (!GenerateKeyboardLayoutList(&keyboard_layouts)) {
    DLOG(ERROR) << "GenerateKeyboardLayoutList failed.";
    return false;
  }

  for (size_t i = 0; i < keyboard_layouts.size(); ++i) {
    const KeyboardLayoutInfo &info = keyboard_layouts[i];
    const LANGID info_langid = static_cast<LANGID>(info.klid & 0xffff);
    if (info_langid == langid) {
      LayoutProfileInfo profile;
      profile.langid = langid;
      profile.is_tip = false;
      profile.klid = info.klid;
      // TODO(yukawa): determine |profile.is_default|
      // TODO(yukawa): determine |profile.is_enabled|
      profile.ime_filename = info.ime_filename;
      installed_profiles->push_back(profile);
    }
  }

  return true;
}

bool GetPreloadLayoutsMain(PreloadOrderToKLIDMap *preload_map) {
  if (preload_map == nullptr) {
    return false;
  }

  // Retrieve keys under kPreloadKeyName.
  CRegKey preload_key;
  LONG result = preload_key.Open(HKEY_CURRENT_USER, kPreloadKeyName);
  if (ERROR_SUCCESS != result) {
    return false;
  }

  wchar_t value_name[kMaxValueNameLength];
  const DWORD kMaxValueLength = 256;
  BYTE value[kMaxValueLength];
  for (DWORD i = 0;; ++i) {
    DWORD value_name_length = kMaxValueNameLength;
    DWORD value_length = kMaxValueLength;
    result = RegEnumValue(preload_key,
                          i,
                          value_name,
                          &value_name_length,
                          nullptr,  // reserved (must be nullptr)
                          nullptr,  // type (optional)
                          value,
                          &value_length);
    if (ERROR_NO_MORE_ITEMS == result) {
      break;
    }
    if (ERROR_SUCCESS != result) {
      return false;
    }

    const int ivalue_name = _wtoi(value_name);
    const wstring wvalue(reinterpret_cast<wchar_t*>(value),
                         (value_length / sizeof(wchar_t)) - 1);
    KeyboardLayoutID klid(wvalue);
    if (!klid.has_id()) {
      continue;
    }
    (*preload_map)[ivalue_name] = klid.id();
  }
  return true;
}

wstring GUIDToString(const GUID &guid) {
  wchar_t buffer[256];
  const int character_length_with_null =
      ::StringFromGUID2(guid, buffer, arraysize(buffer));
  if (character_length_with_null <= 0) {
    return L"";
  }

  const size_t character_length_without_null =
      character_length_with_null - 1;
  return wstring(buffer, buffer + character_length_without_null);
}

wstring LANGIDToString(LANGID langid) {
  wchar_t buffer[5];
  HRESULT hr = ::StringCchPrintf(buffer, arraysize(buffer), L"%04x", langid);
  if (FAILED(hr)) {
    return L"";
  }
  return buffer;
}

bool BroadcastNewIME(const KeyboardLayoutInfo &layout) {
  KeyboardLayoutID klid(layout.klid);

  // We cannot use const HKL because |&mozc_hkl| will be cast into PVOID.
  HKL hkl = ::LoadKeyboardLayout(klid.ToString().c_str(), KLF_ACTIVATE);

  // SPI_SETDEFAULTINPUTLANG ensures that new process in this session will
  // use |hkl| by default but this setting is volatile even if you specified
  // SPIF_UPDATEINIFILE flag.
  // SPI_SETDEFAULTINPUTLANG does not work perfectly for a HKL substituted
  // by a TIP on Windows XP.  It works for notepad but wordpad still uses
  // the previous layout.  Consider to use
  // ITfInputProcessorProfiles::SetDefaultLanguageProfile for TIP backed
  // layout.
  if (::SystemParametersInfo(
          SPI_SETDEFAULTINPUTLANG, 0, &hkl, SPIF_SENDCHANGE) == FALSE) {
    LOG(ERROR) << "SystemParameterInfo failed: " << GetLastError();
    return false;
  }


  // Broadcasting WM_INPUTLANGCHANGEREQUEST so that existing process in the
  // current session will change their input method to |hkl|. This mechanism
  // also works against a HKL which is substituted by a TIP on Windows XP.
  // Note: we have virtually the same code in imm_util.cc too.
  // TODO(yukawa): Make a common function around WM_INPUTLANGCHANGEREQUEST.
  DWORD recipients = BSM_APPLICATIONS;
  const LONG result = ::BroadcastSystemMessage(
      BSF_POSTMESSAGE,
      &recipients,
      WM_INPUTLANGCHANGEREQUEST,
      INPUTLANGCHANGE_SYSCHARSET,
      reinterpret_cast<LPARAM>(hkl));
  if (result == 0) {
    const int error = ::GetLastError();
    LOG(ERROR) << "BroadcastSystemMessage failed. error = " << error;
    return false;
  }

  return true;
}

bool BroadcastNewTIPOnVista(const LayoutProfileInfo &profile) {
  ScopedCOMInitializer com_initializer;
  if (FAILED(com_initializer.error_code())) {
    return false;
  }

  CComPtr<ITfInputProcessorProfileMgr> profile_manager;

  HRESULT hr = S_OK;
  hr = profile_manager.CoCreateInstance(CLSID_TF_InputProcessorProfiles);
  if (FAILED(hr)) {
    return false;
  }

  const DWORD activate_flags =
      TF_IPPMF_FORSESSION | TF_IPPMF_ENABLEPROFILE |
      TF_IPPMF_DONTCARECURRENTINPUTLANGUAGE;

  hr = profile_manager->ActivateProfile(
      TF_PROFILETYPE_INPUTPROCESSOR, profile.langid, profile.clsid,
      profile.profile_guid, nullptr, activate_flags);
  if (FAILED(hr)) {
    return false;
  }

  return true;
}

bool EnableAndBroadcastNewLayout(
    const LayoutProfileInfo &profile, bool broadcast_change) {
  if (profile.is_tip) {
    ScopedCOMInitializer com_initializer;
    if (FAILED(com_initializer.error_code())) {
      return false;
    }

    CComPtr<ITfInputProcessorProfileMgr> profile_manager;

    HRESULT hr = S_OK;
    hr = profile_manager.CoCreateInstance(CLSID_TF_InputProcessorProfiles);
    if (FAILED(hr)) {
      return false;
    }

    DWORD activate_flags = TF_IPPMF_ENABLEPROFILE |
                           TF_IPPMF_DONTCARECURRENTINPUTLANGUAGE;

    if (broadcast_change) {
      activate_flags |= TF_IPPMF_FORSESSION;
    }
    hr = profile_manager->ActivateProfile(
        TF_PROFILETYPE_INPUTPROCESSOR, profile.langid, profile.clsid,
        profile.profile_guid, nullptr, activate_flags);
    if (FAILED(hr)) {
      DLOG(ERROR) << "ActivateProfile failed";
      return false;
    }

    return true;
  }

  // |profile| is IME.
  if (!broadcast_change) {
    return true;
  }

  KeyboardLayoutInfo layout;
  layout.klid = profile.klid;
  layout.ime_filename = profile.ime_filename;
  if (!BroadcastNewIME(layout)) {
    DLOG(ERROR) << "BroadcastNewIME failed";
    return false;
  }
  return true;
}

bool GetActiveKeyboardLayouts(vector<HKL> *keyboard_layouts) {
  if (keyboard_layouts == nullptr) {
    return false;
  }
  keyboard_layouts->clear();

  const int num_keyboard_layout = ::GetKeyboardLayoutList(0, nullptr);
  unique_ptr<HKL[]> buffer(new HKL[num_keyboard_layout]);
  const int num_copied = ::GetKeyboardLayoutList(num_keyboard_layout,
                                                 buffer.get());
  keyboard_layouts->assign(buffer.get(), buffer.get() + num_copied);

  return true;
}

void EnableAndSetDefaultIfLayoutIsTIP(const KeyboardLayoutInfo &layout) {
  ScopedCOMInitializer com_initializer;
  if (FAILED(com_initializer.error_code())) {
    return;
  }

  HRESULT hr = S_OK;

  CComPtr<ITfInputProcessorProfiles> profiles;
  hr = profiles.CoCreateInstance(CLSID_TF_InputProcessorProfiles);
  if (FAILED(hr)) {
    return;
  }
  CComPtr<ITfInputProcessorProfileSubstituteLayout> substitute_layout;
  hr = profiles.QueryInterface(&substitute_layout);
  if (FAILED(hr)) {
    return;
  }

  CComPtr<IEnumTfLanguageProfiles> enum_profiles;
  const LANGID langid = static_cast<LANGID>(layout.klid);
  hr = profiles->EnumLanguageProfiles(langid, &enum_profiles);
  if (FAILED(hr)) {
    return;
  }

  while (true) {
    ULONG num_fetched = 0;
    TF_LANGUAGEPROFILE profile = {0};
    hr = enum_profiles->Next(1, &profile, &num_fetched);
    if (FAILED(hr)) {
      return;
    }
    if ((hr == S_FALSE) || (num_fetched != 1)) {
      return;
    }

    if (profile.catid != GUID_TFCAT_TIP_KEYBOARD) {
      continue;
    }

    HKL hkl = nullptr;
    hr = substitute_layout->GetSubstituteKeyboardLayout(profile.clsid,
                                                        profile.langid,
                                                        profile.guidProfile,
                                                        &hkl);
    if (FAILED(hr)) {
      DLOG(ERROR) << "GetSubstituteKeyboardLayout failed";
      continue;
    }
    if (!WinUtil::SystemEqualString(
             GetIMEFileName(hkl), layout.ime_filename, true)) {
      continue;
    }

    BOOL enabled = TRUE;
    hr = profiles->EnableLanguageProfile(profile.clsid,
                                         profile.langid,
                                         profile.guidProfile,
                                         TRUE);
    if (FAILED(hr)) {
      DLOG(ERROR) << "EnableLanguageProfile failed";
      continue;
    }

    hr = profiles->SetDefaultLanguageProfile(profile.langid,
                                             profile.clsid,
                                             profile.guidProfile);
    if (FAILED(hr)) {
      DLOG(ERROR) << "SetDefaultLanguageProfile failed";
      continue;
    }
    return;
  }
  return;
}

// This function lists all the active keyboard layouts up and unloads each
// layout based on the specified condition.  If |exclude| is true, this
// function unloads any active IME if it is included in |ime_filenames|.
// If |exclude| is false, this function unloads any active IME unless it is
// included in |ime_filenames|.
void UnloadActivatedKeyboardMain(const vector<wstring> &ime_filenames,
                                 bool exclude) {
  vector<HKL> loaded_layouts;
  if (!GetActiveKeyboardLayouts(&loaded_layouts)) {
    return;
  }
  for (size_t i = 0; i < loaded_layouts.size(); ++i) {
    const HKL hkl = loaded_layouts[i];
    const wstring ime_filename = GetIMEFileName(hkl);
    if (ime_filename.empty()) {
      continue;
    }
    bool can_unload = !exclude;
    for (size_t j = 0; j < ime_filenames.size(); ++j) {
      if (WinUtil::SystemEqualString(ime_filename, ime_filenames[j], true)) {
        can_unload = exclude;
        break;
      }
    }
    if (can_unload) {
      ::UnloadKeyboardLayout(hkl);
    }
  }
}

void UnloadProfilesForVista(
    const vector<LayoutProfileInfo> &profiles_to_be_removed) {
  vector <wstring> ime_filenames;
  for (size_t i = 0; i < profiles_to_be_removed.size(); ++i) {
    ime_filenames.push_back(profiles_to_be_removed[i].ime_filename);
  }
  UnloadActivatedKeyboardMain(ime_filenames, true);
}

bool IsEqualProfile(const LayoutProfileInfo &lhs,
                    const LayoutProfileInfo &rhs) {
  // Check if the profile type (TIP or IME) is the same.
  if (lhs.is_tip != rhs.is_tip) {
    return false;
  }
  // Check if the target language is the same.
  if (lhs.langid != rhs.langid) {
    return false;
  }

  if (lhs.is_tip) {
    // If both of them are TIP, check if they have the same CLSID and Profile
    // GUID.  Otherwise, they are different from each other.
    DCHECK(rhs.is_tip);
    if (::IsEqualCLSID(lhs.clsid, rhs.clsid) == 0) {
      return false;
    }
    if (::IsEqualGUID(lhs.profile_guid, rhs.profile_guid) == 0) {
      return false;
    }
    return true;
  }

  // If both of them are IME, check if they have the same KLID and IME file
  // name (if any).  Otherwise, they are different from each other.
  DCHECK(!lhs.is_tip);
  DCHECK(!rhs.is_tip);
  if (lhs.klid != rhs.klid) {
    return false;
  }
  if (!WinUtil::SystemEqualString(
           lhs.ime_filename.c_str(), rhs.ime_filename.c_str(), true)) {
    return false;
  }
  return true;
}

bool IsEqualPreload(const PreloadOrderToKLIDMap &current_preload_map,
                    const vector<KeyboardLayoutInfo> &new_preload_layouts) {
  if (current_preload_map.size() != new_preload_layouts.size()) {
    return false;
  }

  int index = 0;
  for (PreloadOrderToKLIDMap::const_iterator it = current_preload_map.begin();
       it != current_preload_map.end(); ++it) {
    const DWORD klid = it->second;
    DCHECK_GE(index, 0);
    DCHECK_LT(index, new_preload_layouts.size());
    if (klid != new_preload_layouts[index].klid) {
      return false;
    }
    ++index;
  }

  return true;
}

// Currently only keyboard layouts which have IME filename are supported.
bool RemoveHotKeyForIME(
    const vector<KeyboardLayoutInfo> &layouts_to_be_removed) {
  bool succeeded = true;
  for (DWORD id = IME_HOTKEY_DSWITCH_FIRST; id <= IME_HOTKEY_DSWITCH_LAST;
       ++id) {
    UINT modifiers = 0;
    UINT virtual_key = 0;
    HKL hkl = nullptr;
    BOOL result = ::ImmGetHotKey(id, &modifiers, &virtual_key, &hkl);
    if (result == FALSE) {
      continue;
    }
    if (hkl == nullptr) {
      continue;
    }
    const wstring ime_name = GetIMEFileName(hkl);
    for (size_t i = 0; i < layouts_to_be_removed.size(); ++i) {
      const KeyboardLayoutInfo &layout = layouts_to_be_removed[i];
      if (layout.ime_filename.empty()) {
        continue;
      }
      if (!WinUtil::SystemEqualString(layout.ime_filename, ime_name, true)) {
        continue;
      }
      // ImmSetHotKey fails when both 2nd and 3rd arguments are valid while 4th
      // argument is nullptr.  To remove the HotKey, pass 0 to them.
      result = ::ImmSetHotKey(id, 0, 0, nullptr);
      if (result == FALSE) {
        succeeded = false;
      }
      break;
    }
  }
  return succeeded;
}

// Currently this function is Mozc-specific.
// TODO(yukawa): Generalize this function for any IME.
void RemoveHotKeyForVista(const vector<LayoutProfileInfo> &installed_profiles) {
  vector<KeyboardLayoutInfo> hotkey_remove_targets;
  for (size_t i = 0; i < installed_profiles.size(); ++i) {
    const LayoutProfileInfo &profile = installed_profiles[i];
    if (!profile.is_tip && WinUtil::SystemEqualString(
              profile.ime_filename, ImmRegistrar::GetFileNameForIME(), true)) {
      // This is the full IMM32 version of Google Japanese Input.
      KeyboardLayoutInfo info;
      info.klid = profile.klid;
      info.ime_filename = profile.ime_filename;
      hotkey_remove_targets.push_back(info);
      continue;
    }
  }

  if (!RemoveHotKeyForIME(hotkey_remove_targets)) {
    DLOG(ERROR) << "RemoveHotKeyForIME failed.";
  }
}

}  // namespace

KeyboardLayoutInfo::KeyboardLayoutInfo()
    : klid(0) {}

LayoutProfileInfo::LayoutProfileInfo()
    : langid(0),
      clsid(CLSID_NULL),
      profile_guid(GUID_NULL),
      klid(0),
      is_default(false),
      is_tip(false),
      is_enabled(false) {}

// Currently this function is Mozc-specific.
// TODO(yukawa): Generalize this function for any IME and/or TIP.
bool UninstallHelper::GetNewEnabledProfileForVista(
    const vector<LayoutProfileInfo> &current_profiles,
    const vector<LayoutProfileInfo> &installed_profiles,
    LayoutProfileInfo *current_default,
    LayoutProfileInfo *new_default,
    vector<LayoutProfileInfo> *removed_profiles) {
  if (current_default == nullptr) {
    return false;
  }
  // Initialize in case no entry is marked as default.
  *current_default = LayoutProfileInfo();

  if (new_default == nullptr) {
    return false;
  }
  if (removed_profiles == nullptr) {
    return false;
  }
  removed_profiles->clear();

  bool default_found = false;
  bool default_set = false;
  for (size_t i = 0; i < current_profiles.size(); ++i) {
    const LayoutProfileInfo &profile = current_profiles[i];
    if (profile.is_default) {
      *current_default = profile;
    }

    if (!profile.is_tip &&
        WinUtil::SystemEqualString(
            profile.ime_filename, ImmRegistrar::GetFileNameForIME(), true)) {
      // This is the full IMM32 version of Google Japanese Input.
      removed_profiles->push_back(profile);
      continue;
    }
    if (profile.is_tip &&
        ::IsEqualCLSID(TsfProfile::GetTextServiceGuid(), profile.clsid) &&
        ::IsEqualGUID(TsfProfile::GetProfileGuid(), profile.profile_guid)) {
      // This is the full TSF version of Google Japanese Input.
      removed_profiles->push_back(profile);
      continue;
    }

    if (!default_found && profile.is_enabled && profile.is_default) {
      default_found = true;
      default_set = true;
      *new_default = profile;
    }

    if (!default_found && !default_set && profile.is_enabled) {
      default_set = true;
      *new_default = profile;
    }
  }

  if (!default_set) {
    // TODO(yukawa): Consider this case.
    // Use MS-IME as a fallback.
    new_default->langid = MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN);
    new_default->clsid = CLSID_IMJPTIP;
    new_default->profile_guid = GUID_IMJPTIP;
    new_default->klid = 0;
    new_default->ime_filename.clear();
    new_default->is_default = true;
    new_default->is_tip = true;
    new_default->is_enabled = false;
  }

  return true;
}

bool UninstallHelper::GetInstalledProfilesByLanguage(
    LANGID langid,
    vector<LayoutProfileInfo> *installed_profiles) {
  if (installed_profiles == nullptr) {
    return false;
  }
  installed_profiles->clear();

  if (!GetInstalledProfilesByLanguageForTSF(langid, installed_profiles)) {
    // Actually this can fail if user have explicitly unregistered TSF modules
    // like b/2636769.  We do not return false because it would be better to
    // continue with the result of GetInstalledProfilesByLanguageForIMM32.
    LOG(ERROR) << "GetInstalledProfilesByLanguageForTSF failed.";
  }

  if (!GetInstalledProfilesByLanguageForIMM32(langid, installed_profiles)) {
    LOG(ERROR) << "GetInstalledProfilesByLanguageForIMM32 failed.";
    return false;
  }

  return true;
}

bool UninstallHelper::GetCurrentProfilesForVista(
    vector<LayoutProfileInfo> *current_profiles) {
  if (current_profiles == nullptr) {
    return false;
  }
  current_profiles->clear();

  map<DWORD, wstring> keyboard_layouts;
  if (!GenerateKeyboardLayoutMap(&keyboard_layouts)) {
    return false;
  }

  {
    const UINT num_element = ::EnumEnabledLayoutOrTip(
        nullptr, nullptr, nullptr, nullptr, 0);
    unique_ptr<LAYOUTORTIPPROFILE[]> buffer(
        new LAYOUTORTIPPROFILE[num_element]);
    const UINT num_copied = ::EnumEnabledLayoutOrTip(
        nullptr, nullptr, nullptr, buffer.get(), num_element);

    for (size_t i = 0; i < num_copied; ++i) {
      const LAYOUTORTIPPROFILE &src = buffer[i];
      if (src.catid != GUID_TFCAT_TIP_KEYBOARD) {
        continue;
      }

      LayoutProfileInfo profile;
      profile.langid = src.langid;
      profile.is_default = ((src.dwFlags & LOT_DEFAULT) == LOT_DEFAULT);
      profile.is_enabled = !((src.dwFlags & LOT_DISABLED) == LOT_DISABLED);
      profile.clsid = src.clsid;
      profile.profile_guid = src.guidProfile;

      if ((src.dwProfileType & LOTP_INPUTPROCESSOR) == LOTP_INPUTPROCESSOR) {
        profile.is_tip = true;
        current_profiles->push_back(profile);
        continue;
      }

      if ((src.dwProfileType & LOTP_KEYBOARDLAYOUT) == LOTP_KEYBOARDLAYOUT) {
        const wstring id(src.szId);
        // A valid |profile.szId| should consists of language ID (LANGID) and
        // keyboard layout ID (KILD) as follows.
        //  <LangID 1>:<KLID 1>
        //       "0411:E0200411"
        // Check if |id.size()| is expected.
        if (id.size() != 13) {
          continue;
        }
        // Extract KLID.  It should be 8-letter hexadecimal code begins at 6th
        // character in the |id|, that is, |id.substr(5, 8)|.
        const KeyboardLayoutID klid(id.substr(5, 8));
        if (!klid.has_id()) {
          continue;
        }
        profile.klid = klid.id();
        if (keyboard_layouts.find(profile.klid) != keyboard_layouts.end()) {
          profile.ime_filename = keyboard_layouts[profile.klid];
        }
        profile.is_tip = false;
        current_profiles->push_back(profile);
        continue;
      }
    }
  }  // release |buffer|

  return true;
}

bool UninstallHelper::RemoveProfilesForVista(
    const vector<LayoutProfileInfo> &profiles_to_be_removed) {
  if (profiles_to_be_removed.size() == 0) {
    // Nothing to do.
    return true;
  }

  const wstring &profile_string = ComposeProfileStringForVista(
      profiles_to_be_removed);

  const BOOL result = ::InstallLayoutOrTipUserReg(
      nullptr, nullptr, nullptr, profile_string.c_str(), ILOT_UNINSTALL);

  return result != FALSE;
}

wstring UninstallHelper::ComposeProfileStringForVista(
    const vector<LayoutProfileInfo> &profiles) {
  wstringstream ss;
  for (size_t i = 0; i < profiles.size(); ++i) {
    const LayoutProfileInfo &info = profiles[i];
    if (i != 0) {
      ss << L";";
    }

    const wstring &langid_string = LANGIDToString(info.langid);
    if (langid_string.empty()) {
      continue;
    }

    if (info.is_tip) {
      const wstring &clsid_string = GUIDToString(info.clsid);
      const wstring &guid_string = GUIDToString(info.profile_guid);
      if (clsid_string.empty() || guid_string.empty()) {
        continue;
      }
      ss << langid_string << L":" << clsid_string << guid_string;
    } else {
      const KeyboardLayoutID klid(info.klid);
      ss << langid_string << L":" << klid.ToString();
    }
  }
  return ss.str();
}

bool UninstallHelper::SetDefaultForVista(
    const LayoutProfileInfo &current_default,
    const LayoutProfileInfo &new_default, bool broadcast_change) {
  if (current_default.is_default && current_default.is_enabled &&
      IsEqualProfile(current_default, new_default)) {
    // |new_default| is alreasy default and enabled.
    return true;
  }

  if (!EnableAndBroadcastNewLayout(new_default, broadcast_change)) {
    // We do not return false here because the main task of this function is
    // setting the specified profile to default.
    DLOG(ERROR) << "EnableAndBroadcastNewLayout failed.";
  }

  vector<LayoutProfileInfo> profile_list;
  profile_list.push_back(new_default);
  const wstring profile_string = ComposeProfileStringForVista(profile_list);
  if (profile_string.empty()) {
    return false;
  }

  DWORD flag = 0;
  if (!broadcast_change) {
    // If |broadcast_change| prevent the SetDefaultLayoutOrTip API from
    // disturbing the current session in case the thread is impersonated.
    flag = SDLOT_NOAPPLYTOCURRENTSESSION;
  }

  if (!::SetDefaultLayoutOrTip(profile_string.c_str(), flag)) {
    DLOG(ERROR) << "SetDefaultLayoutOrTip failed";
    return false;
  }

  return true;
}

bool UninstallHelper::RestoreUserIMEEnvironmentForVista(bool broadcast_change) {
  vector<LayoutProfileInfo> installed_profiles;
  if (!GetInstalledProfilesByLanguage(kLANGJaJP, &installed_profiles)) {
    return false;
  }

  RemoveHotKeyForVista(installed_profiles);

  vector<LayoutProfileInfo> current_profiles;
  if (!GetCurrentProfilesForVista(&current_profiles)) {
    return false;
  }
  LayoutProfileInfo current_default;
  LayoutProfileInfo new_default;
  vector<LayoutProfileInfo> removed_profiles;
  if (!GetNewEnabledProfileForVista(current_profiles, installed_profiles,
                                    &current_default, &new_default,
                                    &removed_profiles)) {
    return false;
  }
  if (!SetDefaultForVista(current_default, new_default, broadcast_change)) {
    DLOG(ERROR) << "SetDefaultForVista failed.";
  }
  if (!RemoveProfilesForVista(removed_profiles)) {
    DLOG(ERROR) << "RemoveProfilesForVista failed.";
  }
  if (broadcast_change) {
    // Unload unnecessary keyboard layouts.
    UnloadProfilesForVista(removed_profiles);
  }
  return true;
}

bool UninstallHelper::RestoreUserIMEEnvironmentMain() {
  // Basically this function is called from the "non-deferred" custom action
  // with "non-elevated" user privileges, which is enough and prefarable to
  // update entries under HKCU.  Assuming the desktop is available,
  // broadcast messages into existing processes so that these processes
  // start to use the new default IME.
  const bool kBroadcastNewIME = true;

  return RestoreUserIMEEnvironmentForVista(kBroadcastNewIME);
}

bool UninstallHelper::EnsureIMEIsRemovedForCurrentUser(
    bool disable_hkcu_cache) {

  if (disable_hkcu_cache) {
    // For some reason, HKCU in a deferred, non-impersonated custom action is
    // occasionally mapped not to the HKU/.Default but to the active user's
    // profile as if the current thread is impersonated to the active user.
    // To fix up this, we should disable per-process registry cache by calling
    // RegDisablePredefinedCache API.
    const LRESULT result = ::RegDisablePredefinedCache();
    if (result != ERROR_SUCCESS) {
      DLOG(ERROR) << "IsServiceThread failed.  result = " << result;
      return false;
    }
  }

  // Since this function is targeting for the service account, IME change
  // notification will not be sent in case it causes unwilling side-effects
  // against other important processes running in the service session.
  const bool kBroadcastNewIME = false;
  return RestoreUserIMEEnvironmentForVista(kBroadcastNewIME);
}

}  // namespace win32
}  // namespace mozc
