//+-------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1992. // // File: expiter.cxx // // Contents: CExposedIterator implementation // // History: 12-Mar-92 DrewB Created // //--------------------------------------------------------------- #include #pragma hdrstop #include #include #include //+-------------------------------------------------------------- // // 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 (; peltFindGreaterEntry(&_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); }