Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  stg.cxx   Sprache: C

 
/* -*- 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/diagnose.h>
#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::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;

    assert(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 );
        // coverity[overwrite_var] - ownership is not here, but with StgDirStrm
        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 );
                    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& rDest ) const
{
    if( !Validate() || !rDest.Validate( true ) || Equals( rDest ) )
    {
        SetError( SVSTREAM_ACCESS_DENIED );
        return false;
    }
    Storage* pThis = const_cast<Storage*>(this);
    rDest.SetClassId( GetClassId() );
    rDest.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(), &rDest, rInfo.GetName() );
    }
    if( !bRes )
        SetError( rDest.GetError() );
    return Good() && rDest.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( *thistrue );
        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( *thisfalse );
    if( aCompObj.Load() )
        return SvGlobalName( aCompObj.GetClsId() );
    pIo->ResetError();

    if ( pEntry )
        return SvGlobalName( pEntry->m_aEntry.GetClassId() );

    return SvGlobalName();
}

SotClipboardFormatId Storage::GetFormat()
{
    StgCompObjStream aCompObj( *thisfalse );
    if( aCompObj.Load() )
        return aCompObj.GetCbFormat();
    pIo->ResetError();
    return SotClipboardFormatId::NONE;
}

OUString Storage::GetUserName()
{
    StgCompObjStream aCompObj( *thisfalse );
    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: */

Messung V0.5
C=93 H=97 G=94

¤ Dauer der Verarbeitung: 0.15 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge