// 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 "base/win_util.h"

// skip all unless OS_WIN
#ifdef OS_WIN

#include <Aux_ulib.h>
#include <Psapi.h>
#include <Winternl.h>

#define _ATL_NO_AUTOMATIC_NAMESPACE
#define _WTL_NO_AUTOMATIC_NAMESPACE
#include <atlbase.h>

#include <clocale>
#include <memory>

#include "base/logging.h"
#include "base/mutex.h"
#include "base/scoped_handle.h"
#include "base/system_util.h"
#include "base/util.h"

using std::unique_ptr;

namespace mozc {
namespace {

once_t g_aux_lib_initialized = MOZC_ONCE_INIT;

void CallAuxUlibInitialize() {
  ::AuxUlibInitialize();
}

// Adjusts privileges in the process token to be able to shutdown the machine.
// Returns true if the operation finishes without error.
// We do not use LOG functions in this function to avoid dependency to CRT.
bool AdjustPrivilegesForShutdown() {
  TOKEN_PRIVILEGES ns;
  HANDLE htoken;
  LUID LID;
  LUID_AND_ATTRIBUTES att;

  if (!::OpenProcessToken(::GetCurrentProcess(),
                          TOKEN_ADJUST_PRIVILEGES,
                          &htoken)) {
    // Cannot open process token
    return false;
  }

  if (!::LookupPrivilegeValue(nullptr, SE_SHUTDOWN_NAME, &LID)) {
    // LookupPrivilegeValue failed
    return false;
  }

  att.Attributes = SE_PRIVILEGE_ENABLED;
  att.Luid = LID;
  ns.PrivilegeCount = 1;
  ns.Privileges[0] = att;

  if (!::AdjustTokenPrivileges(htoken, FALSE, &ns, 0, nullptr, nullptr)) {
    // AdjustTokenPrivileges failed
    return false;
  }

  return true;
}

bool EqualLuid(const LUID &L1, const LUID &L2) {
  return (L1.LowPart == L2.LowPart && L1.HighPart == L2.HighPart);
}


// The registry key for the CUAS setting.
// Note: We have the same values in win32/base/imm_util.cc
// TODO(yukawa): Define these constants at the same place.
const wchar_t kCUASKey[] = L"Software\\Microsoft\\CTF\\SystemShared";
const wchar_t kCUASValueName[] = L"CUAS";

// Reads CUAS value in the registry keys and returns true if the value is set
// to 1.
// The CUAS value is read from 64 bit registry keys if KEY_WOW64_64KEY is
// specified as |additional_regsam| and read from 32 bit registry keys if
// KEY_WOW64_32KEY is specified.
bool IsCuasEnabledInternal(REGSAM additional_regsam) {
  const REGSAM sam_desired = KEY_QUERY_VALUE | additional_regsam;
  ATL::CRegKey key;
  LONG result = key.Open(HKEY_LOCAL_MACHINE, kCUASKey, sam_desired);
  if (ERROR_SUCCESS != result) {
    LOG(ERROR) << "Cannot open HKEY_LOCAL_MACHINE\\Software\\Microsoft\\CTF\\"
                  "SystemShared: "
               << result;
    return false;
  }
  DWORD cuas;
  result = key.QueryDWORDValue(kCUASValueName, cuas);
  if (ERROR_SUCCESS != result) {
    LOG(ERROR) << "Failed to query CUAS value:" << result;
  }
  return (cuas == 1);
}

}  // namespace

HMODULE WinUtil::LoadSystemLibrary(const wstring &base_filename) {
  wstring fullpath = SystemUtil::GetSystemDir();
  fullpath += L"\\";
  fullpath += base_filename;

  const HMODULE module = ::LoadLibraryExW(fullpath.c_str(),
                                          nullptr,
                                          LOAD_WITH_ALTERED_SEARCH_PATH);
  if (nullptr == module) {
    const int last_error = ::GetLastError();
    DLOG(WARNING) << "LoadLibraryEx failed."
                  << " fullpath = " << fullpath.c_str()
                  << " error = " << last_error;
  }
  return module;
}

HMODULE WinUtil::LoadMozcLibrary(const wstring &base_filename) {
  wstring fullpath;
  Util::UTF8ToWide(SystemUtil::GetServerDirectory().c_str(), &fullpath);
  fullpath += L"\\";
  fullpath += base_filename;

  const HMODULE module = ::LoadLibraryExW(fullpath.c_str(),
                                          nullptr,
                                          LOAD_WITH_ALTERED_SEARCH_PATH);
  if (nullptr == module) {
    const int last_error = ::GetLastError();
    DLOG(WARNING) << "LoadLibraryEx failed."
                  << " fullpath = " << fullpath.c_str()
                  << " error = " << last_error;
  }
  return module;
}

HMODULE WinUtil::GetSystemModuleHandle(const wstring &base_filename) {
  wstring fullpath = SystemUtil::GetSystemDir();
  fullpath += L"\\";
  fullpath += base_filename;

  HMODULE module = nullptr;
  if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
                         fullpath.c_str(), &module) == FALSE) {
    const int last_error = ::GetLastError();
    DLOG(WARNING) << "GetModuleHandleExW failed."
                  << " fullpath = " << fullpath.c_str()
                  << " error = " << last_error;
  }
  return module;
}

HMODULE WinUtil::GetSystemModuleHandleAndIncrementRefCount(
    const wstring &base_filename) {
  wstring fullpath = SystemUtil::GetSystemDir();
  fullpath += L"\\";
  fullpath += base_filename;

  HMODULE module = nullptr;
  if (GetModuleHandleExW(0, fullpath.c_str(), &module) == FALSE) {
    const int last_error = ::GetLastError();
    DLOG(WARNING) << "GetModuleHandleExW failed."
                  << " fullpath = " << fullpath.c_str()
                  << " error = " << last_error;
  }
  return module;
}

bool WinUtil::IsDLLSynchronizationHeld(bool *lock_status) {
  mozc::CallOnce(&g_aux_lib_initialized, &CallAuxUlibInitialize);

  if (lock_status == nullptr) {
    return false;
  }

  BOOL synchronization_held = FALSE;
  const BOOL result =
      ::AuxUlibIsDLLSynchronizationHeld(&synchronization_held);
  if (!result) {
    const int error = ::GetLastError();
    DLOG(ERROR) << "AuxUlibIsDLLSynchronizationHeld failed. error = "
                << error;
    return false;
  }
  *lock_status = (synchronization_held != FALSE);
  return true;
}

bool WinUtil::Logoff() {
  if (!AdjustPrivilegesForShutdown()) {
    return false;
  }
  return (::ExitWindowsEx(EWX_LOGOFF, SHTDN_REASON_MINOR_INSTALLATION) != 0);
}

bool WinUtil::Win32EqualString(const wstring &lhs, const wstring &rhs,
                               bool ignore_case, bool *are_equal) {
  // http://msdn.microsoft.com/en-us/library/dd317762.aspx
  typedef int (WINAPI *FPCompareStringOrdinal)(
      __in LPCWSTR lpString1,
      __in int     cchCount1,
      __in LPCWSTR lpString2,
      __in int     cchCount2,
      __in BOOL    bIgnoreCase);

  const HMODULE kernel = WinUtil::GetSystemModuleHandle(L"kernel32.dll");
  if (kernel == nullptr) {
    LOG(ERROR) << "GetSystemModuleHandle failed";
    return false;
  }

  const FPCompareStringOrdinal compare_string_ordinal =
      reinterpret_cast<FPCompareStringOrdinal>(
          ::GetProcAddress(kernel, "CompareStringOrdinal"));
  if (compare_string_ordinal == nullptr) {
    return false;
  }
  const int compare_result = compare_string_ordinal(
      lhs.c_str(), lhs.size(), rhs.c_str(), rhs.size(),
      (ignore_case ? TRUE : FALSE));

  if (are_equal != nullptr) {
    *are_equal = (compare_result == CSTR_EQUAL);
  }

  return true;
}

bool WinUtil::NativeEqualString(const wstring &lhs, const wstring &rhs,
                                bool ignore_case, bool *are_equal) {
  // http://msdn.microsoft.com/en-us/library/ff561854.aspx
  typedef BOOLEAN (NTAPI *FPRtlEqualUnicodeString)(
      __in PCUNICODE_STRING String1,
      __in PCUNICODE_STRING String2,
      __in BOOLEAN CaseInSensitive);

  const HMODULE ntdll = GetSystemModuleHandle(L"ntdll.dll");
  if (ntdll == nullptr) {
    LOG(ERROR) << "GetSystemModuleHandle failed";
    return false;
  }

  const FPRtlEqualUnicodeString rtl_equal_unicode_string =
      reinterpret_cast<FPRtlEqualUnicodeString>(
          ::GetProcAddress(ntdll, "RtlEqualUnicodeString"));
  if (rtl_equal_unicode_string == nullptr) {
    return false;
  }

  const UNICODE_STRING lhs_string = {
    lhs.size(),                     // Length
    lhs.size() + sizeof(wchar_t),   // MaximumLength
    const_cast<PWSTR>(lhs.c_str())  // Buffer
  };
  const UNICODE_STRING rhs_string = {
    rhs.size(),                     // Length
    rhs.size() + sizeof(wchar_t),   // MaximumLength
    const_cast<PWSTR>(rhs.c_str())  // Buffer
  };
  const BOOL compare_result = rtl_equal_unicode_string(
    &lhs_string, &rhs_string, (ignore_case ? TRUE : FALSE));

  if (are_equal != nullptr) {
    *are_equal = (compare_result != FALSE);
  }

  return true;
}

void WinUtil::CrtEqualString(const wstring &lhs, const wstring &rhs,
                             bool ignore_case, bool *are_equal) {
  if (are_equal == nullptr) {
    return;
  }

  if (!ignore_case) {
    DCHECK_NE(nullptr, are_equal);
    *are_equal = (rhs == lhs);
    return;
  }

  const _locale_t locale_id = _create_locale(LC_ALL, "English");
  const int compare_result = _wcsicmp_l(lhs.c_str(), rhs.c_str(), locale_id);
  _free_locale(locale_id);

  DCHECK_NE(nullptr, are_equal);
  *are_equal = (compare_result == 0);
}

bool WinUtil::SystemEqualString(
      const wstring &lhs, const wstring &rhs, bool ignore_case) {
  bool are_equal = false;

  // We assume a string instance never contains NUL character in principle.
  // So we will raise an error to notify the unexpected situation in debug
  // builds.  In production, however, we will admit such an instance and
  // silently trim it at the first NUL character.
  const wstring::size_type lhs_null_pos = lhs.find_first_of(L'\0');
  const wstring::size_type rhs_null_pos = rhs.find_first_of(L'\0');
  DCHECK_EQ(lhs.npos, lhs_null_pos)
      << "|lhs| should not contain NUL character.";
  DCHECK_EQ(rhs.npos, rhs_null_pos)
      << "|rhs| should not contain NUL character.";
  const wstring &lhs_null_trimmed = lhs.substr(0, lhs_null_pos);
  const wstring &rhs_null_trimmed = rhs.substr(0, rhs_null_pos);

  if (Win32EqualString(
          lhs_null_trimmed, rhs_null_trimmed, ignore_case, &are_equal)) {
    return are_equal;
  }

  if (NativeEqualString(
          lhs_null_trimmed, rhs_null_trimmed, ignore_case, &are_equal)) {
    return are_equal;
  }

  CrtEqualString(lhs_null_trimmed, rhs_null_trimmed, ignore_case, &are_equal);

  return are_equal;
}

bool WinUtil::IsServiceUser(HANDLE hToken, bool *is_service) {
  if (is_service == nullptr) {
    return false;
  }

  TOKEN_STATISTICS ts;
  DWORD dwSize = 0;
  // Use token logon LUID instead of user SID, for brevity and safety
  if (!::GetTokenInformation(hToken, TokenStatistics,
                             (LPVOID)&ts, sizeof(ts), &dwSize)) {
    return false;
  }

  // Compare LUID
  const LUID SystemLuid = SYSTEM_LUID;
  const LUID LocalServiceLuid = LOCALSERVICE_LUID;
  const LUID NetworkServiceLuid = NETWORKSERVICE_LUID;
  if (EqualLuid(SystemLuid, ts.AuthenticationId) ||
      EqualLuid(LocalServiceLuid, ts.AuthenticationId) ||
      EqualLuid(NetworkServiceLuid, ts.AuthenticationId)) {
    *is_service = true;
    return true;
  }

  // Not a service account
  *is_service = false;
  return true;
}

bool WinUtil::IsServiceProcess(bool *is_service) {
  if (is_service == nullptr) {
    return false;
  }

  if (SystemUtil::IsVistaOrLater()) {
    // Session 0 is dedicated to services
    DWORD dwSessionId = 0;
    if (!::ProcessIdToSessionId(::GetCurrentProcessId(), &dwSessionId) ||
        (dwSessionId == 0)) {
      *is_service = true;
      return true;
    }
  }

  // Get process token
  HANDLE hProcessToken = nullptr;
  if (!::OpenProcessToken(::GetCurrentProcess(),
                          TOKEN_QUERY | TOKEN_QUERY_SOURCE,
                          &hProcessToken)) {
    return false;
  }

  ScopedHandle process_token(hProcessToken);

  // Process token is one for a service account.
  if (!IsServiceUser(process_token.get(), is_service)) {
    return false;
  }

  return true;
}

bool WinUtil::IsServiceThread(bool *is_service) {
  if (is_service == nullptr) {
    return false;
  }

  // Get thread token (if any)
  HANDLE hThreadToken = nullptr;
  if (!::OpenThreadToken(::GetCurrentThread(),
                        TOKEN_QUERY, TRUE, &hThreadToken) &&
      ERROR_NO_TOKEN != ::GetLastError()) {
    return false;
  }

  if (hThreadToken == nullptr) {
    // No thread token.
    *is_service = false;
    return true;
  }

  ScopedHandle thread_token(hThreadToken);

  // Check if the thread token (if any) is one for a service account.
  if (!IsServiceUser(thread_token.get(), is_service)) {
    return false;
  }
  return true;
}

bool WinUtil::IsServiceAccount(bool *is_service) {
  if (is_service == nullptr) {
    return false;
  }

  bool is_service_process = false;
  if (!WinUtil::IsServiceProcess(&is_service_process)) {
    DLOG(ERROR) << "WinUtil::IsServiceProcess failed.";
    return false;
  }

  if (is_service_process) {
    *is_service = true;
    return true;
  }

  // Process token is not one for service.
  // Check thread token just in case.
  bool is_service_thread = false;
  if (!WinUtil::IsServiceThread(&is_service_thread)) {
    DLOG(ERROR) << "WinUtil::IsServiceThread failed.";
    return false;
  }

  if (is_service_thread) {
    *is_service = true;
    return true;
  }

  *is_service = false;
  return true;
}

bool WinUtil::IsProcessImmersive(HANDLE process_handle,
                                 bool *is_immersive) {
  if (is_immersive == nullptr) {
    return false;
  }
  *is_immersive = false;
  // ImmersiveMode is supported only in Windows8 and later.
  if (!SystemUtil::IsWindows8OrLater()) {
    return true;
  }

  const HMODULE module = WinUtil::GetSystemModuleHandle(L"user32.dll");
  if (module == nullptr) {
    return false;
  }

  typedef BOOL (WINAPI* IsImmersiveProcessFunc)(HANDLE process);
  IsImmersiveProcessFunc is_immersive_process =
      reinterpret_cast<IsImmersiveProcessFunc>(
          ::GetProcAddress(module, "IsImmersiveProcess"));
  if (is_immersive_process == nullptr) {
    return false;
  }

  *is_immersive = !!is_immersive_process(process_handle);
  return true;
}

bool WinUtil::IsProcessRestricted(HANDLE process_handle, bool *is_restricted) {
  if (is_restricted == nullptr) {
    return false;
  }
  *is_restricted = false;

  HANDLE token = nullptr;
  if (!::OpenProcessToken(process_handle, TOKEN_QUERY, &token)) {
    return false;
  }

  ScopedHandle process_token(token);
  ::SetLastError(NOERROR);
  if (::IsTokenRestricted(process_token.get()) == FALSE) {
    const DWORD error = ::GetLastError();
    if (error != NOERROR) {
      return false;
    }
  } else {
    *is_restricted = true;
  }
  return true;
}

bool WinUtil::IsProcessInAppContainer(HANDLE process_handle,
                                      bool *in_appcontainer) {
  if (in_appcontainer == nullptr) {
    return false;
  }
  *in_appcontainer = false;

  // AppContainer is supported only in Windows8 and later.
  if (!SystemUtil::IsWindows8OrLater()) {
    return true;
  }

  HANDLE token = nullptr;
  if (!::OpenProcessToken(process_handle, TOKEN_QUERY | TOKEN_QUERY_SOURCE,
                          &token)) {
    return false;
  }

  // TokenIsAppContainer is defined only in Windows SDK 8.0 and later.
  ScopedHandle process_token(token);
  const TOKEN_INFORMATION_CLASS kTokenIsAppContainer =
      static_cast<TOKEN_INFORMATION_CLASS>(29);  // TokenIsAppContainer
#if defined(_WIN32_WINNT_WIN8)
  static_assert(kTokenIsAppContainer == TokenIsAppContainer,
                "Checking |kTokenIsAppContainer| has correct value.");
#endif  // _WIN32_WINNT_WIN8
  DWORD returned_size = 0;
  DWORD retval = 0;
  if (!GetTokenInformation(process_token.get(), kTokenIsAppContainer,
                           &retval, sizeof(retval), &returned_size)) {
    return false;
  }
  if (returned_size != sizeof(retval)) {
    return false;
  }

  *in_appcontainer = (retval != 0);
  return true;
}

bool WinUtil::IsCuasEnabled() {
  if (SystemUtil::IsVistaOrLater()) {
    // CUAS is always enabled on Vista or later.
    return true;
  }

  if (SystemUtil::IsWindowsX64()) {
    // see both 64 bit and 32 bit registry keys
    return IsCuasEnabledInternal(KEY_WOW64_64KEY) &&
           IsCuasEnabledInternal(KEY_WOW64_32KEY);
  } else {
    return IsCuasEnabledInternal(0);
  }
}

bool WinUtil::GetFileSystemInfoFromPath(
    const wstring &path, BY_HANDLE_FILE_INFORMATION *info) {
  // no read access is required.
  ScopedHandle handle(::CreateFileW(
      path.c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
      nullptr, OPEN_EXISTING,
      FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_NORMAL, nullptr));

  // Caveats: handle.get() returns nullptr when it is initialized with
  //     INVALID_HANDLE_VALUE.
  if (handle.get() == nullptr) {
    return false;
  }
  return !!::GetFileInformationByHandle(handle.get(), info);
}

bool WinUtil::AreEqualFileSystemObject(const wstring &left_path,
                                       const wstring &right_path) {
  BY_HANDLE_FILE_INFORMATION left_info = {};
  if (!GetFileSystemInfoFromPath(left_path, &left_info)) {
    return false;
  }
  BY_HANDLE_FILE_INFORMATION right_info = {};
  if (!GetFileSystemInfoFromPath(right_path, &right_info)) {
    return false;
  }
  return (left_info.nFileIndexLow == right_info.nFileIndexLow) &&
         (left_info.nFileIndexHigh == right_info.nFileIndexHigh);
}

bool WinUtil::GetNtPath(const wstring &dos_path, wstring *nt_path) {
  if (nt_path == nullptr) {
    return false;
  }

  nt_path->clear();

  typedef DWORD (WINAPI *GetFinalPathNameByHandleWFunc)(
      __in HANDLE file,
      __out wchar_t *buffer,
      __in DWORD buffer_num_chars,
      __in DWORD flags);
  GetFinalPathNameByHandleWFunc get_final_path_name_by_handle =
      reinterpret_cast<GetFinalPathNameByHandleWFunc>(
          ::GetProcAddress(WinUtil::GetSystemModuleHandle(L"kernel32.dll"),
                           "GetFinalPathNameByHandleW"));
  if (get_final_path_name_by_handle == nullptr) {
    return false;
  }

  ScopedHandle file_handle(::CreateFileW(
      dos_path.c_str(), 0,
      FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
      nullptr, OPEN_EXISTING,
      FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_NORMAL, nullptr));
  if (file_handle.get() == nullptr) {
    // Caveats: |file_handle.get()| becomes nullptr instead of
    // INVALID_HANDLE_VALUE when failure.
    return false;
  }

  const size_t kMaxPath = 4096;
  unique_ptr<wchar_t[]> ntpath_buffer(
      new wchar_t[kMaxPath]);
  const DWORD copied_len_without_null = get_final_path_name_by_handle(
      file_handle.get(),
      ntpath_buffer.get(),
      kMaxPath,
      FILE_NAME_NORMALIZED | VOLUME_NAME_NT);
  if (copied_len_without_null == 0 ||
      copied_len_without_null > kMaxPath) {
    const DWORD error = ::GetLastError();
    VLOG(1) << "GetFinalPathNameByHandleW() failed: " << error;
    return false;
  }

  nt_path->assign(ntpath_buffer.get(), copied_len_without_null);
  return true;
}

bool WinUtil::GetProcessInitialNtPath(DWORD pid, wstring *nt_path) {
  if (nt_path == nullptr) {
    return false;
  }
  nt_path->clear();

  const DWORD required_access =
      SystemUtil::IsVistaOrLater() ? PROCESS_QUERY_LIMITED_INFORMATION
                                   : PROCESS_QUERY_INFORMATION;
  ScopedHandle process_handle(::OpenProcess(required_access, FALSE, pid));

  if (process_handle.get() == nullptr) {
    VLOG(1) << "OpenProcess() failed: " << ::GetLastError();
    return false;
  }

  const size_t kMaxPath = 4096;
  unique_ptr<wchar_t[]> ntpath_buffer(new wchar_t[kMaxPath]);
  const DWORD copied_len_without_null =
      ::GetProcessImageFileNameW(process_handle.get(),
                                 ntpath_buffer.get(),
                                 kMaxPath);
  if (copied_len_without_null == 0 || copied_len_without_null > kMaxPath) {
    const DWORD error = ::GetLastError();
    VLOG(1) << "GetProcessImageFileNameW() failed: " << error;
    return false;
  }

  nt_path->assign(ntpath_buffer.get(), copied_len_without_null);
  return true;
}

// SPI_GETTHREADLOCALINPUTSETTINGS is available on Windows 8 SDK and later.
#ifndef SPI_GETTHREADLOCALINPUTSETTINGS
#define SPI_GETTHREADLOCALINPUTSETTINGS 0x104E
#endif  // SPI_GETTHREADLOCALINPUTSETTINGS

bool WinUtil::IsPerUserInputSettingsEnabled() {
  if (!SystemUtil::IsWindows8OrLater()) {
    // Windows 7 and below does not support per-user input mode.
    return false;
  }
  BOOL is_thread_local = FALSE;
  if (::SystemParametersInfo(SPI_GETTHREADLOCALINPUTSETTINGS,
                             0,
                             reinterpret_cast<void *>(&is_thread_local),
                             0) == FALSE) {
    return false;
  }
  return !is_thread_local;
}

ScopedCOMInitializer::ScopedCOMInitializer()
    : hr_(::CoInitialize(nullptr)) {
}

ScopedCOMInitializer::~ScopedCOMInitializer() {
  if (SUCCEEDED(hr_)) {
    ::CoUninitialize();
  }
}

}  // namespace mozc

#endif  // OS_WIN
