18 December, 2013

How to hide credential providers from Login Screen for Windows 7

Two ways to hide other credential providers except yours.

  • Edit your group policy 
Step 1: Run command:gpedit.msc
Step 2: Go to Computer Configuration->Administrative Templates->System->Logon
Step 3: Edit the item Exclude credential providers
Step 4: Enable it, and enter CLSIDs of credential providers you want to exclude

Windows 2008 and Windows 7 have the almost the same CLSIDs.

Please see the CLSIDs below:

Credential ProviderCLSID
Generic Provider{25CBB996-92ED-457e-B28C-4774084BD562}
NPProvider{3dd6bec0-8193-4ffe-ae25-e08e39ea4063}
VaultCredProvider{503739d0-4c5e-4cfd-b3ba-d881334f0df2}
Password Provider{6f45dc1e-5384-457a-bc13-2cd81b0d28ed}
Password Provider\LogonPasswordReset{8841d728-1a76-4682-bb6f-a9ea53b4b3ba}
Smartcard Credential Provider{8bf9a910-a8ff-457f-999f-a5ca10b4a885}
Smartcard Pin Provider{94596c7e-3744-41ce-893e-bbf09122f76a}
CertCredProvider{e74e57b0-6c6d-44d5-9cda-fb2df5ed7435}
Normally you only need to hide the Password Provider or Password Provider\LogonPasswordReset if you also implement the changing password scenario.

  • Implement the credential provider filter
I tested it. 

Steps:
You should have a separate project, e.g. named "CredentialProviderFilter".
Do not use the same project with credential provider, yes, you can, but I don't suggest it, since you have to add some condition logic in the method as below:
CClassFactory_CreateInstance//dll entry point to call this factory method
if(IID_ICredentialProvider == riid)
    hr = Provider_CreateInstance(riid, ppv);
else if(IID_ICredentialProviderFilter == riid)
    hr = Filter_CreateInstance(riid, ppv);

Remind: to include credentialprovider.h

And also mess up your provider or credential.


So here we go:
in your Dll.cpp file, please pay attention to these two methods:


HRESULT CClassFactory_CreateInstance(REFCLSID rclsid, REFIID riid, void** ppv)
{
    HRESULT hr;
    if (CLSID_CSampleProviderFilter == rclsid)
    {
        CClassFactory* pcf = new CClassFactory;
        if (pcf)
        {
            hr = pcf->QueryInterface(riid, ppv);
            pcf->Release();
        }
        else
        {
            hr = E_OUTOFMEMORY;
        }
    }
    else
    {
        hr = CLASS_E_CLASSNOTAVAILABLE;
    }
    return hr;
}


And the other one:


// IClassFactory
   STDMETHOD(CreateInstance)(IUnknown* pUnkOuter, REFIID riid, void** ppv)
    {
        HRESULT hr;
        if (!pUnkOuter)
        {
           // hr = CSampleProvider_CreateInstance(riid, ppv);
            hr = CProviderFilter_CreateInstance(riid,ppv);
        }
        else
        {
            hr = CLASS_E_NOAGGREGATION;
        }
        return hr;
    }

And in your Filter.h file


STDMETHOD(QueryInterface)(REFIID riid, void** ppv)
    {
        HRESULT hr;
        if (IID_IUnknown == riid || 
           IID_ICredentialProviderFilter == riid)
        {
            *ppv = this;
            reinterpret_cast(*ppv)->AddRef();
            hr = S_OK;
        }
        else
        {
            *ppv = NULL;
            hr = E_NOINTERFACE;
        }
        return hr;
    }

And finally in your Filter.cpp file:


HRESULT CProviderFilter_CreateInstance( REFIID riid, void** ppv)
{
    HRESULT hr;
    ProviderFilter * pProvider = new ProviderFilter();

    if (pProvider)
    {
        hr = pProvider->QueryInterface(riid, ppv);
        pProvider->Release();
    }
    else
    {
        hr = E_OUTOFMEMORY;
    }    
    return hr;
}



HRESULT ProviderFilter::Filter(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus,
        DWORD dwFlags,
        GUID *rgclsidProviders,
        BOOL *rgbAllow,
        DWORD cProviders)
{
    switch (cpus)
    {
    case CPUS_CREDUI:
        if (dwFlags & CREDUIWIN_GENERIC) 
            return S_OK;
    case CPUS_LOGON:
    case CPUS_UNLOCK_WORKSTATION:
    case CPUS_CHANGE_PASSWORD:
        for (int i = 0; i < cProviders; i++)
        {
           if (IsEqualGUID(rgclsidProviders[i],CLSID_PasswordCredentialProvider))
            {
                rgbAllow[i] = FALSE;
                break;
            }
            
        }
        return S_OK;
    default:
        return E_NOTIMPL;
    }
}

And the register file content:
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Provider Filters\{BEF85591-235B-4492-A40D-C04CAEEF5D9A}]
@="SampleHardwareEventCredentialProviderFilter"

[HKEY_CLASSES_ROOT\CLSID\{BEF85591-235B-4492-A40D-C04CAEEF5D9A}]
@="SampleHardwareEventCredentialProviderFilter"

[HKEY_CLASSES_ROOT\CLSID\{BEF85591-235B-4492-A40D-C04CAEEF5D9A}\InprocServer32]
@="SampleHardwareEventCredentialProviderFilter.dll"

"ThreadingModel"="Apartment"


Unregister file:

[-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Provider Filters\{BEF85591-235B-4492-A40D-C04CAEEF5D9A}]