update dev300-m58
[ooovba.git] / sot / source / sdstor / stg.cxx
blobeca15bb42698a27e753c365f7466d62d91579de6
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: stg.cxx,v $
10 * $Revision: 1.18 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sot.hxx"
34 #include <storinfo.hxx>
35 #include <osl/file.hxx>
36 #include <tools/tempfile.hxx>
37 #include <tools/ownlist.hxx>
38 #include <tools/string.hxx>
39 #ifndef _TOOLS_FSYS_HXX
40 #include <tools/fsys.hxx>
41 #endif
42 #ifndef _TOOLS_STREAM_HXX
43 #include <tools/stream.hxx>
44 #endif
45 #include <tools/pstm.hxx>
46 #include <tools/debug.hxx>
48 #include "stg.hxx"
49 #include "stgelem.hxx"
50 #include "stgcache.hxx"
51 #include "stgstrms.hxx"
52 #include "stgdir.hxx"
53 #include "stgio.hxx"
54 #include "stgole.hxx"
56 static long nTmpCount = 0;
58 // The internal open mode is STREAM_READ | STREAM_TRUNC, which is silly
59 // by itself. It inhibits the checking of sharing modes and is used
60 // during CopyTo() and MoveTo() for opening a stream in read mode
61 // although it may be open in DENYALL mode
63 #define INTERNAL_MODE ( STREAM_READ | STREAM_TRUNC )
65 ///////////////////////// class StorageBase //////////////////////////////
67 TYPEINIT0( StorageBase );
68 TYPEINIT1( BaseStorageStream, StorageBase );
69 TYPEINIT1( BaseStorage, StorageBase );
71 StorageBase::StorageBase()
72 : m_bAutoCommit( FALSE )
74 m_nMode = STREAM_READ;
75 m_nError = SVSTREAM_OK;
78 StorageBase::~StorageBase()
82 // The following three methods are declared as const, since they
83 // may be called from within a const method.
85 ULONG StorageBase::GetError() const
87 ULONG n = m_nError;
88 ((StorageBase*) this)->m_nError = SVSTREAM_OK;
89 return n;
92 void StorageBase::SetError( ULONG n ) const
94 if( !m_nError )
95 ((StorageBase*) this)->m_nError = n;
98 void StorageBase::ResetError() const
100 ((StorageBase*) this)->m_nError = SVSTREAM_OK;
103 // Retrieve the underlying SvStream for info purposes
105 const SvStream* OLEStorageBase::GetSvStream_Impl() const
107 return pIo ? pIo->GetStrm() : NULL;
110 OLEStorageBase::OLEStorageBase( StgIo* p, StgDirEntry* pe, StreamMode& nMode )
111 : nStreamMode( nMode ), pIo( p ), pEntry( pe )
113 p->IncRef();
114 if( pe )
115 pe->nRefCnt++;
118 OLEStorageBase::~OLEStorageBase()
120 if( pEntry )
122 DBG_ASSERT( pEntry->nRefCnt, "RefCount unter 0" );
123 if( !--pEntry->nRefCnt )
125 if( pEntry->bZombie )
126 delete pEntry;
127 else
128 pEntry->Close();
133 if( !pIo->DecRef() )
134 delete pIo;
137 // Validate the instance for I/O
139 BOOL OLEStorageBase::Validate_Impl( BOOL bWrite ) const
141 if( pEntry
142 && !pEntry->bInvalid
143 && ( !bWrite || !pEntry->bDirect || ( nStreamMode & STREAM_WRITE ) ) )
144 return TRUE;
145 return FALSE;
148 BOOL OLEStorageBase::ValidateMode_Impl( StreamMode m, StgDirEntry* p ) const
150 if( m == INTERNAL_MODE )
151 return TRUE;
152 USHORT nCurMode = ( p && p->nRefCnt ) ? p->nMode : 0xFFFF;
153 if( ( m & 3 ) == STREAM_READ )
155 // only SHARE_DENYWRITE or SHARE_DENYALL allowed
156 if( ( ( m & STREAM_SHARE_DENYWRITE )
157 && ( nCurMode & STREAM_SHARE_DENYWRITE ) )
158 || ( ( m & STREAM_SHARE_DENYALL )
159 && ( nCurMode & STREAM_SHARE_DENYALL ) ) )
160 return TRUE;
162 else
164 // only SHARE_DENYALL allowed
165 // storages open in r/o mode are OK, since only
166 // the commit may fail
167 if( ( m & STREAM_SHARE_DENYALL )
168 && ( nCurMode & STREAM_SHARE_DENYALL ) )
169 return TRUE;
171 return FALSE;
175 //////////////////////// class StorageStream /////////////////////////////
177 TYPEINIT1( StorageStream, BaseStorageStream );
179 StorageStream::StorageStream( StgIo* p, StgDirEntry* q, StreamMode m )
180 : OLEStorageBase( p, q, m_nMode ), nPos( 0L )
182 // The dir entry may be 0; this means that the stream is invalid.
183 if( q )
185 if( q->nRefCnt == 1 )
187 q->nMode = m;
188 q->OpenStream( *p );
191 else
192 m &= ~STREAM_READWRITE;
193 m_nMode = m;
196 StorageStream::~StorageStream()
198 // Do an auto-commit if the entry is open in direct mode
199 if( m_bAutoCommit )
200 Commit();
201 if( pEntry && pEntry->nRefCnt && pEntry->bDirect && (m_nMode & STREAM_WRITE) )
202 pEntry->Commit();
205 BOOL StorageStream::Equals( const BaseStorageStream& rStream ) const
207 const StorageStream* pOther = PTR_CAST( StorageStream, &rStream );
208 return pOther && ( pOther->pEntry == pEntry );
211 ULONG StorageStream::Read( void* pData, ULONG nSize )
213 if( Validate() )
215 pEntry->Seek( nPos );
216 nSize = pEntry->Read( pData, (INT32) nSize );
217 pIo->MoveError( *this );
218 nPos += nSize;
220 else
221 nSize = 0L;
222 return nSize;
225 ULONG StorageStream::Write( const void* pData, ULONG nSize )
227 if( Validate( TRUE ) )
229 pEntry->Seek( nPos );
230 nSize = pEntry->Write( pData, (INT32) nSize );
231 pIo->MoveError( *this );
232 nPos += nSize;
234 else
235 nSize = 0L;
236 return nSize;
239 ULONG StorageStream::Seek( ULONG n )
241 if( Validate() )
242 return nPos = pEntry->Seek( n );
243 else
244 return n;
247 void StorageStream::Flush()
249 // Flushing means committing, since streams are never transacted
250 Commit();
253 BOOL StorageStream::SetSize( ULONG nNewSize )
255 if( Validate( TRUE ) )
257 BOOL b = pEntry->SetSize( (INT32) nNewSize );
258 pIo->MoveError( *this );
259 return b;
261 else
262 return FALSE;
265 BOOL StorageStream::Commit()
267 if( !Validate() )
268 return FALSE;
269 if( !( m_nMode & STREAM_WRITE ) )
271 SetError( SVSTREAM_ACCESS_DENIED );
272 return FALSE;
274 else
276 pEntry->Commit();
277 pIo->MoveError( *this );
278 return Good();
282 BOOL StorageStream::Revert()
284 pEntry->Revert();
285 pIo->MoveError( *this );
286 return Good();
289 BOOL StorageStream::CopyTo( BaseStorageStream* pDest )
291 if( !Validate() || !pDest->Validate( TRUE ) || Equals( *pDest ) )
292 return FALSE;
293 pEntry->Copy( *pDest );
294 pDest->Commit();
295 pIo->MoveError( *this );
296 SetError( pDest->GetError() );
297 return BOOL( Good() && pDest->Good() );
300 const SvStream* StorageStream::GetSvStream() const
302 return GetSvStream_Impl();
305 BOOL StorageStream::Validate( BOOL bValidate ) const
307 BOOL bRet = Validate_Impl( bValidate );
308 if ( !bRet )
309 SetError( SVSTREAM_ACCESS_DENIED );
310 return bRet;
313 BOOL StorageStream::ValidateMode( StreamMode nMode ) const
315 BOOL bRet = ValidateMode_Impl( nMode, NULL );
316 if ( !bRet )
317 SetError( SVSTREAM_ACCESS_DENIED );
318 return bRet;
321 BOOL StorageStream::ValidateMode( StreamMode nMode, StgDirEntry* p ) const
323 BOOL bRet = ValidateMode_Impl( nMode, p );
324 if ( !bRet )
325 SetError( SVSTREAM_ACCESS_DENIED );
326 return bRet;
329 ///////////////////////// class SvStorageInfo //////////////////////////////
331 SvStorageInfo::SvStorageInfo( const StgDirEntry& rE )
333 rE.aEntry.GetName( aName );
334 bStorage = BOOL( rE.aEntry.GetType() == STG_STORAGE );
335 bStream = BOOL( rE.aEntry.GetType() == STG_STREAM );
336 nSize = bStorage ? 0 : rE.aEntry.GetSize();
339 /////////////////////////// class Storage ////////////////////////////////
341 BOOL Storage::IsStorageFile( const String & rFileName )
343 StgIo aIo;
344 if( aIo.Open( rFileName, STREAM_STD_READ ) )
345 return aIo.Load();
346 return FALSE;
349 BOOL Storage::IsStorageFile( SvStream* pStream )
351 StgHeader aHdr;
352 ULONG nPos = pStream->Tell();
353 BOOL bRet = ( aHdr.Load( *pStream ) && aHdr.Check() );
355 // It's not a stream error if it is too small for a OLE storage header
356 if ( pStream->GetErrorCode() == ERRCODE_IO_CANTSEEK )
357 pStream->ResetError();
358 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 String& rFile, StreamMode m, BOOL bDirect )
368 : OLEStorageBase( new StgIo, NULL, m_nMode ), aName( rFile ), bIsRoot( FALSE )
370 BOOL bTemp = FALSE;
371 if( !aName.Len() )
373 // no name = temporary name!
374 aName = 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( BOOL( ( 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 ), bIsRoot( FALSE )
401 m_nMode = STREAM_READ;
402 if( r.IsWritable() )
403 m_nMode = STREAM_READ | STREAM_WRITE;
404 if( r.GetError() == SVSTREAM_OK )
406 pIo->SetStrm( &r, FALSE );
407 ULONG nSize = r.Seek( STREAM_SEEK_TO_END );
408 r.Seek( 0L );
409 // Initializing is OK if the stream is empty
410 Init( BOOL( nSize == 0 ) );
411 if( pEntry )
413 pEntry->bDirect = bDirect;
414 pEntry->nMode = m_nMode;
416 pIo->MoveError( *this );
418 else
420 SetError( r.GetError() );
421 pEntry = NULL;
426 Storage::Storage( UCBStorageStream& rStrm, BOOL bDirect )
427 : OLEStorageBase( new StgIo, NULL, m_nMode ), bIsRoot( FALSE )
429 m_nMode = STREAM_READ;
431 if ( rStrm.GetError() != SVSTREAM_OK )
433 SetError( rStrm.GetError() );
434 pEntry = NULL;
435 return;
438 SvStream* pStream = rStrm.GetModifySvStream();
439 if ( !pStream )
441 OSL_ENSURE( FALSE, "UCBStorageStream can not provide SvStream implementation!\n" );
442 SetError( SVSTREAM_GENERALERROR );
443 pEntry = NULL;
444 return;
447 if( pStream->IsWritable() )
448 m_nMode = STREAM_READ | STREAM_WRITE;
450 pIo->SetStrm( &rStrm );
452 ULONG nSize = pStream->Seek( STREAM_SEEK_TO_END );
453 pStream->Seek( 0L );
454 // Initializing is OK if the stream is empty
455 Init( BOOL( nSize == 0 ) );
456 if( pEntry )
458 pEntry->bDirect = bDirect;
459 pEntry->nMode = m_nMode;
462 pIo->MoveError( *this );
466 // Perform common code for both ctors above.
468 void Storage::Init( BOOL bCreate )
470 pEntry = NULL;
471 BOOL bHdrLoaded = FALSE;
472 bIsRoot = TRUE;
473 if( pIo->Good() )
475 ULONG nSize = pIo->GetStrm()->Seek( STREAM_SEEK_TO_END );
476 pIo->GetStrm()->Seek( 0L );
477 if( nSize )
479 bHdrLoaded = pIo->Load();
480 if( !bHdrLoaded && !bCreate )
482 // File is not a storage and not empty; do not destroy!
483 SetError( SVSTREAM_FILEFORMAT_ERROR );
484 return;
488 // file is a storage, empty or should be overwritten
489 pIo->ResetError();
490 // we have to set up the data structures, since
491 // the file is empty
492 if( !bHdrLoaded )
493 pIo->Init();
494 if( pIo->Good() )
496 pEntry = pIo->pTOC->GetRoot();
497 pEntry->nRefCnt++;
501 // Internal ctor
503 Storage::Storage( StgIo* p, StgDirEntry* q, StreamMode m )
504 : OLEStorageBase( p, q, m_nMode ), bIsRoot( FALSE )
506 if( q )
507 q->aEntry.GetName( aName );
508 else
509 m &= ~STREAM_READWRITE;
510 m_nMode = m;
511 if( q && q->nRefCnt == 1 )
512 q->nMode = m;
515 Storage::~Storage()
517 // Invalidate all open substorages
518 if( m_bAutoCommit )
519 Commit();
520 if( pEntry )
522 // Do an auto-commit if the entry is open in direct mode
523 if( pEntry->nRefCnt && pEntry->bDirect && (m_nMode & STREAM_WRITE) )
524 Commit();
525 if( pEntry->nRefCnt == 1 )
526 pEntry->Invalidate();
528 // close the stream is root storage
529 if( bIsRoot )
530 pIo->Close();
531 // remove the file if temporary root storage
532 if( bIsRoot && pEntry && pEntry->bTemp )
534 osl::File::remove( GetName() );
538 const String& Storage::GetName() const
540 if( !bIsRoot && Validate() )
541 pEntry->aEntry.GetName( ((Storage*) this)->aName );
542 return aName;
545 // Fill in the info list for this storage
547 void Storage::FillInfoList( SvStorageInfoList* pList ) const
549 if( Validate() )
551 StgIterator aIter( *pEntry );
552 StgDirEntry* p = aIter.First();
553 while( p )
555 if( !p->bInvalid )
557 SvStorageInfo aInfo( *p );
558 pList->Append( aInfo );
560 p = aIter.Next();
565 // Open or create a substorage
567 BaseStorage* Storage::OpenUCBStorage( const String& rName, StreamMode m, BOOL bDirect )
569 DBG_ERROR("Not supported!");
571 BaseStorage* pStorage = new Storage( pIo, NULL, m );
572 SetError( ERRCODE_IO_NOTSUPPORTED );
573 return pStorage;
575 return OpenStorage( rName, m, bDirect );
578 BaseStorage* Storage::OpenOLEStorage( const String& rName, StreamMode m, BOOL bDirect )
580 return OpenStorage( rName, m, bDirect );
583 BaseStorage* Storage::OpenStorage( const String& rName, StreamMode m, BOOL bDirect )
585 if( !Validate() || !ValidateMode( m ) )
586 return new Storage( pIo, NULL, m );
587 BOOL bSetAutoCommit = FALSE;
588 if( bDirect && !pEntry->bDirect )
590 bSetAutoCommit = TRUE;
591 bDirect = FALSE;
594 StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
595 if( !p )
597 if( !( m & STREAM_NOCREATE ) )
599 BOOL bTemp = FALSE;
600 // create a new storage
601 String aNewName = rName;
602 if( !aNewName.Len() )
604 aNewName.AssignAscii( "Temp Stg " );
605 aNewName.Append( String::CreateFromInt32( ++nTmpCount ) );
606 bTemp = TRUE;
608 p = pIo->pTOC->Create( *pEntry, aNewName, STG_STORAGE );
609 if( p )
610 p->bTemp = bTemp;
612 if( !p )
613 pIo->SetError( ( m & STREAM_WRITE )
614 ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
616 else if( !ValidateMode( m, p ) )
617 p = NULL;
618 if( p && p->aEntry.GetType() != STG_STORAGE )
620 pIo->SetError( SVSTREAM_FILE_NOT_FOUND );
621 p = NULL;
624 // Either direct or transacted mode is supported
625 if( p && pEntry->nRefCnt == 1 )
626 p->bDirect = bDirect;
628 // Dont check direct conflict if opening readonly
629 if( p && (m & STREAM_WRITE ))
631 if( p->bDirect != bDirect )
632 SetError( SVSTREAM_ACCESS_DENIED );
634 Storage* pStg = new Storage( pIo, p, m );
635 pIo->MoveError( *pStg );
636 if( m & STREAM_WRITE ) pStg->m_bAutoCommit = TRUE;
637 return pStg;
640 // Open a stream
642 BaseStorageStream* Storage::OpenStream( const String& rName, StreamMode m, BOOL,
643 const ByteString*
644 #ifdef DBG_UTIL
646 #endif
649 DBG_ASSERT(!pB, "Encryption not supported");
651 if( !Validate() || !ValidateMode( m ) )
652 return new StorageStream( pIo, NULL, m );
653 StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
654 BOOL bTemp = FALSE;
655 if( !p )
657 if( !( m & STREAM_NOCREATE ) )
659 // create a new stream
660 // make a name if the stream is temporary (has no name)
661 String aNewName( rName );
662 if( !aNewName.Len() )
664 aNewName.AssignAscii( "Temp Strm " );
665 aNewName.Append( String::CreateFromInt32( ++nTmpCount ) );
666 bTemp = TRUE;
668 p = pIo->pTOC->Create( *pEntry, aNewName, STG_STREAM );
670 if( !p )
671 pIo->SetError( ( m & STREAM_WRITE )
672 ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
674 else if( !ValidateMode( m, p ) )
675 p = NULL;
676 if( p && p->aEntry.GetType() != STG_STREAM )
678 pIo->SetError( SVSTREAM_FILE_NOT_FOUND );
679 p = NULL;
681 if( p )
683 p->bTemp = bTemp;
684 p->bDirect = pEntry->bDirect;
686 StorageStream* pStm = new StorageStream( pIo, p, m );
687 if( p && !p->bDirect )
688 pStm->SetAutoCommit( TRUE );
689 pIo->MoveError( *pStm );
690 return pStm;
693 // Delete a stream or substorage by setting the temp bit.
695 BOOL Storage::Remove( const String& rName )
697 if( !Validate( TRUE ) )
698 return FALSE;
699 StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
700 if( p )
702 p->Invalidate( TRUE );
703 return TRUE;
705 else
707 SetError( SVSTREAM_FILE_NOT_FOUND );
708 return FALSE;
712 // Rename a storage element
714 BOOL Storage::Rename( const String& rOld, const String& rNew )
716 if( Validate( TRUE ) )
718 BOOL b = pIo->pTOC->Rename( *pEntry, rOld, rNew );
719 pIo->MoveError( *this );
720 return b;
722 else
723 return FALSE;
726 // Copy one element
728 BOOL Storage::CopyTo( const String& rElem, BaseStorage* pDest, const String& rNew )
730 if( !Validate() || !pDest || !pDest->Validate( TRUE ) )
731 return FALSE;
732 StgDirEntry* pElem = pIo->pTOC->Find( *pEntry, rElem );
733 if( pElem )
736 this lines are misterious !!! MM
737 if( !pElem->IsContained( pDest->pEntry ) )
739 SetError( SVSTREAM_ACCESS_DENIED );
740 return FALSE;
743 if( pElem->aEntry.GetType() == STG_STORAGE )
745 // copy the entire storage
746 BaseStorage* p1 = OpenStorage( rElem, INTERNAL_MODE );
747 BaseStorage* p2 = pDest->OpenOLEStorage( rNew, STREAM_WRITE | STREAM_SHARE_DENYALL, pEntry->bDirect );
749 ULONG nTmpErr = p2->GetError();
750 if( !nTmpErr )
752 p2->SetClassId( p1->GetClassId() );
753 p1->CopyTo( p2 );
754 SetError( p1->GetError() );
756 nTmpErr = p2->GetError();
757 if( !nTmpErr )
758 p2->Commit();
759 else
760 pDest->SetError( nTmpErr );
762 else
763 pDest->SetError( nTmpErr );
765 delete p1;
766 delete p2;
767 return BOOL( Good() && pDest->Good() );
769 else
771 // stream copy
772 BaseStorageStream* p1 = OpenStream( rElem, INTERNAL_MODE );
773 BaseStorageStream* p2 = pDest->OpenStream( rNew, STREAM_WRITE | STREAM_SHARE_DENYALL, pEntry->bDirect );
775 ULONG nTmpErr = p2->GetError();
776 if( !nTmpErr )
778 p1->CopyTo( p2 );
779 SetError( p1->GetError() );
781 nTmpErr = p2->GetError();
782 if( !nTmpErr )
783 p2->Commit();
784 else
785 pDest->SetError( nTmpErr );
787 else
788 pDest->SetError( nTmpErr );
790 delete p1;
791 delete p2;
792 return BOOL( Good() && pDest->Good() );
795 SetError( SVSTREAM_FILE_NOT_FOUND );
796 return FALSE;
799 BOOL Storage::CopyTo( BaseStorage* pDest ) const
801 if( !Validate() || !pDest || !pDest->Validate( TRUE ) || Equals( *pDest ) )
803 SetError( SVSTREAM_ACCESS_DENIED );
804 return FALSE;
806 Storage* pThis = (Storage*) this;
808 if( !pThis->pEntry->IsContained( pDest->pEntry ) )
810 SetError( SVSTREAM_ACCESS_DENIED );
811 return FALSE;
814 pDest->SetClassId( GetClassId() );
815 pDest->SetDirty();
816 SvStorageInfoList aList;
817 FillInfoList( &aList );
818 BOOL bRes = TRUE;
819 for( USHORT i = 0; i < aList.Count() && bRes; i++ )
821 SvStorageInfo& rInfo = aList.GetObject( i );
822 bRes = pThis->CopyTo( rInfo.GetName(), pDest, rInfo.GetName() );
824 if( !bRes )
825 SetError( pDest->GetError() );
826 return BOOL( Good() && pDest->Good() );
829 // Move one element
831 BOOL Storage::MoveTo( const String& rElem, BaseStorage* pODest, const String& rNew )
833 if( !Validate() || !pODest || !pODest->Validate( TRUE ) || Equals( *pODest ) )
835 SetError( SVSTREAM_ACCESS_DENIED );
836 return FALSE;
839 StgDirEntry* pElem = pIo->pTOC->Find( *pEntry, rElem );
840 if( pElem )
842 // Simplest case: both storages share the same file
843 BOOL bRes;
844 Storage *pOther = PTR_CAST( Storage, pODest );
845 if( pOther && pIo == pOther->pIo && rElem == rNew )
847 Storage *p = (Storage*) pODest;
848 Storage *pDest = p;
849 // both storages are conventional storages, use implementation dependent code
850 if( !pElem->IsContained( pDest->pEntry ) )
852 // cyclic move
853 SetError( SVSTREAM_ACCESS_DENIED );
854 return FALSE;
856 bRes = pIo->pTOC->Move( *pEntry, *pDest->pEntry, rNew );
857 if( !bRes )
859 pIo->MoveError( *this );
860 pDest->pIo->MoveError( *pDest );
861 ULONG nErr = GetError();
862 if( !nErr )
863 nErr = pDest->GetError();
864 SetError( nErr );
865 pDest->SetError( nErr );
868 else
870 bRes = CopyTo( rElem, pODest, rNew );
871 if( bRes )
872 bRes = Remove( rElem );
874 if( !bRes )
875 SetError( pIo->GetError() );
876 return bRes;
878 SetError( SVSTREAM_FILE_NOT_FOUND );
879 return FALSE;
882 BOOL Storage::IsStorage( const String& rName ) const
884 if( Validate() )
886 StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
887 if( p )
888 return BOOL( p->aEntry.GetType() == STG_STORAGE );
890 return FALSE;
893 BOOL Storage::IsStream( const String& rName ) const
895 if( Validate() )
897 StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
898 if( p )
899 return BOOL( p->aEntry.GetType() == STG_STREAM );
901 return FALSE;
904 BOOL Storage::IsContained( const String& rName ) const
906 if( Validate() )
907 return BOOL( pIo->pTOC->Find( *pEntry, rName ) != NULL );
908 else
909 return FALSE;
912 // Commit all sub-elements within this storage. If this is
913 // the root, commit the FAT, the TOC and the header as well.
915 BOOL Storage::Commit()
917 BOOL bRes = TRUE;
918 if( !Validate() )
919 return FALSE;
920 if( !( m_nMode & STREAM_WRITE ) )
922 SetError( SVSTREAM_ACCESS_DENIED );
923 return FALSE;
925 else
927 // Also commit the sub-streams and Storages
928 StgIterator aIter( *pEntry );
929 for( StgDirEntry* p = aIter.First(); p && bRes; p = aIter.Next() )
930 bRes = p->Commit();
931 if( bRes && bIsRoot )
933 bRes = pEntry->Commit();
934 if( bRes )
935 bRes = pIo->CommitAll();
937 pIo->MoveError( *this );
939 return bRes;
942 BOOL Storage::Revert()
944 return TRUE;
947 ///////////////////////////// OLE Support ////////////////////////////////
949 // Set the storage type
951 void Storage::SetClass( const SvGlobalName & rClass,
952 ULONG nOriginalClipFormat,
953 const String & rUserTypeName )
955 if( Validate( TRUE ) )
957 // set the class name in the root entry
958 pEntry->aEntry.SetClassId( (const ClsId&) rClass.GetCLSID() );
959 pEntry->SetDirty();
960 // then create the streams
961 StgCompObjStream aCompObj( *this, TRUE );
962 aCompObj.GetClsId() = (const ClsId&) rClass.GetCLSID();
963 aCompObj.GetCbFormat() = nOriginalClipFormat;
964 aCompObj.GetUserName() = rUserTypeName;
965 if( !aCompObj.Store() )
966 SetError( aCompObj.GetError() );
967 else
969 StgOleStream aOle( *this, STREAM_WRITE );
970 if( !aOle.Store() )
971 SetError( aOle.GetError() );
974 else
975 SetError( SVSTREAM_ACCESS_DENIED );
978 void Storage::SetConvertClass( const SvGlobalName & rConvertClass,
979 ULONG nOriginalClipFormat,
980 const String & rUserTypeName )
982 if( Validate( TRUE ) )
984 SetClass( rConvertClass, nOriginalClipFormat, rUserTypeName );
985 // plus the convert flag:
986 StgOleStream aOle( *this, TRUE );
987 aOle.GetFlags() |= 4;
988 if( !aOle.Store() )
989 SetError( aOle.GetError() );
993 SvGlobalName Storage::GetClassName()
995 StgCompObjStream aCompObj( *this, FALSE );
996 if( aCompObj.Load() )
997 return SvGlobalName( (const CLSID&) aCompObj.GetClsId() );
998 pIo->ResetError();
1000 if ( pEntry )
1001 return SvGlobalName( (const CLSID&) pEntry->aEntry.GetClassId() );
1003 return SvGlobalName();
1006 ULONG Storage::GetFormat()
1008 StgCompObjStream aCompObj( *this, FALSE );
1009 if( aCompObj.Load() )
1010 return aCompObj.GetCbFormat();
1011 pIo->ResetError();
1012 return 0;
1015 String Storage::GetUserName()
1017 StgCompObjStream aCompObj( *this, FALSE );
1018 if( aCompObj.Load() )
1019 return aCompObj.GetUserName();
1020 pIo->ResetError();
1021 return String();
1024 BOOL Storage::ShouldConvert()
1026 StgOleStream aOle( *this, FALSE );
1027 if( aOle.Load() )
1028 return BOOL( ( aOle.GetFlags() & 4 ) != 0 );
1029 else
1031 pIo->ResetError();
1032 return FALSE;
1036 BOOL Storage::ValidateFAT()
1038 Link aLink = StgIo::GetErrorLink();
1039 ErrCode nErr = pIo->ValidateFATs();
1040 StgIo::SetErrorLink( aLink );
1041 return nErr == ERRCODE_NONE;
1044 void Storage::SetDirty()
1046 pEntry->SetDirty();
1049 void Storage::SetClassId( const ClsId& rId )
1051 pEntry->aEntry.SetClassId( rId );
1054 const ClsId& Storage::GetClassId() const
1056 return pEntry->aEntry.GetClassId();
1059 const SvStream* Storage::GetSvStream() const
1061 return GetSvStream_Impl();
1064 BOOL Storage::Validate( BOOL bValidate ) const
1066 BOOL bRet = Validate_Impl( bValidate );
1067 if ( !bRet )
1068 SetError( SVSTREAM_ACCESS_DENIED );
1069 return bRet;
1072 BOOL Storage::ValidateMode( StreamMode nMode ) const
1074 BOOL bRet = ValidateMode_Impl( nMode );
1075 if ( !bRet )
1076 SetError( SVSTREAM_ACCESS_DENIED );
1077 return bRet;
1080 BOOL Storage::ValidateMode( StreamMode nMode, StgDirEntry* p ) const
1082 BOOL bRet = ValidateMode_Impl( nMode, p );
1083 if ( !bRet )
1084 SetError( SVSTREAM_ACCESS_DENIED );
1085 return bRet;
1088 BOOL Storage::Equals( const BaseStorage& rStorage ) const
1090 const Storage* pOther = PTR_CAST( Storage, &rStorage );
1091 return pOther && ( pOther->pEntry == pEntry );