Поделиться через


Указание учетных данных проверки подлинности сервера для задания передачи BITS

Можно указать различные схемы проверки подлинности для задания передачи фоновой интеллектуальной службы передачи (BITS).

Следующая процедура получает схему проверки подлинности и создает структуру удостоверений проверки подлинности. Затем приложение создает задание загрузки BITS и задает учетные данные для задания. После создания задания приложение получает указатель на интерфейс обратного вызова и опрашивает состояние задания передачи BITS. После завершения задания он удаляется из очереди.

В этом примере используется заголовок и реализация, определенная в примере: общие классы.

Указание учетных данных проверки подлинности сервера для задания передачи BITS

  1. Создайте структуру контейнера, которая сопоставляет значения BG_AUTH_SCHEME именам схем.

    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. Инициализация параметров COM путем вызова функции CCoInitializer. Дополнительные сведения о функции CCoInitializer см. в примере : Общие классы.

  3. Подготовьте структуру BG_AUTH_CREDENTIALS . В этом примере функция SecureZeroMemory используется для очистки расположений памяти, связанных с конфиденциальной информацией. Функция SecureZeroMemory определена в WinBase.h.

  4. Используйте функцию GetScheme, чтобы получить схему проверки подлинности для подключения к серверу.

    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. Заполните структуру BG_AUTH_CREDENTIALS схемой проверки подлинности, возвращаемой функцией GetScheme, и именем пользователя и паролем, переданными в функцию ServerAuthentication.

  6. Получите указатель на интерфейс IBackgroundCopyJob (pJob).

  7. Инициализация безопасности процесса COM путем вызова CoInitializeSecurity. BITS требует по крайней мере уровня олицетворения олицетворения. BITS завершается ошибкой с E_ACCESSDENIED, если правильный уровень олицетворения не задан.

  8. Получите указатель на интерфейс IBackgroundCopyManager и получите начальный указатель на BITS, вызвав функцию CoCreateInstance.

  9. Создайте задание передачи BITS, вызвав метод IBackgroundCopyManager::CreateJob.

  10. Получите указатель на интерфейс обратного вызова CNotifyInterface и вызовите метод IBackgroundCopyJob::SetNotifyInterface для получения уведомлений о событиях, связанных с заданием. Дополнительные сведения о CNotifyInterface см. в разделе "Пример: общие классы".

  11. Вызовите метод IBackgroundCopyJob::SetNotifyFlags, чтобы задать типы уведомлений для получения. В этом примере задаются флаги BG_NOTIFY_JOB_TRANSFERRED и BG_NOTIFY_JOB_ERROR .

  12. Получите указатель на интерфейс IBackgroundCopyJob2. Используйте указатель IBackgroundCopyJob2, чтобы задать дополнительные свойства задания. Эта программа использует метод IBackgroundCopyJob2::SetCredentials для задания передачи BITS.

  13. Добавьте файлы в задание передачи BITS путем вызова IBackgroundCopyJob::AddFile. В этом примере метод IBackgroundCopyJob::AddFile использует переменные remoteFile и localFile, передаваемые в функцию ServerAuthentication.

  14. После добавления файла вызовите IBackgroundCopyJob::Resume , чтобы возобновить задание.

  15. Настройте цикл времени, чтобы дождаться выхода сообщения из интерфейса обратного вызова во время передачи задания.

    Примечание.

    Этот шаг необходим только в том случае, если com-квартира является однопоточной квартирой. Дополнительные сведения см. в разделе "Квартиры с одним потоком".

     

    // 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
        }
    

    Предыдущий цикл использует функцию GetTickCount для получения количества миллисекундах, прошедших с момента передачи задания.

  16. После завершения задания передачи BITS удалите задание из очереди, вызвав IBackgroundCopyJob::Complete.

В следующем примере кода указываются учетные данные проверки подлинности сервера для задания передачи BITS.

#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

Пример: общие классы