VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/VBoxCredProv/VBoxCredentialProvider.cpp@ 94377

Last change on this file since 94377 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 17.1 KB
Line 
1/* $Id: VBoxCredentialProvider.cpp 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * VBoxCredentialProvider - Main file of the VirtualBox Credential Provider.
4 */
5
6/*
7 * Copyright (C) 2012-2022 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#include <iprt/win/windows.h>
23#include <initguid.h>
24#include <new> /* For bad_alloc. */
25
26#ifdef VBOX_WITH_WIN_SENS
27# include <eventsys.h>
28# include <sens.h>
29# include <Sensevts.h>
30#endif
31
32#include <iprt/buildconfig.h>
33#include <iprt/initterm.h>
34#ifdef VBOX_WITH_WIN_SENS
35# include <VBox/com/string.h>
36using namespace com;
37#endif
38#include <VBox/VBoxGuestLib.h>
39
40#include "VBoxCredentialProvider.h"
41#include "VBoxCredProvFactory.h"
42
43
44/*********************************************************************************************************************************
45* Global Variables *
46*********************************************************************************************************************************/
47static LONG g_cDllRefs = 0; /**< Global DLL reference count. */
48static HINSTANCE g_hDllInst = NULL; /**< Global DLL hInstance. */
49
50#ifdef VBOX_WITH_WIN_SENS
51static bool g_fSENSEnabled = false;
52static IEventSystem *g_pIEventSystem = NULL; /**< Pointer to IEventSystem interface. */
53
54/**
55 * Subscribed SENS events.
56 */
57static struct VBOXCREDPROVSENSEVENTS
58{
59 /** The actual method name the subscription is for. */
60 char *pszMethod;
61 /** A friendly name for the subscription. */
62 char *pszSubscriptionName;
63 /** The actual subscription UUID.
64 * Should not be changed. */
65 char *pszSubscriptionUUID;
66} g_aSENSEvents[] = {
67 { "Logon", "VBoxCredProv SENS Logon", "{561D0791-47C0-4BC3-87C0-CDC2621EA653}" },
68 { "Logoff", "VBoxCredProv SENS Logoff", "{12B618B1-F2E0-4390-BADA-7EB1DC31A70A}" },
69 { "StartShell", "VBoxCredProv SENS StartShell", "{5941931D-015A-4F91-98DA-81AAE262D090}" },
70 { "DisplayLock", "VBoxCredProv SENS DisplayLock", "{B7E2C510-501A-4961-938F-A458970930D7}" },
71 { "DisplayUnlock", "VBoxCredProv SENS DisplayUnlock", "{11305987-8FFC-41AD-A264-991BD5B7488A}" },
72 { "StartScreenSaver", "VBoxCredProv SENS StartScreenSaver", "{6E2D26DF-0095-4EC4-AE00-2395F09AF7F2}" },
73 { "StopScreenSaver", "VBoxCredProv SENS StopScreenSaver", "{F53426BC-412F-41E8-9A5F-E5FA8A164BD6}" }
74};
75
76/**
77 * Implementation of the ISensLogon interface for getting
78 * SENS (System Event Notification Service) events. SENS must be up
79 * and running on this OS!
80 */
81interface VBoxCredProvSensLogon : public ISensLogon
82{
83public:
84
85 VBoxCredProvSensLogon(void)
86 : m_cRefs(1)
87 {
88 }
89
90 virtual ~VBoxCredProvSensLogon()
91 {
92 /* Make VC++ 19.2 happy. */
93 }
94
95 STDMETHODIMP QueryInterface(REFIID interfaceID, void **ppvInterface)
96 {
97 if ( IsEqualIID(interfaceID, IID_IUnknown)
98 || IsEqualIID(interfaceID, IID_IDispatch)
99 || IsEqualIID(interfaceID, IID_ISensLogon))
100 {
101 *ppvInterface = this;
102 AddRef();
103 return S_OK;
104 }
105
106 *ppvInterface = NULL;
107 return E_NOINTERFACE;
108 }
109
110 ULONG STDMETHODCALLTYPE AddRef(void)
111 {
112 return InterlockedIncrement(&m_cRefs);
113 }
114
115 ULONG STDMETHODCALLTYPE Release(void)
116 {
117 ULONG ulTemp = InterlockedDecrement(&m_cRefs);
118 return ulTemp;
119 }
120
121 HRESULT STDMETHODCALLTYPE GetTypeInfoCount(unsigned int FAR *pctInfo)
122 {
123 RT_NOREF(pctInfo);
124 return E_NOTIMPL;
125 }
126
127 HRESULT STDMETHODCALLTYPE GetTypeInfo(unsigned int iTInfo, LCID lcid, ITypeInfo FAR * FAR *ppTInfo)
128 {
129 RT_NOREF(iTInfo, lcid, ppTInfo);
130 return E_NOTIMPL;
131 }
132
133 HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, OLECHAR FAR * FAR *rgszNames, unsigned int cNames,
134 LCID lcid, DISPID FAR *rgDispId)
135 {
136 RT_NOREF(riid, rgszNames, cNames, lcid, rgDispId);
137 return E_NOTIMPL;
138 }
139
140 HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR *pDispParams,
141 VARIANT FAR *parResult, EXCEPINFO FAR *pExcepInfo, unsigned int FAR *puArgErr)
142 {
143 RT_NOREF(dispIdMember, riid, lcid, wFlags, pDispParams, parResult, pExcepInfo, puArgErr);
144 return E_NOTIMPL;
145 }
146
147 /* ISensLogon methods */
148 STDMETHODIMP Logon(BSTR bstrUserName)
149 {
150 RT_NOREF(bstrUserName);
151 VBoxCredProvVerbose(0, "VBoxCredProvSensLogon: Logon\n");
152 return S_OK;
153 }
154
155 STDMETHODIMP Logoff(BSTR bstrUserName)
156 {
157 RT_NOREF(bstrUserName);
158 VBoxCredProvVerbose(0, "VBoxCredProvSensLogon: Logoff\n");
159 return S_OK;
160 }
161
162 STDMETHODIMP StartShell(BSTR bstrUserName)
163 {
164 RT_NOREF(bstrUserName);
165 VBoxCredProvVerbose(0, "VBoxCredProvSensLogon: Logon\n");
166 return S_OK;
167 }
168
169 STDMETHODIMP DisplayLock(BSTR bstrUserName)
170 {
171 RT_NOREF(bstrUserName);
172 VBoxCredProvVerbose(0, "VBoxCredProvSensLogon: DisplayLock\n");
173 return S_OK;
174 }
175
176 STDMETHODIMP DisplayUnlock(BSTR bstrUserName)
177 {
178 RT_NOREF(bstrUserName);
179 VBoxCredProvVerbose(0, "VBoxCredProvSensLogon: DisplayUnlock\n");
180 return S_OK;
181 }
182
183 STDMETHODIMP StartScreenSaver(BSTR bstrUserName)
184 {
185 RT_NOREF(bstrUserName);
186 VBoxCredProvVerbose(0, "VBoxCredProvSensLogon: StartScreenSaver\n");
187 return S_OK;
188 }
189
190 STDMETHODIMP StopScreenSaver(BSTR bstrUserName)
191 {
192 RT_NOREF(bstrUserName);
193 VBoxCredProvVerbose(0, "VBoxCredProvSensLogon: StopScreenSaver\n");
194 return S_OK;
195 }
196
197protected:
198
199 LONG m_cRefs;
200};
201static VBoxCredProvSensLogon *g_pISensLogon = NULL;
202
203
204/**
205 * Register events to be called by SENS.
206 *
207 * @return HRESULT
208 */
209static HRESULT VBoxCredentialProviderRegisterSENS(void)
210{
211 VBoxCredProvVerbose(0, "VBoxCredentialProviderRegisterSENS\n");
212
213 HRESULT hr = CoCreateInstance(CLSID_CEventSystem, 0, CLSCTX_SERVER, IID_IEventSystem, (void**)&g_pIEventSystem);
214 if (FAILED(hr))
215 {
216 VBoxCredProvVerbose(0, "VBoxCredentialProviderRegisterSENS: Could not connect to CEventSystem, hr=%Rhrc\n", hr);
217 return hr;
218 }
219
220 /* Note: Bstr class can also throw -- therefore including the setup procedure in the following try block as well. */
221 try
222 {
223 g_pISensLogon = new VBoxCredProvSensLogon();
224
225 AssertPtr(g_pIEventSystem);
226 AssertPtr(g_pISensLogon);
227
228 IEventSubscription *pIEventSubscription = NULL;
229 int i;
230 for (i = 0; i < RT_ELEMENTS(g_aSENSEvents); i++)
231 {
232 VBoxCredProvVerbose(0, "VBoxCredProv: Registering \"%s\" (%s) ...\n",
233 g_aSENSEvents[i].pszMethod, g_aSENSEvents[i].pszSubscriptionName);
234
235 hr = CoCreateInstance(CLSID_CEventSubscription, 0, CLSCTX_SERVER, IID_IEventSubscription, (LPVOID*)&pIEventSubscription);
236 if (FAILED(hr))
237 continue;
238
239 hr = pIEventSubscription->put_EventClassID(Bstr("{d5978630-5b9f-11d1-8dd2-00aa004abd5e}" /* SENSGUID_EVENTCLASS_LOGON */).raw());
240 if (FAILED(hr))
241 break;
242
243 hr = pIEventSubscription->put_SubscriberInterface((IUnknown*)g_pISensLogon);
244 if (FAILED(hr))
245 break;
246
247 hr = pIEventSubscription->put_MethodName(Bstr(g_aSENSEvents[i].pszMethod).raw());
248 if (FAILED(hr))
249 break;
250
251 hr = pIEventSubscription->put_SubscriptionName(Bstr(g_aSENSEvents[i].pszSubscriptionName).raw());
252 if (FAILED(hr))
253 break;
254
255 hr = pIEventSubscription->put_SubscriptionID(Bstr(g_aSENSEvents[i].pszSubscriptionUUID).raw());
256 if (FAILED(hr))
257 break;
258
259 hr = pIEventSubscription->put_PerUser(TRUE);
260 if (FAILED(hr))
261 break;
262
263 hr = g_pIEventSystem->Store(PROGID_EventSubscription, (IUnknown*)pIEventSubscription);
264 if (FAILED(hr))
265 break;
266
267 pIEventSubscription->Release();
268 pIEventSubscription = NULL;
269 }
270
271 if (FAILED(hr))
272 VBoxCredProvVerbose(0, "VBoxCredentialProviderRegisterSENS: Could not register \"%s\" (%s), hr=%Rhrc\n",
273 g_aSENSEvents[i].pszMethod, g_aSENSEvents[i].pszSubscriptionName, hr);
274
275 if (pIEventSubscription != NULL)
276 pIEventSubscription->Release();
277 }
278 catch (std::bad_alloc &ex)
279 {
280 NOREF(ex);
281 hr = E_OUTOFMEMORY;
282 }
283
284 if (FAILED(hr))
285 {
286 VBoxCredProvVerbose(0, "VBoxCredentialProviderRegisterSENS: Error registering SENS provider, hr=%Rhrc\n", hr);
287
288 if (g_pISensLogon)
289 {
290 delete g_pISensLogon;
291 g_pISensLogon = NULL;
292 }
293
294 if (g_pIEventSystem)
295 {
296 g_pIEventSystem->Release();
297 g_pIEventSystem = NULL;
298 }
299 }
300
301 VBoxCredProvVerbose(0, "VBoxCredentialProviderRegisterSENS: Returning hr=%Rhrc\n", hr);
302 return hr;
303}
304
305/**
306 * Unregisters registered SENS events.
307 */
308static void VBoxCredentialProviderUnregisterSENS(void)
309{
310 if (g_pIEventSystem)
311 {
312 g_pIEventSystem->Release();
313 g_pIEventSystem = NULL;
314 }
315
316 /* We need to reconnecto to the event system because we can be called
317 * in a different context COM can't handle. */
318 HRESULT hr = CoCreateInstance(CLSID_CEventSystem, 0,
319 CLSCTX_SERVER, IID_IEventSystem, (void**)&g_pIEventSystem);
320 if (FAILED(hr))
321 VBoxCredProvVerbose(0, "VBoxCredentialProviderUnregisterSENS: Could not reconnect to CEventSystem, hr=%Rhrc\n", hr);
322
323 try
324 {
325 VBoxCredProvVerbose(0, "VBoxCredentialProviderUnregisterSENS\n");
326
327 for (int i = 0; i < RT_ELEMENTS(g_aSENSEvents); i++)
328 {
329 int iErrorIdX;
330 Bstr strSubToRemove = Utf8StrFmt("SubscriptionID=%s", g_aSENSEvents[i].pszSubscriptionUUID);
331 hr = g_pIEventSystem->Remove(PROGID_EventSubscription, strSubToRemove.raw(), &iErrorIdX);
332 if (FAILED(hr))
333 {
334 VBoxCredProvVerbose(0, "VBoxCredentialProviderUnregisterSENS: Could not unregister \"%s\" (query: %ls), hr=%Rhrc (index: %d)\n",
335 g_aSENSEvents[i].pszMethod, strSubToRemove.raw(), hr, iErrorIdX);
336 /* Keep going. */
337 }
338 }
339 }
340 catch (std::bad_alloc &ex)
341 {
342 NOREF(ex);
343 hr = E_OUTOFMEMORY;
344 }
345
346 if (g_pISensLogon)
347 {
348 delete g_pISensLogon;
349 g_pISensLogon = NULL;
350 }
351
352 if (g_pIEventSystem)
353 {
354 g_pIEventSystem->Release();
355 g_pIEventSystem = NULL;
356 }
357
358 VBoxCredProvVerbose(0, "VBoxCredentialProviderUnregisterSENS: Returning hr=%Rhrc\n", hr);
359}
360#endif /* VBOX_WITH_WIN_SENS */
361
362
363BOOL WINAPI DllMain(HINSTANCE hInst, DWORD dwReason, LPVOID pReserved)
364{
365 NOREF(pReserved);
366
367 g_hDllInst = hInst;
368
369 switch (dwReason)
370 {
371 case DLL_PROCESS_ATTACH:
372 {
373 int rc = RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
374 if (RT_SUCCESS(rc))
375 rc = VbglR3Init();
376
377 if (RT_SUCCESS(rc))
378 {
379 VBoxCredProvVerbose(0, "VBoxCredProv: v%s r%s (%s %s) loaded (refs=%ld)\n",
380 RTBldCfgVersion(), RTBldCfgRevisionStr(),
381 __DATE__, __TIME__, g_cDllRefs);
382 }
383
384 DisableThreadLibraryCalls(hInst);
385 break;
386 }
387
388 case DLL_PROCESS_DETACH:
389
390 VBoxCredProvVerbose(0, "VBoxCredProv: Unloaded (refs=%ld)\n", g_cDllRefs);
391 if (!g_cDllRefs)
392 VbglR3Term();
393 break;
394
395 case DLL_THREAD_ATTACH:
396 case DLL_THREAD_DETACH:
397 break;
398
399 default:
400 break;
401 }
402
403 return TRUE;
404}
405
406
407/**
408 * Increments the reference count by one. Must be released
409 * with VBoxCredentialProviderRelease() when finished.
410 */
411void VBoxCredentialProviderAcquire(void)
412{
413 LONG cRefCount = InterlockedIncrement(&g_cDllRefs);
414 VBoxCredProvVerbose(0, "VBoxCredentialProviderAcquire: Increasing global refcount to %ld\n",
415 cRefCount);
416}
417
418
419/**
420 * Decrements the reference count by one.
421 */
422void VBoxCredentialProviderRelease(void)
423{
424 LONG cRefCount = InterlockedDecrement(&g_cDllRefs);
425 VBoxCredProvVerbose(0, "VBoxCredentialProviderRelease: Decreasing global refcount to %ld\n",
426 cRefCount);
427}
428
429
430/**
431 * Returns the current DLL reference count.
432 *
433 * @return LONG The current reference count.
434 */
435LONG VBoxCredentialProviderRefCount(void)
436{
437 return g_cDllRefs;
438}
439
440
441/**
442 * Entry point for determining whether the credential
443 * provider DLL can be unloaded or not.
444 *
445 * @return HRESULT
446 */
447HRESULT __stdcall DllCanUnloadNow(void)
448{
449 VBoxCredProvVerbose(0, "DllCanUnloadNow (refs=%ld)\n",
450 g_cDllRefs);
451
452#ifdef VBOX_WITH_WIN_SENS
453 if (!g_cDllRefs)
454 {
455 if (g_fSENSEnabled)
456 VBoxCredentialProviderUnregisterSENS();
457
458 CoUninitialize();
459 }
460#endif
461 return (g_cDllRefs > 0) ? S_FALSE : S_OK;
462}
463
464
465/**
466 * Create the VirtualBox credential provider by creating
467 * its factory which then in turn can create instances of the
468 * provider itself.
469 *
470 * @return HRESULT
471 * @param classID The class ID.
472 * @param interfaceID The interface ID.
473 * @param ppvInterface Receives the interface pointer on successful
474 * object creation.
475 */
476HRESULT VBoxCredentialProviderCreate(REFCLSID classID, REFIID interfaceID,
477 void **ppvInterface)
478{
479 HRESULT hr;
480 if (classID == CLSID_VBoxCredProvider)
481 {
482 try
483 {
484 VBoxCredProvFactory* pFactory = new VBoxCredProvFactory();
485 AssertPtr(pFactory);
486 hr = pFactory->QueryInterface(interfaceID,
487 ppvInterface);
488 pFactory->Release();
489
490#ifdef VBOX_WITH_WIN_SENS
491 g_fSENSEnabled = true; /* By default SENS support is enabled. */
492
493 HKEY hKey;
494 /** @todo Add some registry wrapper function(s) as soon as we got more values to retrieve. */
495 DWORD dwRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Oracle\\VirtualBox Guest Additions\\AutoLogon",
496 0L, KEY_QUERY_VALUE, &hKey);
497 if (dwRet == ERROR_SUCCESS)
498 {
499 DWORD dwValue;
500 DWORD dwType = REG_DWORD;
501 DWORD dwSize = sizeof(DWORD);
502
503 dwRet = RegQueryValueEx(hKey, L"HandleSENS", NULL, &dwType, (LPBYTE)&dwValue, &dwSize);
504 if ( dwRet == ERROR_SUCCESS
505 && dwType == REG_DWORD
506 && dwSize == sizeof(DWORD))
507 {
508 g_fSENSEnabled = RT_BOOL(dwValue);
509 }
510
511 RegCloseKey(hKey);
512 }
513
514 VBoxCredProvVerbose(0, "VBoxCredentialProviderCreate: g_fSENSEnabled=%RTbool\n",
515 g_fSENSEnabled);
516 if ( SUCCEEDED(hr)
517 && g_fSENSEnabled)
518 {
519 HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
520 RT_NOREF(hRes); /* probably a great idea to ignore this */
521 VBoxCredentialProviderRegisterSENS();
522 }
523#else /* !VBOX_WITH_WIN_SENS */
524 VBoxCredProvVerbose(0, "VBoxCredentialProviderCreate: SENS support is disabled\n");
525#endif /* !VBOX_WITH_WIN_SENS */
526 }
527 catch (std::bad_alloc &ex)
528 {
529 NOREF(ex);
530 hr = E_OUTOFMEMORY;
531 }
532 }
533 else
534 hr = CLASS_E_CLASSNOTAVAILABLE;
535
536 return hr;
537}
538
539
540/**
541 * Entry point for getting the actual credential provider
542 * class object.
543 *
544 * @return HRESULT
545 * @param classID The class ID.
546 * @param interfaceID The interface ID.
547 * @param ppvInterface Receives the interface pointer on successful
548 * object creation.
549 */
550HRESULT __stdcall DllGetClassObject(REFCLSID classID, REFIID interfaceID, void **ppvInterface)
551{
552 VBoxCredProvVerbose(0, "DllGetClassObject (refs=%ld)\n",
553 g_cDllRefs);
554
555 return VBoxCredentialProviderCreate(classID, interfaceID, ppvInterface);
556}
557
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