I am unable to implement Windows Custom Credential Provider to all the users in a pc during logon when they click sign-in option. Tile is getting displayed for only my main user.
I modified Initialize function in CSampleCredential.cpp file to:
HRESULT CSampleCredential::Initialize(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus,
_In_ CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR const *rgcpfd,
_In_ FIELD_STATE_PAIR const *rgfsp,
_In_ ICredentialProviderUser *pcpUser)
{
HRESULT hr = S_OK;
_cpus = cpus;
GUID guidProvider;
pcpUser->GetProviderID(&guidProvider);
_fIsLocalUser = (guidProvider == Identity_LocalUserProvider);
// Copy the field descriptors for each field. This is useful if you want to vary the field
// descriptors based on what Usage scenario the credential was created for.
for (DWORD i = 0; SUCCEEDED(hr) && i < ARRAYSIZE(_rgCredProvFieldDescriptors); i++)
{
_rgFieldStatePairs[i] = rgfsp[i];
hr = FieldDescriptorCopy(rgcpfd[i], &_rgCredProvFieldDescriptors[i]);
}
// Initialize the String value of all the fields.
if (SUCCEEDED(hr))
{
hr = SHStrDupW(L"Sample Credential", &_rgFieldStrings[SFI_LABEL]);
}
if (SUCCEEDED(hr))
{
hr = SHStrDupW(L"Zaperon Credential Provider", &_rgFieldStrings[SFI_LARGE_TEXT]);
}
if (SUCCEEDED(hr))
{
hr = SHStrDupW(L"Edit Text", &_rgFieldStrings[SFI_EDIT_TEXT]);
}
if (SUCCEEDED(hr))
{
hr = SHStrDupW(L"", &_rgFieldStrings[SFI_PASSWORD]);
}
if (SUCCEEDED(hr))
{
hr = SHStrDupW(L"Submit Test", &_rgFieldStrings[SFI_SUBMIT_BUTTON]);
}
if (SUCCEEDED(hr))
{
hr = SHStrDupW(L"Checkbox Test", &_rgFieldStrings[SFI_CHECKBOX]);
}
if (SUCCEEDED(hr))
{
hr = SHStrDupW(L"Combobox", &_rgFieldStrings[SFI_COMBOBOX]);
}
/*if (SUCCEEDED(hr))
{
hr = SHStrDupW(L"Launch helper window", &_rgFieldStrings[SFI_LAUNCHWINDOW_LINK]);
}*/
if (SUCCEEDED(hr))
{
hr = SHStrDupW(L"Hide additional controls", &_rgFieldStrings[SFI_HIDECONTROLS_LINK]);
}
if (SUCCEEDED(hr))
{
hr = pcpUser->GetStringValue(PKEY_Identity_QualifiedUserName, &_pszQualifiedUserName);
}
if (SUCCEEDED(hr))
{
PWSTR pszUserName;
pcpUser->GetStringValue(PKEY_Identity_UserName, &pszUserName);
if (pszUserName != nullptr)
{
wchar_t szString[256];
StringCchPrintf(szString, ARRAYSIZE(szString), L"User Name: %s", pszUserName);
hr = SHStrDupW(szString, &_rgFieldStrings[SFI_FULLNAME_TEXT]);
CoTaskMemFree(pszUserName);
}
else
{
hr = SHStrDupW(L"User Name is NULL", &_rgFieldStrings[SFI_FULLNAME_TEXT]);
}
}
if (SUCCEEDED(hr))
{
PWSTR pszDisplayName;
pcpUser->GetStringValue(PKEY_Identity_DisplayName, &pszDisplayName);
if (pszDisplayName != nullptr)
{
wchar_t szString[256];
StringCchPrintf(szString, ARRAYSIZE(szString), L"Display Name: %s", pszDisplayName);
hr = SHStrDupW(szString, &_rgFieldStrings[SFI_DISPLAYNAME_TEXT]);
CoTaskMemFree(pszDisplayName);
}
else
{
hr = SHStrDupW(L"Display Name is NULL", &_rgFieldStrings[SFI_DISPLAYNAME_TEXT]);
}
}
if (SUCCEEDED(hr))
{
PWSTR pszLogonStatus;
pcpUser->GetStringValue(PKEY_Identity_LogonStatusString, &pszLogonStatus);
if (pszLogonStatus != nullptr)
{
wchar_t szString[256];
StringCchPrintf(szString, ARRAYSIZE(szString), L"Logon Status: %s", pszLogonStatus);
hr = SHStrDupW(szString, &_rgFieldStrings[SFI_LOGONSTATUS_TEXT]);
CoTaskMemFree(pszLogonStatus);
}
else
{
hr = SHStrDupW(L"Logon Status is NULL", &_rgFieldStrings[SFI_LOGONSTATUS_TEXT]);
}
}
if (SUCCEEDED(hr))
{
hr = pcpUser->GetSid(&_pszUserSid);
}
return hr;
}
I am using microsoft sample credential provider repo here
I have also made following changes in _EnumerateCredentials and GetCredentialCount functions of CSampleprovider.cpp file.
_EnumerateCredentials():
HRESULT CSampleProvider::_EnumerateCredentials()
{
//_pCredential = new(std::nothrow) CSampleCredential();
HRESULT hr = E_UNEXPECTED;
DWORD dwUserCount;
if (_pCredProviderUserArray != nullptr)
{
_pCredProviderUserArray->GetCount(&dwUserCount);
if (dwUserCount > 0)
{
for (DWORD i = 0; i < dwUserCount; i++) {
ICredentialProviderUser* pCredUser;
hr = _pCredProviderUserArray->GetAt(i, &pCredUser);
if (SUCCEEDED(hr))
{
//_pCredential = new(std::nothrow) CSampleCredential();
_pCredentialVector.push_back(new(std::nothrow) CSampleCredential());
if (_pCredentialVector[i] != nullptr)
{
hr = _pCredentialVector[i]->Initialize(_cpus, s_rgCredProvFieldDescriptors, s_rgFieldStatePairs, pCredUser);
if (FAILED(hr))
{
_pCredentialVector[i]->Release();
_pCredentialVector[i] = nullptr;
}
}
else
{
hr = E_OUTOFMEMORY;
}
pCredUser->Release();
}
}
}
if ((dwUserCount == 0) || (IsOS(OS_DOMAINMEMBER) == 1)) {
_pCredentialVector.push_back(new(std::nothrow) CSampleCredential());
if (_pCredentialVector[_pCredentialVector.size() - 1] != nullptr) {
hr = _pCredentialVector[_pCredentialVector.size() - 1]->Initialize(_cpus, s_rgCredProvFieldDescriptors, s_rgFieldStatePairs, nullptr);
}
}
return hr;
}
return hr;
}
GetCredentialCount():
HRESULT CSampleProvider::GetCredentialCount(
_Out_ DWORD *pdwCount,
_Out_ DWORD *pdwDefault,
_Out_ BOOL *pbAutoLogonWithDefault)
{
*pdwDefault = CREDENTIAL_PROVIDER_NO_DEFAULT;
*pbAutoLogonWithDefault = FALSE;
if (_fRecreateEnumeratedCredentials)
{
_fRecreateEnumeratedCredentials = false;
_ReleaseEnumeratedCredentials();
_CreateEnumeratedCredentials();
}
DWORD dwUserCount;
HRESULT hr;
if (_pCredProviderUserArray != nullptr) {
hr = _pCredProviderUserArray->GetCount(&dwUserCount);
}
if ((dwUserCount == 0) || (IsOS(OS_DOMAINMEMBER) == 1)) {
dwUserCount += 1;//display additional empty tile
}
*pdwCount = dwUserCount;
return S_OK;
}
I am still unable to get CP tile to all my users with above provided code. So, How do I display my Credential provider for all users in a pc in sign-in options?