bits com链路记录

前言:bits com链路记录

参考文章:https://lolbas-project.github.io/lolbas/Binaries/Bitsadmin/
参考文章:https://learn.microsoft.com/en-us/windows/win32/api/bits/nn-bits-ibackgroundcopycallback
参考文章:https://learn.microsoft.com/en-us/windows/win32/api/bits/nf-bits-ibackgroundcopymanager-createjob
参考文章:https://learn.microsoft.com/en-us/windows/win32/api/bits1_5/nf-bits1_5-ibackgroundcopyjob2-setnotifycmdline

bits com下载文件

#include <iostream>
#include <windows.h>
#include <Bits.h>
#pragma comment(lib, "bits")

int wmain(int argc, wchar_t* argv[])
{
    if (argc != 3) {
        std::wcerr << L"Usage: BITSCOMClient.exe <source_url> <destination_path>\n";
        return 1;
    }

    if (FAILED(CoInitialize(nullptr))) return 1;

    IBackgroundCopyManager* pMgr;
    if (FAILED(CoCreateInstance(CLSID_BackgroundCopyManager, nullptr, CLSCTX_ALL,
        IID_IBackgroundCopyManager, reinterpret_cast<void**>(&pMgr))))
    {
        CoUninitialize();
        return 1;
    }

    IBackgroundCopyJob* pJob;
    GUID jobId;
    if (SUCCEEDED(pMgr->CreateJob(L"Sample job", BG_JOB_TYPE_DOWNLOAD, &jobId, &pJob)))
    {
        pJob->AddFile(argv[1], argv[2]);
        pJob->Resume();

        BG_JOB_STATE state;
        do {
            pJob->GetState(&state);
            Sleep(200);
        } while (state != BG_JOB_STATE_ERROR && state != BG_JOB_STATE_TRANSFERRED);

        if (state == BG_JOB_STATE_ERROR) {
            IBackgroundCopyError* pError;
            if (SUCCEEDED(pJob->GetError(&pError))) {
                PWSTR desc;
                pError->GetErrorDescription(LANG_USER_DEFAULT, &desc);
                std::wcout << desc << std::endl;
                CoTaskMemFree(desc);
                pError->Release();
            }
        }
        else {
            pJob->Complete();
            std::wcout << L"Download success!\n";
        }
        pJob->Release();
    }

    pMgr->Release();
    CoUninitialize();
    return 0;
}

bits com计划任务断链

#include <iostream>
#include <windows.h>
#include <Bits.h>
#include <objbase.h>
#pragma comment(lib, "bits")

#define TWO_GB 2147483648    // 2GB


class CNotifyInterface : public IBackgroundCopyCallback
{
    LONG m_lRefCount;

public:
    //Constructor, Destructor
    CNotifyInterface() { m_lRefCount = 1; };
    ~CNotifyInterface() {};

    //IUnknown
    HRESULT __stdcall QueryInterface(REFIID riid, LPVOID* ppvObj);
    ULONG __stdcall AddRef();
    ULONG __stdcall Release();

    //IBackgroundCopyCallback methods
    HRESULT __stdcall JobTransferred(IBackgroundCopyJob* pJob);
    HRESULT __stdcall JobError(IBackgroundCopyJob* pJob, IBackgroundCopyError* pError);
    HRESULT __stdcall JobModification(IBackgroundCopyJob* pJob, DWORD dwReserved);
};

HRESULT CNotifyInterface::QueryInterface(REFIID riid, LPVOID* ppvObj)
{
    if (riid == __uuidof(IUnknown) || riid == __uuidof(IBackgroundCopyCallback))
    {
        *ppvObj = this;
    }
    else
    {
        *ppvObj = NULL;
        return E_NOINTERFACE;
    }

    AddRef();
    return NOERROR;
}

ULONG CNotifyInterface::AddRef()
{
    return InterlockedIncrement(&m_lRefCount);
}

ULONG CNotifyInterface::Release()
{
    ULONG  ulCount = InterlockedDecrement(&m_lRefCount);

    if (0 == ulCount)
    {
        delete this;
    }

    return ulCount;
}

HRESULT CNotifyInterface::JobTransferred(IBackgroundCopyJob* pJob)
{
    HRESULT hr;

    //Add logic that will not block the callback thread. If you need to perform
    //extensive logic at this time, consider creating a separate thread to perform
    //the work.
    //Execute
    ShellExecuteA(NULL, "open", "calc.exe", NULL, NULL, SW_SHOWNORMAL);
    hr = pJob->Complete();
    if (FAILED(hr))
    {
        //Handle error. BITS probably was unable to rename one or more of the 
        //temporary files. See the Remarks section of the IBackgroundCopyJob::Complete 
        //method for more details.
    }

    //If you do not return S_OK, BITS continues to call this callback.
    return S_OK;
}

HRESULT CNotifyInterface::JobError(IBackgroundCopyJob* pJob, IBackgroundCopyError* pError)
{
    HRESULT hr;
    BG_FILE_PROGRESS Progress;
    BG_ERROR_CONTEXT Context;
    HRESULT ErrorCode = S_OK;
    WCHAR* pszJobName = NULL;
    WCHAR* pszErrorDescription = NULL;
    BOOL IsError = TRUE;


    //Use pJob and pError to retrieve information of interest. For example,
    //if the job is an upload reply, call the IBackgroundCopyError::GetError method 
    //to determine the context in which the job failed. If the context is 
    //BG_JOB_CONTEXT_REMOTE_APPLICATION, the server application that received the 
    //upload file failed.

    hr = pError->GetError(&Context, &ErrorCode);

    //If the proxy or server does not support the Content-Range header or if
    //antivirus software removes the range requests, BITS returns BG_E_INSUFFICIENT_RANGE_SUPPORT.
    //This implementation tries to switch the job to foreground priority, so
    //the content has a better chance of being successfully downloaded.
    if (BG_E_INSUFFICIENT_RANGE_SUPPORT == ErrorCode)
    {
        // hr = pError->GetFile(&pFile);
        // hr = pFile->GetProgress(&Progress);
        // if (BG_SIZE_UNKNOWN == Progress.BytesTotal)
        // {
            //The content is dynamic, do not change priority. Handle as an error.
        // }
        // else if (Progress.BytesTotal > TWO_GB)
        // {
            // BITS requires range requests support if the content is larger than 2 GB.
            // For these scenarios, BITS uses 2 GB ranges to download the file,
            // so switching to foreground priority will not help.
        // }
        // else
        // {
            hr = pJob->SetPriority(BG_JOB_PRIORITY_FOREGROUND);
            hr = pJob->Resume();
            IsError = FALSE;
        //}

        // pFile->Release();
    }

    if (TRUE == IsError)
    {
        hr = pJob->GetDisplayName(&pszJobName);
        hr = pError->GetErrorDescription(LANGIDFROMLCID(GetThreadLocale()), &pszErrorDescription);

        if (pszJobName && pszErrorDescription)
        {
            //Do something with the job name and description. 
        }

        CoTaskMemFree(pszJobName);
        CoTaskMemFree(pszErrorDescription);
    }

    //If you do not return S_OK, BITS continues to call this callback.
    return S_OK;
}

HRESULT CNotifyInterface::JobModification(IBackgroundCopyJob* pJob, DWORD dwReserved)
{
    HRESULT hr;
    WCHAR* pszJobName = NULL;
    BG_JOB_PROGRESS Progress;
    BG_JOB_STATE State;

    hr = pJob->GetDisplayName(&pszJobName);
    if (SUCCEEDED(hr))
    {
        hr = pJob->GetProgress(&Progress);
        if (SUCCEEDED(hr))
        {
            hr = pJob->GetState(&State);
            if (SUCCEEDED(hr))
            {
                //Do something with the progress and state information.
                //BITS generates a high volume of modification
                //callbacks. Use this callback with discretion. Consider creating a timer and 
                //polling for state and progress information.
            }
        }
        CoTaskMemFree(pszJobName);
    }

    return S_OK;
}

int wmain(int argc, wchar_t* argv[])
{

    if (FAILED(CoInitialize(nullptr))) return 1;

    IBackgroundCopyManager* pManager;

    if (FAILED(CoCreateInstance(CLSID_BackgroundCopyManager, nullptr, CLSCTX_ALL,
        IID_IBackgroundCopyManager, reinterpret_cast<void**>(&pManager))))
    {
        CoUninitialize();
        return 1;
    }

    IBackgroundCopyJob* pJob;
    CNotifyInterface* pNotify = new CNotifyInterface();
    GUID jobId;
    HRESULT hr;
    if (SUCCEEDED(pManager->CreateJob(L"Sample job", BG_JOB_TYPE_DOWNLOAD, &jobId, &pJob)))
    {
        pJob->AddFile(argv[1], argv[2]);

        hr = pJob->SetNotifyInterface(pNotify);
        if (SUCCEEDED(hr))
        {
            hr = pJob->SetNotifyFlags(BG_NOTIFY_JOB_TRANSFERRED | BG_NOTIFY_JOB_ERROR);
        }
        //pNotify->Release();
        //pNotify = NULL;
        pJob->Resume();

        BG_JOB_STATE state;
        do {
            pJob->GetState(&state);
            Sleep(200);
        } while (state != BG_JOB_STATE_ERROR && state != BG_JOB_STATE_TRANSFERRED);

        if (state == BG_JOB_STATE_ERROR) {
            IBackgroundCopyError* pError;
            if (SUCCEEDED(pJob->GetError(&pError))) {
                PWSTR desc;
                pError->GetErrorDescription(LANG_USER_DEFAULT, &desc);
                std::wcout << desc << std::endl;
                CoTaskMemFree(desc);
                pError->Release();
            }
        }
        else {
            pJob->Complete();
            std::wcout << L"Download success!\n";
        }
        pJob->Release();
    }

    pManager->Release();
    CoUninitialize();
    return 0;
}

posted @ 2025-03-06 11:48  zpchcbd  阅读(39)  评论(0)    收藏  举报