// 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.

#ifdef OS_WIN

#include "server/cache_service_manager.h"

#include <windows.h>
#include <strsafe.h>
#include <wincrypt.h>

#include <memory>
#include <string>

#include "base/const.h"
#include "base/file_util.h"
#include "base/scoped_handle.h"
#include "base/system_util.h"
#include "base/util.h"
#include "server/mozc_cache_service_resource.h"
#include "server/win32_service_state.pb.h"

using std::unique_ptr;

namespace mozc {
namespace {

const uint64 kMinimumRequiredMemorySizeForInstall = 384 * 1024 * 1024;

class ScopedSCHandle {
 public:
  ScopedSCHandle()
      : handle_(NULL) {}
  explicit ScopedSCHandle(SC_HANDLE handle)
      : handle_(handle) {}

  ~ScopedSCHandle() {
    if (NULL != handle_) {
      ::CloseServiceHandle(handle_);
    }
  }

  SC_HANDLE get() const { return handle_; }

  void swap(ScopedSCHandle & other) {
    SC_HANDLE tmp = handle_;
    handle_ = other.handle_;
    other.handle_ = tmp;
  }

 private:
  SC_HANDLE handle_;
};

// Returns a redirector for the specified string resource for Vista or later.
// Returns an empty string if any error occurs.
// See http://msdn.microsoft.com/en-us/library/dd374120.aspx for details.
wstring GetRegistryStringRedirector(int resource_id) {
  const wchar_t kRegistryStringRedirectionPattern[] = L"@%s,-%d";
  const wstring &service_path = CacheServiceManager::GetUnquotedServicePath();
  wchar_t buffer[MAX_PATH] = { L'\0' };

  HRESULT hr = ::StringCchPrintf(
      buffer, arraysize(buffer), kRegistryStringRedirectionPattern,
      CacheServiceManager::GetUnquotedServicePath().c_str(), resource_id);
  if (hr != S_OK) {
    return L"";
  }
  const wstring redirector(buffer);
  // If this program is running on Windows Vista or later,
  // just returns the redirector.
  return redirector;
}

wstring GetDisplayName() {
  return GetRegistryStringRedirector(IDS_DISPLAYNAME);
}

wstring GetDescription() {
  return GetRegistryStringRedirector(IDS_DESCRIPTION);
}

// This function serializes a given message (any type of protobuf message)
// as a wstring encoded by base64.
// Returns true if succeeds.
bool SerializeToBase64WString(const ::google::protobuf::Message &message,
                              wstring *dest) {
  if (dest == NULL) {
    return false;
  }

  const int serialized_len = message.ByteSize();
  unique_ptr<BYTE[]> serialized(new BYTE[serialized_len]);
  if (!message.SerializeToArray(serialized.get(), serialized_len)) {
    LOG(ERROR) << "SerializeAsArray failed";
    return false;
  }

  DWORD base64_string_len = 0;
  BOOL result = ::CryptBinaryToString(serialized.get(), serialized_len,
                                      CRYPT_STRING_BASE64, NULL,
                                      &base64_string_len);
  if (result == FALSE) {
    return false;
  }
  unique_ptr<wchar_t[]> base64_string(new wchar_t[base64_string_len]);
  result = ::CryptBinaryToString(serialized.get(), serialized_len,
                                 CRYPT_STRING_BASE64, base64_string.get(),
                                 &base64_string_len);
  if (result == FALSE) {
    return false;
  }
  dest->assign(base64_string.get(), base64_string_len);
  return true;
}

// This function deserializes a message (any type of protobuf message)
// from the given wstring.  This wstring should be generated by
// SerializeToBase64WString.
// Returns true if succeeds
bool DeserializeFromBase64WString(const wstring &src,
                                  ::google::protobuf::Message *message) {
  if (message == NULL) {
    return false;
  }

  DWORD buffer_len = 0;
  BOOL result = ::CryptStringToBinary(src.c_str(),
                                      src.size(),
                                      CRYPT_STRING_BASE64,
                                      NULL,
                                      &buffer_len,
                                      NULL,
                                      NULL);
  if (result == FALSE) {
    return false;
  }
  unique_ptr<BYTE[]> buffer(new BYTE[buffer_len]);
  result = ::CryptStringToBinary(src.c_str(),
                                 src.size(),
                                 CRYPT_STRING_BASE64,
                                 buffer.get(),
                                 &buffer_len,
                                 NULL,
                                 NULL);
  if (result == FALSE) {
    return false;
  }
  if (!message->ParseFromArray(buffer.get(), buffer_len)) {
    LOG(ERROR) << "ParseFromArray failed";
    return false;
  }
  return true;
}

// A helper function to retrieve a service handle of the cache service
// with specified access rights.
// Returns true if one of the following conditions is satisfied.
//  - A valid service handle is retrieved.  In this case, |handle| owns the
//    retrieved handle.
//  - It turns out w/o any error that the cache service is not installed.
//    In this case, |handle| owns a NULL handle.
// Otherwise, returns false.
bool GetCacheService(DWORD service_controler_rights, DWORD service_rights,
                     ScopedSCHandle *handle) {
  if (NULL == handle) {
    return false;
  }

  ScopedSCHandle sc_handle(::OpenSCManager(NULL, NULL,
                                           service_controler_rights));
  if (NULL == sc_handle.get()) {
    LOG(ERROR) << "OpenSCManager failed: " << ::GetLastError();
    return false;
  }

  ScopedSCHandle service_handle(::OpenService(
      sc_handle.get(), CacheServiceManager::GetServiceName(), service_rights));
  const int error = ::GetLastError();

  if (NULL == service_handle.get() && ERROR_SERVICE_DOES_NOT_EXIST != error) {
    LOG(ERROR) << "OpenService failed: " << error;
    return false;
  }

  // |service_handle| is null if and only if the cache service is not
  // installed.
  service_handle.swap(*handle);
  return true;
}

bool IsServiceRunning(const ScopedSCHandle &service_handle) {
  if (NULL == service_handle.get()) {
    return false;
  }

  SERVICE_STATUS service_status = {};
  if (!::QueryServiceStatus(service_handle.get(), &service_status)) {
    LOG(ERROR) << "QueryServiceStatus failed: " << ::GetLastError();
    return false;
  }

  return service_status.dwCurrentState == SERVICE_RUNNING;
}

bool StartServiceInternal(const ScopedSCHandle &service_handle,
                          const vector<wstring> &arguments) {
  if (arguments.size() <= 0) {
    if (!::StartService(service_handle.get(), 0, NULL)) {
      LOG(ERROR) << "StartService failed: " << ::GetLastError();
      return false;
    }
    return true;
  }

  unique_ptr<const wchar_t*[]> args(new const wchar_t*[arguments.size()]);
  for (size_t i = 0; i < arguments.size(); ++i) {
    args[i] = arguments[i].c_str();
  }
  if (!::StartService(service_handle.get(), arguments.size(), args.get())) {
    LOG(ERROR) << "StartService failed: " << ::GetLastError();
    return false;
  }

  return true;
}

bool StopService(const ScopedSCHandle &service_handle) {
  SERVICE_STATUS status;
  if (!::ControlService(service_handle.get(), SERVICE_CONTROL_STOP, &status)) {
    LOG(ERROR) << "ControlService failed: " << ::GetLastError();
    return false;
  }
  return true;
}

bool SetServiceDescription(const ScopedSCHandle &service_handle,
                           const wstring &description) {
  // +1 for '\0'
  const size_t buffer_length = description.size() + 1;
  unique_ptr<wchar_t[]> buffer(new wchar_t[buffer_length]);
  description._Copy_s(buffer.get(), buffer_length, description.size());
  buffer[buffer_length - 1] = L'\0';

  SERVICE_DESCRIPTION desc = {};
  desc.lpDescription = buffer.get();
  if (!::ChangeServiceConfig2(service_handle.get(),
                              SERVICE_CONFIG_DESCRIPTION, &desc)) {
    LOG(ERROR) << "ChangeServiceConfig2 failed: " << ::GetLastError();
    return false;
  }

  return true;
}

// Set *nice-to-have* features for the cache service.
// We do not care about any failure because it is not critical for the
// functionality of the cache service itself.
void SetAdvancedConfig(const ScopedSCHandle &service_handle) {
  // Windows Vista or later has some nice features as described in the
  // following documents.
  // http://msdn.microsoft.com/en-us/magazine/cc164252.aspx

  // Enable "Delayed Auto-start".
  {
    SERVICE_DELAYED_AUTO_START_INFO info = {};
    info.fDelayedAutostart = TRUE;

    if (!::ChangeServiceConfig2(service_handle.get(),
                                SERVICE_CONFIG_DELAYED_AUTO_START_INFO,
                                &info)) {
      LOG(ERROR) << "ChangeServiceConfig2 failed: " << ::GetLastError();
    }
  }

  // http://blogs.technet.com/richard_macdonald/archive/2007/06/27/1375523.aspx
  // See also http://b/2470180

  // Only SE_INC_BASE_PRIORITY_NAME and SE_CHANGE_NOTIFY are needed.
  // According to MSDN Library, we need not explicitly specify the later.
  // See http://msdn.microsoft.com/en-us/library/ms685976.aspx for details.
  {
    SERVICE_REQUIRED_PRIVILEGES_INFO privileges_info = {};
    privileges_info.pmszRequiredPrivileges = SE_INC_BASE_PRIORITY_NAME
                                             TEXT("\0");
    if (!::ChangeServiceConfig2(service_handle.get(),
                                SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO,
                                &privileges_info)) {
      LOG(ERROR) << "ChangeServiceConfig2 failed: " << ::GetLastError();
    }
  }

  // Remove write privileges from the cache service.
  // See http://msdn.microsoft.com/en-us/library/ms685987.aspx for details.
  // This may restrict glog functions such as LOG(ERROR).
  // TODO(yukawa): Output logging messages as debug strings, or output them
  // to the Win32 event log.
  {
    SERVICE_SID_INFO sid_info = {};
    sid_info.dwServiceSidType = SERVICE_SID_TYPE_RESTRICTED;
    if (!::ChangeServiceConfig2(service_handle.get(),
                                SERVICE_CONFIG_SERVICE_SID_INFO,
                                &sid_info)) {
      LOG(ERROR) << "ChangeServiceConfig2 failed: " << ::GetLastError();
    }
  }
}

// This function updates the following settings of the cache service as
// specified.
//  - Display name
//  - Desctiption
//  - Load type (regardless of the amount of the system memory)
// This function also starts or stops the cache service.
// Win32ServiceState::IsInstalled() will be ignored.  You cannot use this
// function to install nor uninstall the cache service.
bool RestoreStateInternal(const cache_service::Win32ServiceState &state) {
  ScopedSCHandle service_handle;
  const DWORD kSCRights = SC_MANAGER_CONNECT;
  const DWORD kServiceRights =
      GENERIC_READ | GENERIC_WRITE | SERVICE_START | SERVICE_STOP;
  if (!GetCacheService(kSCRights, kServiceRights, &service_handle)
      || (NULL == service_handle.get())) {
    return false;
  }

  if (!::ChangeServiceConfig(service_handle.get(), SERVICE_NO_CHANGE,
                             static_cast<DWORD>(state.load_type()),
                             SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL,
                             NULL, GetDisplayName().c_str())) {
    LOG(ERROR) << "ChangeServiceConfig failed: " << ::GetLastError();
    return false;
  }

  if (!SetServiceDescription(service_handle, GetDescription())) {
    return false;
  }

  // We ignore any failure of advanced configurations because they are
  // *nice-to-have* features.
  SetAdvancedConfig(service_handle);

  const bool now_running = IsServiceRunning(service_handle);

  // If the service was runnning and is not running now, start it unless the
  // load type is not DISABLED.
  if (state.running() && !now_running &&
      (state.load_type() != cache_service::Win32ServiceState::DISABLED)) {
    vector<wstring> arguments(state.arguments_size());
    arguments.resize(state.arguments_size());
    for (size_t i = 0; i < state.arguments_size(); ++i) {
      if (Util::UTF8ToWide(state.arguments(i).c_str(), &arguments[i]) <= 0) {
        return false;
      }
    }
    return StartServiceInternal(service_handle, arguments);
  // If the service is now runnning and was not running, stop it.
  } else if (!state.running() && now_running) {
    return StopService(service_handle);
  // Nothing to do.
  } else {
    return true;
  }

  assert(0);
  return false;
}

// Returns true if a byte array which contains valid QUERY_SERVICE_CONFIG
// is successfully retrieved.  Some members of QUERY_SERVICE_CONFIG points
// memory addresses inside the retrieved byte array.
bool GetServiceConfig(const ScopedSCHandle &service_handle,
                      unique_ptr<char[]> *result) {
  if (NULL == result) {
    return false;
  }

  if (NULL == service_handle.get()) {
    return false;
  }

  DWORD size = 0;
  if (!::QueryServiceConfig(service_handle.get(), NULL, 0, &size) &&
      ::GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
    LOG(ERROR) << "QueryServiceConfig failed: " << ::GetLastError();
    return false;
  }

  if (size == 0) {
    LOG(ERROR) << "buffer size is 0";
    return false;
  }

  unique_ptr<char[]> buf(new char[size]);
  LPQUERY_SERVICE_CONFIG service_config =
      reinterpret_cast<LPQUERY_SERVICE_CONFIG>(buf.get());

  if (!::QueryServiceConfig(service_handle.get(),
                            service_config, size, &size)) {
    LOG(ERROR) << "QueryServiceConfig failed: " << ::GetLastError();
    return false;
  }

  buf.swap(*result);
  return true;
}
}  // anonymous namespace

bool CacheServiceManager::IsInstalled() {
  ScopedSCHandle service_handle;
  if (!GetCacheService(SC_MANAGER_CONNECT | GENERIC_READ, SERVICE_QUERY_STATUS,
                       &service_handle)
      || (NULL == service_handle.get())) {
    return false;
  }
  return true;
}

bool CacheServiceManager::IsRunning() {
  ScopedSCHandle service_handle;
  if (!GetCacheService(SC_MANAGER_CONNECT | GENERIC_READ, SERVICE_QUERY_STATUS,
                       &service_handle)
      || (NULL == service_handle.get())) {
    return false;
  }
  return IsServiceRunning(service_handle);
}

bool CacheServiceManager::IsEnabled() {
  ScopedSCHandle service_handle;
  if (!GetCacheService(SC_MANAGER_CONNECT | GENERIC_READ, SERVICE_QUERY_CONFIG,
                       &service_handle)
      || (NULL == service_handle.get())) {
    return false;
  }

  // This byte array will contain both QUERY_SERVICE_CONFIG and some
  // string buffers which are reffered by corresponding members of
  // QUERY_SERVICE_CONFIG.  We have to keep the array until we complete
  // all tasks which use the contents of QUERY_SERVICE_CONFIG.
  unique_ptr<char[]> buffer;
  if (!GetServiceConfig(service_handle, &buffer)) {
    return false;
  }
  const LPQUERY_SERVICE_CONFIG service_config =
      reinterpret_cast<const LPQUERY_SERVICE_CONFIG>(buffer.get());
  return service_config->dwStartType == SERVICE_AUTO_START;
}

const wchar_t *CacheServiceManager::GetServiceName() {
  return kMozcCacheServiceName;
}

wstring CacheServiceManager::GetUnquotedServicePath() {
  const string lock_service_path =
      FileUtil::JoinPath(SystemUtil::GetServerDirectory(),
                         kMozcCacheServiceExeName);
  wstring wlock_service_path;
  if (Util::UTF8ToWide(lock_service_path.c_str(), &wlock_service_path) <= 0) {
    return L"";
  }
  return wlock_service_path;
}

wstring CacheServiceManager::GetQuotedServicePath() {
  return L"\"" + GetUnquotedServicePath() + L"\"";
}

bool CacheServiceManager::EnableAutostart() {
  if (!IsInstalled()) {
    return false;
  }

  const bool enough = CacheServiceManager::HasEnoughMemory();

  // Fortunately, the expected service settings can be descried by
  // Win32ServiceState so we can use RestoreStateInternal to change the
  // settings and start the service (if needed).
  // If the system does not have enough memory, disable the service
  // to reduce the performance impact on the boot-time.
  cache_service::Win32ServiceState state;
  state.set_version(1);
  state.set_installed(true);
  state.set_load_type(enough ? cache_service::Win32ServiceState::AUTO_START
                             : cache_service::Win32ServiceState::DISABLED);
  state.set_running(enough);
  const bool result = RestoreStateInternal(state);
  return enough ? result : false;
}

bool CacheServiceManager::DisableService() {
  if (!IsInstalled()) {
    return false;
  }

  // Fortunately, the expected service settings can be descried by
  // Win32ServiceState so we can use RestoreStateInternal to change the
  // settings and stop the service (if needed).
  cache_service::Win32ServiceState state;
  state.set_version(1);
  state.set_installed(true);
  state.set_load_type(cache_service::Win32ServiceState::DISABLED);
  state.set_running(false);
  return RestoreStateInternal(state);
}

bool CacheServiceManager::RestartService() {
  ScopedSCHandle service_handle;
  if (!GetCacheService(SC_MANAGER_CONNECT,
                       SERVICE_START | SERVICE_STOP | SERVICE_QUERY_STATUS,
                       &service_handle)
      || (NULL == service_handle.get())) {
    return false;
  }

  SERVICE_STATUS status;
  if (!::ControlService(service_handle.get(), SERVICE_CONTROL_STOP, &status)) {
    LOG(ERROR) << "ControlService failed: " << ::GetLastError();
  }

  const int kNumTrial = 10;
  for (int i = 0; i < kNumTrial; ++i) {
    SERVICE_STATUS service_status = {};
    if (!::QueryServiceStatus(service_handle.get(), &service_status)) {
      LOG(ERROR) << "QueryServiceStatus failed: " << ::GetLastError();
      return false;
    }
    if (service_status.dwCurrentState != SERVICE_RUNNING) {
      break;
    }
    ::Sleep(200);  // wait for 0.2sec
  }

  return StartServiceInternal(service_handle, vector<wstring>());
}

bool CacheServiceManager::HasEnoughMemory() {
  return SystemUtil::GetTotalPhysicalMemory() >=
      kMinimumRequiredMemorySizeForInstall;
}

bool CacheServiceManager::BackupStateAsString(wstring *result) {
  if (result == NULL) {
    return false;
  }
  result->clear();

  cache_service::Win32ServiceState state;
  state.set_version(1);

  ScopedSCHandle service_handle;
  if (!GetCacheService(SC_MANAGER_CONNECT | GENERIC_READ,
                       SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG,
                       &service_handle)) {
    // If it turns out w/o any error that the cache service is not installed,
    // |GetCacheService| returns true.  We can conclude any other error
    // occurred.
    return false;
  }

  // If the cachse service is actually installed, |service_handle| should have
  // non-null value.
  state.set_installed(NULL != service_handle.get());
  if (!state.installed()) {
    // The cache service is not installed.
    // Use default settings with setting |installed| flag to false.
    state.set_load_type(cache_service::Win32ServiceState::AUTO_START);
    state.set_running(true);
  } else {
    // This byte array will contain both QUERY_SERVICE_CONFIG and some
    // string buffers which are reffered by corresponding members of
    // QUERY_SERVICE_CONFIG.  We have to keep the array until we complete
    // all tasks which use the contents of QUERY_SERVICE_CONFIG.
    unique_ptr<char[]> buffer;
    if (!GetServiceConfig(service_handle, &buffer)) {
      return false;
    }
    const LPQUERY_SERVICE_CONFIG service_config =
        reinterpret_cast<const LPQUERY_SERVICE_CONFIG>(buffer.get());
    // retrieves the server load type.
    state.set_load_type(
        static_cast<cache_service::Win32ServiceState::LoadType>(
            service_config->dwStartType));
    // retrieves the server running status.
    state.set_running(IsServiceRunning(service_handle));
  }

  if (!SerializeToBase64WString(state, result)) {
    return false;
  }

  return true;
}

bool CacheServiceManager::RestoreStateFromString(const wstring &serialized) {
  cache_service::Win32ServiceState state;
  if (!DeserializeFromBase64WString(serialized, &state)) {
    return false;
  }

  return RestoreStateInternal(state);
}

bool CacheServiceManager::EnsureServiceStopped() {
  ScopedSCHandle service_handle;
  const DWORD kSCRights = SC_MANAGER_CONNECT;
  const DWORD kServiceRights = GENERIC_READ | SERVICE_STOP;
  if (!GetCacheService(kSCRights, kServiceRights, &service_handle)) {
    return false;
  }

  if (NULL == service_handle.get()) {
    return true;
  }

  if (!IsServiceRunning(service_handle)) {
    return true;
  }

  if (!StopService(service_handle)) {
    return false;
  }

  return IsServiceRunning(service_handle);
}

}  // namespace mozc
#endif  // OS_WIN
