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