VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/VBoxGINA/Helper.cpp

Last change on this file was 106061, checked in by vboxsync, 2 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.6 KB
Line 
1/* $Id: Helper.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * VBoxGINA - Windows Logon DLL for VirtualBox, Helper Functions.
4 */
5
6/*
7 * Copyright (C) 2006-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#include <iprt/win/windows.h>
29
30#include <iprt/semaphore.h>
31#include <iprt/string.h>
32#include <iprt/thread.h>
33
34#include "winwlx.h"
35#include "Helper.h"
36#include "VBoxGINA.h"
37
38#include <VBox/log.h>
39#include <VBox/VBoxGuestLib.h>
40
41/** Flag indicating whether remote sessions (over MSRDP) should be
42 * handled or not. Default is disabled. */
43static DWORD g_dwHandleRemoteSessions = 0;
44/** Verbosity flag for guest logging. */
45static DWORD g_dwVerbosity = 0;
46
47/**
48 * Displays a verbose message.
49 *
50 * @param dwLevel Minimum log level required to display this message.
51 * @param pszFormat The message text.
52 * @param ... Format arguments.
53 */
54void VBoxGINAVerbose(DWORD dwLevel, const char *pszFormat, ...)
55{
56 if (dwLevel <= g_dwVerbosity)
57 {
58 va_list args;
59 va_start(args, pszFormat);
60 char *psz = NULL;
61 RTStrAPrintfV(&psz, pszFormat, args);
62 va_end(args);
63
64 AssertPtr(psz);
65 LogRel(("%s", psz));
66
67 RTStrFree(psz);
68 }
69}
70
71/**
72 * Loads the global configuration from registry.
73 *
74 * @return IPRT status code.
75 */
76int VBoxGINALoadConfiguration(void)
77{
78 HKEY hKey;
79 /** @todo Add some registry wrapper function(s) as soon as we got more values to retrieve. */
80 DWORD dwRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Oracle\\VirtualBox Guest Additions\\AutoLogon",
81 0L, KEY_QUERY_VALUE, &hKey);
82 if (dwRet == ERROR_SUCCESS)
83 {
84 DWORD dwValue;
85 DWORD dwType = REG_DWORD;
86 DWORD dwSize = sizeof(DWORD);
87
88 dwRet = RegQueryValueEx(hKey, L"HandleRemoteSessions", NULL, &dwType, (LPBYTE)&dwValue, &dwSize);
89 if ( dwRet == ERROR_SUCCESS
90 && dwType == REG_DWORD
91 && dwSize == sizeof(DWORD))
92 {
93 g_dwHandleRemoteSessions = dwValue;
94 }
95
96 dwRet = RegQueryValueEx(hKey, L"LoggingEnabled", NULL, &dwType, (LPBYTE)&dwValue, &dwSize);
97 if ( dwRet == ERROR_SUCCESS
98 && dwType == REG_DWORD
99 && dwSize == sizeof(DWORD))
100 {
101 g_dwVerbosity = 1; /* Default logging level. */
102 }
103
104 if (g_dwVerbosity) /* Do we want logging at all? */
105 {
106 dwRet = RegQueryValueEx(hKey, L"LoggingLevel", NULL, &dwType, (LPBYTE)&dwValue, &dwSize);
107 if ( dwRet == ERROR_SUCCESS
108 && dwType == REG_DWORD
109 && dwSize == sizeof(DWORD))
110 {
111 g_dwVerbosity = dwValue;
112 }
113 }
114
115 RegCloseKey(hKey);
116 }
117 /* Do not report back an error here yet. */
118 return VINF_SUCCESS;
119}
120
121/**
122 * Determines whether we should handle the current session or not.
123 *
124 * @return bool true if we should handle this session, false if not.
125 */
126bool VBoxGINAHandleCurrentSession(void)
127{
128 /* Load global configuration from registry. */
129 int rc = VBoxGINALoadConfiguration();
130 if (RT_FAILURE(rc))
131 VBoxGINAVerbose(0, "VBoxGINA::handleCurrentSession: Error loading global configuration, rc=%Rrc\n",
132 rc);
133
134 bool fHandle = false;
135 if (VbglR3AutoLogonIsRemoteSession())
136 {
137 if (g_dwHandleRemoteSessions) /* Force remote session handling. */
138 fHandle = true;
139 }
140 else /* No remote session. */
141 fHandle = true;
142
143#ifdef DEBUG
144 VBoxGINAVerbose(3, "VBoxGINA::handleCurrentSession: Handling current session=%RTbool\n", fHandle);
145#endif
146 return fHandle;
147}
148
149/* handle of the poller thread */
150RTTHREAD gThreadPoller = NIL_RTTHREAD;
151
152/**
153 * Poller thread. Checks periodically whether there are credentials.
154 */
155static DECLCALLBACK(int) credentialsPoller(RTTHREAD ThreadSelf, void *pvUser)
156{
157 RT_NOREF(pvUser);
158 VBoxGINAVerbose(0, "VBoxGINA::credentialsPoller\n");
159
160 do
161 {
162 int rc = VbglR3CredentialsQueryAvailability();
163 if (RT_SUCCESS(rc))
164 {
165 VBoxGINAVerbose(0, "VBoxGINA::credentialsPoller: got credentials, simulating C-A-D\n");
166 /* tell WinLogon to start the attestation process */
167 pWlxFuncs->WlxSasNotify(hGinaWlx, WLX_SAS_TYPE_CTRL_ALT_DEL);
168 /* time to say goodbye */
169 return 0;
170 }
171
172 if ( RT_FAILURE(rc)
173 && rc != VERR_NOT_FOUND)
174 {
175 static int s_cBitchedQueryAvail = 0;
176 if (s_cBitchedQueryAvail++ < 5)
177 VBoxGINAVerbose(0, "VBoxGINA::credentialsPoller: querying for credentials failed with rc=%Rrc\n", rc);
178 }
179
180 /* wait a bit */
181 if (RTThreadUserWait(ThreadSelf, 500) == VINF_SUCCESS)
182 {
183 VBoxGINAVerbose(0, "VBoxGINA::credentialsPoller: we were asked to terminate\n");
184 /* we were asked to terminate, do that instantly! */
185 return 0;
186 }
187 }
188 while (1);
189
190 return 0;
191}
192
193int VBoxGINACredentialsPollerCreate(void)
194{
195 if (!VBoxGINAHandleCurrentSession())
196 return VINF_SUCCESS;
197
198 VBoxGINAVerbose(0, "VBoxGINA::credentialsPollerCreate\n");
199
200 /* don't create more than one of them */
201 if (gThreadPoller != NIL_RTTHREAD)
202 {
203 VBoxGINAVerbose(0, "VBoxGINA::credentialsPollerCreate: thread already running, returning!\n");
204 return VINF_SUCCESS;
205 }
206
207 /* create the poller thread */
208 int rc = RTThreadCreate(&gThreadPoller, credentialsPoller, NULL, 0, RTTHREADTYPE_INFREQUENT_POLLER,
209 RTTHREADFLAGS_WAITABLE, "creds");
210 if (RT_FAILURE(rc))
211 VBoxGINAVerbose(0, "VBoxGINA::credentialsPollerCreate: failed to create thread, rc = %Rrc\n", rc);
212
213 return rc;
214}
215
216int VBoxGINACredentialsPollerTerminate(void)
217{
218 if (gThreadPoller == NIL_RTTHREAD)
219 return VINF_SUCCESS;
220
221 VBoxGINAVerbose(0, "VBoxGINA::credentialsPollerTerminate\n");
222
223 /* post termination event semaphore */
224 int rc = RTThreadUserSignal(gThreadPoller);
225 if (RT_SUCCESS(rc))
226 {
227 VBoxGINAVerbose(0, "VBoxGINA::credentialsPollerTerminate: waiting for thread to terminate\n");
228 rc = RTThreadWait(gThreadPoller, RT_INDEFINITE_WAIT, NULL);
229 }
230 else
231 VBoxGINAVerbose(0, "VBoxGINA::credentialsPollerTerminate: thread has terminated? wait rc = %Rrc\n", rc);
232
233 if (RT_SUCCESS(rc))
234 {
235 gThreadPoller = NIL_RTTHREAD;
236 }
237
238 VBoxGINAVerbose(0, "VBoxGINA::credentialsPollerTerminate: returned with rc=%Rrc)\n", rc);
239 return rc;
240}
241
242/**
243 * Reports VBoxGINA's status to the host (treated as a guest facility).
244 *
245 * @return IPRT status code.
246 * @param enmStatus Status to report to the host.
247 */
248int VBoxGINAReportStatus(VBoxGuestFacilityStatus enmStatus)
249{
250 VBoxGINAVerbose(0, "VBoxGINA: reporting status %d\n", enmStatus);
251
252 int rc = VbglR3AutoLogonReportStatus(enmStatus);
253 if (RT_FAILURE(rc))
254 VBoxGINAVerbose(0, "VBoxGINA: failed to report status %d, rc=%Rrc\n", enmStatus, rc);
255 return rc;
256}
257
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