VirtualBox

Changeset 30252 in vbox


Ignore:
Timestamp:
Jun 16, 2010 1:48:29 PM (15 years ago)
Author:
vboxsync
Message:

Windows Guest Additions Credential Provider:

  • Added reverse lookup for using "display names" as the user account name ("John Doe" -> "jdoe").
  • Fixed showing empty user tile on invalid user/credentials.
  • Fixed domain name handling.
  • Fixed "dot" caption when no domain name is used.
  • Wipe credentials after passing over to Kerberos.
  • Beautified code a bit.
Location:
trunk/src/VBox/Additions/WINNT/VBoxCredProv
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/VBoxCredProv/Makefile.kmk

    r28800 r30252  
    4545        $(VBOX_PATH_PSDK_200702)/Lib/Credui.Lib \
    4646        $(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
    4849VBoxCredProv_LIBS.amd64  := \
    4950        $(VBOX_PATH_PSDK_200702)/Lib/x64/Uuid.Lib \
    5051        $(VBOX_PATH_PSDK_200702)/Lib/x64/Credui.Lib \
    5152        $(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
    5355
    5456VBoxCredProv_LIBS    += \
  • trunk/src/VBox/Additions/WINNT/VBoxCredProv/VBoxCredPoller.cpp

    r28800 r30252  
    55
    66/*
    7  * Copyright (C) 2009 Oracle Corporation
     7 * Copyright (C) 2010 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    5757    m_pProv->AddRef();
    5858
    59     /* don't create more than one of them */
     59    /* Don't create more than one of them. */
    6060    if (m_hThreadPoller != NIL_RTTHREAD)
    6161    {
     
    6868        Log(("VBoxCredPoller: Could not init critical section! rc = %Rrc\n", rc));
    6969
    70     /* create the poller thread */
     70    /* Create the poller thread. */
    7171    rc = RTThreadCreate(&m_hThreadPoller, VBoxCredPoller::threadPoller, this, 0, RTTHREADTYPE_INFREQUENT_POLLER,
    7272                        RTTHREADFLAGS_WAITABLE, "creds");
     
    9090    }
    9191
    92     /* Post termination event semaphore */
     92    /* Post termination event semaphore. */
    9393    int rc = RTThreadUserSignal(m_hThreadPoller);
    9494    if (RT_SUCCESS(rc))
    9595    {
    9696        Log(("VBoxCredPoller::Shutdown: Waiting for thread to terminate\n"));
    97         /* wait until the thread has terminated */
     97        /* Wait until the thread has terminated. */
    9898        rc = RTThreadWait(m_hThreadPoller, RT_INDEFINITE_WAIT, NULL);
    9999        Log(("VBoxCredPoller::Shutdown: Thread has (probably) terminated (rc = %Rrc)\n", rc));
     
    101101    else
    102102    {
    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. */
    104104        Log(("VBoxCredPoller::Shutdown: Failed to signal semaphore, rc = %Rrc\n", rc));
    105105        rc = RTThreadWait(m_hThreadPoller, 100, NULL);
     
    125125    credentialsReset();
    126126
    127     /* get credentials */
     127    /* Get credentials. */
    128128    RTCritSectEnter(&m_csCredUpate);
    129129    int rc = VbglR3CredentialsRetrieve(&m_pszUser, &m_pszPw, &m_pszDomain);
    130130    if (RT_SUCCESS(rc))
    131131    {
    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",
    133140             m_pszUser ? m_pszUser : "<empty>",
    134141             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
    159144        AssertPtr(m_pProv);
    160         m_pProv->OnCredentialsProvided(m_pszUser,
    161                                        m_pszPw,
    162                                        m_pszDomain);
     145        m_pProv->OnCredentialsProvided();
    163146    }
    164147    RTCritSectLeave(&m_csCredUpate);
     
    216199        if (RT_FAILURE(rc))
    217200        {
    218             if (rc == VERR_NOT_FOUND)
    219                 Log(("VBoxCredPoller::threadPoller: No credentials availabe.\n"));
    220             else
     201            if (rc != VERR_NOT_FOUND)
    221202                Log(("VBoxCredPoller::threadPoller: Could not retrieve credentials! rc = %Rc\n", rc));
    222203        }
     
    228209        }
    229210
    230         /* wait a bit */
     211        /* Wait a bit. */
    231212        if (RTThreadUserWait(ThreadSelf, 500) == VINF_SUCCESS)
    232213        {
    233214            Log(("VBoxCredPoller::threadPoller: Terminating\n"));
    234             /* we were asked to terminate, do that instantly! */
     215            /* We were asked to terminate, do that instantly! */
    235216            return 0;
    236217        }
  • trunk/src/VBox/Additions/WINNT/VBoxCredProv/VBoxCredProv.cpp

    r29200 r30252  
    2020
    2121
    22 VBoxCredProv::VBoxCredProv(void):
     22VBoxCredProv::VBoxCredProv(void) :
    2323    m_cRef(1),
    2424    m_pPoller(NULL),
     
    3737
    3838    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));
    4641}
    4742
     
    4944VBoxCredProv::~VBoxCredProv(void)
    5045{
     46    Log(("VBoxCredProv::~VBoxCredProv\n"));
     47
    5148    if (m_pCred != NULL)
    5249    {
     
    6259    }
    6360
    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));
    6565
    6666    VbglR3Term();
     
    6969
    7070
    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
    7273 * 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 */
     76HRESULT VBoxCredProv::SetUsageScenario(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpUsageScenario,
     77                                       DWORD                              dwFlags)
    7678{
    7779    UNREFERENCED_PARAMETER(dwFlags);
    7880    HRESULT hr;
    7981
    80     m_cpUS = cpus;
     82    m_cpUsageScenario = cpUsageScenario;
    8183
    8284    /* Decide which scenarios to support here. Returning E_NOTIMPL simply tells the caller
    8385     * that we're not designed for that scenario. */
    84     switch (m_cpUS)
     86    switch (m_cpUsageScenario)
    8587    {
    8688        case CPUS_LOGON:
     
    9799            if (m_pCred == NULL)
    98100            {
    99                 m_pCred = new VBoxCredential();
     101                m_pCred = new VBoxCredential(this);
    100102
    101103                /* All stuff allocated? */
    102104                if (m_pCred != NULL)
    103105                {
    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);
    106109                }
    107110                else
     
    128131            break;
    129132
     133        case CPUS_CHANGE_PASSWORD:
    130134        case CPUS_CREDUI:
    131         case CPUS_CHANGE_PASSWORD:
    132 
     135        case CPUS_PLAP:
     136       
    133137            hr = E_NOTIMPL;
    134138            break;
     
    140144    }
    141145
    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));
    143147    return hr;
    144148}
    145149
    146150
    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 */
     163STDMETHODIMP VBoxCredProv::SetSerialization(const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *pcpCredentialSerialization)
     164{
     165    UNREFERENCED_PARAMETER(pcpCredentialSerialization);
    161166    return E_NOTIMPL;
    162167}
    163168
    164169
    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
    166172 * 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 */
     175HRESULT VBoxCredProv::Advise(ICredentialProviderEvents *pcpEvents,
     176                             UINT_PTR                   upAdviseContext)
    170177{
    171178    Log(("VBoxCredProv::Advise\n"));
     
    174181        m_pCredProvEvents->Release();
    175182
    176     m_pCredProvEvents = pcpe;
     183    m_pCredProvEvents = pcpEvents;
    177184    Assert(m_pCredProvEvents);
    178185    m_pCredProvEvents->AddRef();
    179186
    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     */
    182191    m_upAdviseContext = upAdviseContext;
    183192    return S_OK;
     
    190199    Log(("VBoxCredProv::UnAdvise\n"));
    191200    if (m_pCredProvEvents != NULL)
    192     {
     201    {     
    193202        m_pCredProvEvents->Release();
    194203        m_pCredProvEvents = NULL;
    195204    }
     205
    196206    return S_OK;
    197207}
    198208
    199209
    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 */
     218HRESULT VBoxCredProv::GetFieldDescriptorCount(DWORD *pdwCount)
    207219{
    208220    Assert(pdwCount);
     
    214226
    215227
    216 // Gets the field descriptor for a particular field
     228/* Gets the field descriptor for a particular field. */
    217229HRESULT VBoxCredProv::GetFieldDescriptorAt(DWORD dwIndex,
    218                                            CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR **ppcpfd)
     230                                           CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR **ppcpFieldDescriptor)
    219231{
    220232    /* Verify dwIndex is a valid field */
    221233    HRESULT hr;
    222234    if (   dwIndex < SFI_NUM_FIELDS
    223         && ppcpfd)
    224     {
    225         hr = FieldDescriptorCoAllocCopy(s_rgCredProvFieldDescriptors[dwIndex], ppcpfd);
     235        && ppcpFieldDescriptor)
     236    {
     237        hr = FieldDescriptorCoAllocCopy(s_rgCredProvFieldDescriptors[dwIndex], ppcpFieldDescriptor);
    226238    }
    227239    else
     
    231243
    232244    Log(("VBoxCredProv::GetFieldDescriptorAt: hr=0x%08x, index=%ld, ppcpfd=%p\n",
    233          hr, dwIndex, ppcpfd));
     245         hr, dwIndex, ppcpFieldDescriptor));
    234246    return hr;
    235247}
    236248
    237249
    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 */
    248262HRESULT VBoxCredProv::GetCredentialCount(DWORD *pdwCount,
    249263                                         DWORD *pdwDefault,
     
    265279    if (fGotCredentials)
    266280    {
    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). */
    268282        *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). */
    270284    }
    271285    else
     
    282296
    283297
    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 */
     302HRESULT VBoxCredProv::GetCredentialAt(DWORD                           dwIndex,
     303                                      ICredentialProviderCredential **ppCredProvCredential)
    288304{
    289305    HRESULT hr;
    290306
    291     Log(("VBoxCredProv::GetCredentialAt: Index=%ld, ppcpc=%p\n", dwIndex, ppcpc));
     307    Log(("VBoxCredProv::GetCredentialAt: Index=%ld, ppCredProvCredential=%p\n", dwIndex, ppCredProvCredential));
    292308
    293309    if (m_pCred == NULL)
     
    297313    }
    298314
    299     /* Validate parameters (we only have one credential) */
     315    /* Validate parameters (we only have one credential). */
    300316    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));
    304321    }
    305322    else
    306323    {
     324        Log(("VBoxCredProv::GetCredentialAt: More than one credential not supported!\n"));
    307325        hr = E_INVALIDARG;
    308326    }
    309327    return hr;
     328}
     329
     330
     331/* Do a credential re-enumeration if we got the event to do so. */
     332void VBoxCredProv::OnCredentialsProvided()
     333{
     334    Log(("VBoxCredProv::OnCredentialsProvided\n"));
     335
     336    if (m_pCredProvEvents != NULL)
     337        m_pCredProvEvents->CredentialsChanged(m_upAdviseContext);
    310338}
    311339
     
    329357}
    330358
    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  
    2525    public:
    2626
    27         // IUnknown
     27        /** IUnknown methods. */
    2828        STDMETHOD_(ULONG, AddRef)()
    2929        {
     
    6161    public:
    6262
    63         // ICredentialProvider
    64         IFACEMETHODIMP SetUsageScenario(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus, DWORD dwFlags);
    65         IFACEMETHODIMP SetSerialization(const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *pcpcs);
     63        /** ICredentialProvider interface. */
     64        IFACEMETHODIMP SetUsageScenario(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpUsageScenario, DWORD dwFlags);
     65        IFACEMETHODIMP SetSerialization(const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *pcpCredentialSerialization);
    6666
    67         IFACEMETHODIMP Advise(__in ICredentialProviderEvents *pcpe, UINT_PTR upAdviseContext);
     67        IFACEMETHODIMP Advise(__in ICredentialProviderEvents *pcpEvents, UINT_PTR upAdviseContext);
    6868        IFACEMETHODIMP UnAdvise();
    6969
    7070        IFACEMETHODIMP GetFieldDescriptorCount(__out DWORD* pdwCount);
    71         IFACEMETHODIMP GetFieldDescriptorAt(DWORD dwIndex,  __deref_out CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR **ppcpfd);
     71        IFACEMETHODIMP GetFieldDescriptorAt(DWORD dwIndex,  __deref_out CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR **ppcpFieldDescriptor);
    7272
    7373        IFACEMETHODIMP GetCredentialCount(__out DWORD *pdwCount,
     
    8282
    8383        VBoxCredProv(void);
    84         __override ~VBoxCredProv(void);
     84        virtual ~VBoxCredProv(void);
    8585
    8686    public:
    8787
    88         // Events
    89         void OnCredentialsProvided(const char *pszUser,
    90                                    const char *pszPw,
    91                                    const char *pszDomain);
     88        /** Events. */
     89        void OnCredentialsProvided();
    9290    private:
    9391
    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;
    101106};
    102107
  • trunk/src/VBox/Additions/WINNT/VBoxCredProv/VBoxCredential.cpp

    r29200 r30252  
    1515#endif
    1616
    17 #include <iprt/string.h>
    18 
     17#include "VBoxCredProv.h"
    1918#include "VBoxCredential.h"
    2019#include "guid.h"
    2120
    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
     27struct REPORT_RESULT_STATUS_INFO
     28{
     29    NTSTATUS ntsStatus;
     30    NTSTATUS ntsSubstatus;
     31    PWSTR     pwzMessage;
     32    CREDENTIAL_PROVIDER_STATUS_ICON cpsi;
     33};
     34
     35static 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
     42VBoxCredential::VBoxCredential(VBoxCredProv *pProvider) : m_cRef(1),
     43                                                          m_pCredProvCredentialEvents(NULL)
    2544{
    2645    Log(("VBoxCredential::VBoxCredential\n"));
    2746
    2847    DllAddRef();
     48
     49    AssertPtr(pProvider);
     50    m_pProvider = pProvider;
    2951
    3052    ZeroMemory(m_rgCredProvFieldDescriptors, sizeof(m_rgCredProvFieldDescriptors));
     
    5072
    5173
     74void VBoxCredential::WipeString(const PWSTR pwszString)
     75{
     76    if (pwszString)
     77        SecureZeroMemory(pwszString, wcslen(pwszString) * sizeof(WCHAR));
     78}
     79
     80
    5281void VBoxCredential::Reset(void)
    5382{
    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    }
    7093}
    7194
     
    7598                           const char *pszDomain)
    7699{
    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
    78105    PWSTR *ppwszStored;
    79106
    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"));
    96151    return S_OK;
    97152}
    98153
    99154
    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 */
    103160HRESULT VBoxCredential::Initialize(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus,
    104161                                   const CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR* rgcpfd,
     
    111168    m_cpUS = cpus;
    112169
    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     */
    115174    for (DWORD i = 0; SUCCEEDED(hr) && i < ARRAYSIZE(m_rgCredProvFieldDescriptors); i++)
    116175    {
     
    126185
    127186
    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 */
    130191HRESULT VBoxCredential::Advise(ICredentialProviderCredentialEvents* pcpce)
    131192{
     
    145206    Log(("VBoxCredential::UnAdvise\n"));
    146207
     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     */
    147212    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();
    148220
    149221    if (m_pCredProvCredentialEvents)
     
    154226
    155227
    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 */
    162236HRESULT VBoxCredential::SetSelected(BOOL* pbAutoLogon)
    163237{
    164238    Log(("VBoxCredential::SetSelected\n"));
    165239
    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
    167242     * every credential field (user name, password, domain, ...) which makes
    168243     * winlogon wait before new login attempts can be made.
     
    173248
    174249
    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 */
    178255HRESULT VBoxCredential::SetDeselected()
    179256{
     
    204281
    205282
    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 */
    208287HRESULT VBoxCredential::GetFieldState(DWORD dwFieldID,
    209288                                      CREDENTIAL_PROVIDER_FIELD_STATE* pcpfs,
     
    231310
    232311
    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 */
     316BOOL 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. */
    234429HRESULT 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. */
    239433    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        }
    247452        if (SUCCEEDED(hr))
    248             Log(("VBoxCredential::GetStringValue: dwFieldID=%ld, pwz=%ls\n", dwFieldID, *ppwsz));
     453            Log(("VBoxCredential::GetStringValue: dwFieldID=%ld, ppwszString=%ls\n", dwFieldID, *ppwszString));
    249454    }
    250455    else
    251     {
    252456        hr = E_INVALIDARG;
    253     }
    254 
    255457    return hr;
    256458}
    257459
    258460
    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 */
    263467HRESULT VBoxCredential::GetSubmitButtonValue(DWORD dwFieldID,
    264468                                             DWORD* pdwAdjacentTo)
     
    268472    HRESULT hr;
    269473
    270     // Validate parameters.
     474    /* Validate parameters. */
    271475    if ((SFI_SUBMIT_BUTTON == dwFieldID) && pdwAdjacentTo)
    272476    {
    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. */
    274478        *pdwAdjacentTo = SFI_PASSWORD;
    275479        Log(("VBoxCredential::GetSubmitButtonValue: dwFieldID=%ld, *pdwAdjacentTo=%ld\n", dwFieldID, *pdwAdjacentTo));
     
    284488
    285489
    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 */
    288494HRESULT 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));
    292499
    293500    HRESULT hr;
    294501
    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. */
    296508    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))
    299511    {
    300512        PWSTR* ppwszStored = &m_rgFieldStrings[dwFieldID];
     
    306518        hr = E_INVALIDARG;
    307519    }
     520#else
     521    hr = E_NOTIMPL;
     522#endif
    308523    return hr;
    309524}
    310525
    311526
    312 // The following methods are for logonUI to get the values of various UI elements and then communicate
    313 // 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 */
    317532HRESULT VBoxCredential::GetBitmapValue(DWORD dwFieldID,
    318533                                       HBITMAP* phbmp)
     
    384599
    385600
    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 */
     605HRESULT 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));
    396612
    397613    UNREFERENCED_PARAMETER(ppwszOptionalStatusText);
     
    403619    HRESULT hr;
    404620
    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))
    408624    {
    409625        /* Is a domain name missing? Then use the name of the local computer. */
    410626        if (NULL == m_rgFieldStrings [SFI_DOMAINNAME])
    411             hr = UnicodeStringInitWithString(wsz, &kil.LogonDomainName);
     627            hr = UnicodeStringInitWithString(wszComputerName, &kil.LogonDomainName);
    412628        else
    413             hr = UnicodeStringInitWithString(
    414                 m_rgFieldStrings [SFI_DOMAINNAME], &kil.LogonDomainName);
     629            hr = UnicodeStringInitWithString(m_rgFieldStrings [SFI_DOMAINNAME],
     630                                            &kil.LogonDomainName);
    415631
    416632        /* Fill in the username and password. */
     
    418634        {
    419635            hr = UnicodeStringInitWithString(m_rgFieldStrings[SFI_USERNAME], &kil.UserName);
    420 
    421636            if (SUCCEEDED(hr))
    422637            {
    423638                hr = UnicodeStringInitWithString(m_rgFieldStrings[SFI_PASSWORD], &kil.Password);
    424 
    425639                if (SUCCEEDED(hr))
    426640                {
    427                     // Allocate copies of, and package, the strings in a binary blob
     641                    /* Allocate copies of, and package, the strings in a binary blob. */
    428642                    kil.MessageType = KerbInteractiveLogon;
    429                     hr = KerbInteractiveLogonPack(kil, &pcpcs->rgbSerialization, &pcpcs->cbSerialization);
    430 
     643                    hr = KerbInteractiveLogonPack(kil,
     644                                                  &pcpCredentialSerialization->rgbSerialization,
     645                                                  &pcpCredentialSerialization->cbSerialization);
    431646                    if (SUCCEEDED(hr))
    432647                    {
     
    435650                        if (SUCCEEDED(hr))
    436651                        {
    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;
    445662                        }
    446663                    }
     
    460677
    461678
    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 */
    481685HRESULT VBoxCredential::ReportResult(NTSTATUS ntsStatus,
    482686                                     NTSTATUS ntsSubstatus,
     
    489693    DWORD dwStatusInfo = (DWORD)-1;
    490694
    491     // Look for a match on status and substatus.
     695    /* Look for a match on status and substatus. */
    492696    for (DWORD i = 0; i < ARRAYSIZE(s_rgLogonStatusInfo); i++)
    493697    {
     
    502706    {
    503707        if (SUCCEEDED(SHStrDupW(s_rgLogonStatusInfo[dwStatusInfo].pwzMessage, ppwszOptionalStatusText)))
    504         {
    505708            *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. */
    510712    LPVOID lpMessageBuffer = NULL;
    511     HMODULE hMod = LoadLibrary(L"NTDLL.DLL");
    512     if (hMod)
     713    HMODULE hNtDLL = LoadLibrary(L"NTDLL.DLL");
     714    if (hNtDLL)
    513715    {
    514716        FormatMessage(  FORMAT_MESSAGE_ALLOCATE_BUFFER
    515717                      | FORMAT_MESSAGE_FROM_SYSTEM
    516718                      | FORMAT_MESSAGE_FROM_HMODULE,
    517                       hMod,
     719                      hNtDLL,
    518720                      ntsStatus,
    519721                      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
     
    521723                      0,
    522724                      NULL);
     725        FreeLibrary(hNtDLL);
    523726    }
    524727
    525728    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    }
    527739
    528740    if (lpMessageBuffer)
    529741        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     */
    534747    return S_OK;
    535748}
  • trunk/src/VBox/Additions/WINNT/VBoxCredProv/VBoxCredential.h

    r29200 r30252  
    1818#include "resource.h"
    1919
     20class VBoxCredProv;
     21
    2022class VBoxCredential : public ICredentialProviderCredential
    2123{
     24    public:
     25        VBoxCredential(VBoxCredProv *pProvider);
     26        virtual ~VBoxCredential();
     27
    2228    public:
    2329
     
    8389        IFACEMETHODIMP GetSubmitButtonValue(DWORD dwFieldID, DWORD* pdwAdjacentTo);
    8490
    85         IFACEMETHODIMP SetStringValue(DWORD dwFieldID, PCWSTR pwz);
     91        IFACEMETHODIMP SetStringValue(DWORD dwFieldID, PCWSTR pcwzString);
    8692        IFACEMETHODIMP SetCheckboxValue(DWORD dwFieldID, BOOL bChecked);
    8793        IFACEMETHODIMP SetComboBoxSelectedValue(DWORD dwFieldID, DWORD dwSelectedItem);
    8894        IFACEMETHODIMP CommandLinkClicked(DWORD dwFieldID);
    8995
    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);
    94100        IFACEMETHODIMP ReportResult(NTSTATUS ntsStatus,
    95101                                    NTSTATUS ntsSubstatus,
     
    98104
    99105    public:
    100 
     106        void WipeString(const PWSTR pwszString);
    101107        void Reset();
    102 
    103108        HRESULT Initialize(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus,
    104109                           const CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR* rgcpfd,
    105110                           const FIELD_STATE_PAIR* rgfsp);
    106 
    107111        int Update(const char *pszUser,
    108112                   const char *pszPw,
    109113                   const char *pszDomain);
    110 
    111         VBoxCredential();
    112 
    113         virtual ~VBoxCredential();
    114 
     114        BOOL TranslateAccountName(PWSTR pwszDisplayName, PWSTR *ppwszAccoutName);
    115115    private:
    116116
     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. */
    117123        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];           
    123133        ICredentialProviderCredentialEvents  *m_pCredProvCredentialEvents;
    124134
  • trunk/src/VBox/Additions/WINNT/VBoxCredProv/dll.cpp

    r29200 r30252  
    2626*   Global Variables                                                           *
    2727*******************************************************************************/
    28 static LONG g_cRef = 0;     /* Global dll reference count */
    29 HINSTANCE g_hinst = NULL;   /* Global dll hinstance */
     28static LONG g_cRef = 0;        /* Global DLL reference count. */
     29HINSTANCE g_hDllInst = NULL;   /* Global DLL hinstance. */
    3030
    3131
     
    3535    if (CLSID_VBoxCredProvider == rclsid)
    3636    {
    37         CClassFactory* pcf = new CClassFactory;
    38         if (pcf)
     37        CClassFactory* pClassFactory = new CClassFactory;
     38        if (pClassFactory)
    3939        {
    40             hr = pcf->QueryInterface(riid, ppv);
    41             pcf->Release();
     40            hr = pClassFactory->QueryInterface(riid, ppv);
     41            pClassFactory->Release();
    4242        }
    4343        else
     
    5555
    5656BOOL WINAPI DllMain(HINSTANCE hinstDll,
    57                     DWORD dwReason,
    58                     LPVOID pReserved)
     57                    DWORD     dwReason,
     58                    LPVOID    pReserved)
    5959{
    6060    UNREFERENCED_PARAMETER(pReserved);
     
    7575    }
    7676
    77     g_hinst = hinstDll;
     77    g_hDllInst = hinstDll;
    7878    return TRUE;
    7979}
     
    9292
    9393
    94 /* DLL entry point */
     94LONG DllGetRefCount()
     95{
     96    return g_cRef;
     97}
     98
     99
     100/* DLL entry point. */
    95101STDAPI DllCanUnloadNow()
    96102{
  • trunk/src/VBox/Additions/WINNT/VBoxCredProv/dll.h

    r29200 r30252  
    1919#include <VBox/Log.h>
    2020
    21 extern HINSTANCE g_hinst;
     21extern HINSTANCE g_hDllInst;
    2222
    2323LONG DllAddRef();
    2424LONG DllRelease();
     25LONG DllGetRefCount();
    2526
    2627extern HRESULT VBoxCredProv_CreateInstance(REFIID riid, void** ppv);
Note: See TracChangeset for help on using the changeset viewer.

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