Changeset 30252 in vbox
- Timestamp:
- Jun 16, 2010 1:48:29 PM (15 years ago)
- Location:
- trunk/src/VBox/Additions/WINNT/VBoxCredProv
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/VBoxCredProv/Makefile.kmk
r28800 r30252 45 45 $(VBOX_PATH_PSDK_200702)/Lib/Credui.Lib \ 46 46 $(VBOX_PATH_PSDK_200702)/Lib/Secur32.Lib \ 47 $(VBOX_PATH_PSDK_200702)/Lib/ShLwApi.Lib 47 $(VBOX_PATH_PSDK_200702)/Lib/ShLwApi.Lib \ 48 $(VBOX_PATH_PSDK_200702)/Lib/netapi32.lib 48 49 VBoxCredProv_LIBS.amd64 := \ 49 50 $(VBOX_PATH_PSDK_200702)/Lib/x64/Uuid.Lib \ 50 51 $(VBOX_PATH_PSDK_200702)/Lib/x64/Credui.Lib \ 51 52 $(VBOX_PATH_PSDK_200702)/Lib/x64/Secur32.Lib \ 52 $(VBOX_PATH_PSDK_200702)/Lib/x64/ShLwApi.Lib 53 $(VBOX_PATH_PSDK_200702)/Lib/x64/ShLwApi.Lib \ 54 $(VBOX_PATH_PSDK_200702)/Lib/x64/netapi32.Lib 53 55 54 56 VBoxCredProv_LIBS += \ -
trunk/src/VBox/Additions/WINNT/VBoxCredProv/VBoxCredPoller.cpp
r28800 r30252 5 5 6 6 /* 7 * Copyright (C) 20 09Oracle Corporation7 * Copyright (C) 2010 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 57 57 m_pProv->AddRef(); 58 58 59 /* don't create more than one of them*/59 /* Don't create more than one of them. */ 60 60 if (m_hThreadPoller != NIL_RTTHREAD) 61 61 { … … 68 68 Log(("VBoxCredPoller: Could not init critical section! rc = %Rrc\n", rc)); 69 69 70 /* create the poller thread*/70 /* Create the poller thread. */ 71 71 rc = RTThreadCreate(&m_hThreadPoller, VBoxCredPoller::threadPoller, this, 0, RTTHREADTYPE_INFREQUENT_POLLER, 72 72 RTTHREADFLAGS_WAITABLE, "creds"); … … 90 90 } 91 91 92 /* Post termination event semaphore */92 /* Post termination event semaphore. */ 93 93 int rc = RTThreadUserSignal(m_hThreadPoller); 94 94 if (RT_SUCCESS(rc)) 95 95 { 96 96 Log(("VBoxCredPoller::Shutdown: Waiting for thread to terminate\n")); 97 /* wait until the thread has terminated*/97 /* Wait until the thread has terminated. */ 98 98 rc = RTThreadWait(m_hThreadPoller, RT_INDEFINITE_WAIT, NULL); 99 99 Log(("VBoxCredPoller::Shutdown: Thread has (probably) terminated (rc = %Rrc)\n", rc)); … … 101 101 else 102 102 { 103 /* failed to signal the thread - very unlikely - so no point in waiting long. */103 /* Failed to signal the thread - very unlikely - so no point in waiting long. */ 104 104 Log(("VBoxCredPoller::Shutdown: Failed to signal semaphore, rc = %Rrc\n", rc)); 105 105 rc = RTThreadWait(m_hThreadPoller, 100, NULL); … … 125 125 credentialsReset(); 126 126 127 /* get credentials*/127 /* Get credentials. */ 128 128 RTCritSectEnter(&m_csCredUpate); 129 129 int rc = VbglR3CredentialsRetrieve(&m_pszUser, &m_pszPw, &m_pszDomain); 130 130 if (RT_SUCCESS(rc)) 131 131 { 132 Log(("VBoxCredPoller::credentialsRetrieve: Credentials retrieved (user=%s, pw=%s, domain=%s)\n", 132 /* NULL/free domain if it's empty (""). */ 133 if (m_pszDomain && strlen(m_pszDomain) == 0) 134 { 135 RTStrFree(m_pszDomain); 136 m_pszDomain = NULL; 137 } 138 139 Log(("VBoxCredPoller::credentialsRetrieve: Credentials retrieved (User=%s, Password=%s, Domain=%s)\n", 133 140 m_pszUser ? m_pszUser : "<empty>", 134 141 m_pszPw ? m_pszPw : "<empty>", 135 m_pszDomain ? m_pszDomain : "<empty>")); 136 137 /* allocated but empty? delete and re-fill with default value in block below. */ 138 if (strlen(m_pszDomain) == 0) 139 { 140 RTStrFree(m_pszDomain); 141 m_pszDomain = NULL; 142 } 143 144 /* if we don't have a domain specified, fill in a dot (".") specifying the 145 * local computer. */ 146 if (m_pszDomain == NULL) 147 { 148 rc = RTStrAPrintf(&m_pszDomain, "."); 149 if (RT_FAILURE(rc)) 150 Log(("VBoxCredPoller::credentialsRetrieve: Could not set default domain name, rc = %Rrc", rc)); 151 else 152 Log(("VBoxCredPoller::credentialsRetrieve: No domain name given, set default value to: %s\n", m_pszDomain)); 153 } 154 } 155 156 /* if all went fine, notify parent */ 157 if (RT_SUCCESS(rc)) 158 { 142 m_pszDomain ? m_pszDomain : "NULL")); 143 159 144 AssertPtr(m_pProv); 160 m_pProv->OnCredentialsProvided(m_pszUser, 161 m_pszPw, 162 m_pszDomain); 145 m_pProv->OnCredentialsProvided(); 163 146 } 164 147 RTCritSectLeave(&m_csCredUpate); … … 216 199 if (RT_FAILURE(rc)) 217 200 { 218 if (rc == VERR_NOT_FOUND) 219 Log(("VBoxCredPoller::threadPoller: No credentials availabe.\n")); 220 else 201 if (rc != VERR_NOT_FOUND) 221 202 Log(("VBoxCredPoller::threadPoller: Could not retrieve credentials! rc = %Rc\n", rc)); 222 203 } … … 228 209 } 229 210 230 /* wait a bit*/211 /* Wait a bit. */ 231 212 if (RTThreadUserWait(ThreadSelf, 500) == VINF_SUCCESS) 232 213 { 233 214 Log(("VBoxCredPoller::threadPoller: Terminating\n")); 234 /* we were asked to terminate, do that instantly! */215 /* We were asked to terminate, do that instantly! */ 235 216 return 0; 236 217 } -
trunk/src/VBox/Additions/WINNT/VBoxCredProv/VBoxCredProv.cpp
r29200 r30252 20 20 21 21 22 VBoxCredProv::VBoxCredProv(void) :22 VBoxCredProv::VBoxCredProv(void) : 23 23 m_cRef(1), 24 24 m_pPoller(NULL), … … 37 37 38 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 } 39 LogRel(("VBoxCredProv: Loaded.\n")); 40 Log(("VBoxCredProv: DLL refcount (load) = %ld\n", l)); 46 41 } 47 42 … … 49 44 VBoxCredProv::~VBoxCredProv(void) 50 45 { 46 Log(("VBoxCredProv::~VBoxCredProv\n")); 47 51 48 if (m_pCred != NULL) 52 49 { … … 62 59 } 63 60 64 Log(("VBoxCredProv: DLL instance unloaded.\n")); 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 65 66 66 VbglR3Term(); … … 69 69 70 70 71 /* SetUsageScenario is the provider's cue that it's going to be asked for tiles 71 /* 72 * SetUsageScenario is the provider's cue that it's going to be asked for tiles 72 73 * in a subsequent call. This call happens after the user pressed CTRL+ALT+DEL 73 * and we need to handle the CPUS_LOGON event. */ 74 HRESULT VBoxCredProv::SetUsageScenario(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus, 75 DWORD dwFlags) 74 * and we need to handle the CPUS_LOGON event. 75 */ 76 HRESULT VBoxCredProv::SetUsageScenario(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpUsageScenario, 77 DWORD dwFlags) 76 78 { 77 79 UNREFERENCED_PARAMETER(dwFlags); 78 80 HRESULT hr; 79 81 80 m_cpU S = cpus;82 m_cpUsageScenario = cpUsageScenario; 81 83 82 84 /* Decide which scenarios to support here. Returning E_NOTIMPL simply tells the caller 83 85 * that we're not designed for that scenario. */ 84 switch (m_cpU S)86 switch (m_cpUsageScenario) 85 87 { 86 88 case CPUS_LOGON: … … 97 99 if (m_pCred == NULL) 98 100 { 99 m_pCred = new VBoxCredential( );101 m_pCred = new VBoxCredential(this); 100 102 101 103 /* All stuff allocated? */ 102 104 if (m_pCred != NULL) 103 105 { 104 hr = m_pCred->Initialize(m_cpUS, 105 s_rgCredProvFieldDescriptors, s_rgFieldStatePairs); 106 hr = m_pCred->Initialize(m_cpUsageScenario, 107 s_rgCredProvFieldDescriptors, 108 s_rgFieldStatePairs); 106 109 } 107 110 else … … 128 131 break; 129 132 133 case CPUS_CHANGE_PASSWORD: 130 134 case CPUS_CREDUI: 131 case CPUS_ CHANGE_PASSWORD:132 135 case CPUS_PLAP: 136 133 137 hr = E_NOTIMPL; 134 138 break; … … 140 144 } 141 145 142 Log(("VBoxCredProv::SetUsageScenario returned 0x%08x ( CPUS: %d, Flags: %ld)\n", hr, cpus, dwFlags));146 Log(("VBoxCredProv::SetUsageScenario returned 0x%08x (cpUS: %d, Flags: %ld)\n", hr, cpUsageScenario, dwFlags)); 143 147 return hr; 144 148 } 145 149 146 150 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 // 158 STDMETHODIMP VBoxCredProv::SetSerialization(const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *pcpcs) 159 { 160 UNREFERENCED_PARAMETER(pcpcs); 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 */ 163 STDMETHODIMP VBoxCredProv::SetSerialization(const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *pcpCredentialSerialization) 164 { 165 UNREFERENCED_PARAMETER(pcpCredentialSerialization); 161 166 return E_NOTIMPL; 162 167 } 163 168 164 169 165 /* Called by LogonUI to give you a callback. Providers often use the callback if they 170 /* 171 * Called by LogonUI to give you a callback. Providers often use the callback if they 166 172 * some event would cause them to need to change the set of tiles (visible UI elements) 167 * that they enumerated. */ 168 HRESULT VBoxCredProv::Advise(ICredentialProviderEvents* pcpe, 169 UINT_PTR upAdviseContext) 173 * that they enumerated. 174 */ 175 HRESULT VBoxCredProv::Advise(ICredentialProviderEvents *pcpEvents, 176 UINT_PTR upAdviseContext) 170 177 { 171 178 Log(("VBoxCredProv::Advise\n")); … … 174 181 m_pCredProvEvents->Release(); 175 182 176 m_pCredProvEvents = pcp e;183 m_pCredProvEvents = pcpEvents; 177 184 Assert(m_pCredProvEvents); 178 185 m_pCredProvEvents->AddRef(); 179 186 180 /* Save advice context for later use when binding to 181 certain ICredentialProviderEvents events. */ 187 /* 188 * Save advice context for later use when binding to 189 * certain ICredentialProviderEvents events. 190 */ 182 191 m_upAdviseContext = upAdviseContext; 183 192 return S_OK; … … 190 199 Log(("VBoxCredProv::UnAdvise\n")); 191 200 if (m_pCredProvEvents != NULL) 192 { 201 { 193 202 m_pCredProvEvents->Release(); 194 203 m_pCredProvEvents = NULL; 195 204 } 205 196 206 return S_OK; 197 207 } 198 208 199 209 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. 206 HRESULT VBoxCredProv::GetFieldDescriptorCount(DWORD* pdwCount) 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 */ 218 HRESULT VBoxCredProv::GetFieldDescriptorCount(DWORD *pdwCount) 207 219 { 208 220 Assert(pdwCount); … … 214 226 215 227 216 / / Gets the field descriptor for a particular field228 /* Gets the field descriptor for a particular field. */ 217 229 HRESULT VBoxCredProv::GetFieldDescriptorAt(DWORD dwIndex, 218 CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR **ppcp fd)230 CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR **ppcpFieldDescriptor) 219 231 { 220 232 /* Verify dwIndex is a valid field */ 221 233 HRESULT hr; 222 234 if ( dwIndex < SFI_NUM_FIELDS 223 && ppcp fd)224 { 225 hr = FieldDescriptorCoAllocCopy(s_rgCredProvFieldDescriptors[dwIndex], ppcp fd);235 && ppcpFieldDescriptor) 236 { 237 hr = FieldDescriptorCoAllocCopy(s_rgCredProvFieldDescriptors[dwIndex], ppcpFieldDescriptor); 226 238 } 227 239 else … … 231 243 232 244 Log(("VBoxCredProv::GetFieldDescriptorAt: hr=0x%08x, index=%ld, ppcpfd=%p\n", 233 hr, dwIndex, ppcp fd));245 hr, dwIndex, ppcpFieldDescriptor)); 234 246 return hr; 235 247 } 236 248 237 249 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. 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 */ 248 262 HRESULT VBoxCredProv::GetCredentialCount(DWORD *pdwCount, 249 263 DWORD *pdwDefault, … … 265 279 if (fGotCredentials) 266 280 { 267 *pdwCount = 1; /* This provider always has the same number of credentials (1) */281 *pdwCount = 1; /* This provider always has the same number of credentials (1). */ 268 282 *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) */283 *pbAutoLogonWithDefault = TRUE; /* We always at least try to auto-login (if password is correct). */ 270 284 } 271 285 else … … 282 296 283 297 284 // Returns the credential at the index specified by dwIndex. This function is called by logonUI to enumerate 285 // the tiles. 286 HRESULT VBoxCredProv::GetCredentialAt(DWORD dwIndex, 287 ICredentialProviderCredential **ppcpc) 298 /* 299 * Returns the credential at the index specified by dwIndex. This function is called by logonUI to enumerate 300 * the tiles. 301 */ 302 HRESULT VBoxCredProv::GetCredentialAt(DWORD dwIndex, 303 ICredentialProviderCredential **ppCredProvCredential) 288 304 { 289 305 HRESULT hr; 290 306 291 Log(("VBoxCredProv::GetCredentialAt: Index=%ld, pp cpc=%p\n", dwIndex, ppcpc));307 Log(("VBoxCredProv::GetCredentialAt: Index=%ld, ppCredProvCredential=%p\n", dwIndex, ppCredProvCredential)); 292 308 293 309 if (m_pCred == NULL) … … 297 313 } 298 314 299 /* Validate parameters (we only have one credential) */315 /* Validate parameters (we only have one credential). */ 300 316 if( dwIndex == 0 301 && ppcpc) 302 { 303 hr = m_pCred->QueryInterface(IID_ICredentialProviderCredential, reinterpret_cast<void**>(ppcpc)); 317 && ppCredProvCredential) 318 { 319 hr = m_pCred->QueryInterface(IID_ICredentialProviderCredential, 320 reinterpret_cast<void**>(ppCredProvCredential)); 304 321 } 305 322 else 306 323 { 324 Log(("VBoxCredProv::GetCredentialAt: More than one credential not supported!\n")); 307 325 hr = E_INVALIDARG; 308 326 } 309 327 return hr; 328 } 329 330 331 /* Do a credential re-enumeration if we got the event to do so. */ 332 void VBoxCredProv::OnCredentialsProvided() 333 { 334 Log(("VBoxCredProv::OnCredentialsProvided\n")); 335 336 if (m_pCredProvEvents != NULL) 337 m_pCredProvEvents->CredentialsChanged(m_upAdviseContext); 310 338 } 311 339 … … 329 357 } 330 358 331 332 /* Do a credential re-enumeration if we got the event to do so. */333 void 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 -
trunk/src/VBox/Additions/WINNT/VBoxCredProv/VBoxCredProv.h
r29200 r30252 25 25 public: 26 26 27 / / IUnknown27 /** IUnknown methods. */ 28 28 STDMETHOD_(ULONG, AddRef)() 29 29 { … … 61 61 public: 62 62 63 / / ICredentialProvider64 IFACEMETHODIMP SetUsageScenario(CREDENTIAL_PROVIDER_USAGE_SCENARIO cp us, DWORD dwFlags);65 IFACEMETHODIMP SetSerialization(const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *pcp cs);63 /** ICredentialProvider interface. */ 64 IFACEMETHODIMP SetUsageScenario(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpUsageScenario, DWORD dwFlags); 65 IFACEMETHODIMP SetSerialization(const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *pcpCredentialSerialization); 66 66 67 IFACEMETHODIMP Advise(__in ICredentialProviderEvents *pcp e, UINT_PTR upAdviseContext);67 IFACEMETHODIMP Advise(__in ICredentialProviderEvents *pcpEvents, UINT_PTR upAdviseContext); 68 68 IFACEMETHODIMP UnAdvise(); 69 69 70 70 IFACEMETHODIMP GetFieldDescriptorCount(__out DWORD* pdwCount); 71 IFACEMETHODIMP GetFieldDescriptorAt(DWORD dwIndex, __deref_out CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR **ppcp fd);71 IFACEMETHODIMP GetFieldDescriptorAt(DWORD dwIndex, __deref_out CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR **ppcpFieldDescriptor); 72 72 73 73 IFACEMETHODIMP GetCredentialCount(__out DWORD *pdwCount, … … 82 82 83 83 VBoxCredProv(void); 84 __override~VBoxCredProv(void);84 virtual ~VBoxCredProv(void); 85 85 86 86 public: 87 87 88 // Events 89 void OnCredentialsProvided(const char *pszUser, 90 const char *pszPw, 91 const char *pszDomain); 88 /** Events. */ 89 void OnCredentialsProvided(); 92 90 private: 93 91 94 LONG m_cRef; /* Reference count */ 95 VBoxCredential *m_pCred; /* Our one and only credential */ 96 VBoxCredPoller *m_pPoller; /* Poller thread for credential lookup */ 97 ICredentialProviderEvents *m_pCredProvEvents; /* Used to tell our owner to re-enumerate credentials */ 98 UINT_PTR m_upAdviseContext; /* Used to tell our owner who we are when asking to re-enumerate credentials */ 99 CREDENTIAL_PROVIDER_USAGE_SCENARIO m_cpUS; /* Saved usage scenario */ 100 bool m_fGotCredentials; /* Flag indicating we got some credentials to work with */ 92 /** Interface reference count. */ 93 LONG m_cRef; 94 /** Our one and only credential. */ 95 VBoxCredential *m_pCred; 96 /** Poller thread for credential lookup. */ 97 VBoxCredPoller *m_pPoller; 98 /** Used to tell our owner to re-enumerate credentials. */ 99 ICredentialProviderEvents *m_pCredProvEvents; 100 /** Used to tell our owner who we are when asking to re-enumerate credentials. */ 101 UINT_PTR m_upAdviseContext; 102 /** Saved usage scenario. */ 103 CREDENTIAL_PROVIDER_USAGE_SCENARIO m_cpUsageScenario; 104 /** Flag indicating we got some credentials to work with. */ 105 bool m_fGotCredentials; 101 106 }; 102 107 -
trunk/src/VBox/Additions/WINNT/VBoxCredProv/VBoxCredential.cpp
r29200 r30252 15 15 #endif 16 16 17 #include <iprt/string.h> 18 17 #include "VBoxCredProv.h" 19 18 #include "VBoxCredential.h" 20 19 #include "guid.h" 21 20 22 23 VBoxCredential::VBoxCredential() : m_cRef(1), 24 m_pCredProvCredentialEvents(NULL) 21 #include <lm.h> 22 23 #include <iprt/mem.h> 24 #include <iprt/string.h> 25 26 27 struct REPORT_RESULT_STATUS_INFO 28 { 29 NTSTATUS ntsStatus; 30 NTSTATUS ntsSubstatus; 31 PWSTR pwzMessage; 32 CREDENTIAL_PROVIDER_STATUS_ICON cpsi; 33 }; 34 35 static const REPORT_RESULT_STATUS_INFO s_rgLogonStatusInfo[] = 36 { 37 { STATUS_LOGON_FAILURE, STATUS_SUCCESS, L"Incorrect password or username.", CPSI_ERROR, }, 38 { STATUS_ACCOUNT_RESTRICTION, STATUS_ACCOUNT_DISABLED, L"The account is disabled.", CPSI_WARNING }, 39 }; 40 41 42 VBoxCredential::VBoxCredential(VBoxCredProv *pProvider) : m_cRef(1), 43 m_pCredProvCredentialEvents(NULL) 25 44 { 26 45 Log(("VBoxCredential::VBoxCredential\n")); 27 46 28 47 DllAddRef(); 48 49 AssertPtr(pProvider); 50 m_pProvider = pProvider; 29 51 30 52 ZeroMemory(m_rgCredProvFieldDescriptors, sizeof(m_rgCredProvFieldDescriptors)); … … 50 72 51 73 74 void VBoxCredential::WipeString(const PWSTR pwszString) 75 { 76 if (pwszString) 77 SecureZeroMemory(pwszString, wcslen(pwszString) * sizeof(WCHAR)); 78 } 79 80 52 81 void VBoxCredential::Reset(void) 53 82 { 54 if (m_rgFieldStrings[SFI_PASSWORD]) 55 { 56 // CoTaskMemFree (below) deals with NULL, but StringCchLength does not. 57 size_t lenPassword; 58 HRESULT hr = StringCchLengthW(m_rgFieldStrings[SFI_PASSWORD], 128, &(lenPassword)); 59 if (SUCCEEDED(hr)) 60 { 61 SecureZeroMemory(m_rgFieldStrings[SFI_PASSWORD], lenPassword * sizeof(*m_rgFieldStrings[SFI_PASSWORD])); 62 } 63 else 64 { 65 // TODO: Determine how to handle count error here. 66 } 67 } 68 69 /** @todo securely clear other fields (user name, domain, ...) as well. */ 83 WipeString(m_rgFieldStrings[SFI_USERNAME]); 84 WipeString(m_rgFieldStrings[SFI_PASSWORD]); 85 WipeString(m_rgFieldStrings[SFI_DOMAINNAME]); 86 87 if (m_pCredProvCredentialEvents) 88 { 89 m_pCredProvCredentialEvents->SetFieldString(this, SFI_USERNAME, NULL); 90 m_pCredProvCredentialEvents->SetFieldString(this, SFI_PASSWORD, NULL); 91 m_pCredProvCredentialEvents->SetFieldString(this, SFI_DOMAINNAME, NULL); 92 } 70 93 } 71 94 … … 75 98 const char *pszDomain) 76 99 { 77 /* Convert credentials to unicode. */ 100 Log(("VBoxCredential::Update: User=%s, Password=%s, Domain=%s\n", 101 pszUser ? pszUser : "NULL", 102 pszPw ? pszPw : "NULL", 103 pszDomain ? pszDomain : "NULL")); 104 78 105 PWSTR *ppwszStored; 79 106 80 ppwszStored = &m_rgFieldStrings[SFI_USERNAME]; 81 CoTaskMemFree(*ppwszStored); 82 SHStrDupA(pszUser, ppwszStored); 83 84 ppwszStored = &m_rgFieldStrings[SFI_PASSWORD]; 85 CoTaskMemFree(*ppwszStored); 86 SHStrDupA(pszPw, ppwszStored); 87 88 ppwszStored = &m_rgFieldStrings[SFI_DOMAINNAME]; 89 CoTaskMemFree(*ppwszStored); 90 SHStrDupA(pszDomain, ppwszStored); 91 92 Log(("VBoxCredential::Update: user=%ls, pw=%ls, domain=%ls\n", 93 m_rgFieldStrings[SFI_USERNAME] ? m_rgFieldStrings[SFI_USERNAME] : L"<empty>", 94 m_rgFieldStrings[SFI_PASSWORD] ? m_rgFieldStrings[SFI_PASSWORD] : L"<empty>", 95 m_rgFieldStrings[SFI_DOMAINNAME] ? m_rgFieldStrings[SFI_DOMAINNAME] : L"<empty>")); 107 /* Update user name. */ 108 if (pszUser && strlen(pszUser)) 109 { 110 ppwszStored = &m_rgFieldStrings[SFI_USERNAME]; 111 CoTaskMemFree(*ppwszStored); 112 SHStrDupA(pszUser, ppwszStored); 113 114 /* 115 * In case we got a "display name" (e.g. "John Doe") 116 * instead of the real user name (e.g. "jdoe") we have 117 * to translate the data first ... 118 */ 119 PWSTR pwszAcount; 120 if (TranslateAccountName(*ppwszStored, &pwszAcount)) 121 { 122 CoTaskMemFree(*ppwszStored); 123 m_rgFieldStrings[SFI_USERNAME] = pwszAcount; 124 } 125 } 126 127 /* Update password. */ 128 if (pszPw && strlen(pszPw)) 129 { 130 ppwszStored = &m_rgFieldStrings[SFI_PASSWORD]; 131 CoTaskMemFree(*ppwszStored); 132 SHStrDupA(pszPw, ppwszStored); 133 } 134 135 /* 136 * Update domain name (can be NULL) and will 137 * be later replaced by the local computer name in the 138 * Kerberos authentication package. 139 */ 140 if (pszDomain && strlen(pszDomain)) 141 { 142 ppwszStored = &m_rgFieldStrings[SFI_DOMAINNAME]; 143 CoTaskMemFree(*ppwszStored); 144 SHStrDupA(pszDomain, ppwszStored); 145 } 146 147 Log(("VBoxCredential::Update: Finished - User=%ls, Password=%ls, Domain=%ls\n", 148 m_rgFieldStrings[SFI_USERNAME] ? m_rgFieldStrings[SFI_USERNAME] : L"NULL", 149 m_rgFieldStrings[SFI_PASSWORD] ? m_rgFieldStrings[SFI_PASSWORD] : L"NULL", 150 m_rgFieldStrings[SFI_DOMAINNAME] ? m_rgFieldStrings[SFI_DOMAINNAME] : L"NULL")); 96 151 return S_OK; 97 152 } 98 153 99 154 100 // Initializes one credential with the field information passed in. 101 // Set the value of the SFI_USERNAME field to pwzUsername. 102 // Optionally takes a password for the SetSerialization case. 155 /* 156 * Initializes one credential with the field information passed in. 157 * Set the value of the SFI_USERNAME field to pwzUsername. 158 * Optionally takes a password for the SetSerialization case. 159 */ 103 160 HRESULT VBoxCredential::Initialize(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus, 104 161 const CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR* rgcpfd, … … 111 168 m_cpUS = cpus; 112 169 113 /* Copy the field descriptors for each field. This is useful if you want to vary the 114 * field descriptors based on what Usage scenario the credential was created for. */ 170 /* 171 * Copy the field descriptors for each field. This is useful if you want to vary the 172 * field descriptors based on what Usage scenario the credential was created for. 173 */ 115 174 for (DWORD i = 0; SUCCEEDED(hr) && i < ARRAYSIZE(m_rgCredProvFieldDescriptors); i++) 116 175 { … … 126 185 127 186 128 /* LogonUI calls this in order to give us a callback in case we need to notify it of anything. 129 * Store this callback pointer for later use. */ 187 /* 188 * LogonUI calls this in order to give us a callback in case we need to notify it of anything. 189 * Store this callback pointer for later use. 190 */ 130 191 HRESULT VBoxCredential::Advise(ICredentialProviderCredentialEvents* pcpce) 131 192 { … … 145 206 Log(("VBoxCredential::UnAdvise\n")); 146 207 208 /* 209 * We're done with the current iteration, trigger a refresh of ourselves 210 * to reset credentials and to keep the logon UI clean (no stale entries anymore). 211 */ 147 212 Reset(); 213 214 /* 215 * Force a re-iteration of the provider (which will give zero credentials 216 * to try out because we just resetted our one and only a line above. 217 */ 218 if (m_pProvider) 219 m_pProvider->OnCredentialsProvided(); 148 220 149 221 if (m_pCredProvCredentialEvents) … … 154 226 155 227 156 // LogonUI calls this function when our tile is selected (zoomed). 157 // If you simply want fields to show/hide based on the selected state, 158 // there's no need to do anything here - you can set that up in the 159 // field definitions. But if you want to do something 160 // more complicated, like change the contents of a field when the tile is 161 // selected, you would do it here. 228 /* 229 * LogonUI calls this function when our tile is selected (zoomed). 230 * If you simply want fields to show/hide based on the selected state, 231 * there's no need to do anything here - you can set that up in the 232 * field definitions. But if you want to do something 233 * more complicated, like change the contents of a field when the tile is 234 * selected, you would do it here. 235 */ 162 236 HRESULT VBoxCredential::SetSelected(BOOL* pbAutoLogon) 163 237 { 164 238 Log(("VBoxCredential::SetSelected\n")); 165 239 166 /* Don't do auto logon here because it would retry too often with 240 /* 241 * Don't do auto logon here because it would retry too often with 167 242 * every credential field (user name, password, domain, ...) which makes 168 243 * winlogon wait before new login attempts can be made. … … 173 248 174 249 175 // Similarly to SetSelected, LogonUI calls this when your tile was selected 176 // and now no longer is. The most common thing to do here (which we do below) 177 // is to clear out the password field. 250 /* 251 * Similarly to SetSelected, LogonUI calls this when your tile was selected 252 * and now no longer is. The most common thing to do here (which we do below) 253 * is to clear out the password field. 254 */ 178 255 HRESULT VBoxCredential::SetDeselected() 179 256 { … … 204 281 205 282 206 // Gets info for a particular field of a tile. Called by logonUI to get information to 207 // display the tile. 283 /* 284 * Gets info for a particular field of a tile. Called by logonUI to get information to 285 * display the tile. 286 */ 208 287 HRESULT VBoxCredential::GetFieldState(DWORD dwFieldID, 209 288 CREDENTIAL_PROVIDER_FIELD_STATE* pcpfs, … … 231 310 232 311 233 // Sets ppwsz to the string value of the field at the index dwFieldID. 312 /* 313 * Searches the account name based on a display (real) name (e.g. "John Doe" -> "jdoe"). 314 * Result "ppwszAccoutName" needs to be freed with CoTaskMemFree! 315 */ 316 BOOL VBoxCredential::TranslateAccountName(PWSTR pwszDisplayName, PWSTR *ppwszAccoutName) 317 { 318 Log(("VBoxCredential::TranslateAccountName\n")); 319 320 AssertPtr(pwszDisplayName); 321 Log(("VBoxCredential::TranslateAccountName: Getting account name for '%ls' ...\n", pwszDisplayName)); 322 323 /** @todo Do we need ADS support (e.g. TranslateNameW) here? */ 324 BOOL fFound = FALSE; /* Did we find the desired user? */ 325 NET_API_STATUS nStatus; 326 DWORD dwLevel = 2; /* Detailed information about user accounts. */ 327 DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH; 328 DWORD dwEntriesRead = 0; 329 DWORD dwTotalEntries = 0; 330 DWORD dwResumeHandle = 0; 331 LPUSER_INFO_2 pBuf = NULL; 332 LPUSER_INFO_2 pCurBuf = NULL; 333 do 334 { 335 nStatus = NetUserEnum(NULL, /* Server name, NULL for localhost. */ 336 dwLevel, 337 FILTER_NORMAL_ACCOUNT, 338 (LPBYTE*)&pBuf, 339 dwPrefMaxLen, 340 &dwEntriesRead, 341 &dwTotalEntries, 342 &dwResumeHandle); 343 if ( (nStatus == NERR_Success) 344 || (nStatus == ERROR_MORE_DATA)) 345 { 346 if ((pCurBuf = pBuf) != NULL) 347 { 348 for (DWORD i = 0; i < dwEntriesRead; i++) 349 { 350 /* 351 * Search for the "display name" - that might be 352 * "John Doe" or something similar the user recognizes easier 353 * and may not the same as the "account" name (e.g. "jdoe"). 354 */ 355 if ( pCurBuf 356 && pCurBuf->usri2_full_name 357 && StrCmpI(pwszDisplayName, pCurBuf->usri2_full_name) == 0) 358 { 359 /* 360 * Copy the real user name (e.g. "jdoe") to our 361 * output buffer. 362 */ 363 LPWSTR ppwszTemp; 364 HRESULT hr = SHStrDupW(pCurBuf->usri2_name, &ppwszTemp); 365 if (hr == S_OK) 366 { 367 *ppwszAccoutName = ppwszTemp; 368 fFound = TRUE; 369 } 370 else 371 Log(("VBoxCredential::TranslateAccountName: Error copying data, hr=%08x", hr)); 372 break; 373 } 374 pCurBuf++; 375 } 376 } 377 if (pBuf != NULL) 378 { 379 NetApiBufferFree(pBuf); 380 pBuf = NULL; 381 } 382 } 383 } while (nStatus == ERROR_MORE_DATA && !fFound); 384 385 if (pBuf != NULL) 386 { 387 NetApiBufferFree(pBuf); 388 pBuf = NULL; 389 } 390 391 Log(("VBoxCredential::TranslateAccountName: Returned nStatus=%ld, fFound=%s\n", 392 nStatus, fFound ? "Yes" : "No")); 393 return fFound; 394 395 #if 0 396 DWORD dwErr = NO_ERROR; 397 ULONG cbLen = 0; 398 if ( TranslateNameW(pwszName, NameUnknown, NameUserPrincipal, NULL, &cbLen) 399 && cbLen > 0) 400 { 401 Log(("VBoxCredential::GetAccountName: Translated ADS name has %u characters\n", cbLen)); 402 403 ppwszAccoutName = (PWSTR)RTMemAlloc(cbLen * sizeof(WCHAR)); 404 AssertPtrReturn(pwszName, FALSE); 405 if (TranslateNameW(pwszName, NameUnknown, NameUserPrincipal, ppwszAccoutName, &cbLen)) 406 { 407 Log(("VBoxCredential::GetAccountName: Real ADS account name of '%ls' is '%ls'\n", 408 pwszName, ppwszAccoutName)); 409 } 410 else 411 { 412 RTMemFree(ppwszAccoutName); 413 dwErr = GetLastError(); 414 } 415 } 416 else 417 dwErr = GetLastError(); 418 /* The above method for looking up in ADS failed, try another one. */ 419 if (dwErr != NO_ERROR) 420 { 421 dwErr = NO_ERROR; 422 423 } 424 #endif 425 } 426 427 428 /* Sets ppwsz to the string value of the field at the index dwFieldID. */ 234 429 HRESULT VBoxCredential::GetStringValue(DWORD dwFieldID, 235 PWSTR* ppwsz) 236 { 237 Log(("VBoxCredential::GetStringValue: dwFieldID=%ld, pwz=%p\n", dwFieldID, ppwsz)); 238 430 PWSTR *ppwszString) 431 { 432 /* Check to make sure dwFieldID is a legitimate index. */ 239 433 HRESULT hr; 240 241 // Check to make sure dwFieldID is a legitimate index. 242 if (dwFieldID < ARRAYSIZE(m_rgCredProvFieldDescriptors) && ppwsz) 243 { 244 // Make a copy of the string and return that. The caller 245 // is responsible for freeing it. 246 hr = SHStrDupW(m_rgFieldStrings[dwFieldID], ppwsz); 434 if ( dwFieldID < ARRAYSIZE(m_rgCredProvFieldDescriptors) 435 && ppwszString) 436 { 437 switch (dwFieldID) 438 { 439 /** @todo Add more specific field IDs here if needed. */ 440 441 default: 442 443 /* 444 * Make a copy of the string and return that, the caller is responsible for freeing it. 445 * Note that there can be empty fields (like a missing domain name); handle them 446 * by writing an empty string. 447 */ 448 hr = SHStrDupW(m_rgFieldStrings[dwFieldID] ? m_rgFieldStrings[dwFieldID] : L"", 449 ppwszString); 450 break; 451 } 247 452 if (SUCCEEDED(hr)) 248 Log(("VBoxCredential::GetStringValue: dwFieldID=%ld, p wz=%ls\n", dwFieldID, *ppwsz));453 Log(("VBoxCredential::GetStringValue: dwFieldID=%ld, ppwszString=%ls\n", dwFieldID, *ppwszString)); 249 454 } 250 455 else 251 {252 456 hr = E_INVALIDARG; 253 }254 255 457 return hr; 256 458 } 257 459 258 460 259 // Sets pdwAdjacentTo to the index of the field the submit button should be 260 // adjacent to. We recommend that the submit button is placed next to the last 261 // field which the user is required to enter information in. Optional fields 262 // should be below the submit button. 461 /* 462 * Sets pdwAdjacentTo to the index of the field the submit button should be 463 * adjacent to. We recommend that the submit button is placed next to the last 464 * field which the user is required to enter information in. Optional fields 465 * should be below the submit button. 466 */ 263 467 HRESULT VBoxCredential::GetSubmitButtonValue(DWORD dwFieldID, 264 468 DWORD* pdwAdjacentTo) … … 268 472 HRESULT hr; 269 473 270 / / Validate parameters.474 /* Validate parameters. */ 271 475 if ((SFI_SUBMIT_BUTTON == dwFieldID) && pdwAdjacentTo) 272 476 { 273 / / pdwAdjacentTo is a pointer to the fieldID you want the submit button to appear next to.477 /* pdwAdjacentTo is a pointer to the fieldID you want the submit button to appear next to. */ 274 478 *pdwAdjacentTo = SFI_PASSWORD; 275 479 Log(("VBoxCredential::GetSubmitButtonValue: dwFieldID=%ld, *pdwAdjacentTo=%ld\n", dwFieldID, *pdwAdjacentTo)); … … 284 488 285 489 286 // Sets the value of a field which can accept a string as a value. 287 // This is called on each keystroke when a user types into an edit field. 490 /* 491 * Sets the value of a field which can accept a string as a value. 492 * This is called on each keystroke when a user types into an edit field. 493 */ 288 494 HRESULT VBoxCredential::SetStringValue(DWORD dwFieldID, 289 PCWSTR pwz) 290 { 291 Log(("VBoxCredential::SetStringValue: dwFieldID=%ld, pwz=%ls\n", dwFieldID, pwz)); 495 PCWSTR pcwzString) 496 { 497 Log(("VBoxCredential::SetStringValue: dwFieldID=%ld, pcwzString=%ls\n", 498 dwFieldID, pcwzString)); 292 499 293 500 HRESULT hr; 294 501 295 // Validate parameters. 502 /* 503 * We don't set any values into fields (e.g. the password, hidden 504 * by dots), instead keep it secret by resetting all credentials. 505 */ 506 #if 0 507 /* Validate parameters. */ 296 508 if ( dwFieldID < ARRAYSIZE(m_rgCredProvFieldDescriptors) 297 && ( CPFT_EDIT_TEXT == m_rgCredProvFieldDescriptors[dwFieldID].cpft ||298 CPFT_PASSWORD_TEXT == m_rgCredProvFieldDescriptors[dwFieldID].cpft))509 && ( CPFT_EDIT_TEXT == m_rgCredProvFieldDescriptors[dwFieldID].cpft 510 || CPFT_PASSWORD_TEXT == m_rgCredProvFieldDescriptors[dwFieldID].cpft)) 299 511 { 300 512 PWSTR* ppwszStored = &m_rgFieldStrings[dwFieldID]; … … 306 518 hr = E_INVALIDARG; 307 519 } 520 #else 521 hr = E_NOTIMPL; 522 #endif 308 523 return hr; 309 524 } 310 525 311 526 312 / / The following methods are for logonUI to get the values of various UI elements and then communicate313 // to the credential about what the user did in that field. However, these methods are not implemented 314 // because our tile doesn't contain these types of UI elements 315 316 /* Gets the image to show in the user tile*/527 /* 528 * The following methods are for logonUI to get the values of various UI elements and then communicate 529 * to the credential about what the user did in that field. However, these methods are not implemented 530 * because our tile doesn't contain these types of UI elements. 531 */ 317 532 HRESULT VBoxCredential::GetBitmapValue(DWORD dwFieldID, 318 533 HBITMAP* phbmp) … … 384 599 385 600 386 // Collect the username and password into a serialized credential for the correct usage scenario 387 // (logon/unlock is what's demonstrated in this sample). LogonUI then passes these credentials 388 // back to the system to log on. 389 HRESULT VBoxCredential::GetSerialization(CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE* pcpgsr, 390 CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcs, 391 PWSTR* ppwszOptionalStatusText, 392 CREDENTIAL_PROVIDER_STATUS_ICON* pcpsiOptionalStatusIcon) 393 { 394 Log(("VBoxCredential::GetSerialization: pcpgsr=%p, pcpcs=%p, ppwszOptionalStatusText=%p, pcpsiOptionalStatusIcon=%p\n", 395 pcpgsr, pcpcs, ppwszOptionalStatusText, pcpsiOptionalStatusIcon)); 601 /* 602 * Collect the username and password into a serialized credential for the correct usage scenario 603 * LogonUI then passes these credentials back to the system to log on. 604 */ 605 HRESULT VBoxCredential::GetSerialization(CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE *pcpGetSerializationResponse, 606 CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *pcpCredentialSerialization, 607 PWSTR *ppwszOptionalStatusText, 608 CREDENTIAL_PROVIDER_STATUS_ICON *pcpsiOptionalStatusIcon) 609 { 610 Log(("VBoxCredential::GetSerialization: pcpGetSerializationResponse=%p, pcpCredentialSerialization=%p, ppwszOptionalStatusText=%p, pcpsiOptionalStatusIcon=%p\n", 611 pcpGetSerializationResponse, pcpCredentialSerialization, ppwszOptionalStatusText, pcpsiOptionalStatusIcon)); 396 612 397 613 UNREFERENCED_PARAMETER(ppwszOptionalStatusText); … … 403 619 HRESULT hr; 404 620 405 WCHAR wsz [MAX_COMPUTERNAME_LENGTH+1];406 DWORD cch = ARRAYSIZE(wsz );407 if (GetComputerNameW(wsz , &cch))621 WCHAR wszComputerName[MAX_COMPUTERNAME_LENGTH+1]; 622 DWORD cch = ARRAYSIZE(wszComputerName); 623 if (GetComputerNameW(wszComputerName, &cch)) 408 624 { 409 625 /* Is a domain name missing? Then use the name of the local computer. */ 410 626 if (NULL == m_rgFieldStrings [SFI_DOMAINNAME]) 411 hr = UnicodeStringInitWithString(wsz , &kil.LogonDomainName);627 hr = UnicodeStringInitWithString(wszComputerName, &kil.LogonDomainName); 412 628 else 413 hr = UnicodeStringInitWithString( 414 m_rgFieldStrings [SFI_DOMAINNAME],&kil.LogonDomainName);629 hr = UnicodeStringInitWithString(m_rgFieldStrings [SFI_DOMAINNAME], 630 &kil.LogonDomainName); 415 631 416 632 /* Fill in the username and password. */ … … 418 634 { 419 635 hr = UnicodeStringInitWithString(m_rgFieldStrings[SFI_USERNAME], &kil.UserName); 420 421 636 if (SUCCEEDED(hr)) 422 637 { 423 638 hr = UnicodeStringInitWithString(m_rgFieldStrings[SFI_PASSWORD], &kil.Password); 424 425 639 if (SUCCEEDED(hr)) 426 640 { 427 / / Allocate copies of, and package, the strings in a binary blob641 /* Allocate copies of, and package, the strings in a binary blob. */ 428 642 kil.MessageType = KerbInteractiveLogon; 429 hr = KerbInteractiveLogonPack(kil, &pcpcs->rgbSerialization, &pcpcs->cbSerialization); 430 643 hr = KerbInteractiveLogonPack(kil, 644 &pcpCredentialSerialization->rgbSerialization, 645 &pcpCredentialSerialization->cbSerialization); 431 646 if (SUCCEEDED(hr)) 432 647 { … … 435 650 if (SUCCEEDED(hr)) 436 651 { 437 pcpcs->ulAuthenticationPackage = ulAuthPackage; 438 pcpcs->clsidCredentialProvider = CLSID_VBoxCredProvider; 439 440 // At this point the credential has created the serialized credential used for logon 441 // By setting this to CPGSR_RETURN_CREDENTIAL_FINISHED we are letting logonUI know 442 // that we have all the information we need and it should attempt to submit the 443 // serialized credential. 444 *pcpgsr = CPGSR_RETURN_CREDENTIAL_FINISHED; 652 pcpCredentialSerialization->ulAuthenticationPackage = ulAuthPackage; 653 pcpCredentialSerialization->clsidCredentialProvider = CLSID_VBoxCredProvider; 654 655 /* 656 * At this point the credential has created the serialized credential used for logon 657 * By setting this to CPGSR_RETURN_CREDENTIAL_FINISHED we are letting logonUI know 658 * that we have all the information we need and it should attempt to submit the 659 * serialized credential. 660 */ 661 *pcpGetSerializationResponse = CPGSR_RETURN_CREDENTIAL_FINISHED; 445 662 } 446 663 } … … 460 677 461 678 462 struct REPORT_RESULT_STATUS_INFO 463 { 464 NTSTATUS ntsStatus; 465 NTSTATUS ntsSubstatus; 466 PWSTR pwzMessage; 467 CREDENTIAL_PROVIDER_STATUS_ICON cpsi; 468 }; 469 470 static const REPORT_RESULT_STATUS_INFO s_rgLogonStatusInfo[] = 471 { 472 { STATUS_LOGON_FAILURE, STATUS_SUCCESS, L"Incorrect password or username.", CPSI_ERROR, }, 473 { STATUS_ACCOUNT_RESTRICTION, STATUS_ACCOUNT_DISABLED, L"The account is disabled.", CPSI_WARNING }, 474 }; 475 476 477 // ReportResult is completely optional. Its purpose is to allow a credential to customize the string 478 // and the icon displayed in the case of a logon failure. For example, we have chosen to 479 // customize the error shown in the case of bad username/password and in the case of the account 480 // being disabled. 679 /* 680 * ReportResult is completely optional. Its purpose is to allow a credential to customize the string 681 * and the icon displayed in the case of a logon failure. For example, we have chosen to 682 * customize the error shown in the case of bad username/password and in the case of the account 683 * being disabled. 684 */ 481 685 HRESULT VBoxCredential::ReportResult(NTSTATUS ntsStatus, 482 686 NTSTATUS ntsSubstatus, … … 489 693 DWORD dwStatusInfo = (DWORD)-1; 490 694 491 / / Look for a match on status and substatus.695 /* Look for a match on status and substatus. */ 492 696 for (DWORD i = 0; i < ARRAYSIZE(s_rgLogonStatusInfo); i++) 493 697 { … … 502 706 { 503 707 if (SUCCEEDED(SHStrDupW(s_rgLogonStatusInfo[dwStatusInfo].pwzMessage, ppwszOptionalStatusText))) 504 {505 708 *pcpsiOptionalStatusIcon = s_rgLogonStatusInfo[dwStatusInfo].cpsi; 506 } 507 } 508 509 /* Try to lookup a text message for error code */ 709 } 710 711 /* Try to lookup a text message for error code. */ 510 712 LPVOID lpMessageBuffer = NULL; 511 HMODULE h Mod= LoadLibrary(L"NTDLL.DLL");512 if (h Mod)713 HMODULE hNtDLL = LoadLibrary(L"NTDLL.DLL"); 714 if (hNtDLL) 513 715 { 514 716 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER 515 717 | FORMAT_MESSAGE_FROM_SYSTEM 516 718 | FORMAT_MESSAGE_FROM_HMODULE, 517 h Mod,719 hNtDLL, 518 720 ntsStatus, 519 721 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), … … 521 723 0, 522 724 NULL); 725 FreeLibrary(hNtDLL); 523 726 } 524 727 525 728 Log(("VBoxCredential::ReportResult: ntsStatus=%ld, ntsSubstatus=%ld, ppwszOptionalStatusText=%p, pcpsiOptionalStatusIcon=%p, dwStatusInfo=%ld, Message=%ls\n", 526 ntsStatus, ntsSubstatus, ppwszOptionalStatusText, pcpsiOptionalStatusIcon, dwStatusInfo, lpMessageBuffer ? lpMessageBuffer : L"none")); 729 ntsStatus, ntsSubstatus, ppwszOptionalStatusText, pcpsiOptionalStatusIcon, dwStatusInfo, lpMessageBuffer ? lpMessageBuffer : L"<None>")); 730 731 /* Print to user-friendly message to release log. */ 732 if (FAILED(ntsStatus)) 733 { 734 if (lpMessageBuffer) 735 LogRel(("VBoxCredProv: %ls\n", lpMessageBuffer)); 736 /* Login attempt failed; reset and clear all data. */ 737 Reset(); 738 } 527 739 528 740 if (lpMessageBuffer) 529 741 LocalFree(lpMessageBuffer); 530 FreeLibrary(hMod); 531 532 // Since NULL is a valid value for *ppwszOptionalStatusText and *pcpsiOptionalStatusIcon 533 // this function can't fail. 742 743 /* 744 * Since NULL is a valid value for *ppwszOptionalStatusText and *pcpsiOptionalStatusIcon 745 * this function can't fail 746 */ 534 747 return S_OK; 535 748 } -
trunk/src/VBox/Additions/WINNT/VBoxCredProv/VBoxCredential.h
r29200 r30252 18 18 #include "resource.h" 19 19 20 class VBoxCredProv; 21 20 22 class VBoxCredential : public ICredentialProviderCredential 21 23 { 24 public: 25 VBoxCredential(VBoxCredProv *pProvider); 26 virtual ~VBoxCredential(); 27 22 28 public: 23 29 … … 83 89 IFACEMETHODIMP GetSubmitButtonValue(DWORD dwFieldID, DWORD* pdwAdjacentTo); 84 90 85 IFACEMETHODIMP SetStringValue(DWORD dwFieldID, PCWSTR p wz);91 IFACEMETHODIMP SetStringValue(DWORD dwFieldID, PCWSTR pcwzString); 86 92 IFACEMETHODIMP SetCheckboxValue(DWORD dwFieldID, BOOL bChecked); 87 93 IFACEMETHODIMP SetComboBoxSelectedValue(DWORD dwFieldID, DWORD dwSelectedItem); 88 94 IFACEMETHODIMP CommandLinkClicked(DWORD dwFieldID); 89 95 90 IFACEMETHODIMP GetSerialization(CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE * pcpgsr,91 CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcs,92 PWSTR*ppwszOptionalStatusText,93 CREDENTIAL_PROVIDER_STATUS_ICON*pcpsiOptionalStatusIcon);96 IFACEMETHODIMP GetSerialization(CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE *pcpGetSerializationResponse, 97 CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *pcpCredentialSerialization, 98 PWSTR *ppwszOptionalStatusText, 99 CREDENTIAL_PROVIDER_STATUS_ICON *pcpsiOptionalStatusIcon); 94 100 IFACEMETHODIMP ReportResult(NTSTATUS ntsStatus, 95 101 NTSTATUS ntsSubstatus, … … 98 104 99 105 public: 100 106 void WipeString(const PWSTR pwszString); 101 107 void Reset(); 102 103 108 HRESULT Initialize(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus, 104 109 const CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR* rgcpfd, 105 110 const FIELD_STATE_PAIR* rgfsp); 106 107 111 int Update(const char *pszUser, 108 112 const char *pszPw, 109 113 const char *pszDomain); 110 111 VBoxCredential(); 112 113 virtual ~VBoxCredential(); 114 114 BOOL TranslateAccountName(PWSTR pwszDisplayName, PWSTR *ppwszAccoutName); 115 115 private: 116 116 117 /** @todo Merge all arrays which depend on SFI_NUM_FIELDS below 118 into an own structure! */ 119 120 /** Pointer to parent. */ 121 VBoxCredProv *m_pProvider; 122 /** Internal reference count. */ 117 123 LONG m_cRef; 118 CREDENTIAL_PROVIDER_USAGE_SCENARIO m_cpUS; /* The usage scenario for which we were enumerated */ 119 CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR m_rgCredProvFieldDescriptors[SFI_NUM_FIELDS]; /* Holding type and name of each field in the tile */ 120 FIELD_STATE_PAIR m_rgFieldStatePairs[SFI_NUM_FIELDS]; /* Holding state of each field in the tile */ 121 PWSTR m_rgFieldStrings[SFI_NUM_FIELDS]; /* Holding string value of each field. This is different from the name of 122 * the field held in m_rgCredProvFieldDescriptors */ 124 /** The usage scenario for which we were enumerated. */ 125 CREDENTIAL_PROVIDER_USAGE_SCENARIO m_cpUS; 126 /** Holding type and name of each field in the tile. */ 127 CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR m_rgCredProvFieldDescriptors[SFI_NUM_FIELDS]; 128 /** Holding state of each field in the tile. */ 129 FIELD_STATE_PAIR m_rgFieldStatePairs[SFI_NUM_FIELDS]; 130 /** Holding string value of each field. This is different from the name of 131 the field held in m_rgCredProvFieldDescriptors. */ 132 PWSTR m_rgFieldStrings[SFI_NUM_FIELDS]; 123 133 ICredentialProviderCredentialEvents *m_pCredProvCredentialEvents; 124 134 -
trunk/src/VBox/Additions/WINNT/VBoxCredProv/dll.cpp
r29200 r30252 26 26 * Global Variables * 27 27 *******************************************************************************/ 28 static LONG g_cRef = 0; /* Global dll reference count*/29 HINSTANCE g_h inst = NULL; /* Global dll hinstance*/28 static LONG g_cRef = 0; /* Global DLL reference count. */ 29 HINSTANCE g_hDllInst = NULL; /* Global DLL hinstance. */ 30 30 31 31 … … 35 35 if (CLSID_VBoxCredProvider == rclsid) 36 36 { 37 CClassFactory* p cf= new CClassFactory;38 if (p cf)37 CClassFactory* pClassFactory = new CClassFactory; 38 if (pClassFactory) 39 39 { 40 hr = p cf->QueryInterface(riid, ppv);41 p cf->Release();40 hr = pClassFactory->QueryInterface(riid, ppv); 41 pClassFactory->Release(); 42 42 } 43 43 else … … 55 55 56 56 BOOL WINAPI DllMain(HINSTANCE hinstDll, 57 DWORD dwReason,58 LPVOID pReserved)57 DWORD dwReason, 58 LPVOID pReserved) 59 59 { 60 60 UNREFERENCED_PARAMETER(pReserved); … … 75 75 } 76 76 77 g_h inst = hinstDll;77 g_hDllInst = hinstDll; 78 78 return TRUE; 79 79 } … … 92 92 93 93 94 /* DLL entry point */ 94 LONG DllGetRefCount() 95 { 96 return g_cRef; 97 } 98 99 100 /* DLL entry point. */ 95 101 STDAPI DllCanUnloadNow() 96 102 { -
trunk/src/VBox/Additions/WINNT/VBoxCredProv/dll.h
r29200 r30252 19 19 #include <VBox/Log.h> 20 20 21 extern HINSTANCE g_h inst;21 extern HINSTANCE g_hDllInst; 22 22 23 23 LONG DllAddRef(); 24 24 LONG DllRelease(); 25 LONG DllGetRefCount(); 25 26 26 27 extern HRESULT VBoxCredProv_CreateInstance(REFIID riid, void** ppv);
Note:
See TracChangeset
for help on using the changeset viewer.