home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / activexcontrol / basectl / framewrk / internet.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-05  |  10.6 KB  |  426 lines

  1. //=--------------------------------------------------------------------------=
  2. // Internet.Cpp
  3. //=--------------------------------------------------------------------------=
  4. // Copyright 1995-1997 Microsoft Corporation.  All Rights Reserved.
  5. //
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
  7. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
  8. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
  9. // PARTICULAR PURPOSE.
  10. //=--------------------------------------------------------------------------=
  11. //
  12. // contains internet helper classes CDownloadSink and CInternetControl
  13. //
  14. #include "IPServer.H"
  15. #include "Internet.H"
  16. #include "Util.H"
  17.  
  18. static VARTYPE rgI4[] = { VT_I4 };
  19.  
  20. typedef enum {
  21.     InternetEvent_Progress = 0,
  22.     InternetEvent_ReadyStateChange = 1
  23. } INTERNETEVENTS;
  24.  
  25. static EVENTINFO rgEvents [] = {
  26.     { DISPID_PROGRESS, 1, rgI4 },           // (long percentDone)
  27.     { DISPID_READYSTATECHANGE, 1, rgI4 },       // (OLE_READYSTATE newState)
  28. };
  29.  
  30.  
  31. // local class for doing async monitoring. It's not really all that
  32. // general purpose, but it does the job...
  33.  
  34.  
  35. class CDownloadSink : public IBindStatusCallback
  36. {
  37. public:
  38.     CDownloadSink(IUnknown *punkOuter,CInternetControl *,DISPID );
  39.     ~CDownloadSink();
  40.  
  41.     STDMETHOD(QueryInterface)(REFIID riid, void **ppvObjOut);
  42.     STDMETHOD_(ULONG, AddRef)();
  43.     STDMETHOD_(ULONG, Release)();
  44.  
  45.         STDMETHOD(OnStartBinding)(
  46.             /* [in] */ DWORD grfBSCOption,
  47.             /* [in] */ IBinding *pib);
  48.  
  49.         STDMETHOD(GetPriority)(
  50.             /* [out] */ LONG *pnPriority);
  51.  
  52.         STDMETHOD(OnLowResource)(
  53.             /* [in] */ DWORD reserved);
  54.  
  55.         STDMETHOD(OnProgress)(
  56.             /* [in] */ ULONG ulProgress,
  57.             /* [in] */ ULONG ulProgressMax,
  58.             /* [in] */ ULONG ulStatusCode,
  59.             /* [in] */ LPCWSTR szStatusText);
  60.  
  61.         STDMETHOD(OnStopBinding)(
  62.             /* [in] */ HRESULT hresult,
  63.             /* [in] */ LPCWSTR szError);
  64.  
  65.         STDMETHOD(GetBindInfo)(
  66.             /* [out] */ DWORD *grfBINDINFOF,
  67.             /* [unique][out][in] */ BINDINFO *pbindinfo);
  68.  
  69.         STDMETHOD(OnDataAvailable)(
  70.             /* [in] */ DWORD grfBSCF,
  71.             /* [in] */ DWORD dwSize,
  72.             /* [in] */ FORMATETC *pformatetc,
  73.             /* [in] */ STGMEDIUM *pstgmed);
  74.  
  75.         STDMETHOD(OnObjectAvailable)(
  76.             /* [in] */ REFIID riid,
  77.             /* [iid_is][in] */ IUnknown *punk);
  78.  
  79.  
  80.  
  81.         CDownloadSink * Next()                  { return(m_next); }
  82.         void            Next(CDownloadSink *n)  { m_next = n; }
  83.  
  84.         DISPID          DispId()  { return(m_propId); }
  85.         IBinding *      Binding() { return(m_binding); }
  86.  
  87. private:
  88.  
  89.         CDownloadSink *         m_next;
  90.         CInternetControl *      m_control;
  91.         DISPID                  m_propId;
  92.         IBinding *              m_binding;
  93.         DWORD                   m_ref;
  94.                 IStream *                               m_stream;
  95.  
  96. };
  97.  
  98.  
  99. CDownloadSink::CDownloadSink
  100. (
  101.         IUnknown *              punkOuter,
  102.         CInternetControl *      control,
  103.         DISPID                  propId
  104. )
  105. {
  106. //      CHECK_POINTER(control);
  107.  
  108.         m_control = control;
  109.         m_control->AddRef();
  110.  
  111.         m_propId  = propId;
  112.         m_next    = 0;
  113.         m_binding = 0;
  114.         m_ref     = 0;
  115.         m_stream  = 0;
  116. }
  117.  
  118. CDownloadSink::~CDownloadSink()
  119. {
  120.         if( m_control )
  121.                 m_control->Release();
  122.         if( m_binding )
  123.                 m_binding->Release();
  124.         if( m_stream )
  125.                 m_stream->Release();
  126. }
  127.  
  128. STDMETHODIMP
  129. CDownloadSink::QueryInterface(const GUID &iid,void **ppv )
  130. {
  131.         if( IsEqualGUID(iid,IID_IUnknown) || IsEqualGUID(iid,IID_IBindStatusCallback) )
  132.         {
  133.                 *ppv = this;
  134.                 AddRef();
  135.                 return(NOERROR);
  136.         }
  137.         return( E_NOINTERFACE );
  138. }
  139.  
  140. STDMETHODIMP_(ULONG)
  141. CDownloadSink::AddRef()
  142. {
  143.         return(++m_ref);
  144. }
  145.  
  146. STDMETHODIMP_(ULONG)
  147. CDownloadSink::Release()
  148. {
  149.         if(!--m_ref)
  150.         {
  151.                 delete this;
  152.                 return(0);
  153.         }
  154.         return( m_ref );
  155. }
  156.  
  157.  
  158. STDMETHODIMP
  159. CDownloadSink::GetBindInfo( DWORD *grfBINDF, BINDINFO *pbindInfo)
  160. {
  161.     *grfBINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA;
  162.         return(NOERROR);
  163. }
  164.  
  165.  
  166. STDMETHODIMP
  167. CDownloadSink::OnStartBinding(DWORD /*grfBSCOption*/,IBinding *pib)
  168. {
  169.         // BUGBUG: should check to see options are what we think they are
  170.         m_binding = pib;
  171.         pib->AddRef();
  172.         return(NOERROR);
  173. }
  174.  
  175.  
  176. STDMETHODIMP
  177. CDownloadSink::GetPriority( LONG *pnPriority)
  178. {
  179.         return(E_NOTIMPL);
  180. }
  181.  
  182. STDMETHODIMP
  183. CDownloadSink::OnProgress
  184. (
  185.      ULONG ulProgress,
  186.      ULONG ulProgressMax,
  187.      ULONG ulStatusCode,
  188.      LPCWSTR pwzStatusText
  189. )
  190. {
  191.         return(m_control->OnProgress(m_propId,ulProgress,
  192.                                                         ulProgressMax,ulStatusCode,pwzStatusText) );
  193. }
  194.  
  195. STDMETHODIMP
  196. CDownloadSink::OnDataAvailable
  197. (
  198.      DWORD                      grfBSCF,
  199.      DWORD                      dwSize,
  200.      FORMATETC *        pFmtetc,
  201.          STGMEDIUM *    pstgmed
  202. )
  203. {
  204. #ifdef DEBUG
  205.         char msg[200];
  206.         wsprintf(msg,"::OnDataAvailable(%0xd,%d,%s,%s)\n",grfBSCF,dwSize,
  207.                 pFmtetc ? "pFmtetc" : "NULL", pstgmed ? "pstgmed" : "NULL" );
  208.         OutputDebugString(msg);
  209. #endif
  210.  
  211.     if( !m_stream )
  212.                 m_stream = pstgmed->pstm;
  213.  
  214.         return(m_control->OnData(       m_propId,
  215.                                                                 grfBSCF,
  216.                                                                 m_stream,
  217.                                                                 dwSize ));
  218. }
  219.  
  220. STDMETHODIMP
  221. CDownloadSink::OnObjectAvailable
  222. (
  223.         REFIID riid,
  224.     IUnknown *punk
  225. )
  226. {
  227.         return(E_NOTIMPL);
  228. }
  229.  
  230.  
  231. STDMETHODIMP
  232. CDownloadSink::OnLowResource( DWORD reserved)
  233. {
  234.         // BUGBUG: really should have this kind of harsh policy on this ...
  235.         m_binding->Abort();
  236.         return(S_OK);
  237. }
  238.  
  239. STDMETHODIMP
  240. CDownloadSink::OnStopBinding(HRESULT hrError, LPCWSTR szError)
  241. {
  242.         m_binding->Release();
  243.         m_binding = 0;
  244.         m_control->Release();
  245.         m_control = 0;
  246.  
  247.         return(NOERROR);
  248. }
  249.  
  250.  
  251.  
  252. //------------------------------------------------------
  253. //
  254. // class CInternetControl
  255. //
  256. //
  257. CInternetControl::CInternetControl
  258. (
  259.         IUnknown *      pUnkOuter,
  260.         int                     iPrimaryDispatch,
  261.         void *          pMainInterface
  262. )
  263.         : COleControl(pUnkOuter,iPrimaryDispatch,pMainInterface)
  264. {
  265.         m_host = 0;
  266.         m_readyState = READYSTATE_LOADING;
  267. }
  268.  
  269. CInternetControl::~CInternetControl()
  270. {
  271.         if( m_host )
  272.                 m_host->Release();
  273. }
  274.  
  275.  
  276. HRESULT CInternetControl::InternalQueryInterface
  277. (
  278.     REFIID  riid,
  279.     void  **ppvObjOut
  280. )
  281. {
  282.     *ppvObjOut = NULL;
  283.      return COleControl::InternalQueryInterface(riid, ppvObjOut);
  284. }
  285.  
  286.  
  287.  
  288. HRESULT
  289. CInternetControl::GetBindHost()
  290. {
  291.  
  292.         if( m_host )
  293.                 return(NOERROR);
  294.  
  295.     // Try service provider first...
  296.  
  297.         IServiceProvider * serviceProvider = 0;
  298.  
  299.         HRESULT hr = m_pClientSite->QueryInterface
  300.                                                                         (
  301.                                                                                 IID_IServiceProvider,
  302.                                                                                 (void**)&serviceProvider
  303.                                                                         );
  304.  
  305.         if( SUCCEEDED(hr) )
  306.     {
  307.                 hr = serviceProvider->QueryService
  308.                                     (
  309.                                         SID_IBindHost,
  310.                                         IID_IBindHost,
  311.                                         (void**)&m_host
  312.                                     );
  313.                 serviceProvider->Release();
  314.     }
  315.  
  316.     if( FAILED(hr) )
  317.     {
  318.         // Some containers put IBindHost directly on the client site
  319.  
  320.         hr = m_pClientSite->QueryInterface
  321.                                                                         (
  322.                                         IID_IBindHost,
  323.                                         (void**)&m_host
  324.                                                                         );
  325.  
  326.  
  327.     }
  328.  
  329.         return(hr);
  330.  
  331. }
  332.  
  333.  
  334. HRESULT CInternetControl::GetAMoniker( LPOLESTR url, IMoniker ** ppmkr )
  335. {
  336.         HRESULT hr = GetBindHost();
  337.  
  338.         if( SUCCEEDED(hr) )
  339.                 hr = m_host->CreateMoniker(url,NULL, ppmkr,0);
  340.  
  341.         if( FAILED(hr) )
  342.     {
  343.            // FUTURE: This really should be a call to MkParseDisplayNameEx!!!
  344.        hr = ::CreateURLMoniker(0,url,ppmkr);
  345.        // hr = ::MkParseDisplayNameEx(0, url, 0, ppmkr);
  346.     }
  347.  
  348.         return( hr );
  349. }
  350.  
  351.  
  352. HRESULT CInternetControl::SetupDownload( LPOLESTR url, DISPID propId )
  353. {
  354.         CHECK_POINTER(url);
  355.  
  356.         IMoniker * pmkr;
  357.  
  358.         HRESULT hr = GetAMoniker( url, &pmkr );
  359.  
  360.         IBindCtx * pBindCtx = 0;
  361.  
  362.         if( SUCCEEDED(hr) )
  363.     {
  364.         hr = ::CreateBindCtx(0,&pBindCtx);
  365.     }
  366.  
  367.         CDownloadSink * sink = 0;
  368.  
  369.         if( SUCCEEDED(hr) )
  370.         {
  371.                 sink = new CDownloadSink(0,this,propId);
  372.                 if( sink )
  373.                         sink->AddRef();
  374.         }
  375.  
  376.         if( SUCCEEDED(hr) && !sink )
  377.                 hr = E_OUTOFMEMORY;
  378.  
  379.         if( SUCCEEDED(hr) )
  380.         {
  381.                 // BUGBUG: There should be a define for 0x77
  382.                 hr = ::RegisterBindStatusCallback(pBindCtx, sink,0, 0) ;
  383.         }
  384.  
  385.         IStream * strm = 0;
  386.  
  387.         if( SUCCEEDED(hr) )
  388.                 hr = pmkr->BindToStorage( pBindCtx, 0, IID_IStream, (void**)&strm );
  389.  
  390.         if( strm )
  391.                 strm->Release();
  392.  
  393.         if( pBindCtx )
  394.                 pBindCtx->Release();
  395.  
  396.         if( FAILED(hr) && sink )
  397.                 sink->Release();
  398.  
  399.         return(hr);
  400.  
  401. }
  402.  
  403.  
  404. HRESULT CInternetControl::OnData( DISPID, DWORD,IStream *, DWORD)
  405. {
  406.         return(NOERROR);
  407. }
  408.  
  409. HRESULT CInternetControl::OnProgress( DISPID, ULONG progress, ULONG themax, ULONG, LPCWSTR)
  410. {
  411.         return(NOERROR);
  412. }
  413.  
  414.  
  415. HRESULT CInternetControl::FireReadyStateChange( long newState )
  416. {
  417.         FireEvent( &::rgEvents[InternetEvent_ReadyStateChange], m_readyState = newState );
  418.         return(S_OK);
  419. }
  420.  
  421. HRESULT CInternetControl::FireProgress( ULONG dwAmount )
  422. {
  423.         FireEvent( &::rgEvents[InternetEvent_Progress], dwAmount );
  424.         return(S_OK);
  425. }
  426.