VirtualBox

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

最後變更 在這個檔案從26084是 25811,由 vboxsync 提交於 15 年 前

VBoxCredProv: Enabled building by default on OSE (second try).

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 10.0 KB
 
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 Sun Microsystems, Inc.
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 {
40 LogRel(("VBoxCredProv: DLL instance created: %ld\n", l));
41 }
42 else
43 {
44 Log(("VBoxCredProv: DLL instance %ld created.\n", l));
45 }
46}
47
48
49VBoxCredProv::~VBoxCredProv(void)
50{
51 if (m_pCred != NULL)
52 {
53 m_pCred->Release();
54 m_pCred = NULL;
55 }
56
57 if (m_pPoller != NULL)
58 {
59 m_pPoller->Shutdown();
60 delete m_pPoller;
61 m_pPoller = NULL;
62 }
63
64 Log(("VBoxCredProv: DLL instance unloaded.\n"));
65
66 VbglR3Term();
67 DllRelease();
68}
69
70
71/* SetUsageScenario is the provider's cue that it's going to be asked for tiles
72 * in a subsequent call. This call happens after the user pressed CTRL+ALT+DEL
73 * and we need to handle the CPUS_LOGON event. */
74HRESULT VBoxCredProv::SetUsageScenario(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus,
75 DWORD dwFlags)
76{
77 UNREFERENCED_PARAMETER(dwFlags);
78 HRESULT hr;
79
80 m_cpUS = cpus;
81
82 /* Decide which scenarios to support here. Returning E_NOTIMPL simply tells the caller
83 * that we're not designed for that scenario. */
84 switch (m_cpUS)
85 {
86 case CPUS_LOGON:
87 case CPUS_UNLOCK_WORKSTATION:
88
89 if (m_pPoller == NULL)
90 {
91 m_pPoller = new VBoxCredPoller();
92 Assert(m_pPoller);
93 if (false == m_pPoller->Initialize(this))
94 Log(("VBoxCredProv::SetUsageScenario: Could not initialize credentials poller thread!\n"));
95 }
96
97 if (m_pCred == NULL)
98 {
99 m_pCred = new VBoxCredential();
100
101 /* All stuff allocated? */
102 if (m_pCred != NULL)
103 {
104 hr = m_pCred->Initialize(m_cpUS,
105 s_rgCredProvFieldDescriptors, s_rgFieldStatePairs);
106 }
107 else
108 {
109 hr = E_OUTOFMEMORY;
110 Log(("VBoxCredProv::SetUsageScenario: Out of memory!\n"));
111 }
112 }
113 else
114 {
115 /* All set up already! */
116 hr = S_OK;
117 }
118
119 /* If we did fail -> cleanup */
120 if (FAILED(hr))
121 {
122 if (m_pCred != NULL)
123 {
124 m_pCred->Release();
125 m_pCred = NULL;
126 }
127 }
128 break;
129
130 case CPUS_CREDUI:
131 case CPUS_CHANGE_PASSWORD:
132
133 hr = E_NOTIMPL;
134 break;
135
136 default:
137
138 hr = E_INVALIDARG;
139 break;
140 }
141
142 Log(("VBoxCredProv::SetUsageScenario returned 0x%08x (CPUS: %d, Flags: %ld)\n", hr, cpus, dwFlags));
143 return hr;
144}
145
146
147// SetSerialization takes the kind of buffer that you would normally return to LogonUI for
148// an authentication attempt. It's the opposite of ICredentialProviderCredential::GetSerialization.
149// GetSerialization is implement by a credential and serializes that credential. Instead,
150// SetSerialization takes the serialization and uses it to create a credential.
151//
152// SetSerialization is called for two main scenarios. The first scenario is in the credui case
153// where it is prepopulating a tile with credentials that the user chose to store in the OS.
154// The second situation is in a remote logon case where the remote client may wish to
155// prepopulate a tile with a username, or in some cases, completely populate the tile and
156// use it to logon without showing any UI.
157//
158STDMETHODIMP VBoxCredProv::SetSerialization(const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *pcpcs)
159{
160 UNREFERENCED_PARAMETER(pcpcs);
161 return E_NOTIMPL;
162}
163
164
165/* Called by LogonUI to give you a callback. Providers often use the callback if they
166 * some event would cause them to need to change the set of tiles (visible UI elements)
167 * that they enumerated. */
168HRESULT VBoxCredProv::Advise(ICredentialProviderEvents* pcpe,
169 UINT_PTR upAdviseContext)
170{
171 Log(("VBoxCredProv::Advise\n"));
172
173 if (m_pCredProvEvents != NULL)
174 m_pCredProvEvents->Release();
175
176 m_pCredProvEvents = pcpe;
177 Assert(m_pCredProvEvents);
178 m_pCredProvEvents->AddRef();
179
180 /* Save advice context for later use when binding to
181 certain ICredentialProviderEvents events. */
182 m_upAdviseContext = upAdviseContext;
183 return S_OK;
184}
185
186
187/* Called by LogonUI when the ICredentialProviderEvents callback is no longer valid. */
188HRESULT VBoxCredProv::UnAdvise()
189{
190 Log(("VBoxCredProv::UnAdvise\n"));
191 if (m_pCredProvEvents != NULL)
192 {
193 m_pCredProvEvents->Release();
194 m_pCredProvEvents = NULL;
195 }
196 return S_OK;
197}
198
199
200// Called by LogonUI to determine the number of fields in your tiles. This
201// does mean that all your tiles must have the same number of fields.
202// This number must include both visible and invisible fields. If you want a tile
203// to have different fields from the other tiles you enumerate for a given usage
204// scenario you must include them all in this count and then hide/show them as desired
205// using the field descriptors.
206HRESULT VBoxCredProv::GetFieldDescriptorCount(DWORD* pdwCount)
207{
208 Assert(pdwCount);
209 *pdwCount = SFI_NUM_FIELDS;
210
211 Log(("VBoxCredProv::GetFieldDescriptorCount: %ld\n", *pdwCount));
212 return S_OK;
213}
214
215
216// Gets the field descriptor for a particular field
217HRESULT VBoxCredProv::GetFieldDescriptorAt(DWORD dwIndex,
218 CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR **ppcpfd)
219{
220 /* Verify dwIndex is a valid field */
221 HRESULT hr;
222 if ( dwIndex < SFI_NUM_FIELDS
223 && ppcpfd)
224 {
225 hr = FieldDescriptorCoAllocCopy(s_rgCredProvFieldDescriptors[dwIndex], ppcpfd);
226 }
227 else
228 {
229 hr = E_INVALIDARG;
230 }
231
232 Log(("VBoxCredProv::GetFieldDescriptorAt: hr=0x%08x, index=%ld, ppcpfd=%p\n",
233 hr, dwIndex, ppcpfd));
234 return hr;
235}
236
237
238// Sets pdwCount to the number of tiles that we wish to show at this time.
239// Sets pdwDefault to the index of the tile which should be used as the default.
240//
241// The default tile is the tile which will be shown in the zoomed view by default. If
242// more than one provider specifies a default tile the behavior is the last used cred
243// prov gets to specify the default tile to be displayed
244//
245// If *pbAutoLogonWithDefault is TRUE, LogonUI will immediately call GetSerialization
246// on the credential you've specified as the default and will submit that credential
247// for authentication without showing any further UI.
248HRESULT VBoxCredProv::GetCredentialCount(DWORD *pdwCount,
249 DWORD *pdwDefault,
250 BOOL *pbAutoLogonWithDefault)
251{
252 Assert(pdwCount);
253 Assert(pdwDefault);
254 Assert(pbAutoLogonWithDefault);
255
256 bool fGotCredentials = false;
257
258 /* Poller thread create/active? */
259 if ( m_pPoller
260 && m_pCred)
261 {
262 fGotCredentials = m_pPoller->QueryCredentials(m_pCred);
263 }
264
265 if (fGotCredentials)
266 {
267 *pdwCount = 1; /* This provider always has the same number of credentials (1) */
268 *pdwDefault = 0; /* The credential we provide is *always* at index 0! */
269 *pbAutoLogonWithDefault = TRUE; /* We always at least try to auto-login (if password is correct) */
270 }
271 else
272 {
273 *pdwCount = 0;
274 *pdwDefault = CREDENTIAL_PROVIDER_NO_DEFAULT;
275 *pbAutoLogonWithDefault = FALSE;
276 }
277
278 Log(("VBoxCredProv::GetCredentialCount: *pdwCount=%ld, *pdwDefault=%ld, *pbAutoLogonWithDefault=%s\n",
279 *pdwCount, *pdwDefault, *pbAutoLogonWithDefault ? "true" : "false"));
280 return S_OK;
281}
282
283
284// Returns the credential at the index specified by dwIndex. This function is called by logonUI to enumerate
285// the tiles.
286HRESULT VBoxCredProv::GetCredentialAt(DWORD dwIndex,
287 ICredentialProviderCredential **ppcpc)
288{
289 HRESULT hr;
290
291 Log(("VBoxCredProv::GetCredentialAt: Index=%ld, ppcpc=%p\n", dwIndex, ppcpc));
292
293 if (m_pCred == NULL)
294 {
295 Log(("VBoxCredProv::GetCredentialAt: No credentials available.\n"));
296 return E_INVALIDARG;
297 }
298
299 /* Validate parameters (we only have one credential) */
300 if( dwIndex == 0
301 && ppcpc)
302 {
303 hr = m_pCred->QueryInterface(IID_ICredentialProviderCredential, reinterpret_cast<void**>(ppcpc));
304 }
305 else
306 {
307 hr = E_INVALIDARG;
308 }
309 return hr;
310}
311
312
313/* Creates our provider. This happens *before* CTRL-ALT-DEL was pressed! */
314HRESULT VBoxCredProv_CreateInstance(REFIID riid, void** ppv)
315{
316 HRESULT hr;
317
318 VBoxCredProv* pProvider = new VBoxCredProv();
319 if (pProvider)
320 {
321 hr = pProvider->QueryInterface(riid, ppv);
322 pProvider->Release();
323 }
324 else
325 {
326 hr = E_OUTOFMEMORY;
327 }
328 return hr;
329}
330
331
332/* Do a credential re-enumeration if we got the event to do so. */
333void VBoxCredProv::OnCredentialsProvided(const char *pszUser,
334 const char *pszPw,
335 const char *pszDomain)
336{
337 Log(("VBoxCredProv::OnCredentialsProvided\n"));
338
339 if (m_pCredProvEvents != NULL)
340 m_pCredProvEvents->CredentialsChanged(m_upAdviseContext);
341}
342
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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