Windows2000/private/inet/urlmon/eapp/mimehndl.cxx
2020-09-30 17:12:32 +02:00

845 lines
19 KiB
C++

// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995.
// File: mimehndl.cxx
// Contents: Class that performs the download of a particular request.
// Classes:
// Functions:
// History: 12-04-95 JohannP (Johann Posch) Created
#include <eapp.h>
PerfDbgTag(tagCTransaction, "Urlmon", "Log CTransaction", DEB_TRANS)
DbgTag(tagCTransactionErr, "Urlmon", "Log CTransaction Errors", DEB_TRANS|DEB_ERROR)
typedef struct _tagPROTOCOLFILTERDATA
{
DWORD cbSize;
IOInetProtocolSink *pProtocolSink; // out parameter
IOInetProtocol *pProtocol; // in parameter
IUnknown *pUnk;
DWORD dwFilterFlags;
} PROTOCOLFILTERDATA;
CMimeHandlerTest1::CMimeHandlerTest1(REFCLSID rclsid, IUnknown *pUnkOuter, IUnknown **ppUnkInner) : CBaseProtocol(rclsid, pUnkOuter, ppUnkInner)
{
_pUnk = 0;
_pProt = 0;
_pProtSnk = 0;
_dwMode = 0;
_dwOInetBdgFlags = 0;
_pBuffer = 0; // DNLD_BUFFER_SIZE size buffer
_cbBufferSize = 0;
_cbTotalBytesRead = 0;
_cbBufferFilled = 0; //how much of the buffer is in use
_cbDataSniffMin = 0;
_cbBytesReported = 0;
_fDocFile = 0;
_fMimeVerified = 0;
_pwzFileName = 0;
_pwzMimeSuggested = 0;
_fDelete = 0;
}
// Method: CMimeHandlerTest1::QueryInterface
// Synopsis:
// Arguments: [riid] --
// [ppvObj] --
// Returns:
// History: 10-29-1996 JohannP (Johann Posch) Created
// Notes:
STDMETHODIMP CMimeHandlerTest1::QueryInterface(REFIID riid, void **ppvObj)
{
VDATEPTROUT(ppvObj, void *);
VDATETHIS(this);
HRESULT hr = NOERROR;
PerfDbgLog(tagCTransaction, this, "+CMimeHandlerTest1::QueryInterface");
*ppvObj = NULL;
{
if ( (riid == IID_IUnknown)
|| (riid == IID_IOInetProtocol))
{
*ppvObj = (IOInetProtocol *) this;
AddRef();
}
else if (riid == IID_IOInetProtocolSink)
{
*ppvObj = (IOInetProtocolSink *) this;
AddRef();
}
else
{
hr = E_NOINTERFACE;
}
}
PerfDbgLog1(tagCTransaction, this, "-CMimeHandlerTest1::QueryInterface (hr:%lx)", hr);
return hr;
}
// Function: CMimeHandlerTest1::AddRef
// Synopsis:
// Arguments: [ULONG] --
// Returns:
// History: 10-29-1996 JohannP (Johann Posch) Created
// Notes:
STDMETHODIMP_(ULONG) CMimeHandlerTest1::AddRef(void)
{
PerfDbgLog(tagCTransaction, this, "+CMimeHandlerTest1::AddRef");
LONG lRet;
{
lRet = ++_CRefs;
}
PerfDbgLog1(tagCTransaction, this, "-CMimeHandlerTest1::AddRef (cRefs:%ld)", lRet);
return lRet;
}
// Function: CMimeHandlerTest1::Release
// Synopsis:
// Arguments: [ULONG] --
// Returns:
// History: 10-29-1996 JohannP (Johann Posch) Created
// Notes:
STDMETHODIMP_(ULONG) CMimeHandlerTest1::Release(void)
{
PerfDbgLog(tagCTransaction, this, "+CMimeHandlerTest1::Release");
LONG lRet;
{
lRet = --_CRefs;
if (_CRefs == 0 && _fDelete)
{
delete this;
}
}
PerfDbgLog1(tagCTransaction, this, "-CMimeHandlerTest1::Release (cRefs:%ld)", lRet);
return lRet;
}
// Method: CMimeHandlerTest1::Start
// Synopsis:
// Arguments: [pwzUrl] --
// [pTrans] --
// [pOIBindInfo] --
// [grfSTI] --
// [dwReserved] --
// Returns:
// History: 10-29-1996 JohannP (Johann Posch) Created
// Notes:
STDMETHODIMP CMimeHandlerTest1::Start(LPCWSTR pwzUrl, IOInetProtocolSink *pOInetProtSnk, IOInetBindInfo *pOIBindInfo,
DWORD grfSTI, DWORD dwReserved)
{
PerfDbgLog(tagCTransaction, this, "+CMimeHandlerTest1::Start\n");
HRESULT hr = NOERROR;
PROTOCOLFILTERDATA *pFilterData = 0;
TransAssert((pOIBindInfo && pOInetProtSnk));
if (dwReserved)
{
pFilterData = (PROTOCOLFILTERDATA *)dwReserved;
}
if (pFilterData && pOInetProtSnk)
{
TransAssert((pOIBindInfo && pOInetProtSnk));
_pProt = pFilterData->pProtocol;
if (_pProt)
{
_pProt->AddRef();
}
else
{
hr = E_FAIL;
}
_pProtSnk = pOInetProtSnk;
_pProtSnk->AddRef();
}
else
{
hr = E_FAIL;
}
PerfDbgLog1(tagCTransaction, this, "+CMimeHandlerTest1::Start (hr:%lx)\n", hr);
return hr;
}
// Method: CMimeHandlerTest1::Continue
// Synopsis:
// Arguments: [pStateInfoIn] --
// Returns:
// History: 10-29-1996 JohannP (Johann Posch) Created
// Notes:
STDMETHODIMP CMimeHandlerTest1::Continue(PROTOCOLDATA *pStateInfoIn)
{
PerfDbgLog(tagCTransaction, this, "+CMimeHandlerTest1::Continue\n");
HRESULT hr = _pProt->Continue(pStateInfoIn);
PerfDbgLog1(tagCTransaction, this, "-CMimeHandlerTest1::Continue (hr:%lx)\n",hr);
return hr;
}
// Method: CMimeHandlerTest1::Abort
// Synopsis:
// Arguments: [hrReason] --
// [dwOptions] --
// Returns:
// History: 11-09-1996 JohannP (Johann Posch) Created
// Notes:
STDMETHODIMP CMimeHandlerTest1::Abort(HRESULT hrReason, DWORD dwOptions)
{
PerfDbgLog(tagCTransaction, this, "+CMimeHandlerTest1::Abort\n");
HRESULT hr = NOERROR;
hr = _pProt->Abort(hrReason, dwOptions);
PerfDbgLog1(tagCTransaction, this, "-CMimeHandlerTest1::Abort (hr:%lx)\n", hr);
return hr;
}
// Method: CMimeHandlerTest1::Terminate
// Synopsis:
// Arguments: [dwOptions] --
// Returns:
// History: 10-29-1996 JohannP (Johann Posch) Created
// Notes:
STDMETHODIMP CMimeHandlerTest1::Terminate(DWORD dwOptions)
{
PerfDbgLog(tagCTransaction, this, "+CMimeHandlerTest1::Terminate\n");
HRESULT hr = NOERROR;
TransAssert((_pProt));
//IOInetProtocol *pProt = _pProt;
hr = _pProt->Terminate(dwOptions);
//pProt->Release();
//_pProt = 0;
_pProtSnk->Release();
_pProtSnk = 0;
PerfDbgLog1(tagCTransaction, this, "-CMimeHandlerTest1::Terminate (hr:%lx)\n", hr);
return hr;
}
// Method: CMimeHandlerTest1::Suspend
// Synopsis:
// Arguments: (none)
// Returns:
// History: 10-29-1996 JohannP (Johann Posch) Created
// Notes:
STDMETHODIMP CMimeHandlerTest1::Suspend()
{
PerfDbgLog(tagCTransaction, this, "+CMimeHandlerTest1::Suspend\n");
HRESULT hr = _pProt->Suspend();
PerfDbgLog1(tagCTransaction, this, "-CMimeHandlerTest1::Suspend (hr:%lx)\n", hr);
return hr;
}
// Method: CMimeHandlerTest1::Resume
// Synopsis:
// Arguments: (none)
// Returns:
// History: 10-29-1996 JohannP (Johann Posch) Created
// Notes:
STDMETHODIMP CMimeHandlerTest1::Resume()
{
PerfDbgLog(tagCTransaction, this, "+CMimeHandlerTest1::Resume\n");
HRESULT hr = _pProt->Resume();
PerfDbgLog1(tagCTransaction, this, "-CMimeHandlerTest1::Resume (hr:%lx)\n", hr);
return hr;
}
// Method: CMimeHandlerTest1::Read
// Synopsis:
// Arguments: [ULONG] --
// [ULONG] --
// [pcbRead] --
// Returns:
// History: 10-29-1996 JohannP (Johann Posch) Created
// Notes:
STDMETHODIMP CMimeHandlerTest1::Read(void *pBuffer, ULONG cbBuffer,ULONG *pcbRead)
{
PerfDbgLog(tagCTransaction, this, "+CMimeHandlerTest1::Read\n");
HRESULT hr = E_FAIL;
BOOL fRead = TRUE;
DWORD dwCopy = 0;
DWORD dwCopyNew = 0;
if ( (_dwOInetBdgFlags & (PI_MIMEVERIFICATION | PI_DOCFILECLSIDLOOKUP))
&& (_cbBufferFilled))
{
fRead = FALSE;
// copy data form the local buffer to the provide buffer
if (cbBuffer < _cbBufferFilled)
{
dwCopy = cbBuffer;
memcpy(pBuffer, _pBuffer, cbBuffer);
// move the memory to the front
memcpy(_pBuffer, _pBuffer + cbBuffer, _cbBufferFilled - cbBuffer);
_cbBufferFilled -= cbBuffer;
hr = S_OK;
}
else if (cbBuffer == _cbBufferFilled)
{
dwCopy = _cbBufferFilled;
memcpy(pBuffer, _pBuffer, _cbBufferFilled);
_cbBufferFilled = 0;
hr = S_OK;
}
else
{
// user buffer is greater than what is available in
dwCopy = _cbBufferFilled;
memcpy(pBuffer, _pBuffer, _cbBufferFilled);
_cbBufferFilled = 0;
fRead = TRUE;
hr = E_PENDING;
}
}
if (fRead)
{
if (_pProt)
{
hr = _pProt->Read( ((LPBYTE)pBuffer) + dwCopy, cbBuffer - dwCopy, &dwCopyNew);
_cbTotalBytesRead += dwCopyNew;
}
else
{
hr = S_FALSE;
}
}
if (pcbRead)
{
*pcbRead = dwCopy + dwCopyNew;
}
PerfDbgLog1(tagCTransaction, this, "-CMimeHandlerTest1::Read (hr:%lx)\n",hr);
return hr;
}
// Method: CMimeHandlerTest1::Seek
// Synopsis:
// Arguments: [DWORD] --
// [ULARGE_INTEGER] --
// [plibNewPosition] --
// Returns:
// History: 10-29-1996 JohannP (Johann Posch) Created
// Notes:
STDMETHODIMP CMimeHandlerTest1::Seek(LARGE_INTEGER dlibMove,DWORD dwOrigin,ULARGE_INTEGER *plibNewPosition)
{
PerfDbgLog(tagCTransaction, this, "+CMimeHandlerTest1::Seek\n");
HRESULT hr = _pProt->Seek(dlibMove, dwOrigin, plibNewPosition);
PerfDbgLog1(tagCTransaction, this, "-CMimeHandlerTest1::Seek (hr:%lx)\n", hr);
return hr;
}
// Method: CMimeHandlerTest1::LockRequest
// Synopsis:
// Arguments: [dwOptions] --
// Returns:
// History: 10-29-1996 JohannP (Johann Posch) Created
// Notes:
STDMETHODIMP CMimeHandlerTest1::LockRequest(DWORD dwOptions)
{
PerfDbgLog(tagCTransaction, this, "+CMimeHandlerTest1::LockRequest\n");
HRESULT hr = hr = _pProt->LockRequest(dwOptions);
PerfDbgLog1(tagCTransaction, this, "-CMimeHandlerTest1::LockRequest (hr:%lx)\n",hr);
return hr;
}
// Method: CMimeHandlerTest1::UnlockRequest
// Synopsis:
// Arguments: (none)
// Returns:
// History: 10-29-1996 JohannP (Johann Posch) Created
// Notes:
STDMETHODIMP CMimeHandlerTest1::UnlockRequest()
{
PerfDbgLog(tagCTransaction, this, "+CMimeHandlerTest1::UnlockRequest\n");
HRESULT hr = NOERROR;
hr = _pProt->UnlockRequest();
PerfDbgLog1(tagCTransaction, this, "-CMimeHandlerTest1::UnlockRequest (hr:%lx)\n", hr);
return hr;
}
// Method: CTransaction::OnDataReceived
// Synopsis:
// Arguments: [grfBSC] --
// [cbBytesAvailable] --
// [dwTotalSize] --
// [pcbNewAvailable] --
// Returns:
// History: 4-15-1997 JohannP (Johann Posch) Created
// Notes:
#if 0
STDMETHODIMP CMimeHandlerTest1::OnDataReceived(DWORD *pgrfBSC, DWORD *pcbBytesAvailable, DWORD *pdwTotalSize) //, DWORD *pcbNewAvailable)
{
PerfDbgLog3(tagCTransaction, this, "+CMimeHandlerTest1::OnDataReceived (grfBSC:%lx, cbBytesAvailable:%ld, _cbTotalBytesRead:%ld)",
*pgrfBSC, *pcbBytesAvailable, _cbTotalBytesRead);
HRESULT hr = NOERROR;
DWORD grfBSC = *pgrfBSC;
DWORD cbBytesAvailable = *pcbBytesAvailable;
DWORD dwTotalSize = *pdwTotalSize;
DWORD *pcbNewAvailable = &cbBytesAvailable;
*pcbNewAvailable = cbBytesAvailable;
if (_dwOInetBdgFlags & (PI_MIMEVERIFICATION | PI_DOCFILECLSIDLOOKUP))
{
DWORD dwNewData = 0;
TransAssert((_pProt && _cbDataSniffMin));
// _cbTotalBytesRead = # of bytes read so far
if (_cbTotalBytesRead < _cbDataSniffMin)
{
// no bytes read so far
TransAssert((_cbTotalBytesRead < _cbDataSniffMin));
// read data into buffer and report progess
do
{
hr = _pProt->Read(_pBuffer + _cbBufferFilled, _cbBufferSize - _cbBufferFilled, &dwNewData);
_cbTotalBytesRead += dwNewData;
_cbBufferFilled += dwNewData;
} while ((hr == S_OK) && (_cbTotalBytesRead < _cbDataSniffMin));
// now check if this is docfile
// if so download at least 2k
if (!_fDocFile && _cbBufferFilled && (IsDocFile(_pBuffer, _cbBufferFilled) == S_OK))
{
_fDocFile = TRUE;
_cbDataSniffMin = (dwTotalSize && dwTotalSize < DATASNIFSIZEDOCFILE_MIN) ? dwTotalSize : DATASNIFSIZEDOCFILE_MIN;
}
if ((hr == E_PENDING) && (_cbTotalBytesRead < _cbDataSniffMin))
{
// do not report anything - wait until we get more data
// a request is pending at this time
// need more data to sniff properly
hr = S_NEEDMOREDATA;
}
else if (hr == NOERROR || hr == E_PENDING)
{
TransAssert((_cbTotalBytesRead != 0));
// report the data we have in the buffer or
// the available #
DWORD cbBytesReport = (cbBytesAvailable > _cbTotalBytesRead) ? cbBytesAvailable : _cbTotalBytesRead + 1;
if (dwTotalSize && ((cbBytesReport > dwTotalSize)))
{
cbBytesReport = dwTotalSize;
}
*pcbNewAvailable = cbBytesReport;
}
else if (hr == S_FALSE)
{
// end of stream
*pgrfBSC |= (BSCF_LASTDATANOTIFICATION & BSCF_DATAFULLYAVAILABLE);
*pcbBytesAvailable = *pdwTotalSize = _cbTotalBytesRead;
}
if ( (!_fMimeVerified)
&& ( (*pcbNewAvailable >= _cbDataSniffMin)
|| (hr == S_FALSE)) )
{
// enough data or end of stream
_fMimeVerified = TRUE;
LPCWSTR pwzStr = FindMimeFromDataIntern(_pwzFileName,_pBuffer, _cbBufferFilled, _pwzMimeSuggested, 0);
_pProtSnk->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, pwzStr);
if (_pwzMimeSuggested != pwzStr)
{
if (_pwzMimeSuggested)
{
delete [] _pwzMimeSuggested;
}
if (pwzStr)
{
_pwzMimeSuggested = OLESTRDuplicate((LPWSTR)pwzStr);
}
}
if ( _fDocFile
&& (_dwOInetBdgFlags & PI_DOCFILECLSIDLOOKUP))
{
// find the class id and send it on
CLSID clsid;
HRESULT hr1 = GetClassDocFileBuffer(_pBuffer, _cbBufferFilled, &clsid);
if (hr1 == NOERROR)
{
LPOLESTR pwzStrClsId;
StringFromCLSID(clsid, &pwzStrClsId);
_pProtSnk->ReportProgress(BINDSTATUS_CLASSIDAVAILABLE, pwzStrClsId);
delete [] pwzStrClsId;
}
}
}
hr = NOERROR;
}
//TransAssert((cbBytesAvailable <= *pcbNewAvailable));
if (cbBytesAvailable > *pcbNewAvailable)
{
*pcbNewAvailable = cbBytesAvailable;
}
if (dwTotalSize && (dwTotalSize < *pcbNewAvailable))
{
*pcbNewAvailable = dwTotalSize;
}
}
{
CLock lck(_mxs);
_cbBytesReported = *pcbNewAvailable;
*pdwTotalSize = dwTotalSize;
}
PerfDbgLog2(tagCTransaction, this, "-CMimeHandlerTest1::OnDataReceived (hr:%lx, _cbBufferFilled:%lx)", hr, _cbBufferFilled);
return hr;
}
#endif // 0
// Method: CMimeHandlerTest1::Switch
// Synopsis:
// Arguments: [pStateInfo] --
// Returns:
// History: 11-07-1996 JohannP (Johann Posch) Created
// Notes:
STDMETHODIMP CMimeHandlerTest1::Switch(PROTOCOLDATA *pStateInfo)
{
PerfDbgLog(tagCTransaction, this, "+CMimeHandlerTest1::Switch");
HRESULT hr = NOERROR;
hr = _pProtSnk->Switch(pStateInfo);
PerfDbgLog1(tagCTransaction, this, "-CMimeHandlerTest1::Switch (hr:%lx)", hr);
return hr;
}
// Method: CMimeHandlerTest1::ReportProgress
// Synopsis:
// Arguments: [NotMsg] --
// [szStatusText] --
// Returns:
// History: 11-07-1996 JohannP (Johann Posch) Created
// Notes:
STDMETHODIMP CMimeHandlerTest1::ReportProgress(ULONG NotMsg, LPCWSTR pwzStatusText)
{
PerfDbgLog(tagCTransaction, this, "+CMimeHandlerTest1::ReportProgress");
HRESULT hr = NOERROR;
switch (NotMsg)
{
case BINDSTATUS_MIMETYPEAVAILABLE:
if (_dwOInetBdgFlags & (PI_MIMEVERIFICATION | PI_DOCFILECLSIDLOOKUP))
{
// report the mime later after sniffing data
_pwzMimeSuggested = OLESTRDuplicate(pwzStatusText);
}
else
{
hr = _pProtSnk->ReportProgress(NotMsg, pwzStatusText);
}
break;
case BINDSTATUS_CACHEFILENAMEAVAILABLE :
_pwzFileName = OLESTRDuplicate(pwzStatusText);
default:
{
hr = _pProtSnk->ReportProgress(NotMsg, pwzStatusText);
}
} // end switch
PerfDbgLog1(tagCTransaction, this, "-CMimeHandlerTest1::ReportProgress (hr:%lx)", hr);
return hr;
}
// Method: CMimeHandlerTest1::ReportData
// Synopsis:
// Arguments: [grfBSCF] --
// [ULONG] --
// [ulProgressMax] --
// Returns:
// History: 11-07-1996 JohannP (Johann Posch) Created
// Notes:
STDMETHODIMP CMimeHandlerTest1::ReportData(DWORD grfBSCF, ULONG ulProgress,ULONG ulProgressMax)
{
PerfDbgLog3(tagCTransaction, this, "+CMimeHandlerTest1::ReportData(grfBSCF:%lx, ulProgress:%ld, ulProgressMax:%ld)",
grfBSCF, ulProgress, ulProgressMax);
HRESULT hr = NOERROR;
/*
if ( (_dwOInetBdgFlags & (PI_MIMEVERIFICATION | PI_DOCFILECLSIDLOOKUP)
&& (OnDataReceived(&grfBSCF, &ulProgress, &ulProgressMax) == NOERROR)) )
{
hr = _pProtSnk->ReportData( grfBSCF, ulProgress, ulProgressMax);
}
else
*/
{
hr = _pProtSnk->ReportData( grfBSCF, ulProgress, ulProgressMax);
}
PerfDbgLog1(tagCTransaction, this, "-CMimeHandlerTest1::ReportData (hr:%lx)", hr);
return hr;
}
// Method: CMimeHandlerTest1::ReportResult
// Synopsis:
// Arguments: [DWORD] --
// [dwError] --
// [wzResult] --
// Returns:
// History: 11-07-1996 JohannP (Johann Posch) Created
// Notes:
STDMETHODIMP CMimeHandlerTest1::ReportResult(HRESULT hrResult, DWORD dwError, LPCWSTR wzResult)
{
PerfDbgLog(tagCTransaction, this, "+CMimeHandlerTest1::ReportResult");
HRESULT hr = NOERROR;
hr = _pProtSnk->ReportResult(hrResult, dwError, wzResult);
PerfDbgLog1(tagCTransaction, this, "-CMimeHandlerTest1::ReportResult (hr:%lx)", hr);
return hr;
}
STDMETHODIMP CMimeHandlerTest1::Initialize(DWORD dwMode, DWORD dwOptions, IUnknown *pUnk, IOInetProtocol *pProt, IOInetProtocolSink *pProtSnk)
{
HRESULT hr = NOERROR;
_dwMode = dwMode;
_pUnk = pUnk;
_pProt = pProt;
_pProtSnk = pProtSnk;
if (_pProtSnk)
{
_pProtSnk->AddRef();
}
if (_pUnk)
{
_pUnk->AddRef();
}
_dwOInetBdgFlags = dwOptions;
if (_dwOInetBdgFlags & (PI_MIMEVERIFICATION | PI_DOCFILECLSIDLOOKUP))
{
_cbBufferSize = DATASNIFSIZEDOCFILE_MIN;
_pBuffer = (LPBYTE) new BYTE[_cbBufferSize];
if (!_pBuffer)
{
_cbBufferSize = 0;
hr = E_OUTOFMEMORY;
}
_cbDataSniffMin = _cbBufferSize;
}
TransAssert((_pUnk && _pProt && _pProtSnk));
return hr;
}