VirtualBox

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

最後變更 在這個檔案從95890是 95889,由 vboxsync 提交於 3 年 前

Add/Nt/VBoxCredProv: Make it compile in VBOX_WITH_NOCRT_STATIC mode. bugref:10261

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette