// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/credential_provider/gaiacp/gaia_credential_provider.h"

#include <iomanip>
#include <map>
#include <utility>

#include "base/files/file_path.h"
#include "base/json/json_reader.h"
#include "base/stl_util.h"
#include "base/strings/string16.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chrome/common/chrome_version.h"
#include "chrome/credential_provider/common/gcp_strings.h"
#include "chrome/credential_provider/gaiacp/associated_user_validator.h"
#include "chrome/credential_provider/gaiacp/auth_utils.h"
#include "chrome/credential_provider/gaiacp/gaia_credential.h"
#include "chrome/credential_provider/gaiacp/gaia_credential_other_user.h"
#include "chrome/credential_provider/gaiacp/gaia_credential_provider_i.h"
#include "chrome/credential_provider/gaiacp/logging.h"
#include "chrome/credential_provider/gaiacp/mdm_utils.h"
#include "chrome/credential_provider/gaiacp/os_user_manager.h"
#include "chrome/credential_provider/gaiacp/reauth_credential.h"
#include "chrome/credential_provider/gaiacp/reg_utils.h"

namespace credential_provider {

#define W2CW(p) const_cast<wchar_t*>(p)

static const CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR g_field_desc[] = {
    {FID_DESCRIPTION, CPFT_LARGE_TEXT, W2CW(L"Description"), GUID_NULL},
    {FID_CURRENT_PASSWORD_FIELD, CPFT_PASSWORD_TEXT, W2CW(L"Windows Password"),
     GUID_NULL},
    {FID_SUBMIT, CPFT_SUBMIT_BUTTON, W2CW(L"Submit button"), GUID_NULL},
    {FID_FORGOT_PASSWORD_LINK, CPFT_COMMAND_LINK, W2CW(L"Forgot Password"),
     GUID_NULL},
    {FID_PROVIDER_LOGO, CPFT_TILE_IMAGE, W2CW(L"Provider logo"),
     CPFG_CREDENTIAL_PROVIDER_LOGO},
    {FID_PROVIDER_LABEL, CPFT_LARGE_TEXT, W2CW(L"Provider label"),
     CPFG_CREDENTIAL_PROVIDER_LABEL},
};

static_assert(base::size(g_field_desc) == FIELD_COUNT,
              "g_field_desc does not match FIELDID enum");

namespace {

// Initializes an object that implements IReauthCredential.
HRESULT InitializeReauthCredential(CGaiaCredentialProvider* provider,
                                   const base::string16& sid,
                                   const base::string16& domain,
                                   const base::string16& username,
                                   const CComPtr<IGaiaCredential>& gaia_cred) {
  CComPtr<IReauthCredential> reauth;
  HRESULT hr = gaia_cred.QueryInterface(&reauth);
  if (FAILED(hr)) {
    LOG(ERROR) << "Could not get reauth credential interface hr=" << putHR(hr);
    return hr;
  }

  hr = gaia_cred->Initialize(provider);
  if (FAILED(hr)) {
    LOG(ERROR) << "Could not initialize credential hr=" << putHR(hr);
    return hr;
  }

  // Get the user's email address.  If not found, proceed anyway.  The net
  // effect is that the user will need to enter their email address manually
  // instead of it being pre-filled.
  wchar_t email[64];
  ULONG email_length = base::size(email);
  hr = GetUserProperty(sid.c_str(), kUserEmail, email, &email_length);
  if (FAILED(hr))
    email[0] = 0;

  hr = reauth->SetOSUserInfo(CComBSTR(W2COLE(sid.c_str())),
                             CComBSTR(W2COLE(domain.c_str())),
                             CComBSTR(W2COLE(username.c_str())));
  if (FAILED(hr)) {
    LOGFN(ERROR) << "cred->SetOSUserInfo hr=" << putHR(hr);
    return hr;
  }

  if (email[0]) {
    hr = reauth->SetEmailForReauth(CComBSTR(email));
    if (FAILED(hr))
      LOGFN(ERROR) << "reauth->SetEmailForReauth hr=" << putHR(hr);
  } else {
    LOGFN(INFO) << "reauth for sid " << sid
                << " doesn't contain the email association";
  }

  return S_OK;
}

template <class CredentialT>
HRESULT CreateCredentialObject(
    CGaiaCredentialProvider::CredentialCreatorFn creator_fn,
    CGaiaCredentialProvider::GaiaCredentialComPtrStorage* credential_com_ptr) {
  if (creator_fn) {
    return creator_fn(credential_com_ptr);
  }

  return CComCreator<CComObject<CredentialT>>::CreateInstance(
      nullptr, IID_IGaiaCredential,
      reinterpret_cast<void**>(&credential_com_ptr->gaia_cred));
}

}  // namespace

// Class that when constructed automatically starts a thread that tries
// to update the validity of available token handles. If the background
// thread detects that any token handle has changed, then it will notify
// the provider |event_handler| object of this event.
class BackgroundTokenHandleUpdater {
 public:
  BackgroundTokenHandleUpdater(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus,
                               ICredentialUpdateEventsHandler* event_handler);
  ~BackgroundTokenHandleUpdater();

 private:
  static unsigned __stdcall PeriodicTokenHandleUpdate(void* param);

  CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus_;

  // Raw pointer to the interface on CGaiaCredentialProvider that is used
  // to notify that token handle validity has changed. Any instance of this
  // class should be owned by the CGaiaCredentialProvider to ensure that
  // this pointer outlives the updater.
  ICredentialUpdateEventsHandler* event_handler_;

  base::win::ScopedHandle token_update_thread_;
  base::WaitableEvent token_update_quit_event_;
};

BackgroundTokenHandleUpdater::BackgroundTokenHandleUpdater(
    CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus,
    ICredentialUpdateEventsHandler* event_handler)
    : cpus_(cpus), event_handler_(event_handler) {
  unsigned wait_thread_id;
  uintptr_t wait_thread =
      _beginthreadex(nullptr, 0, PeriodicTokenHandleUpdate,
                     reinterpret_cast<void*>(this), 0, &wait_thread_id);
  if (wait_thread != 0) {
    token_update_thread_.Set(
        reinterpret_cast<base::win::ScopedHandle::Handle>(wait_thread));
  }
}

BackgroundTokenHandleUpdater::~BackgroundTokenHandleUpdater() {
  if (token_update_thread_.IsValid()) {
    // Tell the background thread to quit and then make sure it does.  This
    // prevents it from accessing data members that have been freed.
    token_update_quit_event_.Signal();
    ::WaitForSingleObject(token_update_thread_.Get(), INFINITE);
  }
}

unsigned __stdcall BackgroundTokenHandleUpdater::PeriodicTokenHandleUpdate(
    void* param) {
  BackgroundTokenHandleUpdater* updater =
      reinterpret_cast<BackgroundTokenHandleUpdater*>(param);
  ICredentialUpdateEventsHandler* event_handler = updater->event_handler_;
  base::WaitableEvent& stop_event = updater->token_update_quit_event_;

  while (true) {
    HRESULT hr = ::WaitForSingleObject(
        stop_event.handle(),
        AssociatedUserValidator::kTokenHandleValidityLifetime.InMilliseconds());

    if (hr != WAIT_TIMEOUT)
      break;

    bool user_access_changed =
        AssociatedUserValidator::Get()
            ->DenySigninForUsersWithInvalidTokenHandles(updater->cpus_);
    if (user_access_changed) {
      LOGFN(INFO) << "A user token handle has been invalidated. Refreshing "
                     "credentials";
    }
    event_handler->UpdateCredentialsIfNeeded(user_access_changed);
  }

  return 0;
}

CGaiaCredentialProvider::GaiaCredentialComPtrStorage::
    GaiaCredentialComPtrStorage() = default;
CGaiaCredentialProvider::GaiaCredentialComPtrStorage::
    ~GaiaCredentialComPtrStorage() = default;

CGaiaCredentialProvider::ProviderConcurrentState::ProviderConcurrentState() =
    default;
CGaiaCredentialProvider::ProviderConcurrentState::~ProviderConcurrentState() =
    default;

bool CGaiaCredentialProvider::ProviderConcurrentState::
    RequestUserRefreshIfNeeded(bool user_access_changed) {
  base::AutoLock locker(state_update_lock_);
  if (auto_logon_credential_) {
    // Auto logon has precedence and has already signalled a credential changed,
    // save the user refresh for a later update and don't signal the change
    // again.
    if (user_access_changed)
      pending_users_refresh_needed_ = user_access_changed;
    return false;
  }

  // No auto logon present and there is a user access change or a pending
  // refresh to be executed. We clear the pending the refresh and just set
  // |users_need_to_be_refreshed_| to notify that a refresh is needed on the
  // next GetCredentialCount.
  if (user_access_changed || pending_users_refresh_needed_) {
    users_need_to_be_refreshed_ = true;
    pending_users_refresh_needed_ = false;
  }

  return users_need_to_be_refreshed_;
}

bool CGaiaCredentialProvider::ProviderConcurrentState::SetAutoLogonCredential(
    const CComPtr<IGaiaCredential>& auto_logon_credential) {
  base::AutoLock locker(state_update_lock_);
  // Always update the credential.
  auto_logon_credential_ = auto_logon_credential;
  if (auto_logon_credential_) {
    // If a previous user refresh was signalled, then the credential changed
    // was already sent. Don't need to send it again, but we need save the
    // user refresh for a later credential change event since auto logon has
    // precedence.
    if (users_need_to_be_refreshed_) {
      pending_users_refresh_needed_ = users_need_to_be_refreshed_;
      users_need_to_be_refreshed_ = false;
      return false;
    }

    return true;
  }

  // No auto logon credential was set, no need to send credential changed event.
  return false;
}

void CGaiaCredentialProvider::ProviderConcurrentState::GetUpdatedState(
    bool* needs_to_refresh_users,
    GaiaCredentialComPtrStorage* auto_logon_credential) {
  DCHECK(needs_to_refresh_users);
  DCHECK(auto_logon_credential);
  base::AutoLock locker(state_update_lock_);

  // States need to be mutually exclusive.
  DCHECK(!users_need_to_be_refreshed_ || !auto_logon_credential_);

  *needs_to_refresh_users = users_need_to_be_refreshed_;
  auto_logon_credential->gaia_cred = auto_logon_credential_;

  // No specific state set this cycle, maybe there was a user update pending
  // that should now be processed.
  if (!users_need_to_be_refreshed_ && !auto_logon_credential_) {
    *needs_to_refresh_users = pending_users_refresh_needed_;
    // Can now reset the pending refresh since it has been processed.
    pending_users_refresh_needed_ = false;
  }

  // State has been extracted for use, reset back to the default state.
  InternalReset();
}

void CGaiaCredentialProvider::ProviderConcurrentState::Reset() {
  base::AutoLock locker(state_update_lock_);
  InternalReset();

  // This is a full explicit reset, we also need to reset any pending refresh
  // that may be needed.
  pending_users_refresh_needed_ = false;
}

void CGaiaCredentialProvider::ProviderConcurrentState::InternalReset() {
  users_need_to_be_refreshed_ = false;
  auto_logon_credential_.Release();
}

CGaiaCredentialProvider::CGaiaCredentialProvider() {}

CGaiaCredentialProvider::~CGaiaCredentialProvider() {}

HRESULT CGaiaCredentialProvider::FinalConstruct() {
  LOGFN(INFO);
  CleanupOlderVersions();
  return S_OK;
}

void CGaiaCredentialProvider::FinalRelease() {
  LOGFN(INFO);
  CHECK(!token_handle_updater_);
  ClearTransient();
  // Unlock all the users that had their access locked due to invalid token
  // handles.
  AssociatedUserValidator::Get()->AllowSigninForUsersWithInvalidTokenHandles();
}

HRESULT CGaiaCredentialProvider::DestroyCredentials() {
  LOGFN(INFO);
  for (auto it = users_.begin(); it != users_.end(); ++it)
    (*it)->Terminate();

  users_.clear();
  return S_OK;
}

void CGaiaCredentialProvider::ClearTransient() {
  LOGFN(INFO);
  CHECK(!token_handle_updater_);
  // Reset event support.
  advise_context_ = 0;
  events_.Release();
  set_serialization_sid_.clear();
  concurrent_state_.Reset();
  user_array_.Release();
}

void CGaiaCredentialProvider::CleanupOlderVersions() {
  base::FilePath versions_directory = GetInstallDirectory();
  if (!versions_directory.empty())
    DeleteVersionsExcept(versions_directory, TEXT(CHROME_VERSION_STRING));
}

HRESULT CGaiaCredentialProvider::CreateAnonymousCredentialIfNeeded(
    bool showing_other_user) {
  GaiaCredentialComPtrStorage cred;
  HRESULT hr = E_FAIL;
  if (showing_other_user) {
    hr = CreateCredentialObject<COtherUserGaiaCredential>(
        other_user_cred_creator_, &cred);
  } else if (CanNewUsersBeCreated(cpus_)) {
    hr =
        CreateCredentialObject<CGaiaCredential>(anonymous_cred_creator_, &cred);
  } else {
    return S_OK;
  }

  if (SUCCEEDED(hr)) {
    hr = cred.gaia_cred->Initialize(this);
    if (SUCCEEDED(hr)) {
      AddCredentialAndCheckAutoLogon(cred.gaia_cred, base::string16(), nullptr);
    } else {
      LOG(ERROR) << "Could not create credential hr=" << putHR(hr);
    }
  }

  return hr;
}

HRESULT CGaiaCredentialProvider::CreateReauthCredentials(
    ICredentialProviderUserArray* users,
    GaiaCredentialComPtrStorage* auto_logon_credential) {
  std::map<base::string16, std::pair<base::string16, base::string16>>
      sid_to_username;

  OSUserManager* manager = OSUserManager::Get();

  // Get the SIDs of all users being shown in the logon UI.
  if (!users) {
    LOGFN(ERROR) << "hr=" << putHR(E_INVALIDARG);
    return E_INVALIDARG;
  }

  HRESULT hr = users->SetProviderFilter(Identity_LocalUserProvider);
  if (FAILED(hr)) {
    LOGFN(ERROR) << "users->SetProviderFilter hr=" << putHR(hr);
    return hr;
  }

  DWORD count;
  hr = users->GetCount(&count);
  if (FAILED(hr)) {
    LOGFN(ERROR) << "users->GetCount hr=" << putHR(hr);
    return hr;
  }

  LOGFN(INFO) << "count=" << count;

  if (!AssociatedUserValidator::Get()->HasInternetConnection()) {
    // When there is no internet, do not associate GCPW as a reauth
    // credential for all sids.
    return S_OK;
  }

  for (DWORD i = 0; i < count; ++i) {
    CComPtr<ICredentialProviderUser> user;
    hr = users->GetAt(i, &user);
    if (FAILED(hr)) {
      LOGFN(ERROR) << "users->GetAt hr=" << putHR(hr);
      return hr;
    }

    wchar_t* sid_buffer = nullptr;

    hr = user->GetSid(&sid_buffer);
    if (FAILED(hr)) {
      LOGFN(ERROR) << "user->GetSid hr=" << putHR(hr);
      continue;
    }

    base::string16 sid = sid_buffer;
    ::CoTaskMemFree(sid_buffer);

    wchar_t username[kWindowsUsernameBufferLength];
    wchar_t domain[kWindowsDomainBufferLength];

    hr = manager->FindUserBySID(sid.c_str(), username, base::size(username),
                                domain, base::size(domain));
    if (FAILED(hr)) {
      LOGFN(ERROR) << "Can't get sid or username hr=" << putHR(hr);
      continue;
    }

    // Get the user's gaia id from registry stored against the sid if it
    // exists.
    wchar_t user_id[64];
    ULONG user_id_length = base::size(user_id);
    hr = GetUserProperty(sid.c_str(), kUserId, user_id, &user_id_length);
    if (FAILED(hr))
      user_id[0] = L'\0';

    bool is_token_handle_valid_for_user =
        (AssociatedUserValidator::Get()->IsTokenHandleValidForUser(sid));

    // (1) For a domain joined user, only check for token validity if the
    // user id is not empty. If user id is empty, we should create the
    // reauth credential by default for all AD user sids.
    // (2) For a non-domain joined user, just check if the token handle is
    // valid. If valid, then no need to create a re-auth credential for
    // this sid.
    if (CGaiaCredentialBase::IsAdToGoogleAssociationEnabled() &&
        OSUserManager::Get()->IsUserDomainJoined(sid)) {
      if (user_id[0] && is_token_handle_valid_for_user)
        continue;
    } else if (is_token_handle_valid_for_user) {
      // If the token handle is valid, no need to create a reauth credential.
      // The user can just sign in using their password.
      continue;
    }

    GaiaCredentialComPtrStorage cred;
    HRESULT hr =
        CreateCredentialObject<CReauthCredential>(reauth_cred_creator_, &cred);
    if (FAILED(hr)) {
      LOG(ERROR) << "Could not create credential hr=" << putHR(hr);
      return hr;
    }

    hr =
        InitializeReauthCredential(this, sid, domain, username, cred.gaia_cred);
    if (FAILED(hr)) {
      LOG(ERROR) << "InitializeReauthCredential hr=" << putHR(hr);
      return hr;
    }

    AddCredentialAndCheckAutoLogon(cred.gaia_cred, sid, auto_logon_credential);
  }

  return S_OK;
}

void CGaiaCredentialProvider::AddCredentialAndCheckAutoLogon(
    const CComPtr<IGaiaCredential>& cred,
    const base::string16& sid,
    GaiaCredentialComPtrStorage* auto_logon_credential) {
  USES_CONVERSION;
  users_.emplace_back(cred);

  if (!auto_logon_credential)
    return;

  if (sid.empty())
    return;

  if (set_serialization_sid_.empty())
    return;

  // If serialization sid is set, then try to see if this credential is a reauth
  // credential that needs to be auto signed in.
  CComPtr<IReauthCredential> associated_user;
  if (FAILED(cred.QueryInterface(&associated_user)))
    return;

  if (set_serialization_sid_ != sid)
    return;

  auto_logon_credential->gaia_cred = cred;
  set_serialization_sid_.clear();
}

void CGaiaCredentialProvider::RecreateCredentials(
    GaiaCredentialComPtrStorage* auto_logon_credential) {
  LOGFN(INFO);
  DCHECK(user_array_);

  DestroyCredentials();

  CREDENTIAL_PROVIDER_ACCOUNT_OPTIONS options;
  HRESULT hr = user_array_->GetAccountOptions(&options);
  bool showing_other_user =
      SUCCEEDED(hr) && options != CPAO_EMPTY_CONNECTED && options != CPAO_NONE;
  hr = CreateAnonymousCredentialIfNeeded(showing_other_user);
  if (FAILED(hr))
    LOG(ERROR) << "Could not create anonymous credential hr=" << putHR(hr);

  hr = CreateReauthCredentials(user_array_, auto_logon_credential);
  if (FAILED(hr))
    LOG(ERROR) << "CreateReauthCredentials hr=" << putHR(hr);
}

void CGaiaCredentialProvider::SetCredentialCreatorFunctionsForTesting(
    CredentialCreatorFn anonymous_cred_creator,
    CredentialCreatorFn other_user_cred_creator,
    CredentialCreatorFn reauth_cred_creator) {
  DCHECK(!anonymous_cred_creator_);
  DCHECK(!other_user_cred_creator_);
  DCHECK(!reauth_cred_creator_);

  anonymous_cred_creator_ = anonymous_cred_creator;
  other_user_cred_creator_ = other_user_cred_creator;
  reauth_cred_creator_ = reauth_cred_creator;
}

HRESULT CGaiaCredentialProvider::OnUserAuthenticatedImpl(
    IUnknown* credential,
    BSTR /*username*/,
    BSTR /*password*/,
    BSTR sid,
    BOOL fire_credentials_changed) {
  DCHECK(!credential || sid);

  if (!fire_credentials_changed)
    return S_OK;

  // Ensure that user access cannot be denied at this time so that the user
  // that is about to sign in won't be locked. If a ScopedLockDenyAccessUpdate
  // is created before calling this function this should guarantee that
  // situation because the call to BlockDenyAccessUpdate is locked with the
  // same lock that is used in DenySigninForUsersWithInvalidTokenHandles.
  // So either the call to Deny has finished and no new deny will occur
  // afterwards or the Deny will be disabled because the block has been
  // incremented first.
  CHECK(!credential ||
        AssociatedUserValidator::Get()->IsDenyAccessUpdateBlocked());

  CComPtr<IGaiaCredential> gaia_credential;
  if (credential->QueryInterface(IID_IGaiaCredential,
                                 reinterpret_cast<void**>(&gaia_credential)) ==
      S_OK) {
    // Try to set the auto logon credential. If it succeeds we can raise a
    // credential changed event.
    if (concurrent_state_.SetAutoLogonCredential(gaia_credential) && events_)
      events_->CredentialsChanged(advise_context_);
  }

  LOGFN(INFO) << "Signing in authenticated sid=" << OLE2CW(sid);
  return S_OK;
}

// Static.
bool CGaiaCredentialProvider::IsUsageScenarioSupported(
    CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus) {
  return cpus == CPUS_LOGON || cpus == CPUS_UNLOCK_WORKSTATION;
}

// Static.
bool CGaiaCredentialProvider::CanNewUsersBeCreated(
    CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus) {
  // When in an unlock usage, only the user that locked the computer will be
  // allowed to sign in, so no new users can be added.
  if (cpus == CPUS_UNLOCK_WORKSTATION)
    return false;

  return GetGlobalFlagOrDefault(kRegMdmSupportsMultiUser, 1) ||
         !AssociatedUserValidator::Get()->GetAssociatedUsersCount();
}

// ICredentialUpdateEventsHandler //////////////////////////////////////////////

void CGaiaCredentialProvider::UpdateCredentialsIfNeeded(
    bool user_access_changed) {
  // Defer refresh of the users to the next GetCredentialCount that will be
  // called after the credentials changed event. This prevents potential
  // contention of the |users_| list in multiple places. If the call to
  // RequestUserRefreshIfNeeded returns true, this means we are allowed to
  // proceed with a credentials changed event. Otherwise either no credentials
  // need to be updated (|user_access_changed| == false) or a higher priority
  // update is pending (e.g. auto logon) and thus we cannot send a
  // credentials changed event.
  if (concurrent_state_.RequestUserRefreshIfNeeded(user_access_changed) &&
      events_) {
    events_->CredentialsChanged(advise_context_);
  }
}

// IGaiaCredentialProvider ////////////////////////////////////////////////////

HRESULT CGaiaCredentialProvider::GetUsageScenario(DWORD* cpus) {
  DCHECK(cpus);
  *cpus = static_cast<DWORD>(cpus_);
  return S_OK;
}

HRESULT CGaiaCredentialProvider::OnUserAuthenticated(
    IUnknown* credential,
    BSTR username,
    BSTR password,
    BSTR sid,
    BOOL fire_credentials_changed) {
  return OnUserAuthenticatedImpl(credential, username, password, sid,
                                 fire_credentials_changed);
}

// ICredentialProviderSetUserArray ////////////////////////////////////////////

HRESULT CGaiaCredentialProvider::SetUserArray(
    ICredentialProviderUserArray* users) {
  LOGFN(INFO);
  CHECK(!token_handle_updater_);

  if (!IsUsageScenarioSupported(cpus_))
    return S_OK;

  if (users_.size() > 0) {
    LOG(ERROR) << "Users should be empty";
    return E_UNEXPECTED;
  }

  user_array_ = users;
  // Force refresh of all users on the next GetCredentialCount.
  concurrent_state_.RequestUserRefreshIfNeeded(true);

  return S_OK;
}

// ICredentialProvider ////////////////////////////////////////////////////////

HRESULT CGaiaCredentialProvider::SetUsageScenario(
    CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus,
    DWORD flags) {
  ClearTransient();
  CHECK(!token_handle_updater_);

  cpus_ = cpus;
  cpus_flags_ = flags;

  LOGFN(INFO) << " cpu=" << cpus << " flags=" << std::setbase(16) << flags;
  return IsUsageScenarioSupported(cpus_) ? S_OK : E_NOTIMPL;
}

HRESULT CGaiaCredentialProvider::SetSerialization(
    const CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcs) {
  DCHECK(pcpcs);
  CHECK(!token_handle_updater_);

  if (pcpcs->clsidCredentialProvider != CLSID_GaiaCredentialProvider)
    return E_NOTIMPL;

  ULONG auth_package_id;
  HRESULT hr = GetAuthenticationPackageId(&auth_package_id);
  if (FAILED(hr))
    return E_NOTIMPL;

  if (pcpcs->ulAuthenticationPackage != auth_package_id)
    return E_NOTIMPL;

  if (pcpcs->cbSerialization == 0)
    return E_NOTIMPL;

  // If serialziation data is set, try to extract the sid for the user
  // referenced in the serialization data.
  hr = DetermineUserSidFromAuthenticationBuffer(pcpcs, &set_serialization_sid_);
  if (FAILED(hr))
    LOGFN(ERROR) << "DetermineUserSidFromAuthenticationBuffer hr=" << putHR(hr);

  return S_OK;
}

HRESULT CGaiaCredentialProvider::Advise(ICredentialProviderEvents* pcpe,
                                        UINT_PTR context) {
  DCHECK(pcpe);
  CHECK(!token_handle_updater_);

  events_ = pcpe;
  advise_context_ = context;

  if (AssociatedUserValidator::Get()->IsUserAccessBlockingEnforced(cpus_)) {
    token_handle_updater_ =
        std::make_unique<BackgroundTokenHandleUpdater>(cpus_, this);
  }

  return S_OK;
}

HRESULT CGaiaCredentialProvider::UnAdvise() {
  // Kill the updater thread (if any).
  token_handle_updater_.reset();

  ClearTransient();
  DestroyCredentials();

  // Delete the startup sentinel file if any still exists. It can still exist in
  // 2 cases:

  // 1. The UnAdvise should only occur after the user has logged in, so if they
  // never selected any gaia credential and just used normal credentials this
  // function will be called in that situation and it is guaranteed that the
  // user has at least been able provide some input to winlogon.
  // 2. When no usage scenario is supported, none of the credentials will be
  // selected and thus the gcpw startup sentinel file will not be deleted. So in
  // the case where the user is asked for CPUS_CRED_UI enough times, the
  // sentinel file size will keep growing without being deleted and eventually
  // GCPW will be disabled completely. In the unsupported usage scenario,
  // FinalRelease will be called shortly after SetUsageScenario if the function
  // returns E_NOTIMPL so try to catch potential crashes of the destruction of
  // the provider when it is not used because crashes in this case will prevent
  // the cred ui from coming up and not allow the user to access their desired
  // resource.
  DeleteStartupSentinel();

  return S_OK;
}

HRESULT CGaiaCredentialProvider::GetFieldDescriptorCount(DWORD* count) {
  *count = FIELD_COUNT;
  return S_OK;
}

HRESULT CGaiaCredentialProvider::GetFieldDescriptorAt(
    DWORD index,
    CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR** ppcpfd) {
  *ppcpfd = nullptr;
  HRESULT hr = E_INVALIDARG;
  if (index < FIELD_COUNT) {
    // Always return a CoTask copy of the structure as well as any strings
    // pointed to by that structure.
    *ppcpfd = reinterpret_cast<CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR*>(
        ::CoTaskMemAlloc(sizeof(**ppcpfd)));
    if (*ppcpfd) {
      **ppcpfd = g_field_desc[index];
      // The password field has special greyed out text that is not set through
      // calls to ICredentialProviderCredential::GetStringValue so we need to
      // localize it manually here.
      if (index == FID_CURRENT_PASSWORD_FIELD) {
        base::string16 password_label(
            GetStringResource(IDS_WINDOWS_PASSWORD_FIELD_LABEL_BASE));
        hr = ::SHStrDupW(password_label.c_str(), &(*ppcpfd)->pszLabel);
      } else if ((*ppcpfd)->pszLabel) {
        hr = ::SHStrDupW((*ppcpfd)->pszLabel, &(*ppcpfd)->pszLabel);
      } else {
        (*ppcpfd)->pszLabel = nullptr;
        hr = S_OK;
      }
    }

    if (FAILED(hr)) {
      ::CoTaskMemFree(*ppcpfd);
      *ppcpfd = nullptr;
    }
  }

  return hr;
}

HRESULT CGaiaCredentialProvider::GetCredentialCount(
    DWORD* count,
    DWORD* default_index,
    BOOL* autologin_with_default) {
  bool needs_to_refresh_users = false;
  GaiaCredentialComPtrStorage local_auto_logon_credential;

  // Get the mutually exclusive state of the provider so that we can
  // determine the correct next step (recreate credentials or auto logon).
  concurrent_state_.GetUpdatedState(&needs_to_refresh_users,
                                    &local_auto_logon_credential);

  // NOTE: assumes SetUserArray() is called before this.
  if (needs_to_refresh_users)
    RecreateCredentials(&local_auto_logon_credential);

  *count = users_.size();
  *default_index = CREDENTIAL_PROVIDER_NO_DEFAULT;
  *autologin_with_default = false;

  // If a user was authenticated, winlogon was notified of credentials changes
  // and is re-enumerating the credentials.  Make sure autologin is enabled.
  if (local_auto_logon_credential.gaia_cred) {
    // Find the index of the credential that should contain the authentication
    // information.
    for (size_t i = 0;
         i < users_.size() && *default_index == CREDENTIAL_PROVIDER_NO_DEFAULT;
         ++i) {
      if (local_auto_logon_credential.gaia_cred.IsEqualObject(users_[i]))
        *default_index = i;
    }

    *autologin_with_default = *default_index != CREDENTIAL_PROVIDER_NO_DEFAULT;
  }

  LOGFN(INFO) << " count=" << *count << " default=" << *default_index
              << " auto=" << *autologin_with_default;
  return S_OK;
}

HRESULT CGaiaCredentialProvider::GetCredentialAt(
    DWORD index,
    ICredentialProviderCredential** ppcpc) {
  HRESULT hr = E_INVALIDARG;
  if (!ppcpc || index >= users_.size()) {
    LOG(ERROR) << "hr=" << putHR(hr) << " index=" << index;
    return hr;
  }

  *ppcpc = nullptr;
  hr = users_[index]->QueryInterface(IID_ICredentialProviderCredential,
                                     (void**)ppcpc);

  LOGFN(INFO) << "hr=" << putHR(hr) << " index=" << index;
  return hr;
}

}  // namespace credential_provider
