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.
 
 
 
 
 
 

876 lines
26 KiB

/******************************************************************************
Copyright (c) 2000 Microsoft Corporation
Module Name:
HyperLinks.cpp
Abstract:
This file contains the implementation of the HyperLinks library.
Revision History:
Davide Massarenti (Dmassare) 11/28/2000
created
******************************************************************************/
#include "stdafx.h"
////////////////////////////////////////////////////////////////////////////////
static const DATE l_TIME_hour = 1.0 / 24.0;
static const DATE l_TIME_minute = l_TIME_hour / 60.0;
static const DATE l_TIME_second = l_TIME_hour / 60.0;
static const DATE l_TIME_timeout = l_TIME_minute * 5.0;
static const WCHAR l_szMS_ITS [] = L"ms-its:";
static const WCHAR l_szMSITSTORE [] = L"mk:@MSITStore:";
static const WCHAR l_szITS [] = L"its:";
static const WCHAR l_szHOMEPAGE [] = L"hcp://services/centers/homepage";
static const WCHAR l_szSUPPORT [] = L"hcp://services/centers/support";
static const WCHAR l_szOPTIONS [] = L"hcp://services/centers/options";
static const WCHAR l_szUPDATE [] = L"hcp://services/centers/update";
static const WCHAR l_szCOMPAT [] = L"hcp://services/centers/compat";
static const WCHAR l_szTOOLS [] = L"hcp://services/centers/tools";
static const WCHAR l_szERRMSG [] = L"hcp://services/centers/errmsg";
static const WCHAR l_szSEARCH [] = L"hcp://services/search";
static const WCHAR l_szINDEX [] = L"hcp://services/index";
static const WCHAR l_szSUBSITE [] = L"hcp://services/subsite";
static const WCHAR l_szFULLWINDOW [] = L"hcp://services/layout/fullwindow";
static const WCHAR l_szCONTENTONLY[] = L"hcp://services/layout/contentonly";
static const WCHAR l_szKIOSK [] = L"hcp://services/layout/kiosk";
static const WCHAR l_szXML [] = L"hcp://services/layout/xml";
static const WCHAR l_szREDIRECT [] = L"hcp://services/redirect";
static const WCHAR l_szHCP [] = L"hcp://";
static const WCHAR l_szHCP_redir [] = L"hcp:";
static const WCHAR l_szAPPLICATION[] = L"app:";
static const WCHAR l_szRESOURCE [] = L"res://";
////////////////////
typedef enum
{
QFT_TEXT ,
QFT_URL ,
QFT_TAXONOMY ,
QFT_APPLICATION,
} QueryFieldType;
struct QueryField
{
LPCWSTR szName;
QueryFieldType qft;
bool fOptional;
};
struct Pattern
{
LPCWSTR szTxt;
size_t iLen; /* -1 for complete match */
HyperLinks::Format fmt;
const QueryField* rgQueryFields;
size_t iQueryFields;
};
////////////////////
static const QueryField l_rgTopic [] = { { L"topic" , QFT_URL , false } };
static const QueryField l_rgTopicOpt[] = { { L"topic" , QFT_URL , true } };
static const QueryField l_rgSEARCH [] = { { L"query" , QFT_TEXT , false } ,
{ L"topic" , QFT_URL , true } };
static const QueryField l_rgINDEX [] = { { L"scope" , QFT_APPLICATION, true } ,
{ L"select" , QFT_APPLICATION, true } ,
{ L"topic" , QFT_URL , true } };
static const QueryField l_rgSUBSITE [] = { { L"node" , QFT_TAXONOMY , false } ,
{ L"select" , QFT_TAXONOMY , true } ,
{ L"topic" , QFT_URL , true } };
static const QueryField l_rgXML [] = { { L"definition" , QFT_URL , false } ,
{ L"topic" , QFT_URL , true } };
static const QueryField l_rgREDIRECT[] = { { L"online" , QFT_URL , false } ,
{ L"offline" , QFT_URL , false } };
static const QueryField l_rgAPP [] = { { L"topic" , QFT_URL , true } };
static const Pattern l_rgPattern[] =
{
{ l_szMS_ITS , MAXSTRLEN( l_szMS_ITS ), HyperLinks::FMT_MSITS },
{ l_szMSITSTORE , MAXSTRLEN( l_szMSITSTORE ), HyperLinks::FMT_MSITS },
{ l_szITS , MAXSTRLEN( l_szITS ), HyperLinks::FMT_MSITS },
////////////////////
{ l_szHOMEPAGE , -1 , HyperLinks::FMT_CENTER_HOMEPAGE },
{ l_szSUPPORT , -1 , HyperLinks::FMT_CENTER_SUPPORT , l_rgTopicOpt, ARRAYSIZE(l_rgTopicOpt ) },
{ l_szOPTIONS , -1 , HyperLinks::FMT_CENTER_OPTIONS , l_rgTopicOpt, ARRAYSIZE(l_rgTopicOpt ) },
{ l_szUPDATE , -1 , HyperLinks::FMT_CENTER_UPDATE },
{ l_szCOMPAT , -1 , HyperLinks::FMT_CENTER_COMPAT },
{ l_szTOOLS , -1 , HyperLinks::FMT_CENTER_TOOLS , l_rgTopicOpt, ARRAYSIZE(l_rgTopicOpt ) },
{ l_szERRMSG , -1 , HyperLinks::FMT_CENTER_ERRMSG },
{ l_szSEARCH , -1 , HyperLinks::FMT_SEARCH , l_rgSEARCH , ARRAYSIZE(l_rgSEARCH ) },
{ l_szINDEX , -1 , HyperLinks::FMT_INDEX , l_rgINDEX , ARRAYSIZE(l_rgINDEX ) },
{ l_szSUBSITE , -1 , HyperLinks::FMT_SUBSITE , l_rgSUBSITE , ARRAYSIZE(l_rgSUBSITE ) },
{ l_szFULLWINDOW , -1 , HyperLinks::FMT_LAYOUT_FULLWINDOW , l_rgTopic , ARRAYSIZE(l_rgTopic ) },
{ l_szCONTENTONLY, -1 , HyperLinks::FMT_LAYOUT_CONTENTONLY, l_rgTopic , ARRAYSIZE(l_rgTopic ) },
{ l_szKIOSK , -1 , HyperLinks::FMT_LAYOUT_KIOSK , l_rgTopic , ARRAYSIZE(l_rgTopic ) },
{ l_szXML , -1 , HyperLinks::FMT_LAYOUT_XML , l_rgXML , ARRAYSIZE(l_rgXML ) },
{ l_szREDIRECT , -1 , HyperLinks::FMT_REDIRECT , l_rgREDIRECT, ARRAYSIZE(l_rgREDIRECT ) },
{ l_szHCP , MAXSTRLEN( l_szHCP ), HyperLinks::FMT_HCP },
{ l_szHCP_redir , MAXSTRLEN( l_szHCP_redir ), HyperLinks::FMT_HCP_REDIR },
////////////////////
{ l_szAPPLICATION, MAXSTRLEN( l_szAPPLICATION ), HyperLinks::FMT_APPLICATION , l_rgAPP , ARRAYSIZE(l_rgAPP ) },
////////////////////
{ l_szRESOURCE , MAXSTRLEN( l_szRESOURCE ), HyperLinks::FMT_RESOURCE },
////////////////////
{ NULL }
};
HyperLinks::ParsedUrl::ParsedUrl()
{
// MPC::wstring m_strURL;
m_fmt = HyperLinks::FMT_INVALID; // Format m_fmt;
m_state = HyperLinks::STATE_INVALID; // State m_state;
m_dLastChecked = 0; // DATE m_dLastChecked;
m_fBackground = true; // bool m_fBackground;
//
// MPC::wstring m_strBasePart;
// MPC::WStringLookup m_mapQuery;
}
HRESULT HyperLinks::ParsedUrl::Initialize( /*[in]*/ LPCWSTR szURL )
{
__HCP_FUNC_ENTRY( "HyperLinks::ParsedUrl::Initialize" );
HRESULT hr;
SANITIZEWSTR(szURL);
m_strURL = szURL;
m_fmt = HyperLinks::FMT_INVALID;
m_state = HyperLinks::STATE_NOTPROCESSED;
MPC::HTML::ParseHREF( m_strURL.c_str(), m_strBasePart, m_mapQuery );
if(m_strBasePart.size() == 0)
{
m_state = HyperLinks::STATE_MALFORMED;
}
else if(MPC::MSITS::IsCHM( m_strBasePart.c_str() ))
{
m_fmt = HyperLinks::FMT_MSITS;
}
else
{
CComBSTR bstrURL( m_strBasePart.c_str() ); if(bstrURL) ::CharLowerW( bstrURL );
szURL = bstrURL;
for(const Pattern* ptr=l_rgPattern; ptr->szTxt; ptr++)
{
int iCmp;
if(ptr->iLen) iCmp = wcsncmp( szURL, ptr->szTxt, ptr->iLen );
else iCmp = wcscmp ( szURL, ptr->szTxt );
if(iCmp == 0)
{
const QueryField* field = ptr->rgQueryFields;
for(size_t i=0; i<ptr->iQueryFields; i++, field++)
{
CComBSTR bstrValue;
if(GetQueryField( field->szName, bstrValue ) == false)
{
if(field->fOptional == false)
{
m_state = HyperLinks::STATE_MALFORMED;
break;
}
}
else
{
if(field->qft == QFT_TEXT)
{
;
}
else if(field->qft == QFT_URL)
{
if(FAILED(IsValid( bstrValue )))
{
m_state = HyperLinks::STATE_MALFORMED;
break;
}
}
else if(field->qft == QFT_TAXONOMY)
{
/* TO DO */
}
else if(field->qft == QFT_APPLICATION)
{
/* TO DO */
}
}
}
m_fmt = ptr->fmt;
break;
}
}
//
// If the URL begins with HCP: but not HCP://, it's a protocol redirection, so recurse.
//
if(m_fmt == HyperLinks::FMT_HCP_REDIR)
{
__MPC_SET_ERROR_AND_EXIT(hr, Initialize( szURL + MAXSTRLEN( l_szHCP_redir ) ));
}
if(m_fmt == HyperLinks::FMT_INVALID) // Still not resolved...
{
MPC::URL url;
INTERNET_SCHEME scheme;
if(SUCCEEDED(url.put_URL ( szURL )) &&
SUCCEEDED(url.get_Scheme( scheme )) )
{
switch(scheme)
{
case INTERNET_SCHEME_UNKNOWN : m_fmt = HyperLinks::FMT_INTERNET_UNKNOWN ; break;
case INTERNET_SCHEME_FTP : m_fmt = HyperLinks::FMT_INTERNET_FTP ; break;
case INTERNET_SCHEME_GOPHER : m_fmt = HyperLinks::FMT_INTERNET_GOPHER ; break;
case INTERNET_SCHEME_HTTP : m_fmt = HyperLinks::FMT_INTERNET_HTTP ; break;
case INTERNET_SCHEME_HTTPS : m_fmt = HyperLinks::FMT_INTERNET_HTTPS ; break;
case INTERNET_SCHEME_FILE : m_fmt = HyperLinks::FMT_INTERNET_FILE ; break;
case INTERNET_SCHEME_NEWS : m_fmt = HyperLinks::FMT_INTERNET_NEWS ; break;
case INTERNET_SCHEME_MAILTO : m_fmt = HyperLinks::FMT_INTERNET_MAILTO ; break;
case INTERNET_SCHEME_SOCKS : m_fmt = HyperLinks::FMT_INTERNET_SOCKS ; break;
case INTERNET_SCHEME_JAVASCRIPT: m_fmt = HyperLinks::FMT_INTERNET_JAVASCRIPT; break;
case INTERNET_SCHEME_VBSCRIPT : m_fmt = HyperLinks::FMT_INTERNET_VBSCRIPT ; break;
default : m_state = HyperLinks::STATE_MALFORMED ; break;
}
}
}
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
bool HyperLinks::ParsedUrl::IsLocal()
{
switch(m_fmt)
{
case HyperLinks::FMT_INTERNET_UNKNOWN :
case HyperLinks::FMT_INTERNET_FTP :
case HyperLinks::FMT_INTERNET_GOPHER :
case HyperLinks::FMT_INTERNET_HTTP :
case HyperLinks::FMT_INTERNET_HTTPS :
case HyperLinks::FMT_INTERNET_FILE :
case HyperLinks::FMT_INTERNET_NEWS :
case HyperLinks::FMT_INTERNET_MAILTO :
case HyperLinks::FMT_INTERNET_SOCKS :
case HyperLinks::FMT_INTERNET_JAVASCRIPT:
case HyperLinks::FMT_INTERNET_VBSCRIPT :
return false;
case HyperLinks::FMT_MSITS:
//
// Make sure it's not on a network share!
//
{
CComBSTR bstrStorageName;
CComBSTR bstrFilePath;
if(MPC::MSITS::IsCHM( m_strURL.c_str(), &bstrStorageName, &bstrFilePath ))
{
if(wcsncmp( L"\\\\", SAFEBSTR(bstrStorageName), 2 ) == 0)
{
return false;
}
}
}
break;
}
return true;
}
HyperLinks::State HyperLinks::ParsedUrl::CheckState( /*[in/out]*/ bool& fFirstWinInetUse )
{
HRESULT hr;
State state = HyperLinks::STATE_NOTFOUND;
LPCWSTR szURL = m_strURL.c_str();
LPCWSTR szEnd;
CComBSTR bstrURL;
//
// Skip the bookmark sign.
//
if((szEnd = wcschr( szURL, '#' )))
{
bstrURL.Attach( ::SysAllocStringLen( szURL, (szEnd - szURL) ) );
szURL = SAFEBSTR( bstrURL );
}
switch(m_fmt)
{
case HyperLinks::FMT_INVALID :
state = HyperLinks::STATE_MALFORMED;
break;
case HyperLinks::FMT_INTERNET_FTP :
case HyperLinks::FMT_INTERNET_GOPHER :
case HyperLinks::FMT_INTERNET_HTTP :
case HyperLinks::FMT_INTERNET_HTTPS :
case HyperLinks::FMT_INTERNET_FILE :
case HyperLinks::FMT_INTERNET_NEWS :
while(1)
{
DWORD dwTimeout = m_fBackground ? HC_TIMEOUT_LINKCHECKER_BACKGROUND : HC_TIMEOUT_LINKCHECKER_FOREGROUND;
if(SUCCEEDED(hr = MPC::Connectivity::DestinationReachable( szURL, dwTimeout )))
{
state = HyperLinks::STATE_ALIVE;
}
else if(hr == E_INVALIDARG) // Unsupported protocol, assume the link is OK.
{
state = HyperLinks::STATE_ALIVE;
}
else if(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
{
state = HyperLinks::STATE_NOTFOUND;
}
else if(hr == HRESULT_FROM_WIN32(ERROR_INTERNET_DISCONNECTED))
{
state = HyperLinks::STATE_OFFLINE;
}
else
{
//
// If it's the first time through, it could be that WinINET couldn't activate the proxy code in time...
//
if(fFirstWinInetUse == true)
{
fFirstWinInetUse = false; continue;
}
if(SUCCEEDED(MPC::Connectivity::NetworkAlive( dwTimeout )))
{
state = HyperLinks::STATE_UNREACHABLE;
}
else
{
state = HyperLinks::STATE_OFFLINE;
}
}
fFirstWinInetUse = false; break;
}
break;
case HyperLinks::FMT_INTERNET_UNKNOWN :
case HyperLinks::FMT_INTERNET_MAILTO :
case HyperLinks::FMT_INTERNET_SOCKS :
case HyperLinks::FMT_INTERNET_JAVASCRIPT:
case HyperLinks::FMT_INTERNET_VBSCRIPT :
state = HyperLinks::STATE_ALIVE;
break;
case HyperLinks::FMT_HCP :
{
CComPtr<IInternetProtocolRoot> obj;
state = HyperLinks::STATE_NOTFOUND;
if(SUCCEEDED(CHCPProtocol::CreateInstance( &obj )))
{
if(SUCCEEDED(obj->Start( szURL, NULL, NULL, 0, NULL )))
{
state = HyperLinks::STATE_ALIVE;
}
}
}
break;
case HyperLinks::FMT_MSITS :
{
MPC::wstring strUrlModified;
MPC::wstring strUrlModified2;
CComBSTR bstrStorageName;
CComBSTR bstrFilePath;
CComPtr<IStream> stream;
state = HyperLinks::STATE_NOTFOUND;
CPCHWrapProtocolInfo::NormalizeUrl( szURL , strUrlModified , /*fReverse*/true );
CPCHWrapProtocolInfo::NormalizeUrl( strUrlModified.c_str(), strUrlModified2, /*fReverse*/false );
if(MPC::MSITS::IsCHM( strUrlModified2.c_str(), &bstrStorageName, &bstrFilePath ))
{
if(SUCCEEDED(MPC::MSITS::OpenAsStream( bstrStorageName, bstrFilePath, &stream )))
{
state = HyperLinks::STATE_ALIVE;
}
}
}
break;
case HyperLinks::FMT_CENTER_HOMEPAGE :
case HyperLinks::FMT_CENTER_SUPPORT :
case HyperLinks::FMT_CENTER_OPTIONS :
case HyperLinks::FMT_CENTER_UPDATE :
case HyperLinks::FMT_CENTER_COMPAT :
case HyperLinks::FMT_CENTER_TOOLS :
case HyperLinks::FMT_CENTER_ERRMSG :
state = HyperLinks::STATE_ALIVE;
break;
case HyperLinks::FMT_SEARCH :
case HyperLinks::FMT_INDEX :
case HyperLinks::FMT_SUBSITE :
state = HyperLinks::STATE_ALIVE;
break;
case HyperLinks::FMT_LAYOUT_FULLWINDOW :
case HyperLinks::FMT_LAYOUT_CONTENTONLY :
case HyperLinks::FMT_LAYOUT_KIOSK :
case HyperLinks::FMT_LAYOUT_XML :
state = HyperLinks::STATE_ALIVE;
break;
case HyperLinks::FMT_REDIRECT :
state = HyperLinks::STATE_ALIVE;
break;
case HyperLinks::FMT_APPLICATION :
state = HyperLinks::STATE_ALIVE;
break;
case HyperLinks::FMT_RESOURCE :
state = HyperLinks::STATE_UNREACHABLE;
break;
}
m_dLastChecked = MPC::GetLocalTime();
return state;
}
bool HyperLinks::ParsedUrl::IsOkToProceed()
{
switch(m_state)
{
case HyperLinks::STATE_NOTPROCESSED:
case HyperLinks::STATE_CHECKING :
case HyperLinks::STATE_ALIVE :
return true;
}
return false;
}
bool HyperLinks::ParsedUrl::HasQueryField( /*[in]*/ LPCWSTR szField )
{
MPC::WStringLookupIter it = m_mapQuery.find( szField );
return (it != m_mapQuery.end());
}
bool HyperLinks::ParsedUrl::GetQueryField( /*[in]*/ LPCWSTR szField, /*[in]*/ CComBSTR& bstrValue )
{
MPC::WStringLookupIter it = m_mapQuery.find( szField );
if(it != m_mapQuery.end())
{
bstrValue = it->second.c_str();
return true;
}
bstrValue.Empty();
return false;
}
////////////////////////////////////////////////////////////////////////////////
HyperLinks::UrlHandle::UrlHandle()
{
m_main = NULL; // Lookup* m_main;
m_pu = NULL; // ParsedUrl* m_pu;
}
HyperLinks::UrlHandle::~UrlHandle()
{
Release();
}
void HyperLinks::UrlHandle::Attach( /*[in]*/ Lookup* main ,
/*[in]*/ ParsedUrl* pu )
{
Release();
m_main = main; if(main) main->Lock();
m_pu = pu;
}
void HyperLinks::UrlHandle::Release()
{
if(m_main) m_main->Unlock();
m_main = NULL;
m_pu = NULL;
}
////////////////////////////////////////////////////////////////////////////////
HyperLinks::Lookup::Lookup()
{
// PendingUrlList m_lst;
// UrlMap m_map;
}
HyperLinks::Lookup::~Lookup()
{
Thread_Wait();
}
////////////////////
HyperLinks::Lookup* HyperLinks::Lookup::s_GLOBAL( NULL );
HRESULT HyperLinks::Lookup::InitializeSystem()
{
if(s_GLOBAL == NULL)
{
s_GLOBAL = new HyperLinks::Lookup;
}
return s_GLOBAL ? S_OK : E_OUTOFMEMORY;
}
void HyperLinks::Lookup::FinalizeSystem()
{
if(s_GLOBAL)
{
delete s_GLOBAL; s_GLOBAL = NULL;
}
}
////////////////////
HRESULT HyperLinks::Lookup::RunChecker()
{
__HCP_FUNC_ENTRY( "HyperLinks::Lookup::RunChecker" );
HRESULT hr;
MPC::SmartLock<_ThreadModel> lock( this );
bool fFirstWinInetUse = true;
Thread_SignalMain();
while(Thread_IsAborted() == false)
{
bool fSleep = true;
ParsedUrl* urlBest = NULL;
PendingUrlIter it;
//
// Look for the first query store not ready and execute it.
//
for(it = m_lst.begin(); it != m_lst.end();)
{
ParsedUrl* url = *it;
if(url->m_state != HyperLinks::STATE_NOTPROCESSED)
{
m_lst.erase( it );
it = m_lst.begin();
urlBest = NULL;
}
else
{
if(url->m_fBackground == false)
{
urlBest = url;
break;
}
urlBest = url;
it++;
}
}
if(urlBest)
{
State state = HyperLinks::STATE_NOTFOUND;
//
// Remove this query from the pending list.
//
for(it = m_lst.begin(); it != m_lst.end(); )
{
if(*it == urlBest)
{
m_lst.erase( it );
it = m_lst.begin();
}
else
{
it++;
}
}
DebugLog( L"%%%%%%%%%%%%%%%%%%%% CHECKING %s\n", urlBest->m_strURL.c_str() );
urlBest->m_state = HyperLinks::STATE_CHECKING;
lock = NULL;
__MPC_PROTECT( state = urlBest->CheckState( fFirstWinInetUse ) );
lock = this;
urlBest->m_state = state;
Thread_SignalMain();
fSleep = false;
}
if(fSleep)
{
lock = NULL;
Thread_WaitForEvents( NULL, INFINITE );
lock = this;
}
}
hr = S_OK;
Thread_Abort();
__HCP_FUNC_EXIT(hr);
}
HRESULT HyperLinks::Lookup::CreateItem( /*[in ]*/ LPCWSTR szURL ,
/*[out]*/ ParsedUrl*& pu )
{
__HCP_FUNC_ENTRY( "HyperLinks::Lookup::CreateItem" );
HRESULT hr;
UrlIter it;
MPC::wstringUC strURL( SAFEWSTR( szURL ) );
it = m_map.find( strURL );
if(it == m_map.end())
{
pu = &(m_map[ strURL ]);
__MPC_EXIT_IF_METHOD_FAILS(hr, pu->Initialize( szURL ));
}
else
{
pu = &it->second;
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
////////////////////
HRESULT HyperLinks::Lookup::Queue( /*[in]*/ LPCWSTR szURL )
{
UrlHandle uh;
return Get( szURL, uh );
}
HRESULT HyperLinks::Lookup::Get( /*[in]*/ LPCWSTR szURL ,
/*[in]*/ UrlHandle& uh ,
/*[in]*/ DWORD dwWaitForCheck ,
/*[in]*/ bool fForce )
{
__HCP_FUNC_ENTRY( "HyperLinks::Lookup::Get" );
HRESULT hr;
MPC::SmartLock<_ThreadModel> lock( this );
ParsedUrl* pu;
uh.Release();
////////////////////////////////////////////////////////////////////////////////
if(Thread_IsRunning() == false)
{
lock = NULL;
__MPC_EXIT_IF_METHOD_FAILS(hr, Thread_Start( this, RunChecker, NULL ));
Thread_WaitNotificationFromWorker( INFINITE, /*fNoMessagePump*/true );
lock = this;
}
////////////////////////////////////////////////////////////////////////////////
__MPC_EXIT_IF_METHOD_FAILS(hr, CreateItem( szURL, pu ));
if(fForce)
{
pu->m_state = HyperLinks::STATE_NOTPROCESSED;
}
switch(pu->m_state)
{
case HyperLinks::STATE_ALIVE :
case HyperLinks::STATE_NOTFOUND :
case HyperLinks::STATE_UNREACHABLE:
case HyperLinks::STATE_OFFLINE :
if(dwWaitForCheck)
{
//
// Make sure the state is not stale.
//
DATE dNow = MPC::GetLocalTime();
if((dNow - pu->m_dLastChecked) >= l_TIME_timeout)
{
pu->m_state = HyperLinks::STATE_NOTPROCESSED;
}
}
break;
}
if(pu->m_state == HyperLinks::STATE_NOTPROCESSED)
{
bool fQueue = false;
bool fWait = false;
if(dwWaitForCheck)
{
//
// Elevate the URL to "important".
//
pu->m_fBackground = false;
fWait = true;
if(pu->IsLocal() == false)
{
fQueue = true;
}
}
else
{
fQueue = true;
}
if(fQueue)
{
m_lst.push_back( pu );
Thread_Signal();
}
if(fWait)
{
if(pu->IsLocal())
{
bool fFirstWinInetUse = false;
pu->m_state = pu->CheckState( fFirstWinInetUse );
}
else
{
int iRetry = 5;
dwWaitForCheck /= iRetry;
while(pu->m_state == HyperLinks::STATE_NOTPROCESSED ||
pu->m_state == HyperLinks::STATE_CHECKING )
{
DWORD dwRes;
lock = NULL;
dwRes = Thread_WaitNotificationFromWorker( dwWaitForCheck, /*fNoMessagePump*/true );
lock = this;
if(iRetry-- == 0)
{
__MPC_SET_ERROR_AND_EXIT(hr, S_FALSE);
}
}
}
}
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
if(pu) uh.Attach( this, pu );
__HCP_FUNC_EXIT(hr);
}
////////////////////////////////////////////////////////////////////////////////
HRESULT HyperLinks::IsValid( /*[in]*/ LPCWSTR szURL )
{
__HCP_FUNC_ENTRY( "HyperLinks::IsValid" );
HRESULT hr;
ParsedUrl pu;
__MPC_EXIT_IF_METHOD_FAILS(hr, pu.Initialize( szURL ));
switch(pu.m_state)
{
case HyperLinks::STATE_INVALID :
case HyperLinks::STATE_MALFORMED:
__MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}