342 lines
7 KiB
C++
342 lines
7 KiB
C++
// Copyright (C) 1996-1997 Microsoft Corporation. All rights reserved.
|
|
|
|
// contains internet helper classes CDownloadSink and CInternetControl
|
|
|
|
#include "header.h"
|
|
#include "Internet.H"
|
|
|
|
static VARTYPE rgI4[] = { VT_I4 };
|
|
|
|
typedef enum {
|
|
InternetEvent_Progress = 0,
|
|
InternetEvent_ReadyStateChange = 1
|
|
} INTERNETEVENTS;
|
|
|
|
static EVENTINFO rgEvents [] = {
|
|
{ DISPID_PROGRESS, 1, rgI4 }, // (long percentDone)
|
|
{ DISPID_READYSTATECHANGE, 1, rgI4 }, // (OLE_READYSTATE newState)
|
|
};
|
|
|
|
// local class for doing async monitoring. It's not really all that
|
|
// general purpose, but it does the job...
|
|
|
|
// REVIEW: 06-Jul-1997 [ralphw] Why do we need this for HHCtrl?
|
|
|
|
class CDownloadSink : public IBindStatusCallback
|
|
{
|
|
public:
|
|
CDownloadSink(IUnknown *punkOuter,CInternetControl *,DISPID );
|
|
~CDownloadSink();
|
|
|
|
STDMETHOD(QueryInterface)(REFIID riid, void **ppvObjOut);
|
|
STDMETHOD_(ULONG, AddRef)();
|
|
STDMETHOD_(ULONG, Release)();
|
|
|
|
STDMETHOD(OnStartBinding)(
|
|
/* [in] */ DWORD grfBSCOption,
|
|
/* [in] */ IBinding *pib);
|
|
|
|
STDMETHOD(GetPriority)(
|
|
/* [out] */ LONG *pnPriority);
|
|
|
|
STDMETHOD(OnLowResource)(
|
|
/* [in] */ DWORD reserved);
|
|
|
|
STDMETHOD(OnProgress)(
|
|
/* [in] */ ULONG ulProgress,
|
|
/* [in] */ ULONG ulProgressMax,
|
|
/* [in] */ ULONG ulStatusCode,
|
|
/* [in] */ LPCWSTR szStatusText);
|
|
|
|
STDMETHOD(OnStopBinding)(
|
|
/* [in] */ HRESULT hresult,
|
|
/* [in] */ LPCWSTR szError);
|
|
|
|
STDMETHOD(GetBindInfo)(
|
|
/* [out] */ DWORD *grfBINDINFOF,
|
|
/* [unique][out][in] */ BINDINFO *pbindinfo);
|
|
|
|
STDMETHOD(OnDataAvailable)(
|
|
/* [in] */ DWORD grfBSCF,
|
|
/* [in] */ DWORD dwSize,
|
|
/* [in] */ FORMATETC *pformatetc,
|
|
/* [in] */ STGMEDIUM *pstgmed);
|
|
|
|
STDMETHOD(OnObjectAvailable)(
|
|
/* [in] */ REFIID riid,
|
|
/* [iid_is][in] */ IUnknown *punk);
|
|
|
|
|
|
|
|
CDownloadSink * Next() { return(m_next); }
|
|
void Next(CDownloadSink *n) { m_next = n; }
|
|
|
|
DISPID DispId() { return(m_propId); }
|
|
IBinding * Binding() { return(m_binding); }
|
|
|
|
private:
|
|
|
|
CDownloadSink * m_next;
|
|
CInternetControl * m_control;
|
|
DISPID m_propId;
|
|
IBinding * m_binding;
|
|
DWORD m_ref;
|
|
IStream * m_stream;
|
|
};
|
|
|
|
CDownloadSink::CDownloadSink(IUnknown * punkOuter,
|
|
CInternetControl * control, DISPID propId)
|
|
{
|
|
m_control = control;
|
|
m_control->AddRef();
|
|
|
|
m_propId = propId;
|
|
m_next = 0;
|
|
m_binding = 0;
|
|
m_ref = 0;
|
|
m_stream = 0;
|
|
|
|
DBWIN("CDownloadSink created.");
|
|
}
|
|
|
|
CDownloadSink::~CDownloadSink()
|
|
{
|
|
if (m_control)
|
|
m_control->Release();
|
|
if (m_binding)
|
|
m_binding->Release();
|
|
if (m_stream)
|
|
m_stream->Release();
|
|
}
|
|
|
|
STDMETHODIMP CDownloadSink::QueryInterface(const GUID &iid, void **ppv)
|
|
{
|
|
if (IsEqualGUID(iid, IID_IUnknown) ||
|
|
IsEqualGUID(iid, IID_IBindStatusCallback)) {
|
|
*ppv = this;
|
|
AddRef();
|
|
return(NOERROR);
|
|
}
|
|
return(E_NOINTERFACE);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CDownloadSink::AddRef()
|
|
{
|
|
return(++m_ref);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CDownloadSink::Release()
|
|
{
|
|
if (!--m_ref) {
|
|
delete this;
|
|
return(0);
|
|
}
|
|
return(m_ref);
|
|
}
|
|
|
|
STDMETHODIMP CDownloadSink::GetBindInfo(DWORD *grfBINDF, BINDINFO *pbindInfo)
|
|
{
|
|
*grfBINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_NOCOPYDATA;
|
|
return(NOERROR);
|
|
}
|
|
|
|
|
|
STDMETHODIMP CDownloadSink::OnStartBinding(DWORD /*grfBSCOption*/,
|
|
IBinding *pib)
|
|
{
|
|
// BUGBUG: should check to see options are what we think they are
|
|
m_binding = pib;
|
|
pib->AddRef();
|
|
return(NOERROR);
|
|
}
|
|
|
|
|
|
STDMETHODIMP CDownloadSink::GetPriority( LONG *pnPriority)
|
|
{
|
|
return(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP CDownloadSink::OnProgress(ULONG ulProgress, ULONG ulProgressMax,
|
|
ULONG ulStatusCode, LPCWSTR pwzStatusText)
|
|
{
|
|
return m_control->OnProgress(m_propId,ulProgress, ulProgressMax,
|
|
ulStatusCode, pwzStatusText);
|
|
}
|
|
|
|
STDMETHODIMP CDownloadSink::OnDataAvailable(DWORD grfBSCF, DWORD dwSize,
|
|
FORMATETC * pFmtetc, STGMEDIUM * pstgmed)
|
|
{
|
|
#ifdef DEBUG
|
|
char msg[200];
|
|
wsprintf(msg,"::OnDataAvailable(%0xd,%d,%s,%s)", grfBSCF, dwSize,
|
|
pFmtetc ? "pFmtetc" : "NULL", pstgmed ? "pstgmed" : "NULL");
|
|
DBWIN(msg);
|
|
#endif
|
|
|
|
if (!m_stream)
|
|
m_stream = pstgmed->pstm;
|
|
|
|
return (m_control->OnData(m_propId, grfBSCF, m_stream, dwSize));
|
|
}
|
|
|
|
STDMETHODIMP CDownloadSink::OnObjectAvailable(REFIID riid, IUnknown *punk)
|
|
{
|
|
return(E_NOTIMPL);
|
|
}
|
|
|
|
STDMETHODIMP CDownloadSink::OnLowResource(DWORD reserved)
|
|
{
|
|
m_binding->Abort();
|
|
return(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP CDownloadSink::OnStopBinding(HRESULT hrError, LPCWSTR szError)
|
|
{
|
|
m_binding->Release();
|
|
m_binding = 0;
|
|
m_control->Release();
|
|
m_control = 0;
|
|
|
|
return(NOERROR);
|
|
}
|
|
|
|
// class CInternetControl
|
|
|
|
CInternetControl::CInternetControl(IUnknown * pUnkOuter,
|
|
int iPrimaryDispatch, void * pMainInterface)
|
|
: COleControl(pUnkOuter,iPrimaryDispatch,pMainInterface)
|
|
{
|
|
m_host = 0;
|
|
m_readyState = READYSTATE_LOADING;
|
|
}
|
|
|
|
CInternetControl::~CInternetControl()
|
|
{
|
|
if (m_host)
|
|
m_host->Release();
|
|
}
|
|
|
|
HRESULT CInternetControl::InternalQueryInterface(REFIID riid,
|
|
void **ppvObjOut)
|
|
{
|
|
*ppvObjOut = NULL;
|
|
return COleControl::InternalQueryInterface(riid, ppvObjOut);
|
|
}
|
|
|
|
HRESULT CInternetControl::GetBindHost()
|
|
{
|
|
if (m_host)
|
|
return(NOERROR);
|
|
|
|
// Try service provider first...
|
|
|
|
IServiceProvider * serviceProvider = 0;
|
|
|
|
HRESULT hr = m_pClientSite->QueryInterface(IID_IServiceProvider,
|
|
(void**) &serviceProvider);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = serviceProvider->QueryService(SID_IBindHost, IID_IBindHost,
|
|
(void**) &m_host);
|
|
serviceProvider->Release();
|
|
}
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
// Some containers put IBindHost directly on the client site
|
|
|
|
hr = m_pClientSite->QueryInterface (IID_IBindHost, (void**) &m_host);
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT CInternetControl::GetAMoniker(LPOLESTR url, IMoniker ** ppmkr)
|
|
{
|
|
#if 0
|
|
11-Jun-1997 [ralphw] m_host->CreateMoniker generates a compiler
|
|
error. Doesn't exist in any header file that I can find.
|
|
|
|
HRESULT hr = GetBindHost();
|
|
|
|
|
|
if( SUCCEEDED(hr) )
|
|
hr = m_host->CreateMoniker(url,NULL, ppmkr,0);
|
|
|
|
if( FAILED(hr) )
|
|
{
|
|
// FUTURE: This really should be a call to MkParseDisplayNameEx!!!
|
|
hr = ::CreateURLMoniker(0,url,ppmkr);
|
|
// hr = ::MkParseDisplayNameEx(0, url, 0, ppmkr);
|
|
}
|
|
|
|
return( hr );
|
|
#else
|
|
return ::CreateURLMoniker(0,url,ppmkr);
|
|
#endif
|
|
}
|
|
|
|
HRESULT CInternetControl::SetupDownload(LPOLESTR url, DISPID propId)
|
|
{
|
|
CHECK_POINTER(url);
|
|
|
|
IMoniker * pmkr;
|
|
|
|
HRESULT hr = GetAMoniker(url, &pmkr);
|
|
|
|
IBindCtx * pBindCtx = 0;
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = ::CreateBindCtx(0, &pBindCtx);
|
|
}
|
|
|
|
CDownloadSink * sink = 0;
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
sink = new CDownloadSink(0, this, propId);
|
|
if (sink)
|
|
sink->AddRef();
|
|
}
|
|
|
|
if (SUCCEEDED(hr) && !sink)
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
hr = ::RegisterBindStatusCallback(pBindCtx, sink, 0, 0);
|
|
}
|
|
|
|
IStream * strm = 0;
|
|
|
|
if (SUCCEEDED(hr))
|
|
hr = pmkr->BindToStorage(pBindCtx, 0, IID_IStream, (void**) &strm);
|
|
|
|
if (strm)
|
|
strm->Release();
|
|
|
|
if (pBindCtx)
|
|
pBindCtx->Release();
|
|
|
|
if (FAILED(hr) && sink)
|
|
sink->Release();
|
|
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT CInternetControl::OnProgress( DISPID, ULONG progress, ULONG themax, ULONG, LPCWSTR)
|
|
{
|
|
return(NOERROR);
|
|
}
|
|
|
|
HRESULT CInternetControl::FireReadyStateChange(LONG newState)
|
|
{
|
|
FireEvent(&::rgEvents[InternetEvent_ReadyStateChange], m_readyState = newState);
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT CInternetControl::FireProgress(ULONG dwAmount)
|
|
{
|
|
FireEvent(&::rgEvents[InternetEvent_Progress], dwAmount);
|
|
return(S_OK);
|
|
}
|