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 <oleembobj.hxx>
21 #include <com/sun/star/embed/EmbedStates.hpp>
22 #include <com/sun/star/embed/EmbedVerbs.hpp>
23 #include <com/sun/star/embed/UnreachableStateException.hpp>
24 #include <com/sun/star/embed/XStorage.hpp>
25 #include <com/sun/star/embed/ElementModes.hpp>
26 #include <com/sun/star/embed/EmbedUpdateModes.hpp>
27 #include <com/sun/star/embed/NeedsRunningStateException.hpp>
28 #include <com/sun/star/embed/StateChangeInProgressException.hpp>
29 #include <com/sun/star/embed/EmbedMisc.hpp>
30 #include <com/sun/star/embed/XEmbedObjectCreator.hpp>
31 #include <com/sun/star/io/TempFile.hpp>
32 #include <com/sun/star/io/XSeekable.hpp>
33 #include <com/sun/star/lang/DisposedException.hpp>
34 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
35 #include <com/sun/star/beans/NamedValue.hpp>
36 #include <com/sun/star/beans/XPropertySet.hpp>
37 #include <com/sun/star/frame/XLoadable.hpp>
38 #include <com/sun/star/document/XStorageBasedDocument.hpp>
39 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
40 #include <com/sun/star/container/XNameAccess.hpp>
41 #include <com/sun/star/container/XNameContainer.hpp>
42 #include <com/sun/star/system/SystemShellExecute.hpp>
43 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
45 #include <cppuhelper/exc_hlp.hxx>
46 #include <cppuhelper/interfacecontainer.h>
47 #include <comphelper/processfactory.hxx>
48 #include <comphelper/mimeconfighelper.hxx>
49 #include <sal/log.hxx>
50 #include <tools/diagnose_ex.h>
53 #include <targetstatecontrol.hxx>
55 #include "ownview.hxx"
58 #include "olecomponent.hxx"
61 using namespace ::com::sun::star
;
65 void OleEmbeddedObject::SwitchComponentToRunningState_Impl()
67 if ( !m_pOleComponent
)
69 throw embed::UnreachableStateException();
73 m_pOleComponent
->RunObject();
75 catch( const embed::UnreachableStateException
& )
80 catch( const embed::WrongStateException
& )
88 uno::Sequence
< sal_Int32
> OleEmbeddedObject::GetReachableStatesList_Impl(
89 const uno::Sequence
< embed::VerbDescriptor
>& aVerbList
)
91 uno::Sequence
< sal_Int32
> aStates(2);
92 aStates
[0] = embed::EmbedStates::LOADED
;
93 aStates
[1] = embed::EmbedStates::RUNNING
;
94 for ( sal_Int32 nInd
= 0; nInd
< aVerbList
.getLength(); nInd
++ )
95 if ( aVerbList
[nInd
].VerbID
== embed::EmbedVerbs::MS_OLEVERB_OPEN
)
98 aStates
[2] = embed::EmbedStates::ACTIVE
;
105 uno::Sequence
< sal_Int32
> OleEmbeddedObject::GetIntermediateVerbsSequence_Impl( sal_Int32 nNewState
)
107 SAL_WARN_IF( m_nObjectState
== embed::EmbedStates::LOADED
, "embeddedobj.ole", "Loaded object is switched to running state without verbs using!" );
109 // actually there will be only one verb
110 if ( m_nObjectState
== embed::EmbedStates::RUNNING
&& nNewState
== embed::EmbedStates::ACTIVE
)
112 uno::Sequence
< sal_Int32
> aVerbs( 1 );
113 aVerbs
[0] = embed::EmbedVerbs::MS_OLEVERB_OPEN
;
116 return uno::Sequence
< sal_Int32
>();
120 void OleEmbeddedObject::MoveListeners()
122 if ( m_pInterfaceContainer
)
124 // move state change listeners
126 ::cppu::OInterfaceContainerHelper
* pStateChangeContainer
=
127 m_pInterfaceContainer
->getContainer( cppu::UnoType
<embed::XStateChangeListener
>::get());
128 if ( pStateChangeContainer
!= nullptr )
130 if ( m_xWrappedObject
.is() )
132 ::cppu::OInterfaceIteratorHelper
pIterator( *pStateChangeContainer
);
133 while ( pIterator
.hasMoreElements() )
137 m_xWrappedObject
->addStateChangeListener( static_cast<embed::XStateChangeListener
*>(pIterator
.next()) );
139 catch( const uno::RuntimeException
& )
148 // move event listeners
150 ::cppu::OInterfaceContainerHelper
* pEventContainer
=
151 m_pInterfaceContainer
->getContainer( cppu::UnoType
<document::XEventListener
>::get());
152 if ( pEventContainer
!= nullptr )
154 if ( m_xWrappedObject
.is() )
156 ::cppu::OInterfaceIteratorHelper
pIterator( *pEventContainer
);
157 while ( pIterator
.hasMoreElements() )
161 m_xWrappedObject
->addEventListener( static_cast<document::XEventListener
*>(pIterator
.next()) );
163 catch( const uno::RuntimeException
& )
172 // move close listeners
174 ::cppu::OInterfaceContainerHelper
* pCloseContainer
=
175 m_pInterfaceContainer
->getContainer( cppu::UnoType
<util::XCloseListener
>::get());
176 if ( pCloseContainer
!= nullptr )
178 if ( m_xWrappedObject
.is() )
180 ::cppu::OInterfaceIteratorHelper
pIterator( *pCloseContainer
);
181 while ( pIterator
.hasMoreElements() )
185 m_xWrappedObject
->addCloseListener( static_cast<util::XCloseListener
*>(pIterator
.next()) );
187 catch( const uno::RuntimeException
& )
196 m_pInterfaceContainer
.reset();
201 uno::Reference
< embed::XStorage
> OleEmbeddedObject::CreateTemporarySubstorage( OUString
& o_aStorageName
)
203 uno::Reference
< embed::XStorage
> xResult
;
205 for ( sal_Int32 nInd
= 0; nInd
< 32000 && !xResult
.is(); nInd
++ )
207 OUString aName
= OUString::number( nInd
) + "TMPSTOR" + m_aEntryName
;
208 if ( !m_xParentStorage
->hasByName( aName
) )
210 xResult
= m_xParentStorage
->openStorageElement( aName
, embed::ElementModes::READWRITE
);
211 o_aStorageName
= aName
;
217 o_aStorageName
.clear();
218 throw uno::RuntimeException();
225 OUString
OleEmbeddedObject::MoveToTemporarySubstream()
228 for ( sal_Int32 nInd
= 0; nInd
< 32000 && aResult
.isEmpty(); nInd
++ )
230 OUString aName
= OUString::number( nInd
) + "TMPSTREAM" + m_aEntryName
;
231 if ( !m_xParentStorage
->hasByName( aName
) )
233 m_xParentStorage
->renameElement( m_aEntryName
, aName
);
238 if ( aResult
.isEmpty() )
239 throw uno::RuntimeException();
245 bool OleEmbeddedObject::TryToConvertToOOo( const uno::Reference
< io::XStream
>& xStream
)
247 bool bResult
= false;
249 OUString aStorageName
;
250 OUString aTmpStreamName
;
253 if ( m_pOleComponent
|| m_bReadOnly
)
258 changeState( embed::EmbedStates::LOADED
);
260 // the stream must be seekable
261 uno::Reference
< io::XSeekable
> xSeekable( xStream
, uno::UNO_QUERY_THROW
);
262 xSeekable
->seek( 0 );
263 m_aFilterName
= OwnView_Impl::GetFilterNameFromExtentionAndInStream( m_xFactory
, OUString(), xStream
->getInputStream() );
265 if ( !m_aFilterName
.isEmpty()
266 && ( m_aFilterName
== "Calc MS Excel 2007 XML" || m_aFilterName
== "Impress MS PowerPoint 2007 XML" || m_aFilterName
== "MS Word 2007 XML"
267 || m_aFilterName
== "MS Excel 97 Vorlage/Template" || m_aFilterName
== "MS Word 97 Vorlage" ) )
269 uno::Reference
< container::XNameAccess
> xFilterFactory(
270 m_xFactory
->createInstance("com.sun.star.document.FilterFactory"),
271 uno::UNO_QUERY_THROW
);
273 OUString aDocServiceName
;
274 uno::Any aFilterAnyData
= xFilterFactory
->getByName( m_aFilterName
);
275 uno::Sequence
< beans::PropertyValue
> aFilterData
;
276 if ( aFilterAnyData
>>= aFilterData
)
278 for ( sal_Int32 nInd
= 0; nInd
< aFilterData
.getLength(); nInd
++ )
279 if ( aFilterData
[nInd
].Name
== "DocumentService" )
280 aFilterData
[nInd
].Value
>>= aDocServiceName
;
283 if ( !aDocServiceName
.isEmpty() )
286 uno::Sequence
< uno::Any
> aArguments(1);
287 aArguments
[0] <<= beans::NamedValue( "EmbeddedObject", uno::makeAny( true ));
289 uno::Reference
< util::XCloseable
> xDocument( m_xFactory
->createInstanceWithArguments( aDocServiceName
, aArguments
), uno::UNO_QUERY_THROW
);
290 uno::Reference
< frame::XLoadable
> xLoadable( xDocument
, uno::UNO_QUERY_THROW
);
291 uno::Reference
< document::XStorageBasedDocument
> xStorDoc( xDocument
, uno::UNO_QUERY_THROW
);
293 // let the model behave as embedded one
294 uno::Reference
< frame::XModel
> xModel( xDocument
, uno::UNO_QUERY_THROW
);
295 uno::Sequence
< beans::PropertyValue
> aSeq( 1 );
296 aSeq
[0].Name
= "SetEmbedded";
297 aSeq
[0].Value
<<= true;
298 xModel
->attachResource( OUString(), aSeq
);
300 // load the model from the stream
301 uno::Sequence
< beans::PropertyValue
> aArgs( 5 );
302 aArgs
[0].Name
= "HierarchicalDocumentName";
303 aArgs
[0].Value
<<= m_aEntryName
;
304 aArgs
[1].Name
= "ReadOnly";
305 aArgs
[1].Value
<<= true;
306 aArgs
[2].Name
= "FilterName";
307 aArgs
[2].Value
<<= m_aFilterName
;
308 aArgs
[3].Name
= "URL";
309 aArgs
[3].Value
<<= OUString( "private:stream" );
310 aArgs
[4].Name
= "InputStream";
311 aArgs
[4].Value
<<= xStream
->getInputStream();
313 xSeekable
->seek( 0 );
314 xLoadable
->load( aArgs
);
316 // the model is successfully loaded, create a new storage and store the model to the storage
317 uno::Reference
< embed::XStorage
> xTmpStorage
= CreateTemporarySubstorage( aStorageName
);
318 xStorDoc
->storeToStorage( xTmpStorage
, uno::Sequence
< beans::PropertyValue
>() );
319 xDocument
->close( true );
320 uno::Reference
< beans::XPropertySet
> xStorProps( xTmpStorage
, uno::UNO_QUERY_THROW
);
322 xStorProps
->getPropertyValue("MediaType") >>= aMediaType
;
323 xTmpStorage
->dispose();
325 // look for the related embedded object factory
326 ::comphelper::MimeConfigurationHelper
aConfigHelper( comphelper::getComponentContext(m_xFactory
) );
327 OUString aEmbedFactory
;
328 if ( !aMediaType
.isEmpty() )
329 aEmbedFactory
= aConfigHelper
.GetFactoryNameByMediaType( aMediaType
);
331 if ( aEmbedFactory
.isEmpty() )
332 throw uno::RuntimeException();
334 uno::Reference
< uno::XInterface
> xFact
= m_xFactory
->createInstance( aEmbedFactory
);
336 uno::Reference
< embed::XEmbedObjectCreator
> xEmbCreator( xFact
, uno::UNO_QUERY_THROW
);
338 // now the object should be adjusted to become the wrapper
340 uno::Reference
< lang::XComponent
> xComp( m_xObjectStream
, uno::UNO_QUERY_THROW
);
342 m_xObjectStream
.clear();
346 aTmpStreamName
= MoveToTemporarySubstream();
349 m_xParentStorage
->renameElement( aStorageName
, m_aEntryName
);
352 m_xWrappedObject
.set( xEmbCreator
->createInstanceInitFromEntry( m_xParentStorage
, m_aEntryName
, uno::Sequence
< beans::PropertyValue
>(), uno::Sequence
< beans::PropertyValue
>() ), uno::UNO_QUERY_THROW
);
354 // remember parent document name to show in the title bar
355 m_xWrappedObject
->setContainerName( m_aContainerName
);
357 bResult
= true; // the change is no more revertable
360 m_xParentStorage
->removeElement( aTmpStreamName
);
362 catch( const uno::Exception
& )
364 // the success of the removing is not so important
369 catch( const uno::Exception
& )
371 // repair the object if necessary
376 if ( !aTmpStreamName
.isEmpty() && aTmpStreamName
!= m_aEntryName
)
379 if ( m_xParentStorage
->hasByName( m_aEntryName
) )
380 m_xParentStorage
->removeElement( m_aEntryName
);
381 m_xParentStorage
->renameElement( aTmpStreamName
, m_aEntryName
);
383 catch ( const uno::Exception
& ex
)
385 css::uno::Any anyEx
= cppu::getCaughtException();
388 } catch( const uno::Exception
& ) {}
390 m_xParentStorage
->dispose(); // ??? the storage has information loss, it should be closed without committing!
391 throw css::lang::WrappedTargetRuntimeException( ex
.Message
,
392 nullptr, anyEx
); // the repairing is not possible
398 m_xObjectStream
= m_xParentStorage
->openStreamElement( m_aEntryName
, m_bReadOnly
? embed::ElementModes::READ
: embed::ElementModes::READWRITE
);
399 m_nObjectState
= embed::EmbedStates::LOADED
;
401 catch( const uno::Exception
& ex
)
403 css::uno::Any anyEx
= cppu::getCaughtException();
406 } catch( const uno::Exception
& ) {}
408 throw css::lang::WrappedTargetRuntimeException( ex
.Message
,
409 nullptr, anyEx
); // the repairing is not possible
415 if ( !aStorageName
.isEmpty() )
417 m_xParentStorage
->removeElement( aStorageName
);
418 } catch( const uno::Exception
& ) { SAL_WARN( "embeddedobj.ole", "Can not remove temporary storage!" ); }
425 // the conversion was done successfully, now the additional initializations should happen
428 m_xWrappedObject
->setClientSite( m_xClientSite
);
429 if ( m_xParent
.is() )
431 uno::Reference
< container::XChild
> xChild( m_xWrappedObject
, uno::UNO_QUERY
);
433 xChild
->setParent( m_xParent
);
442 void SAL_CALL
OleEmbeddedObject::changeState( sal_Int32 nNewState
)
444 // begin wrapping related part ====================
445 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
446 if ( xWrappedObject
.is() )
448 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
449 xWrappedObject
->changeState( nNewState
);
452 // end wrapping related part ====================
454 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
457 throw lang::DisposedException(); // TODO
459 if ( m_nObjectState
== -1 )
460 throw embed::WrongStateException( "The object has no persistence!",
461 static_cast< ::cppu::OWeakObject
* >(this) );
463 // in case the object is already in requested state
464 if ( m_nObjectState
== nNewState
)
468 if ( m_pOleComponent
)
470 if ( m_nTargetState
!= -1 )
472 // means that the object is currently trying to reach the target state
473 throw embed::StateChangeInProgressException( OUString(),
474 uno::Reference
< uno::XInterface
>(),
478 TargetStateControl_Impl
aControl( m_nTargetState
, nNewState
);
480 // TODO: additional verbs can be a problem, since nobody knows how the object
481 // will behave after activation
483 sal_Int32 nOldState
= m_nObjectState
;
485 StateChangeNotification_Impl( true, nOldState
, nNewState
);
490 if ( nNewState
== embed::EmbedStates::LOADED
)
492 // This means just closing of the current object
493 // If component can not be closed the object stays in loaded state
494 // and it holds reference to "incomplete" component
495 // If the object is switched to running state later
496 // the component will become "complete"
498 // the loaded state must be set before, because of notifications!
499 m_nObjectState
= nNewState
;
502 VerbExecutionControllerGuard
aVerbGuard( m_aVerbExecutionController
);
503 m_pOleComponent
->CloseObject();
507 StateChangeNotification_Impl( false, nOldState
, m_nObjectState
);
510 else if ( nNewState
== embed::EmbedStates::RUNNING
|| nNewState
== embed::EmbedStates::ACTIVE
)
512 if ( m_nObjectState
== embed::EmbedStates::LOADED
)
514 // if the target object is in loaded state and a different state is specified
515 // as a new one the object first must be switched to running state.
517 // the component can exist already in nonrunning state
518 // it can be created during loading to detect type of object
519 CreateOleComponentAndLoad_Impl( m_pOleComponent
);
521 SwitchComponentToRunningState_Impl();
522 m_nObjectState
= embed::EmbedStates::RUNNING
;
524 StateChangeNotification_Impl( false, nOldState
, m_nObjectState
);
527 if ( m_pOleComponent
&& m_bHasSizeToSet
)
531 m_pOleComponent
->SetExtent( m_aSizeToSet
, m_nAspectToSet
);
532 m_bHasSizeToSet
= false;
534 catch( const uno::Exception
& ) {}
538 if ( m_nObjectState
== nNewState
)
542 // so now the object is either switched from Active to Running state or viceversa
543 // the notification about object state change will be done asynchronously
544 if ( m_nObjectState
== embed::EmbedStates::RUNNING
&& nNewState
== embed::EmbedStates::ACTIVE
)
546 // execute OPEN verb, if object does not reach active state it is an object's problem
548 m_pOleComponent
->ExecuteVerb( embed::EmbedVerbs::MS_OLEVERB_OPEN
);
551 // some objects do not allow to set the size even in running state
552 if ( m_pOleComponent
&& m_bHasSizeToSet
)
556 m_pOleComponent
->SetExtent( m_aSizeToSet
, m_nAspectToSet
);
557 m_bHasSizeToSet
= false;
559 catch( uno::Exception
& ) {}
563 m_nObjectState
= nNewState
;
565 else if ( m_nObjectState
== embed::EmbedStates::ACTIVE
&& nNewState
== embed::EmbedStates::RUNNING
)
568 m_pOleComponent
->CloseObject();
569 m_pOleComponent
->RunObject(); // Should not fail, the object already was active
571 m_nObjectState
= nNewState
;
575 throw embed::UnreachableStateException();
579 throw embed::UnreachableStateException();
581 catch( uno::Exception
& )
584 StateChangeNotification_Impl( false, nOldState
, m_nObjectState
);
591 throw embed::UnreachableStateException();
596 uno::Sequence
< sal_Int32
> SAL_CALL
OleEmbeddedObject::getReachableStates()
598 // begin wrapping related part ====================
599 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
600 if ( xWrappedObject
.is() )
602 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
603 return xWrappedObject
->getReachableStates();
605 // end wrapping related part ====================
607 ::osl::MutexGuard
aGuard( m_aMutex
);
609 throw lang::DisposedException(); // TODO
611 if ( m_nObjectState
== -1 )
612 throw embed::WrongStateException( "The object has no persistence!",
613 static_cast< ::cppu::OWeakObject
* >(this) );
616 if ( m_pOleComponent
)
618 if ( m_nObjectState
== embed::EmbedStates::LOADED
)
620 // the list of supported verbs can be retrieved only when object is in running state
621 throw embed::NeedsRunningStateException(); // TODO:
624 // the list of states can only be guessed based on standard verbs,
625 // since there is no way to detect what additional verbs do
626 return GetReachableStatesList_Impl( m_pOleComponent
->GetVerbList() );
631 return uno::Sequence
< sal_Int32
>();
636 sal_Int32 SAL_CALL
OleEmbeddedObject::getCurrentState()
638 // begin wrapping related part ====================
639 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
640 if ( xWrappedObject
.is() )
642 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
643 return xWrappedObject
->getCurrentState();
645 // end wrapping related part ====================
647 ::osl::MutexGuard
aGuard( m_aMutex
);
649 throw lang::DisposedException(); // TODO
651 if ( m_nObjectState
== -1 )
652 throw embed::WrongStateException( "The object has no persistence!",
653 static_cast< ::cppu::OWeakObject
* >(this) );
655 // TODO: Shouldn't we ask object? ( I guess no )
656 return m_nObjectState
;
661 bool lcl_CopyStream(const uno::Reference
<io::XInputStream
>& xIn
, const uno::Reference
<io::XOutputStream
>& xOut
, sal_Int32 nMaxCopy
= SAL_MAX_INT32
)
666 const sal_Int32 nChunkSize
= 4096;
667 uno::Sequence
< sal_Int8
> aData(nChunkSize
);
668 sal_Int32 nTotalRead
= 0;
672 if (nTotalRead
+ aData
.getLength() > nMaxCopy
)
674 aData
.realloc(nMaxCopy
- nTotalRead
);
676 nRead
= xIn
->readBytes(aData
, aData
.getLength());
678 xOut
->writeBytes(aData
);
679 } while (nRead
== nChunkSize
&& nTotalRead
<= nMaxCopy
);
680 return nTotalRead
!= 0;
683 uno::Reference
< io::XStream
> lcl_GetExtractedStream( OUString
& rUrl
,
684 const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xFactory
,
685 const css::uno::Reference
< css::io::XStream
>& xObjectStream
)
687 uno::Reference
<beans::XPropertySet
> xNativeTempFile(
688 io::TempFile::create(comphelper::getComponentContext(xFactory
)),
689 uno::UNO_QUERY_THROW
);
690 uno::Reference
< io::XStream
> xStream(xNativeTempFile
, uno::UNO_QUERY_THROW
);
692 uno::Sequence
< uno::Any
> aArgs( 2 );
693 aArgs
[0] <<= xObjectStream
;
694 aArgs
[1] <<= true; // do not create copy
695 uno::Reference
< container::XNameContainer
> xNameContainer(
696 xFactory
->createInstanceWithArguments(
697 "com.sun.star.embed.OLESimpleStorage",
698 aArgs
), uno::UNO_QUERY_THROW
);
700 //various stream names that can contain the real document contents for
701 //this object in a straightforward direct way
702 static const OUStringLiteral aStreamNames
[] =
709 "PowerPoint Document"
712 bool bCopied
= false;
713 for (size_t i
= 0; i
< SAL_N_ELEMENTS(aStreamNames
) && !bCopied
; ++i
)
715 uno::Reference
<io::XStream
> xEmbeddedFile
;
718 xNameContainer
->getByName(aStreamNames
[i
]) >>= xEmbeddedFile
;
720 catch (const container::NoSuchElementException
&)
724 bCopied
= xEmbeddedFile
.is() && lcl_CopyStream(xEmbeddedFile
->getInputStream(), xStream
->getOutputStream());
729 uno::Reference
< io::XStream
> xOle10Native
;
732 xNameContainer
->getByName("\1Ole10Native") >>= xOle10Native
;
734 catch (container::NoSuchElementException
const&)
738 if (xOle10Native
.is())
740 const uno::Reference
<io::XInputStream
> xIn
= xOle10Native
->getInputStream();
741 xIn
->skipBytes(4); //size of the entire stream minus 4 bytes
742 xIn
->skipBytes(2); //word that represent the directory type
743 uno::Sequence
< sal_Int8
> aData(1);
747 nRead
= xIn
->readBytes(aData
, 1);
748 } while (nRead
== 1 && aData
[0] != 0); // file name plus extension of the attachment null terminated
751 nRead
= xIn
->readBytes(aData
, 1);
752 } while (nRead
== 1 && aData
[0] != 0); // Fully Qualified File name with extension
753 xIn
->skipBytes(1); //single byte
754 xIn
->skipBytes(1); //single byte
755 xIn
->skipBytes(2); //Word that represent the directory type
756 xIn
->skipBytes(4); //len of string
759 nRead
= xIn
->readBytes(aData
, 1);
760 } while (nRead
== 1 && aData
[0] != 0); // Actual string representing the file path
761 uno::Sequence
< sal_Int8
> aLenData(4);
762 xIn
->readBytes(aLenData
, 4); //len of attachment
763 sal_uInt32 nLen
= static_cast<sal_uInt32
>(
764 (aLenData
[0] & 0xFF) |
765 ((aLenData
[1] & 0xFF) << 8) |
766 ((aLenData
[2] & 0xFF) << 16) |
767 ((aLenData
[3] & 0xFF) << 24));
769 bCopied
= lcl_CopyStream(xIn
, xStream
->getOutputStream(), nLen
);
773 uno::Reference
< io::XSeekable
> xSeekableStor(xObjectStream
, uno::UNO_QUERY
);
774 if (xSeekableStor
.is())
775 xSeekableStor
->seek(0);
778 bCopied
= lcl_CopyStream(xObjectStream
->getInputStream(), xStream
->getOutputStream());
782 xNativeTempFile
->setPropertyValue("RemoveFile",
783 uno::makeAny(false));
784 uno::Any aUrl
= xNativeTempFile
->getPropertyValue("Uri");
787 xNativeTempFile
.clear();
789 uno::Reference
< ucb::XSimpleFileAccess3
> xSimpleFileAccess(
790 ucb::SimpleFileAccess::create( comphelper::getComponentContext(xFactory
) ) );
792 xSimpleFileAccess
->setReadOnly(rUrl
, true);
796 xNativeTempFile
->setPropertyValue("RemoveFile",
803 //Dump the objects content to a tempfile, just the "CONTENTS" stream if
804 //there is one for non-compound documents, otherwise the whole content.
805 //On success a file is returned which must be removed by the caller
806 OUString
lcl_ExtractObject(const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xFactory
,
807 const css::uno::Reference
< css::io::XStream
>& xObjectStream
)
811 // the solution is only active for Unix systems
813 lcl_GetExtractedStream(sUrl
, xFactory
, xObjectStream
);
816 (void) xObjectStream
;
821 uno::Reference
< io::XStream
> lcl_ExtractObjectStream( const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xFactory
,
822 const css::uno::Reference
< css::io::XStream
>& xObjectStream
)
825 return lcl_GetExtractedStream( sUrl
, xFactory
, xObjectStream
);
830 void SAL_CALL
OleEmbeddedObject::doVerb( sal_Int32 nVerbID
)
832 // begin wrapping related part ====================
833 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
834 if ( xWrappedObject
.is() )
836 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
837 xWrappedObject
->doVerb(embed::EmbedVerbs::MS_OLEVERB_OPEN
); // open content in the window not in-place
840 // end wrapping related part ====================
842 ::osl::ResettableMutexGuard
aGuard( m_aMutex
);
844 throw lang::DisposedException(); // TODO
846 if ( m_nObjectState
== -1 )
847 throw embed::WrongStateException( "The object has no persistence!",
848 static_cast< ::cppu::OWeakObject
* >(this) );
851 if ( m_pOleComponent
)
853 sal_Int32 nOldState
= m_nObjectState
;
855 // TODO/LATER detect target state here and do a notification
856 // StateChangeNotification_Impl( sal_True, nOldState, nNewState );
857 if ( m_nObjectState
== embed::EmbedStates::LOADED
)
859 // if the target object is in loaded state
860 // it must be switched to running state to execute verb
862 changeState( embed::EmbedStates::RUNNING
);
867 if ( !m_pOleComponent
)
868 throw uno::RuntimeException();
870 // ==== the STAMPIT related solution =============================
871 m_aVerbExecutionController
.StartControlExecution();
874 m_pOleComponent
->ExecuteVerb( nVerbID
);
875 m_pOleComponent
->SetHostName( OUString(), m_aContainerName
);
877 // ==== the STAMPIT related solution =============================
878 bool bModifiedOnExecution
= m_aVerbExecutionController
.EndControlExecution_WasModified();
880 // this workaround is implemented for STAMPIT object
881 // if object was modified during verb execution it is saved here
882 if ( bModifiedOnExecution
&& m_pOleComponent
->IsDirty() )
886 catch( uno::Exception
& )
888 // ==== the STAMPIT related solution =============================
889 m_aVerbExecutionController
.EndControlExecution_WasModified();
893 StateChangeNotification_Impl( false, nOldState
, m_nObjectState
);
904 throw embed::UnreachableStateException();
907 // the workaround verb to show the object in case no server is available
909 // if it is possible, the object will be converted to OOo format
910 if ( !m_bTriedConversion
)
912 m_bTriedConversion
= true;
913 if ( TryToConvertToOOo( m_xObjectStream
) )
915 changeState( embed::EmbedStates::ACTIVE
);
920 if ( !m_xOwnView
.is() && m_xObjectStream
.is() && m_aFilterName
!= "Text" )
923 uno::Reference
< io::XSeekable
> xSeekable( m_xObjectStream
, uno::UNO_QUERY
);
924 if ( xSeekable
.is() )
925 xSeekable
->seek( 0 );
927 m_xOwnView
= new OwnView_Impl( m_xFactory
, m_xObjectStream
->getInputStream() );
929 catch( uno::RuntimeException
& )
933 catch (uno::Exception
const&)
935 TOOLS_WARN_EXCEPTION("embeddedobj.ole", "OleEmbeddedObject::doVerb: -9 fallback path:");
939 // it may be the OLE Storage, try to extract stream
940 if ( !m_xOwnView
.is() && m_xObjectStream
.is() && m_aFilterName
== "Text" )
942 uno::Reference
< io::XStream
> xStream
= lcl_ExtractObjectStream( m_xFactory
, m_xObjectStream
);
944 if ( TryToConvertToOOo( xStream
) )
946 changeState( embed::EmbedStates::ACTIVE
);
951 if (!m_xOwnView
.is() || !m_xOwnView
->Open())
953 //Make a RO copy and see if the OS can find something to at
954 //least display the content for us
955 if (m_aTempDumpURL
.isEmpty())
956 m_aTempDumpURL
= lcl_ExtractObject(m_xFactory
, m_xObjectStream
);
958 if (m_aTempDumpURL
.isEmpty())
959 throw embed::UnreachableStateException();
961 uno::Reference
< css::system::XSystemShellExecute
> xSystemShellExecute(
962 css::system::SystemShellExecute::create(comphelper::getComponentContext(m_xFactory
)) );
963 xSystemShellExecute
->execute(m_aTempDumpURL
, OUString(), css::system::SystemShellExecuteFlags::URIS_ONLY
);
971 uno::Sequence
< embed::VerbDescriptor
> SAL_CALL
OleEmbeddedObject::getSupportedVerbs()
973 // begin wrapping related part ====================
974 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
975 if ( xWrappedObject
.is() )
977 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
978 return xWrappedObject
->getSupportedVerbs();
980 // end wrapping related part ====================
982 ::osl::MutexGuard
aGuard( m_aMutex
);
984 throw lang::DisposedException(); // TODO
986 if ( m_nObjectState
== -1 )
987 throw embed::WrongStateException( "The object has no persistence!",
988 static_cast< ::cppu::OWeakObject
* >(this) );
990 if ( m_pOleComponent
)
992 // registry could be used in this case
993 // if ( m_nObjectState == embed::EmbedStates::LOADED )
995 // // the list of supported verbs can be retrieved only when object is in running state
996 // throw embed::NeedsRunningStateException(); // TODO:
999 return m_pOleComponent
->GetVerbList();
1004 return uno::Sequence
< embed::VerbDescriptor
>();
1009 void SAL_CALL
OleEmbeddedObject::setClientSite(
1010 const uno::Reference
< embed::XEmbeddedClient
>& xClient
)
1012 // begin wrapping related part ====================
1013 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
1014 if ( xWrappedObject
.is() )
1016 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1017 xWrappedObject
->setClientSite( xClient
);
1020 // end wrapping related part ====================
1022 ::osl::MutexGuard
aGuard( m_aMutex
);
1024 throw lang::DisposedException(); // TODO
1026 if ( m_xClientSite
!= xClient
)
1028 if ( m_nObjectState
!= embed::EmbedStates::LOADED
&& m_nObjectState
!= embed::EmbedStates::RUNNING
)
1029 throw embed::WrongStateException(
1030 "The client site can not be set currently!",
1031 static_cast< ::cppu::OWeakObject
* >(this) );
1033 m_xClientSite
= xClient
;
1038 uno::Reference
< embed::XEmbeddedClient
> SAL_CALL
OleEmbeddedObject::getClientSite()
1040 // begin wrapping related part ====================
1041 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
1042 if ( xWrappedObject
.is() )
1044 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1045 return xWrappedObject
->getClientSite();
1047 // end wrapping related part ====================
1049 ::osl::MutexGuard
aGuard( m_aMutex
);
1051 throw lang::DisposedException(); // TODO
1053 if ( m_nObjectState
== -1 )
1054 throw embed::WrongStateException( "The object has no persistence!",
1055 static_cast< ::cppu::OWeakObject
* >(this) );
1057 return m_xClientSite
;
1061 void SAL_CALL
OleEmbeddedObject::update()
1063 // begin wrapping related part ====================
1064 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
1065 if ( xWrappedObject
.is() )
1067 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1068 xWrappedObject
->update();
1071 // end wrapping related part ====================
1073 ::osl::MutexGuard
aGuard( m_aMutex
);
1075 throw lang::DisposedException(); // TODO
1077 if ( m_nObjectState
== -1 )
1078 throw embed::WrongStateException( "The object has no persistence!",
1079 static_cast< ::cppu::OWeakObject
* >(this) );
1081 if ( m_nUpdateMode
== embed::EmbedUpdateModes::EXPLICIT_UPDATE
)
1083 // TODO: update view representation
1087 // the object must be up to date
1088 SAL_WARN_IF( m_nUpdateMode
!= embed::EmbedUpdateModes::ALWAYS_UPDATE
, "embeddedobj.ole", "Unknown update mode!" );
1093 void SAL_CALL
OleEmbeddedObject::setUpdateMode( sal_Int32 nMode
)
1095 // begin wrapping related part ====================
1096 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
1097 if ( xWrappedObject
.is() )
1099 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1100 xWrappedObject
->setUpdateMode( nMode
);
1103 // end wrapping related part ====================
1105 ::osl::MutexGuard
aGuard( m_aMutex
);
1107 throw lang::DisposedException(); // TODO
1109 if ( m_nObjectState
== -1 )
1110 throw embed::WrongStateException( "The object has no persistence!",
1111 static_cast< ::cppu::OWeakObject
* >(this) );
1113 OSL_ENSURE( nMode
== embed::EmbedUpdateModes::ALWAYS_UPDATE
1114 || nMode
== embed::EmbedUpdateModes::EXPLICIT_UPDATE
,
1115 "Unknown update mode!" );
1116 m_nUpdateMode
= nMode
;
1120 sal_Int64 SAL_CALL
OleEmbeddedObject::getStatus( sal_Int64
1124 // begin wrapping related part ====================
1125 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
1126 if ( xWrappedObject
.is() )
1128 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1129 return xWrappedObject
->getStatus( nAspect
);
1131 // end wrapping related part ====================
1133 ::osl::MutexGuard
aGuard( m_aMutex
);
1135 throw lang::DisposedException(); // TODO
1137 if ( m_nObjectState
== -1 )
1138 throw embed::WrongStateException( "The object must be in running state!",
1139 static_cast< ::cppu::OWeakObject
* >(this) );
1141 sal_Int64 nResult
= 0;
1144 if ( m_bGotStatus
&& m_nStatusAspect
== nAspect
)
1145 nResult
= m_nStatus
;
1146 else if ( m_pOleComponent
)
1149 m_nStatus
= m_pOleComponent
->GetMiscStatus( nAspect
);
1150 m_nStatusAspect
= nAspect
;
1151 m_bGotStatus
= true;
1152 nResult
= m_nStatus
;
1156 // this implementation needs size to be provided after object loading/creating to work in optimal way
1157 return ( nResult
| embed::EmbedMisc::EMBED_NEEDSSIZEONLOAD
);
1161 void SAL_CALL
OleEmbeddedObject::setContainerName( const OUString
& sName
)
1163 // begin wrapping related part ====================
1164 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
1165 if ( xWrappedObject
.is() )
1167 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1168 xWrappedObject
->setContainerName( sName
);
1171 // end wrapping related part ====================
1173 ::osl::MutexGuard
aGuard( m_aMutex
);
1175 throw lang::DisposedException(); // TODO
1177 m_aContainerName
= sName
;
1181 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */