blob: 67177cf0985fd383da891fab59758dfa061d9ab9 [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sot.hxx"
#include <sot/storinfo.hxx>
#include <osl/file.hxx>
#include <tools/tempfile.hxx>
#include <tools/ownlist.hxx>
#include <tools/string.hxx>
#ifndef _TOOLS_FSYS_HXX
#include <tools/fsys.hxx>
#endif
#ifndef _TOOLS_STREAM_HXX
#include <tools/stream.hxx>
#endif
#include <tools/pstm.hxx>
#include <tools/debug.hxx>
#include "sot/stg.hxx"
#include "stgelem.hxx"
#include "stgcache.hxx"
#include "stgstrms.hxx"
#include "stgdir.hxx"
#include "stgio.hxx"
#include "stgole.hxx"
static long nTmpCount = 0;
// The internal open mode is STREAM_READ | STREAM_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 ( STREAM_READ | STREAM_TRUNC )
///////////////////////// class StorageBase //////////////////////////////
TYPEINIT0( StorageBase );
TYPEINIT1( BaseStorageStream, StorageBase );
TYPEINIT1( BaseStorage, StorageBase );
StorageBase::StorageBase()
: m_bAutoCommit( sal_False )
{
m_nMode = STREAM_READ;
m_nError = SVSTREAM_OK;
}
StorageBase::~StorageBase()
{
}
// The following three methods are declared as const, since they
// may be called from within a const method.
sal_uLong StorageBase::GetError() const
{
sal_uLong n = m_nError;
((StorageBase*) this)->m_nError = SVSTREAM_OK;
return n;
}
void StorageBase::SetError( sal_uLong n ) const
{
if( !m_nError )
((StorageBase*) this)->m_nError = n;
}
void StorageBase::ResetError() const
{
((StorageBase*) this)->m_nError = SVSTREAM_OK;
}
// Retrieve the underlying SvStream for info purposes
const SvStream* OLEStorageBase::GetSvStream_Impl() const
{
return pIo ? pIo->GetStrm() : NULL;
}
OLEStorageBase::OLEStorageBase( StgIo* p, StgDirEntry* pe, StreamMode& nMode )
: nStreamMode( nMode ), pIo( p ), pEntry( pe )
{
if ( p )
p->IncRef();
if( pe )
pe->nRefCnt++;
}
OLEStorageBase::~OLEStorageBase()
{
if( pEntry )
{
DBG_ASSERT( pEntry->nRefCnt, "RefCount unter 0" );
if( !--pEntry->nRefCnt )
{
if( pEntry->bZombie )
delete pEntry;
else
pEntry->Close();
}
pEntry = NULL;
}
if( pIo && !pIo->DecRef() )
{
delete pIo;
pIo = NULL;
}
}
// Validate the instance for I/O
sal_Bool OLEStorageBase::Validate_Impl( sal_Bool bWrite ) const
{
if( pIo
&& pIo->pTOC
&& pEntry
&& !pEntry->bInvalid
&& ( !bWrite || !pEntry->bDirect || ( nStreamMode & STREAM_WRITE ) ) )
return sal_True;
return sal_False;
}
sal_Bool OLEStorageBase::ValidateMode_Impl( StreamMode m, StgDirEntry* p ) const
{
if( m == INTERNAL_MODE )
return sal_True;
sal_uInt16 nCurMode = ( p && p->nRefCnt ) ? p->nMode : 0xFFFF;
if( ( m & 3 ) == STREAM_READ )
{
// only SHARE_DENYWRITE or SHARE_DENYALL allowed
if( ( ( m & STREAM_SHARE_DENYWRITE )
&& ( nCurMode & STREAM_SHARE_DENYWRITE ) )
|| ( ( m & STREAM_SHARE_DENYALL )
&& ( nCurMode & STREAM_SHARE_DENYALL ) ) )
return sal_True;
}
else
{
// only SHARE_DENYALL allowed
// storages open in r/o mode are OK, since only
// the commit may fail
if( ( m & STREAM_SHARE_DENYALL )
&& ( nCurMode & STREAM_SHARE_DENYALL ) )
return sal_True;
}
return sal_False;
}
//////////////////////// class StorageStream /////////////////////////////
TYPEINIT1( StorageStream, BaseStorageStream );
StorageStream::StorageStream( StgIo* p, StgDirEntry* q, StreamMode m )
: OLEStorageBase( p, q, m_nMode ), nPos( 0L )
{
// The dir entry may be 0; this means that the stream is invalid.
if( q && p )
{
if( q->nRefCnt == 1 )
{
q->nMode = m;
q->OpenStream( *p );
}
}
else
m &= ~STREAM_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->nRefCnt && pEntry->bDirect && (m_nMode & STREAM_WRITE) )
pEntry->Commit();
}
sal_Bool StorageStream::Equals( const BaseStorageStream& rStream ) const
{
const StorageStream* pOther = PTR_CAST( StorageStream, &rStream );
return pOther && ( pOther->pEntry == pEntry );
}
sal_uLong StorageStream::Read( void* pData, sal_uLong nSize )
{
if( Validate() )
{
pEntry->Seek( nPos );
nSize = pEntry->Read( pData, (sal_Int32) nSize );
pIo->MoveError( *this );
nPos += nSize;
}
else
nSize = 0L;
return nSize;
}
sal_uLong StorageStream::Write( const void* pData, sal_uLong nSize )
{
if( Validate( sal_True ) )
{
pEntry->Seek( nPos );
nSize = pEntry->Write( pData, (sal_Int32) nSize );
pIo->MoveError( *this );
nPos += nSize;
}
else
nSize = 0L;
return nSize;
}
sal_uLong StorageStream::Seek( sal_uLong n )
{
if( Validate() )
return nPos = pEntry->Seek( n );
else
return n;
}
void StorageStream::Flush()
{
// Flushing means committing, since streams are never transacted
Commit();
}
sal_Bool StorageStream::SetSize( sal_uLong nNewSize )
{
if( Validate( sal_True ) )
{
sal_Bool b = pEntry->SetSize( (sal_Int32) nNewSize );
pIo->MoveError( *this );
return b;
}
else
return sal_False;
}
sal_Bool StorageStream::Commit()
{
if( !Validate() )
return sal_False;
if( !( m_nMode & STREAM_WRITE ) )
{
SetError( SVSTREAM_ACCESS_DENIED );
return sal_False;
}
else
{
pEntry->Commit();
pIo->MoveError( *this );
return Good();
}
}
sal_Bool StorageStream::Revert()
{
sal_Bool bResult = sal_False;
if ( Validate() )
{
pEntry->Revert();
pIo->MoveError( *this );
bResult = Good();
}
return bResult;
}
sal_Bool StorageStream::CopyTo( BaseStorageStream* pDest )
{
if( !Validate() || !pDest || !pDest->Validate( sal_True ) || Equals( *pDest ) )
return sal_False;
pEntry->Copy( *pDest );
pDest->Commit();
pIo->MoveError( *this );
SetError( pDest->GetError() );
return sal_Bool( Good() && pDest->Good() );
}
const SvStream* StorageStream::GetSvStream() const
{
return GetSvStream_Impl();
}
sal_Bool StorageStream::Validate( sal_Bool bValidate ) const
{
sal_Bool bRet = Validate_Impl( bValidate );
if ( !bRet )
SetError( SVSTREAM_ACCESS_DENIED );
return bRet;
}
sal_Bool StorageStream::ValidateMode( StreamMode nMode ) const
{
sal_Bool bRet = ValidateMode_Impl( nMode, NULL );
if ( !bRet )
SetError( SVSTREAM_ACCESS_DENIED );
return bRet;
}
sal_Bool StorageStream::ValidateMode( StreamMode nMode, StgDirEntry* p ) const
{
sal_Bool bRet = ValidateMode_Impl( nMode, p );
if ( !bRet )
SetError( SVSTREAM_ACCESS_DENIED );
return bRet;
}
///////////////////////// class SvStorageInfo //////////////////////////////
SvStorageInfo::SvStorageInfo( const StgDirEntry& rE )
{
rE.aEntry.GetName( aName );
bStorage = sal_Bool( rE.aEntry.GetType() == STG_STORAGE );
bStream = sal_Bool( rE.aEntry.GetType() == STG_STREAM );
nSize = bStorage ? 0 : rE.aEntry.GetSize();
}
/////////////////////////// class Storage ////////////////////////////////
sal_Bool Storage::IsStorageFile( const String & rFileName )
{
StgIo aIo;
if( aIo.Open( rFileName, STREAM_STD_READ ) )
return aIo.Load();
return sal_False;
}
sal_Bool Storage::IsStorageFile( SvStream* pStream )
{
sal_Bool bRet = sal_False;
if ( pStream )
{
StgHeader aHdr;
sal_uLong nPos = pStream->Tell();
bRet = ( aHdr.Load( *pStream ) && aHdr.Check() );
// It's not a stream error if it is too small for a 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.
TYPEINIT1( Storage, BaseStorage );
Storage::Storage( const String& rFile, StreamMode m, sal_Bool bDirect )
: OLEStorageBase( new StgIo, NULL, m_nMode ), aName( rFile ), bIsRoot( sal_False )
{
sal_Bool bTemp = sal_False;
if( !aName.Len() )
{
// no name = temporary name!
aName = TempFile::CreateTempName();
bTemp = sal_True;
}
// the root storage creates the I/O system
m_nMode = m;
if( pIo->Open( aName, m ) )
{
Init( sal_Bool( ( m & ( STREAM_TRUNC | STREAM_NOCREATE ) ) == STREAM_TRUNC ) );
if( pEntry )
{
pEntry->bDirect = bDirect;
pEntry->nMode = m;
pEntry->bTemp = bTemp;
}
}
else
{
pIo->MoveError( *this );
pEntry = NULL;
}
}
// Create a storage on a given stream.
Storage::Storage( SvStream& r, sal_Bool bDirect )
: OLEStorageBase( new StgIo, NULL, m_nMode ), bIsRoot( sal_False )
{
m_nMode = STREAM_READ;
if( r.IsWritable() )
m_nMode = STREAM_READ | STREAM_WRITE;
if( r.GetError() == SVSTREAM_OK )
{
pIo->SetStrm( &r, sal_False );
sal_uLong nSize = r.Seek( STREAM_SEEK_TO_END );
r.Seek( 0L );
// Initializing is OK if the stream is empty
Init( sal_Bool( nSize == 0 ) );
if( pEntry )
{
pEntry->bDirect = bDirect;
pEntry->nMode = m_nMode;
}
pIo->MoveError( *this );
}
else
{
SetError( r.GetError() );
pEntry = NULL;
}
}
Storage::Storage( UCBStorageStream& rStrm, sal_Bool bDirect )
: OLEStorageBase( new StgIo, NULL, m_nMode ), bIsRoot( sal_False )
{
m_nMode = STREAM_READ;
if ( rStrm.GetError() != SVSTREAM_OK )
{
SetError( rStrm.GetError() );
pEntry = NULL;
return;
}
SvStream* pStream = rStrm.GetModifySvStream();
if ( !pStream )
{
OSL_ENSURE( sal_False, "UCBStorageStream can not provide SvStream implementation!\n" );
SetError( SVSTREAM_GENERALERROR );
pEntry = NULL;
return;
}
if( pStream->IsWritable() )
m_nMode = STREAM_READ | STREAM_WRITE;
pIo->SetStrm( &rStrm );
sal_uLong nSize = pStream->Seek( STREAM_SEEK_TO_END );
pStream->Seek( 0L );
// Initializing is OK if the stream is empty
Init( sal_Bool( nSize == 0 ) );
if( pEntry )
{
pEntry->bDirect = bDirect;
pEntry->nMode = m_nMode;
}
pIo->MoveError( *this );
}
// Perform common code for both ctors above.
void Storage::Init( sal_Bool bCreate )
{
pEntry = NULL;
sal_Bool bHdrLoaded = sal_False;
bIsRoot = sal_True;
OSL_ENSURE( pIo, "The pointer may not be empty at this point!" );
if( pIo->Good() && pIo->GetStrm() )
{
sal_uLong nSize = pIo->GetStrm()->Seek( STREAM_SEEK_TO_END );
pIo->GetStrm()->Seek( 0L );
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->pTOC )
{
pEntry = pIo->pTOC->GetRoot();
pEntry->nRefCnt++;
}
}
// Internal ctor
Storage::Storage( StgIo* p, StgDirEntry* q, StreamMode m )
: OLEStorageBase( p, q, m_nMode ), bIsRoot( sal_False )
{
if( q )
q->aEntry.GetName( aName );
else
m &= ~STREAM_READWRITE;
m_nMode = m;
if( q && q->nRefCnt == 1 )
q->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->nRefCnt && pEntry->bDirect && (m_nMode & STREAM_WRITE) )
Commit();
if( pEntry->nRefCnt == 1 )
pEntry->Invalidate();
}
// close the stream is root storage
if( bIsRoot )
pIo->Close();
// remove the file if temporary root storage
if( bIsRoot && pEntry && pEntry->bTemp )
{
osl::File::remove( GetName() );
}
}
const String& Storage::GetName() const
{
if( !bIsRoot && Validate() )
pEntry->aEntry.GetName( ((Storage*) this)->aName );
return aName;
}
// Fill in the info list for this storage
void Storage::FillInfoList( SvStorageInfoList* pList ) const
{
if( Validate() && pList )
{
StgIterator aIter( *pEntry );
StgDirEntry* p = aIter.First();
while( p )
{
if( !p->bInvalid )
{
SvStorageInfo aInfo( *p );
pList->Append( aInfo );
}
p = aIter.Next();
}
}
}
// Open or create a substorage
BaseStorage* Storage::OpenUCBStorage( const String& rName, StreamMode m, sal_Bool bDirect )
{
DBG_ERROR("Not supported!");
/*
BaseStorage* pStorage = new Storage( pIo, NULL, m );
SetError( ERRCODE_IO_NOTSUPPORTED );
return pStorage;
*/
return OpenStorage( rName, m, bDirect );
}
BaseStorage* Storage::OpenOLEStorage( const String& rName, StreamMode m, sal_Bool bDirect )
{
return OpenStorage( rName, m, bDirect );
}
BaseStorage* Storage::OpenStorage( const String& rName, StreamMode m, sal_Bool bDirect )
{
if( !Validate() || !ValidateMode( m ) )
return new Storage( pIo, NULL, m );
sal_Bool bSetAutoCommit = sal_False;
if( bDirect && !pEntry->bDirect )
{
bSetAutoCommit = sal_True;
bDirect = sal_False;
}
StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
if( !p )
{
if( !( m & STREAM_NOCREATE ) )
{
sal_Bool bTemp = sal_False;
// create a new storage
String aNewName = rName;
if( !aNewName.Len() )
{
aNewName.AssignAscii( "Temp Stg " );
aNewName.Append( String::CreateFromInt32( ++nTmpCount ) );
bTemp = sal_True;
}
p = pIo->pTOC->Create( *pEntry, aNewName, STG_STORAGE );
if( p )
p->bTemp = bTemp;
}
if( !p )
pIo->SetError( ( m & STREAM_WRITE )
? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
}
else if( !ValidateMode( m, p ) )
p = NULL;
if( p && p->aEntry.GetType() != STG_STORAGE )
{
pIo->SetError( SVSTREAM_FILE_NOT_FOUND );
p = NULL;
}
// Either direct or transacted mode is supported
if( p && pEntry->nRefCnt == 1 )
p->bDirect = bDirect;
// Dont check direct conflict if opening readonly
if( p && (m & STREAM_WRITE ))
{
if( p->bDirect != bDirect )
SetError( SVSTREAM_ACCESS_DENIED );
}
Storage* pStg = new Storage( pIo, p, m );
pIo->MoveError( *pStg );
if( m & STREAM_WRITE ) pStg->m_bAutoCommit = sal_True;
return pStg;
}
// Open a stream
BaseStorageStream* Storage::OpenStream( const String& rName, StreamMode m, sal_Bool,
const ByteString*
#ifdef DBG_UTIL
pB
#endif
)
{
DBG_ASSERT(!pB, "Encryption not supported");
if( !Validate() || !ValidateMode( m ) )
return new StorageStream( pIo, NULL, m );
StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
sal_Bool bTemp = sal_False;
if( !p )
{
if( !( m & STREAM_NOCREATE ) )
{
// create a new stream
// make a name if the stream is temporary (has no name)
String aNewName( rName );
if( !aNewName.Len() )
{
aNewName.AssignAscii( "Temp Strm " );
aNewName.Append( String::CreateFromInt32( ++nTmpCount ) );
bTemp = sal_True;
}
p = pIo->pTOC->Create( *pEntry, aNewName, STG_STREAM );
}
if( !p )
pIo->SetError( ( m & STREAM_WRITE )
? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
}
else if( !ValidateMode( m, p ) )
p = NULL;
if( p && p->aEntry.GetType() != STG_STREAM )
{
pIo->SetError( SVSTREAM_FILE_NOT_FOUND );
p = NULL;
}
if( p )
{
p->bTemp = bTemp;
p->bDirect = pEntry->bDirect;
}
StorageStream* pStm = new StorageStream( pIo, p, m );
if( p && !p->bDirect )
pStm->SetAutoCommit( sal_True );
pIo->MoveError( *pStm );
return pStm;
}
// Delete a stream or substorage by setting the temp bit.
sal_Bool Storage::Remove( const String& rName )
{
if( !Validate( sal_True ) )
return sal_False;
StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
if( p )
{
p->Invalidate( sal_True );
return sal_True;
}
else
{
SetError( SVSTREAM_FILE_NOT_FOUND );
return sal_False;
}
}
// Rename a storage element
sal_Bool Storage::Rename( const String& rOld, const String& rNew )
{
if( Validate( sal_True ) )
{
sal_Bool b = pIo->pTOC->Rename( *pEntry, rOld, rNew );
pIo->MoveError( *this );
return b;
}
else
return sal_False;
}
// Copy one element
sal_Bool Storage::CopyTo( const String& rElem, BaseStorage* pDest, const String& rNew )
{
if( !Validate() || !pDest || !pDest->Validate( sal_True ) )
return sal_False;
StgDirEntry* pElem = pIo->pTOC->Find( *pEntry, rElem );
if( pElem )
{
/*
this lines are misterious !!! MM
if( !pElem->IsContained( pDest->pEntry ) )
{
SetError( SVSTREAM_ACCESS_DENIED );
return sal_False;
}
*/
if( pElem->aEntry.GetType() == STG_STORAGE )
{
// copy the entire storage
BaseStorage* p1 = OpenStorage( rElem, INTERNAL_MODE );
BaseStorage* p2 = pDest->OpenOLEStorage( rNew, STREAM_WRITE | STREAM_SHARE_DENYALL, pEntry->bDirect );
if ( p2 )
{
sal_uLong nTmpErr = p2->GetError();
if( !nTmpErr )
{
p2->SetClassId( p1->GetClassId() );
p1->CopyTo( p2 );
SetError( p1->GetError() );
nTmpErr = p2->GetError();
if( !nTmpErr )
p2->Commit();
else
pDest->SetError( nTmpErr );
}
else
pDest->SetError( nTmpErr );
}
delete p1;
delete p2;
return sal_Bool( Good() && pDest->Good() );
}
else
{
// stream copy
BaseStorageStream* p1 = OpenStream( rElem, INTERNAL_MODE );
BaseStorageStream* p2 = pDest->OpenStream( rNew, STREAM_WRITE | STREAM_SHARE_DENYALL, pEntry->bDirect );
if ( p2 )
{
sal_uLong nTmpErr = p2->GetError();
if( !nTmpErr )
{
p1->CopyTo( p2 );
SetError( p1->GetError() );
nTmpErr = p2->GetError();
if( !nTmpErr )
p2->Commit();
else
pDest->SetError( nTmpErr );
}
else
pDest->SetError( nTmpErr );
}
delete p1;
delete p2;
return sal_Bool( Good() && pDest->Good() );
}
}
SetError( SVSTREAM_FILE_NOT_FOUND );
return sal_False;
}
sal_Bool Storage::CopyTo( BaseStorage* pDest ) const
{
if( !Validate() || !pDest || !pDest->Validate( sal_True ) || Equals( *pDest ) )
{
SetError( SVSTREAM_ACCESS_DENIED );
return sal_False;
}
Storage* pThis = (Storage*) this;
/*
if( !pThis->pEntry->IsContained( pDest->pEntry ) )
{
SetError( SVSTREAM_ACCESS_DENIED );
return sal_False;
}
*/
pDest->SetClassId( GetClassId() );
pDest->SetDirty();
SvStorageInfoList aList;
FillInfoList( &aList );
sal_Bool bRes = sal_True;
for( sal_uInt16 i = 0; i < aList.Count() && bRes; i++ )
{
SvStorageInfo& rInfo = aList.GetObject( i );
bRes = pThis->CopyTo( rInfo.GetName(), pDest, rInfo.GetName() );
}
if( !bRes )
SetError( pDest->GetError() );
return sal_Bool( Good() && pDest->Good() );
}
// Move one element
sal_Bool Storage::MoveTo( const String& rElem, BaseStorage* pODest, const String& rNew )
{
if( !Validate() || !pODest || !pODest->Validate( sal_True ) || Equals( *pODest ) )
{
SetError( SVSTREAM_ACCESS_DENIED );
return sal_False;
}
StgDirEntry* pElem = pIo->pTOC->Find( *pEntry, rElem );
if( pElem )
{
// Simplest case: both storages share the same file
sal_Bool bRes;
Storage *pOther = PTR_CAST( Storage, pODest );
if( pOther && pIo == pOther->pIo && rElem == rNew )
{
Storage *p = (Storage*) pODest;
Storage *pDest = p;
// both storages are conventional storages, use implementation dependent code
if( !pElem->IsContained( pDest->pEntry ) )
{
// cyclic move
SetError( SVSTREAM_ACCESS_DENIED );
return sal_False;
}
bRes = pIo->pTOC->Move( *pEntry, *pDest->pEntry, rNew );
if( !bRes )
{
pIo->MoveError( *this );
pDest->pIo->MoveError( *pDest );
sal_uLong nErr = GetError();
if( !nErr )
nErr = pDest->GetError();
SetError( nErr );
pDest->SetError( nErr );
}
}
else
{
bRes = CopyTo( rElem, pODest, rNew );
if( bRes )
bRes = Remove( rElem );
}
if( !bRes )
SetError( pIo->GetError() );
return bRes;
}
SetError( SVSTREAM_FILE_NOT_FOUND );
return sal_False;
}
sal_Bool Storage::IsStorage( const String& rName ) const
{
if( Validate() )
{
StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
if( p )
return sal_Bool( p->aEntry.GetType() == STG_STORAGE );
}
return sal_False;
}
sal_Bool Storage::IsStream( const String& rName ) const
{
if( Validate() )
{
StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
if( p )
return sal_Bool( p->aEntry.GetType() == STG_STREAM );
}
return sal_False;
}
sal_Bool Storage::IsContained( const String& rName ) const
{
if( Validate() )
return sal_Bool( pIo->pTOC->Find( *pEntry, rName ) != NULL );
else
return sal_False;
}
// Commit all sub-elements within this storage. If this is
// the root, commit the FAT, the TOC and the header as well.
sal_Bool Storage::Commit()
{
sal_Bool bRes = sal_True;
if( !Validate() )
return sal_False;
if( !( m_nMode & STREAM_WRITE ) )
{
SetError( SVSTREAM_ACCESS_DENIED );
return sal_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;
}
sal_Bool Storage::Revert()
{
return sal_True;
}
///////////////////////////// OLE Support ////////////////////////////////
// Set the storage type
void Storage::SetClass( const SvGlobalName & rClass,
sal_uLong nOriginalClipFormat,
const String & rUserTypeName )
{
if( Validate( sal_True ) )
{
// set the class name in the root entry
pEntry->aEntry.SetClassId( (const ClsId&) rClass.GetCLSID() );
pEntry->SetDirty();
// then create the streams
StgCompObjStream aCompObj( *this, sal_True );
aCompObj.GetClsId() = (const ClsId&) rClass.GetCLSID();
aCompObj.GetCbFormat() = nOriginalClipFormat;
aCompObj.GetUserName() = rUserTypeName;
if( !aCompObj.Store() )
SetError( aCompObj.GetError() );
else
{
StgOleStream aOle( *this, STREAM_WRITE );
if( !aOle.Store() )
SetError( aOle.GetError() );
}
}
else
SetError( SVSTREAM_ACCESS_DENIED );
}
void Storage::SetConvertClass( const SvGlobalName & rConvertClass,
sal_uLong nOriginalClipFormat,
const String & rUserTypeName )
{
if( Validate( sal_True ) )
{
SetClass( rConvertClass, nOriginalClipFormat, rUserTypeName );
// plus the convert flag:
StgOleStream aOle( *this, sal_True );
aOle.GetFlags() |= 4;
if( !aOle.Store() )
SetError( aOle.GetError() );
}
}
SvGlobalName Storage::GetClassName()
{
StgCompObjStream aCompObj( *this, sal_False );
if( aCompObj.Load() )
return SvGlobalName( (const CLSID&) aCompObj.GetClsId() );
pIo->ResetError();
if ( pEntry )
return SvGlobalName( (const CLSID&) pEntry->aEntry.GetClassId() );
return SvGlobalName();
}
sal_uLong Storage::GetFormat()
{
StgCompObjStream aCompObj( *this, sal_False );
if( aCompObj.Load() )
return aCompObj.GetCbFormat();
pIo->ResetError();
return 0;
}
String Storage::GetUserName()
{
StgCompObjStream aCompObj( *this, sal_False );
if( aCompObj.Load() )
return aCompObj.GetUserName();
pIo->ResetError();
return String();
}
sal_Bool Storage::ShouldConvert()
{
StgOleStream aOle( *this, sal_False );
if( aOle.Load() )
return sal_Bool( ( aOle.GetFlags() & 4 ) != 0 );
else
{
pIo->ResetError();
return sal_False;
}
}
sal_Bool Storage::ValidateFAT()
{
Link aLink = StgIo::GetErrorLink();
ErrCode nErr = pIo->ValidateFATs();
StgIo::SetErrorLink( aLink );
return nErr == ERRCODE_NONE;
}
void Storage::SetDirty()
{
if ( pEntry )
pEntry->SetDirty();
}
void Storage::SetClassId( const ClsId& rId )
{
if ( pEntry )
pEntry->aEntry.SetClassId( rId );
}
const ClsId& Storage::GetClassId() const
{
if ( pEntry )
return pEntry->aEntry.GetClassId();
static ClsId aDummyId = {0,0,0,0,0,0,0,0,0,0,0};
return aDummyId;
}
const SvStream* Storage::GetSvStream() const
{
return GetSvStream_Impl();
}
sal_Bool Storage::Validate( sal_Bool bValidate ) const
{
sal_Bool bRet = Validate_Impl( bValidate );
if ( !bRet )
SetError( SVSTREAM_ACCESS_DENIED );
return bRet;
}
sal_Bool Storage::ValidateMode( StreamMode nMode ) const
{
sal_Bool bRet = ValidateMode_Impl( nMode );
if ( !bRet )
SetError( SVSTREAM_ACCESS_DENIED );
return bRet;
}
sal_Bool Storage::ValidateMode( StreamMode nMode, StgDirEntry* p ) const
{
sal_Bool bRet = ValidateMode_Impl( nMode, p );
if ( !bRet )
SetError( SVSTREAM_ACCESS_DENIED );
return bRet;
}
sal_Bool Storage::Equals( const BaseStorage& rStorage ) const
{
const Storage* pOther = PTR_CAST( Storage, &rStorage );
return pOther && ( pOther->pEntry == pEntry );
}