⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chmprotocol.cpp

📁 evc浏览器编程示例
💻 CPP
字号:
// CHMProtocol.cpp: implementation of the CCHMProtocolCF class and CCHMProtocol class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include <windows.h>
#include <shlwapi.h>
#include "CHMProtocol.h"
#define INITGUID
#include "initguid.h"
#include "debug.h"

// {31B96E65-8388-470b-801F-06D5884CAF34}
DEFINE_GUID(CLSID_CHMProtocol, 0x31b96e65, 0x8388, 0x470b, 0x80, 0x1f, 0x6, 0xd5, 0x88, 0x4c, 0xaf, 0x34);

// Utility: Swap two interfaces
void ReplaceInterfaceFn(IUnknown ** ppUnk, IUnknown * pUnk)
{
    IUnknown * pUnkOld = *ppUnk;

    *ppUnk = pUnk;

    //  Note that we do AddRef before Release; this avoids
    //    accidentally destroying an object if this function
    //    is passed two aliases to it

    if (pUnk)
        pUnk->AddRef();

    if (pUnkOld)
        pUnkOld->Release();
}

//+----------------------------------------------------------------------------
//
//  Construction
//
//-----------------------------------------------------------------------------
CCHMProtocolCF::CCHMProtocolCF(pfnCallbackFunction pfncallback, void *pContext) 
{
	_cRefs = 1; 
	m_pfnCallBack = pfncallback;
	m_pCallBackContext = pContext;
}

//+----------------------------------------------------------------------------
//
//  IUnknown
//
//-----------------------------------------------------------------------------
STDMETHODIMP_(ULONG)
CCHMProtocolCF::AddRef()
{
	return(++_cRefs);
}

STDMETHODIMP_(ULONG)
CCHMProtocolCF::Release()
{
	--_cRefs;
	if (_cRefs == 0)
	{
		delete this;
		return 0;
	}
	return _cRefs;
}

STDMETHODIMP
CCHMProtocolCF::QueryInterface(REFIID riid, void ** ppv)
{
	if(riid == IID_IClassFactory)
	{
		*ppv = static_cast<IClassFactory*>(this);
	}
	else if(riid == IID_IInternetProtocolInfo)
	{
		*ppv = static_cast<IInternetProtocolInfo*>(this);
		RETAILMSG(1, (_T("%s:line:%d:CCHMProtocolCF:QueryInterface:IID_IInternetProtocolInfo\r\n"),TEXT(__FILE__), __LINE__));
	}
	else
	{
		RETAILMSG(1, (_T("%s:line:%d:CCHMProtocolCF:QueryInterface unsupport:%s\r\n"),TEXT(__FILE__), __LINE__,riid));
		*ppv = NULL;
		return(E_NOINTERFACE);
	}
	reinterpret_cast<IUnknown*>(*ppv)->AddRef();
	return(S_OK);
}


HRESULT CCHMProtocolCF::CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppv)
{
	*ppv = NULL;
	HRESULT hres = E_NOINTERFACE;
    
	if (punkOuter)
	{
		return CLASS_E_NOAGGREGATION;
	}
	else if(riid == IID_IOInetProtocol)
	{
        
		CCHMProtocol * pHelpProtocol = new CCHMProtocol(this, m_pfnCallBack, m_pCallBackContext);
		if(pHelpProtocol)
		{
            
			hres = pHelpProtocol->QueryInterface(IID_IInternetProtocol, ppv);
			pHelpProtocol->Release();
		}
	}   
	return hres;
}

HRESULT CCHMProtocolCF::LockServer(BOOL fLock)
{
	// this is implemented out of the help app, the server will go away when the app does
	return S_OK;
}

HRESULT CCHMProtocolCF::ParseUrl(LPCWSTR     pwzUrl,
                          PARSEACTION ParseAction,
                          DWORD       dwFlags,
                          LPWSTR      pwzResult,
                          DWORD       cchResult,
                          DWORD *     pcchResult,
                          DWORD       dwReserved)
{
	WCHAR *szSpecial;
	HRESULT hr = INET_E_DEFAULT_ACTION;

	if (!pcchResult || !pwzResult)
	{
		hr = E_POINTER;
	}
	else
	{
		WCHAR *szURL = new WCHAR[MAX_URL];
		if(!szURL)
			return FALSE;
		
		szURL[0] = L'\0';

		wcscpy(szURL,_T("file:"));
		szSpecial = _tcschr(pwzUrl, ':');
		if(szSpecial)
		{
			szSpecial += 1;
		}
		else
		{
			szSpecial = (WCHAR *)pwzUrl;
		}
		wcscat(szURL, szSpecial);
		wcscpy(pwzResult, szURL);

		hr = S_OK;
	}
	hr = S_OK;
	/*
	if(m_pfnCallBack && m_pCallBackContext)
	{
		m_pfnCallBack(m_pCallBackContext, (void *)pwzUrl , 0);
	}
	*/
	return hr;
}

HRESULT CCHMProtocolCF::CombineUrl(LPCWSTR     pwzBaseUrl,
                            LPCWSTR     pwzRelativeUrl,
                            DWORD       dwFlags,
                            LPWSTR      pwzResult,
                            DWORD       cchResult,
                            DWORD *     pcchResult,
                            DWORD       dwReserved)
{
	return INET_E_DEFAULT_ACTION;
}

HRESULT CCHMProtocolCF::CompareUrl(LPCWSTR     pwzUrl1,
                            LPCWSTR     pwzUrl2,
                            DWORD       dwFlags)
{
	return (E_NOTIMPL);
}

HRESULT CCHMProtocolCF::QueryInfo(LPCWSTR         pwzUrl,
                           QUERYOPTION     QueryOption,
                           DWORD           dwQueryFlags,
                           LPVOID          pBuffer,
                           DWORD           cbBuffer,
                           DWORD *         pcbBuf,
                           DWORD           dwReserved)
{
	HRESULT     hr = INET_E_DEFAULT_ACTION;
	DWORD       dwRetval;

	switch (QueryOption)
	{
		case QUERY_USES_NETWORK:
		case QUERY_IS_CACHED:
			dwRetval = FALSE;
			goto ReturnDword;
		case QUERY_IS_SECURE:
			dwRetval = TRUE;
			goto ReturnDword;
		default:
			hr = INET_E_DEFAULT_ACTION;
			break;
        }
Cleanup:
	return hr;
    
ReturnDword:
	if (!pBuffer || cbBuffer < sizeof(DWORD))
	{
		hr = E_FAIL;
		goto Cleanup;
	}

	if (pcbBuf)
	{
		*pcbBuf = sizeof(DWORD);
	}
    
	*(DWORD *)pBuffer = dwRetval;
	hr = S_OK;
	goto Cleanup;
}

CCHMProtocol::CCHMProtocol(CCHMProtocolCF *pOwner, pfnCallbackFunction pfncallback, void *pContext)
{
	_cRefs = 1;
	m_file = NULL;
	m_pOwnerCF = pOwner;
	m_pfnCallBack = pfncallback;
	m_pCallBackContext = pContext;
	if(m_pOwnerCF)
		m_pOwnerCF->AddRef();	
}


CCHMProtocol::~CCHMProtocol()
{
	if(m_pOwnerCF)
		m_pOwnerCF->Release();
}

//+----------------------------------------------------------------------------
//
//  IUnknown
//
//-----------------------------------------------------------------------------
STDMETHODIMP_(ULONG)
CCHMProtocol::AddRef()
{
	return(++_cRefs);
}

STDMETHODIMP_(ULONG)
CCHMProtocol::Release()
{
	--_cRefs;
	if (_cRefs == 0)
	{
		if(m_file)
		{
			CloseHandle(m_file);
			m_file = NULL;
			RETAILMSG(1, (_T("CCHMProtocol::Release:close file ok!\r\n")));
		}
		delete this;
		return 0;
	}
	return _cRefs;
}

STDMETHODIMP
CCHMProtocol::QueryInterface(REFIID riid, void ** ppv)
{
	if(riid == IID_IInternetProtocol || riid == IID_IInternetProtocolRoot)
	{
		*ppv = static_cast<IInternetProtocol*>(this);
		RETAILMSG(1, (_T("%s:line:%d:CHelpProtocol:QueryInterface IID_IInternetProtocol or IID_IInternetProtocolRoot\r\n"), TEXT(__FILE__), __LINE__));
	}
	else if(riid == IID_IInternetPriority)
	{
		*ppv = static_cast<IInternetPriority*>(this);
		RETAILMSG(1, (_T("%s:line:%d:CHelpProtocol:QueryInterface IID_IInternetPriority\r\n"), TEXT(__FILE__), __LINE__));
	}
	else
	{
		*ppv = NULL;
		RETAILMSG(1, (_T("%s:line:%d:CHelpProtocol:QueryInterface unsupport:%s\r\n"), TEXT(__FILE__), __LINE__,riid));
		return(E_NOINTERFACE);
	}
	reinterpret_cast<IUnknown*>(*ppv)->AddRef();
	return(S_OK);
}
HRESULT 
CCHMProtocol::SetPriority(LONG nPriority)
{
	RETAILMSG(1, (_T("%s:line:%d:CHelpProtocol:SetPriority:%d\r\n"),TEXT(__FILE__), __LINE__, nPriority));
	m_priority = nPriority;
	return S_OK;
};
HRESULT 
CCHMProtocol::GetPriority(LONG __RPC_FAR *pnPriority)
{
	*pnPriority = m_priority;
	RETAILMSG(1, (_T("%s:line:%d:CHelpProtocol:GetPriority:%d\r\n"),TEXT(__FILE__), __LINE__, m_priority));
	return S_OK;
}
HRESULT
CCHMProtocol::Start(
    LPCWSTR pchUrl, 
    IInternetProtocolSink *pTrans, 
    IInternetBindInfo *pOIBindInfo,
    DWORD grfSTI, 
    HANDLE_PTR dwReserved)
{
	HRESULT         hr = S_OK;
	static const WCHAR wszFile[]  = {'f','i','l','e',':'};
	DWORD dwlen = 0;
	DWORD dwSize = 0;
	DWORD grfBINDF = 0;
	BINDINFO bindinfo;
	LPWSTR szurl = NULL;
	LPWSTR szmime = NULL;
	LPWSTR ppwcsfilename;
	WCHAR null_char = 0;
	BOOL first_call = FALSE;
	
	ASSERT(pOIBindInfo && pTrans);
	memset(&bindinfo, 0, sizeof(bindinfo));
	bindinfo.cbSize = sizeof(BINDINFO);
	hr = pOIBindInfo->GetBindInfo(&grfBINDF, &bindinfo);
	if(FAILED(hr))
	{
		goto Cleanup;
	}

	if(lstrlenW(pchUrl) < sizeof(wszFile)/sizeof(WCHAR)|| memcmp(pchUrl, wszFile, sizeof(wszFile)))
	{
		return MK_E_SYNTAX;
	}
	
	szurl = new WCHAR[MAX_URL];
	if(!szurl)
	{
		hr = E_OUTOFMEMORY;
		goto Cleanup;
	}

	//
	// First get the basic url.  Unescape it first.
	//

	hr = CoInternetParseUrl(pchUrl, PARSE_ENCODE, 0, szurl, MAX_URL, &dwlen, 0);
	if (FAILED(hr))
	{
		goto Cleanup;
	}

	if(!m_file)
	{
		first_call = TRUE;
		pTrans->ReportProgress(BINDSTATUS_SENDINGREQUEST, &null_char);
		if(m_pfnCallBack && m_pCallBackContext)
		{
			ppwcsfilename = szurl+ sizeof(wszFile)/sizeof(WCHAR);
			m_pfnCallBack(m_pCallBackContext, (void *)ppwcsfilename, 0);
			if(ppwcsfilename != NULL && wcslen(ppwcsfilename) > 0)
			{
				m_file = CreateFile(ppwcsfilename, 
					GENERIC_READ, 
					0,
					NULL, 
					OPEN_EXISTING, 
					FILE_ATTRIBUTE_NORMAL, 
					NULL);
				if(m_file == INVALID_HANDLE_VALUE) 
				{
					m_file = NULL;
					pTrans->ReportResult(INET_E_RESOURCE_NOT_FOUND, GetLastError(), NULL);
					hr = INET_E_RESOURCE_NOT_FOUND;
					RETAILMSG(1, (_T("CCHMProtocol::Start:Open file error:%s\r\n"), ppwcsfilename));
					goto Cleanup;
				}
				RETAILMSG(1, (_T("CCHMProtocol::Start:Open file ok:%s\r\n"), ppwcsfilename));
				pTrans->ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE, ppwcsfilename);
				hr = FindMimeFromData(NULL, szurl, NULL, 0, NULL, 0, &szmime, 0);
				if(SUCCEEDED(hr) && szmime)
				{
					pTrans->ReportProgress((grfBINDF & BINDF_FROMURLMON) ?
						BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE : BINDSTATUS_MIMETYPEAVAILABLE, szmime);
				}			
				
				dwSize = GetFileSize(m_file, NULL);
				if(dwSize != 0xFFFFFFFF)
				{
					pTrans->ReportData(BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE, 
						(ULONG)dwSize,(ULONG)dwSize);
					RETAILMSG(1, (_T("CCHMProtocol::Start:file size:%d\r\n"), dwSize));
				}
			}
		}		
	}

	if(first_call)
	{
		pTrans->ReportResult(S_OK, 0, NULL);
	}

	hr = S_OK;
Cleanup:
	delete[] szurl;
	return (hr);
}


HRESULT
CCHMProtocol::Continue(PROTOCOLDATA *pStateInfoIn)
{
	RETAILMSG(1, (_T("CCHMProtocol::Continue\r\n")));	
	return E_NOTIMPL;
}

HRESULT
CCHMProtocol::Abort(HRESULT hrReason, DWORD dwOptions)
{
	RETAILMSG(1, (_T("CCHMProtocol::Abort\r\n")));	
	return E_NOTIMPL;
}

HRESULT
CCHMProtocol::Terminate(DWORD dwOptions)
{
	RETAILMSG(1, (_T("CCHMProtocol::Terminate\r\n")));
	return S_OK;	
}

HRESULT
CCHMProtocol::Suspend()
{
	RETAILMSG(1, (_T("CCHMProtocol::Suspend\r\n")));
	return (E_NOTIMPL);
}


HRESULT
CCHMProtocol::Resume()
{
	RETAILMSG(1, (_T("CCHMProtocol::Resume\r\n")));
	return (E_NOTIMPL);
}

HRESULT
CCHMProtocol::Read(void *pv,ULONG cb,ULONG *pcbRead)
{
	DWORD dwReadCnt = 0;
	HRESULT hr = S_FALSE;
	if(!m_file)
	{
		return INET_E_DATA_NOT_AVAILABLE;
	}
	ReadFile(m_file, pv, cb, &dwReadCnt, NULL);

	if(pcbRead)
	{
		*pcbRead = dwReadCnt;	
	}

	//if(cb != dwReadCnt)
	//{
		//SetFilePointer(m_file, 0, NULL, FILE_BEGIN);
	//}
	RETAILMSG(1, (_T("CCHMProtocol::Read:cb:%d, dwReadCnt:%d\r\n"), cb, dwReadCnt));
	return ((cb == dwReadCnt) ? S_OK : S_FALSE);
}

HRESULT
CCHMProtocol::Seek(
    LARGE_INTEGER dlibMove,
    DWORD dwOrigin,
    ULARGE_INTEGER *plibNewPosition)
{
	RETAILMSG(1, (_T("CCHMProtocol::Seek\r\n")));
	return (E_NOTIMPL);
}

HRESULT
CCHMProtocol::LockRequest(DWORD dwOptions)
{
	RETAILMSG(1, (_T("CCHMProtocol::LockRequest\r\n")));
	return S_OK;
}

HRESULT
CCHMProtocol::UnlockRequest()
{
	RETAILMSG(1, (_T("CCHMProtocol::UnlockRequest\r\n")));
	return S_OK;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -