Leaked source code of windows server 2003
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.
 
 
 
 
 
 

630 lines
16 KiB

// NextLink.cpp : Implementation of CNextLink
#include "stdafx.h"
#include "NxtLnk.h"
#include "NextLink.h"
#define MAX_RESSTRINGSIZE 512
CNextLink::LinkFileMapT CNextLink::s_linkFileMap;
/////////////////////////////////////////////////////////////////////////////
// CNextLink
STDMETHODIMP CNextLink::InterfaceSupportsErrorInfo(REFIID riid)
{
static const IID* arr[] =
{
&IID_INextLink,
};
for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
{
if (InlineIsEqualGUID(*arr[i],riid))
return S_OK;
}
return S_FALSE;
}
STDMETHODIMP CNextLink::get_GetNextURL(BSTR bstrLinkFile, BSTR * pVal)
{
SCODE rc = E_FAIL;
try
{
CLinkFilePtr pLinkFile;
String strPage;
if ( GetFileAndPage( IDS_ERROR_CANNOT_XLATE_VIRT_ROOT_GETNEXTURL, bstrLinkFile, pLinkFile, strPage ) )
{
if ( pLinkFile.IsValid() )
{
CReader rdr(*pLinkFile);
CLinkPtr pLink = pLinkFile->NextLink( strPage );
if ( pLink.IsValid() )
{
if ( pVal )
{
if ( *pVal )
{
::SysFreeString( *pVal );
}
HRESULT hr;
CMBCSToWChar convStr;
if (hr = convStr.Init(pLink->Link().c_str(),
pLinkFile->fUTF8() ? 65001 : CP_ACP)) {
throw _com_error(hr);
}
*pVal = ::SysAllocString(convStr.GetString());
THROW_IF_NULL(*pVal);
rc = S_OK;
}
else
{
rc = E_POINTER;
}
}
}
}
}
catch ( _com_error& ce )
{
rc = ce.Error();
}
catch ( ... )
{
rc = E_FAIL;
}
return rc;
}
STDMETHODIMP CNextLink::get_GetNextDescription(BSTR bstrLinkFile, BSTR * pVal)
{
SCODE rc = E_FAIL;
try
{
CLinkFilePtr pLinkFile;
String strPage;
if ( GetFileAndPage( IDS_ERROR_CANNOT_XLATE_VIRT_ROOT_GETNEXTDESCRIPTION, bstrLinkFile, pLinkFile, strPage ) )
{
if ( pLinkFile.IsValid() )
{
CReader rdr(*pLinkFile);
CLinkPtr pLink = pLinkFile->NextLink( strPage );
if ( pLink.IsValid() )
{
if ( pVal )
{
if ( *pVal )
{
::SysFreeString( *pVal );
}
HRESULT hr;
CMBCSToWChar convStr;
if (hr = convStr.Init(pLink->Desc().c_str(),
pLinkFile->fUTF8() ? 65001 : CP_ACP)) {
throw _com_error(hr);
}
*pVal = ::SysAllocString(convStr.GetString());
THROW_IF_NULL(*pVal);
rc = S_OK;
}
else
{
rc = E_POINTER;
}
}
}
}
}
catch ( _com_error& ce )
{
rc = ce.Error();
}
catch ( ... )
{
rc = E_FAIL;
}
return rc;
}
STDMETHODIMP CNextLink::get_GetPreviousURL(BSTR bstrLinkFile, BSTR * pVal)
{
SCODE rc = E_FAIL;
try
{
CLinkFilePtr pLinkFile;
String strPage;
if ( GetFileAndPage( IDS_ERROR_CANNOT_XLATE_VIRT_ROOT_GETPREVIOUSURL, bstrLinkFile, pLinkFile, strPage ) )
{
if ( pLinkFile.IsValid() )
{
CReader rdr(*pLinkFile);
CLinkPtr pLink = pLinkFile->PreviousLink( strPage );
if ( pLink.IsValid() )
{
if ( pVal )
{
if ( *pVal )
{
::SysFreeString( *pVal );
}
HRESULT hr;
CMBCSToWChar convStr;
if (hr = convStr.Init(pLink->Link().c_str(),
pLinkFile->fUTF8() ? 65001 : CP_ACP)) {
throw _com_error(hr);
}
*pVal = ::SysAllocString(convStr.GetString());
THROW_IF_NULL( *pVal );
rc = S_OK;
}
else
{
rc = E_POINTER;
}
}
}
}
}
catch ( _com_error& ce )
{
rc = ce.Error();
}
catch ( ... )
{
rc = E_FAIL;
}
return rc;
}
STDMETHODIMP CNextLink::get_GetPreviousDescription(BSTR bstrLinkFile, BSTR * pVal)
{
SCODE rc = E_FAIL;
try
{
CLinkFilePtr pLinkFile;
String strPage;
if ( GetFileAndPage( IDS_ERROR_CANNOT_XLATE_VIRT_ROOT_GETPREVIOUSDDESCRIPTION, bstrLinkFile, pLinkFile, strPage ) )
{
if ( pLinkFile.IsValid() )
{
CReader rdr(*pLinkFile);
CLinkPtr pLink = pLinkFile->PreviousLink( strPage );
if ( pLink.IsValid() )
{
if ( pVal )
{
if ( *pVal )
{
::SysFreeString( *pVal );
}
HRESULT hr;
CMBCSToWChar convStr;
if (hr = convStr.Init(pLink->Desc().c_str(),
pLinkFile->fUTF8() ? 65001 : CP_ACP)) {
throw _com_error(hr);
}
*pVal = ::SysAllocString(convStr.GetString());
THROW_IF_NULL( *pVal );
rc = S_OK;
}
else
{
rc = E_POINTER;
}
}
}
}
}
catch ( _com_error& ce )
{
rc = ce.Error();
}
catch ( ... )
{
rc = E_FAIL;
}
return rc;
}
STDMETHODIMP CNextLink::get_GetNthURL(BSTR bstrLinkFile, int nIndex, BSTR * pVal)
{
SCODE rc = E_FAIL;
try
{
CLinkFilePtr pLinkFile = LinkFile( IDS_ERROR_CANNOT_XLATE_VIRT_ROOT_GETNTHURL, bstrLinkFile );
if ( pLinkFile.IsValid() )
{
CReader rdr(*pLinkFile);
if ( (nIndex <= 0) || (nIndex > pLinkFile->NumLinks()) ) {
RaiseException( IDS_ERROR_INVALID_NTH_INDEX );
goto err;
}
CLinkPtr pLink = pLinkFile->Link( nIndex );
if ( pLink.IsValid() )
{
if ( pVal )
{
if (*pVal)
{
::SysFreeString(*pVal);
}
HRESULT hr;
CMBCSToWChar convStr;
if (hr = convStr.Init(pLink->Link().c_str(),
pLinkFile->fUTF8() ? 65001 : CP_ACP)) {
throw _com_error(hr);
}
*pVal = ::SysAllocString(convStr.GetString());
THROW_IF_NULL(*pVal);
rc = S_OK;
}
else
{
rc = E_POINTER;
}
}
}
}
catch ( _com_error& ce )
{
rc = ce.Error();
}
catch ( ... )
{
rc = E_FAIL;
}
err:
return rc;
}
STDMETHODIMP CNextLink::get_GetNthDescription(BSTR bstrLinkFile, int nIndex, BSTR * pVal)
{
SCODE rc = E_FAIL;
try
{
CLinkFilePtr pLinkFile = LinkFile( IDS_ERROR_CANNOT_XLATE_VIRT_ROOT_GETNTHDESCRIPTION, bstrLinkFile );
if ( pLinkFile.IsValid() )
{
CReader rdr(*pLinkFile);
if ( (nIndex <= 0) || (nIndex > pLinkFile->NumLinks()) ) {
RaiseException( IDS_ERROR_INVALID_NTH_INDEX );
goto err;
}
CLinkPtr pLink = pLinkFile->Link( nIndex );
if ( pLink.IsValid() )
{
if ( pVal )
{
if ( *pVal )
{
::SysFreeString( *pVal );
}
HRESULT hr;
CMBCSToWChar convStr;
if (hr = convStr.Init(pLink->Desc().c_str(),
pLinkFile->fUTF8() ? 65001 : CP_ACP)) {
throw _com_error(hr);
}
*pVal = ::SysAllocString(convStr.GetString());
THROW_IF_NULL( *pVal );
rc = S_OK;
}
else
{
rc = E_POINTER;
}
}
}
}
catch ( _com_error& ce )
{
rc = ce.Error();
}
catch ( ... )
{
rc = E_FAIL;
}
err:
return rc;
}
STDMETHODIMP CNextLink::get_GetListCount(BSTR bstrLinkFile, int * pVal)
{
SCODE rc = E_FAIL;
try
{
CLinkFilePtr pLinkFile = LinkFile( IDS_ERROR_CANNOT_XLATE_VIRT_ROOT_GETLISTCOUNT, bstrLinkFile );
if ( pLinkFile.IsValid() )
{
CReader rdr(*pLinkFile);
*pVal = pLinkFile->NumLinks();
rc = S_OK;
}
}
catch ( _com_error& ce )
{
rc = ce.Error();
}
catch ( ... )
{
rc = E_FAIL;
}
return rc;
}
STDMETHODIMP CNextLink::get_GetListIndex(BSTR bstrLinkFile, int * pVal)
{
SCODE rc = E_FAIL;
try
{
CLinkFilePtr pLinkFile;
String strPage;
if ( GetFileAndPage( IDS_ERROR_CANNOT_XLATE_VIRT_ROOT_GETLISTINDEX, bstrLinkFile, pLinkFile, strPage ) )
{
if ( pLinkFile.IsValid() )
{
CReader rdr(*pLinkFile);
*pVal = pLinkFile->LinkIndex( strPage );
rc = S_OK;
}
}
}
catch ( _com_error& ce )
{
rc = ce.Error();
}
catch ( ... )
{
rc = E_FAIL;
}
return rc;
}
STDMETHODIMP CNextLink::get_About(BSTR * pVal)
{
USES_CONVERSION;
#ifdef _DEBUG
LPCTSTR szVersion = _T("Debug");
#else
LPCTSTR szVersion = _T("Release");
#endif
const int kAboutSize = 1024;
_TCHAR szAboutFmt[kAboutSize];
_TCHAR szBuffer[ kAboutSize + sizeof(__DATE__) + sizeof(__TIME__) + sizeof(szVersion) ];
::LoadString( _Module.GetResourceInstance(), IDS_ABOUT_FMT, szAboutFmt, kAboutSize );
_stprintf(szBuffer, szAboutFmt, szVersion, __DATE__, __TIME__);
if ( pVal )
{
if ( *pVal )
{
::SysFreeString( *pVal );
}
*pVal = T2BSTR( szBuffer );
if ( *pVal == NULL )
{
return E_OUTOFMEMORY;
}
}
else
{
return E_POINTER;
}
return S_OK;
}
bool
CNextLink::GetPage(
CContext& cxt,
String& strPage )
{
USES_CONVERSION;
bool rc = false;
if ( cxt.Request() != NULL )
{
CComPtr<IDispatch> piPathInfo;
HRESULT hr = cxt.Request()->get_Item( L"PATH_INFO", &piPathInfo );
if ( !FAILED(hr) )
{
CComVariant vt = piPathInfo;
hr = vt.ChangeType( VT_BSTR );
if ( !FAILED( hr ) )
{
strPage = OLE2T(vt.bstrVal);
rc = true;
}
}
}
return rc;
}
CLinkFilePtr
CNextLink::LinkFile(
CContext& cxt,
UINT errorID,
BSTR bstrFile )
{
USES_CONVERSION;
CLinkFilePtr pLinkFile;
if ( cxt.Server() != NULL )
{
CComBSTR bstrPath;
HRESULT hr = cxt.Server()->MapPath( bstrFile, &bstrPath );
if ( !FAILED( hr ) )
{
String strFile = OLE2T(bstrPath);
CLock l( s_linkFileMap );
CLinkFilePtr& rpLinkFile = s_linkFileMap[strFile];
if ( !rpLinkFile.IsValid() )
{
rpLinkFile = new CLinkFile( strFile );
}
else
{
// make sure the file is up to date
rpLinkFile->Refresh();
}
if ( rpLinkFile->IsOkay() )
{
}
else
{
rpLinkFile = NULL;
}
pLinkFile = rpLinkFile;
}
else
{
RaiseException( errorID );
}
}
return pLinkFile;
}
CLinkFilePtr
CNextLink::LinkFile(
UINT errorID,
BSTR bstrFile )
{
CLinkFilePtr pLinkFile;
CContext cxt;
HRESULT hr = cxt.Init( CContext::get_Server );
if ( !FAILED(hr) )
{
pLinkFile = LinkFile( cxt, errorID, bstrFile );
}
else
{
RaiseException( IDS_ERROR_NOSVR );
}
return pLinkFile;
}
bool
CNextLink::GetFileAndPage(
UINT errorID,
BSTR bstrFile,
CLinkFilePtr& pLinkFile,
String& strPage )
{
bool rc = false;
CContext cxt;
HRESULT hr = cxt.Init( CContext::get_Server | CContext::get_Request );
if ( !FAILED( hr ) )
{
pLinkFile = LinkFile( cxt, errorID, bstrFile );
if ( pLinkFile.IsValid() )
{
rc = GetPage( cxt, strPage );
}
}
else
{
RaiseException( IDS_ERROR_NOSVR );
}
return rc;
}
void
CNextLink::ClearLinkFiles()
{
CLock l(s_linkFileMap);
s_linkFileMap.clear();
}
//---------------------------------------------------------------------------
// RaiseException
//
// Raises an exception using the given source and description
//---------------------------------------------------------------------------
void
CNextLink::RaiseException (
LPOLESTR strDescr
)
{
HRESULT hr;
ICreateErrorInfo *pICreateErr;
IErrorInfo *pIErr;
LANGID langID = LANG_NEUTRAL;
/*
* Thread-safe exception handling means that we call
* CreateErrorInfo which gives us an ICreateErrorInfo pointer
* that we then use to set the error information (basically
* to set the fields of an EXCEPINFO structure. We then
* call SetErrorInfo to attach this error to the current
* thread. ITypeInfo::Invoke will look for this when it
* returns from whatever function was invokes by calling
* GetErrorInfo.
*/
_TCHAR tstrSource[MAX_RESSTRINGSIZE];
if ( ::LoadString(
_Module.GetResourceInstance(),
IDS_ERROR_SOURCE,
tstrSource,
MAX_RESSTRINGSIZE ) > 0 )
{
USES_CONVERSION;
LPOLESTR strSource = T2OLE(tstrSource);
//Not much we can do if this fails.
if (!FAILED(CreateErrorInfo(&pICreateErr)))
{
pICreateErr->SetGUID(CLSID_NextLink);
pICreateErr->SetHelpFile(L"");
pICreateErr->SetHelpContext(0L);
pICreateErr->SetSource(strSource);
pICreateErr->SetDescription(strDescr);
hr = pICreateErr->QueryInterface(IID_IErrorInfo, (void**)&pIErr);
if (SUCCEEDED(hr))
{
if(SUCCEEDED(SetErrorInfo(0L, pIErr)))
{
pIErr->Release();
}
}
pICreateErr->Release();
}
}
}
void
CNextLink::RaiseException(
UINT DescrID
)
{
_TCHAR tstrDescr[MAX_RESSTRINGSIZE];
if ( ::LoadString(
_Module.GetResourceInstance(),
DescrID,
tstrDescr,
MAX_RESSTRINGSIZE) > 0 )
{
USES_CONVERSION;
LPOLESTR strDescr = T2OLE(tstrDescr);
RaiseException( strDescr );
}
}