|
|
//=--------------------------------------------------------------------------=
// Internet.Cpp
//=--------------------------------------------------------------------------=
// Copyright 1995-1996 Microsoft Corporation. All Rights Reserved.
//
// 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.
//=--------------------------------------------------------------------------=
//
// contains internet helper classes CDownloadSink and CInternetControl
//
#include "IPServer.H"
#include "Internet.H"
#include "Util.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...
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 ) { // CHECK_POINTER(control);
m_control = control; m_control->AddRef();
m_propId = propId; m_next = 0; m_binding = 0; m_ref = 0; m_stream = 0; }
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_PULLDATA; 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)\n",grfBSCF,dwSize, pFmtetc ? "pFmtetc" : "NULL", pstgmed ? "pstgmed" : "NULL" ); OutputDebugString(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) { // BUGBUG: really should have this kind of harsh policy on this ...
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 ) { 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 ); }
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) ) { // BUGBUG: There should be a define for 0x77
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::OnData( DISPID, DWORD,IStream *, DWORD) { return(NOERROR); }
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); }
|