753 lines
21 KiB
C++
753 lines
21 KiB
C++
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
//
|
||
|
// Copyright (C) Microsoft Corporation, 2000
|
||
|
//
|
||
|
// File: mmcprotocol.h
|
||
|
//
|
||
|
// Purpose: Creates a temporary pluggable internet protocol, mmc://
|
||
|
//
|
||
|
// History: 14-April-2000 Vivekj added
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#include<stdafx.h>
|
||
|
|
||
|
#include<mmcprotocol.h>
|
||
|
#include "tasks.h"
|
||
|
#include "typeinfo.h" // for COleCacheCleanupObserver
|
||
|
|
||
|
// {3C5F432A-EF40-4669-9974-9671D4FC2E12}
|
||
|
static const CLSID CLSID_MMCProtocol = { 0x3c5f432a, 0xef40, 0x4669, { 0x99, 0x74, 0x96, 0x71, 0xd4, 0xfc, 0x2e, 0x12 } };
|
||
|
static const WCHAR szMMC[] = _W(MMC_PROTOCOL_SCHEMA_NAME);
|
||
|
static const WCHAR szMMCC[] = _W(MMC_PROTOCOL_SCHEMA_NAME) _W(":");
|
||
|
static const WCHAR szPageBreak[] = _W(MMC_PAGEBREAK_RELATIVE_URL);
|
||
|
|
||
|
static const WCHAR szMMCRES[] = L"%mmcres%";
|
||
|
static const WCHAR chUNICODE = 0xfeff;
|
||
|
|
||
|
#ifdef DBG
|
||
|
CTraceTag tagProtocol(_T("MMC iNet Protocol"), _T("MMCProtocol"));
|
||
|
#endif //DBG
|
||
|
|
||
|
/***************************************************************************\
|
||
|
*
|
||
|
* FUNCTION: HasSchema
|
||
|
*
|
||
|
* PURPOSE: helper: determines if URL contains schema (like "something:" or "http:" )
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
* LPCWSTR strURL
|
||
|
*
|
||
|
* RETURNS:
|
||
|
* bool ; true == does contain schema
|
||
|
*
|
||
|
\***************************************************************************/
|
||
|
inline bool HasSchema(LPCWSTR strURL)
|
||
|
{
|
||
|
if (strURL == NULL)
|
||
|
return false;
|
||
|
|
||
|
// skip spaces and schema name
|
||
|
while ( iswspace(*strURL) || iswalnum(*strURL) )
|
||
|
strURL++;
|
||
|
|
||
|
// valid schema ends with ':'
|
||
|
return *strURL == L':';
|
||
|
}
|
||
|
|
||
|
/***************************************************************************\
|
||
|
*
|
||
|
* FUNCTION: HasMMCSchema
|
||
|
*
|
||
|
* PURPOSE: helper: determines if URL contains mmc schema ( begins with "mmc:" )
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
* LPCWSTR strURL
|
||
|
*
|
||
|
* RETURNS:
|
||
|
* bool ; true == does contain mmc schema
|
||
|
*
|
||
|
\***************************************************************************/
|
||
|
inline bool HasMMCSchema(LPCWSTR strURL)
|
||
|
{
|
||
|
if (strURL == NULL)
|
||
|
return false;
|
||
|
|
||
|
// skip spaces
|
||
|
while ( iswspace(*strURL) )
|
||
|
strURL++;
|
||
|
|
||
|
return (0 == _wcsnicmp( strURL, szMMCC, wcslen(szMMCC) ) );
|
||
|
}
|
||
|
|
||
|
/***************************************************************************\
|
||
|
*
|
||
|
* CLASS: CMMCProtocolRegistrar
|
||
|
*
|
||
|
* PURPOSE: register/ unregisters mmc protocol.
|
||
|
* Also class provides cleanup functionality. Because it registers as
|
||
|
* COleCacheCleanupObserver, it will receive the event when MMC
|
||
|
* is about to uninitialize OLE, and will revoke registered mmc protocol
|
||
|
*
|
||
|
\***************************************************************************/
|
||
|
class CMMCProtocolRegistrar : public COleCacheCleanupObserver
|
||
|
{
|
||
|
bool m_bRegistered;
|
||
|
IClassFactoryPtr m_spClassFactory;
|
||
|
public:
|
||
|
// c-tor.
|
||
|
CMMCProtocolRegistrar() : m_bRegistered(false) {}
|
||
|
|
||
|
// registration / unregistration
|
||
|
SC ScRegister();
|
||
|
SC ScUnregister();
|
||
|
|
||
|
// event sensor - unregisters mmc protocol
|
||
|
virtual SC ScOnReleaseCachedOleObjects()
|
||
|
{
|
||
|
DECLARE_SC(sc, TEXT("ScOnReleaseCachedOleObjects"));
|
||
|
|
||
|
return sc = ScUnregister();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/***************************************************************************\
|
||
|
*
|
||
|
* METHOD: CMMCProtocolRegistrar::ScRegister
|
||
|
*
|
||
|
* PURPOSE: registers the protocol if required
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
* RETURNS:
|
||
|
* SC - result code
|
||
|
*
|
||
|
\***************************************************************************/
|
||
|
SC CMMCProtocolRegistrar::ScRegister()
|
||
|
{
|
||
|
DECLARE_SC(sc, TEXT("CMMCProtocolRegistrar::ScRegister"));
|
||
|
|
||
|
// one time registration only
|
||
|
if(m_bRegistered)
|
||
|
return sc;
|
||
|
|
||
|
// get internet session
|
||
|
IInternetSessionPtr spInternetSession;
|
||
|
sc = CoInternetGetSession(0, &spInternetSession, 0);
|
||
|
if(sc)
|
||
|
return sc;
|
||
|
|
||
|
// doublecheck
|
||
|
sc = ScCheckPointers(spInternetSession, E_FAIL);
|
||
|
if(sc)
|
||
|
return sc;
|
||
|
|
||
|
// ask CComModule for the class factory
|
||
|
sc = _Module.GetClassObject(CLSID_MMCProtocol, IID_IClassFactory, (void **)&m_spClassFactory);
|
||
|
if(sc)
|
||
|
return sc;
|
||
|
|
||
|
// register the namespace
|
||
|
sc = spInternetSession->RegisterNameSpace(m_spClassFactory, CLSID_MMCProtocol, szMMC, 0, NULL, 0);
|
||
|
if(sc)
|
||
|
return sc;
|
||
|
|
||
|
// start observing cleanup requests - to unregister in time
|
||
|
COleCacheCleanupManager::AddOleObserver(this);
|
||
|
|
||
|
m_bRegistered = true; // did it.
|
||
|
return sc;
|
||
|
}
|
||
|
|
||
|
/***************************************************************************\
|
||
|
*
|
||
|
* METHOD: CMMCProtocolRegistrar::ScUnregister
|
||
|
*
|
||
|
* PURPOSE: unregisters the protocol if one was registered
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
* RETURNS:
|
||
|
* SC - result code
|
||
|
*
|
||
|
\***************************************************************************/
|
||
|
SC CMMCProtocolRegistrar::ScUnregister()
|
||
|
{
|
||
|
DECLARE_SC(sc, TEXT("CMMCProtocolRegistrar::ScUnregister"));
|
||
|
|
||
|
if (!m_bRegistered)
|
||
|
return sc;
|
||
|
|
||
|
// unregister
|
||
|
IInternetSessionPtr spInternetSession;
|
||
|
sc = CoInternetGetSession(0, &spInternetSession, 0);
|
||
|
if(sc)
|
||
|
{
|
||
|
sc.Clear(); // no session - no headache
|
||
|
}
|
||
|
else // need to unregister
|
||
|
{
|
||
|
// recheck
|
||
|
sc = ScCheckPointers(spInternetSession, E_UNEXPECTED);
|
||
|
if(sc)
|
||
|
return sc;
|
||
|
|
||
|
// unregister the namespace
|
||
|
sc = spInternetSession->UnregisterNameSpace(m_spClassFactory, szMMC);
|
||
|
if(sc)
|
||
|
return sc;
|
||
|
}
|
||
|
|
||
|
m_spClassFactory.Release();
|
||
|
m_bRegistered = false;
|
||
|
|
||
|
return sc;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/***************************************************************************\
|
||
|
*
|
||
|
* METHOD: CMMCProtocol::ScRegisterProtocol
|
||
|
*
|
||
|
* PURPOSE: Registers mmc protocol. IE will resove "mmc:..." ULRs to it
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
* RETURNS:
|
||
|
* SC - result code
|
||
|
*
|
||
|
\***************************************************************************/
|
||
|
SC
|
||
|
CMMCProtocol::ScRegisterProtocol()
|
||
|
{
|
||
|
DECLARE_SC(sc, TEXT("CMMCProtocol::ScRegisterProtocol"));
|
||
|
|
||
|
// registrar (unregisters on cleanup event) - needs to be static
|
||
|
static CMMCProtocolRegistrar registrar;
|
||
|
|
||
|
// let the registrar do the job
|
||
|
return sc = registrar.ScRegister();
|
||
|
}
|
||
|
|
||
|
//*****************************************************************************
|
||
|
// IInternetProtocolRoot interface
|
||
|
//*****************************************************************************
|
||
|
|
||
|
/***************************************************************************\
|
||
|
*
|
||
|
* METHOD: CMMCProtocol::Start
|
||
|
*
|
||
|
* PURPOSE: Starts data download thru this protocol
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
* LPCWSTR szUrl
|
||
|
* IInternetProtocolSink *pOIProtSink
|
||
|
* IInternetBindInfo *pOIBindInfo
|
||
|
* DWORD grfPI
|
||
|
* HANDLE_PTR dwReserved
|
||
|
*
|
||
|
* RETURNS:
|
||
|
* SC - result code
|
||
|
*
|
||
|
\***************************************************************************/
|
||
|
STDMETHODIMP
|
||
|
CMMCProtocol::Start(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved)
|
||
|
{
|
||
|
DECLARE_SC(sc, TEXT("CMMCProtocol::Start"));
|
||
|
|
||
|
// check inputs
|
||
|
sc = ScCheckPointers(szUrl, pOIProtSink, pOIBindInfo);
|
||
|
if(sc)
|
||
|
return sc.ToHr();
|
||
|
|
||
|
// reset position for reading
|
||
|
m_uiReadOffs = 0;
|
||
|
|
||
|
bool bPageBreakRequest = false;
|
||
|
|
||
|
// see if it was a pagebreak requested
|
||
|
sc = ScParsePageBreakURL( szUrl, bPageBreakRequest );
|
||
|
if(sc)
|
||
|
return sc.ToHr();
|
||
|
|
||
|
if ( bPageBreakRequest )
|
||
|
{
|
||
|
// just report success (S_OK/S_FALSE) in case we were just parsing
|
||
|
if ( grfPI & PI_PARSE_URL )
|
||
|
return sc.ToHr();
|
||
|
|
||
|
// construct a pagebreak
|
||
|
m_strData = L"<HTML/>";
|
||
|
|
||
|
sc = pOIProtSink->ReportProgress(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE, L"text/html");
|
||
|
if (sc)
|
||
|
sc.TraceAndClear(); // ignore and continue
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//if not a pagebreak - then taskpad
|
||
|
GUID guidTaskpad = GUID_NULL;
|
||
|
sc = ScParseTaskpadURL( szUrl, guidTaskpad );
|
||
|
if(sc)
|
||
|
return sc.ToHr();
|
||
|
|
||
|
// report the S_FALSE instead of error in case we were just parsing
|
||
|
if ( grfPI & PI_PARSE_URL )
|
||
|
return ( sc.IsError() ? (sc = S_FALSE) : sc ).ToHr();
|
||
|
|
||
|
if (sc)
|
||
|
return sc.ToHr();
|
||
|
|
||
|
// load the contents
|
||
|
sc = ScGetTaskpadXML( guidTaskpad, m_strData );
|
||
|
if (sc)
|
||
|
return sc.ToHr();
|
||
|
|
||
|
sc = pOIProtSink->ReportProgress(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE, L"text/html");
|
||
|
if (sc)
|
||
|
sc.TraceAndClear(); // ignore and continue
|
||
|
}
|
||
|
|
||
|
const DWORD grfBSCF = BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE;
|
||
|
const DWORD dwDataSize = m_strData.length() * sizeof (WCHAR);
|
||
|
sc = pOIProtSink->ReportData(grfBSCF, dwDataSize , dwDataSize);
|
||
|
if (sc)
|
||
|
sc.TraceAndClear(); // ignore and continue
|
||
|
|
||
|
sc = pOIProtSink->ReportResult(0, 0, 0);
|
||
|
if (sc)
|
||
|
sc.TraceAndClear(); // ignore and continue
|
||
|
|
||
|
return sc.ToHr();
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CMMCProtocol::Continue(PROTOCOLDATA *pProtocolData) { return E_NOTIMPL; }
|
||
|
STDMETHODIMP CMMCProtocol::Abort(HRESULT hrReason, DWORD dwOptions) { return S_OK; }
|
||
|
STDMETHODIMP CMMCProtocol::Terminate(DWORD dwOptions) { return S_OK; }
|
||
|
STDMETHODIMP CMMCProtocol::LockRequest(DWORD dwOptions) { return S_OK; }
|
||
|
STDMETHODIMP CMMCProtocol::UnlockRequest() { return S_OK; }
|
||
|
STDMETHODIMP CMMCProtocol::Suspend() { return E_NOTIMPL; }
|
||
|
STDMETHODIMP CMMCProtocol::Resume() { return E_NOTIMPL; }
|
||
|
|
||
|
STDMETHODIMP CMMCProtocol::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
|
||
|
{
|
||
|
return E_NOTIMPL;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//*****************************************************************************
|
||
|
// IInternetProtocol interface
|
||
|
//*****************************************************************************
|
||
|
|
||
|
/***************************************************************************\
|
||
|
*
|
||
|
* METHOD: CMMCProtocol::Read
|
||
|
*
|
||
|
* PURPOSE: Reads data from the protocol
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
* void *pv
|
||
|
* ULONG cb
|
||
|
* ULONG *pcbRead
|
||
|
*
|
||
|
* RETURNS:
|
||
|
* SC - result code
|
||
|
*
|
||
|
\***************************************************************************/
|
||
|
STDMETHODIMP CMMCProtocol::Read(void *pv, ULONG cb, ULONG *pcbRead)
|
||
|
{
|
||
|
DECLARE_SC(sc, TEXT("CMMCProtocol::Read"));
|
||
|
|
||
|
// parameter check;
|
||
|
sc = ScCheckPointers(pv, pcbRead);
|
||
|
if(sc)
|
||
|
return sc.ToHr();
|
||
|
|
||
|
// init out parameter;
|
||
|
*pcbRead = 0;
|
||
|
|
||
|
size_t size = ( m_strData.length() ) * sizeof(WCHAR);
|
||
|
|
||
|
if ( size <= m_uiReadOffs )
|
||
|
return (sc = S_FALSE).ToHr(); // no more data
|
||
|
|
||
|
// calculate the size we'll return
|
||
|
*pcbRead = size - m_uiReadOffs;
|
||
|
if (size - m_uiReadOffs > cb)
|
||
|
*pcbRead = cb;
|
||
|
|
||
|
if (*pcbRead)
|
||
|
memcpy( pv, reinterpret_cast<const BYTE*>( m_strData.begin() ) + m_uiReadOffs, *pcbRead );
|
||
|
|
||
|
m_uiReadOffs += *pcbRead;
|
||
|
|
||
|
if ( size <= m_uiReadOffs )
|
||
|
return (sc = S_FALSE).ToHr(); // no more data
|
||
|
|
||
|
return sc.ToHr();
|
||
|
}
|
||
|
|
||
|
//*****************************************************************************
|
||
|
// IInternetProtocolInfo interface
|
||
|
//*****************************************************************************
|
||
|
|
||
|
STDMETHODIMP
|
||
|
CMMCProtocol::ParseUrl( LPCWSTR pwzUrl, PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved)
|
||
|
{
|
||
|
DECLARE_SC(sc, TEXT("CMMCProtocol::ParseUrl"));
|
||
|
|
||
|
if (ParseAction == PARSE_SECURITY_URL)
|
||
|
{
|
||
|
// get system directory (like "c:\winnt\system32\")
|
||
|
std::wstring windir;
|
||
|
AppendMMCPath(windir);
|
||
|
windir += L'\\';
|
||
|
|
||
|
// we are as secure as windir is - report the url (like "c:\winnt\system32\")
|
||
|
*pcchResult = windir.length() + 1;
|
||
|
|
||
|
// check if we have enough place for the result and terminating zero
|
||
|
if ( cchResult <= windir.length() )
|
||
|
return S_FALSE; // not enough
|
||
|
|
||
|
wcscpy(pwzResult, windir.c_str());
|
||
|
return (sc = S_OK).ToHr();
|
||
|
}
|
||
|
|
||
|
return INET_E_DEFAULT_ACTION;
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************\
|
||
|
*
|
||
|
* METHOD: CMMCProtocol::CombineUrl
|
||
|
*
|
||
|
* PURPOSE: combines base + relative url to resulting url
|
||
|
* we do local variable substitution here
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
* LPCWSTR pwzBaseUrl
|
||
|
* LPCWSTR pwzRelativeUrl
|
||
|
* DWORD dwCombineFlags
|
||
|
* LPWSTR pwzResult
|
||
|
* DWORD cchResult
|
||
|
* DWORD *pcchResult
|
||
|
* DWORD dwReserved
|
||
|
*
|
||
|
* RETURNS:
|
||
|
* SC - result code
|
||
|
*
|
||
|
\***************************************************************************/
|
||
|
STDMETHODIMP CMMCProtocol::CombineUrl(LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags, LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved)
|
||
|
{
|
||
|
DECLARE_SC(sc, TEXT("CMMCProtocol::CombineUrl"));
|
||
|
|
||
|
#ifdef DBG
|
||
|
USES_CONVERSION;
|
||
|
Trace(tagProtocol, _T("CombineUrl: [%s] + [%s]"), W2CT(pwzBaseUrl), W2CT(pwzRelativeUrl));
|
||
|
#endif //DBG
|
||
|
|
||
|
std::wstring temp1;
|
||
|
if (HasMMCSchema(pwzBaseUrl))
|
||
|
{
|
||
|
// our stuff
|
||
|
|
||
|
temp1 = pwzRelativeUrl;
|
||
|
ExpandMMCVars(temp1);
|
||
|
|
||
|
if ( ! HasSchema( temp1.c_str() ) )
|
||
|
{
|
||
|
// combine everything into relative URL
|
||
|
temp1.insert( 0, pwzBaseUrl );
|
||
|
}
|
||
|
|
||
|
// form 'new' relative address
|
||
|
pwzRelativeUrl = temp1.c_str();
|
||
|
|
||
|
// say we are refered from http - let it do the dirty job ;)
|
||
|
pwzBaseUrl = L"http://";
|
||
|
}
|
||
|
|
||
|
// since we stripped out ourselfs from pwzBaseUrl - it will not recurse back,
|
||
|
// but will do original html stuff
|
||
|
sc = CoInternetCombineUrl( pwzBaseUrl, pwzRelativeUrl, dwCombineFlags, pwzResult, cchResult, pcchResult, dwReserved );
|
||
|
if (sc)
|
||
|
return sc.ToHr();
|
||
|
|
||
|
Trace(tagProtocol, _T("CombineUrl: == [%s]"), W2CT(pwzResult));
|
||
|
|
||
|
return sc.ToHr();
|
||
|
}
|
||
|
|
||
|
/***************************************************************************\
|
||
|
*
|
||
|
* METHOD: CMMCProtocol::CompareUrl
|
||
|
*
|
||
|
* PURPOSE: compares URLs if they are the same
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
* LPCWSTR pwzUrl1
|
||
|
* LPCWSTR pwzUrl2
|
||
|
* DWORD dwCompareFlags
|
||
|
*
|
||
|
* RETURNS:
|
||
|
* SC - result code
|
||
|
*
|
||
|
\***************************************************************************/
|
||
|
STDMETHODIMP CMMCProtocol::CompareUrl(LPCWSTR pwzUrl1, LPCWSTR pwzUrl2,DWORD dwCompareFlags)
|
||
|
{
|
||
|
DECLARE_SC(sc, TEXT("CMMCProtocol::CompareUrl"));
|
||
|
|
||
|
return INET_E_DEFAULT_ACTION;
|
||
|
}
|
||
|
|
||
|
/***************************************************************************\
|
||
|
*
|
||
|
* METHOD: CMMCProtocol::QueryInfo
|
||
|
*
|
||
|
* PURPOSE: Queries info about URL
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
* LPCWSTR pwzUrl
|
||
|
* QUERYOPTION QueryOption
|
||
|
* DWORD dwQueryFlags
|
||
|
* LPVOID pBuffer
|
||
|
* DWORD cbBuffer
|
||
|
* DWORD *pcbBuf
|
||
|
* DWORD dwReserved
|
||
|
*
|
||
|
* RETURNS:
|
||
|
* SC - result code
|
||
|
*
|
||
|
\***************************************************************************/
|
||
|
STDMETHODIMP CMMCProtocol::QueryInfo( LPCWSTR pwzUrl, QUERYOPTION QueryOption,DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD *pcbBuf, DWORD dwReserved)
|
||
|
{
|
||
|
DECLARE_SC(sc, TEXT("CMMCProtocol::QueryInfo"));
|
||
|
|
||
|
if (QueryOption == QUERY_USES_NETWORK)
|
||
|
{
|
||
|
if (cbBuffer >= 4)
|
||
|
{
|
||
|
*(LPDWORD)pBuffer = FALSE; // does not use the network
|
||
|
*pcbBuf = 4;
|
||
|
return S_OK;
|
||
|
}
|
||
|
}
|
||
|
else if (QueryOption == QUERY_IS_SAFE)
|
||
|
{
|
||
|
if (cbBuffer >= 4)
|
||
|
{
|
||
|
*(LPDWORD)pBuffer = TRUE; // only serves trusted content
|
||
|
*pcbBuf = 4;
|
||
|
return S_OK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
return INET_E_DEFAULT_ACTION;
|
||
|
}
|
||
|
|
||
|
/***************************************************************************\
|
||
|
*
|
||
|
* METHOD: CMMCProtocol::ScParseTaskpadURL
|
||
|
*
|
||
|
* PURPOSE: Extracts taskpad guid from URL given to the protocol
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
* LPCWSTR strURL [in] - URL
|
||
|
* GUID& guid [out] - extracted guid
|
||
|
*
|
||
|
* RETURNS:
|
||
|
* SC - result code
|
||
|
*
|
||
|
\***************************************************************************/
|
||
|
SC CMMCProtocol::ScParseTaskpadURL( LPCWSTR strURL, GUID& guid )
|
||
|
{
|
||
|
DECLARE_SC(sc, TEXT("CMMCProtocol::ScParseTaskpadURL"));
|
||
|
|
||
|
guid = GUID_NULL;
|
||
|
|
||
|
sc = ScCheckPointers(strURL);
|
||
|
if (sc)
|
||
|
return sc;
|
||
|
|
||
|
// taskpad url should be in form "mmc:{guid}"
|
||
|
|
||
|
// check for "mmc:"
|
||
|
if ( 0 != _wcsnicmp( strURL, szMMCC, wcslen(szMMCC) ) )
|
||
|
return sc = E_FAIL;
|
||
|
|
||
|
// skip "mmc:"
|
||
|
strURL += wcslen(szMMCC);
|
||
|
|
||
|
// get the url
|
||
|
sc = CLSIDFromString( const_cast<LPWSTR>(strURL), &guid );
|
||
|
if (sc)
|
||
|
return sc;
|
||
|
|
||
|
return sc;
|
||
|
}
|
||
|
|
||
|
/***************************************************************************\
|
||
|
*
|
||
|
* METHOD: CMMCProtocol::ScParsePageBreakURL
|
||
|
*
|
||
|
* PURPOSE: Checks if URL given to the protocol is a request for a pagebreak
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
* LPCWSTR strURL [in] - URL
|
||
|
* bool& bPageBreak [out] - true it it is a request for pagebreak
|
||
|
*
|
||
|
* RETURNS:
|
||
|
* SC - result code
|
||
|
*
|
||
|
\***************************************************************************/
|
||
|
SC CMMCProtocol::ScParsePageBreakURL( LPCWSTR strURL, bool& bPageBreak )
|
||
|
{
|
||
|
DECLARE_SC(sc, TEXT("CMMCProtocol::ScParsePageBreakURL"));
|
||
|
|
||
|
bPageBreak = false;
|
||
|
|
||
|
sc = ScCheckPointers(strURL);
|
||
|
if (sc)
|
||
|
return sc;
|
||
|
|
||
|
// pagebreak url should be in form "mmc:pagebreak.<number>"
|
||
|
|
||
|
// check for "mmc:"
|
||
|
if ( 0 != _wcsnicmp( strURL, szMMCC, wcslen(szMMCC) ) )
|
||
|
return sc; // not an error - return value updated
|
||
|
|
||
|
// skip "mmc:"
|
||
|
strURL += wcslen(szMMCC);
|
||
|
|
||
|
// get the url
|
||
|
bPageBreak = ( 0 == wcsncmp( strURL, szPageBreak, wcslen(szPageBreak) ) );
|
||
|
|
||
|
return sc;
|
||
|
}
|
||
|
|
||
|
/***************************************************************************\
|
||
|
*
|
||
|
* METHOD: CMMCProtocol::ScGetTaskpadXML
|
||
|
*
|
||
|
* PURPOSE: given the guid uploads taskpad XML string to the string
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
* const GUID& guid [in] - taskpad guid
|
||
|
* std::wstring& strResultData [out] - taskpad xml string
|
||
|
*
|
||
|
* RETURNS:
|
||
|
* SC - result code
|
||
|
*
|
||
|
\***************************************************************************/
|
||
|
SC CMMCProtocol::ScGetTaskpadXML( const GUID& guid, std::wstring& strResultData )
|
||
|
{
|
||
|
DECLARE_SC(sc, TEXT("CMMCProtocol::ScGetTaskpadXML"));
|
||
|
|
||
|
strResultData.erase();
|
||
|
|
||
|
CScopeTree* pScopeTree = CScopeTree::GetScopeTree();
|
||
|
|
||
|
sc = ScCheckPointers(pScopeTree, E_FAIL);
|
||
|
if(sc)
|
||
|
return sc.ToHr();
|
||
|
|
||
|
CConsoleTaskpadList * pConsoleTaskpadList = pScopeTree->GetConsoleTaskpadList();
|
||
|
sc = ScCheckPointers(pConsoleTaskpadList, E_FAIL);
|
||
|
if(sc)
|
||
|
return sc.ToHr();
|
||
|
|
||
|
for(CConsoleTaskpadList::iterator iter = pConsoleTaskpadList->begin(); iter!= pConsoleTaskpadList->end(); ++iter)
|
||
|
{
|
||
|
CConsoleTaskpad &consoleTaskpad = *iter;
|
||
|
|
||
|
// check if this is the one we are looking for
|
||
|
if ( !IsEqualGUID( guid, consoleTaskpad.GetID() ) )
|
||
|
continue;
|
||
|
|
||
|
// convert the taskpad to a string
|
||
|
CStr strTaskpadHTML;
|
||
|
sc = consoleTaskpad.ScGetHTML(strTaskpadHTML); // create a string version of the taskpad
|
||
|
if(sc)
|
||
|
return sc.ToHr();
|
||
|
|
||
|
// form the result string
|
||
|
USES_CONVERSION;
|
||
|
strResultData = chUNICODE;
|
||
|
strResultData += T2CW(strTaskpadHTML);
|
||
|
|
||
|
return sc;
|
||
|
}
|
||
|
|
||
|
// not found
|
||
|
return sc = E_FAIL;
|
||
|
}
|
||
|
|
||
|
/***************************************************************************\
|
||
|
*
|
||
|
* METHOD: CMMCProtocol::AppendMMCPath
|
||
|
*
|
||
|
* PURPOSE: helper. Appends the mmcndmgr.dll dir (no file name) to the string
|
||
|
* It may append something like: "c:\winnt\system32"
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
* std::wstring& str [in/out] - string to edit
|
||
|
*
|
||
|
* RETURNS:
|
||
|
* SC - result code
|
||
|
*
|
||
|
\***************************************************************************/
|
||
|
void CMMCProtocol::AppendMMCPath(std::wstring& str)
|
||
|
{
|
||
|
TCHAR szModule[_MAX_PATH+10] = { 0 };
|
||
|
GetModuleFileName(_Module.GetModuleInstance(), szModule, _MAX_PATH);
|
||
|
|
||
|
USES_CONVERSION;
|
||
|
LPCWSTR strModule = T2CW(szModule);
|
||
|
|
||
|
LPCWSTR dirEnd = wcsrchr( strModule, L'\\' );
|
||
|
if (dirEnd != NULL)
|
||
|
str.append(strModule, dirEnd);
|
||
|
}
|
||
|
|
||
|
/***************************************************************************\
|
||
|
*
|
||
|
* METHOD: CMMCProtocol::ExpandMMCVars
|
||
|
*
|
||
|
* PURPOSE: helper. expands any %mmcres% contained in the string
|
||
|
* It expands it to something like "res://c:\winnt\system32\mmcndmgr.dll"
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
* std::wstring& str [in/out] - string to edit
|
||
|
*
|
||
|
* RETURNS:
|
||
|
* SC - result code
|
||
|
*
|
||
|
\***************************************************************************/
|
||
|
void CMMCProtocol::ExpandMMCVars(std::wstring& str)
|
||
|
{
|
||
|
// first - form the values
|
||
|
TCHAR szModule[_MAX_PATH+10] = { 0 };
|
||
|
GetModuleFileName(_Module.GetModuleInstance(), szModule, _MAX_PATH);
|
||
|
|
||
|
USES_CONVERSION;
|
||
|
LPCWSTR strModule = T2CW(szModule);
|
||
|
|
||
|
std::wstring mmcres = L"res://";
|
||
|
mmcres += strModule;
|
||
|
|
||
|
// second - replace the instances
|
||
|
|
||
|
int pos;
|
||
|
while (std::wstring::npos != (pos = str.find(szMMCRES) ) )
|
||
|
{
|
||
|
// make one substitution
|
||
|
str.replace( pos, wcslen(szMMCRES), mmcres) ;
|
||
|
}
|
||
|
}
|
||
|
|