13d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org/*
23d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
33d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org *
43d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org *  Use of this source code is governed by a BSD-style license
53d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org *  that can be found in the LICENSE file in the root of the source
63d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org *  tree. An additional intellectual property rights grant can be found
73d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org *  in the file PATENTS.  All contributing project authors may
83d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org *  be found in the AUTHORS file in the root of the source tree.
93d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org */
103d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org
113d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org#include "webrtc/modules/desktop_capture/win/desktop.h"
123d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org
133d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org#include <vector>
143d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org
1598f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/logging.h"
163d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org
173d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.orgnamespace webrtc {
183d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org
193d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.orgDesktop::Desktop(HDESK desktop, bool own) : desktop_(desktop), own_(own) {
203d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org}
213d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org
223d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.orgDesktop::~Desktop() {
233d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  if (own_ && desktop_ != NULL) {
243d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org    if (!::CloseDesktop(desktop_)) {
253d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org      LOG(LS_ERROR) << "Failed to close the owned desktop handle: "
263d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org                    << GetLastError();
273d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org    }
283d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  }
293d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org}
303d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org
313d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.orgbool Desktop::GetName(std::wstring* desktop_name_out) const {
323d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  if (desktop_ == NULL)
333d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org    return false;
343d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org
353d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  DWORD length = 0;
363d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  int rv = GetUserObjectInformationW(desktop_, UOI_NAME, NULL, 0, &length);
373d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  if (rv || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
383d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org    abort();
393d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org
403d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  length /= sizeof(WCHAR);
413d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  std::vector<WCHAR> buffer(length);
423d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  if (!GetUserObjectInformationW(desktop_, UOI_NAME, &buffer[0],
433d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org                                 length * sizeof(WCHAR), &length)) {
443d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org    LOG(LS_ERROR) << "Failed to query the desktop name: " << GetLastError();
453d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org    return false;
463d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  }
473d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org
483d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  desktop_name_out->assign(&buffer[0], length / sizeof(WCHAR));
493d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  return true;
503d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org}
513d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org
523d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.orgbool Desktop::IsSame(const Desktop& other) const {
533d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  std::wstring name;
543d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  if (!GetName(&name))
553d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org    return false;
563d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org
573d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  std::wstring other_name;
583d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  if (!other.GetName(&other_name))
593d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org    return false;
603d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org
613d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  return name == other_name;
623d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org}
633d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org
643d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.orgbool Desktop::SetThreadDesktop() const {
653d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  if (!::SetThreadDesktop(desktop_)) {
663d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org    LOG(LS_ERROR) << "Failed to assign the desktop to the current thread: "
673d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org                  << GetLastError();
683d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org    return false;
693d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  }
703d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org
713d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  return true;
723d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org}
733d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org
743d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.orgDesktop* Desktop::GetDesktop(const WCHAR* desktop_name) {
753d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  ACCESS_MASK desired_access =
763d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org      DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_ENUMERATE |
773d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org      DESKTOP_HOOKCONTROL | DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
783d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org      DESKTOP_SWITCHDESKTOP | GENERIC_WRITE;
793d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  HDESK desktop = OpenDesktop(desktop_name, 0, FALSE, desired_access);
803d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  if (desktop == NULL) {
813d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org    LOG(LS_ERROR) << "Failed to open the desktop '" << desktop_name << "': "
823d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org                  << GetLastError();
833d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org    return NULL;
843d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  }
853d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org
863d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  return new Desktop(desktop, true);
873d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org}
883d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org
893d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.orgDesktop* Desktop::GetInputDesktop() {
903d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  HDESK desktop = OpenInputDesktop(
913d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org      0, FALSE, GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE);
923d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  if (desktop == NULL)
933d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org    return NULL;
943d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org
953d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  return new Desktop(desktop, true);
963d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org}
973d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org
983d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.orgDesktop* Desktop::GetThreadDesktop() {
993d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  HDESK desktop = ::GetThreadDesktop(GetCurrentThreadId());
1003d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  if (desktop == NULL) {
1013d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org    LOG(LS_ERROR) << "Failed to retrieve the handle of the desktop assigned to "
1023d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org                     "the current thread: "
1033d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org                  << GetLastError();
1043d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org    return NULL;
1053d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  }
1063d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org
1073d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org  return new Desktop(desktop, false);
1083d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org}
1093d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org
1103d34f66292ad4d3950d94026d08c3659880d30e2sergeyu@chromium.org}  // namespace webrtc
111