bump product version to 5.0.4.1
[LibreOffice.git] / sot / source / sdstor / stg.cxx
bloba3e20858b1e407c203e2618a4aaec230e664d698
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <sot/storinfo.hxx>
22 #include <sot/exchange.hxx>
23 #include <osl/file.hxx>
24 #include <unotools/tempfile.hxx>
25 #include <tools/stream.hxx>
26 #include <tools/debug.hxx>
28 #include "sot/stg.hxx"
29 #include "stgelem.hxx"
30 #include "stgcache.hxx"
31 #include "stgstrms.hxx"
32 #include "stgdir.hxx"
33 #include "stgio.hxx"
34 #include "stgole.hxx"
36 static long nTmpCount = 0;
38 // The internal open mode is StreamMode::READ | StreamMode::TRUNC, which is silly
39 // by itself. It inhibits the checking of sharing modes and is used
40 // during CopyTo() and MoveTo() for opening a stream in read mode
41 // although it may be open in DENYALL mode
43 #define INTERNAL_MODE ( StreamMode::READ | StreamMode::TRUNC )
45 ///////////////////////// class StorageBase
47 TYPEINIT0( StorageBase );
48 TYPEINIT1( BaseStorageStream, StorageBase );
49 TYPEINIT1( BaseStorage, StorageBase );
51 StorageBase::StorageBase()
52 : m_bAutoCommit( false )
54 m_nMode = StreamMode::READ;
55 m_nError = SVSTREAM_OK;
58 StorageBase::~StorageBase()
62 // The following three methods are declared as const, since they
63 // may be called from within a const method.
65 sal_uLong StorageBase::GetError() const
67 sal_uLong n = m_nError;
68 const_cast<StorageBase*>(this)->m_nError = SVSTREAM_OK;
69 return n;
72 void StorageBase::SetError( sal_uLong n ) const
74 if( !m_nError )
75 const_cast<StorageBase*>(this)->m_nError = n;
78 void StorageBase::ResetError() const
80 const_cast<StorageBase*>(this)->m_nError = SVSTREAM_OK;
83 // Retrieve the underlying SvStream for info purposes
85 const SvStream* OLEStorageBase::GetSvStream_Impl() const
87 return pIo ? pIo->GetStrm() : NULL;
90 OLEStorageBase::OLEStorageBase( StgIo* p, StgDirEntry* pe, StreamMode& nMode )
91 : nStreamMode( nMode ), pIo( p ), pEntry( pe )
93 if ( p )
94 p->IncRef();
95 if( pe )
96 pe->nRefCnt++;
99 OLEStorageBase::~OLEStorageBase()
101 if( pEntry )
103 DBG_ASSERT( pEntry->nRefCnt, "RefCount unter 0" );
104 if( !--pEntry->nRefCnt )
106 if( pEntry->bZombie )
107 delete pEntry;
108 else
109 pEntry->Close();
112 pEntry = NULL;
116 if( pIo && !pIo->DecRef() )
118 delete pIo;
119 pIo = NULL;
123 // Validate the instance for I/O
125 bool OLEStorageBase::Validate_Impl( bool bWrite ) const
127 if( pIo
128 && pIo->pTOC
129 && pEntry
130 && !pEntry->bInvalid
131 && ( !bWrite || !pEntry->bDirect || ( nStreamMode & StreamMode::WRITE ) ) )
132 return true;
133 return false;
136 bool OLEStorageBase::ValidateMode_Impl( StreamMode m, StgDirEntry* p )
138 if( m == INTERNAL_MODE )
139 return true;
140 StreamMode nCurMode = ( p && p->nRefCnt ) ? p->nMode : StreamMode::SHARE_DENYALL;
141 if( ( m & STREAM_READWRITE ) == StreamMode::READ )
143 // only SHARE_DENYWRITE or SHARE_DENYALL allowed
144 if( ( ( m & StreamMode::SHARE_DENYWRITE )
145 && ( nCurMode & StreamMode::SHARE_DENYWRITE ) )
146 || ( ( m & StreamMode::SHARE_DENYALL )
147 && ( nCurMode & StreamMode::SHARE_DENYALL ) ) )
148 return true;
150 else
152 // only SHARE_DENYALL allowed
153 // storages open in r/o mode are OK, since only
154 // the commit may fail
155 if( ( m & StreamMode::SHARE_DENYALL )
156 && ( nCurMode & StreamMode::SHARE_DENYALL ) )
157 return true;
159 return false;
163 //////////////////////// class StorageStream
165 TYPEINIT1( StorageStream, BaseStorageStream );
167 StorageStream::StorageStream( StgIo* p, StgDirEntry* q, StreamMode m )
168 : OLEStorageBase( p, q, m_nMode ), nPos( 0L )
170 // The dir entry may be 0; this means that the stream is invalid.
171 if( q && p )
173 if( q->nRefCnt == 1 )
175 q->nMode = m;
176 q->OpenStream( *p );
179 else
180 m &= ~StreamMode(STREAM_READWRITE);
181 m_nMode = m;
184 StorageStream::~StorageStream()
186 // Do an auto-commit if the entry is open in direct mode
187 if( m_bAutoCommit )
188 Commit();
189 if( pEntry && pEntry->nRefCnt && pEntry->bDirect && (m_nMode & StreamMode::WRITE) )
190 pEntry->Commit();
193 bool StorageStream::Equals( const BaseStorageStream& rStream ) const
195 const StorageStream* pOther = PTR_CAST( StorageStream, &rStream );
196 return pOther && ( pOther->pEntry == pEntry );
199 sal_uLong StorageStream::Read( void* pData, sal_uLong nSize )
201 if( Validate() )
203 pEntry->Seek( nPos );
204 nSize = pEntry->Read( pData, (sal_Int32) nSize );
205 pIo->MoveError( *this );
206 nPos += nSize;
208 else
209 nSize = 0L;
210 return nSize;
213 sal_uLong StorageStream::Write( const void* pData, sal_uLong nSize )
215 if( Validate( true ) )
217 pEntry->Seek( nPos );
218 nSize = pEntry->Write( pData, (sal_Int32) nSize );
219 pIo->MoveError( *this );
220 nPos += nSize;
222 else
223 nSize = 0L;
224 return nSize;
227 sal_uInt64 StorageStream::Seek( sal_uInt64 n )
229 if( Validate() )
230 return nPos = pEntry->Seek( n );
231 else
232 return n;
235 void StorageStream::Flush()
237 // Flushing means committing, since streams are never transacted
238 Commit();
241 bool StorageStream::SetSize( sal_uLong nNewSize )
243 if( Validate( true ) )
245 bool b = pEntry->SetSize( (sal_Int32) nNewSize );
246 pIo->MoveError( *this );
247 return b;
249 else
250 return false;
253 sal_uLong StorageStream::GetSize() const
255 if( Validate() )
256 return pEntry->GetSize();
257 return 0;
260 bool StorageStream::Commit()
262 if( !Validate() )
263 return false;
264 if( !( m_nMode & StreamMode::WRITE ) )
266 SetError( SVSTREAM_ACCESS_DENIED );
267 return false;
269 else
271 pEntry->Commit();
272 pIo->MoveError( *this );
273 return Good();
277 bool StorageStream::Revert()
279 bool bResult = false;
281 if ( Validate() )
283 pEntry->Revert();
284 pIo->MoveError( *this );
285 bResult = Good();
288 return bResult;
291 bool StorageStream::CopyTo( BaseStorageStream* pDest )
293 if( !Validate() || !pDest || !pDest->Validate( true ) || Equals( *pDest ) )
294 return false;
295 pEntry->Copy( *pDest );
296 pDest->Commit();
297 pIo->MoveError( *this );
298 SetError( pDest->GetError() );
299 return Good() && pDest->Good();
302 const SvStream* StorageStream::GetSvStream() const
304 return GetSvStream_Impl();
307 bool StorageStream::Validate( bool bValidate ) const
309 bool bRet = Validate_Impl( bValidate );
310 if ( !bRet )
311 SetError( SVSTREAM_ACCESS_DENIED );
312 return bRet;
315 bool StorageStream::ValidateMode( StreamMode nMode ) const
317 bool bRet = ValidateMode_Impl( nMode, NULL );
318 if ( !bRet )
319 SetError( SVSTREAM_ACCESS_DENIED );
320 return bRet;
323 ///////////////////////// class SvStorageInfo
325 SvStorageInfo::SvStorageInfo( const StgDirEntry& rE )
327 rE.aEntry.GetName( aName );
328 bStorage = rE.aEntry.GetType() == STG_STORAGE;
329 bStream = rE.aEntry.GetType() == STG_STREAM;
330 nSize = bStorage ? 0 : rE.aEntry.GetSize();
333 /////////////////////////// class Storage
335 bool Storage::IsStorageFile( const OUString & rFileName )
337 StgIo aIo;
338 if( aIo.Open( rFileName, STREAM_STD_READ ) )
339 return aIo.Load();
340 return false;
343 bool Storage::IsStorageFile( SvStream* pStream )
345 bool bRet = false;
347 if ( pStream )
349 StgHeader aHdr;
350 sal_uLong nPos = pStream->Tell();
351 bRet = ( aHdr.Load( *pStream ) && aHdr.Check() );
353 // It's not a stream error if it is too small for a OLE storage header
354 if ( pStream->GetErrorCode() == ERRCODE_IO_CANTSEEK )
355 pStream->ResetError();
356 pStream->Seek( nPos );
359 return bRet;
362 // Open the storage file. If writing is permitted and the file is not
363 // a storage file, initialize it.
365 TYPEINIT1( Storage, BaseStorage );
367 Storage::Storage( const OUString& rFile, StreamMode m, bool bDirect )
368 : OLEStorageBase( new StgIo, NULL, m_nMode )
369 , aName( rFile ), bIsRoot( false )
371 bool bTemp = false;
372 if( aName.isEmpty() )
374 // no name = temporary name!
375 aName = utl::TempFile::CreateTempName();
376 bTemp = true;
378 // the root storage creates the I/O system
379 m_nMode = m;
380 if( pIo->Open( aName, m ) )
382 Init( ( m & ( StreamMode::TRUNC | StreamMode::NOCREATE ) ) == StreamMode::TRUNC );
383 if( pEntry )
385 pEntry->bDirect = bDirect;
386 pEntry->nMode = m;
387 pEntry->bTemp = bTemp;
390 else
392 pIo->MoveError( *this );
393 pEntry = NULL;
397 // Create a storage on a given stream.
399 Storage::Storage( SvStream& r, bool bDirect )
400 : OLEStorageBase( new StgIo, NULL, m_nMode )
401 , bIsRoot( false )
403 m_nMode = StreamMode::READ;
404 if( r.IsWritable() )
405 m_nMode = StreamMode::READ | StreamMode::WRITE;
406 if( r.GetError() == SVSTREAM_OK )
408 pIo->SetStrm( &r, false );
409 sal_uLong nSize = r.Seek( STREAM_SEEK_TO_END );
410 r.Seek( 0L );
411 // Initializing is OK if the stream is empty
412 Init( nSize == 0 );
413 if( pEntry )
415 pEntry->bDirect = bDirect;
416 pEntry->nMode = m_nMode;
418 pIo->MoveError( *this );
420 else
422 SetError( r.GetError() );
423 pEntry = NULL;
428 Storage::Storage( UCBStorageStream& rStrm, bool bDirect )
429 : OLEStorageBase( new StgIo, NULL, m_nMode ), bIsRoot( false )
431 m_nMode = StreamMode::READ;
433 if ( rStrm.GetError() != SVSTREAM_OK )
435 SetError( rStrm.GetError() );
436 pEntry = NULL;
437 return;
440 SvStream* pStream = rStrm.GetModifySvStream();
441 if ( !pStream )
443 OSL_FAIL( "UCBStorageStream can not provide SvStream implementation!\n" );
444 SetError( SVSTREAM_GENERALERROR );
445 pEntry = NULL;
446 return;
449 if( pStream->IsWritable() )
450 m_nMode = StreamMode::READ | StreamMode::WRITE;
452 pIo->SetStrm( &rStrm );
454 sal_uLong nSize = pStream->Seek( STREAM_SEEK_TO_END );
455 pStream->Seek( 0L );
456 // Initializing is OK if the stream is empty
457 Init( nSize == 0 );
458 if( pEntry )
460 pEntry->bDirect = bDirect;
461 pEntry->nMode = m_nMode;
464 pIo->MoveError( *this );
468 // Perform common code for both ctors above.
470 void Storage::Init( bool bCreate )
472 pEntry = NULL;
473 bool bHdrLoaded = false;
474 bIsRoot = true;
476 OSL_ENSURE( pIo, "The pointer may not be empty at this point!" );
477 if( pIo->Good() && pIo->GetStrm() )
479 sal_uLong nSize = pIo->GetStrm()->Seek( STREAM_SEEK_TO_END );
480 pIo->GetStrm()->Seek( 0L );
481 if( nSize )
483 bHdrLoaded = pIo->Load();
484 if( !bHdrLoaded && !bCreate )
486 // File is not a storage and not empty; do not destroy!
487 SetError( SVSTREAM_FILEFORMAT_ERROR );
488 return;
492 // file is a storage, empty or should be overwritten
493 pIo->ResetError();
494 // we have to set up the data structures, since
495 // the file is empty
496 if( !bHdrLoaded )
497 pIo->Init();
498 if( pIo->Good() && pIo->pTOC )
500 pEntry = pIo->pTOC->GetRoot();
501 pEntry->nRefCnt++;
505 // Internal ctor
507 Storage::Storage( StgIo* p, StgDirEntry* q, StreamMode m )
508 : OLEStorageBase( p, q, m_nMode ), bIsRoot( false )
510 if( q )
511 q->aEntry.GetName( aName );
512 else
513 m &= ~StreamMode(STREAM_READWRITE);
514 m_nMode = m;
515 if( q && q->nRefCnt == 1 )
516 q->nMode = m;
519 Storage::~Storage()
521 // Invalidate all open substorages
522 if( m_bAutoCommit )
523 Commit();
524 if( pEntry )
526 // Do an auto-commit if the entry is open in direct mode
527 if( pEntry->nRefCnt && pEntry->bDirect && (m_nMode & StreamMode::WRITE) )
528 Commit();
529 if( pEntry->nRefCnt == 1 )
530 pEntry->Invalidate();
532 // close the stream is root storage
533 if( bIsRoot )
534 pIo->Close();
535 // remove the file if temporary root storage
536 if( bIsRoot && pEntry && pEntry->bTemp )
538 osl::File::remove( GetName() );
542 const OUString& Storage::GetName() const
544 if( !bIsRoot && Validate() )
545 pEntry->aEntry.GetName( const_cast<Storage*>(this)->aName );
546 return aName;
549 // Fill in the info list for this storage
551 void Storage::FillInfoList( SvStorageInfoList* pList ) const
553 if( Validate() && pList )
555 StgIterator aIter( *pEntry );
556 StgDirEntry* p = aIter.First();
557 while( p )
559 if( !p->bInvalid )
561 SvStorageInfo aInfo( *p );
562 pList->push_back( aInfo );
564 p = aIter.Next();
569 // Open or create a substorage
571 BaseStorage* Storage::OpenUCBStorage( const OUString& rName, StreamMode m, bool bDirect )
573 OSL_FAIL("Not supported!");
574 return OpenStorage( rName, m, bDirect );
577 BaseStorage* Storage::OpenOLEStorage( const OUString& rName, StreamMode m, bool bDirect )
579 return OpenStorage( rName, m, bDirect );
582 BaseStorage* Storage::OpenStorage( const OUString& rName, StreamMode m, bool bDirect )
584 if( !Validate() || !ValidateMode( m ) )
585 return new Storage( pIo, NULL, m );
586 if( bDirect && !pEntry->bDirect )
587 bDirect = false;
589 StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
590 if( !p )
592 if( !( m & StreamMode::NOCREATE ) )
594 bool bTemp = false;
595 // create a new storage
596 OUString aNewName = rName;
597 if( aNewName.isEmpty() )
599 aNewName = "Temp Stg " + OUString::number( ++nTmpCount );
600 bTemp = true;
602 p = pIo->pTOC->Create( *pEntry, aNewName, STG_STORAGE );
603 if( p )
604 p->bTemp = bTemp;
606 if( !p )
607 pIo->SetError( ( m & StreamMode::WRITE )
608 ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
610 else if( !ValidateMode( m, p ) )
611 p = NULL;
612 if( p && p->aEntry.GetType() != STG_STORAGE )
614 pIo->SetError( SVSTREAM_FILE_NOT_FOUND );
615 p = NULL;
618 // Either direct or transacted mode is supported
619 if( p && pEntry->nRefCnt == 1 )
620 p->bDirect = bDirect;
622 // Dont check direct conflict if opening readonly
623 if( p && (m & StreamMode::WRITE ))
625 if( p->bDirect != bDirect )
626 SetError( SVSTREAM_ACCESS_DENIED );
628 Storage* pStg = new Storage( pIo, p, m );
629 pIo->MoveError( *pStg );
630 if( m & StreamMode::WRITE ) pStg->m_bAutoCommit = true;
631 return pStg;
634 // Open a stream
636 BaseStorageStream* Storage::OpenStream( const OUString& rName, StreamMode m, bool,
637 const OString*
638 #ifdef DBG_UTIL
640 #endif
643 DBG_ASSERT(!pB, "Encryption not supported");
645 if( !Validate() || !ValidateMode( m ) )
646 return new StorageStream( pIo, NULL, m );
647 StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
648 bool bTemp = false;
649 if( !p )
651 if( !( m & StreamMode::NOCREATE ) )
653 // create a new stream
654 // make a name if the stream is temporary (has no name)
655 OUString aNewName( rName );
656 if( aNewName.isEmpty() )
658 aNewName = "Temp Strm " + OUString::number( ++nTmpCount );
659 bTemp = true;
661 p = pIo->pTOC->Create( *pEntry, aNewName, STG_STREAM );
663 if( !p )
664 pIo->SetError( ( m & StreamMode::WRITE )
665 ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
667 else if( !ValidateMode( m, p ) )
668 p = NULL;
669 if( p && p->aEntry.GetType() != STG_STREAM )
671 pIo->SetError( SVSTREAM_FILE_NOT_FOUND );
672 p = NULL;
674 if( p )
676 p->bTemp = bTemp;
677 p->bDirect = pEntry->bDirect;
679 StorageStream* pStm = new StorageStream( pIo, p, m );
680 if( p && !p->bDirect )
681 pStm->SetAutoCommit( true );
682 pIo->MoveError( *pStm );
683 return pStm;
686 // Delete a stream or substorage by setting the temp bit.
688 bool Storage::Remove( const OUString& rName )
690 if( !Validate( true ) )
691 return false;
692 StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
693 if( p )
695 p->Invalidate( true );
696 return true;
698 else
700 SetError( SVSTREAM_FILE_NOT_FOUND );
701 return false;
705 // Rename a storage element
707 bool Storage::Rename( const OUString& rOld, const OUString& rNew )
709 if( Validate( true ) )
711 bool b = pIo->pTOC->Rename( *pEntry, rOld, rNew );
712 pIo->MoveError( *this );
713 return b;
715 else
716 return false;
719 // Copy one element
721 bool Storage::CopyTo( const OUString& rElem, BaseStorage* pDest, const OUString& rNew )
723 if( !Validate() || !pDest || !pDest->Validate( true ) )
724 return false;
725 StgDirEntry* pElem = pIo->pTOC->Find( *pEntry, rElem );
726 if( pElem )
728 if( pElem->aEntry.GetType() == STG_STORAGE )
730 // copy the entire storage
731 BaseStorage* p1 = OpenStorage( rElem, INTERNAL_MODE );
732 BaseStorage* p2 = pDest->OpenOLEStorage( rNew, StreamMode::WRITE | StreamMode::SHARE_DENYALL, pEntry->bDirect );
734 if ( p2 )
736 sal_uLong nTmpErr = p2->GetError();
737 if( !nTmpErr )
739 p2->SetClassId( p1->GetClassId() );
740 p1->CopyTo( p2 );
741 SetError( p1->GetError() );
743 nTmpErr = p2->GetError();
744 if( !nTmpErr )
745 p2->Commit();
746 else
747 pDest->SetError( nTmpErr );
749 else
750 pDest->SetError( nTmpErr );
753 delete p1;
754 delete p2;
755 return Good() && pDest->Good();
757 else
759 // stream copy
760 BaseStorageStream* p1 = OpenStream( rElem, INTERNAL_MODE );
761 BaseStorageStream* p2 = pDest->OpenStream( rNew, StreamMode::WRITE | StreamMode::SHARE_DENYALL, pEntry->bDirect );
763 if ( p2 )
765 sal_uLong nTmpErr = p2->GetError();
766 if( !nTmpErr )
768 p1->CopyTo( p2 );
769 SetError( p1->GetError() );
771 nTmpErr = p2->GetError();
772 if( !nTmpErr )
773 p2->Commit();
774 else
775 pDest->SetError( nTmpErr );
777 else
778 pDest->SetError( nTmpErr );
781 delete p1;
782 delete p2;
783 return Good() && pDest->Good();
786 SetError( SVSTREAM_FILE_NOT_FOUND );
787 return false;
790 bool Storage::CopyTo( BaseStorage* pDest ) const
792 if( !Validate() || !pDest || !pDest->Validate( true ) || Equals( *pDest ) )
794 SetError( SVSTREAM_ACCESS_DENIED );
795 return false;
797 Storage* pThis = const_cast<Storage*>(this);
798 pDest->SetClassId( GetClassId() );
799 pDest->SetDirty();
800 SvStorageInfoList aList;
801 FillInfoList( &aList );
802 bool bRes = true;
803 for( size_t i = 0; i < aList.size() && bRes; i++ )
805 SvStorageInfo& rInfo = aList[ i ];
806 bRes = pThis->CopyTo( rInfo.GetName(), pDest, rInfo.GetName() );
808 if( !bRes )
809 SetError( pDest->GetError() );
810 return Good() && pDest->Good();
813 // Move one element
815 bool Storage::MoveTo( const OUString& rElem, BaseStorage* pODest, const OUString& rNew )
817 if( !Validate() || !pODest || !pODest->Validate( true ) || Equals( *pODest ) )
819 SetError( SVSTREAM_ACCESS_DENIED );
820 return false;
823 StgDirEntry* pElem = pIo->pTOC->Find( *pEntry, rElem );
824 if( pElem )
826 // Simplest case: both storages share the same file
827 bool bRes;
828 Storage *pOther = PTR_CAST( Storage, pODest );
829 if( pOther && pIo == pOther->pIo && rElem == rNew )
831 Storage *p = static_cast<Storage*>(pODest);
832 Storage *pDest = p;
833 // both storages are conventional storages, use implementation dependent code
834 if( !pElem->IsContained( pDest->pEntry ) )
836 // cyclic move
837 SetError( SVSTREAM_ACCESS_DENIED );
838 return false;
840 bRes = pIo->pTOC->Move( *pEntry, *pDest->pEntry, rNew );
841 if( !bRes )
843 pIo->MoveError( *this );
844 pDest->pIo->MoveError( *pDest );
845 sal_uLong nErr = GetError();
846 if( !nErr )
847 nErr = pDest->GetError();
848 SetError( nErr );
849 pDest->SetError( nErr );
852 else
854 bRes = CopyTo( rElem, pODest, rNew );
855 if( bRes )
856 bRes = Remove( rElem );
858 if( !bRes )
859 SetError( pIo->GetError() );
860 return bRes;
862 SetError( SVSTREAM_FILE_NOT_FOUND );
863 return false;
866 bool Storage::IsStorage( const OUString& rName ) const
868 if( Validate() )
870 StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
871 if( p )
872 return p->aEntry.GetType() == STG_STORAGE;
874 return false;
877 bool Storage::IsStream( const OUString& rName ) const
879 if( Validate() )
881 StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
882 if( p )
883 return p->aEntry.GetType() == STG_STREAM;
885 return false;
888 bool Storage::IsContained( const OUString& rName ) const
890 if( Validate() )
891 return pIo->pTOC->Find( *pEntry, rName ) != NULL;
892 else
893 return false;
896 // Commit all sub-elements within this storage. If this is
897 // the root, commit the FAT, the TOC and the header as well.
899 bool Storage::Commit()
901 bool bRes = true;
902 if( !Validate() )
903 return false;
904 if( !( m_nMode & StreamMode::WRITE ) )
906 SetError( SVSTREAM_ACCESS_DENIED );
907 return false;
909 else
911 // Also commit the sub-streams and Storages
912 StgIterator aIter( *pEntry );
913 for( StgDirEntry* p = aIter.First(); p && bRes; p = aIter.Next() )
914 bRes = p->Commit();
915 if( bRes && bIsRoot )
917 bRes = pEntry->Commit();
918 if( bRes )
919 bRes = pIo->CommitAll();
921 pIo->MoveError( *this );
923 return bRes;
926 bool Storage::Revert()
928 return true;
931 ///////////////////////////// OLE Support
933 // Set the storage type
935 void Storage::SetClass( const SvGlobalName & rClass,
936 SotClipboardFormatId nOriginalClipFormat,
937 const OUString & rUserTypeName )
939 if( Validate( true ) )
941 // set the class name in the root entry
942 pEntry->aEntry.SetClassId( (const ClsId&) rClass.GetCLSID() );
943 pEntry->SetDirty();
944 // then create the streams
945 StgCompObjStream aCompObj( *this, true );
946 aCompObj.GetClsId() = (const ClsId&) rClass.GetCLSID();
947 aCompObj.GetCbFormat() = nOriginalClipFormat;
948 aCompObj.GetUserName() = rUserTypeName;
949 if( !aCompObj.Store() )
950 SetError( aCompObj.GetError() );
951 else
953 StgOleStream aOle(*this, true);
954 if( !aOle.Store() )
955 SetError( aOle.GetError() );
958 else
959 SetError( SVSTREAM_ACCESS_DENIED );
962 void Storage::SetConvertClass( const SvGlobalName & rConvertClass,
963 SotClipboardFormatId nOriginalClipFormat,
964 const OUString & rUserTypeName )
966 if( Validate( true ) )
968 SetClass( rConvertClass, nOriginalClipFormat, rUserTypeName );
969 // plus the convert flag:
970 StgOleStream aOle( *this, true );
971 aOle.GetFlags() |= 4;
972 if( !aOle.Store() )
973 SetError( aOle.GetError() );
977 SvGlobalName Storage::GetClassName()
979 StgCompObjStream aCompObj( *this, false );
980 if( aCompObj.Load() )
981 return SvGlobalName( aCompObj.GetClsId() );
982 pIo->ResetError();
984 if ( pEntry )
985 return SvGlobalName( pEntry->aEntry.GetClassId() );
987 return SvGlobalName();
990 SotClipboardFormatId Storage::GetFormat()
992 StgCompObjStream aCompObj( *this, false );
993 if( aCompObj.Load() )
994 return aCompObj.GetCbFormat();
995 pIo->ResetError();
996 return SotClipboardFormatId::NONE;
999 OUString Storage::GetUserName()
1001 StgCompObjStream aCompObj( *this, false );
1002 if( aCompObj.Load() )
1003 return aCompObj.GetUserName();
1004 pIo->ResetError();
1005 return OUString();
1008 bool Storage::ShouldConvert()
1010 StgOleStream aOle( *this, false );
1011 if( aOle.Load() )
1012 return ( aOle.GetFlags() & 4 ) != 0;
1013 else
1015 pIo->ResetError();
1016 return false;
1020 bool Storage::ValidateFAT()
1022 Link<> aLink = StgIo::GetErrorLink();
1023 ErrCode nErr = pIo->ValidateFATs();
1024 StgIo::SetErrorLink( aLink );
1025 return nErr == ERRCODE_NONE;
1028 void Storage::SetDirty()
1030 if ( pEntry )
1031 pEntry->SetDirty();
1034 void Storage::SetClassId( const ClsId& rId )
1036 if ( pEntry )
1037 pEntry->aEntry.SetClassId( rId );
1040 const ClsId& Storage::GetClassId() const
1042 if ( pEntry )
1043 return pEntry->aEntry.GetClassId();
1045 static ClsId aDummyId = {0,0,0,{0,0,0,0,0,0,0,0}};
1046 return aDummyId;
1049 const SvStream* Storage::GetSvStream() const
1051 return GetSvStream_Impl();
1054 bool Storage::Validate( bool bValidate ) const
1056 bool bRet = Validate_Impl( bValidate );
1057 if ( !bRet )
1058 SetError( SVSTREAM_ACCESS_DENIED );
1059 return bRet;
1062 bool Storage::ValidateMode( StreamMode nMode ) const
1064 bool bRet = ValidateMode_Impl( nMode );
1065 if ( !bRet )
1066 SetError( SVSTREAM_ACCESS_DENIED );
1067 return bRet;
1070 bool Storage::ValidateMode( StreamMode nMode, StgDirEntry* p ) const
1072 bool bRet = ValidateMode_Impl( nMode, p );
1073 if ( !bRet )
1074 SetError( SVSTREAM_ACCESS_DENIED );
1075 return bRet;
1078 bool Storage::Equals( const BaseStorage& rStorage ) const
1080 const Storage* pOther = PTR_CAST( Storage, &rStorage );
1081 return pOther && ( pOther->pEntry == pEntry );
1085 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */