I've trying to make my custom credential provider with c++.I have read official documentation and checked existing samples. But, I misunderstand how to authenticate in windows, what function I should to use or where I should compare the entered password to login in system?
I have created a tile with one password field, but idk what I should do with entered data, how I should validate it and where I need to transfer it.
HRESULT CSampleCredential::GetSerialization(
CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE* pcpgsr,
CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION* pcpcs,
PWSTR* ppwzOptionalStatusText,
CREDENTIAL_PROVIDER_STATUS_ICON* pcpsiOptionalStatusIcon
)
{
UNREFERENCED_PARAMETER(ppwzOptionalStatusText);
UNREFERENCED_PARAMETER(pcpsiOptionalStatusIcon);
HRESULT hr;
WCHAR wsz[MAX_COMPUTERNAME_LENGTH+1];
DWORD cch = ARRAYSIZE(wsz);
DWORD cb = 0;
BYTE* rgb = NULL;
if (GetComputerNameW(wsz, &cch))
{
PWSTR pwzProtectedPassword;
hr = ProtectIfNecessaryAndCopyPassword(_rgFieldStrings[SFI_PASSWORD], _cpus, &pwzProtectedPassword);
// Only CredUI scenarios should use CredPackAuthenticationBuffer. Custom packing logic is necessary for
// logon and unlock scenarios in order to specify the correct MessageType.
if (CPUS_CREDUI == _cpus)
{
if (SUCCEEDED(hr))
{
PWSTR pwzDomainUsername = NULL;
hr = DomainUsernameStringAlloc(wsz, _rgFieldStrings[SFI_USERNAME], &pwzDomainUsername);
if (SUCCEEDED(hr))
{
// We use KERB_INTERACTIVE_UNLOCK_LOGON in both unlock and logon scenarios. It contains a
// KERB_INTERACTIVE_LOGON to hold the creds plus a LUID that is filled in for us by Winlogon
// as necessary.
if (!CredPackAuthenticationBufferW((CREDUIWIN_PACK_32_WOW & _dwFlags) ? CRED_PACK_WOW_BUFFER : 0, pwzDomainUsername, pwzProtectedPassword, rgb, &cb))
{
if (ERROR_INSUFFICIENT_BUFFER == GetLastError())
{
rgb = (BYTE*)HeapAlloc(GetProcessHeap(), 0, cb);
if (rgb)
{
// If the CREDUIWIN_PACK_32_WOW flag is set we need to return 32 bit buffers to our caller we do this by
// passing CRED_PACK_WOW_BUFFER to CredPacAuthenticationBufferW.
if (!CredPackAuthenticationBufferW((CREDUIWIN_PACK_32_WOW & _dwFlags) ? CRED_PACK_WOW_BUFFER : 0, pwzDomainUsername, pwzProtectedPassword, rgb, &cb))
{
HeapFree(GetProcessHeap(), 0, rgb);
hr = HRESULT_FROM_WIN32(GetLastError());
}
else
{
hr = S_OK;
}
}
else
{
hr = E_OUTOFMEMORY;
}
}
else
{
hr = E_FAIL;
}
HeapFree(GetProcessHeap(), 0, pwzDomainUsername);
}
else
{
hr = E_FAIL;
}
}
CoTaskMemFree(pwzProtectedPassword);
}
}
else
{
KERB_INTERACTIVE_UNLOCK_LOGON kiul;
// Initialize kiul with weak references to our credential.
hr = KerbInteractiveUnlockLogonInit(wsz, _rgFieldStrings[SFI_USERNAME], pwzProtectedPassword, _cpus, &kiul);
if (SUCCEEDED(hr))
{
// We use KERB_INTERACTIVE_UNLOCK_LOGON in both unlock and logon scenarios. It contains a
// KERB_INTERACTIVE_LOGON to hold the creds plus a LUID that is filled in for us by Winlogon
// as necessary.
hr = KerbInteractiveUnlockLogonPack(kiul, &pcpcs->rgbSerialization, &pcpcs->cbSerialization);
}
}
if (SUCCEEDED(hr))
{
ULONG ulAuthPackage;
hr = RetrieveNegotiateAuthPackage(&ulAuthPackage);
if (SUCCEEDED(hr))
{
pcpcs->ulAuthenticationPackage = ulAuthPackage;
pcpcs->clsidCredentialProvider = CLSID_CSampleProvider;
// In CredUI scenarios, we must pass back the buffer constructed with CredPackAuthenticationBuffer.
if (CPUS_CREDUI == _cpus)
{
pcpcs->rgbSerialization = rgb;
pcpcs->cbSerialization = cb;
}
// At this point the credential has created the serialized credential used for logon
// By setting this to CPGSR_RETURN_CREDENTIAL_FINISHED we are letting logonUI know
// that we have all the information we need and it should attempt to submit the
// serialized credential.
*pcpgsr = CPGSR_RETURN_CREDENTIAL_FINISHED;
}
else
{
HeapFree(GetProcessHeap(), 0, rgb);
}
}
}
else
{
DWORD dwErr = GetLastError();
hr = HRESULT_FROM_WIN32(dwErr);
}
return hr;
}