/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "modules/desktop_capture/win/desktop.h"

#include <vector>

#include "rtc_base/logging.h"

namespace webrtc {

Desktop::Desktop(HDESK desktop, bool own) : desktop_(desktop), own_(own) {
}

Desktop::~Desktop() {
  if (own_ && desktop_ != NULL) {
    if (!::CloseDesktop(desktop_)) {
      RTC_LOG(LS_ERROR) << "Failed to close the owned desktop handle: "
                        << GetLastError();
    }
  }
}

bool Desktop::GetName(std::wstring* desktop_name_out) const {
  if (desktop_ == NULL)
    return false;

  DWORD length = 0;
  int rv = GetUserObjectInformationW(desktop_, UOI_NAME, NULL, 0, &length);
  if (rv || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
    abort();

  length /= sizeof(WCHAR);
  std::vector<WCHAR> buffer(length);
  if (!GetUserObjectInformationW(desktop_, UOI_NAME, &buffer[0],
                                 length * sizeof(WCHAR), &length)) {
    RTC_LOG(LS_ERROR) << "Failed to query the desktop name: " << GetLastError();
    return false;
  }

  desktop_name_out->assign(&buffer[0], length / sizeof(WCHAR));
  return true;
}

bool Desktop::IsSame(const Desktop& other) const {
  std::wstring name;
  if (!GetName(&name))
    return false;

  std::wstring other_name;
  if (!other.GetName(&other_name))
    return false;

  return name == other_name;
}

bool Desktop::SetThreadDesktop() const {
  if (!::SetThreadDesktop(desktop_)) {
    RTC_LOG(LS_ERROR) << "Failed to assign the desktop to the current thread: "
                      << GetLastError();
    return false;
  }

  return true;
}

Desktop* Desktop::GetDesktop(const WCHAR* desktop_name) {
  ACCESS_MASK desired_access =
      DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_ENUMERATE |
      DESKTOP_HOOKCONTROL | DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
      DESKTOP_SWITCHDESKTOP | GENERIC_WRITE;
  HDESK desktop = OpenDesktop(desktop_name, 0, FALSE, desired_access);
  if (desktop == NULL) {
    RTC_LOG(LS_ERROR) << "Failed to open the desktop '" << desktop_name
                      << "': " << GetLastError();
    return NULL;
  }

  return new Desktop(desktop, true);
}

Desktop* Desktop::GetInputDesktop() {
  HDESK desktop = OpenInputDesktop(
      0, FALSE, GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE);
  if (desktop == NULL)
    return NULL;

  return new Desktop(desktop, true);
}

Desktop* Desktop::GetThreadDesktop() {
  HDESK desktop = ::GetThreadDesktop(GetCurrentThreadId());
  if (desktop == NULL) {
    RTC_LOG(LS_ERROR)
        << "Failed to retrieve the handle of the desktop assigned to "
           "the current thread: "
        << GetLastError();
    return NULL;
  }

  return new Desktop(desktop, false);
}

}  // namespace webrtc
