//+-------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1992. // // File: expdf.cxx // // Contents: Exposed DocFile implementation // // History: 20-Jan-92 DrewB Created // //--------------------------------------------------------------- #include #pragma hdrstop #include #include #include #include #include #include #include #include #include #include #include #if WIN32 == 300 IMPLEMENT_UNWIND(CSafeAccess); IMPLEMENT_UNWIND(CSafeSem); #endif extern WCHAR const wcsContents[]; //+-------------------------------------------------------------- // // Member: CExposedDocFile::CExposedDocFile, public // // Synopsis: Constructor // // Arguments: [pdf] - Public DocFile // [pdfb] - DocFile basis // [ppc] - Context // // History: 20-Jan-92 DrewB Created // //--------------------------------------------------------------- CExposedDocFile::CExposedDocFile(CPubDocFile *pdf, CDFBasis *pdfb, CPerContext *ppc) : CPropertySetStorage(MAPPED_STREAM_QI), _PropertyBagEx( DFlagsToMode( pdf->GetDFlags() )) { olDebugOut((DEB_ITRACE, "In CExposedDocFile::CExposedDocFile(" "%p, %p, %p)\n", pdf, pdfb, ppc)); _ppc = ppc; _pdf = P_TO_BP(CBasedPubDocFilePtr, pdf); _pdfb = P_TO_BP(CBasedDFBasisPtr, pdfb); _pdfb->vAddRef(); _cReferences = 1; _sig = CEXPOSEDDOCFILE_SIG; #if WIN32 >= 300 _pIAC = NULL; #endif // Initialize CPropertySetStorage and CPropertyBagEx CPropertySetStorage::Init( static_cast(this), static_cast(this), FALSE ); // fControlLifetimes (=> Don't addref) _PropertyBagEx.Init( static_cast(this), // Not addref-ed static_cast(this) ); // Not addref-ed // // CoQueryReleaseObject needs to have the address of the exposed docfiles // query interface routine. // if (adwQueryInterfaceTable[QI_TABLE_CExposedDocFile] == 0) { adwQueryInterfaceTable[QI_TABLE_CExposedDocFile] = **(ULONG_PTR **)((IStorage *)this); } #ifdef COORD _ulLock = _cbSizeBase = _cbSizeOrig = 0; _sigMSF = 0; #endif olDebugOut((DEB_ITRACE, "Out CExposedDocFile::CExposedDocFile\n")); } SCODE CExposedDocFile::InitMarshal(DWORD dwAsyncFlags, IDocfileAsyncConnectionPoint *pdacp) { return _cpoint.InitMarshal(this, dwAsyncFlags, pdacp); } //+-------------------------------------------------------------- // // Member: CExposedDocFile::~CExposedDocFile, public // // Synopsis: Destructor // // History: 23-Jan-92 DrewB Created // //--------------------------------------------------------------- CExposedDocFile::~CExposedDocFile(void) { BOOL fClose = FALSE; olDebugOut((DEB_ITRACE, "In CExposedDocFile::~CExposedDocFile\n")); olAssert(_cReferences == 0); //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. //If _ppc is NULL, we're partially constructed and don't need to //worry. SCODE sc; #if WIN32 >= 300 if (_pIAC != NULL) { _pIAC->Release(); _pIAC = NULL; } #endif #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 if (_pdf) { // If we're the last reference on a root object // we close the context because all children will become // reverted so it is no longer necessary if (_pdf->GetRefCount() == 1 && _pdf->IsRoot()) fClose = TRUE; _pdf->CPubDocFile::vRelease(); } if (_pdfb) _pdfb->CDFBasis::vRelease(); #if !defined(MULTIHEAP) if (_ppc) { if (fClose) _ppc->Close(); if (_ppc->Release() > 0) 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 _sig = CEXPOSEDDOCFILE_SIGDEL; olDebugOut((DEB_ITRACE, "Out CExposedDocFile::~CExposedDocFile\n")); } //+-------------------------------------------------------------- // // Member: CExposedDocFile::Release, public // // Synopsis: Releases resources for a CExposedDocFile // // Returns: Appropriate status code // // History: 20-Jan-92 DrewB Created // //--------------------------------------------------------------- STDMETHODIMP_(ULONG) CExposedDocFile::Release(void) { LONG lRet; olLog(("%p::In CExposedDocFile::Release()\n", this)); olDebugOut((DEB_TRACE, "In CExposedDocFile::Release()\n")); if (FAILED(Validate())) return 0; olAssert(_cReferences > 0); lRet = InterlockedDecrement(&_cReferences); if (lRet == 0) { SCODE sc = S_OK; sc = _PropertyBagEx.Commit( STGC_DEFAULT ); olAssert(SUCCEEDED(sc)); sc = _PropertyBagEx.ShutDown(); olAssert(SUCCEEDED(sc)); #ifdef MULTIHEAP CSafeMultiHeap smh(_ppc); CPerContext *ppc = _ppc; if (_ppc) { sc = TakeSem(); SetWriteAccess(); olAssert(SUCCEEDED(sc)); } #ifdef ASYNC IDocfileAsyncConnectionPoint *pdacp = _cpoint.GetMarshalPoint(); #endif BOOL fClose = (_pdf) && (_pdf->GetRefCount()==1) && _pdf->IsRoot(); #endif //MULTIHEAP delete this; #ifdef MULTIHEAP if (ppc) { if (fClose) ppc->Close(); if (ppc->Release() == 0) g_smAllocator.Uninit(); else 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 } else if (lRet < 0) lRet = 0; olDebugOut((DEB_TRACE, "Out CExposedDocFile::Release %p() => %lu\n", this, lRet)); olLog(("%p::Out CExposedDocFile::Release(). ret == %lu\n", this, lRet)); FreeLogFile(); return (ULONG)lRet; } //+-------------------------------------------------------------- // // Member: CExposedDocFile::CheckCopyTo, private // // Synopsis: Checks for CopyTo legality // // Returns: Appropriate status code // // History: 07-Jul-92 DrewB Created // //--------------------------------------------------------------- inline SCODE CExposedDocFile::CheckCopyTo(void) { return _pdfb->GetCopyBase() != NULL && _pdf->IsAtOrAbove(_pdfb->GetCopyBase()) ? STG_E_ACCESSDENIED : S_OK; } //+-------------------------------------------------------------- // // Member: CExposedDocFile::ConvertInternalStream, private // // Synopsis: Converts an internal stream to a storage // // Arguments: [pwcsName] - Name // [pdfExp] - Destination docfile // // Returns: Appropriate status code // // History: 23-Jun-92 DrewB Created // //--------------------------------------------------------------- static WCHAR const wcsIllegalName[] = {'\\', '\0'}; SCODE CExposedDocFile::ConvertInternalStream(CExposedDocFile *pdfExp) { CPubStream *pstFrom, *pstTo; SCODE sc; CDfName const dfnIllegal(wcsIllegalName); CDfName const dfnContents(wcsContents); olDebugOut((DEB_ITRACE, "In CExposedDocFile::ConvertInternalStream(%p)\n", pdfExp)); olChk(_pdf->GetStream(&dfnIllegal, DF_READWRITE | DF_DENYALL, &pstFrom)); olChkTo(EH_pstFrom, pdfExp->GetPub()->CreateStream(&dfnContents, DF_WRITE | DF_DENYALL, &pstTo)); olChkTo(EH_pstTo, CopySStreamToSStream(pstFrom->GetSt(), pstTo->GetSt())); olChkTo(EH_pstTo, _pdf->DestroyEntry(&dfnIllegal, FALSE)); sc = S_OK; olDebugOut((DEB_ITRACE, "Out CExposedDocFile::ConvertInternalStream\n")); // Fall through EH_pstTo: pstTo->CPubStream::vRelease(); EH_pstFrom: pstFrom->CPubStream::vRelease(); EH_Err: return sc; } //+--------------------------------------------------------------------------- // // Member: CExposedDocFile::CreateEntry, private // // Synopsis: Creates elements, used in CreateStream, CreateStorage. // // Arguments: [pdfn] - Name // [dwType] - Entry type // [grfMode] - Access mode // [ppv] - Object return // // Returns: Appropriate status code // // Modifies: [ppv] // // History: 18-Dec-92 DrewB Created // //---------------------------------------------------------------------------- SCODE CExposedDocFile::CreateEntry(CDfName const *pdfn, DWORD dwType, DWORD grfMode, void **ppv) { SCODE sc; SEntryBuffer eb; BOOL fRenamed = FALSE; CPubStream *pst; CExposedStream *pstExp; CPubDocFile *pdf; CExposedDocFile *pdfExp; olDebugOut((DEB_ITRACE, "In CExposedDocFile::CreateEntry:%p(" "%p, %lX, %lX, %p)\n", this, pdfn, dwType, grfMode, ppv)); olChk(EnforceSingle(grfMode)); // 3/11/93 - Demand scratch when opening/creating transacted if ((grfMode & STGM_TRANSACTED) == STGM_TRANSACTED) { olChk(_ppc->GetDirty()->InitScratch()); } if (grfMode & (STGM_CREATE | STGM_CONVERT)) { if (FAILED(sc = _pdf->IsEntry(pdfn, &eb))) { if (sc != STG_E_FILENOTFOUND) olErr(EH_Err, sc); } else if (eb.dwType == dwType && (grfMode & STGM_CREATE)) olChk(_pdf->DestroyEntry(pdfn, FALSE)); else if (eb.dwType == STGTY_STREAM && (grfMode & STGM_CONVERT) && dwType == STGTY_STORAGE) { CDfName const dfnIllegal(wcsIllegalName); olChk(_pdf->RenameEntry(pdfn, &dfnIllegal)); fRenamed = TRUE; } else olErr(EH_Err, STG_E_FILEALREADYEXISTS); } if (REAL_STGTY(dwType) == STGTY_STREAM) { olChk(_pdf->CreateStream(pdfn, ModeToDFlags(grfMode), &pst)); olMemTo(EH_pst, pstExp = new (_pdfb->GetMalloc()) CExposedStream); olChkTo(EH_pstExp, pstExp->Init(pst, BP_TO_P(CDFBasis *, _pdfb), _ppc, NULL)); _ppc->AddRef(); #ifdef ASYNC if (_cpoint.IsInitialized()) { olChkTo(EH_connSt, pstExp->InitConnection(&_cpoint)); } #endif *ppv = pstExp; } else { olAssert(REAL_STGTY(dwType) == STGTY_STORAGE); olChk(_pdf->CreateDocFile(pdfn, ModeToDFlags(grfMode), &pdf)); olMemTo(EH_pdf, pdfExp = new (_pdfb->GetMalloc()) CExposedDocFile(pdf, BP_TO_P(CDFBasis *, _pdfb), _ppc)); _ppc->AddRef(); if (_cpoint.IsInitialized()) { olChkTo(EH_pdfExpInit, pdfExp->InitConnection(&_cpoint)); } // If we've renamed the original stream for conversion, convert if (fRenamed) { olChkTo(EH_pdfExpInit, ConvertInternalStream(pdfExp)); sc = STG_S_CONVERTED; } *ppv = pdfExp; } olDebugOut((DEB_ITRACE, "Out CExposedDocFile::CreateEntry\n")); return sc; EH_connSt: pstExp->Release(); goto EH_Del; EH_pstExp: delete pstExp; EH_pst: pst->CPubStream::vRelease(); goto EH_Del; EH_pdfExpInit: pdfExp->Release(); goto EH_Del; EH_pdf: pdf->CPubDocFile::vRelease(); // Fall through EH_Del: olVerSucc(_pdf->DestroyEntry(pdfn, TRUE)); EH_Err: return sc; } //+--------------------------------------------------------------------------- // // Member: CExposedDocFile::OpenEntry, private // // Synopsis: Opens elements, used in OpenStream, OpenStorage. // // Arguments: [pdfn] - Name // [dwType] - Entry type // [grfMode] - Access mode // [ppv] - Object return // // Returns: Appropriate status code // // Modifies: [ppv] // // History: 18-Dec-92 DrewB Created // //---------------------------------------------------------------------------- SCODE CExposedDocFile::OpenEntry(CDfName const *pdfn, DWORD dwType, DWORD grfMode, void **ppv) { SCODE sc; CPubDocFile *pdf; CExposedDocFile *pdfExp; CPubStream *pst; CExposedStream *pstExp; olDebugOut((DEB_ITRACE, "In CExposedDocFile::OpenEntry:%p(" "%p, %lX, %lX, %p)\n", this, pdfn, dwType, grfMode, ppv)); olChk(EnforceSingle(grfMode)); // 3/11/93 - Demand scratch when opening/creating transacted if ((grfMode & STGM_TRANSACTED) == STGM_TRANSACTED) { olChk(_ppc->GetDirty()->InitScratch()); } if (REAL_STGTY(dwType) == STGTY_STREAM) { olChk(_pdf->GetStream(pdfn, ModeToDFlags(grfMode), &pst)); olMemTo(EH_pst, pstExp = new (_pdfb->GetMalloc()) CExposedStream); olChkTo(EH_pstExp, pstExp->Init(pst, BP_TO_P(CDFBasis *, _pdfb), _ppc, NULL)); _ppc->AddRef(); if (_cpoint.IsInitialized()) { olChkTo(EH_connSt, pstExp->InitConnection(&_cpoint)); } *ppv = pstExp; } else { olAssert(REAL_STGTY(dwType) == STGTY_STORAGE); olChk(_pdf->GetDocFile(pdfn, ModeToDFlags(grfMode), &pdf)); olMemTo(EH_pdf, pdfExp = new (_pdfb->GetMalloc()) CExposedDocFile(pdf, BP_TO_P(CDFBasis *, _pdfb), _ppc)); _ppc->AddRef(); if (_cpoint.IsInitialized()) { olChkTo(EH_connDf, pdfExp->InitConnection(&_cpoint)); } *ppv = pdfExp; } olDebugOut((DEB_ITRACE, "Out CExposedDocFile::OpenEntry\n")); return S_OK; EH_connSt: pstExp->Release(); return sc; EH_pstExp: delete pstExp; // Fall through to clean up CPubStream EH_pst: pst->CPubStream::vRelease(); return sc; EH_connDf: pdfExp->Release(); return sc; EH_pdf: pdf->CPubDocFile::vRelease(); // Fall through EH_Err: return sc; } //+-------------------------------------------------------------- // // Member: CExposedDocFile::CreateStream, public // // Synopsis: Creates a stream // // Arguments: [pwcsName] - Name // [grfMode] - Permissions // [reserved1] // [reserved2] // [ppstm] - Stream return // // Returns: Appropriate status code // // Modifies: [ppstm] // // History: 20-Jan-92 DrewB Created // //--------------------------------------------------------------- _OLESTDMETHODIMP CExposedDocFile::CreateStream(WCHAR const *pwcsName, DWORD grfMode, DWORD reserved1, DWORD reserved2, IStream **ppstm) { SCODE sc; SAFE_SEM; SAFE_ACCESS; SafeCExposedStream pestm; CDfName dfn; olDebugOut((DEB_TRACE, "In CExposedDocFile::CreateStream(" "%ws, %lX, %lu, %lu, %p)\n", pwcsName, grfMode, reserved1, reserved2, ppstm)); olLog(("%p::In CExposedDocFile::CreateStream(%ws, %lX, %lu, %lu, %p)\n", this, pwcsName, grfMode, reserved1, reserved2, ppstm)); OL_VALIDATE(CreateStream(pwcsName, grfMode, reserved1, reserved2, ppstm)); olChk(Validate()); BEGIN_PENDING_LOOP; olChk(TakeSafeSem()); olChk(CheckCopyTo()); SafeWriteAccess(); #ifdef DIRECTWRITERLOCK olChk(ValidateWriteAccess()); #endif dfn.Set(pwcsName); sc = CreateEntry(&dfn, STGTY_STREAM, grfMode, (void **)&pestm); END_PENDING_LOOP; if (SUCCEEDED(sc)) TRANSFER_INTERFACE(pestm, IStream, ppstm); olDebugOut((DEB_TRACE, "Out CExposedDocFile::CreateStream => %p\n", *ppstm)); EH_Err: olLog(("%p::Out CExposedDocFile::CreateStream(). " "*ppstm == %p, ret == %lx\n", this, *ppstm, sc)); return _OLERETURN(sc); } //+-------------------------------------------------------------- // // Member: CExposedDocFile::OpenStream, public // // Synopsis: Opens an existing stream // // Arguments: [pwcsName] - Name // [reserved1] // [grfMode] - Permissions // [reserved2] // [ppstm] - Stream return // // Returns: Appropriate status code // // Modifies: [ppstm] // // History: 20-Jan-92 DrewB Created // //--------------------------------------------------------------- _OLESTDMETHODIMP CExposedDocFile::OpenStream(WCHAR const *pwcsName, void *reserved1, DWORD grfMode, DWORD reserved2, IStream **ppstm) { SCODE sc; SAFE_SEM; SAFE_ACCESS; SafeCExposedStream pestm; CDfName dfn; olDebugOut((DEB_TRACE, "In CExposedDocFile::OpenStream(" "%ws, %p, %lX, %lu, %p)\n", pwcsName, reserved1, grfMode, reserved2, ppstm)); olLog(("%p::In CExposedDocFile::OpenStream(%ws, %lu %lX, %lu, %p)\n", this, pwcsName, reserved1, grfMode, reserved2, ppstm)); OL_VALIDATE(OpenStream(pwcsName, reserved1, grfMode, reserved2, ppstm)); olChk(Validate()); BEGIN_PENDING_LOOP; olChk(TakeSafeSem()); SafeReadAccess(); dfn.Set(pwcsName); sc = OpenEntry(&dfn, STGTY_STREAM, grfMode, (void **)&pestm); END_PENDING_LOOP; if (SUCCEEDED(sc)) TRANSFER_INTERFACE(pestm, IStream, ppstm); olDebugOut((DEB_TRACE, "Out CExposedDocFile::OpenStream => %p\n", *ppstm)); EH_Err: olLog(("%p::Out CExposedDocFile::OpenStream(). " "*ppstm == %p, ret == %lx\n", this, *ppstm, sc)); return _OLERETURN(sc); } //+-------------------------------------------------------------- // // Member: CExposedDocFile::CreateStorage, public // // Synopsis: Creates an embedded DocFile // // Arguments: [pwcsName] - Name // [grfMode] - Permissions // [reserved1] // [reserved2] // [ppstg] - New DocFile return // // Returns: Appropriate status code // // Modifies: [ppstg] // // History: 20-Jan-92 DrewB Created // //--------------------------------------------------------------- _OLESTDMETHODIMP CExposedDocFile::CreateStorage( WCHAR const *pwcsName, DWORD grfMode, DWORD reserved1, LPSTGSECURITY reserved2, IStorage **ppstg) { SCODE sc; SAFE_SEM; SAFE_ACCESS; SafeCExposedDocFile pedf; CDfName dfn; olLog(("%p::In CExposedDocFile::CreateStorage(%ws, %lX, %lu, %lu, %p)\n", this, pwcsName, grfMode, reserved1, reserved2, ppstg)); olDebugOut((DEB_TRACE, "In CExposedDocFile::CreateStorage:%p(" "%ws, %lX, %lu, %lu, %p)\n", this, pwcsName, grfMode, reserved1, reserved2, ppstg)); OL_VALIDATE(CreateStorage(pwcsName, grfMode, reserved1, reserved2, ppstg)); olChk(Validate()); BEGIN_PENDING_LOOP; olChk(TakeSafeSem()); olChk(CheckCopyTo()); SafeWriteAccess(); #ifdef DIRECTWRITERLOCK olChk(ValidateWriteAccess()); #endif dfn.Set(pwcsName); sc = CreateEntry(&dfn, STGTY_STORAGE, grfMode, (void **)&pedf); END_PENDING_LOOP; if (SUCCEEDED(sc)) TRANSFER_INTERFACE(pedf, IStorage, ppstg); olDebugOut((DEB_TRACE, "Out CExposedDocFile::CreateStorage => %p\n", *ppstg)); EH_Err: olLog(("%p::Out CExposedDocFile::CreateStorage(). " "*ppstg == %p, ret == %lX\n", this, *ppstg, sc)); return _OLERETURN(sc); } //+-------------------------------------------------------------- // // Member: CExposedDocFile::OpenStorage, public // // Synopsis: Gets an existing embedded DocFile // // Arguments: [pwcsName] - Name // [pstgPriority] - Priority reopens // [grfMode] - Permissions // [snbExclude] - Priority reopens // [reserved] // [ppstg] - DocFile return // // Returns: Appropriate status code // // Modifies: [ppstg] // // History: 20-Jan-92 DrewB Created // //--------------------------------------------------------------- _OLESTDMETHODIMP CExposedDocFile::OpenStorage(WCHAR const *pwcsName, IStorage *pstgPriority, DWORD grfMode, SNBW snbExclude, DWORD reserved, IStorage **ppstg) { SCODE sc; SAFE_SEM; SAFE_ACCESS; SafeCExposedDocFile pdfExp; CDfName dfn; olLog(("%p::In CExposedDocFile::OpenStorage(%ws, %p, %lX, %p, %lu, %p)\n", this, pwcsName, pstgPriority, grfMode, snbExclude, reserved, ppstg)); olDebugOut((DEB_TRACE, "In CExposedDocFile::OpenStorage:%p(" "%ws, %p, %lX, %p, %lu, %p)\n", this, pwcsName, pstgPriority, grfMode, snbExclude, reserved, ppstg)); OL_VALIDATE(OpenStorage(pwcsName, pstgPriority, grfMode, snbExclude, reserved, ppstg)); olChk(Validate()); if (snbExclude != NULL) olErr(EH_Err, STG_E_INVALIDPARAMETER); BEGIN_PENDING_LOOP; olChk(TakeSafeSem()); SafeReadAccess(); dfn.Set(pwcsName); sc = OpenEntry(&dfn, STGTY_STORAGE, grfMode, (void **)&pdfExp); END_PENDING_LOOP; if (SUCCEEDED(sc)) { TRANSFER_INTERFACE(pdfExp, IStorage, ppstg); } olDebugOut((DEB_TRACE, "Out CExposedDocFile::OpenStorage => %p\n", *ppstg)); EH_Err: olLog(("%p::Out CExposedDocFile::OpenStorage(). " "*ppstg == %p, ret == %lX\n", this, *ppstg, sc)); return _OLERETURN(sc); } //+--------------------------------------------------------------------------- // // Member: CExposedDocFile::MakeCopyFlags, public // // Synopsis: Translates IID array into bit fields // // Arguments: [ciidExclude] - Count of IIDs // [rgiidExclude] - IIDs not to copy // // Returns: Appropriate status code // // History: 23-Dec-92 DrewB Created // //---------------------------------------------------------------------------- DWORD CExposedDocFile::MakeCopyFlags(DWORD ciidExclude, IID const *rgiidExclude) { DWORD dwCopyFlags; olDebugOut((DEB_ITRACE, "In CExposedDocFile::MakeCopyFlags(%lu, %p)\n", ciidExclude, rgiidExclude)); // Copy everything by default dwCopyFlags = COPY_ALL; for (; ciidExclude > 0; ciidExclude--, rgiidExclude++) if (IsEqualIID(*rgiidExclude, IID_IStorage)) dwCopyFlags &= ~COPY_STORAGES; else if (IsEqualIID(*rgiidExclude, IID_IStream)) dwCopyFlags &= ~COPY_STREAMS; olDebugOut((DEB_ITRACE, "Out CExposedDocFile::MakeCopyFlags\n")); return dwCopyFlags; } //+-------------------------------------------------------------- // // Member: CExposedDocFile::CopyTo, public // // Synopsis: Makes a copy of a DocFile // // Arguments: [ciidExclude] - Length of rgiid array // [rgiidExclude] - Array of IIDs to exclude // [snbExclude] - Names to exclude // [pstgDest] - Parent of copy // // Returns: Appropriate status code // // History: 20-Jan-92 DrewB Created // //--------------------------------------------------------------- _OLESTDMETHODIMP CExposedDocFile::CopyTo(DWORD ciidExclude, IID const *rgiidExclude, SNBW snbExclude, IStorage *pstgDest) { SCODE sc; #ifdef MULTIHEAP CSafeMultiHeap smh(_ppc); #endif SAFE_SEM; DWORD i; olLog(("%p::In CExposedDocFile::CopyTo(%lu, %p, %p, %p)\n", this, ciidExclude, rgiidExclude, snbExclude, pstgDest)); olDebugOut((DEB_TRACE, "In CExposedDocFile::CopyTo(%lu, %p, %p, %p)\n", ciidExclude, rgiidExclude, snbExclude, pstgDest)); OL_VALIDATE(CopyTo(ciidExclude, rgiidExclude, snbExclude, pstgDest)); olChk(Validate()); BEGIN_PENDING_LOOP; olChk(TakeSafeSem()); olChk(_pdf->CheckReverted()); olAssert(_pdfb->GetCopyBase() == NULL); _pdfb->SetCopyBase(BP_TO_P(CPubDocFile *, _pdf)); // Flush all descendant property set buffers so that their // underlying Streams (which are about to be copied) are // up to date. SetWriteAccess(); olChkTo(EH_Loop, _pdf->FlushBufferedData(0)); ClearWriteAccess(); // Perform the copy. sc = CopyDocFileToIStorage(_pdf->GetDF(), pstgDest, snbExclude, MakeCopyFlags(ciidExclude, rgiidExclude)); EH_Loop: _pdfb->SetCopyBase(NULL); END_PENDING_LOOP; olDebugOut((DEB_TRACE, "Out CExposedDocFile::CopyTo\n")); EH_Err: _pdfb->SetCopyBase(NULL); olLog(("%p::Out ExposedDocFile::CopyTo(). ret == %lX\n", this, sc)); return _OLERETURN(sc); } //+-------------------------------------------------------------- // // Member: CExposedDocFile::Commit, public // // Synopsis: Commits transacted changes // // Arguments: [dwFlags] - DFC_* // // Returns: Appropriate status code // // History: 20-Jan-92 DrewB Created // //--------------------------------------------------------------- STDMETHODIMP CExposedDocFile::Commit(DWORD dwFlags) { SCODE sc; SAFE_SEM; SAFE_ACCESS; olLog(("%p::In CExposedDocFile::Commit(%lX)\n",this, dwFlags)); olDebugOut((DEB_TRACE, "In CExposedDocFile::Commit(%lX)\n", dwFlags)); OL_VALIDATE(Commit(dwFlags)); olChk(Validate()); BEGIN_PENDING_LOOP; olChk( _PropertyBagEx.Commit( dwFlags )); olChk(TakeSafeSem()); SafeWriteAccess(); #ifdef DIRECTWRITERLOCK if (_pdf->GetTransactedDepth() <= 1) // topmost transacted level or direct { if (_pdfb->DirectWriterMode() && (*_ppc->GetRecursionCount()) == 0) olChk(STG_E_ACCESSDENIED); } #endif olChkTo(EH_Loop, _pdf->Commit(dwFlags)); #if WIN32 >= 300 if (SUCCEEDED(sc) && _pIAC != NULL) sc = _pIAC->CommitAccessRights(0); #endif EH_Loop: END_PENDING_LOOP; olDebugOut((DEB_TRACE, "Out CExposedDocFile::Commit\n")); EH_Err: olLog(("%p::Out CExposedDocFile::Commit(). ret == %lx\n",this, sc)); return ResultFromScode(sc); } //+-------------------------------------------------------------- // // Member: CExposedDocFile::Revert, public // // Synopsis: Reverts transacted changes // // Returns: Appropriate status code // // History: 20-Jan-92 DrewB Created // //--------------------------------------------------------------- STDMETHODIMP CExposedDocFile::Revert(void) { SCODE sc; SAFE_SEM; SAFE_ACCESS; olLog(("%p::In CExposedDocFile::Revert()\n", this)); olDebugOut((DEB_TRACE, "In CExposedDocFile::Revert\n")); OL_VALIDATE(Revert()); olChk(Validate()); BEGIN_PENDING_LOOP; olChk(TakeSafeSem()); SafeWriteAccess(); olChkTo(EH_Loop, _pdf->Revert()); #if WIN32 >= 300 if (SUCCEEDED(sc) && _pIAC != NULL) sc = _pIAC->RevertAccessRights(); #endif EH_Loop: END_PENDING_LOOP; olDebugOut((DEB_TRACE, "Out CExposedDocFile::Revert\n")); EH_Err: olLog(("%p::Out CExposedDocFile::Revert(). ret == %lx\n", this, sc)); return ResultFromScode(sc); } //+-------------------------------------------------------------- // // Member: CExposedDocFile::EnumElements, public // // Synopsis: Starts an iterator // // Arguments: [reserved1] // [reserved2] // [reserved3] // [ppenm] - Enumerator return // // Returns: Appropriate status code // // Modifies: [ppenm] // // History: 20-Jan-92 DrewB Created // //--------------------------------------------------------------- STDMETHODIMP CExposedDocFile::EnumElements(DWORD reserved1, void *reserved2, DWORD reserved3, IEnumSTATSTG **ppenm) { SCODE sc; SAFE_SEM; SAFE_ACCESS; SafeCExposedIterator pdiExp; CDfName dfnTmp; olLog(("%p::In CExposedDocFile::EnumElements(%lu, %p, %lu, %p)\n", this, reserved1, reserved2, reserved3, ppenm)); olDebugOut((DEB_TRACE, "In CExposedDocFile::EnumElements(%p)\n", ppenm)); OL_VALIDATE(EnumElements(reserved1, reserved2, reserved3, ppenm)); olChk(Validate()); //ASYNC Note: It doesn't appear that there's any way that this // function can fail with STG_E_PENDING, so we don't need a pending // loop here. olChk(TakeSafeSem()); if (!P_READ(_pdf->GetDFlags())) olErr(EH_Err, STG_E_ACCESSDENIED); olChk(_pdf->CheckReverted()); SafeReadAccess(); pdiExp.Attach(new CExposedIterator(BP_TO_P(CPubDocFile *, _pdf), &dfnTmp, BP_TO_P(CDFBasis *, _pdfb), _ppc)); olMem((CExposedIterator *)pdiExp); _ppc->AddRef(); #ifdef ASYNC if (_cpoint.IsInitialized()) { olChkTo(EH_Exp, pdiExp->InitConnection(&_cpoint)); } #endif TRANSFER_INTERFACE(pdiExp, IEnumSTATSTG, ppenm); olDebugOut((DEB_TRACE, "Out CExposedDocFile::EnumElements => %p\n", *ppenm)); EH_Err: olLog(("%p::Out CExposedDocFile::EnumElements(). ret == %lx\n",this, sc)); return ResultFromScode(sc); EH_Exp: pdiExp->Release(); return ResultFromScode(sc); } //+-------------------------------------------------------------- // // Member: CExposedDocFile::DestroyElement, public // // Synopsis: Permanently deletes an element of a DocFile // // Arguments: [pwcsName] - Name of element // // Returns: Appropriate status code // // History: 20-Jan-92 DrewB Created // //--------------------------------------------------------------- _OLESTDMETHODIMP CExposedDocFile::DestroyElement(WCHAR const *pwcsName) { SCODE sc; SAFE_SEM; SAFE_ACCESS; CDfName dfn; olLog(("%p::In CExposedDocFile::DestroyElement(%ws)\n", this, pwcsName)); olDebugOut((DEB_TRACE, "In CExposedDocFile::DestroyElement(%ws)\n", pwcsName)); OL_VALIDATE(DestroyElement(pwcsName)); olChk(Validate()); dfn.Set(pwcsName); BEGIN_PENDING_LOOP; olChk(TakeSafeSem()); SafeWriteAccess(); #ifdef DIRECTWRITERLOCK olChk(ValidateWriteAccess()); #endif sc = _pdf->DestroyEntry(&dfn, FALSE); END_PENDING_LOOP; olDebugOut((DEB_TRACE, "Out CExposedDocFile::DestroyElement\n")); EH_Err: olLog(("%p::Out CExposedDocFile::DestroyElement(). ret == %lx\n", this, sc)); return _OLERETURN(sc); } _OLESTDMETHODIMP CExposedDocFile::MoveElementTo(WCHAR const *pwcsName, IStorage *pstgParent, OLECHAR const *ptcsNewName, DWORD grfFlags) { SCODE sc; #ifdef MULTIHEAP CSafeMultiHeap smh(_ppc); #endif olLog(("%p::In CExposedDocFile::MoveElementTo(" "%ws, %p, " OLEFMT ", %lu)\n", this, pwcsName, pstgParent, ptcsNewName, grfFlags)); olDebugOut((DEB_TRACE, "In CExposedDocFile::MoveElementTo(" "%ws, %p, " OLEFMT ", %lu)\n", pwcsName, pstgParent, ptcsNewName, grfFlags)); OL_VALIDATE(MoveElementTo(pwcsName, pstgParent, ptcsNewName, grfFlags)); olChk(Validate()); #ifdef ASYNC //ASYNC Note: We don't use the normal pending loop macros here because // we have no safe sem and need to pass a NULL. do { #endif sc = MoveElementWorker(pwcsName, pstgParent, ptcsNewName, grfFlags); #ifdef ASYNC if (!ISPENDINGERROR(sc)) { break; } else { SCODE sc2; sc2 = _cpoint.Notify(sc, _ppc->GetBase(), _ppc, NULL); if (sc2 != S_OK) { return ResultFromScode(sc2); } } } while (TRUE); #endif EH_Err: olLog(("%p::Out CExposedDocFile::MoveElementTo(). ret == %lx\n", this, sc)); return _OLERETURN(sc); } //+-------------------------------------------------------------- // // Member: CExposedDocFile::MoveElementToWorker, public // // Synopsis: Move an element of a DocFile to an IStorage // // Arguments: [pwcsName] - Current name // [ptcsNewName] - New name // // Returns: Appropriate status code // // Algorithm: Open source as storage or stream (whatever works) // Create appropriate destination // Copy source to destination // Set create time of destination equal to create time of source // If appropriate, delete source // // History: 10-Nov-92 AlexT Created // //--------------------------------------------------------------- SCODE CExposedDocFile::MoveElementWorker(WCHAR const *pwcsName, IStorage *pstgParent, OLECHAR const *ptcsNewName, DWORD grfFlags) { IUnknown *punksrc = NULL; SCODE sc; IUnknown *punkdst = NULL; IStorage *pstgsrc; STATSTG statstg; BOOL fCreate = TRUE; // Determine source type sc = GetScode(OpenStorage(pwcsName, NULL, STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE, NULL, NULL, &pstgsrc)); if (SUCCEEDED(sc)) { HRESULT hr; // It's a storage punksrc = pstgsrc; IStorage *pstgdst; olHChkTo(EH_UnkSrc, pstgsrc->Stat(&statstg, STATFLAG_NONAME)); hr = pstgParent->CreateStorage(ptcsNewName, STGM_DIRECT | STGM_WRITE | STGM_SHARE_EXCLUSIVE | STGM_FAILIFTHERE, 0, 0, &pstgdst); if (DfGetScode(hr) == STG_E_FILEALREADYEXISTS && grfFlags == STGMOVE_COPY) { fCreate = FALSE; //If we're opening an existing thing for merging, we need // read and write permissions so we can traverse the tree. hr = pstgParent->OpenStorage(ptcsNewName, NULL, STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &pstgdst); } olHChkTo(EH_UnkSrc, hr); punkdst = pstgdst; sc = DfGetScode(pstgsrc->CopyTo(0, NULL, NULL, pstgdst)); } else if (sc == STG_E_FILENOTFOUND) { // Try opening it as a stream HRESULT hr; IStream *pstmsrc, *pstmdst; olHChk(OpenStream(pwcsName, NULL, STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE, NULL, &pstmsrc)); // It's a stream punksrc = pstmsrc; olHChkTo(EH_UnkSrc, pstmsrc->Stat(&statstg, STATFLAG_NONAME)); hr = pstgParent->CreateStream(ptcsNewName, STGM_DIRECT | STGM_WRITE | STGM_SHARE_EXCLUSIVE | STGM_FAILIFTHERE, 0, 0, &pstmdst); if (DfGetScode(hr) == STG_E_FILEALREADYEXISTS && grfFlags == STGMOVE_COPY) { ULARGE_INTEGER uli; uli.QuadPart = 0; fCreate = FALSE; //Try to open it instead //Note: We do this instead of doing a CreateStream with // STGM_CREATE because CreateStream can open over an already // open stream, which leads to problems when the destination // and the source are the same. olHChkTo(EH_UnkSrc, pstgParent->OpenStream(ptcsNewName, 0, STGM_DIRECT | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, &pstmdst)); sc = pstmdst->SetSize(uli); if (FAILED(sc)) { pstmdst->Release(); olErr(EH_UnkSrc, sc); } } else olHChkTo(EH_UnkSrc, hr); punkdst = pstmdst; ULARGE_INTEGER cb; ULISetLow (cb, 0xffffffff); ULISetHigh(cb, 0xffffffff); sc = DfGetScode(pstmsrc->CopyTo(pstmdst, cb, NULL, NULL)); } else olChk(sc); punkdst->Release(); if (SUCCEEDED(sc)) { // Make destination create time match source create time // Note that we don't really care if this call succeeded. pstgParent->SetElementTimes(ptcsNewName, &statstg.ctime, NULL, NULL); //OK to ignore failure from DestroyElement if ((grfFlags & STGMOVE_COPY) == STGMOVE_MOVE) DestroyElement(pwcsName); } else { // The copy/move failed, so get rid of the partial result. //Only do a delete if the object was newly created. if (fCreate) pstgParent->DestroyElement(ptcsNewName); } olDebugOut((DEB_TRACE, "Out CExposedDocFile::MoveElementTo\n")); // Fall through EH_UnkSrc: if (punksrc) punksrc->Release(); EH_Err: return sc; } //+-------------------------------------------------------------- // // Member: CExposedDocFile::RenameElement, public // // Synopsis: Renames an element of a DocFile // // Arguments: [pwcsName] - Current name // [pwcsNewName] - New name // // Returns: Appropriate status code // // History: 20-Jan-92 DrewB Created // //--------------------------------------------------------------- _OLESTDMETHODIMP CExposedDocFile::RenameElement(WCHAR const *pwcsName, WCHAR const *pwcsNewName) { SCODE sc; SAFE_SEM; SAFE_ACCESS; CDfName dfnOld, dfnNew; olLog(("%p::In CExposedDocFile::RenameElement(%ws, %ws)\n", this, pwcsName, pwcsNewName)); olDebugOut((DEB_TRACE, "In CExposedDocFile::RenameElement(%ws, %ws)\n", pwcsName, pwcsNewName)); OL_VALIDATE(RenameElement(pwcsName, pwcsNewName)); olChk(Validate()); dfnOld.Set(pwcsName); dfnNew.Set(pwcsNewName); BEGIN_PENDING_LOOP; olChk(TakeSafeSem()); SafeWriteAccess(); #ifdef DIRECTWRITERLOCK olChk(ValidateWriteAccess()); #endif sc = _pdf->RenameEntry(&dfnOld, &dfnNew); END_PENDING_LOOP; olDebugOut((DEB_TRACE, "Out CExposedDocFile::RenameElement\n")); EH_Err: olLog(("%p::Out CExposedDocFile::RenameElement(). ret == %lx\n", this, sc)); return _OLERETURN(sc); } //+-------------------------------------------------------------- // // Member: CExposedDocFile::SetElementTimes, public // // Synopsis: Sets element time stamps // // Arguments: [pwcsName] - Name // [pctime] - create time // [patime] - access time // [pmtime] - modify time // // Returns: Appropriate status code // // History: 05-Oct-92 AlexT Created // //--------------------------------------------------------------- _OLESTDMETHODIMP CExposedDocFile::SetElementTimes(WCHAR const *pwcsName, FILETIME const *pctime, FILETIME const *patime, FILETIME const *pmtime) { SCODE sc; SAFE_SEM; SAFE_ACCESS; CDfName dfn; CDfName *pdfn = NULL; FILETIME ctime, atime, mtime; olLog(("%p::In CExposedDocFile::SetElementTimes(%ws, %p, %p, %p)\n", this, pwcsName, pctime, patime, pmtime)); olDebugOut((DEB_TRACE, "In CExposedDocFile::SetElementTimes:%p(" "%ws, %p, %p, %p)\n", this, pwcsName, pctime, patime, pmtime)); OL_VALIDATE(SetElementTimes(pwcsName, pctime, patime, pmtime)); olChk(Validate()); // Probe arguments and make local copies if necessary if (pctime) { ctime = *pctime; pctime = &ctime; } if (patime) { atime = *patime; patime = &atime; } if (pmtime) { mtime = *pmtime; pmtime = &mtime; } if (pwcsName != NULL) { dfn.Set(pwcsName); pdfn = &dfn; } BEGIN_PENDING_LOOP; olChk(TakeSafeSem()); SafeWriteAccess(); #ifdef DIRECTWRITERLOCK olChk(ValidateWriteAccess()); #endif sc = _pdf->SetElementTimes(pdfn, pctime, patime, pmtime); END_PENDING_LOOP; olDebugOut((DEB_TRACE, "Out CExposedDocFile::SetElementTimes\n")); EH_Err: olLog(("%p::Out CExposedDocFile::SetElementTimes(). ret == %lx\n", this, sc)); return _OLERETURN(sc); } //+-------------------------------------------------------------- // // Member: CExposedDocFile::SetClass, public // // Synopsis: Sets storage class // // Arguments: [clsid] - class id // // Returns: Appropriate status code // // History: 05-Oct-92 AlexT Created // //--------------------------------------------------------------- STDMETHODIMP CExposedDocFile::SetClass(REFCLSID rclsid) { SCODE sc; SAFE_SEM; SAFE_ACCESS; CLSID clsid; olLog(("%p::In CExposedDocFile::SetClass(?)\n", this)); olDebugOut((DEB_TRACE, "In CExposedDocFile::SetClass:%p(?)\n", this)); OL_VALIDATE(SetClass(rclsid)); olChk(Validate()); clsid = rclsid; BEGIN_PENDING_LOOP; olChk(TakeSafeSem()); SafeWriteAccess(); #ifdef DIRECTWRITERLOCK olChk(ValidateWriteAccess()); #endif sc = _pdf->SetClass(clsid); END_PENDING_LOOP; olDebugOut((DEB_TRACE, "Out CExposedDocFile::SetClass\n")); EH_Err: olLog(("%p::Out CExposedDocFile::SetClass(). ret == %lx\n", this, sc)); return ResultFromScode(sc); } //+-------------------------------------------------------------- // // Member: CExposedDocFile::SetStateBits, public // // Synopsis: Sets state bits // // Arguments: [grfStateBits] - state bits // [grfMask] - state bits mask // // Returns: Appropriate status code // // History: 05-Oct-92 AlexT Created // //--------------------------------------------------------------- STDMETHODIMP CExposedDocFile::SetStateBits(DWORD grfStateBits, DWORD grfMask) { SCODE sc; SAFE_SEM; SAFE_ACCESS; olLog(("%p::In CExposedDocFile::SetStateBits(%lu, %lu)\n", this, grfStateBits, grfMask)); olDebugOut((DEB_TRACE, "In CExposedDocFile::SetStateBits:%p(" "%lu, %lu)\n", this, grfStateBits, grfMask)); OL_VALIDATE(SetStateBits(grfStateBits, grfMask)); olChk(Validate()); BEGIN_PENDING_LOOP; olChk(TakeSafeSem()); SafeWriteAccess(); #ifdef DIRECTWRITERLOCK olChk(ValidateWriteAccess()); #endif sc = _pdf->SetStateBits(grfStateBits, grfMask); END_PENDING_LOOP; olDebugOut((DEB_TRACE, "Out CExposedDocFile::SetStateBits\n")); EH_Err: olLog(("%p::Out CExposedDocFile::SetStateBits(). ret == %lx\n", this, sc)); return ResultFromScode(sc); } //+-------------------------------------------------------------- // // Member: CExposedDocFile::Stat, public // // Synopsis: Fills in a buffer of information about this object // // Arguments: [pstatstg] - Buffer // // Returns: Appropriate status code // // Modifies: [pstatstg] // // History: 24-Mar-92 DrewB Created // //--------------------------------------------------------------- _OLESTDMETHODIMP CExposedDocFile::Stat(STATSTGW *pstatstg, DWORD grfStatFlag) { SAFE_SEM; SAFE_ACCESS; SCODE sc; STATSTGW stat; olLog(("%p::In CExposedDocFile::Stat(%p)\n", this, pstatstg)); olDebugOut((DEB_TRACE, "In CExposedDocFile::Stat(%p)\n", pstatstg)); OL_VALIDATE(Stat(pstatstg, grfStatFlag)); BEGIN_PENDING_LOOP; olChk(TakeSafeSem()); SafeReadAccess(); sc = _pdf->Stat(&stat, grfStatFlag); END_PENDING_LOOP; if (SUCCEEDED(sc)) { TRY { *pstatstg = stat; pstatstg->type = STGTY_STORAGE; ULISet32(pstatstg->cbSize, 0); pstatstg->grfLocksSupported = 0; pstatstg->STATSTG_dwStgFmt = 0; } CATCH(CException, e) { UNREFERENCED_PARM(e); if (stat.pwcsName) TaskMemFree(stat.pwcsName); } END_CATCH } olDebugOut((DEB_TRACE, "Out CExposedDocFile::Stat\n")); EH_Err: olLog(("%p::Out CExposedDocFile::Stat(). *pstatstg == %p ret == %lx\n", this, *pstatstg, sc)); return _OLERETURN(sc); } //+-------------------------------------------------------------- // // Member: CExposedDocFile::AddRef, public // // Synopsis: Increments the ref count // // Returns: Appropriate status code // // History: 16-Mar-92 DrewB Created // //--------------------------------------------------------------- STDMETHODIMP_(ULONG) CExposedDocFile::AddRef(void) { ULONG ulRet; olLog(("%p::In CExposedDocFile::AddRef()\n", this)); olDebugOut((DEB_TRACE, "In CExposedDocFile::AddRef()\n")); if (FAILED(Validate())) return 0; InterlockedIncrement(&_cReferences); ulRet = _cReferences; olDebugOut((DEB_TRACE, "Out CExposedDocFile::AddRef %p()=> %lu\n", this, _cReferences)); olLog(("%p::Out CExposedDocFile::AddRef(). ret == %lu\n", this, ulRet)); return ulRet; } //+-------------------------------------------------------------- // // Member: CExposedDocFile::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 CExposedDocFile::QueryInterface(REFIID iid, void **ppvObj) { SCODE sc; #ifdef MULTIHEAP CSafeMultiHeap smh(_ppc); #endif olLog(("%p::In CExposedDocFile::QueryInterface(?, %p)\n", this, ppvObj)); olDebugOut((DEB_TRACE, "In CExposedDocFile::QueryInterface(?, %p)\n", ppvObj)); OL_VALIDATE(QueryInterface(iid, ppvObj)); olChk(Validate()); olChk(_pdf->CheckReverted()); sc = S_OK; if (IsEqualIID(iid, IID_IStorage) || IsEqualIID(iid, IID_IUnknown)) { *ppvObj = (IStorage *)this; CExposedDocFile::AddRef(); } else if (IsEqualIID(iid, IID_IMarshal)) { if (P_PRIORITY(_pdf->GetDFlags()) && _pdf->IsRoot()) olErr(EH_Err, E_NOINTERFACE); //If the ILockBytes we'd need to marshal doesn't support IMarshal // then we want to do standard marshalling on the storage, mostly // to prevent deadlock problems but also because you'll get better // performance. So check, then do the right thing. IMarshal *pim; ILockBytes *plkb; plkb = _ppc->GetOriginal(); if (plkb == NULL) { plkb = _ppc->GetBase(); } sc = plkb->QueryInterface(IID_IMarshal, (void **)&pim); if (FAILED(sc)) { olErr(EH_Err, E_NOINTERFACE); } pim->Release(); #ifdef MULTIHEAP if (_ppc->GetHeapBase() == NULL) olErr (EH_Err, E_NOINTERFACE); #endif *ppvObj = (IMarshal *)this; CExposedDocFile::AddRef(); } else if (IsEqualIID(iid, IID_IRootStorage)) { #ifdef COORD if ((!_pdf->IsRoot()) && (!_pdf->IsCoord())) #else if (!_pdf->IsRoot()) #endif olErr(EH_Err, E_NOINTERFACE); *ppvObj = (IRootStorage *)this; CExposedDocFile::AddRef(); } #ifdef NEWPROPS else if (IsEqualIID(iid, IID_IPropertySetStorage)) { *ppvObj = (IPropertySetStorage *)this; CExposedDocFile::AddRef(); } #endif #ifdef ASYNC else if (IsEqualIID(iid, IID_IConnectionPointContainer) && _cpoint.IsInitialized()) { *ppvObj = (IConnectionPointContainer *)this; CExposedDocFile::AddRef(); } #endif #if WIN32 >= 300 else if (_pdf->IsRoot() && IsEqualIID(iid, IID_IAccessControl)) { ILockBytes *piLB = _pdf->GetBaseMS()->GetILB(); olAssert((piLB != NULL)); SCODE scode = S_OK; if (_pIAC == NULL) // use existing _pIAC if available scode = piLB->QueryInterface(IID_IAccessControl,(void **)&_pIAC); if (SUCCEEDED(scode)) { *ppvObj = (IAccessControl *)this; CExposedDocFile::AddRef(); } else sc = E_NOINTERFACE; } #endif #ifdef DIRECTWRITERLOCK else if (_pdf->IsRoot() && IsEqualIID(iid, IID_IDirectWriterLock) && _pdfb->DirectWriterMode()) { *ppvObj = (IDirectWriterLock *) this; CExposedDocFile::AddRef(); } #endif // DIRECTWRITERLOCK else if( IsEqualIID( iid, IID_IPropertyBagEx )) { *ppvObj = static_cast(&_PropertyBagEx); CExposedDocFile::AddRef(); } else if( IsEqualIID( iid, IID_IPropertyBag )) { *ppvObj = static_cast(&_PropertyBagEx); CExposedDocFile::AddRef(); } else sc = E_NOINTERFACE; olDebugOut((DEB_TRACE, "Out CExposedDocFile::QueryInterface => %p\n", *ppvObj)); EH_Err: olLog(("%p::Out CExposedDocFile::QueryInterface(). " "*ppvObj == %p ret == %lx\n", this, *ppvObj, sc)); return ResultFromScode(sc); } //+-------------------------------------------------------------- // // Method: CExposedDocFile::CopySStreamToIStream, private // // Synopsis: Copies a PSStream to an IStream // // Arguments: [psstFrom] - SStream // [pstTo] - IStream // // Returns: Appropriate status code // // History: 07-May-92 DrewB Created // 26-Jun-92 AlexT Moved to CExposedDocFile // so we can call SetReadAccess // //--------------------------------------------------------------- SCODE CExposedDocFile::CopySStreamToIStream(PSStream *psstFrom, IStream *pstTo) { BYTE *pbBuffer; SCODE sc; #ifdef LARGE_STREAMS ULONGLONG cbPos; ULONG cbRead, cbWritten; #else ULONG cbRead, cbWritten, cbPos, cbSizeLow; #endif ULONG ulBufferSize; ULARGE_INTEGER cbSize; cbSize.QuadPart = 0; ulBufferSize = (_pdfb->GetOpenFlags() & DF_LARGE) ? LARGESTREAMBUFFERSIZE : STREAMBUFFERSIZE; // This is part of CopyTo and therefore we are allowed to // fail with out-of-memory olChk(GetBuffer(STREAMBUFFERSIZE, ulBufferSize, &pbBuffer, &ulBufferSize)); // Set destination size for contiguity SetReadAccess(); #ifdef LARGE_STREAMS psstFrom->GetSize(&cbSize.QuadPart); #else psstFrom->GetSize(&cbSize.LowPart); cbSize.HighPart = 0; #endif ClearReadAccess(); // Don't need to SetReadAccess here because pstTo is an IStream olHChk(pstTo->SetSize(cbSize)); // Copy between streams cbPos = 0; for (;;) { SetReadAccess(); olChk(psstFrom->ReadAt(cbPos, pbBuffer, ulBufferSize, (ULONG STACKBASED *)&cbRead)); ClearReadAccess(); if (cbRead == 0) // EOF break; // Don't need to SetReadAccess here because pstTo is an IStream olHChk(pstTo->Write(pbBuffer, cbRead, &cbWritten)); if (cbRead != cbWritten) olErr(EH_Err, STG_E_WRITEFAULT); cbPos += cbWritten; } sc = S_OK; EH_Err: DfMemFree(pbBuffer); return sc; } //+-------------------------------------------------------------- // // Method: CExposedDocFile::CopyDocFileToIStorage, private // // Synopsis: Copies a docfile's contents to an IStorage // // Arguments: [pdfFrom] - From // [pstgTo] - To // [snbExclude] - Names to not copy // [dwCopyFlags] - Bitwise flags for types of objects to copy // // Returns: Appropriate status code // // History: 07-May-92 DrewB Created // 26-Jun-92 AlexT Moved to CExposedDocFile // so we can call SetReadAccess // //--------------------------------------------------------------- // Variables used by CopyDocFileToIStorage that we // want to allocate dynamically rather than eating stack space struct SCopyVars : public CLocalAlloc { PSStream *psstFrom; IStream *pstTo; PDocFile *pdfFromChild; IStorage *pstgToChild; DWORD grfStateBits; CLSID clsid; CDfName dfnKey; SIterBuffer ib; OLECHAR atcName[CWCSTORAGENAME]; }; SCODE CExposedDocFile::CopyDocFileToIStorage(PDocFile *pdfFrom, IStorage *pstgTo, SNBW snbExclude, DWORD dwCopyFlags) { SCODE sc; SCopyVars *pcv = NULL; olDebugOut((DEB_ITRACE, "In CopyDocFileToIStorage:%p(%p, %p, %p, %lX)\n", this, pdfFrom, pstgTo, snbExclude, dwCopyFlags)); // Allocate variables dynamically to conserve stack space since // this is a recursive call olMem(pcv = new SCopyVars); SetReadAccess(); sc = pdfFrom->GetClass(&pcv->clsid); ClearReadAccess(); olChk(sc); // Assume STG_E_INVALIDFUNCTION means that the destination storage // doesn't support class IDs sc = GetScode(pstgTo->SetClass(pcv->clsid)); if (FAILED(sc) && sc != STG_E_INVALIDFUNCTION) olErr(EH_Err, sc); SetReadAccess(); sc = pdfFrom->GetStateBits(&pcv->grfStateBits); ClearReadAccess(); olChk(sc); sc = GetScode(pstgTo->SetStateBits(pcv->grfStateBits, 0xffffffff)); if (FAILED(sc) && sc != STG_E_INVALIDFUNCTION) olErr(EH_Err, sc); for (;;) { SetReadAccess(); sc = pdfFrom->FindGreaterEntry(&pcv->dfnKey, &pcv->ib, NULL); ClearReadAccess(); if (sc == STG_E_NOMOREFILES) break; else if (FAILED(sc)) olErr(EH_pdfi, sc); pcv->dfnKey.Set(&pcv->ib.dfnName); if (snbExclude && NameInSNB(&pcv->ib.dfnName, snbExclude) == S_OK) continue; if ((pcv->ib.type == STGTY_STORAGE && (dwCopyFlags & COPY_STORAGES) == 0) || (pcv->ib.type == STGTY_STREAM && (dwCopyFlags & COPY_STREAMS) == 0)) continue; switch(pcv->ib.type) { case STGTY_STORAGE: // Embedded DocFile, create destination and recurse SetReadAccess(); sc = pdfFrom->GetDocFile(&pcv->ib.dfnName, DF_READ, pcv->ib.type, &pcv->pdfFromChild); ClearReadAccess(); olChkTo(EH_pdfi, sc); // Not optimally efficient, but reduces #ifdef's StringCbCopyW (pcv->atcName, sizeof(pcv->atcName), (WCHAR *)pcv->ib.dfnName.GetBuffer()); // Don't need to SetReadAccess here because pstgTo is an IStorage. #ifdef MULTIHEAP { CSafeMultiHeap smh(_ppc); // if pstgTo is an IStorage proxy, then returned IStorage // can be custom marshaled and allocator state is lost #endif sc = DfGetScode(pstgTo->CreateStorage(pcv->atcName, STGM_WRITE | STGM_SHARE_EXCLUSIVE | STGM_FAILIFTHERE, 0, 0, &pcv->pstgToChild)); if (sc == STG_E_FILEALREADYEXISTS) //We need read and write permissions so we can traverse // the destination IStorage olHChkTo(EH_Get, pstgTo->OpenStorage(pcv->atcName, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &pcv->pstgToChild)); else if (FAILED(sc)) olErr(EH_Get, sc); #ifdef MULTIHEAP } #endif olChkTo(EH_Create, CopyDocFileToIStorage(pcv->pdfFromChild, pcv->pstgToChild, NULL, dwCopyFlags)); pcv->pdfFromChild->Release(); pcv->pstgToChild->Release(); break; case STGTY_STREAM: SetReadAccess(); sc = pdfFrom->GetStream(&pcv->ib.dfnName, DF_READ, pcv->ib.type, &pcv->psstFrom); ClearReadAccess(); olChkTo(EH_pdfi, sc); // Not optimally efficient, but reduces #ifdef's StringCbCopyW (pcv->atcName, sizeof(pcv->atcName), (WCHAR *)pcv->ib.dfnName.GetBuffer()); // Don't need to SetReadAccess here because pstgTo is an IStorage. #ifdef MULTIHEAP { CSafeMultiHeap smh(_ppc); // if pstgTo is an IStorage proxy, then returned IStream // can be custom marshaled and allocator state is lost #endif olHChkTo(EH_Get, pstgTo->CreateStream(pcv->atcName, STGM_WRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, 0, &pcv->pstTo)); #ifdef MULTIHEAP } #endif olChkTo(EH_Create, CopySStreamToIStream(pcv->psstFrom, pcv->pstTo)); pcv->psstFrom->Release(); pcv->pstTo->Release(); break; default: olAssert(!aMsg("Unknown type in CopyDocFileToIStorage")); break; } } olDebugOut((DEB_ITRACE, "Out CopyDocFileToIStorage\n")); sc = S_OK; EH_pdfi: EH_Err: delete pcv; return sc; EH_Create: if (pcv->ib.type == STGTY_STORAGE) pcv->pstgToChild->Release(); else pcv->pstTo->Release(); olVerSucc(pstgTo->DestroyElement(pcv->atcName)); EH_Get: if (pcv->ib.type == STGTY_STORAGE) pcv->pdfFromChild->Release(); else pcv->psstFrom->Release(); goto EH_Err; } //+-------------------------------------------------------------- // // Member: CExposedDocFile::Unmarshal, public // // Synopsis: Creates a duplicate DocFile from parts // // Arguments: [pstm] - Marshal stream // [ppv] - Object return // [mshlflags] - Marshal flags // // Returns: Appropriate status code // // Modifies: [ppv] // // History: 26-Feb-92 DrewB Created // //--------------------------------------------------------------- SCODE CExposedDocFile::Unmarshal(IStream *pstm, void **ppv, DWORD mshlflags) { SCODE sc; CDfMutex mtx; CPerContext *ppc; CPubDocFile *pdf; CGlobalContext *pgc; CDFBasis *pdfb; CExposedDocFile *pedf; IStorage *pstgStd = NULL; ULONG_PTR df; #ifdef ASYNC DWORD dwAsyncFlags; IDocfileAsyncConnectionPoint *pdacp; #endif #ifdef POINTER_IDENTITY CMarshalList *pml; #endif olDebugOut((DEB_ITRACE, "In CExposedDocFile::Unmarshal(%p, %p)\n", pstm, ppv)); #ifdef MULTIHEAP void *pvBaseOld; void *pvBaseNew; ContextId cntxid; CPerContext pcSharedMemory (NULL); // bootstrap object #endif //First unmarshal the standard marshalled version sc = CoUnmarshalInterface(pstm, IID_IStorage, (void**)&pstgStd); if (FAILED(sc)) { // assume that entire standard marshaling stream has been read olAssert (pstgStd == NULL); sc = S_OK; } #ifdef MULTIHEAP sc = UnmarshalSharedMemory(pstm, mshlflags, &pcSharedMemory, &cntxid); if (!SUCCEEDED(sc)) { #ifdef POINTER_IDENTITY UnmarshalPointer(pstm, (void **) &pedf); #endif UnmarshalPointer(pstm, (void **)&pdf); UnmarshalPointer(pstm, (void **)&pdfb); UnmarshalPointer(pstm, (void **)&df); #ifdef ASYNC ReleaseContext(pstm, TRUE, P_INDEPENDENT(df) != 0, mshlflags); ReleaseConnection(pstm, mshlflags); #else ReleaseContext(pstm, P_INDEPENDENT(df), mshlflags); #endif olChkTo(EH_std, sc); } pvBaseOld = DFBASEPTR; #endif #ifdef POINTER_IDENTITY olChkTo(EH_mem, UnmarshalPointer(pstm, (void **) &pedf)); #endif olChkTo(EH_mem, UnmarshalPointer(pstm, (void **)&pdf)); olChkTo(EH_mem, CPubDocFile::Validate(pdf)); olChkTo(EH_pdf, UnmarshalPointer(pstm, (void **)&pdfb)); olChkTo(EH_pdfb, UnmarshalPointer(pstm, (void **) &df)); olChkTo(EH_pdfb, UnmarshalPointer(pstm, (void **)&pgc)); olChkTo(EH_pgc, ValidateBuffer(pgc, sizeof(CGlobalContext))); //So far, nothing has called into the tree so we don't really need // to be holding the tree mutex. The UnmarshalContext call does // call into the tree, though, so we need to make sure this is // threadsafe. We'll do this my getting the mutex name from the // CGlobalContext, then creating a new CDfMutex object. While // this is obviously not optimal, since it's possible we could // reuse an existing CDfMutex, the reuse strategy isn't threadsafe // since we can't do a lookup without the possibility of the thing // we're looking for being released by another thread. TCHAR atcMutexName[CONTEXT_MUTEX_NAME_LENGTH]; pgc->GetMutexName(atcMutexName); olChkTo(EH_pgc, mtx.Init(atcMutexName)); olChkTo(EH_pgc, mtx.Take(INFINITE)); //At this point we're holding the mutex. #ifdef MULTIHEAP #ifdef ASYNC olChkTo(EH_mtx, UnmarshalContext(pstm, pgc, &ppc, mshlflags, TRUE, P_INDEPENDENT(pdf->GetDFlags()), cntxid, pdf->IsRoot())); #else olChkTo(EH_mtx, UnmarshalContext(pstm, pgc, &ppc, mshlflags, P_INDEPENDENT(pdf->GetDFlags()), cntxid, pdf->IsRoot())); #endif if ((pvBaseNew = DFBASEPTR) != pvBaseOld) { pdf = (CPubDocFile*) ((ULONG_PTR)pdf - (ULONG_PTR)pvBaseOld + (ULONG_PTR)pvBaseNew); pedf = (CExposedDocFile*) ((ULONG_PTR)pedf - (ULONG_PTR)pvBaseOld + (ULONG_PTR)pvBaseNew); pdfb = (CDFBasis*) ((ULONG_PTR)pdfb - (ULONG_PTR)pvBaseOld + (ULONG_PTR)pvBaseNew); } #else #ifdef ASYNC olChkTo(EH_mtx, UnmarshalContext(pstm, pgc, &ppc, mshlflags, TRUE, P_INDEPENDENT(pdf->GetDFlags()), pdf->IsRoot())); #else olChkTo(EH_mtx, UnmarshalContext(pstm, pgc, &ppc, mshlflags, P_INDEPENDENT(pdf->GetDFlags()), pdf->IsRoot())); #endif //ASYNC #endif #ifdef ASYNC olChkTo(EH_mtx, UnmarshalConnection(pstm, &dwAsyncFlags, &pdacp, mshlflags)); #endif // if we use up 1Gig of address space, use standard unmarshaling if (gs_iSharedHeaps > (DOCFILE_SM_LIMIT / DOCFILE_SM_SIZE)) olErr (EH_ppc, STG_E_INSUFFICIENTMEMORY); #ifdef POINTER_IDENTITY olAssert (pedf != NULL); pml = (CMarshalList *) pedf; // Warning: these checks must remain valid across processes if (SUCCEEDED(pedf->Validate()) && pedf->GetPub() == pdf) { pedf = (CExposedDocFile *) pml->FindMarshal(GetCurrentContextId()); } else { pml = NULL; pedf = NULL; } // exposed object is not found or has been deleted if (pedf == NULL) { #endif olMemTo(EH_ppc, pedf = new (pdfb->GetMalloc()) CExposedDocFile(pdf, pdfb, ppc)); olChkTo(EH_exp, pedf->InitMarshal(dwAsyncFlags, pdacp)); //InitMarshal adds a reference. if (pdacp) pdacp->Release(); #ifdef POINTER_IDENTITY if (pml) pml->AddMarshal(pedf); pdf->vAddRef(); // CExposedDocFile ctor does not AddRef } else { pdfb->SetAccess(ppc); pedf->AddRef(); // reuse this object ppc->Release(); // reuse percontext } #else pdf->vAddRef(); #endif *ppv = (void *)pedf; #ifdef MULTIHEAP if (pvBaseOld != pvBaseNew) { pcSharedMemory.SetThreadAllocatorState(NULL); g_smAllocator.Uninit(); // delete the extra mapping } g_smAllocator.SetState(NULL, NULL, 0, NULL, NULL); #endif mtx.Release(); //We're returning the custom marshalled version, so we don't need //the std marshalled one anymore. if (pstgStd != NULL) pstgStd->Release(); olDebugOut((DEB_ITRACE, "Out CExposedDocFile::Unmarshal => %p\n", *ppv)); return S_OK; EH_exp: pedf->Release(); goto EH_Err; EH_ppc: ppc->Release(); EH_mtx: mtx.Release(); goto EH_Err; EH_pgc: CoReleaseMarshalData(pstm); // release the ILockBytes CoReleaseMarshalData(pstm); // release the ILockBytes if (P_INDEPENDENT(pdf->GetDFlags())) CoReleaseMarshalData(pstm); // release the ILockBytes #ifdef ASYNC ReleaseConnection(pstm, mshlflags); #endif EH_pdfb: EH_pdf: EH_mem: EH_Err: #ifdef MULTIHEAP pcSharedMemory.SetThreadAllocatorState(NULL); g_smAllocator.Uninit(); // delete the file mapping in error case g_smAllocator.SetState(NULL, NULL, 0, NULL, NULL); #endif EH_std: if (pstgStd != NULL) { //We can return the standard marshalled version and still succeed. *ppv = pstgStd; return S_OK; } return sc; } //+-------------------------------------------------------------- // // Member: CExposedDocFile::GetUnmarshalClass, public // // Synopsis: Returns the class ID // // Arguments: [riid] - IID of object // [pv] - Unreferenced // [dwDestContext] - Unreferenced // [pvDestContext] - Unreferenced // [mshlflags] - Unreferenced // [pcid] - CLSID return // // Returns: Appropriate status code // // Modifies: [pcid] // // History: 04-May-92 DrewB Created // //--------------------------------------------------------------- STDMETHODIMP CExposedDocFile::GetUnmarshalClass(REFIID riid, void *pv, DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags, LPCLSID pcid) { SCODE sc; #ifdef MULTIHEAP CSafeMultiHeap smh(_ppc); #endif olLog(("%p::In CExposedDocFile::GetUnmarshalClass(" "riid, %p, %lu, %p, %lu, %p)\n", this, pv, dwDestContext, pvDestContext, mshlflags, pcid)); olDebugOut((DEB_TRACE, "In CExposedDocFile::GetUnmarshalClass:%p(" "riid, %p, %lu, %p, %lu, %p)\n", this, pv, dwDestContext, pvDestContext, mshlflags, pcid)); UNREFERENCED_PARM(pv); UNREFERENCED_PARM(mshlflags); olChk(ValidateOutBuffer(pcid, sizeof(CLSID))); memset(pcid, 0, sizeof(CLSID)); olChk(ValidateIid(riid)); olChk(Validate()); olChk(_pdf->CheckReverted()); if ((dwDestContext != MSHCTX_LOCAL) && (dwDestContext != MSHCTX_INPROC)) { IMarshal *pmsh; if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv, dwDestContext, pvDestContext, mshlflags, &pmsh))) { sc = GetScode(pmsh->GetUnmarshalClass(riid, pv, dwDestContext, pvDestContext, mshlflags, pcid)); pmsh->Release(); } } else if (pvDestContext != NULL) { sc = STG_E_INVALIDPARAMETER; } else { olChk(VerifyIid(riid, IID_IStorage)); *pcid = CLSID_DfMarshal; } olDebugOut((DEB_TRACE, "Out CExposedDocFile::GetUnmarshalClass\n")); EH_Err: olLog(("%p::Out CExposedDocFile::GetUnmarshalClass(). ret = %lx\n", this, sc)); return ResultFromScode(sc); } //+-------------------------------------------------------------- // // Member: CExposedDocFile::GetMarshalSizeMax, public // // Synopsis: Returns the size needed for the marshal buffer // // Arguments: [riid] - IID of object being marshaled // [pv] - Unreferenced // [dwDestContext] - Unreferenced // [pvDestContext] - Unreferenced // [mshlflags] - Unreferenced // [pcbSize] - Size return // // Returns: Appropriate status code // // Modifies: [pcbSize] // // History: 04-May-92 DrewB Created // //--------------------------------------------------------------- STDMETHODIMP CExposedDocFile::GetMarshalSizeMax(REFIID riid, void *pv, DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags, LPDWORD pcbSize) { SCODE sc; #ifdef MULTIHEAP CSafeMultiHeap smh(_ppc); #endif UNREFERENCED_PARM(pv); olLog(("%p::In CExposedDocFile::GetMarshalSizeMax(" "riid, %p, %lu, %p, %lu, %p)\n", this, pv, dwDestContext, pvDestContext, mshlflags, pcbSize)); olDebugOut((DEB_TRACE, "In CExposedDocFile::GetMarshalSizeMax:%p(" "riid, %p, %lu, %p, %lu, %p)\n", this, pv, dwDestContext, pvDestContext, mshlflags, pcbSize)); olChk(Validate()); olChk(_pdf->CheckReverted()); if ((dwDestContext != MSHCTX_LOCAL) && (dwDestContext != MSHCTX_INPROC)) { IMarshal *pmsh; if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv, dwDestContext, pvDestContext, mshlflags, &pmsh))) { sc = GetScode(pmsh->GetMarshalSizeMax(riid, pv, dwDestContext, pvDestContext, mshlflags, pcbSize)); pmsh->Release(); } } else if (pvDestContext != NULL) { sc = STG_E_INVALIDPARAMETER; } else { sc = GetStdMarshalSize(riid, IID_IStorage, dwDestContext, pvDestContext, mshlflags, pcbSize, sizeof(CPubDocFile *)+sizeof(CDFBasis *)+ sizeof(DFLAGS), #ifdef ASYNC &_cpoint, TRUE, #endif _ppc, P_INDEPENDENT(_pdf->GetDFlags())); DWORD cbSize = 0; IMarshal *pmsh; if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv, dwDestContext, pvDestContext, mshlflags, &pmsh))) { sc = GetScode(pmsh->GetMarshalSizeMax(riid, pv, dwDestContext, pvDestContext, mshlflags, &cbSize)); pmsh->Release(); *pcbSize += cbSize; } } olDebugOut((DEB_TRACE, "Out CExposedDocFile::GetMarshalSizeMax\n")); EH_Err: olLog(("%p::Out CExposedDocFile::GetMarshalSizeMax()." "*pcbSize == %lu, ret == %lx\n", this, *pcbSize, sc)); return ResultFromScode(sc); } //+-------------------------------------------------------------- // // Member: CExposedDocFile::MarshalInterface, public // // Synopsis: Marshals a given object // // Arguments: [pstStm] - Stream to write marshal data into // [riid] - Interface to marshal // [pv] - Unreferenced // [dwDestContext] - Unreferenced // [pvDestContext] - Unreferenced // [mshlflags] - Unreferenced // // Returns: Appropriate status code // // History: 04-May-92 DrewB Created // //--------------------------------------------------------------- STDMETHODIMP CExposedDocFile::MarshalInterface(IStream *pstStm, REFIID riid, void *pv, DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags) { SCODE sc; #ifdef MULTIHEAP CSafeMultiHeap smh(_ppc); #endif olLog(("%p::In CExposedDocFile::MarshalInterface(" "%p, riid, %p, %lu, %p, %lu). Context == %lX\n", this, pstStm, pv, dwDestContext, pvDestContext, mshlflags,(ULONG)GetCurrentContextId())); olDebugOut((DEB_TRACE, "In CExposedDocFile::MarshalInterface:%p(" "%p, riid, %p, %lu, %p, %lu)\n", this, pstStm, pv, dwDestContext, pvDestContext, mshlflags)); UNREFERENCED_PARM(pv); olChk(Validate()); olChk(_pdf->CheckReverted()); if ((dwDestContext != MSHCTX_LOCAL) && (dwDestContext != MSHCTX_INPROC)) { IMarshal *pmsh; if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv, dwDestContext, pvDestContext, mshlflags, &pmsh))) { sc = GetScode(pmsh->MarshalInterface(pstStm, riid, pv, dwDestContext, pvDestContext, mshlflags)); pmsh->Release(); } } else if (pvDestContext != NULL) { sc = STG_E_INVALIDPARAMETER; } else { olChk(StartMarshal(pstStm, riid, IID_IStorage, mshlflags)); //Always standard marshal, in case we get an error during //unmarshalling of the custom stuff. { IMarshal *pmsh; if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv, dwDestContext, pvDestContext, mshlflags, &pmsh))) { sc = GetScode(pmsh->MarshalInterface(pstStm, riid, pv, dwDestContext, pvDestContext, mshlflags)); pmsh->Release(); } olChk(sc); } #ifdef MULTIHEAP olChk(MarshalSharedMemory(pstStm, _ppc)); #endif #ifdef POINTER_IDENTITY olChk(MarshalPointer(pstStm, (CExposedDocFile*) GetNextMarshal())); #endif olChk(MarshalPointer(pstStm, BP_TO_P(CPubDocFile *, _pdf))); olChk(MarshalPointer(pstStm, BP_TO_P(CDFBasis *, _pdfb))); olChk(MarshalPointer(pstStm, (void *) LongToPtr(_pdf->GetDFlags()) )); #ifdef ASYNC olChk(MarshalContext(pstStm, _ppc, dwDestContext, pvDestContext, mshlflags, TRUE, P_INDEPENDENT(_pdf->GetDFlags()))); sc = MarshalConnection(pstStm, &_cpoint, dwDestContext, pvDestContext, mshlflags); #else olChk(MarshalContext(pstStm, _ppc, dwDestContext, pvDestContext, mshlflags, P_INDEPENDENT(_pdf->GetDFlags()))); #endif } olDebugOut((DEB_TRACE, "Out CExposedDocFile::MarshalInterface\n")); EH_Err: olLog(("%p::Out CExposedDocFile::MarshalInterface(). ret == %lx\n", this, sc)); return ResultFromScode(sc); } //+-------------------------------------------------------------- // // Member: CExposedDocFile::UnmarshalInterface, public // // Synopsis: Non-functional // // Arguments: [pstStm] - // [riid] - // [ppvObj] - // // Returns: Appropriate status code // // Modifies: [ppvObj] // // History: 04-May-92 DrewB Created // //--------------------------------------------------------------- STDMETHODIMP CExposedDocFile::UnmarshalInterface(IStream *pstStm, REFIID riid, void **ppvObj) { olLog(("%p::INVALID CALL TO CExposedDocFile::UnmarshalInterface()\n", this)); return ResultFromScode(STG_E_INVALIDFUNCTION); } //+-------------------------------------------------------------- // // Member: CExposedDocFile::StaticReleaseMarshalData, public static // // Synopsis: Releases any references held in marshal data // // Arguments: [pstStm] - Marshal data stream // // Returns: Appropriate status code // // History: 02-Feb-94 DrewB Created // // Notes: Assumes standard marshal header has already been read // //--------------------------------------------------------------- SCODE CExposedDocFile::StaticReleaseMarshalData(IStream *pstStm, DWORD mshlflags) { SCODE sc; CPubDocFile *pdf; CDFBasis *pdfb; ULONG_PTR df; #ifdef POINTER_IDENTITY CExposedDocFile *pedf; #endif olDebugOut((DEB_ITRACE, "In CExposedDocFile::StaticReleaseMarshalData:(" "%p, %lX)\n", pstStm, mshlflags)); //First unmarshal the standard marshalled version olChk(CoReleaseMarshalData(pstStm)); // The final release of the exposed object may have shut down the // shared memory heap, so do not access shared memory after this point //Then do the rest of it. #ifdef MULTIHEAP olChk(SkipSharedMemory(pstStm, mshlflags)); #endif #ifdef POINTER_IDENTITY olChk(UnmarshalPointer(pstStm, (void **) &pedf)); #endif olChk(UnmarshalPointer(pstStm, (void **)&pdf)); olChk(UnmarshalPointer(pstStm, (void **)&pdfb)); olChk(UnmarshalPointer(pstStm, (void **)&df)); #ifdef ASYNC olChk(ReleaseContext(pstStm, TRUE, P_INDEPENDENT(df) != 0, mshlflags)); olChk(ReleaseConnection(pstStm, mshlflags)); #else olChk(ReleaseContext(pstStm, P_INDEPENDENT(df), mshlflags)); #endif #ifdef MULTIHEAP g_smAllocator.SetState(NULL, NULL, 0, NULL, NULL); #endif olDebugOut((DEB_ITRACE, "Out CExposedDocFile::StaticReleaseMarshalData\n")); EH_Err: return sc; } //+-------------------------------------------------------------- // // Member: CExposedDocFile::ReleaseMarshalData, public // // Synopsis: Non-functional // // Arguments: [pstStm] - // // Returns: Appropriate status code // // History: 18-Sep-92 DrewB Created // //--------------------------------------------------------------- STDMETHODIMP CExposedDocFile::ReleaseMarshalData(IStream *pstStm) { SCODE sc; DWORD mshlflags; IID iid; #ifdef MULTIHEAP CSafeMultiHeap smh(_ppc); #endif olLog(("%p::In CExposedDocFile::ReleaseMarshalData(%p)\n", this, pstStm)); olDebugOut((DEB_TRACE, "In CExposedDocFile::ReleaseMarshalData:%p(%p)\n", this, pstStm)); olChk(Validate()); olChk(_pdf->CheckReverted()); olChk(SkipStdMarshal(pstStm, &iid, &mshlflags)); olAssert(IsEqualIID(iid, IID_IStorage)); sc = StaticReleaseMarshalData(pstStm, mshlflags); olDebugOut((DEB_TRACE, "Out CExposedDocFile::ReleaseMarshalData\n")); EH_Err: olLog(("%p::Out CExposedDocFile::ReleaseMarshalData(). ret == %lx\n", this, sc)); return ResultFromScode(sc); } //+-------------------------------------------------------------- // // Member: CExposedDocFile::DisconnectObject, public // // Synopsis: Non-functional // // Arguments: [dwRevserved] - // // Returns: Appropriate status code // // History: 18-Sep-92 DrewB Created // //--------------------------------------------------------------- STDMETHODIMP CExposedDocFile::DisconnectObject(DWORD dwReserved) { olLog(("%p::INVALID CALL TO CExposedDocFile::DisconnectObject()\n", this)); return ResultFromScode(STG_E_INVALIDFUNCTION); } //+--------------------------------------------------------------------------- // // Member: CExposedDocFile::SwitchToFile, public // // Synopsis: Switches the underlying file to another file // // Arguments: [ptcsFile] - New file name // // Returns: Appropriate status code // // History: 08-Jan-93 DrewB Created // //---------------------------------------------------------------------------- STDMETHODIMP CExposedDocFile::SwitchToFile(OLECHAR *ptcsFile) { ULONG ulOpenLock; SCODE sc; SAFE_SEM; SAFE_ACCESS; olLog(("%p::In CExposedDocFile::SwitchToFile(" OLEFMT ")\n", this, ptcsFile)); olDebugOut((DEB_TRACE, "In CExposedDocFile::SwitchToFile:" "%p(" OLEFMT ")\n", this, ptcsFile)); olChk(ValidateNameW(ptcsFile, _MAX_PATH)); olChk(Validate()); olChk(TakeSafeSem()); olChk(_pdf->CheckReverted()); #ifdef COORD olAssert(_pdf->IsRoot() || _pdf->IsCoord()); #else olAssert(_pdf->IsRoot()); #endif SafeReadAccess(); ulOpenLock = _ppc->GetOpenLock(); #ifdef COORD sc = _pdf->GetRoot()->SwitchToFile(ptcsFile, _ppc->GetOriginal(), &ulOpenLock); #else sc = ((CRootPubDocFile *)(CPubDocFile*)_pdf)->SwitchToFile(ptcsFile, _ppc->GetOriginal(), &ulOpenLock); #endif _ppc->SetOpenLock(ulOpenLock); olDebugOut((DEB_TRACE, "Out CExposedDocFile::SwitchToFile\n")); EH_Err: olLog(("%p::Out CExposedDocFile::SwitchToFile(). ret == %lx\n", this, sc)); return ResultFromScode(sc); } #if WIN32 >= 300 // IAccessControl methods STDMETHODIMP CExposedDocFile::GrantAccessRights(ULONG cCount, ACCESS_REQUEST pAccessRequestList[]) { olAssert((_pIAC != NULL)); return _pIAC->GrantAccessRights(cCount, pAccessRequestList); } STDMETHODIMP CExposedDocFile::SetAccessRights(ULONG cCount, ACCESS_REQUEST pAccessRequestList[]) { olAssert((_pIAC != NULL)); return _pIAC->SetAccessRights(cCount, pAccessRequestList); } STDMETHODIMP CExposedDocFile::ReplaceAllAccessRights(ULONG cCount, ACCESS_REQUEST pAccessRequestList[]) { olAssert((_pIAC != NULL)); return _pIAC->ReplaceAllAccessRights(cCount, pAccessRequestList); } STDMETHODIMP CExposedDocFile::DenyAccessRights(ULONG cCount, ACCESS_REQUEST pAccessRequestList[]) { olAssert((_pIAC != NULL)); return _pIAC->DenyAccessRights(cCount, pAccessRequestList); } STDMETHODIMP CExposedDocFile::RevokeExplicitAccessRights(ULONG cCount, TRUSTEE pTrustee[]) { olAssert((_pIAC != NULL)); return _pIAC->RevokeExplicitAccessRights(cCount, pTrustee); } STDMETHODIMP CExposedDocFile::IsAccessPermitted(TRUSTEE *pTrustee, DWORD grfAccessPermissions) { olAssert((_pIAC != NULL)); return _pIAC->IsAccessPermitted(pTrustee, grfAccessPermissions); } STDMETHODIMP CExposedDocFile::GetEffectiveAccessRights(TRUSTEE *pTrustee, DWORD *pgrfAccessPermissions ) { olAssert((_pIAC != NULL)); return _pIAC->GetEffectiveAccessRights(pTrustee, pgrfAccessPermissions); } STDMETHODIMP CExposedDocFile::GetExplicitAccessRights(ULONG *pcCount, PEXPLICIT_ACCESS *pExplicitAccessList) { olAssert((_pIAC != NULL)); return _pIAC->GetExplicitAccessRights(pcCount, pExplicitAccessList); } STDMETHODIMP CExposedDocFile::CommitAccessRights(DWORD grfCommitFlags) { olAssert((_pIAC != NULL)); return _pIAC->CommitAccessRights(grfCommitFlags); } STDMETHODIMP CExposedDocFile::RevertAccessRights() { olAssert((_pIAC != NULL)); return _pIAC->RevertAccessRights(); } #endif // if WIN32 >= 300 #ifdef COORD //+--------------------------------------------------------------------------- // // Member: CExposedDocFile::CommitPhase1, public // // Synopsis: Do phase 1 of an exposed two phase commit // // Arguments: [grfCommitFlags] -- Commit flags // // Returns: Appropriate status code // // History: 08-Aug-95 PhilipLa Created // //---------------------------------------------------------------------------- SCODE CExposedDocFile::CommitPhase1(DWORD grfCommitFlags) { SCODE sc; SAFE_SEM; SAFE_ACCESS; olChk(VerifyCommitFlags(grfCommitFlags)); olChk(Validate()); olChk(TakeSafeSem()); SafeWriteAccess(); #ifdef DIRECTWRITERLOCK olChk(ValidateWriteAccess()); #endif sc = _pdf->CommitPhase1(grfCommitFlags, &_ulLock, &_sigMSF, &_cbSizeBase, &_cbSizeOrig); EH_Err: return sc; } //+--------------------------------------------------------------------------- // // Member: CExposedDocFile::CommitPhase2, public // // Synopsis: Do phase 2 of an exposed two phase commit // // Arguments: [grfCommitFlags] -- Commit flags // [fCommit] -- TRUE if transaction is to commit, FALSE if abort // // Returns: Appropriate status code // // History: 08-Aug-95 PhilipLa Created // //---------------------------------------------------------------------------- SCODE CExposedDocFile::CommitPhase2(DWORD grfCommitFlags, BOOL fCommit) { SCODE sc; SAFE_SEM; SAFE_ACCESS; olChk(Validate()); olChk(TakeSafeSem()); SafeWriteAccess(); #ifdef DIRECTWRITERLOCK olChk(ValidateWriteAccess()); #endif sc = _pdf->CommitPhase2(grfCommitFlags, fCommit, _ulLock, _sigMSF, _cbSizeBase, _cbSizeOrig); _ulLock = _cbSizeBase = _cbSizeOrig = 0; _sigMSF = 0; EH_Err: return sc; } #endif //COORD #ifdef NEWPROPS //+--------------------------------------------------------------------------- // // Member: CExposedDocFile::Lock, IBlockingLock // // Synopsis: Acquires the semaphore associated with the docfile. // // Notes: This member is called by CPropertyStorage. // //---------------------------------------------------------------------------- STDMETHODIMP CExposedDocFile::Lock(DWORD dwTimeout) { #ifdef MULTIHEAP CSafeMultiHeap smh(_ppc); #endif TakeSem(); SetDifferentBasisAccess(_pdfb, _ppc); return S_OK; } //+--------------------------------------------------------------------------- // // Member: CExposedDocFile::Unlock, public IBlockingLock // // Synopsis: Releases the semaphore associated with the docfile. // // Notes: This member is called by CPropertyStorage. // //---------------------------------------------------------------------------- STDMETHODIMP CExposedDocFile::Unlock(VOID) { #ifdef MULTIHEAP CSafeMultiHeap smh(_ppc); #endif ClearBasisAccess(_pdfb); ReleaseSem(S_OK); return( S_OK ); } #endif #ifdef DIRECTWRITERLOCK //+--------------------------------------------------------------------------- // // Member: CExposedDocFile::WaitForWriteAccess, public IDirectWriterLock // // Synopsis: tries to obtain exclusive write access in direct mode // // Notes: Tree mutex must be taken when accessing recursion count // //---------------------------------------------------------------------------- STDMETHODIMP CExposedDocFile::WaitForWriteAccess (DWORD dwTimeout) { SAFE_SEM; SAFE_ACCESS; HRESULT hr = TakeSafeSem(); if (SUCCEEDED(hr) && *_ppc->GetRecursionCount() == 0) { SafeReadAccess(); hr = _pdfb->WaitForWriteAccess (dwTimeout, _ppc->GetGlobal()); } if (SUCCEEDED(hr)) ++(*_ppc->GetRecursionCount()); return hr; } //+--------------------------------------------------------------------------- // // Member: CExposedDocFile::ReleaseWriteAccess, public IDirectWriterLock // // Synopsis: releases exclusive write access from WaitForWriteAccess // // Notes: Tree mutex must be taken when accessing recursion count // //---------------------------------------------------------------------------- STDMETHODIMP CExposedDocFile::ReleaseWriteAccess () { SAFE_SEM; SAFE_ACCESS; HRESULT hr = TakeSafeSem(); if (SUCCEEDED(hr) && *_ppc->GetRecursionCount() == 1) { SafeReadAccess(); hr = _pdf->Commit(STGC_DEFAULT); // Flush if (SUCCEEDED(hr)) hr = _pdfb->ReleaseWriteAccess(); } if (SUCCEEDED(hr)) --(*_ppc->GetRecursionCount()); return hr; } //+--------------------------------------------------------------------------- // // Member: CExposedDocFile::HaveWriteAccess, public IDirectWriterLock // // Synopsis: returns S_OK if write lock is active, S_FALSE if not // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP CExposedDocFile::HaveWriteAccess () { SAFE_SEM; HRESULT hr = TakeSafeSem(); olAssert(_pdfb->DirectWriterMode()); if (SUCCEEDED(hr)) { hr = (_pdfb->HaveWriteAccess()) ? S_OK : S_FALSE; } return hr; } //+-------------------------------------------------------------- // // Member: CExposedDocFile::ValidateWriteAccess, public // // Synopsis: returns whether writer currently has write access // // Notes: tree mutex must be taken // // History: 30-Apr-96 HenryLee Created // //--------------------------------------------------------------- HRESULT CExposedDocFile::ValidateWriteAccess() { if (_pdf->GetTransactedDepth() >= 1) return S_OK; return (!_pdfb->DirectWriterMode() || (*_ppc->GetRecursionCount()) > 0) ? S_OK : STG_E_ACCESSDENIED; }; #endif // DIRECTWRITERLOCK