VirtualBox

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

Last change on this file since 42220 was 40940, checked in by vboxsync, 13 years ago

VBoxCredProv: Build fix.

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