VirtualBox

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

Last change on this file since 78326 was 76553, checked in by vboxsync, 6 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.0 KB
Line 
1/* $Id: VBoxCredentialProvider.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * VBoxCredentialProvider - Main file of the VirtualBox Credential Provider.
4 */
5
6/*
7 * Copyright (C) 2012-2019 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 STDMETHODIMP QueryInterface(REFIID interfaceID, void **ppvInterface)
91 {
92 if ( IsEqualIID(interfaceID, IID_IUnknown)
93 || IsEqualIID(interfaceID, IID_IDispatch)
94 || IsEqualIID(interfaceID, IID_ISensLogon))
95 {
96 *ppvInterface = this;
97 AddRef();
98 return S_OK;
99 }
100
101 *ppvInterface = NULL;
102 return E_NOINTERFACE;
103 }
104
105 ULONG STDMETHODCALLTYPE AddRef(void)
106 {
107 return InterlockedIncrement(&m_cRefs);
108 }
109
110 ULONG STDMETHODCALLTYPE Release(void)
111 {
112 ULONG ulTemp = InterlockedDecrement(&m_cRefs);
113 return ulTemp;
114 }
115
116 HRESULT STDMETHODCALLTYPE GetTypeInfoCount(unsigned int FAR *pctInfo)
117 {
118 RT_NOREF(pctInfo);
119 return E_NOTIMPL;
120 }
121
122 HRESULT STDMETHODCALLTYPE GetTypeInfo(unsigned int iTInfo, LCID lcid, ITypeInfo FAR * FAR *ppTInfo)
123 {
124 RT_NOREF(iTInfo, lcid, ppTInfo);
125 return E_NOTIMPL;
126 }
127
128 HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, OLECHAR FAR * FAR *rgszNames, unsigned int cNames,
129 LCID lcid, DISPID FAR *rgDispId)
130 {
131 RT_NOREF(riid, rgszNames, cNames, lcid, rgDispId);
132 return E_NOTIMPL;
133 }
134
135 HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR *pDispParams,
136 VARIANT FAR *parResult, EXCEPINFO FAR *pExcepInfo, unsigned int FAR *puArgErr)
137 {
138 RT_NOREF(dispIdMember, riid, lcid, wFlags, pDispParams, parResult, pExcepInfo, puArgErr);
139 return E_NOTIMPL;
140 }
141
142 /* ISensLogon methods */
143 STDMETHODIMP Logon(BSTR bstrUserName)
144 {
145 RT_NOREF(bstrUserName);
146 VBoxCredProvVerbose(0, "VBoxCredProvSensLogon: Logon\n");
147 return S_OK;
148 }
149
150 STDMETHODIMP Logoff(BSTR bstrUserName)
151 {
152 RT_NOREF(bstrUserName);
153 VBoxCredProvVerbose(0, "VBoxCredProvSensLogon: Logoff\n");
154 return S_OK;
155 }
156
157 STDMETHODIMP StartShell(BSTR bstrUserName)
158 {
159 RT_NOREF(bstrUserName);
160 VBoxCredProvVerbose(0, "VBoxCredProvSensLogon: Logon\n");
161 return S_OK;
162 }
163
164 STDMETHODIMP DisplayLock(BSTR bstrUserName)
165 {
166 RT_NOREF(bstrUserName);
167 VBoxCredProvVerbose(0, "VBoxCredProvSensLogon: DisplayLock\n");
168 return S_OK;
169 }
170
171 STDMETHODIMP DisplayUnlock(BSTR bstrUserName)
172 {
173 RT_NOREF(bstrUserName);
174 VBoxCredProvVerbose(0, "VBoxCredProvSensLogon: DisplayUnlock\n");
175 return S_OK;
176 }
177
178 STDMETHODIMP StartScreenSaver(BSTR bstrUserName)
179 {
180 RT_NOREF(bstrUserName);
181 VBoxCredProvVerbose(0, "VBoxCredProvSensLogon: StartScreenSaver\n");
182 return S_OK;
183 }
184
185 STDMETHODIMP StopScreenSaver(BSTR bstrUserName)
186 {
187 RT_NOREF(bstrUserName);
188 VBoxCredProvVerbose(0, "VBoxCredProvSensLogon: StopScreenSaver\n");
189 return S_OK;
190 }
191
192protected:
193
194 LONG m_cRefs;
195};
196static VBoxCredProvSensLogon *g_pISensLogon = NULL;
197
198
199/**
200 * Register events to be called by SENS.
201 *
202 * @return HRESULT
203 */
204static HRESULT VBoxCredentialProviderRegisterSENS(void)
205{
206 VBoxCredProvVerbose(0, "VBoxCredentialProviderRegisterSENS\n");
207
208 HRESULT hr = CoCreateInstance(CLSID_CEventSystem, 0, CLSCTX_SERVER, IID_IEventSystem, (void**)&g_pIEventSystem);
209 if (FAILED(hr))
210 {
211 VBoxCredProvVerbose(0, "VBoxCredentialProviderRegisterSENS: Could not connect to CEventSystem, hr=%Rhrc\n", hr);
212 return hr;
213 }
214
215 /* Note: Bstr class can also throw -- therefore including the setup procedure in the following try block as well. */
216 try
217 {
218 g_pISensLogon = new VBoxCredProvSensLogon();
219
220 AssertPtr(g_pIEventSystem);
221 AssertPtr(g_pISensLogon);
222
223 IEventSubscription *pIEventSubscription = NULL;
224 int i;
225 for (i = 0; i < RT_ELEMENTS(g_aSENSEvents); i++)
226 {
227 VBoxCredProvVerbose(0, "VBoxCredProv: Registering \"%s\" (%s) ...\n",
228 g_aSENSEvents[i].pszMethod, g_aSENSEvents[i].pszSubscriptionName);
229
230 hr = CoCreateInstance(CLSID_CEventSubscription, 0, CLSCTX_SERVER, IID_IEventSubscription, (LPVOID*)&pIEventSubscription);
231 if (FAILED(hr))
232 continue;
233
234 hr = pIEventSubscription->put_EventClassID(Bstr("{d5978630-5b9f-11d1-8dd2-00aa004abd5e}" /* SENSGUID_EVENTCLASS_LOGON */).raw());
235 if (FAILED(hr))
236 break;
237
238 hr = pIEventSubscription->put_SubscriberInterface((IUnknown*)g_pISensLogon);
239 if (FAILED(hr))
240 break;
241
242 hr = pIEventSubscription->put_MethodName(Bstr(g_aSENSEvents[i].pszMethod).raw());
243 if (FAILED(hr))
244 break;
245
246 hr = pIEventSubscription->put_SubscriptionName(Bstr(g_aSENSEvents[i].pszSubscriptionName).raw());
247 if (FAILED(hr))
248 break;
249
250 hr = pIEventSubscription->put_SubscriptionID(Bstr(g_aSENSEvents[i].pszSubscriptionUUID).raw());
251 if (FAILED(hr))
252 break;
253
254 hr = pIEventSubscription->put_PerUser(TRUE);
255 if (FAILED(hr))
256 break;
257
258 hr = g_pIEventSystem->Store(PROGID_EventSubscription, (IUnknown*)pIEventSubscription);
259 if (FAILED(hr))
260 break;
261
262 pIEventSubscription->Release();
263 pIEventSubscription = NULL;
264 }
265
266 if (FAILED(hr))
267 VBoxCredProvVerbose(0, "VBoxCredentialProviderRegisterSENS: Could not register \"%s\" (%s), hr=%Rhrc\n",
268 g_aSENSEvents[i].pszMethod, g_aSENSEvents[i].pszSubscriptionName, hr);
269
270 if (pIEventSubscription != NULL)
271 pIEventSubscription->Release();
272 }
273 catch (std::bad_alloc &ex)
274 {
275 NOREF(ex);
276 hr = E_OUTOFMEMORY;
277 }
278
279 if (FAILED(hr))
280 {
281 VBoxCredProvVerbose(0, "VBoxCredentialProviderRegisterSENS: Error registering SENS provider, hr=%Rhrc\n", hr);
282
283 if (g_pISensLogon)
284 {
285 delete g_pISensLogon;
286 g_pISensLogon = NULL;
287 }
288
289 if (g_pIEventSystem)
290 {
291 g_pIEventSystem->Release();
292 g_pIEventSystem = NULL;
293 }
294 }
295
296 VBoxCredProvVerbose(0, "VBoxCredentialProviderRegisterSENS: Returning hr=%Rhrc\n", hr);
297 return hr;
298}
299
300/**
301 * Unregisters registered SENS events.
302 */
303static void VBoxCredentialProviderUnregisterSENS(void)
304{
305 if (g_pIEventSystem)
306 {
307 g_pIEventSystem->Release();
308 g_pIEventSystem = NULL;
309 }
310
311 /* We need to reconnecto to the event system because we can be called
312 * in a different context COM can't handle. */
313 HRESULT hr = CoCreateInstance(CLSID_CEventSystem, 0,
314 CLSCTX_SERVER, IID_IEventSystem, (void**)&g_pIEventSystem);
315 if (FAILED(hr))
316 VBoxCredProvVerbose(0, "VBoxCredentialProviderUnregisterSENS: Could not reconnect to CEventSystem, hr=%Rhrc\n", hr);
317
318 try
319 {
320 VBoxCredProvVerbose(0, "VBoxCredentialProviderUnregisterSENS\n");
321
322 HRESULT hr;
323
324 for (int i = 0; i < RT_ELEMENTS(g_aSENSEvents); i++)
325 {
326 int iErrorIdX;
327 Bstr strSubToRemove = Utf8StrFmt("SubscriptionID=%s", g_aSENSEvents[i].pszSubscriptionUUID);
328 hr = g_pIEventSystem->Remove(PROGID_EventSubscription, strSubToRemove.raw(), &iErrorIdX);
329 if (FAILED(hr))
330 {
331 VBoxCredProvVerbose(0, "VBoxCredentialProviderUnregisterSENS: Could not unregister \"%s\" (query: %ls), hr=%Rhrc (index: %d)\n",
332 g_aSENSEvents[i].pszMethod, strSubToRemove.raw(), hr, iErrorIdX);
333 /* Keep going. */
334 }
335 }
336 }
337 catch (std::bad_alloc &ex)
338 {
339 NOREF(ex);
340 hr = E_OUTOFMEMORY;
341 }
342
343 if (g_pISensLogon)
344 {
345 delete g_pISensLogon;
346 g_pISensLogon = NULL;
347 }
348
349 if (g_pIEventSystem)
350 {
351 g_pIEventSystem->Release();
352 g_pIEventSystem = NULL;
353 }
354
355 VBoxCredProvVerbose(0, "VBoxCredentialProviderUnregisterSENS: Returning hr=%Rhrc\n", hr);
356}
357#endif /* VBOX_WITH_WIN_SENS */
358
359
360BOOL WINAPI DllMain(HINSTANCE hInst, DWORD dwReason, LPVOID pReserved)
361{
362 NOREF(pReserved);
363
364 g_hDllInst = hInst;
365
366 switch (dwReason)
367 {
368 case DLL_PROCESS_ATTACH:
369 {
370 int rc = RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
371 if (RT_SUCCESS(rc))
372 rc = VbglR3Init();
373
374 if (RT_SUCCESS(rc))
375 {
376 VBoxCredProvVerbose(0, "VBoxCredProv: v%s r%s (%s %s) loaded (refs=%ld)\n",
377 RTBldCfgVersion(), RTBldCfgRevisionStr(),
378 __DATE__, __TIME__, g_cDllRefs);
379 }
380
381 DisableThreadLibraryCalls(hInst);
382 break;
383 }
384
385 case DLL_PROCESS_DETACH:
386
387 VBoxCredProvVerbose(0, "VBoxCredProv: Unloaded (refs=%ld)\n", g_cDllRefs);
388 if (!g_cDllRefs)
389 VbglR3Term();
390 break;
391
392 case DLL_THREAD_ATTACH:
393 case DLL_THREAD_DETACH:
394 break;
395
396 default:
397 break;
398 }
399
400 return TRUE;
401}
402
403
404/**
405 * Increments the reference count by one. Must be released
406 * with VBoxCredentialProviderRelease() when finished.
407 */
408void VBoxCredentialProviderAcquire(void)
409{
410 LONG cRefCount = InterlockedIncrement(&g_cDllRefs);
411 VBoxCredProvVerbose(0, "VBoxCredentialProviderAcquire: Increasing global refcount to %ld\n",
412 cRefCount);
413}
414
415
416/**
417 * Decrements the reference count by one.
418 */
419void VBoxCredentialProviderRelease(void)
420{
421 LONG cRefCount = InterlockedDecrement(&g_cDllRefs);
422 VBoxCredProvVerbose(0, "VBoxCredentialProviderRelease: Decreasing global refcount to %ld\n",
423 cRefCount);
424}
425
426
427/**
428 * Returns the current DLL reference count.
429 *
430 * @return LONG The current reference count.
431 */
432LONG VBoxCredentialProviderRefCount(void)
433{
434 return g_cDllRefs;
435}
436
437
438/**
439 * Entry point for determining whether the credential
440 * provider DLL can be unloaded or not.
441 *
442 * @return HRESULT
443 */
444HRESULT __stdcall DllCanUnloadNow(void)
445{
446 VBoxCredProvVerbose(0, "DllCanUnloadNow (refs=%ld)\n",
447 g_cDllRefs);
448
449#ifdef VBOX_WITH_WIN_SENS
450 if (!g_cDllRefs)
451 {
452 if (g_fSENSEnabled)
453 VBoxCredentialProviderUnregisterSENS();
454
455 CoUninitialize();
456 }
457#endif
458 return (g_cDllRefs > 0) ? S_FALSE : S_OK;
459}
460
461
462/**
463 * Create the VirtualBox credential provider by creating
464 * its factory which then in turn can create instances of the
465 * provider itself.
466 *
467 * @return HRESULT
468 * @param classID The class ID.
469 * @param interfaceID The interface ID.
470 * @param ppvInterface Receives the interface pointer on successful
471 * object creation.
472 */
473HRESULT VBoxCredentialProviderCreate(REFCLSID classID, REFIID interfaceID,
474 void **ppvInterface)
475{
476 HRESULT hr;
477 if (classID == CLSID_VBoxCredProvider)
478 {
479 try
480 {
481 VBoxCredProvFactory* pFactory = new VBoxCredProvFactory();
482 AssertPtr(pFactory);
483 hr = pFactory->QueryInterface(interfaceID,
484 ppvInterface);
485 pFactory->Release();
486
487#ifdef VBOX_WITH_WIN_SENS
488 g_fSENSEnabled = true; /* By default SENS support is enabled. */
489
490 HKEY hKey;
491 /** @todo Add some registry wrapper function(s) as soon as we got more values to retrieve. */
492 DWORD dwRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Oracle\\VirtualBox Guest Additions\\AutoLogon",
493 0L, KEY_QUERY_VALUE, &hKey);
494 if (dwRet == ERROR_SUCCESS)
495 {
496 DWORD dwValue;
497 DWORD dwType = REG_DWORD;
498 DWORD dwSize = sizeof(DWORD);
499
500 dwRet = RegQueryValueEx(hKey, L"HandleSENS", NULL, &dwType, (LPBYTE)&dwValue, &dwSize);
501 if ( dwRet == ERROR_SUCCESS
502 && dwType == REG_DWORD
503 && dwSize == sizeof(DWORD))
504 {
505 g_fSENSEnabled = RT_BOOL(dwValue);
506 }
507
508 RegCloseKey(hKey);
509 }
510
511 VBoxCredProvVerbose(0, "VBoxCredentialProviderCreate: g_fSENSEnabled=%RTbool\n",
512 g_fSENSEnabled);
513 if ( SUCCEEDED(hr)
514 && g_fSENSEnabled)
515 {
516 HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
517 RT_NOREF(hRes); /* probably a great idea to ignore this */
518 VBoxCredentialProviderRegisterSENS();
519 }
520#else /* !VBOX_WITH_WIN_SENS */
521 VBoxCredProvVerbose(0, "VBoxCredentialProviderCreate: SENS support is disabled\n");
522#endif /* !VBOX_WITH_WIN_SENS */
523 }
524 catch (std::bad_alloc &ex)
525 {
526 NOREF(ex);
527 hr = E_OUTOFMEMORY;
528 }
529 }
530 else
531 hr = CLASS_E_CLASSNOTAVAILABLE;
532
533 return hr;
534}
535
536
537/**
538 * Entry point for getting the actual credential provider
539 * class object.
540 *
541 * @return HRESULT
542 * @param classID The class ID.
543 * @param interfaceID The interface ID.
544 * @param ppvInterface Receives the interface pointer on successful
545 * object creation.
546 */
547HRESULT __stdcall DllGetClassObject(REFCLSID classID, REFIID interfaceID, void **ppvInterface)
548{
549 VBoxCredProvVerbose(0, "DllGetClassObject (refs=%ld)\n",
550 g_cDllRefs);
551
552 return VBoxCredentialProviderCreate(classID, interfaceID, ppvInterface);
553}
554
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