You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
5164 lines
147 KiB
5164 lines
147 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// 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 <trans.h>
|
|
#include "oinet.hxx"
|
|
|
|
static CHAR gwzAcceptEncHeaders[] = "Accept-Encoding: gzip, deflate";
|
|
extern BOOL g_bHasMimeHandlerForTextHtml;
|
|
|
|
extern IInternetSecurityManager* g_pSecurityManager;
|
|
extern CMutexSem g_mxsSession;
|
|
|
|
PerfDbgExtern(tagCTransaction);
|
|
DbgExtern(tagCTransactionErr);
|
|
|
|
HRESULT GetClassDocFileBuffer(LPVOID pbuffer, DWORD dwSize, CLSID *pclsid);
|
|
extern DWORD g_dwSettings;
|
|
|
|
#if DBG==1
|
|
|
|
#else
|
|
#define USE_NOTIFICATION_EXCEPTION_FILTER //Not in this lifetime
|
|
#endif //
|
|
|
|
|
|
#define szHKSniffFlag "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
|
|
#define szHKSniffValue "SniffDocFile"
|
|
|
|
BOOL IsSpecialUrl(WCHAR *pchURL);
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransData::QueryInterface
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [riid] --
|
|
// [ppvObj] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-27-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CTransaction::QueryInterface(REFIID riid, void **ppvObj)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::IUnknown::QueryInterface",
|
|
"this=%#x, %#x, %#x",
|
|
this, &riid, ppvObj
|
|
));
|
|
|
|
VDATEPTROUT(ppvObj, void *);
|
|
VDATETHIS(this);
|
|
HRESULT hr = NOERROR;
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::QueryInterface");
|
|
|
|
*ppvObj = NULL;
|
|
hr = _pUnkOuter->QueryInterface(riid, ppvObj);
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::QueryInterface (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CTransaction::AddRef
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [ULONG] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-27-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG) CTransaction::AddRef(void)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Dword,
|
|
"CTransaction::IUnknown::AddRef",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
LONG lRet = ++_CRefs;
|
|
PerfDbgLog1(tagCTransaction, this, "CTransaction::AddRef (cRefs:%ld)", lRet);
|
|
|
|
DEBUG_LEAVE(lRet);
|
|
return lRet;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CTransaction::Release
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [ULONG] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-27-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG) CTransaction::Release(void)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Dword,
|
|
"CTransaction::IUnknown::Release",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::Release");
|
|
|
|
LONG lRet = --_CRefs;
|
|
|
|
if (_CRefs == 0)
|
|
{
|
|
delete this;
|
|
}
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::Release (cRefs:%ld)", lRet);
|
|
|
|
DEBUG_LEAVE(lRet);
|
|
return lRet;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::Switch
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pStateInfo] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 11-07-1996 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CTransaction::Switch(PROTOCOLDATA *pStateInfo)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::IInternetProtocolSink::Switch",
|
|
"this=%#x, %#x",
|
|
this, pStateInfo
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::Switch");
|
|
HRESULT hr = NOERROR;
|
|
|
|
DWORD grfFlags = pStateInfo->grfFlags;
|
|
AddRef();
|
|
|
|
if (IsFreeThreaded())
|
|
{
|
|
if (grfFlags & PD_FORCE_SWITCH)
|
|
{
|
|
CTransPacket * pCTP = new CTransPacket(pStateInfo);
|
|
|
|
if (pCTP)
|
|
{
|
|
hr = _pClntProtSink->Switch(pCTP);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// handle request on this thread
|
|
_pProt->Continue(pStateInfo);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CTransPacket *pCTP = new CTransPacket(pStateInfo);
|
|
|
|
if (pCTP)
|
|
{
|
|
AddCTransPacket(pCTP);
|
|
|
|
if ((grfFlags & PI_FORCE_ASYNC) || !IsApartmentThread())
|
|
{
|
|
_cPostedMsg++;
|
|
AddRef();
|
|
/****
|
|
PerfDbgLog4(tagCTransaction, this, "CINet:%lx === PostMessage (Msg:%#x) WM_TRANS_PACKET - dwCurrentSize:%ld, dwTotalSize:%ld",
|
|
_pProt, XDBG(++_wTotalPostedMsg,0), pCTP->_dwCurrentSize, pCTP->_dwTotalSize);
|
|
****/
|
|
PostMessage(_hwndNotify, WM_TRANS_PACKET, (WPARAM) (WPARAM)GetTotalPostedMsgId(), (LPARAM)this);
|
|
}
|
|
else
|
|
{
|
|
OnINetCallback();
|
|
}
|
|
}
|
|
}
|
|
Release();
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::Switch (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::ReportProgress
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [NotMsg] --
|
|
// [szStatusText] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 11-07-1996 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CTransaction::ReportProgress(ULONG NotMsg, LPCWSTR szStatusText)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::IInternetProtocolSink::ReportProgress",
|
|
"this=%#x, %#x, %.80wq",
|
|
this, NotMsg, szStatusText
|
|
));
|
|
|
|
|
|
AddRef();
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::ReportProgress");
|
|
HRESULT hr = NOERROR;
|
|
|
|
if (PreDispatch() != S_OK)
|
|
{
|
|
// nothing to do any more!
|
|
}
|
|
else if (IsFreeThreaded())
|
|
{
|
|
// handle request on this thread
|
|
hr = DispatchReport((BINDSTATUS) NotMsg, _grfBSCF, _ulCurrentSize, _ulTotalSize, (LPWSTR)szStatusText, 0);
|
|
}
|
|
else
|
|
{
|
|
CTransPacket *pCTP = new CTransPacket( (BINDSTATUS) NotMsg, NOERROR, szStatusText, _ulCurrentSize, _ulTotalSize);
|
|
|
|
if (pCTP)
|
|
{
|
|
#if DBG==1
|
|
DWORD dwCurrentSizePerf = pCTP->_dwCurrentSize;
|
|
DWORD dwTotalSizePerf = pCTP->_dwTotalSize;
|
|
#elif defined(PERFTAGS)
|
|
DWORD dwCurrentSizePerf = pCTP->_dwCurrentSize;
|
|
DWORD dwTotalSizePerf = pCTP->_dwTotalSize;
|
|
#endif
|
|
|
|
//BUGBUG: this is a hack where small doc files are loaded in one swipe and
|
|
//the class install filter is not loaded because an BINDSTATUS_ENDDOWNLOAD
|
|
//already occurs in transaction packet list.
|
|
if (NotMsg == BINDSTATUS_CLASSINSTALLLOCATION)
|
|
{
|
|
AddCTransPacket(pCTP, FALSE);
|
|
}
|
|
else
|
|
{
|
|
AddCTransPacket(pCTP);
|
|
}
|
|
|
|
if (!IsApartmentThread())
|
|
{
|
|
_cPostedMsg++;
|
|
AddRef();
|
|
PerfDbgLog4(tagCTransaction, this, "CINet:%lx === PostMessage (Msg:%#x) WM_TRANS_PACKET - dwCurrentSize:%ld, dwTotalSize:%ld",
|
|
_pProt, XDBG(++_wTotalPostedMsg,0), dwCurrentSizePerf, dwTotalSizePerf);
|
|
PostMessage(_hwndNotify, WM_TRANS_PACKET, (WPARAM)GetTotalPostedMsgId(), (LPARAM)this);
|
|
|
|
}
|
|
else
|
|
{
|
|
OnINetCallback();
|
|
}
|
|
}
|
|
}
|
|
|
|
PostDispatch();
|
|
|
|
Release();
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::ReportProgress (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::ReportData
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [grfBSCF] --
|
|
// [ULONG] --
|
|
// [ulProgressMax] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 11-07-1996 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CTransaction::ReportData(DWORD grfBSCF, ULONG ulProgress,ULONG ulProgressMax)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::IInternetProtocolSink::ReportData",
|
|
"this=%#x, %#x, %u, %u",
|
|
this, grfBSCF, ulProgress, ulProgressMax
|
|
));
|
|
|
|
|
|
PerfDbgLog3(tagCTransaction, this, "+CTransaction::ReportData(grfBSCF:%lx, ulProgress:%ld, ulProgressMax:%ld)",
|
|
grfBSCF, ulProgress, ulProgressMax);
|
|
|
|
HRESULT hr = NOERROR;
|
|
BOOL fAsync = FALSE;
|
|
|
|
BINDSTATUS bndStatus = BINDSTATUS_DOWNLOADINGDATA;
|
|
AddRef();
|
|
|
|
if ( (PreDispatch() == S_OK)
|
|
&& ( (_ulCurrentSize <= ulProgress)
|
|
|| ( (grfBSCF & BSCF_LASTDATANOTIFICATION)
|
|
&& !(_grfBSCF & BSCF_LASTDATANOTIFICATION))
|
|
|| (grfBSCF & BSCF_ASYNCDATANOTIFICATION)
|
|
))
|
|
{
|
|
|
|
if (grfBSCF & BSCF_FIRSTDATANOTIFICATION)
|
|
{
|
|
bndStatus = BINDSTATUS_BEGINDOWNLOADDATA;
|
|
_grfBSCF |= BSCF_FIRSTDATANOTIFICATION;
|
|
}
|
|
|
|
if (grfBSCF & BSCF_LASTDATANOTIFICATION)
|
|
{
|
|
bndStatus = BINDSTATUS_ENDDOWNLOADDATA;
|
|
_grfBSCF |= BSCF_LASTDATANOTIFICATION;
|
|
}
|
|
|
|
if (grfBSCF & BSCF_DATAFULLYAVAILABLE)
|
|
{
|
|
_grfBSCF |= BSCF_DATAFULLYAVAILABLE;
|
|
}
|
|
|
|
if (grfBSCF & BSCF_ASYNCDATANOTIFICATION)
|
|
{
|
|
fAsync = TRUE;
|
|
}
|
|
|
|
_ulCurrentSize = ulProgress;
|
|
_ulTotalSize = ulProgressMax;
|
|
TransAssert(( (_ulTotalSize == 0)
|
|
|| (_ulCurrentSize <= _ulTotalSize) ));
|
|
|
|
if (IsFreeThreaded())
|
|
{
|
|
hr = DispatchReport(bndStatus, _grfBSCF, _ulCurrentSize, _ulTotalSize, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
CTransPacket *pCTP = new CTransPacket(bndStatus, NOERROR, NULL, _ulCurrentSize, _ulTotalSize);
|
|
|
|
if (pCTP)
|
|
{
|
|
#if DBG==1
|
|
DWORD dwCurrentSizePerf = pCTP->_dwCurrentSize;
|
|
DWORD dwTotalSizePerf = pCTP->_dwTotalSize;
|
|
#elif defined(PERFTAGS)
|
|
DWORD dwCurrentSizePerf = pCTP->_dwCurrentSize;
|
|
DWORD dwTotalSizePerf = pCTP->_dwTotalSize;
|
|
#endif
|
|
AddCTransPacket(pCTP);
|
|
|
|
if (!IsApartmentThread() || fAsync)
|
|
{
|
|
_cPostedMsg++;
|
|
AddRef();
|
|
PerfDbgLog4(tagCTransaction, this, "CINet:%lx === PostMessage (Msg:%#x) WM_TRANS_PACKET - dwCurrentSize:%ld, dwTotalSize:%ld",
|
|
_pProt, XDBG(++_wTotalPostedMsg,0), dwCurrentSizePerf, dwTotalSizePerf);
|
|
PostMessage(_hwndNotify, WM_TRANS_PACKET, (WPARAM) (WPARAM)GetTotalPostedMsgId(), (LPARAM)this);
|
|
|
|
}
|
|
else
|
|
{
|
|
OnINetCallback();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
PostDispatch();
|
|
|
|
Release();
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::ReportData (hr:%lx)", 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 CTransaction::OnDataReceived(DWORD *pgrfBSC, DWORD *pcbBytesAvailable, DWORD *pdwTotalSize) //, DWORD *pcbNewAvailable)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::OnDataReceived",
|
|
"this=%#x, %#x, %#x, %#x",
|
|
this, pgrfBSC, pcbBytesAvailable, pdwTotalSize
|
|
));
|
|
|
|
PerfDbgLog3(tagCTransaction, this, "+CTransaction::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;
|
|
|
|
do
|
|
{
|
|
// check if mimeverification was requested
|
|
//
|
|
if (!(_dwOInetBdgFlags & (PI_MIMEVERIFICATION | PI_DOCFILECLSIDLOOKUP)) )
|
|
{
|
|
break;
|
|
}
|
|
// get the buffer
|
|
//
|
|
if (!_pBuffer)
|
|
{
|
|
_cbBufferSize = DATASNIFSIZEDOCFILE_MIN; //DATASNIFSIZE_MIN;
|
|
_pBuffer = (LPBYTE) new BYTE[_cbBufferSize];
|
|
}
|
|
if (!_pBuffer)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
|
|
|
|
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;
|
|
LPWSTR pwzStr = 0;
|
|
FindMimeFromData(NULL, _pwzFileName,_pBuffer, _cbBufferFilled, _pwzMimeSuggested, 0, &pwzStr, 0);
|
|
|
|
if (pwzStr)
|
|
{
|
|
_pClntProtSink->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)
|
|
{
|
|
LPOLESTR pwzStrClsId;
|
|
StringFromCLSID(clsid, &pwzStrClsId);
|
|
if (pwzStrClsId)
|
|
{
|
|
_pClntProtSink->ReportProgress(BINDSTATUS_CLASSIDAVAILABLE, pwzStrClsId);
|
|
}
|
|
delete [] pwzStrClsId;
|
|
}
|
|
}
|
|
delete [] pwzStr;
|
|
|
|
}
|
|
hr = NOERROR;
|
|
}
|
|
//TransAssert((cbBytesAvailable <= *pcbNewAvailable));
|
|
if (cbBytesAvailable > *pcbNewAvailable)
|
|
{
|
|
*pcbNewAvailable = cbBytesAvailable;
|
|
}
|
|
if (dwTotalSize && (dwTotalSize < *pcbNewAvailable))
|
|
{
|
|
*pcbNewAvailable = dwTotalSize;
|
|
}
|
|
|
|
break;
|
|
} while (TRUE);
|
|
|
|
{
|
|
CLock lck(_mxs);
|
|
_cbBytesReported = *pcbNewAvailable;
|
|
*pdwTotalSize = dwTotalSize;
|
|
}
|
|
|
|
PerfDbgLog2(tagCTransaction, this, "-CTransaction::OnDataReceived (hr:%lx, _cbBufferFilled:%lx)", hr, _cbBufferFilled);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::ReportResult
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [DWORD] --
|
|
// [dwError] --
|
|
// [wzResult] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 11-07-1996 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CTransaction::ReportResult(HRESULT hrResult, DWORD dwError, LPCWSTR wzResult)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::IInternetProtocolSink::ReportResult",
|
|
"this=%#x, %#x, %#x, %.80wq",
|
|
this, hrResult, dwError, wzResult
|
|
));
|
|
|
|
PerfDbgLog3(tagCTransaction, this, "+CTransaction::ReportResult [hr:%lX, dwError;%lX (%ld)]", hrResult, dwError, dwError);
|
|
HRESULT hr = NOERROR;
|
|
|
|
AddRef();
|
|
|
|
BOOL fReport = FALSE;
|
|
|
|
{ //BEGIN SYNC BLOCK
|
|
CLock lck(_mxsBind);
|
|
if (!_fResultReported)
|
|
{
|
|
_fResultReported = TRUE;
|
|
fReport = TRUE;
|
|
}
|
|
} // END SYNC BLOCK
|
|
|
|
if (fReport)
|
|
{
|
|
_hrResult = hrResult;
|
|
_dwResult = dwError;
|
|
|
|
if (_pwzResult)
|
|
{
|
|
delete [] _pwzResult;
|
|
}
|
|
_pwzResult = OLESTRDuplicate((LPWSTR)wzResult);
|
|
|
|
if (IsFreeThreaded())
|
|
{
|
|
|
|
// handle request on this thread
|
|
hr = DispatchReport(BINDSTATUS_RESULT, _grfBSCF, _ulCurrentSize, _ulTotalSize, _pwzResult, _dwResult, _hrResult);
|
|
}
|
|
else
|
|
{
|
|
CTransPacket *pCTP = new CTransPacket( (BINDSTATUS) ((_hrResult == NOERROR) ? BINDSTATUS_RESULT : BINDSTATUS_ERROR),
|
|
_hrResult, _pwzResult, _ulCurrentSize, _ulTotalSize, _dwResult);
|
|
|
|
if (pCTP)
|
|
{
|
|
#if DBG==1
|
|
DWORD dwCurrentSizePerf = pCTP->_dwCurrentSize;
|
|
DWORD dwTotalSizePerf = pCTP->_dwTotalSize;
|
|
#elif defined(PERFTAGS)
|
|
DWORD dwCurrentSizePerf = pCTP->_dwCurrentSize;
|
|
DWORD dwTotalSizePerf = pCTP->_dwTotalSize;
|
|
#endif
|
|
AddCTransPacket(pCTP);
|
|
|
|
if (!IsApartmentThread() ||
|
|
_fForceAsyncReportResult ||
|
|
((_hrResult==INET_E_REDIRECTING) && (_dwOInetBdgFlags & PI_SYNCHRONOUS)))
|
|
{
|
|
_cPostedMsg++;
|
|
AddRef();
|
|
PerfDbgLog4(tagCTransaction, this, "CINet:%lx === PostMessage (Msg:%#x) WM_TRANS_PACKET - dwCurrentSize:%ld, dwTotalSize:%ld",
|
|
_pProt, XDBG(++_wTotalPostedMsg,0), dwCurrentSizePerf, dwTotalSizePerf);
|
|
PostMessage(_hwndNotify, WM_TRANS_PACKET, (WPARAM) (WPARAM)GetTotalPostedMsgId(), (LPARAM)this);
|
|
|
|
}
|
|
else
|
|
{
|
|
OnINetCallback();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// should not happen with our protocols
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
Release();
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::ReportResult (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::QueryBindFlags
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [DWORD* ] -- emits binding flags
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 04-07-2000 RajeevD (Rajeev Dujari) Created
|
|
//
|
|
// Notes: Hack for netdocs to grab binding flags.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CTransaction::QueryBindFlags (DWORD* pdwFlags)
|
|
{
|
|
*pdwFlags = _dwOInetBdgFlags;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// protocolinfo methods
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::Authenticate
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [phwnd] --
|
|
// [LPWSTR] --
|
|
// [pszPassword] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 11-07-1996 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CTransaction::Authenticate(HWND* phwnd, LPWSTR *pszUsername,LPWSTR *pszPassword)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::IAuthenticate::Authenticate",
|
|
"this=%#x, %#x, %#x, %#x",
|
|
this, phwnd, pszUsername, pszPassword
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::Authenticate");
|
|
HRESULT hr = E_FAIL;
|
|
IAuthenticate *pBasicAuth = 0;
|
|
|
|
AddRef();
|
|
hr = QueryService(IID_IAuthenticate,IID_IAuthenticate, (void **) &pBasicAuth);
|
|
|
|
if ((hr == NOERROR) && pBasicAuth)
|
|
{
|
|
hr = pBasicAuth->Authenticate(phwnd, pszUsername,pszPassword);
|
|
}
|
|
else
|
|
{
|
|
UrlMkAssert((pBasicAuth == NULL));
|
|
*phwnd = 0;
|
|
*pszUsername = 0;
|
|
*pszPassword = 0;
|
|
}
|
|
Release();
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::Authenticate (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::QueryOption
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [dwOption] --
|
|
// [pBuffer] --
|
|
// [pcbBuf] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 11-07-1996 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CTransaction::QueryOption(DWORD dwOption, LPVOID pBuffer, DWORD *pcbBuf)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::QueryOption",
|
|
"this=%#x, %#x, %#x, %#x",
|
|
this, dwOption, pBuffer, pcbBuf
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::QueryOption");
|
|
HRESULT hr = E_FAIL;
|
|
if (_pProt)
|
|
{
|
|
if (!_pInetInfo)
|
|
{
|
|
hr = _pProt->QueryInterface(IID_IWinInetInfo, (void **) &_pInetInfo);
|
|
TransAssert(( (hr == NOERROR && _pInetInfo) || (hr != NOERROR && !_pInetInfo) ));
|
|
if ((hr == NOERROR) && _pUnkInner)
|
|
{
|
|
Release();
|
|
}
|
|
|
|
}
|
|
|
|
if (_pInetInfo)
|
|
{
|
|
|
|
hr = _pInetInfo->QueryOption(dwOption, pBuffer, pcbBuf);
|
|
}
|
|
}
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::QueryOption (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::QueryInfo
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [dwOption] --
|
|
// [pBuffer] --
|
|
// [pcbBuf] --
|
|
// [pdwFlags] --
|
|
// [pdwReserved] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 11-07-1996 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CTransaction::QueryInfo(DWORD dwOption, LPVOID pBuffer, DWORD *pcbBuf, DWORD *pdwFlags, DWORD *pdwReserved)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::QueryInfo",
|
|
"this=%#x, %#x, %#x, %#x, %#x, %#x",
|
|
this, dwOption, pBuffer, pcbBuf, pdwFlags, pdwReserved
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::QueryInfo");
|
|
HRESULT hr = E_FAIL;
|
|
if (_pProt)
|
|
{
|
|
if (!_pInetHttpInfo)
|
|
{
|
|
hr = _pProt->QueryInterface(IID_IWinInetHttpInfo, (void **) &_pInetHttpInfo);
|
|
TransAssert(( (hr == NOERROR && _pInetHttpInfo) || (hr != NOERROR && !_pInetHttpInfo) ));
|
|
if ((hr == NOERROR) && _pUnkInner)
|
|
{
|
|
Release();
|
|
}
|
|
|
|
}
|
|
if (_pInetHttpInfo)
|
|
{
|
|
hr = _pInetHttpInfo->QueryInfo(dwOption, pBuffer, pcbBuf, pdwFlags, pdwReserved);
|
|
}
|
|
}
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::QueryInfo (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//IOInetBindInfo methods
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::GetBindInfo
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pdwBINDF] --
|
|
// [pbindinfo] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 11-07-1996 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CTransaction::GetBindInfo(DWORD *pdwBINDF, BINDINFO *pbindinfo)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::IInternetBindInfo::GetBindInfo",
|
|
"this=%#x, %#x, %#x",
|
|
this, pdwBINDF, pbindinfo
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::GetBindInfo");
|
|
HRESULT hr = NOERROR;
|
|
|
|
TransAssert((pdwBINDF && pbindinfo));
|
|
|
|
TransAssert((_pClntBindInfo));
|
|
hr = _pClntBindInfo->GetBindInfo(pdwBINDF, pbindinfo);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
PerfDbgLog(tagCTransaction, this, "---CTrans::BINDF_FROMURLMON---");
|
|
*pdwBINDF |= BINDF_FROMURLMON;
|
|
}
|
|
|
|
// never do a post on redirect
|
|
if (_pwzRedirectUrl)
|
|
{
|
|
if( pbindinfo && (pbindinfo->dwBindVerb == BINDVERB_POST) )
|
|
{
|
|
pbindinfo->dwBindVerb = BINDVERB_GET;
|
|
}
|
|
}
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::GetBindInfo (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::GetBindString
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [ulStringType] --
|
|
// [ppwzStr] --
|
|
// [cEl] --
|
|
// [pcElFetched] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 11-07-1996 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CTransaction::GetBindString(ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::IInternetBindInfo::GetBindString",
|
|
"this=%#x, %#x, #%#x, %u, %#x",
|
|
this, ulStringType, ppwzStr, cEl, pcElFetched
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::GetBindString");
|
|
HRESULT hr = INET_E_USE_DEFAULT_SETTING;
|
|
|
|
// we handles the encoding here
|
|
|
|
if ( _fEncodingHandlerEnabled
|
|
&& ulStringType == BINDSTRING_ACCEPT_ENCODINGS
|
|
&& ppwzStr
|
|
&& cEl )
|
|
{
|
|
LPWSTR pwzAcpHeaders = NULL;
|
|
pwzAcpHeaders = DupA2W(gwzAcceptEncHeaders);
|
|
|
|
if( pwzAcpHeaders )
|
|
{
|
|
*ppwzStr = pwzAcpHeaders;
|
|
*pcElFetched = 1;
|
|
hr = NOERROR;
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
*pcElFetched = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
TransAssert((_pClntBindInfo));
|
|
|
|
hr = _pClntBindInfo->GetBindString(ulStringType, ppwzStr, cEl, pcElFetched);
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::GetBindString (hr:%lx)", hr);
|
|
}
|
|
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::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 CTransaction::QueryService(REFGUID rsid, REFIID riid, void ** ppvObj)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::IServiceProvider::QueryService",
|
|
"this=%#x, %#x, %#x, %#x",
|
|
this, &rsid, &riid, ppvObj
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::QueryService");
|
|
HRESULT hr = NOERROR;
|
|
VDATETHIS(this);
|
|
TransAssert((ppvObj));
|
|
|
|
hr = IUnknown_QueryService(_pClntProtSink, rsid, riid, ppvObj);
|
|
|
|
TransAssert(( ((hr == E_NOINTERFACE) && !*ppvObj) || ((hr == NOERROR) && *ppvObj) ));
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::QueryService (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::CTransaction
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: (none)
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 12-11-95 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CTransaction::CTransaction(DWORD grfFlags, LPBYTE pByte, ULONG cbSizeBuffer, IUnknown *pUnkOuter)
|
|
: _CRefs(), _cPacketsInList(0), _cPostedMsg(0)
|
|
, _CProtEmbed(), _CProtClsInstaller()
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
None,
|
|
"CTransaction::CTransaction",
|
|
"this=%#x, %#x, %#x, %#x, %#x",
|
|
this, grfFlags, pByte, cbSizeBuffer, pUnkOuter
|
|
));
|
|
|
|
_flags = 0;
|
|
|
|
if (!pUnkOuter)
|
|
{
|
|
pUnkOuter = &_Unknown;
|
|
}
|
|
_pUnkOuter = pUnkOuter;
|
|
|
|
|
|
_pCTransNext = NULL;
|
|
_pClntProtSink = NULL;
|
|
_hwndNotify = NULL;
|
|
_pCTransMgr = GetThreadTransactionMgr();
|
|
_State = TransSt_None;
|
|
_cBdgRefs = 0;
|
|
_pCTPHead = NULL;
|
|
_pCTPTail = NULL;
|
|
_pCTPCur = NULL;
|
|
_fDispatch = FALSE;
|
|
_ThreadTransferState = TS_None;
|
|
_fResultReported = FALSE;
|
|
_fTerminated = FALSE;
|
|
_fTerminating = FALSE;
|
|
_fResultDispatched = FALSE;
|
|
_fResultReceived = TRUE;
|
|
_hrResult = NOERROR;
|
|
_dwResult = 0;
|
|
_dwPacketsTotal = 0;
|
|
_grfInternalFlags = 0;
|
|
_pProt = NULL;
|
|
_clsidProtocol = CLSID_NULL;
|
|
_pBndInfo = NULL;
|
|
_pInetInfo = NULL;
|
|
_pInetHttpInfo = NULL;
|
|
_pBndCtx = NULL;
|
|
_dwThreadId = GetCurrentThreadId();
|
|
_dwProcessId = GetCurrentProcessId();
|
|
_grfBSCF = 0;
|
|
_pUnkInner = 0;
|
|
_dwOInetBdgFlags = grfFlags;
|
|
|
|
_pBuffer = pByte; // DNLD_BUFFER_SIZE size buffer
|
|
_cbBufferSize = cbSizeBuffer;
|
|
_cbTotalBytesRead = 0 ;
|
|
_cbBufferFilled = 0; //how much of the buffer is in use
|
|
_pwzUrl = 0;
|
|
_pwzRedirectUrl = 0;
|
|
_dwTerminateOptions = 0;
|
|
_cbDataSniffMin = DATASNIFSIZE_MIN;
|
|
_fDocFile = FALSE;
|
|
_fMimeVerified = FALSE;
|
|
_fAttached = FALSE;
|
|
_fLocked = FALSE;
|
|
_fModalLoopRunning = FALSE;
|
|
_fUnlocked = FALSE;
|
|
_fMimeHandlerEnabled = TRUE;
|
|
_fEncodingHandlerEnabled = TRUE;
|
|
_fClsInstallerHandlerEnabled = TRUE;
|
|
_fMimeHandlerLoaded = FALSE;
|
|
_pwzFileName = 0;
|
|
_pwzAttachmentName = 0;
|
|
_pwzMimeSuggested = 0;
|
|
_fProtEmbed = TRUE;
|
|
_fStarting = FALSE;
|
|
_fReceivedAbort = FALSE;
|
|
_fReceivedTerminate = FALSE;
|
|
_hrAbort = NOERROR;
|
|
_dwAbort = 0;
|
|
_dwDispatchLevel = 0;
|
|
_fForceAsyncReportResult = FALSE;
|
|
_fPreferDefaultHandler = FALSE;
|
|
_pwzResult = NULL;
|
|
|
|
#if DBG==1
|
|
_wTotalPostedMsg = 0;
|
|
#endif
|
|
_pClntBindInfo = 0;
|
|
|
|
_nPriority = THREAD_PRIORITY_NORMAL;
|
|
|
|
_fContentDispositionAttach = FALSE;
|
|
_fAcceptRanges = FALSE;
|
|
|
|
DEBUG_LEAVE(0);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::~CTransaction
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: (none)
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 12-11-95 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CTransaction::~CTransaction()
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
None,
|
|
"CTransaction::~CTransaction",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "+CTransaction::~CTransaction [Url:%ws]", _pwzUrl);
|
|
|
|
if (_fLocked && _pProt)
|
|
{
|
|
_pProt->UnlockRequest();
|
|
}
|
|
|
|
if (_pBuffer)
|
|
{
|
|
delete [] _pBuffer;
|
|
}
|
|
|
|
if (_pwzRedirectUrl)
|
|
{
|
|
delete [] _pwzRedirectUrl;
|
|
}
|
|
|
|
if (_pwzUrl)
|
|
{
|
|
delete [] _pwzUrl;
|
|
}
|
|
|
|
if (_pwzFileName)
|
|
{
|
|
delete [] _pwzFileName;
|
|
}
|
|
|
|
if (_pwzAttachmentName)
|
|
{
|
|
delete [] _pwzAttachmentName;
|
|
}
|
|
|
|
if (_pwzMimeSuggested)
|
|
{
|
|
delete [] _pwzMimeSuggested;
|
|
}
|
|
|
|
if (_pwzProtClsId)
|
|
{
|
|
delete [] _pwzProtClsId;
|
|
}
|
|
|
|
if (_pwzResult)
|
|
{
|
|
delete [] _pwzResult;
|
|
}
|
|
|
|
// Remove ourselves from the global internet transaction list.
|
|
// We should always be in the list.
|
|
if (_pCTransMgr)
|
|
{
|
|
_pCTransMgr->RemoveTransaction(this);
|
|
_pCTransMgr = NULL;
|
|
}
|
|
|
|
// Release any leftover packets
|
|
|
|
while (_pCTPHead)
|
|
{
|
|
CTransPacket * pCTP = _pCTPHead;
|
|
_pCTPHead = pCTP->GetNext();
|
|
delete pCTP;
|
|
}
|
|
|
|
if (_pBndCtx)
|
|
{
|
|
_pBndCtx->Release();
|
|
}
|
|
|
|
if (_pClntBindInfo)
|
|
{
|
|
_pClntBindInfo->Release();
|
|
_pClntBindInfo = 0;
|
|
}
|
|
|
|
if (_pClntProtSink)
|
|
{
|
|
_pClntProtSink->Release();
|
|
}
|
|
|
|
if (_pProt && !_pUnkInner)
|
|
{
|
|
_pProt->Release();
|
|
}
|
|
_pProt = NULL;
|
|
|
|
if (_pInetInfo && !_pUnkInner)
|
|
{
|
|
_pInetInfo->Release();
|
|
}
|
|
_pInetInfo = NULL;
|
|
|
|
if (_pInetHttpInfo && !_pUnkInner)
|
|
{
|
|
_pInetHttpInfo->Release();
|
|
}
|
|
_pInetHttpInfo = NULL;
|
|
|
|
if (_pUnkInner)
|
|
{
|
|
PerfDbgLog1(tagCTransaction, this, "+CTransaction::~CTransaction release pUnkInner (pCINet:%lx)", _pProt);
|
|
_pUnkInner->Release();
|
|
_pUnkInner = NULL;
|
|
}
|
|
|
|
if (_pBndInfo)
|
|
{
|
|
// BINDINFO_FIX(laszlog) 8-18-96
|
|
|
|
#if DBG == 1
|
|
if (_pBndInfo->stgmedData.tymed != TYMED_NULL)
|
|
{
|
|
PerfDbgLog1(tagCTransaction, this, "+CTransaction::~CTransaction ReleaseStgMedium (%lx)", _pBndInfo->stgmedData);
|
|
}
|
|
#endif
|
|
|
|
ReleaseBindInfo(_pBndInfo);
|
|
|
|
delete _pBndInfo;
|
|
}
|
|
|
|
PerfDbgLog(tagCTransaction, this, "-CTransaction::~CTransaction");
|
|
|
|
DEBUG_LEAVE(0);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::Create
|
|
//
|
|
// Synopsis: Creates and initializes a new transaction object
|
|
//
|
|
// Arguments: [pCBdg] --
|
|
// [fConvertData] --
|
|
// [ppCTrans] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 12-07-95 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CTransaction::Create(IBindCtx *pBC, DWORD grfFlags, IUnknown *pUnkOuter, IUnknown **ppUnk, CTransaction **ppCTrans)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::Create",
|
|
"%#x, %#x, %#x, %#x, %#x",
|
|
pBC, grfFlags, pUnkOuter, ppUnk, ppCTrans
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, NULL, "+CTransaction::Create");
|
|
|
|
HRESULT hr = NOERROR;
|
|
TransAssert((ppCTrans != NULL));
|
|
|
|
// Create the object
|
|
CTransaction *pCTrans = new CTransaction(grfFlags, NULL, 0, pUnkOuter);
|
|
|
|
if (pCTrans)
|
|
{
|
|
// notification window is needed for apartment threaded case
|
|
if ( (grfFlags & OIBDG_APARTMENTTHREADED )
|
|
&& (pCTrans->GetNotificationWnd() == NULL))
|
|
{
|
|
delete pCTrans;
|
|
*ppCTrans = NULL;
|
|
hr = E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
// set the cbinding assosiated with it
|
|
pCTrans->SetState(TransSt_Initialized);
|
|
*ppCTrans = pCTrans;
|
|
|
|
// pCTrans has refcount of 1 now
|
|
// get the pUnkInner; pUnkInner does not addref pUnkOuter
|
|
if (pUnkOuter && ppUnk)
|
|
{
|
|
*ppUnk = pCTrans->GetIUnkInner();
|
|
// addref the outer object since releasing pCINet will go cause a release on pUnkOuter
|
|
PProtAssert((*ppUnk));
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
PerfDbgLog1(tagCTransaction, NULL, "-CTransaction::Create (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::GetTransBindInfo
|
|
//
|
|
// Synopsis: Get the transaction bindinfo
|
|
// Called to pass bindinfo on in IBSC::GetBindInfo and
|
|
// also called by CINet
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-16-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BINDINFO *CTransaction::GetTransBindInfo()
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Pointer,
|
|
"CTransaction::GetTransBindInfo",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
if (_pBndInfo == NULL)
|
|
{
|
|
_pBndInfo = new BINDINFO;
|
|
|
|
if (_pBndInfo)
|
|
{
|
|
_pBndInfo->cbSize = sizeof(BINDINFO);
|
|
_pBndInfo->szExtraInfo = 0;
|
|
_pBndInfo->grfBindInfoF = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_pBndInfo->cbSize = sizeof(BINDINFO);
|
|
}
|
|
|
|
DEBUG_LEAVE(_pBndInfo);
|
|
return _pBndInfo;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::RestartOperation
|
|
//
|
|
// Synopsis: Starts the asycn transaction operation
|
|
//
|
|
// Arguments: (none)
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 12-07-95 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CTransaction::RestartOperation(LPWSTR pwzURL, DWORD dwCase)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::RestartOperation",
|
|
"this=%#x, %.80wq, %#x",
|
|
this, pwzURL, dwCase
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::RestartOperation");
|
|
|
|
HRESULT hr = NOERROR;
|
|
VDATETHIS(this);
|
|
COInetSession *pCOInetSession = 0;
|
|
IOInetProtocol *pProt = 0;
|
|
|
|
DWORD dwLocation = 0;
|
|
|
|
AddRef();
|
|
|
|
do
|
|
{
|
|
|
|
if (GetState() == TransSt_OperationFinished)
|
|
{
|
|
hr = E_FAIL;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// case: Start of Transaction
|
|
//
|
|
|
|
//TransAssert((_pClntProtSink == NULL));
|
|
BOOL fFirstCreated = FALSE;
|
|
|
|
if (dwCase != 0x00000001)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
break;
|
|
}
|
|
|
|
// We must have at least one node in the client request linked list
|
|
TransAssert((_pClntProtSink != NULL));
|
|
TransAssert((_pUnkInner == 0));
|
|
TransAssert((_pProt));
|
|
|
|
hr = QueryService(IID_IOInetProtocol, IID_IOInetProtocol ,(void **)&pProt);
|
|
|
|
if (hr != NOERROR)
|
|
{
|
|
if ((hr = GetCOInetSession(0,&pCOInetSession,0)) == NOERROR)
|
|
{
|
|
DWORD dwOption = _fPreferDefaultHandler ? BINDF_PREFERDEFAULTHANDLER : 0;
|
|
hr = pCOInetSession->CreateFirstProtocol(pwzURL, (IOInetBindInfo *) this, &_pUnkInner, &pProt, &_clsidProtocol, &dwLocation, dwOption);
|
|
fFirstCreated = TRUE;
|
|
if ((hr == NOERROR) && _pUnkInner)
|
|
{
|
|
TransAssert((pProt));
|
|
pProt->Release();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// bugbug: find the correct cls id here.
|
|
_clsidProtocol = CLSID_FtpProtocol;
|
|
}
|
|
|
|
if (hr != NOERROR)
|
|
{
|
|
TransAssert((!pProt && !_pUnkInner));
|
|
pProt = 0;
|
|
_pUnkInner = 0;
|
|
break;
|
|
}
|
|
|
|
BOOL fNext;
|
|
TransAssert((pProt));
|
|
do // loop over protocols
|
|
{
|
|
fNext = FALSE;
|
|
TransAssert((hr == NOERROR));
|
|
|
|
// Start the download operation
|
|
TransAssert((pProt != NULL));
|
|
|
|
{
|
|
delete [] _pwzProtClsId;
|
|
_pwzProtClsId = 0;
|
|
|
|
HRESULT hr1 = StringFromCLSID(_clsidProtocol, &_pwzProtClsId);
|
|
if (SUCCEEDED(hr1))
|
|
{
|
|
_pClntProtSink->ReportProgress(BINDSTATUS_PROTOCOLCLASSID, _pwzProtClsId);
|
|
}
|
|
}
|
|
|
|
SetState(TransSt_OperationStarted);
|
|
|
|
|
|
if (_fProtEmbed)
|
|
{
|
|
_CProtEmbed.SetProtocol(pProt);
|
|
}
|
|
else
|
|
{
|
|
_pProt = pProt;
|
|
}
|
|
_fResultReported = FALSE;
|
|
|
|
hr = pProt->Start(pwzURL, this, (IOInetBindInfo *)this, 0,0);
|
|
|
|
if (hr == E_PENDING)
|
|
{
|
|
hr = NOERROR;
|
|
}
|
|
else if (hr == INET_E_USE_DEFAULT_PROTOCOLHANDLER)
|
|
{
|
|
fNext = TRUE;
|
|
|
|
if (!_pUnkInner)
|
|
{
|
|
pProt->Release();
|
|
}
|
|
|
|
if( _fProtEmbed )
|
|
{
|
|
_CProtEmbed.SetProtocol(NULL);
|
|
}
|
|
|
|
pProt = 0;
|
|
if (_pUnkInner)
|
|
{
|
|
_pUnkInner->Release();
|
|
_pUnkInner = 0;
|
|
}
|
|
|
|
// bugbug: need to reset the protocol inside the embed protocol handler
|
|
|
|
|
|
if (!fFirstCreated)
|
|
{
|
|
DWORD dwOption = _fPreferDefaultHandler ? BINDF_PREFERDEFAULTHANDLER : 0;
|
|
hr = pCOInetSession->CreateFirstProtocol(pwzURL, (IOInetBindInfo *) this, &_pUnkInner, &pProt, &_clsidProtocol, &dwLocation, dwOption);
|
|
fFirstCreated = TRUE;
|
|
}
|
|
else
|
|
{
|
|
hr = pCOInetSession->CreateNextProtocol(pwzURL, (IOInetBindInfo *) this, &_pUnkInner, &pProt, &_clsidProtocol, &dwLocation);
|
|
}
|
|
|
|
if (hr != NOERROR)
|
|
{
|
|
TransAssert((!pProt && !_pUnkInner));
|
|
pProt = 0;
|
|
_pUnkInner = 0;
|
|
fNext = FALSE;
|
|
|
|
}
|
|
else if (_pUnkInner)
|
|
{
|
|
// release the extra addref - aggregation
|
|
Release();
|
|
}
|
|
}
|
|
else if (hr != NOERROR)
|
|
{
|
|
// do not allow pending packages be dispatched
|
|
// any more
|
|
fNext = FALSE;
|
|
_fDispatch = TRUE;
|
|
|
|
if (pProt)
|
|
{
|
|
// Bug# 18869: If pwzURL ends up redirecting again (in other words,
|
|
// a nested call to CTransaction::RestartOperation again), and the URL
|
|
// redirected to errors out, Terminate() would be called within the
|
|
// nested call. Now when the pProt->Start() method propogates that error
|
|
// from that nested call, and this section of code is hit again, _pClntProtSink
|
|
// has already been released (and nulled) by the nested CTransaction::RestartOperation.
|
|
// Alternatively, _fResultDispatched could be checked for TRUE:
|
|
if(_pClntProtSink)
|
|
{
|
|
if( hr == INET_E_REDIRECT_TO_DIR && _pwzRedirectUrl)
|
|
{
|
|
_pClntProtSink->ReportResult(hr, 0, _pwzRedirectUrl);
|
|
}
|
|
else
|
|
{
|
|
_pClntProtSink->ReportResult(_hrResult, _dwResult, 0);
|
|
}
|
|
}
|
|
_fResultDispatched = TRUE;
|
|
Terminate(0);
|
|
}
|
|
}
|
|
|
|
} while (fNext == TRUE);
|
|
|
|
if ( (_dwOInetBdgFlags & PI_SYNCHRONOUS)
|
|
&& SUCCEEDED(hr)
|
|
&& (_fModalLoopRunning == FALSE))
|
|
{
|
|
// complet the binding in case of sychronous bind
|
|
TransAssert((_dwOInetBdgFlags & OIBDG_APARTMENTTHREADED));
|
|
_fModalLoopRunning = TRUE;
|
|
hr = CompleteOperation(_dwOInetBdgFlags & (BDGFLAGS_ATTACHED|BDGFLAGS_BTS_BTO));
|
|
_fModalLoopRunning = FALSE;
|
|
}
|
|
|
|
break;
|
|
} while (TRUE);
|
|
|
|
if (pCOInetSession)
|
|
{
|
|
pCOInetSession->Release();
|
|
}
|
|
|
|
Release();
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::RestartOperation (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Create global security manager object on demand.
|
|
//
|
|
HRESULT EnsureSecurityManager ()
|
|
{
|
|
if(g_pSecurityManager == NULL)
|
|
{
|
|
// Only 1 thread should be in here, this is to protect
|
|
// global variable g_pSecurityManager
|
|
CLock lck(g_mxsSession);
|
|
|
|
if (g_pSecurityManager == NULL)
|
|
return CoInternetCreateSecurityManager( NULL, &g_pSecurityManager, 0);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::Redirect
|
|
//
|
|
// Synopsis: creates a new cinet object
|
|
//
|
|
// Arguments: [szUrl] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 7-17-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CTransaction::Redirect(LPWSTR pwzUrl)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::Redirect",
|
|
"this=%#x, %.80wq",
|
|
this, pwzUrl
|
|
));
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "+CTransaction::Redirect (szUrlL:%ws)", pwzUrl);
|
|
HRESULT hr = NOERROR;
|
|
|
|
TransAssert((pwzUrl != NULL));
|
|
CLSID clsid;
|
|
|
|
// Check to see if a non-"special" URL is redirecting to a "special" URL
|
|
//
|
|
if (!IsSpecialUrl(_pwzUrl) // The original URL
|
|
&& IsSpecialUrl(pwzUrl)) // The redirected URL
|
|
{
|
|
// Check the registry workaround
|
|
//
|
|
static DWORD bAllowRedirectToScript = 2;
|
|
|
|
if (bAllowRedirectToScript == 2)
|
|
{
|
|
// Read the key and set the static
|
|
BOOL fDefault = FALSE;
|
|
DWORD dwSize = sizeof(DWORD);
|
|
|
|
SHRegGetUSValue(
|
|
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
|
|
"AllowRedirectToScript",
|
|
NULL,
|
|
(LPBYTE) &bAllowRedirectToScript,
|
|
&dwSize,
|
|
FALSE,
|
|
(LPVOID) &fDefault,
|
|
sizeof(fDefault));
|
|
}
|
|
|
|
// If it's not allowed, abort the transaction
|
|
//
|
|
if (!bAllowRedirectToScript)
|
|
{
|
|
// Can't redirect to a scripting URL.
|
|
//
|
|
hr = E_ACCESSDENIED;
|
|
}
|
|
}
|
|
|
|
// NOTICE-2002/03/04-ganeshs - NTRAID#NTBUG9-556240 - Security: Block redirects to local machine
|
|
//
|
|
if(SUCCEEDED(hr) && SUCCEEDED(hr = EnsureSecurityManager()))
|
|
{
|
|
// Set conservative defaults:
|
|
DWORD dwZoneIDSource = URLZONE_UNTRUSTED;
|
|
DWORD dwZoneIDTarget = URLZONE_LOCAL_MACHINE;
|
|
|
|
if (SUCCEEDED(hr = g_pSecurityManager->MapUrlToZone(pwzUrl, &dwZoneIDTarget, 0))
|
|
&& (dwZoneIDTarget == URLZONE_LOCAL_MACHINE)
|
|
&& (SUCCEEDED(hr = g_pSecurityManager->MapUrlToZone(_pwzUrl, &dwZoneIDSource, 0))))
|
|
{
|
|
|
|
if (dwZoneIDSource != URLZONE_LOCAL_MACHINE
|
|
&& dwZoneIDSource != URLZONE_INTRANET
|
|
&& dwZoneIDSource != URLZONE_TRUSTED)
|
|
{
|
|
// Block redirect:
|
|
hr = E_ACCESSDENIED;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!SUCCEEDED(hr))
|
|
{
|
|
Abort(hr, 0);
|
|
}
|
|
else
|
|
{
|
|
{
|
|
COInetSession *pCOInetSession = 0;
|
|
if ((hr = GetCOInetSession(0,&pCOInetSession,0)) == NOERROR)
|
|
{
|
|
hr = pCOInetSession->FindOInetProtocolClsID(pwzUrl, &clsid);
|
|
pCOInetSession->Release();
|
|
}
|
|
}
|
|
|
|
if (hr == NOERROR)
|
|
{
|
|
//
|
|
// remove remaining packages from the queue
|
|
//
|
|
{
|
|
CTransPacket *pCTP = 0;
|
|
|
|
while ((pCTP = GetNextCTransPacket()) != NULL)
|
|
{
|
|
// delete the data now
|
|
delete pCTP;
|
|
}
|
|
}
|
|
|
|
IOInetProtocol *pCINetOld = _pProt;
|
|
|
|
if (_pInetInfo && !_pUnkInner)
|
|
{
|
|
_pInetInfo->Release();
|
|
}
|
|
_pInetInfo = NULL;
|
|
|
|
if (_pInetHttpInfo && !_pUnkInner)
|
|
{
|
|
_pInetHttpInfo->Release();
|
|
}
|
|
_pInetHttpInfo = NULL;
|
|
|
|
//
|
|
// no post on redirect
|
|
if (_pBndInfo && (_pBndInfo->dwBindVerb == BINDVERB_POST))
|
|
{
|
|
_pBndInfo->dwBindVerb = BINDVERB_GET;
|
|
}
|
|
if (_fProtEmbed)
|
|
{
|
|
IOInetProtocol *pProt = 0;
|
|
|
|
hr = _CProtEmbed.GetProtocol(&pProt);
|
|
if (hr == NOERROR)
|
|
{
|
|
pProt->Terminate(0);
|
|
pProt->Release();
|
|
}
|
|
_CProtEmbed.SetProtocol(0);
|
|
if (_pUnkInner)
|
|
{
|
|
//PerfDbgLog2(tagCTransaction, this, "+CTransaction::~CTransaction Nulling (pCINet:%lx, hServer:%lx)", _pProt, _pProt->_hServer);
|
|
_pUnkInner->Release();
|
|
_pUnkInner = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_pProt->Terminate(0);
|
|
|
|
if (_pProt && !_pUnkInner)
|
|
{
|
|
//PerfDbgLog2(tagCTransaction, this, "+CTransaction::~CTransaction Nulling (pCINet:%lx, hServer:%lx)", _pProt, _pProt->_hServer);
|
|
_pProt->Release();
|
|
}
|
|
_pProt = NULL;
|
|
|
|
if (_pUnkInner)
|
|
{
|
|
//PerfDbgLog2(tagCTransaction, this, "+CTransaction::~CTransaction Nulling (pCINet:%lx, hServer:%lx)", _pProt, _pProt->_hServer);
|
|
_pUnkInner->Release();
|
|
_pUnkInner = NULL;
|
|
}
|
|
}
|
|
|
|
SetState(TransSt_Initialized);
|
|
hr = RestartOperation(pwzUrl,0x00000001);
|
|
|
|
}
|
|
}
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::Redirect(hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::AddClientOInet
|
|
//
|
|
// Synopsis: Adds clients OInet interfaces.
|
|
//
|
|
// Arguments: [pCBdg] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History:
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CTransaction::AddClientOInet(IOInetProtocolSink *pOInetProtSink, IOInetBindInfo *pOInetBindInfo)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::AddClientOInet",
|
|
"this=%#x, %#x, %#x",
|
|
this, pOInetProtSink, pOInetBindInfo
|
|
));
|
|
|
|
PerfDbgLog2(tagCTransaction, this, "+CTransaction::AddClientOInet, pProtocolSink:%lx, pBindInfo:%lx", pOInetProtSink, pOInetBindInfo);
|
|
|
|
TransAssert((pOInetProtSink && pOInetBindInfo));
|
|
|
|
RemoveClientOInet();
|
|
|
|
if (_fProtEmbed)
|
|
{
|
|
_CProtEmbed.SetProtocolSink(pOInetProtSink);
|
|
_pClntProtSink = &_CProtEmbed;
|
|
_cBdgRefs++;
|
|
}
|
|
else
|
|
{
|
|
_cBdgRefs++;
|
|
_pClntProtSink = pOInetProtSink;
|
|
pOInetProtSink->AddRef();
|
|
}
|
|
|
|
_pClntBindInfo = pOInetBindInfo;
|
|
pOInetBindInfo->AddRef();
|
|
|
|
PerfDbgLog(tagCTransaction, this, "-CTransaction::AddClientOInet");
|
|
|
|
DEBUG_LEAVE(NOERROR);
|
|
return NOERROR;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::RemoveClientOInet
|
|
//
|
|
// Synopsis: Removes OInetProtocolSink and OInetBindInfo interfaces.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 2-02-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CTransaction::RemoveClientOInet()
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::RemoveClientOInet",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "+CTransaction::RemoveClientOInet _pClntProtSink:%lx", _pClntProtSink);
|
|
HRESULT hr = NOERROR;
|
|
BOOL fRelease = FALSE;
|
|
|
|
if (_fProtEmbed && _cBdgRefs)
|
|
{
|
|
_CProtEmbed.SetProtocolSink(0);
|
|
_CProtEmbed.SetServiceProvider(0);
|
|
_pClntProtSink = 0;
|
|
_cBdgRefs--;
|
|
}
|
|
else if (_pClntProtSink)
|
|
{
|
|
_pClntProtSink->Release();
|
|
_pClntProtSink = 0;
|
|
_cBdgRefs--;
|
|
fRelease = TRUE;
|
|
}
|
|
|
|
if (_pClntBindInfo)
|
|
{
|
|
_pClntBindInfo->Release();
|
|
_pClntBindInfo = 0;
|
|
}
|
|
|
|
TransAssert((_pClntProtSink == 0 && _cBdgRefs == 0));
|
|
|
|
hr = (fRelease) ? S_OK : S_FALSE;
|
|
|
|
PerfDbgLog2(tagCTransaction, this, "-CTransaction::RemoveClientOInet (_pClntProtSink:%lx, hr:%lx)", _pClntProtSink, hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
#if 0
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::RemoveAllCBindings
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: (none)
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 2-02-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CTransaction::RemoveAllCBindings()
|
|
{
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::RemoveAllCBindings");
|
|
HRESULT hr = NOERROR;
|
|
CBinding *pCBdg;
|
|
CBinding *pCBdgNext;
|
|
|
|
TransAssert((_pClntProtSink == 0 && _cBdgRefs == 0));
|
|
/*
|
|
|
|
TransAssert(( (_cBdgRefs == 0 && _pClntProtSink == NULL)
|
|
|| (_cBdgRefs != 0 && _pClntProtSink != NULL) ));
|
|
|
|
if (_pClntProtSink)
|
|
{
|
|
_pClntProtSink->Release();
|
|
_pClntProtSink = 0;
|
|
_cBdgRefs--;
|
|
|
|
}
|
|
|
|
// the list should be empty now
|
|
DbgLog1(tagCTransaction, this, "=== CTransaction::RemoveAllCBindings Removing transaction, cRefs:%ld", _cBdgRefs);
|
|
TransAssert((_cBdgRefs == 0));
|
|
TransAssert((_pCTransMgr));
|
|
|
|
// remove the transaction if no cbindings left
|
|
//_pCTransMgr->RemoveTransaction(this);
|
|
//_pCTransMgr = NULL;
|
|
|
|
_pClntProtSink = NULL;
|
|
*/
|
|
|
|
PerfDbgLog(tagCTransaction, this, "-CTransaction::RemoveAllCBindings");
|
|
return hr;
|
|
}
|
|
#endif // 0
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::MyPeekMessage
|
|
//
|
|
// Synopsis: This function is called whenever we want to do a PeekMessage.
|
|
// It has special handling for WM_QUIT messages.
|
|
//
|
|
// Arguments: [pMsg] - message structure
|
|
// [hWnd] - window to peek on
|
|
// [min/max] - min and max message numbers
|
|
// [wFlag] - peek flags
|
|
//
|
|
// Returns: TRUE - a message is available
|
|
// FALSE - no messages available
|
|
//
|
|
// Algorithm:
|
|
//
|
|
// History: 7-26-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CTransaction::MyPeekMessage(MSG *pMsg, HWND hwnd, UINT min, UINT max, WORD wFlag)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::MyPeekMessage",
|
|
"this=%#x, %#x, %#x, %#x, %#x, %#x",
|
|
this, pMsg, hwnd, min, max, wFlag
|
|
));
|
|
|
|
HRESULT hr = S_OK;
|
|
BOOL fRet = PeekMessage(pMsg, hwnd, min, max, wFlag);
|
|
if (fRet)
|
|
{
|
|
PerfDbgLog3(tagCTransaction, this, "MyPeekMessage: hwnd:%#x, msg:%#x time:%#x", pMsg->hwnd, pMsg->message, pMsg->time);
|
|
if (pMsg->message == WM_QUIT)
|
|
{
|
|
PostQuitMessage((int)pMsg->wParam);
|
|
hr = S_FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::CompleteOperation
|
|
//
|
|
// Synopsis: Simple modal loop
|
|
//
|
|
// Arguments: (none)
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 12-13-95 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes: BUGBUG: NOT COMPLETE YET!
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CTransaction::CompleteOperation(BOOL fNested)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::CompleteOperation",
|
|
"this=%#x, %B",
|
|
this, fNested
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::CompleteOperation");
|
|
|
|
MSG msg;
|
|
HRESULT hr = NO_ERROR;
|
|
|
|
CUrlMkTls tls(hr);
|
|
LONG cDispatchLevel;
|
|
BOOL fDispatch = _fDispatch;
|
|
|
|
if (hr == NOERROR)
|
|
{
|
|
HRESULT hr1 = NOERROR;
|
|
HRESULT hrPeek;
|
|
|
|
CModalLoop MsgFlter(&hr1);
|
|
|
|
AddRef();
|
|
cDispatchLevel = tls->cDispatchLevel;
|
|
|
|
TransAssert((cDispatchLevel >= 0));
|
|
tls->cDispatchLevel++;
|
|
|
|
if (fNested)
|
|
{
|
|
fDispatch = _fDispatch;
|
|
_fDispatch = FALSE;
|
|
}
|
|
|
|
// run the modal loop in case we have a IMessageFilter
|
|
if (hr1 == NOERROR)
|
|
{
|
|
DWORD dwWakeReason = WAIT_TIMEOUT;
|
|
DWORD dwInput = QS_ALLINPUT;
|
|
DWORD dwWaitTime = 1000;
|
|
DWORD dwIBSCLevel = (tls->cDispatchLevel > 1)
|
|
? IBSCLEVEL_TOPLEVEL : IBSCLEVEL_NESTED;
|
|
|
|
while (GetState() != TransSt_OperationFinished)
|
|
{
|
|
dwWakeReason = MsgWaitForMultipleObjects(0, 0, FALSE, dwWaitTime, dwInput);
|
|
|
|
if ( (dwWakeReason == (WAIT_OBJECT_0 + 0))
|
|
|| (dwWakeReason == WAIT_TIMEOUT))
|
|
{
|
|
DWORD dwStatus = GetQueueStatus(QS_ALLINPUT);
|
|
|
|
|
|
// some messages are in the queue
|
|
if (dwStatus)
|
|
{
|
|
|
|
while ((hrPeek = MyPeekMessage(&msg, _hwndNotify, WM_USER, WM_TRANS_LAST, PM_REMOVE | PM_NOYIELD)) == S_OK)
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
if (hrPeek == S_FALSE)
|
|
{
|
|
hr = S_FALSE;
|
|
goto End;
|
|
}
|
|
// call MessagePending on
|
|
MsgFlter.HandlePendingMessage(dwStatus,cDispatchLevel,0);
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// just run a dispatch loop for our own messages
|
|
while (GetState() != TransSt_OperationFinished)
|
|
{
|
|
// wake up every 5 seconds
|
|
// this is needed since our msg might be dispatched somewhere else
|
|
// on the stack inside the protocol
|
|
DWORD dwWaitTime = 5000;
|
|
//changed QS_ALLINPUT to QS_POSTMESSAGE so that we wake up only for new posted messages.
|
|
//QS_ALLINPUT was making us return as soon as there were any messges in the queue.
|
|
//Ideally, we only want to wait for posted messages for the _hwndNotify handle in the WM_USER
|
|
//to WM_TRANS_LAST range.
|
|
DWORD dwWakeReason = MsgWaitForMultipleObjects(0, 0, FALSE, dwWaitTime, QS_POSTMESSAGE);
|
|
|
|
|
|
if (dwWakeReason == (WAIT_OBJECT_0 + 0))
|
|
{
|
|
while ((hrPeek = MyPeekMessage(&msg, _hwndNotify, WM_USER, WM_TRANS_LAST, PM_REMOVE | PM_NOYIELD)) == S_OK)
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
if (hrPeek == S_FALSE)
|
|
{
|
|
hr = S_FALSE;
|
|
goto End;
|
|
}
|
|
}
|
|
else if (dwWakeReason == WAIT_TIMEOUT)
|
|
{
|
|
// nothing to do here
|
|
}
|
|
}
|
|
}
|
|
|
|
hr = GetHResult();
|
|
|
|
//
|
|
// dispatch all the other notification messages
|
|
//
|
|
while ((hrPeek = MyPeekMessage(&msg, _hwndNotify, WM_USER, WM_TRANS_LAST, PM_REMOVE | PM_NOYIELD)) == S_OK)
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
|
|
End:
|
|
if (fNested)
|
|
{
|
|
_fDispatch = fDispatch;
|
|
}
|
|
|
|
// reset the dispatch level
|
|
tls->cDispatchLevel--;
|
|
Release();
|
|
}
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::CompleteOperation (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::PrepareThreadTransfer
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: (none)
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 10-09-1996 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CTransaction::PrepareThreadTransfer()
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::PrepareThreadTransfer",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::PrepareThreadTransfer");
|
|
TransAssert(( IsApartmentThread() ));
|
|
TransAssert((_ThreadTransferState == TS_None));
|
|
|
|
HRESULT hr = E_OUTOFMEMORY;
|
|
|
|
if ( _ThreadTransferState == TS_None
|
|
&& _pCTPCur)
|
|
{
|
|
// make a copy of the current packet
|
|
// this packet will be send to the new
|
|
// thread once the transfer completed
|
|
|
|
_pCTPTransfer = new CTransPacket( (BINDSTATUS) BINDSTATUS_INTERNAL);
|
|
|
|
if (_pCTPTransfer)
|
|
{
|
|
hr = NOERROR;
|
|
*_pCTPTransfer = *_pCTPCur;
|
|
|
|
_ThreadTransferState = TS_Prepared;
|
|
|
|
if (_pProt)
|
|
{
|
|
IOInetThreadSwitch *pOInetThS;
|
|
HRESULT hr1 = _pProt->QueryInterface(IID_IOInetThreadSwitch,(void **) &pOInetThS);
|
|
|
|
if (hr1 == NOERROR)
|
|
{
|
|
TransAssert((pOInetThS));
|
|
pOInetThS->Prepare();
|
|
pOInetThS->Release();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
PerfDbgLog(tagCTransaction, this, "-CTransaction::PrepareThreadTransfer");
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::ThreadTransfer
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: (none)
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 10-09-1996 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CTransaction::ThreadTransfer()
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::ThreadTransfer",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::ThreadTransfer");
|
|
TransAssert(( !IsApartmentThread() ));
|
|
TransAssert((_ThreadTransferState == TS_Prepared));
|
|
|
|
HRESULT hr = NOERROR;
|
|
|
|
if (_ThreadTransferState == TS_Prepared)
|
|
{
|
|
_hwndNotify = GetThreadNotificationWnd();
|
|
|
|
// check the threadID and set the new window
|
|
_dwThreadId = GetCurrentThreadId();
|
|
|
|
_ThreadTransferState = TS_Completed;
|
|
TransAssert((_pCTPTransfer));
|
|
if (_pCTPTransfer)
|
|
{
|
|
CTransPacket *pCTP = _pCTPTransfer;
|
|
#if DBG==1
|
|
DWORD dwCurrentSizePerf = pCTP->_dwCurrentSize;
|
|
DWORD dwTotalSizePerf = pCTP->_dwTotalSize;
|
|
#elif defined(PERFTAGS)
|
|
DWORD dwCurrentSizePerf = pCTP->_dwCurrentSize;
|
|
DWORD dwTotalSizePerf = pCTP->_dwTotalSize;
|
|
#endif
|
|
_pCTPTransfer = NULL;
|
|
|
|
AddCTransPacket(pCTP, FALSE);
|
|
{
|
|
_cPostedMsg++;
|
|
AddRef();
|
|
PerfDbgLog4(tagCTransaction, this, "CINet:%lx === CTransaction::ThreadTransfer (Msg:%#x) WM_TRANS_PACKET - dwCurrentSize:%ld, dwTotalSize:%ld",
|
|
_pProt, XDBG(++_wTotalPostedMsg,0), dwCurrentSizePerf, dwTotalSizePerf);
|
|
#if DBG==1
|
|
PostMessage(_hwndNotify, WM_TRANS_PACKET, (WPARAM)_wTotalPostedMsg, (LPARAM)this);
|
|
#else
|
|
PostMessage(_hwndNotify, WM_TRANS_PACKET, (WPARAM) 0, (LPARAM)this);
|
|
#endif
|
|
|
|
}
|
|
{
|
|
IOInetThreadSwitch *pOInetThS;
|
|
HRESULT hr1 =_pProt->QueryInterface(IID_IOInetThreadSwitch,(void **) &pOInetThS);
|
|
|
|
if (hr1 == NOERROR)
|
|
{
|
|
TransAssert((pOInetThS));
|
|
pOInetThS->Continue();
|
|
pOInetThS->Release();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
PerfDbgLog(tagCTransaction, this, "-CTransaction::ThreadTransfer");
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
/* this code path valid only for Trident BTS -> Shdocvw BTO */
|
|
void CTransaction::ResumeDispatchingPackets()
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
None,
|
|
"CTransaction::ResumeDispatchingPackets",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::ResumeReadingPackets");
|
|
TransAssert(( IsApartmentThread() ));
|
|
|
|
TransAssert((_pCTPTransfer));
|
|
if (_pCTPTransfer)
|
|
{
|
|
CTransPacket *pCTP = _pCTPTransfer;
|
|
#if DBG==1
|
|
DWORD dwCurrentSizePerf = pCTP->_dwCurrentSize;
|
|
DWORD dwTotalSizePerf = pCTP->_dwTotalSize;
|
|
#elif defined(PERFTAGS)
|
|
DWORD dwCurrentSizePerf = pCTP->_dwCurrentSize;
|
|
DWORD dwTotalSizePerf = pCTP->_dwTotalSize;
|
|
#endif
|
|
_pCTPTransfer = NULL;
|
|
|
|
AddCTransPacket(pCTP, FALSE);
|
|
|
|
// report AcceptRanges and ContentDispositionAttach.
|
|
{
|
|
CTransPacket *pCTP;
|
|
|
|
if (_fAcceptRanges)
|
|
{
|
|
pCTP = new CTransPacket(
|
|
BINDSTATUS_ACCEPTRANGES, NOERROR, NULL, _ulCurrentSize, _ulTotalSize);
|
|
if (pCTP)
|
|
AddCTransPacket(pCTP, FALSE);
|
|
}
|
|
|
|
if (_fContentDispositionAttach)
|
|
{
|
|
pCTP = new CTransPacket(
|
|
BINDSTATUS_CONTENTDISPOSITIONATTACH, NOERROR, (_pwzFileName?_pwzFileName:_pwzAttachmentName), _ulCurrentSize, _ulTotalSize);
|
|
if (pCTP)
|
|
AddCTransPacket(pCTP, FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
_fDispatch = FALSE;
|
|
{
|
|
_cPostedMsg++;
|
|
AddRef();
|
|
PerfDbgLog4(tagCTransaction, this, "CINet:%lx === CTransaction::ThreadTransfer (Msg:%#x) WM_TRANS_PACKET - dwCurrentSize:%ld, dwTotalSize:%ld",
|
|
_pProt, XDBG(++_wTotalPostedMsg,0), dwCurrentSizePerf, dwTotalSizePerf);
|
|
#if DBG==1
|
|
PostMessage(_hwndNotify, WM_TRANS_PACKET, (WPARAM)_wTotalPostedMsg, (LPARAM)this);
|
|
#else
|
|
PostMessage(_hwndNotify, WM_TRANS_PACKET, (WPARAM) 0, (LPARAM)this);
|
|
#endif
|
|
|
|
}
|
|
}
|
|
|
|
PerfDbgLog(tagCTransaction, this, "-CTransaction::ResumeDispatchingPackets");
|
|
|
|
DEBUG_LEAVE(0);
|
|
return;
|
|
}
|
|
|
|
/* this code path valid only for Trident BTS -> Shdocvw BTO */
|
|
void CTransaction::SuspendDispatchingPackets(CTransPacket* pCTP)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
None,
|
|
"CTransaction::SuspendDispatchingPackets",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
_pCTPTransfer = new CTransPacket( (BINDSTATUS) BINDSTATUS_INTERNAL);
|
|
|
|
if (_pCTPTransfer)
|
|
*_pCTPTransfer = *pCTP;
|
|
|
|
DEBUG_LEAVE(0);
|
|
return;
|
|
}
|
|
|
|
#ifdef UNUSED
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::TransmitPaket
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [uiMsg] --
|
|
// [pdld] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 12-08-95 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CTransaction::TransmitPacket(BINDSTATUS NMsg, CINet * pCINet, LPCWSTR szStr,DWORD cbAvailable, DWORD cbTotal)
|
|
{
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::TransmitPacket");
|
|
|
|
HRESULT hr = NOERROR;
|
|
|
|
_dwPacketsTotal++;
|
|
|
|
CTransPacket *pCTP = new CTransPacket(NMsg, NOERROR, szStr,cbAvailable,cbTotal);
|
|
|
|
if (pCTP)
|
|
{
|
|
#if DBG==1
|
|
DWORD dwCurrentSizePerf = pCTP->_dwCurrentSize;
|
|
DWORD dwTotalSizePerf = pCTP->_dwTotalSize;
|
|
#elif defined(PERFTAGS)
|
|
DWORD dwCurrentSizePerf = pCTP->_dwCurrentSize;
|
|
DWORD dwTotalSizePerf = pCTP->_dwTotalSize;
|
|
#endif
|
|
if (cbAvailable)
|
|
{
|
|
pCTP->_dwCurrentSize = cbAvailable;
|
|
}
|
|
if (cbTotal)
|
|
{
|
|
pCTP->_dwTotalSize = cbTotal;
|
|
}
|
|
|
|
AddCTransPacket(pCTP);
|
|
|
|
if ( pCTP->IsLastNotMsg() || !IsApartmentThread() || pCTP->IsAsyncNotMsg() )
|
|
{
|
|
_cPostedMsg++;
|
|
AddRef();
|
|
PerfDbgLog4(tagCTransaction, this, "CINet:%lx === CTransaction::TransmitPacket (Msg:%#x) WM_TRANS_PACKET - dwCurrentSize:%ld, dwTotalSize:%ld",
|
|
_pProt, XDBG(++_wTotalPostedMsg,0), dwCurrentSizePerf, dwTotalSizePerf);
|
|
#if DBG==1
|
|
PostMessage(_hwndNotify, WM_TRANS_PACKET, (WPARAM)_wTotalPostedMsg, (LPARAM)this);
|
|
#else
|
|
PostMessage(_hwndNotify, WM_TRANS_PACKET, (WPARAM) 0, (LPARAM)this);
|
|
#endif
|
|
|
|
}
|
|
else
|
|
{
|
|
OnINetCallback();
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// post message indicating the packet could not be allocated
|
|
PostMessage(_hwndNotify, WM_TRANS_OUTOFMEMORY, (WPARAM)NULL, (LPARAM)this);
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
PerfDbgLog(tagCTransaction, this, "-CTransaction::TransmitPacket");
|
|
return hr;
|
|
}
|
|
#endif //UNUSED
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::DispatchReport
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [NotMsg] --
|
|
// [grfBSCF] --
|
|
// [dwCurrentSize] --
|
|
// [dwTotalSize] --
|
|
// [pwzStr] --
|
|
// [dwError] --
|
|
// [hrReport] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 4-15-1997 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CTransaction::DispatchReport(BINDSTATUS NotMsg, DWORD grfBSCF, DWORD dwCurrentSize, DWORD dwTotalSize, LPCWSTR pwzStr, DWORD dwError, HRESULT hresult)
|
|
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::DispatchReport",
|
|
"this=%#x, %#x, %#x, %#x, %#x, %.80wq, %#x, %#x",
|
|
this, NotMsg, grfBSCF, dwCurrentSize, dwTotalSize, pwzStr, dwError, hresult
|
|
));
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "+CTransaction::DispatchReport [NotMsg:%lx]", NotMsg);
|
|
HRESULT hr = NOERROR;
|
|
IOInetProtocolSink *pCBdg = _pClntProtSink;
|
|
static const WCHAR *wzClsStr = L"Class Install Handler ";
|
|
|
|
if (_fTerminated || !_pClntProtSink)
|
|
{
|
|
// nothing to do
|
|
if ( !_fTerminated
|
|
&& ( (BINDSTATUS_RESULT == NotMsg)
|
|
|| (BINDSTATUS_ERROR == NotMsg)) )
|
|
{
|
|
_fResultDispatched = TRUE;
|
|
Terminate(0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// clean out the old transfer state
|
|
//
|
|
if (_ThreadTransferState == TS_Completed)
|
|
{
|
|
_ThreadTransferState = TS_None;
|
|
}
|
|
|
|
switch (NotMsg)
|
|
{
|
|
case BINDSTATUS_BEGINDOWNLOADDATA:
|
|
if (_dwOInetBdgFlags & PI_DATAPROGRESS)
|
|
{
|
|
pCBdg->ReportProgress(NotMsg, pwzStr);
|
|
}
|
|
case BINDSTATUS_DOWNLOADINGDATA:
|
|
case BINDSTATUS_ENDDOWNLOADDATA:
|
|
{
|
|
//
|
|
// check amount of data an verify mime is requested
|
|
//
|
|
if (OnDataReceived(&grfBSCF, &dwCurrentSize, &dwTotalSize) == NOERROR)
|
|
{
|
|
if ( (NotMsg == BINDSTATUS_ENDDOWNLOADDATA)
|
|
&& (_dwOInetBdgFlags & PI_DATAPROGRESS))
|
|
{
|
|
pCBdg->ReportProgress(NotMsg, pwzStr);
|
|
}
|
|
hr = pCBdg->ReportData(grfBSCF, dwCurrentSize, dwTotalSize);
|
|
}
|
|
}
|
|
break;
|
|
case BINDSTATUS_REDIRECTING :
|
|
{
|
|
// report the progress on the redirect url
|
|
TransAssert((pwzStr));
|
|
hr = pCBdg->ReportProgress(NotMsg, pwzStr);
|
|
SetRedirectUrl((LPWSTR)pwzStr);
|
|
}
|
|
break;
|
|
case BINDSTATUS_RESULT:
|
|
case BINDSTATUS_ERROR:
|
|
{
|
|
if ( (hresult == INET_E_REDIRECTING)
|
|
&& (pwzStr))
|
|
{
|
|
// Note: it is legal here NOT to have a redirect url
|
|
// if wininet does redirct and it fails it will reprot this error.
|
|
|
|
// report progress on redirect and to the redirect
|
|
hr = pCBdg->ReportProgress(BINDSTATUS_REDIRECTING, pwzStr);
|
|
SetRedirectUrl((LPWSTR)pwzStr);
|
|
hr = Redirect((LPWSTR)pwzStr);
|
|
if ( (hr != NOERROR)
|
|
&& (hr != E_PENDING)
|
|
&& !_fResultDispatched)
|
|
{
|
|
_fResultDispatched = TRUE;
|
|
hr = pCBdg->ReportResult(hr, 0, 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_fResultDispatched = TRUE;
|
|
hr = pCBdg->ReportResult(_hrResult, _dwResult, pwzStr);
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
case BINDSTATUS_ENCODING:
|
|
{
|
|
/****
|
|
// load the encode filter here
|
|
TransAssert((pwzStr));
|
|
|
|
if (_fEncodingHandlerEnabled && pwzStr)
|
|
{
|
|
// disable data sniff on _CProtEmbed
|
|
DWORD dwEmbedBndFlags = _CProtEmbed.GetOInetBindFlags();
|
|
dwEmbedBndFlags &= (~PI_MIMEVERIFICATION & ~PI_DOCFILECLSIDLOOKUP & ~PI_CLASSINSTALL);
|
|
_CProtEmbed.SetOInetBindFlags(dwEmbedBndFlags);
|
|
_CProtEncoding.Initialize(this, 0, PP_PRE_SWITCH, _dwOInetBdgFlags, 0, _pProt, _pClntProtSink, 0);
|
|
//hr = LoadHandler(pwzStr, &_CProtEncoding, 0);
|
|
LoadHandler(pwzStr, &_CProtEncoding, 0);
|
|
}
|
|
***/
|
|
}
|
|
break;
|
|
|
|
case BINDSTATUS_CLASSINSTALLLOCATION:
|
|
TransAssert((pwzStr));
|
|
if (_fClsInstallerHandlerEnabled && pwzStr)
|
|
{
|
|
_CProtClsInstaller.Initialize(this, 0, PP_PRE_SWITCH, _dwOInetBdgFlags, 0, _pProt, _pClntProtSink, 0);
|
|
LPWSTR pwzClsURL = 0;
|
|
|
|
pwzClsURL = new WCHAR[lstrlenW(_pwzUrl) + lstrlenW(pwzStr) + lstrlenW(wzClsStr) + 2]; // +1 for NULL, +1 for another NULL after _pwzUrl
|
|
|
|
if (pwzClsURL)
|
|
{
|
|
StrCpyW(pwzClsURL, wzClsStr);
|
|
|
|
StrCatW(pwzClsURL, _pwzUrl);
|
|
StrCatW(pwzClsURL, L" ");
|
|
StrCatW(pwzClsURL, pwzStr);
|
|
|
|
pwzClsURL[lstrlenW(wzClsStr) - 1] = L'\0';
|
|
pwzClsURL[lstrlenW(_pwzUrl) + lstrlenW(wzClsStr)] = L'\0';
|
|
|
|
hr = LoadHandler(pwzClsURL, &_CProtClsInstaller, 0);
|
|
|
|
delete [] pwzClsURL;
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
// tell sink to stop waiting on handler (since we're broken)
|
|
if (FAILED(hr))
|
|
{
|
|
pCBdg->ReportProgress(BINDSTATUS_ENDDOWNLOADCOMPONENTS,NULL);
|
|
}
|
|
|
|
break;
|
|
|
|
case BINDSTATUS_CLASSIDAVAILABLE:
|
|
TransAssert((pwzStr));
|
|
hr = pCBdg->ReportProgress(NotMsg, pwzStr);
|
|
break;
|
|
|
|
case BINDSTATUS_MIMETYPEAVAILABLE:
|
|
TransAssert((pwzStr));
|
|
if ( _fMimeHandlerEnabled && pwzStr && _fProtEmbed &&
|
|
!_fMimeHandlerLoaded)
|
|
{
|
|
//
|
|
// load a mime filter with the embedded prot class
|
|
if( StrCmpNIW( pwzStr, L"text/html", 9) )
|
|
{
|
|
hr = LoadHandler(pwzStr, &_CProtEmbed, 0);
|
|
if (hr == NOERROR)
|
|
{
|
|
pCBdg->ReportProgress(BINDSTATUS_LOADINGMIMEHANDLER, NULL);
|
|
_fMimeHandlerLoaded = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// special treatment for text/html to speed up the
|
|
// main IE download path
|
|
//
|
|
if(g_bHasMimeHandlerForTextHtml)
|
|
{
|
|
hr = LoadHandler(pwzStr, &_CProtEmbed, 0);
|
|
if (hr == NOERROR)
|
|
{
|
|
pCBdg->ReportProgress(BINDSTATUS_LOADINGMIMEHANDLER, NULL);
|
|
_fMimeHandlerLoaded = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// to account for cases where the mime type has additional
|
|
// attribute=value pairs after text/html.
|
|
// ( RFC for HTTP 1.1 provides for this. )
|
|
// eg. Content-Type: text/html; charset=ISO-8859-4
|
|
if ( StrCmpNIW(pwzStr, L"text/html;", 10) )
|
|
g_bHasMimeHandlerForTextHtml = FALSE;
|
|
else
|
|
{
|
|
hr = LoadHandler(L"text/html", &_CProtEmbed, 0);
|
|
if (hr == NOERROR)
|
|
{
|
|
pCBdg->ReportProgress(BINDSTATUS_LOADINGMIMEHANDLER, NULL);
|
|
_fMimeHandlerLoaded = TRUE;
|
|
}
|
|
else
|
|
g_bHasMimeHandlerForTextHtml = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (_dwOInetBdgFlags & (PI_MIMEVERIFICATION | PI_DOCFILECLSIDLOOKUP))
|
|
{
|
|
// report the mime later after sniffing data
|
|
_pwzMimeSuggested = OLESTRDuplicate((LPWSTR)pwzStr);
|
|
}
|
|
else
|
|
{
|
|
hr = pCBdg->ReportProgress(NotMsg, pwzStr);
|
|
}
|
|
|
|
break;
|
|
|
|
case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
|
|
{
|
|
TransAssert((pwzStr));
|
|
if (_fMimeHandlerEnabled && pwzStr && _fProtEmbed && !_fMimeHandlerLoaded)
|
|
{
|
|
// load a mime filter with the embedded prot class
|
|
hr = LoadHandler(pwzStr, &_CProtEmbed, 0);
|
|
if (hr == NOERROR)
|
|
{
|
|
pCBdg->ReportProgress(BINDSTATUS_LOADINGMIMEHANDLER, NULL);
|
|
_fMimeHandlerLoaded = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
// disable datasniff on _CProtEmbed so we are able to pass through
|
|
DWORD dwEmbedBndFlags = _CProtEmbed.GetOInetBindFlags();
|
|
dwEmbedBndFlags &= (~PI_MIMEVERIFICATION &~PI_DOCFILECLSIDLOOKUP &~PI_CLASSINSTALL);
|
|
_CProtEmbed.SetOInetBindFlags(dwEmbedBndFlags);
|
|
|
|
// the mime filter may already updated the mime type
|
|
// if we are already verified, then ignore this one
|
|
if( _fMimeHandlerLoaded && _fMimeVerified && _pwzMimeSuggested )
|
|
{
|
|
hr = pCBdg->ReportProgress(
|
|
BINDSTATUS_MIMETYPEAVAILABLE, _pwzMimeSuggested);
|
|
}
|
|
else
|
|
{
|
|
_pwzMimeSuggested = OLESTRDuplicate((LPWSTR)pwzStr);
|
|
_fMimeVerified = TRUE;
|
|
|
|
// we should only report BINDSTATUS_MIMETYPEAVAILABLE
|
|
// (BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE stops at here)
|
|
hr = pCBdg->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, pwzStr);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case BINDSTATUS_CACHEFILENAMEAVAILABLE :
|
|
TransAssert((pwzStr));
|
|
if (_pwzFileName)
|
|
delete [] _pwzFileName;
|
|
_pwzFileName = OLESTRDuplicate((LPWSTR)pwzStr);
|
|
hr = pCBdg->ReportProgress(NotMsg, pwzStr);
|
|
break;
|
|
|
|
case BINDSTATUS_CONTENTDISPOSITIONATTACH:
|
|
_fContentDispositionAttach = TRUE;
|
|
if (_pwzAttachmentName)
|
|
delete [] _pwzAttachmentName;
|
|
if (pwzStr)
|
|
_pwzAttachmentName = OLESTRDuplicate((LPWSTR)pwzStr);
|
|
else
|
|
_pwzAttachmentName = NULL;
|
|
hr = pCBdg->ReportProgress(NotMsg, pwzStr);
|
|
break;
|
|
|
|
case BINDSTATUS_ACCEPTRANGES:
|
|
_fAcceptRanges = TRUE;
|
|
hr = pCBdg->ReportProgress(NotMsg, pwzStr);
|
|
break;
|
|
|
|
default:
|
|
{
|
|
hr = pCBdg->ReportProgress(NotMsg, pwzStr);
|
|
}
|
|
|
|
} // end switch
|
|
}
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::DispatchReport (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CTransaction::PreDispatch()
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::PreDispatch",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::PreDispatch");
|
|
HRESULT hr = S_OK;
|
|
|
|
{ // single access block
|
|
CLock lck(_mxsBind);
|
|
if (_fTerminated || _fTerminating)
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
else
|
|
{
|
|
_dwDispatchLevel++;
|
|
}
|
|
}
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::PreDispatch (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CTransaction::PostDispatch()
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::PostDispatch",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::PostDispatch");
|
|
HRESULT hr = NOERROR;
|
|
BOOL fCallTerminate = FALSE;
|
|
|
|
|
|
{ // single access block
|
|
CLock lck(_mxsBind);
|
|
_dwDispatchLevel--;
|
|
fCallTerminate = _fReceivedTerminate;
|
|
_fReceivedTerminate = FALSE;
|
|
}
|
|
|
|
if (fCallTerminate)
|
|
{
|
|
Terminate(_dwTerminateOptions);
|
|
}
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::PostDispatch (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::DispatchPacket
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pCTPIn] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 2-02-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CTransaction::DispatchPacket(CTransPacket *pCTPIn)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::DispatchPacket",
|
|
"this=%#x, %#x",
|
|
this, pCTPIn
|
|
));
|
|
|
|
PerfDbgLog2(tagCTransaction, this, "+CTransaction::DispatchPacket [pCTPIn:%lx, NotMsg:%lx]", pCTPIn, pCTPIn->GetNotMsg());
|
|
HRESULT hr = NOERROR;
|
|
|
|
// the packet should be in the list
|
|
TransAssert((_fDispatch == TRUE));
|
|
TransAssert((_pCTPCur == NULL && pCTPIn));
|
|
_pCTPCur = pCTPIn;
|
|
|
|
hr = DispatchReport(pCTPIn->GetNotMsg(), _grfBSCF, pCTPIn->_dwCurrentSize, pCTPIn->_dwTotalSize, pCTPIn->_pwzStr, pCTPIn->_dwResult, pCTPIn->_hrResult);
|
|
|
|
_pCTPCur = NULL;
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::DispatchPacket (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::OnINetCallback
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pCTPIn] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 12-11-95 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CTransaction::OnINetCallback(BOOL fFromMsgQueue)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::OnINetCallback",
|
|
"this=%#x, %B",
|
|
this, fFromMsgQueue
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::OnINetCallback");
|
|
HRESULT hrRelease = NOERROR;
|
|
CTransPacket *pCTP = NULL;
|
|
|
|
if (fFromMsgQueue)
|
|
{
|
|
_cPostedMsg--;
|
|
}
|
|
|
|
// the packet should be in the list
|
|
if ( IsApartmentThread()
|
|
&& (_fDispatch == FALSE)
|
|
&& GotCTransPacket() )
|
|
{
|
|
_fDispatch = TRUE;
|
|
BOOL fDispatch = (_ThreadTransferState == TS_None) || (_ThreadTransferState == TS_Completed);
|
|
|
|
ThreadSwitchState TSState = _ThreadTransferState;
|
|
|
|
// multiple packets migth be dispatched -
|
|
// therefor the list of packets might be empty
|
|
|
|
while ( fDispatch
|
|
&& ((pCTP = GetNextCTransPacket()) != NULL))
|
|
{
|
|
if (pCTP->GetNotMsg() == BINDSTATUS_INTERNAL)
|
|
{
|
|
OnINetInternalCallback(pCTP);
|
|
}
|
|
else
|
|
{
|
|
hrRelease = DispatchPacket(pCTP);
|
|
}
|
|
|
|
if ( (TSState == TS_None)
|
|
&& (_ThreadTransferState == TS_Prepared))
|
|
{
|
|
// do not dispatch any further packages on this thread
|
|
// wait until the transfer completes
|
|
fDispatch = FALSE;
|
|
}
|
|
|
|
//TRIDENT BTS->BTO
|
|
if (hrRelease == INET_E_TERMINATED_BIND)
|
|
{
|
|
SuspendDispatchingPackets(pCTP);
|
|
|
|
fDispatch = FALSE;
|
|
}
|
|
|
|
// delete the data now
|
|
delete pCTP;
|
|
}
|
|
|
|
if (hrRelease == INET_E_TERMINATED_BIND)
|
|
hrRelease = NOERROR; //TRIDENT BTS->BTO reset hrRelease
|
|
else
|
|
_fDispatch = FALSE;
|
|
}
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::OnINetCallback (hr:%lx)", hrRelease);
|
|
|
|
DEBUG_LEAVE(hrRelease);
|
|
return hrRelease;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::OnINetInternalCallback
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [dwState] --
|
|
// [fFromMsgQueue] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 3-05-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CTransaction::OnINetInternalCallback(CTransPacket *pCTPIn)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::OnINetInternalCallback",
|
|
"this=%#x, %#x",
|
|
this, pCTPIn
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::OnINetInternalCallback");
|
|
HRESULT hr = NOERROR;
|
|
TransAssert((IsApartmentThread()));
|
|
TransAssert((_pProt));
|
|
|
|
_cPostedMsg--;
|
|
_pProt->Continue(pCTPIn);
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::OnINetInternalCallback (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: UrlMonInvokeExceptionFilter
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [lCode] --
|
|
// [lpep] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 2-14-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
LONG UrlMonInvokeExceptionFilter( DWORD lCode, LPEXCEPTION_POINTERS lpep )
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Int,
|
|
"UrlMonInvokeExceptionFilter",
|
|
"%#x, %#x",
|
|
lCode, lpep
|
|
));
|
|
|
|
#if DBG == 1
|
|
DbgLog2(tagCTransactionErr, NULL, "Exception 0x%#x at address 0x%#x",
|
|
lCode, lpep->ExceptionRecord->ExceptionAddress);
|
|
DebugBreak();
|
|
#endif
|
|
|
|
DEBUG_LEAVE(EXCEPTION_EXECUTE_HANDLER);
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: TransactionWndProc
|
|
//
|
|
// Synopsis: the transaction callback function
|
|
//
|
|
// Arguments: [hWnd] --
|
|
// [WPARAM] --
|
|
// [wParam] --
|
|
// [lParam] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 12-02-95 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
LRESULT CALLBACK TransactionWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Dword,
|
|
"TransactionWndProc",
|
|
"%#x, %#u, %#x, %#x",
|
|
hWnd, msg, wParam, lParam
|
|
));
|
|
|
|
if ((msg >= WM_TRANS_FIRST && msg <= WM_TRANS_LAST))
|
|
{
|
|
switch (msg)
|
|
{
|
|
case WM_TRANS_PACKET:
|
|
{
|
|
DWORD dwFault;
|
|
CTransaction *pCTrans = (CTransaction *) lParam;
|
|
#ifdef WITH_EXCEPTION
|
|
_try
|
|
#endif //WITH_EXCEPTION
|
|
{
|
|
TransAssert((pCTrans != NULL));
|
|
PerfDbgLog1(tagCTransaction, pCTrans, "+CTransaction::TransactionWndProc (Msg:%#x)", wParam);
|
|
|
|
pCTrans->OnINetCallback(TRUE);
|
|
|
|
if (pCTrans->Release() == 0)
|
|
{
|
|
DbgLog(tagCTransaction, pCTrans, "=== CTransaction::TransactionWndProc Last Release!");
|
|
pCTrans = 0;
|
|
}
|
|
|
|
PerfDbgLog1(tagCTransaction, pCTrans, "-CTransaction::TransactionWndProc (Msg:%#x) WM_TRANS_PACKET", wParam);
|
|
}
|
|
#ifdef WITH_EXCEPTION
|
|
_except(UrlMonInvokeExceptionFilter(GetExceptionCode(), GetExceptionInformation()))
|
|
{
|
|
dwFault = GetExceptionCode();
|
|
|
|
#if DBG == 1
|
|
//
|
|
// UrlMon catches exceptions when the client generates them. This is so we can
|
|
// cleanup properly, and allow urlmon to continue.
|
|
//
|
|
if ( dwFault == STATUS_ACCESS_VIOLATION
|
|
|| dwFault == 0xC0000194 /*STATUS_POSSIBLE_DEADLOCK*/
|
|
|| dwFault == 0xC00000AA /*STATUS_INSTRUCTION_MISALIGNMENT*/
|
|
|| dwFault == 0x80000002 /*STATUS_DATATYPE_MISALIGNMENT*/ )
|
|
{
|
|
WCHAR iidName[256];
|
|
iidName[0] = 0;
|
|
char achProgname[256];
|
|
achProgname[0] = 0;
|
|
|
|
GetModuleFileNameA(NULL,achProgname,sizeof(achProgname));
|
|
DbgLog2(tagCTransactionErr, pCTrans,
|
|
"UrlMon has caught a fault 0x%08x on behalf of application %s",
|
|
dwFault, achProgname);
|
|
|
|
}
|
|
#endif
|
|
}
|
|
#ifdef unix
|
|
__endexcept
|
|
#endif /* unix */
|
|
#endif //WITH_EXCEPTION
|
|
}
|
|
break;
|
|
case WM_TRANS_NOPACKET:
|
|
case WM_TRANS_OUTOFMEMORY:
|
|
// tell the
|
|
break;
|
|
case WM_TRANS_INTERNAL:
|
|
{
|
|
TransAssert((FALSE));
|
|
}
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
DWORD lResult = (DWORD)DefWindowProc(hWnd, msg, wParam, lParam);
|
|
|
|
DEBUG_LEAVE(lResult);
|
|
return lResult;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::AddCTransPacket
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pCTP] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 12-11-95 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
void CTransaction::AddCTransPacket(CTransPacket *pCTP, BOOL fTail)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
None,
|
|
"CTransaction::AddCTransPacket",
|
|
"this=%#x, %#x, %B",
|
|
this, pCTP, fTail
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::AddCTransPacket");
|
|
CLock lck(_mxs);
|
|
//TransAssert((pCTP != NULL && (pCTP->GetNotMsg() > Notify_None && pCTP->GetNotMsg() <= Notify_Internal) ));
|
|
|
|
if (fTail)
|
|
{
|
|
|
|
if (_pCTPHead == NULL)
|
|
{
|
|
TransAssert((_pCTPTail == NULL));
|
|
TransAssert((_cPacketsInList == 0));
|
|
_pCTPHead = pCTP;
|
|
_pCTPTail = pCTP;
|
|
_pCTPTail->SetNext(NULL);
|
|
|
|
}
|
|
else
|
|
{
|
|
_pCTPTail->SetNext(pCTP);
|
|
_pCTPTail = pCTP;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// add it at the front
|
|
if (_pCTPHead == NULL)
|
|
{
|
|
TransAssert((_pCTPTail == NULL));
|
|
TransAssert((_cPacketsInList == 0));
|
|
_pCTPHead = pCTP;
|
|
_pCTPTail = pCTP;
|
|
_pCTPTail->SetNext(NULL);
|
|
|
|
}
|
|
else
|
|
{
|
|
pCTP->SetNext(_pCTPHead);
|
|
_pCTPHead = pCTP;
|
|
}
|
|
}
|
|
_cPacketsInList++;
|
|
TransAssert((_cPacketsInList > 0));
|
|
|
|
PerfDbgLog3(tagCTransaction, this, "-CTransaction::AddCTransPacket [pCTP(%lx)[%lx], cPackets:%ld] ",
|
|
pCTP, pCTP->GetNotMsg(),_cPacketsInList);
|
|
|
|
DEBUG_LEAVE(0);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::GetNextCTransPacket
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: (none)
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 12-11-95 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CTransPacket *CTransaction::GetNextCTransPacket()
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Pointer,
|
|
"CTransaction::GetNextCTransPacket",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::GetNextCTransPacket");
|
|
CLock lck(_mxs);
|
|
CTransPacket *pCTP;
|
|
|
|
pCTP = _pCTPHead;
|
|
if (_pCTPHead == NULL)
|
|
{
|
|
TransAssert((_pCTPTail == NULL));
|
|
TransAssert((_cPacketsInList == 0));
|
|
}
|
|
else if (_pCTPHead == _pCTPTail)
|
|
{
|
|
TransAssert((_pCTPTail->GetNext() == NULL));
|
|
// only one packet in fifo
|
|
_pCTPHead = _pCTPTail = NULL;
|
|
}
|
|
else
|
|
{
|
|
_pCTPHead = _pCTPHead->GetNext();
|
|
}
|
|
|
|
if (pCTP)
|
|
{
|
|
_cPacketsInList--;
|
|
}
|
|
|
|
//TransAssert(( (pCTP == NULL) || (pCTP != NULL && (pCTP->GetNotMsg() > Notify_None && pCTP->GetNotMsg() <= Notify_Internal)) ));
|
|
|
|
TransAssert(( ((pCTP == NULL) && (_cPacketsInList == 0))
|
|
|| ((pCTP != NULL) && (_cPacketsInList >= 0)) ));
|
|
|
|
/*
|
|
TransAssert(( ((pCTP == NULL) && (_cPacketsInList == 0))
|
|
|| ((pCTP != NULL) && (_cPacketsInList >= 0))
|
|
|| ((pCTP != NULL) && (_cPacketsInList == 0) && ((pCTP->GetNotMsg() == Notify_None) || (pCTP->GetNotMsg() == Notify_Error )))
|
|
));
|
|
*/
|
|
|
|
|
|
PerfDbgLog2(tagCTransaction, this, "-CTransaction::GetNextCTransPacket [pCTP(%lx), cPackets:%ld] ",
|
|
pCTP, _cPacketsInList);
|
|
|
|
DEBUG_LEAVE(pCTP);
|
|
return pCTP;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::GotCTransPacket
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: (none)
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 12-11-95 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL CTransaction::GotCTransPacket()
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Bool,
|
|
"CTransaction::GotCTransPacket",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::GotCTransPacket");
|
|
CLock lck(_mxs);
|
|
BOOL fGot = _pCTPHead ? true : false;
|
|
PerfDbgLog(tagCTransaction, this, "-CTransaction::GotCTransPacket");
|
|
|
|
DEBUG_LEAVE(fGot);
|
|
return fGot;
|
|
}
|
|
|
|
CTransPacket::CTransPacket(PROTOCOLDATA *pSI)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
None,
|
|
"CTransPacket::CTransPacket",
|
|
"this=%#x, %#x",
|
|
this, pSI
|
|
));
|
|
|
|
TransAssert((pSI));
|
|
grfFlags = pSI->grfFlags;
|
|
dwState = pSI->dwState ;
|
|
pData = pSI->pData ;
|
|
cbData = pSI->cbData ;
|
|
|
|
_dwCurrentSize = 0;
|
|
_dwTotalSize = 0;
|
|
_dwResult = 0;
|
|
_pwzStr = 0;
|
|
_hrResult = 0;
|
|
_NotMsg = (BINDSTATUS) BINDSTATUS_INTERNAL;
|
|
|
|
DEBUG_LEAVE(0);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransPacket::CTransPacket
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [NMsg] --
|
|
// [hrRet] --
|
|
// [szStr] --
|
|
// [cbAvailable] --
|
|
// [cbTotal] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 11-09-1996 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CTransPacket::CTransPacket(BINDSTATUS NMsg, HRESULT hrRet, LPCWSTR szStr, DWORD cbAvailable, DWORD cbTotal, DWORD dwResult)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
None,
|
|
"CTransPacket::CTransPacket",
|
|
"this=%#x, %#x, %#x, %.80wq, %#x, %#x, %#x",
|
|
this, NMsg, hrRet, szStr, cbAvailable, cbTotal, dwResult
|
|
));
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "+CTransPacket::CTransPacket (NMsg:%lx)", NMsg);
|
|
|
|
_dwCurrentSize = cbAvailable;
|
|
_dwTotalSize = cbTotal;
|
|
_hrResult = hrRet;
|
|
_pCTPNext = NULL;
|
|
_NotMsg = NMsg;
|
|
_pwzStr = NULL;
|
|
_dwResult = dwResult;
|
|
|
|
if (szStr)
|
|
{
|
|
_pwzStr = OLESTRDuplicate( (LPWSTR)szStr );
|
|
}
|
|
|
|
dwState = _NotMsg;
|
|
pData = this;
|
|
cbData = sizeof(CTransPacket);
|
|
grfFlags = 0;
|
|
|
|
PerfDbgLog(tagCTransaction, this, "-CTransPacket::CTransPacket");
|
|
|
|
DEBUG_LEAVE(0);
|
|
}
|
|
|
|
CTransPacket& CTransPacket::operator=(const CTransPacket& CTPSrc)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
None,
|
|
"CTransPacket::operator=",
|
|
"this=%#x, %#x",
|
|
this, CTPSrc
|
|
));
|
|
|
|
if (&CTPSrc != this)
|
|
{
|
|
grfFlags = CTPSrc.grfFlags;
|
|
dwState = CTPSrc.dwState ;
|
|
pData = CTPSrc.pData ;
|
|
cbData = CTPSrc.cbData ;
|
|
|
|
_dwCurrentSize = CTPSrc._dwCurrentSize;
|
|
_dwTotalSize = CTPSrc._dwTotalSize;
|
|
_dwResult = CTPSrc._dwResult;
|
|
_pwzStr = NULL;
|
|
_hrResult = CTPSrc._hrResult;
|
|
_NotMsg = CTPSrc._NotMsg;
|
|
_pCTPNext = CTPSrc._pCTPNext;
|
|
|
|
if (CTPSrc._pwzStr)
|
|
{
|
|
_pwzStr = OLESTRDuplicate( CTPSrc._pwzStr );
|
|
}
|
|
}
|
|
|
|
DEBUG_LEAVE(0);
|
|
return *this;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransPacket::~CTransPacket
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: (none)
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 12-11-95 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CTransPacket::~CTransPacket()
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
None,
|
|
"CTransPacket::~CTransPacket",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransPacket::~CTransPacket");
|
|
|
|
if (_pwzStr)
|
|
{
|
|
delete _pwzStr;
|
|
}
|
|
|
|
PerfDbgLog(tagCTransaction, this, "-CTransPacket::~CTransPacket");
|
|
|
|
DEBUG_LEAVE(0);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::CPrivUnknown::QueryInterface
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [riid] --
|
|
// [ppvObj] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 10-29-1996 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CTransaction::CPrivUnknown::QueryInterface(REFIID riid, void **ppvObj)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::CPrivUnknown::IUnknown::QueryInterface",
|
|
"this=%#x, %#x, %#x",
|
|
this, &riid, ppvObj
|
|
));
|
|
|
|
VDATEPTROUT(ppvObj, void *);
|
|
VDATETHIS(this);
|
|
HRESULT hr = NOERROR;
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::CPrivUnknown::QueryInterface");
|
|
CTransaction *pCTrans = GETPPARENT(this, CTransaction, _Unknown);
|
|
|
|
*ppvObj = NULL;
|
|
if ((riid == IID_IUnknown) || (riid == IID_IOInetProtocolSink) )
|
|
{
|
|
*ppvObj = (IOInetProtocolSink *) pCTrans;
|
|
pCTrans->AddRef();
|
|
}
|
|
else if (riid == IID_IOInetBindInfo)
|
|
{
|
|
*ppvObj = (IOInetBindInfo *) pCTrans;
|
|
pCTrans->AddRef();
|
|
}
|
|
else if (riid == IID_IServiceProvider)
|
|
{
|
|
*ppvObj = (IServiceProvider *) pCTrans;
|
|
pCTrans->AddRef();
|
|
}
|
|
else if (riid == IID_IAuthenticate)
|
|
{
|
|
*ppvObj = (IAuthenticate *) pCTrans;
|
|
pCTrans->AddRef();
|
|
}
|
|
else if (riid == IID_IOInetProtocol)
|
|
{
|
|
*ppvObj = (IOInetProtocol *) pCTrans;
|
|
pCTrans->AddRef();
|
|
}
|
|
else if (riid == IID_IOInetPriority)
|
|
{
|
|
*ppvObj = (IOInetPriority *) pCTrans;
|
|
pCTrans->AddRef();
|
|
}
|
|
else if (riid == IID_ITransProtocolSink)
|
|
{
|
|
*ppvObj = (ITransProtocolSink *) pCTrans;
|
|
pCTrans->AddRef();
|
|
}
|
|
else if (riid == IID_IWrappedProtocol)
|
|
{
|
|
*ppvObj = (IWrappedProtocol *) pCTrans;
|
|
pCTrans->AddRef();
|
|
}
|
|
else if (pCTrans->_pUnkInner)
|
|
{
|
|
hr = pCTrans->_pUnkInner->QueryInterface(riid, ppvObj);
|
|
}
|
|
else
|
|
{
|
|
hr = E_NOINTERFACE;
|
|
}
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::CPrivUnknown::QueryInterface (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CTransaction::CPrivUnknown::AddRef
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [ULONG] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 10-29-1996 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG) CTransaction::CPrivUnknown::AddRef(void)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Dword,
|
|
"CTransaction::CPrivUnknown::AddRef",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::CPrivUnknown::IUnknown::AddRef");
|
|
|
|
LONG lRet = ++_CRefs;
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::CPrivUnknown::AddRef (cRefs:%ld)", lRet);
|
|
|
|
DEBUG_LEAVE(lRet);
|
|
return lRet;
|
|
}
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CTransaction::Release
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [ULONG] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 10-29-1996 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG) CTransaction::CPrivUnknown::Release(void)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Dword,
|
|
"CTransaction::CPrivUnknown::IUnknown::Release",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::CPrivUnknown::Release");
|
|
|
|
CTransaction *pCTransaction = GETPPARENT(this, CTransaction, _Unknown);
|
|
|
|
LONG lRet = --_CRefs;
|
|
|
|
if (lRet == 0)
|
|
{
|
|
delete pCTransaction;
|
|
}
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::CPrivUnknown::Release (cRefs:%ld)", lRet);
|
|
|
|
DEBUG_LEAVE(lRet);
|
|
return lRet;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::OnAttach
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pwzURL] --
|
|
// [pOInetBindInfo] --
|
|
// [pOInetProtSink] --
|
|
// [riid] --
|
|
// [grfOptions] --
|
|
// [pClsidProtocol] --
|
|
// [dwReserved] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 4-10-1997 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CTransaction::OnAttach(LPCWSTR pwzURL, IOInetBindInfo *pOInetBindInfo, IOInetProtocolSink *pOInetProtSink, DWORD grfOptions, DWORD_PTR dwReserved)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::OnAttach",
|
|
"this=%#x, %.80wq, %#x, %#x, %#x, %#x",
|
|
this, pwzURL, pOInetBindInfo, pOInetProtSink, grfOptions, dwReserved
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::OnAttach");
|
|
HRESULT hr = NOERROR;
|
|
VDATETHIS(this);
|
|
do
|
|
{
|
|
hr = NOERROR;
|
|
if (_pwzProtClsId)
|
|
{
|
|
pOInetProtSink->ReportProgress(BINDSTATUS_PROTOCOLCLASSID, _pwzProtClsId);
|
|
}
|
|
|
|
if (_pwzRedirectUrl)
|
|
{
|
|
pOInetProtSink->ReportProgress(BINDSTATUS_REDIRECTING,_pwzRedirectUrl);
|
|
}
|
|
|
|
if ( (grfOptions & (PI_MIMEVERIFICATION | PI_DOCFILECLSIDLOOKUP))
|
|
&& _fMimeVerified
|
|
&& _pwzMimeSuggested)
|
|
{
|
|
pOInetProtSink->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, _pwzMimeSuggested);
|
|
}
|
|
|
|
if (_fMimeHandlerLoaded)
|
|
{
|
|
pOInetProtSink->ReportProgress(BINDSTATUS_LOADINGMIMEHANDLER, NULL);
|
|
}
|
|
|
|
if (_pwzFileName)
|
|
{
|
|
pOInetProtSink->ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE, _pwzFileName);
|
|
}
|
|
|
|
// report data now
|
|
// Shdocvw BTO->BTS case
|
|
if (!IsApartmentThread())
|
|
{
|
|
ThreadTransfer();
|
|
}
|
|
// Shdocvw BTO -> Trident BTS case
|
|
else if (_pCTPCur)
|
|
{
|
|
HRESULT hr1;
|
|
hr1 = DispatchReport(_pCTPCur->GetNotMsg(),_grfBSCF, _pCTPCur->_dwCurrentSize, _pCTPCur->_dwTotalSize, _pCTPCur->_pwzStr, 0);
|
|
}
|
|
// Trident BTS-> Shdocvw BTO
|
|
else if (_grfInternalFlags & BDGFLAGS_BTS_BTO)
|
|
{
|
|
ResumeDispatchingPackets();
|
|
}
|
|
|
|
break;
|
|
} while (TRUE);
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::OnAttach (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//
|
|
// IOInetProtocol
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::Start
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pwzURL] --
|
|
// [pOInetProtSink] --
|
|
// [pOInetBindInfo] --
|
|
// [grfOptions] --
|
|
// [dwReserved] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 4-10-1997 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CTransaction::Start(LPCWSTR pwzURL, IOInetProtocolSink *pOInetProtSink,
|
|
IOInetBindInfo *pOInetBindInfo, DWORD grfOptions, DWORD_PTR dwReserved)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::IInternetProtocolRoot::Start",
|
|
"this=%#x, %.80wq, %#x, %#x, %#x, %#x",
|
|
this, pwzURL, pOInetProtSink, pOInetBindInfo, grfOptions, dwReserved
|
|
));
|
|
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::Start");
|
|
HRESULT hr = NOERROR;
|
|
VDATETHIS(this);
|
|
COInetSession *pCOInetSession = 0;
|
|
DWORD dwLocation = 0;
|
|
|
|
AddRef();
|
|
|
|
do
|
|
{
|
|
if ( !pwzURL
|
|
|| !pOInetBindInfo
|
|
|| !pOInetProtSink
|
|
)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
break;
|
|
}
|
|
if (GetState() == TransSt_OperationFinished)
|
|
{
|
|
hr = E_FAIL;
|
|
break;
|
|
}
|
|
|
|
_fPreferDefaultHandler = (grfOptions & BINDF_PREFERDEFAULTHANDLER)?TRUE:FALSE;
|
|
//
|
|
// case Attachment
|
|
//
|
|
if (GetState() == TransSt_OperationStarted)
|
|
{
|
|
{ // single access block
|
|
CLock lck(_mxsBind);
|
|
|
|
TransAssert((grfOptions & (BDGFLAGS_ATTACHED|BDGFLAGS_BTS_BTO)));
|
|
|
|
if (grfOptions & BDGFLAGS_PARTIAL)
|
|
{
|
|
_grfInternalFlags |= BDGFLAGS_PARTIAL;
|
|
}
|
|
|
|
/* False asserts after Trident BTS->BTO
|
|
TransAssert((_grfInternalFlags & BDGFLAGS_PARTIAL));
|
|
TransAssert((!_fAttached));
|
|
*/
|
|
_fAttached = TRUE;
|
|
if (grfOptions & BDGFLAGS_ATTACHED)
|
|
{
|
|
_grfInternalFlags &= ~BDGFLAGS_BTS_BTO;
|
|
_grfInternalFlags |= BDGFLAGS_ATTACHED;
|
|
}
|
|
else if (grfOptions & BDGFLAGS_BTS_BTO)
|
|
{
|
|
_grfInternalFlags |= BDGFLAGS_BTS_BTO;
|
|
_CProtEmbed.InitAttachedBindToObject();
|
|
}
|
|
|
|
if (_fProtEmbed)
|
|
{
|
|
// no sniffing in this object
|
|
_dwOInetBdgFlags = (grfOptions & ~(PI_MIMEVERIFICATION | PI_DOCFILECLSIDLOOKUP | PI_CLASSINSTALL));
|
|
}
|
|
else
|
|
{
|
|
_dwOInetBdgFlags = (grfOptions | PI_DATAPROGRESS);
|
|
}
|
|
|
|
|
|
AddClientOInet(pOInetProtSink, pOInetBindInfo);
|
|
|
|
}
|
|
|
|
hr = OnAttach(pwzURL, pOInetBindInfo, pOInetProtSink, grfOptions, dwReserved);
|
|
break;
|
|
}
|
|
|
|
if (grfOptions & PI_NOMIMEHANDLER)
|
|
_fMimeHandlerEnabled = FALSE;
|
|
|
|
//
|
|
// case: Start of Transaction
|
|
//
|
|
|
|
TransAssert((_pClntProtSink == NULL));
|
|
BOOL fFirstCreated = FALSE;
|
|
|
|
{ // single access block
|
|
CLock lck(_mxsBind);
|
|
|
|
int cchUrlLen;
|
|
|
|
cchUrlLen = wcslen(pwzURL) + 1;
|
|
_pwzUrl = (LPWSTR) new WCHAR [cchUrlLen];
|
|
if (!_pwzUrl)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
|
|
wcscpy(_pwzUrl, pwzURL);
|
|
|
|
TransAssert((_pClntProtSink == 0 && _cBdgRefs == 0));
|
|
|
|
AddClientOInet(pOInetProtSink, pOInetBindInfo);
|
|
|
|
if (grfOptions & BDGFLAGS_PARTIAL)
|
|
{
|
|
_grfInternalFlags |= BDGFLAGS_PARTIAL;
|
|
}
|
|
|
|
if (_fProtEmbed)
|
|
{
|
|
// no sniffing in this object
|
|
_dwOInetBdgFlags = (grfOptions & ~(PI_MIMEVERIFICATION | PI_DOCFILECLSIDLOOKUP | PI_CLASSINSTALL));
|
|
}
|
|
else
|
|
{
|
|
_dwOInetBdgFlags = (grfOptions | PI_DATAPROGRESS);
|
|
}
|
|
|
|
} // end single access
|
|
|
|
//
|
|
// OE4( yet another shipped-so-we-can't-fix product ) will assume
|
|
// ReportResult is always Async (urlmon post a message), because
|
|
// they will do TWO reportResult, if we don't do Async, Terminate
|
|
// will called before the first ReportResult returns, which cleans
|
|
// up everything, when OE4 calls back with second ReportResult, they
|
|
// will fault in urlmon.
|
|
//
|
|
LONG dwMS = sizeof("mhtml:") - 1;
|
|
if( wcslen(_pwzUrl) >= dwMS && !StrCmpNIW(_pwzUrl, L"mhtml:", dwMS) )
|
|
{
|
|
_fForceAsyncReportResult = TRUE;
|
|
}
|
|
|
|
|
|
|
|
// We must have at least one node in the client request linked list
|
|
TransAssert((_pClntProtSink != NULL));
|
|
|
|
hr = QueryService(IID_IOInetProtocol, IID_IOInetProtocol ,(void **)&_pProt);
|
|
// work around InfoViewer bug(IE4 RAID #53224),
|
|
// they will return NOERROR with _pProt=NULL on QueryService()
|
|
if( hr == NOERROR && _pProt == NULL)
|
|
{
|
|
hr = E_NOINTERFACE;
|
|
}
|
|
|
|
if (hr != NOERROR)
|
|
{
|
|
if ((hr = GetCOInetSession(0,&pCOInetSession,0)) == NOERROR)
|
|
{
|
|
DWORD dwOption = _fPreferDefaultHandler ? BINDF_PREFERDEFAULTHANDLER : 0;
|
|
hr = pCOInetSession->CreateFirstProtocol(pwzURL, (IOInetBindInfo *) this, &_pUnkInner, &_pProt, &_clsidProtocol, &dwLocation, dwOption);
|
|
fFirstCreated = TRUE;
|
|
if ((hr == NOERROR) && _pUnkInner)
|
|
{
|
|
TransAssert((_pProt));
|
|
_pProt->Release();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// bugbug: find the correct cls id here.
|
|
_clsidProtocol = CLSID_FtpProtocol;
|
|
}
|
|
|
|
if (hr != NOERROR)
|
|
{
|
|
TransAssert((!_pProt && !_pUnkInner));
|
|
_pProt = 0;
|
|
_pUnkInner = 0;
|
|
break;
|
|
}
|
|
|
|
BOOL fNext;
|
|
BOOL fProtEmbedded = FALSE; // embed only once
|
|
TransAssert((_pProt));
|
|
do // loop over protocols
|
|
{
|
|
fNext = FALSE;
|
|
TransAssert((hr == NOERROR));
|
|
|
|
// Start the download operation
|
|
TransAssert((_pProt != NULL));
|
|
TransAssert(( !IsEqualIID(GetProtocolClassID(),CLSID_NULL) ));
|
|
|
|
{
|
|
delete [] _pwzProtClsId;
|
|
_pwzProtClsId = 0;
|
|
|
|
HRESULT hr1 = StringFromCLSID(_clsidProtocol, &_pwzProtClsId);
|
|
if (SUCCEEDED(hr1))
|
|
{
|
|
pOInetProtSink->ReportProgress(BINDSTATUS_PROTOCOLCLASSID, _pwzProtClsId);
|
|
}
|
|
}
|
|
|
|
SetState(TransSt_OperationStarted);
|
|
|
|
|
|
IOInetProtocol* pProtNotAgged = NULL;
|
|
if (_fProtEmbed && !fProtEmbedded)
|
|
{
|
|
_CProtEmbed.Initialize(this, 0, PP_PRE_SWITCH, grfOptions, 0, _pProt, pOInetProtSink, (LPWSTR )pwzURL);
|
|
_pClntProtSink = (IOInetProtocolSink *)&_CProtEmbed;
|
|
|
|
if (_pUnkInner)
|
|
{
|
|
// release the protocol we loaded
|
|
_pProt->Release();
|
|
}
|
|
else
|
|
{
|
|
// hold on to the non-aggregrated original prot,
|
|
// we will need to release it in case of we don't use
|
|
// this protocol
|
|
pProtNotAgged = _pProt;
|
|
}
|
|
|
|
_pProt = &_CProtEmbed;
|
|
fProtEmbedded = TRUE;
|
|
if (_pUnkInner)
|
|
{
|
|
// extra addref for second pointer to this class
|
|
_pProt->AddRef();
|
|
}
|
|
|
|
}
|
|
|
|
// 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();
|
|
}
|
|
|
|
{ // single access block
|
|
CLock lck(_mxsBind);
|
|
_fStarting = TRUE;
|
|
}
|
|
|
|
hr = _pProt->Start(pwzURL, this, (IOInetBindInfo *)this, 0,0);
|
|
|
|
{ // single access block
|
|
CLock lck(_mxsBind);
|
|
_fStarting = FALSE;
|
|
}
|
|
|
|
if (_fReceivedAbort && (hr != NOERROR))
|
|
{
|
|
Abort(_hrAbort, _dwAbort);
|
|
}
|
|
else if (hr == E_PENDING)
|
|
{
|
|
hr = NOERROR;
|
|
}
|
|
else if (hr == INET_E_USE_DEFAULT_PROTOCOLHANDLER)
|
|
{
|
|
fNext = TRUE;
|
|
AddRef();
|
|
|
|
if (!_pUnkInner)
|
|
{
|
|
_pProt->Release();
|
|
}
|
|
if (fProtEmbedded)
|
|
{
|
|
if(pProtNotAgged)
|
|
{
|
|
pProtNotAgged->Release();
|
|
pProtNotAgged = 0;
|
|
}
|
|
_CProtEmbed.SetProtocol(NULL);
|
|
}
|
|
fProtEmbedded = FALSE;
|
|
_pProt = 0;
|
|
|
|
if (_pUnkInner)
|
|
{
|
|
_pUnkInner->Release();
|
|
_pUnkInner = 0;
|
|
}
|
|
|
|
// bugbug: need to reset the protocol inside the embed protocol handler
|
|
|
|
if (!fFirstCreated)
|
|
{
|
|
DWORD dwOption = _fPreferDefaultHandler ? BINDF_PREFERDEFAULTHANDLER : 0;
|
|
hr = pCOInetSession->CreateFirstProtocol(pwzURL, (IOInetBindInfo *) this, &_pUnkInner, &_pProt, &_clsidProtocol, &dwLocation, dwOption);
|
|
fFirstCreated = TRUE;
|
|
}
|
|
else
|
|
{
|
|
hr = pCOInetSession->CreateNextProtocol(pwzURL, (IOInetBindInfo *) this, &_pUnkInner, &_pProt, &_clsidProtocol, &dwLocation);
|
|
}
|
|
|
|
if (hr != NOERROR)
|
|
{
|
|
TransAssert((!_pProt && !_pUnkInner));
|
|
_pProt = 0;
|
|
_pUnkInner = 0;
|
|
fNext = FALSE;
|
|
|
|
}
|
|
else if (_pUnkInner)
|
|
{
|
|
// release the extra addref - aggregation
|
|
Release();
|
|
}
|
|
|
|
}
|
|
else if (hr != NOERROR)
|
|
{
|
|
// do not allow pending packages be dispatched
|
|
// any more
|
|
fNext = FALSE;
|
|
_fDispatch = TRUE;
|
|
if (_pProt && !_fTerminated)
|
|
{
|
|
_fResultDispatched = TRUE;
|
|
|
|
if (fProtEmbedded)
|
|
{
|
|
_pClntProtSink->ReportResult(_hrResult, _dwResult, 0);
|
|
}
|
|
else
|
|
{
|
|
pOInetProtSink->ReportResult(_hrResult, _dwResult, 0);
|
|
}
|
|
Terminate(0);
|
|
}
|
|
}
|
|
|
|
if(pProtNotAgged)
|
|
{
|
|
pProtNotAgged->Release();
|
|
pProtNotAgged = 0;
|
|
}
|
|
|
|
} while (fNext == TRUE);
|
|
|
|
if ( (grfOptions & PI_SYNCHRONOUS)
|
|
&& SUCCEEDED(hr)
|
|
&& (_fModalLoopRunning == FALSE))
|
|
{
|
|
// complet the binding in case of sychronous bind
|
|
TransAssert((grfOptions & OIBDG_APARTMENTTHREADED));
|
|
_fModalLoopRunning = TRUE;
|
|
hr = CompleteOperation(grfOptions & (BDGFLAGS_ATTACHED|BDGFLAGS_BTS_BTO));
|
|
_fModalLoopRunning = FALSE;
|
|
}
|
|
|
|
break;
|
|
} while (TRUE);
|
|
|
|
if (pCOInetSession)
|
|
{
|
|
pCOInetSession->Release();
|
|
}
|
|
|
|
Release();
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::Start (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::Continue
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pStateInfo] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 4-10-1997 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CTransaction::Continue(PROTOCOLDATA *pStateInfo)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::IInternetProtocolRoot::Continue",
|
|
"this=%#x, %#x",
|
|
this, pStateInfo
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::Continue");
|
|
VDATETHIS(this);
|
|
|
|
HRESULT hr = NOERROR;
|
|
|
|
hr = _pProt->Continue(pStateInfo);
|
|
|
|
delete (CTransPacket *)pStateInfo;
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::Continue (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::Abort
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [hrReason] --
|
|
// [dwOptions] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 4-10-1997 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CTransaction::Abort(HRESULT hrReason, DWORD dwOptions)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::IInternetProtocolRoot::Abort",
|
|
"this=%#x, %#x, %#x",
|
|
this, hrReason, dwOptions
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::Abort");
|
|
VDATETHIS(this);
|
|
|
|
HRESULT hr = NOERROR;
|
|
BOOL fAbort = FALSE;
|
|
{ // single access block
|
|
|
|
CLock lck(_mxsBind);
|
|
|
|
if (!_fAborted && !_fTerminated && _pProt && (_ThreadTransferState == TS_None))
|
|
{
|
|
_fReceivedAbort = TRUE;
|
|
_hrAbort = hrReason;
|
|
_dwAbort = dwOptions;
|
|
// terminate might complete async!
|
|
if (hrReason == NOERROR)
|
|
{
|
|
hrReason = E_ABORT;
|
|
}
|
|
if (!_fStarting)
|
|
{
|
|
_fAborted = TRUE;
|
|
fAbort = TRUE;
|
|
}
|
|
}
|
|
} // end single access
|
|
|
|
if (fAbort)
|
|
{
|
|
hr = _pProt->Abort(hrReason, dwOptions);
|
|
if( hr == INET_E_RESULT_DISPATCHED )
|
|
{
|
|
//
|
|
// CINet already dispatch the ReportResult and it
|
|
// is currently in the CTrans's msg queue, we need to
|
|
// reset those flag so that when the ReportResult
|
|
// finally get processed, we won't get confused
|
|
// (Terminate gets called)
|
|
//
|
|
_fAborted = FALSE;
|
|
_fReceivedAbort = FALSE;
|
|
}
|
|
}
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::Abort (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::Terminate
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [dwOptions] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 4-10-1997 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CTransaction::Terminate(DWORD dwOptions)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::IInternetProtocolRoot::Terminate",
|
|
"this=%#x, %#x",
|
|
this, dwOptions
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::Terminate");
|
|
VDATETHIS(this);
|
|
HRESULT hr = E_FAIL;
|
|
BOOL fTotalTerminate = FALSE;
|
|
|
|
do
|
|
{
|
|
|
|
{ // single access block
|
|
CLock lck(_mxsBind);
|
|
|
|
if (_fTerminated)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (_dwDispatchLevel)
|
|
{
|
|
_fReceivedTerminate = TRUE;
|
|
_dwTerminateOptions = dwOptions;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
_fTerminating = TRUE;
|
|
}
|
|
fTotalTerminate = _fTerminated;
|
|
|
|
TransAssert(( (dwOptions == BDGFLAGS_PARTIAL)
|
|
|| (dwOptions == BDGFLAGS_ATTACHED)
|
|
|| (dwOptions == BDGFLAGS_BTS_BTO)
|
|
|| (dwOptions == 0) ));
|
|
|
|
//TransAssert((_grfInternalFlags & BDGFLAGS_PARTIAL));
|
|
|
|
if (dwOptions & BDGFLAGS_PARTIAL)
|
|
{
|
|
// remove the first sink
|
|
//
|
|
if (!(_grfInternalFlags & BDGFLAGS_ATTACHED))
|
|
{
|
|
// the new sink is not yet attached
|
|
TransAssert((_cBdgRefs == 1));
|
|
RemoveClientOInet();
|
|
|
|
// now make sure we shut down this on case no thread transfer is going on
|
|
if (_ThreadTransferState == TS_None)
|
|
{
|
|
_fAborted = TRUE;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
TransAssert(( ((_cBdgRefs == 1) && (_pClntProtSink != 0))
|
|
|| ((_cBdgRefs == 0) && (_pClntProtSink == 0)) ));
|
|
}
|
|
}
|
|
else if (dwOptions & BDGFLAGS_ATTACHED)
|
|
{
|
|
TransAssert((_cBdgRefs == 1));
|
|
RemoveClientOInet();
|
|
}
|
|
else if (dwOptions & BDGFLAGS_BTS_BTO)
|
|
{
|
|
TransAssert((_cBdgRefs == 1));
|
|
RemoveClientOInet();
|
|
}
|
|
else
|
|
{
|
|
// nothing to do here
|
|
}
|
|
|
|
}
|
|
|
|
if ( !fTotalTerminate
|
|
&& (_fResultDispatched || _fAborted))
|
|
{
|
|
fTotalTerminate = TRUE;
|
|
|
|
hr = NOERROR;
|
|
RemoveClientOInet();
|
|
|
|
//
|
|
// release pointers from the APP
|
|
//
|
|
if (_pInetInfo && !_pUnkInner)
|
|
{
|
|
_pInetInfo->Release();
|
|
_pInetInfo = NULL;
|
|
}
|
|
|
|
if (_pInetHttpInfo && !_pUnkInner)
|
|
{
|
|
_pInetHttpInfo->Release();
|
|
_pInetHttpInfo = NULL;
|
|
}
|
|
|
|
if (_pProt)
|
|
{
|
|
_pProt->Terminate(0);
|
|
}
|
|
|
|
if (_pBndInfo)
|
|
{
|
|
//
|
|
#if DBG == 1
|
|
if (_pBndInfo->stgmedData.tymed != TYMED_NULL)
|
|
{
|
|
PerfDbgLog1(tagCTransaction, this, "+CTransaction::Terminate ReleaseStgMedium (%lx)", _pBndInfo->stgmedData);
|
|
}
|
|
#endif
|
|
ReleaseBindInfo(_pBndInfo);
|
|
delete _pBndInfo;
|
|
_pBndInfo = NULL;
|
|
}
|
|
if (_fProtEmbed && _pUnkInner && !_fLocked && !_fUnlocked)
|
|
{
|
|
// remove extra refcount
|
|
_pProt->Release();
|
|
}
|
|
|
|
//
|
|
//
|
|
SetState(TransSt_OperationFinished);
|
|
|
|
TransAssert((_cBdgRefs == 0));
|
|
//TransAssert(( _fAborted || (!_fAborted && (_cPacketsInList == 0)) ));
|
|
}
|
|
|
|
{ // single access block
|
|
CLock lck(_mxsBind);
|
|
_fTerminating = FALSE;
|
|
if (fTotalTerminate)
|
|
{
|
|
_fTerminated = TRUE;
|
|
}
|
|
}
|
|
|
|
break;
|
|
} while (TRUE);
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::Terminate (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::Suspend
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: (none)
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 4-10-1997 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CTransaction::Suspend()
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::IInternetProtocolRoot::Suspend",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::Suspend");
|
|
VDATETHIS(this);
|
|
CLock lck(_mxsBind);
|
|
|
|
HRESULT hr = NOERROR;
|
|
|
|
if( _pProt )
|
|
{
|
|
hr = _pProt->Suspend();
|
|
}
|
|
else
|
|
{
|
|
hr = E_NOTIMPL;
|
|
}
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::Suspend (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::Resume
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: (none)
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 4-10-1997 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CTransaction::Resume()
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::IInternetProtocolRoot::Resume",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::Resume");
|
|
VDATETHIS(this);
|
|
CLock lck(_mxsBind);
|
|
|
|
HRESULT hr = NOERROR;
|
|
|
|
hr = _pProt->Resume();
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::Resume (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::Read
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pBuffer] --
|
|
// [cbBuffer] --
|
|
// [pcbRead] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 4-10-1997 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CTransaction::Read(void *pBuffer, ULONG cbBuffer, ULONG *pcbRead)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::IInternetProtocol::Read",
|
|
"this=%#x, %#x, %#x, %#x",
|
|
this, pBuffer, cbBuffer, pcbRead
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::Read");
|
|
HRESULT hr = E_FAIL;
|
|
VDATETHIS(this);
|
|
CLock lck(_mxsBind);
|
|
|
|
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 == TRUE)
|
|
{
|
|
if (_pProt)
|
|
{
|
|
hr = _pProt->Read( ((LPBYTE)pBuffer) + dwCopy, cbBuffer - dwCopy, &dwCopyNew);
|
|
_cbTotalBytesRead += dwCopyNew;
|
|
}
|
|
else
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
}
|
|
|
|
if (pcbRead)
|
|
{
|
|
*pcbRead = dwCopy + dwCopyNew;
|
|
}
|
|
|
|
PerfDbgLog4(tagCTransaction, this, "-CTransaction::Read (hr:%lx, cbRead:%lx, _cbTotalBytesRead:%lx, _cbBytesReported:%lx)",
|
|
hr, *pcbRead, _cbTotalBytesRead, _cbBytesReported);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::Seek
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [dlibMove] --
|
|
// [dwOrigin] --
|
|
// [plibNewPosition] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 4-10-1997 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CTransaction::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::IInternetProtocol::Seek",
|
|
"this=%#x, %#x, %#x, %#x",
|
|
this, dlibMove, dwOrigin, plibNewPosition
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::Seek");
|
|
VDATETHIS(this);
|
|
CLock lck(_mxsBind);
|
|
|
|
HRESULT hr = NOERROR;
|
|
|
|
hr = _pProt->Seek(dlibMove, dwOrigin, plibNewPosition);
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::Seek (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::LockRequest
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [dwOptions] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 4-10-1997 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CTransaction::LockRequest(DWORD dwOptions)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::IInternetProtocol::LockRequest",
|
|
"this=%#x, %#x",
|
|
this, dwOptions
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::LockRequest");
|
|
VDATETHIS(this);
|
|
CLock lck(_mxsBind);
|
|
|
|
HRESULT hr = NOERROR;
|
|
|
|
hr = _pProt->LockRequest(dwOptions);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
_fLocked = TRUE;
|
|
}
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::LockRequest (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::UnlockRequest
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: (none)
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 4-10-1997 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CTransaction::UnlockRequest()
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::IInternetProtocol::UnlockRequest",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::UnlockRequest");
|
|
VDATETHIS(this);
|
|
CLock lck(_mxsBind);
|
|
|
|
HRESULT hr = NOERROR;
|
|
|
|
hr = _pProt->UnlockRequest();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
_fLocked = FALSE;
|
|
_fUnlocked = TRUE;
|
|
if (_fProtEmbed && _pUnkInner)
|
|
{
|
|
// remove extra refcount to the protocol
|
|
_pProt->Release();
|
|
}
|
|
}
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::UnlockRequest (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::SetPriority
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [nPriority] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 10-29-1996 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CTransaction::SetPriority(LONG nPriority)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::IInternetPriority::SetPriority",
|
|
"this=%#x, %d",
|
|
this, nPriority
|
|
));
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "+CTransaction::SetPriority (%ld)", nPriority);
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
_nPriority = nPriority;
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::SetPriority (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::GetPriority
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pnPriority] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 10-29-1996 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CTransaction::GetPriority(LONG * pnPriority)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::IInternetPriority::GetPriority",
|
|
"this=%#x, %#x",
|
|
this, pnPriority
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::GetPriority");
|
|
|
|
HRESULT hr;
|
|
|
|
if (!pnPriority)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
*pnPriority = _nPriority;
|
|
hr = S_OK;
|
|
}
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::GetPriority (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::LoadHandler
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pwzStr] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 4-10-1997 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CTransaction::LoadHandler(LPCWSTR pwzURL, COInetProt *pCProtHndl, DWORD dwMode)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::LoadHandler",
|
|
"this=%#x, %.80wq, %#x, %#x",
|
|
this, pwzURL, pCProtHndl, dwMode
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::LoadHandler");
|
|
|
|
HRESULT hr = NOERROR;
|
|
VDATETHIS(this);
|
|
|
|
IOInetProtocol *pProtHandler = 0;
|
|
IOInetProtocolSink *pProtSnkHandler = 0;
|
|
|
|
IOInetProtocolSink *pProtSnkHandlerToMe = 0;
|
|
IOInetProtocol *pProtHandlerToMe = 0;
|
|
|
|
COInetSession *pCOInetSession = 0;
|
|
CLSID clsidHandler;
|
|
|
|
PROTOCOLFILTERDATA FilterData = {sizeof(PROTOCOLFILTERDATA), 0 ,0, 0,0};
|
|
|
|
hr = E_FAIL;
|
|
|
|
do
|
|
{
|
|
if (!pwzURL || !pCProtHndl)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
break;
|
|
}
|
|
|
|
if (!_fProtEmbed)
|
|
{
|
|
// can not load a handler without the embedded object
|
|
break;
|
|
}
|
|
|
|
if ((hr = GetCOInetSession(0,&pCOInetSession,0)) != NOERROR)
|
|
{
|
|
break;
|
|
}
|
|
hr = pCOInetSession->CreateHandler(pwzURL, 0, 0, &pProtHandler, &clsidHandler);
|
|
if (FAILED(hr))
|
|
{
|
|
break;
|
|
}
|
|
//
|
|
// get the interfaces for the handler
|
|
//
|
|
TransAssert((pProtHandler));
|
|
|
|
FilterData.pProtocolSink = 0;
|
|
FilterData.pProtocol = 0;
|
|
FilterData.pUnk = 0;
|
|
FilterData.dwFilterFlags = 0;
|
|
|
|
if (_dwOInetBdgFlags & PI_PASSONBINDCTX)
|
|
{
|
|
// do not need to addref pointer
|
|
FilterData.pUnk = _pBndCtx;
|
|
}
|
|
|
|
|
|
hr = pProtHandler->QueryInterface(IID_IOInetProtocolSink, (void **) &pProtSnkHandler);
|
|
if (hr != NOERROR)
|
|
{
|
|
break;
|
|
}
|
|
// set up the handler now
|
|
{
|
|
DWORD dwOptions = 0;
|
|
TransAssert((pProtSnkHandler));
|
|
pProtHandlerToMe = (IOInetProtocol *) pCProtHndl;
|
|
pProtSnkHandlerToMe = (IOInetProtocolSink *) pCProtHndl;
|
|
FilterData.pProtocol = pProtHandlerToMe;
|
|
_pClntProtSink = pProtSnkHandler;
|
|
_pProt = pProtHandler;
|
|
}
|
|
|
|
hr = pProtHandler->Start(pwzURL, pProtSnkHandlerToMe, (IOInetBindInfo *)this, PI_FILTER_MODE | PI_FORCE_ASYNC, (DWORD_PTR) &FilterData);
|
|
|
|
if (hr == NOERROR)
|
|
{
|
|
}
|
|
else if (hr == E_PENDING)
|
|
{
|
|
// send on the first junk of data
|
|
|
|
hr = NOERROR;
|
|
}
|
|
else
|
|
{
|
|
pProtHandler->Release();
|
|
pProtHandler = 0;
|
|
}
|
|
|
|
break;
|
|
} while (TRUE);
|
|
|
|
if (pCOInetSession)
|
|
{
|
|
pCOInetSession->Release();
|
|
}
|
|
|
|
if (pProtHandler)
|
|
{
|
|
pProtHandler->Release();
|
|
}
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction:: (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CTransaction::UpdateVerifiedMimeType
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pwzMime] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 5-20-1998 DanpoZ (Danpo Zhang) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
void CTransaction::UpdateVerifiedMimeType(LPCWSTR pwzMime)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
None,
|
|
"CTransaction::UpdateVerifiedMimeType",
|
|
"this=%#x, %.80wq",
|
|
this, pwzMime
|
|
));
|
|
|
|
if( pwzMime )
|
|
{
|
|
|
|
if( _pwzMimeSuggested )
|
|
{
|
|
delete [] _pwzMimeSuggested;
|
|
}
|
|
|
|
_pwzMimeSuggested = OLESTRDuplicate((LPWSTR)pwzMime);
|
|
_fMimeVerified = TRUE;
|
|
}
|
|
|
|
DEBUG_LEAVE(0);
|
|
}
|
|
|
|
|
|
HRESULT CTransaction::GetWrapperCode(LONG * pnCode, DWORD_PTR dwReserved)
|
|
{
|
|
DEBUG_ENTER((DBG_TRANS,
|
|
Hresult,
|
|
"CTransaction::IWrappedProtocol::GetWrapperCode",
|
|
"this=%#x, %#x, %#x",
|
|
this, pnCode, dwReserved
|
|
));
|
|
|
|
PerfDbgLog(tagCTransaction, this, "+CTransaction::GetWrapperCode");
|
|
|
|
HRESULT hr;
|
|
|
|
if(!pnCode)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
*pnCode = 0;
|
|
hr = S_OK;
|
|
}
|
|
|
|
PerfDbgLog1(tagCTransaction, this, "-CTransaction::GetWrapperCode (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|