Delen via


Referenties voor serverauthenticatie opgeven voor een BITS-taak voor overdracht

U kunt verschillende verificatieschema's opgeven voor een BITS-overdrachtstaak (Background Intelligent Transfer Service).

Met de volgende procedure wordt een verificatieschema verkregen en een identificatiestructuur voor authenticatie aangemaakt. Vervolgens maakt de toepassing een BITS-downloadtaak en stelt de referenties voor de taak in. Nadat de taak is aangemaakt, ontvangt de toepassing een verwijzing naar een callback-interface en controleert vervolgens de status van de BITS-overdrachtstaak. Nadat de taak is voltooid, wordt deze uit de wachtrij verwijderd.

In dit voorbeeld wordt de header en implementatie gebruikt die zijn gedefinieerd in Voorbeeld: Algemene klassen.

Voor het opgeven van serververificatiereferenties voor een BITS-overdrachtstaak

  1. Maak een containerstructuur waarmee BG_AUTH_SCHEME waarden worden toegewezen aan schemanamen.

    struct
    {
        LPCWSTR        Name;
        BG_AUTH_SCHEME Scheme;
    }
    SchemeNames[] =
    {
        { L"basic",      BG_AUTH_SCHEME_BASIC },
        { L"digest",     BG_AUTH_SCHEME_DIGEST },
        { L"ntlm",       BG_AUTH_SCHEME_NTLM },
        { L"negotiate",  BG_AUTH_SCHEME_NEGOTIATE },
        { L"passport",   BG_AUTH_SCHEME_PASSPORT },
    
        { NULL,         BG_AUTH_SCHEME_BASIC }
    };
    
  2. Initialiseer COM-parameters door de functie CCoInitializer aan te roepen. Voor meer informatie over de functie CCoInitializer, zie Voorbeeld: Gemeenschappelijke klassen.

  3. Bereid een BG_AUTH_CREDENTIALS structuur voor. In het voorbeeld wordt de functie SecureZeroMemory gebruikt om de geheugenlocaties te wissen die zijn gekoppeld aan de gevoelige informatie. De functie SecureZeroMemory is gedefinieerd in WinBase.h.

  4. Gebruik de functie GetScheme om het verificatieschema op te halen dat moet worden gebruikt om verbinding te maken met de server.

    bool GetScheme( LPCWSTR s, BG_AUTH_SCHEME *scheme )
    {
        int i;
    
        i = 0;
        while (SchemeNames[i].Name != NULL)
        {
            if (0 == _wcsicmp( s, SchemeNames[i].Name ))
            {
    
                *scheme = SchemeNames[i].Scheme;
                return true;
            }
    
            ++i;
        }
    
        return false;
    }
    
  5. Vul de BG_AUTH_CREDENTIALS structuur in met het verificatieschema dat wordt geretourneerd door de functie GetScheme en de gebruikersnaam en het wachtwoord die zijn doorgegeven aan de functie ServerAuthentication.

  6. Krijg een verwijzing naar de IBackgroundCopyJob interface (pJob).

  7. Initialiseer COM-procesbeveiliging door CoInitializeSecurity-aan te roepen. BITS vereist ten minste het IMPERSONEREN-niveau van impersonatie. BITS mislukt met E_ACCESSDENIED als het juiste imitatieniveau niet is ingesteld.

  8. Haal een aanwijzer naar de IBackgroundCopyManager-interface op, en verkrijg de initiƫle locator naar BITS door de CoCreateInstance-functie aan te roepen.

  9. Maak een BITS-overdrachtstaak door de methode IBackgroundCopyManager::CreateJob aan te roepen.

  10. Haal een aanwijzer op naar de callback-interface van CNotifyInterface en roep de IBackgroundCopyJob::SetNotifyInterface methode aan om meldingen van taakgerelateerde gebeurtenissen te ontvangen. Zie Voorbeeld: Algemene klassenvoor meer informatie over CNotifyInterface.

  11. Roep de IBackgroundCopyJob::SetNotifyFlags methode aan om de typen meldingen in te stellen die moeten worden ontvangen. In dit voorbeeld worden de vlaggen BG_NOTIFY_JOB_TRANSFERRED en BG_NOTIFY_JOB_ERROR ingesteld.

  12. Verkrijg een pointer naar de IBackgroundCopyJob2-interface. Gebruik de IBackgroundCopyJob2 aanwijzer om extra eigenschappen voor de taak in te stellen. Dit programma maakt gebruik van de IBackgroundCopyJob2::SetCredentials methode om de referenties voor de BITS-overdrachtstaak in te stellen.

  13. Voeg bestanden toe aan de BITS-overdrachtstaak door IBackgroundCopyJob::AddFileaan te roepen. In dit voorbeeld gebruikt de methode IBackgroundCopyJob::AddFile de variabelen remoteFile en localFile die zijn doorgegeven aan de functie ServerAuthentication.

  14. Nadat het bestand is toegevoegd, roept u IBackgroundCopyJob::Resume aan om de taak te hervatten.

  15. Stel een while-lus in om te wachten op een Afsluitbericht van de callback-interface terwijl de taak wordt uitgevoerd.

    Notitie

    Deze stap is alleen nodig als het COM-appartement een enkelvoudig thread-appartement is. Zie Single-Threaded Appartementenvoor meer informatie.

     

    // Wait for QuitMessage from CallBack
        DWORD dwLimit = GetTickCount() + (15 * 60 * 1000);  // set 15 minute limit
        while (dwLimit > GetTickCount())
        {
            MSG msg;
    
            while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
            { 
                // If it is a quit message, exit.
                if (msg.message == WM_QUIT) 
                {
                    return;
                }
    
                // Otherwise, dispatch the message.
                DispatchMessage(&msg); 
            } // End of PeekMessage while loop
        }
    

    De voorgaande lus maakt gebruik van de functie GetTickCount om het aantal milliseconden op te halen die zijn verstreken sinds de taak begon met de overdracht.

  16. Nadat de BITS-overdrachtstaak is voltooid, verwijdert u de taak uit de wachtrij door IBackgroundCopyJob::Completeaan te roepen.

In het volgende codevoorbeeld worden serververificatiereferenties voor een BITS-overdrachtstaak opgegeven.

#include <bits.h>
#include <bits4_0.h>
#include <stdio.h>
#include <tchar.h>
#include <lm.h>
#include <iostream>
#include <exception>
#include <string>
#include <atlbase.h>
#include <memory>
#include <new>
#include "CommonCode.h"

//
// Retrieve BG_AUTH_SCHEME from scheme name.
//
//
struct
{
    LPCWSTR        Name;
    BG_AUTH_SCHEME Scheme;
}
SchemeNames[] =
{
    { L"basic",      BG_AUTH_SCHEME_BASIC },
    { L"digest",     BG_AUTH_SCHEME_DIGEST },
    { L"ntlm",       BG_AUTH_SCHEME_NTLM },
    { L"negotiate",  BG_AUTH_SCHEME_NEGOTIATE },
    { L"passport",   BG_AUTH_SCHEME_PASSPORT },

    { NULL,         BG_AUTH_SCHEME_BASIC }
};

bool GetScheme( LPCWSTR s, BG_AUTH_SCHEME *scheme )
{
    int i;

    i = 0;
    while (SchemeNames[i].Name != NULL)
    {
        if (0 == _wcsicmp( s, SchemeNames[i].Name ))
        {

            *scheme = SchemeNames[i].Scheme;
            return true;
        }

        ++i;
    }

    return false;
}

void ServerAuthentication(const LPWSTR &remoteFile, const LPWSTR &localFile, const LPWSTR &scheme, const LPWSTR &username, const LPWSTR &password)
{

 // If CoInitializeEx fails, the exception is unhandled and the program terminates  
 CCoInitializer coInitializer(COINIT_APARTMENTTHREADED);
    
    // Prepare the credentials structure.
    BG_AUTH_CREDENTIALS cred;
    ZeroMemory(&cred, sizeof(cred));
    if (!GetScheme(scheme,&cred.Scheme))
    {
        wprintf(L"Invalid authentication scheme specified\n");
        return;
    }

    cred.Target = BG_AUTH_TARGET_SERVER;
    cred.Credentials.Basic.UserName = username;
    if (0 == _wcsicmp(cred.Credentials.Basic.UserName, L"NULL"))
    {
        cred.Credentials.Basic.UserName = NULL;
    }

    cred.Credentials.Basic.Password = password;
    if (0 == _wcsicmp(cred.Credentials.Basic.Password, L"NULL"))
    {
        cred.Credentials.Basic.Password = NULL;
    }

    CComPtr<IBackgroundCopyJob> pJob;
    try
    {
        //The impersonation level must be at least RPC_C_IMP_LEVEL_IMPERSONATE.
        HRESULT hr = CoInitializeSecurity(NULL, 
            -1, 
            NULL, 
            NULL,
            RPC_C_AUTHN_LEVEL_CONNECT,
            RPC_C_IMP_LEVEL_IMPERSONATE,
            NULL, 
            EOAC_DYNAMIC_CLOAKING, 
            0);
        if (FAILED(hr))
        {
            throw MyException(hr, L"CoInitializeSecurity");
        }

        // Connect to BITS.
        CComPtr<IBackgroundCopyManager> pQueueMgr;
        hr = CoCreateInstance(__uuidof(BackgroundCopyManager), NULL,
            CLSCTX_LOCAL_SERVER,
            __uuidof(IBackgroundCopyManager),
            (void**)&pQueueMgr);

        if (FAILED(hr))
        {
            // Failed to connect.
            throw MyException(hr, L"CoCreateInstance");
        }

        // Create a job.
        wprintf(L"Creating Job...\n");

        GUID guidJob;
        hr = pQueueMgr->CreateJob(L"BitsAuthSample",
            BG_JOB_TYPE_DOWNLOAD,
            &guidJob,
            &pJob);

        if (FAILED(hr))
        {
            // Failed to connect.
            throw MyException(hr, L"CreateJob");
        }

        // Set the File Completed call.
        CComPtr<CNotifyInterface> pNotify;
        pNotify = new CNotifyInterface();
        hr = pJob->SetNotifyInterface(pNotify);
        if (FAILED(hr))
        {
            // Failed to connect.
            throw MyException(hr, L"SetNotifyInterface");
        }
        hr = pJob->SetNotifyFlags(BG_NOTIFY_JOB_TRANSFERRED | 
            BG_NOTIFY_JOB_ERROR);

        if (FAILED(hr))
        {
            // Failed to connect.
            throw MyException(hr, L"SetNotifyFlags");
        }

        // Set credentials.
        CComPtr<IBackgroundCopyJob2> job2;
        hr = pJob.QueryInterface(&job2);
        if (FAILED(hr))
        {
            // Failed to connect.
            throw MyException(hr, L"QueryInterface");
        }

        hr = job2->SetCredentials(&cred);
        if (FAILED(hr))
        {
            // Failed to connect.
            throw MyException(hr, L"SetCredentials");
        }

        // Add a file.
        wprintf(L"Adding File to Job\n");
        hr = pJob->AddFile(remoteFile, localFile);
        if (FAILED(hr))
        {
            // Failed to connect.
            throw MyException(hr, L"AddFile");
        }

        //Resume the job.
        wprintf(L"Resuming Job...\n");
        hr = pJob->Resume();
        if (FAILED(hr))
        {
            // Failed to connect.
            throw MyException(hr, L"Resume");
        }
    }
    catch(const std::bad_alloc &)
    {
        wprintf(L"Memory allocation failed");
        if (pJob)
        {
            pJob->Cancel();
        }

        return;
    }
    catch(const MyException &ex)
    {
        wprintf(L"Error %x occurred during operation", ex.Error);
        if (pJob)
        {
            pJob->Cancel();
        }

        return;
    }

    wprintf(L"Transferring file and waiting for callback.\n");

    // Wait for QuitMessage from CallBack.
    DWORD dwLimit = GetTickCount() + (15 * 60 * 1000);  // set 15 minute limit
    while (dwLimit > GetTickCount())
    {
        MSG msg;

        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
        { 
            // If it is a quit message, exit.
            if (msg.message == WM_QUIT) 
            {
                return;
            }

            // Otherwise, dispatch the message.
            DispatchMessage(&msg); 
        } // End of PeekMessage while loop
    }

    pJob->Cancel();
    return;
}

void _cdecl _tmain(int argc, LPWSTR* argv)
{   
    if (argc != 6)
    {
        wprintf(L"Usage:");
        wprintf(L"%s", argv[0]);
        wprintf(L" [remote name] [local name] [server authentication scheme =\"NTLM\"|\"NEGOTIATE\"|\"BASIC\"|\"DIGEST\"] [username] [password]\n");
        return;
    }

    ServerAuthentication(argv[1], argv[2], argv[3], argv[4], argv[5]); 

}

IBackgroundCopyManager

IBackgroundCopyJob

IBackgroundCopyJob2

voorbeeld: Algemene klassen