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.

341 lines
7.0 KiB

  1. // Copyright (C) 1996-1997 Microsoft Corporation. All rights reserved.
  2. // contains internet helper classes CDownloadSink and CInternetControl
  3. #include "header.h"
  4. #include "Internet.H"
  5. static VARTYPE rgI4[] = { VT_I4 };
  6. typedef enum {
  7. InternetEvent_Progress = 0,
  8. InternetEvent_ReadyStateChange = 1
  9. } INTERNETEVENTS;
  10. static EVENTINFO rgEvents [] = {
  11. { DISPID_PROGRESS, 1, rgI4 }, // (long percentDone)
  12. { DISPID_READYSTATECHANGE, 1, rgI4 }, // (OLE_READYSTATE newState)
  13. };
  14. // local class for doing async monitoring. It's not really all that
  15. // general purpose, but it does the job...
  16. // REVIEW: 06-Jul-1997 [ralphw] Why do we need this for HHCtrl?
  17. class CDownloadSink : public IBindStatusCallback
  18. {
  19. public:
  20. CDownloadSink(IUnknown *punkOuter,CInternetControl *,DISPID );
  21. ~CDownloadSink();
  22. STDMETHOD(QueryInterface)(REFIID riid, void **ppvObjOut);
  23. STDMETHOD_(ULONG, AddRef)();
  24. STDMETHOD_(ULONG, Release)();
  25. STDMETHOD(OnStartBinding)(
  26. /* [in] */ DWORD grfBSCOption,
  27. /* [in] */ IBinding *pib);
  28. STDMETHOD(GetPriority)(
  29. /* [out] */ LONG *pnPriority);
  30. STDMETHOD(OnLowResource)(
  31. /* [in] */ DWORD reserved);
  32. STDMETHOD(OnProgress)(
  33. /* [in] */ ULONG ulProgress,
  34. /* [in] */ ULONG ulProgressMax,
  35. /* [in] */ ULONG ulStatusCode,
  36. /* [in] */ LPCWSTR szStatusText);
  37. STDMETHOD(OnStopBinding)(
  38. /* [in] */ HRESULT hresult,
  39. /* [in] */ LPCWSTR szError);
  40. STDMETHOD(GetBindInfo)(
  41. /* [out] */ DWORD *grfBINDINFOF,
  42. /* [unique][out][in] */ BINDINFO *pbindinfo);
  43. STDMETHOD(OnDataAvailable)(
  44. /* [in] */ DWORD grfBSCF,
  45. /* [in] */ DWORD dwSize,
  46. /* [in] */ FORMATETC *pformatetc,
  47. /* [in] */ STGMEDIUM *pstgmed);
  48. STDMETHOD(OnObjectAvailable)(
  49. /* [in] */ REFIID riid,
  50. /* [iid_is][in] */ IUnknown *punk);
  51. CDownloadSink * Next() { return(m_next); }
  52. void Next(CDownloadSink *n) { m_next = n; }
  53. DISPID DispId() { return(m_propId); }
  54. IBinding * Binding() { return(m_binding); }
  55. private:
  56. CDownloadSink * m_next;
  57. CInternetControl * m_control;
  58. DISPID m_propId;
  59. IBinding * m_binding;
  60. DWORD m_ref;
  61. IStream * m_stream;
  62. };
  63. CDownloadSink::CDownloadSink(IUnknown * punkOuter,
  64. CInternetControl * control, DISPID propId)
  65. {
  66. m_control = control;
  67. m_control->AddRef();
  68. m_propId = propId;
  69. m_next = 0;
  70. m_binding = 0;
  71. m_ref = 0;
  72. m_stream = 0;
  73. DBWIN("CDownloadSink created.");
  74. }
  75. CDownloadSink::~CDownloadSink()
  76. {
  77. if (m_control)
  78. m_control->Release();
  79. if (m_binding)
  80. m_binding->Release();
  81. if (m_stream)
  82. m_stream->Release();
  83. }
  84. STDMETHODIMP CDownloadSink::QueryInterface(const GUID &iid, void **ppv)
  85. {
  86. if (IsEqualGUID(iid, IID_IUnknown) ||
  87. IsEqualGUID(iid, IID_IBindStatusCallback)) {
  88. *ppv = this;
  89. AddRef();
  90. return(NOERROR);
  91. }
  92. return(E_NOINTERFACE);
  93. }
  94. STDMETHODIMP_(ULONG) CDownloadSink::AddRef()
  95. {
  96. return(++m_ref);
  97. }
  98. STDMETHODIMP_(ULONG) CDownloadSink::Release()
  99. {
  100. if (!--m_ref) {
  101. delete this;
  102. return(0);
  103. }
  104. return(m_ref);
  105. }
  106. STDMETHODIMP CDownloadSink::GetBindInfo(DWORD *grfBINDF, BINDINFO *pbindInfo)
  107. {
  108. *grfBINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_NOCOPYDATA;
  109. return(NOERROR);
  110. }
  111. STDMETHODIMP CDownloadSink::OnStartBinding(DWORD /*grfBSCOption*/,
  112. IBinding *pib)
  113. {
  114. // BUGBUG: should check to see options are what we think they are
  115. m_binding = pib;
  116. pib->AddRef();
  117. return(NOERROR);
  118. }
  119. STDMETHODIMP CDownloadSink::GetPriority( LONG *pnPriority)
  120. {
  121. return(E_NOTIMPL);
  122. }
  123. STDMETHODIMP CDownloadSink::OnProgress(ULONG ulProgress, ULONG ulProgressMax,
  124. ULONG ulStatusCode, LPCWSTR pwzStatusText)
  125. {
  126. return m_control->OnProgress(m_propId,ulProgress, ulProgressMax,
  127. ulStatusCode, pwzStatusText);
  128. }
  129. STDMETHODIMP CDownloadSink::OnDataAvailable(DWORD grfBSCF, DWORD dwSize,
  130. FORMATETC * pFmtetc, STGMEDIUM * pstgmed)
  131. {
  132. #ifdef DEBUG
  133. char msg[200];
  134. wsprintf(msg,"::OnDataAvailable(%0xd,%d,%s,%s)", grfBSCF, dwSize,
  135. pFmtetc ? "pFmtetc" : "NULL", pstgmed ? "pstgmed" : "NULL");
  136. DBWIN(msg);
  137. #endif
  138. if (!m_stream)
  139. m_stream = pstgmed->pstm;
  140. return (m_control->OnData(m_propId, grfBSCF, m_stream, dwSize));
  141. }
  142. STDMETHODIMP CDownloadSink::OnObjectAvailable(REFIID riid, IUnknown *punk)
  143. {
  144. return(E_NOTIMPL);
  145. }
  146. STDMETHODIMP CDownloadSink::OnLowResource(DWORD reserved)
  147. {
  148. m_binding->Abort();
  149. return(S_OK);
  150. }
  151. STDMETHODIMP CDownloadSink::OnStopBinding(HRESULT hrError, LPCWSTR szError)
  152. {
  153. m_binding->Release();
  154. m_binding = 0;
  155. m_control->Release();
  156. m_control = 0;
  157. return(NOERROR);
  158. }
  159. // class CInternetControl
  160. CInternetControl::CInternetControl(IUnknown * pUnkOuter,
  161. int iPrimaryDispatch, void * pMainInterface)
  162. : COleControl(pUnkOuter,iPrimaryDispatch,pMainInterface)
  163. {
  164. m_host = 0;
  165. m_readyState = READYSTATE_LOADING;
  166. }
  167. CInternetControl::~CInternetControl()
  168. {
  169. if (m_host)
  170. m_host->Release();
  171. }
  172. HRESULT CInternetControl::InternalQueryInterface(REFIID riid,
  173. void **ppvObjOut)
  174. {
  175. *ppvObjOut = NULL;
  176. return COleControl::InternalQueryInterface(riid, ppvObjOut);
  177. }
  178. HRESULT CInternetControl::GetBindHost()
  179. {
  180. if (m_host)
  181. return(NOERROR);
  182. // Try service provider first...
  183. IServiceProvider * serviceProvider = 0;
  184. HRESULT hr = m_pClientSite->QueryInterface(IID_IServiceProvider,
  185. (void**) &serviceProvider);
  186. if (SUCCEEDED(hr)) {
  187. hr = serviceProvider->QueryService(SID_IBindHost, IID_IBindHost,
  188. (void**) &m_host);
  189. serviceProvider->Release();
  190. }
  191. if (FAILED(hr)) {
  192. // Some containers put IBindHost directly on the client site
  193. hr = m_pClientSite->QueryInterface (IID_IBindHost, (void**) &m_host);
  194. }
  195. return(hr);
  196. }
  197. HRESULT CInternetControl::GetAMoniker(LPOLESTR url, IMoniker ** ppmkr)
  198. {
  199. #if 0
  200. 11-Jun-1997 [ralphw] m_host->CreateMoniker generates a compiler
  201. error. Doesn't exist in any header file that I can find.
  202. HRESULT hr = GetBindHost();
  203. if( SUCCEEDED(hr) )
  204. hr = m_host->CreateMoniker(url,NULL, ppmkr,0);
  205. if( FAILED(hr) )
  206. {
  207. // FUTURE: This really should be a call to MkParseDisplayNameEx!!!
  208. hr = ::CreateURLMoniker(0,url,ppmkr);
  209. // hr = ::MkParseDisplayNameEx(0, url, 0, ppmkr);
  210. }
  211. return( hr );
  212. #else
  213. return ::CreateURLMoniker(0,url,ppmkr);
  214. #endif
  215. }
  216. HRESULT CInternetControl::SetupDownload(LPOLESTR url, DISPID propId)
  217. {
  218. CHECK_POINTER(url);
  219. IMoniker * pmkr;
  220. HRESULT hr = GetAMoniker(url, &pmkr);
  221. IBindCtx * pBindCtx = 0;
  222. if (SUCCEEDED(hr)) {
  223. hr = ::CreateBindCtx(0, &pBindCtx);
  224. }
  225. CDownloadSink * sink = 0;
  226. if (SUCCEEDED(hr)) {
  227. sink = new CDownloadSink(0, this, propId);
  228. if (sink)
  229. sink->AddRef();
  230. }
  231. if (SUCCEEDED(hr) && !sink)
  232. hr = E_OUTOFMEMORY;
  233. if (SUCCEEDED(hr)) {
  234. hr = ::RegisterBindStatusCallback(pBindCtx, sink, 0, 0);
  235. }
  236. IStream * strm = 0;
  237. if (SUCCEEDED(hr))
  238. hr = pmkr->BindToStorage(pBindCtx, 0, IID_IStream, (void**) &strm);
  239. if (strm)
  240. strm->Release();
  241. if (pBindCtx)
  242. pBindCtx->Release();
  243. if (FAILED(hr) && sink)
  244. sink->Release();
  245. return(hr);
  246. }
  247. HRESULT CInternetControl::OnProgress( DISPID, ULONG progress, ULONG themax, ULONG, LPCWSTR)
  248. {
  249. return(NOERROR);
  250. }
  251. HRESULT CInternetControl::FireReadyStateChange(LONG newState)
  252. {
  253. FireEvent(&::rgEvents[InternetEvent_ReadyStateChange], m_readyState = newState);
  254. return(S_OK);
  255. }
  256. HRESULT CInternetControl::FireProgress(ULONG dwAmount)
  257. {
  258. FireEvent(&::rgEvents[InternetEvent_Progress], dwAmount);
  259. return(S_OK);
  260. }