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 "webrtc/modules/desktop_capture/win/desktop.h"
12 
13 #include <vector>
14 
15 #include "webrtc/system_wrappers/interface/logging.h"
16 
17 namespace webrtc {
18 
Desktop(HDESK desktop,bool own)19 Desktop::Desktop(HDESK desktop, bool own) : desktop_(desktop), own_(own) {
20 }
21 
~Desktop()22 Desktop::~Desktop() {
23   if (own_ && desktop_ != NULL) {
24     if (!::CloseDesktop(desktop_)) {
25       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     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     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 =
76       DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_ENUMERATE |
77       DESKTOP_HOOKCONTROL | DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
78       DESKTOP_SWITCHDESKTOP | GENERIC_WRITE;
79   HDESK desktop = OpenDesktop(desktop_name, 0, FALSE, desired_access);
80   if (desktop == NULL) {
81     LOG(LS_ERROR) << "Failed to open the desktop '" << desktop_name << "': "
82                   << 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     LOG(LS_ERROR) << "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