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 #pragma warning(disable : 4917 4555)
23 #include "embeddoc.hxx"
24 #include <com/sun/star/uno/Exception.hpp>
25 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
26 #include <com/sun/star/lang/XComponent.hpp>
27 #include <com/sun/star/io/TempFile.hpp>
28 #include <com/sun/star/io/XInputStream.hpp>
29 #include <com/sun/star/io/XOutputStream.hpp>
30 #include <com/sun/star/io/XSeekable.hpp>
31 #include <com/sun/star/frame/XModel.hpp>
32 #include <com/sun/star/frame/XLoadable.hpp>
33 #include <com/sun/star/util/XModifiable.hpp>
34 #include <com/sun/star/frame/XStorable.hpp>
35 #include <com/sun/star/frame/XComponentLoader.hpp>
36 #include <com/sun/star/util/URLTransformer.hpp>
37 #include <com/sun/star/util/XURLTransformer.hpp>
39 #include <comphelper/processfactory.hxx>
40 #include <osl/mutex.hxx>
41 #include <osl/diagnose.h>
42 #include <sal/types.h>
46 #define EXT_STREAM_LENGTH 16
50 const sal_Int32 nConstBufferSize
= 32000;
54 using namespace ::com::sun::star
;
56 extern OUString
getStorageTypeFromGUID_Impl( GUID
* guid
);
57 extern OUString
getServiceNameFromGUID_Impl( GUID
* );
58 extern OUString
getFilterNameFromGUID_Impl( GUID
* );
60 const OUString
aOfficeEmbedStreamName( "package_stream" );
61 const OUString
aExtentStreamName( "properties_stream" );
63 uno::Reference
< io::XInputStream
> createTempXInStreamFromIStream(
64 uno::Reference
< lang::XMultiServiceFactory
> xFactory
,
67 uno::Reference
< io::XInputStream
> xResult
;
72 uno::Reference
< io::XOutputStream
> xTempOut( io::TempFile::create(comphelper::getComponentContext(xFactory
)),
73 uno::UNO_QUERY_THROW
);
74 ULARGE_INTEGER nNewPos
;
75 LARGE_INTEGER aZero
= { 0L, 0L };
76 HRESULT hr
= pStream
->Seek( aZero
, STREAM_SEEK_SET
, &nNewPos
);
77 if ( FAILED( hr
) ) return xResult
;
80 hr
= pStream
->Stat( &aStat
, STATFLAG_NONAME
);
81 if ( FAILED( hr
) ) return xResult
;
83 sal_uInt32 nSize
= (sal_uInt32
)aStat
.cbSize
.QuadPart
;
84 sal_uInt32 nCopied
= 0;
85 uno::Sequence
< sal_Int8
> aBuffer( nConstBufferSize
);
91 pStream
->Read( (void*)aBuffer
.getArray(), nConstBufferSize
, &nRead
);
93 if ( nRead
< nConstBufferSize
)
94 aBuffer
.realloc( nRead
);
96 xTempOut
->writeBytes( aBuffer
);
98 } while( nRead
== nConstBufferSize
);
100 if ( nCopied
== nSize
)
102 uno::Reference
< io::XSeekable
> xTempSeek ( xTempOut
, uno::UNO_QUERY
);
103 if ( xTempSeek
.is() )
105 xTempSeek
->seek ( 0 );
106 xResult
.set( xTempOut
, uno::UNO_QUERY
);
110 catch( const uno::Exception
& )
117 HRESULT
copyXTempOutToIStream( uno::Reference
< io::XOutputStream
> xTempOut
, IStream
* pStream
)
119 if ( !xTempOut
.is() || !pStream
)
122 uno::Reference
< io::XSeekable
> xTempSeek ( xTempOut
, uno::UNO_QUERY
);
123 if ( !xTempSeek
.is() )
126 xTempSeek
->seek ( 0 );
128 uno::Reference
< io::XInputStream
> xTempIn ( xTempOut
, uno::UNO_QUERY
);
129 if ( !xTempSeek
.is() )
132 // Seek to zero and truncate the stream
133 ULARGE_INTEGER nNewPos
;
134 LARGE_INTEGER aZero
= { 0L, 0L };
135 HRESULT hr
= pStream
->Seek( aZero
, STREAM_SEEK_SET
, &nNewPos
);
136 if ( FAILED( hr
) ) return E_FAIL
;
137 ULARGE_INTEGER aUZero
= { 0L, 0L };
138 hr
= pStream
->SetSize( aUZero
);
139 if ( FAILED( hr
) ) return E_FAIL
;
141 uno::Sequence
< sal_Int8
> aBuffer( nConstBufferSize
);
142 sal_uInt32 nReadBytes
= 0;
147 nReadBytes
= xTempIn
->readBytes( aBuffer
, nConstBufferSize
);
149 catch( const uno::Exception
& )
154 sal_uInt32 nWritten
= 0;
155 hr
= pStream
->Write( (void*)aBuffer
.getArray(), nReadBytes
, &nWritten
);
156 if ( !SUCCEEDED( hr
) || nWritten
!= nReadBytes
)
159 } while( nReadBytes
== nConstBufferSize
);
165 // EmbedDocument_Impl
168 EmbedDocument_Impl::EmbedDocument_Impl( const uno::Reference
< lang::XMultiServiceFactory
>& xFactory
, const GUID
* guid
)
170 , m_xFactory( xFactory
)
172 , m_bIsDirty( sal_False
)
174 , m_bIsInVerbHandling( sal_False
)
175 //, m_bLoadedFromFile( sal_False )
177 m_xOwnAccess
= new EmbeddedDocumentInstanceAccess_Impl( this );
178 m_pDocHolder
= new DocumentHolder( xFactory
, m_xOwnAccess
);
179 m_pDocHolder
->acquire();
182 EmbedDocument_Impl::~EmbedDocument_Impl()
184 m_pDocHolder
->FreeOffice();
186 if ( m_pDocHolder
->HasFrame() && m_pDocHolder
->IsLink() )
188 // a link with frame should be only disconnected, not closed
189 m_pDocHolder
->DisconnectFrameDocument( sal_True
);
193 m_pDocHolder
->CloseDocument();
194 m_pDocHolder
->CloseFrame();
197 m_pDocHolder
->release();
200 uno::Sequence
< beans::PropertyValue
> EmbedDocument_Impl::fillArgsForLoading_Impl( uno::Reference
< io::XInputStream
> xStream
, DWORD
/*nStreamMode*/, LPCOLESTR pFilePath
)
202 uno::Sequence
< beans::PropertyValue
> aArgs( 3 );
204 sal_Int32 nInd
= 0; // must not be bigger than the preset size
205 aArgs
[nInd
].Name
= "FilterName";
206 aArgs
[nInd
++].Value
<<= getFilterNameFromGUID_Impl( &m_guid
);
210 aArgs
[nInd
].Name
= "InputStream";
211 aArgs
[nInd
++].Value
<<= xStream
;
212 aArgs
[nInd
].Name
= "URL";
213 aArgs
[nInd
++].Value
<<= OUString( "private:stream" );
217 aArgs
[nInd
].Name
= "URL";
222 uno::Reference
< util::XURLTransformer
> aTransformer( util::URLTransformer::create(comphelper::getComponentContext(m_xFactory
)) );
225 aURL
.Complete
= OUString( reinterpret_cast<const sal_Unicode
*>(pFilePath
) );
227 if ( aTransformer
->parseSmart( aURL
, OUString() ) )
228 sDocUrl
= aURL
.Complete
;
231 aArgs
[nInd
++].Value
<<= sDocUrl
;
234 aArgs
.realloc( nInd
);
236 // aArgs[].Name = "ReadOnly";
237 // aArgs[].Value <<= sal_False; //( ( nStreamMode & ( STGM_READWRITE | STGM_WRITE ) ) ? sal_True : sal_False );
242 uno::Sequence
< beans::PropertyValue
> EmbedDocument_Impl::fillArgsForStoring_Impl( uno::Reference
< io::XOutputStream
> xStream
)
244 uno::Sequence
< beans::PropertyValue
> aArgs( xStream
.is() ? 2 : 1 );
246 aArgs
[0].Name
= "FilterName";
247 aArgs
[0].Value
<<= getFilterNameFromGUID_Impl( &m_guid
);
251 aArgs
[1].Name
= "OutputStream";
252 aArgs
[1].Value
<<= xStream
;
258 HRESULT
EmbedDocument_Impl::SaveTo_Impl( IStorage
* pStg
)
260 if ( !pStg
|| pStg
== m_pMasterStorage
)
263 // for saveto operation the master storage
264 // should not enter NoScribble mode
265 CComPtr
< IStream
> pOrigOwn
= m_pOwnStream
;
266 CComPtr
< IStream
> pOrigExt
= m_pExtStream
;
267 HRESULT hr
= Save( pStg
, sal_False
);
268 pStg
->Commit( STGC_ONLYIFCURRENT
);
269 m_pOwnStream
= pOrigOwn
;
270 m_pExtStream
= pOrigExt
;
278 STDMETHODIMP
EmbedDocument_Impl::QueryInterface( REFIID riid
, void FAR
* FAR
* ppv
)
280 if(IsEqualIID(riid
, IID_IUnknown
))
283 *ppv
= (IUnknown
*) (IPersistStorage
*) this;
286 else if (IsEqualIID(riid
, IID_IPersist
))
289 *ppv
= (IPersist
*) (IPersistStorage
*) this;
292 else if (IsEqualIID(riid
, IID_IExternalConnection
))
295 *ppv
= (IExternalConnection
*) this;
298 else if (IsEqualIID(riid
, IID_IPersistStorage
))
301 *ppv
= (IPersistStorage
*) this;
304 else if (IsEqualIID(riid
, IID_IDataObject
))
307 *ppv
= (IDataObject
*) this;
310 else if (IsEqualIID(riid
, IID_IOleObject
))
313 *ppv
= (IOleObject
*) this;
316 else if (IsEqualIID(riid
, IID_IOleWindow
))
319 *ppv
= (IOleWindow
*) this;
322 else if (IsEqualIID(riid
, IID_IOleInPlaceObject
))
325 *ppv
= (IOleInPlaceObject
*) this;
328 else if (IsEqualIID(riid
, IID_IPersistFile
))
331 *ppv
= (IPersistFile
*) this;
334 else if (IsEqualIID(riid
, IID_IDispatch
))
337 *ppv
= (IDispatch
*) this;
342 return ResultFromScode(E_NOINTERFACE
);
345 STDMETHODIMP_(ULONG
) EmbedDocument_Impl::AddRef()
347 return osl_atomic_increment( &m_refCount
);
350 STDMETHODIMP_(ULONG
) EmbedDocument_Impl::Release()
352 // if there is a time when the last reference is destructed, that means that only internal pointers are alive
353 // after the following call either the refcount is increased or the pointers are empty
354 if ( m_refCount
== 1 )
355 m_xOwnAccess
->ClearEmbedDocument();
357 sal_Int32 nCount
= osl_atomic_decrement( &m_refCount
);
366 STDMETHODIMP
EmbedDocument_Impl::GetClassID( CLSID
* pClassId
)
368 *pClassId
= *&m_guid
;
375 STDMETHODIMP
EmbedDocument_Impl::IsDirty()
377 // the link modified state is controlled by the document
378 if ( m_bIsDirty
&& !m_aFileName
.getLength() )
381 uno::Reference
< util::XModifiable
> xMod( m_pDocHolder
->GetDocument(), uno::UNO_QUERY
);
383 return xMod
->isModified() ? S_OK
: S_FALSE
;
387 STDMETHODIMP
EmbedDocument_Impl::InitNew( IStorage
*pStg
)
389 HRESULT hr
= CO_E_ALREADYINITIALIZED
;
391 if ( !m_pDocHolder
->GetDocument().is() )
395 hr
= pStg
->Stat( &aStat
, STATFLAG_NONAME
);
396 if ( FAILED( hr
) ) return E_FAIL
;
398 DWORD nStreamMode
= aStat
.grfMode
;
401 if ( m_xFactory
.is() && pStg
)
403 uno::Reference
< frame::XModel
> aDocument(
404 m_xFactory
->createInstance( getServiceNameFromGUID_Impl( &m_guid
) ),
406 if ( aDocument
.is() )
408 m_pDocHolder
->SetDocument( aDocument
);
410 uno::Reference
< frame::XLoadable
> xLoadable( m_pDocHolder
->GetDocument(), uno::UNO_QUERY
);
415 xLoadable
->initNew();
416 // xLoadable->load( fillArgsForLoading_Impl( uno::Reference< io::XInputStream >(), nStreamMode ) );
419 catch( const uno::Exception
& )
426 OUString aCurType
= getStorageTypeFromGUID_Impl( &m_guid
); // ???
427 CLIPFORMAT cf
= (CLIPFORMAT
)RegisterClipboardFormatA( "Embedded Object" );
428 hr
= WriteFmtUserTypeStg( pStg
,
430 reinterpret_cast<LPWSTR
>(( sal_Unicode
* )aCurType
.getStr()) );
434 hr
= pStg
->CreateStream( reinterpret_cast<LPCWSTR
>(aOfficeEmbedStreamName
.getStr()),
435 STGM_CREATE
| ( nStreamMode
& 0x73 ),
440 if ( hr
== S_OK
&& m_pOwnStream
)
442 hr
= pStg
->CreateStream( reinterpret_cast<LPCWSTR
>(aExtentStreamName
.getStr()),
443 STGM_CREATE
| ( nStreamMode
& 0x73 ),
448 if ( hr
== S_OK
&& m_pExtStream
)
451 m_pMasterStorage
= pStg
;
452 m_bIsDirty
= sal_True
;
465 m_pDocHolder
->CloseDocument();
473 STDMETHODIMP
EmbedDocument_Impl::Load( IStorage
*pStg
)
475 if ( m_pDocHolder
->GetDocument().is() )
476 return CO_E_ALREADYINITIALIZED
;
478 if ( !m_xFactory
.is() || !pStg
)
484 hr
= pStg
->Stat( &aStat
, STATFLAG_NONAME
);
485 if ( FAILED( hr
) ) return E_FAIL
;
487 DWORD nStreamMode
= aStat
.grfMode
;
488 hr
= pStg
->OpenStream( reinterpret_cast<LPCWSTR
>(aOfficeEmbedStreamName
.getStr()),
493 if ( !m_pOwnStream
) hr
= E_FAIL
;
495 if ( SUCCEEDED( hr
) )
497 hr
= pStg
->OpenStream( reinterpret_cast<LPCWSTR
>(aExtentStreamName
.getStr()),
502 if ( !m_pExtStream
) hr
= E_FAIL
;
507 if ( SUCCEEDED( hr
) )
509 ULARGE_INTEGER nNewPos
;
510 LARGE_INTEGER aZero
= { 0L, 0L };
511 hr
= m_pExtStream
->Seek( aZero
, STREAM_SEEK_SET
, &nNewPos
);
512 if ( SUCCEEDED( hr
) )
515 sal_Int8 aInf
[EXT_STREAM_LENGTH
];
516 hr
= m_pExtStream
->Read( (void*)aInf
, EXT_STREAM_LENGTH
, &nRead
);
517 if ( nRead
!= EXT_STREAM_LENGTH
) hr
= E_FAIL
;
519 if ( SUCCEEDED( hr
) )
521 // aRectToSet.left = *((sal_Int32*)aInf);
522 // aRectToSet.top = *((sal_Int32*)&aInf[4]);
523 // aRectToSet.right = *((sal_Int32*)&aInf[8]);
524 // aRectToSet.bottom = *((sal_Int32*)&aInf[12]);
525 aSizeToSet
.cx
= *((sal_Int32
*)&aInf
[8]) - *((sal_Int32
*)aInf
);
526 aSizeToSet
.cy
= *((sal_Int32
*)&aInf
[12]) - *((sal_Int32
*)&aInf
[4]);
531 if ( SUCCEEDED( hr
) )
535 uno::Reference
< io::XInputStream
> xTempIn
= createTempXInStreamFromIStream( m_xFactory
, m_pOwnStream
);
538 uno::Reference
< frame::XModel
> aDocument(
539 m_xFactory
->createInstance( getServiceNameFromGUID_Impl( &m_guid
) ),
541 if ( aDocument
.is() )
543 m_pDocHolder
->SetDocument( aDocument
);
545 uno::Reference
< frame::XLoadable
> xLoadable( m_pDocHolder
->GetDocument(), uno::UNO_QUERY
);
550 xLoadable
->load( fillArgsForLoading_Impl( xTempIn
, nStreamMode
) );
551 m_pMasterStorage
= pStg
;
552 hr
= m_pDocHolder
->SetExtent( &aSizeToSet
);
553 // hr = m_pDocHolder->SetVisArea( &aRectToSet );
555 catch( const uno::Exception
& )
561 m_pDocHolder
->CloseDocument();
568 m_pOwnStream
= CComPtr
< IStream
>();
569 m_pExtStream
= CComPtr
< IStream
>();
570 hr
= pStg
->DestroyElement( reinterpret_cast<LPCWSTR
>(aOfficeEmbedStreamName
.getStr()) );
571 hr
= pStg
->DestroyElement( reinterpret_cast<LPCWSTR
>(aExtentStreamName
.getStr()) );
573 OSL_ENSURE( SUCCEEDED( hr
), "Can not destroy created stream!\n" );
581 STDMETHODIMP
EmbedDocument_Impl::Save( IStorage
*pStgSave
, BOOL fSameAsLoad
)
583 if ( !m_pDocHolder
->GetDocument().is() || !m_xFactory
.is() || !pStgSave
|| !m_pOwnStream
|| !m_pExtStream
)
586 CComPtr
< IStream
> pTargetStream
;
587 CComPtr
< IStream
> pNewExtStream
;
589 if ( !fSameAsLoad
&& pStgSave
!= m_pMasterStorage
)
591 OSL_ENSURE( m_pMasterStorage
, "How could the document be initialized without storage!??\n" );
592 HRESULT hr
= m_pMasterStorage
->CopyTo( NULL
, NULL
, NULL
, pStgSave
);
593 if ( FAILED( hr
) ) return E_FAIL
;
596 hr
= pStgSave
->Stat( &aStat
, STATFLAG_NONAME
);
597 if ( FAILED( hr
) ) return E_FAIL
;
599 DWORD nStreamMode
= aStat
.grfMode
;
600 hr
= pStgSave
->CreateStream( reinterpret_cast<LPCWSTR
>(aOfficeEmbedStreamName
.getStr()),
601 STGM_CREATE
| ( nStreamMode
& 0x73 ),
605 if ( FAILED( hr
) || !pTargetStream
) return E_FAIL
;
607 hr
= pStgSave
->CreateStream( reinterpret_cast<LPCWSTR
>(aExtentStreamName
.getStr()),
608 STGM_CREATE
| ( nStreamMode
& 0x73 ),
612 if ( FAILED( hr
) || !pNewExtStream
) return E_FAIL
;
616 pTargetStream
= m_pOwnStream
;
617 pNewExtStream
= m_pExtStream
;
622 uno::Reference
< io::XOutputStream
> xTempOut( io::TempFile::create(comphelper::getComponentContext(m_xFactory
)),
623 uno::UNO_QUERY_THROW
);
625 uno::Reference
< frame::XStorable
> xStorable( m_pDocHolder
->GetDocument(), uno::UNO_QUERY
);
630 xStorable
->storeToURL( OUString( "private:stream" ),
631 fillArgsForStoring_Impl( xTempOut
) );
632 hr
= copyXTempOutToIStream( xTempOut
, pTargetStream
);
633 if ( SUCCEEDED( hr
) )
635 // no need to truncate the stream, the size of the stream is always the same
636 ULARGE_INTEGER nNewPos
;
637 LARGE_INTEGER aZero
= { 0L, 0L };
638 hr
= pNewExtStream
->Seek( aZero
, STREAM_SEEK_SET
, &nNewPos
);
639 if ( SUCCEEDED( hr
) )
642 hr
= m_pDocHolder
->GetExtent( &aSize
);
644 if ( SUCCEEDED( hr
) )
647 sal_Int8 aInf
[EXT_STREAM_LENGTH
];
648 *((sal_Int32
*)aInf
) = 0;
649 *((sal_Int32
*)&aInf
[4]) = 0;
650 *((sal_Int32
*)&aInf
[8]) = aSize
.cx
;
651 *((sal_Int32
*)&aInf
[12]) = aSize
.cy
;
653 hr
= pNewExtStream
->Write( (void*)aInf
, EXT_STREAM_LENGTH
, &nWritten
);
654 if ( nWritten
!= EXT_STREAM_LENGTH
) hr
= E_FAIL
;
656 if ( SUCCEEDED( hr
) )
658 m_pOwnStream
= CComPtr
< IStream
>();
659 m_pExtStream
= CComPtr
< IStream
>();
660 if ( fSameAsLoad
|| pStgSave
== m_pMasterStorage
)
662 uno::Reference
< util::XModifiable
> xMod( m_pDocHolder
->GetDocument(), uno::UNO_QUERY
);
664 xMod
->setModified( sal_False
);
665 m_bIsDirty
= sal_False
;
672 catch( const uno::Exception
& )
680 STDMETHODIMP
EmbedDocument_Impl::SaveCompleted( IStorage
*pStgNew
)
682 // m_pOwnStream == NULL && m_pMasterStorage != NULL means the object is in NoScribble mode
683 // m_pOwnStream == NULL && m_pMasterStorage == NULL means the object is in HandsOff mode
685 if ( m_pOwnStream
|| m_pExtStream
)
688 if ( !m_pMasterStorage
&& !pStgNew
)
692 m_pMasterStorage
= pStgNew
;
695 HRESULT hr
= m_pMasterStorage
->Stat( &aStat
, STATFLAG_NONAME
);
696 if ( FAILED( hr
) ) return E_OUTOFMEMORY
;
698 DWORD nStreamMode
= aStat
.grfMode
;
699 hr
= m_pMasterStorage
->OpenStream( reinterpret_cast<LPCWSTR
>(aOfficeEmbedStreamName
.getStr()),
704 if ( FAILED( hr
) || !m_pOwnStream
) return E_OUTOFMEMORY
;
706 hr
= m_pMasterStorage
->OpenStream( reinterpret_cast<LPCWSTR
>(aExtentStreamName
.getStr()),
711 if ( FAILED( hr
) || !m_pExtStream
) return E_OUTOFMEMORY
;
713 sal_Bool bModified
= sal_False
;
714 uno::Reference
< util::XModifiable
> xMod( m_pDocHolder
->GetDocument(), uno::UNO_QUERY
);
716 bModified
= xMod
->isModified();
718 for ( AdviseSinkHashMapIterator iAdvise
= m_aAdviseHashMap
.begin(); iAdvise
!= m_aAdviseHashMap
.end(); iAdvise
++ )
720 if ( iAdvise
->second
)
721 iAdvise
->second
->OnSave();
725 bModified
= xMod
->isModified();
730 STDMETHODIMP
EmbedDocument_Impl::HandsOffStorage()
732 m_pMasterStorage
= CComPtr
< IStorage
>();
733 m_pOwnStream
= CComPtr
< IStream
>();
734 m_pExtStream
= CComPtr
< IStream
>();
742 STDMETHODIMP
EmbedDocument_Impl::Load( LPCOLESTR pszFileName
, DWORD
/*dwMode*/ )
744 if ( m_pDocHolder
->GetDocument().is() )
745 return CO_E_ALREADYINITIALIZED
;
747 if ( !m_xFactory
.is() )
750 DWORD nStreamMode
= STGM_CREATE
| STGM_READWRITE
| STGM_DELETEONRELEASE
| STGM_SHARE_EXCLUSIVE
;
751 HRESULT hr
= StgCreateDocfile( NULL
,
756 if ( FAILED( hr
) || !m_pMasterStorage
) return E_FAIL
;
758 OUString aCurType
= getServiceNameFromGUID_Impl( &m_guid
); // ???
759 CLIPFORMAT cf
= (CLIPFORMAT
)RegisterClipboardFormatA( "Embedded Object" );
760 hr
= WriteFmtUserTypeStg( m_pMasterStorage
,
762 reinterpret_cast<LPWSTR
>(( sal_Unicode
* )aCurType
.getStr()) );
763 if ( FAILED( hr
) ) return E_FAIL
;
765 hr
= m_pMasterStorage
->SetClass( m_guid
);
766 if ( FAILED( hr
) ) return E_FAIL
;
768 hr
= m_pMasterStorage
->CreateStream( reinterpret_cast<LPCWSTR
>(aOfficeEmbedStreamName
.getStr()),
769 STGM_CREATE
| ( nStreamMode
& 0x73 ),
773 if ( FAILED( hr
) || !m_pOwnStream
) return E_FAIL
;
775 hr
= m_pMasterStorage
->CreateStream( reinterpret_cast<LPCWSTR
>(aExtentStreamName
.getStr()),
776 STGM_CREATE
| ( nStreamMode
& 0x73 ),
780 if ( FAILED( hr
) || !m_pExtStream
) return E_FAIL
;
783 uno::Reference
< frame::XModel
> aDocument(
784 m_xFactory
->createInstance( getServiceNameFromGUID_Impl( &m_guid
) ),
786 if ( aDocument
.is() )
788 m_pDocHolder
->SetDocument( aDocument
, sal_True
);
790 uno::Reference
< frame::XLoadable
> xLoadable( m_pDocHolder
->GetDocument(), uno::UNO_QUERY
);
795 xLoadable
->load( fillArgsForLoading_Impl( uno::Reference
< io::XInputStream
>(),
800 m_aFileName
= OUString( reinterpret_cast<const sal_Unicode
*>(pszFileName
) );
802 catch( const uno::Exception
& )
809 aCurType
= getServiceNameFromGUID_Impl( &m_guid
); // ???
810 cf
= (CLIPFORMAT
)RegisterClipboardFormatA( "Embedded Object" );
811 hr
= WriteFmtUserTypeStg( m_pMasterStorage
,
813 reinterpret_cast<LPWSTR
>(( sal_Unicode
* )aCurType
.getStr()) );
815 if ( SUCCEEDED( hr
) )
817 // no need to truncate the stream, the size of the stream is always the same
818 ULARGE_INTEGER nNewPos
;
819 LARGE_INTEGER aZero
= { 0L, 0L };
820 hr
= m_pExtStream
->Seek( aZero
, STREAM_SEEK_SET
, &nNewPos
);
821 if ( SUCCEEDED( hr
) )
824 hr
= m_pDocHolder
->GetExtent( &aSize
);
826 if ( SUCCEEDED( hr
) )
829 sal_Int8 aInf
[EXT_STREAM_LENGTH
];
830 *((sal_Int32
*)aInf
) = 0;
831 *((sal_Int32
*)&aInf
[4]) = 0;
832 *((sal_Int32
*)&aInf
[8]) = aSize
.cx
;
833 *((sal_Int32
*)&aInf
[12]) = aSize
.cy
;
835 hr
= m_pExtStream
->Write( (void*)aInf
, EXT_STREAM_LENGTH
, &nWritten
);
836 if ( nWritten
!= EXT_STREAM_LENGTH
) hr
= E_FAIL
;
841 if ( SUCCEEDED( hr
) )
842 m_bIsDirty
= sal_True
;
849 m_pDocHolder
->CloseDocument();
852 m_pMasterStorage
= NULL
;
859 STDMETHODIMP
EmbedDocument_Impl::Save( LPCOLESTR pszFileName
, BOOL fRemember
)
861 if ( !m_pDocHolder
->GetDocument().is() || !m_xFactory
.is() )
866 // TODO/LATER: currently there is no hands off state implemented
869 uno::Reference
< frame::XStorable
> xStorable( m_pDocHolder
->GetDocument(), uno::UNO_QUERY_THROW
);
876 aURL
.Complete
= OUString( reinterpret_cast<const sal_Unicode
*>( pszFileName
) );
878 uno::Reference
< util::XURLTransformer
> aTransformer( util::URLTransformer::create(comphelper::getComponentContext(m_xFactory
)) );
880 if ( aTransformer
->parseSmart( aURL
, OUString() ) && aURL
.Complete
.getLength() )
884 xStorable
->storeAsURL( aURL
.Complete
, fillArgsForStoring_Impl( uno::Reference
< io::XOutputStream
>() ) );
885 m_aFileName
= aURL
.Complete
;
888 xStorable
->storeToURL( aURL
.Complete
, fillArgsForStoring_Impl( uno::Reference
< io::XOutputStream
>() ) );
894 catch( const uno::Exception
& )
901 STDMETHODIMP
EmbedDocument_Impl::SaveCompleted( LPCOLESTR pszFileName
)
903 // the different file name would mean error here
904 m_aFileName
= OUString( reinterpret_cast<const sal_Unicode
*>(pszFileName
) );
908 STDMETHODIMP
EmbedDocument_Impl::GetCurFile( LPOLESTR
*ppszFileName
)
910 CComPtr
<IMalloc
> pMalloc
;
912 HRESULT hr
= CoGetMalloc( 1, &pMalloc
);
913 if ( FAILED( hr
) || !pMalloc
) return E_FAIL
;
915 *ppszFileName
= (LPOLESTR
)( pMalloc
->Alloc( sizeof( sal_Unicode
) * ( m_aFileName
.getLength() + 1 ) ) );
916 wcsncpy( *ppszFileName
, reinterpret_cast<LPCWSTR
>(m_aFileName
.getStr()), m_aFileName
.getLength() + 1 );
918 return m_aFileName
.getLength() ? S_OK
: S_FALSE
;
922 LockedEmbedDocument_Impl
EmbeddedDocumentInstanceAccess_Impl::GetEmbedDocument()
924 ::osl::MutexGuard
aGuard( m_aMutex
);
925 return LockedEmbedDocument_Impl( m_pEmbedDocument
);
928 void EmbeddedDocumentInstanceAccess_Impl::ClearEmbedDocument()
930 ::osl::MutexGuard
aGuard( m_aMutex
);
931 m_pEmbedDocument
= NULL
;
935 LockedEmbedDocument_Impl::LockedEmbedDocument_Impl()
936 : m_pEmbedDocument( NULL
)
939 LockedEmbedDocument_Impl::LockedEmbedDocument_Impl( EmbedDocument_Impl
* pEmbedDocument
)
940 : m_pEmbedDocument( pEmbedDocument
)
942 if ( m_pEmbedDocument
)
943 m_pEmbedDocument
->AddRef();
946 LockedEmbedDocument_Impl::LockedEmbedDocument_Impl( const LockedEmbedDocument_Impl
& aDocLock
)
947 : m_pEmbedDocument( aDocLock
.m_pEmbedDocument
)
949 if ( m_pEmbedDocument
)
950 m_pEmbedDocument
->AddRef();
953 LockedEmbedDocument_Impl
& LockedEmbedDocument_Impl::operator=( const LockedEmbedDocument_Impl
& aDocLock
)
955 if ( m_pEmbedDocument
)
956 m_pEmbedDocument
->Release();
958 m_pEmbedDocument
= aDocLock
.m_pEmbedDocument
;
959 if ( m_pEmbedDocument
)
960 m_pEmbedDocument
->AddRef();
965 LockedEmbedDocument_Impl::~LockedEmbedDocument_Impl()
967 if ( m_pEmbedDocument
)
968 m_pEmbedDocument
->Release();
971 void LockedEmbedDocument_Impl::ExecuteMethod( sal_Int16 nId
)
973 if ( m_pEmbedDocument
)
975 if ( nId
== OLESERV_SAVEOBJECT
)
976 m_pEmbedDocument
->SaveObject();
977 else if ( nId
== OLESERV_CLOSE
)
978 m_pEmbedDocument
->Close( 0 );
979 else if ( nId
== OLESERV_NOTIFY
)
980 m_pEmbedDocument
->notify();
981 else if ( nId
== OLESERV_NOTIFYCLOSING
)
982 m_pEmbedDocument
->OLENotifyClosing();
983 else if ( nId
== OLESERV_SHOWOBJECT
)
984 m_pEmbedDocument
->ShowObject();
985 else if ( nId
== OLESERV_DEACTIVATE
)
986 m_pEmbedDocument
->Deactivate();
990 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */