📄 chmprotocol.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 + -