1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "modules/desktop_capture/win/desktop.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <vector>
14*d9f75844SAndroid Build Coastguard Worker
15*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
16*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/string_utils.h"
17*d9f75844SAndroid Build Coastguard Worker
18*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
19*d9f75844SAndroid Build Coastguard Worker
Desktop(HDESK desktop,bool own)20*d9f75844SAndroid Build Coastguard Worker Desktop::Desktop(HDESK desktop, bool own) : desktop_(desktop), own_(own) {}
21*d9f75844SAndroid Build Coastguard Worker
~Desktop()22*d9f75844SAndroid Build Coastguard Worker Desktop::~Desktop() {
23*d9f75844SAndroid Build Coastguard Worker if (own_ && desktop_ != NULL) {
24*d9f75844SAndroid Build Coastguard Worker if (!::CloseDesktop(desktop_)) {
25*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_ERROR) << "Failed to close the owned desktop handle: "
26*d9f75844SAndroid Build Coastguard Worker << GetLastError();
27*d9f75844SAndroid Build Coastguard Worker }
28*d9f75844SAndroid Build Coastguard Worker }
29*d9f75844SAndroid Build Coastguard Worker }
30*d9f75844SAndroid Build Coastguard Worker
GetName(std::wstring * desktop_name_out) const31*d9f75844SAndroid Build Coastguard Worker bool Desktop::GetName(std::wstring* desktop_name_out) const {
32*d9f75844SAndroid Build Coastguard Worker if (desktop_ == NULL)
33*d9f75844SAndroid Build Coastguard Worker return false;
34*d9f75844SAndroid Build Coastguard Worker
35*d9f75844SAndroid Build Coastguard Worker DWORD length = 0;
36*d9f75844SAndroid Build Coastguard Worker int rv = GetUserObjectInformationW(desktop_, UOI_NAME, NULL, 0, &length);
37*d9f75844SAndroid Build Coastguard Worker if (rv || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
38*d9f75844SAndroid Build Coastguard Worker abort();
39*d9f75844SAndroid Build Coastguard Worker
40*d9f75844SAndroid Build Coastguard Worker length /= sizeof(WCHAR);
41*d9f75844SAndroid Build Coastguard Worker std::vector<WCHAR> buffer(length);
42*d9f75844SAndroid Build Coastguard Worker if (!GetUserObjectInformationW(desktop_, UOI_NAME, &buffer[0],
43*d9f75844SAndroid Build Coastguard Worker length * sizeof(WCHAR), &length)) {
44*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_ERROR) << "Failed to query the desktop name: " << GetLastError();
45*d9f75844SAndroid Build Coastguard Worker return false;
46*d9f75844SAndroid Build Coastguard Worker }
47*d9f75844SAndroid Build Coastguard Worker
48*d9f75844SAndroid Build Coastguard Worker desktop_name_out->assign(&buffer[0], length / sizeof(WCHAR));
49*d9f75844SAndroid Build Coastguard Worker return true;
50*d9f75844SAndroid Build Coastguard Worker }
51*d9f75844SAndroid Build Coastguard Worker
IsSame(const Desktop & other) const52*d9f75844SAndroid Build Coastguard Worker bool Desktop::IsSame(const Desktop& other) const {
53*d9f75844SAndroid Build Coastguard Worker std::wstring name;
54*d9f75844SAndroid Build Coastguard Worker if (!GetName(&name))
55*d9f75844SAndroid Build Coastguard Worker return false;
56*d9f75844SAndroid Build Coastguard Worker
57*d9f75844SAndroid Build Coastguard Worker std::wstring other_name;
58*d9f75844SAndroid Build Coastguard Worker if (!other.GetName(&other_name))
59*d9f75844SAndroid Build Coastguard Worker return false;
60*d9f75844SAndroid Build Coastguard Worker
61*d9f75844SAndroid Build Coastguard Worker return name == other_name;
62*d9f75844SAndroid Build Coastguard Worker }
63*d9f75844SAndroid Build Coastguard Worker
SetThreadDesktop() const64*d9f75844SAndroid Build Coastguard Worker bool Desktop::SetThreadDesktop() const {
65*d9f75844SAndroid Build Coastguard Worker if (!::SetThreadDesktop(desktop_)) {
66*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_ERROR) << "Failed to assign the desktop to the current thread: "
67*d9f75844SAndroid Build Coastguard Worker << GetLastError();
68*d9f75844SAndroid Build Coastguard Worker return false;
69*d9f75844SAndroid Build Coastguard Worker }
70*d9f75844SAndroid Build Coastguard Worker
71*d9f75844SAndroid Build Coastguard Worker return true;
72*d9f75844SAndroid Build Coastguard Worker }
73*d9f75844SAndroid Build Coastguard Worker
GetDesktop(const WCHAR * desktop_name)74*d9f75844SAndroid Build Coastguard Worker Desktop* Desktop::GetDesktop(const WCHAR* desktop_name) {
75*d9f75844SAndroid Build Coastguard Worker ACCESS_MASK desired_access = DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |
76*d9f75844SAndroid Build Coastguard Worker DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |
77*d9f75844SAndroid Build Coastguard Worker DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
78*d9f75844SAndroid Build Coastguard Worker DESKTOP_SWITCHDESKTOP | GENERIC_WRITE;
79*d9f75844SAndroid Build Coastguard Worker HDESK desktop = OpenDesktopW(desktop_name, 0, FALSE, desired_access);
80*d9f75844SAndroid Build Coastguard Worker if (desktop == NULL) {
81*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_ERROR) << "Failed to open the desktop '"
82*d9f75844SAndroid Build Coastguard Worker << rtc::ToUtf8(desktop_name) << "': " << GetLastError();
83*d9f75844SAndroid Build Coastguard Worker return NULL;
84*d9f75844SAndroid Build Coastguard Worker }
85*d9f75844SAndroid Build Coastguard Worker
86*d9f75844SAndroid Build Coastguard Worker return new Desktop(desktop, true);
87*d9f75844SAndroid Build Coastguard Worker }
88*d9f75844SAndroid Build Coastguard Worker
GetInputDesktop()89*d9f75844SAndroid Build Coastguard Worker Desktop* Desktop::GetInputDesktop() {
90*d9f75844SAndroid Build Coastguard Worker HDESK desktop = OpenInputDesktop(
91*d9f75844SAndroid Build Coastguard Worker 0, FALSE, GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE);
92*d9f75844SAndroid Build Coastguard Worker if (desktop == NULL)
93*d9f75844SAndroid Build Coastguard Worker return NULL;
94*d9f75844SAndroid Build Coastguard Worker
95*d9f75844SAndroid Build Coastguard Worker return new Desktop(desktop, true);
96*d9f75844SAndroid Build Coastguard Worker }
97*d9f75844SAndroid Build Coastguard Worker
GetThreadDesktop()98*d9f75844SAndroid Build Coastguard Worker Desktop* Desktop::GetThreadDesktop() {
99*d9f75844SAndroid Build Coastguard Worker HDESK desktop = ::GetThreadDesktop(GetCurrentThreadId());
100*d9f75844SAndroid Build Coastguard Worker if (desktop == NULL) {
101*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_ERROR)
102*d9f75844SAndroid Build Coastguard Worker << "Failed to retrieve the handle of the desktop assigned to "
103*d9f75844SAndroid Build Coastguard Worker "the current thread: "
104*d9f75844SAndroid Build Coastguard Worker << GetLastError();
105*d9f75844SAndroid Build Coastguard Worker return NULL;
106*d9f75844SAndroid Build Coastguard Worker }
107*d9f75844SAndroid Build Coastguard Worker
108*d9f75844SAndroid Build Coastguard Worker return new Desktop(desktop, false);
109*d9f75844SAndroid Build Coastguard Worker }
110*d9f75844SAndroid Build Coastguard Worker
111*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc
112