diff options
Diffstat (limited to 'embedserv/source/embed/ed_ipersiststr.cxx')
-rwxr-xr-x | embedserv/source/embed/ed_ipersiststr.cxx | 1018 |
1 files changed, 1018 insertions, 0 deletions
diff --git a/embedserv/source/embed/ed_ipersiststr.cxx b/embedserv/source/embed/ed_ipersiststr.cxx new file mode 100755 index 000000000000..c36247eef46b --- /dev/null +++ b/embedserv/source/embed/ed_ipersiststr.cxx @@ -0,0 +1,1018 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#if defined(_MSC_VER) && (_MSC_VER > 1310) +#pragma warning(disable : 4917 4555) +#endif + +#include "embeddoc.hxx" +#include <com/sun/star/uno/Any.h> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XSeekable.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/frame/XLoadable.hpp> +#include <com/sun/star/util/XModifiable.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/frame/XComponentLoader.hpp> +#include <com/sun/star/util/XUrlTransformer.hpp> + + +#include <osl/mutex.hxx> +#include <osl/diagnose.h> + +#include <string.h> + +#define EXT_STREAM_LENGTH 16 + +using namespace ::com::sun::star; + +extern ::rtl::OUString getStorageTypeFromGUID_Impl( GUID* guid ); +extern ::rtl::OUString getServiceNameFromGUID_Impl( GUID* ); +extern ::rtl::OUString getFilterNameFromGUID_Impl( GUID* ); +// extern CLIPFORMAT getClipFormatFromGUID_Impl( GUID* ); +::rtl::OUString getTestFileURLFromGUID_Impl( GUID* guid ); + +const ::rtl::OUString aOfficeEmbedStreamName( RTL_CONSTASCII_USTRINGPARAM ( "package_stream" ) ); +const ::rtl::OUString aExtentStreamName( RTL_CONSTASCII_USTRINGPARAM ( "properties_stream" ) ); + +uno::Reference< io::XInputStream > createTempXInStreamFromIStream( + uno::Reference< lang::XMultiServiceFactory > xFactory, + IStream *pStream ) +{ + uno::Reference< io::XInputStream > xResult; + + if ( !pStream ) + return xResult; + + const ::rtl::OUString aServiceName ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.io.TempFile" ) ); + uno::Reference < io::XOutputStream > xTempOut = uno::Reference < io::XOutputStream > ( + xFactory->createInstance ( aServiceName ), + uno::UNO_QUERY ); + if ( xTempOut.is() ) + { + ULARGE_INTEGER nNewPos; + LARGE_INTEGER aZero = { 0L, 0L }; + HRESULT hr = pStream->Seek( aZero, STREAM_SEEK_SET, &nNewPos ); + if ( FAILED( hr ) ) return xResult; + + STATSTG aStat; + hr = pStream->Stat( &aStat, STATFLAG_NONAME ); + if ( FAILED( hr ) ) return xResult; + + sal_uInt32 nSize = (sal_uInt32)aStat.cbSize.QuadPart; + sal_uInt32 nCopied = 0; + uno::Sequence< sal_Int8 > aBuffer( nConstBufferSize ); + try + { + sal_uInt32 nRead = 0; + do + { + pStream->Read( (void*)aBuffer.getArray(), nConstBufferSize, &nRead ); + + if ( nRead < nConstBufferSize ) + aBuffer.realloc( nRead ); + + xTempOut->writeBytes( aBuffer ); + nCopied += nRead; + } while( nRead == nConstBufferSize ); + + if ( nCopied == nSize ) + { + uno::Reference < io::XSeekable > xTempSeek ( xTempOut, uno::UNO_QUERY ); + if ( xTempSeek.is() ) + { + xTempSeek->seek ( 0 ); + xResult = uno::Reference< io::XInputStream >( xTempOut, uno::UNO_QUERY ); + } + } + } + catch( uno::Exception& ) + { + } + } + + return xResult; +} + +HRESULT copyXTempOutToIStream( uno::Reference< io::XOutputStream > xTempOut, IStream* pStream ) +{ + if ( !xTempOut.is() || !pStream ) + return E_FAIL; + + uno::Reference < io::XSeekable > xTempSeek ( xTempOut, uno::UNO_QUERY ); + if ( !xTempSeek.is() ) + return E_FAIL; + + xTempSeek->seek ( 0 ); + + uno::Reference< io::XInputStream > xTempIn ( xTempOut, uno::UNO_QUERY ); + if ( !xTempSeek.is() ) + return E_FAIL; + + // Seek to zero and truncate the stream + ULARGE_INTEGER nNewPos; + LARGE_INTEGER aZero = { 0L, 0L }; + HRESULT hr = pStream->Seek( aZero, STREAM_SEEK_SET, &nNewPos ); + if ( FAILED( hr ) ) return E_FAIL; + ULARGE_INTEGER aUZero = { 0L, 0L }; + hr = pStream->SetSize( aUZero ); + if ( FAILED( hr ) ) return E_FAIL; + + uno::Sequence< sal_Int8 > aBuffer( nConstBufferSize ); + sal_uInt32 nReadBytes = 0; + + do + { + try { + nReadBytes = xTempIn->readBytes( aBuffer, nConstBufferSize ); + } + catch( uno::Exception& ) + { + return E_FAIL; + } + + sal_uInt32 nWritten = 0; + HRESULT hr = pStream->Write( (void*)aBuffer.getArray(), nReadBytes, &nWritten ); + if ( !SUCCEEDED( hr ) || nWritten != nReadBytes ) + return E_FAIL; + + } while( nReadBytes == nConstBufferSize ); + + return S_OK; +} + + +//=============================================================================== +// EmbedDocument_Impl +//=============================================================================== + +EmbedDocument_Impl::EmbedDocument_Impl( const uno::Reference< lang::XMultiServiceFactory >& xFactory, const GUID* guid ) +: m_refCount( 0L ) +, m_xFactory( xFactory ) +, m_guid( *guid ) +, m_bIsDirty( sal_False ) +, m_nAdviseNum( 0 ) +, m_bIsInVerbHandling( sal_False ) +//, m_bLoadedFromFile( sal_False ) +{ + m_xOwnAccess = new EmbeddedDocumentInstanceAccess_Impl( this ); + m_pDocHolder = new DocumentHolder( xFactory, m_xOwnAccess ); + m_pDocHolder->acquire(); +} + +EmbedDocument_Impl::~EmbedDocument_Impl() +{ + m_pDocHolder->FreeOffice(); + + if ( m_pDocHolder->HasFrame() && m_pDocHolder->IsLink() ) + { + // a link with frame should be only disconnected, not closed + m_pDocHolder->DisconnectFrameDocument( sal_True ); + } + else + { + m_pDocHolder->CloseDocument(); + m_pDocHolder->CloseFrame(); + } + + m_pDocHolder->release(); +} + +uno::Sequence< beans::PropertyValue > EmbedDocument_Impl::fillArgsForLoading_Impl( uno::Reference< io::XInputStream > xStream, DWORD /*nStreamMode*/, LPCOLESTR pFilePath ) +{ + uno::Sequence< beans::PropertyValue > aArgs( 3 ); + + sal_Int32 nInd = 0; // must not be bigger than the preset size + aArgs[nInd].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "FilterName" ) ); + aArgs[nInd++].Value <<= getFilterNameFromGUID_Impl( &m_guid ); + + if ( xStream.is() ) + { + aArgs[nInd].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "InputStream" ) ); + aArgs[nInd++].Value <<= xStream; + aArgs[nInd].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "URL" ) ); + aArgs[nInd++].Value <<= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "private:stream" ) ); + } + else + { + aArgs[nInd].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "URL" ) ); + + rtl::OUString sDocUrl; + if ( pFilePath ) + { + ::rtl::OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.util.URLTransformer" ) ); + uno::Reference< util::XURLTransformer > aTransformer( m_xFactory->createInstance( aServiceName ), + uno::UNO_QUERY ); + if ( aTransformer.is() ) + { + util::URL aURL; + + aURL.Complete = ::rtl::OUString( reinterpret_cast<const sal_Unicode*>(pFilePath) ); + + if ( aTransformer->parseSmart( aURL, ::rtl::OUString() ) ) + sDocUrl = aURL.Complete; + } + } + + aArgs[nInd++].Value <<= sDocUrl; + } + + aArgs.realloc( nInd ); + + // aArgs[].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "ReadOnly" ) ); + // aArgs[].Value <<= sal_False; //( ( nStreamMode & ( STGM_READWRITE | STGM_WRITE ) ) ? sal_True : sal_False ); + + return aArgs; +} + +uno::Sequence< beans::PropertyValue > EmbedDocument_Impl::fillArgsForStoring_Impl( uno::Reference< io::XOutputStream > xStream) +{ + uno::Sequence< beans::PropertyValue > aArgs( xStream.is() ? 2 : 1 ); + + aArgs[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "FilterName" ) ); + aArgs[0].Value <<= getFilterNameFromGUID_Impl( &m_guid ); + + if ( xStream.is() ) + { + aArgs[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "OutputStream" ) ); + aArgs[1].Value <<= xStream; + } + + return aArgs; +} + +HRESULT EmbedDocument_Impl::SaveTo_Impl( IStorage* pStg ) +{ + if ( !pStg || pStg == m_pMasterStorage ) + return E_FAIL; + + // for saveto operation the master storage + // should not enter NoScribble mode + CComPtr< IStream > pOrigOwn = m_pOwnStream; + CComPtr< IStream > pOrigExt = m_pExtStream; + HRESULT hr = Save( pStg, sal_False ); + pStg->Commit( STGC_ONLYIFCURRENT ); + m_pOwnStream = pOrigOwn; + m_pExtStream = pOrigExt; + + return hr; +} + +//------------------------------------------------------------------------------- +// IUnknown + +STDMETHODIMP EmbedDocument_Impl::QueryInterface( REFIID riid, void FAR* FAR* ppv ) +{ + if(IsEqualIID(riid, IID_IUnknown)) + { + AddRef(); + *ppv = (IUnknown*) (IPersistStorage*) this; + return S_OK; + } + else if (IsEqualIID(riid, IID_IPersist)) + { + AddRef(); + *ppv = (IPersist*) (IPersistStorage*) this; + return S_OK; + } + else if (IsEqualIID(riid, IID_IExternalConnection)) + { + AddRef(); + *ppv = (IExternalConnection*) this; + return S_OK; + } + else if (IsEqualIID(riid, IID_IPersistStorage)) + { + AddRef(); + *ppv = (IPersistStorage*) this; + return S_OK; + } + else if (IsEqualIID(riid, IID_IDataObject)) + { + AddRef(); + *ppv = (IDataObject*) this; + return S_OK; + } + else if (IsEqualIID(riid, IID_IOleObject)) + { + AddRef(); + *ppv = (IOleObject*) this; + return S_OK; + } + else if (IsEqualIID(riid, IID_IOleWindow)) + { + AddRef(); + *ppv = (IOleWindow*) this; + return S_OK; + } + else if (IsEqualIID(riid, IID_IOleInPlaceObject)) + { + AddRef(); + *ppv = (IOleInPlaceObject*) this; + return S_OK; + } + else if (IsEqualIID(riid, IID_IPersistFile)) + { + AddRef(); + *ppv = (IPersistFile*) this; + return S_OK; + } + else if (IsEqualIID(riid, IID_IDispatch)) + { + AddRef(); + *ppv = (IDispatch*) this; + return S_OK; + } + + *ppv = NULL; + return ResultFromScode(E_NOINTERFACE); +} + +STDMETHODIMP_(ULONG) EmbedDocument_Impl::AddRef() +{ + return osl_incrementInterlockedCount( &m_refCount); +} + +STDMETHODIMP_(ULONG) EmbedDocument_Impl::Release() +{ + // if there is a time when the last reference is destructed, that means that only internal pointers are alive + // after the following call either the refcount is increased or the pointers are empty + if ( m_refCount == 1 ) + m_xOwnAccess->ClearEmbedDocument(); + + sal_Int32 nCount = osl_decrementInterlockedCount( &m_refCount ); + if ( nCount == 0 ) + delete this; + return nCount; +} + +//------------------------------------------------------------------------------- +// IPersist + +STDMETHODIMP EmbedDocument_Impl::GetClassID( CLSID* pClassId ) +{ + *pClassId = *&m_guid; + return S_OK; +} + +//------------------------------------------------------------------------------- +// IPersistStorage + +STDMETHODIMP EmbedDocument_Impl::IsDirty() +{ + // the link modified state is controlled by the document + if ( m_bIsDirty && !m_aFileName.getLength() ) + return S_OK; + + uno::Reference< util::XModifiable > xMod( m_pDocHolder->GetDocument(), uno::UNO_QUERY ); + if ( xMod.is() ) + return xMod->isModified() ? S_OK : S_FALSE; + return S_FALSE; +} + +STDMETHODIMP EmbedDocument_Impl::InitNew( IStorage *pStg ) +{ + HRESULT hr = CO_E_ALREADYINITIALIZED; + + if ( !m_pDocHolder->GetDocument().is() ) + { + + STATSTG aStat; + hr = pStg->Stat( &aStat, STATFLAG_NONAME ); + if ( FAILED( hr ) ) return E_FAIL; + + DWORD nStreamMode = aStat.grfMode; + + hr = E_FAIL; + if ( m_xFactory.is() && pStg ) + { + uno::Reference< frame::XModel > aDocument( + m_xFactory->createInstance( getServiceNameFromGUID_Impl( &m_guid ) ), + uno::UNO_QUERY ); + if ( aDocument.is() ) + { + m_pDocHolder->SetDocument( aDocument ); + + uno::Reference< frame::XLoadable > xLoadable( m_pDocHolder->GetDocument(), uno::UNO_QUERY ); + if( xLoadable.is() ) + { + try + { + xLoadable->initNew(); + // xLoadable->load( fillArgsForLoading_Impl( uno::Reference< io::XInputStream >(), nStreamMode ) ); + hr = S_OK; + } + catch( uno::Exception& ) + { + } + } + + if ( hr == S_OK ) + { + ::rtl::OUString aCurType = getStorageTypeFromGUID_Impl( &m_guid ); // ??? + CLIPFORMAT cf = (CLIPFORMAT)RegisterClipboardFormatA( "Embedded Object" ); + hr = WriteFmtUserTypeStg( pStg, + cf, // ??? + reinterpret_cast<LPWSTR>(( sal_Unicode* )aCurType.getStr()) ); + + if ( hr == S_OK ) + { + hr = pStg->CreateStream( reinterpret_cast<LPCWSTR>(aOfficeEmbedStreamName.getStr()), + STGM_CREATE | ( nStreamMode & 0x73 ), + 0, + 0, + &m_pOwnStream ); + + if ( hr == S_OK && m_pOwnStream ) + { + hr = pStg->CreateStream( reinterpret_cast<LPCWSTR>(aExtentStreamName.getStr()), + STGM_CREATE | ( nStreamMode & 0x73 ), + 0, + 0, + &m_pExtStream ); + + if ( hr == S_OK && m_pExtStream ) + { + + m_pMasterStorage = pStg; + m_bIsDirty = sal_True; + } + else + hr = E_FAIL; + } + else + hr = E_FAIL; + } + else + hr = E_FAIL; + } + + if ( hr != S_OK ) + m_pDocHolder->CloseDocument(); + } + } + } + + return hr; +} + +STDMETHODIMP EmbedDocument_Impl::Load( IStorage *pStg ) +{ + if ( m_pDocHolder->GetDocument().is() ) + return CO_E_ALREADYINITIALIZED; + + if ( !m_xFactory.is() || !pStg ) + return E_FAIL; + + HRESULT hr = E_FAIL; + + STATSTG aStat; + hr = pStg->Stat( &aStat, STATFLAG_NONAME ); + if ( FAILED( hr ) ) return E_FAIL; + + DWORD nStreamMode = aStat.grfMode; + hr = pStg->OpenStream( reinterpret_cast<LPCWSTR>(aOfficeEmbedStreamName.getStr()), + 0, + nStreamMode & 0x73, + 0, + &m_pOwnStream ); + if ( !m_pOwnStream ) hr = E_FAIL; + + if ( SUCCEEDED( hr ) ) + { + hr = pStg->OpenStream( reinterpret_cast<LPCWSTR>(aExtentStreamName.getStr()), + 0, + nStreamMode & 0x73, + 0, + &m_pExtStream ); + if ( !m_pExtStream ) hr = E_FAIL; + } + + // RECTL aRectToSet; + SIZEL aSizeToSet; + if ( SUCCEEDED( hr ) ) + { + ULARGE_INTEGER nNewPos; + LARGE_INTEGER aZero = { 0L, 0L }; + hr = m_pExtStream->Seek( aZero, STREAM_SEEK_SET, &nNewPos ); + if ( SUCCEEDED( hr ) ) + { + sal_uInt32 nRead; + sal_Int8 aInf[EXT_STREAM_LENGTH]; + hr = m_pExtStream->Read( (void*)aInf, EXT_STREAM_LENGTH, &nRead ); + if ( nRead != EXT_STREAM_LENGTH ) hr = E_FAIL; + + if ( SUCCEEDED( hr ) ) + { + // aRectToSet.left = *((sal_Int32*)aInf); + // aRectToSet.top = *((sal_Int32*)&aInf[4]); + // aRectToSet.right = *((sal_Int32*)&aInf[8]); + // aRectToSet.bottom = *((sal_Int32*)&aInf[12]); + aSizeToSet.cx = *((sal_Int32*)&aInf[8]) - *((sal_Int32*)aInf); + aSizeToSet.cy = *((sal_Int32*)&aInf[12]) - *((sal_Int32*)&aInf[4]); + } + } + } + + if ( SUCCEEDED( hr ) ) + { + hr = E_FAIL; + + uno::Reference < io::XInputStream > xTempIn = createTempXInStreamFromIStream( m_xFactory, m_pOwnStream ); + if ( xTempIn.is() ) + { + uno::Reference< frame::XModel > aDocument( + m_xFactory->createInstance( getServiceNameFromGUID_Impl( &m_guid ) ), + uno::UNO_QUERY ); + if ( aDocument.is() ) + { + m_pDocHolder->SetDocument( aDocument ); + + uno::Reference< frame::XLoadable > xLoadable( m_pDocHolder->GetDocument(), uno::UNO_QUERY ); + if( xLoadable.is() ) + { + try + { + xLoadable->load( fillArgsForLoading_Impl( xTempIn, nStreamMode ) ); + m_pMasterStorage = pStg; + hr = m_pDocHolder->SetExtent( &aSizeToSet ); + // hr = m_pDocHolder->SetVisArea( &aRectToSet ); + } + catch( uno::Exception& ) + { + } + } + + if ( FAILED( hr ) ) + m_pDocHolder->CloseDocument(); + } + } + } + + if ( FAILED( hr ) ) + { + m_pOwnStream = CComPtr< IStream >(); + m_pExtStream = CComPtr< IStream >(); + hr = pStg->DestroyElement( reinterpret_cast<LPCWSTR>(aOfficeEmbedStreamName.getStr()) ); + hr = pStg->DestroyElement( reinterpret_cast<LPCWSTR>(aExtentStreamName.getStr()) ); + + OSL_ENSURE( SUCCEEDED( hr ), "Can not destroy created stream!\n" ); + if ( FAILED( hr ) ) + hr = E_FAIL; + } + + return hr; +} + +STDMETHODIMP EmbedDocument_Impl::Save( IStorage *pStgSave, BOOL fSameAsLoad ) +{ + if ( !m_pDocHolder->GetDocument().is() || !m_xFactory.is() || !pStgSave || !m_pOwnStream || !m_pExtStream ) + return E_FAIL; + + CComPtr< IStream > pTargetStream; + CComPtr< IStream > pNewExtStream; + + if ( !fSameAsLoad && pStgSave != m_pMasterStorage ) + { + OSL_ENSURE( m_pMasterStorage, "How could the document be initialized without storage!??\n" ); + HRESULT hr = m_pMasterStorage->CopyTo( NULL, NULL, NULL, pStgSave ); + if ( FAILED( hr ) ) return E_FAIL; + + STATSTG aStat; + hr = pStgSave->Stat( &aStat, STATFLAG_NONAME ); + if ( FAILED( hr ) ) return E_FAIL; + + DWORD nStreamMode = aStat.grfMode; + hr = pStgSave->CreateStream( reinterpret_cast<LPCWSTR>(aOfficeEmbedStreamName.getStr()), + STGM_CREATE | ( nStreamMode & 0x73 ), + 0, + 0, + &pTargetStream ); + if ( FAILED( hr ) || !pTargetStream ) return E_FAIL; + + hr = pStgSave->CreateStream( reinterpret_cast<LPCWSTR>(aExtentStreamName.getStr()), + STGM_CREATE | ( nStreamMode & 0x73 ), + 0, + 0, + &pNewExtStream ); + if ( FAILED( hr ) || !pNewExtStream ) return E_FAIL; + } + else + { + pTargetStream = m_pOwnStream; + pNewExtStream = m_pExtStream; + } + + HRESULT hr = E_FAIL; + + const ::rtl::OUString aServiceName ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.io.TempFile" ) ); + uno::Reference < io::XOutputStream > xTempOut = uno::Reference < io::XOutputStream > ( + m_xFactory->createInstance ( aServiceName ), + uno::UNO_QUERY ); + + if ( xTempOut.is() ) + { + uno::Reference< frame::XStorable > xStorable( m_pDocHolder->GetDocument(), uno::UNO_QUERY ); + if( xStorable.is() ) + { + try + { + xStorable->storeToURL( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "private:stream" ) ), + fillArgsForStoring_Impl( xTempOut ) ); + hr = copyXTempOutToIStream( xTempOut, pTargetStream ); + if ( SUCCEEDED( hr ) ) + { + // no need to truncate the stream, the size of the stream is always the same + ULARGE_INTEGER nNewPos; + LARGE_INTEGER aZero = { 0L, 0L }; + hr = pNewExtStream->Seek( aZero, STREAM_SEEK_SET, &nNewPos ); + if ( SUCCEEDED( hr ) ) + { + SIZEL aSize; + hr = m_pDocHolder->GetExtent( &aSize ); + + if ( SUCCEEDED( hr ) ) + { + sal_uInt32 nWritten; + sal_Int8 aInf[EXT_STREAM_LENGTH]; + *((sal_Int32*)aInf) = 0; + *((sal_Int32*)&aInf[4]) = 0; + *((sal_Int32*)&aInf[8]) = aSize.cx; + *((sal_Int32*)&aInf[12]) = aSize.cy; + + hr = pNewExtStream->Write( (void*)aInf, EXT_STREAM_LENGTH, &nWritten ); + if ( nWritten != EXT_STREAM_LENGTH ) hr = E_FAIL; + + if ( SUCCEEDED( hr ) ) + { + m_pOwnStream = CComPtr< IStream >(); + m_pExtStream = CComPtr< IStream >(); + if ( fSameAsLoad || pStgSave == m_pMasterStorage ) + { + uno::Reference< util::XModifiable > xMod( m_pDocHolder->GetDocument(), uno::UNO_QUERY ); + if ( xMod.is() ) + xMod->setModified( sal_False ); + m_bIsDirty = sal_False; + } + } + } + } + } + } + catch( uno::Exception& ) + { + } + } + } + + return hr; +} + +STDMETHODIMP EmbedDocument_Impl::SaveCompleted( IStorage *pStgNew ) +{ + // m_pOwnStream == NULL && m_pMasterStorage != NULL means the object is in NoScribble mode + // m_pOwnStream == NULL && m_pMasterStorage == NULL means the object is in HandsOff mode + + if ( m_pOwnStream || m_pExtStream ) + return E_UNEXPECTED; + + if ( !m_pMasterStorage && !pStgNew ) + return E_INVALIDARG; + + if ( pStgNew ) + m_pMasterStorage = pStgNew; + + STATSTG aStat; + HRESULT hr = m_pMasterStorage->Stat( &aStat, STATFLAG_NONAME ); + if ( FAILED( hr ) ) return E_OUTOFMEMORY; + + DWORD nStreamMode = aStat.grfMode; + hr = m_pMasterStorage->OpenStream( reinterpret_cast<LPCWSTR>(aOfficeEmbedStreamName.getStr()), + 0, + nStreamMode & 0x73, + 0, + &m_pOwnStream ); + if ( FAILED( hr ) || !m_pOwnStream ) return E_OUTOFMEMORY; + + hr = m_pMasterStorage->OpenStream( reinterpret_cast<LPCWSTR>(aExtentStreamName.getStr()), + 0, + nStreamMode & 0x73, + 0, + &m_pExtStream ); + if ( FAILED( hr ) || !m_pExtStream ) return E_OUTOFMEMORY; + + sal_Bool bModified = sal_False; + uno::Reference< util::XModifiable > xMod( m_pDocHolder->GetDocument(), uno::UNO_QUERY ); + if ( xMod.is() ) + bModified = xMod->isModified(); + + for ( AdviseSinkHashMapIterator iAdvise = m_aAdviseHashMap.begin(); iAdvise != m_aAdviseHashMap.end(); iAdvise++ ) + { + if ( iAdvise->second ) + iAdvise->second->OnSave(); + } + + if ( xMod.is() ) + bModified = xMod->isModified(); + + return S_OK; +} + +STDMETHODIMP EmbedDocument_Impl::HandsOffStorage() +{ + m_pMasterStorage = CComPtr< IStorage >(); + m_pOwnStream = CComPtr< IStream >(); + m_pExtStream = CComPtr< IStream >(); + + return S_OK; +} + +//------------------------------------------------------------------------------- +// IPersistFile + +STDMETHODIMP EmbedDocument_Impl::Load( LPCOLESTR pszFileName, DWORD /*dwMode*/ ) +{ + if ( m_pDocHolder->GetDocument().is() ) + return CO_E_ALREADYINITIALIZED; + + if ( !m_xFactory.is() ) + return E_FAIL; + + DWORD nStreamMode = STGM_CREATE | STGM_READWRITE | STGM_DELETEONRELEASE | STGM_SHARE_EXCLUSIVE; + HRESULT hr = StgCreateDocfile( NULL, + nStreamMode , + 0, + &m_pMasterStorage ); + + if ( FAILED( hr ) || !m_pMasterStorage ) return E_FAIL; + + ::rtl::OUString aCurType = getServiceNameFromGUID_Impl( &m_guid ); // ??? + CLIPFORMAT cf = (CLIPFORMAT)RegisterClipboardFormatA( "Embedded Object" ); + hr = WriteFmtUserTypeStg( m_pMasterStorage, + cf, // ??? + reinterpret_cast<LPWSTR>(( sal_Unicode* )aCurType.getStr()) ); + if ( FAILED( hr ) ) return E_FAIL; + + hr = m_pMasterStorage->SetClass( m_guid ); + if ( FAILED( hr ) ) return E_FAIL; + + hr = m_pMasterStorage->CreateStream( reinterpret_cast<LPCWSTR>(aOfficeEmbedStreamName.getStr()), + STGM_CREATE | ( nStreamMode & 0x73 ), + 0, + 0, + &m_pOwnStream ); + if ( FAILED( hr ) || !m_pOwnStream ) return E_FAIL; + + hr = m_pMasterStorage->CreateStream( reinterpret_cast<LPCWSTR>(aExtentStreamName.getStr()), + STGM_CREATE | ( nStreamMode & 0x73 ), + 0, + 0, + &m_pExtStream ); + if ( FAILED( hr ) || !m_pExtStream ) return E_FAIL; + + + uno::Reference< frame::XModel > aDocument( + m_xFactory->createInstance( getServiceNameFromGUID_Impl( &m_guid ) ), + uno::UNO_QUERY ); + if ( aDocument.is() ) + { + m_pDocHolder->SetDocument( aDocument, sal_True ); + + uno::Reference< frame::XLoadable > xLoadable( m_pDocHolder->GetDocument(), uno::UNO_QUERY ); + if( xLoadable.is() ) + { + try + { + xLoadable->load( fillArgsForLoading_Impl( uno::Reference< io::XInputStream >(), + STGM_READWRITE, + pszFileName ) ); + hr = S_OK; + + m_aFileName = ::rtl::OUString( reinterpret_cast<const sal_Unicode*>(pszFileName) ); + } + catch( uno::Exception& ) + { + } + } + + if ( hr == S_OK ) + { + ::rtl::OUString aCurType = getServiceNameFromGUID_Impl( &m_guid ); // ??? + CLIPFORMAT cf = (CLIPFORMAT)RegisterClipboardFormatA( "Embedded Object" ); + hr = WriteFmtUserTypeStg( m_pMasterStorage, + cf, // ??? + reinterpret_cast<LPWSTR>(( sal_Unicode* )aCurType.getStr()) ); + + if ( SUCCEEDED( hr ) ) + { + // no need to truncate the stream, the size of the stream is always the same + ULARGE_INTEGER nNewPos; + LARGE_INTEGER aZero = { 0L, 0L }; + hr = m_pExtStream->Seek( aZero, STREAM_SEEK_SET, &nNewPos ); + if ( SUCCEEDED( hr ) ) + { + SIZEL aSize; + hr = m_pDocHolder->GetExtent( &aSize ); + + if ( SUCCEEDED( hr ) ) + { + sal_uInt32 nWritten; + sal_Int8 aInf[EXT_STREAM_LENGTH]; + *((sal_Int32*)aInf) = 0; + *((sal_Int32*)&aInf[4]) = 0; + *((sal_Int32*)&aInf[8]) = aSize.cx; + *((sal_Int32*)&aInf[12]) = aSize.cy; + + hr = m_pExtStream->Write( (void*)aInf, EXT_STREAM_LENGTH, &nWritten ); + if ( nWritten != EXT_STREAM_LENGTH ) hr = E_FAIL; + } + } + } + + if ( SUCCEEDED( hr ) ) + m_bIsDirty = sal_True; + else + hr = E_FAIL; + } + + if ( FAILED( hr ) ) + { + m_pDocHolder->CloseDocument(); + m_pOwnStream = NULL; + m_pExtStream = NULL; + m_pMasterStorage = NULL; + } + } + + return hr; +} + +STDMETHODIMP EmbedDocument_Impl::Save( LPCOLESTR pszFileName, BOOL fRemember ) +{ + if ( !m_pDocHolder->GetDocument().is() || !m_xFactory.is() ) + return E_FAIL; + + HRESULT hr = E_FAIL; + + // TODO/LATER: currently there is no hands off state implemented + try + { + uno::Reference< frame::XStorable > xStorable( m_pDocHolder->GetDocument(), uno::UNO_QUERY_THROW ); + + if ( !pszFileName ) + xStorable->store(); + else + { + util::URL aURL; + aURL.Complete = ::rtl::OUString( reinterpret_cast<const sal_Unicode*>( pszFileName ) ); + + ::rtl::OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.util.URLTransformer" ) ); + uno::Reference< util::XURLTransformer > aTransformer( m_xFactory->createInstance( aServiceName ), + uno::UNO_QUERY_THROW ); + + if ( aTransformer->parseSmart( aURL, ::rtl::OUString() ) && aURL.Complete.getLength() ) + { + if ( fRemember ) + { + xStorable->storeAsURL( aURL.Complete, fillArgsForStoring_Impl( uno::Reference< io::XOutputStream >() ) ); + m_aFileName = aURL.Complete; + } + else + xStorable->storeToURL( aURL.Complete, fillArgsForStoring_Impl( uno::Reference< io::XOutputStream >() ) ); + } + } + + hr = S_OK; + } + catch( uno::Exception& ) + { + } + + return hr; +} + +STDMETHODIMP EmbedDocument_Impl::SaveCompleted( LPCOLESTR pszFileName ) +{ + // the different file name would mean error here + m_aFileName = ::rtl::OUString( reinterpret_cast<const sal_Unicode*>(pszFileName) ); + return S_OK; +} + +STDMETHODIMP EmbedDocument_Impl::GetCurFile( LPOLESTR *ppszFileName ) +{ + CComPtr<IMalloc> pMalloc; + + HRESULT hr = CoGetMalloc( 1, &pMalloc ); + if ( FAILED( hr ) || !pMalloc ) return E_FAIL; + + *ppszFileName = (LPOLESTR)( pMalloc->Alloc( sizeof( sal_Unicode ) * ( m_aFileName.getLength() + 1 ) ) ); + wcsncpy( *ppszFileName, reinterpret_cast<LPCWSTR>(m_aFileName.getStr()), m_aFileName.getLength() + 1 ); + + return m_aFileName.getLength() ? S_OK : S_FALSE; +} + +// =============================================== + +LockedEmbedDocument_Impl EmbeddedDocumentInstanceAccess_Impl::GetEmbedDocument() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + return LockedEmbedDocument_Impl( m_pEmbedDocument ); +} + +void EmbeddedDocumentInstanceAccess_Impl::ClearEmbedDocument() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + m_pEmbedDocument = NULL; +} + +// =============================================== + +LockedEmbedDocument_Impl::LockedEmbedDocument_Impl() +: m_pEmbedDocument( NULL ) +{} + +LockedEmbedDocument_Impl::LockedEmbedDocument_Impl( EmbedDocument_Impl* pEmbedDocument ) +: m_pEmbedDocument( pEmbedDocument ) +{ + if ( m_pEmbedDocument ) + m_pEmbedDocument->AddRef(); +} + +LockedEmbedDocument_Impl::LockedEmbedDocument_Impl( const LockedEmbedDocument_Impl& aDocLock ) +: m_pEmbedDocument( aDocLock.m_pEmbedDocument ) +{ + if ( m_pEmbedDocument ) + m_pEmbedDocument->AddRef(); +} + +LockedEmbedDocument_Impl& LockedEmbedDocument_Impl::operator=( const LockedEmbedDocument_Impl& aDocLock ) +{ + if ( m_pEmbedDocument ) + m_pEmbedDocument->Release(); + + m_pEmbedDocument = aDocLock.m_pEmbedDocument; + if ( m_pEmbedDocument ) + m_pEmbedDocument->AddRef(); + + return *this; +} + +LockedEmbedDocument_Impl::~LockedEmbedDocument_Impl() +{ + if ( m_pEmbedDocument ) + m_pEmbedDocument->Release(); +} + +void LockedEmbedDocument_Impl::ExecuteMethod( sal_Int16 nId ) +{ + if ( m_pEmbedDocument ) + { + if ( nId == OLESERV_SAVEOBJECT ) + m_pEmbedDocument->SaveObject(); + else if ( nId == OLESERV_CLOSE ) + m_pEmbedDocument->Close( 0 ); + else if ( nId == OLESERV_NOTIFY ) + m_pEmbedDocument->notify(); + else if ( nId == OLESERV_NOTIFYCLOSING ) + m_pEmbedDocument->OLENotifyClosing(); + else if ( nId == OLESERV_SHOWOBJECT ) + m_pEmbedDocument->ShowObject(); + else if ( nId == OLESERV_DEACTIVATE ) + m_pEmbedDocument->Deactivate(); + } +} + +// Fix strange warnings about some +// ATL::CAxHostWindow::QueryInterface|AddRef|Releae functions. +// warning C4505: 'xxx' : unreferenced local function has been removed +#if defined(_MSC_VER) +#pragma warning(disable: 4505) +#endif + |