VBoxCredProvProvider.cpp revision 352bb6b9d2fa1f7df7797f50c58e297ac37059a2
/* $Id$ */
/** @file
* VBoxCredProvProvider - The actual credential provider class.
*/
/*
* Copyright (C) 2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include <credentialprovider.h>
#include <VBox/VBoxGuestLib.h>
#include "VBoxCredentialProvider.h"
#include "VBoxCredProvProvider.h"
#include "VBoxCredProvCredential.h"
VBoxCredProvProvider::VBoxCredProvProvider(void) :
m_cRefs(1),
m_fHandleRemoteSessions(false)
{
}
{
VBoxCredProvVerbose(0, "VBoxCredProv: Destroying\n");
if (m_pCred)
{
}
if (m_pPoller)
{
delete m_pPoller;
}
}
/* IUnknown overrides. */
VBoxCredProvProvider::AddRef(void)
{
VBoxCredProvVerbose(0, "VBoxCredProv: AddRef: Returning refcount=%ld\n",
cRefs);
return cRefs;
}
VBoxCredProvProvider::Release(void)
{
VBoxCredProvVerbose(0, "VBoxCredProv: Release: Returning refcount=%ld\n",
cRefs);
if (!cRefs)
{
VBoxCredProvVerbose(0, "VBoxCredProv: Calling destructor\n");
delete this;
}
return cRefs;
}
{
if (ppvInterface)
{
if ( IID_IUnknown == interfaceID
{
*ppvInterface = static_cast<IUnknown*>(this);
}
else
{
*ppvInterface = NULL;
hr = E_NOINTERFACE;
}
}
else
hr = E_INVALIDARG;
return hr;
}
/**
* Loads the global configuration from registry.
*
* @return DWORD Windows error code.
*/
{
/** @todo Add some registry wrapper function(s) as soon as we got more values to retrieve. */
DWORD dwRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Oracle\\VirtualBox Guest Additions\\AutoLogon",
0L, KEY_QUERY_VALUE, &hKey);
if (dwRet == ERROR_SUCCESS)
{
if ( dwRet == ERROR_SUCCESS
{
m_fHandleRemoteSessions = true;
}
if ( dwRet == ERROR_SUCCESS
{
}
if (g_dwVerbosity) /* Do we want logging at all? */
{
if ( dwRet == ERROR_SUCCESS
{
}
}
}
/* Do not report back an error here yet. */
return ERROR_SUCCESS;
}
/**
* Determines whether we should handle the current session or not.
*
* @return bool true if we should handle this session, false if not.
*/
bool
{
/* Load global configuration from registry. */
int rc = LoadConfiguration();
if (RT_FAILURE(rc))
VBoxCredProvVerbose(0, "VBoxCredProv: Error loading global configuration, rc=%Rrc\n",
rc);
bool fHandle = false;
{
if (m_fHandleRemoteSessions) /* Force remote session handling. */
fHandle = true;
}
else /* No remote session. */
fHandle = true;
return fHandle;
}
/**
* Tells this provider the current usage scenario.
*
* @return HRESULT
* @param enmUsageScenario Current usage scenario this provider will be
* used in.
* @param dwFlags Optional flags for the usage scenario.
*/
VBoxCredProvProvider::SetUsageScenario(CREDENTIAL_PROVIDER_USAGE_SCENARIO enmUsageScenario, DWORD dwFlags)
{
VBoxCredProvVerbose(0, "VBoxCredProv::SetUsageScenario: enmUsageScenario=%d, dwFlags=%ld\n",
switch (m_enmUsageScenario)
{
case CPUS_LOGON:
case CPUS_UNLOCK_WORKSTATION:
{
dwErr = LoadConfiguration();
if (dwErr != ERROR_SUCCESS)
/* Do not stop running on a misconfigured system. */
/*
* If we're told to not handle the current session just bail out and let the
* user know.
*/
if (!HandleCurrentSession())
break;
if (!m_pPoller)
{
/** @todo try catch please. */
m_pPoller = new VBoxCredProvPoller();
if (RT_FAILURE(rc))
VBoxCredProvVerbose(0, "VBoxCredProv::SetUsageScenario: Error initializing poller thread, rc=%Rrc\n", rc);
}
if (!m_pCred)
{
/** @todo try catch please. */
m_pCred = new VBoxCredProvCredential();
if (m_pCred)
else
hr = E_OUTOFMEMORY;
}
else
{
/* All set up already! Nothing to do here right now. */
}
/* If we failed, do some cleanup. */
{
{
}
}
break;
}
case CPUS_CHANGE_PASSWORD:
case CPUS_CREDUI:
case CPUS_PLAP:
break;
default:
hr = E_INVALIDARG;
break;
}
return hr;
}
/**
* Tells this provider how the serialization will be handled. Currently not used.
*
* @return STDMETHODIMP
* @param pcpCredentialSerialization Credentials serialization.
*/
VBoxCredProvProvider::SetSerialization(const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION *pcpCredentialSerialization)
{
return E_NOTIMPL;
}
/**
* Initializes the communication with LogonUI through callbacks events which we can later
* use to start re-enumeration of credentials.
*
* @return HRESULT
* @param pcpEvents Pointer to event interface.
* @param upAdviseContext The current advise context.
*/
{
VBoxCredProvVerbose(0, "VBoxCredProv::Advise, pcpEvents=0x%p, upAdviseContext=%u\n",
if (m_pEvents)
{
}
if (m_pEvents)
/*
* Save advice context for later use when binding to
* certain ICredentialProviderEvents events.
*/
return S_OK;
}
/**
* Uninitializes the callback events so that they're no longer valid.
*
* @return HRESULT
*/
VBoxCredProvProvider::UnAdvise(void)
{
VBoxCredProvVerbose(0, "VBoxCredProv::UnAdvise: pEvents=0x%p\n",
if (m_pEvents)
{
}
return S_OK;
}
/**
* Retrieves the total count of fields we're handling (needed for field enumeration
* through LogonUI).
*
* @return HRESULT
* @param pdwCount Receives total count of fields.
*/
{
if (pdwCount)
{
}
return S_OK;
}
/**
* Retrieves a descriptor of a specified field.
*
* @return HRESULT
* @param dwIndex ID of field to retrieve descriptor for.
* @param ppFieldDescriptor Pointer which receives the allocated field
* descriptor.
*/
VBoxCredProvProvider::GetFieldDescriptorAt(DWORD dwIndex, CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR **ppFieldDescriptor)
{
if ( dwIndex < VBOXCREDPROV_NUM_FIELDS
{
(PCREDENTIAL_PROVIDER_FIELD_DESCRIPTOR)CoTaskMemAlloc(sizeof(CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR));
if (pcpFieldDesc)
{
}
else
hr = E_OUTOFMEMORY;
else
}
else
hr = E_INVALIDARG;
VBoxCredProvVerbose(0, "VBoxCredProv::GetFieldDescriptorAt: dwIndex=%ld, ppDesc=0x%p, hr=0x%08x\n",
return hr;
}
/**
* Retrieves the total number of credentials this provider can offer at the current time and
* if a logon attempt should be made.
*
* @return HRESULT
* @param pdwCount Receives number of credentials to serve.
* @param pdwDefault Receives the credentials index to try
* logging on if there is more than one
* credential provided. 0 is default.
* @param pfAutoLogonWithDefault Receives a flag indicating whether a
* logon attempt using the default
* credential should be made or not.
*/
VBoxCredProvProvider::GetCredentialCount(DWORD *pdwCount, DWORD *pdwDefault, BOOL *pfAutoLogonWithDefault)
{
bool fHasCredentials = false;
/* Do we have credentials? */
if (m_pCred)
{
}
if (fHasCredentials)
{
*pdwDefault = 0; /* The credential we provide is *always* at index 0! */
*pfAutoLogonWithDefault = TRUE; /* We always at least try to auto-login (if password is correct). */
}
else
{
*pdwCount = 0;
}
VBoxCredProvVerbose(0, "VBoxCredProv::GetCredentialCount: *pdwCount=%ld, *pdwDefault=%ld, *pfAutoLogonWithDefault=%s\n",
return S_OK;
}
/**
* Called by Winlogon to retrieve the interface of our current ICredentialProviderCredential interface.
*
* @return HRESULT
* @param dwIndex Index of credential (in case there is more than one credential at a time) to
* retrieve the interface for.
* @param ppCredProvCredential Pointer that receives the credential interface.
*/
VBoxCredProvProvider::GetCredentialAt(DWORD dwIndex, ICredentialProviderCredential **ppCredProvCredential)
{
VBoxCredProvVerbose(0, "VBoxCredProv::GetCredentialAt: Index=%ld, ppCredProvCredential=0x%p\n",
if (!m_pCred)
{
VBoxCredProvVerbose(0, "VBoxCredProv::GetCredentialAt: No credentials available\n");
return E_INVALIDARG;
}
if ( dwIndex == 0
{
reinterpret_cast<void**>(ppCredProvCredential));
}
else
{
VBoxCredProvVerbose(0, "VBoxCredProv::GetCredentialAt: More than one credential not supported!\n");
hr = E_INVALIDARG;
}
return hr;
}
/**
* Triggers a credential re-enumeration -- will be called by our poller thread. This then invokes
* GetCredentialCount() and GetCredentialAt() called by Winlogon.
*/
void
{
VBoxCredProvVerbose(0, "VBoxCredProv::OnCredentialsProvided\n");
if (m_pEvents)
}
/**
* Creates our provider. This happens *before* CTRL-ALT-DEL was pressed!
*/
{
/** @todo try-catch. */
if (pProvider)
{
}
else
hr = E_OUTOFMEMORY;
return hr;
}