次の方法で共有


IMFNetCredentialManager の実装

IMFNetCredentialManager::BeginGetCredentials メソッドで、次の操作を行います。

  1. IMFNetCredentialCache ポインターがまだない場合は、MFCreateCredentialCache を呼び出して資格情報キャッシュ オブジェクトを作成します。 このポインターを格納します。
  2. IMFNetCredentialCache::GetCredential を呼び出します。 dwAuthenticationFlags パラメーターのフラグを次のように設定します。
    • MFNetCredentialManagerGetParam 構造体の hrOp メンバーがNS_E_PROXY_ACCESSDENIEDと等しい場合は、MFNET_AUTHENTICATION_PROXY フラグを設定します。
    • fClearTextPackageTRUE の場合は、MFNET_AUTHENTICATION_CLEAR_TEXT フラグを設定します。
    • fAllowLoggedOnUserTRUE の場合は、MFNET_AUTHENTICATION_LOGGED_ON_USER フラグを設定します。
  3. GetCredential メソッドは、IMFNetCredential ポインターと、場合によっては REQUIRE_PROMPT フラグを返します。 IMFNetCredential ポインターを格納します。
  4. GetCredential がREQUIRE_PROMPT フラグを返さない場合は、完了です。 ステップ 9 に進みます。
  5. それ以外の場合、 GetCredential がREQUIRE_PROMPT フラグを返す場合は、ユーザーにユーザー名とパスワードの入力を求める必要があります。
  6. fClearTextPackageFALSE の場合は、資格情報を暗号化します。
  7. IMFNetCredential::SetUserIMFNetCredential::SetPassword を呼び出して、資格情報オブジェクトにユーザーの名前とパスワードを設定します。
  8. 必要に応じて、 IMFNetCredentialCache::SetUserOptions を呼び出して、資格情報の格納と送信に関するユーザー設定で資格情報キャッシュ オブジェクトを更新します。
  9. MFInvokeCallback を呼び出して、IMFAsyncCallback コールバックを呼び出します。

IMFNetCredentialManager::EndGetCredentials メソッドで、BeginGetCredentials メソッドで取得した IMFNetCredential ポインターを返します。

IMFNetCredentialManager::SetGood メソッドで、入力パラメーターを IMFNetCredentialCache::SetGood メソッドに直接渡します。 これにより、資格情報がサーバーによって受け入れられたかどうかを資格情報キャッシュに通知します。

ユーザーにプロンプトを表示する必要がある場合 (手順 5) または資格情報を暗号化する (手順 6) 場合は、Microsoft Media Foundation パイプラインをブロックしないように、作業キュー スレッドで行う必要があります。 MFPutWorkItem を呼び出し、作業キュー コールバック内で残りの手順を実行します。

注意

ネットワーク ソースの作成中 に BeginGetCredentials が呼び出される可能性があることに注意してください。 したがって、同期 IMFSourceResolver::CreateObjectFromURL メソッドを呼び出してネットワーク ソースを作成すると、資格情報の取得中に呼び出し元のスレッドがブロックされる可能性があります。 そのため、代わりに非同期 の IMFSourceResolver::BeginCreateObjectFromURL メソッドを使用することをお勧めします。

 

この例では、資格情報マネージャーが提供できる 1 種類の動作を示します。

IMFNetCredentialManager を実装する クラスの宣言を次に示します。

class CCredentialManager : public IMFNetCredentialManager, IMFAsyncCallback 
{
    long                    m_cRef;
    IMFNetCredentialCache   *m_pCredentialCache;

public:
    CCredentialManager () : m_cRef(1), m_pCredentialCache(NULL)
    { 
    }
    ~CCredentialManager()
    {
        SafeRelease(&m_pCredentialCache);
    }

    STDMETHODIMP QueryInterface(REFIID riid, void** ppv)
    {
        static const QITAB qit[] = 
        {
            QITABENT(CCredentialManager, IMFNetCredentialManager),
            QITABENT(CCredentialManager, IMFAsyncCallback),
            { 0 }
        };
        return QISearch(this, qit, riid, ppv);
    }      

    STDMETHODIMP_(ULONG) AddRef()
    {
        return InterlockedIncrement(&m_cRef);
    }

    STDMETHODIMP_(ULONG) Release()
    {
        LONG cRef = InterlockedDecrement(&m_cRef);
        if (cRef == 0)
        {
            delete this;
        }
        return cRef;
    }

    STDMETHODIMP BeginGetCredentials(
        MFNetCredentialManagerGetParam* pParam,
        IMFAsyncCallback* pCallback,
        IUnknown* pState
        );

    STDMETHODIMP EndGetCredentials(
        IMFAsyncResult* pResult, 
        IMFNetCredential** ppCred);

    STDMETHODIMP SetGood(IMFNetCredential* pCred, BOOL fGood)
    {
        if (!pCred)
        {
            return E_POINTER;
        }

        return m_pCredentialCache->SetGood(pCred, fGood);
    }


    STDMETHODIMP GetParameters(DWORD* pdwFlags, DWORD* pdwQueue)
    {
        return E_NOTIMPL;
    }

    STDMETHODIMP Invoke(IMFAsyncResult* pResult);
};

BeginGetCredentials 操作の状態を追跡するために、 クラスは次のヘルパー オブジェクトを使用します。

// Holds state information for the GetCredentials operation, so that work can 
// be moved to a work-queue thread.

struct CredentialOp : public IUnknown
{
    long                m_cRef;
    IMFNetCredential    *m_pCredential;
    DWORD               m_dwFlags;

    CredentialOp(IMFNetCredential *pCredential) 
        : m_cRef(1), m_dwFlags(0), m_pCredential(pCredential)
    {
        m_pCredential->AddRef();
    }

    ~CredentialOp()
    {
        SafeRelease(&m_pCredential);
    }

    STDMETHODIMP QueryInterface(REFIID riid, void** ppv)
    {
        static const QITAB qit[] = 
        {
            QITABENT(CredentialOp, IUnknown),
            { 0 }
        };
        return QISearch(this, qit, riid, ppv);
    }      

    STDMETHODIMP_(ULONG) AddRef()
    {
        return InterlockedIncrement(&m_cRef);
    }

    STDMETHODIMP_(ULONG) Release()
    {
        LONG cRef = InterlockedDecrement(&m_cRef);
        if (cRef == 0)
        {
            delete this;
        }
        return cRef;
    }
};

BeginGetCredentials メソッドは、資格情報キャッシュを作成し、IMFNetCredential ポインターを取得します。 ユーザーにメッセージを表示する必要がある場合 ( REQUIRE_PROMPT フラグで示されます)、メソッドは MFPutWorkItem を呼び出して新しい作業項目をキューに入れます。

STDMETHODIMP CCredentialManager::BeginGetCredentials(
    MFNetCredentialManagerGetParam* pParam,
    IMFAsyncCallback* pCallback,
    IUnknown* pState
    )
{
    if (!pParam || !pCallback)
    {
        return E_POINTER;
    }

    DWORD dwAuthenticationFlags = 0;
    DWORD dwRequirementFlags = 0;

    if (pParam->hrOp == NS_E_PROXY_ACCESSDENIED)
    {
        dwAuthenticationFlags |= MFNET_AUTHENTICATION_PROXY;
    }

    if (pParam->fAllowLoggedOnUser)
    {
        dwAuthenticationFlags |= MFNET_AUTHENTICATION_LOGGED_ON_USER;
    }

    if (pParam->fClearTextPackage)
    {
        dwAuthenticationFlags |= MFNET_AUTHENTICATION_CLEAR_TEXT;
    }

    IMFNetCredential *pCredential =  NULL;
    IMFAsyncResult* pResult = NULL;

    HRESULT hr = S_OK;

    if (m_pCredentialCache == NULL)
    {
        hr = MFCreateCredentialCache(&m_pCredentialCache);
        if (FAILED(hr))
        {
            goto done;
        }
    }

    hr = m_pCredentialCache->GetCredential(
        pParam->pszUrl, 
        pParam->pszRealm, 
        dwAuthenticationFlags, 
        &pCredential, 
        &dwRequirementFlags
        );

    if (FAILED(hr))
    {
        goto done;
    }

    if( ( dwRequirementFlags & REQUIRE_PROMPT ) == 0 )
    {
        // The credential is good to use. Prompting the user is not required.
        hr = S_OK;
        goto done;
    }

    // The credential requires prompting the user. 
    CredentialOp *pOp = new (std::nothrow) CredentialOp(pCredential);

    if (pOp == NULL)
    {
        hr = E_OUTOFMEMORY;
        goto done;
    }

    // Set flags. Use these to inform the user if the credentials will
    // be sent in plaintext or saved in the credential cache.

    if (pParam->fClearTextPackage)
    {
        // Notify the user that credentials will be sent in plaintext.
        pOp->m_dwFlags |= MFNET_CREDENTIAL_ALLOW_CLEAR_TEXT;
    }

    if(dwRequirementFlags & REQUIRE_SAVE_SELECTED )
    {
        // Credentials will be saved in the cache by default.
        pOp->m_dwFlags |= MFNET_CREDENTIAL_SAVE;
    }

    // NOTE: The application should enable to user to deselect these two flags;
    // for example, through check boxes in the prompt dialog.


    // Now queue the work item.

    hr = MFCreateAsyncResult(pOp, pCallback, pState, &pResult);
    if (FAILED(hr))
    {
        goto done;
    }

    hr = MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_LONG_FUNCTION, this, pResult);

done:
    SafeRelease(&pResult);
    SafeRelease(&pCredential);
    SafeRelease(&pOp);
    return hr;
}

作業キュー スレッドは Invoke を呼び出します。これにより、ユーザーにプロンプトが表示され、 MFInvokeCallback が呼び出されて 、BeginGetCredentials で提供されたコールバック ポインターが呼び出されます。

STDMETHODIMP CCredentialManager::Invoke(IMFAsyncResult* pResult)
{
    IUnknown *pState = NULL;
    IMFAsyncResult *pGetCredentialsResult = NULL;
    IUnknown *pOpState = NULL;

    CredentialOp *pOp = NULL;   // not AddRef'd

    HRESULT hr = pResult->GetState(&pState);

    if (SUCCEEDED(hr))
    {
        hr = pState->QueryInterface(IID_PPV_ARGS(&pGetCredentialsResult));
    }

    if (SUCCEEDED(hr))
    {
        hr = pGetCredentialsResult->GetObject(&pOpState);
    }

    if (SUCCEEDED(hr))
    {
        pOp = static_cast<CredentialOp*>(pOpState);

        // Display a dialog for the user to enter user name and password.
        hr = PromptUserCredentials(pOp);
    }

    if (SUCCEEDED(hr) && m_pCredentialCache)
    {
        // Update with options set by the user.
        hr = m_pCredentialCache->SetUserOptions(
            pOp->m_pCredential, 
            pOp->m_dwFlags
            );
    }

    if (pGetCredentialsResult)
    {
        pGetCredentialsResult->SetStatus(hr);
        MFInvokeCallback(pGetCredentialsResult);
    }

    SafeRelease(&pState);
    SafeRelease(&pGetCredentialsResult);
    SafeRelease(&pOpState);
    return S_OK;
}

EndGetCredentials メソッドは、呼び出し元への IMFNetCredential ポインターを返すことによって操作を完了します。

STDMETHODIMP CCredentialManager::EndGetCredentials(
    IMFAsyncResult* pResult, 
    IMFNetCredential** ppCred
    )
{
    if (!pResult || !ppCred)
    {
        return E_POINTER;
    }

    *ppCred = NULL;

    IUnknown *pUnk = NULL;

    // Check the result of the asynchronous operation.
    HRESULT hr = pResult->GetStatus();

    if (FAILED(hr))
    {
        // The operation failed.
        goto done;
    }

    hr = pResult->GetObject(&pUnk);
    if (FAILED(hr))
    {
        goto done;
    }

    CredentialOp *pOp = static_cast<CredentialOp*>(pUnk);

    *ppCred = pOp->m_pCredential;
    pOp->m_pCredential = NULL;

done:
    SafeRelease(&pUnk);
    return hr;
}

ネットワーク ソース認証