|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995.
//
// File: transdata.cxx
//
// Contents: Contains the module which provide data passed on in OnDataAvailable
//
// Classes:
//
// Functions:
//
// History: 12-07-95 JohannP (Johann Posch) Created
//
//----------------------------------------------------------------------------
#include <trans.h>
#ifndef unix
#include "..\stg\rostmdir.hxx"
#include "..\stg\rostmfil.hxx"
#else
#include "../stg/rostmdir.hxx"
#include "../stg/rostmfil.hxx"
#endif /* unix */
PerfDbgTag(tagCTransData, "Urlmon", "Log CTransData", DEB_DATA); DbgTag(tagCTransDataErr, "Urlmon", "Log CTransData Errors", DEB_DATA|DEB_ERROR);
HRESULT FindMediaType(LPCSTR pszType, CLIPFORMAT *cfType); HRESULT FindMediaTypeW(LPCWSTR pwzType, CLIPFORMAT *cfType);
static LPSTR g_szCF_NULL = "*/*";
char szContent[] = "Content Type"; char szClassID[] = "CLSID"; char szFlags[] = "Flags"; char szExtension[] = "Extension"; char szMimeKey[] = "MIME\\Database\\Content Type\\"; const ULONG ulMimeKeyLen = ((sizeof(szMimeKey)/sizeof(char))-1);
// The byte combination that identifies that a file is a storage of
// some kind
const BYTE SIGSTG[] = {0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1}; const BYTE CBSIGSTG = sizeof(SIGSTG);
#define CBSNIFFDATA_MAX 256
#ifdef DBG
char *szDataSinkName[] = { "Unknown" ,"StreamNoCopyData" ,"File" ,"Storage" ,"StreamOnFile" ,"StreamBindToObject" ,"GenericStream" };
#define GetDataSinkName(ds) szDataSinkName[ds]
#else
#define GetDataSinkName(ds) ""
#endif
//+---------------------------------------------------------------------------
//
// Method: CTransData::CTransData
//
// Synopsis:
//
// Arguments: [pTrans] --
// [DWORD] --
// [dwSizeBuffer] --
// [fBindToObject] --
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
CTransData::CTransData(CTransaction *pTrans, LPBYTE pByte,DWORD dwSizeBuffer, BOOL fBindToObject) : _CRefs() { DEBUG_ENTER((DBG_TRANSDAT, None, "CTransData::CTransData", "this=%#x, %#x, %#x, %#x, %B", this, pTrans, pByte, dwSizeBuffer, fBindToObject )); _TransDataState = TransData_Initialized; _wzMime[0] = '\0'; _wzFileName[0]= 0; _pwzUrl = 0; _pwzRedirectUrl = 0; _pStgMed = 0; _lpBuffer = pByte; _cbBufferSize = dwSizeBuffer; _cbDataSize = 0; _cbTotalBytesRead = 0; _cbReadReturn = 0; _cbBufferFilled = 0; _cbDataSniffMin = DATASNIFSIZE_MIN; _pEnumFE = 0; _pStgMed = NULL; _pProt = NULL;
_fBindToObject = fBindToObject; //Flag changes on attachment.. Use sparingly.
_fMimeTypeVerified = TRUE; _fDocFile = FALSE; _fInitialized = FALSE; _fRemoteReady = FALSE; _fCache = FALSE; _fLocked = FALSE; _fFileAsStmOnFile = FALSE; _fEOFOnSwitchSink = FALSE;
_hFile = NULL; _cbBytesReported = 0; _dwAttached = 0; _grfBindF = 0; _grfBSC = 0;
DEBUG_LEAVE(0); }
//+---------------------------------------------------------------------------
//
// Method: CTransData::~CTransData
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
CTransData::~CTransData() { DEBUG_ENTER((DBG_TRANSDAT, None, "CTransData::~CTransData", "this=%#x", this )); PerfDbgLog(tagCTransData, this, "+CTransData::~CTransData");
if (_pwzUrl) { delete [] _pwzUrl; }
if (_pwzRedirectUrl) { delete [] _pwzRedirectUrl; } if (_pProt) { if (_fLocked) { _pProt->UnlockRequest(); } _pProt->Release(); _pProt = NULL; }
if (_pBndCtx) { _pBndCtx->Release(); }
if (_pStgMed) { TransAssert(( (_pStgMed->pUnkForRelease == NULL) || (_pStgMed->pUnkForRelease == this)));
if (_pStgMed->tymed == TYMED_ISTREAM) { _pStgMed->pstm->Release(); } else if (_pStgMed->tymed == TYMED_FILE) { if (_pStgMed->lpszFileName) { delete _pStgMed->lpszFileName; } } else if (_pStgMed->tymed == TYMED_ISTORAGE) { _pStgMed->pstg->Release(); }
DbgLog1(tagCTransData, this, "=== CTransData::~CTransData: (pStgMed:%lx)", _pStgMed); delete _pStgMed; _pStgMed = NULL; }
if (_hFile) { DbgLog1(tagCTransData, this, "=== CTransData::~CTransData (CloseHandle(%lx)", _hFile); CloseHandle(_hFile); _hFile = NULL; }
if (_lpBuffer) { delete _lpBuffer; }
PerfDbgLog(tagCTransData, this, "-CTransData::~CTransData"); DEBUG_LEAVE(0); }
//+---------------------------------------------------------------------------
//
// Method: CTransData::QueryInterface
//
// Synopsis:
//
// Arguments: [riid] --
// [ppvObj] --
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CTransData::QueryInterface(REFIID riid, void **ppvObj) { DEBUG_ENTER((DBG_TRANSDAT, Hresult, "CTransData::IUnknown::QueryInterface", "this=%#x, %#x, %#x", this, &riid, ppvObj )); VDATEPTROUT(ppvObj, void *); VDATETHIS(this); HRESULT hr = NOERROR;
PerfDbgLog(tagCTransData, this, "+CTransData::QueryInterface");
*ppvObj = NULL; if ((riid == IID_IUnknown) || (riid == IID_ITransactionData)) { *ppvObj = this; AddRef(); } else { hr = E_NOINTERFACE; }
PerfDbgLog1(tagCTransData, this, "-CTransData::QueryInterface (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: CTransData::AddRef
//
// Synopsis:
//
// Arguments: [ULONG] --
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CTransData::AddRef(void) { DEBUG_ENTER((DBG_TRANSDAT, Dword, "CTransData::IUnknown::AddRef", "this=%#x", this )); LONG lRet = ++_CRefs; PerfDbgLog1(tagCTransData, this, "CTransData::AddRef (cRefs:%ld)", lRet);
DEBUG_LEAVE(lRet); return lRet; }
//+---------------------------------------------------------------------------
//
// Function: CTransData::Release
//
// Synopsis:
//
// Arguments: [ULONG] --
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CTransData::Release(void) { DEBUG_ENTER((DBG_TRANSDAT, Dword, "CTransData::IUnknown::Release", "this=%#x", this )); PerfDbgLog(tagCTransData, this, "+CTransData::Release");
LONG lRet = --_CRefs;
if (_CRefs == 0) { delete this; }
PerfDbgLog1(tagCTransData, this, "-CTransData::Release (cRefs:%ld)", lRet);
DEBUG_LEAVE(lRet); return lRet; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::GetTransactionData
//
// Synopsis:
//
// Arguments: [pwzUrl] --
// [ppwzFilename] --
// [ppwzMime] --
// [pdwSizeTotal] --
// [pdwSizeAvailable] --
// [dwReserved] --
//
// Returns:
//
// History: 9-09-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CTransData::GetTransactionData(LPCWSTR pwzUrl, LPOLESTR *ppwzFilename, LPOLESTR *ppwzMime, DWORD *pdwSizeTotal, DWORD *pdwSizeAvailable, DWORD dwReserved) { DEBUG_ENTER((DBG_TRANSDAT, Hresult, "CTransData::GetTransactionData", "this=%#x, %.80wq, %#x, %#x, %#x, %#x, %#x", this, pwzUrl, ppwzFilename, ppwzMime, pdwSizeTotal, pdwSizeAvailable, dwReserved )); PerfDbgLog(tagCTransData, this, "+CTransData::GetTransactionData"); HRESULT hr = NOERROR; TransAssert((pwzUrl && ppwzFilename && ppwzMime && pdwSizeTotal && pdwSizeAvailable )); TransAssert((_wzFileName[0] != 0));
if (ppwzFilename && ppwzMime && pdwSizeTotal && pdwSizeAvailable) { LPWSTR pwzUrlLocal = GetUrl(); TransAssert((pwzUrlLocal));
DbgLog2(tagCTransData, this, "=== CTransData::GetTransactionData (pwzUrlLocal:%ws, pwzUrl:%ws)", pwzUrlLocal, pwzUrl);
if (!wcscmp(pwzUrl, _pwzUrl) || (_pwzRedirectUrl && !wcscmp(pwzUrl, _pwzRedirectUrl))) { *ppwzFilename = OLESTRDuplicate(_wzFileName);
*ppwzMime = OLESTRDuplicate(_wzMime);
if (_cbDataSize) { *pdwSizeTotal = _cbDataSize; } else { *pdwSizeTotal = _cbTotalBytesRead; } *pdwSizeAvailable = _cbTotalBytesRead;
} else { *ppwzFilename = 0; *ppwzMime = NULL; *pdwSizeTotal = 0; *pdwSizeAvailable = 0; hr = E_INVALIDARG; } } else { hr = E_INVALIDARG; }
PerfDbgLog5(tagCTransData, this, "-CTransData::GetTransactionData (hr:%lx, Filename:%ws, Mime:%ws, _cbDataSize:%ld, _cbTotalBytesRead:%ld)", hr, XDBG(*ppwzFilename,L""), XDBG(*ppwzMime,L""), _cbDataSize, _cbTotalBytesRead);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::Create
//
// Synopsis: Set up the transaction data object.
//
// Arguments: [pTrans] -- pointer to transaction
// [riid] -- riid the users passed in
// [ppCTD] -- the transdata object passed back
//
// Returns:
//
// History: 1-18-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CTransData::Create(LPCWSTR pwUrl, DWORD grfBindF, REFIID riid, IBindCtx *pBndCtx, BOOL fBindToObject, CTransData **ppCTD) { DEBUG_ENTER((DBG_TRANSDAT, Hresult, "CTransData::Create", "%.80wq, %#x, %#x, %#x, %B, %#x", pwUrl, grfBindF, &riid, pBndCtx, fBindToObject, ppCTD )); HRESULT hr = NOERROR; PerfDbgLog1(tagCTransData, NULL, "+CTransData::Create(fBindToObject:%d)", fBindToObject); CTransData *pCTData;
LPBYTE lpBuffer; ULONG cbBufferSize; cbBufferSize = DNLD_BUFFER_SIZE;
TransAssert((DATASNIFSIZEDOCFILE_MIN <= cbBufferSize)); lpBuffer = (LPBYTE) new BYTE[cbBufferSize]; pCTData = new CTransData(NULL,lpBuffer,cbBufferSize, fBindToObject);
if (lpBuffer && pCTData) { *ppCTD = pCTData; pCTData->Initialize(pwUrl, grfBindF, riid, pBndCtx);
// Try to get an IEnumFORMATETC pointer from the bind context
//hr = GetObjectParam(pbc, REG_ENUMFORMATETC, IID_IEnumFORMATETC, (IUnknown**)&_pEnumFE);
} else { if (pCTData) { delete pCTData; } else if (lpBuffer) { delete lpBuffer; }
hr = E_OUTOFMEMORY; *ppCTD = 0; }
PerfDbgLog2(tagCTransData, NULL, "-CTransData::Create (out:%lx,hr:%lx)", *ppCTD, hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::Initialize
//
// Synopsis:
//
// Arguments: [riid] --
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CTransData::Initialize(LPCWSTR pwzUrl, DWORD grfBindF, REFIID riid, IBindCtx *pBndCtx, BOOL fBindToObject) { DEBUG_ENTER((DBG_TRANSDAT, Hresult, "CTransData::Initialize", "this=%#x, %.80wq, %#x, %#x, %#x, %B", this, pwzUrl, grfBindF, &riid, pBndCtx, fBindToObject )); PerfDbgLog(tagCTransData, this, "+CTransData::Initialize"); HRESULT hr = NOERROR;
if (_fInitialized == FALSE) { _ds = DataSink_Unknown; _formatetc.tymed = TYMED_NULL; _grfBindF = grfBindF; _pBndCtx = pBndCtx; _pBndCtx->AddRef(); _pwzUrl = OLESTRDuplicate((LPWSTR)pwzUrl); if (!_pwzUrl) { hr = E_OUTOFMEMORY; }
if (SUCCEEDED(hr)) { if (_fBindToObject) { _formatetc.tymed = TYMED_ISTREAM; _ds = DataSink_Unknown; } else if (riid == IID_IUnknown) { // this is the BindToStorage
_formatetc.tymed = TYMED_FILE; _ds = DataSink_File; } else if (riid == IID_IStream) { // We do not know yet which kind of stream
// SetDataSink will determine this.
_formatetc.tymed = TYMED_ISTREAM; _ds = DataSink_StreamOnFile; } else if (riid == IID_IStorage) { BIND_OPTS bindopts; bindopts.cbStruct = sizeof(BIND_OPTS); hr = pBndCtx->GetBindOptions(&bindopts); _grfMode = bindopts.grfMode;
_formatetc.tymed = TYMED_ISTORAGE; _ds = DataSink_Storage;
} else { // this call should fail
hr = E_INVALIDARG; TransAssert((FALSE && "Unknown data sink for this request!")); } } if (SUCCEEDED(hr)) { HRESULT hr1; ITransactionData *pCTransData = NULL; LPWSTR pwzFilename = NULL; LPWSTR pwzMime = NULL;
hr1 = GetObjectParam(pBndCtx, SZ_TRANSACTIONDATA, IID_ITransactionData, (IUnknown **)&pCTransData); DbgLog2(tagCTransData, this, "=== CTransData::Initialize GetObjectParam: pbndctx:%lx, hr:%lx)", pBndCtx, hr1);
if (SUCCEEDED(hr1)) { TransAssert((pCTransData)); hr1 = pCTransData->GetTransactionData(_pwzUrl,&pwzFilename, &pwzMime, &_cbDataSize, &_cbTotalBytesRead, 0); DbgLog5(tagCTransData, this, "=== CTransData::Initialize GetTransactionData (hr:%lx, Filename:%ws, Mime:%ws, _cbDataSize:%ld, _cbTotalBytesRead:%ld)", hr1, pwzFilename, pwzMime, _cbDataSize, _cbTotalBytesRead); pCTransData->Release(); }
if (SUCCEEDED(hr1) ) { // set the url filename
SetFileName(pwzFilename); if (pwzMime) { SetMimeType(pwzMime); _fMimeTypeVerified = TRUE; } _fRemoteReady = TRUE;
if (pwzMime) { delete pwzMime; } if (pwzFilename) { delete pwzFilename; } } } _fInitialized = TRUE; } else { _dwAttached++; if (_pBndCtx) { _pBndCtx->Release(); }
_pBndCtx = pBndCtx;
if (_pBndCtx) { _pBndCtx->AddRef(); }
// no set up the righte datasink
if (fBindToObject) { _fBindToObject = TRUE; SwitchDataSink(DataSink_StreamBindToObject); } else if (riid == IID_IUnknown) { SwitchDataSink(DataSink_File); } else if ( (riid == IID_IStream) && (grfBindF & BINDF_NEEDFILE)) { SwitchDataSink(DataSink_StreamOnFile); }
}
PerfDbgLog3(tagCTransData, this, "-CTransData::Initialize (_formatetc.tymed:%ld, _ds:%lx, hr:%lx)", _formatetc.tymed,_ds, hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::PrepareThreadTransfer
//
// Synopsis:
//
// Arguments:
//
// Returns:
//
// History: 10-09-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CTransData::PrepareThreadTransfer() { DEBUG_ENTER((DBG_TRANSDAT, Hresult, "CTransData::PrepareThreadTransfer", "this=%#x", this )); PerfDbgLog(tagCTransData, this, "+CTransData::PrepareThreadTransfer"); HRESULT hr = NOERROR;
if (_pBndCtx) { _pBndCtx->Release(); _pBndCtx = NULL; }
PerfDbgLog1(tagCTransData, this, "-CTransData::PrepareThreadTransfer (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::GetDataSink
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 2-22-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
DataSink CTransData::GetDataSink() { DEBUG_ENTER((DBG_TRANSDAT, Pointer, "CTransData::GetDataSink", "this=%#x", this )); PerfDbgLog(tagCTransData, this, "+CTransData::GetDataSink"); DataSink dsRet = DataSink_Unknown;
if (_ds == DataSink_Unknown) { DWORD dwBindF = GetBindFlags();
if ( (dwBindF & BINDF_ASYNCSTORAGE) && (dwBindF & BINDF_PULLDATA) && (_formatetc.tymed == TYMED_ISTREAM)) { dsRet = _ds = DataSink_StreamNoCopyData; } } else { dsRet = _ds; }
PerfDbgLog1(tagCTransData, this, "-CTransData::GetDataSink (dsRet:%lx)", dsRet);
DEBUG_LEAVE(dsRet); return dsRet; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::SetDataSink
//
// Synopsis:
//
// Arguments: [dwBindF] --
//
// Returns:
//
// History: 2-25-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
DataSink CTransData::SetDataSink(DWORD dwBindF) { DEBUG_ENTER((DBG_TRANSDAT, Pointer, "CTransData::SetDataSink", "this=%#x, %#x", this, dwBindF )); PerfDbgLog1(tagCTransData, this, "+CTransData::SetDataSink (_ds:%lx)", _ds);
TransAssert((_formatetc.tymed != TYMED_NULL)); _grfBindF = dwBindF;
switch (_ds) { case DataSink_Unknown: { if (_fBindToObject) { TransAssert((_formatetc.tymed == TYMED_ISTREAM)); _ds = DataSink_StreamBindToObject; } } break; case DataSink_File: { TransAssert((_formatetc.tymed == TYMED_FILE));
} break; case DataSink_StreamOnFile: { TransAssert((_formatetc.tymed == TYMED_ISTREAM)); if ((dwBindF & BINDF_ASYNCSTORAGE) && (dwBindF & BINDF_PULLDATA)) { _ds = DataSink_StreamNoCopyData; } } break;
case DataSink_StreamBindToObject: { TransAssert((_formatetc.tymed == TYMED_ISTREAM)); TransAssert((_fBindToObject == TRUE));
if (IsObjectReady() == NOERROR) { //
// change it to file - stream on file will be opened
//
_ds = DataSink_StreamOnFile; } else if ((dwBindF & BINDF_ASYNCSTORAGE) && (dwBindF & BINDF_PULLDATA)) { _ds = DataSink_StreamNoCopyData; }
} break;
case DataSink_Storage: { TransAssert((_formatetc.tymed == TYMED_ISTORAGE)); } break;
case DataSink_GenericStream: { TransAssert((_formatetc.tymed == TYMED_ISTREAM)); } break;
default: TransAssert((FALSE && "CTransData::SetDataSink -- Invalid data location")); break; }
PerfDbgLog1(tagCTransData, this, "-CTransData::SetDataSink (_ds:%lx)", _ds);
DEBUG_LEAVE(_ds); return _ds; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::SwitchDataSink
//
// Synopsis:
//
// Arguments: [dwBindF] --
//
// Returns:
//
// History: 2-25-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
DataSink CTransData::SwitchDataSink(DataSink dsNew) { DEBUG_ENTER((DBG_TRANSDAT, Pointer, "CTransData::SwitchDataSink", "this=%#x, %#x", this, dsNew )); PerfDbgLog2(tagCTransData, this, "+CTransData::SwitchDataSink (_ds:%lx, dsNew:%lx)", _ds, dsNew);
TransAssert((_ds != DataSink_Unknown)); TransAssert((_formatetc.tymed != TYMED_NULL)); HRESULT hr = NOERROR;
switch (_ds) { case DataSink_File: { TransAssert((_formatetc.tymed == TYMED_FILE)); } break; case DataSink_StreamOnFile: { TransAssert((_wzFileName[0] != 0)); _formatetc.tymed = TYMED_ISTREAM; } break;
case DataSink_GenericStream: { TransAssert((_formatetc.tymed == TYMED_ISTREAM)); } break;
case DataSink_StreamNoCopyData: TransAssert((_formatetc.tymed == TYMED_ISTREAM)); if ( dsNew == DataSink_StreamOnFile || dsNew == DataSink_GenericStream || dsNew == DataSink_StreamBindToObject) { _ds = dsNew; DWORD dwNew = 0; hr = OnDataReceived(_grfBSC, 0, 0, &dwNew); if( hr == S_FALSE) { _fEOFOnSwitchSink = TRUE; } }
break;
case DataSink_StreamBindToObject: { TransAssert((_formatetc.tymed == TYMED_ISTREAM)); TransAssert((_fBindToObject == TRUE)); _ds = dsNew; if (_ds == DataSink_File) { _formatetc.tymed = TYMED_FILE; DWORD dwNew = 0; hr = OnDataReceived(_grfBSC, 0, 0, &dwNew); if( hr == S_FALSE) { _fEOFOnSwitchSink = TRUE; } }
} break;
case DataSink_Storage: { TransAssert((_formatetc.tymed == TYMED_ISTORAGE)); } break;
default: TransAssert((FALSE && "CTransData::SwitchDataSink -- Invalid data location")); break; }
PerfDbgLog2(tagCTransData, this, "-CTransData::SwitchDataSink (_ds:%lx, dsNew:%lx)", _ds, dsNew);
DEBUG_LEAVE(_ds); return _ds; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::IsFileRequired()
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 2-22-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
BOOL CTransData::IsFileRequired() { DEBUG_ENTER((DBG_TRANSDAT, Bool, "CTransData::IsFileRequired", "this=%#x", this )); PerfDbgLog(tagCTransData, this, "+CTransData::IsFileRequired()"); BOOL fRet = FALSE; TransAssert((_ds != DataSink_Unknown));
switch (_ds) { case DataSink_File: case DataSink_StreamOnFile: fRet = TRUE; }
PerfDbgLog1(tagCTransData, this, "-CTransData::IsFileRequired() (fRet:%d)", fRet);
DEBUG_LEAVE(fRet); return fRet; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::GetData
//
// Synopsis:
//
// Arguments: [ppformatetc] --
// [ppStgMed] --
// [grfBSCF] --
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CTransData::GetData(FORMATETC **ppformatetc, STGMEDIUM **ppStgMed, DWORD grfBSCF) { DEBUG_ENTER((DBG_TRANSDAT, Hresult, "CTransData::GetData", "this=%#x, %#x, %#x, %#x", this, ppformatetc, ppStgMed, grfBSCF )); PerfDbgLog1(tagCTransData, this, "+CTransData::GetData (_ds:%ld)", _ds); HRESULT hr = INET_E_DATA_NOT_AVAILABLE; BOOL fNewStgMed = FALSE; DataSink ds;
*ppStgMed = 0; *ppformatetc = 0;
if (_pStgMed == NULL) { // first find the formatETC based on
// clipformat and the EnumFormatETC
FindFormatETC();
_pStgMed = new STGMEDIUM; if (_pStgMed == NULL) { hr = E_OUTOFMEMORY; goto End; }
*ppformatetc = &_formatetc;
_pStgMed->tymed = TYMED_NULL; _pStgMed->hGlobal = NULL; _pStgMed->pUnkForRelease = 0; _pStgMed->pstm = NULL; fNewStgMed = TRUE;
}
ds = _ds; if( _fFileAsStmOnFile && _ds == DataSink_File ) { ds = DataSink_StreamOnFile; } switch (ds) { case DataSink_File: { //TransAssert(( (grfBSCF & ~BSCF_LASTDATANOTIFICATION)
// || ((grfBSCF & BSCF_LASTDATANOTIFICATION) && (_formatetc.tymed == TYMED_FILE)) ));
if (_wzFileName[0] != 0) { TransAssert((_wzFileName[0] != 0)); if (_pStgMed->tymed == TYMED_FILE) { if (_pStgMed->lpszFileName == NULL) { _pStgMed->lpszFileName = (LPWSTR) new WCHAR [wcslen(_wzFileName)+2]; if (_pStgMed->lpszFileName) { wcscpy(_pStgMed->lpszFileName, _wzFileName); } else { hr = E_OUTOFMEMORY; goto End; } } } else { ASSERT(_pStgMed->tymed == TYMED_NULL); _pStgMed->tymed = TYMED_FILE; _pStgMed->lpszFileName = (LPWSTR) new WCHAR [wcslen(_wzFileName)+2]; if (_pStgMed->lpszFileName) { wcscpy(_pStgMed->lpszFileName, _wzFileName); } else { hr = E_OUTOFMEMORY; goto End; } }
if (_pStgMed->pUnkForRelease == NULL) { _pStgMed->pUnkForRelease = this; }
hr = NOERROR; DbgLog1(tagCTransData, this, "+CTransData::GetData -> TYMED_FILE: %ws", _wzFileName); } else { // filename is not available yet
hr = INET_E_DATA_NOT_AVAILABLE; } } break;
case DataSink_GenericStream: case DataSink_StreamBindToObject: case DataSink_StreamNoCopyData: { DbgLog1(tagCTransData, this, "=== CTransData::GetData (_ds:%lx)", _ds); TransAssert((_formatetc.tymed == TYMED_ISTREAM));
if (_pStgMed->tymed == TYMED_NULL) { CReadOnlyStreamDirect *pCRoStm = new CReadOnlyStreamDirect( this, _grfBindF);
if (pCRoStm) { _pStgMed->tymed = TYMED_ISTREAM; _pStgMed->pstm = pCRoStm; _pStgMed->pUnkForRelease = this; hr = NOERROR; } else { hr = E_OUTOFMEMORY; }
DbgLog1(tagCTransData, this, "+CTransData::GetData -> TYMED_ISTREAM: %lx", pCRoStm); } else { hr = NOERROR; }
DbgLog2(tagCTransData, this, "=== CTransData::GetData (_ds:%lx,pstm:%lx)", _ds,_pStgMed->pstm); DbgLog2(tagCTransData, this, "=== (_cbBufferFilled:%ld, _cbBufferSize:%ld)", _cbBufferFilled,_cbBufferSize);
} break;
case DataSink_StreamOnFile: { DbgLog1(tagCTransData, this, "=== CTransData::GetData (_ds:%lx)", _ds); TransAssert((_formatetc.tymed == TYMED_ISTREAM));
if (_wzFileName[0] != 0) { if (_pStgMed->tymed == TYMED_NULL) { if( _pStgMed->pstm ) { //BUG-BUG : relying on undocumented behavior of ReleaseStgMedium..
// may or may not zero this out in future.
_pStgMed->tymed = TYMED_ISTREAM; _pStgMed->pUnkForRelease = this;
// When pStm gets created, the ctor set the ref count
// to 1, so no need any additional AddRef.
//
// Here we are not create a new pStm, we need to do an
// AddRef on the pStm because
// CBinding::OnDataNotification (the only caller of this)
// will call ReleaseStgMedia() which will call
// _pStgMeg->pstm->Release()
_pStgMed->pstm->AddRef();
hr = NOERROR; } else { char szTempFile[MAX_PATH]; CReadOnlyStreamFile *pCRoStm = NULL; W2A(_wzFileName, szTempFile, MAX_PATH);
hr = CReadOnlyStreamFile::Create(szTempFile, &pCRoStm, _pwzUrl);
if (pCRoStm) { _pStgMed->tymed = TYMED_ISTREAM; _pStgMed->pstm = pCRoStm; _pStgMed->pUnkForRelease = this; hr = NOERROR; } else { // filename is not available yet
hr = INET_E_DATA_NOT_AVAILABLE; }
DbgLog2(tagCTransData, this, "+CTransData::GetData -> TYMED_ISTREAM: %lx (hr:%lx)", pCRoStm,hr); }
} else { TransAssert((_pStgMed->tymed == TYMED_ISTREAM)); hr = NOERROR; } } else { DbgLog(tagCTransDataErr, this, "+CTransData::GetData ->StreamOnFile: no filename!");
// filename is not available yet
hr = INET_E_DATA_NOT_AVAILABLE; }
} break;
case DataSink_Storage: { DbgLog2(tagCTransData, this, "=== CTransData::GetData (_ds:%lx, _wzFileName:%ws)", _ds, _wzFileName); TransAssert((_formatetc.tymed == TYMED_ISTORAGE));
TransAssert((_wzFileName != NULL));
if (_wzFileName[0] != 0) { if (_pStgMed->tymed == TYMED_NULL) { IStorage *pStg = NULL;
hr = StgOpenStorage(_wzFileName, NULL, STGM_READ | STGM_SHARE_DENY_WRITE, NULL, 0, &pStg ); DbgLog1(tagCTransData, this, "+CTransData::GetData -> TYMED_ISTORAGE: %ws", _wzFileName);
if (pStg) { _pStgMed->tymed = TYMED_ISTORAGE; _pStgMed->pstg = pStg; _pStgMed->pUnkForRelease = this; hr = NOERROR; }
DbgLog2(tagCTransData, this, "+CTransData::GetData -> TYMED_ISTORAGE: %lx (hr:%lx)", pStg,hr); } else { TransAssert((_pStgMed->tymed == TYMED_ISTORAGE)); hr = NOERROR; } } // else return default error
} break;
default: // this needs to be implemented
TransAssert((FALSE && "CTransData::GetData -- Invalid data location")); break; }
if (SUCCEEDED(hr) && _pStgMed) { // this object was addref on punkforrelease
*ppStgMed = _pStgMed; *ppformatetc = &_formatetc;
// Use ourselves as the unknown for release, so that the temp file
// doesn't get removed when ReleaseStgMedium() is called. We need
// to AddRef ourselves to balance the Release that will occur.
if (_pStgMed->pUnkForRelease) { AddRef(); if ( _pProt && fNewStgMed && SUCCEEDED(_pProt->LockRequest(0)) ) { _fLocked = TRUE; } }
hr = NOERROR;
TransAssert((_pStgMed->pUnkForRelease != NULL)); }
End: PerfDbgLog1(tagCTransData, this, "-CTransData::GetData (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::ReadHere
//
// Synopsis:
//
// Arguments: [pBuffer] --
// [cbBuffer] --
// [pdwRead] --
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CTransData::ReadHere(LPBYTE pBuffer, DWORD cbBuffer, DWORD *pdwRead) { DEBUG_ENTER((DBG_TRANSDAT, Hresult, "CTransData::ReadHere", "this=%#x, %#x, %#x, %#x", this, pBuffer, cbBuffer, pdwRead )); PerfDbgLog2(tagCTransData, this, "+CTransData::ReadHere (_ds:%lx,cbBuffer:%ld)", _ds,cbBuffer); HRESULT hr = NOERROR;
switch (_ds) { case DataSink_StreamNoCopyData: case DataSink_StreamBindToObject: { TransAssert((_formatetc.tymed == TYMED_ISTREAM)); BOOL fRead = TRUE; DWORD dwCopy = 0; DWORD dwCopyNew = 0;
if (_cbBufferFilled) { fRead = FALSE;
// copy data form the local buffer to the provide buffer
if (cbBuffer < _cbBufferFilled) { dwCopy = cbBuffer; memcpy(pBuffer, _lpBuffer, cbBuffer); // move the memory to the front
memcpy(_lpBuffer, _lpBuffer + cbBuffer, _cbBufferFilled - cbBuffer); _cbBufferFilled -= cbBuffer; hr = S_OK; } else if (cbBuffer == _cbBufferFilled) { dwCopy = _cbBufferFilled; memcpy(pBuffer, _lpBuffer, _cbBufferFilled); _cbBufferFilled = 0; hr = S_OK; } else { //
// user buffer is greater than what is available in
//
dwCopy = _cbBufferFilled; memcpy(pBuffer, _lpBuffer, _cbBufferFilled); _cbBufferFilled = 0; fRead = TRUE; hr = E_PENDING; } }
// now read from the wire
if ((_cbBufferFilled == 0) && (fRead == TRUE)) { // read data from our buffer
if (_TransDataState == TransData_ProtoTerminated) { // download completed
hr = (dwCopy) ? S_OK : S_FALSE; } else if (pBuffer && cbBuffer) { hr = _pProt->Read(pBuffer + dwCopy, cbBuffer - dwCopy, &dwCopyNew); _cbTotalBytesRead += dwCopyNew; } else { hr = E_INVALIDARG; } }
if (pdwRead) { *pdwRead = dwCopy + dwCopyNew;
if (*pdwRead && (hr != E_PENDING)) // some data in buffer
{ hr = S_OK; } } } break;
case DataSink_StreamOnFile: { DbgLog(tagCTransData, this, "=== CTransData::ReadHere (_ds:DataSink_StreamNoCopyData)"); TransAssert((_formatetc.tymed == TYMED_ISTREAM)); TransAssert((pdwRead != NULL));
// read data from our buffer
if (_TransDataState == TransData_ProtoTerminated) { // download completed
hr = S_FALSE; } else if (pBuffer && cbBuffer) { hr = _pProt->Read(pBuffer, cbBuffer, pdwRead); } else { hr = E_INVALIDARG; } } break;
case DataSink_File: { TransAssert((_formatetc.tymed == TYMED_FILE));
} break;
default: // this needs to be implemented
hr = E_FAIL; TransAssert((FALSE && "CTransData::ReadHere -- Invalid data location")); break; }
TransAssert(( ( (hr == S_FALSE && *pdwRead == 0) || (hr == S_OK && *pdwRead != 0) || (hr == E_PENDING) || (hr == E_INVALIDARG) || (hr == INET_E_DATA_NOT_AVAILABLE) || (hr == INET_E_DOWNLOAD_FAILURE) ) && "CTransData::ReadHere -- Invalid return code"));
PerfDbgLog3(tagCTransData, this, "-CTransData::ReadHere (hr:%lx,cbBuffer:%ld,pdwRead:%ld)", hr,cbBuffer,*pdwRead);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::Seek
//
// Synopsis:
//
// Arguments: [DWORD] --
// [ULARGE_INTEGER] --
// [plibNewPosition] --
//
// Returns:
//
// History: 10-30-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CTransData::Seek(LARGE_INTEGER dlibMove,DWORD dwOrigin,ULARGE_INTEGER *plibNewPosition) { DEBUG_ENTER((DBG_TRANSDAT, Hresult, "CTransData::Seek", "this=%#x, %#x, %#x, %#x", this, dlibMove, dwOrigin, plibNewPosition )); PerfDbgLog(tagCTransData, this, "+CTransData::Seek"); HRESULT hr;
hr = _pProt->Seek(dlibMove, dwOrigin,plibNewPosition);
PerfDbgLog1(tagCTransData, this, "-CTransData::Seek (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::GetReadBuffer
//
// Synopsis:
//
// Arguments: [ppBuffer] --
// [pcbBytes] --
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CTransData::GetReadBuffer(BYTE **ppBuffer, DWORD *pcbBytes) { DEBUG_ENTER((DBG_TRANSDAT, Hresult, "CTransData::GetReadBuffer", "this=%#x, %#x, %#x", this, ppBuffer, pcbBytes )); PerfDbgLog(tagCTransData, this, "+CTransData::GetReadBuffer"); HRESULT hr;
TransAssert((_cbBufferSize >= _cbBufferFilled));
*ppBuffer = _lpBuffer + _cbBufferFilled; *pcbBytes = _cbBufferSize - _cbBufferFilled;
hr = ((_cbBufferSize - _cbBufferFilled) > 0) ? NOERROR : E_FAIL;
PerfDbgLog3(tagCTransData, this, "-CTransData::GetReadBuffer (pBuffer:%lx,size:%ld,hr:%lx)", *ppBuffer, *pcbBytes, hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::OnDataInBuffer
//
// Synopsis:
//
// Arguments: [pBuffer] --
// [cbBytesAvailable] --
// [dwBytesTotal] --
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CTransData::OnDataInBuffer(BYTE *pBuffer, DWORD cbBytesRead, DWORD dwBytesTotal) { DEBUG_ENTER((DBG_TRANSDAT, Hresult, "CTransData::OnDataInBuffer", "this=%#x, %#x, %#x, %#x", this, pBuffer, cbBytesRead, dwBytesTotal )); PerfDbgLog(tagCTransData, this, "+CTransData::OnDataInBuffer"); HRESULT hr = NOERROR;
_cbTotalBytesRead += cbBytesRead; _cbBufferFilled += cbBytesRead;
PerfDbgLog1(tagCTransData, this, "-CTransData::OnDataInBuffer (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::OnDataReceived
//
// Synopsis:
//
// Arguments: [cbBytesAvailable] --
// [dwBytesTotalRead] --
// [dwTotalSize] --
//
// Returns:
//
// History: 2-23-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CTransData::OnDataReceived(DWORD grfBSC, DWORD cbBytesAvailable, DWORD dwTotalSize, DWORD *pcbNewAvailable) { DEBUG_ENTER((DBG_TRANSDAT, Hresult, "CTransData::OnDataReceived", "this=%#x, %#x, %#x, %#x, %#x", this, grfBSC, cbBytesAvailable, dwTotalSize, pcbNewAvailable )); PerfDbgLog4(tagCTransData, this, "+CTransData::OnDataReceived (_ds:%s, grfBSC:%lx, cbBytesAvailable:%ld, _cbTotalBytesRead:%ld)", GetDataSinkName(_ds), grfBSC, cbBytesAvailable, _cbTotalBytesRead); HRESULT hr = NOERROR;
*pcbNewAvailable = cbBytesAvailable; _grfBSC |= grfBSC;
switch (_ds) { case DataSink_StreamNoCopyData: TransAssert((_formatetc.tymed == TYMED_ISTREAM));
case DataSink_StreamBindToObject: { 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
hr = _pProt->Read(_lpBuffer + _cbBufferFilled, _cbBufferSize - _cbBufferFilled, &dwNewData); _cbTotalBytesRead += dwNewData; _cbBufferFilled += dwNewData;
// now check if this is docfile
// if so download at least 2k
if (!_fDocFile && _cbBufferFilled && (IsDocFile(_lpBuffer, _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; } } }
break;
case DataSink_File: case DataSink_Storage: case DataSink_StreamOnFile: { DWORD dwNewData = 0;
TransAssert((_pProt));
if (_cbTotalBytesRead < _cbDataSniffMin) { _cbDataSniffMin = (dwTotalSize && dwTotalSize < DATASNIFSIZEDOCFILE_MIN) ? dwTotalSize : DATASNIFSIZEDOCFILE_MIN;
// read data into buffer and report progess
hr = _pProt->Read(_lpBuffer + _cbBufferFilled, _cbBufferSize - _cbBufferFilled, &dwNewData);
_cbTotalBytesRead += dwNewData; _cbBufferFilled += dwNewData;
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)); } *pcbNewAvailable = _cbTotalBytesRead; }
// Note: read until pending or eof and report progress
// this is important to keep the download going
if (hr == NOERROR) { // reset the buffer - don't overwrite sniffing data
_cbBufferFilled = (_fMimeTypeVerified) ? 0 : _cbDataSniffMin; // bugbug: need special flag which indicates not to read if fully available
//if (!(grfBSC & BSCF_DATAFULLYAVAILABLE))
if (1) { //read as much data until S_OK or E_PENDING or error
do { hr = _pProt->Read(_lpBuffer + _cbBufferFilled, _cbBufferSize - _cbBufferFilled, &dwNewData); _cbTotalBytesRead += dwNewData;
} while (hr == NOERROR);
// report available data
if (hr == NOERROR || hr == E_PENDING) { TransAssert((_cbTotalBytesRead != 0)); } *pcbNewAvailable = (cbBytesAvailable > _cbTotalBytesRead) ? _cbTotalBytesRead : _cbTotalBytesRead; } else { TransAssert((dwTotalSize == cbBytesAvailable)); *pcbNewAvailable = dwTotalSize; }
} } break;
default: TransAssert((FALSE && "CTransData::OnDataReceived -- Invalid data location")); break; }
// cbBytesAvailable might be off be 1
//TransAssert((cbBytesAvailable <= *pcbNewAvailable));
PerfDbgLog1(tagCTransData, this, "-CTransData::OnDataReceived (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::OnStart
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 2-23-96 JohannP (Johann Posch) Created
//
// Notes: TransData does not keep CINet alive
// and will NOT call delete on it!
//
//----------------------------------------------------------------------------
STDMETHODIMP CTransData::OnStart(IOInetProtocol *pCINet) { DEBUG_ENTER((DBG_TRANSDAT, Hresult, "CTransData::OnStart", "this=%#x, %#x", this, pCINet )); HRESULT hr = NOERROR; PerfDbgLog(tagCTransData, this, "+CTransData::OnStart"); TransAssert((pCINet != NULL));
if (_pProt) { _pProt->Release(); _pProt = NULL; }
switch (_ds) { case DataSink_StreamBindToObject: case DataSink_StreamNoCopyData: case DataSink_StreamOnFile: case DataSink_GenericStream: { TransAssert((_formatetc.tymed == TYMED_ISTREAM)); // this point is not addref by CTransData
TransAssert((_pProt == NULL)); _pProt = pCINet; } break;
case DataSink_Storage: { TransAssert((_formatetc.tymed == TYMED_ISTORAGE)); // this point is not addref by CTransData
TransAssert((_pProt == NULL)); _pProt = pCINet; } break;
case DataSink_File: { TransAssert((_formatetc.tymed == TYMED_FILE)); // this point is not addref by CTransData
TransAssert((_pProt == NULL)); _pProt = pCINet; } break;
default: TransAssert((FALSE && "Invalid data location")); break; }
if (_pProt) { _pProt->AddRef(); } else { TransAssert((FALSE)); }
PerfDbgLog1(tagCTransData, this, "-CTransData::OnStart (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::OnTerminate
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CTransData::OnTerminate() { DEBUG_ENTER((DBG_TRANSDAT, Hresult, "CTransData::OnTerminate", "this=%#x", this )); HRESULT hr = NOERROR; PerfDbgLog(tagCTransData, this, "+CTransData::OnTerminate");
TransAssert((_TransDataState < TransData_ProtoTerminated));
switch (_ds) {
case DataSink_Storage: case DataSink_File: { TransAssert((_formatetc.tymed == TYMED_FILE) || (_formatetc.tymed == TYMED_ISTORAGE)); DbgLog2(tagCTransData, this, ">>> CTransData::OnTerminate (hr:%lx, _wzTempFile:%ws)", hr, _wzFileName); } break;
case DataSink_StreamBindToObject: case DataSink_StreamNoCopyData: case DataSink_StreamOnFile: case DataSink_GenericStream: { TransAssert((_formatetc.tymed == TYMED_ISTREAM)); TransAssert((_pProt != NULL)); } break; default: TransAssert((FALSE && "Invalid data location")); break; }
if (_pBndCtx) { _pBndCtx->Release(); _pBndCtx = NULL; }
PerfDbgLog1(tagCTransData, this, "-CTransData::OnTerminate (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::FindFormatETC
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CTransData::FindFormatETC() { DEBUG_ENTER((DBG_TRANSDAT, Hresult, "CTransData::FindFormatETC", "this=%#x", this )); HRESULT hr = NOERROR; PerfDbgLog1(tagCTransData, this, "+CTransData::FindFormatETC (_cbBufferFilled:%ld)", _cbBufferFilled);
_formatetc.ptd = NULL; _formatetc.dwAspect = DVASPECT_CONTENT; _formatetc.lindex = -1;
_formatetc.cfFormat = 0; TransAssert(( _formatetc.tymed == TYMED_ISTREAM || _formatetc.tymed == TYMED_FILE || _formatetc.tymed == TYMED_ISTORAGE ));
LPCWSTR pwzStrOrg = GetMimeType(); LPCWSTR pwzStr = pwzStrOrg;
// If not already done so, attempt to
// verify mime type by examining data.
if (!_fMimeTypeVerified) { DWORD dwFlags = 0; DWORD dwSniffFlags = 0; DWORD cbLen = sizeof(dwFlags); LPWSTR pwzFileName = GetFileName(); LPWSTR pwzStrOut = 0;
// the buffer should contain data if the no mime
TransAssert(( (_cbBufferFilled == 0 && (pwzStr || pwzFileName)) || ( _cbBufferFilled != 0) ));
FindMimeFromData(NULL, pwzFileName,_lpBuffer, _cbBufferFilled, pwzStrOrg, dwSniffFlags, &pwzStrOut, 0);
if (pwzStrOut) { SetMimeType(pwzStrOut); pwzStr = GetMimeType(); } delete [] pwzStrOut; _fMimeTypeVerified = TRUE; }
// the new mime should never be NULL if we had a proposed mime
TransAssert(( (pwzStrOrg && pwzStr) || (pwzStrOrg == NULL) ));
if (pwzStr) { char szMime[SZMIMESIZE_MAX]; W2A(pwzStr, szMime, SZMIMESIZE_MAX);
CLIPFORMAT cfType; if (FindMediaTypeW(pwzStr,&cfType) != NOERROR) { _formatetc.cfFormat = (CLIPFORMAT) RegisterClipboardFormat(szMime); } else { _formatetc.cfFormat = cfType; } } else { _formatetc.cfFormat = CF_NULL; }
// Check if the format that we got is one of the format that
// is requested, and if so, use it
#ifdef UNUSED
if (_pEnumFE) { FORMATETC FmtetcT; BOOL fDone = FALSE;
_pEnumFE->Reset();
while (!fDone && ((hr = _pEnumFE->Next(1, &FmtetcT,NULL)) == NOERROR)) { TransAssert((SUCCEEDED(hr)));
if (FmtetcT.cfFormat == _cfFormat) { _formatetc.cfFormat = _cfFormat; } } } #endif //UNUSED
PerfDbgLog3(tagCTransData, this, "-CTransData::FindFormatETC (hr:%lx, szStr:%ws, _formatetc.cfFormat:%lx)", hr, pwzStr?pwzStr:L"", _formatetc.cfFormat);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::GetAcceptStr
//
// Synopsis:
//
// Arguments: [ppwzStr] --
// [pcElements] --
//
// Returns:
//
// History: 3-29-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CTransData::GetAcceptStr(LPWSTR *ppwzStr, ULONG *pcElements) { DEBUG_ENTER((DBG_TRANSDAT, Hresult, "CTransData::GetAcceptStr", "this=%#x, %#x, %#x", this, ppwzStr, pcElements )); HRESULT hr = NOERROR; PerfDbgLog(tagCTransData, this, "+CTransData::GetAcceptStr"); IEnumFORMATETC *pIEnumFE = NULL;
TransAssert((ppwzStr)); TransAssert((*pcElements > 0));
CHAR pszUnknownName[MAX_PATH]; ULONG cMimes = 0; *ppwzStr = 0; hr = GetObjectParam(_pBndCtx, REG_ENUMFORMATETC, IID_IEnumFORMATETC, (IUnknown**)&pIEnumFE);
if (hr == NOERROR) { BOOL fCF_NULL = FALSE; #define ELEMENTS 10
ULONG cElementsIn = ELEMENTS; ULONG cElements = 0; FORMATETC rgFormatEtc[ELEMENTS];
pIEnumFE->Reset(); // find # of elements
do { ULONG cEl = 0; hr = pIEnumFE->Next(cElementsIn, rgFormatEtc ,&cEl); cElements += cEl; } while (hr == S_OK);
UrlMkAssert((cElements > 0));
if ( (cElements > 0) && (hr == S_OK || hr == S_FALSE)) {
{ ULONG cElementsOut = 0; pIEnumFE->Reset(); do { ULONG cEl = 0; FORMATETC *pFmtEtc = rgFormatEtc;
hr = pIEnumFE->Next(cElementsIn, rgFormatEtc ,&cEl); cElementsOut += cEl; // (hr==S_FALSE) => (cElementsOut==cEl)
UrlMkAssert((!(hr==S_FALSE) || (cElementsOut == cElements)));
// On the last call to ->Next() enumerator, we get back an S_FALSE
// if the # of elements received (cEl) < asked for (cElementsIn)
if ((cElementsOut == cElements) && (hr == S_FALSE)) hr = S_OK;
for (ULONG i = 0; i < cEl; i++) { if( cMimes >= (*pcElements - 1) ) { // exceeding the income array size, stop
break; }
LPSTR szFormat = NULL; CLIPFORMAT cfFormat = (pFmtEtc + i)->cfFormat; if (cfFormat == CF_NULL) { fCF_NULL = TRUE; } else { hr = FindMediaString(cfFormat, &szFormat); if (hr != NOERROR || !szFormat) { // unknown cfFormat
if( GetClipboardFormatName(cfFormat, pszUnknownName, MAX_PATH)) { hr = NOERROR; szFormat = pszUnknownName; } else { // word97 will send out cfFormat=1
// which associated to "" string
hr = NOERROR; } } if( szFormat ) {
*(ppwzStr + cMimes)= NULL; *(ppwzStr + cMimes) = DupA2W(szFormat); if( *(ppwzStr + cMimes) ) { cMimes++; } else { hr = E_OUTOFMEMORY; break; } } } }
} while ( (cElementsOut < cElements) && (hr == NOERROR) );
// append the cf_null (*/*)
if( hr == NOERROR && (fCF_NULL || (cMimes == 0)) ) { *(ppwzStr + cMimes) = DupA2W(g_szCF_NULL); if( !*(ppwzStr + cMimes) ) { hr = E_OUTOFMEMORY; } else { cMimes++; hr = NOERROR; } }
if( hr == NOERROR ) { *(ppwzStr + cMimes) = NULL; } } }
pIEnumFE->Release(); } else { { *ppwzStr = DupA2W(g_szCF_NULL); if( *ppwzStr ) { cMimes = 1; *(ppwzStr + 1) = NULL; hr = NOERROR; } else { hr = E_OUTOFMEMORY; } } }
if( hr == NOERROR ) { *pcElements = cMimes; } else { *pcElements = 0; if( cMimes >= 1 ) { for( ULONG i = 0; i < cMimes; i ++) { delete [] *(ppwzStr + i); } } *ppwzStr = NULL; }
PerfDbgLog1(tagCTransData, this, "-CTransData::GetAcceptStr (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::GetAcceptMimes
//
// Synopsis:
//
// Arguments: [ppStr] --
//
// Returns:
//
// History: 3-29-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CTransData::GetAcceptMimes(LPWSTR *ppwzStr, ULONG cel, ULONG *pcElements) { DEBUG_ENTER((DBG_TRANSDAT, Hresult, "CTransData::GetAcceptMimes", "this=%#x, %#x, %#x, %#x", this, ppwzStr, cel, pcElements )); HRESULT hr = NOERROR; PerfDbgLog(tagCTransData, this, "+CTransData::GetAcceptMimes");
TransAssert((ppwzStr && pcElements && *pcElements));
if (ppwzStr && pcElements) { if( *pcElements > 1 ) { hr = GetAcceptStr( ppwzStr, pcElements ); } else if( *pcElements == 1) { // zero terminated
*ppwzStr = NULL; } else { hr = E_INVALIDARG; } } else { hr = E_INVALIDARG; } PerfDbgLog1(tagCTransData, this, "-CTransData::GetAcceptMimes (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::SetClipFormat
//
// Synopsis:
//
// Arguments: [cfFormat] --
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CTransData::SetClipFormat(CLIPFORMAT cfFormat) { DEBUG_ENTER((DBG_TRANSDAT, Hresult, "CTransData::SetClipFormat", "this=%#x, %#x", this, cfFormat )); HRESULT hr = NOERROR; PerfDbgLog(tagCTransData, this, "+CTransData::SetClipFormat");
_cfFormat = cfFormat;
PerfDbgLog1(tagCTransData, this, "-CTransData::SetClipFormat (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::IsObjectReady
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CTransData::IsObjectReady( ) { DEBUG_ENTER((DBG_TRANSDAT, Hresult, "CTransData::IsObjectReady", "this=%#x", this )); HRESULT hr = E_FAIL; PerfDbgLog(tagCTransData, this, "+CTransData::IsObjectReady");
// check size and
if ((_cbDataSize != 0) && (_cbDataSize == _cbTotalBytesRead)) { hr = NOERROR; }
PerfDbgLog3(tagCTransData, this, "-CTransData::IsObjectReady (hr:%lx, _cbDataSize:%ld, _cbTotalBytesRead:%ld)", hr, _cbDataSize, _cbTotalBytesRead);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::InProgress
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CTransData::InProgress() { DEBUG_ENTER((DBG_TRANSDAT, Hresult, "CTransData::InProgress", "this=%#x", this )); HRESULT hr = S_FALSE; PerfDbgLog(tagCTransData, this, "+CTransData::InProgress");
if (_grfBSC & (BSCF_LASTDATANOTIFICATION | BSCF_FIRSTDATANOTIFICATION)) { hr = S_FALSE; } else if (_cbTotalBytesRead == 0) { // check if some bits already in the buffer
hr = S_OK; }
PerfDbgLog1(tagCTransData, this, "-CTransData::InProgress (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::GetFileName
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
LPWSTR CTransData::GetFileName() { DEBUG_ENTER((DBG_TRANSDAT, Pointer, "CTransData::GetFileName", "this=%#x", this )); PerfDbgLog(tagCTransData, this, "+CTransData::GetFileName"); LPWSTR pwzFileName = NULL;
//TransAssert((_wzFileName[0] != 0));
if (_wzFileName[0] != 0) { pwzFileName = _wzFileName; }
PerfDbgLog1(tagCTransData, this, "-CTransData::GetFileName (szFile:%ws)", pwzFileName?pwzFileName:L"");
DEBUG_LEAVE(pwzFileName); return pwzFileName; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::GetClassID
//
// Synopsis:
//
// Arguments: [pclsid] --
// [fReOpen] --
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CTransData::GetClassID(CLSID clsidIn, CLSID *pclsid) { DEBUG_ENTER((DBG_TRANSDAT, Hresult, "CTransData::GetClassID", "this=%#x, %#x, %#x", this, clsidIn, pclsid )); PerfDbgLog(tagCTransData, this, "+CTransData::GetClassID"); WCHAR wzMime[SZMIMESIZE_MAX]; HRESULT hr; LPWSTR pwzTempFile = NULL;
DWORD fIgnoreMimeClsid = GetBindFlags() & BINDF_IGNOREMIMECLSID; LPCWSTR pwzMime = GetMimeType();
pwzTempFile = GetFileName();
if ( (_cbBufferFilled != 0) && (_cbTotalBytesRead <= _cbBufferSize) && (IsDocFile(_lpBuffer, _cbBufferFilled) == S_OK)) { _fDocFile = TRUE; _fMimeTypeVerified = TRUE;
// Storage file (docfile) case
// GetClassFileOrMime takes care of class mapping
hr = GetClassFileOrMime2(_pBndCtx, pwzTempFile, _lpBuffer, _cbBufferFilled, pwzMime, 0, pclsid, fIgnoreMimeClsid); if (hr != NOERROR) { // S_FALSE means keep downloading
hr = S_FALSE; } } else { if (!_fMimeTypeVerified) { DWORD dwFlags = 0; DWORD dwSniffFlags = 0; DWORD cbLen = sizeof(dwFlags);
LPWSTR pwzStr = 0; FindMimeFromData(NULL, pwzTempFile, _lpBuffer, _cbBufferFilled, pwzMime, dwSniffFlags, &pwzStr, 0); if (pwzStr) { SetMimeType(pwzStr); } _fMimeTypeVerified = TRUE; delete [] pwzStr; }
hr = GetClassFileOrMime2(_pBndCtx, pwzTempFile, NULL, 0, pwzMime, 0, pclsid, fIgnoreMimeClsid); }
#if DBG==1
if (hr == NOERROR) { LPOLESTR pszStr; StringFromCLSID(*pclsid, &pszStr); DbgLog2(tagCTransData, this, "CTransData::GetClassID (file:%ws)(class:%ws)", pwzTempFile, pszStr); delete pszStr; } #endif
PerfDbgLog1(tagCTransData, this, "-CTransData::GetClassID (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::SetMimeType
//
// Synopsis:
//
// Arguments: [pszMime] --
//
// Returns:
//
// History: 2-07-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CTransData::SetMimeType(LPCWSTR pwzMime) { DEBUG_ENTER((DBG_TRANSDAT, Hresult, "CTransData::SetMimeType", "this=%#x, %.80wq", this, pwzMime )); PerfDbgLog2(tagCTransData, this, "+CTransData::SetMimeType (OldMime:%ws; MimeStr:%ws)", _wzMime?_wzMime:L"", pwzMime?pwzMime:L""); HRESULT hr = NOERROR;
if (pwzMime) {
#if DBG_XXX
if (pwzMime) { if ( !wcscmp(_wzMime, CFWSTR_MIME_HTML) || !wcscmp(_wzMime, CFWSTR_MIME_TEXT)) { if ( !wcscmp(pwzMime, CFWSTR_MIME_RAWDATA) || !wcscmp(pwzMime,L"application/octet-stream")) { DbgLog2(tagCTransDataErr, "=== SetMimeType: OldMime:%ws, NewMime:%ws", _wzMime, pwzMime); //TransAssert((FALSE));
} } }
if (_wzMime[0] != 0 && strcmp(_wzMime,pwzMime)) { DbgLog2(tagTransDataErr, "=== SetMimeType: OldMime:%s, NewMime:%s", _wzMime, pwzMime); }
#endif //DBG
DWORD cLen = wcslen((LPWSTR)pwzMime);
if (cLen >= SZMIMESIZE_MAX) { cLen = SZMIMESIZE_MAX - 1; wcsncpy(_wzMime, (LPWSTR)pwzMime, cLen); _wzMime[cLen] = 0; } else { wcscpy(_wzMime, (LPWSTR)pwzMime); } } else { DbgLog(tagCTransDataErr, this, "CTransData::SetMimeType ->invalid mime"); }
PerfDbgLog2(tagCTransData, this, "-CTransData::SetMimeType (hr:%lx, Mime:%ws)", hr,_wzMime?_wzMime:L"");
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::SetFileName
//
// Synopsis:
//
// Arguments: [szFile] --
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CTransData::SetFileName(LPWSTR pwzFile) { DEBUG_ENTER((DBG_TRANSDAT, Hresult, "CTransData::SetFileName", "this=%#x, %.80wq", this, pwzFile )); PerfDbgLog(tagCTransData, this, "+CTransData::SetFileName");
TransAssert((pwzFile)); if(pwzFile) { wcscpy(_wzFileName, pwzFile); }
PerfDbgLog2(tagCTransData, this, "-CTransData::SetFileName (_wzFileName:%ws, hr:%lx)", _wzFileName?_wzFileName:L"", NOERROR);
DEBUG_LEAVE(NOERROR); return NOERROR; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::GetMimeType
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 4-24-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
LPCWSTR CTransData::GetMimeType() { DEBUG_ENTER((DBG_TRANSDAT, Pointer, "CTransData::GetMimeType", "this=%#x", this )); PerfDbgLog(tagCTransData, this, "+CTransData::GetMimeType"); LPWSTR pwzStr = NULL;
if (_wzMime[0] != 0) { pwzStr = _wzMime; }
PerfDbgLog1(tagCTransData, this, "-CTransData::GetMimeType (pStr:%ws)", pwzStr?pwzStr:L"");
DEBUG_LEAVE(pwzStr); return pwzStr; }
//+---------------------------------------------------------------------------
//
// Method: CTransData::OnEndofData()
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 7-30-97 DanpoZ(Danpo Zhang) Created
//
// Notes:
//
//----------------------------------------------------------------------------
void CTransData::OnEndofData() { DEBUG_ENTER((DBG_TRANSDAT, None, "CTransData::OnEndofData", "this=%#x", this )); PerfDbgLog1(tagCTransData, this, "+CTransData::OnEndofData(_ds:%ld)", _ds); BOOL fNewStgMed = FALSE;
if (_pStgMed && _ds == DataSink_StreamOnFile && _pStgMed->pstm ) { ((CReadOnlyStreamFile*)(_pStgMed->pstm))->SetDataFullyAvailable(); }
PerfDbgLog(tagCTransData, this, "-CTransData::OnEndofData");
DEBUG_LEAVE(0); }
|