// 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 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; }