diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /sot/source/sdstor/stg.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-upstream.tar.xz libreoffice-upstream.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sot/source/sdstor/stg.cxx')
-rw-r--r-- | sot/source/sdstor/stg.cxx | 939 |
1 files changed, 939 insertions, 0 deletions
diff --git a/sot/source/sdstor/stg.cxx b/sot/source/sdstor/stg.cxx new file mode 100644 index 000000000..08af34309 --- /dev/null +++ b/sot/source/sdstor/stg.cxx @@ -0,0 +1,939 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <sot/storinfo.hxx> +#include <osl/file.hxx> +#include <unotools/tempfile.hxx> +#include <tools/stream.hxx> +#include <tools/debug.hxx> + +#include <sot/stg.hxx> +#include <utility> +#include "stgelem.hxx" +#include "stgdir.hxx" +#include "stgio.hxx" +#include "stgole.hxx" + +static tools::Long nTmpCount = 0; + +// The internal open mode is StreamMode::READ | StreamMode::TRUNC, which is silly +// by itself. It inhibits the checking of sharing modes and is used +// during CopyTo() and MoveTo() for opening a stream in read mode +// although it may be open in DENYALL mode + +#define INTERNAL_MODE ( StreamMode::READ | StreamMode::TRUNC ) + +///////////////////////// class StorageBase + + +StorageBase::StorageBase() + : m_bAutoCommit( false ) +{ + m_nMode = StreamMode::READ; + m_nError = ERRCODE_NONE; +} + +StorageBase::~StorageBase() +{ +} + +// The following three methods are declared as const, since they +// may be called from within a const method. + +ErrCode StorageBase::GetError() const +{ + const ErrCode n = m_nError; + m_nError = ERRCODE_NONE; + return n; +} + +void StorageBase::SetError( ErrCode n ) const +{ + if( !m_nError ) + m_nError = n; +} + +void StorageBase::ResetError() const +{ + m_nError = ERRCODE_NONE; +} + +OLEStorageBase::OLEStorageBase( StgIo* p, StgDirEntry* pe, StreamMode& nMode ) + : nStreamMode( nMode ), pIo( p ), pEntry( pe ) +{ + if ( p ) + p->IncRef(); + if( pe ) + pe->m_nRefCnt++; +} + +OLEStorageBase::~OLEStorageBase() +{ + if( pEntry ) + { + DBG_ASSERT( pEntry->m_nRefCnt, "RefCount under 0" ); + if( !--pEntry->m_nRefCnt ) + { + if( pEntry->m_bZombie ) + delete pEntry; + else + pEntry->Close(); + } + + pEntry = nullptr; + } + + + if( pIo && !pIo->DecRef() ) + { + delete pIo; + pIo = nullptr; + } +} + +// Validate the instance for I/O + +bool OLEStorageBase::Validate_Impl( bool bWrite ) const +{ + return pIo + && pIo->m_pTOC + && pEntry + && !pEntry->m_bInvalid + && ( !bWrite || !pEntry->m_bDirect || ( nStreamMode & StreamMode::WRITE ) ); +} + +bool OLEStorageBase::ValidateMode_Impl( StreamMode m, StgDirEntry const * p ) +{ + if( m == INTERNAL_MODE ) + return true; + StreamMode nCurMode = ( p && p->m_nRefCnt ) ? p->m_nMode : StreamMode::SHARE_DENYALL; + if( ( m & StreamMode::READWRITE ) == StreamMode::READ ) + { + // only SHARE_DENYWRITE or SHARE_DENYALL allowed + if( ( ( m & StreamMode::SHARE_DENYWRITE ) + && ( nCurMode & StreamMode::SHARE_DENYWRITE ) ) + || ( ( m & StreamMode::SHARE_DENYALL ) + && ( nCurMode & StreamMode::SHARE_DENYALL ) ) ) + return true; + } + else + { + // only SHARE_DENYALL allowed + // storages open in r/o mode are OK, since only + // the commit may fail + if( ( m & StreamMode::SHARE_DENYALL ) + && ( nCurMode & StreamMode::SHARE_DENYALL ) ) + return true; + } + return false; +} + + +//////////////////////// class StorageStream + + +StorageStream::StorageStream( StgIo* p, StgDirEntry* q, StreamMode m ) + : OLEStorageBase( p, q, m_nMode ), nPos( 0 ) +{ + // The dir entry may be 0; this means that the stream is invalid. + if( q && p ) + { + if( q->m_nRefCnt == 1 ) + { + q->m_nMode = m; + q->OpenStream( *p ); + } + } + else + m &= ~StreamMode::READWRITE; + m_nMode = m; +} + +StorageStream::~StorageStream() +{ + // Do an auto-commit if the entry is open in direct mode + if( m_bAutoCommit ) + Commit(); + if( pEntry && pEntry->m_nRefCnt && pEntry->m_bDirect && (m_nMode & StreamMode::WRITE) ) + pEntry->Commit(); +} + +bool StorageStream::Equals( const BaseStorageStream& rStream ) const +{ + const StorageStream* pOther = dynamic_cast<const StorageStream*>( &rStream ); + return pOther && ( pOther->pEntry == pEntry ); +} + +sal_Int32 StorageStream::Read( void* pData, sal_Int32 nSize ) +{ + if( Validate() ) + { + pEntry->Seek( nPos ); + nSize = pEntry->Read( pData, nSize ); + pIo->MoveError( *this ); + nPos += nSize; + } + else + nSize = 0; + return nSize; +} + +sal_Int32 StorageStream::Write( const void* pData, sal_Int32 nSize ) +{ + if( Validate( true ) ) + { + pEntry->Seek( nPos ); + nSize = pEntry->Write( pData, nSize ); + pIo->MoveError( *this ); + nPos += nSize; + } + else + nSize = 0; + return nSize; +} + +sal_uInt64 StorageStream::Seek( sal_uInt64 n ) +{ + if( Validate() ) + { + nPos = pEntry->Seek( n ); + return nPos; + } + else + return n; +} + +void StorageStream::Flush() +{ + // Flushing means committing, since streams are never transacted + Commit(); +} + +bool StorageStream::SetSize( sal_uInt64 nNewSize ) +{ + if( Validate( true ) ) + { + bool b = pEntry->SetSize( nNewSize ); + pIo->MoveError( *this ); + return b; + } + else + return false; +} + +sal_uInt64 StorageStream::GetSize() const +{ + if( Validate() ) + return pEntry->GetSize(); + return 0; +} + +bool StorageStream::Commit() +{ + if( !Validate() ) + return false; + if( !( m_nMode & StreamMode::WRITE ) ) + { + SetError( SVSTREAM_ACCESS_DENIED ); + return false; + } + else + { + pEntry->Commit(); + pIo->MoveError( *this ); + return Good(); + } +} + +void StorageStream::CopyTo( BaseStorageStream* pDest ) +{ + if( !Validate() || !pDest || !pDest->Validate( true ) || Equals( *pDest ) ) + return; + pEntry->Copy( *pDest ); + pDest->Commit(); + pIo->MoveError( *this ); + SetError( pDest->GetError() ); +} + +bool StorageStream::Validate( bool bValidate ) const +{ + bool bRet = Validate_Impl( bValidate ); + if ( !bRet ) + SetError( SVSTREAM_ACCESS_DENIED ); + return bRet; +} + +bool StorageStream::ValidateMode( StreamMode nMode ) const +{ + bool bRet = ValidateMode_Impl( nMode ); + if ( !bRet ) + SetError( SVSTREAM_ACCESS_DENIED ); + return bRet; +} + +///////////////////////// class SvStorageInfo + +SvStorageInfo::SvStorageInfo( const StgDirEntry& rE ) +{ + rE.m_aEntry.GetName( aName ); + bStorage = rE.m_aEntry.GetType() == STG_STORAGE; + bStream = rE.m_aEntry.GetType() == STG_STREAM; + nSize = bStorage ? 0 : rE.m_aEntry.GetSize(); +} + +/////////////////////////// class Storage + +bool Storage::IsStorageFile( const OUString & rFileName ) +{ + StgIo aIo; + if( aIo.Open( rFileName, StreamMode::STD_READ ) ) + return aIo.Load(); + return false; +} + +bool Storage::IsStorageFile( SvStream* pStream ) +{ + bool bRet = false; + + if ( pStream ) + { + StgHeader aHdr; + sal_uInt64 nPos = pStream->Tell(); + bRet = ( aHdr.Load( *pStream ) && aHdr.Check() ); + + // It's not a stream error if it is too small for an OLE storage header + if ( pStream->GetErrorCode() == ERRCODE_IO_CANTSEEK ) + pStream->ResetError(); + pStream->Seek( nPos ); + } + + return bRet; +} + +// Open the storage file. If writing is permitted and the file is not +// a storage file, initialize it. + + +Storage::Storage( OUString aFile, StreamMode m, bool bDirect ) + : OLEStorageBase( new StgIo, nullptr, m_nMode ) + , aName(std::move( aFile )), bIsRoot( false ) +{ + bool bTemp = false; + if( aName.isEmpty() ) + { + // no name = temporary name! + aName = utl::TempFile::CreateTempName(); + bTemp = true; + } + // the root storage creates the I/O system + m_nMode = m; + if( pIo->Open( aName, m ) ) + { + Init( ( m & ( StreamMode::TRUNC | StreamMode::NOCREATE ) ) == StreamMode::TRUNC ); + if( pEntry ) + { + pEntry->m_bDirect = bDirect; + pEntry->m_nMode = m; + pEntry->m_bTemp = bTemp; + } + } + else + { + pIo->MoveError( *this ); + pEntry = nullptr; + } +} + +// Create a storage on a given stream. + +Storage::Storage( SvStream& r, bool bDirect ) + : OLEStorageBase( new StgIo, nullptr, m_nMode ) + , bIsRoot( false ) +{ + m_nMode = StreamMode::READ; + if( r.IsWritable() ) + m_nMode = StreamMode::READ | StreamMode::WRITE; + if( r.GetError() == ERRCODE_NONE ) + { + pIo->SetStrm( &r, false ); + sal_uInt64 nSize = r.TellEnd(); + r.Seek( 0 ); + // Initializing is OK if the stream is empty + Init( nSize == 0 ); + if( pEntry ) + { + pEntry->m_bDirect = bDirect; + pEntry->m_nMode = m_nMode; + } + pIo->MoveError( *this ); + } + else + { + SetError( r.GetError() ); + pEntry = nullptr; + } +} + + +Storage::Storage( UCBStorageStream& rStrm, bool bDirect ) + : OLEStorageBase( new StgIo, nullptr, m_nMode ), bIsRoot( false ) +{ + m_nMode = StreamMode::READ; + + if ( rStrm.GetError() != ERRCODE_NONE ) + { + SetError( rStrm.GetError() ); + pEntry = nullptr; + return; + } + + SvStream* pStream = rStrm.GetModifySvStream(); + if ( !pStream ) + { + OSL_FAIL( "UCBStorageStream can not provide SvStream implementation!" ); + SetError( SVSTREAM_GENERALERROR ); + pEntry = nullptr; + return; + } + + if( pStream->IsWritable() ) + m_nMode = StreamMode::READ | StreamMode::WRITE; + + pIo->SetStrm( &rStrm ); + + sal_uInt64 nSize = pStream->TellEnd(); + pStream->Seek( 0 ); + // Initializing is OK if the stream is empty + Init( nSize == 0 ); + if( pEntry ) + { + pEntry->m_bDirect = bDirect; + pEntry->m_nMode = m_nMode; + } + + pIo->MoveError( *this ); +} + + +// Perform common code for both ctors above. + +void Storage::Init( bool bCreate ) +{ + pEntry = nullptr; + bool bHdrLoaded = false; + bIsRoot = true; + + OSL_ENSURE( pIo, "The pointer may not be empty at this point!" ); + if( pIo->Good() && pIo->GetStrm() ) + { + sal_uInt64 nSize = pIo->GetStrm()->TellEnd(); + pIo->GetStrm()->Seek( 0 ); + if( nSize ) + { + bHdrLoaded = pIo->Load(); + if( !bHdrLoaded && !bCreate ) + { + // File is not a storage and not empty; do not destroy! + SetError( SVSTREAM_FILEFORMAT_ERROR ); + return; + } + } + } + // file is a storage, empty or should be overwritten + pIo->ResetError(); + // we have to set up the data structures, since + // the file is empty + if( !bHdrLoaded ) + pIo->Init(); + if( pIo->Good() && pIo->m_pTOC ) + { + pEntry = pIo->m_pTOC->GetRoot(); + pEntry->m_nRefCnt++; + } +} + +// Internal ctor + +Storage::Storage( StgIo* p, StgDirEntry* q, StreamMode m ) + : OLEStorageBase( p, q, m_nMode ), bIsRoot( false ) +{ + if( q ) + q->m_aEntry.GetName( aName ); + else + m &= ~StreamMode::READWRITE; + m_nMode = m; + if( q && q->m_nRefCnt == 1 ) + q->m_nMode = m; +} + +Storage::~Storage() +{ + // Invalidate all open substorages + if( m_bAutoCommit ) + Commit(); + if( pEntry ) + { + // Do an auto-commit if the entry is open in direct mode + if( pEntry->m_nRefCnt && pEntry->m_bDirect && (m_nMode & StreamMode::WRITE) ) + Commit(); + if( pEntry->m_nRefCnt == 1 ) + pEntry->Invalidate(false); + } + // close the stream is root storage + if( bIsRoot ) + pIo->Close(); + // remove the file if temporary root storage + if( bIsRoot && pEntry && pEntry->m_bTemp ) + { + osl::File::remove( GetName() ); + } +} + +const OUString& Storage::GetName() const +{ + if( !bIsRoot && Validate() ) + pEntry->m_aEntry.GetName( const_cast<Storage*>(this)->aName ); + return aName; +} + +// Fill in the info list for this storage + +void Storage::FillInfoList( SvStorageInfoList* pList ) const +{ + if( !(Validate() && pList) ) + return; + + StgIterator aIter( *pEntry ); + StgDirEntry* p = aIter.First(); + while( p ) + { + if( !p->m_bInvalid ) + { + SvStorageInfo aInfo( *p ); + pList->push_back( aInfo ); + } + p = aIter.Next(); + } +} + +// Open or create a substorage + +BaseStorage* Storage::OpenUCBStorage( const OUString& rName, StreamMode m, bool bDirect ) +{ + OSL_FAIL("Not supported!"); + return OpenStorage( rName, m, bDirect ); +} + +BaseStorage* Storage::OpenOLEStorage( const OUString& rName, StreamMode m, bool bDirect ) +{ + return OpenStorage( rName, m, bDirect ); +} + +BaseStorage* Storage::OpenStorage( const OUString& rName, StreamMode m, bool bDirect ) +{ + if( !Validate() || !ValidateMode( m ) ) + return new Storage( pIo, nullptr, m ); + if( bDirect && !pEntry->m_bDirect ) + bDirect = false; + + StgDirEntry* p = StgDirStrm::Find( *pEntry, rName ); + if( !p ) + { + if( !( m & StreamMode::NOCREATE ) ) + { + bool bTemp = false; + // create a new storage + OUString aNewName = rName; + if( aNewName.isEmpty() ) + { + aNewName = "Temp Stg " + OUString::number( ++nTmpCount ); + bTemp = true; + } + p = pIo->m_pTOC->Create( *pEntry, aNewName, STG_STORAGE ); + if( p ) + p->m_bTemp = bTemp; + } + if( !p ) + pIo->SetError( ( m & StreamMode::WRITE ) + ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND ); + } + else if( !ValidateMode( m, p ) ) + p = nullptr; + if( p && p->m_aEntry.GetType() != STG_STORAGE ) + { + pIo->SetError( SVSTREAM_FILE_NOT_FOUND ); + p = nullptr; + } + + // Either direct or transacted mode is supported + if( p && pEntry->m_nRefCnt == 1 ) + p->m_bDirect = bDirect; + + // Don't check direct conflict if opening readonly + if( p && (m & StreamMode::WRITE )) + { + if( p->m_bDirect != bDirect ) + SetError( SVSTREAM_ACCESS_DENIED ); + } + Storage* pStg = new Storage( pIo, p, m ); + pIo->MoveError( *pStg ); + if( m & StreamMode::WRITE ) pStg->m_bAutoCommit = true; + return pStg; +} + +// Open a stream + +BaseStorageStream* Storage::OpenStream( const OUString& rName, StreamMode m, bool ) +{ + if( !Validate() || !ValidateMode( m ) ) + return new StorageStream( pIo, nullptr, m ); + StgDirEntry* p = StgDirStrm::Find( *pEntry, rName ); + bool bTemp = false; + if( !p ) + { + if( !( m & StreamMode::NOCREATE ) ) + { + // create a new stream + // make a name if the stream is temporary (has no name) + OUString aNewName( rName ); + if( aNewName.isEmpty() ) + { + aNewName = "Temp Strm " + OUString::number( ++nTmpCount ); + bTemp = true; + } + p = pIo->m_pTOC->Create( *pEntry, aNewName, STG_STREAM ); + } + if( !p ) + pIo->SetError( ( m & StreamMode::WRITE ) + ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND ); + } + else if( !ValidateMode( m, p ) ) + p = nullptr; + // coverity[Resource leak : FALSE] - "Create" method is called with STG_STREAM line 620, + // so we won't enter into this "if" block here. + if( p && p->m_aEntry.GetType() != STG_STREAM ) + { + pIo->SetError( SVSTREAM_FILE_NOT_FOUND ); + p = nullptr; + } + if( p ) + { + p->m_bTemp = bTemp; + p->m_bDirect = pEntry->m_bDirect; + } + StorageStream* pStm = new StorageStream( pIo, p, m ); + if( p && !p->m_bDirect ) + pStm->SetAutoCommit( true ); + pIo->MoveError( *pStm ); + return pStm; +} + +// Delete a stream or substorage by setting the temp bit. + +void Storage::Remove( const OUString& rName ) +{ + if( !Validate( true ) ) + return; + StgDirEntry* p = StgDirStrm::Find( *pEntry, rName ); + if( p ) + { + p->Invalidate( true ); + } + else + { + SetError( SVSTREAM_FILE_NOT_FOUND ); + } +} + +// Copy one element + +bool Storage::CopyTo( const OUString& rElem, BaseStorage* pDest, const OUString& rNew ) +{ + if( !Validate() || !pDest || !pDest->Validate( true ) ) + return false; + StgDirEntry* pElem = StgDirStrm::Find( *pEntry, rElem ); + if( pElem ) + { + if( pElem->m_aEntry.GetType() == STG_STORAGE ) + { + // copy the entire storage + tools::SvRef<BaseStorage> p1 = OpenStorage( rElem, INTERNAL_MODE ); + tools::SvRef<BaseStorage> p2 = pDest->OpenOLEStorage( rNew, StreamMode::WRITE | StreamMode::SHARE_DENYALL, pEntry->m_bDirect ); + + if ( p2 ) + { + ErrCode nTmpErr = p2->GetError(); + if( !nTmpErr ) + { + p2->SetClassId( p1->GetClassId() ); + p1->CopyTo( p2.get() ); + SetError( p1->GetError() ); + + nTmpErr = p2->GetError(); + if( !nTmpErr ) + p2->Commit(); + else + pDest->SetError( nTmpErr ); + } + else + pDest->SetError( nTmpErr ); + } + + return Good() && pDest->Good(); + } + else + { + // stream copy + tools::SvRef<BaseStorageStream> p1 = OpenStream( rElem, INTERNAL_MODE ); + tools::SvRef<BaseStorageStream> p2 = pDest->OpenStream( rNew, StreamMode::WRITE | StreamMode::SHARE_DENYALL, pEntry->m_bDirect ); + + if ( p2 ) + { + ErrCode nTmpErr = p2->GetError(); + if( !nTmpErr ) + { + p1->CopyTo( p2.get() ); + SetError( p1->GetError() ); + + nTmpErr = p2->GetError(); + if( !nTmpErr ) + p2->Commit(); + else + pDest->SetError( nTmpErr ); + } + else + pDest->SetError( nTmpErr ); + } + + return Good() && pDest->Good(); + } + } + SetError( SVSTREAM_FILE_NOT_FOUND ); + return false; +} + +bool Storage::CopyTo( BaseStorage* pDest ) const +{ + if( !Validate() || !pDest || !pDest->Validate( true ) || Equals( *pDest ) ) + { + SetError( SVSTREAM_ACCESS_DENIED ); + return false; + } + Storage* pThis = const_cast<Storage*>(this); + pDest->SetClassId( GetClassId() ); + pDest->SetDirty(); + SvStorageInfoList aList; + FillInfoList( &aList ); + bool bRes = true; + for( size_t i = 0; i < aList.size() && bRes; i++ ) + { + SvStorageInfo& rInfo = aList[ i ]; + bRes = pThis->CopyTo( rInfo.GetName(), pDest, rInfo.GetName() ); + } + if( !bRes ) + SetError( pDest->GetError() ); + return Good() && pDest->Good(); +} + +bool Storage::IsStorage( const OUString& rName ) const +{ + if( Validate() ) + { + StgDirEntry* p = StgDirStrm::Find( *pEntry, rName ); + if( p ) + return p->m_aEntry.GetType() == STG_STORAGE; + } + return false; +} + +bool Storage::IsStream( const OUString& rName ) const +{ + if( Validate() ) + { + StgDirEntry* p = StgDirStrm::Find( *pEntry, rName ); + if( p ) + return p->m_aEntry.GetType() == STG_STREAM; + } + return false; +} + +bool Storage::IsContained( const OUString& rName ) const +{ + if( Validate() ) + return StgDirStrm::Find( *pEntry, rName ) != nullptr; + else + return false; +} + +// Commit all sub-elements within this storage. If this is +// the root, commit the FAT, the TOC and the header as well. + +bool Storage::Commit() +{ + bool bRes = true; + if( !Validate() ) + return false; + if( !( m_nMode & StreamMode::WRITE ) ) + { + SetError( SVSTREAM_ACCESS_DENIED ); + return false; + } + else + { + // Also commit the sub-streams and Storages + StgIterator aIter( *pEntry ); + for( StgDirEntry* p = aIter.First(); p && bRes; p = aIter.Next() ) + bRes = p->Commit(); + if( bRes && bIsRoot ) + { + bRes = pEntry->Commit(); + if( bRes ) + bRes = pIo->CommitAll(); + } + pIo->MoveError( *this ); + } + return bRes; +} + +bool Storage::Revert() +{ + return true; +} + +///////////////////////////// OLE Support + +// Set the storage type + +void Storage::SetClass( const SvGlobalName & rClass, + SotClipboardFormatId nOriginalClipFormat, + const OUString & rUserTypeName ) +{ + if( Validate( true ) ) + { + // set the class name in the root entry + pEntry->m_aEntry.SetClassId( rClass.GetCLSID() ); + pEntry->SetDirty(); + // then create the streams + StgCompObjStream aCompObj( *this, true ); + aCompObj.GetClsId() = rClass.GetCLSID(); + aCompObj.GetCbFormat() = nOriginalClipFormat; + aCompObj.GetUserName() = rUserTypeName; + if( !aCompObj.Store() ) + SetError( aCompObj.GetError() ); + else + { + StgOleStream aOle(*this); + if( !aOle.Store() ) + SetError( aOle.GetError() ); + } + } + else + SetError( SVSTREAM_ACCESS_DENIED ); +} + +SvGlobalName Storage::GetClassName() +{ + StgCompObjStream aCompObj( *this, false ); + if( aCompObj.Load() ) + return SvGlobalName( aCompObj.GetClsId() ); + pIo->ResetError(); + + if ( pEntry ) + return SvGlobalName( pEntry->m_aEntry.GetClassId() ); + + return SvGlobalName(); +} + +SotClipboardFormatId Storage::GetFormat() +{ + StgCompObjStream aCompObj( *this, false ); + if( aCompObj.Load() ) + return aCompObj.GetCbFormat(); + pIo->ResetError(); + return SotClipboardFormatId::NONE; +} + +OUString Storage::GetUserName() +{ + StgCompObjStream aCompObj( *this, false ); + if( aCompObj.Load() ) + return aCompObj.GetUserName(); + pIo->ResetError(); + return OUString(); +} + +bool Storage::ValidateFAT() +{ + FatError nErr = pIo->ValidateFATs(); + return nErr == FatError::Ok; +} + +void Storage::SetDirty() +{ + if ( pEntry ) + pEntry->SetDirty(); +} + +void Storage::SetClassId( const ClsId& rId ) +{ + if ( pEntry ) + pEntry->m_aEntry.SetClassId( rId ); +} + +const ClsId& Storage::GetClassId() const +{ + if ( pEntry ) + return pEntry->m_aEntry.GetClassId(); + + static const ClsId aDummyId = {0,0,0,{0,0,0,0,0,0,0,0}}; + return aDummyId; +} + +bool Storage::Validate( bool bValidate ) const +{ + bool bRet = Validate_Impl( bValidate ); + if ( !bRet ) + SetError( SVSTREAM_ACCESS_DENIED ); + return bRet; +} + +bool Storage::ValidateMode( StreamMode nMode ) const +{ + bool bRet = ValidateMode_Impl( nMode ); + if ( !bRet ) + SetError( SVSTREAM_ACCESS_DENIED ); + return bRet; +} + +bool Storage::ValidateMode( StreamMode nMode, StgDirEntry const * p ) const +{ + bool bRet = ValidateMode_Impl( nMode, p ); + if ( !bRet ) + SetError( SVSTREAM_ACCESS_DENIED ); + return bRet; +} + +bool Storage::Equals( const BaseStorage& rStorage ) const +{ + const Storage* pOther = dynamic_cast<const Storage*>( &rStorage ); + return pOther && ( pOther->pEntry == pEntry ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |