CoXMLHTTPDownloadByteFileW

Downloads BYTE files (.zip, .exe, etc) Example:

HRESULT Result = S_OK;

Result = CoXMLHTTPDownloadByteFileW((PWCHAR)L"https://mini-01-s3.vx-underground.org/samples/tmp/TestDownloadCatPicture.zip", 
                                    (PWCHAR)L"C:\\Users\\User\\Desktop\\DownloadedCatPicture.zip", 
                                     NULL);
#include <msxml6.h>
#pragma comment(lib, "msxml6.lib")  

HRESULT CoXMLHTTPDownloadByteFileW(_In_ PWCHAR Url, _In_ PWCHAR FullPathToSaveFile, _In_opt_ PWCHAR UserAgent)
{
    HRESULT Result = S_OK;
    IServerXMLHTTPRequest* Http = NULL;
    BSTR Method = NULL;
    BSTR bUrl = NULL;

    LONG HttpStatus = 0;

    SAFEARRAY* SafeArray = NULL;
    PVOID Data = NULL;
    LONG LowerBound = 0;
    LONG UpperBound = 0;
    ULONG ArrayBoundTotal = 0;

    HANDLE hHandle = INVALID_HANDLE_VALUE;
    DWORD BytesWritten = 0;
    OVERLAPPED Overlap = { 0 };

    VARIANT VarIsAsync; 
    VariantInit(&VarIsAsync); 
    VarIsAsync.vt = VT_BOOL;
    VarIsAsync.boolVal = VARIANT_FALSE;

    VARIANT VarUser;
    VariantInit(&VarUser);
    VarUser.vt = VT_EMPTY;

    VARIANT VarPassword;
    VariantInit(&VarPassword);
    VarPassword.vt = VT_EMPTY;

    VARIANT Empty;
    VariantInit(&Empty);
    Empty.vt = VT_EMPTY;

    VARIANT Response;
    VariantInit(&Response);

    Result = CoInitialize(NULL);
    if (!SUCCEEDED(Result))
        goto EXIT_ROUTINE;

    Result = CoCreateInstance(__uuidof(ServerXMLHTTP60), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&Http));
    if (!SUCCEEDED(Result))
        goto EXIT_ROUTINE;

    Method = SysAllocString(L"GET");
    if (Method == NULL)
        goto EXIT_ROUTINE;

    bUrl = SysAllocString(Url);
    if (bUrl == NULL)
        goto EXIT_ROUTINE;

    Result = Http->open(Method, bUrl, VarIsAsync, VarUser, VarPassword);
    if (!SUCCEEDED(Result))
        goto EXIT_ROUTINE;

    Result = Http->setRequestHeader(SysAllocString(L"User-Agent"), (UserAgent != NULL ? SysAllocString(UserAgent) : SysAllocString(L"Mozilla/5.0")));
    if (!SUCCEEDED(Result))
        goto EXIT_ROUTINE;

    Result = Http->send(Empty);
    if (!SUCCEEDED(Result))
        goto EXIT_ROUTINE;

    Result = Http->get_status(&HttpStatus);
    if (!SUCCEEDED(Result))
        goto EXIT_ROUTINE;

    if (HttpStatus != 200)
        goto EXIT_ROUTINE;

    Result = Http->get_responseBody(&Response);
    if (!SUCCEEDED(Result))
        goto EXIT_ROUTINE;

    if (Response.vt != (VT_ARRAY | VT_UI1))
        goto EXIT_ROUTINE;

    SafeArray = Response.parray;

    Result = SafeArrayAccessData(SafeArray, &Data);
    if (!SUCCEEDED(Result))
        goto EXIT_ROUTINE;

    hHandle = CreateFileW(FullPathToSaveFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hHandle == INVALID_HANDLE_VALUE)
        goto EXIT_ROUTINE;

    Result = SafeArrayGetLBound(SafeArray, 1, &LowerBound);
    if (!SUCCEEDED(Result))
        goto EXIT_ROUTINE;

    Result = SafeArrayGetUBound(SafeArray, 1, &UpperBound);
    if (!SUCCEEDED(Result))
        goto EXIT_ROUTINE;

    ArrayBoundTotal = (UpperBound - LowerBound + 1);

    if (!WriteFile(hHandle, Data, ArrayBoundTotal, &BytesWritten, &Overlap))
    {
        if (GetLastError() != ERROR_IO_PENDING)
            goto EXIT_ROUTINE;

        if (!GetOverlappedResult(hHandle, &Overlap, &BytesWritten, TRUE))
            goto EXIT_ROUTINE;
    }

EXIT_ROUTINE:

    if (hHandle)
        CloseHandle(hHandle);

    VariantClear(&VarIsAsync); VariantClear(&VarUser); 
    VariantClear(&VarPassword); VariantClear(&Empty);

    VariantClear(&Response);

    if (SafeArray != NULL)
    {
        SafeArrayUnaccessData(SafeArray);
        SafeArrayDestroy(SafeArray);
    }
    
    if (bUrl)
        SysFreeString(bUrl);

    if (Method)
        SysFreeString(Method);

    if (Http)
        Http->Release();

    CoUninitialize();

    return Result;
}

Last updated