495 lines
12 KiB
C++
495 lines
12 KiB
C++
//+--------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1992.
|
|
//
|
|
// File: expiter.cxx
|
|
//
|
|
// Contents: CExposedIterator implementation
|
|
//
|
|
// History: 12-Mar-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
#include <exphead.cxx>
|
|
#pragma hdrstop
|
|
|
|
#include <expiter.hxx>
|
|
#include <sstream.hxx>
|
|
#include <ptrcache.hxx>
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedIterator::CExposedIterator, public
|
|
//
|
|
// Synopsis: Constructor
|
|
//
|
|
// Arguments: [ppdf] - Public docfile
|
|
// [pdfnKey] - Initial key
|
|
// [pdfb] - DocFile basis
|
|
// [ppc] - Context
|
|
// [fOwnContext] - Whether this object owns the context
|
|
//
|
|
// History: 12-Mar-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
CExposedIterator::CExposedIterator(CPubDocFile *ppdf,
|
|
CDfName *pdfnKey,
|
|
CDFBasis *pdfb,
|
|
CPerContext *ppc,
|
|
BOOL fOwnContext)
|
|
{
|
|
olDebugOut((DEB_ITRACE, "In CExposedIterator::CExposedIterator("
|
|
"%p, %d:%s, %p, %p, %u)\n", ppdf, pdfnKey->GetLength(),
|
|
pdfnKey->GetBuffer(), pdfb, ppc, fOwnContext));
|
|
_ppc = ppc;
|
|
_fOwnContext = fOwnContext;
|
|
_ppdf = P_TO_BP(CBasedPubDocFilePtr, ppdf);
|
|
_ppdf->vAddRef();
|
|
_dfnKey.Set(pdfnKey);
|
|
_pdfb = P_TO_BP(CBasedDFBasisPtr, pdfb);
|
|
_pdfb->vAddRef();
|
|
_cReferences = 1;
|
|
_sig = CEXPOSEDITER_SIG;
|
|
olDebugOut((DEB_ITRACE, "Out CExposedIterator::CExposedIterator\n"));
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedIterator::~CExposedIterator, public
|
|
//
|
|
// Synopsis: Destructor
|
|
//
|
|
// History: 22-Jan-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
CExposedIterator::~CExposedIterator(void)
|
|
{
|
|
olDebugOut((DEB_ITRACE, "In CExposedIterator::~CExposedIterator\n"));
|
|
_sig = CEXPOSEDITER_SIGDEL;
|
|
|
|
//In order to call into the tree, we need to take the mutex.
|
|
//The mutex may get deleted in _ppc->Release(), so we can't
|
|
//release it here. The mutex actually gets released in
|
|
//CPerContext::Release() or in the CPerContext destructor.
|
|
SCODE sc;
|
|
|
|
#if !defined(MULTIHEAP)
|
|
// TakeSem and ReleaseSem are moved to the Release Method
|
|
// so that the deallocation for this object is protected
|
|
if (_ppc)
|
|
{
|
|
sc = TakeSem();
|
|
SetWriteAccess();
|
|
olAssert(SUCCEEDED(sc));
|
|
}
|
|
#ifdef ASYNC
|
|
IDocfileAsyncConnectionPoint *pdacp = _cpoint.GetMarshalPoint();
|
|
#endif
|
|
#endif //MULTIHEAP
|
|
|
|
olAssert(_cReferences == 0);
|
|
if (_ppdf)
|
|
_ppdf->CPubDocFile::vRelease();
|
|
if (_pdfb)
|
|
_pdfb->CDFBasis::vRelease();
|
|
#if !defined(MULTIHEAP)
|
|
if (_fOwnContext && _ppc)
|
|
{
|
|
_ppc->Release();
|
|
}
|
|
else if (_ppc)
|
|
{
|
|
ReleaseSem(sc);
|
|
}
|
|
#ifdef ASYNC
|
|
//Mutex has been released, so we can release the connection point
|
|
// without fear of deadlock.
|
|
if (pdacp != NULL)
|
|
pdacp->Release;
|
|
#endif
|
|
#endif // MULTIHEAP
|
|
olDebugOut((DEB_ITRACE, "Out CExposedIterator::~CExposedIterator\n"));
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedIterator::Next, public
|
|
//
|
|
// Synopsis: Gets N entries from an iterator
|
|
//
|
|
// Arguments: [celt] - Count of elements
|
|
// [rgelt] - Array for element return
|
|
// [pceltFetched] - If non-NULL, contains the number of
|
|
// elements fetched
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [rgelt]
|
|
// [pceltFetched]
|
|
//
|
|
// History: 16-Mar-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
_OLESTDMETHODIMP CExposedIterator::Next(ULONG celt,
|
|
STATSTGW FAR *rgelt,
|
|
ULONG *pceltFetched)
|
|
{
|
|
SAFE_SEM;
|
|
SAFE_ACCESS;
|
|
SCODE sc;
|
|
STATSTGW *pelt = rgelt;
|
|
ULONG celtDone;
|
|
CDfName dfnInitial;
|
|
CPtrCache pc;
|
|
STATSTGW stat;
|
|
|
|
olDebugOut((DEB_TRACE, "In CExposedIterator::Next(%lu, %p, %p)\n",
|
|
celt, rgelt, pceltFetched));
|
|
|
|
if (pceltFetched)
|
|
{
|
|
olChkTo(EH_RetSc, ValidateOutBuffer(pceltFetched, sizeof(ULONG)));
|
|
*pceltFetched = 0;
|
|
}
|
|
else if (celt > 1)
|
|
olErr(EH_Err, STG_E_INVALIDPARAMETER);
|
|
olChkTo(EH_RetSc, ValidateOutBuffer(rgelt,
|
|
(size_t)(sizeof(STATSTGW)*celt)));
|
|
memset(rgelt, 0, (size_t)(sizeof(STATSTGW)*celt));
|
|
olChk(Validate());
|
|
|
|
BEGIN_PENDING_LOOP;
|
|
olChk(TakeSafeSem());
|
|
SetReadAccess();
|
|
|
|
olChk(_ppdf->CheckReverted());
|
|
|
|
// Preserve initial key to reset on failure
|
|
dfnInitial.Set(&_dfnKey);
|
|
|
|
TRY
|
|
{
|
|
for (; pelt<rgelt+celt; pelt++)
|
|
{
|
|
sc = _ppdf->FindGreaterEntry(&_dfnKey, NULL, &stat, FALSE);
|
|
if (FAILED(sc))
|
|
{
|
|
if (sc == STG_E_NOMOREFILES)
|
|
sc = S_FALSE;
|
|
break;
|
|
}
|
|
|
|
if (FAILED(sc = pc.Add(stat.pwcsName)))
|
|
{
|
|
TaskMemFree(stat.pwcsName);
|
|
break;
|
|
}
|
|
|
|
_dfnKey.Set(stat.pwcsName);
|
|
|
|
stat.grfMode = 0;
|
|
stat.grfLocksSupported = 0;
|
|
stat.STATSTG_dwStgFmt = 0;
|
|
|
|
*pelt = stat;
|
|
}
|
|
}
|
|
CATCH(CException, e)
|
|
{
|
|
sc = e.GetErrorCode();
|
|
}
|
|
END_CATCH
|
|
END_PENDING_LOOP;
|
|
|
|
// Can't move this down because dfnInitial isn't set for all EH_Err cases
|
|
if (FAILED(sc))
|
|
_dfnKey.Set(&dfnInitial);
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedIterator::Next => %lX\n", sc));
|
|
EH_Err:
|
|
celtDone = pelt-rgelt;
|
|
if (FAILED(sc))
|
|
{
|
|
void *pv;
|
|
|
|
pc.StartEnum();
|
|
while (pc.Next(&pv))
|
|
TaskMemFree(pv);
|
|
|
|
}
|
|
else if (pceltFetched)
|
|
// May fault but that's acceptable
|
|
*pceltFetched = celtDone;
|
|
EH_RetSc:
|
|
return _OLERETURN(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedIterator::Skip, public
|
|
//
|
|
// Synopsis: Skips N entries from an iterator
|
|
//
|
|
// Arguments: [celt] - Count of elements
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 16-Mar-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedIterator::Skip(ULONG celt)
|
|
{
|
|
SCODE sc;
|
|
|
|
olDebugOut((DEB_TRACE, "In CExposedIterator::Skip(%lu)\n", celt));
|
|
|
|
if (SUCCEEDED(sc = Validate()))
|
|
sc = hSkip(celt, FALSE);
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedIterator::Skip\n"));
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedIterator::Reset, public
|
|
//
|
|
// Synopsis: Rewinds the iterator
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 22-Jan-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedIterator::Reset(void)
|
|
{
|
|
SCODE sc;
|
|
|
|
olDebugOut((DEB_TRACE, "In CExposedIterator::Reset()\n"));
|
|
|
|
if (SUCCEEDED(sc = Validate()))
|
|
sc = hReset();
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedIterator::Reset\n"));
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedIterator::Clone, public
|
|
//
|
|
// Synopsis: Clones this iterator
|
|
//
|
|
// Arguments: [ppenm] - Clone return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppenm]
|
|
//
|
|
// History: 26-Mar-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedIterator::Clone(IEnumSTATSTG **ppenm)
|
|
{
|
|
SCODE sc, scSem = STG_E_INUSE;
|
|
SafeCExposedIterator piExp;
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
#endif
|
|
|
|
olDebugOut((DEB_TRACE, "In CExposedIterator::Clone(%p)\n", ppenm));
|
|
|
|
olChk(ValidateOutPtrBuffer(ppenm));
|
|
*ppenm = NULL;
|
|
olChk(Validate());
|
|
olChk(scSem = TakeSem());
|
|
if (!SUCCEEDED(sc = _ppdf->CheckReverted()))
|
|
{
|
|
ReleaseSem(scSem);
|
|
olChk(sc);
|
|
}
|
|
SetReadAccess();
|
|
|
|
piExp.Attach(new CExposedIterator(BP_TO_P(CPubDocFile *, _ppdf),
|
|
&_dfnKey,
|
|
BP_TO_P(CDFBasis *, _pdfb),
|
|
_ppc,
|
|
TRUE));
|
|
if ((CExposedIterator *)piExp == NULL)
|
|
sc = STG_E_INSUFFICIENTMEMORY;
|
|
|
|
ClearReadAccess();
|
|
ReleaseSem(scSem);
|
|
|
|
if (SUCCEEDED(sc))
|
|
{
|
|
_ppc->AddRef();
|
|
TRANSFER_INTERFACE(piExp, IEnumSTATSTG, ppenm);
|
|
}
|
|
|
|
if (_cpoint.IsInitialized())
|
|
{
|
|
olChkTo(EH_init, piExp->InitClone(&_cpoint));
|
|
}
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedIterator::Clone => %p\n",
|
|
*ppenm));
|
|
// Fall through
|
|
EH_Err:
|
|
return ResultFromScode(sc);
|
|
EH_init:
|
|
piExp->Release();
|
|
goto EH_Err;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedIterator::Release, public
|
|
//
|
|
// Synopsis: Releases resources for the iterator
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 22-Jan-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP_(ULONG) CExposedIterator::Release(void)
|
|
{
|
|
LONG lRet;
|
|
|
|
olDebugOut((DEB_TRACE, "In CExposedIterator::Release()\n"));
|
|
|
|
#ifdef MULTIHEAP
|
|
CSafeMultiHeap smh(_ppc);
|
|
CPerContext *ppc = _ppc;
|
|
BOOL fOwnContext = _fOwnContext;
|
|
SCODE sc = S_OK;
|
|
#endif
|
|
if (FAILED(Validate()))
|
|
return 0;
|
|
if ((lRet = hRelease()) == 0)
|
|
#ifdef MULTIHEAP
|
|
{
|
|
if (_ppc)
|
|
{
|
|
sc = TakeSem();
|
|
SetWriteAccess();
|
|
olAssert(SUCCEEDED(sc));
|
|
}
|
|
#ifdef ASYNC
|
|
IDocfileAsyncConnectionPoint *pdacp = _cpoint.GetMarshalPoint();
|
|
#endif
|
|
#endif //MULTIHEAP
|
|
delete this;
|
|
#ifdef MULTIHEAP
|
|
if (fOwnContext && ppc)
|
|
{
|
|
BOOL fLastRef = ppc->LastRef();
|
|
ppc->Release();
|
|
if (fLastRef)
|
|
g_smAllocator.Uninit();
|
|
}
|
|
else if (ppc)
|
|
{
|
|
if (SUCCEEDED(sc)) ppc->UntakeSem();
|
|
}
|
|
#ifdef ASYNC
|
|
//Mutex has been released, so we can release the connection point
|
|
// without fear of deadlock.
|
|
if (pdacp != NULL)
|
|
pdacp->Release();
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedIterator::Release\n"));
|
|
return lRet;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedIterator::AddRef, public
|
|
//
|
|
// Synopsis: Increments the ref count
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 16-Mar-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP_(ULONG) CExposedIterator::AddRef(void)
|
|
{
|
|
ULONG ulRet;
|
|
|
|
olDebugOut((DEB_TRACE, "In CExposedIterator::AddRef()\n"));
|
|
|
|
if (FAILED(Validate()))
|
|
return 0;
|
|
ulRet = hAddRef();
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedIterator::AddRef\n"));
|
|
return ulRet;
|
|
}
|
|
|
|
//+--------------------------------------------------------------
|
|
//
|
|
// Member: CExposedIterator::QueryInterface, public
|
|
//
|
|
// Synopsis: Returns an object for the requested interface
|
|
//
|
|
// Arguments: [iid] - Interface ID
|
|
// [ppvObj] - Object return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppvObj]
|
|
//
|
|
// History: 26-Mar-92 DrewB Created
|
|
//
|
|
//---------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP CExposedIterator::QueryInterface(REFIID iid, void **ppvObj)
|
|
{
|
|
SCODE sc;
|
|
|
|
olDebugOut((DEB_TRACE, "In CExposedIterator::QueryInterface(?, %p)\n",
|
|
ppvObj));
|
|
|
|
if (SUCCEEDED(sc = Validate()))
|
|
sc = hQueryInterface(iid,
|
|
IID_IEnumSTATSTG,
|
|
(IEnumSTATSTG *)this,
|
|
ppvObj);
|
|
#ifdef ASYNC
|
|
if (FAILED(sc) &&
|
|
IsEqualIID(iid, IID_IConnectionPointContainer) &&
|
|
_cpoint.IsInitialized())
|
|
{
|
|
*ppvObj = (IConnectionPointContainer *)this;
|
|
CExposedIterator::AddRef();
|
|
}
|
|
#endif
|
|
|
|
olDebugOut((DEB_TRACE, "Out CExposedIterator::QueryInterface => %p\n",
|
|
ppvObj));
|
|
return ResultFromScode(sc);
|
|
}
|