/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sot.hxx" #include #include #include #include #include #ifndef _TOOLS_FSYS_HXX #include #endif #ifndef _TOOLS_STREAM_HXX #include #endif #include #include #include "sot/stg.hxx" #include "stgelem.hxx" #include "stgcache.hxx" #include "stgstrms.hxx" #include "stgdir.hxx" #include "stgio.hxx" #include "stgole.hxx" static long nTmpCount = 0; // The internal open mode is STREAM_READ | STREAM_TRUNC, which is silly // by itself. It inhibits the checking of sharing modes and is used // during CopyTo() and MoveTo() for opening a stream in read mode // although it may be open in DENYALL mode #define INTERNAL_MODE ( STREAM_READ | STREAM_TRUNC ) ///////////////////////// class StorageBase ////////////////////////////// TYPEINIT0( StorageBase ); TYPEINIT1( BaseStorageStream, StorageBase ); TYPEINIT1( BaseStorage, StorageBase ); StorageBase::StorageBase() : m_bAutoCommit( sal_False ) { m_nMode = STREAM_READ; m_nError = SVSTREAM_OK; } StorageBase::~StorageBase() { } // The following three methods are declared as const, since they // may be called from within a const method. sal_uLong StorageBase::GetError() const { sal_uLong n = m_nError; ((StorageBase*) this)->m_nError = SVSTREAM_OK; return n; } void StorageBase::SetError( sal_uLong n ) const { if( !m_nError ) ((StorageBase*) this)->m_nError = n; } void StorageBase::ResetError() const { ((StorageBase*) this)->m_nError = SVSTREAM_OK; } // Retrieve the underlying SvStream for info purposes const SvStream* OLEStorageBase::GetSvStream_Impl() const { return pIo ? pIo->GetStrm() : NULL; } OLEStorageBase::OLEStorageBase( StgIo* p, StgDirEntry* pe, StreamMode& nMode ) : nStreamMode( nMode ), pIo( p ), pEntry( pe ) { if ( p ) p->IncRef(); if( pe ) pe->nRefCnt++; } OLEStorageBase::~OLEStorageBase() { if( pEntry ) { DBG_ASSERT( pEntry->nRefCnt, "RefCount unter 0" ); if( !--pEntry->nRefCnt ) { if( pEntry->bZombie ) delete pEntry; else pEntry->Close(); } pEntry = NULL; } if( pIo && !pIo->DecRef() ) { delete pIo; pIo = NULL; } } // Validate the instance for I/O sal_Bool OLEStorageBase::Validate_Impl( sal_Bool bWrite ) const { if( pIo && pIo->pTOC && pEntry && !pEntry->bInvalid && ( !bWrite || !pEntry->bDirect || ( nStreamMode & STREAM_WRITE ) ) ) return sal_True; return sal_False; } sal_Bool OLEStorageBase::ValidateMode_Impl( StreamMode m, StgDirEntry* p ) const { if( m == INTERNAL_MODE ) return sal_True; sal_uInt16 nCurMode = ( p && p->nRefCnt ) ? p->nMode : 0xFFFF; if( ( m & 3 ) == STREAM_READ ) { // only SHARE_DENYWRITE or SHARE_DENYALL allowed if( ( ( m & STREAM_SHARE_DENYWRITE ) && ( nCurMode & STREAM_SHARE_DENYWRITE ) ) || ( ( m & STREAM_SHARE_DENYALL ) && ( nCurMode & STREAM_SHARE_DENYALL ) ) ) return sal_True; } else { // only SHARE_DENYALL allowed // storages open in r/o mode are OK, since only // the commit may fail if( ( m & STREAM_SHARE_DENYALL ) && ( nCurMode & STREAM_SHARE_DENYALL ) ) return sal_True; } return sal_False; } //////////////////////// class StorageStream ///////////////////////////// TYPEINIT1( StorageStream, BaseStorageStream ); StorageStream::StorageStream( StgIo* p, StgDirEntry* q, StreamMode m ) : OLEStorageBase( p, q, m_nMode ), nPos( 0L ) { // The dir entry may be 0; this means that the stream is invalid. if( q && p ) { if( q->nRefCnt == 1 ) { q->nMode = m; q->OpenStream( *p ); } } else m &= ~STREAM_READWRITE; m_nMode = m; } StorageStream::~StorageStream() { // Do an auto-commit if the entry is open in direct mode if( m_bAutoCommit ) Commit(); if( pEntry && pEntry->nRefCnt && pEntry->bDirect && (m_nMode & STREAM_WRITE) ) pEntry->Commit(); } sal_Bool StorageStream::Equals( const BaseStorageStream& rStream ) const { const StorageStream* pOther = PTR_CAST( StorageStream, &rStream ); return pOther && ( pOther->pEntry == pEntry ); } sal_uLong StorageStream::Read( void* pData, sal_uLong nSize ) { if( Validate() ) { pEntry->Seek( nPos ); nSize = pEntry->Read( pData, (sal_Int32) nSize ); pIo->MoveError( *this ); nPos += nSize; } else nSize = 0L; return nSize; } sal_uLong StorageStream::Write( const void* pData, sal_uLong nSize ) { if( Validate( sal_True ) ) { pEntry->Seek( nPos ); nSize = pEntry->Write( pData, (sal_Int32) nSize ); pIo->MoveError( *this ); nPos += nSize; } else nSize = 0L; return nSize; } sal_uLong StorageStream::Seek( sal_uLong n ) { if( Validate() ) return nPos = pEntry->Seek( n ); else return n; } void StorageStream::Flush() { // Flushing means committing, since streams are never transacted Commit(); } sal_Bool StorageStream::SetSize( sal_uLong nNewSize ) { if( Validate( sal_True ) ) { sal_Bool b = pEntry->SetSize( (sal_Int32) nNewSize ); pIo->MoveError( *this ); return b; } else return sal_False; } sal_Bool StorageStream::Commit() { if( !Validate() ) return sal_False; if( !( m_nMode & STREAM_WRITE ) ) { SetError( SVSTREAM_ACCESS_DENIED ); return sal_False; } else { pEntry->Commit(); pIo->MoveError( *this ); return Good(); } } sal_Bool StorageStream::Revert() { sal_Bool bResult = sal_False; if ( Validate() ) { pEntry->Revert(); pIo->MoveError( *this ); bResult = Good(); } return bResult; } sal_Bool StorageStream::CopyTo( BaseStorageStream* pDest ) { if( !Validate() || !pDest || !pDest->Validate( sal_True ) || Equals( *pDest ) ) return sal_False; pEntry->Copy( *pDest ); pDest->Commit(); pIo->MoveError( *this ); SetError( pDest->GetError() ); return sal_Bool( Good() && pDest->Good() ); } const SvStream* StorageStream::GetSvStream() const { return GetSvStream_Impl(); } sal_Bool StorageStream::Validate( sal_Bool bValidate ) const { sal_Bool bRet = Validate_Impl( bValidate ); if ( !bRet ) SetError( SVSTREAM_ACCESS_DENIED ); return bRet; } sal_Bool StorageStream::ValidateMode( StreamMode nMode ) const { sal_Bool bRet = ValidateMode_Impl( nMode, NULL ); if ( !bRet ) SetError( SVSTREAM_ACCESS_DENIED ); return bRet; } sal_Bool StorageStream::ValidateMode( StreamMode nMode, StgDirEntry* p ) const { sal_Bool bRet = ValidateMode_Impl( nMode, p ); if ( !bRet ) SetError( SVSTREAM_ACCESS_DENIED ); return bRet; } ///////////////////////// class SvStorageInfo ////////////////////////////// SvStorageInfo::SvStorageInfo( const StgDirEntry& rE ) { rE.aEntry.GetName( aName ); bStorage = sal_Bool( rE.aEntry.GetType() == STG_STORAGE ); bStream = sal_Bool( rE.aEntry.GetType() == STG_STREAM ); nSize = bStorage ? 0 : rE.aEntry.GetSize(); } /////////////////////////// class Storage //////////////////////////////// sal_Bool Storage::IsStorageFile( const String & rFileName ) { StgIo aIo; if( aIo.Open( rFileName, STREAM_STD_READ ) ) return aIo.Load(); return sal_False; } sal_Bool Storage::IsStorageFile( SvStream* pStream ) { sal_Bool bRet = sal_False; if ( pStream ) { StgHeader aHdr; sal_uLong nPos = pStream->Tell(); bRet = ( aHdr.Load( *pStream ) && aHdr.Check() ); // It's not a stream error if it is too small for a OLE storage header if ( pStream->GetErrorCode() == ERRCODE_IO_CANTSEEK ) pStream->ResetError(); pStream->Seek( nPos ); } return bRet; } // Open the storage file. If writing is permitted and the file is not // a storage file, initialize it. TYPEINIT1( Storage, BaseStorage ); Storage::Storage( const String& rFile, StreamMode m, sal_Bool bDirect ) : OLEStorageBase( new StgIo, NULL, m_nMode ), aName( rFile ), bIsRoot( sal_False ) { sal_Bool bTemp = sal_False; if( !aName.Len() ) { // no name = temporary name! aName = TempFile::CreateTempName(); bTemp = sal_True; } // the root storage creates the I/O system m_nMode = m; if( pIo->Open( aName, m ) ) { Init( sal_Bool( ( m & ( STREAM_TRUNC | STREAM_NOCREATE ) ) == STREAM_TRUNC ) ); if( pEntry ) { pEntry->bDirect = bDirect; pEntry->nMode = m; pEntry->bTemp = bTemp; } } else { pIo->MoveError( *this ); pEntry = NULL; } } // Create a storage on a given stream. Storage::Storage( SvStream& r, sal_Bool bDirect ) : OLEStorageBase( new StgIo, NULL, m_nMode ), bIsRoot( sal_False ) { m_nMode = STREAM_READ; if( r.IsWritable() ) m_nMode = STREAM_READ | STREAM_WRITE; if( r.GetError() == SVSTREAM_OK ) { pIo->SetStrm( &r, sal_False ); sal_uLong nSize = r.Seek( STREAM_SEEK_TO_END ); r.Seek( 0L ); // Initializing is OK if the stream is empty Init( sal_Bool( nSize == 0 ) ); if( pEntry ) { pEntry->bDirect = bDirect; pEntry->nMode = m_nMode; } pIo->MoveError( *this ); } else { SetError( r.GetError() ); pEntry = NULL; } } Storage::Storage( UCBStorageStream& rStrm, sal_Bool bDirect ) : OLEStorageBase( new StgIo, NULL, m_nMode ), bIsRoot( sal_False ) { m_nMode = STREAM_READ; if ( rStrm.GetError() != SVSTREAM_OK ) { SetError( rStrm.GetError() ); pEntry = NULL; return; } SvStream* pStream = rStrm.GetModifySvStream(); if ( !pStream ) { OSL_ENSURE( sal_False, "UCBStorageStream can not provide SvStream implementation!\n" ); SetError( SVSTREAM_GENERALERROR ); pEntry = NULL; return; } if( pStream->IsWritable() ) m_nMode = STREAM_READ | STREAM_WRITE; pIo->SetStrm( &rStrm ); sal_uLong nSize = pStream->Seek( STREAM_SEEK_TO_END ); pStream->Seek( 0L ); // Initializing is OK if the stream is empty Init( sal_Bool( nSize == 0 ) ); if( pEntry ) { pEntry->bDirect = bDirect; pEntry->nMode = m_nMode; } pIo->MoveError( *this ); } // Perform common code for both ctors above. void Storage::Init( sal_Bool bCreate ) { pEntry = NULL; sal_Bool bHdrLoaded = sal_False; bIsRoot = sal_True; OSL_ENSURE( pIo, "The pointer may not be empty at this point!" ); if( pIo->Good() && pIo->GetStrm() ) { sal_uLong nSize = pIo->GetStrm()->Seek( STREAM_SEEK_TO_END ); pIo->GetStrm()->Seek( 0L ); if( nSize ) { bHdrLoaded = pIo->Load(); if( !bHdrLoaded && !bCreate ) { // File is not a storage and not empty; do not destroy! SetError( SVSTREAM_FILEFORMAT_ERROR ); return; } } } // file is a storage, empty or should be overwritten pIo->ResetError(); // we have to set up the data structures, since // the file is empty if( !bHdrLoaded ) pIo->Init(); if( pIo->Good() && pIo->pTOC ) { pEntry = pIo->pTOC->GetRoot(); pEntry->nRefCnt++; } } // Internal ctor Storage::Storage( StgIo* p, StgDirEntry* q, StreamMode m ) : OLEStorageBase( p, q, m_nMode ), bIsRoot( sal_False ) { if( q ) q->aEntry.GetName( aName ); else m &= ~STREAM_READWRITE; m_nMode = m; if( q && q->nRefCnt == 1 ) q->nMode = m; } Storage::~Storage() { // Invalidate all open substorages if( m_bAutoCommit ) Commit(); if( pEntry ) { // Do an auto-commit if the entry is open in direct mode if( pEntry->nRefCnt && pEntry->bDirect && (m_nMode & STREAM_WRITE) ) Commit(); if( pEntry->nRefCnt == 1 ) pEntry->Invalidate(); } // close the stream is root storage if( bIsRoot ) pIo->Close(); // remove the file if temporary root storage if( bIsRoot && pEntry && pEntry->bTemp ) { osl::File::remove( GetName() ); } } const String& Storage::GetName() const { if( !bIsRoot && Validate() ) pEntry->aEntry.GetName( ((Storage*) this)->aName ); return aName; } // Fill in the info list for this storage void Storage::FillInfoList( SvStorageInfoList* pList ) const { if( Validate() && pList ) { StgIterator aIter( *pEntry ); StgDirEntry* p = aIter.First(); while( p ) { if( !p->bInvalid ) { SvStorageInfo aInfo( *p ); pList->Append( aInfo ); } p = aIter.Next(); } } } // Open or create a substorage BaseStorage* Storage::OpenUCBStorage( const String& rName, StreamMode m, sal_Bool bDirect ) { DBG_ERROR("Not supported!"); /* BaseStorage* pStorage = new Storage( pIo, NULL, m ); SetError( ERRCODE_IO_NOTSUPPORTED ); return pStorage; */ return OpenStorage( rName, m, bDirect ); } BaseStorage* Storage::OpenOLEStorage( const String& rName, StreamMode m, sal_Bool bDirect ) { return OpenStorage( rName, m, bDirect ); } BaseStorage* Storage::OpenStorage( const String& rName, StreamMode m, sal_Bool bDirect ) { if( !Validate() || !ValidateMode( m ) ) return new Storage( pIo, NULL, m ); sal_Bool bSetAutoCommit = sal_False; if( bDirect && !pEntry->bDirect ) { bSetAutoCommit = sal_True; bDirect = sal_False; } StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName ); if( !p ) { if( !( m & STREAM_NOCREATE ) ) { sal_Bool bTemp = sal_False; // create a new storage String aNewName = rName; if( !aNewName.Len() ) { aNewName.AssignAscii( "Temp Stg " ); aNewName.Append( String::CreateFromInt32( ++nTmpCount ) ); bTemp = sal_True; } p = pIo->pTOC->Create( *pEntry, aNewName, STG_STORAGE ); if( p ) p->bTemp = bTemp; } if( !p ) pIo->SetError( ( m & STREAM_WRITE ) ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND ); } else if( !ValidateMode( m, p ) ) p = NULL; if( p && p->aEntry.GetType() != STG_STORAGE ) { pIo->SetError( SVSTREAM_FILE_NOT_FOUND ); p = NULL; } // Either direct or transacted mode is supported if( p && pEntry->nRefCnt == 1 ) p->bDirect = bDirect; // Dont check direct conflict if opening readonly if( p && (m & STREAM_WRITE )) { if( p->bDirect != bDirect ) SetError( SVSTREAM_ACCESS_DENIED ); } Storage* pStg = new Storage( pIo, p, m ); pIo->MoveError( *pStg ); if( m & STREAM_WRITE ) pStg->m_bAutoCommit = sal_True; return pStg; } // Open a stream BaseStorageStream* Storage::OpenStream( const String& rName, StreamMode m, sal_Bool, const ByteString* #ifdef DBG_UTIL pB #endif ) { DBG_ASSERT(!pB, "Encryption not supported"); if( !Validate() || !ValidateMode( m ) ) return new StorageStream( pIo, NULL, m ); StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName ); sal_Bool bTemp = sal_False; if( !p ) { if( !( m & STREAM_NOCREATE ) ) { // create a new stream // make a name if the stream is temporary (has no name) String aNewName( rName ); if( !aNewName.Len() ) { aNewName.AssignAscii( "Temp Strm " ); aNewName.Append( String::CreateFromInt32( ++nTmpCount ) ); bTemp = sal_True; } p = pIo->pTOC->Create( *pEntry, aNewName, STG_STREAM ); } if( !p ) pIo->SetError( ( m & STREAM_WRITE ) ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND ); } else if( !ValidateMode( m, p ) ) p = NULL; if( p && p->aEntry.GetType() != STG_STREAM ) { pIo->SetError( SVSTREAM_FILE_NOT_FOUND ); p = NULL; } if( p ) { p->bTemp = bTemp; p->bDirect = pEntry->bDirect; } StorageStream* pStm = new StorageStream( pIo, p, m ); if( p && !p->bDirect ) pStm->SetAutoCommit( sal_True ); pIo->MoveError( *pStm ); return pStm; } // Delete a stream or substorage by setting the temp bit. sal_Bool Storage::Remove( const String& rName ) { if( !Validate( sal_True ) ) return sal_False; StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName ); if( p ) { p->Invalidate( sal_True ); return sal_True; } else { SetError( SVSTREAM_FILE_NOT_FOUND ); return sal_False; } } // Rename a storage element sal_Bool Storage::Rename( const String& rOld, const String& rNew ) { if( Validate( sal_True ) ) { sal_Bool b = pIo->pTOC->Rename( *pEntry, rOld, rNew ); pIo->MoveError( *this ); return b; } else return sal_False; } // Copy one element sal_Bool Storage::CopyTo( const String& rElem, BaseStorage* pDest, const String& rNew ) { if( !Validate() || !pDest || !pDest->Validate( sal_True ) ) return sal_False; StgDirEntry* pElem = pIo->pTOC->Find( *pEntry, rElem ); if( pElem ) { /* this lines are misterious !!! MM if( !pElem->IsContained( pDest->pEntry ) ) { SetError( SVSTREAM_ACCESS_DENIED ); return sal_False; } */ if( pElem->aEntry.GetType() == STG_STORAGE ) { // copy the entire storage BaseStorage* p1 = OpenStorage( rElem, INTERNAL_MODE ); BaseStorage* p2 = pDest->OpenOLEStorage( rNew, STREAM_WRITE | STREAM_SHARE_DENYALL, pEntry->bDirect ); if ( p2 ) { sal_uLong nTmpErr = p2->GetError(); if( !nTmpErr ) { p2->SetClassId( p1->GetClassId() ); p1->CopyTo( p2 ); SetError( p1->GetError() ); nTmpErr = p2->GetError(); if( !nTmpErr ) p2->Commit(); else pDest->SetError( nTmpErr ); } else pDest->SetError( nTmpErr ); } delete p1; delete p2; return sal_Bool( Good() && pDest->Good() ); } else { // stream copy BaseStorageStream* p1 = OpenStream( rElem, INTERNAL_MODE ); BaseStorageStream* p2 = pDest->OpenStream( rNew, STREAM_WRITE | STREAM_SHARE_DENYALL, pEntry->bDirect ); if ( p2 ) { sal_uLong nTmpErr = p2->GetError(); if( !nTmpErr ) { p1->CopyTo( p2 ); SetError( p1->GetError() ); nTmpErr = p2->GetError(); if( !nTmpErr ) p2->Commit(); else pDest->SetError( nTmpErr ); } else pDest->SetError( nTmpErr ); } delete p1; delete p2; return sal_Bool( Good() && pDest->Good() ); } } SetError( SVSTREAM_FILE_NOT_FOUND ); return sal_False; } sal_Bool Storage::CopyTo( BaseStorage* pDest ) const { if( !Validate() || !pDest || !pDest->Validate( sal_True ) || Equals( *pDest ) ) { SetError( SVSTREAM_ACCESS_DENIED ); return sal_False; } Storage* pThis = (Storage*) this; /* if( !pThis->pEntry->IsContained( pDest->pEntry ) ) { SetError( SVSTREAM_ACCESS_DENIED ); return sal_False; } */ pDest->SetClassId( GetClassId() ); pDest->SetDirty(); SvStorageInfoList aList; FillInfoList( &aList ); sal_Bool bRes = sal_True; for( sal_uInt16 i = 0; i < aList.Count() && bRes; i++ ) { SvStorageInfo& rInfo = aList.GetObject( i ); bRes = pThis->CopyTo( rInfo.GetName(), pDest, rInfo.GetName() ); } if( !bRes ) SetError( pDest->GetError() ); return sal_Bool( Good() && pDest->Good() ); } // Move one element sal_Bool Storage::MoveTo( const String& rElem, BaseStorage* pODest, const String& rNew ) { if( !Validate() || !pODest || !pODest->Validate( sal_True ) || Equals( *pODest ) ) { SetError( SVSTREAM_ACCESS_DENIED ); return sal_False; } StgDirEntry* pElem = pIo->pTOC->Find( *pEntry, rElem ); if( pElem ) { // Simplest case: both storages share the same file sal_Bool bRes; Storage *pOther = PTR_CAST( Storage, pODest ); if( pOther && pIo == pOther->pIo && rElem == rNew ) { Storage *p = (Storage*) pODest; Storage *pDest = p; // both storages are conventional storages, use implementation dependent code if( !pElem->IsContained( pDest->pEntry ) ) { // cyclic move SetError( SVSTREAM_ACCESS_DENIED ); return sal_False; } bRes = pIo->pTOC->Move( *pEntry, *pDest->pEntry, rNew ); if( !bRes ) { pIo->MoveError( *this ); pDest->pIo->MoveError( *pDest ); sal_uLong nErr = GetError(); if( !nErr ) nErr = pDest->GetError(); SetError( nErr ); pDest->SetError( nErr ); } } else { bRes = CopyTo( rElem, pODest, rNew ); if( bRes ) bRes = Remove( rElem ); } if( !bRes ) SetError( pIo->GetError() ); return bRes; } SetError( SVSTREAM_FILE_NOT_FOUND ); return sal_False; } sal_Bool Storage::IsStorage( const String& rName ) const { if( Validate() ) { StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName ); if( p ) return sal_Bool( p->aEntry.GetType() == STG_STORAGE ); } return sal_False; } sal_Bool Storage::IsStream( const String& rName ) const { if( Validate() ) { StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName ); if( p ) return sal_Bool( p->aEntry.GetType() == STG_STREAM ); } return sal_False; } sal_Bool Storage::IsContained( const String& rName ) const { if( Validate() ) return sal_Bool( pIo->pTOC->Find( *pEntry, rName ) != NULL ); else return sal_False; } // Commit all sub-elements within this storage. If this is // the root, commit the FAT, the TOC and the header as well. sal_Bool Storage::Commit() { sal_Bool bRes = sal_True; if( !Validate() ) return sal_False; if( !( m_nMode & STREAM_WRITE ) ) { SetError( SVSTREAM_ACCESS_DENIED ); return sal_False; } else { // Also commit the sub-streams and Storages StgIterator aIter( *pEntry ); for( StgDirEntry* p = aIter.First(); p && bRes; p = aIter.Next() ) bRes = p->Commit(); if( bRes && bIsRoot ) { bRes = pEntry->Commit(); if( bRes ) bRes = pIo->CommitAll(); } pIo->MoveError( *this ); } return bRes; } sal_Bool Storage::Revert() { return sal_True; } ///////////////////////////// OLE Support //////////////////////////////// // Set the storage type void Storage::SetClass( const SvGlobalName & rClass, sal_uLong nOriginalClipFormat, const String & rUserTypeName ) { if( Validate( sal_True ) ) { // set the class name in the root entry pEntry->aEntry.SetClassId( (const ClsId&) rClass.GetCLSID() ); pEntry->SetDirty(); // then create the streams StgCompObjStream aCompObj( *this, sal_True ); aCompObj.GetClsId() = (const ClsId&) rClass.GetCLSID(); aCompObj.GetCbFormat() = nOriginalClipFormat; aCompObj.GetUserName() = rUserTypeName; if( !aCompObj.Store() ) SetError( aCompObj.GetError() ); else { StgOleStream aOle( *this, STREAM_WRITE ); if( !aOle.Store() ) SetError( aOle.GetError() ); } } else SetError( SVSTREAM_ACCESS_DENIED ); } void Storage::SetConvertClass( const SvGlobalName & rConvertClass, sal_uLong nOriginalClipFormat, const String & rUserTypeName ) { if( Validate( sal_True ) ) { SetClass( rConvertClass, nOriginalClipFormat, rUserTypeName ); // plus the convert flag: StgOleStream aOle( *this, sal_True ); aOle.GetFlags() |= 4; if( !aOle.Store() ) SetError( aOle.GetError() ); } } SvGlobalName Storage::GetClassName() { StgCompObjStream aCompObj( *this, sal_False ); if( aCompObj.Load() ) return SvGlobalName( (const CLSID&) aCompObj.GetClsId() ); pIo->ResetError(); if ( pEntry ) return SvGlobalName( (const CLSID&) pEntry->aEntry.GetClassId() ); return SvGlobalName(); } sal_uLong Storage::GetFormat() { StgCompObjStream aCompObj( *this, sal_False ); if( aCompObj.Load() ) return aCompObj.GetCbFormat(); pIo->ResetError(); return 0; } String Storage::GetUserName() { StgCompObjStream aCompObj( *this, sal_False ); if( aCompObj.Load() ) return aCompObj.GetUserName(); pIo->ResetError(); return String(); } sal_Bool Storage::ShouldConvert() { StgOleStream aOle( *this, sal_False ); if( aOle.Load() ) return sal_Bool( ( aOle.GetFlags() & 4 ) != 0 ); else { pIo->ResetError(); return sal_False; } } sal_Bool Storage::ValidateFAT() { Link aLink = StgIo::GetErrorLink(); ErrCode nErr = pIo->ValidateFATs(); StgIo::SetErrorLink( aLink ); return nErr == ERRCODE_NONE; } void Storage::SetDirty() { if ( pEntry ) pEntry->SetDirty(); } void Storage::SetClassId( const ClsId& rId ) { if ( pEntry ) pEntry->aEntry.SetClassId( rId ); } const ClsId& Storage::GetClassId() const { if ( pEntry ) return pEntry->aEntry.GetClassId(); static ClsId aDummyId = {0,0,0,0,0,0,0,0,0,0,0}; return aDummyId; } const SvStream* Storage::GetSvStream() const { return GetSvStream_Impl(); } sal_Bool Storage::Validate( sal_Bool bValidate ) const { sal_Bool bRet = Validate_Impl( bValidate ); if ( !bRet ) SetError( SVSTREAM_ACCESS_DENIED ); return bRet; } sal_Bool Storage::ValidateMode( StreamMode nMode ) const { sal_Bool bRet = ValidateMode_Impl( nMode ); if ( !bRet ) SetError( SVSTREAM_ACCESS_DENIED ); return bRet; } sal_Bool Storage::ValidateMode( StreamMode nMode, StgDirEntry* p ) const { sal_Bool bRet = ValidateMode_Impl( nMode, p ); if ( !bRet ) SetError( SVSTREAM_ACCESS_DENIED ); return bRet; } sal_Bool Storage::Equals( const BaseStorage& rStorage ) const { const Storage* pOther = PTR_CAST( Storage, &rStorage ); return pOther && ( pOther->pEntry == pEntry ); }