bump product version to 4.2.0.1
[LibreOffice.git] / sot / source / sdstor / stg.cxx
blob684d36f4b61c75d13e5649450ba5c4e1625921bb
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 <osl/file.hxx>
23 #include <unotools/tempfile.hxx>
24 #include <tools/stream.hxx>
25 #include <tools/debug.hxx>
27 #include "sot/stg.hxx"
28 #include "stgelem.hxx"
29 #include "stgcache.hxx"
30 #include "stgstrms.hxx"
31 #include "stgdir.hxx"
32 #include "stgio.hxx"
33 #include "stgole.hxx"
35 static long nTmpCount = 0;
37 // The internal open mode is STREAM_READ | STREAM_TRUNC, which is silly
38 // by itself. It inhibits the checking of sharing modes and is used
39 // during CopyTo() and MoveTo() for opening a stream in read mode
40 // although it may be open in DENYALL mode
42 #define INTERNAL_MODE ( STREAM_READ | STREAM_TRUNC )
44 ///////////////////////// class StorageBase //////////////////////////////
46 TYPEINIT0( StorageBase );
47 TYPEINIT1( BaseStorageStream, StorageBase );
48 TYPEINIT1( BaseStorage, StorageBase );
50 StorageBase::StorageBase()
51 : m_bAutoCommit( false )
53 m_nMode = STREAM_READ;
54 m_nError = SVSTREAM_OK;
57 StorageBase::~StorageBase()
61 // The following three methods are declared as const, since they
62 // may be called from within a const method.
64 sal_uLong StorageBase::GetError() const
66 sal_uLong n = m_nError;
67 ((StorageBase*) this)->m_nError = SVSTREAM_OK;
68 return n;
71 void StorageBase::SetError( sal_uLong n ) const
73 if( !m_nError )
74 ((StorageBase*) this)->m_nError = n;
77 void StorageBase::ResetError() const
79 ((StorageBase*) this)->m_nError = SVSTREAM_OK;
82 // Retrieve the underlying SvStream for info purposes
84 const SvStream* OLEStorageBase::GetSvStream_Impl() const
86 return pIo ? pIo->GetStrm() : NULL;
89 OLEStorageBase::OLEStorageBase( StgIo* p, StgDirEntry* pe, StreamMode& nMode )
90 : nStreamMode( nMode ), pIo( p ), pEntry( pe )
92 if ( p )
93 p->IncRef();
94 if( pe )
95 pe->nRefCnt++;
98 OLEStorageBase::~OLEStorageBase()
100 if( pEntry )
102 DBG_ASSERT( pEntry->nRefCnt, "RefCount unter 0" );
103 if( !--pEntry->nRefCnt )
105 if( pEntry->bZombie )
106 delete pEntry;
107 else
108 pEntry->Close();
111 pEntry = NULL;
115 if( pIo && !pIo->DecRef() )
117 delete pIo;
118 pIo = NULL;
122 // Validate the instance for I/O
124 bool OLEStorageBase::Validate_Impl( bool bWrite ) const
126 if( pIo
127 && pIo->pTOC
128 && pEntry
129 && !pEntry->bInvalid
130 && ( !bWrite || !pEntry->bDirect || ( nStreamMode & STREAM_WRITE ) ) )
131 return true;
132 return false;
135 bool OLEStorageBase::ValidateMode_Impl( StreamMode m, StgDirEntry* p ) const
137 if( m == INTERNAL_MODE )
138 return true;
139 sal_uInt16 nCurMode = ( p && p->nRefCnt ) ? p->nMode : 0xFFFF;
140 if( ( m & 3 ) == STREAM_READ )
142 // only SHARE_DENYWRITE or SHARE_DENYALL allowed
143 if( ( ( m & STREAM_SHARE_DENYWRITE )
144 && ( nCurMode & STREAM_SHARE_DENYWRITE ) )
145 || ( ( m & STREAM_SHARE_DENYALL )
146 && ( nCurMode & STREAM_SHARE_DENYALL ) ) )
147 return true;
149 else
151 // only SHARE_DENYALL allowed
152 // storages open in r/o mode are OK, since only
153 // the commit may fail
154 if( ( m & STREAM_SHARE_DENYALL )
155 && ( nCurMode & STREAM_SHARE_DENYALL ) )
156 return true;
158 return false;
162 //////////////////////// class StorageStream /////////////////////////////
164 TYPEINIT1( StorageStream, BaseStorageStream );
166 StorageStream::StorageStream( StgIo* p, StgDirEntry* q, StreamMode m )
167 : OLEStorageBase( p, q, m_nMode ), nPos( 0L )
169 // The dir entry may be 0; this means that the stream is invalid.
170 if( q && p )
172 if( q->nRefCnt == 1 )
174 q->nMode = m;
175 q->OpenStream( *p );
178 else
179 m &= ~STREAM_READWRITE;
180 m_nMode = m;
183 StorageStream::~StorageStream()
185 // Do an auto-commit if the entry is open in direct mode
186 if( m_bAutoCommit )
187 Commit();
188 if( pEntry && pEntry->nRefCnt && pEntry->bDirect && (m_nMode & STREAM_WRITE) )
189 pEntry->Commit();
192 bool StorageStream::Equals( const BaseStorageStream& rStream ) const
194 const StorageStream* pOther = PTR_CAST( StorageStream, &rStream );
195 return pOther && ( pOther->pEntry == pEntry );
198 sal_uLong StorageStream::Read( void* pData, sal_uLong nSize )
200 if( Validate() )
202 pEntry->Seek( nPos );
203 nSize = pEntry->Read( pData, (sal_Int32) nSize );
204 pIo->MoveError( *this );
205 nPos += nSize;
207 else
208 nSize = 0L;
209 return nSize;
212 sal_uLong StorageStream::Write( const void* pData, sal_uLong nSize )
214 if( Validate( true ) )
216 pEntry->Seek( nPos );
217 nSize = pEntry->Write( pData, (sal_Int32) nSize );
218 pIo->MoveError( *this );
219 nPos += nSize;
221 else
222 nSize = 0L;
223 return nSize;
226 sal_uLong StorageStream::Seek( sal_uLong n )
228 if( Validate() )
229 return nPos = pEntry->Seek( n );
230 else
231 return n;
234 void StorageStream::Flush()
236 // Flushing means committing, since streams are never transacted
237 Commit();
240 bool StorageStream::SetSize( sal_uLong nNewSize )
242 if( Validate( true ) )
244 bool b = pEntry->SetSize( (sal_Int32) nNewSize );
245 pIo->MoveError( *this );
246 return b;
248 else
249 return false;
252 sal_uLong StorageStream::GetSize() const
254 if( Validate() )
255 return pEntry->GetSize();
256 return 0;
259 bool StorageStream::Commit()
261 if( !Validate() )
262 return false;
263 if( !( m_nMode & STREAM_WRITE ) )
265 SetError( SVSTREAM_ACCESS_DENIED );
266 return false;
268 else
270 pEntry->Commit();
271 pIo->MoveError( *this );
272 return Good();
276 bool StorageStream::Revert()
278 bool bResult = false;
280 if ( Validate() )
282 pEntry->Revert();
283 pIo->MoveError( *this );
284 bResult = Good();
287 return bResult;
290 bool StorageStream::CopyTo( BaseStorageStream* pDest )
292 if( !Validate() || !pDest || !pDest->Validate( true ) || Equals( *pDest ) )
293 return false;
294 pEntry->Copy( *pDest );
295 pDest->Commit();
296 pIo->MoveError( *this );
297 SetError( pDest->GetError() );
298 return Good() && pDest->Good();
301 const SvStream* StorageStream::GetSvStream() const
303 return GetSvStream_Impl();
306 bool StorageStream::Validate( bool bValidate ) const
308 bool bRet = Validate_Impl( bValidate );
309 if ( !bRet )
310 SetError( SVSTREAM_ACCESS_DENIED );
311 return bRet;
314 bool StorageStream::ValidateMode( StreamMode nMode ) const
316 bool bRet = ValidateMode_Impl( nMode, NULL );
317 if ( !bRet )
318 SetError( SVSTREAM_ACCESS_DENIED );
319 return bRet;
322 ///////////////////////// class SvStorageInfo //////////////////////////////
324 SvStorageInfo::SvStorageInfo( const StgDirEntry& rE )
326 rE.aEntry.GetName( aName );
327 bStorage = rE.aEntry.GetType() == STG_STORAGE;
328 bStream = rE.aEntry.GetType() == STG_STREAM;
329 nSize = bStorage ? 0 : rE.aEntry.GetSize();
332 /////////////////////////// class Storage ////////////////////////////////
334 bool Storage::IsStorageFile( const OUString & rFileName )
336 StgIo aIo;
337 if( aIo.Open( rFileName, STREAM_STD_READ ) )
338 return aIo.Load();
339 return false;
342 bool Storage::IsStorageFile( SvStream* pStream )
344 bool bRet = false;
346 if ( pStream )
348 StgHeader aHdr;
349 sal_uLong nPos = pStream->Tell();
350 bRet = ( aHdr.Load( *pStream ) && aHdr.Check() );
352 // It's not a stream error if it is too small for a OLE storage header
353 if ( pStream->GetErrorCode() == ERRCODE_IO_CANTSEEK )
354 pStream->ResetError();
355 pStream->Seek( nPos );
358 return bRet;
361 // Open the storage file. If writing is permitted and the file is not
362 // a storage file, initialize it.
364 TYPEINIT1( Storage, BaseStorage );
366 Storage::Storage( const OUString& rFile, StreamMode m, bool bDirect )
367 : OLEStorageBase( new StgIo, NULL, m_nMode )
368 , aName( rFile ), bIsRoot( false )
370 bool bTemp = false;
371 if( aName.isEmpty() )
373 // no name = temporary name!
374 aName = utl::TempFile::CreateTempName();
375 bTemp = true;
377 // the root storage creates the I/O system
378 m_nMode = m;
379 if( pIo->Open( aName, m ) )
381 Init( ( m & ( STREAM_TRUNC | STREAM_NOCREATE ) ) == STREAM_TRUNC );
382 if( pEntry )
384 pEntry->bDirect = bDirect;
385 pEntry->nMode = m;
386 pEntry->bTemp = bTemp;
389 else
391 pIo->MoveError( *this );
392 pEntry = NULL;
396 // Create a storage on a given stream.
398 Storage::Storage( SvStream& r, bool bDirect )
399 : OLEStorageBase( new StgIo, NULL, m_nMode )
400 , bIsRoot( false )
402 m_nMode = STREAM_READ;
403 if( r.IsWritable() )
404 m_nMode = STREAM_READ | STREAM_WRITE;
405 if( r.GetError() == SVSTREAM_OK )
407 pIo->SetStrm( &r, false );
408 sal_uLong nSize = r.Seek( STREAM_SEEK_TO_END );
409 r.Seek( 0L );
410 // Initializing is OK if the stream is empty
411 Init( nSize == 0 );
412 if( pEntry )
414 pEntry->bDirect = bDirect;
415 pEntry->nMode = m_nMode;
417 pIo->MoveError( *this );
419 else
421 SetError( r.GetError() );
422 pEntry = NULL;
427 Storage::Storage( UCBStorageStream& rStrm, bool bDirect )
428 : OLEStorageBase( new StgIo, NULL, m_nMode ), bIsRoot( false )
430 m_nMode = STREAM_READ;
432 if ( rStrm.GetError() != SVSTREAM_OK )
434 SetError( rStrm.GetError() );
435 pEntry = NULL;
436 return;
439 SvStream* pStream = rStrm.GetModifySvStream();
440 if ( !pStream )
442 OSL_FAIL( "UCBStorageStream can not provide SvStream implementation!\n" );
443 SetError( SVSTREAM_GENERALERROR );
444 pEntry = NULL;
445 return;
448 if( pStream->IsWritable() )
449 m_nMode = STREAM_READ | STREAM_WRITE;
451 pIo->SetStrm( &rStrm );
453 sal_uLong nSize = pStream->Seek( STREAM_SEEK_TO_END );
454 pStream->Seek( 0L );
455 // Initializing is OK if the stream is empty
456 Init( nSize == 0 );
457 if( pEntry )
459 pEntry->bDirect = bDirect;
460 pEntry->nMode = m_nMode;
463 pIo->MoveError( *this );
467 // Perform common code for both ctors above.
469 void Storage::Init( bool bCreate )
471 pEntry = NULL;
472 bool bHdrLoaded = false;
473 bIsRoot = true;
475 OSL_ENSURE( pIo, "The pointer may not be empty at this point!" );
476 if( pIo->Good() && pIo->GetStrm() )
478 sal_uLong nSize = pIo->GetStrm()->Seek( STREAM_SEEK_TO_END );
479 pIo->GetStrm()->Seek( 0L );
480 if( nSize )
482 bHdrLoaded = pIo->Load();
483 if( !bHdrLoaded && !bCreate )
485 // File is not a storage and not empty; do not destroy!
486 SetError( SVSTREAM_FILEFORMAT_ERROR );
487 return;
491 // file is a storage, empty or should be overwritten
492 pIo->ResetError();
493 // we have to set up the data structures, since
494 // the file is empty
495 if( !bHdrLoaded )
496 pIo->Init();
497 if( pIo->Good() && pIo->pTOC )
499 pEntry = pIo->pTOC->GetRoot();
500 pEntry->nRefCnt++;
504 // Internal ctor
506 Storage::Storage( StgIo* p, StgDirEntry* q, StreamMode m )
507 : OLEStorageBase( p, q, m_nMode ), bIsRoot( false )
509 if( q )
510 q->aEntry.GetName( aName );
511 else
512 m &= ~STREAM_READWRITE;
513 m_nMode = m;
514 if( q && q->nRefCnt == 1 )
515 q->nMode = m;
518 Storage::~Storage()
520 // Invalidate all open substorages
521 if( m_bAutoCommit )
522 Commit();
523 if( pEntry )
525 // Do an auto-commit if the entry is open in direct mode
526 if( pEntry->nRefCnt && pEntry->bDirect && (m_nMode & STREAM_WRITE) )
527 Commit();
528 if( pEntry->nRefCnt == 1 )
529 pEntry->Invalidate();
531 // close the stream is root storage
532 if( bIsRoot )
533 pIo->Close();
534 // remove the file if temporary root storage
535 if( bIsRoot && pEntry && pEntry->bTemp )
537 osl::File::remove( GetName() );
541 const OUString& Storage::GetName() const
543 if( !bIsRoot && Validate() )
544 pEntry->aEntry.GetName( ((Storage*) this)->aName );
545 return aName;
548 // Fill in the info list for this storage
550 void Storage::FillInfoList( SvStorageInfoList* pList ) const
552 if( Validate() && pList )
554 StgIterator aIter( *pEntry );
555 StgDirEntry* p = aIter.First();
556 while( p )
558 if( !p->bInvalid )
560 SvStorageInfo aInfo( *p );
561 pList->push_back( aInfo );
563 p = aIter.Next();
568 // Open or create a substorage
570 BaseStorage* Storage::OpenUCBStorage( const OUString& rName, StreamMode m, bool bDirect )
572 OSL_FAIL("Not supported!");
573 return OpenStorage( rName, m, bDirect );
576 BaseStorage* Storage::OpenOLEStorage( const OUString& rName, StreamMode m, bool bDirect )
578 return OpenStorage( rName, m, bDirect );
581 BaseStorage* Storage::OpenStorage( const OUString& rName, StreamMode m, bool bDirect )
583 if( !Validate() || !ValidateMode( m ) )
584 return new Storage( pIo, NULL, m );
585 if( bDirect && !pEntry->bDirect )
586 bDirect = false;
588 StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
589 if( !p )
591 if( !( m & STREAM_NOCREATE ) )
593 bool bTemp = false;
594 // create a new storage
595 OUString aNewName = rName;
596 if( aNewName.isEmpty() )
598 aNewName = "Temp Stg " + OUString::number( ++nTmpCount );
599 bTemp = true;
601 p = pIo->pTOC->Create( *pEntry, aNewName, STG_STORAGE );
602 if( p )
603 p->bTemp = bTemp;
605 if( !p )
606 pIo->SetError( ( m & STREAM_WRITE )
607 ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
609 else if( !ValidateMode( m, p ) )
610 p = NULL;
611 if( p && p->aEntry.GetType() != STG_STORAGE )
613 pIo->SetError( SVSTREAM_FILE_NOT_FOUND );
614 p = NULL;
617 // Either direct or transacted mode is supported
618 if( p && pEntry->nRefCnt == 1 )
619 p->bDirect = bDirect;
621 // Dont check direct conflict if opening readonly
622 if( p && (m & STREAM_WRITE ))
624 if( p->bDirect != bDirect )
625 SetError( SVSTREAM_ACCESS_DENIED );
627 Storage* pStg = new Storage( pIo, p, m );
628 pIo->MoveError( *pStg );
629 if( m & STREAM_WRITE ) pStg->m_bAutoCommit = true;
630 return pStg;
633 // Open a stream
635 BaseStorageStream* Storage::OpenStream( const OUString& rName, StreamMode m, bool,
636 const OString*
637 #ifdef DBG_UTIL
639 #endif
642 DBG_ASSERT(!pB, "Encryption not supported");
644 if( !Validate() || !ValidateMode( m ) )
645 return new StorageStream( pIo, NULL, m );
646 StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
647 bool bTemp = false;
648 if( !p )
650 if( !( m & STREAM_NOCREATE ) )
652 // create a new stream
653 // make a name if the stream is temporary (has no name)
654 OUString aNewName( rName );
655 if( aNewName.isEmpty() )
657 aNewName = "Temp Strm " + OUString::number( ++nTmpCount );
658 bTemp = true;
660 p = pIo->pTOC->Create( *pEntry, aNewName, STG_STREAM );
662 if( !p )
663 pIo->SetError( ( m & STREAM_WRITE )
664 ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
666 else if( !ValidateMode( m, p ) )
667 p = NULL;
668 if( p && p->aEntry.GetType() != STG_STREAM )
670 pIo->SetError( SVSTREAM_FILE_NOT_FOUND );
671 p = NULL;
673 if( p )
675 p->bTemp = bTemp;
676 p->bDirect = pEntry->bDirect;
678 StorageStream* pStm = new StorageStream( pIo, p, m );
679 if( p && !p->bDirect )
680 pStm->SetAutoCommit( true );
681 pIo->MoveError( *pStm );
682 return pStm;
685 // Delete a stream or substorage by setting the temp bit.
687 bool Storage::Remove( const OUString& rName )
689 if( !Validate( true ) )
690 return false;
691 StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
692 if( p )
694 p->Invalidate( true );
695 return true;
697 else
699 SetError( SVSTREAM_FILE_NOT_FOUND );
700 return false;
704 // Rename a storage element
706 bool Storage::Rename( const OUString& rOld, const OUString& rNew )
708 if( Validate( true ) )
710 bool b = pIo->pTOC->Rename( *pEntry, rOld, rNew );
711 pIo->MoveError( *this );
712 return b;
714 else
715 return false;
718 // Copy one element
720 bool Storage::CopyTo( const OUString& rElem, BaseStorage* pDest, const OUString& rNew )
722 if( !Validate() || !pDest || !pDest->Validate( true ) )
723 return false;
724 StgDirEntry* pElem = pIo->pTOC->Find( *pEntry, rElem );
725 if( pElem )
727 if( pElem->aEntry.GetType() == STG_STORAGE )
729 // copy the entire storage
730 BaseStorage* p1 = OpenStorage( rElem, INTERNAL_MODE );
731 BaseStorage* p2 = pDest->OpenOLEStorage( rNew, STREAM_WRITE | STREAM_SHARE_DENYALL, pEntry->bDirect );
733 if ( p2 )
735 sal_uLong nTmpErr = p2->GetError();
736 if( !nTmpErr )
738 p2->SetClassId( p1->GetClassId() );
739 p1->CopyTo( p2 );
740 SetError( p1->GetError() );
742 nTmpErr = p2->GetError();
743 if( !nTmpErr )
744 p2->Commit();
745 else
746 pDest->SetError( nTmpErr );
748 else
749 pDest->SetError( nTmpErr );
752 delete p1;
753 delete p2;
754 return Good() && pDest->Good();
756 else
758 // stream copy
759 BaseStorageStream* p1 = OpenStream( rElem, INTERNAL_MODE );
760 BaseStorageStream* p2 = pDest->OpenStream( rNew, STREAM_WRITE | STREAM_SHARE_DENYALL, pEntry->bDirect );
762 if ( p2 )
764 sal_uLong nTmpErr = p2->GetError();
765 if( !nTmpErr )
767 p1->CopyTo( p2 );
768 SetError( p1->GetError() );
770 nTmpErr = p2->GetError();
771 if( !nTmpErr )
772 p2->Commit();
773 else
774 pDest->SetError( nTmpErr );
776 else
777 pDest->SetError( nTmpErr );
780 delete p1;
781 delete p2;
782 return Good() && pDest->Good();
785 SetError( SVSTREAM_FILE_NOT_FOUND );
786 return false;
789 bool Storage::CopyTo( BaseStorage* pDest ) const
791 if( !Validate() || !pDest || !pDest->Validate( true ) || Equals( *pDest ) )
793 SetError( SVSTREAM_ACCESS_DENIED );
794 return false;
796 Storage* pThis = (Storage*) this;
797 pDest->SetClassId( GetClassId() );
798 pDest->SetDirty();
799 SvStorageInfoList aList;
800 FillInfoList( &aList );
801 bool bRes = true;
802 for( size_t i = 0; i < aList.size() && bRes; i++ )
804 SvStorageInfo& rInfo = aList[ i ];
805 bRes = pThis->CopyTo( rInfo.GetName(), pDest, rInfo.GetName() );
807 if( !bRes )
808 SetError( pDest->GetError() );
809 return Good() && pDest->Good();
812 // Move one element
814 bool Storage::MoveTo( const OUString& rElem, BaseStorage* pODest, const OUString& rNew )
816 if( !Validate() || !pODest || !pODest->Validate( true ) || Equals( *pODest ) )
818 SetError( SVSTREAM_ACCESS_DENIED );
819 return false;
822 StgDirEntry* pElem = pIo->pTOC->Find( *pEntry, rElem );
823 if( pElem )
825 // Simplest case: both storages share the same file
826 bool bRes;
827 Storage *pOther = PTR_CAST( Storage, pODest );
828 if( pOther && pIo == pOther->pIo && rElem == rNew )
830 Storage *p = (Storage*) pODest;
831 Storage *pDest = p;
832 // both storages are conventional storages, use implementation dependent code
833 if( !pElem->IsContained( pDest->pEntry ) )
835 // cyclic move
836 SetError( SVSTREAM_ACCESS_DENIED );
837 return false;
839 bRes = pIo->pTOC->Move( *pEntry, *pDest->pEntry, rNew );
840 if( !bRes )
842 pIo->MoveError( *this );
843 pDest->pIo->MoveError( *pDest );
844 sal_uLong nErr = GetError();
845 if( !nErr )
846 nErr = pDest->GetError();
847 SetError( nErr );
848 pDest->SetError( nErr );
851 else
853 bRes = CopyTo( rElem, pODest, rNew );
854 if( bRes )
855 bRes = Remove( rElem );
857 if( !bRes )
858 SetError( pIo->GetError() );
859 return bRes;
861 SetError( SVSTREAM_FILE_NOT_FOUND );
862 return false;
865 bool Storage::IsStorage( const OUString& rName ) const
867 if( Validate() )
869 StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
870 if( p )
871 return p->aEntry.GetType() == STG_STORAGE;
873 return false;
876 bool Storage::IsStream( const OUString& rName ) const
878 if( Validate() )
880 StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
881 if( p )
882 return p->aEntry.GetType() == STG_STREAM;
884 return false;
887 bool Storage::IsContained( const OUString& rName ) const
889 if( Validate() )
890 return pIo->pTOC->Find( *pEntry, rName ) != NULL;
891 else
892 return false;
895 // Commit all sub-elements within this storage. If this is
896 // the root, commit the FAT, the TOC and the header as well.
898 bool Storage::Commit()
900 bool bRes = true;
901 if( !Validate() )
902 return false;
903 if( !( m_nMode & STREAM_WRITE ) )
905 SetError( SVSTREAM_ACCESS_DENIED );
906 return false;
908 else
910 // Also commit the sub-streams and Storages
911 StgIterator aIter( *pEntry );
912 for( StgDirEntry* p = aIter.First(); p && bRes; p = aIter.Next() )
913 bRes = p->Commit();
914 if( bRes && bIsRoot )
916 bRes = pEntry->Commit();
917 if( bRes )
918 bRes = pIo->CommitAll();
920 pIo->MoveError( *this );
922 return bRes;
925 bool Storage::Revert()
927 return true;
930 ///////////////////////////// OLE Support ////////////////////////////////
932 // Set the storage type
934 void Storage::SetClass( const SvGlobalName & rClass,
935 sal_uLong nOriginalClipFormat,
936 const OUString & rUserTypeName )
938 if( Validate( true ) )
940 // set the class name in the root entry
941 pEntry->aEntry.SetClassId( (const ClsId&) rClass.GetCLSID() );
942 pEntry->SetDirty();
943 // then create the streams
944 StgCompObjStream aCompObj( *this, true );
945 aCompObj.GetClsId() = (const ClsId&) rClass.GetCLSID();
946 aCompObj.GetCbFormat() = nOriginalClipFormat;
947 aCompObj.GetUserName() = rUserTypeName;
948 if( !aCompObj.Store() )
949 SetError( aCompObj.GetError() );
950 else
952 StgOleStream aOle(*this, true);
953 if( !aOle.Store() )
954 SetError( aOle.GetError() );
957 else
958 SetError( SVSTREAM_ACCESS_DENIED );
961 void Storage::SetConvertClass( const SvGlobalName & rConvertClass,
962 sal_uLong nOriginalClipFormat,
963 const OUString & rUserTypeName )
965 if( Validate( true ) )
967 SetClass( rConvertClass, nOriginalClipFormat, rUserTypeName );
968 // plus the convert flag:
969 StgOleStream aOle( *this, true );
970 aOle.GetFlags() |= 4;
971 if( !aOle.Store() )
972 SetError( aOle.GetError() );
976 SvGlobalName Storage::GetClassName()
978 StgCompObjStream aCompObj( *this, false );
979 if( aCompObj.Load() )
980 return SvGlobalName( (const CLSID&) aCompObj.GetClsId() );
981 pIo->ResetError();
983 if ( pEntry )
984 return SvGlobalName( (const CLSID&) pEntry->aEntry.GetClassId() );
986 return SvGlobalName();
989 sal_uLong Storage::GetFormat()
991 StgCompObjStream aCompObj( *this, false );
992 if( aCompObj.Load() )
993 return aCompObj.GetCbFormat();
994 pIo->ResetError();
995 return 0;
998 OUString Storage::GetUserName()
1000 StgCompObjStream aCompObj( *this, false );
1001 if( aCompObj.Load() )
1002 return aCompObj.GetUserName();
1003 pIo->ResetError();
1004 return OUString();
1007 bool Storage::ShouldConvert()
1009 StgOleStream aOle( *this, false );
1010 if( aOle.Load() )
1011 return ( aOle.GetFlags() & 4 ) != 0;
1012 else
1014 pIo->ResetError();
1015 return false;
1019 bool Storage::ValidateFAT()
1021 Link aLink = StgIo::GetErrorLink();
1022 ErrCode nErr = pIo->ValidateFATs();
1023 StgIo::SetErrorLink( aLink );
1024 return nErr == ERRCODE_NONE;
1027 void Storage::SetDirty()
1029 if ( pEntry )
1030 pEntry->SetDirty();
1033 void Storage::SetClassId( const ClsId& rId )
1035 if ( pEntry )
1036 pEntry->aEntry.SetClassId( rId );
1039 const ClsId& Storage::GetClassId() const
1041 if ( pEntry )
1042 return pEntry->aEntry.GetClassId();
1044 static ClsId aDummyId = {0,0,0,0,0,0,0,0,0,0,0};
1045 return aDummyId;
1048 const SvStream* Storage::GetSvStream() const
1050 return GetSvStream_Impl();
1053 bool Storage::Validate( bool bValidate ) const
1055 bool bRet = Validate_Impl( bValidate );
1056 if ( !bRet )
1057 SetError( SVSTREAM_ACCESS_DENIED );
1058 return bRet;
1061 bool Storage::ValidateMode( StreamMode nMode ) const
1063 bool bRet = ValidateMode_Impl( nMode );
1064 if ( !bRet )
1065 SetError( SVSTREAM_ACCESS_DENIED );
1066 return bRet;
1069 bool Storage::ValidateMode( StreamMode nMode, StgDirEntry* p ) const
1071 bool bRet = ValidateMode_Impl( nMode, p );
1072 if ( !bRet )
1073 SetError( SVSTREAM_ACCESS_DENIED );
1074 return bRet;
1077 bool Storage::Equals( const BaseStorage& rStorage ) const
1079 const Storage* pOther = PTR_CAST( Storage, &rStorage );
1080 return pOther && ( pOther->pEntry == pEntry );
1084 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */