|
|
/******************************************************************************
Copyright (c) 1999 Microsoft Corporation
Module Name: Connection.cpp
Abstract: This file contains the implementation of the CHCPConnection class, which implements the internet connection functionality.
Revision History: Anand Arvind (aarvind) 2000-03-22 created
Test Code : UnitTest/test_concheck.htm
******************************************************************************/
#include "stdafx.h"
/////////////////////////////////////////////////////////////////////////////
CPCHConnectionCheck::UrlEntry::UrlEntry() { m_lStatus = CN_URL_INVALID; // CN_URL_STATUS m_lStatus;
// CComBSTR m_bstrURL;
// CComVariant m_vCtx;
}
HRESULT CPCHConnectionCheck::UrlEntry::CheckStatus() { __HCP_FUNC_ENTRY( "CPCHConnectionCheck::UrlEntry::CheckStatus" );
HRESULT hr;
m_lStatus = CN_URL_UNREACHABLE;
//
// Verify immediately if it's a CHM.
//
{ CComBSTR bstrStorageName; CComBSTR bstrFilePath;
if(MPC::MSITS::IsCHM( SAFEBSTR( m_bstrURL ), &bstrStorageName, &bstrFilePath )) { CComPtr<IStream> stream;
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::MSITS::OpenAsStream( bstrStorageName, bstrFilePath, &stream ));
m_lStatus = CN_URL_ALIVE;
__MPC_SET_ERROR_AND_EXIT(hr, S_OK); } }
//
// Check destination
//
{ HyperLinks::UrlHandle uh; HyperLinks::ParsedUrl* pu;
__MPC_EXIT_IF_METHOD_FAILS(hr, HyperLinks::Lookup::s_GLOBAL->Get( m_bstrURL, uh, /*dwWaitForCheck*/HC_TIMEOUT_CONNECTIONCHECK, /*fForce*/true ));
pu = uh; if(!pu) __MPC_EXIT_IF_METHOD_FAILS(hr, E_FAIL);
switch(pu->m_state) { case HyperLinks::STATE_ALIVE : break; case HyperLinks::STATE_NOTFOUND : __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_INTERNET_ITEM_NOT_FOUND ); break; case HyperLinks::STATE_UNREACHABLE: __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_INTERNET_SERVER_UNREACHABLE); break; case HyperLinks::STATE_OFFLINE : __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_INTERNET_DISCONNECTED ); break; } }
m_lStatus = CN_URL_ALIVE; hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr); }
/////////////////////////////////////////////////////////////////////////////
CPCHConnectionCheck::CPCHConnectionCheck() { __HCP_FUNC_ENTRY( "CPCHConnectionCheck::CPCHConnectionCheck" );
m_cnStatus = CN_NOTACTIVE; // CN_STATUS m_cnStatus;
// UrlList m_lstUrl;
//
// MPC::CComPtrThreadNeutral<IDispatch> m_sink_onProgressURL;
// MPC::CComPtrThreadNeutral<IDispatch> m_sink_onComplete;
}
void CPCHConnectionCheck::FinalRelease() { __HCP_FUNC_ENTRY( "CPCHConnectionCheck::FinalRelease" );
Thread_Wait(); }
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
HRESULT CPCHConnectionCheck::Run() { __HCP_FUNC_ENTRY( "CPCHConnectionCheck::Run" );
HRESULT hr; MPC::SmartLock<_ThreadModel> lock( this ); HRESULT hrExtendedError; UrlEntry urlEntry; UrlIter it;
::SetThreadPriority( ::GetCurrentThread(), THREAD_PRIORITY_LOWEST );
while(1) { //
// If no item in the list, go back to WaitForSingleObject.
//
it = m_lstUrl.begin(); if(it == m_lstUrl.end()) break;
//
// Get the first event in the list.
//
urlEntry = *it;
//
// Remove the event from the list.
//
m_lstUrl.erase( it );
put_Status( CN_CHECKING );
//
// Now that we have the data, let's unlock the object.
//
lock = NULL;
if(Thread_IsAborted()) { urlEntry.m_lStatus = CN_URL_ABORTED; hrExtendedError = E_ABORT; } else { hrExtendedError = E_ABORT;
__MPC_PROTECT( hrExtendedError = urlEntry.CheckStatus() ); }
//
// Fire event for the destination's status
//
(void)Fire_onCheckDone( this, urlEntry.m_lStatus, hrExtendedError, urlEntry.m_bstrURL, urlEntry.m_vCtx );
//
// Before looping, relock the object.
//
lock = this; }
put_Status( CN_IDLE );
__HCP_FUNC_EXIT(S_OK); }
/////////////////////////////////////////////////////////////////////////////
////////////////
// //
// Properties //
// //
////////////////
STDMETHODIMP CPCHConnectionCheck::put_onCheckDone( /*[in]*/ IDispatch* function ) { __HCP_BEGIN_PROPERTY_PUT("CPCHConnectionCheck::put_onCheckDone",hr);
if(Thread_IsRunning()) { __MPC_SET_ERROR_AND_EXIT(hr, E_ACCESSDENIED); }
m_sink_onCheckDone = function;
__HCP_END_PROPERTY(hr); }
STDMETHODIMP CPCHConnectionCheck::put_onStatusChange( /*[in]*/ IDispatch* function ) { __HCP_BEGIN_PROPERTY_PUT("CPCHConnectionCheck::put_onStatusChange",hr);
if(Thread_IsRunning()) { __MPC_SET_ERROR_AND_EXIT(hr, E_ACCESSDENIED); }
m_sink_onStatusChange = function;
__HCP_END_PROPERTY(hr); }
HRESULT CPCHConnectionCheck::put_Status( /*[in]*/ CN_STATUS pVal ) // Inner method
{ __HCP_BEGIN_PROPERTY_PUT("CPCHConnectionCheck::put_Status",hr);
if(m_cnStatus != pVal) { Fire_onStatusChange( this, m_cnStatus = pVal ); }
__HCP_END_PROPERTY(hr); }
STDMETHODIMP CPCHConnectionCheck::get_Status( /*[out]*/ CN_STATUS *pVal ) { __HCP_BEGIN_PROPERTY_GET2("CPCHConnectionCheck::get_Status",hr,pVal,m_cnStatus);
__HCP_END_PROPERTY(hr); }
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CPCHConnectionCheck::StartUrlCheck( /*[in]*/ BSTR bstrURL, /*[in]*/ VARIANT vCtx ) { __HCP_FUNC_ENTRY( "CPCHConnectionCheck::StartUrlCheck" );
HRESULT hr; MPC::SmartLock<_ThreadModel> lock( this );
__MPC_PARAMCHECK_BEGIN(hr) __MPC_PARAMCHECK_STRING_NOT_EMPTY(bstrURL); __MPC_PARAMCHECK_END();
__MPC_EXIT_IF_METHOD_FAILS(hr, HyperLinks::IsValid( bstrURL ));
//
// Add the URL to the list of pending items.
//
{ UrlIter it = m_lstUrl.insert( m_lstUrl.end() );
it->m_bstrURL = bstrURL; it->m_vCtx = vCtx; }
if(Thread_IsRunning() == false || Thread_IsAborted() == true ) { //
// Release the lock on current object, otherwise a deadlock could occur.
//
lock = NULL;
__MPC_EXIT_IF_METHOD_FAILS(hr, Thread_Start( this, Run, NULL )); }
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr); }
STDMETHODIMP CPCHConnectionCheck::Abort() { __HCP_FUNC_ENTRY( "CPCHConnectionCheck::Abort" );
Thread_Abort(); // To tell the MPC:Thread object to close the worker thread...
__HCP_FUNC_EXIT(S_OK); }
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//////////////////////////
// //
// Event Firing Methods //
// //
//////////////////////////
HRESULT CPCHConnectionCheck::Fire_onCheckDone( IPCHConnectionCheck* obj, CN_URL_STATUS lStatus, HRESULT hr, BSTR bstrURL, VARIANT vCtx ) { CComVariant pvars[5];
pvars[4] = obj; pvars[3] = lStatus; pvars[2] = hr; pvars[1] = bstrURL; pvars[0] = vCtx;
return FireAsync_Generic( DISPID_PCH_CNE__ONCHECKDONE, pvars, ARRAYSIZE( pvars ), m_sink_onCheckDone ); }
HRESULT CPCHConnectionCheck::Fire_onStatusChange( IPCHConnectionCheck* obj, CN_STATUS lStatus ) { CComVariant pvars[2];
pvars[1] = obj; pvars[0] = lStatus;
return FireAsync_Generic( DISPID_PCH_CNE__ONSTATUSCHANGE, pvars, ARRAYSIZE( pvars ), m_sink_onStatusChange ); }
|