Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / embedserv / source / embed / ed_ipersiststr.cxx
blob9679c4a1908f4d5d525056e8a57ae443ea1d4838
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
19 #ifdef _MSC_VER
20 #pragma warning(disable : 4917 4555)
21 #endif
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>
44 #include <string.h>
46 #define EXT_STREAM_LENGTH 16
48 namespace {
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,
65 IStream *pStream )
67 uno::Reference< io::XInputStream > xResult;
69 if ( !pStream )
70 return 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;
79 STATSTG aStat;
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 );
86 try
88 sal_uInt32 nRead = 0;
91 pStream->Read( (void*)aBuffer.getArray(), nConstBufferSize, &nRead );
93 if ( nRead < nConstBufferSize )
94 aBuffer.realloc( nRead );
96 xTempOut->writeBytes( aBuffer );
97 nCopied += nRead;
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& )
114 return xResult;
117 HRESULT copyXTempOutToIStream( uno::Reference< io::XOutputStream > xTempOut, IStream* pStream )
119 if ( !xTempOut.is() || !pStream )
120 return E_FAIL;
122 uno::Reference < io::XSeekable > xTempSeek ( xTempOut, uno::UNO_QUERY );
123 if ( !xTempSeek.is() )
124 return E_FAIL;
126 xTempSeek->seek ( 0 );
128 uno::Reference< io::XInputStream > xTempIn ( xTempOut, uno::UNO_QUERY );
129 if ( !xTempSeek.is() )
130 return E_FAIL;
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;
146 try {
147 nReadBytes = xTempIn->readBytes( aBuffer, nConstBufferSize );
149 catch( const uno::Exception& )
151 return E_FAIL;
154 sal_uInt32 nWritten = 0;
155 hr = pStream->Write( (void*)aBuffer.getArray(), nReadBytes, &nWritten );
156 if ( !SUCCEEDED( hr ) || nWritten != nReadBytes )
157 return E_FAIL;
159 } while( nReadBytes == nConstBufferSize );
161 return S_OK;
165 // EmbedDocument_Impl
168 EmbedDocument_Impl::EmbedDocument_Impl( const uno::Reference< lang::XMultiServiceFactory >& xFactory, const GUID* guid )
169 : m_refCount( 0L )
170 , m_xFactory( xFactory )
171 , m_guid( *guid )
172 , m_bIsDirty( sal_False )
173 , m_nAdviseNum( 0 )
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 );
191 else
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 );
208 if ( xStream.is() )
210 aArgs[nInd].Name = "InputStream";
211 aArgs[nInd++].Value <<= xStream;
212 aArgs[nInd].Name = "URL";
213 aArgs[nInd++].Value <<= OUString( "private:stream" );
215 else
217 aArgs[nInd].Name = "URL";
219 OUString sDocUrl;
220 if ( pFilePath )
222 uno::Reference< util::XURLTransformer > aTransformer( util::URLTransformer::create(comphelper::getComponentContext(m_xFactory)) );
223 util::URL aURL;
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 );
239 return aArgs;
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 );
249 if ( xStream.is() )
251 aArgs[1].Name = "OutputStream";
252 aArgs[1].Value <<= xStream;
255 return aArgs;
258 HRESULT EmbedDocument_Impl::SaveTo_Impl( IStorage* pStg )
260 if ( !pStg || pStg == m_pMasterStorage )
261 return E_FAIL;
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;
272 return hr;
276 // IUnknown
278 STDMETHODIMP EmbedDocument_Impl::QueryInterface( REFIID riid, void FAR* FAR* ppv )
280 if(IsEqualIID(riid, IID_IUnknown))
282 AddRef();
283 *ppv = (IUnknown*) (IPersistStorage*) this;
284 return S_OK;
286 else if (IsEqualIID(riid, IID_IPersist))
288 AddRef();
289 *ppv = (IPersist*) (IPersistStorage*) this;
290 return S_OK;
292 else if (IsEqualIID(riid, IID_IExternalConnection))
294 AddRef();
295 *ppv = (IExternalConnection*) this;
296 return S_OK;
298 else if (IsEqualIID(riid, IID_IPersistStorage))
300 AddRef();
301 *ppv = (IPersistStorage*) this;
302 return S_OK;
304 else if (IsEqualIID(riid, IID_IDataObject))
306 AddRef();
307 *ppv = (IDataObject*) this;
308 return S_OK;
310 else if (IsEqualIID(riid, IID_IOleObject))
312 AddRef();
313 *ppv = (IOleObject*) this;
314 return S_OK;
316 else if (IsEqualIID(riid, IID_IOleWindow))
318 AddRef();
319 *ppv = (IOleWindow*) this;
320 return S_OK;
322 else if (IsEqualIID(riid, IID_IOleInPlaceObject))
324 AddRef();
325 *ppv = (IOleInPlaceObject*) this;
326 return S_OK;
328 else if (IsEqualIID(riid, IID_IPersistFile))
330 AddRef();
331 *ppv = (IPersistFile*) this;
332 return S_OK;
334 else if (IsEqualIID(riid, IID_IDispatch))
336 AddRef();
337 *ppv = (IDispatch*) this;
338 return S_OK;
341 *ppv = NULL;
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 );
358 if ( nCount == 0 )
359 delete this;
360 return nCount;
364 // IPersist
366 STDMETHODIMP EmbedDocument_Impl::GetClassID( CLSID* pClassId )
368 *pClassId = *&m_guid;
369 return S_OK;
373 // IPersistStorage
375 STDMETHODIMP EmbedDocument_Impl::IsDirty()
377 // the link modified state is controlled by the document
378 if ( m_bIsDirty && !m_aFileName.getLength() )
379 return S_OK;
381 uno::Reference< util::XModifiable > xMod( m_pDocHolder->GetDocument(), uno::UNO_QUERY );
382 if ( xMod.is() )
383 return xMod->isModified() ? S_OK : S_FALSE;
384 return S_FALSE;
387 STDMETHODIMP EmbedDocument_Impl::InitNew( IStorage *pStg )
389 HRESULT hr = CO_E_ALREADYINITIALIZED;
391 if ( !m_pDocHolder->GetDocument().is() )
394 STATSTG aStat;
395 hr = pStg->Stat( &aStat, STATFLAG_NONAME );
396 if ( FAILED( hr ) ) return E_FAIL;
398 DWORD nStreamMode = aStat.grfMode;
400 hr = E_FAIL;
401 if ( m_xFactory.is() && pStg )
403 uno::Reference< frame::XModel > aDocument(
404 m_xFactory->createInstance( getServiceNameFromGUID_Impl( &m_guid ) ),
405 uno::UNO_QUERY );
406 if ( aDocument.is() )
408 m_pDocHolder->SetDocument( aDocument );
410 uno::Reference< frame::XLoadable > xLoadable( m_pDocHolder->GetDocument(), uno::UNO_QUERY );
411 if( xLoadable.is() )
415 xLoadable->initNew();
416 // xLoadable->load( fillArgsForLoading_Impl( uno::Reference< io::XInputStream >(), nStreamMode ) );
417 hr = S_OK;
419 catch( const uno::Exception& )
424 if ( hr == S_OK )
426 OUString aCurType = getStorageTypeFromGUID_Impl( &m_guid ); // ???
427 CLIPFORMAT cf = (CLIPFORMAT)RegisterClipboardFormatA( "Embedded Object" );
428 hr = WriteFmtUserTypeStg( pStg,
429 cf, // ???
430 reinterpret_cast<LPWSTR>(( sal_Unicode* )aCurType.getStr()) );
432 if ( hr == S_OK )
434 hr = pStg->CreateStream( reinterpret_cast<LPCWSTR>(aOfficeEmbedStreamName.getStr()),
435 STGM_CREATE | ( nStreamMode & 0x73 ),
438 &m_pOwnStream );
440 if ( hr == S_OK && m_pOwnStream )
442 hr = pStg->CreateStream( reinterpret_cast<LPCWSTR>(aExtentStreamName.getStr()),
443 STGM_CREATE | ( nStreamMode & 0x73 ),
446 &m_pExtStream );
448 if ( hr == S_OK && m_pExtStream )
451 m_pMasterStorage = pStg;
452 m_bIsDirty = sal_True;
454 else
455 hr = E_FAIL;
457 else
458 hr = E_FAIL;
460 else
461 hr = E_FAIL;
464 if ( hr != S_OK )
465 m_pDocHolder->CloseDocument();
470 return hr;
473 STDMETHODIMP EmbedDocument_Impl::Load( IStorage *pStg )
475 if ( m_pDocHolder->GetDocument().is() )
476 return CO_E_ALREADYINITIALIZED;
478 if ( !m_xFactory.is() || !pStg )
479 return E_FAIL;
481 HRESULT hr = E_FAIL;
483 STATSTG aStat;
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()),
490 nStreamMode & 0x73,
492 &m_pOwnStream );
493 if ( !m_pOwnStream ) hr = E_FAIL;
495 if ( SUCCEEDED( hr ) )
497 hr = pStg->OpenStream( reinterpret_cast<LPCWSTR>(aExtentStreamName.getStr()),
499 nStreamMode & 0x73,
501 &m_pExtStream );
502 if ( !m_pExtStream ) hr = E_FAIL;
505 // RECTL aRectToSet;
506 SIZEL aSizeToSet;
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 ) )
514 sal_uInt32 nRead;
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 ) )
533 hr = E_FAIL;
535 uno::Reference < io::XInputStream > xTempIn = createTempXInStreamFromIStream( m_xFactory, m_pOwnStream );
536 if ( xTempIn.is() )
538 uno::Reference< frame::XModel > aDocument(
539 m_xFactory->createInstance( getServiceNameFromGUID_Impl( &m_guid ) ),
540 uno::UNO_QUERY );
541 if ( aDocument.is() )
543 m_pDocHolder->SetDocument( aDocument );
545 uno::Reference< frame::XLoadable > xLoadable( m_pDocHolder->GetDocument(), uno::UNO_QUERY );
546 if( xLoadable.is() )
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& )
560 if ( FAILED( hr ) )
561 m_pDocHolder->CloseDocument();
566 if ( FAILED( hr ) )
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" );
574 if ( FAILED( hr ) )
575 hr = E_FAIL;
578 return hr;
581 STDMETHODIMP EmbedDocument_Impl::Save( IStorage *pStgSave, BOOL fSameAsLoad )
583 if ( !m_pDocHolder->GetDocument().is() || !m_xFactory.is() || !pStgSave || !m_pOwnStream || !m_pExtStream )
584 return E_FAIL;
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;
595 STATSTG aStat;
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 ),
604 &pTargetStream );
605 if ( FAILED( hr ) || !pTargetStream ) return E_FAIL;
607 hr = pStgSave->CreateStream( reinterpret_cast<LPCWSTR>(aExtentStreamName.getStr()),
608 STGM_CREATE | ( nStreamMode & 0x73 ),
611 &pNewExtStream );
612 if ( FAILED( hr ) || !pNewExtStream ) return E_FAIL;
614 else
616 pTargetStream = m_pOwnStream;
617 pNewExtStream = m_pExtStream;
620 HRESULT hr = E_FAIL;
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 );
626 if( xStorable.is() )
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 ) )
641 SIZEL aSize;
642 hr = m_pDocHolder->GetExtent( &aSize );
644 if ( SUCCEEDED( hr ) )
646 sal_uInt32 nWritten;
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 );
663 if ( xMod.is() )
664 xMod->setModified( sal_False );
665 m_bIsDirty = sal_False;
672 catch( const uno::Exception& )
677 return hr;
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 )
686 return E_UNEXPECTED;
688 if ( !m_pMasterStorage && !pStgNew )
689 return E_INVALIDARG;
691 if ( pStgNew )
692 m_pMasterStorage = pStgNew;
694 STATSTG aStat;
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()),
701 nStreamMode & 0x73,
703 &m_pOwnStream );
704 if ( FAILED( hr ) || !m_pOwnStream ) return E_OUTOFMEMORY;
706 hr = m_pMasterStorage->OpenStream( reinterpret_cast<LPCWSTR>(aExtentStreamName.getStr()),
708 nStreamMode & 0x73,
710 &m_pExtStream );
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 );
715 if ( xMod.is() )
716 bModified = xMod->isModified();
718 for ( AdviseSinkHashMapIterator iAdvise = m_aAdviseHashMap.begin(); iAdvise != m_aAdviseHashMap.end(); iAdvise++ )
720 if ( iAdvise->second )
721 iAdvise->second->OnSave();
724 if ( xMod.is() )
725 bModified = xMod->isModified();
727 return S_OK;
730 STDMETHODIMP EmbedDocument_Impl::HandsOffStorage()
732 m_pMasterStorage = CComPtr< IStorage >();
733 m_pOwnStream = CComPtr< IStream >();
734 m_pExtStream = CComPtr< IStream >();
736 return S_OK;
740 // IPersistFile
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() )
748 return E_FAIL;
750 DWORD nStreamMode = STGM_CREATE | STGM_READWRITE | STGM_DELETEONRELEASE | STGM_SHARE_EXCLUSIVE;
751 HRESULT hr = StgCreateDocfile( NULL,
752 nStreamMode ,
754 &m_pMasterStorage );
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,
761 cf, // ???
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 ),
772 &m_pOwnStream );
773 if ( FAILED( hr ) || !m_pOwnStream ) return E_FAIL;
775 hr = m_pMasterStorage->CreateStream( reinterpret_cast<LPCWSTR>(aExtentStreamName.getStr()),
776 STGM_CREATE | ( nStreamMode & 0x73 ),
779 &m_pExtStream );
780 if ( FAILED( hr ) || !m_pExtStream ) return E_FAIL;
783 uno::Reference< frame::XModel > aDocument(
784 m_xFactory->createInstance( getServiceNameFromGUID_Impl( &m_guid ) ),
785 uno::UNO_QUERY );
786 if ( aDocument.is() )
788 m_pDocHolder->SetDocument( aDocument, sal_True );
790 uno::Reference< frame::XLoadable > xLoadable( m_pDocHolder->GetDocument(), uno::UNO_QUERY );
791 if( xLoadable.is() )
795 xLoadable->load( fillArgsForLoading_Impl( uno::Reference< io::XInputStream >(),
796 STGM_READWRITE,
797 pszFileName ) );
798 hr = S_OK;
800 m_aFileName = OUString( reinterpret_cast<const sal_Unicode*>(pszFileName) );
802 catch( const uno::Exception& )
807 if ( hr == S_OK )
809 aCurType = getServiceNameFromGUID_Impl( &m_guid ); // ???
810 cf = (CLIPFORMAT)RegisterClipboardFormatA( "Embedded Object" );
811 hr = WriteFmtUserTypeStg( m_pMasterStorage,
812 cf, // ???
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 ) )
823 SIZEL aSize;
824 hr = m_pDocHolder->GetExtent( &aSize );
826 if ( SUCCEEDED( hr ) )
828 sal_uInt32 nWritten;
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;
843 else
844 hr = E_FAIL;
847 if ( FAILED( hr ) )
849 m_pDocHolder->CloseDocument();
850 m_pOwnStream = NULL;
851 m_pExtStream = NULL;
852 m_pMasterStorage = NULL;
856 return hr;
859 STDMETHODIMP EmbedDocument_Impl::Save( LPCOLESTR pszFileName, BOOL fRemember )
861 if ( !m_pDocHolder->GetDocument().is() || !m_xFactory.is() )
862 return E_FAIL;
864 HRESULT hr = E_FAIL;
866 // TODO/LATER: currently there is no hands off state implemented
869 uno::Reference< frame::XStorable > xStorable( m_pDocHolder->GetDocument(), uno::UNO_QUERY_THROW );
871 if ( !pszFileName )
872 xStorable->store();
873 else
875 util::URL aURL;
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() )
882 if ( fRemember )
884 xStorable->storeAsURL( aURL.Complete, fillArgsForStoring_Impl( uno::Reference< io::XOutputStream >() ) );
885 m_aFileName = aURL.Complete;
887 else
888 xStorable->storeToURL( aURL.Complete, fillArgsForStoring_Impl( uno::Reference< io::XOutputStream >() ) );
892 hr = S_OK;
894 catch( const uno::Exception& )
898 return hr;
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) );
905 return S_OK;
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();
962 return *this;
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: */