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.

327 lines
8.3 KiB

  1. /******************************************************************************
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. Connection.cpp
  5. Abstract:
  6. This file contains the implementation of the CHCPConnection class,
  7. which implements the internet connection functionality.
  8. Revision History:
  9. Anand Arvind (aarvind) 2000-03-22
  10. created
  11. Test Code : UnitTest/test_concheck.htm
  12. ******************************************************************************/
  13. #include "stdafx.h"
  14. /////////////////////////////////////////////////////////////////////////////
  15. CPCHConnectionCheck::UrlEntry::UrlEntry()
  16. {
  17. m_lStatus = CN_URL_INVALID; // CN_URL_STATUS m_lStatus;
  18. // CComBSTR m_bstrURL;
  19. // CComVariant m_vCtx;
  20. }
  21. HRESULT CPCHConnectionCheck::UrlEntry::CheckStatus()
  22. {
  23. __HCP_FUNC_ENTRY( "CPCHConnectionCheck::UrlEntry::CheckStatus" );
  24. HRESULT hr;
  25. m_lStatus = CN_URL_UNREACHABLE;
  26. //
  27. // Verify immediately if it's a CHM.
  28. //
  29. {
  30. CComBSTR bstrStorageName;
  31. CComBSTR bstrFilePath;
  32. if(MPC::MSITS::IsCHM( SAFEBSTR( m_bstrURL ), &bstrStorageName, &bstrFilePath ))
  33. {
  34. CComPtr<IStream> stream;
  35. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::MSITS::OpenAsStream( bstrStorageName, bstrFilePath, &stream ));
  36. m_lStatus = CN_URL_ALIVE;
  37. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  38. }
  39. }
  40. //
  41. // Check destination
  42. //
  43. {
  44. HyperLinks::UrlHandle uh;
  45. HyperLinks::ParsedUrl* pu;
  46. __MPC_EXIT_IF_METHOD_FAILS(hr, HyperLinks::Lookup::s_GLOBAL->Get( m_bstrURL, uh, /*dwWaitForCheck*/HC_TIMEOUT_CONNECTIONCHECK, /*fForce*/true ));
  47. pu = uh;
  48. if(!pu) __MPC_EXIT_IF_METHOD_FAILS(hr, E_FAIL);
  49. switch(pu->m_state)
  50. {
  51. case HyperLinks::STATE_ALIVE : break;
  52. case HyperLinks::STATE_NOTFOUND : __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_INTERNET_ITEM_NOT_FOUND ); break;
  53. case HyperLinks::STATE_UNREACHABLE: __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_INTERNET_SERVER_UNREACHABLE); break;
  54. case HyperLinks::STATE_OFFLINE : __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_INTERNET_DISCONNECTED ); break;
  55. }
  56. }
  57. m_lStatus = CN_URL_ALIVE;
  58. hr = S_OK;
  59. __HCP_FUNC_CLEANUP;
  60. __HCP_FUNC_EXIT(hr);
  61. }
  62. /////////////////////////////////////////////////////////////////////////////
  63. CPCHConnectionCheck::CPCHConnectionCheck()
  64. {
  65. __HCP_FUNC_ENTRY( "CPCHConnectionCheck::CPCHConnectionCheck" );
  66. m_cnStatus = CN_NOTACTIVE; // CN_STATUS m_cnStatus;
  67. // UrlList m_lstUrl;
  68. //
  69. // MPC::CComPtrThreadNeutral<IDispatch> m_sink_onProgressURL;
  70. // MPC::CComPtrThreadNeutral<IDispatch> m_sink_onComplete;
  71. }
  72. void CPCHConnectionCheck::FinalRelease()
  73. {
  74. __HCP_FUNC_ENTRY( "CPCHConnectionCheck::FinalRelease" );
  75. Thread_Wait();
  76. }
  77. /////////////////////////////////////////////////////////////////////////////
  78. /////////////////////////////////////////////////////////////////////////////
  79. HRESULT CPCHConnectionCheck::Run()
  80. {
  81. __HCP_FUNC_ENTRY( "CPCHConnectionCheck::Run" );
  82. HRESULT hr;
  83. MPC::SmartLock<_ThreadModel> lock( this );
  84. HRESULT hrExtendedError;
  85. UrlEntry urlEntry;
  86. UrlIter it;
  87. ::SetThreadPriority( ::GetCurrentThread(), THREAD_PRIORITY_LOWEST );
  88. while(1)
  89. {
  90. //
  91. // If no item in the list, go back to WaitForSingleObject.
  92. //
  93. it = m_lstUrl.begin(); if(it == m_lstUrl.end()) break;
  94. //
  95. // Get the first event in the list.
  96. //
  97. urlEntry = *it;
  98. //
  99. // Remove the event from the list.
  100. //
  101. m_lstUrl.erase( it );
  102. put_Status( CN_CHECKING );
  103. //
  104. // Now that we have the data, let's unlock the object.
  105. //
  106. lock = NULL;
  107. if(Thread_IsAborted())
  108. {
  109. urlEntry.m_lStatus = CN_URL_ABORTED;
  110. hrExtendedError = E_ABORT;
  111. }
  112. else
  113. {
  114. hrExtendedError = E_ABORT;
  115. __MPC_PROTECT( hrExtendedError = urlEntry.CheckStatus() );
  116. }
  117. //
  118. // Fire event for the destination's status
  119. //
  120. (void)Fire_onCheckDone( this, urlEntry.m_lStatus, hrExtendedError, urlEntry.m_bstrURL, urlEntry.m_vCtx );
  121. //
  122. // Before looping, relock the object.
  123. //
  124. lock = this;
  125. }
  126. put_Status( CN_IDLE );
  127. __HCP_FUNC_EXIT(S_OK);
  128. }
  129. /////////////////////////////////////////////////////////////////////////////
  130. ////////////////
  131. // //
  132. // Properties //
  133. // //
  134. ////////////////
  135. STDMETHODIMP CPCHConnectionCheck::put_onCheckDone( /*[in]*/ IDispatch* function )
  136. {
  137. __HCP_BEGIN_PROPERTY_PUT("CPCHConnectionCheck::put_onCheckDone",hr);
  138. if(Thread_IsRunning())
  139. {
  140. __MPC_SET_ERROR_AND_EXIT(hr, E_ACCESSDENIED);
  141. }
  142. m_sink_onCheckDone = function;
  143. __HCP_END_PROPERTY(hr);
  144. }
  145. STDMETHODIMP CPCHConnectionCheck::put_onStatusChange( /*[in]*/ IDispatch* function )
  146. {
  147. __HCP_BEGIN_PROPERTY_PUT("CPCHConnectionCheck::put_onStatusChange",hr);
  148. if(Thread_IsRunning())
  149. {
  150. __MPC_SET_ERROR_AND_EXIT(hr, E_ACCESSDENIED);
  151. }
  152. m_sink_onStatusChange = function;
  153. __HCP_END_PROPERTY(hr);
  154. }
  155. HRESULT CPCHConnectionCheck::put_Status( /*[in]*/ CN_STATUS pVal ) // Inner method
  156. {
  157. __HCP_BEGIN_PROPERTY_PUT("CPCHConnectionCheck::put_Status",hr);
  158. if(m_cnStatus != pVal)
  159. {
  160. Fire_onStatusChange( this, m_cnStatus = pVal );
  161. }
  162. __HCP_END_PROPERTY(hr);
  163. }
  164. STDMETHODIMP CPCHConnectionCheck::get_Status( /*[out]*/ CN_STATUS *pVal )
  165. {
  166. __HCP_BEGIN_PROPERTY_GET2("CPCHConnectionCheck::get_Status",hr,pVal,m_cnStatus);
  167. __HCP_END_PROPERTY(hr);
  168. }
  169. /////////////////////////////////////////////////////////////////////////////
  170. /////////////////////////////////////////////////////////////////////////////
  171. STDMETHODIMP CPCHConnectionCheck::StartUrlCheck( /*[in]*/ BSTR bstrURL, /*[in]*/ VARIANT vCtx )
  172. {
  173. __HCP_FUNC_ENTRY( "CPCHConnectionCheck::StartUrlCheck" );
  174. HRESULT hr;
  175. MPC::SmartLock<_ThreadModel> lock( this );
  176. __MPC_PARAMCHECK_BEGIN(hr)
  177. __MPC_PARAMCHECK_STRING_NOT_EMPTY(bstrURL);
  178. __MPC_PARAMCHECK_END();
  179. __MPC_EXIT_IF_METHOD_FAILS(hr, HyperLinks::IsValid( bstrURL ));
  180. //
  181. // Add the URL to the list of pending items.
  182. //
  183. {
  184. UrlIter it = m_lstUrl.insert( m_lstUrl.end() );
  185. it->m_bstrURL = bstrURL;
  186. it->m_vCtx = vCtx;
  187. }
  188. if(Thread_IsRunning() == false ||
  189. Thread_IsAborted() == true )
  190. {
  191. //
  192. // Release the lock on current object, otherwise a deadlock could occur.
  193. //
  194. lock = NULL;
  195. __MPC_EXIT_IF_METHOD_FAILS(hr, Thread_Start( this, Run, NULL ));
  196. }
  197. hr = S_OK;
  198. __HCP_FUNC_CLEANUP;
  199. __HCP_FUNC_EXIT(hr);
  200. }
  201. STDMETHODIMP CPCHConnectionCheck::Abort()
  202. {
  203. __HCP_FUNC_ENTRY( "CPCHConnectionCheck::Abort" );
  204. Thread_Abort(); // To tell the MPC:Thread object to close the worker thread...
  205. __HCP_FUNC_EXIT(S_OK);
  206. }
  207. /////////////////////////////////////////////////////////////////////////////
  208. /////////////////////////////////////////////////////////////////////////////
  209. //////////////////////////
  210. // //
  211. // Event Firing Methods //
  212. // //
  213. //////////////////////////
  214. HRESULT CPCHConnectionCheck::Fire_onCheckDone( IPCHConnectionCheck* obj, CN_URL_STATUS lStatus, HRESULT hr, BSTR bstrURL, VARIANT vCtx )
  215. {
  216. CComVariant pvars[5];
  217. pvars[4] = obj;
  218. pvars[3] = lStatus;
  219. pvars[2] = hr;
  220. pvars[1] = bstrURL;
  221. pvars[0] = vCtx;
  222. return FireAsync_Generic( DISPID_PCH_CNE__ONCHECKDONE, pvars, ARRAYSIZE( pvars ), m_sink_onCheckDone );
  223. }
  224. HRESULT CPCHConnectionCheck::Fire_onStatusChange( IPCHConnectionCheck* obj, CN_STATUS lStatus )
  225. {
  226. CComVariant pvars[2];
  227. pvars[1] = obj;
  228. pvars[0] = lStatus;
  229. return FireAsync_Generic( DISPID_PCH_CNE__ONSTATUSCHANGE, pvars, ARRAYSIZE( pvars ), m_sink_onStatusChange );
  230. }