tdf#161411 - UI: Add Better wording for ASCII-only characters
[LibreOffice.git] / sot / source / sdstor / stg.cxx
blobc3b66ca9956c89e786e76ba62b60e2947c01d0be
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/diagnose.h>
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 <utility>
30 #include "stgelem.hxx"
31 #include "stgdir.hxx"
32 #include "stgio.hxx"
33 #include "stgole.hxx"
35 static tools::Long nTmpCount = 0;
37 // The internal open mode is StreamMode::READ | StreamMode::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 ( StreamMode::READ | StreamMode::TRUNC )
44 ///////////////////////// class StorageBase
47 StorageBase::StorageBase()
48 : m_bAutoCommit( false )
50 m_nMode = StreamMode::READ;
51 m_nError = ERRCODE_NONE;
54 StorageBase::~StorageBase()
58 // The following three methods are declared as const, since they
59 // may be called from within a const method.
61 ErrCode StorageBase::GetError() const
63 const ErrCode n = m_nError;
64 m_nError = ERRCODE_NONE;
65 return n;
68 void StorageBase::SetError( ErrCode n ) const
70 if( !m_nError )
71 m_nError = n;
74 void StorageBase::ResetError() const
76 m_nError = ERRCODE_NONE;
79 OLEStorageBase::OLEStorageBase( StgIo* p, StgDirEntry* pe, StreamMode& nMode )
80 : nStreamMode( nMode ), pIo( p ), pEntry( pe )
82 if ( p )
83 p->IncRef();
84 if( pe )
85 pe->m_nRefCnt++;
88 OLEStorageBase::~OLEStorageBase()
90 if( pEntry )
92 DBG_ASSERT( pEntry->m_nRefCnt, "RefCount under 0" );
93 if( !--pEntry->m_nRefCnt )
95 if( pEntry->m_bZombie )
96 delete pEntry;
97 else
98 pEntry->Close();
101 pEntry = nullptr;
105 if( pIo && !pIo->DecRef() )
107 delete pIo;
108 pIo = nullptr;
112 // Validate the instance for I/O
114 bool OLEStorageBase::Validate_Impl( bool bWrite ) const
116 return pIo
117 && pIo->m_pTOC
118 && pEntry
119 && !pEntry->m_bInvalid
120 && ( !bWrite || !pEntry->m_bDirect || ( nStreamMode & StreamMode::WRITE ) );
123 bool OLEStorageBase::ValidateMode_Impl( StreamMode m, StgDirEntry const * p )
125 if( m == INTERNAL_MODE )
126 return true;
127 StreamMode nCurMode = ( p && p->m_nRefCnt ) ? p->m_nMode : StreamMode::SHARE_DENYALL;
128 if( ( m & StreamMode::READWRITE ) == StreamMode::READ )
130 // only SHARE_DENYWRITE or SHARE_DENYALL allowed
131 if( ( ( m & StreamMode::SHARE_DENYWRITE )
132 && ( nCurMode & StreamMode::SHARE_DENYWRITE ) )
133 || ( ( m & StreamMode::SHARE_DENYALL )
134 && ( nCurMode & StreamMode::SHARE_DENYALL ) ) )
135 return true;
137 else
139 // only SHARE_DENYALL allowed
140 // storages open in r/o mode are OK, since only
141 // the commit may fail
142 if( ( m & StreamMode::SHARE_DENYALL )
143 && ( nCurMode & StreamMode::SHARE_DENYALL ) )
144 return true;
146 return false;
150 //////////////////////// class StorageStream
153 StorageStream::StorageStream( StgIo* p, StgDirEntry* q, StreamMode m )
154 : OLEStorageBase( p, q, m_nMode ), nPos( 0 )
156 // The dir entry may be 0; this means that the stream is invalid.
157 if( q && p )
159 if( q->m_nRefCnt == 1 )
161 q->m_nMode = m;
162 q->OpenStream( *p );
165 else
166 m &= ~StreamMode::READWRITE;
167 m_nMode = m;
170 StorageStream::~StorageStream()
172 // Do an auto-commit if the entry is open in direct mode
173 if( m_bAutoCommit )
174 Commit();
175 if( pEntry && pEntry->m_nRefCnt && pEntry->m_bDirect && (m_nMode & StreamMode::WRITE) )
176 pEntry->Commit();
179 bool StorageStream::Equals( const BaseStorageStream& rStream ) const
181 const StorageStream* pOther = dynamic_cast<const StorageStream*>( &rStream );
182 return pOther && ( pOther->pEntry == pEntry );
185 sal_Int32 StorageStream::Read( void* pData, sal_Int32 nSize )
187 if( Validate() )
189 pEntry->Seek( nPos );
190 nSize = pEntry->Read( pData, nSize );
191 pIo->MoveError( *this );
192 nPos += nSize;
194 else
195 nSize = 0;
196 return nSize;
199 sal_Int32 StorageStream::Write( const void* pData, sal_Int32 nSize )
201 if( Validate( true ) )
203 pEntry->Seek( nPos );
204 nSize = pEntry->Write( pData, nSize );
205 pIo->MoveError( *this );
206 nPos += nSize;
208 else
209 nSize = 0;
210 return nSize;
213 sal_uInt64 StorageStream::Seek( sal_uInt64 n )
215 if( Validate() )
217 nPos = pEntry->Seek( n );
218 return nPos;
220 else
221 return n;
224 void StorageStream::Flush()
226 // Flushing means committing, since streams are never transacted
227 Commit();
230 bool StorageStream::SetSize( sal_uInt64 nNewSize )
232 if( Validate( true ) )
234 bool b = pEntry->SetSize( nNewSize );
235 pIo->MoveError( *this );
236 return b;
238 else
239 return false;
242 sal_uInt64 StorageStream::GetSize() const
244 if( Validate() )
245 return pEntry->GetSize();
246 return 0;
249 bool StorageStream::Commit()
251 if( !Validate() )
252 return false;
253 if( !( m_nMode & StreamMode::WRITE ) )
255 SetError( SVSTREAM_ACCESS_DENIED );
256 return false;
258 else
260 pEntry->Commit();
261 pIo->MoveError( *this );
262 return Good();
266 void StorageStream::CopyTo( BaseStorageStream* pDest )
268 if( !Validate() || !pDest || !pDest->Validate( true ) || Equals( *pDest ) )
269 return;
270 pEntry->Copy( *pDest );
271 pDest->Commit();
272 pIo->MoveError( *this );
273 SetError( pDest->GetError() );
276 bool StorageStream::Validate( bool bValidate ) const
278 bool bRet = Validate_Impl( bValidate );
279 if ( !bRet )
280 SetError( SVSTREAM_ACCESS_DENIED );
281 return bRet;
284 bool StorageStream::ValidateMode( StreamMode nMode ) const
286 bool bRet = ValidateMode_Impl( nMode );
287 if ( !bRet )
288 SetError( SVSTREAM_ACCESS_DENIED );
289 return bRet;
292 ///////////////////////// class SvStorageInfo
294 SvStorageInfo::SvStorageInfo( const StgDirEntry& rE )
296 rE.m_aEntry.GetName( aName );
297 bStorage = rE.m_aEntry.GetType() == STG_STORAGE;
298 bStream = rE.m_aEntry.GetType() == STG_STREAM;
299 nSize = bStorage ? 0 : rE.m_aEntry.GetSize();
302 /////////////////////////// class Storage
304 bool Storage::IsStorageFile( const OUString & rFileName )
306 StgIo aIo;
307 if( aIo.Open( rFileName, StreamMode::STD_READ ) )
308 return aIo.Load();
309 return false;
312 bool Storage::IsStorageFile( SvStream* pStream )
314 bool bRet = false;
316 if ( pStream )
318 StgHeader aHdr;
319 sal_uInt64 nPos = pStream->Tell();
320 bRet = ( aHdr.Load( *pStream ) && aHdr.Check() );
322 // It's not a stream error if it is too small for an OLE storage header
323 if ( pStream->GetErrorCode() == ERRCODE_IO_CANTSEEK )
324 pStream->ResetError();
325 pStream->Seek( nPos );
328 return bRet;
331 // Open the storage file. If writing is permitted and the file is not
332 // a storage file, initialize it.
335 Storage::Storage( OUString aFile, StreamMode m, bool bDirect )
336 : OLEStorageBase( new StgIo, nullptr, m_nMode )
337 , aName(std::move( aFile )), bIsRoot( false )
339 bool bTemp = false;
340 if( aName.isEmpty() )
342 // no name = temporary name!
343 aName = utl::CreateTempName();
344 bTemp = true;
346 // the root storage creates the I/O system
347 m_nMode = m;
348 if( pIo->Open( aName, m ) )
350 Init( ( m & ( StreamMode::TRUNC | StreamMode::NOCREATE ) ) == StreamMode::TRUNC );
351 if( pEntry )
353 pEntry->m_bDirect = bDirect;
354 pEntry->m_nMode = m;
355 pEntry->m_bTemp = bTemp;
358 else
360 pIo->MoveError( *this );
361 pEntry = nullptr;
365 // Create a storage on a given stream.
367 Storage::Storage( SvStream& r, bool bDirect )
368 : OLEStorageBase( new StgIo, nullptr, m_nMode )
369 , bIsRoot( false )
371 m_nMode = StreamMode::READ;
372 if( r.IsWritable() )
373 m_nMode = StreamMode::READ | StreamMode::WRITE;
374 if( r.GetError() == ERRCODE_NONE )
376 pIo->SetStrm( &r, false );
377 sal_uInt64 nSize = r.TellEnd();
378 r.Seek( 0 );
379 // Initializing is OK if the stream is empty
380 Init( nSize == 0 );
381 if( pEntry )
383 pEntry->m_bDirect = bDirect;
384 pEntry->m_nMode = m_nMode;
386 pIo->MoveError( *this );
388 else
390 SetError( r.GetError() );
391 pEntry = nullptr;
396 Storage::Storage( UCBStorageStream& rStrm, bool bDirect )
397 : OLEStorageBase( new StgIo, nullptr, m_nMode ), bIsRoot( false )
399 m_nMode = StreamMode::READ;
401 if ( rStrm.GetError() != ERRCODE_NONE )
403 SetError( rStrm.GetError() );
404 pEntry = nullptr;
405 return;
408 SvStream* pStream = rStrm.GetModifySvStream();
409 if ( !pStream )
411 OSL_FAIL( "UCBStorageStream can not provide SvStream implementation!" );
412 SetError( SVSTREAM_GENERALERROR );
413 pEntry = nullptr;
414 return;
417 if( pStream->IsWritable() )
418 m_nMode = StreamMode::READ | StreamMode::WRITE;
420 pIo->SetStrm( &rStrm );
422 sal_uInt64 nSize = pStream->TellEnd();
423 pStream->Seek( 0 );
424 // Initializing is OK if the stream is empty
425 Init( nSize == 0 );
426 if( pEntry )
428 pEntry->m_bDirect = bDirect;
429 pEntry->m_nMode = m_nMode;
432 pIo->MoveError( *this );
436 // Perform common code for both ctors above.
438 void Storage::Init( bool bCreate )
440 pEntry = nullptr;
441 bool bHdrLoaded = false;
442 bIsRoot = true;
444 assert(pIo && "The pointer may not be empty at this point!");
445 if( pIo->Good() && pIo->GetStrm() )
447 sal_uInt64 nSize = pIo->GetStrm()->TellEnd();
448 pIo->GetStrm()->Seek( 0 );
449 if( nSize )
451 bHdrLoaded = pIo->Load();
452 if( !bHdrLoaded && !bCreate )
454 // File is not a storage and not empty; do not destroy!
455 SetError( SVSTREAM_FILEFORMAT_ERROR );
456 return;
460 // file is a storage, empty or should be overwritten
461 pIo->ResetError();
462 // we have to set up the data structures, since
463 // the file is empty
464 if( !bHdrLoaded )
465 pIo->Init();
466 if( pIo->Good() && pIo->m_pTOC )
468 pEntry = pIo->m_pTOC->GetRoot();
469 pEntry->m_nRefCnt++;
473 // Internal ctor
475 Storage::Storage( StgIo* p, StgDirEntry* q, StreamMode m )
476 : OLEStorageBase( p, q, m_nMode ), bIsRoot( false )
478 if( q )
479 q->m_aEntry.GetName( aName );
480 else
481 m &= ~StreamMode::READWRITE;
482 m_nMode = m;
483 if( q && q->m_nRefCnt == 1 )
484 q->m_nMode = m;
487 Storage::~Storage()
489 // Invalidate all open substorages
490 if( m_bAutoCommit )
491 Commit();
492 if( pEntry )
494 // Do an auto-commit if the entry is open in direct mode
495 if( pEntry->m_nRefCnt && pEntry->m_bDirect && (m_nMode & StreamMode::WRITE) )
496 Commit();
497 if( pEntry->m_nRefCnt == 1 )
498 pEntry->Invalidate(false);
500 // close the stream is root storage
501 if( bIsRoot )
502 pIo->Close();
503 // remove the file if temporary root storage
504 if( bIsRoot && pEntry && pEntry->m_bTemp )
506 osl::File::remove( GetName() );
510 const OUString& Storage::GetName() const
512 if( !bIsRoot && Validate() )
513 pEntry->m_aEntry.GetName( const_cast<Storage*>(this)->aName );
514 return aName;
517 // Fill in the info list for this storage
519 void Storage::FillInfoList( SvStorageInfoList* pList ) const
521 if( !(Validate() && pList) )
522 return;
524 StgIterator aIter( *pEntry );
525 StgDirEntry* p = aIter.First();
526 while( p )
528 if( !p->m_bInvalid )
530 SvStorageInfo aInfo( *p );
531 pList->push_back( aInfo );
533 p = aIter.Next();
537 // Open or create a substorage
539 BaseStorage* Storage::OpenUCBStorage( const OUString& rName, StreamMode m, bool bDirect )
541 OSL_FAIL("Not supported!");
542 return OpenStorage( rName, m, bDirect );
545 BaseStorage* Storage::OpenOLEStorage( const OUString& rName, StreamMode m, bool bDirect )
547 return OpenStorage( rName, m, bDirect );
550 BaseStorage* Storage::OpenStorage( const OUString& rName, StreamMode m, bool bDirect )
552 if( !Validate() || !ValidateMode( m ) )
553 return new Storage( pIo, nullptr, m );
554 if( bDirect && !pEntry->m_bDirect )
555 bDirect = false;
557 StgDirEntry* p = StgDirStrm::Find( *pEntry, rName );
558 if( !p )
560 if( !( m & StreamMode::NOCREATE ) )
562 bool bTemp = false;
563 // create a new storage
564 OUString aNewName = rName;
565 if( aNewName.isEmpty() )
567 aNewName = "Temp Stg " + OUString::number( ++nTmpCount );
568 bTemp = true;
570 p = pIo->m_pTOC->Create( *pEntry, aNewName, STG_STORAGE );
571 if( p )
572 p->m_bTemp = bTemp;
574 if( !p )
575 pIo->SetError( ( m & StreamMode::WRITE )
576 ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
578 else if( !ValidateMode( m, p ) )
579 p = nullptr;
580 if( p && p->m_aEntry.GetType() != STG_STORAGE )
582 pIo->SetError( SVSTREAM_FILE_NOT_FOUND );
583 // coverity[overwrite_var] - ownership is not here, but with StgDirStrm
584 p = nullptr;
587 // Either direct or transacted mode is supported
588 if( p && pEntry->m_nRefCnt == 1 )
589 p->m_bDirect = bDirect;
591 // Don't check direct conflict if opening readonly
592 if( p && (m & StreamMode::WRITE ))
594 if( p->m_bDirect != bDirect )
595 SetError( SVSTREAM_ACCESS_DENIED );
597 Storage* pStg = new Storage( pIo, p, m );
598 pIo->MoveError( *pStg );
599 if( m & StreamMode::WRITE ) pStg->m_bAutoCommit = true;
600 return pStg;
603 // Open a stream
605 BaseStorageStream* Storage::OpenStream( const OUString& rName, StreamMode m, bool )
607 if( !Validate() || !ValidateMode( m ) )
608 return new StorageStream( pIo, nullptr, m );
609 StgDirEntry* p = StgDirStrm::Find( *pEntry, rName );
610 bool bTemp = false;
611 if( !p )
613 if( !( m & StreamMode::NOCREATE ) )
615 // create a new stream
616 // make a name if the stream is temporary (has no name)
617 OUString aNewName( rName );
618 if( aNewName.isEmpty() )
620 aNewName = "Temp Strm " + OUString::number( ++nTmpCount );
621 bTemp = true;
623 p = pIo->m_pTOC->Create( *pEntry, aNewName, STG_STREAM );
625 if( !p )
626 pIo->SetError( ( m & StreamMode::WRITE )
627 ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
629 else if( !ValidateMode( m, p ) )
630 p = nullptr;
631 // coverity[Resource leak : FALSE] - "Create" method is called with STG_STREAM line 620,
632 // so we won't enter into this "if" block here.
633 if( p && p->m_aEntry.GetType() != STG_STREAM )
635 pIo->SetError( SVSTREAM_FILE_NOT_FOUND );
636 p = nullptr;
638 if( p )
640 p->m_bTemp = bTemp;
641 p->m_bDirect = pEntry->m_bDirect;
643 StorageStream* pStm = new StorageStream( pIo, p, m );
644 if( p && !p->m_bDirect )
645 pStm->SetAutoCommit( true );
646 pIo->MoveError( *pStm );
647 return pStm;
650 // Delete a stream or substorage by setting the temp bit.
652 void Storage::Remove( const OUString& rName )
654 if( !Validate( true ) )
655 return;
656 StgDirEntry* p = StgDirStrm::Find( *pEntry, rName );
657 if( p )
659 p->Invalidate( true );
661 else
663 SetError( SVSTREAM_FILE_NOT_FOUND );
667 // Copy one element
669 bool Storage::CopyTo( const OUString& rElem, BaseStorage* pDest, const OUString& rNew )
671 if( !Validate() || !pDest || !pDest->Validate( true ) )
672 return false;
673 StgDirEntry* pElem = StgDirStrm::Find( *pEntry, rElem );
674 if( pElem )
676 if( pElem->m_aEntry.GetType() == STG_STORAGE )
678 // copy the entire storage
679 tools::SvRef<BaseStorage> p1 = OpenStorage( rElem, INTERNAL_MODE );
680 tools::SvRef<BaseStorage> p2 = pDest->OpenOLEStorage( rNew, StreamMode::WRITE | StreamMode::SHARE_DENYALL, pEntry->m_bDirect );
682 if ( p2 )
684 ErrCode nTmpErr = p2->GetError();
685 if( !nTmpErr )
687 p2->SetClassId( p1->GetClassId() );
688 p1->CopyTo( *p2 );
689 SetError( p1->GetError() );
691 nTmpErr = p2->GetError();
692 if( !nTmpErr )
693 p2->Commit();
694 else
695 pDest->SetError( nTmpErr );
697 else
698 pDest->SetError( nTmpErr );
701 return Good() && pDest->Good();
703 else
705 // stream copy
706 tools::SvRef<BaseStorageStream> p1 = OpenStream( rElem, INTERNAL_MODE );
707 tools::SvRef<BaseStorageStream> p2 = pDest->OpenStream( rNew, StreamMode::WRITE | StreamMode::SHARE_DENYALL, pEntry->m_bDirect );
709 if ( p2 )
711 ErrCode nTmpErr = p2->GetError();
712 if( !nTmpErr )
714 p1->CopyTo( p2.get() );
715 SetError( p1->GetError() );
717 nTmpErr = p2->GetError();
718 if( !nTmpErr )
719 p2->Commit();
720 else
721 pDest->SetError( nTmpErr );
723 else
724 pDest->SetError( nTmpErr );
727 return Good() && pDest->Good();
730 SetError( SVSTREAM_FILE_NOT_FOUND );
731 return false;
734 bool Storage::CopyTo( BaseStorage& rDest ) const
736 if( !Validate() || !rDest.Validate( true ) || Equals( rDest ) )
738 SetError( SVSTREAM_ACCESS_DENIED );
739 return false;
741 Storage* pThis = const_cast<Storage*>(this);
742 rDest.SetClassId( GetClassId() );
743 rDest.SetDirty();
744 SvStorageInfoList aList;
745 FillInfoList( &aList );
746 bool bRes = true;
747 for( size_t i = 0; i < aList.size() && bRes; i++ )
749 SvStorageInfo& rInfo = aList[ i ];
750 bRes = pThis->CopyTo( rInfo.GetName(), &rDest, rInfo.GetName() );
752 if( !bRes )
753 SetError( rDest.GetError() );
754 return Good() && rDest.Good();
757 bool Storage::IsStorage( const OUString& rName ) const
759 if( Validate() )
761 StgDirEntry* p = StgDirStrm::Find( *pEntry, rName );
762 if( p )
763 return p->m_aEntry.GetType() == STG_STORAGE;
765 return false;
768 bool Storage::IsStream( const OUString& rName ) const
770 if( Validate() )
772 StgDirEntry* p = StgDirStrm::Find( *pEntry, rName );
773 if( p )
774 return p->m_aEntry.GetType() == STG_STREAM;
776 return false;
779 bool Storage::IsContained( const OUString& rName ) const
781 if( Validate() )
782 return StgDirStrm::Find( *pEntry, rName ) != nullptr;
783 else
784 return false;
787 // Commit all sub-elements within this storage. If this is
788 // the root, commit the FAT, the TOC and the header as well.
790 bool Storage::Commit()
792 bool bRes = true;
793 if( !Validate() )
794 return false;
795 if( !( m_nMode & StreamMode::WRITE ) )
797 SetError( SVSTREAM_ACCESS_DENIED );
798 return false;
800 else
802 // Also commit the sub-streams and Storages
803 StgIterator aIter( *pEntry );
804 for( StgDirEntry* p = aIter.First(); p && bRes; p = aIter.Next() )
805 bRes = p->Commit();
806 if( bRes && bIsRoot )
808 bRes = pEntry->Commit();
809 if( bRes )
810 bRes = pIo->CommitAll();
812 pIo->MoveError( *this );
814 return bRes;
817 bool Storage::Revert()
819 return true;
822 ///////////////////////////// OLE Support
824 // Set the storage type
826 void Storage::SetClass( const SvGlobalName & rClass,
827 SotClipboardFormatId nOriginalClipFormat,
828 const OUString & rUserTypeName )
830 if( Validate( true ) )
832 // set the class name in the root entry
833 pEntry->m_aEntry.SetClassId( rClass.GetCLSID() );
834 pEntry->SetDirty();
835 // then create the streams
836 StgCompObjStream aCompObj( *this, true );
837 aCompObj.GetClsId() = rClass.GetCLSID();
838 aCompObj.GetCbFormat() = nOriginalClipFormat;
839 aCompObj.GetUserName() = rUserTypeName;
840 if( !aCompObj.Store() )
841 SetError( aCompObj.GetError() );
842 else
844 StgOleStream aOle(*this);
845 if( !aOle.Store() )
846 SetError( aOle.GetError() );
849 else
850 SetError( SVSTREAM_ACCESS_DENIED );
853 SvGlobalName Storage::GetClassName()
855 StgCompObjStream aCompObj( *this, false );
856 if( aCompObj.Load() )
857 return SvGlobalName( aCompObj.GetClsId() );
858 pIo->ResetError();
860 if ( pEntry )
861 return SvGlobalName( pEntry->m_aEntry.GetClassId() );
863 return SvGlobalName();
866 SotClipboardFormatId Storage::GetFormat()
868 StgCompObjStream aCompObj( *this, false );
869 if( aCompObj.Load() )
870 return aCompObj.GetCbFormat();
871 pIo->ResetError();
872 return SotClipboardFormatId::NONE;
875 OUString Storage::GetUserName()
877 StgCompObjStream aCompObj( *this, false );
878 if( aCompObj.Load() )
879 return aCompObj.GetUserName();
880 pIo->ResetError();
881 return OUString();
884 bool Storage::ValidateFAT()
886 FatError nErr = pIo->ValidateFATs();
887 return nErr == FatError::Ok;
890 void Storage::SetDirty()
892 if ( pEntry )
893 pEntry->SetDirty();
896 void Storage::SetClassId( const ClsId& rId )
898 if ( pEntry )
899 pEntry->m_aEntry.SetClassId( rId );
902 const ClsId& Storage::GetClassId() const
904 if ( pEntry )
905 return pEntry->m_aEntry.GetClassId();
907 static const ClsId aDummyId = {0,0,0,{0,0,0,0,0,0,0,0}};
908 return aDummyId;
911 bool Storage::Validate( bool bValidate ) const
913 bool bRet = Validate_Impl( bValidate );
914 if ( !bRet )
915 SetError( SVSTREAM_ACCESS_DENIED );
916 return bRet;
919 bool Storage::ValidateMode( StreamMode nMode ) const
921 bool bRet = ValidateMode_Impl( nMode );
922 if ( !bRet )
923 SetError( SVSTREAM_ACCESS_DENIED );
924 return bRet;
927 bool Storage::ValidateMode( StreamMode nMode, StgDirEntry const * p ) const
929 bool bRet = ValidateMode_Impl( nMode, p );
930 if ( !bRet )
931 SetError( SVSTREAM_ACCESS_DENIED );
932 return bRet;
935 bool Storage::Equals( const BaseStorage& rStorage ) const
937 const Storage* pOther = dynamic_cast<const Storage*>( &rStorage );
938 return pOther && ( pOther->pEntry == pEntry );
941 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */