简体   繁体   中英

Diamond inheritance using Windows V2 Credential Providers

Following situation:

I have a working V1 CP that implements the IConnectableCredentialProviderCredential interface. This dependency is necessary to have access to the IQueryContinueWithStatus interface, which I need.

class CCredential : public IConnectableCredentialProviderCredential
{
    [...]

IConnectableCredentialProviderCredential implements ICredentialProviderCredential .

The COM IUknown query method is done using this snippet:

IFACEMETHODIMP QueryInterface(__in REFIID riid, __deref_out void** ppv)
{
    static const QITAB qitOnlyCredUI[] =
    {
        QITABENT(CCredential, ICredentialProviderCredential),
        { 0 },
    };

    static const QITAB qitFull[] =
    {
        QITABENT(CCredential, ICredentialProviderCredential), // IID_ICredentialProviderCredential
        QITABENT(CCredential, IConnectableCredentialProviderCredential), // IID_IConnectableCredentialProviderCredential            
        { 0 },
    };

[...]

Now I want to migrate the provider to be a V2 CP and implement the ICredentialProviderCredential2 interface, but stay compatible to the IQueryContinueWithStatus interface. Also, dropping QITABENT(CCredential, ICredentialProviderCredential) out is no option, because qitOnlyCredUI is necessary in case a CredUI is requested, which does not support IQueryContinueWithStatus .

class CCredential : public IConnectableCredentialProviderCredential,
                    public ICredentialProviderCredential2,
                    public ICredentialProviderCredentialWithFieldOptions
{
    [...]

ICredentialProviderCredential2 implements ICredentialProviderCredential .

Implementing the COM QueryInterface method like:

IFACEMETHODIMP QueryInterface(__in REFIID riid, __deref_out void** ppv)
{
    static const QITAB qitOnlyCredUI[] =
    {
        QITABENT(CCredential, ICredentialProviderCredential),
        { 0 },
    };

    static const QITAB qitFull[] =
    {
        QITABENT(CCredential, ICredentialProviderCredential), // IID_ICredentialProviderCredential
        QITABENT(CCredential, ICredentialProviderCredential2), // IID_ICredentialProviderCredential2
        QITABENT(CCredential, IConnectableCredentialProviderCredential), // IID_IConnectableCredentialProviderCredential            
        QITABENT(CCredential, ICredentialProviderCredentialWithFieldOptions), //IID_ICredentialProviderCredentialWithFieldOptions
        { 0 },
    };

This is where the Diamond Problem starts, as ICredentialProviderCredential2 and IConnectableCredentialProviderCredential both implement ICredentialProviderCredential .

Trying to compile certainly leads to the compiler complaining about ambiguous definitions for the ICredentialProviderCredential base class.

Any ideas how this can be accomplished?

You will need to use the QITABENTMULTI() macro for your case. It's documented in shlwapi.h . I have no idea why it isn't on MSDN.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM