Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

426 lines
10 KiB

  1. //=--------------------------------------------------------------------------=
  2. // Internet.Cpp
  3. //=--------------------------------------------------------------------------=
  4. // Copyright 1995-1996 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. static VARTYPE rgI4[] = { VT_I4 };
  18. typedef enum {
  19. InternetEvent_Progress = 0,
  20. InternetEvent_ReadyStateChange = 1
  21. } INTERNETEVENTS;
  22. static EVENTINFO rgEvents [] = {
  23. { DISPID_PROGRESS, 1, rgI4 }, // (long percentDone)
  24. { DISPID_READYSTATECHANGE, 1, rgI4 }, // (OLE_READYSTATE newState)
  25. };
  26. // local class for doing async monitoring. It's not really all that
  27. // general purpose, but it does the job...
  28. class CDownloadSink : public IBindStatusCallback
  29. {
  30. public:
  31. CDownloadSink(IUnknown *punkOuter,CInternetControl *,DISPID );
  32. ~CDownloadSink();
  33. STDMETHOD(QueryInterface)(REFIID riid, void **ppvObjOut);
  34. STDMETHOD_(ULONG, AddRef)();
  35. STDMETHOD_(ULONG, Release)();
  36. STDMETHOD(OnStartBinding)(
  37. /* [in] */ DWORD grfBSCOption,
  38. /* [in] */ IBinding *pib);
  39. STDMETHOD(GetPriority)(
  40. /* [out] */ LONG *pnPriority);
  41. STDMETHOD(OnLowResource)(
  42. /* [in] */ DWORD reserved);
  43. STDMETHOD(OnProgress)(
  44. /* [in] */ ULONG ulProgress,
  45. /* [in] */ ULONG ulProgressMax,
  46. /* [in] */ ULONG ulStatusCode,
  47. /* [in] */ LPCWSTR szStatusText);
  48. STDMETHOD(OnStopBinding)(
  49. /* [in] */ HRESULT hresult,
  50. /* [in] */ LPCWSTR szError);
  51. STDMETHOD(GetBindInfo)(
  52. /* [out] */ DWORD *grfBINDINFOF,
  53. /* [unique][out][in] */ BINDINFO *pbindinfo);
  54. STDMETHOD(OnDataAvailable)(
  55. /* [in] */ DWORD grfBSCF,
  56. /* [in] */ DWORD dwSize,
  57. /* [in] */ FORMATETC *pformatetc,
  58. /* [in] */ STGMEDIUM *pstgmed);
  59. STDMETHOD(OnObjectAvailable)(
  60. /* [in] */ REFIID riid,
  61. /* [iid_is][in] */ IUnknown *punk);
  62. CDownloadSink * Next() { return(m_next); }
  63. void Next(CDownloadSink *n) { m_next = n; }
  64. DISPID DispId() { return(m_propId); }
  65. IBinding * Binding() { return(m_binding); }
  66. private:
  67. CDownloadSink * m_next;
  68. CInternetControl * m_control;
  69. DISPID m_propId;
  70. IBinding * m_binding;
  71. DWORD m_ref;
  72. IStream * m_stream;
  73. };
  74. CDownloadSink::CDownloadSink
  75. (
  76. IUnknown * punkOuter,
  77. CInternetControl * control,
  78. DISPID propId
  79. )
  80. {
  81. // CHECK_POINTER(control);
  82. m_control = control;
  83. m_control->AddRef();
  84. m_propId = propId;
  85. m_next = 0;
  86. m_binding = 0;
  87. m_ref = 0;
  88. m_stream = 0;
  89. }
  90. CDownloadSink::~CDownloadSink()
  91. {
  92. if( m_control )
  93. m_control->Release();
  94. if( m_binding )
  95. m_binding->Release();
  96. if( m_stream )
  97. m_stream->Release();
  98. }
  99. STDMETHODIMP
  100. CDownloadSink::QueryInterface(const GUID &iid,void **ppv )
  101. {
  102. if( IsEqualGUID(iid,IID_IUnknown) || IsEqualGUID(iid,IID_IBindStatusCallback) )
  103. {
  104. *ppv = this;
  105. AddRef();
  106. return(NOERROR);
  107. }
  108. return( E_NOINTERFACE );
  109. }
  110. STDMETHODIMP_(ULONG)
  111. CDownloadSink::AddRef()
  112. {
  113. return(++m_ref);
  114. }
  115. STDMETHODIMP_(ULONG)
  116. CDownloadSink::Release()
  117. {
  118. if(!--m_ref)
  119. {
  120. delete this;
  121. return(0);
  122. }
  123. return( m_ref );
  124. }
  125. STDMETHODIMP
  126. CDownloadSink::GetBindInfo( DWORD *grfBINDF, BINDINFO *pbindInfo)
  127. {
  128. *grfBINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA;
  129. return(NOERROR);
  130. }
  131. STDMETHODIMP
  132. CDownloadSink::OnStartBinding(DWORD /*grfBSCOption*/,IBinding *pib)
  133. {
  134. // BUGBUG: should check to see options are what we think they are
  135. m_binding = pib;
  136. pib->AddRef();
  137. return(NOERROR);
  138. }
  139. STDMETHODIMP
  140. CDownloadSink::GetPriority( LONG *pnPriority)
  141. {
  142. return(E_NOTIMPL);
  143. }
  144. STDMETHODIMP
  145. CDownloadSink::OnProgress
  146. (
  147. ULONG ulProgress,
  148. ULONG ulProgressMax,
  149. ULONG ulStatusCode,
  150. LPCWSTR pwzStatusText
  151. )
  152. {
  153. return(m_control->OnProgress(m_propId,ulProgress,
  154. ulProgressMax,ulStatusCode,pwzStatusText) );
  155. }
  156. STDMETHODIMP
  157. CDownloadSink::OnDataAvailable
  158. (
  159. DWORD grfBSCF,
  160. DWORD dwSize,
  161. FORMATETC * pFmtetc,
  162. STGMEDIUM * pstgmed
  163. )
  164. {
  165. #ifdef DEBUG
  166. char msg[200];
  167. wsprintf(msg,"::OnDataAvailable(%0xd,%d,%s,%s)\n",grfBSCF,dwSize,
  168. pFmtetc ? "pFmtetc" : "NULL", pstgmed ? "pstgmed" : "NULL" );
  169. OutputDebugString(msg);
  170. #endif
  171. if( !m_stream )
  172. m_stream = pstgmed->pstm;
  173. return(m_control->OnData( m_propId,
  174. grfBSCF,
  175. m_stream,
  176. dwSize ));
  177. }
  178. STDMETHODIMP
  179. CDownloadSink::OnObjectAvailable
  180. (
  181. REFIID riid,
  182. IUnknown *punk
  183. )
  184. {
  185. return(E_NOTIMPL);
  186. }
  187. STDMETHODIMP
  188. CDownloadSink::OnLowResource( DWORD reserved)
  189. {
  190. // BUGBUG: really should have this kind of harsh policy on this ...
  191. m_binding->Abort();
  192. return(S_OK);
  193. }
  194. STDMETHODIMP
  195. CDownloadSink::OnStopBinding(HRESULT hrError, LPCWSTR szError)
  196. {
  197. m_binding->Release();
  198. m_binding = 0;
  199. m_control->Release();
  200. m_control = 0;
  201. return(NOERROR);
  202. }
  203. //------------------------------------------------------
  204. //
  205. // class CInternetControl
  206. //
  207. //
  208. CInternetControl::CInternetControl
  209. (
  210. IUnknown * pUnkOuter,
  211. int iPrimaryDispatch,
  212. void * pMainInterface
  213. )
  214. : COleControl(pUnkOuter,iPrimaryDispatch,pMainInterface)
  215. {
  216. m_host = 0;
  217. m_readyState = READYSTATE_LOADING;
  218. }
  219. CInternetControl::~CInternetControl()
  220. {
  221. if( m_host )
  222. m_host->Release();
  223. }
  224. HRESULT CInternetControl::InternalQueryInterface
  225. (
  226. REFIID riid,
  227. void **ppvObjOut
  228. )
  229. {
  230. *ppvObjOut = NULL;
  231. return COleControl::InternalQueryInterface(riid, ppvObjOut);
  232. }
  233. HRESULT
  234. CInternetControl::GetBindHost()
  235. {
  236. if( m_host )
  237. return(NOERROR);
  238. // Try service provider first...
  239. IServiceProvider * serviceProvider = 0;
  240. HRESULT hr = m_pClientSite->QueryInterface
  241. (
  242. IID_IServiceProvider,
  243. (void**)&serviceProvider
  244. );
  245. if( SUCCEEDED(hr) )
  246. {
  247. hr = serviceProvider->QueryService
  248. (
  249. SID_IBindHost,
  250. IID_IBindHost,
  251. (void**)&m_host
  252. );
  253. serviceProvider->Release();
  254. }
  255. if( FAILED(hr) )
  256. {
  257. // Some containers put IBindHost directly on the client site
  258. hr = m_pClientSite->QueryInterface
  259. (
  260. IID_IBindHost,
  261. (void**)&m_host
  262. );
  263. }
  264. return(hr);
  265. }
  266. HRESULT CInternetControl::GetAMoniker( LPOLESTR url, IMoniker ** ppmkr )
  267. {
  268. HRESULT hr = GetBindHost();
  269. if( SUCCEEDED(hr) )
  270. hr = m_host->CreateMoniker(url,NULL, ppmkr,0);
  271. if( FAILED(hr) )
  272. {
  273. // FUTURE: This really should be a call to MkParseDisplayNameEx!!!
  274. hr = ::CreateURLMoniker(0,url,ppmkr);
  275. // hr = ::MkParseDisplayNameEx(0, url, 0, ppmkr);
  276. }
  277. return( hr );
  278. }
  279. HRESULT CInternetControl::SetupDownload( LPOLESTR url, DISPID propId )
  280. {
  281. CHECK_POINTER(url);
  282. IMoniker * pmkr;
  283. HRESULT hr = GetAMoniker( url, &pmkr );
  284. IBindCtx * pBindCtx = 0;
  285. if( SUCCEEDED(hr) )
  286. {
  287. hr = ::CreateBindCtx(0,&pBindCtx);
  288. }
  289. CDownloadSink * sink = 0;
  290. if( SUCCEEDED(hr) )
  291. {
  292. sink = new CDownloadSink(0,this,propId);
  293. if( sink )
  294. sink->AddRef();
  295. }
  296. if( SUCCEEDED(hr) && !sink )
  297. hr = E_OUTOFMEMORY;
  298. if( SUCCEEDED(hr) )
  299. {
  300. // BUGBUG: There should be a define for 0x77
  301. hr = ::RegisterBindStatusCallback(pBindCtx, sink,0, 0) ;
  302. }
  303. IStream * strm = 0;
  304. if( SUCCEEDED(hr) )
  305. hr = pmkr->BindToStorage( pBindCtx, 0, IID_IStream, (void**)&strm );
  306. if( strm )
  307. strm->Release();
  308. if( pBindCtx )
  309. pBindCtx->Release();
  310. if( FAILED(hr) && sink )
  311. sink->Release();
  312. return(hr);
  313. }
  314. HRESULT CInternetControl::OnData( DISPID, DWORD,IStream *, DWORD)
  315. {
  316. return(NOERROR);
  317. }
  318. HRESULT CInternetControl::OnProgress( DISPID, ULONG progress, ULONG themax, ULONG, LPCWSTR)
  319. {
  320. return(NOERROR);
  321. }
  322. HRESULT CInternetControl::FireReadyStateChange( long newState )
  323. {
  324. FireEvent( &::rgEvents[InternetEvent_ReadyStateChange], m_readyState = newState );
  325. return(S_OK);
  326. }
  327. HRESULT CInternetControl::FireProgress( ULONG dwAmount )
  328. {
  329. FireEvent( &::rgEvents[InternetEvent_Progress], dwAmount );
  330. return(S_OK);
  331. }
  332.