1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <string_view>
24 #include <embeddoc.hxx>
25 #include <com/sun/star/uno/Exception.hpp>
26 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
27 #include <com/sun/star/lang/XComponent.hpp>
28 #include <com/sun/star/io/TempFile.hpp>
29 #include <com/sun/star/io/XInputStream.hpp>
30 #include <com/sun/star/io/XOutputStream.hpp>
31 #include <com/sun/star/io/XSeekable.hpp>
32 #include <com/sun/star/frame/XModel.hpp>
33 #include <com/sun/star/frame/XLoadable.hpp>
34 #include <com/sun/star/util/XModifiable.hpp>
35 #include <com/sun/star/frame/XStorable.hpp>
36 #include <com/sun/star/util/URLTransformer.hpp>
37 #include <com/sun/star/util/XURLTransformer.hpp>
39 #include <comphelper/processfactory.hxx>
40 #include <o3tl/char16_t2wchar_t.hxx>
41 #include <osl/mutex.hxx>
42 #include <osl/diagnose.h>
43 #include <sal/types.h>
49 #define EXT_STREAM_LENGTH 4
53 const sal_Int32 nConstBufferSize
= 32000;
57 using namespace ::com::sun::star
;
59 const wchar_t aOfficeEmbedStreamName
[] = L
"package_stream";
60 const wchar_t aExtentStreamName
[] = L
"properties_stream";
62 static uno::Reference
< io::XInputStream
> createTempXInStreamFromIStream(
63 uno::Reference
< lang::XMultiServiceFactory
> const & xFactory
,
66 uno::Reference
< io::XInputStream
> xResult
;
71 uno::Reference
< io::XOutputStream
> xTempOut( io::TempFile::create(comphelper::getComponentContext(xFactory
)),
72 uno::UNO_QUERY_THROW
);
73 ULARGE_INTEGER nNewPos
;
74 LARGE_INTEGER
const aZero
= { 0, 0 };
75 HRESULT hr
= pStream
->Seek( aZero
, STREAM_SEEK_SET
, &nNewPos
);
76 if ( FAILED( hr
) ) return xResult
;
79 hr
= pStream
->Stat( &aStat
, STATFLAG_NONAME
);
80 if ( FAILED( hr
) ) return xResult
;
82 sal_uInt32 nSize
= static_cast<sal_uInt32
>(aStat
.cbSize
.QuadPart
);
83 sal_uInt32 nCopied
= 0;
84 uno::Sequence
< sal_Int8
> aBuffer( nConstBufferSize
);
90 pStream
->Read( aBuffer
.getArray(), nConstBufferSize
, &nRead
);
92 if ( nRead
< nConstBufferSize
)
93 aBuffer
.realloc( nRead
);
95 xTempOut
->writeBytes( aBuffer
);
97 } while( nRead
== nConstBufferSize
);
99 if ( nCopied
== nSize
)
101 uno::Reference
< io::XSeekable
> xTempSeek ( xTempOut
, uno::UNO_QUERY
);
102 if ( xTempSeek
.is() )
104 xTempSeek
->seek ( 0 );
105 xResult
.set( xTempOut
, uno::UNO_QUERY
);
109 catch( const uno::Exception
& )
116 static HRESULT
copyXTempOutToIStream( uno::Reference
< io::XOutputStream
> const & xTempOut
, IStream
* pStream
)
118 if ( !xTempOut
.is() || !pStream
)
121 uno::Reference
< io::XSeekable
> xTempSeek ( xTempOut
, uno::UNO_QUERY
);
122 if ( !xTempSeek
.is() )
125 xTempSeek
->seek ( 0 );
127 uno::Reference
< io::XInputStream
> xTempIn ( xTempOut
, uno::UNO_QUERY
);
128 if ( !xTempSeek
.is() )
131 // Seek to zero and truncate the stream
132 ULARGE_INTEGER nNewPos
;
133 LARGE_INTEGER
const aZero
= { 0, 0 };
134 HRESULT hr
= pStream
->Seek( aZero
, STREAM_SEEK_SET
, &nNewPos
);
135 if ( FAILED( hr
) ) return E_FAIL
;
136 ULARGE_INTEGER
const aUZero
= { 0, 0 };
137 hr
= pStream
->SetSize( aUZero
);
138 if ( FAILED( hr
) ) return E_FAIL
;
140 uno::Sequence
< sal_Int8
> aBuffer( nConstBufferSize
);
141 sal_uInt32 nReadBytes
= 0;
146 nReadBytes
= xTempIn
->readBytes( aBuffer
, nConstBufferSize
);
148 catch( const uno::Exception
& )
153 sal_uInt32 nWritten
= 0;
154 hr
= pStream
->Write( aBuffer
.getArray(), nReadBytes
, &nWritten
);
155 if ( !SUCCEEDED( hr
) || nWritten
!= nReadBytes
)
158 } while( nReadBytes
== nConstBufferSize
);
164 // EmbedDocument_Impl
167 EmbedDocument_Impl::EmbedDocument_Impl( const uno::Reference
< lang::XMultiServiceFactory
>& xFactory
, const GUID
* guid
)
169 , m_xFactory( xFactory
)
171 , m_bIsDirty( false )
173 , m_bIsInVerbHandling( false )
174 //, m_bLoadedFromFile( sal_False )
176 m_xOwnAccess
= new EmbeddedDocumentInstanceAccess_Impl( this );
177 m_pDocHolder
= new DocumentHolder( xFactory
, m_xOwnAccess
);
180 EmbedDocument_Impl::~EmbedDocument_Impl()
182 m_pDocHolder
->FreeOffice();
184 if ( m_pDocHolder
->HasFrame() && m_pDocHolder
->IsLink() )
186 // a link with frame should be only disconnected, not closed
187 m_pDocHolder
->DisconnectFrameDocument( true );
191 m_pDocHolder
->CloseDocument();
192 m_pDocHolder
->CloseFrame();
196 uno::Sequence
< beans::PropertyValue
> EmbedDocument_Impl::fillArgsForLoading_Impl( uno::Reference
< io::XInputStream
> const & xStream
, DWORD
/*nStreamMode*/, LPCOLESTR pFilePath
)
198 uno::Sequence
< beans::PropertyValue
> aArgs( xStream
.is() ? 3 : 2 );
199 auto pArgs
= aArgs
.getArray();
200 pArgs
[0].Name
= "FilterName";
201 pArgs
[0].Value
<<= getFilterNameFromGUID_Impl( m_guid
);
205 pArgs
[1].Name
= "InputStream";
206 pArgs
[1].Value
<<= xStream
;
207 pArgs
[2].Name
= "URL";
208 pArgs
[2].Value
<<= OUString( "private:stream" );
212 pArgs
[1].Name
= "URL";
217 uno::Reference
< util::XURLTransformer
> aTransformer( util::URLTransformer::create(comphelper::getComponentContext(m_xFactory
)) );
220 aURL
.Complete
= o3tl::toU(pFilePath
);
222 if ( aTransformer
->parseSmart( aURL
, OUString() ) )
223 sDocUrl
= aURL
.Complete
;
226 pArgs
[1].Value
<<= sDocUrl
;
229 // aArgs[].Name = "ReadOnly";
230 // aArgs[].Value <<= sal_False; //( ( nStreamMode & ( STGM_READWRITE | STGM_WRITE ) ) ? sal_True : sal_False );
235 uno::Sequence
< beans::PropertyValue
> EmbedDocument_Impl::fillArgsForStoring_Impl( uno::Reference
< io::XOutputStream
> const & xStream
)
237 uno::Sequence
< beans::PropertyValue
> aArgs( xStream
.is() ? 2 : 1 );
238 auto pArgs
= aArgs
.getArray();
239 pArgs
[0].Name
= "FilterName";
240 pArgs
[0].Value
<<= getFilterNameFromGUID_Impl( m_guid
);
244 pArgs
[1].Name
= "OutputStream";
245 pArgs
[1].Value
<<= xStream
;
251 HRESULT
EmbedDocument_Impl::SaveTo_Impl( IStorage
* pStg
)
253 if ( !pStg
|| pStg
== m_pMasterStorage
)
256 // for saveto operation the master storage
257 // should not enter NoScribble mode
258 CComPtr
< IStream
> pOrigOwn
= m_pOwnStream
;
259 CComPtr
< IStream
> pOrigExt
= m_pExtStream
;
260 HRESULT hr
= Save( pStg
, false );
261 pStg
->Commit( STGC_ONLYIFCURRENT
);
262 m_pOwnStream
= pOrigOwn
;
263 m_pExtStream
= pOrigExt
;
271 COM_DECLSPEC_NOTHROW STDMETHODIMP
EmbedDocument_Impl::QueryInterface(REFIID riid
, void** ppv
)
273 if(IsEqualIID(riid
, IID_IUnknown
))
276 *ppv
= static_cast<IUnknown
*>(static_cast<IPersistStorage
*>(this));
279 else if (IsEqualIID(riid
, IID_IPersist
))
282 *ppv
= static_cast<IPersist
*>(static_cast<IPersistStorage
*>(this));
285 else if (IsEqualIID(riid
, IID_IExternalConnection
))
288 *ppv
= static_cast<IExternalConnection
*>(this);
291 else if (IsEqualIID(riid
, IID_IPersistStorage
))
294 *ppv
= static_cast<IPersistStorage
*>(this);
297 else if (IsEqualIID(riid
, IID_IDataObject
))
300 *ppv
= static_cast<IDataObject
*>(this);
303 else if (IsEqualIID(riid
, IID_IOleObject
))
306 *ppv
= static_cast<IOleObject
*>(this);
309 else if (IsEqualIID(riid
, IID_IOleWindow
))
312 *ppv
= static_cast<IOleWindow
*>(this);
315 else if (IsEqualIID(riid
, IID_IOleInPlaceObject
))
318 *ppv
= static_cast<IOleInPlaceObject
*>(this);
321 else if (IsEqualIID(riid
, IID_IPersistFile
))
324 *ppv
= static_cast<IPersistFile
*>(this);
327 else if (IsEqualIID(riid
, IID_IDispatch
))
330 *ppv
= static_cast<IDispatch
*>(this);
335 return ResultFromScode(E_NOINTERFACE
);
338 COM_DECLSPEC_NOTHROW
STDMETHODIMP_(ULONG
) EmbedDocument_Impl::AddRef()
340 return osl_atomic_increment( &m_refCount
);
343 COM_DECLSPEC_NOTHROW
STDMETHODIMP_(ULONG
) EmbedDocument_Impl::Release()
345 // if there is a time when the last reference is destructed, that means that only internal pointers are alive
346 // after the following call either the refcount is increased or the pointers are empty
347 if ( m_refCount
== 1 )
348 m_xOwnAccess
->ClearEmbedDocument();
350 sal_Int32 nCount
= osl_atomic_decrement( &m_refCount
);
359 COM_DECLSPEC_NOTHROW STDMETHODIMP
EmbedDocument_Impl::GetClassID( CLSID
* pClassId
)
368 COM_DECLSPEC_NOTHROW STDMETHODIMP
EmbedDocument_Impl::IsDirty()
370 // the link modified state is controlled by the document
371 if ( m_bIsDirty
&& !m_aFileName
.getLength() )
374 uno::Reference
< util::XModifiable
> xMod( m_pDocHolder
->GetDocument(), uno::UNO_QUERY
);
376 return xMod
->isModified() ? S_OK
: S_FALSE
;
380 COM_DECLSPEC_NOTHROW STDMETHODIMP
EmbedDocument_Impl::InitNew( IStorage
*pStg
)
382 HRESULT hr
= CO_E_ALREADYINITIALIZED
;
384 if ( !m_pDocHolder
->GetDocument().is() )
388 hr
= pStg
->Stat( &aStat
, STATFLAG_NONAME
);
389 if ( FAILED( hr
) ) return E_FAIL
;
391 DWORD nStreamMode
= aStat
.grfMode
;
394 if ( m_xFactory
.is() && pStg
)
396 uno::Reference
< frame::XModel
> aDocument(
397 m_xFactory
->createInstance( OUString(getServiceNameFromGUID_Impl( m_guid
)) ),
399 if ( aDocument
.is() )
401 m_pDocHolder
->SetDocument( aDocument
);
403 uno::Reference
< frame::XLoadable
> xLoadable( m_pDocHolder
->GetDocument(), uno::UNO_QUERY
);
408 xLoadable
->initNew();
409 // xLoadable->load( fillArgsForLoading_Impl( uno::Reference< io::XInputStream >(), nStreamMode ) );
412 catch( const uno::Exception
& )
419 wchar_t const * aCurType
= getStorageTypeFromGUID_Impl( m_guid
); // ???
420 CLIPFORMAT cf
= static_cast<CLIPFORMAT
>(RegisterClipboardFormatW( L
"Embedded Object" ));
421 hr
= WriteFmtUserTypeStg( pStg
,
423 const_cast<wchar_t *>(aCurType
) );
427 hr
= pStg
->CreateStream( aOfficeEmbedStreamName
,
428 STGM_CREATE
| ( nStreamMode
& 0x73 ),
433 if ( hr
== S_OK
&& m_pOwnStream
)
435 hr
= pStg
->CreateStream( aExtentStreamName
,
436 STGM_CREATE
| ( nStreamMode
& 0x73 ),
441 if ( hr
== S_OK
&& m_pExtStream
)
444 m_pMasterStorage
= pStg
;
458 m_pDocHolder
->CloseDocument();
466 COM_DECLSPEC_NOTHROW STDMETHODIMP
EmbedDocument_Impl::Load( IStorage
*pStg
)
468 if ( m_pDocHolder
->GetDocument().is() )
469 return CO_E_ALREADYINITIALIZED
;
471 if ( !m_xFactory
.is() || !pStg
)
477 hr
= pStg
->Stat( &aStat
, STATFLAG_NONAME
);
478 if ( FAILED( hr
) ) return E_FAIL
;
480 DWORD nStreamMode
= aStat
.grfMode
;
481 hr
= pStg
->OpenStream( aOfficeEmbedStreamName
,
486 if ( !m_pOwnStream
) hr
= E_FAIL
;
488 if ( SUCCEEDED( hr
) )
490 hr
= pStg
->OpenStream( aExtentStreamName
,
495 if ( !m_pExtStream
) hr
= E_FAIL
;
500 if ( SUCCEEDED( hr
) )
502 ULARGE_INTEGER nNewPos
;
503 LARGE_INTEGER
const aZero
= { 0, 0 };
504 hr
= m_pExtStream
->Seek( aZero
, STREAM_SEEK_SET
, &nNewPos
);
505 if ( SUCCEEDED( hr
) )
508 sal_Int32 aInf
[EXT_STREAM_LENGTH
];
509 hr
= m_pExtStream
->Read( aInf
, sizeof aInf
, &nRead
);
510 if ( nRead
!= sizeof aInf
) hr
= E_FAIL
;
512 if ( SUCCEEDED( hr
) )
514 // aRectToSet.left = *((sal_Int32*)aInf);
515 // aRectToSet.top = *((sal_Int32*)&aInf[4]);
516 // aRectToSet.right = *((sal_Int32*)&aInf[8]);
517 // aRectToSet.bottom = *((sal_Int32*)&aInf[12]);
518 aSizeToSet
.cx
= aInf
[2] - aInf
[0];
519 aSizeToSet
.cy
= aInf
[3] - aInf
[1];
524 if ( SUCCEEDED( hr
) )
528 uno::Reference
< io::XInputStream
> xTempIn
= createTempXInStreamFromIStream( m_xFactory
, m_pOwnStream
);
531 uno::Reference
< frame::XModel
> aDocument(
532 m_xFactory
->createInstance( OUString(getServiceNameFromGUID_Impl( m_guid
)) ),
534 if ( aDocument
.is() )
536 m_pDocHolder
->SetDocument( aDocument
);
538 uno::Reference
< frame::XLoadable
> xLoadable( m_pDocHolder
->GetDocument(), uno::UNO_QUERY
);
543 xLoadable
->load( fillArgsForLoading_Impl( xTempIn
, nStreamMode
) );
544 m_pMasterStorage
= pStg
;
545 hr
= m_pDocHolder
->SetExtent( &aSizeToSet
);
546 // hr = m_pDocHolder->SetVisArea( &aRectToSet );
548 catch( const uno::Exception
& )
554 m_pDocHolder
->CloseDocument();
561 m_pOwnStream
= CComPtr
< IStream
>();
562 m_pExtStream
= CComPtr
< IStream
>();
563 hr
= pStg
->DestroyElement( aOfficeEmbedStreamName
);
564 hr
= pStg
->DestroyElement( aExtentStreamName
);
566 OSL_ENSURE( SUCCEEDED( hr
), "Can not destroy created stream!" );
574 COM_DECLSPEC_NOTHROW STDMETHODIMP
EmbedDocument_Impl::Save( IStorage
*pStgSave
, BOOL fSameAsLoad
)
576 if ( !m_pDocHolder
->GetDocument().is() || !m_xFactory
.is() || !pStgSave
|| !m_pOwnStream
|| !m_pExtStream
)
579 CComPtr
< IStream
> pTargetStream
;
580 CComPtr
< IStream
> pNewExtStream
;
582 if ( !fSameAsLoad
&& pStgSave
!= m_pMasterStorage
)
584 OSL_ENSURE( m_pMasterStorage
, "How could the document be initialized without storage!??" );
585 HRESULT hr
= m_pMasterStorage
->CopyTo( 0, nullptr, nullptr, pStgSave
);
586 if ( FAILED( hr
) ) return E_FAIL
;
589 hr
= pStgSave
->Stat( &aStat
, STATFLAG_NONAME
);
590 if ( FAILED( hr
) ) return E_FAIL
;
592 DWORD nStreamMode
= aStat
.grfMode
;
593 hr
= pStgSave
->CreateStream( aOfficeEmbedStreamName
,
594 STGM_CREATE
| ( nStreamMode
& 0x73 ),
598 if ( FAILED( hr
) || !pTargetStream
) return E_FAIL
;
600 hr
= pStgSave
->CreateStream( aExtentStreamName
,
601 STGM_CREATE
| ( nStreamMode
& 0x73 ),
605 if ( FAILED( hr
) || !pNewExtStream
) return E_FAIL
;
609 pTargetStream
= m_pOwnStream
;
610 pNewExtStream
= m_pExtStream
;
615 uno::Reference
< io::XOutputStream
> xTempOut( io::TempFile::create(comphelper::getComponentContext(m_xFactory
)),
616 uno::UNO_QUERY_THROW
);
618 uno::Reference
< frame::XStorable
> xStorable( m_pDocHolder
->GetDocument(), uno::UNO_QUERY
);
623 xStorable
->storeToURL( "private:stream",
624 fillArgsForStoring_Impl( xTempOut
) );
625 hr
= copyXTempOutToIStream( xTempOut
, pTargetStream
);
626 if ( SUCCEEDED( hr
) )
628 // no need to truncate the stream, the size of the stream is always the same
629 ULARGE_INTEGER nNewPos
;
630 LARGE_INTEGER
const aZero
= { 0, 0 };
631 hr
= pNewExtStream
->Seek( aZero
, STREAM_SEEK_SET
, &nNewPos
);
632 if ( SUCCEEDED( hr
) )
635 hr
= m_pDocHolder
->GetExtent( &aSize
);
637 if ( SUCCEEDED( hr
) )
640 sal_Int32 aInf
[EXT_STREAM_LENGTH
] = {0, 0, aSize
.cx
, aSize
.cy
};
642 hr
= pNewExtStream
->Write( aInf
, sizeof aInf
, &nWritten
);
643 if ( nWritten
!= sizeof aInf
) hr
= E_FAIL
;
645 if ( SUCCEEDED( hr
) )
647 m_pOwnStream
= CComPtr
< IStream
>();
648 m_pExtStream
= CComPtr
< IStream
>();
649 if ( fSameAsLoad
|| pStgSave
== m_pMasterStorage
)
651 uno::Reference
< util::XModifiable
> xMod( m_pDocHolder
->GetDocument(), uno::UNO_QUERY
);
653 xMod
->setModified( false );
661 catch( const uno::Exception
& )
669 COM_DECLSPEC_NOTHROW STDMETHODIMP
EmbedDocument_Impl::SaveCompleted( IStorage
*pStgNew
)
671 // m_pOwnStream == NULL && m_pMasterStorage != NULL means the object is in NoScribble mode
672 // m_pOwnStream == NULL && m_pMasterStorage == NULL means the object is in HandsOff mode
674 if ( m_pOwnStream
|| m_pExtStream
)
677 if ( !m_pMasterStorage
&& !pStgNew
)
681 m_pMasterStorage
= pStgNew
;
684 HRESULT hr
= m_pMasterStorage
->Stat( &aStat
, STATFLAG_NONAME
);
685 if ( FAILED( hr
) ) return E_OUTOFMEMORY
;
687 DWORD nStreamMode
= aStat
.grfMode
;
688 hr
= m_pMasterStorage
->OpenStream( aOfficeEmbedStreamName
,
693 if ( FAILED( hr
) || !m_pOwnStream
) return E_OUTOFMEMORY
;
695 hr
= m_pMasterStorage
->OpenStream( aExtentStreamName
,
700 if ( FAILED( hr
) || !m_pExtStream
) return E_OUTOFMEMORY
;
702 for (auto const& advise
: m_aAdviseHashMap
)
705 advise
.second
->OnSave();
711 COM_DECLSPEC_NOTHROW STDMETHODIMP
EmbedDocument_Impl::HandsOffStorage()
713 m_pMasterStorage
= CComPtr
< IStorage
>();
714 m_pOwnStream
= CComPtr
< IStream
>();
715 m_pExtStream
= CComPtr
< IStream
>();
723 COM_DECLSPEC_NOTHROW STDMETHODIMP
EmbedDocument_Impl::Load( LPCOLESTR pszFileName
, DWORD
/*dwMode*/ )
725 if ( m_pDocHolder
->GetDocument().is() )
726 return CO_E_ALREADYINITIALIZED
;
728 if ( !m_xFactory
.is() )
731 DWORD nStreamMode
= STGM_CREATE
| STGM_READWRITE
| STGM_DELETEONRELEASE
| STGM_SHARE_EXCLUSIVE
;
732 HRESULT hr
= StgCreateDocfile( nullptr,
737 if ( FAILED( hr
) || !m_pMasterStorage
) return E_FAIL
;
739 std::u16string_view aCurType
= getServiceNameFromGUID_Impl( m_guid
); // ???
740 CLIPFORMAT cf
= static_cast<CLIPFORMAT
>(RegisterClipboardFormatW( L
"Embedded Object" ));
741 hr
= WriteFmtUserTypeStg( m_pMasterStorage
,
743 const_cast<LPOLESTR
>( o3tl::toW(aCurType
.data())) );
744 if ( FAILED( hr
) ) return E_FAIL
;
746 hr
= m_pMasterStorage
->SetClass( m_guid
);
747 if ( FAILED( hr
) ) return E_FAIL
;
749 hr
= m_pMasterStorage
->CreateStream( aOfficeEmbedStreamName
,
750 STGM_CREATE
| ( nStreamMode
& 0x73 ),
754 if ( FAILED( hr
) || !m_pOwnStream
) return E_FAIL
;
756 hr
= m_pMasterStorage
->CreateStream( aExtentStreamName
,
757 STGM_CREATE
| ( nStreamMode
& 0x73 ),
761 if ( FAILED( hr
) || !m_pExtStream
) return E_FAIL
;
764 uno::Reference
< frame::XModel
> aDocument(
765 m_xFactory
->createInstance( OUString(getServiceNameFromGUID_Impl( m_guid
)) ),
767 if ( aDocument
.is() )
769 m_pDocHolder
->SetDocument( aDocument
, true );
771 uno::Reference
< frame::XLoadable
> xLoadable( m_pDocHolder
->GetDocument(), uno::UNO_QUERY
);
776 xLoadable
->load( fillArgsForLoading_Impl( uno::Reference
< io::XInputStream
>(),
781 m_aFileName
= o3tl::toU(pszFileName
);
783 catch( const uno::Exception
& )
790 aCurType
= getServiceNameFromGUID_Impl( m_guid
); // ???
791 cf
= static_cast<CLIPFORMAT
>(RegisterClipboardFormatW( L
"Embedded Object" ));
792 hr
= WriteFmtUserTypeStg( m_pMasterStorage
,
794 const_cast<LPOLESTR
>( o3tl::toW(aCurType
.data())) );
796 if ( SUCCEEDED( hr
) )
798 // no need to truncate the stream, the size of the stream is always the same
799 ULARGE_INTEGER nNewPos
;
800 LARGE_INTEGER
const aZero
= { 0, 0 };
801 hr
= m_pExtStream
->Seek( aZero
, STREAM_SEEK_SET
, &nNewPos
);
802 if ( SUCCEEDED( hr
) )
805 hr
= m_pDocHolder
->GetExtent( &aSize
);
807 if ( SUCCEEDED( hr
) )
810 sal_Int32 aInf
[EXT_STREAM_LENGTH
] = {0, 0, aSize
.cx
, aSize
.cy
};
812 hr
= m_pExtStream
->Write( aInf
, sizeof aInf
, &nWritten
);
813 if ( nWritten
!= sizeof aInf
) hr
= E_FAIL
;
818 if ( SUCCEEDED( hr
) )
826 m_pDocHolder
->CloseDocument();
827 m_pOwnStream
= nullptr;
828 m_pExtStream
= nullptr;
829 m_pMasterStorage
= nullptr;
836 COM_DECLSPEC_NOTHROW STDMETHODIMP
EmbedDocument_Impl::Save( LPCOLESTR pszFileName
, BOOL fRemember
)
838 if ( !m_pDocHolder
->GetDocument().is() || !m_xFactory
.is() )
843 // TODO/LATER: currently there is no hands off state implemented
846 uno::Reference
< frame::XStorable
> xStorable( m_pDocHolder
->GetDocument(), uno::UNO_QUERY_THROW
);
853 aURL
.Complete
= o3tl::toU( pszFileName
);
855 uno::Reference
< util::XURLTransformer
> aTransformer( util::URLTransformer::create(comphelper::getComponentContext(m_xFactory
)) );
857 if ( aTransformer
->parseSmart( aURL
, OUString() ) && aURL
.Complete
.getLength() )
861 xStorable
->storeAsURL( aURL
.Complete
, fillArgsForStoring_Impl( uno::Reference
< io::XOutputStream
>() ) );
862 m_aFileName
= aURL
.Complete
;
865 xStorable
->storeToURL( aURL
.Complete
, fillArgsForStoring_Impl( uno::Reference
< io::XOutputStream
>() ) );
871 catch( const uno::Exception
& )
878 COM_DECLSPEC_NOTHROW STDMETHODIMP
EmbedDocument_Impl::SaveCompleted( LPCOLESTR pszFileName
)
880 // the different file name would mean error here
881 m_aFileName
= o3tl::toU(pszFileName
);
885 COM_DECLSPEC_NOTHROW STDMETHODIMP
EmbedDocument_Impl::GetCurFile( LPOLESTR
*ppszFileName
)
887 CComPtr
<IMalloc
> pMalloc
;
889 HRESULT hr
= CoGetMalloc( 1, &pMalloc
);
890 if ( FAILED( hr
) || !pMalloc
) return E_FAIL
;
892 *ppszFileName
= static_cast<LPOLESTR
>( pMalloc
->Alloc( sizeof( sal_Unicode
) * ( m_aFileName
.getLength() + 1 ) ) );
893 wcsncpy( *ppszFileName
, o3tl::toW(m_aFileName
.getStr()), m_aFileName
.getLength() + 1 );
895 return m_aFileName
.getLength() ? S_OK
: S_FALSE
;
899 LockedEmbedDocument_Impl
EmbeddedDocumentInstanceAccess_Impl::GetEmbedDocument()
901 ::osl::MutexGuard
aGuard( m_aMutex
);
902 return LockedEmbedDocument_Impl( m_pEmbedDocument
);
905 void EmbeddedDocumentInstanceAccess_Impl::ClearEmbedDocument()
907 ::osl::MutexGuard
aGuard( m_aMutex
);
908 m_pEmbedDocument
= nullptr;
912 LockedEmbedDocument_Impl::LockedEmbedDocument_Impl()
913 : m_pEmbedDocument( nullptr )
916 LockedEmbedDocument_Impl::LockedEmbedDocument_Impl( EmbedDocument_Impl
* pEmbedDocument
)
917 : m_pEmbedDocument( pEmbedDocument
)
919 if ( m_pEmbedDocument
)
920 m_pEmbedDocument
->AddRef();
923 LockedEmbedDocument_Impl::LockedEmbedDocument_Impl( const LockedEmbedDocument_Impl
& aDocLock
)
924 : m_pEmbedDocument( aDocLock
.m_pEmbedDocument
)
926 if ( m_pEmbedDocument
)
927 m_pEmbedDocument
->AddRef();
930 LockedEmbedDocument_Impl
& LockedEmbedDocument_Impl::operator=( const LockedEmbedDocument_Impl
& aDocLock
)
932 if ( m_pEmbedDocument
)
933 m_pEmbedDocument
->Release();
935 m_pEmbedDocument
= aDocLock
.m_pEmbedDocument
;
936 if ( m_pEmbedDocument
)
937 m_pEmbedDocument
->AddRef();
942 LockedEmbedDocument_Impl::~LockedEmbedDocument_Impl()
944 if ( m_pEmbedDocument
)
945 m_pEmbedDocument
->Release();
948 void LockedEmbedDocument_Impl::ExecuteMethod( sal_Int16 nId
)
950 if ( m_pEmbedDocument
)
952 if ( nId
== OLESERV_SAVEOBJECT
)
953 m_pEmbedDocument
->SaveObject();
954 else if ( nId
== OLESERV_CLOSE
)
955 m_pEmbedDocument
->Close( 0 );
956 else if ( nId
== OLESERV_NOTIFY
)
957 m_pEmbedDocument
->notify();
958 else if ( nId
== OLESERV_NOTIFYCLOSING
)
959 m_pEmbedDocument
->OLENotifyClosing();
960 else if ( nId
== OLESERV_SHOWOBJECT
)
961 m_pEmbedDocument
->ShowObject();
962 else if ( nId
== OLESERV_DEACTIVATE
)
963 m_pEmbedDocument
->Deactivate();
967 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */