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