windows-nt/Source/XPSP1/NT/admin/pchealth/helpctr/shell/connectivity/connectioncheck.cpp
2020-09-26 16:20:57 +08:00

328 lines
8.3 KiB
C++

/******************************************************************************
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 );
}