VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDesktopTracking.cpp@ 106945

Last change on this file since 106945 was 106411, checked in by vboxsync, 8 weeks ago

Additions/VBoxTray: Implemented ability for easier user-controllable logging (also via verbose levels), support for running in foreground mode (with a console window attached to) and selective starting of sub services to easier pinpoint errors in release builds. Cleaned up initialization / termination code a little. See command line help for new options. bugref:10763

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.8 KB
Line 
1/* $Id: VBoxDesktopTracking.cpp 106411 2024-10-17 07:44:43Z vboxsync $ */
2/** @file
3 * VBoxDesktopTracking.cpp - Desktop tracking.
4 */
5
6/*
7 * Copyright (C) 2013-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29#include <iprt/errcore.h>
30#include <iprt/ldr.h>
31#include <iprt/log.h>
32#include <iprt/string.h>
33#include <iprt/system.h>
34#include <iprt/win/windows.h>
35
36#include <VBoxHook.h>
37
38#include "VBoxTray.h"
39#include "VBoxTrayInternal.h"
40
41/* Default desktop state tracking */
42#include <Wtsapi32.h>
43
44
45/** @todo r=andy Lacks documentation / Doxygen headers. What does this, and why? */
46
47/*
48 * Dt (desktop [state] tracking) functionality API impl
49 *
50 * !!!NOTE: this API is NOT thread-safe!!!
51 * */
52
53typedef struct VBOXDT
54{
55 HANDLE hNotifyEvent;
56 BOOL fIsInputDesktop;
57 UINT_PTR idTimer;
58 RTLDRMOD hLdrModHook;
59 BOOL (* pfnVBoxHookInstallActiveDesktopTracker)(HMODULE hDll);
60 BOOL (* pfnVBoxHookRemoveActiveDesktopTracker)();
61 HDESK (WINAPI * pfnGetThreadDesktop)(DWORD dwThreadId);
62 HDESK (WINAPI * pfnOpenInputDesktop)(DWORD dwFlags, BOOL fInherit, ACCESS_MASK dwDesiredAccess);
63 BOOL (WINAPI * pfnCloseDesktop)(HDESK hDesktop);
64} VBOXDT;
65
66static VBOXDT gVBoxDt;
67
68BOOL vboxDtCalculateIsInputDesktop()
69{
70 BOOL fIsInputDt = FALSE;
71 HDESK hInput = gVBoxDt.pfnOpenInputDesktop(0, FALSE, DESKTOP_CREATEWINDOW);
72 if (hInput)
73 {
74// DWORD dwThreadId = GetCurrentThreadId();
75// HDESK hThreadDt = gVBoxDt.pfnGetThreadDesktop(dwThreadId);
76// if (hThreadDt)
77// {
78 fIsInputDt = TRUE;
79// }
80// else
81// {
82// DWORD dwErr = GetLastError();
83// LogFlowFunc(("pfnGetThreadDesktop for Seamless failed, last error = %08X\n", dwErr));
84// }
85
86 gVBoxDt.pfnCloseDesktop(hInput);
87 }
88 else
89 {
90// DWORD dwErr = GetLastError();
91// LogFlowFunc(("pfnOpenInputDesktop for Seamless failed, last error = %08X\n", dwErr));
92 }
93 return fIsInputDt;
94}
95
96void vboxDtDoCheck()
97{
98 BOOL fOldAllowedState = VBoxConsoleIsAllowed();
99 if (vboxDtHandleEvent())
100 {
101 if (!VBoxConsoleIsAllowed() != !fOldAllowedState)
102 VBoxConsoleEnable(!fOldAllowedState);
103 }
104}
105
106BOOL vboxDtCheckTimer(WPARAM wParam)
107{
108 if (wParam != gVBoxDt.idTimer)
109 return FALSE;
110
111 vboxDtDoCheck();
112
113 return TRUE;
114}
115
116int vboxDtInit()
117{
118 RT_ZERO(gVBoxDt);
119
120 int rc;
121 gVBoxDt.hNotifyEvent = CreateEvent(NULL, FALSE, FALSE, VBOXHOOK_GLOBAL_DT_EVENT_NAME);
122 if (gVBoxDt.hNotifyEvent != NULL)
123 {
124 /* Load the hook dll and resolve the necessary entry points. */
125 rc = RTLdrLoadAppPriv(VBOXHOOK_DLL_NAME, &gVBoxDt.hLdrModHook);
126 if (RT_SUCCESS(rc))
127 {
128 rc = RTLdrGetSymbol(gVBoxDt.hLdrModHook, "VBoxHookInstallActiveDesktopTracker",
129 (void **)&gVBoxDt.pfnVBoxHookInstallActiveDesktopTracker);
130 if (RT_SUCCESS(rc))
131 {
132 rc = RTLdrGetSymbol(gVBoxDt.hLdrModHook, "VBoxHookRemoveActiveDesktopTracker",
133 (void **)&gVBoxDt.pfnVBoxHookRemoveActiveDesktopTracker);
134 if (RT_FAILURE(rc))
135 LogFlowFunc(("VBoxHookRemoveActiveDesktopTracker not found\n"));
136 }
137 else
138 LogFlowFunc(("VBoxHookInstallActiveDesktopTracker not found\n"));
139 if (RT_SUCCESS(rc))
140 {
141 /* Try get the system APIs we need. */
142 *(void **)&gVBoxDt.pfnGetThreadDesktop = RTLdrGetSystemSymbol("user32.dll", "GetThreadDesktop");
143 if (!gVBoxDt.pfnGetThreadDesktop)
144 {
145 LogFlowFunc(("GetThreadDesktop not found\n"));
146 rc = VERR_NOT_SUPPORTED;
147 }
148
149 *(void **)&gVBoxDt.pfnOpenInputDesktop = RTLdrGetSystemSymbol("user32.dll", "OpenInputDesktop");
150 if (!gVBoxDt.pfnOpenInputDesktop)
151 {
152 LogFlowFunc(("OpenInputDesktop not found\n"));
153 rc = VERR_NOT_SUPPORTED;
154 }
155
156 *(void **)&gVBoxDt.pfnCloseDesktop = RTLdrGetSystemSymbol("user32.dll", "CloseDesktop");
157 if (!gVBoxDt.pfnCloseDesktop)
158 {
159 LogFlowFunc(("CloseDesktop not found\n"));
160 rc = VERR_NOT_SUPPORTED;
161 }
162
163 if (RT_SUCCESS(rc))
164 {
165 BOOL fRc = FALSE;
166 /* For Vista and up we need to change the integrity of the security descriptor, too. */
167 uint64_t const uNtVersion = RTSystemGetNtVersion();
168 if (uNtVersion >= RTSYSTEM_MAKE_NT_VERSION(6, 0, 0))
169 {
170 HMODULE hModHook = (HMODULE)RTLdrGetNativeHandle(gVBoxDt.hLdrModHook);
171 Assert((uintptr_t)hModHook != ~(uintptr_t)0);
172 fRc = gVBoxDt.pfnVBoxHookInstallActiveDesktopTracker(hModHook);
173 if (!fRc)
174 LogFlowFunc(("pfnVBoxHookInstallActiveDesktopTracker failed, last error = %08X\n", GetLastError()));
175 }
176
177 if (!fRc)
178 {
179 gVBoxDt.idTimer = SetTimer(g_hwndToolWindow, TIMERID_VBOXTRAY_DT_TIMER, 500, (TIMERPROC)NULL);
180 if (!gVBoxDt.idTimer)
181 {
182 DWORD dwErr = GetLastError();
183 LogFlowFunc(("SetTimer error %08X\n", dwErr));
184 rc = RTErrConvertFromWin32(dwErr);
185 }
186 }
187
188 if (RT_SUCCESS(rc))
189 {
190 gVBoxDt.fIsInputDesktop = vboxDtCalculateIsInputDesktop();
191 return VINF_SUCCESS;
192 }
193 }
194 }
195
196 RTLdrClose(gVBoxDt.hLdrModHook);
197 }
198 else
199 {
200 DWORD dwErr = GetLastError();
201 LogFlowFunc(("CreateEvent for Seamless failed, last error = %08X\n", dwErr));
202 rc = RTErrConvertFromWin32(dwErr);
203 }
204
205 CloseHandle(gVBoxDt.hNotifyEvent);
206 }
207 else
208 {
209 DWORD dwErr = GetLastError();
210 LogFlowFunc(("CreateEvent for Seamless failed, last error = %08X\n", dwErr));
211 rc = RTErrConvertFromWin32(dwErr);
212 }
213
214
215 RT_ZERO(gVBoxDt);
216 gVBoxDt.fIsInputDesktop = TRUE;
217
218 if (RT_FAILURE(rc))
219 VBoxTrayError("Initializing desktop tracking failed with %Rrc\n", rc);
220
221 return rc;
222}
223
224void vboxDtTerm()
225{
226 if (!gVBoxDt.hLdrModHook)
227 return;
228
229 gVBoxDt.pfnVBoxHookRemoveActiveDesktopTracker();
230
231 RTLdrClose(gVBoxDt.hLdrModHook);
232 CloseHandle(gVBoxDt.hNotifyEvent);
233
234 RT_ZERO(gVBoxDt);
235}
236
237/* @returns true on "IsInputDesktop" state change */
238BOOL vboxDtHandleEvent()
239{
240 BOOL fIsInputDesktop = gVBoxDt.fIsInputDesktop;
241 gVBoxDt.fIsInputDesktop = vboxDtCalculateIsInputDesktop();
242 return !fIsInputDesktop != !gVBoxDt.fIsInputDesktop;
243}
244
245HANDLE vboxDtGetNotifyEvent()
246{
247 return gVBoxDt.hNotifyEvent;
248}
249
250/* @returns true iff the application (VBoxTray) desktop is input */
251BOOL vboxDtIsInputDesktop()
252{
253 return gVBoxDt.fIsInputDesktop;
254}
255
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette