DOWNLOAD.CPP
// =========================================================================== 
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
// PARTICULAR PURPOSE. 
// 
// Copyright 1996 Microsoft Corporation.  All Rights Reserved. 
// =========================================================================== 
#include <urlmon.h> 
#include <wininet.h> 
// #include <datapath.h> 
#include "range.h" 
#include "callback.hpp" 
 
//============================================================================== 
HRESULT GetAnInterface 
( 
    IUnknown  *     punk, 
    const IID &     riid, 
    void **         pout, 
    BOOL            bCheckServiceProvider, 
    const IID &     siid, 
    const IID &     siid_riid, 
    void **         sout 
) 
{ 
    IOleObject *      oleObj    = 0; 
    IOleClientSite *  oleSite   = 0; 
    IOleContainer *   container = 0; 
    IUnknown *        service   = 0; 
 
    HRESULT       hr = E_FAIL; 
 
    // Initialize passed in interface pointers: calling code assumes NULL for failure 
    if(pout) 
        *pout = NULL; 
    if(sout) 
        *sout = NULL; 
 
    if(punk) 
        hr = punk->QueryInterface( IID_IOleObject, (void **)&oleObj ); 
 
    while( SUCCEEDED(hr) && oleObj ) 
    { 
        if( oleSite ) 
        { 
            //oleSite->Release(); 
            oleSite = 0; 
        } 
 
        hr = oleObj->GetClientSite(&oleSite); 
 
        if( FAILED(hr) ) 
            break; 
 
        if( bCheckServiceProvider ) 
        { 
            IServiceProvider * servProv; 
 
            hr = oleSite->QueryInterface( IID_IServiceProvider, (void**)&servProv); 
 
            if( SUCCEEDED(hr) ) 
            { 
                hr = servProv->QueryService 
                    (siid, siid_riid, (void **) &service); 
                servProv->Release(); 
            } 
 
            if( SUCCEEDED(hr) ) 
            { 
                bCheckServiceProvider = FALSE; 
 
                hr = service->QueryInterface( riid, pout ); 
            } 
 
            if( SUCCEEDED(hr) ) 
                break; 
 
        } 
 
        if( container ) 
        { 
            container->Release(); 
            container = 0; 
        } 
 
        hr = oleSite->GetContainer( &container ); 
 
        if( FAILED(hr) ) 
            break; 
 
        hr = container->QueryInterface( riid, pout ); 
 
        if( SUCCEEDED(hr) ) 
            break; 
 
        oleObj->Release(); 
        oleObj = 0; 
 
        hr = container->QueryInterface( IID_IOleObject, (void**)&oleObj ); 
 
    } 
 
    if( oleSite ) 
    { 
        //oleSite->Release(); 
    } 
 
    if( oleObj ) 
        oleObj->Release(); 
 
    if( container ) 
        container->Release(); 
 
    if( service ) 
        *sout = service; 
 
    return( hr ); 
 
} 
 
//============================================================================== 
BOOL HttpReadFromServer (PHTTP_REQUEST_PARAM pParam) 
{ 
    IMoniker*            m_pmk   = NULL; 
    IBindStatusCallback* m_pbsc  = NULL; 
    HRESULT hr = S_OK; 
     
    IBindHost *pBindHost = NULL; 
 
    // Create a callback object. 
    m_pbsc = new CUrlmonCallback (pParam); 
    if (m_pbsc == NULL) 
    { 
        hr = E_OUTOFMEMORY; 
        goto err; 
    } 
 
    // Look for a bind host. 
    if (pParam->punkOuter) 
    { 
        hr = GetAnInterface 
        ( 
            (IUnknown *) pParam->punkOuter, 
            IID_IBindHost,           // const IID &  riid, 
            (void **) &pBindHost,    // void **      pout,   
            TRUE,                    // BOOL         bCheckServiceProvider, 
            IID_IBindHost,           // const IID &  siid, 
            IID_IBindHost,           // const IID &  siid_riid, 
            (void **) &pBindHost     // void **      sout 
        ); 
    } 
 
    // Convert ANSI URL to Unicode. 
    WCHAR wszUrl[INTERNET_MAX_URL_LENGTH]; 
    MultiByteToWideChar(CP_ACP, 0, pParam->pszUrl, -1, wszUrl, sizeof(wszUrl)); 
 
    // Initialize bind context, stream. 
    IBindCtx *pbc; 
    IStream *pstm; 
    pbc =  NULL; 
    pstm = NULL; 
 
    // Call the appropriate BindToStorage. 
    if (pBindHost) 
    { 
         pBindHost->CreateMoniker (wszUrl, NULL, &m_pmk, 0); 
         pBindHost->MonikerBindToStorage 
             (m_pmk, NULL, m_pbsc, IID_IStream, (void **) &pstm); 
    }    
    else 
    { 
        CreateURLMoniker(NULL, wszUrl, &m_pmk); 
        CreateAsyncBindCtx(0, m_pbsc, NULL, &pbc); 
        m_pmk->BindToStorage(pbc, NULL, IID_IStream, (void **) &pstm); 
    } 
 
    // Clean up bind context, stream. 
    if (pbc) 
        pbc->Release(); 
    if (pstm) 
        pstm->Release(); 
 
    return SUCCEEDED(hr); 
 
err: 
    delete m_pbsc; 
 
    if (m_pmk != NULL) 
    { 
        m_pmk->Release(); 
        m_pmk = NULL; 
    } 
    return FALSE; 
 
}