VirtualBox

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

Last change on this file since 61559 was 60255, checked in by vboxsync, 9 years ago

Additions/VBoxCredProv: Fixes for BSTR handling (untested, thanks PVS).

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