VirtualBox

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

Last change on this file since 48789 was 46593, checked in by vboxsync, 12 years ago

updates

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.1 KB
Line 
1/* $Id: VBoxCredentialProvider.cpp 46593 2013-06-17 14:32:51Z vboxsync $ */
2/** @file
3 * VBoxCredentialProvider - Main file of the VirtualBox Credential Provider.
4 */
5
6/*
7 * Copyright (C) 2012-2013 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* Header Files *
20*******************************************************************************/
21#include <windows.h>
22#include <initguid.h>
23#include <new> /* For bad_alloc. */
24
25#ifdef VBOX_WITH_SENS
26# include <eventsys.h>
27# include <sens.h>
28# include <Sensevts.h>
29#endif
30
31#include <iprt/buildconfig.h>
32#include <iprt/initterm.h>
33#ifdef VBOX_WITH_SENS
34# include <iprt/string.h>
35#endif
36#include <VBox/VBoxGuestLib.h>
37
38#include "VBoxCredentialProvider.h"
39#include "VBoxCredProvFactory.h"
40
41/*******************************************************************************
42* Global Variables *
43*******************************************************************************/
44static LONG g_cDllRefs = 0; /**< Global DLL reference count. */
45static HINSTANCE g_hDllInst = NULL; /**< Global DLL hInstance. */
46
47#ifdef VBOX_WITH_SENS
48static IEventSystem *g_pIEventSystem; /**< Pointer to IEventSystem interface. */
49
50/**
51 * Subscribed SENS events.
52 */
53static struct VBOXCREDPROVSENSEVENTS
54{
55 /** The actual method name the subscription is for. */
56 char *pszMethod;
57 /** A friendly name for the subscription. */
58 char *pszSubscriptionName;
59 /** The actual subscription UUID.
60 * Should not be changed. */
61 char *pszSubscriptionUUID;
62} g_aSENSEvents[] = {
63 { "Logon", "VBoxCredProv SENS Logon", "{561D0791-47C0-4BC3-87C0-CDC2621EA653}" },
64 { "Logoff", "VBoxCredProv SENS Logoff", "{12B618B1-F2E0-4390-BADA-7EB1DC31A70A}" },
65 { "StartShell", "VBoxCredProv SENS StartShell", "{5941931D-015A-4F91-98DA-81AAE262D090}" },
66 { "DisplayLock", "VBoxCredProv SENS DisplayLock", "{B7E2C510-501A-4961-938F-A458970930D7}" },
67 { "DisplayUnlock", "VBoxCredProv SENS DisplayUnlock", "{11305987-8FFC-41AD-A264-991BD5B7488A}" },
68 { "StartScreenSaver", "VBoxCredProv SENS StartScreenSaver", "{6E2D26DF-0095-4EC4-AE00-2395F09AF7F2}" },
69 { "StopScreenSaver", "VBoxCredProv SENS StopScreenSaver", "{F53426BC-412F-41E8-9A5F-E5FA8A164BD6}" }
70};
71
72/**
73 * Implementation of the ISensLogon interface for getting
74 * SENS (System Event Notification Service) events. SENS must be up
75 * and running on this OS!
76 */
77interface VBoxCredProvSensLogon : public ISensLogon
78{
79public:
80
81 VBoxCredProvSensLogon(void) :
82 m_cRefs(1)
83 {
84 }
85
86 STDMETHODIMP QueryInterface(REFIID interfaceID, void **ppvInterface)
87 {
88 if ( IsEqualIID(interfaceID, IID_IUnknown)
89 || IsEqualIID(interfaceID, IID_IDispatch)
90 || IsEqualIID(interfaceID, IID_ISensLogon))
91 {
92 *ppvInterface = this;
93 AddRef();
94 return S_OK;
95 }
96
97 *ppvInterface = NULL;
98 return E_NOINTERFACE;
99 }
100
101 ULONG STDMETHODCALLTYPE AddRef(void)
102 {
103 return InterlockedIncrement(&m_cRefs);
104 }
105
106 ULONG STDMETHODCALLTYPE Release(void)
107 {
108 ULONG ulTemp = InterlockedDecrement(&m_cRefs);
109 return ulTemp;
110 }
111
112 HRESULT STDMETHODCALLTYPE GetTypeInfoCount(unsigned int FAR* pctinfo)
113 {
114 return E_NOTIMPL;
115 }
116
117 HRESULT STDMETHODCALLTYPE GetTypeInfo(unsigned int iTInfo, LCID lcid, ITypeInfo FAR* FAR* ppTInfo)
118 {
119 return E_NOTIMPL;
120 }
121
122 HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid,
123 OLECHAR FAR* FAR* rgszNames, unsigned int cNames,
124 LCID lcid, DISPID FAR* rgDispId)
125 {
126 return E_NOTIMPL;
127 }
128
129 HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
130 DISPPARAMS FAR* pDispParams, VARIANT FAR* parResult, EXCEPINFO FAR* pExcepInfo,
131 unsigned int FAR* puArgErr)
132 {
133 return E_NOTIMPL;
134 }
135
136 /* ISensLogon methods */
137 STDMETHODIMP Logon(BSTR bstrUserName)
138 {
139 VBoxCredProvVerbose(0, "VBoxCredProvSensLogon: Logon\n");
140 return S_OK;
141 }
142
143 STDMETHODIMP Logoff(BSTR bstrUserName)
144 {
145 VBoxCredProvVerbose(0, "VBoxCredProvSensLogon: Logoff\n");
146 return S_OK;
147 }
148
149 STDMETHODIMP StartShell(BSTR bstrUserName)
150 {
151 VBoxCredProvVerbose(0, "VBoxCredProvSensLogon: Logon\n");
152 return S_OK;
153 }
154
155 STDMETHODIMP DisplayLock(BSTR bstrUserName)
156 {
157 VBoxCredProvVerbose(0, "VBoxCredProvSensLogon: DisplayLock\n");
158 return S_OK;
159 }
160
161 STDMETHODIMP DisplayUnlock(BSTR bstrUserName)
162 {
163 VBoxCredProvVerbose(0, "VBoxCredProvSensLogon: DisplayUnlock\n");
164 return S_OK;
165 }
166
167 STDMETHODIMP StartScreenSaver(BSTR bstrUserName)
168 {
169 VBoxCredProvVerbose(0, "VBoxCredProvSensLogon: StartScreenSaver\n");
170 return S_OK;
171 }
172
173 STDMETHODIMP StopScreenSaver(BSTR bstrUserName)
174 {
175 VBoxCredProvVerbose(0, "VBoxCredProvSensLogon: StopScreenSaver\n");
176 return S_OK;
177 }
178
179protected:
180
181 LONG m_cRefs;
182};
183static VBoxCredProvSensLogon *g_pISensLogon;
184
185
186/**
187 * Register events to be called by SENS.
188 *
189 * @return HRESULT
190 */
191static HRESULT VBoxCredentialProviderRegisterSENS(void)
192{
193 VBoxCredProvVerbose(0, "VBoxCredentialProviderRegisterSENS\n");
194
195 HRESULT hr = CoCreateInstance(CLSID_CEventSystem, 0, CLSCTX_SERVER, IID_IEventSystem, (void**)&g_pIEventSystem);
196 if (FAILED(hr))
197 {
198 VBoxCredProvVerbose(0, "VBoxCredentialProviderRegisterSENS: Could not connect to CEventSystem, hr=%Rhrc\n",
199 hr);
200 return hr;
201 }
202
203 try
204 {
205 g_pISensLogon = new VBoxCredProvSensLogon();
206 AssertPtr(g_pISensLogon);
207 }
208 catch (std::bad_alloc &ex)
209 {
210 NOREF(ex);
211 hr = E_OUTOFMEMORY;
212 }
213
214 if (SUCCEEDED(hr))
215 {
216 IEventSubscription *pIEventSubscription;
217 int i;
218 for (i = 0; i < RT_ELEMENTS(g_aSENSEvents); i++)
219 {
220 VBoxCredProvVerbose(0, "VBoxCredProv: Registering \"%s\" (%s) ...\n",
221 g_aSENSEvents[i].pszMethod, g_aSENSEvents[i].pszSubscriptionName);
222
223 hr = CoCreateInstance(CLSID_CEventSubscription, 0, CLSCTX_SERVER, IID_IEventSubscription, (LPVOID*)&pIEventSubscription);
224 if (FAILED(hr))
225 continue;
226
227 hr = pIEventSubscription->put_EventClassID(L"{d5978630-5b9f-11d1-8dd2-00aa004abd5e}" /* SENSGUID_EVENTCLASS_LOGON */);
228 if (FAILED(hr))
229 break;
230
231 hr = pIEventSubscription->put_SubscriberInterface((IUnknown*)g_pISensLogon);
232 if (FAILED(hr))
233 break;
234
235 PRTUTF16 pwszTemp;
236 int rc = RTStrToUtf16(g_aSENSEvents[i].pszMethod, &pwszTemp);
237 if (RT_SUCCESS(rc))
238 {
239 hr = pIEventSubscription->put_MethodName(pwszTemp);
240 RTUtf16Free(pwszTemp);
241 }
242 else
243 hr = ERROR_OUTOFMEMORY;
244 if (FAILED(hr))
245 break;
246
247 rc = RTStrToUtf16(g_aSENSEvents[i].pszSubscriptionName, &pwszTemp);
248 if (RT_SUCCESS(rc))
249 {
250 hr = pIEventSubscription->put_SubscriptionName(pwszTemp);
251 RTUtf16Free(pwszTemp);
252 }
253 else
254 hr = ERROR_OUTOFMEMORY;
255 if (FAILED(hr))
256 break;
257
258 rc = RTStrToUtf16(g_aSENSEvents[i].pszSubscriptionUUID, &pwszTemp);
259 if (RT_SUCCESS(rc))
260 {
261 hr = pIEventSubscription->put_SubscriptionID(pwszTemp);
262 RTUtf16Free(pwszTemp);
263 }
264 else
265 hr = ERROR_OUTOFMEMORY;
266 if (FAILED(hr))
267 break;
268
269 hr = pIEventSubscription->put_PerUser(TRUE);
270 if (FAILED(hr))
271 break;
272
273 hr = g_pIEventSystem->Store(PROGID_EventSubscription, (IUnknown*)pIEventSubscription);
274 if (FAILED(hr))
275 break;
276
277 pIEventSubscription->Release();
278 pIEventSubscription = NULL;
279 }
280
281 if (FAILED(hr))
282 VBoxCredProvVerbose(0, "VBoxCredentialProviderRegisterSENS: Could not register \"%s\" (%s), hr=%Rhrc\n",
283 g_aSENSEvents[i].pszMethod, g_aSENSEvents[i].pszSubscriptionName, hr);
284
285 if (pIEventSubscription != NULL)
286 pIEventSubscription->Release();
287 }
288
289 if (FAILED(hr))
290 {
291 VBoxCredProvVerbose(0, "VBoxCredentialProviderRegisterSENS: Error registering SENS provider, hr=%Rhrc\n", hr);
292 if (g_pIEventSystem)
293 g_pIEventSystem->Release();
294 }
295
296 return hr;
297}
298
299/**
300 * Unregisters registered SENS events.
301 */
302static void VBoxCredentialProviderUnregisterSENS(void)
303{
304 if (g_pIEventSystem)
305 g_pIEventSystem->Release();
306
307 /* We need to reconnecto to the event system because we can be called
308 * in a different context COM can't handle. */
309 HRESULT hr = CoCreateInstance(CLSID_CEventSystem, 0, CLSCTX_SERVER, IID_IEventSystem, (void**)&g_pIEventSystem);
310 if (SUCCEEDED(hr))
311 {
312 VBoxCredProvVerbose(0, "VBoxCredentialProviderUnregisterSENS\n");
313
314 HRESULT hr;
315
316 for (int i = 0; i < RT_ELEMENTS(g_aSENSEvents); i++)
317 {
318 int iErrorIdX;
319
320 char *pszSubToRemove;
321 if (!RTStrAPrintf(&pszSubToRemove, "SubscriptionID=%s",
322 g_aSENSEvents[i].pszSubscriptionUUID))
323 {
324 continue; /* Keep going. */
325 }
326
327 PRTUTF16 pwszTemp;
328 int rc2 = RTStrToUtf16(pszSubToRemove, &pwszTemp);
329 if (RT_SUCCESS(rc2))
330 {
331 hr = g_pIEventSystem->Remove(PROGID_EventSubscription, pwszTemp,
332 &iErrorIdX);
333 RTUtf16Free(pwszTemp);
334 }
335 else
336 hr = ERROR_OUTOFMEMORY;
337
338 if (FAILED(hr))
339 VBoxCredProvVerbose(0, "VBoxCredentialProviderUnregisterSENS: Could not unregister \"%s\" (query: %s), hr=%Rhrc (index: %d)\n",
340 g_aSENSEvents[i].pszMethod, pszSubToRemove, hr, iErrorIdX);
341 /* Keep going. */
342
343 RTStrFree(pszSubToRemove);
344 }
345
346 g_pIEventSystem->Release();
347 }
348
349 if (g_pISensLogon)
350 delete g_pISensLogon;
351}
352#endif /* VBOX_WITH_SENS */
353
354
355BOOL WINAPI DllMain(HINSTANCE hInst, DWORD dwReason, LPVOID pReserved)
356{
357 NOREF(pReserved);
358
359 g_hDllInst = hInst;
360
361 switch (dwReason)
362 {
363 case DLL_PROCESS_ATTACH:
364 {
365 int rc = RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
366 if (RT_SUCCESS(rc))
367 rc = VbglR3Init();
368
369 if (RT_SUCCESS(rc))
370 {
371 VBoxCredProvVerbose(0, "VBoxCredProv: v%s r%s (%s %s) loaded (refs=%ld)\n",
372 RTBldCfgVersion(), RTBldCfgRevisionStr(),
373 __DATE__, __TIME__, g_cDllRefs);
374 }
375
376 DisableThreadLibraryCalls(hInst);
377 break;
378 }
379
380 case DLL_PROCESS_DETACH:
381
382 VBoxCredProvVerbose(0, "VBoxCredProv: Unloaded (refs=%ld)\n", g_cDllRefs);
383 if (!g_cDllRefs)
384 VbglR3Term();
385 break;
386
387 case DLL_THREAD_ATTACH:
388 case DLL_THREAD_DETACH:
389 break;
390 }
391
392 return TRUE;
393}
394
395
396/**
397 * Increments the reference count by one. Must be released
398 * with VBoxCredentialProviderRelease() when finished.
399 */
400void VBoxCredentialProviderAcquire(void)
401{
402 LONG cRefCount = InterlockedIncrement(&g_cDllRefs);
403 VBoxCredProvVerbose(0, "VBoxCredentialProviderAcquire: Increasing global refcount to %ld\n",
404 cRefCount);
405}
406
407
408/**
409 * Decrements the reference count by one.
410 */
411void VBoxCredentialProviderRelease(void)
412{
413 LONG cRefCount = InterlockedDecrement(&g_cDllRefs);
414 VBoxCredProvVerbose(0, "VBoxCredentialProviderRelease: Decreasing global refcount to %ld\n",
415 cRefCount);
416}
417
418
419/**
420 * Returns the current DLL reference count.
421 *
422 * @return LONG The current reference count.
423 */
424LONG VBoxCredentialProviderRefCount(void)
425{
426 return g_cDllRefs;
427}
428
429
430/**
431 * Entry point for determining whether the credential
432 * provider DLL can be unloaded or not.
433 *
434 * @return HRESULT
435 */
436HRESULT __stdcall DllCanUnloadNow(void)
437{
438 VBoxCredProvVerbose(0, "DllCanUnloadNow (refs=%ld)\n",
439 g_cDllRefs);
440
441#ifdef VBOX_WITH_SENS
442 if (!g_cDllRefs)
443 {
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_SENS
479 if (SUCCEEDED(hr))
480 {
481 HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
482 VBoxCredentialProviderRegisterSENS();
483 }
484#endif
485 }
486 catch (std::bad_alloc &ex)
487 {
488 NOREF(ex);
489 hr = E_OUTOFMEMORY;
490 }
491 }
492 else
493 hr = CLASS_E_CLASSNOTAVAILABLE;
494
495 return hr;
496}
497
498
499/**
500 * Entry point for getting the actual credential provider
501 * class object.
502 *
503 * @return HRESULT
504 * @param classID The class ID.
505 * @param interfaceID The interface ID.
506 * @param ppvInterface Receives the interface pointer on successful
507 * object creation.
508 */
509HRESULT __stdcall DllGetClassObject(REFCLSID classID, REFIID interfaceID,
510 void **ppvInterface)
511{
512 VBoxCredProvVerbose(0, "DllGetClassObject (refs=%ld)\n",
513 g_cDllRefs);
514
515 return VBoxCredentialProviderCreate(classID, interfaceID, ppvInterface);
516}
517
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