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.
2710 lines
74 KiB
2710 lines
74 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// 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);
|
|
}
|