VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxSessionTracking.cpp

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.5 KB
Line 
1/* $Id: VBoxSessionTracking.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBoxSessionTracking.cpp - Session tracking.
4 */
5
6/*
7 * Copyright (C) 2013-2023 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/win/windows.h>
34
35/* Default desktop state tracking */
36#include <Wtsapi32.h>
37
38#include "VBoxTray.h"
39
40
41/* St (session [state] tracking) functionality API impl */
42
43typedef struct VBOXST
44{
45 HWND hWTSAPIWnd;
46 RTLDRMOD hLdrModWTSAPI32;
47 BOOL fIsConsole;
48 WTS_CONNECTSTATE_CLASS enmConnectState;
49 UINT_PTR idDelayedInitTimer;
50 BOOL (WINAPI * pfnWTSRegisterSessionNotification)(HWND hWnd, DWORD dwFlags);
51 BOOL (WINAPI * pfnWTSUnRegisterSessionNotification)(HWND hWnd);
52 BOOL (WINAPI * pfnWTSQuerySessionInformationA)(HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPTSTR *ppBuffer, DWORD *pBytesReturned);
53} VBOXST;
54
55static VBOXST gVBoxSt;
56
57/** @todo r=andy Lacks documentation / Doxygen headers. What does this, and why? */
58
59int vboxStCheckState()
60{
61 int rc = VINF_SUCCESS;
62 WTS_CONNECTSTATE_CLASS *penmConnectState = NULL;
63 USHORT *pProtocolType = NULL;
64 DWORD cbBuf = 0;
65 if (gVBoxSt.pfnWTSQuerySessionInformationA(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSConnectState,
66 (LPTSTR *)&penmConnectState, &cbBuf))
67 {
68 if (gVBoxSt.pfnWTSQuerySessionInformationA(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSClientProtocolType,
69 (LPTSTR *)&pProtocolType, &cbBuf))
70 {
71 gVBoxSt.fIsConsole = (*pProtocolType == 0);
72 gVBoxSt.enmConnectState = *penmConnectState;
73 return VINF_SUCCESS;
74 }
75
76 DWORD dwErr = GetLastError();
77 LogFlowFunc(("WTSQuerySessionInformationA WTSClientProtocolType failed, error = %08X\n", dwErr));
78 rc = RTErrConvertFromWin32(dwErr);
79 }
80 else
81 {
82 DWORD dwErr = GetLastError();
83 LogFlowFunc(("WTSQuerySessionInformationA WTSConnectState failed, error = %08X\n", dwErr));
84 rc = RTErrConvertFromWin32(dwErr);
85 }
86
87 /* failure branch, set to "console-active" state */
88 gVBoxSt.fIsConsole = TRUE;
89 gVBoxSt.enmConnectState = WTSActive;
90
91 return rc;
92}
93
94int vboxStInit(HWND hWnd)
95{
96 RT_ZERO(gVBoxSt);
97 int rc = RTLdrLoadSystem("WTSAPI32.DLL", false /*fNoUnload*/, &gVBoxSt.hLdrModWTSAPI32);
98 if (RT_SUCCESS(rc))
99 {
100 rc = RTLdrGetSymbol(gVBoxSt.hLdrModWTSAPI32, "WTSRegisterSessionNotification",
101 (void **)&gVBoxSt.pfnWTSRegisterSessionNotification);
102 if (RT_SUCCESS(rc))
103 {
104 rc = RTLdrGetSymbol(gVBoxSt.hLdrModWTSAPI32, "WTSUnRegisterSessionNotification",
105 (void **)&gVBoxSt.pfnWTSUnRegisterSessionNotification);
106 if (RT_SUCCESS(rc))
107 {
108 rc = RTLdrGetSymbol(gVBoxSt.hLdrModWTSAPI32, "WTSQuerySessionInformationA",
109 (void **)&gVBoxSt.pfnWTSQuerySessionInformationA);
110 if (RT_FAILURE(rc))
111 LogFlowFunc(("WTSQuerySessionInformationA not found\n"));
112 }
113 else
114 LogFlowFunc(("WTSUnRegisterSessionNotification not found\n"));
115 }
116 else
117 LogFlowFunc(("WTSRegisterSessionNotification not found\n"));
118 if (RT_SUCCESS(rc))
119 {
120 gVBoxSt.hWTSAPIWnd = hWnd;
121 if (gVBoxSt.pfnWTSRegisterSessionNotification(gVBoxSt.hWTSAPIWnd, NOTIFY_FOR_THIS_SESSION))
122 vboxStCheckState();
123 else
124 {
125 DWORD dwErr = GetLastError();
126 LogFlowFunc(("WTSRegisterSessionNotification failed, error = %08X\n", dwErr));
127 if (dwErr == RPC_S_INVALID_BINDING)
128 {
129 gVBoxSt.idDelayedInitTimer = SetTimer(gVBoxSt.hWTSAPIWnd, TIMERID_VBOXTRAY_ST_DELAYED_INIT_TIMER,
130 2000, (TIMERPROC)NULL);
131 gVBoxSt.fIsConsole = TRUE;
132 gVBoxSt.enmConnectState = WTSActive;
133 rc = VINF_SUCCESS;
134 }
135 else
136 rc = RTErrConvertFromWin32(dwErr);
137 }
138
139 if (RT_SUCCESS(rc))
140 return VINF_SUCCESS;
141 }
142
143 RTLdrClose(gVBoxSt.hLdrModWTSAPI32);
144 }
145 else
146 LogFlowFunc(("WTSAPI32 load failed, rc = %Rrc\n", rc));
147
148 RT_ZERO(gVBoxSt);
149 gVBoxSt.fIsConsole = TRUE;
150 gVBoxSt.enmConnectState = WTSActive;
151 return rc;
152}
153
154void vboxStTerm(void)
155{
156 if (!gVBoxSt.hWTSAPIWnd)
157 {
158 LogFlowFunc(("vboxStTerm called for non-initialized St\n"));
159 return;
160 }
161
162 if (gVBoxSt.idDelayedInitTimer)
163 {
164 /* notification is not registered, just kill timer */
165 KillTimer(gVBoxSt.hWTSAPIWnd, gVBoxSt.idDelayedInitTimer);
166 gVBoxSt.idDelayedInitTimer = 0;
167 }
168 else
169 {
170 if (!gVBoxSt.pfnWTSUnRegisterSessionNotification(gVBoxSt.hWTSAPIWnd))
171 {
172 LogFlowFunc(("WTSAPI32 load failed, error = %08X\n", GetLastError()));
173 }
174 }
175
176 RTLdrClose(gVBoxSt.hLdrModWTSAPI32);
177 RT_ZERO(gVBoxSt);
178}
179
180#define VBOXST_DBG_MAKECASE(_val) case _val: return #_val;
181
182static const char* vboxStDbgGetString(DWORD val)
183{
184 switch (val)
185 {
186 VBOXST_DBG_MAKECASE(WTS_CONSOLE_CONNECT);
187 VBOXST_DBG_MAKECASE(WTS_CONSOLE_DISCONNECT);
188 VBOXST_DBG_MAKECASE(WTS_REMOTE_CONNECT);
189 VBOXST_DBG_MAKECASE(WTS_REMOTE_DISCONNECT);
190 VBOXST_DBG_MAKECASE(WTS_SESSION_LOGON);
191 VBOXST_DBG_MAKECASE(WTS_SESSION_LOGOFF);
192 VBOXST_DBG_MAKECASE(WTS_SESSION_LOCK);
193 VBOXST_DBG_MAKECASE(WTS_SESSION_UNLOCK);
194 VBOXST_DBG_MAKECASE(WTS_SESSION_REMOTE_CONTROL);
195 default:
196 LogFlowFunc(("invalid WTS state %d\n", val));
197 return "Unknown";
198 }
199}
200
201BOOL vboxStCheckTimer(WPARAM wEvent)
202{
203 if (wEvent != gVBoxSt.idDelayedInitTimer)
204 return FALSE;
205
206 if (gVBoxSt.pfnWTSRegisterSessionNotification(gVBoxSt.hWTSAPIWnd, NOTIFY_FOR_THIS_SESSION))
207 {
208 KillTimer(gVBoxSt.hWTSAPIWnd, gVBoxSt.idDelayedInitTimer);
209 gVBoxSt.idDelayedInitTimer = 0;
210 vboxStCheckState();
211 }
212 else
213 {
214 LogFlowFunc(("timer WTSRegisterSessionNotification failed, error = %08X\n", GetLastError()));
215 Assert(gVBoxSt.fIsConsole == TRUE);
216 Assert(gVBoxSt.enmConnectState == WTSActive);
217 }
218
219 return TRUE;
220}
221
222BOOL vboxStIsActiveConsole(void)
223{
224 return (gVBoxSt.enmConnectState == WTSActive && gVBoxSt.fIsConsole);
225}
226
227BOOL vboxStHandleEvent(WPARAM wEvent)
228{
229 RT_NOREF(wEvent);
230 LogFlowFunc(("WTS Event: %s\n", vboxStDbgGetString(wEvent)));
231 BOOL fOldIsActiveConsole = vboxStIsActiveConsole();
232
233 vboxStCheckState();
234
235 return !vboxStIsActiveConsole() != !fOldIsActiveConsole;
236}
237
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use