VirtualBox

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

Last change on this file since 34079 was 32431, checked in by vboxsync, 14 years ago

scm cleanup

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.6 KB
Line 
1//
2// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
3// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
4// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
5// PARTICULAR PURPOSE.
6//
7// Copyright (c) 2006 Microsoft Corporation. All rights reserved.
8//
9// Modifications (c) 2009-2010 Oracle Corporation
10//
11
12#include <credentialprovider.h>
13
14#include <iprt/err.h>
15#include <VBox/VBoxGuestLib.h>
16
17#include "VBoxCredProv.h"
18#include "VBoxCredential.h"
19#include "guid.h"
20
21
22VBoxCredProv::VBoxCredProv(void) :
23 m_cRef(1),
24 m_pPoller(NULL),
25 m_pCred(NULL),
26 m_pCredProvEvents(NULL),
27 m_fGotCredentials(false)
28{
29 LONG l = DllAddRef();
30
31 int rc = RTR3Init(); /* Never terminate the runtime! */
32 if (RT_FAILURE(rc))
33 LogRel(("VBoxCredProv: Could not init runtime! rc = %Rrc\n", rc));
34 rc = VbglR3Init();
35 if (RT_FAILURE(rc))
36 LogRel(("VBoxCredProv: Could not init guest library! rc = %Rrc\n", rc));
37
38 if (l == 1) /* First instance? */
39 LogRel(("VBoxCredProv: Loaded.\n"));
40 Log(("VBoxCredProv: DLL refcount (load) = %ld\n", l));
41}
42
43
44VBoxCredProv::~VBoxCredProv(void)
45{
46 Log(("VBoxCredProv::~VBoxCredProv\n"));
47
48 if (m_pCred != NULL)
49 {
50 m_pCred->Release();
51 m_pCred = NULL;
52 }
53
54 if (m_pPoller != NULL)
55 {
56 m_pPoller->Shutdown();
57 delete m_pPoller;
58 m_pPoller = NULL;
59 }
60
61 LONG lRefCount = DllGetRefCount();
62 if (lRefCount == 1) /* First (=last) instance unloaded? */
63 LogRel(("VBoxCredProv: Unloaded.\n"));
64 Log(("VBoxCredProv: DLL refcount (unload) = %ld\n", lRefCount));
65
66 VbglR3Term();
67 DllRelease();
68}
69
70
71/*
72 * SetUsageScenario is the provider's cue that it's going to be asked for tiles
73 * in a subsequent call. This call happens after the user pressed CTRL+ALT+DEL
74 * and we need to handle the CPUS_LOGON event.
75 */
76HRESULT VBoxCredProv::SetUsageScenario(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpUsageScenario,
77 DWORD dwFlags)
78{
79 UNREFERENCED_PARAMETER(dwFlags);
80 HRESULT hr;
81
82 m_cpUsageScenario = cpUsageScenario;
83
84 /* Decide which scenarios to support here. Returning E_NOTIMPL simply tells the caller
85 * that we're not designed for that scenario. */
86 switch (m_cpUsageScenario)
87 {
88 case CPUS_LOGON:
89 case CPUS_UNLOCK_WORKSTATION:
90
91 if (m_pPoller == NULL)
92 {
93 m_pPoller = new VBoxCredPoller();
94 Assert(m_pPoller);
95 if (false == m_pPoller->Initialize(this))
96 Log(("VBoxCredProv::SetUsageScenario: Could not initialize credentials poller thread!\n"));
97 }
98
99 if (m_pCred == NULL)
100 {
101 m_pCred = new VBoxCredential(this);
102
103 /* All stuff allocated? */
104 if (m_pCred != NULL)
105 {
106 hr = m_pCred->Initialize(m_cpUsageScenario,
107 s_rgCredProvFieldDescriptors,
108 s_rgFieldStatePairs);
109 }
110 else
111 {
112 hr = E_OUTOFMEMORY;
113 Log(("VBoxCredProv::SetUsageScenario: Out of memory!\n"));
114 }
115 }
116 else
117 {
118 /* All set up already! */
119 hr = S_OK;
120 }
121
122 /* If we did fail -> cleanup */
123 if (FAILED(hr))
124 {
125 if (m_pCred != NULL)
126 {
127 m_pCred->Release();
128 m_pCred = NULL;
129 }
130 }
131 break;
132
133 case CPUS_CHANGE_PASSWORD:
134 case CPUS_CREDUI:
135 case CPUS_PLAP:
136
137 hr = E_NOTIMPL;
138 break;
139
140 default:
141
142 hr = E_INVALIDARG;
143 break;
144 }
145
146 Log(("VBoxCredProv::SetUsageScenario returned 0x%08x (cpUS: %d, Flags: %ld)\n", hr, cpUsageScenario, dwFlags));
147 return hr;
148}
149
150
151/*
152 * SetSerialization takes the kind of buffer that you would normally return to LogonUI for
153 * an authentication attempt. It's the opposite of ICredentialProviderCredential::GetSerialization.
154 * GetSerialization is implement by a credential and serializes that credential. Instead,
155 * SetSerialization takes the serialization and uses it to create a credential.
156 *
157 * SetSerialization is called for two main scenarios. The first scenario is in the credUI case
158 * where it is prepopulating a tile with credentials that the user chose to store in the OS.
159 * The second situation is in a remote logon case where the remote client may wish to
160 * prepopulate a tile with a username, or in some cases, completely populate the tile and
161 * use it to logon without showing any UI.
162 */
163STDMETHODIMP VBoxCredProv::SetSerialization(const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *pcpCredentialSerialization)
164{
165 UNREFERENCED_PARAMETER(pcpCredentialSerialization);
166 return E_NOTIMPL;
167}
168
169
170/*
171 * Called by LogonUI to give you a callback. Providers often use the callback if they
172 * some event would cause them to need to change the set of tiles (visible UI elements)
173 * that they enumerated.
174 */
175HRESULT VBoxCredProv::Advise(ICredentialProviderEvents *pcpEvents,
176 UINT_PTR upAdviseContext)
177{
178 Log(("VBoxCredProv::Advise\n"));
179
180 if (m_pCredProvEvents != NULL)
181 m_pCredProvEvents->Release();
182
183 m_pCredProvEvents = pcpEvents;
184 Assert(m_pCredProvEvents);
185 m_pCredProvEvents->AddRef();
186
187 /*
188 * Save advice context for later use when binding to
189 * certain ICredentialProviderEvents events.
190 */
191 m_upAdviseContext = upAdviseContext;
192 return S_OK;
193}
194
195
196/* Called by LogonUI when the ICredentialProviderEvents callback is no longer valid. */
197HRESULT VBoxCredProv::UnAdvise()
198{
199 Log(("VBoxCredProv::UnAdvise\n"));
200 if (m_pCredProvEvents != NULL)
201 {
202 m_pCredProvEvents->Release();
203 m_pCredProvEvents = NULL;
204 }
205
206 return S_OK;
207}
208
209
210/*
211 * Called by LogonUI to determine the number of fields in your tiles. This
212 * does mean that all your tiles must have the same number of fields.
213 * This number must include both visible and invisible fields. If you want a tile
214 * to have different fields from the other tiles you enumerate for a given usage
215 * scenario you must include them all in this count and then hide/show them as desired
216 * using the field descriptors.
217 */
218HRESULT VBoxCredProv::GetFieldDescriptorCount(DWORD *pdwCount)
219{
220 Assert(pdwCount);
221 *pdwCount = SFI_NUM_FIELDS;
222
223 Log(("VBoxCredProv::GetFieldDescriptorCount: %ld\n", *pdwCount));
224 return S_OK;
225}
226
227
228/* Gets the field descriptor for a particular field. */
229HRESULT VBoxCredProv::GetFieldDescriptorAt(DWORD dwIndex,
230 CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR **ppcpFieldDescriptor)
231{
232 /* Verify dwIndex is a valid field */
233 HRESULT hr;
234 if ( dwIndex < SFI_NUM_FIELDS
235 && ppcpFieldDescriptor)
236 {
237 hr = FieldDescriptorCoAllocCopy(s_rgCredProvFieldDescriptors[dwIndex], ppcpFieldDescriptor);
238 }
239 else
240 {
241 hr = E_INVALIDARG;
242 }
243
244 Log(("VBoxCredProv::GetFieldDescriptorAt: hr=0x%08x, index=%ld, ppcpfd=%p\n",
245 hr, dwIndex, ppcpFieldDescriptor));
246 return hr;
247}
248
249
250/*
251 * Sets pdwCount to the number of tiles that we wish to show at this time.
252 * Sets pdwDefault to the index of the tile which should be used as the default.
253 *
254 * The default tile is the tile which will be shown in the zoomed view by default. If
255 * more than one provider specifies a default tile the behavior is the last used cred
256 * prov gets to specify the default tile to be displayed
257 *
258 * If *pbAutoLogonWithDefault is TRUE, LogonUI will immediately call GetSerialization
259 * on the credential you've specified as the default and will submit that credential
260 * for authentication without showing any further UI.
261 */
262HRESULT VBoxCredProv::GetCredentialCount(DWORD *pdwCount,
263 DWORD *pdwDefault,
264 BOOL *pbAutoLogonWithDefault)
265{
266 Assert(pdwCount);
267 Assert(pdwDefault);
268 Assert(pbAutoLogonWithDefault);
269
270 bool fGotCredentials = false;
271
272 /* Poller thread create/active? */
273 if ( m_pPoller
274 && m_pCred)
275 {
276 fGotCredentials = m_pPoller->QueryCredentials(m_pCred);
277 }
278
279 if (fGotCredentials)
280 {
281 *pdwCount = 1; /* This provider always has the same number of credentials (1). */
282 *pdwDefault = 0; /* The credential we provide is *always* at index 0! */
283 *pbAutoLogonWithDefault = TRUE; /* We always at least try to auto-login (if password is correct). */
284 }
285 else
286 {
287 *pdwCount = 0;
288 *pdwDefault = CREDENTIAL_PROVIDER_NO_DEFAULT;
289 *pbAutoLogonWithDefault = FALSE;
290 }
291
292 Log(("VBoxCredProv::GetCredentialCount: *pdwCount=%ld, *pdwDefault=%ld, *pbAutoLogonWithDefault=%s\n",
293 *pdwCount, *pdwDefault, *pbAutoLogonWithDefault ? "true" : "false"));
294 return S_OK;
295}
296
297
298/*
299 * Returns the credential at the index specified by dwIndex. This function is called by logonUI to enumerate
300 * the tiles.
301 */
302HRESULT VBoxCredProv::GetCredentialAt(DWORD dwIndex,
303 ICredentialProviderCredential **ppCredProvCredential)
304{
305 HRESULT hr;
306
307 Log(("VBoxCredProv::GetCredentialAt: Index=%ld, ppCredProvCredential=%p\n", dwIndex, ppCredProvCredential));
308
309 if (m_pCred == NULL)
310 {
311 Log(("VBoxCredProv::GetCredentialAt: No credentials available.\n"));
312 return E_INVALIDARG;
313 }
314
315 /* Validate parameters (we only have one credential). */
316 if( dwIndex == 0
317 && ppCredProvCredential)
318 {
319 hr = m_pCred->QueryInterface(IID_ICredentialProviderCredential,
320 reinterpret_cast<void**>(ppCredProvCredential));
321 }
322 else
323 {
324 Log(("VBoxCredProv::GetCredentialAt: More than one credential not supported!\n"));
325 hr = E_INVALIDARG;
326 }
327 return hr;
328}
329
330
331/* Do a credential re-enumeration if we got the event to do so. */
332void VBoxCredProv::OnCredentialsProvided()
333{
334 Log(("VBoxCredProv::OnCredentialsProvided\n"));
335
336 if (m_pCredProvEvents != NULL)
337 m_pCredProvEvents->CredentialsChanged(m_upAdviseContext);
338}
339
340
341/* Creates our provider. This happens *before* CTRL-ALT-DEL was pressed! */
342HRESULT VBoxCredProv_CreateInstance(REFIID riid, void** ppv)
343{
344 HRESULT hr;
345
346 VBoxCredProv* pProvider = new VBoxCredProv();
347 if (pProvider)
348 {
349 hr = pProvider->QueryInterface(riid, ppv);
350 pProvider->Release();
351 }
352 else
353 {
354 hr = E_OUTOFMEMORY;
355 }
356 return hr;
357}
358
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