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 
17 namespace webrtc {
18 
Desktop(HDESK desktop,bool own)19 Desktop::Desktop(HDESK desktop, bool own) : desktop_(desktop), own_(own) {}
20 
~Desktop()21 Desktop::~Desktop() {
22   if (own_ && desktop_ != NULL) {
23     if (!::CloseDesktop(desktop_)) {
24       RTC_LOG(LS_ERROR) << "Failed to close the owned desktop handle: "
25                         << GetLastError();
26     }
27   }
28 }
29 
GetName(std::wstring * desktop_name_out) const30 bool Desktop::GetName(std::wstring* desktop_name_out) const {
31   if (desktop_ == NULL)
32     return false;
33 
34   DWORD length = 0;
35   int rv = GetUserObjectInformationW(desktop_, UOI_NAME, NULL, 0, &length);
36   if (rv || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
37     abort();
38 
39   length /= sizeof(WCHAR);
40   std::vector<WCHAR> buffer(length);
41   if (!GetUserObjectInformationW(desktop_, UOI_NAME, &buffer[0],
42                                  length * sizeof(WCHAR), &length)) {
43     RTC_LOG(LS_ERROR) << "Failed to query the desktop name: " << GetLastError();
44     return false;
45   }
46 
47   desktop_name_out->assign(&buffer[0], length / sizeof(WCHAR));
48   return true;
49 }
50 
IsSame(const Desktop & other) const51 bool Desktop::IsSame(const Desktop& other) const {
52   std::wstring name;
53   if (!GetName(&name))
54     return false;
55 
56   std::wstring other_name;
57   if (!other.GetName(&other_name))
58     return false;
59 
60   return name == other_name;
61 }
62 
SetThreadDesktop() const63 bool Desktop::SetThreadDesktop() const {
64   if (!::SetThreadDesktop(desktop_)) {
65     RTC_LOG(LS_ERROR) << "Failed to assign the desktop to the current thread: "
66                       << GetLastError();
67     return false;
68   }
69 
70   return true;
71 }
72 
GetDesktop(const WCHAR * desktop_name)73 Desktop* Desktop::GetDesktop(const WCHAR* desktop_name) {
74   ACCESS_MASK desired_access = DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |
75                                DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |
76                                DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
77                                DESKTOP_SWITCHDESKTOP | GENERIC_WRITE;
78   HDESK desktop = OpenDesktopW(desktop_name, 0, FALSE, desired_access);
79   if (desktop == NULL) {
80     RTC_LOG(LS_ERROR) << "Failed to open the desktop '" << desktop_name
81                       << "': " << GetLastError();
82     return NULL;
83   }
84 
85   return new Desktop(desktop, true);
86 }
87 
GetInputDesktop()88 Desktop* Desktop::GetInputDesktop() {
89   HDESK desktop = OpenInputDesktop(
90       0, FALSE, GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE);
91   if (desktop == NULL)
92     return NULL;
93 
94   return new Desktop(desktop, true);
95 }
96 
GetThreadDesktop()97 Desktop* Desktop::GetThreadDesktop() {
98   HDESK desktop = ::GetThreadDesktop(GetCurrentThreadId());
99   if (desktop == NULL) {
100     RTC_LOG(LS_ERROR)
101         << "Failed to retrieve the handle of the desktop assigned to "
102            "the current thread: "
103         << GetLastError();
104     return NULL;
105   }
106 
107   return new Desktop(desktop, false);
108 }
109 
110 }  // namespace webrtc
111