/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2008 by Sun Microsystems, Inc. * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: ed_ipersiststr.cxx,v $ * $Revision: 1.27 $ * * 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 * * for a copy of the LGPLv3 License. * ************************************************************************/ #if defined(_MSC_VER) && (_MSC_VER > 1310) #pragma warning(disable : 4917 4555) #endif #include "embeddoc.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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(); 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(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 ); 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_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(( sal_Unicode* )aCurType.getStr()) ); if ( hr == S_OK ) { hr = pStg->CreateStream( reinterpret_cast(aOfficeEmbedStreamName.getStr()), STGM_CREATE | ( nStreamMode & 0x73 ), 0, 0, &m_pOwnStream ); if ( hr == S_OK && m_pOwnStream ) { hr = pStg->CreateStream( reinterpret_cast(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(aOfficeEmbedStreamName.getStr()), 0, nStreamMode & 0x73, 0, &m_pOwnStream ); if ( !m_pOwnStream ) hr = E_FAIL; if ( SUCCEEDED( hr ) ) { hr = pStg->OpenStream( reinterpret_cast(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(aOfficeEmbedStreamName.getStr()) ); hr = pStg->DestroyElement( reinterpret_cast(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(aOfficeEmbedStreamName.getStr()), STGM_CREATE | ( nStreamMode & 0x73 ), 0, 0, &pTargetStream ); if ( FAILED( hr ) || !pTargetStream ) return E_FAIL; hr = pStgSave->CreateStream( reinterpret_cast(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(aOfficeEmbedStreamName.getStr()), 0, nStreamMode & 0x73, 0, &m_pOwnStream ); if ( FAILED( hr ) || !m_pOwnStream ) return E_OUTOFMEMORY; hr = m_pMasterStorage->OpenStream( reinterpret_cast(aExtentStreamName.getStr()), 0, nStreamMode & 0x73, 0, &m_pExtStream ); if ( FAILED( hr ) || !m_pExtStream ) return E_OUTOFMEMORY; for ( AdviseSinkHashMapIterator iAdvise = m_aAdviseHashMap.begin(); iAdvise != m_aAdviseHashMap.end(); iAdvise++ ) { if ( iAdvise->second ) iAdvise->second->OnSave(); } 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(( 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(aOfficeEmbedStreamName.getStr()), STGM_CREATE | ( nStreamMode & 0x73 ), 0, 0, &m_pOwnStream ); if ( FAILED( hr ) || !m_pOwnStream ) return E_FAIL; hr = m_pMasterStorage->CreateStream( reinterpret_cast(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(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(( 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( 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(pszFileName) ); return S_OK; } STDMETHODIMP EmbedDocument_Impl::GetCurFile( LPOLESTR *ppszFileName ) { CComPtr 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(m_aFileName.getStr()), m_aFileName.getLength() + 1 ); return m_aFileName.getLength() ? S_OK : S_FALSE; } // =============================================== LockedEmbedDocument_Impl EmbeddedDocumentInstanceAccess_Impl::GetEmbedDocument() { LockedEmbedDocument_Impl aResult; ::osl::MutexGuard aGuard( m_aMutex ); aResult.m_pLocker = static_cast< IPersistStorage* >( m_pEmbedDocument ); aResult.m_pEmbedDocument = m_pEmbedDocument; return aResult; } void EmbeddedDocumentInstanceAccess_Impl::ClearEmbedDocument() { ::osl::MutexGuard aGuard( m_aMutex ); m_pEmbedDocument = NULL; } // 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