How to change the Password in Custom Credential Provider, In LOCK Scenario i.e., CPUS_UNLOCK_WORKSTATION in C++

Aslam Mahaboob A 1 Reputation point


Platform Windows 10.
Language C++, Visual Studio 2019

I am writing a Custom Credential Provider in C++, where I need to change the Domain password for a user in LOCK Scenario i.e., CPUS_UNLOCK_WORKSTATION, Can any one help me in guiding to tell me the steps or help in writing the code.


Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,412 questions
Windows 10 Compatibility
Windows 10 Compatibility
Windows 10: A Microsoft operating system that runs on personal computers and tablets.Compatibility: The extent to which hardware or software adheres to an accepted standard.
454 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Xiaopo Yang - MSFT 11,336 Reputation points Microsoft Vendor

    Perhaps The Issue How do I support the CPUS_UNLOCK_WORKSTATION scenario? can help you. Also pay attention to that attached code link which involve changing the Password in CPUS_UNLOCK_WORKSTATION condition.

  2. Xiaopo Yang - MSFT 11,336 Reputation points Microsoft Vendor

    I regret that the attached sample cannot run in my computer which even doesn't show logon UI.
    With Microsoft Github Sample:sampleallcontrolscredentialprovider, I found a solution which can hide and show UI in LOCK Scenario.
    The following code exists because I found that The Sample clears the password content. Hope helpful.

    HRESULT CSampleCredential::ReportResult(
        __in NTSTATUS ntsStatus, 
        __in NTSTATUS ntsSubstatus,
        __deref_out_opt PWSTR* ppwszOptionalStatusText, 
        __out CREDENTIAL_PROVIDER_STATUS_ICON* pcpsiOptionalStatusIcon
        *ppwszOptionalStatusText = NULL;
        *pcpsiOptionalStatusIcon = CPSI_NONE;
        DWORD dwStatusInfo = (DWORD)-1;
        // Look for a match on status and substatus.
        for (DWORD i = 0; i < ARRAYSIZE(s_rgLogonStatusInfo); i++)
            if (s_rgLogonStatusInfo[i].ntsStatus == ntsStatus && s_rgLogonStatusInfo[i].ntsSubstatus == ntsSubstatus)
                dwStatusInfo = i;
        if ((DWORD)-1 != dwStatusInfo)
            if (SUCCEEDED(SHStrDupW(s_rgLogonStatusInfo[dwStatusInfo].pwzMessage, ppwszOptionalStatusText)))
                *pcpsiOptionalStatusIcon = s_rgLogonStatusInfo[dwStatusInfo].cpsi;
        // If we failed the logon, try to erase the password field.
        if (!SUCCEEDED(HRESULT_FROM_NT(ntsStatus)))
            if (_pCredProvCredentialEvents)
                _pCredProvCredentialEvents->SetFieldString(this, SFI_PASSWORD, L"");
            /*PWSTR pwszDest = (PWSTR)HeapAlloc(GetProcessHeap(), 0, 255);
            if (pwszDest)
                StringCbPrintfW(pwszDest, 255, L"ntsStatus %d, ntsSubstatus %d", ntsStatus, ntsSubstatus);
                ::MessageBox(NULL,pwszDest, TEXT("SEE ME?"), 0);
                HeapFree(GetProcessHeap(), 0, pwszDest);
            //The user's password must be changed before signing in.
            if (STATUS_PASSWORD_MUST_CHANGE == ntsStatus)
                //::MessageBox(NULL, TEXT("can we"), TEXT("Here?"), 0);
                _pCredProvCredentialEvents->SetFieldState(this, SFI_CHECKBOX, CPFS_HIDDEN);
                _pCredProvCredentialEvents->SetFieldState(this, SFI_COMMAND_LINK, CPFS_DISPLAY_IN_SELECTED_TILE);
            //Change UI For Password Expired
            if (STATUS_PASSWORD_EXPIRED == ntsSubstatus)
                _pCredProvCredentialEvents->SetFieldState(this, SFI_CHECKBOX, CPFS_DISPLAY_IN_SELECTED_TILE);
                _pCredProvCredentialEvents->SetFieldState(this, SFI_COMMAND_LINK, CPFS_HIDDEN);
        // Since NULL is a valid value for *ppwszOptionalStatusText and *pcpsiOptionalStatusIcon
        // this function can't fail.
        return S_OK;