Teach symstore more duplicated DLLs
[LibreOffice.git] / sot / source / sdstor / stg.cxx
blobedc2477f76511c85b92da8ef22c2039c0ecf7ed0
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 "stgdir.hxx"
30 #include "stgio.hxx"
31 #include "stgole.hxx"
33 static long nTmpCount = 0;
35 // The internal open mode is StreamMode::READ | StreamMode::TRUNC, which is silly
36 // by itself. It inhibits the checking of sharing modes and is used
37 // during CopyTo() and MoveTo() for opening a stream in read mode
38 // although it may be open in DENYALL mode
40 #define INTERNAL_MODE ( StreamMode::READ | StreamMode::TRUNC )
42 ///////////////////////// class StorageBase
45 StorageBase::StorageBase()
46 : m_bAutoCommit( false )
48 m_nMode = StreamMode::READ;
49 m_nError = ERRCODE_NONE;
52 StorageBase::~StorageBase()
56 // The following three methods are declared as const, since they
57 // may be called from within a const method.
59 ErrCode StorageBase::GetError() const
61 const ErrCode n = m_nError;
62 m_nError = ERRCODE_NONE;
63 return n;
66 void StorageBase::SetError( ErrCode n ) const
68 if( !m_nError )
69 m_nError = n;
72 void StorageBase::ResetError() const
74 m_nError = ERRCODE_NONE;
77 OLEStorageBase::OLEStorageBase( StgIo* p, StgDirEntry* pe, StreamMode& nMode )
78 : nStreamMode( nMode ), pIo( p ), pEntry( pe )
80 if ( p )
81 p->IncRef();
82 if( pe )
83 pe->m_nRefCnt++;
86 OLEStorageBase::~OLEStorageBase()
88 if( pEntry )
90 DBG_ASSERT( pEntry->m_nRefCnt, "RefCount under 0" );
91 if( !--pEntry->m_nRefCnt )
93 if( pEntry->m_bZombie )
94 delete pEntry;
95 else
96 pEntry->Close();
99 pEntry = nullptr;
103 if( pIo && !pIo->DecRef() )
105 delete pIo;
106 pIo = nullptr;
110 // Validate the instance for I/O
112 bool OLEStorageBase::Validate_Impl( bool bWrite ) const
114 return pIo
115 && pIo->m_pTOC
116 && pEntry
117 && !pEntry->m_bInvalid
118 && ( !bWrite || !pEntry->m_bDirect || ( nStreamMode & StreamMode::WRITE ) );
121 bool OLEStorageBase::ValidateMode_Impl( StreamMode m, StgDirEntry const * p )
123 if( m == INTERNAL_MODE )
124 return true;
125 StreamMode nCurMode = ( p && p->m_nRefCnt ) ? p->m_nMode : StreamMode::SHARE_DENYALL;
126 if( ( m & StreamMode::READWRITE ) == StreamMode::READ )
128 // only SHARE_DENYWRITE or SHARE_DENYALL allowed
129 if( ( ( m & StreamMode::SHARE_DENYWRITE )
130 && ( nCurMode & StreamMode::SHARE_DENYWRITE ) )
131 || ( ( m & StreamMode::SHARE_DENYALL )
132 && ( nCurMode & StreamMode::SHARE_DENYALL ) ) )
133 return true;
135 else
137 // only SHARE_DENYALL allowed
138 // storages open in r/o mode are OK, since only
139 // the commit may fail
140 if( ( m & StreamMode::SHARE_DENYALL )
141 && ( nCurMode & StreamMode::SHARE_DENYALL ) )
142 return true;
144 return false;
148 //////////////////////// class StorageStream
151 StorageStream::StorageStream( StgIo* p, StgDirEntry* q, StreamMode m )
152 : OLEStorageBase( p, q, m_nMode ), nPos( 0 )
154 // The dir entry may be 0; this means that the stream is invalid.
155 if( q && p )
157 if( q->m_nRefCnt == 1 )
159 q->m_nMode = m;
160 q->OpenStream( *p );
163 else
164 m &= ~StreamMode::READWRITE;
165 m_nMode = m;
168 StorageStream::~StorageStream()
170 // Do an auto-commit if the entry is open in direct mode
171 if( m_bAutoCommit )
172 Commit();
173 if( pEntry && pEntry->m_nRefCnt && pEntry->m_bDirect && (m_nMode & StreamMode::WRITE) )
174 pEntry->Commit();
177 bool StorageStream::Equals( const BaseStorageStream& rStream ) const
179 const StorageStream* pOther = dynamic_cast<const StorageStream*>( &rStream );
180 return pOther && ( pOther->pEntry == pEntry );
183 sal_uLong StorageStream::Read( void* pData, sal_uLong nSize )
185 if( Validate() )
187 pEntry->Seek( nPos );
188 nSize = pEntry->Read( pData, static_cast<sal_Int32>(nSize) );
189 pIo->MoveError( *this );
190 nPos += nSize;
192 else
193 nSize = 0;
194 return nSize;
197 sal_uLong StorageStream::Write( const void* pData, sal_uLong nSize )
199 if( Validate( true ) )
201 pEntry->Seek( nPos );
202 nSize = pEntry->Write( pData, static_cast<sal_Int32>(nSize) );
203 pIo->MoveError( *this );
204 nPos += nSize;
206 else
207 nSize = 0;
208 return nSize;
211 sal_uInt64 StorageStream::Seek( sal_uInt64 n )
213 if( Validate() )
214 return nPos = pEntry->Seek( n );
215 else
216 return n;
219 void StorageStream::Flush()
221 // Flushing means committing, since streams are never transacted
222 Commit();
225 bool StorageStream::SetSize( sal_uLong nNewSize )
227 if( Validate( true ) )
229 bool b = pEntry->SetSize( static_cast<sal_Int32>(nNewSize) );
230 pIo->MoveError( *this );
231 return b;
233 else
234 return false;
237 sal_uLong StorageStream::GetSize() const
239 if( Validate() )
240 return pEntry->GetSize();
241 return 0;
244 bool StorageStream::Commit()
246 if( !Validate() )
247 return false;
248 if( !( m_nMode & StreamMode::WRITE ) )
250 SetError( SVSTREAM_ACCESS_DENIED );
251 return false;
253 else
255 pEntry->Commit();
256 pIo->MoveError( *this );
257 return Good();
261 void StorageStream::CopyTo( BaseStorageStream* pDest )
263 if( !Validate() || !pDest || !pDest->Validate( true ) || Equals( *pDest ) )
264 return;
265 pEntry->Copy( *pDest );
266 pDest->Commit();
267 pIo->MoveError( *this );
268 SetError( pDest->GetError() );
271 bool StorageStream::Validate( bool bValidate ) const
273 bool bRet = Validate_Impl( bValidate );
274 if ( !bRet )
275 SetError( SVSTREAM_ACCESS_DENIED );
276 return bRet;
279 bool StorageStream::ValidateMode( StreamMode nMode ) const
281 bool bRet = ValidateMode_Impl( nMode );
282 if ( !bRet )
283 SetError( SVSTREAM_ACCESS_DENIED );
284 return bRet;
287 ///////////////////////// class SvStorageInfo
289 SvStorageInfo::SvStorageInfo( const StgDirEntry& rE )
291 rE.m_aEntry.GetName( aName );
292 bStorage = rE.m_aEntry.GetType() == STG_STORAGE;
293 bStream = rE.m_aEntry.GetType() == STG_STREAM;
294 nSize = bStorage ? 0 : rE.m_aEntry.GetSize();
297 /////////////////////////// class Storage
299 bool Storage::IsStorageFile( const OUString & rFileName )
301 StgIo aIo;
302 if( aIo.Open( rFileName, StreamMode::STD_READ ) )
303 return aIo.Load();
304 return false;
307 bool Storage::IsStorageFile( SvStream* pStream )
309 bool bRet = false;
311 if ( pStream )
313 StgHeader aHdr;
314 sal_uInt64 nPos = pStream->Tell();
315 bRet = ( aHdr.Load( *pStream ) && aHdr.Check() );
317 // It's not a stream error if it is too small for an OLE storage header
318 if ( pStream->GetErrorCode() == ERRCODE_IO_CANTSEEK )
319 pStream->ResetError();
320 pStream->Seek( nPos );
323 return bRet;
326 // Open the storage file. If writing is permitted and the file is not
327 // a storage file, initialize it.
330 Storage::Storage( const OUString& rFile, StreamMode m, bool bDirect )
331 : OLEStorageBase( new StgIo, nullptr, m_nMode )
332 , aName( rFile ), bIsRoot( false )
334 bool bTemp = false;
335 if( aName.isEmpty() )
337 // no name = temporary name!
338 aName = utl::TempFile::CreateTempName();
339 bTemp = true;
341 // the root storage creates the I/O system
342 m_nMode = m;
343 if( pIo->Open( aName, m ) )
345 Init( ( m & ( StreamMode::TRUNC | StreamMode::NOCREATE ) ) == StreamMode::TRUNC );
346 if( pEntry )
348 pEntry->m_bDirect = bDirect;
349 pEntry->m_nMode = m;
350 pEntry->m_bTemp = bTemp;
353 else
355 pIo->MoveError( *this );
356 pEntry = nullptr;
360 // Create a storage on a given stream.
362 Storage::Storage( SvStream& r, bool bDirect )
363 : OLEStorageBase( new StgIo, nullptr, m_nMode )
364 , bIsRoot( false )
366 m_nMode = StreamMode::READ;
367 if( r.IsWritable() )
368 m_nMode = StreamMode::READ | StreamMode::WRITE;
369 if( r.GetError() == ERRCODE_NONE )
371 pIo->SetStrm( &r, false );
372 sal_uInt64 nSize = r.TellEnd();
373 r.Seek( 0 );
374 // Initializing is OK if the stream is empty
375 Init( nSize == 0 );
376 if( pEntry )
378 pEntry->m_bDirect = bDirect;
379 pEntry->m_nMode = m_nMode;
381 pIo->MoveError( *this );
383 else
385 SetError( r.GetError() );
386 pEntry = nullptr;
391 Storage::Storage( UCBStorageStream& rStrm, bool bDirect )
392 : OLEStorageBase( new StgIo, nullptr, m_nMode ), bIsRoot( false )
394 m_nMode = StreamMode::READ;
396 if ( rStrm.GetError() != ERRCODE_NONE )
398 SetError( rStrm.GetError() );
399 pEntry = nullptr;
400 return;
403 SvStream* pStream = rStrm.GetModifySvStream();
404 if ( !pStream )
406 OSL_FAIL( "UCBStorageStream can not provide SvStream implementation!" );
407 SetError( SVSTREAM_GENERALERROR );
408 pEntry = nullptr;
409 return;
412 if( pStream->IsWritable() )
413 m_nMode = StreamMode::READ | StreamMode::WRITE;
415 pIo->SetStrm( &rStrm );
417 sal_uInt64 nSize = pStream->TellEnd();
418 pStream->Seek( 0 );
419 // Initializing is OK if the stream is empty
420 Init( nSize == 0 );
421 if( pEntry )
423 pEntry->m_bDirect = bDirect;
424 pEntry->m_nMode = m_nMode;
427 pIo->MoveError( *this );
431 // Perform common code for both ctors above.
433 void Storage::Init( bool bCreate )
435 pEntry = nullptr;
436 bool bHdrLoaded = false;
437 bIsRoot = true;
439 OSL_ENSURE( pIo, "The pointer may not be empty at this point!" );
440 if( pIo->Good() && pIo->GetStrm() )
442 sal_uInt64 nSize = pIo->GetStrm()->TellEnd();
443 pIo->GetStrm()->Seek( 0 );
444 if( nSize )
446 bHdrLoaded = pIo->Load();
447 if( !bHdrLoaded && !bCreate )
449 // File is not a storage and not empty; do not destroy!
450 SetError( SVSTREAM_FILEFORMAT_ERROR );
451 return;
455 // file is a storage, empty or should be overwritten
456 pIo->ResetError();
457 // we have to set up the data structures, since
458 // the file is empty
459 if( !bHdrLoaded )
460 pIo->Init();
461 if( pIo->Good() && pIo->m_pTOC )
463 pEntry = pIo->m_pTOC->GetRoot();
464 pEntry->m_nRefCnt++;
468 // Internal ctor
470 Storage::Storage( StgIo* p, StgDirEntry* q, StreamMode m )
471 : OLEStorageBase( p, q, m_nMode ), bIsRoot( false )
473 if( q )
474 q->m_aEntry.GetName( aName );
475 else
476 m &= ~StreamMode::READWRITE;
477 m_nMode = m;
478 if( q && q->m_nRefCnt == 1 )
479 q->m_nMode = m;
482 Storage::~Storage()
484 // Invalidate all open substorages
485 if( m_bAutoCommit )
486 Commit();
487 if( pEntry )
489 // Do an auto-commit if the entry is open in direct mode
490 if( pEntry->m_nRefCnt && pEntry->m_bDirect && (m_nMode & StreamMode::WRITE) )
491 Commit();
492 if( pEntry->m_nRefCnt == 1 )
493 pEntry->Invalidate(false);
495 // close the stream is root storage
496 if( bIsRoot )
497 pIo->Close();
498 // remove the file if temporary root storage
499 if( bIsRoot && pEntry && pEntry->m_bTemp )
501 osl::File::remove( GetName() );
505 const OUString& Storage::GetName() const
507 if( !bIsRoot && Validate() )
508 pEntry->m_aEntry.GetName( const_cast<Storage*>(this)->aName );
509 return aName;
512 // Fill in the info list for this storage
514 void Storage::FillInfoList( SvStorageInfoList* pList ) const
516 if( !(Validate() && pList) )
517 return;
519 StgIterator aIter( *pEntry );
520 StgDirEntry* p = aIter.First();
521 while( p )
523 if( !p->m_bInvalid )
525 SvStorageInfo aInfo( *p );
526 pList->push_back( aInfo );
528 p = aIter.Next();
532 // Open or create a substorage
534 BaseStorage* Storage::OpenUCBStorage( const OUString& rName, StreamMode m, bool bDirect )
536 OSL_FAIL("Not supported!");
537 return OpenStorage( rName, m, bDirect );
540 BaseStorage* Storage::OpenOLEStorage( const OUString& rName, StreamMode m, bool bDirect )
542 return OpenStorage( rName, m, bDirect );
545 BaseStorage* Storage::OpenStorage( const OUString& rName, StreamMode m, bool bDirect )
547 if( !Validate() || !ValidateMode( m ) )
548 return new Storage( pIo, nullptr, m );
549 if( bDirect && !pEntry->m_bDirect )
550 bDirect = false;
552 StgDirEntry* p = StgDirStrm::Find( *pEntry, rName );
553 if( !p )
555 if( !( m & StreamMode::NOCREATE ) )
557 bool bTemp = false;
558 // create a new storage
559 OUString aNewName = rName;
560 if( aNewName.isEmpty() )
562 aNewName = "Temp Stg " + OUString::number( ++nTmpCount );
563 bTemp = true;
565 p = pIo->m_pTOC->Create( *pEntry, aNewName, STG_STORAGE );
566 if( p )
567 p->m_bTemp = bTemp;
569 if( !p )
570 pIo->SetError( ( m & StreamMode::WRITE )
571 ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
573 else if( !ValidateMode( m, p ) )
574 p = nullptr;
575 if( p && p->m_aEntry.GetType() != STG_STORAGE )
577 pIo->SetError( SVSTREAM_FILE_NOT_FOUND );
578 p = nullptr;
581 // Either direct or transacted mode is supported
582 if( p && pEntry->m_nRefCnt == 1 )
583 p->m_bDirect = bDirect;
585 // Don't check direct conflict if opening readonly
586 if( p && (m & StreamMode::WRITE ))
588 if( p->m_bDirect != bDirect )
589 SetError( SVSTREAM_ACCESS_DENIED );
591 Storage* pStg = new Storage( pIo, p, m );
592 pIo->MoveError( *pStg );
593 if( m & StreamMode::WRITE ) pStg->m_bAutoCommit = true;
594 return pStg;
597 // Open a stream
599 BaseStorageStream* Storage::OpenStream( const OUString& rName, StreamMode m, bool )
601 if( !Validate() || !ValidateMode( m ) )
602 return new StorageStream( pIo, nullptr, m );
603 StgDirEntry* p = StgDirStrm::Find( *pEntry, rName );
604 bool bTemp = false;
605 if( !p )
607 if( !( m & StreamMode::NOCREATE ) )
609 // create a new stream
610 // make a name if the stream is temporary (has no name)
611 OUString aNewName( rName );
612 if( aNewName.isEmpty() )
614 aNewName = "Temp Strm " + OUString::number( ++nTmpCount );
615 bTemp = true;
617 p = pIo->m_pTOC->Create( *pEntry, aNewName, STG_STREAM );
619 if( !p )
620 pIo->SetError( ( m & StreamMode::WRITE )
621 ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
623 else if( !ValidateMode( m, p ) )
624 p = nullptr;
625 if( p && p->m_aEntry.GetType() != STG_STREAM )
627 pIo->SetError( SVSTREAM_FILE_NOT_FOUND );
628 p = nullptr;
630 if( p )
632 p->m_bTemp = bTemp;
633 p->m_bDirect = pEntry->m_bDirect;
635 StorageStream* pStm = new StorageStream( pIo, p, m );
636 if( p && !p->m_bDirect )
637 pStm->SetAutoCommit( true );
638 pIo->MoveError( *pStm );
639 return pStm;
642 // Delete a stream or substorage by setting the temp bit.
644 void Storage::Remove( const OUString& rName )
646 if( !Validate( true ) )
647 return;
648 StgDirEntry* p = StgDirStrm::Find( *pEntry, rName );
649 if( p )
651 p->Invalidate( true );
653 else
655 SetError( SVSTREAM_FILE_NOT_FOUND );
659 // Copy one element
661 bool Storage::CopyTo( const OUString& rElem, BaseStorage* pDest, const OUString& rNew )
663 if( !Validate() || !pDest || !pDest->Validate( true ) )
664 return false;
665 StgDirEntry* pElem = StgDirStrm::Find( *pEntry, rElem );
666 if( pElem )
668 if( pElem->m_aEntry.GetType() == STG_STORAGE )
670 // copy the entire storage
671 tools::SvRef<BaseStorage> p1 = OpenStorage( rElem, INTERNAL_MODE );
672 tools::SvRef<BaseStorage> p2 = pDest->OpenOLEStorage( rNew, StreamMode::WRITE | StreamMode::SHARE_DENYALL, pEntry->m_bDirect );
674 if ( p2 )
676 ErrCode nTmpErr = p2->GetError();
677 if( !nTmpErr )
679 p2->SetClassId( p1->GetClassId() );
680 p1->CopyTo( p2.get() );
681 SetError( p1->GetError() );
683 nTmpErr = p2->GetError();
684 if( !nTmpErr )
685 p2->Commit();
686 else
687 pDest->SetError( nTmpErr );
689 else
690 pDest->SetError( nTmpErr );
693 return Good() && pDest->Good();
695 else
697 // stream copy
698 tools::SvRef<BaseStorageStream> p1 = OpenStream( rElem, INTERNAL_MODE );
699 tools::SvRef<BaseStorageStream> p2 = pDest->OpenStream( rNew, StreamMode::WRITE | StreamMode::SHARE_DENYALL, pEntry->m_bDirect );
701 if ( p2 )
703 ErrCode nTmpErr = p2->GetError();
704 if( !nTmpErr )
706 p1->CopyTo( p2.get() );
707 SetError( p1->GetError() );
709 nTmpErr = p2->GetError();
710 if( !nTmpErr )
711 p2->Commit();
712 else
713 pDest->SetError( nTmpErr );
715 else
716 pDest->SetError( nTmpErr );
719 return Good() && pDest->Good();
722 SetError( SVSTREAM_FILE_NOT_FOUND );
723 return false;
726 bool Storage::CopyTo( BaseStorage* pDest ) const
728 if( !Validate() || !pDest || !pDest->Validate( true ) || Equals( *pDest ) )
730 SetError( SVSTREAM_ACCESS_DENIED );
731 return false;
733 Storage* pThis = const_cast<Storage*>(this);
734 pDest->SetClassId( GetClassId() );
735 pDest->SetDirty();
736 SvStorageInfoList aList;
737 FillInfoList( &aList );
738 bool bRes = true;
739 for( size_t i = 0; i < aList.size() && bRes; i++ )
741 SvStorageInfo& rInfo = aList[ i ];
742 bRes = pThis->CopyTo( rInfo.GetName(), pDest, rInfo.GetName() );
744 if( !bRes )
745 SetError( pDest->GetError() );
746 return Good() && pDest->Good();
749 bool Storage::IsStorage( const OUString& rName ) const
751 if( Validate() )
753 StgDirEntry* p = StgDirStrm::Find( *pEntry, rName );
754 if( p )
755 return p->m_aEntry.GetType() == STG_STORAGE;
757 return false;
760 bool Storage::IsStream( const OUString& rName ) const
762 if( Validate() )
764 StgDirEntry* p = StgDirStrm::Find( *pEntry, rName );
765 if( p )
766 return p->m_aEntry.GetType() == STG_STREAM;
768 return false;
771 bool Storage::IsContained( const OUString& rName ) const
773 if( Validate() )
774 return StgDirStrm::Find( *pEntry, rName ) != nullptr;
775 else
776 return false;
779 // Commit all sub-elements within this storage. If this is
780 // the root, commit the FAT, the TOC and the header as well.
782 bool Storage::Commit()
784 bool bRes = true;
785 if( !Validate() )
786 return false;
787 if( !( m_nMode & StreamMode::WRITE ) )
789 SetError( SVSTREAM_ACCESS_DENIED );
790 return false;
792 else
794 // Also commit the sub-streams and Storages
795 StgIterator aIter( *pEntry );
796 for( StgDirEntry* p = aIter.First(); p && bRes; p = aIter.Next() )
797 bRes = p->Commit();
798 if( bRes && bIsRoot )
800 bRes = pEntry->Commit();
801 if( bRes )
802 bRes = pIo->CommitAll();
804 pIo->MoveError( *this );
806 return bRes;
809 bool Storage::Revert()
811 return true;
814 ///////////////////////////// OLE Support
816 // Set the storage type
818 void Storage::SetClass( const SvGlobalName & rClass,
819 SotClipboardFormatId nOriginalClipFormat,
820 const OUString & rUserTypeName )
822 if( Validate( true ) )
824 // set the class name in the root entry
825 pEntry->m_aEntry.SetClassId( rClass.GetCLSID() );
826 pEntry->SetDirty();
827 // then create the streams
828 StgCompObjStream aCompObj( *this, true );
829 aCompObj.GetClsId() = rClass.GetCLSID();
830 aCompObj.GetCbFormat() = nOriginalClipFormat;
831 aCompObj.GetUserName() = rUserTypeName;
832 if( !aCompObj.Store() )
833 SetError( aCompObj.GetError() );
834 else
836 StgOleStream aOle(*this);
837 if( !aOle.Store() )
838 SetError( aOle.GetError() );
841 else
842 SetError( SVSTREAM_ACCESS_DENIED );
845 SvGlobalName Storage::GetClassName()
847 StgCompObjStream aCompObj( *this, false );
848 if( aCompObj.Load() )
849 return SvGlobalName( aCompObj.GetClsId() );
850 pIo->ResetError();
852 if ( pEntry )
853 return SvGlobalName( pEntry->m_aEntry.GetClassId() );
855 return SvGlobalName();
858 SotClipboardFormatId Storage::GetFormat()
860 StgCompObjStream aCompObj( *this, false );
861 if( aCompObj.Load() )
862 return aCompObj.GetCbFormat();
863 pIo->ResetError();
864 return SotClipboardFormatId::NONE;
867 OUString Storage::GetUserName()
869 StgCompObjStream aCompObj( *this, false );
870 if( aCompObj.Load() )
871 return aCompObj.GetUserName();
872 pIo->ResetError();
873 return OUString();
876 bool Storage::ValidateFAT()
878 FatError nErr = pIo->ValidateFATs();
879 return nErr == FatError::Ok;
882 void Storage::SetDirty()
884 if ( pEntry )
885 pEntry->SetDirty();
888 void Storage::SetClassId( const ClsId& rId )
890 if ( pEntry )
891 pEntry->m_aEntry.SetClassId( rId );
894 const ClsId& Storage::GetClassId() const
896 if ( pEntry )
897 return pEntry->m_aEntry.GetClassId();
899 static const ClsId aDummyId = {0,0,0,{0,0,0,0,0,0,0,0}};
900 return aDummyId;
903 bool Storage::Validate( bool bValidate ) const
905 bool bRet = Validate_Impl( bValidate );
906 if ( !bRet )
907 SetError( SVSTREAM_ACCESS_DENIED );
908 return bRet;
911 bool Storage::ValidateMode( StreamMode nMode ) const
913 bool bRet = ValidateMode_Impl( nMode );
914 if ( !bRet )
915 SetError( SVSTREAM_ACCESS_DENIED );
916 return bRet;
919 bool Storage::ValidateMode( StreamMode nMode, StgDirEntry const * p ) const
921 bool bRet = ValidateMode_Impl( nMode, p );
922 if ( !bRet )
923 SetError( SVSTREAM_ACCESS_DENIED );
924 return bRet;
927 bool Storage::Equals( const BaseStorage& rStorage ) const
929 const Storage* pOther = dynamic_cast<const Storage*>( &rStorage );
930 return pOther && ( pOther->pEntry == pEntry );
933 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */