//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1995. // // File: transact.cxx // // Contents: Class that performs the download of a particular request. // // Classes: // // Functions: // // History: 12-04-95 JohannP (Johann Posch) Created // //---------------------------------------------------------------------------- #include #include #include "oinet.hxx" PerfDbgTag(tagCTransaction, "Urlmon", "Log CTransaction", DEB_TRANS); DbgTag(tagCTransactionErr, "Urlmon", "Log CTransaction Errors", DEB_TRANS|DEB_ERROR); HRESULT GetClassDocFileBuffer(LPVOID pbuffer, DWORD dwSize, CLSID *pclsid); HRESULT GetCodeBaseFromDocFile(LPBYTE pBuffer, ULONG ulSize, LPWSTR *pwzClassStr, LPWSTR pwzBaseUrl, DWORD *lpdwVersionMS, DWORD *lpdwVersionLS); HRESULT IsHandlerAvailable(LPWSTR pwzUrl, LPWSTR pwzMime, CLSID *pclsid, LPBYTE pBuffer, ULONG cbSize); #if 0 //+--------------------------------------------------------------------------- // // Method: COInetProtSnk::QueryInterface // // Synopsis: // // Arguments: [riid] -- // [ppvObj] -- // // Returns: // // History: 10-29-1996 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP COInetProtSnk::QueryInterface(REFIID riid, void **ppvObj) { VDATEPTROUT(ppvObj, void *); VDATETHIS(this); HRESULT hr = NOERROR; PerfDbgLog(tagCTransaction, this, "+COInetProtSnk::QueryInterface"); *ppvObj = NULL; if (_pUnk) { hr = _pUnk->QueryInterface(riid, ppvObj); } else { 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, "-COInetProtSnk::QueryInterface (hr:%lx)", hr); return hr; } //+--------------------------------------------------------------------------- // // Function: COInetProtSnk::AddRef // // Synopsis: // // Arguments: [ULONG] -- // // Returns: // // History: 10-29-1996 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP_(ULONG) COInetProtSnk::AddRef(void) { PerfDbgLog(tagCTransaction, this, "+COInetProtSnk::AddRef"); LONG lRet = _pProtSnk->AddRef(); PerfDbgLog1(tagCTransaction, this, "-COInetProtSnk::AddRef (cRefs:%ld)", lRet); return lRet; } //+--------------------------------------------------------------------------- // // Function: COInetProtSnk::Release // // Synopsis: // // Arguments: [ULONG] -- // // Returns: // // History: 10-29-1996 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP_(ULONG) COInetProtSnk::Release(void) { PerfDbgLog(tagCTransaction, this, "+COInetProtSnk::Release"); LONG lRet = _pProtSnk->Release(); PerfDbgLog1(tagCTransaction, this, "-COInetProtSnk::Release (cRefs:%ld)", lRet); return lRet; } //+--------------------------------------------------------------------------- // // Method: COInetProtSnk::Switch // // Synopsis: // // Arguments: [pStateInfo] -- // // Returns: // // History: 11-07-1996 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP COInetProtSnk::Switch(PROTOCOLDATA *pStateInfo) { PerfDbgLog(tagCTransaction, this, "+COInetProtSnk::Switch"); HRESULT hr = NOERROR; hr = _pProtSnk->Switch(pStateInfo); PerfDbgLog1(tagCTransaction, this, "-COInetProtSnk::Switch (hr:%lx)", hr); return hr; } //+--------------------------------------------------------------------------- // // Method: COInetProtSnk::ReportProgress // // Synopsis: // // Arguments: [NotMsg] -- // [szStatusText] -- // // Returns: // // History: 11-07-1996 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP COInetProtSnk::ReportProgress(ULONG NotMsg, LPCWSTR pwzStatusText) { PerfDbgLog1(tagCTransaction, this, "+COInetProtSnk::ReportProgress pwzStatusText:%ws", pwzStatusText); HRESULT hr = NOERROR; hr = _pProtSnk->ReportProgress(NotMsg, pwzStatusText); PerfDbgLog2(tagCTransaction, this, "-COInetProtSnk::ReportProgress (pwzStatusText:%ws, hr:%lx)", pwzStatusText, hr); return hr; } //+--------------------------------------------------------------------------- // // Method: COInetProtSnk::ReportData // // Synopsis: // // Arguments: [grfBSCF] -- // [ULONG] -- // [ulProgressMax] -- // // Returns: // // History: 11-07-1996 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP COInetProtSnk::ReportData(DWORD grfBSCF, ULONG ulProgress,ULONG ulProgressMax) { PerfDbgLog3(tagCTransaction, this, "+COInetProtSnk::ReportData(grfBSCF:%lx, ulProgress:%ld, ulProgressMax:%ld)", grfBSCF, ulProgress, ulProgressMax); HRESULT hr = NOERROR; hr = _pProtSnk->ReportData( grfBSCF, ulProgress, ulProgressMax); PerfDbgLog1(tagCTransaction, this, "-COInetProtSnk::ReportData (hr:%lx)", hr); return hr; } //+--------------------------------------------------------------------------- // // Method: COInetProtSnk::ReportResult // // Synopsis: // // Arguments: [DWORD] -- // [dwError] -- // [wzResult] -- // // Returns: // // History: 11-07-1996 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP COInetProtSnk::ReportResult(HRESULT hrResult, DWORD dwError, LPCWSTR wzResult) { PerfDbgLog(tagCTransaction, this, "+COInetProtSnk::ReportResult"); HRESULT hr = NOERROR; hr = _pProtSnk->ReportResult(hrResult, dwError, wzResult); PerfDbgLog1(tagCTransaction, this, "-COInetProtSnk::ReportResult (hr:%lx)", hr); return hr; } #endif // 0 //+--------------------------------------------------------------------------- // // Method: COInetProt::QueryInterface // // Synopsis: // // Arguments: [riid] -- // [ppvObj] -- // // Returns: // // History: 10-29-1996 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP COInetProt::QueryInterface(REFIID riid, void **ppvObj) { DEBUG_ENTER((DBG_TRANS, Hresult, "COInetProt::IUnknown::QueryInterface", "this=%#x, %#x, %#x", this, &riid, ppvObj )); VDATEPTROUT(ppvObj, void *); VDATETHIS(this); HRESULT hr = NOERROR; PerfDbgLog(tagCTransaction, this, "+COInetProt::QueryInterface"); *ppvObj = NULL; if (_pUnk) { hr = _pUnk->QueryInterface(riid, ppvObj); } else { if ( (riid == IID_IUnknown) || (riid == IID_IOInetProtocol)) { *ppvObj = (IOInetProtocol *) this; AddRef(); } else if (riid == IID_IOInetProtocolSink) { *ppvObj = (IOInetProtocolSink *) this; AddRef(); } else if (riid == IID_IServiceProvider) { *ppvObj = (IServiceProvider *) this; AddRef(); } else if (riid == IID_IOInetPriority) { *ppvObj = (IOInetPriority *) this; AddRef(); } else { hr = E_NOINTERFACE; } } PerfDbgLog1(tagCTransaction, this, "-COInetProt::QueryInterface (hr:%lx)", hr); DEBUG_LEAVE(hr); return hr; } //+--------------------------------------------------------------------------- // // Function: COInetProt::AddRef // // Synopsis: // // Arguments: [ULONG] -- // // Returns: // // History: 10-29-1996 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP_(ULONG) COInetProt::AddRef(void) { DEBUG_ENTER((DBG_TRANS, Dword, "COInetProt::IUnknown::AddRef", "this=%#x", this )); PerfDbgLog(tagCTransaction, this, "+COInetProt::AddRef"); LONG lRet; if (_pUnk) { lRet = _pUnk->AddRef(); } else { lRet = ++_CRefs; } PerfDbgLog1(tagCTransaction, this, "-COInetProt::AddRef (cRefs:%ld)", lRet); DEBUG_LEAVE(lRet); return lRet; } //+--------------------------------------------------------------------------- // // Function: COInetProt::Release // // Synopsis: // // Arguments: [ULONG] -- // // Returns: // // History: 10-29-1996 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP_(ULONG) COInetProt::Release(void) { DEBUG_ENTER((DBG_TRANS, Dword, "COInetProt::IUnknown::Release", "this=%#x", this )); PerfDbgLog(tagCTransaction, this, "+COInetProt::Release"); LONG lRet; if (_pUnk) { lRet = _pUnk->Release(); } else { lRet = --_CRefs; if (_CRefs == 0) { // // release all objects if (_pProtSnk) { _pProtSnk->Release(); } if (_pProt) { _pProt->Release(); } if (_dwMode & PP_DELETE) { delete this; } } } PerfDbgLog1(tagCTransaction, this, "-COInetProt::Release (cRefs:%ld)", lRet); DEBUG_LEAVE(lRet); return lRet; } //+--------------------------------------------------------------------------- // // Method: COInetProt::Start // // Synopsis: // // Arguments: [pwzUrl] -- // [pTrans] -- // [pOIBindInfo] -- // [grfSTI] -- // [dwReserved] -- // // Returns: // // History: 10-29-1996 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP COInetProt::Start(LPCWSTR pwzUrl, IOInetProtocolSink *pOInetProtSnk, IOInetBindInfo *pOIBindInfo, DWORD grfSTI, DWORD_PTR dwReserved) { DEBUG_ENTER((DBG_TRANS, Hresult, "COInetProt::IInternetProtocolRoot::Start", "this=%#x, %.80wq, %#x, %#x, %#x, %#x", this, pwzUrl, pOInetProtSnk, pOIBindInfo, grfSTI, dwReserved )); PerfDbgLog(tagCTransaction, this, "+COInetProt::Start\n"); HRESULT hr = NOERROR; TransAssert((pOIBindInfo && pOInetProtSnk && pwzUrl)); // Just before starting the transaction give it the priority. IOInetPriority * pOInetPriority = NULL; if (_pProt->QueryInterface(IID_IOInetPriority, (void **) &pOInetPriority) == S_OK) { pOInetPriority->SetPriority(_nPriority); pOInetPriority->Release(); } delete [] _pwzUrl; _pwzUrl = OLESTRDuplicate(pwzUrl); hr = _pProt->Start(pwzUrl, pOInetProtSnk, pOIBindInfo, grfSTI, dwReserved); PerfDbgLog1(tagCTransaction, this, "-COInetProt::Start (hr:%lx)\n", hr); DEBUG_LEAVE(hr); return hr; } //+--------------------------------------------------------------------------- // // Method: COInetProt::Continue // // Synopsis: // // Arguments: [pStateInfoIn] -- // // Returns: // // History: 10-29-1996 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP COInetProt::Continue(PROTOCOLDATA *pStateInfoIn) { DEBUG_ENTER((DBG_TRANS, Hresult, "COInetProt::IInternetProtocolRoot::Continue", "this=%#x, %#x", this, pStateInfoIn )); PerfDbgLog(tagCTransaction, this, "+COInetProt::Continue\n"); HRESULT hr = _pProt->Continue(pStateInfoIn); PerfDbgLog1(tagCTransaction, this, "-COInetProt::Continue (hr:%lx)\n",hr); DEBUG_LEAVE(hr); return hr; } //+--------------------------------------------------------------------------- // // Method: COInetProt::Abort // // Synopsis: // // Arguments: [hrReason] -- // [dwOptions] -- // // Returns: // // History: 11-09-1996 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP COInetProt::Abort(HRESULT hrReason, DWORD dwOptions) { DEBUG_ENTER((DBG_TRANS, Hresult, "COInetProt::IInternetProtocolRoot::Abort", "this=%#x, %#x, %#x", this, hrReason, dwOptions )); PerfDbgLog(tagCTransaction, this, "+COInetProt::Abort\n"); HRESULT hr = NOERROR; hr = _pProt->Abort(hrReason, dwOptions); PerfDbgLog1(tagCTransaction, this, "-COInetProt::Abort (hr:%lx)\n", hr); DEBUG_LEAVE(hr); return hr; } //+--------------------------------------------------------------------------- // // Method: COInetProt::Terminate // // Synopsis: // // Arguments: [dwOptions] -- // // Returns: // // History: 10-29-1996 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP COInetProt::Terminate(DWORD dwOptions) { DEBUG_ENTER((DBG_TRANS, Hresult, "COInetProt::IInternetProtocolRoot::Terminate", "this=%#x, %#x", this, dwOptions )); PerfDbgLog(tagCTransaction, this, "+COInetProt::Terminate\n"); HRESULT hr = NOERROR; TransAssert((_pProt)); hr = _pProt->Terminate(dwOptions); SetProtocolSink(0); SetServiceProvider(0); PerfDbgLog1(tagCTransaction, this, "-COInetProt::Terminate (hr:%lx)\n", hr); DEBUG_LEAVE(hr); return hr; } //+--------------------------------------------------------------------------- // // Method: COInetProt::Suspend // // Synopsis: // // Arguments: (none) // // Returns: // // History: 10-29-1996 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP COInetProt::Suspend() { DEBUG_ENTER((DBG_TRANS, Hresult, "COInetProt::IInternetProtocolRoot::Suspend", "this=%#x", this )); PerfDbgLog(tagCTransaction, this, "+COInetProt::Suspend\n"); HRESULT hr = _pProt->Suspend(); PerfDbgLog1(tagCTransaction, this, "-COInetProt::Suspend (hr:%lx)\n", hr); DEBUG_LEAVE(hr); return hr; } //+--------------------------------------------------------------------------- // // Method: COInetProt::Resume // // Synopsis: // // Arguments: (none) // // Returns: // // History: 10-29-1996 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP COInetProt::Resume() { DEBUG_ENTER((DBG_TRANS, Hresult, "COInetProt::IInternetProtocolRoot::Resume", "this=%#x", this )); PerfDbgLog(tagCTransaction, this, "+COInetProt::Resume\n"); HRESULT hr = _pProt->Resume(); PerfDbgLog1(tagCTransaction, this, "-COInetProt::Resume (hr:%lx)\n", hr); DEBUG_LEAVE(hr); return hr; } //+--------------------------------------------------------------------------- // // Method: COInetProt::Read // // Synopsis: // // Arguments: [ULONG] -- // [ULONG] -- // [pcbRead] -- // // Returns: // // History: 10-29-1996 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP COInetProt::Read(void *pBuffer, ULONG cbBuffer,ULONG *pcbRead) { DEBUG_ENTER((DBG_TRANS, Hresult, "COInetProt::IInternetProtocol::Read", "this=%#x, %#x, %#x, %#x", this, pBuffer, cbBuffer, pcbRead )); PerfDbgLog(tagCTransaction, this, "+COInetProt::Read\n"); HRESULT hr = E_FAIL; BOOL fRead = TRUE; DWORD dwCopy = 0; DWORD dwCopyNew = 0; if ((_dwOInetBdgFlags & (PI_MIMEVERIFICATION | PI_DOCFILECLSIDLOOKUP)) && _cbBufferUnread) { fRead = FALSE; // copy data form the local buffer to the provide buffer if (cbBuffer <= _cbBufferUnread) { dwCopy = cbBuffer; hr = S_OK; } else { dwCopy = _cbBufferUnread; fRead = TRUE; } memcpy(pBuffer, _pBuffer+(_cbBufferFilled-_cbBufferUnread), dwCopy); _cbBufferUnread -= dwCopy; } 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, "-COInetProt::Read (hr:%lx)\n",hr); DEBUG_LEAVE(hr); return hr; } //+--------------------------------------------------------------------------- // // Method: COInetProt::Seek // // Synopsis: // // Arguments: [DWORD] -- // [ULARGE_INTEGER] -- // [plibNewPosition] -- // // Returns: // // History: 10-29-1996 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP COInetProt::Seek(LARGE_INTEGER dlibMove,DWORD dwOrigin,ULARGE_INTEGER *plibNewPosition) { DEBUG_ENTER((DBG_TRANS, Hresult, "COInetProt::IInternetProtocol::Seek", "this=%#x, %#x, %#x, %#x", this, dlibMove, dwOrigin, plibNewPosition )); PerfDbgLog(tagCTransaction, this, "+COInetProt::Seek\n"); HRESULT hr = _pProt->Seek(dlibMove, dwOrigin, plibNewPosition); PerfDbgLog1(tagCTransaction, this, "-COInetProt::Seek (hr:%lx)\n", hr); DEBUG_LEAVE(hr); return hr; } //+--------------------------------------------------------------------------- // // Method: COInetProt::LockRequest // // Synopsis: // // Arguments: [dwOptions] -- // // Returns: // // History: 10-29-1996 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP COInetProt::LockRequest(DWORD dwOptions) { DEBUG_ENTER((DBG_TRANS, Hresult, "COInetProt::IInternetProtocol::LockRequest", "this=%#x, %#x", this, dwOptions )); PerfDbgLog(tagCTransaction, this, "+COInetProt::LockRequest\n"); HRESULT hr = hr = _pProt->LockRequest(dwOptions); PerfDbgLog1(tagCTransaction, this, "-COInetProt::LockRequest (hr:%lx)\n",hr); DEBUG_LEAVE(hr); return hr; } //+--------------------------------------------------------------------------- // // Method: COInetProt::UnlockRequest // // Synopsis: // // Arguments: (none) // // Returns: // // History: 10-29-1996 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP COInetProt::UnlockRequest() { DEBUG_ENTER((DBG_TRANS, Hresult, "COInetProt::IInternetProtocol::UnlockRequest", "this=%#x", this )); PerfDbgLog(tagCTransaction, this, "+COInetProt::UnlockRequest\n"); HRESULT hr = NOERROR; hr = _pProt->UnlockRequest(); PerfDbgLog1(tagCTransaction, this, "-COInetProt::UnlockRequest (hr:%lx)\n", hr); DEBUG_LEAVE(hr); return hr; } //+--------------------------------------------------------------------------- // // Method: CTransaction::OnDataReceived // // Synopsis: // // Arguments: [grfBSC] -- // [cbBytesAvailable] -- // [dwTotalSize] -- // [pcbNewAvailable] -- // // Returns: // // History: 4-15-1997 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP COInetProt::OnDataReceived(DWORD *pgrfBSC, DWORD *pcbBytesAvailable, DWORD *pdwTotalSize) { DEBUG_ENTER((DBG_TRANS, Hresult, "COInetProt::OnDataReceived", "this=%#x, %#x, %#x, %#x", this, pgrfBSC, pcbBytesAvailable, pdwTotalSize )); PerfDbgLog3(tagCTransaction, this, "+COInetProt::OnDataReceived (grfBSC:%lx, *pcbBytesAvailable:%ld, _cbTotalBytesRead:%ld)", *pgrfBSC, *pcbBytesAvailable, _cbTotalBytesRead); HRESULT hr = NOERROR; DWORD grfBSC = *pgrfBSC; BOOL fEndOfData = FALSE; if (_fWaitOnHandler) { hr = S_NEEDMOREDATA; } else if ( ((_dwOInetBdgFlags & (PI_MIMEVERIFICATION | PI_DOCFILECLSIDLOOKUP | PI_CLASSINSTALL)) && (!_fMimeVerified || _fNeedMoreData)) || ((_dwOInetBdgFlags & PI_CLASSINSTALL) && !_fClassInstallChecked) ) { DWORD dwNewData = 0; TransAssert((_pProt && _cbDataSniffMin)); //TransAssert((pcbBytesAvailable && *pcbBytesAvailable)); //TransAssert((pdwTotalSize)); // _cbTotalBytesRead = # of bytes read so far if (_cbBufferFilled < _cbDataSniffMin) { // no bytes read so far TransAssert((_cbTotalBytesRead < _cbDataSniffMin)); // read data into buffer and report progess do { PProtAssert((_pBuffer && (_pBuffer + _cbBufferFilled) )); hr = _pProt->Read(_pBuffer + _cbBufferFilled, _cbBufferSize - _cbBufferFilled, &dwNewData); _cbTotalBytesRead += dwNewData; _cbBufferFilled += dwNewData; _cbBufferUnread += dwNewData; } while ((hr == S_OK) && (_cbBufferFilled < _cbDataSniffMin)); // now check if this is docfile // if so download at least 2k if (!_fDocFile && _cbBufferFilled && (IsDocFile(_pBuffer, _cbBufferFilled) == S_OK)) { _fDocFile = TRUE; // we may need to sniff to maximum to find handler if (_cbBufferSize < DATASNIFSIZEDOCFILE_MAX) { LPBYTE pBufferTemp; pBufferTemp = (LPBYTE) new BYTE[DATASNIFSIZEDOCFILE_MAX]; if (pBufferTemp) { memcpy(pBufferTemp, _pBuffer, _cbBufferFilled); delete [] _pBuffer; _pBuffer = pBufferTemp; _cbBufferSize = DATASNIFSIZEDOCFILE_MAX; if (hr == NOERROR) { //since we increased the buffersize and we want to drain DATASNIFSIZEDOCFILE_MAX bytes. do { PProtAssert((_pBuffer && (_pBuffer + _cbBufferFilled) )); hr = _pProt->Read(_pBuffer + _cbBufferFilled, _cbBufferSize - _cbBufferFilled, &dwNewData); _cbTotalBytesRead += dwNewData; _cbBufferFilled += dwNewData; _cbBufferUnread += dwNewData; } while ((hr == S_OK) && (_cbBufferFilled < _cbBufferSize)); } } } _cbDataSniffMin = (*pdwTotalSize && *pdwTotalSize < _cbBufferSize) ? *pdwTotalSize : _cbBufferSize; } if ((hr == E_PENDING) && (_cbBufferFilled < _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 = (*pcbBytesAvailable > _cbTotalBytesRead) ? *pcbBytesAvailable : _cbTotalBytesRead + 1; if (*pdwTotalSize && ((cbBytesReport > *pdwTotalSize))) { cbBytesReport = *pdwTotalSize; } *pcbBytesAvailable = cbBytesReport; } else if (hr == S_FALSE) { // end of stream *pgrfBSC |= (BSCF_LASTDATANOTIFICATION & BSCF_DATAFULLYAVAILABLE); *pcbBytesAvailable = *pdwTotalSize = _cbTotalBytesRead; fEndOfData = TRUE; } if ( (!_fMimeVerified) && ( (*pcbBytesAvailable >= _cbDataSniffMin) || (hr == S_FALSE)) ) { // enough data or end of stream _fMimeVerified = TRUE; LPWSTR pwzStr = 0; DWORD dwMimeFlags = FMFD_DEFAULT; if( !_pwzFileName ) { dwMimeFlags = FMFD_URLASFILENAME; } hr = FindMimeFromData(NULL, (_pwzFileName) ? _pwzFileName : _pwzUrl, _pBuffer, _cbBufferFilled, _pwzMimeSuggested, dwMimeFlags, &pwzStr, 0); TransAssert(pwzStr); // note: _pwzUrl & _pwzFileName may be used later for composing URL // in code base attribute of active document (deleted in destructor) if (pwzStr) { _fMimeReported = 1; _pProtSnk->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, pwzStr); } else { TransAssert((!_pwzMimeSuggested)); } if (pwzStr) { delete [] _pwzMimeSuggested; _pwzMimeSuggested = pwzStr; pwzStr = 0; } if ( _fDocFile && (_dwOInetBdgFlags & PI_DOCFILECLSIDLOOKUP)) { // find the class id and send it on CLSID clsid; HRESULT hr1 = GetClassDocFileBuffer(_pBuffer, _cbBufferFilled, &clsid); if (hr1 == NOERROR) { if (_pwzStrClsId) { delete [] _pwzStrClsId; _pwzStrClsId = NULL; } StringFromCLSID(clsid, &_pwzStrClsId); if (_pwzStrClsId) { _fReportedClassId = TRUE; _pProtSnk->ReportProgress(BINDSTATUS_CLASSIDAVAILABLE, _pwzStrClsId); } } } } } //On a BTS->BTO scenario, we should get into this loop with the lesser of DATASNIFSIZEDOCFILE_MIN or TOTAL_SIZE. //On a BTO scenario, the situation is the same as before, except hr=S_NEEDMOREDATA if sizeReportProgress(BINDSTATUS_CLASSIDAVAILABLE, _pwzStrClsId); } if (IsHandlerAvailable((_pwzFileName) ? _pwzFileName : _pwzUrl, _pwzMimeSuggested, &clsid, _pBuffer, _cbBufferFilled) == S_OK) { _fGotHandler = TRUE; } else if (_fDocFile) { // try get code base + version information // even if handler is installed, a newer version may be required for this doc file hr1 = GetCodeBaseFromDocFile(_pBuffer, _cbBufferFilled, &pwzCodeBase, _pwzUrl, &dwVersionMS, &dwVersionLS); // convert version info. to string if (SUCCEEDED(hr1) && (dwVersionMS || dwVersionLS)) { CHAR szVerInfo[MAX_PATH]; wsprintfA(szVerInfo,"%ld,%ld", dwVersionMS, dwVersionLS); pwzVerInfo = DupA2W(szVerInfo); } // if failed to get codebase, keep sniffing // if we are at end of bits then go with out a code base _fNeedMoreData = FAILED(hr1) && (_cbBufferFilled < _cbDataSniffMin) && (!fEndOfData); } //BUGBUG #51944: This currently requires a DocFile and CodeBase property if (!_fNeedMoreData && !_fGotHandler && _fDocFile && pwzCodeBase) { LPOLESTR pwzClsId = 0; if (!IsEqualCLSID(clsid, CLSID_NULL)) { StringFromCLSID(clsid, &pwzClsId); } else if (_pwzMimeSuggested) { // this is an optimization, if no CLSID and only this as mime type // then we won't find anything in ObjectStore if (!StrCmpNIW(_pwzMimeSuggested, L"application/octet-stream", 24)) { _fGotHandler = TRUE; } } if (!_fGotHandler && (pwzClsId || _pwzMimeSuggested)) { LPWSTR pwzClassStr = 0; int cbClassStr; cbClassStr = (pwzCodeBase ? lstrlenW(pwzCodeBase) : 0) + (pwzClsId ? lstrlenW(pwzClsId) : 0) + (_pwzMimeSuggested ? lstrlenW(_pwzMimeSuggested) : 0) + (pwzVerInfo ? (lstrlenW(pwzVerInfo) + 1) : 0) + 3; pwzClassStr = new WCHAR[cbClassStr]; if (pwzClassStr) { //BUGBUG: This is a bit of a hack, we have a collection of //info to pass into filter, we concatenate it into one long //string and send it in. *pwzClassStr = '\0'; if (pwzCodeBase && *pwzCodeBase) { StrCpyW(pwzClassStr, pwzCodeBase); } StrCatW(pwzClassStr, L"?"); if (pwzClsId) { StrCatW(pwzClassStr, pwzClsId); } else if (_pwzMimeSuggested) { StrCatW(pwzClassStr, _pwzMimeSuggested); } if (pwzVerInfo) { StrCatW(pwzClassStr, L"?"); StrCatW(pwzClassStr, pwzVerInfo); } _pCTrans->ReportProgress(BINDSTATUS_CLASSINSTALLLOCATION, pwzClassStr); delete [] pwzClassStr; // don't process this code branch again _fGotHandler = TRUE; // wait on more data now hr = S_NEEDMOREDATA; // wait on more data for future calls _fWaitOnHandler = TRUE; // wait for more data to sniff _fNeedMoreData = TRUE; } delete [] pwzClsId; } // pwzClsId || _pwzMimeSuggested } // !_fNeedMoreData if (pwzCodeBase) { CoTaskMemFree(pwzCodeBase); } if (pwzVerInfo) { delete [] pwzVerInfo; } // if we don't need to sniff any more, curb _cbDataSniffMin if (_fDocFile && _fGotHandler) { _cbDataSniffMin = (*pdwTotalSize && *pdwTotalSize < DATASNIFSIZEDOCFILE_MIN) ? *pdwTotalSize : DATASNIFSIZEDOCFILE_MIN; } // once we have a handler we can release pwzUrl & pwzFilename if (_fGotHandler) { delete [] _pwzUrl; _pwzUrl = 0; delete [] _pwzFileName; _pwzFileName = 0; } // report the data we have in the buffer or // the available # *pcbBytesAvailable = (*pcbBytesAvailable > _cbTotalBytesRead) ? *pcbBytesAvailable : _cbTotalBytesRead + 1; } // PI_CLASSINSTALL && !_fGotHandler if (*pdwTotalSize && (*pdwTotalSize < *pcbBytesAvailable)) { *pcbBytesAvailable = *pdwTotalSize; } if (hr == S_FALSE) { hr = NOERROR; } } { CLock lck(_mxs); _cbBytesReported = *pcbBytesAvailable; } //TransAssert((pcbBytesAvailable && *pcbBytesAvailable)); //TransAssert((hr == NOERROR || hr == S_NEEDMOREDATA)); PerfDbgLog2(tagCTransaction, this, "-COInetProt::OnDataReceived (hr:%lx, _cbBufferFilled:%ld)", hr, _cbBufferFilled); DEBUG_LEAVE(hr); return hr; } //+--------------------------------------------------------------------------- // // Method: COInetProt::Switch // // Synopsis: // // Arguments: [pStateInfo] -- // // Returns: // // History: 11-07-1996 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP COInetProt::Switch(PROTOCOLDATA *pStateInfo) { DEBUG_ENTER((DBG_TRANS, Hresult, "COInetProt::IInternetProtocolSink::Switch", "this=%#x, %#x", this, pStateInfo )); PerfDbgLog(tagCTransaction, this, "+COInetProt::Switch"); HRESULT hr = NOERROR; hr = _pProtSnk->Switch(pStateInfo); PerfDbgLog1(tagCTransaction, this, "-COInetProt::Switch (hr:%lx)", hr); DEBUG_LEAVE(hr); return hr; } //+--------------------------------------------------------------------------- // // Method: COInetProt::ReportProgress // // Synopsis: // // Arguments: [NotMsg] -- // [szStatusText] -- // // Returns: // // History: 11-07-1996 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP COInetProt::ReportProgress(ULONG NotMsg, LPCWSTR pwzStatusText) { DEBUG_ENTER((DBG_TRANS, Hresult, "COInetProt::IInternetProtocolSink::ReportProgress", "this=%#x, %#x, %.80wq", this, NotMsg, pwzStatusText )); PerfDbgLog(tagCTransaction, this, "+COInetProt::ReportProgress"); HRESULT hr = NOERROR; switch (NotMsg) { case BINDSTATUS_FILTERREPORTMIMETYPE: { if( _pCTrans && pwzStatusText ) { // mime filter sending signal to tell us the true mime type _pCTrans->UpdateVerifiedMimeType(pwzStatusText); } } break; case BINDSTATUS_MIMETYPEAVAILABLE: if (_dwOInetBdgFlags & (PI_MIMEVERIFICATION | PI_DOCFILECLSIDLOOKUP | PI_CLASSINSTALL)) { // report the mime later after sniffing data _pwzMimeSuggested = OLESTRDuplicate(pwzStatusText); } else { hr = _pProtSnk->ReportProgress(NotMsg, pwzStatusText); } break; case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE: { // disable mime sniffing _dwOInetBdgFlags &= (~PI_MIMEVERIFICATION &~PI_DOCFILECLSIDLOOKUP &~PI_CLASSINSTALL); hr = _pProtSnk->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, pwzStatusText); } break; case BINDSTATUS_CACHEFILENAMEAVAILABLE : _pwzFileName = OLESTRDuplicate(pwzStatusText); hr = _pProtSnk->ReportProgress(NotMsg, pwzStatusText); break; case BINDSTATUS_DIRECTBIND: _fMimeVerified = TRUE; break; case BINDSTATUS_ENDDOWNLOADCOMPONENTS : if (_fWaitOnHandler) { // don't stall ReportData any more _fWaitOnHandler = FALSE; // we're done with our stuff, skip sniffing _fNeedMoreData = FALSE; } default: { hr = _pProtSnk->ReportProgress(NotMsg, pwzStatusText); } } // end switch PerfDbgLog1(tagCTransaction, this, "-COInetProt::ReportProgress (hr:%lx)", hr); DEBUG_LEAVE(hr); return hr; } //+--------------------------------------------------------------------------- // // Method: COInetProt::ReportData // // Synopsis: // // Arguments: [grfBSCF] -- // [ULONG] -- // [ulProgressMax] -- // // Returns: // // History: 11-07-1996 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP COInetProt::ReportData(DWORD grfBSCF, ULONG ulProgress,ULONG ulProgressMax) { DEBUG_ENTER((DBG_TRANS, Hresult, "COInetProt::IInternetProtocolSink::ReportData", "this=%#x, %#x, %#x, %#x", this, grfBSCF, ulProgress, ulProgressMax )); PerfDbgLog3(tagCTransaction, this, "+COInetProt::ReportData(grfBSCF:%lx, ulProgress:%ld, ulProgressMax:%ld)", grfBSCF, ulProgress, ulProgressMax); HRESULT hr = NOERROR, hr2; TransAssert((ulProgress)); if ( ((_dwOInetBdgFlags & (PI_MIMEVERIFICATION | PI_DOCFILECLSIDLOOKUP | PI_CLASSINSTALL)) && (!_fMimeVerified || _fNeedMoreData)) || ((_dwOInetBdgFlags & PI_CLASSINSTALL) && !_fClassInstallChecked) ) { if ( (OnDataReceived(&grfBSCF, &ulProgress, &ulProgressMax) == NOERROR) && _pProtSnk && (ulProgress || (!ulProgress && !ulProgressMax)) ) { // OnDataReceived sniffs data and calls Read - EOF with ReportResult might occure //TransAssert((ulProgress)); TransAssert((_fMimeReported)); hr = _pProtSnk->ReportData( grfBSCF, ulProgress, ulProgressMax); } } else { TransAssert((ulProgress)); hr = _pProtSnk->ReportData( grfBSCF, ulProgress, ulProgressMax); } PerfDbgLog1(tagCTransaction, this, "-COInetProt::ReportData (hr:%lx)", hr); DEBUG_LEAVE(hr); return hr; } //+--------------------------------------------------------------------------- // // Method: COInetProt::ReportResult // // Synopsis: // // Arguments: [DWORD] -- // [dwError] -- // [wzResult] -- // // Returns: // // History: 11-07-1996 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP COInetProt::ReportResult(HRESULT hrResult, DWORD dwError, LPCWSTR wzResult) { DEBUG_ENTER((DBG_TRANS, Hresult, "COInetProt::IInternetProtocolSink::ReportResult", "this=%#x, %#x, %#x, %.80wq", this, hrResult, dwError, wzResult )); PerfDbgLog(tagCTransaction, this, "+COInetProt::ReportResult"); HRESULT hr = NOERROR; hr = _pProtSnk->ReportResult(hrResult, dwError, wzResult); PerfDbgLog1(tagCTransaction, this, "-COInetProt::ReportResult (hr:%lx)", hr); DEBUG_LEAVE(hr); return hr; } //+--------------------------------------------------------------------------- // // Method: COInetProt::Initialize // // Synopsis: // // Arguments: [pCTrans] -- // [dwMode] -- // [dwOptions] -- // [pUnk] -- // [pProt] -- // [pProtSnk] -- // // Returns: // // History: 11-07-1996 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP COInetProt::Initialize(CTransaction *pCTrans,IServiceProvider *pSrvPrv, DWORD dwMode, DWORD dwOptions, IUnknown *pUnk, IOInetProtocol *pProt, IOInetProtocolSink *pProtSnk, LPWSTR pwzUrl) { DEBUG_ENTER((DBG_TRANS, Hresult, "COInetProt::Initialize", "this=%#x, %#x, %#x, %#x, %#x, %#x, %#x, %#x, %.80wq", this, pCTrans, pSrvPrv, dwMode, dwOptions, pUnk, pProt, pProtSnk, pwzUrl )); HRESULT hr = NOERROR; _dwMode = dwMode; _pUnk = pUnk; //_pProt = pProt; //_pProtSnk = pProtSnk; _pCTrans = pCTrans; _pSrvPrv = pSrvPrv; if (_pSrvPrv) { _pSrvPrv->AddRef(); } SetProtocolSink(pProtSnk); SetProtocol(pProt); _dwOInetBdgFlags = dwOptions; if (_dwOInetBdgFlags & (PI_MIMEVERIFICATION | PI_DOCFILECLSIDLOOKUP)) { ULONG cbBufferSize; TransAssert(( DATASNIFSIZE_MIN <= DATASNIFSIZEDOCFILE_MIN)); if (_dwOInetBdgFlags & PI_CLASSINSTALL) { cbBufferSize = DATASNIFSIZEDOCFILE_MAX; } else { cbBufferSize = DATASNIFSIZEDOCFILE_MIN; //DATASNIFSIZE_MIN; } if (cbBufferSize != _cbBufferSize) { _cbBufferSize = cbBufferSize; delete [] _pBuffer; _pBuffer = (LPBYTE) new BYTE[_cbBufferSize]; } if (!_pBuffer) { _cbBufferSize = 0; hr = E_OUTOFMEMORY; } else { _cbDataSniffMin = DATASNIFSIZE_MIN; } if (pwzUrl) { delete [] _pwzUrl; _pwzUrl = OLESTRDuplicate(pwzUrl); } } TransAssert((_pProt && _pProtSnk)); DEBUG_LEAVE(hr); return hr; } //+--------------------------------------------------------------------------- // // Method: COInetProt::QueryService // // Synopsis: // // Arguments: [rsid] -- // [riid] -- // [ppvObj] -- // // Returns: // // History: 11-07-1996 JohannP (Johann Posch) Created // // Notes: // //---------------------------------------------------------------------------- HRESULT IUnknown_QueryService(IUnknown* punk, REFGUID rsid, REFIID riid, void ** ppvObj); HRESULT COInetProt::QueryService(REFGUID rsid, REFIID riid, void ** ppvObj) { DEBUG_ENTER((DBG_TRANS, Hresult, "COInetProt::IServiceProvider::QueryService", "this=%#x, %#x, %#x, %#x", this, &rsid, &riid, ppvObj )); PerfDbgLog(tagCTransaction, this, "+COInetProt::QueryService"); HRESULT hr = NOERROR; VDATETHIS(this); TransAssert((ppvObj)); if (_pSrvPrv) { hr = _pSrvPrv->QueryService(rsid,riid, ppvObj); } else { hr = IUnknown_QueryService(_pProtSnk, rsid, riid, ppvObj); } TransAssert(( ((hr == E_NOINTERFACE) && !*ppvObj) || ((hr == NOERROR) && *ppvObj) )); PerfDbgLog1(tagCTransaction, this, "-COInetProt::QueryService (hr:%lx)", hr); DEBUG_LEAVE(hr); return hr; } STDMETHODIMP COInetProt::SetPriority(LONG nPriority) { DEBUG_ENTER((DBG_TRANS, Hresult, "COInetProt::IInternetPriority::SetPriority", "this=%#x, %#x", this, nPriority )); PerfDbgLog1(tagCTransaction, this, "+COInetProt::SetPriority (%ld)", nPriority); HRESULT hr = S_OK; _nPriority = nPriority; PerfDbgLog1(tagCTransaction, this, "-COInetProt::SetPriority (hr:%lx)", hr); DEBUG_LEAVE(hr); return hr; } STDMETHODIMP COInetProt::GetPriority(LONG * pnPriority) { DEBUG_ENTER((DBG_TRANS, Hresult, "COInetProt::IInternetPriority::GetPriority", "this=%#x, %#x", this, pnPriority )); PerfDbgLog(tagCTransaction, this, "+COInetProt::GetPriority"); HRESULT hr; if (!pnPriority) { hr = E_INVALIDARG; } else { *pnPriority = _nPriority; hr = S_OK; } PerfDbgLog1(tagCTransaction, this, "-COInetProt::GetPriority (hr:%lx)", hr); DEBUG_LEAVE(hr); return hr; }