update dev300-m58
[ooovba.git] / embedserv / source / embed / ed_ipersiststr.cxx
blob240d25047b9405455d40de710fbf66fc9ee4422e
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ed_ipersiststr.cxx,v $
10 * $Revision: 1.27.10.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
30 #if defined(_MSC_VER) && (_MSC_VER > 1310)
31 #pragma warning(disable : 4917 4555)
32 #endif
34 #include "embeddoc.hxx"
35 #include <com/sun/star/uno/Any.h>
36 #include <com/sun/star/uno/Exception.hpp>
37 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
38 #include <com/sun/star/lang/XComponent.hpp>
39 #include <com/sun/star/io/XInputStream.hpp>
40 #include <com/sun/star/io/XOutputStream.hpp>
41 #include <com/sun/star/io/XSeekable.hpp>
42 #include <com/sun/star/frame/XModel.hpp>
43 #include <com/sun/star/frame/XLoadable.hpp>
44 #include <com/sun/star/util/XModifiable.hpp>
45 #include <com/sun/star/frame/XStorable.hpp>
46 #include <com/sun/star/frame/XComponentLoader.hpp>
47 #include <com/sun/star/util/XUrlTransformer.hpp>
50 #include <osl/mutex.hxx>
51 #include <osl/diagnose.h>
53 #include <string.h>
55 #define EXT_STREAM_LENGTH 16
57 using namespace ::com::sun::star;
59 extern ::rtl::OUString getStorageTypeFromGUID_Impl( GUID* guid );
60 extern ::rtl::OUString getServiceNameFromGUID_Impl( GUID* );
61 extern ::rtl::OUString getFilterNameFromGUID_Impl( GUID* );
62 // extern CLIPFORMAT getClipFormatFromGUID_Impl( GUID* );
63 ::rtl::OUString getTestFileURLFromGUID_Impl( GUID* guid );
65 const ::rtl::OUString aOfficeEmbedStreamName( RTL_CONSTASCII_USTRINGPARAM ( "package_stream" ) );
66 const ::rtl::OUString aExtentStreamName( RTL_CONSTASCII_USTRINGPARAM ( "properties_stream" ) );
68 uno::Reference< io::XInputStream > createTempXInStreamFromIStream(
69 uno::Reference< lang::XMultiServiceFactory > xFactory,
70 IStream *pStream )
72 uno::Reference< io::XInputStream > xResult;
74 if ( !pStream )
75 return xResult;
77 const ::rtl::OUString aServiceName ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.io.TempFile" ) );
78 uno::Reference < io::XOutputStream > xTempOut = uno::Reference < io::XOutputStream > (
79 xFactory->createInstance ( aServiceName ),
80 uno::UNO_QUERY );
81 if ( xTempOut.is() )
83 ULARGE_INTEGER nNewPos;
84 LARGE_INTEGER aZero = { 0L, 0L };
85 HRESULT hr = pStream->Seek( aZero, STREAM_SEEK_SET, &nNewPos );
86 if ( FAILED( hr ) ) return xResult;
88 STATSTG aStat;
89 hr = pStream->Stat( &aStat, STATFLAG_NONAME );
90 if ( FAILED( hr ) ) return xResult;
92 sal_uInt32 nSize = (sal_uInt32)aStat.cbSize.QuadPart;
93 sal_uInt32 nCopied = 0;
94 uno::Sequence< sal_Int8 > aBuffer( nConstBufferSize );
95 try
97 sal_uInt32 nRead = 0;
100 pStream->Read( (void*)aBuffer.getArray(), nConstBufferSize, &nRead );
102 if ( nRead < nConstBufferSize )
103 aBuffer.realloc( nRead );
105 xTempOut->writeBytes( aBuffer );
106 nCopied += nRead;
107 } while( nRead == nConstBufferSize );
109 if ( nCopied == nSize )
111 uno::Reference < io::XSeekable > xTempSeek ( xTempOut, uno::UNO_QUERY );
112 if ( xTempSeek.is() )
114 xTempSeek->seek ( 0 );
115 xResult = uno::Reference< io::XInputStream >( xTempOut, uno::UNO_QUERY );
119 catch( uno::Exception& )
124 return xResult;
127 HRESULT copyXTempOutToIStream( uno::Reference< io::XOutputStream > xTempOut, IStream* pStream )
129 if ( !xTempOut.is() || !pStream )
130 return E_FAIL;
132 uno::Reference < io::XSeekable > xTempSeek ( xTempOut, uno::UNO_QUERY );
133 if ( !xTempSeek.is() )
134 return E_FAIL;
136 xTempSeek->seek ( 0 );
138 uno::Reference< io::XInputStream > xTempIn ( xTempOut, uno::UNO_QUERY );
139 if ( !xTempSeek.is() )
140 return E_FAIL;
142 // Seek to zero and truncate the stream
143 ULARGE_INTEGER nNewPos;
144 LARGE_INTEGER aZero = { 0L, 0L };
145 HRESULT hr = pStream->Seek( aZero, STREAM_SEEK_SET, &nNewPos );
146 if ( FAILED( hr ) ) return E_FAIL;
147 ULARGE_INTEGER aUZero = { 0L, 0L };
148 hr = pStream->SetSize( aUZero );
149 if ( FAILED( hr ) ) return E_FAIL;
151 uno::Sequence< sal_Int8 > aBuffer( nConstBufferSize );
152 sal_uInt32 nReadBytes = 0;
156 try {
157 nReadBytes = xTempIn->readBytes( aBuffer, nConstBufferSize );
159 catch( uno::Exception& )
161 return E_FAIL;
164 sal_uInt32 nWritten = 0;
165 HRESULT hr = pStream->Write( (void*)aBuffer.getArray(), nReadBytes, &nWritten );
166 if ( !SUCCEEDED( hr ) || nWritten != nReadBytes )
167 return E_FAIL;
169 } while( nReadBytes == nConstBufferSize );
171 return S_OK;
175 //===============================================================================
176 // EmbedDocument_Impl
177 //===============================================================================
179 EmbedDocument_Impl::EmbedDocument_Impl( const uno::Reference< lang::XMultiServiceFactory >& xFactory, const GUID* guid )
180 : m_refCount( 0L )
181 , m_xFactory( xFactory )
182 , m_guid( *guid )
183 , m_bIsDirty( sal_False )
184 , m_nAdviseNum( 0 )
185 , m_bIsInVerbHandling( sal_False )
186 //, m_bLoadedFromFile( sal_False )
188 m_xOwnAccess = new EmbeddedDocumentInstanceAccess_Impl( this );
189 m_pDocHolder = new DocumentHolder( xFactory, m_xOwnAccess );
190 m_pDocHolder->acquire();
193 EmbedDocument_Impl::~EmbedDocument_Impl()
195 m_pDocHolder->FreeOffice();
197 if ( m_pDocHolder->HasFrame() && m_pDocHolder->IsLink() )
199 // a link with frame should be only disconnected, not closed
200 m_pDocHolder->DisconnectFrameDocument( sal_True );
202 else
204 m_pDocHolder->CloseDocument();
205 m_pDocHolder->CloseFrame();
208 m_pDocHolder->release();
211 uno::Sequence< beans::PropertyValue > EmbedDocument_Impl::fillArgsForLoading_Impl( uno::Reference< io::XInputStream > xStream, DWORD /*nStreamMode*/, LPCOLESTR pFilePath )
213 uno::Sequence< beans::PropertyValue > aArgs( 3 );
215 sal_Int32 nInd = 0; // must not be bigger than the preset size
216 aArgs[nInd].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "FilterName" ) );
217 aArgs[nInd++].Value <<= getFilterNameFromGUID_Impl( &m_guid );
219 if ( xStream.is() )
221 aArgs[nInd].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "InputStream" ) );
222 aArgs[nInd++].Value <<= xStream;
223 aArgs[nInd].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "URL" ) );
224 aArgs[nInd++].Value <<= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "private:stream" ) );
226 else
228 aArgs[nInd].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "URL" ) );
230 rtl::OUString sDocUrl;
231 if ( pFilePath )
233 ::rtl::OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.util.URLTransformer" ) );
234 uno::Reference< util::XURLTransformer > aTransformer( m_xFactory->createInstance( aServiceName ),
235 uno::UNO_QUERY );
236 if ( aTransformer.is() )
238 util::URL aURL;
240 aURL.Complete = ::rtl::OUString( reinterpret_cast<const sal_Unicode*>(pFilePath) );
242 if ( aTransformer->parseSmart( aURL, ::rtl::OUString() ) )
243 sDocUrl = aURL.Complete;
247 aArgs[nInd++].Value <<= sDocUrl;
250 aArgs.realloc( nInd );
252 // aArgs[].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "ReadOnly" ) );
253 // aArgs[].Value <<= sal_False; //( ( nStreamMode & ( STGM_READWRITE | STGM_WRITE ) ) ? sal_True : sal_False );
255 return aArgs;
258 uno::Sequence< beans::PropertyValue > EmbedDocument_Impl::fillArgsForStoring_Impl( uno::Reference< io::XOutputStream > xStream)
260 uno::Sequence< beans::PropertyValue > aArgs( xStream.is() ? 2 : 1 );
262 aArgs[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "FilterName" ) );
263 aArgs[0].Value <<= getFilterNameFromGUID_Impl( &m_guid );
265 if ( xStream.is() )
267 aArgs[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "OutputStream" ) );
268 aArgs[1].Value <<= xStream;
271 return aArgs;
274 HRESULT EmbedDocument_Impl::SaveTo_Impl( IStorage* pStg )
276 if ( !pStg || pStg == m_pMasterStorage )
277 return E_FAIL;
279 // for saveto operation the master storage
280 // should not enter NoScribble mode
281 CComPtr< IStream > pOrigOwn = m_pOwnStream;
282 CComPtr< IStream > pOrigExt = m_pExtStream;
283 HRESULT hr = Save( pStg, sal_False );
284 pStg->Commit( STGC_ONLYIFCURRENT );
285 m_pOwnStream = pOrigOwn;
286 m_pExtStream = pOrigExt;
288 return hr;
291 //-------------------------------------------------------------------------------
292 // IUnknown
294 STDMETHODIMP EmbedDocument_Impl::QueryInterface( REFIID riid, void FAR* FAR* ppv )
296 if(IsEqualIID(riid, IID_IUnknown))
298 AddRef();
299 *ppv = (IUnknown*) (IPersistStorage*) this;
300 return S_OK;
302 else if (IsEqualIID(riid, IID_IPersist))
304 AddRef();
305 *ppv = (IPersist*) (IPersistStorage*) this;
306 return S_OK;
308 else if (IsEqualIID(riid, IID_IExternalConnection))
310 AddRef();
311 *ppv = (IExternalConnection*) this;
312 return S_OK;
314 else if (IsEqualIID(riid, IID_IPersistStorage))
316 AddRef();
317 *ppv = (IPersistStorage*) this;
318 return S_OK;
320 else if (IsEqualIID(riid, IID_IDataObject))
322 AddRef();
323 *ppv = (IDataObject*) this;
324 return S_OK;
326 else if (IsEqualIID(riid, IID_IOleObject))
328 AddRef();
329 *ppv = (IOleObject*) this;
330 return S_OK;
332 else if (IsEqualIID(riid, IID_IOleWindow))
334 AddRef();
335 *ppv = (IOleWindow*) this;
336 return S_OK;
338 else if (IsEqualIID(riid, IID_IOleInPlaceObject))
340 AddRef();
341 *ppv = (IOleInPlaceObject*) this;
342 return S_OK;
344 else if (IsEqualIID(riid, IID_IPersistFile))
346 AddRef();
347 *ppv = (IPersistFile*) this;
348 return S_OK;
350 else if (IsEqualIID(riid, IID_IDispatch))
352 AddRef();
353 *ppv = (IDispatch*) this;
354 return S_OK;
357 *ppv = NULL;
358 return ResultFromScode(E_NOINTERFACE);
361 STDMETHODIMP_(ULONG) EmbedDocument_Impl::AddRef()
363 return osl_incrementInterlockedCount( &m_refCount);
366 STDMETHODIMP_(ULONG) EmbedDocument_Impl::Release()
368 // if there is a time when the last reference is destructed, that means that only internal pointers are alive
369 // after the following call either the refcount is increased or the pointers are empty
370 if ( m_refCount == 1 )
371 m_xOwnAccess->ClearEmbedDocument();
373 sal_Int32 nCount = osl_decrementInterlockedCount( &m_refCount );
374 if ( nCount == 0 )
375 delete this;
376 return nCount;
379 //-------------------------------------------------------------------------------
380 // IPersist
382 STDMETHODIMP EmbedDocument_Impl::GetClassID( CLSID* pClassId )
384 *pClassId = *&m_guid;
385 return S_OK;
388 //-------------------------------------------------------------------------------
389 // IPersistStorage
391 STDMETHODIMP EmbedDocument_Impl::IsDirty()
393 // the link modified state is controlled by the document
394 if ( m_bIsDirty && !m_aFileName.getLength() )
395 return S_OK;
397 uno::Reference< util::XModifiable > xMod( m_pDocHolder->GetDocument(), uno::UNO_QUERY );
398 if ( xMod.is() )
399 return xMod->isModified() ? S_OK : S_FALSE;
400 return S_FALSE;
403 STDMETHODIMP EmbedDocument_Impl::InitNew( IStorage *pStg )
405 HRESULT hr = CO_E_ALREADYINITIALIZED;
407 if ( !m_pDocHolder->GetDocument().is() )
410 STATSTG aStat;
411 hr = pStg->Stat( &aStat, STATFLAG_NONAME );
412 if ( FAILED( hr ) ) return E_FAIL;
414 DWORD nStreamMode = aStat.grfMode;
416 hr = E_FAIL;
417 if ( m_xFactory.is() && pStg )
419 uno::Reference< frame::XModel > aDocument(
420 m_xFactory->createInstance( getServiceNameFromGUID_Impl( &m_guid ) ),
421 uno::UNO_QUERY );
422 if ( aDocument.is() )
424 m_pDocHolder->SetDocument( aDocument );
426 uno::Reference< frame::XLoadable > xLoadable( m_pDocHolder->GetDocument(), uno::UNO_QUERY );
427 if( xLoadable.is() )
431 xLoadable->initNew();
432 // xLoadable->load( fillArgsForLoading_Impl( uno::Reference< io::XInputStream >(), nStreamMode ) );
433 hr = S_OK;
435 catch( uno::Exception& )
440 if ( hr == S_OK )
442 ::rtl::OUString aCurType = getStorageTypeFromGUID_Impl( &m_guid ); // ???
443 CLIPFORMAT cf = (CLIPFORMAT)RegisterClipboardFormatA( "Embedded Object" );
444 hr = WriteFmtUserTypeStg( pStg,
445 cf, // ???
446 reinterpret_cast<LPWSTR>(( sal_Unicode* )aCurType.getStr()) );
448 if ( hr == S_OK )
450 hr = pStg->CreateStream( reinterpret_cast<LPCWSTR>(aOfficeEmbedStreamName.getStr()),
451 STGM_CREATE | ( nStreamMode & 0x73 ),
454 &m_pOwnStream );
456 if ( hr == S_OK && m_pOwnStream )
458 hr = pStg->CreateStream( reinterpret_cast<LPCWSTR>(aExtentStreamName.getStr()),
459 STGM_CREATE | ( nStreamMode & 0x73 ),
462 &m_pExtStream );
464 if ( hr == S_OK && m_pExtStream )
467 m_pMasterStorage = pStg;
468 m_bIsDirty = sal_True;
470 else
471 hr = E_FAIL;
473 else
474 hr = E_FAIL;
476 else
477 hr = E_FAIL;
480 if ( hr != S_OK )
481 m_pDocHolder->CloseDocument();
486 return hr;
489 STDMETHODIMP EmbedDocument_Impl::Load( IStorage *pStg )
491 if ( m_pDocHolder->GetDocument().is() )
492 return CO_E_ALREADYINITIALIZED;
494 if ( !m_xFactory.is() || !pStg )
495 return E_FAIL;
497 HRESULT hr = E_FAIL;
499 STATSTG aStat;
500 hr = pStg->Stat( &aStat, STATFLAG_NONAME );
501 if ( FAILED( hr ) ) return E_FAIL;
503 DWORD nStreamMode = aStat.grfMode;
504 hr = pStg->OpenStream( reinterpret_cast<LPCWSTR>(aOfficeEmbedStreamName.getStr()),
506 nStreamMode & 0x73,
508 &m_pOwnStream );
509 if ( !m_pOwnStream ) hr = E_FAIL;
511 if ( SUCCEEDED( hr ) )
513 hr = pStg->OpenStream( reinterpret_cast<LPCWSTR>(aExtentStreamName.getStr()),
515 nStreamMode & 0x73,
517 &m_pExtStream );
518 if ( !m_pExtStream ) hr = E_FAIL;
521 // RECTL aRectToSet;
522 SIZEL aSizeToSet;
523 if ( SUCCEEDED( hr ) )
525 ULARGE_INTEGER nNewPos;
526 LARGE_INTEGER aZero = { 0L, 0L };
527 hr = m_pExtStream->Seek( aZero, STREAM_SEEK_SET, &nNewPos );
528 if ( SUCCEEDED( hr ) )
530 sal_uInt32 nRead;
531 sal_Int8 aInf[EXT_STREAM_LENGTH];
532 hr = m_pExtStream->Read( (void*)aInf, EXT_STREAM_LENGTH, &nRead );
533 if ( nRead != EXT_STREAM_LENGTH ) hr = E_FAIL;
535 if ( SUCCEEDED( hr ) )
537 // aRectToSet.left = *((sal_Int32*)aInf);
538 // aRectToSet.top = *((sal_Int32*)&aInf[4]);
539 // aRectToSet.right = *((sal_Int32*)&aInf[8]);
540 // aRectToSet.bottom = *((sal_Int32*)&aInf[12]);
541 aSizeToSet.cx = *((sal_Int32*)&aInf[8]) - *((sal_Int32*)aInf);
542 aSizeToSet.cy = *((sal_Int32*)&aInf[12]) - *((sal_Int32*)&aInf[4]);
547 if ( SUCCEEDED( hr ) )
549 hr = E_FAIL;
551 uno::Reference < io::XInputStream > xTempIn = createTempXInStreamFromIStream( m_xFactory, m_pOwnStream );
552 if ( xTempIn.is() )
554 uno::Reference< frame::XModel > aDocument(
555 m_xFactory->createInstance( getServiceNameFromGUID_Impl( &m_guid ) ),
556 uno::UNO_QUERY );
557 if ( aDocument.is() )
559 m_pDocHolder->SetDocument( aDocument );
561 uno::Reference< frame::XLoadable > xLoadable( m_pDocHolder->GetDocument(), uno::UNO_QUERY );
562 if( xLoadable.is() )
566 xLoadable->load( fillArgsForLoading_Impl( xTempIn, nStreamMode ) );
567 m_pMasterStorage = pStg;
568 hr = m_pDocHolder->SetExtent( &aSizeToSet );
569 // hr = m_pDocHolder->SetVisArea( &aRectToSet );
571 catch( uno::Exception& )
576 if ( FAILED( hr ) )
577 m_pDocHolder->CloseDocument();
582 if ( FAILED( hr ) )
584 m_pOwnStream = CComPtr< IStream >();
585 m_pExtStream = CComPtr< IStream >();
586 hr = pStg->DestroyElement( reinterpret_cast<LPCWSTR>(aOfficeEmbedStreamName.getStr()) );
587 hr = pStg->DestroyElement( reinterpret_cast<LPCWSTR>(aExtentStreamName.getStr()) );
589 OSL_ENSURE( SUCCEEDED( hr ), "Can not destroy created stream!\n" );
590 if ( FAILED( hr ) )
591 hr = E_FAIL;
594 return hr;
597 STDMETHODIMP EmbedDocument_Impl::Save( IStorage *pStgSave, BOOL fSameAsLoad )
599 if ( !m_pDocHolder->GetDocument().is() || !m_xFactory.is() || !pStgSave || !m_pOwnStream || !m_pExtStream )
600 return E_FAIL;
602 CComPtr< IStream > pTargetStream;
603 CComPtr< IStream > pNewExtStream;
605 if ( !fSameAsLoad && pStgSave != m_pMasterStorage )
607 OSL_ENSURE( m_pMasterStorage, "How could the document be initialized without storage!??\n" );
608 HRESULT hr = m_pMasterStorage->CopyTo( NULL, NULL, NULL, pStgSave );
609 if ( FAILED( hr ) ) return E_FAIL;
611 STATSTG aStat;
612 hr = pStgSave->Stat( &aStat, STATFLAG_NONAME );
613 if ( FAILED( hr ) ) return E_FAIL;
615 DWORD nStreamMode = aStat.grfMode;
616 hr = pStgSave->CreateStream( reinterpret_cast<LPCWSTR>(aOfficeEmbedStreamName.getStr()),
617 STGM_CREATE | ( nStreamMode & 0x73 ),
620 &pTargetStream );
621 if ( FAILED( hr ) || !pTargetStream ) return E_FAIL;
623 hr = pStgSave->CreateStream( reinterpret_cast<LPCWSTR>(aExtentStreamName.getStr()),
624 STGM_CREATE | ( nStreamMode & 0x73 ),
627 &pNewExtStream );
628 if ( FAILED( hr ) || !pNewExtStream ) return E_FAIL;
630 else
632 pTargetStream = m_pOwnStream;
633 pNewExtStream = m_pExtStream;
636 HRESULT hr = E_FAIL;
638 const ::rtl::OUString aServiceName ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.io.TempFile" ) );
639 uno::Reference < io::XOutputStream > xTempOut = uno::Reference < io::XOutputStream > (
640 m_xFactory->createInstance ( aServiceName ),
641 uno::UNO_QUERY );
643 if ( xTempOut.is() )
645 uno::Reference< frame::XStorable > xStorable( m_pDocHolder->GetDocument(), uno::UNO_QUERY );
646 if( xStorable.is() )
650 xStorable->storeToURL( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "private:stream" ) ),
651 fillArgsForStoring_Impl( xTempOut ) );
652 hr = copyXTempOutToIStream( xTempOut, pTargetStream );
653 if ( SUCCEEDED( hr ) )
655 // no need to truncate the stream, the size of the stream is always the same
656 ULARGE_INTEGER nNewPos;
657 LARGE_INTEGER aZero = { 0L, 0L };
658 hr = pNewExtStream->Seek( aZero, STREAM_SEEK_SET, &nNewPos );
659 if ( SUCCEEDED( hr ) )
661 SIZEL aSize;
662 hr = m_pDocHolder->GetExtent( &aSize );
664 if ( SUCCEEDED( hr ) )
666 sal_uInt32 nWritten;
667 sal_Int8 aInf[EXT_STREAM_LENGTH];
668 *((sal_Int32*)aInf) = 0;
669 *((sal_Int32*)&aInf[4]) = 0;
670 *((sal_Int32*)&aInf[8]) = aSize.cx;
671 *((sal_Int32*)&aInf[12]) = aSize.cy;
673 hr = pNewExtStream->Write( (void*)aInf, EXT_STREAM_LENGTH, &nWritten );
674 if ( nWritten != EXT_STREAM_LENGTH ) hr = E_FAIL;
676 if ( SUCCEEDED( hr ) )
678 m_pOwnStream = CComPtr< IStream >();
679 m_pExtStream = CComPtr< IStream >();
680 if ( fSameAsLoad || pStgSave == m_pMasterStorage )
682 uno::Reference< util::XModifiable > xMod( m_pDocHolder->GetDocument(), uno::UNO_QUERY );
683 if ( xMod.is() )
684 xMod->setModified( sal_False );
685 m_bIsDirty = sal_False;
692 catch( uno::Exception& )
698 return hr;
701 STDMETHODIMP EmbedDocument_Impl::SaveCompleted( IStorage *pStgNew )
703 // m_pOwnStream == NULL && m_pMasterStorage != NULL means the object is in NoScribble mode
704 // m_pOwnStream == NULL && m_pMasterStorage == NULL means the object is in HandsOff mode
706 if ( m_pOwnStream || m_pExtStream )
707 return E_UNEXPECTED;
709 if ( !m_pMasterStorage && !pStgNew )
710 return E_INVALIDARG;
712 if ( pStgNew )
713 m_pMasterStorage = pStgNew;
715 STATSTG aStat;
716 HRESULT hr = m_pMasterStorage->Stat( &aStat, STATFLAG_NONAME );
717 if ( FAILED( hr ) ) return E_OUTOFMEMORY;
719 DWORD nStreamMode = aStat.grfMode;
720 hr = m_pMasterStorage->OpenStream( reinterpret_cast<LPCWSTR>(aOfficeEmbedStreamName.getStr()),
722 nStreamMode & 0x73,
724 &m_pOwnStream );
725 if ( FAILED( hr ) || !m_pOwnStream ) return E_OUTOFMEMORY;
727 hr = m_pMasterStorage->OpenStream( reinterpret_cast<LPCWSTR>(aExtentStreamName.getStr()),
729 nStreamMode & 0x73,
731 &m_pExtStream );
732 if ( FAILED( hr ) || !m_pExtStream ) return E_OUTOFMEMORY;
734 sal_Bool bModified = sal_False;
735 uno::Reference< util::XModifiable > xMod( m_pDocHolder->GetDocument(), uno::UNO_QUERY );
736 if ( xMod.is() )
737 bModified = xMod->isModified();
739 for ( AdviseSinkHashMapIterator iAdvise = m_aAdviseHashMap.begin(); iAdvise != m_aAdviseHashMap.end(); iAdvise++ )
741 if ( iAdvise->second )
742 iAdvise->second->OnSave();
745 if ( xMod.is() )
746 bModified = xMod->isModified();
748 return S_OK;
751 STDMETHODIMP EmbedDocument_Impl::HandsOffStorage()
753 m_pMasterStorage = CComPtr< IStorage >();
754 m_pOwnStream = CComPtr< IStream >();
755 m_pExtStream = CComPtr< IStream >();
757 return S_OK;
760 //-------------------------------------------------------------------------------
761 // IPersistFile
763 STDMETHODIMP EmbedDocument_Impl::Load( LPCOLESTR pszFileName, DWORD /*dwMode*/ )
765 if ( m_pDocHolder->GetDocument().is() )
766 return CO_E_ALREADYINITIALIZED;
768 if ( !m_xFactory.is() )
769 return E_FAIL;
771 DWORD nStreamMode = STGM_CREATE | STGM_READWRITE | STGM_DELETEONRELEASE | STGM_SHARE_EXCLUSIVE;
772 HRESULT hr = StgCreateDocfile( NULL,
773 nStreamMode ,
775 &m_pMasterStorage );
777 if ( FAILED( hr ) || !m_pMasterStorage ) return E_FAIL;
779 ::rtl::OUString aCurType = getServiceNameFromGUID_Impl( &m_guid ); // ???
780 CLIPFORMAT cf = (CLIPFORMAT)RegisterClipboardFormatA( "Embedded Object" );
781 hr = WriteFmtUserTypeStg( m_pMasterStorage,
782 cf, // ???
783 reinterpret_cast<LPWSTR>(( sal_Unicode* )aCurType.getStr()) );
784 if ( FAILED( hr ) ) return E_FAIL;
786 hr = m_pMasterStorage->SetClass( m_guid );
787 if ( FAILED( hr ) ) return E_FAIL;
789 hr = m_pMasterStorage->CreateStream( reinterpret_cast<LPCWSTR>(aOfficeEmbedStreamName.getStr()),
790 STGM_CREATE | ( nStreamMode & 0x73 ),
793 &m_pOwnStream );
794 if ( FAILED( hr ) || !m_pOwnStream ) return E_FAIL;
796 hr = m_pMasterStorage->CreateStream( reinterpret_cast<LPCWSTR>(aExtentStreamName.getStr()),
797 STGM_CREATE | ( nStreamMode & 0x73 ),
800 &m_pExtStream );
801 if ( FAILED( hr ) || !m_pExtStream ) return E_FAIL;
804 uno::Reference< frame::XModel > aDocument(
805 m_xFactory->createInstance( getServiceNameFromGUID_Impl( &m_guid ) ),
806 uno::UNO_QUERY );
807 if ( aDocument.is() )
809 m_pDocHolder->SetDocument( aDocument, sal_True );
811 uno::Reference< frame::XLoadable > xLoadable( m_pDocHolder->GetDocument(), uno::UNO_QUERY );
812 if( xLoadable.is() )
816 xLoadable->load( fillArgsForLoading_Impl( uno::Reference< io::XInputStream >(),
817 STGM_READWRITE,
818 pszFileName ) );
819 hr = S_OK;
821 m_aFileName = ::rtl::OUString( reinterpret_cast<const sal_Unicode*>(pszFileName) );
823 catch( uno::Exception& )
828 if ( hr == S_OK )
830 ::rtl::OUString aCurType = getServiceNameFromGUID_Impl( &m_guid ); // ???
831 CLIPFORMAT cf = (CLIPFORMAT)RegisterClipboardFormatA( "Embedded Object" );
832 hr = WriteFmtUserTypeStg( m_pMasterStorage,
833 cf, // ???
834 reinterpret_cast<LPWSTR>(( sal_Unicode* )aCurType.getStr()) );
836 if ( SUCCEEDED( hr ) )
838 // no need to truncate the stream, the size of the stream is always the same
839 ULARGE_INTEGER nNewPos;
840 LARGE_INTEGER aZero = { 0L, 0L };
841 hr = m_pExtStream->Seek( aZero, STREAM_SEEK_SET, &nNewPos );
842 if ( SUCCEEDED( hr ) )
844 SIZEL aSize;
845 hr = m_pDocHolder->GetExtent( &aSize );
847 if ( SUCCEEDED( hr ) )
849 sal_uInt32 nWritten;
850 sal_Int8 aInf[EXT_STREAM_LENGTH];
851 *((sal_Int32*)aInf) = 0;
852 *((sal_Int32*)&aInf[4]) = 0;
853 *((sal_Int32*)&aInf[8]) = aSize.cx;
854 *((sal_Int32*)&aInf[12]) = aSize.cy;
856 hr = m_pExtStream->Write( (void*)aInf, EXT_STREAM_LENGTH, &nWritten );
857 if ( nWritten != EXT_STREAM_LENGTH ) hr = E_FAIL;
862 if ( SUCCEEDED( hr ) )
863 m_bIsDirty = sal_True;
864 else
865 hr = E_FAIL;
868 if ( FAILED( hr ) )
870 m_pDocHolder->CloseDocument();
871 m_pOwnStream = NULL;
872 m_pExtStream = NULL;
873 m_pMasterStorage = NULL;
877 return hr;
880 STDMETHODIMP EmbedDocument_Impl::Save( LPCOLESTR pszFileName, BOOL fRemember )
882 if ( !m_pDocHolder->GetDocument().is() || !m_xFactory.is() )
883 return E_FAIL;
885 HRESULT hr = E_FAIL;
887 // TODO/LATER: currently there is no hands off state implemented
890 uno::Reference< frame::XStorable > xStorable( m_pDocHolder->GetDocument(), uno::UNO_QUERY_THROW );
892 if ( !pszFileName )
893 xStorable->store();
894 else
896 util::URL aURL;
897 aURL.Complete = ::rtl::OUString( reinterpret_cast<const sal_Unicode*>( pszFileName ) );
899 ::rtl::OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.util.URLTransformer" ) );
900 uno::Reference< util::XURLTransformer > aTransformer( m_xFactory->createInstance( aServiceName ),
901 uno::UNO_QUERY_THROW );
903 if ( aTransformer->parseSmart( aURL, ::rtl::OUString() ) && aURL.Complete.getLength() )
905 if ( fRemember )
907 xStorable->storeAsURL( aURL.Complete, fillArgsForStoring_Impl( uno::Reference< io::XOutputStream >() ) );
908 m_aFileName = aURL.Complete;
910 else
911 xStorable->storeToURL( aURL.Complete, fillArgsForStoring_Impl( uno::Reference< io::XOutputStream >() ) );
915 hr = S_OK;
917 catch( uno::Exception& )
921 return hr;
924 STDMETHODIMP EmbedDocument_Impl::SaveCompleted( LPCOLESTR pszFileName )
926 // the different file name would mean error here
927 m_aFileName = ::rtl::OUString( reinterpret_cast<const sal_Unicode*>(pszFileName) );
928 return S_OK;
931 STDMETHODIMP EmbedDocument_Impl::GetCurFile( LPOLESTR *ppszFileName )
933 CComPtr<IMalloc> pMalloc;
935 HRESULT hr = CoGetMalloc( 1, &pMalloc );
936 if ( FAILED( hr ) || !pMalloc ) return E_FAIL;
938 *ppszFileName = (LPOLESTR)( pMalloc->Alloc( sizeof( sal_Unicode ) * ( m_aFileName.getLength() + 1 ) ) );
939 wcsncpy( *ppszFileName, reinterpret_cast<LPCWSTR>(m_aFileName.getStr()), m_aFileName.getLength() + 1 );
941 return m_aFileName.getLength() ? S_OK : S_FALSE;
944 // ===============================================
946 LockedEmbedDocument_Impl EmbeddedDocumentInstanceAccess_Impl::GetEmbedDocument()
948 ::osl::MutexGuard aGuard( m_aMutex );
949 return LockedEmbedDocument_Impl( m_pEmbedDocument );
952 void EmbeddedDocumentInstanceAccess_Impl::ClearEmbedDocument()
954 ::osl::MutexGuard aGuard( m_aMutex );
955 m_pEmbedDocument = NULL;
958 // ===============================================
960 LockedEmbedDocument_Impl::LockedEmbedDocument_Impl()
961 : m_pEmbedDocument( NULL )
964 LockedEmbedDocument_Impl::LockedEmbedDocument_Impl( EmbedDocument_Impl* pEmbedDocument )
965 : m_pEmbedDocument( pEmbedDocument )
967 if ( m_pEmbedDocument )
968 m_pEmbedDocument->AddRef();
971 LockedEmbedDocument_Impl::LockedEmbedDocument_Impl( const LockedEmbedDocument_Impl& aDocLock )
972 : m_pEmbedDocument( aDocLock.m_pEmbedDocument )
974 if ( m_pEmbedDocument )
975 m_pEmbedDocument->AddRef();
978 LockedEmbedDocument_Impl& LockedEmbedDocument_Impl::operator=( const LockedEmbedDocument_Impl& aDocLock )
980 if ( m_pEmbedDocument )
981 m_pEmbedDocument->Release();
983 m_pEmbedDocument = aDocLock.m_pEmbedDocument;
984 if ( m_pEmbedDocument )
985 m_pEmbedDocument->AddRef();
987 return *this;
990 LockedEmbedDocument_Impl::~LockedEmbedDocument_Impl()
992 if ( m_pEmbedDocument )
993 m_pEmbedDocument->Release();
996 void LockedEmbedDocument_Impl::ExecuteMethod( sal_Int16 nId )
998 if ( m_pEmbedDocument )
1000 if ( nId == OLESERV_SAVEOBJECT )
1001 m_pEmbedDocument->SaveObject();
1002 else if ( nId == OLESERV_CLOSE )
1003 m_pEmbedDocument->Close( 0 );
1004 else if ( nId == OLESERV_NOTIFY )
1005 m_pEmbedDocument->notify();
1006 else if ( nId == OLESERV_NOTIFYCLOSING )
1007 m_pEmbedDocument->OLENotifyClosing();
1008 else if ( nId == OLESERV_SHOWOBJECT )
1009 m_pEmbedDocument->ShowObject();
1010 else if ( nId == OLESERV_DEACTIVATE )
1011 m_pEmbedDocument->Deactivate();
1015 // Fix strange warnings about some
1016 // ATL::CAxHostWindow::QueryInterface|AddRef|Releae functions.
1017 // warning C4505: 'xxx' : unreferenced local function has been removed
1018 #if defined(_MSC_VER)
1019 #pragma warning(disable: 4505)
1020 #endif