/****************************************************************************** Copyright (c) 2000 Microsoft Corporation Module Name: ProtocolWrap.cpp Abstract: This file contains the implementation of the CPCHWrapProtocolInfo class, that is used to fix problems in the MS-ITS protocol. Revision History: Davide Massarenti (Dmassare) 05/07/2000 created ******************************************************************************/ #include "stdafx.h" static const WCHAR l_szWINDIR [] = L"%WINDIR%"; static const WCHAR l_szHELP_LOCATION[] = L"%HELP_LOCATION%"; ///////////////////////////////////////////////////////////////////////////// CPCHWrapProtocolInfo::CPCHWrapProtocolInfo() { __HCP_FUNC_ENTRY("CPCHWrapProtocolInfo::CPCHWrapProtocolInfo"); // CComPtr m_realClass; // CComPtr m_realInfo; } CPCHWrapProtocolInfo::~CPCHWrapProtocolInfo() { __HCP_FUNC_ENTRY("CPCHWrapProtocolInfo::~CPCHWrapProtocolInfo"); } HRESULT CPCHWrapProtocolInfo::Init( REFGUID realClass ) { __HCP_FUNC_ENTRY( "CPCHWrapProtocolInfo::Init" ); HRESULT hr; __MPC_EXIT_IF_METHOD_FAILS(hr, ::CoGetClassObject( realClass, CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory, (void **)&m_realClass )); __MPC_EXIT_IF_METHOD_FAILS(hr, m_realClass->CreateInstance( NULL, IID_IInternetProtocolInfo, (void **)&m_realInfo )); hr = S_OK; __HCP_FUNC_CLEANUP; __HCP_FUNC_EXIT(hr); } //////////////////////////////////////////////////////////////////////////////// void CPCHWrapProtocolInfo::ExpandAndConcat( /*[out]*/ CComBSTR& bstrStorageName , /*[in]*/ LPCWSTR szVariable , /*[in]*/ LPCWSTR szAppend ) { MPC::wstring strExpanded( szVariable ); MPC::SubstituteEnvVariables( strExpanded ); if(szAppend) { if(szAppend[0] != '\\' && szAppend[0] != '/' ) { strExpanded += L"\\"; } strExpanded += szAppend; } bstrStorageName = strExpanded.c_str(); } void CPCHWrapProtocolInfo::NormalizeUrl( /*[in] */ LPCWSTR pwzUrl , /*[out]*/ MPC::wstring& strUrlModified , /*[in] */ bool fReverse ) { CComBSTR bstrStorageName; CComBSTR bstrFilePath; bool fModified = false; SANITIZEWSTR( pwzUrl ); if(MPC::MSITS::IsCHM( pwzUrl, &bstrStorageName, &bstrFilePath ) && bstrStorageName.Length() > 0) { if(!_wcsnicmp( bstrStorageName, l_szHELP_LOCATION, MAXSTRLEN( l_szHELP_LOCATION ) )) { CComBSTR bstrTmp; while(1) { LPCWSTR szRest = &bstrStorageName[ MAXSTRLEN( l_szHELP_LOCATION ) ]; WCHAR rgDir[MAX_PATH]; // // First, try the current help directory. // ExpandAndConcat( bstrTmp, CHCPProtocolEnvironment::s_GLOBAL->HelpLocation(), szRest ); if(MPC::FileSystemObject::IsFile( bstrTmp )) break; // // Then, try the MUI version of the help directory. // StringCchPrintfW( rgDir, ARRAYSIZE(rgDir), L"%s\\MUI\\%04lx", HC_HELPSVC_HELPFILES_DEFAULT, CHCPProtocolEnvironment::s_GLOBAL->Instance().m_ths.GetLanguage() ); ExpandAndConcat( bstrTmp, rgDir, szRest ); if(MPC::FileSystemObject::IsFile( bstrTmp )) break; // // Finally, try the system help directory. // ExpandAndConcat( bstrTmp, HC_HELPSVC_HELPFILES_DEFAULT, szRest ); break; } if(MPC::FileSystemObject::IsFile( bstrTmp )) { bstrStorageName = bstrTmp; fModified = true; } } if(!_wcsnicmp( bstrStorageName, l_szWINDIR, MAXSTRLEN( l_szWINDIR ) )) { ExpandAndConcat( bstrStorageName, l_szWINDIR, &bstrStorageName[ MAXSTRLEN( l_szWINDIR ) ] ); fModified = true; } if(::PathIsRelativeW( bstrStorageName )) { ExpandAndConcat( bstrStorageName, CHCPProtocolEnvironment::s_GLOBAL->HelpLocation(), bstrStorageName ); fModified = true; } if(fReverse) { MPC::wstring strHelpLocation = CHCPProtocolEnvironment::s_GLOBAL->HelpLocation(); MPC::SubstituteEnvVariables( strHelpLocation ); int iSize = strHelpLocation.size(); if(!_wcsnicmp( bstrStorageName, strHelpLocation.c_str(), iSize )) { strHelpLocation = l_szHELP_LOCATION; strHelpLocation += &bstrStorageName[iSize]; bstrStorageName = strHelpLocation.c_str(); fModified = true; } } } if(fModified) { strUrlModified = L"MS-ITS:"; strUrlModified += bstrStorageName; if(bstrFilePath.Length() > 0) { strUrlModified += L"::/"; strUrlModified += bstrFilePath; } { LPCWSTR pwzQuery; LPCWSTR pwzAnchor; LPCWSTR pwzEnd; pwzQuery = wcsrchr( pwzUrl, '?' ); pwzAnchor = wcsrchr( pwzUrl, '#' ); if(pwzQuery) { if(pwzAnchor) pwzEnd = min(pwzQuery,pwzAnchor); else pwzEnd = pwzQuery; } else { if(pwzAnchor) pwzEnd = pwzAnchor; else pwzEnd = NULL; } if(pwzEnd) strUrlModified += pwzEnd; } } else { strUrlModified = pwzUrl; } } ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CPCHWrapProtocolInfo::CombineUrl( /*[in] */ LPCWSTR pwzBaseUrl , /*[in] */ LPCWSTR pwzRelativeUrl, /*[in] */ DWORD dwCombineFlags, /*[out]*/ LPWSTR pwzResult , /*[in] */ DWORD cchResult , /*[out]*/ DWORD *pcchResult , /*[in] */ DWORD dwReserved ) { __HCP_FUNC_ENTRY("CPCHWrapProtocolInfo::CombineUrl"); HRESULT hr; if(MPC::MSITS::IsCHM( pwzRelativeUrl )) { MPC::wstring strUrlModified; NormalizeUrl( pwzRelativeUrl, strUrlModified, /*fReverse*/false ); if(strUrlModified.size() > cchResult-1) { hr = S_FALSE; } else { StringCchCopyW( pwzResult, cchResult, strUrlModified.c_str() ); hr = S_OK; } *pcchResult = strUrlModified.size()+1; } else { hr = m_realInfo->CombineUrl( pwzBaseUrl , pwzRelativeUrl, dwCombineFlags, pwzResult , cchResult , pcchResult , dwReserved ); } __HCP_FUNC_EXIT(hr); } STDMETHODIMP CPCHWrapProtocolInfo::CompareUrl( /*[in]*/ LPCWSTR pwzUrl1 , /*[in]*/ LPCWSTR pwzUrl2 , /*[in]*/ DWORD dwCompareFlags ) { __HCP_FUNC_ENTRY("CPCHWrapProtocolInfo::CompareUrl"); HRESULT hr; hr = m_realInfo->CompareUrl( pwzUrl1 , pwzUrl2 , dwCompareFlags ); __HCP_FUNC_EXIT(hr); } STDMETHODIMP CPCHWrapProtocolInfo::ParseUrl( /*[in] */ LPCWSTR pwzUrl , /*[in] */ PARSEACTION parseAction , /*[in] */ DWORD dwParseFlags, /*[out]*/ LPWSTR pwzResult , /*[in] */ DWORD cchResult , /*[out]*/ DWORD *pcchResult , /*[in] */ DWORD dwReserved ) { __HCP_FUNC_ENTRY("CPCHWrapProtocolInfo::ParseUrl"); HRESULT hr; MPC::wstring strUrlModified; if(parseAction == PARSE_CANONICALIZE || parseAction == PARSE_SECURITY_URL ) { NormalizeUrl( pwzUrl, strUrlModified, /*fReverse*/false ); pwzUrl = strUrlModified.c_str(); } hr = m_realInfo->ParseUrl( pwzUrl , parseAction , dwParseFlags, pwzResult , cchResult , pcchResult , dwReserved ); // // The MS-ITS: handler returns E_OUTOFMEMORY instead of S_FALSE on a "buffer too small" situation... // if(parseAction == PARSE_SECURITY_URL && hr == E_OUTOFMEMORY) hr = S_FALSE; __HCP_FUNC_EXIT(hr); } STDMETHODIMP CPCHWrapProtocolInfo::QueryInfo( /*[in] */ LPCWSTR pwzUrl , /*[in] */ QUERYOPTION QueryOption , /*[in] */ DWORD dwQueryFlags, /*[out]*/ LPVOID pBuffer , /*[in] */ DWORD cbBuffer , /*[out]*/ DWORD *pcbBuf , /*[in] */ DWORD dwReserved ) { __HCP_FUNC_ENTRY("CPCHWrapProtocolInfo::QueryInfo"); HRESULT hr; hr = m_realInfo->QueryInfo( pwzUrl , QueryOption , dwQueryFlags, pBuffer , cbBuffer , pcbBuf , dwReserved ); __HCP_FUNC_EXIT(hr); } //////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CPCHWrapProtocolInfo::CreateInstance( /*[in] */ LPUNKNOWN pUnkOuter , /*[in] */ REFIID riid , /*[out]*/ void* *ppvObj ) { HRESULT hr = E_POINTER; if(ppvObj) { *ppvObj = NULL; if(InlineIsEqualGUID( IID_IInternetProtocolInfo, riid )) { hr = QueryInterface( riid, ppvObj ); } else if(InlineIsEqualGUID( IID_IUnknown , riid ) || InlineIsEqualGUID( IID_IInternetProtocol , riid ) || InlineIsEqualGUID( IID_IInternetProtocolRoot, riid ) ) { hr = m_realClass->CreateInstance( pUnkOuter, riid, ppvObj ); } } return hr; } STDMETHODIMP CPCHWrapProtocolInfo::LockServer( /*[in]*/ BOOL fLock ) { return m_realClass->LockServer( fLock ); }