Index: /trunk/src/VBox/Additions/WINNT/VBoxCredProv/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxCredProv/Makefile.kmk	(revision 30251)
+++ /trunk/src/VBox/Additions/WINNT/VBoxCredProv/Makefile.kmk	(revision 30252)
@@ -45,10 +45,12 @@
 	$(VBOX_PATH_PSDK_200702)/Lib/Credui.Lib \
 	$(VBOX_PATH_PSDK_200702)/Lib/Secur32.Lib \
-	$(VBOX_PATH_PSDK_200702)/Lib/ShLwApi.Lib
+	$(VBOX_PATH_PSDK_200702)/Lib/ShLwApi.Lib \
+	$(VBOX_PATH_PSDK_200702)/Lib/netapi32.lib
 VBoxCredProv_LIBS.amd64  := \
 	$(VBOX_PATH_PSDK_200702)/Lib/x64/Uuid.Lib \
 	$(VBOX_PATH_PSDK_200702)/Lib/x64/Credui.Lib \
 	$(VBOX_PATH_PSDK_200702)/Lib/x64/Secur32.Lib \
-	$(VBOX_PATH_PSDK_200702)/Lib/x64/ShLwApi.Lib
+	$(VBOX_PATH_PSDK_200702)/Lib/x64/ShLwApi.Lib \
+	$(VBOX_PATH_PSDK_200702)/Lib/x64/netapi32.Lib
 
 VBoxCredProv_LIBS    += \
Index: /trunk/src/VBox/Additions/WINNT/VBoxCredProv/VBoxCredPoller.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxCredProv/VBoxCredPoller.cpp	(revision 30251)
+++ /trunk/src/VBox/Additions/WINNT/VBoxCredProv/VBoxCredPoller.cpp	(revision 30252)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2009 Oracle Corporation
+ * Copyright (C) 2010 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -57,5 +57,5 @@
     m_pProv->AddRef();
 
-    /* don't create more than one of them */
+    /* Don't create more than one of them. */
     if (m_hThreadPoller != NIL_RTTHREAD)
     {
@@ -68,5 +68,5 @@
         Log(("VBoxCredPoller: Could not init critical section! rc = %Rrc\n", rc));
 
-    /* create the poller thread */
+    /* Create the poller thread. */
     rc = RTThreadCreate(&m_hThreadPoller, VBoxCredPoller::threadPoller, this, 0, RTTHREADTYPE_INFREQUENT_POLLER,
                         RTTHREADFLAGS_WAITABLE, "creds");
@@ -90,10 +90,10 @@
     }
 
-    /* Post termination event semaphore */
+    /* Post termination event semaphore. */
     int rc = RTThreadUserSignal(m_hThreadPoller);
     if (RT_SUCCESS(rc))
     {
         Log(("VBoxCredPoller::Shutdown: Waiting for thread to terminate\n"));
-        /* wait until the thread has terminated */
+        /* Wait until the thread has terminated. */
         rc = RTThreadWait(m_hThreadPoller, RT_INDEFINITE_WAIT, NULL);
         Log(("VBoxCredPoller::Shutdown: Thread has (probably) terminated (rc = %Rrc)\n", rc));
@@ -101,5 +101,5 @@
     else
     {
-        /* failed to signal the thread - very unlikely - so no point in waiting long. */
+        /* Failed to signal the thread - very unlikely - so no point in waiting long. */
         Log(("VBoxCredPoller::Shutdown: Failed to signal semaphore, rc = %Rrc\n", rc));
         rc = RTThreadWait(m_hThreadPoller, 100, NULL);
@@ -125,40 +125,23 @@
     credentialsReset();
 
-    /* get credentials */
+    /* Get credentials. */
     RTCritSectEnter(&m_csCredUpate);
     int rc = VbglR3CredentialsRetrieve(&m_pszUser, &m_pszPw, &m_pszDomain);
     if (RT_SUCCESS(rc))
     {
-        Log(("VBoxCredPoller::credentialsRetrieve: Credentials retrieved (user=%s, pw=%s, domain=%s)\n",
+        /* NULL/free domain if it's empty (""). */
+        if (m_pszDomain && strlen(m_pszDomain) == 0)
+        {
+            RTStrFree(m_pszDomain);
+            m_pszDomain = NULL;
+        }
+
+        Log(("VBoxCredPoller::credentialsRetrieve: Credentials retrieved (User=%s, Password=%s, Domain=%s)\n",
              m_pszUser ? m_pszUser : "<empty>",
              m_pszPw ? m_pszPw : "<empty>",
-             m_pszDomain ? m_pszDomain : "<empty>"));
-
-        /* allocated but empty? delete and re-fill with default value in block below. */
-        if (strlen(m_pszDomain) == 0)
-        {
-            RTStrFree(m_pszDomain);
-            m_pszDomain = NULL;
-        }
-
-        /* if we don't have a domain specified, fill in a dot (".") specifying the
-         * local computer. */
-        if (m_pszDomain == NULL)
-        {
-            rc = RTStrAPrintf(&m_pszDomain, ".");
-            if (RT_FAILURE(rc))
-                Log(("VBoxCredPoller::credentialsRetrieve: Could not set default domain name, rc = %Rrc", rc));
-            else
-                Log(("VBoxCredPoller::credentialsRetrieve: No domain name given, set default value to: %s\n", m_pszDomain));
-        }
-    }
-
-    /* if all went fine, notify parent */
-    if (RT_SUCCESS(rc))
-    {
+             m_pszDomain ? m_pszDomain : "NULL"));
+
         AssertPtr(m_pProv);
-        m_pProv->OnCredentialsProvided(m_pszUser,
-                                       m_pszPw,
-                                       m_pszDomain);
+        m_pProv->OnCredentialsProvided();
     }
     RTCritSectLeave(&m_csCredUpate);
@@ -216,7 +199,5 @@
         if (RT_FAILURE(rc))
         {
-            if (rc == VERR_NOT_FOUND)
-                Log(("VBoxCredPoller::threadPoller: No credentials availabe.\n"));
-            else
+            if (rc != VERR_NOT_FOUND)
                 Log(("VBoxCredPoller::threadPoller: Could not retrieve credentials! rc = %Rc\n", rc));
         }
@@ -228,9 +209,9 @@
         }
 
-        /* wait a bit */
+        /* Wait a bit. */
         if (RTThreadUserWait(ThreadSelf, 500) == VINF_SUCCESS)
         {
             Log(("VBoxCredPoller::threadPoller: Terminating\n"));
-            /* we were asked to terminate, do that instantly! */
+            /* We were asked to terminate, do that instantly! */
             return 0;
         }
Index: /trunk/src/VBox/Additions/WINNT/VBoxCredProv/VBoxCredProv.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxCredProv/VBoxCredProv.cpp	(revision 30251)
+++ /trunk/src/VBox/Additions/WINNT/VBoxCredProv/VBoxCredProv.cpp	(revision 30252)
@@ -20,5 +20,5 @@
 
 
-VBoxCredProv::VBoxCredProv(void):
+VBoxCredProv::VBoxCredProv(void) :
     m_cRef(1),
     m_pPoller(NULL),
@@ -37,11 +37,6 @@
 
     if (l == 1) /* First instance? */
-    {
-        LogRel(("VBoxCredProv: DLL instance created: %ld\n", l));
-    }
-    else
-    {
-        Log(("VBoxCredProv: DLL instance %ld created.\n", l));
-    }
+        LogRel(("VBoxCredProv: Loaded.\n"));
+    Log(("VBoxCredProv: DLL refcount (load) = %ld\n", l));
 }
 
@@ -49,4 +44,6 @@
 VBoxCredProv::~VBoxCredProv(void)
 {
+    Log(("VBoxCredProv::~VBoxCredProv\n"));
+
     if (m_pCred != NULL)
     {
@@ -62,5 +59,8 @@
     }
 
-    Log(("VBoxCredProv: DLL instance unloaded.\n"));
+    LONG lRefCount = DllGetRefCount();
+    if (lRefCount == 1) /* First (=last) instance unloaded? */
+        LogRel(("VBoxCredProv: Unloaded.\n"));
+    Log(("VBoxCredProv: DLL refcount (unload) = %ld\n", lRefCount));
 
     VbglR3Term();
@@ -69,18 +69,20 @@
 
 
-/* SetUsageScenario is the provider's cue that it's going to be asked for tiles
+/* 
+ * SetUsageScenario is the provider's cue that it's going to be asked for tiles
  * in a subsequent call. This call happens after the user pressed CTRL+ALT+DEL
- * and we need to handle the CPUS_LOGON event. */
-HRESULT VBoxCredProv::SetUsageScenario(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus,
-                                       DWORD dwFlags)
+ * and we need to handle the CPUS_LOGON event. 
+ */
+HRESULT VBoxCredProv::SetUsageScenario(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpUsageScenario,
+                                       DWORD                              dwFlags)
 {
     UNREFERENCED_PARAMETER(dwFlags);
     HRESULT hr;
 
-    m_cpUS = cpus;
+    m_cpUsageScenario = cpUsageScenario;
 
     /* Decide which scenarios to support here. Returning E_NOTIMPL simply tells the caller
      * that we're not designed for that scenario. */
-    switch (m_cpUS)
+    switch (m_cpUsageScenario)
     {
         case CPUS_LOGON:
@@ -97,11 +99,12 @@
             if (m_pCred == NULL)
             {
-                m_pCred = new VBoxCredential();
+                m_pCred = new VBoxCredential(this);
 
                 /* All stuff allocated? */
                 if (m_pCred != NULL)
                 {
-                    hr = m_pCred->Initialize(m_cpUS,
-                        s_rgCredProvFieldDescriptors, s_rgFieldStatePairs);
+                    hr = m_pCred->Initialize(m_cpUsageScenario,
+                                             s_rgCredProvFieldDescriptors, 
+                                             s_rgFieldStatePairs);
                 }
                 else
@@ -128,7 +131,8 @@
             break;
 
+        case CPUS_CHANGE_PASSWORD:
         case CPUS_CREDUI:
-        case CPUS_CHANGE_PASSWORD:
-
+        case CPUS_PLAP:
+        
             hr = E_NOTIMPL;
             break;
@@ -140,32 +144,35 @@
     }
 
-    Log(("VBoxCredProv::SetUsageScenario returned 0x%08x (CPUS: %d, Flags: %ld)\n", hr, cpus, dwFlags));
+    Log(("VBoxCredProv::SetUsageScenario returned 0x%08x (cpUS: %d, Flags: %ld)\n", hr, cpUsageScenario, dwFlags));
     return hr;
 }
 
 
-// SetSerialization takes the kind of buffer that you would normally return to LogonUI for
-// an authentication attempt.  It's the opposite of ICredentialProviderCredential::GetSerialization.
-// GetSerialization is implement by a credential and serializes that credential.  Instead,
-// SetSerialization takes the serialization and uses it to create a credential.
-//
-// SetSerialization is called for two main scenarios.  The first scenario is in the credui case
-// where it is prepopulating a tile with credentials that the user chose to store in the OS.
-// The second situation is in a remote logon case where the remote client may wish to
-// prepopulate a tile with a username, or in some cases, completely populate the tile and
-// use it to logon without showing any UI.
-//
-STDMETHODIMP VBoxCredProv::SetSerialization(const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *pcpcs)
-{
-    UNREFERENCED_PARAMETER(pcpcs);
+/* 
+ * SetSerialization takes the kind of buffer that you would normally return to LogonUI for
+ * an authentication attempt.  It's the opposite of ICredentialProviderCredential::GetSerialization.
+ * GetSerialization is implement by a credential and serializes that credential.  Instead,
+ * SetSerialization takes the serialization and uses it to create a credential.
+ *
+ * SetSerialization is called for two main scenarios.  The first scenario is in the credUI case
+ * where it is prepopulating a tile with credentials that the user chose to store in the OS.
+ * The second situation is in a remote logon case where the remote client may wish to
+ * prepopulate a tile with a username, or in some cases, completely populate the tile and
+ * use it to logon without showing any UI.
+ */
+STDMETHODIMP VBoxCredProv::SetSerialization(const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *pcpCredentialSerialization)
+{
+    UNREFERENCED_PARAMETER(pcpCredentialSerialization);
     return E_NOTIMPL;
 }
 
 
-/* Called by LogonUI to give you a callback.  Providers often use the callback if they
+/* 
+ * Called by LogonUI to give you a callback.  Providers often use the callback if they
  * some event would cause them to need to change the set of tiles (visible UI elements)
- * that they enumerated. */
-HRESULT VBoxCredProv::Advise(ICredentialProviderEvents* pcpe,
-                             UINT_PTR upAdviseContext)
+ * that they enumerated. 
+ */
+HRESULT VBoxCredProv::Advise(ICredentialProviderEvents *pcpEvents,
+                             UINT_PTR                   upAdviseContext)
 {
     Log(("VBoxCredProv::Advise\n"));
@@ -174,10 +181,12 @@
         m_pCredProvEvents->Release();
 
-    m_pCredProvEvents = pcpe;
+    m_pCredProvEvents = pcpEvents;
     Assert(m_pCredProvEvents);
     m_pCredProvEvents->AddRef();
 
-    /* Save advice context for later use when binding to
-       certain ICredentialProviderEvents events. */
+    /*
+     * Save advice context for later use when binding to
+     * certain ICredentialProviderEvents events. 
+     */
     m_upAdviseContext = upAdviseContext;
     return S_OK;
@@ -190,19 +199,22 @@
     Log(("VBoxCredProv::UnAdvise\n"));
     if (m_pCredProvEvents != NULL)
-    {
+    {      
         m_pCredProvEvents->Release();
         m_pCredProvEvents = NULL;
     }
+
     return S_OK;
 }
 
 
-// Called by LogonUI to determine the number of fields in your tiles.  This
-// does mean that all your tiles must have the same number of fields.
-// This number must include both visible and invisible fields. If you want a tile
-// to have different fields from the other tiles you enumerate for a given usage
-// scenario you must include them all in this count and then hide/show them as desired
-// using the field descriptors.
-HRESULT VBoxCredProv::GetFieldDescriptorCount(DWORD* pdwCount)
+/* 
+ * Called by LogonUI to determine the number of fields in your tiles. This
+ * does mean that all your tiles must have the same number of fields.
+ * This number must include both visible and invisible fields. If you want a tile
+ * to have different fields from the other tiles you enumerate for a given usage
+ * scenario you must include them all in this count and then hide/show them as desired
+ * using the field descriptors.
+ */
+HRESULT VBoxCredProv::GetFieldDescriptorCount(DWORD *pdwCount)
 {
     Assert(pdwCount);
@@ -214,14 +226,14 @@
 
 
-// Gets the field descriptor for a particular field
+/* Gets the field descriptor for a particular field. */
 HRESULT VBoxCredProv::GetFieldDescriptorAt(DWORD dwIndex,
-                                           CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR **ppcpfd)
+                                           CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR **ppcpFieldDescriptor)
 {
     /* Verify dwIndex is a valid field */
     HRESULT hr;
     if (   dwIndex < SFI_NUM_FIELDS
-        && ppcpfd)
-    {
-        hr = FieldDescriptorCoAllocCopy(s_rgCredProvFieldDescriptors[dwIndex], ppcpfd);
+        && ppcpFieldDescriptor)
+    {
+        hr = FieldDescriptorCoAllocCopy(s_rgCredProvFieldDescriptors[dwIndex], ppcpFieldDescriptor);
     }
     else
@@ -231,19 +243,21 @@
 
     Log(("VBoxCredProv::GetFieldDescriptorAt: hr=0x%08x, index=%ld, ppcpfd=%p\n",
-         hr, dwIndex, ppcpfd));
+         hr, dwIndex, ppcpFieldDescriptor));
     return hr;
 }
 
 
-// Sets pdwCount to the number of tiles that we wish to show at this time.
-// Sets pdwDefault to the index of the tile which should be used as the default.
-//
-// The default tile is the tile which will be shown in the zoomed view by default. If
-// more than one provider specifies a default tile the behavior is the last used cred
-// prov gets to specify the default tile to be displayed
-//
-// If *pbAutoLogonWithDefault is TRUE, LogonUI will immediately call GetSerialization
-// on the credential you've specified as the default and will submit that credential
-// for authentication without showing any further UI.
+/* 
+ * Sets pdwCount to the number of tiles that we wish to show at this time.
+ * Sets pdwDefault to the index of the tile which should be used as the default.
+ *
+ * The default tile is the tile which will be shown in the zoomed view by default. If
+ * more than one provider specifies a default tile the behavior is the last used cred
+ * prov gets to specify the default tile to be displayed
+ *
+ * If *pbAutoLogonWithDefault is TRUE, LogonUI will immediately call GetSerialization
+ * on the credential you've specified as the default and will submit that credential
+ * for authentication without showing any further UI.
+ */
 HRESULT VBoxCredProv::GetCredentialCount(DWORD *pdwCount,
                                          DWORD *pdwDefault,
@@ -265,7 +279,7 @@
     if (fGotCredentials)
     {
-        *pdwCount = 1;                   /* This provider always has the same number of credentials (1) */
+        *pdwCount = 1;                   /* This provider always has the same number of credentials (1). */
         *pdwDefault = 0;                 /* The credential we provide is *always* at index 0! */
-        *pbAutoLogonWithDefault = TRUE;  /* We always at least try to auto-login (if password is correct) */
+        *pbAutoLogonWithDefault = TRUE;  /* We always at least try to auto-login (if password is correct). */
     }
     else
@@ -282,12 +296,14 @@
 
 
-// Returns the credential at the index specified by dwIndex. This function is called by logonUI to enumerate
-// the tiles.
-HRESULT VBoxCredProv::GetCredentialAt(DWORD dwIndex,
-                                      ICredentialProviderCredential **ppcpc)
+/*
+ * Returns the credential at the index specified by dwIndex. This function is called by logonUI to enumerate
+ * the tiles.
+ */
+HRESULT VBoxCredProv::GetCredentialAt(DWORD                           dwIndex,
+                                      ICredentialProviderCredential **ppCredProvCredential)
 {
     HRESULT hr;
 
-    Log(("VBoxCredProv::GetCredentialAt: Index=%ld, ppcpc=%p\n", dwIndex, ppcpc));
+    Log(("VBoxCredProv::GetCredentialAt: Index=%ld, ppCredProvCredential=%p\n", dwIndex, ppCredProvCredential));
 
     if (m_pCred == NULL)
@@ -297,15 +313,27 @@
     }
 
-    /* Validate parameters (we only have one credential) */
+    /* Validate parameters (we only have one credential). */
     if(   dwIndex == 0
-       && ppcpc)
-    {
-        hr = m_pCred->QueryInterface(IID_ICredentialProviderCredential, reinterpret_cast<void**>(ppcpc));
+       && ppCredProvCredential)
+    {
+        hr = m_pCred->QueryInterface(IID_ICredentialProviderCredential, 
+                                     reinterpret_cast<void**>(ppCredProvCredential));
     }
     else
     {
+        Log(("VBoxCredProv::GetCredentialAt: More than one credential not supported!\n"));
         hr = E_INVALIDARG;
     }
     return hr;
+}
+
+
+/* Do a credential re-enumeration if we got the event to do so. */
+void VBoxCredProv::OnCredentialsProvided()
+{
+    Log(("VBoxCredProv::OnCredentialsProvided\n"));
+
+    if (m_pCredProvEvents != NULL)
+        m_pCredProvEvents->CredentialsChanged(m_upAdviseContext);
 }
 
@@ -329,14 +357,2 @@
 }
 
-
-/* Do a credential re-enumeration if we got the event to do so. */
-void VBoxCredProv::OnCredentialsProvided(const char *pszUser,
-                                         const char *pszPw,
-                                         const char *pszDomain)
-{
-    Log(("VBoxCredProv::OnCredentialsProvided\n"));
-
-    if (m_pCredProvEvents != NULL)
-        m_pCredProvEvents->CredentialsChanged(m_upAdviseContext);
-}
-
Index: /trunk/src/VBox/Additions/WINNT/VBoxCredProv/VBoxCredProv.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxCredProv/VBoxCredProv.h	(revision 30251)
+++ /trunk/src/VBox/Additions/WINNT/VBoxCredProv/VBoxCredProv.h	(revision 30252)
@@ -25,5 +25,5 @@
     public:
 
-        // IUnknown
+        /** IUnknown methods. */
         STDMETHOD_(ULONG, AddRef)()
         {
@@ -61,13 +61,13 @@
     public:
 
-        // ICredentialProvider
-        IFACEMETHODIMP SetUsageScenario(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus, DWORD dwFlags);
-        IFACEMETHODIMP SetSerialization(const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *pcpcs);
+        /** ICredentialProvider interface. */
+        IFACEMETHODIMP SetUsageScenario(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpUsageScenario, DWORD dwFlags);
+        IFACEMETHODIMP SetSerialization(const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *pcpCredentialSerialization);
 
-        IFACEMETHODIMP Advise(__in ICredentialProviderEvents *pcpe, UINT_PTR upAdviseContext);
+        IFACEMETHODIMP Advise(__in ICredentialProviderEvents *pcpEvents, UINT_PTR upAdviseContext);
         IFACEMETHODIMP UnAdvise();
 
         IFACEMETHODIMP GetFieldDescriptorCount(__out DWORD* pdwCount);
-        IFACEMETHODIMP GetFieldDescriptorAt(DWORD dwIndex,  __deref_out CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR **ppcpfd);
+        IFACEMETHODIMP GetFieldDescriptorAt(DWORD dwIndex,  __deref_out CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR **ppcpFieldDescriptor);
 
         IFACEMETHODIMP GetCredentialCount(__out DWORD *pdwCount,
@@ -82,21 +82,26 @@
 
         VBoxCredProv(void);
-        __override ~VBoxCredProv(void);
+        virtual ~VBoxCredProv(void);
 
     public:
 
-        // Events
-        void OnCredentialsProvided(const char *pszUser,
-                                   const char *pszPw,
-                                   const char *pszDomain);
+        /** Events. */
+        void OnCredentialsProvided();
     private:
 
-        LONG                                     m_cRef;                              /* Reference count */
-        VBoxCredential                          *m_pCred;                             /* Our one and only credential */
-        VBoxCredPoller                          *m_pPoller;                           /* Poller thread for credential lookup */
-        ICredentialProviderEvents               *m_pCredProvEvents;                   /* Used to tell our owner to re-enumerate credentials */
-        UINT_PTR                                 m_upAdviseContext;                   /* Used to tell our owner who we are when asking to re-enumerate credentials */
-        CREDENTIAL_PROVIDER_USAGE_SCENARIO       m_cpUS;                              /* Saved usage scenario */
-        bool                                     m_fGotCredentials;                   /* Flag indicating we got some credentials to work with */
+        /** Interface reference count. */
+        LONG                                     m_cRef;                              
+        /** Our one and only credential. */
+        VBoxCredential                          *m_pCred;  
+        /** Poller thread for credential lookup. */                           
+        VBoxCredPoller                          *m_pPoller;
+        /** Used to tell our owner to re-enumerate credentials. */
+        ICredentialProviderEvents               *m_pCredProvEvents;
+        /** Used to tell our owner who we are when asking to re-enumerate credentials. */           
+        UINT_PTR                                 m_upAdviseContext;
+        /** Saved usage scenario. */
+        CREDENTIAL_PROVIDER_USAGE_SCENARIO       m_cpUsageScenario;
+        /** Flag indicating we got some credentials to work with. */
+        bool                                     m_fGotCredentials;
 };
 
Index: /trunk/src/VBox/Additions/WINNT/VBoxCredProv/VBoxCredential.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxCredProv/VBoxCredential.cpp	(revision 30251)
+++ /trunk/src/VBox/Additions/WINNT/VBoxCredProv/VBoxCredential.cpp	(revision 30252)
@@ -15,16 +15,38 @@
 #endif
 
-#include <iprt/string.h>
-
+#include "VBoxCredProv.h"
 #include "VBoxCredential.h"
 #include "guid.h"
 
-
-VBoxCredential::VBoxCredential() : m_cRef(1),
-                                   m_pCredProvCredentialEvents(NULL)
+#include <lm.h>
+
+#include <iprt/mem.h>
+#include <iprt/string.h>
+
+
+struct REPORT_RESULT_STATUS_INFO
+{
+    NTSTATUS ntsStatus;
+    NTSTATUS ntsSubstatus;
+    PWSTR     pwzMessage;
+    CREDENTIAL_PROVIDER_STATUS_ICON cpsi;
+};
+
+static const REPORT_RESULT_STATUS_INFO s_rgLogonStatusInfo[] =
+{
+    { STATUS_LOGON_FAILURE, STATUS_SUCCESS, L"Incorrect password or username.", CPSI_ERROR, },
+    { STATUS_ACCOUNT_RESTRICTION, STATUS_ACCOUNT_DISABLED, L"The account is disabled.", CPSI_WARNING },
+};
+
+
+VBoxCredential::VBoxCredential(VBoxCredProv *pProvider) : m_cRef(1),
+                                                          m_pCredProvCredentialEvents(NULL)
 {
     Log(("VBoxCredential::VBoxCredential\n"));
 
     DllAddRef();
+
+    AssertPtr(pProvider);
+    m_pProvider = pProvider;
 
     ZeroMemory(m_rgCredProvFieldDescriptors, sizeof(m_rgCredProvFieldDescriptors));
@@ -50,22 +72,23 @@
 
 
+void VBoxCredential::WipeString(const PWSTR pwszString)
+{
+    if (pwszString)
+        SecureZeroMemory(pwszString, wcslen(pwszString) * sizeof(WCHAR));
+}
+
+
 void VBoxCredential::Reset(void)
 {
-    if (m_rgFieldStrings[SFI_PASSWORD])
-    {
-        // CoTaskMemFree (below) deals with NULL, but StringCchLength does not.
-        size_t lenPassword;
-        HRESULT hr = StringCchLengthW(m_rgFieldStrings[SFI_PASSWORD], 128, &(lenPassword));
-        if (SUCCEEDED(hr))
-        {
-            SecureZeroMemory(m_rgFieldStrings[SFI_PASSWORD], lenPassword * sizeof(*m_rgFieldStrings[SFI_PASSWORD]));
-        }
-        else
-        {
-            // TODO: Determine how to handle count error here.
-        }
-    }
-
-    /** @todo securely clear other fields (user name, domain, ...) as well. */
+    WipeString(m_rgFieldStrings[SFI_USERNAME]);
+    WipeString(m_rgFieldStrings[SFI_PASSWORD]);
+    WipeString(m_rgFieldStrings[SFI_DOMAINNAME]);
+
+    if (m_pCredProvCredentialEvents)
+    {
+        m_pCredProvCredentialEvents->SetFieldString(this, SFI_USERNAME, NULL);
+        m_pCredProvCredentialEvents->SetFieldString(this, SFI_PASSWORD, NULL);
+        m_pCredProvCredentialEvents->SetFieldString(this, SFI_DOMAINNAME, NULL);
+    }
 }
 
@@ -75,30 +98,64 @@
                            const char *pszDomain)
 {
-    /* Convert credentials to unicode. */
+    Log(("VBoxCredential::Update: User=%s, Password=%s, Domain=%s\n",
+         pszUser ? pszUser : "NULL",
+         pszPw ? pszPw : "NULL",
+         pszDomain ? pszDomain : "NULL"));
+
     PWSTR *ppwszStored;
 
-    ppwszStored = &m_rgFieldStrings[SFI_USERNAME];
-    CoTaskMemFree(*ppwszStored);
-    SHStrDupA(pszUser, ppwszStored);
-
-    ppwszStored = &m_rgFieldStrings[SFI_PASSWORD];
-    CoTaskMemFree(*ppwszStored);
-    SHStrDupA(pszPw, ppwszStored);
-
-    ppwszStored = &m_rgFieldStrings[SFI_DOMAINNAME];
-    CoTaskMemFree(*ppwszStored);
-    SHStrDupA(pszDomain, ppwszStored);
-
-    Log(("VBoxCredential::Update: user=%ls, pw=%ls, domain=%ls\n",
-         m_rgFieldStrings[SFI_USERNAME] ? m_rgFieldStrings[SFI_USERNAME] : L"<empty>",
-         m_rgFieldStrings[SFI_PASSWORD] ? m_rgFieldStrings[SFI_PASSWORD] : L"<empty>",
-         m_rgFieldStrings[SFI_DOMAINNAME] ? m_rgFieldStrings[SFI_DOMAINNAME] : L"<empty>"));
+    /* Update user name. */
+    if (pszUser && strlen(pszUser))
+    {
+        ppwszStored = &m_rgFieldStrings[SFI_USERNAME];
+        CoTaskMemFree(*ppwszStored);
+        SHStrDupA(pszUser, ppwszStored);
+
+        /*
+         * In case we got a "display name" (e.g. "John Doe")
+         * instead of the real user name (e.g. "jdoe") we have
+         * to translate the data first ...
+         */
+        PWSTR pwszAcount;
+        if (TranslateAccountName(*ppwszStored, &pwszAcount))
+        {
+            CoTaskMemFree(*ppwszStored);
+            m_rgFieldStrings[SFI_USERNAME] = pwszAcount;
+        }
+    }
+
+    /* Update password. */
+    if (pszPw && strlen(pszPw))
+    {
+        ppwszStored = &m_rgFieldStrings[SFI_PASSWORD];
+        CoTaskMemFree(*ppwszStored);
+        SHStrDupA(pszPw, ppwszStored);
+    }
+
+    /* 
+     * Update domain name (can be NULL) and will
+     * be later replaced by the local computer name in the
+     * Kerberos authentication package. 
+     */
+    if (pszDomain && strlen(pszDomain))
+    {
+        ppwszStored = &m_rgFieldStrings[SFI_DOMAINNAME];
+        CoTaskMemFree(*ppwszStored);
+        SHStrDupA(pszDomain, ppwszStored);
+    }
+
+    Log(("VBoxCredential::Update: Finished - User=%ls, Password=%ls, Domain=%ls\n",
+         m_rgFieldStrings[SFI_USERNAME] ? m_rgFieldStrings[SFI_USERNAME] : L"NULL",
+         m_rgFieldStrings[SFI_PASSWORD] ? m_rgFieldStrings[SFI_PASSWORD] : L"NULL",
+         m_rgFieldStrings[SFI_DOMAINNAME] ? m_rgFieldStrings[SFI_DOMAINNAME] : L"NULL"));
     return S_OK;
 }
 
 
-// Initializes one credential with the field information passed in.
-// Set the value of the SFI_USERNAME field to pwzUsername.
-// Optionally takes a password for the SetSerialization case.
+/* 
+ * Initializes one credential with the field information passed in.
+ * Set the value of the SFI_USERNAME field to pwzUsername.
+ * Optionally takes a password for the SetSerialization case.
+ */
 HRESULT VBoxCredential::Initialize(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus,
                                    const CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR* rgcpfd,
@@ -111,6 +168,8 @@
     m_cpUS = cpus;
 
-    /* Copy the field descriptors for each field. This is useful if you want to vary the
-     * field descriptors based on what Usage scenario the credential was created for. */
+    /* 
+     * Copy the field descriptors for each field. This is useful if you want to vary the
+     * field descriptors based on what Usage scenario the credential was created for. 
+     */
     for (DWORD i = 0; SUCCEEDED(hr) && i < ARRAYSIZE(m_rgCredProvFieldDescriptors); i++)
     {
@@ -126,6 +185,8 @@
 
 
-/* LogonUI calls this in order to give us a callback in case we need to notify it of anything.
- * Store this callback pointer for later use. */
+/* 
+ * LogonUI calls this in order to give us a callback in case we need to notify it of anything.
+ * Store this callback pointer for later use. 
+ */
 HRESULT VBoxCredential::Advise(ICredentialProviderCredentialEvents* pcpce)
 {
@@ -145,5 +206,16 @@
     Log(("VBoxCredential::UnAdvise\n"));
 
+    /*
+     * We're done with the current iteration, trigger a refresh of ourselves
+     * to reset credentials and to keep the logon UI clean (no stale entries anymore). 
+     */
     Reset();
+
+    /* 
+     * Force a re-iteration of the provider (which will give zero credentials
+     * to try out because we just resetted our one and only a line above. 
+     */
+    if (m_pProvider)
+        m_pProvider->OnCredentialsProvided();
 
     if (m_pCredProvCredentialEvents)
@@ -154,15 +226,18 @@
 
 
-// LogonUI calls this function when our tile is selected (zoomed).
-// If you simply want fields to show/hide based on the selected state,
-// there's no need to do anything here - you can set that up in the
-// field definitions.  But if you want to do something
-// more complicated, like change the contents of a field when the tile is
-// selected, you would do it here.
+/*
+ * LogonUI calls this function when our tile is selected (zoomed).
+ * If you simply want fields to show/hide based on the selected state,
+ * there's no need to do anything here - you can set that up in the
+ * field definitions.  But if you want to do something
+ * more complicated, like change the contents of a field when the tile is
+ * selected, you would do it here.
+ */
 HRESULT VBoxCredential::SetSelected(BOOL* pbAutoLogon)
 {
     Log(("VBoxCredential::SetSelected\n"));
 
-    /* Don't do auto logon here because it would retry too often with
+    /* 
+     * Don't do auto logon here because it would retry too often with
      * every credential field (user name, password, domain, ...) which makes
      * winlogon wait before new login attempts can be made.
@@ -173,7 +248,9 @@
 
 
-// Similarly to SetSelected, LogonUI calls this when your tile was selected
-// and now no longer is. The most common thing to do here (which we do below)
-// is to clear out the password field.
+/*
+ * Similarly to SetSelected, LogonUI calls this when your tile was selected
+ * and now no longer is. The most common thing to do here (which we do below)
+ * is to clear out the password field.
+ */
 HRESULT VBoxCredential::SetDeselected()
 {
@@ -204,6 +281,8 @@
 
 
-// Gets info for a particular field of a tile. Called by logonUI to get information to
-// display the tile.
+/*
+ * Gets info for a particular field of a tile. Called by logonUI to get information to
+ * display the tile.
+ */
 HRESULT VBoxCredential::GetFieldState(DWORD dwFieldID,
                                       CREDENTIAL_PROVIDER_FIELD_STATE* pcpfs,
@@ -231,34 +310,159 @@
 
 
-// Sets ppwsz to the string value of the field at the index dwFieldID.
+/*
+ * Searches the account name based on a display (real) name (e.g. "John Doe" -> "jdoe").
+ * Result "ppwszAccoutName" needs to be freed with CoTaskMemFree!
+ */
+BOOL VBoxCredential::TranslateAccountName(PWSTR pwszDisplayName, PWSTR *ppwszAccoutName)
+{
+    Log(("VBoxCredential::TranslateAccountName\n"));
+
+    AssertPtr(pwszDisplayName);
+    Log(("VBoxCredential::TranslateAccountName: Getting account name for '%ls' ...\n", pwszDisplayName));
+
+    /** @todo Do we need ADS support (e.g. TranslateNameW) here? */
+    BOOL fFound = FALSE;                        /* Did we find the desired user? */
+    NET_API_STATUS nStatus;
+    DWORD dwLevel = 2;                          /* Detailed information about user accounts. */
+    DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH;
+    DWORD dwEntriesRead = 0;
+    DWORD dwTotalEntries = 0;
+    DWORD dwResumeHandle = 0;
+    LPUSER_INFO_2 pBuf = NULL;
+    LPUSER_INFO_2 pCurBuf = NULL;
+    do
+    {
+        nStatus = NetUserEnum(NULL,             /* Server name, NULL for localhost. */
+                              dwLevel,
+                              FILTER_NORMAL_ACCOUNT,
+                              (LPBYTE*)&pBuf,
+                              dwPrefMaxLen,
+                              &dwEntriesRead,
+                              &dwTotalEntries,
+                              &dwResumeHandle);
+        if (   (nStatus == NERR_Success) 
+            || (nStatus == ERROR_MORE_DATA))
+        {
+            if ((pCurBuf = pBuf) != NULL)
+            {
+                for (DWORD i = 0; i < dwEntriesRead; i++)
+                {
+                    /* 
+                     * Search for the "display name" - that might be 
+                     * "John Doe" or something similar the user recognizes easier
+                     * and may not the same as the "account" name (e.g. "jdoe").
+                     */
+                    if (   pCurBuf 
+                        && pCurBuf->usri2_full_name
+                        && StrCmpI(pwszDisplayName, pCurBuf->usri2_full_name) == 0)
+                    {
+                        /* 
+                         * Copy the real user name (e.g. "jdoe") to our 
+                         * output buffer.
+                         */
+                        LPWSTR ppwszTemp;
+                        HRESULT hr = SHStrDupW(pCurBuf->usri2_name, &ppwszTemp);
+                        if (hr == S_OK)
+                        {
+                            *ppwszAccoutName = ppwszTemp;
+                            fFound = TRUE;
+                        }
+                        else
+                            Log(("VBoxCredential::TranslateAccountName: Error copying data, hr=%08x", hr));
+                        break;
+                    }
+                    pCurBuf++;
+                }
+            }
+            if (pBuf != NULL)
+            {
+                NetApiBufferFree(pBuf);
+                pBuf = NULL;
+            }
+        }
+    } while (nStatus == ERROR_MORE_DATA && !fFound);
+
+    if (pBuf != NULL)
+    {
+        NetApiBufferFree(pBuf);
+        pBuf = NULL;
+    }
+
+    Log(("VBoxCredential::TranslateAccountName: Returned nStatus=%ld, fFound=%s\n", 
+         nStatus, fFound ? "Yes" : "No"));
+    return fFound;
+
+#if 0
+    DWORD dwErr = NO_ERROR;
+    ULONG cbLen = 0;
+    if (   TranslateNameW(pwszName, NameUnknown, NameUserPrincipal, NULL, &cbLen)
+        && cbLen > 0)
+    {
+        Log(("VBoxCredential::GetAccountName: Translated ADS name has %u characters\n", cbLen));
+
+        ppwszAccoutName = (PWSTR)RTMemAlloc(cbLen * sizeof(WCHAR));
+        AssertPtrReturn(pwszName, FALSE);
+        if (TranslateNameW(pwszName, NameUnknown, NameUserPrincipal, ppwszAccoutName, &cbLen))
+        {
+            Log(("VBoxCredential::GetAccountName: Real ADS account name of '%ls' is '%ls'\n", 
+                 pwszName, ppwszAccoutName));
+        }
+        else
+        {
+            RTMemFree(ppwszAccoutName);
+            dwErr = GetLastError();
+        }
+    }
+    else
+        dwErr = GetLastError();
+    /* The above method for looking up in ADS failed, try another one. */
+    if (dwErr != NO_ERROR)
+    {
+        dwErr = NO_ERROR;
+        
+    }
+#endif
+}
+
+
+/* Sets ppwsz to the string value of the field at the index dwFieldID. */
 HRESULT VBoxCredential::GetStringValue(DWORD dwFieldID,
-                                       PWSTR* ppwsz)
-{
-    Log(("VBoxCredential::GetStringValue: dwFieldID=%ld, pwz=%p\n", dwFieldID, ppwsz));
-
+                                       PWSTR *ppwszString)
+{
+    /* Check to make sure dwFieldID is a legitimate index. */
     HRESULT hr;
-
-    // Check to make sure dwFieldID is a legitimate index.
-    if (dwFieldID < ARRAYSIZE(m_rgCredProvFieldDescriptors) && ppwsz)
-    {
-        // Make a copy of the string and return that. The caller
-        // is responsible for freeing it.
-        hr = SHStrDupW(m_rgFieldStrings[dwFieldID], ppwsz);
+    if (   dwFieldID < ARRAYSIZE(m_rgCredProvFieldDescriptors) 
+        && ppwszString)
+    {
+        switch (dwFieldID)
+        {
+            /** @todo Add more specific field IDs here if needed. */
+
+            default:
+
+                /*
+                 * Make a copy of the string and return that, the caller is responsible for freeing it. 
+                 * Note that there can be empty fields (like a missing domain name); handle them
+                 * by writing an empty string.
+                 */
+                hr = SHStrDupW(m_rgFieldStrings[dwFieldID] ? m_rgFieldStrings[dwFieldID] : L"",
+                               ppwszString);
+                break;
+        }
         if (SUCCEEDED(hr))
-            Log(("VBoxCredential::GetStringValue: dwFieldID=%ld, pwz=%ls\n", dwFieldID, *ppwsz));
+            Log(("VBoxCredential::GetStringValue: dwFieldID=%ld, ppwszString=%ls\n", dwFieldID, *ppwszString));
     }
     else
-    {
         hr = E_INVALIDARG;
-    }
-
     return hr;
 }
 
 
-// Sets pdwAdjacentTo to the index of the field the submit button should be
-// adjacent to. We recommend that the submit button is placed next to the last
-// field which the user is required to enter information in. Optional fields
-// should be below the submit button.
+/*
+ * Sets pdwAdjacentTo to the index of the field the submit button should be
+ * adjacent to. We recommend that the submit button is placed next to the last
+ * field which the user is required to enter information in. Optional fields
+ * should be below the submit button.
+ */
 HRESULT VBoxCredential::GetSubmitButtonValue(DWORD dwFieldID,
                                              DWORD* pdwAdjacentTo)
@@ -268,8 +472,8 @@
     HRESULT hr;
 
-    // Validate parameters.
+    /* Validate parameters. */
     if ((SFI_SUBMIT_BUTTON == dwFieldID) && pdwAdjacentTo)
     {
-        // pdwAdjacentTo is a pointer to the fieldID you want the submit button to appear next to.
+        /* pdwAdjacentTo is a pointer to the fieldID you want the submit button to appear next to. */
         *pdwAdjacentTo = SFI_PASSWORD;
         Log(("VBoxCredential::GetSubmitButtonValue: dwFieldID=%ld, *pdwAdjacentTo=%ld\n", dwFieldID, *pdwAdjacentTo));
@@ -284,17 +488,25 @@
 
 
-// Sets the value of a field which can accept a string as a value.
-// This is called on each keystroke when a user types into an edit field.
+/* 
+ * Sets the value of a field which can accept a string as a value.
+ * This is called on each keystroke when a user types into an edit field.
+ */
 HRESULT VBoxCredential::SetStringValue(DWORD dwFieldID,
-                                       PCWSTR pwz)
-{
-    Log(("VBoxCredential::SetStringValue: dwFieldID=%ld, pwz=%ls\n", dwFieldID, pwz));
+                                       PCWSTR pcwzString)
+{
+    Log(("VBoxCredential::SetStringValue: dwFieldID=%ld, pcwzString=%ls\n", 
+         dwFieldID, pcwzString));
 
     HRESULT hr;
 
-    // Validate parameters.
+    /*
+     * We don't set any values into fields (e.g. the password, hidden
+     * by dots), instead keep it secret by resetting all credentials.
+     */
+#if 0
+    /* Validate parameters. */
     if (   dwFieldID < ARRAYSIZE(m_rgCredProvFieldDescriptors)
-        && (CPFT_EDIT_TEXT     == m_rgCredProvFieldDescriptors[dwFieldID].cpft ||
-            CPFT_PASSWORD_TEXT == m_rgCredProvFieldDescriptors[dwFieldID].cpft))
+        && (   CPFT_EDIT_TEXT     == m_rgCredProvFieldDescriptors[dwFieldID].cpft 
+            || CPFT_PASSWORD_TEXT == m_rgCredProvFieldDescriptors[dwFieldID].cpft))
     {
         PWSTR* ppwszStored = &m_rgFieldStrings[dwFieldID];
@@ -306,13 +518,16 @@
         hr = E_INVALIDARG;
     }
+#else
+    hr = E_NOTIMPL;
+#endif
     return hr;
 }
 
 
-// The following methods are for logonUI to get the values of various UI elements and then communicate
-// to the credential about what the user did in that field.  However, these methods are not implemented
-// because our tile doesn't contain these types of UI elements
-
-/* Gets the image to show in the user tile */
+/*
+ * The following methods are for logonUI to get the values of various UI elements and then communicate
+ * to the credential about what the user did in that field. However, these methods are not implemented
+ * because our tile doesn't contain these types of UI elements.
+ */
 HRESULT VBoxCredential::GetBitmapValue(DWORD dwFieldID,
                                        HBITMAP* phbmp)
@@ -384,14 +599,15 @@
 
 
-// Collect the username and password into a serialized credential for the correct usage scenario
-// (logon/unlock is what's demonstrated in this sample).  LogonUI then passes these credentials
-// back to the system to log on.
-HRESULT VBoxCredential::GetSerialization(CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE* pcpgsr,
-                                         CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcs,
-                                         PWSTR* ppwszOptionalStatusText,
-                                         CREDENTIAL_PROVIDER_STATUS_ICON* pcpsiOptionalStatusIcon)
-{
-    Log(("VBoxCredential::GetSerialization: pcpgsr=%p, pcpcs=%p, ppwszOptionalStatusText=%p, pcpsiOptionalStatusIcon=%p\n",
-         pcpgsr, pcpcs, ppwszOptionalStatusText, pcpsiOptionalStatusIcon));
+/*
+ * Collect the username and password into a serialized credential for the correct usage scenario
+ * LogonUI then passes these credentials back to the system to log on.
+ */
+HRESULT VBoxCredential::GetSerialization(CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE *pcpGetSerializationResponse,
+                                         CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION   *pcpCredentialSerialization,
+                                         PWSTR                                          *ppwszOptionalStatusText,
+                                         CREDENTIAL_PROVIDER_STATUS_ICON                *pcpsiOptionalStatusIcon)
+{
+    Log(("VBoxCredential::GetSerialization: pcpGetSerializationResponse=%p, pcpCredentialSerialization=%p, ppwszOptionalStatusText=%p, pcpsiOptionalStatusIcon=%p\n",
+         pcpGetSerializationResponse, pcpCredentialSerialization, ppwszOptionalStatusText, pcpsiOptionalStatusIcon));
 
     UNREFERENCED_PARAMETER(ppwszOptionalStatusText);
@@ -403,14 +619,14 @@
     HRESULT hr;
 
-    WCHAR wsz[MAX_COMPUTERNAME_LENGTH+1];
-    DWORD cch = ARRAYSIZE(wsz);
-    if (GetComputerNameW(wsz, &cch))
+    WCHAR wszComputerName[MAX_COMPUTERNAME_LENGTH+1];
+    DWORD cch = ARRAYSIZE(wszComputerName);
+    if (GetComputerNameW(wszComputerName, &cch))
     {
         /* Is a domain name missing? Then use the name of the local computer. */
         if (NULL == m_rgFieldStrings [SFI_DOMAINNAME])
-            hr = UnicodeStringInitWithString(wsz, &kil.LogonDomainName);
+            hr = UnicodeStringInitWithString(wszComputerName, &kil.LogonDomainName);
         else
-            hr = UnicodeStringInitWithString(
-                m_rgFieldStrings [SFI_DOMAINNAME], &kil.LogonDomainName);
+            hr = UnicodeStringInitWithString(m_rgFieldStrings [SFI_DOMAINNAME], 
+                                             &kil.LogonDomainName);
 
         /* Fill in the username and password. */
@@ -418,15 +634,14 @@
         {
             hr = UnicodeStringInitWithString(m_rgFieldStrings[SFI_USERNAME], &kil.UserName);
-
             if (SUCCEEDED(hr))
             {
                 hr = UnicodeStringInitWithString(m_rgFieldStrings[SFI_PASSWORD], &kil.Password);
-
                 if (SUCCEEDED(hr))
                 {
-                    // Allocate copies of, and package, the strings in a binary blob
+                    /* Allocate copies of, and package, the strings in a binary blob. */
                     kil.MessageType = KerbInteractiveLogon;
-                    hr = KerbInteractiveLogonPack(kil, &pcpcs->rgbSerialization, &pcpcs->cbSerialization);
-
+                    hr = KerbInteractiveLogonPack(kil, 
+                                                  &pcpCredentialSerialization->rgbSerialization, 
+                                                  &pcpCredentialSerialization->cbSerialization);
                     if (SUCCEEDED(hr))
                     {
@@ -435,12 +650,14 @@
                         if (SUCCEEDED(hr))
                         {
-                            pcpcs->ulAuthenticationPackage = ulAuthPackage;
-                            pcpcs->clsidCredentialProvider = CLSID_VBoxCredProvider;
-
-                            // At this point the credential has created the serialized credential used for logon
-                            // By setting this to CPGSR_RETURN_CREDENTIAL_FINISHED we are letting logonUI know
-                            // that we have all the information we need and it should attempt to submit the
-                            // serialized credential.
-                            *pcpgsr = CPGSR_RETURN_CREDENTIAL_FINISHED;
+                            pcpCredentialSerialization->ulAuthenticationPackage = ulAuthPackage;
+                            pcpCredentialSerialization->clsidCredentialProvider = CLSID_VBoxCredProvider;
+
+                            /*
+                             * At this point the credential has created the serialized credential used for logon
+                             * By setting this to CPGSR_RETURN_CREDENTIAL_FINISHED we are letting logonUI know
+                             * that we have all the information we need and it should attempt to submit the
+                             * serialized credential. 
+                             */
+                            *pcpGetSerializationResponse = CPGSR_RETURN_CREDENTIAL_FINISHED;
                         }
                     }
@@ -460,23 +677,10 @@
 
 
-struct REPORT_RESULT_STATUS_INFO
-{
-    NTSTATUS ntsStatus;
-    NTSTATUS ntsSubstatus;
-    PWSTR     pwzMessage;
-    CREDENTIAL_PROVIDER_STATUS_ICON cpsi;
-};
-
-static const REPORT_RESULT_STATUS_INFO s_rgLogonStatusInfo[] =
-{
-    { STATUS_LOGON_FAILURE, STATUS_SUCCESS, L"Incorrect password or username.", CPSI_ERROR, },
-    { STATUS_ACCOUNT_RESTRICTION, STATUS_ACCOUNT_DISABLED, L"The account is disabled.", CPSI_WARNING },
-};
-
-
-// ReportResult is completely optional.  Its purpose is to allow a credential to customize the string
-// and the icon displayed in the case of a logon failure.  For example, we have chosen to
-// customize the error shown in the case of bad username/password and in the case of the account
-// being disabled.
+/* 
+ * ReportResult is completely optional.  Its purpose is to allow a credential to customize the string
+ * and the icon displayed in the case of a logon failure.  For example, we have chosen to
+ * customize the error shown in the case of bad username/password and in the case of the account
+ * being disabled.
+ */
 HRESULT VBoxCredential::ReportResult(NTSTATUS ntsStatus,
                                      NTSTATUS ntsSubstatus,
@@ -489,5 +693,5 @@
     DWORD dwStatusInfo = (DWORD)-1;
 
-    // Look for a match on status and substatus.
+    /* Look for a match on status and substatus. */
     for (DWORD i = 0; i < ARRAYSIZE(s_rgLogonStatusInfo); i++)
     {
@@ -502,18 +706,16 @@
     {
         if (SUCCEEDED(SHStrDupW(s_rgLogonStatusInfo[dwStatusInfo].pwzMessage, ppwszOptionalStatusText)))
-        {
             *pcpsiOptionalStatusIcon = s_rgLogonStatusInfo[dwStatusInfo].cpsi;
-        }
-    }
-
-    /* Try to lookup a text message for error code */
+    }
+
+    /* Try to lookup a text message for error code. */
     LPVOID lpMessageBuffer = NULL;
-    HMODULE hMod = LoadLibrary(L"NTDLL.DLL");
-    if (hMod)
+    HMODULE hNtDLL = LoadLibrary(L"NTDLL.DLL");
+    if (hNtDLL)
     {
         FormatMessage(  FORMAT_MESSAGE_ALLOCATE_BUFFER
                       | FORMAT_MESSAGE_FROM_SYSTEM
                       | FORMAT_MESSAGE_FROM_HMODULE,
-                      hMod,
+                      hNtDLL,
                       ntsStatus,
                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
@@ -521,15 +723,26 @@
                       0,
                       NULL);
+        FreeLibrary(hNtDLL);
     }
 
     Log(("VBoxCredential::ReportResult: ntsStatus=%ld, ntsSubstatus=%ld, ppwszOptionalStatusText=%p, pcpsiOptionalStatusIcon=%p, dwStatusInfo=%ld, Message=%ls\n",
-         ntsStatus, ntsSubstatus, ppwszOptionalStatusText, pcpsiOptionalStatusIcon, dwStatusInfo, lpMessageBuffer ? lpMessageBuffer : L"none"));
+         ntsStatus, ntsSubstatus, ppwszOptionalStatusText, pcpsiOptionalStatusIcon, dwStatusInfo, lpMessageBuffer ? lpMessageBuffer : L"<None>"));
+
+    /* Print to user-friendly message to release log. */
+    if (FAILED(ntsStatus))
+    {
+        if (lpMessageBuffer)
+            LogRel(("VBoxCredProv: %ls\n", lpMessageBuffer));
+        /* Login attempt failed; reset and clear all data. */
+        Reset();
+    }
 
     if (lpMessageBuffer)
         LocalFree(lpMessageBuffer);
-    FreeLibrary(hMod);
-
-    // Since NULL is a valid value for *ppwszOptionalStatusText and *pcpsiOptionalStatusIcon
-    // this function can't fail.
+
+    /*
+     * Since NULL is a valid value for *ppwszOptionalStatusText and *pcpsiOptionalStatusIcon
+     * this function can't fail
+     */
     return S_OK;
 }
Index: /trunk/src/VBox/Additions/WINNT/VBoxCredProv/VBoxCredential.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxCredProv/VBoxCredential.h	(revision 30251)
+++ /trunk/src/VBox/Additions/WINNT/VBoxCredProv/VBoxCredential.h	(revision 30252)
@@ -18,6 +18,12 @@
 #include "resource.h"
 
+class VBoxCredProv;
+
 class VBoxCredential : public ICredentialProviderCredential
 {
+    public:
+        VBoxCredential(VBoxCredProv *pProvider);
+        virtual ~VBoxCredential();
+
     public:
 
@@ -83,13 +89,13 @@
         IFACEMETHODIMP GetSubmitButtonValue(DWORD dwFieldID, DWORD* pdwAdjacentTo);
 
-        IFACEMETHODIMP SetStringValue(DWORD dwFieldID, PCWSTR pwz);
+        IFACEMETHODIMP SetStringValue(DWORD dwFieldID, PCWSTR pcwzString);
         IFACEMETHODIMP SetCheckboxValue(DWORD dwFieldID, BOOL bChecked);
         IFACEMETHODIMP SetComboBoxSelectedValue(DWORD dwFieldID, DWORD dwSelectedItem);
         IFACEMETHODIMP CommandLinkClicked(DWORD dwFieldID);
 
-        IFACEMETHODIMP GetSerialization(CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE* pcpgsr,
-                                        CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcs,
-                                        PWSTR* ppwszOptionalStatusText,
-                                        CREDENTIAL_PROVIDER_STATUS_ICON* pcpsiOptionalStatusIcon);
+        IFACEMETHODIMP GetSerialization(CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE *pcpGetSerializationResponse,
+                                         CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION  *pcpCredentialSerialization,
+                                         PWSTR                                         *ppwszOptionalStatusText,
+                                         CREDENTIAL_PROVIDER_STATUS_ICON               *pcpsiOptionalStatusIcon);
         IFACEMETHODIMP ReportResult(NTSTATUS ntsStatus,
                                     NTSTATUS ntsSubstatus,
@@ -98,27 +104,31 @@
 
     public:
-
+        void WipeString(const PWSTR pwszString);
         void Reset();
-
         HRESULT Initialize(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus,
                            const CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR* rgcpfd,
                            const FIELD_STATE_PAIR* rgfsp);
-
         int Update(const char *pszUser,
                    const char *pszPw,
                    const char *pszDomain);
-
-        VBoxCredential();
-
-        virtual ~VBoxCredential();
-
+        BOOL TranslateAccountName(PWSTR pwszDisplayName, PWSTR *ppwszAccoutName);
     private:
 
+        /** @todo Merge all arrays which depend on SFI_NUM_FIELDS below
+                  into an own structure! */
+
+        /** Pointer to parent. */
+        VBoxCredProv                         *m_pProvider;
+        /** Internal reference count. */
         LONG                                  m_cRef;
-        CREDENTIAL_PROVIDER_USAGE_SCENARIO    m_cpUS;                                       /* The usage scenario for which we were enumerated */
-        CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR  m_rgCredProvFieldDescriptors[SFI_NUM_FIELDS]; /* Holding type and name of each field in the tile */
-        FIELD_STATE_PAIR                      m_rgFieldStatePairs[SFI_NUM_FIELDS];          /* Holding state of each field in the tile */
-        PWSTR                                 m_rgFieldStrings[SFI_NUM_FIELDS];             /* Holding string value of each field. This is different from the name of
-                                                                                             * the field held in m_rgCredProvFieldDescriptors */
+        /** The usage scenario for which we were enumerated. */
+        CREDENTIAL_PROVIDER_USAGE_SCENARIO    m_cpUS;      
+        /** Holding type and name of each field in the tile. */
+        CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR  m_rgCredProvFieldDescriptors[SFI_NUM_FIELDS];
+        /** Holding state of each field in the tile. */
+        FIELD_STATE_PAIR                      m_rgFieldStatePairs[SFI_NUM_FIELDS];          
+        /** Holding string value of each field. This is different from the name of
+            the field held in m_rgCredProvFieldDescriptors. */
+        PWSTR                                 m_rgFieldStrings[SFI_NUM_FIELDS];            
         ICredentialProviderCredentialEvents  *m_pCredProvCredentialEvents;
 
Index: /trunk/src/VBox/Additions/WINNT/VBoxCredProv/dll.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxCredProv/dll.cpp	(revision 30251)
+++ /trunk/src/VBox/Additions/WINNT/VBoxCredProv/dll.cpp	(revision 30252)
@@ -26,6 +26,6 @@
 *   Global Variables                                                           *
 *******************************************************************************/
-static LONG g_cRef = 0;     /* Global dll reference count */
-HINSTANCE g_hinst = NULL;   /* Global dll hinstance */
+static LONG g_cRef = 0;        /* Global DLL reference count. */
+HINSTANCE g_hDllInst = NULL;   /* Global DLL hinstance. */
 
 
@@ -35,9 +35,9 @@
     if (CLSID_VBoxCredProvider == rclsid)
     {
-        CClassFactory* pcf = new CClassFactory;
-        if (pcf)
+        CClassFactory* pClassFactory = new CClassFactory;
+        if (pClassFactory)
         {
-            hr = pcf->QueryInterface(riid, ppv);
-            pcf->Release();
+            hr = pClassFactory->QueryInterface(riid, ppv);
+            pClassFactory->Release();
         }
         else
@@ -55,6 +55,6 @@
 
 BOOL WINAPI DllMain(HINSTANCE hinstDll,
-                    DWORD dwReason,
-                    LPVOID pReserved)
+                    DWORD     dwReason,
+                    LPVOID    pReserved)
 {
     UNREFERENCED_PARAMETER(pReserved);
@@ -75,5 +75,5 @@
     }
 
-    g_hinst = hinstDll;
+    g_hDllInst = hinstDll;
     return TRUE;
 }
@@ -92,5 +92,11 @@
 
 
-/* DLL entry point */
+LONG DllGetRefCount()
+{
+    return g_cRef;
+}
+
+
+/* DLL entry point. */
 STDAPI DllCanUnloadNow()
 {
Index: /trunk/src/VBox/Additions/WINNT/VBoxCredProv/dll.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxCredProv/dll.h	(revision 30251)
+++ /trunk/src/VBox/Additions/WINNT/VBoxCredProv/dll.h	(revision 30252)
@@ -19,8 +19,9 @@
 #include <VBox/Log.h>
 
-extern HINSTANCE g_hinst;
+extern HINSTANCE g_hDllInst;
 
 LONG DllAddRef();
 LONG DllRelease();
+LONG DllGetRefCount();
 
 extern HRESULT VBoxCredProv_CreateInstance(REFIID riid, void** ppv);
