Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/embeddedobj/source/msole/oleembed.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
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/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
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 .
18
 */
19
20
#include <sal/config.h>
21
22
#include <string_view>
23
24
#include <oleembobj.hxx>
25
#include <com/sun/star/embed/EmbedStates.hpp>
26
#include <com/sun/star/embed/EmbedVerbs.hpp>
27
#include <com/sun/star/embed/UnreachableStateException.hpp>
28
#include <com/sun/star/embed/XStorage.hpp>
29
#include <com/sun/star/embed/ElementModes.hpp>
30
#include <com/sun/star/embed/EmbedUpdateModes.hpp>
31
#include <com/sun/star/embed/NeedsRunningStateException.hpp>
32
#include <com/sun/star/embed/StateChangeInProgressException.hpp>
33
#include <com/sun/star/embed/EmbedMisc.hpp>
34
#include <com/sun/star/embed/XEmbedObjectCreator.hpp>
35
#include <com/sun/star/io/TempFile.hpp>
36
#include <com/sun/star/io/XSeekable.hpp>
37
#include <com/sun/star/lang/DisposedException.hpp>
38
#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
39
#include <com/sun/star/beans/NamedValue.hpp>
40
#include <com/sun/star/beans/XPropertySet.hpp>
41
#include <com/sun/star/frame/XLoadable.hpp>
42
#include <com/sun/star/document/XStorageBasedDocument.hpp>
43
#include <com/sun/star/ucb/SimpleFileAccess.hpp>
44
#include <com/sun/star/container/XNameAccess.hpp>
45
#include <com/sun/star/container/XNameContainer.hpp>
46
#include <com/sun/star/system/SystemShellExecute.hpp>
47
#include <com/sun/star/system/SystemShellExecuteFlags.hpp>
48
49
#include <cppuhelper/exc_hlp.hxx>
50
#include <comphelper/multicontainer2.hxx>
51
#include <comphelper/mimeconfighelper.hxx>
52
#include <comphelper/propertyvalue.hxx>
53
#include <sal/log.hxx>
54
#include <comphelper/diagnose_ex.hxx>
55
#include <officecfg/Office/Common.hxx>
56
57
#include <targetstatecontrol.hxx>
58
59
#include "ownview.hxx"
60
61
#if defined(_WIN32)
62
#include "olecomponent.hxx"
63
#endif
64
65
using namespace ::com::sun::star;
66
67
#ifdef _WIN32
68
69
void OleEmbeddedObject::SwitchComponentToRunningState_Impl(osl::ResettableMutexGuard& guard)
70
{
71
    if ( !m_pOleComponent )
72
    {
73
        throw embed::UnreachableStateException();
74
    }
75
    try
76
    {
77
        m_pOleComponent->RunObject();
78
    }
79
    catch( const embed::UnreachableStateException& )
80
    {
81
        GetRidOfComponent(&guard);
82
        throw;
83
    }
84
    catch( const embed::WrongStateException& )
85
    {
86
        GetRidOfComponent(&guard);
87
        throw;
88
    }
89
}
90
91
92
uno::Sequence< sal_Int32 > OleEmbeddedObject::GetReachableStatesList_Impl(
93
                                                        const uno::Sequence< embed::VerbDescriptor >& aVerbList )
94
{
95
    uno::Sequence< sal_Int32 > aStates { embed::EmbedStates::LOADED, embed::EmbedStates::RUNNING };
96
    for ( embed::VerbDescriptor const & vd : aVerbList )
97
        if ( vd.VerbID == embed::EmbedVerbs::MS_OLEVERB_OPEN )
98
        {
99
            aStates.realloc(3);
100
            aStates.getArray()[2] = embed::EmbedStates::ACTIVE;
101
            break;
102
        }
103
104
    return aStates;
105
}
106
107
108
uno::Sequence< sal_Int32 > OleEmbeddedObject::GetIntermediateVerbsSequence_Impl( sal_Int32 nNewState )
109
{
110
    SAL_WARN_IF( m_nObjectState == embed::EmbedStates::LOADED, "embeddedobj.ole", "Loaded object is switched to running state without verbs using!" );
111
112
    // actually there will be only one verb
113
    if ( m_nObjectState == embed::EmbedStates::RUNNING && nNewState == embed::EmbedStates::ACTIVE )
114
    {
115
        return { embed::EmbedVerbs::MS_OLEVERB_OPEN };
116
    }
117
118
    return uno::Sequence< sal_Int32 >();
119
}
120
#endif
121
122
void OleEmbeddedObject::MoveListeners()
123
0
{
124
0
    if ( !m_pInterfaceContainer )
125
0
        return;
126
127
    // move state change listeners
128
0
    {
129
0
        comphelper::OInterfaceContainerHelper2* pStateChangeContainer =
130
0
            m_pInterfaceContainer->getContainer( cppu::UnoType<embed::XStateChangeListener>::get());
131
0
        if ( pStateChangeContainer != nullptr )
132
0
        {
133
0
            if ( m_xWrappedObject.is() )
134
0
            {
135
0
                comphelper::OInterfaceIteratorHelper2 pIterator( *pStateChangeContainer );
136
0
                while ( pIterator.hasMoreElements() )
137
0
                {
138
0
                    try
139
0
                    {
140
0
                        m_xWrappedObject->addStateChangeListener( static_cast<embed::XStateChangeListener*>(pIterator.next()) );
141
0
                    }
142
0
                    catch( const uno::RuntimeException& )
143
0
                    {
144
0
                        pIterator.remove();
145
0
                    }
146
0
                }
147
0
            }
148
0
        }
149
0
    }
150
151
    // move event listeners
152
0
    {
153
0
        comphelper::OInterfaceContainerHelper2* pEventContainer =
154
0
            m_pInterfaceContainer->getContainer( cppu::UnoType<document::XEventListener>::get());
155
0
        if ( pEventContainer != nullptr )
156
0
        {
157
0
            if ( m_xWrappedObject.is() )
158
0
            {
159
0
                comphelper::OInterfaceIteratorHelper2 pIterator( *pEventContainer );
160
0
                while ( pIterator.hasMoreElements() )
161
0
                {
162
0
                    try
163
0
                    {
164
0
                        m_xWrappedObject->addEventListener( static_cast<document::XEventListener*>(pIterator.next()) );
165
0
                    }
166
0
                    catch( const uno::RuntimeException& )
167
0
                    {
168
0
                        pIterator.remove();
169
0
                    }
170
0
                }
171
0
            }
172
0
        }
173
0
    }
174
175
    // move close listeners
176
0
    {
177
0
        comphelper::OInterfaceContainerHelper2* pCloseContainer =
178
0
            m_pInterfaceContainer->getContainer( cppu::UnoType<util::XCloseListener>::get());
179
0
        if ( pCloseContainer != nullptr )
180
0
        {
181
0
            if ( m_xWrappedObject.is() )
182
0
            {
183
0
                comphelper::OInterfaceIteratorHelper2 pIterator( *pCloseContainer );
184
0
                while ( pIterator.hasMoreElements() )
185
0
                {
186
0
                    try
187
0
                    {
188
0
                        m_xWrappedObject->addCloseListener( static_cast<util::XCloseListener*>(pIterator.next()) );
189
0
                    }
190
0
                    catch( const uno::RuntimeException& )
191
0
                    {
192
0
                        pIterator.remove();
193
0
                    }
194
0
                }
195
0
            }
196
0
        }
197
0
    }
198
199
0
    m_pInterfaceContainer.reset();
200
0
}
201
202
203
uno::Reference< embed::XStorage > OleEmbeddedObject::CreateTemporarySubstorage( OUString& o_aStorageName )
204
0
{
205
0
    uno::Reference< embed::XStorage > xResult;
206
207
0
    for ( sal_Int32 nInd = 0; nInd < 32000 && !xResult.is(); nInd++ )
208
0
    {
209
0
        OUString aName = OUString::number( nInd ) + "TMPSTOR" + m_aEntryName;
210
0
        if ( !m_xParentStorage->hasByName( aName ) )
211
0
        {
212
0
            xResult = m_xParentStorage->openStorageElement( aName, embed::ElementModes::READWRITE );
213
0
            o_aStorageName = aName;
214
0
        }
215
0
    }
216
217
0
    if ( !xResult.is() )
218
0
    {
219
0
        o_aStorageName.clear();
220
0
        throw uno::RuntimeException(u"Failed to create temporary storage for OLE embed object"_ustr);
221
0
    }
222
223
0
    return xResult;
224
0
}
225
226
227
OUString OleEmbeddedObject::MoveToTemporarySubstream()
228
0
{
229
0
    OUString aResult;
230
0
    for ( sal_Int32 nInd = 0; nInd < 32000 && aResult.isEmpty(); nInd++ )
231
0
    {
232
0
        OUString aName = OUString::number( nInd ) + "TMPSTREAM" + m_aEntryName;
233
0
        if ( !m_xParentStorage->hasByName( aName ) )
234
0
        {
235
0
            m_xParentStorage->renameElement( m_aEntryName, aName );
236
0
            aResult = aName;
237
0
        }
238
0
    }
239
240
0
    if ( aResult.isEmpty() )
241
0
        throw uno::RuntimeException(u"Failed to rename temporary storage for OLE embed object"_ustr);
242
243
0
    return aResult;
244
0
}
245
246
247
bool OleEmbeddedObject::TryToConvertToOOo( const uno::Reference< io::XStream >& xStream )
248
0
{
249
0
    bool bResult = false;
250
251
0
    OUString aStorageName;
252
0
    OUString aTmpStreamName;
253
0
    sal_Int32 nStep = 0;
254
255
0
    if ( m_pOleComponent || m_bReadOnly )
256
0
        return false;
257
258
0
    try
259
0
    {
260
0
        changeState( embed::EmbedStates::LOADED );
261
262
        // the stream must be seekable
263
0
        uno::Reference< io::XSeekable > xSeekable( xStream, uno::UNO_QUERY_THROW );
264
0
        xSeekable->seek( 0 );
265
0
        m_aFilterName = OwnView_Impl::GetFilterNameFromExtentionAndInStream( m_xContext, std::u16string_view(), xStream->getInputStream() );
266
267
0
        if ( !m_aFilterName.isEmpty()
268
0
          && ( m_aFilterName == "Calc MS Excel 2007 XML" || m_aFilterName == "Impress MS PowerPoint 2007 XML" || m_aFilterName == "MS Word 2007 XML"
269
0
              || m_aFilterName == "MS Excel 97 Vorlage/Template" || m_aFilterName == "MS Word 97 Vorlage" ) )
270
0
        {
271
0
            uno::Reference< container::XNameAccess > xFilterFactory(
272
0
                m_xContext->getServiceManager()->createInstanceWithContext(u"com.sun.star.document.FilterFactory"_ustr, m_xContext),
273
0
                uno::UNO_QUERY_THROW );
274
275
0
            OUString aDocServiceName;
276
0
            uno::Any aFilterAnyData = xFilterFactory->getByName( m_aFilterName );
277
0
            uno::Sequence< beans::PropertyValue > aFilterData;
278
0
            if ( aFilterAnyData >>= aFilterData )
279
0
            {
280
0
                for (beans::PropertyValue const& prop : aFilterData)
281
0
                    if ( prop.Name == "DocumentService" )
282
0
                        prop.Value >>= aDocServiceName;
283
0
            }
284
285
0
            if ( !aDocServiceName.isEmpty() )
286
0
            {
287
                // create the model
288
0
                uno::Sequence< uno::Any > aArguments{ uno::Any(
289
0
                    beans::NamedValue( u"EmbeddedObject"_ustr, uno::Any( true ))) };
290
291
0
                uno::Reference< util::XCloseable > xDocument( m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext( aDocServiceName, aArguments, m_xContext ), uno::UNO_QUERY_THROW );
292
0
                uno::Reference< frame::XLoadable > xLoadable( xDocument, uno::UNO_QUERY_THROW );
293
0
                uno::Reference< document::XStorageBasedDocument > xStorDoc( xDocument, uno::UNO_QUERY_THROW );
294
295
                // let the model behave as embedded one
296
0
                uno::Reference< frame::XModel > xModel( xDocument, uno::UNO_QUERY_THROW );
297
0
                uno::Sequence< beans::PropertyValue > aSeq{ comphelper::makePropertyValue(
298
0
                    u"SetEmbedded"_ustr, true) };
299
0
                xModel->attachResource( OUString(), aSeq );
300
301
                // load the model from the stream
302
0
                uno::Sequence< beans::PropertyValue > aArgs{
303
0
                    comphelper::makePropertyValue(u"HierarchicalDocumentName"_ustr, m_aEntryName),
304
0
                    comphelper::makePropertyValue(u"ReadOnly"_ustr, true),
305
0
                    comphelper::makePropertyValue(u"FilterName"_ustr, m_aFilterName),
306
0
                    comphelper::makePropertyValue(u"URL"_ustr, u"private:stream"_ustr),
307
0
                    comphelper::makePropertyValue(u"InputStream"_ustr, xStream->getInputStream())
308
0
                };
309
310
0
                xSeekable->seek( 0 );
311
0
                xLoadable->load( aArgs );
312
313
                // the model is successfully loaded, create a new storage and store the model to the storage
314
0
                uno::Reference< embed::XStorage > xTmpStorage = CreateTemporarySubstorage( aStorageName );
315
0
                xStorDoc->storeToStorage( xTmpStorage, uno::Sequence< beans::PropertyValue >() );
316
0
                xDocument->close( true );
317
0
                uno::Reference< beans::XPropertySet > xStorProps( xTmpStorage, uno::UNO_QUERY_THROW );
318
0
                OUString aMediaType;
319
0
                xStorProps->getPropertyValue(u"MediaType"_ustr) >>= aMediaType;
320
0
                xTmpStorage->dispose();
321
322
                // look for the related embedded object factory
323
0
                ::comphelper::MimeConfigurationHelper aConfigHelper( m_xContext );
324
0
                OUString aEmbedFactory;
325
0
                if ( !aMediaType.isEmpty() )
326
0
                    aEmbedFactory = aConfigHelper.GetFactoryNameByMediaType( aMediaType );
327
328
0
                if ( aEmbedFactory.isEmpty() )
329
0
                    throw uno::RuntimeException(u"Failed to get OLE embedded object factory"_ustr);
330
331
0
                uno::Reference< uno::XInterface > xFact = m_xContext->getServiceManager()->createInstanceWithContext( aEmbedFactory, m_xContext );
332
333
0
                uno::Reference< embed::XEmbedObjectCreator > xEmbCreator( xFact, uno::UNO_QUERY_THROW );
334
335
                // now the object should be adjusted to become the wrapper
336
0
                nStep = 1;
337
0
                uno::Reference< lang::XComponent > xComp( m_xObjectStream, uno::UNO_QUERY_THROW );
338
0
                xComp->dispose();
339
0
                m_xObjectStream.clear();
340
0
                m_nObjectState = -1;
341
342
0
                nStep = 2;
343
0
                aTmpStreamName = MoveToTemporarySubstream();
344
345
0
                nStep = 3;
346
0
                m_xParentStorage->renameElement( aStorageName, m_aEntryName );
347
348
0
                nStep = 4;
349
0
                m_xWrappedObject.set( xEmbCreator->createInstanceInitFromEntry( m_xParentStorage, m_aEntryName, uno::Sequence< beans::PropertyValue >(), uno::Sequence< beans::PropertyValue >() ), uno::UNO_QUERY_THROW );
350
351
                // remember parent document name to show in the title bar
352
0
                m_xWrappedObject->setContainerName( m_aContainerName );
353
354
0
                bResult = true; // the change is no more revertable
355
0
                try
356
0
                {
357
0
                    m_xParentStorage->removeElement( aTmpStreamName );
358
0
                }
359
0
                catch( const uno::Exception& )
360
0
                {
361
                    // the success of the removing is not so important
362
0
                }
363
0
            }
364
0
        }
365
0
    }
366
0
    catch( const uno::Exception& )
367
0
    {
368
        // repair the object if necessary
369
0
        switch( nStep )
370
0
        {
371
0
            case 4:
372
0
            case 3:
373
0
            if ( !aTmpStreamName.isEmpty() && aTmpStreamName != m_aEntryName )
374
0
                try
375
0
                {
376
0
                    if ( m_xParentStorage->hasByName( m_aEntryName ) )
377
0
                        m_xParentStorage->removeElement( m_aEntryName );
378
0
                    m_xParentStorage->renameElement( aTmpStreamName, m_aEntryName );
379
0
                }
380
0
                catch ( const uno::Exception& ex )
381
0
                {
382
0
                    css::uno::Any anyEx = cppu::getCaughtException();
383
0
                    try {
384
0
                        close( true );
385
0
                    } catch( const uno::Exception& ) {}
386
387
0
                    m_xParentStorage->dispose(); // ??? the storage has information loss, it should be closed without committing!
388
0
                    throw css::lang::WrappedTargetRuntimeException( ex.Message,
389
0
                                    nullptr, anyEx ); // the repairing is not possible
390
0
                }
391
0
            [[fallthrough]];
392
0
            case 2:
393
0
                try
394
0
                {
395
0
                    m_xObjectStream = m_xParentStorage->openStreamElement( m_aEntryName, m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE );
396
0
                    m_nObjectState = embed::EmbedStates::LOADED;
397
0
                }
398
0
                catch( const uno::Exception& ex )
399
0
                {
400
0
                    css::uno::Any anyEx = cppu::getCaughtException();
401
0
                    try {
402
0
                        close( true );
403
0
                    } catch( const uno::Exception& ) {}
404
405
0
                    throw css::lang::WrappedTargetRuntimeException( ex.Message,
406
0
                                    nullptr, anyEx ); // the repairing is not possible
407
0
                }
408
0
                [[fallthrough]];
409
410
0
            case 1:
411
0
            case 0:
412
0
                if ( !aStorageName.isEmpty() )
413
0
                    try {
414
0
                        m_xParentStorage->removeElement( aStorageName );
415
0
                    } catch( const uno::Exception& ) { SAL_WARN( "embeddedobj.ole", "Can not remove temporary storage!" ); }
416
0
                break;
417
0
        }
418
0
    }
419
420
0
    if ( bResult )
421
0
    {
422
        // the conversion was done successfully, now the additional initializations should happen
423
424
0
        MoveListeners();
425
0
        m_xWrappedObject->setClientSite( m_xClientSite );
426
0
        if ( m_xParent.is() )
427
0
        {
428
0
            uno::Reference< container::XChild > xChild( m_xWrappedObject, uno::UNO_QUERY );
429
0
            if ( xChild.is() )
430
0
                xChild->setParent( m_xParent );
431
0
        }
432
433
0
    }
434
435
0
    return bResult;
436
0
}
437
438
439
void SAL_CALL OleEmbeddedObject::changeState( sal_Int32 nNewState )
440
0
{
441
0
    if ( officecfg::Office::Common::Security::Scripting::DisableActiveContent::get()
442
0
         && nNewState != embed::EmbedStates::LOADED )
443
0
        throw embed::UnreachableStateException();
444
    // begin wrapping related part ====================
445
0
    uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
446
0
    if ( xWrappedObject.is() )
447
0
    {
448
        // the object was converted to OOo embedded object, the current implementation is now only a wrapper
449
0
        xWrappedObject->changeState( nNewState );
450
0
        return;
451
0
    }
452
    // end wrapping related part ====================
453
454
0
    ::osl::ResettableMutexGuard aGuard( m_aMutex );
455
456
0
    if ( m_bDisposed )
457
0
        throw lang::DisposedException(); // TODO
458
459
0
    if ( m_nObjectState == -1 )
460
0
        throw embed::WrongStateException( u"The object has no persistence!"_ustr,
461
0
                                        static_cast< ::cppu::OWeakObject* >(this) );
462
463
    // in case the object is already in requested state
464
0
    if ( m_nObjectState == nNewState )
465
0
        return;
466
467
#ifdef _WIN32
468
    if ( m_pOleComponent )
469
    {
470
        if ( m_nTargetState != -1 )
471
        {
472
            // means that the object is currently trying to reach the target state
473
            throw embed::StateChangeInProgressException( OUString(),
474
                                                        uno::Reference< uno::XInterface >(),
475
                                                        m_nTargetState );
476
        }
477
478
        TargetStateControl_Impl aControl( m_nTargetState, nNewState );
479
480
        // TODO: additional verbs can be a problem, since nobody knows how the object
481
        //       will behave after activation
482
483
        sal_Int32 nOldState = m_nObjectState;
484
        StateChangeNotification_Impl( true, nOldState, nNewState, aGuard );
485
486
        try
487
        {
488
            if ( nNewState == embed::EmbedStates::LOADED )
489
            {
490
                // This means just closing of the current object
491
                // If component can not be closed the object stays in loaded state
492
                // and it holds reference to "incomplete" component
493
                // If the object is switched to running state later
494
                // the component will become "complete"
495
496
                // the loaded state must be set before, because of notifications!
497
                m_nObjectState = nNewState;
498
499
                {
500
                    VerbExecutionControllerGuard aVerbGuard( m_aVerbExecutionController );
501
                    ExecUnlocked([p = m_pOleComponent] { p->CloseObject(); }, aGuard);
502
                }
503
504
                StateChangeNotification_Impl( false, nOldState, m_nObjectState, aGuard );
505
            }
506
            else if ( nNewState == embed::EmbedStates::RUNNING || nNewState == embed::EmbedStates::ACTIVE )
507
            {
508
                if ( m_nObjectState == embed::EmbedStates::LOADED )
509
                {
510
                    // if the target object is in loaded state and a different state is specified
511
                    // as a new one the object first must be switched to running state.
512
513
                    // the component can exist already in nonrunning state
514
                    // it can be created during loading to detect type of object
515
                    CreateOleComponentAndLoad_Impl( m_pOleComponent );
516
517
                    SwitchComponentToRunningState_Impl(aGuard);
518
                    m_nObjectState = embed::EmbedStates::RUNNING;
519
                    StateChangeNotification_Impl( false, nOldState, m_nObjectState, aGuard );
520
521
                    if ( m_pOleComponent && m_bHasSizeToSet )
522
                    {
523
                        try {
524
                            ExecUnlocked([p = m_pOleComponent, s = m_aSizeToSet,
525
                                          a = m_nAspectToSet]() { p->SetExtent(s, a); },
526
                                         aGuard);
527
                            m_bHasSizeToSet = false;
528
                        }
529
                        catch( const uno::Exception& ) {}
530
                    }
531
532
                    if ( m_nObjectState == nNewState )
533
                        return;
534
                }
535
536
                // so now the object is either switched from Active to Running state or viceversa
537
                // the notification about object state change will be done asynchronously
538
                if ( m_nObjectState == embed::EmbedStates::RUNNING && nNewState == embed::EmbedStates::ACTIVE )
539
                {
540
                    // execute OPEN verb, if object does not reach active state it is an object's problem
541
                    ExecUnlocked([p = m_pOleComponent]()
542
                                 { p->ExecuteVerb(embed::EmbedVerbs::MS_OLEVERB_OPEN); },
543
                                 aGuard);
544
545
                    // some objects do not allow to set the size even in running state
546
                    if ( m_pOleComponent && m_bHasSizeToSet )
547
                    {
548
                        try {
549
                            ExecUnlocked([p = m_pOleComponent, s = m_aSizeToSet,
550
                                          a = m_nAspectToSet]() { p->SetExtent(s, a); },
551
                                         aGuard);
552
                            m_bHasSizeToSet = false;
553
                        }
554
                        catch( uno::Exception& ) {}
555
                    }
556
557
                    m_nObjectState = nNewState;
558
                }
559
                else if ( m_nObjectState == embed::EmbedStates::ACTIVE && nNewState == embed::EmbedStates::RUNNING )
560
                {
561
                    ExecUnlocked(
562
                        [p = m_pOleComponent]()
563
                        {
564
                            p->CloseObject();
565
                            p->RunObject(); // Should not fail, the object already was active
566
                        },
567
                        aGuard);
568
                    m_nObjectState = nNewState;
569
                }
570
                else
571
                {
572
                    throw embed::UnreachableStateException();
573
                }
574
            }
575
            else
576
                throw embed::UnreachableStateException();
577
        }
578
        catch( uno::Exception& )
579
        {
580
            StateChangeNotification_Impl( false, nOldState, m_nObjectState, aGuard );
581
            throw;
582
        }
583
    }
584
    else
585
#endif
586
0
    {
587
0
        throw embed::UnreachableStateException();
588
0
    }
589
0
}
590
591
592
uno::Sequence< sal_Int32 > SAL_CALL OleEmbeddedObject::getReachableStates()
593
0
{
594
    // begin wrapping related part ====================
595
0
    uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
596
0
    if ( xWrappedObject.is() )
597
0
    {
598
        // the object was converted to OOo embedded object, the current implementation is now only a wrapper
599
0
        return xWrappedObject->getReachableStates();
600
0
    }
601
    // end wrapping related part ====================
602
603
0
    ::osl::ResettableMutexGuard aGuard( m_aMutex );
604
0
    if ( m_bDisposed )
605
0
        throw lang::DisposedException(); // TODO
606
607
0
    if ( m_nObjectState == -1 )
608
0
        throw embed::WrongStateException( u"The object has no persistence!"_ustr,
609
0
                                        static_cast< ::cppu::OWeakObject* >(this) );
610
611
#ifdef _WIN32
612
    if ( m_pOleComponent )
613
    {
614
        if ( m_nObjectState == embed::EmbedStates::LOADED )
615
        {
616
            // the list of supported verbs can be retrieved only when object is in running state
617
            throw embed::NeedsRunningStateException(); // TODO:
618
        }
619
620
        // the list of states can only be guessed based on standard verbs,
621
        // since there is no way to detect what additional verbs do
622
        // Pass m_pOleComponent to the lambda by copy, to make sure it doesn't depend on possible
623
        // destruction of 'this', while the lock is unset
624
        return GetReachableStatesList_Impl(
625
            ExecUnlocked([p = m_pOleComponent] { return p->GetVerbList(); }, aGuard));
626
    }
627
    else
628
#endif
629
0
    {
630
0
        return uno::Sequence< sal_Int32 >();
631
0
    }
632
0
}
633
634
635
sal_Int32 SAL_CALL OleEmbeddedObject::getCurrentState()
636
0
{
637
    // begin wrapping related part ====================
638
0
    uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
639
0
    if ( xWrappedObject.is() )
640
0
    {
641
        // the object was converted to OOo embedded object, the current implementation is now only a wrapper
642
0
        return xWrappedObject->getCurrentState();
643
0
    }
644
    // end wrapping related part ====================
645
646
0
    ::osl::MutexGuard aGuard( m_aMutex );
647
0
    if ( m_bDisposed )
648
0
        throw lang::DisposedException(); // TODO
649
650
0
    if ( m_nObjectState == -1 )
651
0
        throw embed::WrongStateException( u"The object has no persistence!"_ustr,
652
0
                                        static_cast< ::cppu::OWeakObject* >(this) );
653
654
    // TODO: Shouldn't we ask object? ( I guess no )
655
0
    return m_nObjectState;
656
0
}
657
658
namespace
659
{
660
    bool lcl_CopyStream(const uno::Reference<io::XInputStream>& xIn, const uno::Reference<io::XOutputStream>& xOut, sal_Int32 nMaxCopy = SAL_MAX_INT32)
661
0
    {
662
0
        if (nMaxCopy <= 0)
663
0
            return false;
664
665
0
        const sal_Int32 nChunkSize = 4096;
666
0
        uno::Sequence< sal_Int8 > aData(nChunkSize);
667
0
        sal_Int32 nTotalRead = 0;
668
0
        sal_Int32 nRead;
669
0
        do
670
0
        {
671
0
            if (nTotalRead + aData.getLength() > nMaxCopy)
672
0
            {
673
0
                aData.realloc(nMaxCopy - nTotalRead);
674
0
            }
675
0
            nRead = xIn->readBytes(aData, aData.getLength());
676
0
            nTotalRead += nRead;
677
0
            xOut->writeBytes(aData);
678
0
        } while (nRead == nChunkSize && nTotalRead <= nMaxCopy);
679
0
        return nTotalRead != 0;
680
0
    }
681
682
    uno::Reference < io::XStream > lcl_GetExtractedStream( OUString& rUrl,
683
        const css::uno::Reference< css::uno::XComponentContext >& xContext,
684
        const css::uno::Reference< css::io::XStream >& xObjectStream )
685
0
    {
686
0
        uno::Reference <io::XTempFile> xNativeTempFile(
687
0
            io::TempFile::create(xContext),
688
0
            uno::UNO_SET_THROW);
689
0
        uno::Reference < io::XStream > xStream(xNativeTempFile);
690
691
0
        uno::Sequence< uno::Any > aArgs{ uno::Any(xObjectStream),
692
0
                                         uno::Any(true) }; // do not create copy
693
0
        uno::Reference< container::XNameContainer > xNameContainer(
694
0
            xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
695
0
                u"com.sun.star.embed.OLESimpleStorage"_ustr,
696
0
                aArgs, xContext ), uno::UNO_QUERY_THROW );
697
698
        //various stream names that can contain the real document contents for
699
        //this object in a straightforward direct way
700
0
        static const std::u16string_view aStreamNames[] =
701
0
        {
702
0
            u"CONTENTS",
703
0
            u"Package",
704
0
            u"EmbeddedOdf",
705
0
            u"WordDocument",
706
0
            u"Workbook",
707
0
            u"PowerPoint Document"
708
0
        };
709
710
0
        bool bCopied = false;
711
0
        for (size_t i = 0; i < std::size(aStreamNames) && !bCopied; ++i)
712
0
        {
713
0
            uno::Reference<io::XStream> xEmbeddedFile;
714
0
            try
715
0
            {
716
0
                xNameContainer->getByName(OUString(aStreamNames[i])) >>= xEmbeddedFile;
717
0
            }
718
0
            catch (const container::NoSuchElementException&)
719
0
            {
720
                // ignore
721
0
            }
722
0
            bCopied = xEmbeddedFile.is() && lcl_CopyStream(xEmbeddedFile->getInputStream(), xStream->getOutputStream());
723
0
        }
724
725
0
        if (!bCopied)
726
0
        {
727
0
            uno::Reference< io::XStream > xOle10Native;
728
0
            try
729
0
            {
730
0
                xNameContainer->getByName(u"\1Ole10Native"_ustr) >>= xOle10Native;
731
0
            }
732
0
            catch (container::NoSuchElementException const&)
733
0
            {
734
                // ignore
735
0
            }
736
0
            if (xOle10Native.is())
737
0
            {
738
0
                const uno::Reference<io::XInputStream> xIn = xOle10Native->getInputStream();
739
0
                xIn->skipBytes(4); //size of the entire stream minus 4 bytes
740
0
                xIn->skipBytes(2); //word that represent the directory type
741
0
                uno::Sequence< sal_Int8 > aData(1);
742
0
                sal_Int32 nRead;
743
0
                do
744
0
                {
745
0
                    nRead = xIn->readBytes(aData, 1);
746
0
                } while (nRead == 1 && aData[0] != 0);  // file name plus extension of the attachment null terminated
747
0
                do
748
0
                {
749
0
                    nRead = xIn->readBytes(aData, 1);
750
0
                } while (nRead == 1 && aData[0] != 0);  // Fully Qualified File name with extension
751
0
                xIn->skipBytes(1); //single byte
752
0
                xIn->skipBytes(1); //single byte
753
0
                xIn->skipBytes(2); //Word that represent the directory type
754
0
                xIn->skipBytes(4); //len of string
755
0
                do
756
0
                {
757
0
                    nRead = xIn->readBytes(aData, 1);
758
0
                } while (nRead == 1 && aData[0] != 0);  // Actual string representing the file path
759
0
                uno::Sequence< sal_Int8 > aLenData(4);
760
0
                xIn->readBytes(aLenData, 4); //len of attachment
761
0
                sal_uInt32 nLen = static_cast<sal_uInt32>(
762
0
                                              (aLenData[0] & 0xFF) |
763
0
                                              ((aLenData[1] & 0xFF) <<  8) |
764
0
                                              ((aLenData[2] & 0xFF) << 16) |
765
0
                                              ((aLenData[3] & 0xFF) << 24));
766
767
0
                bCopied = lcl_CopyStream(xIn, xStream->getOutputStream(), nLen);
768
0
            }
769
0
        }
770
771
0
        uno::Reference< io::XSeekable > xSeekableStor(xObjectStream, uno::UNO_QUERY);
772
0
        if (xSeekableStor.is())
773
0
            xSeekableStor->seek(0);
774
775
0
        if (!bCopied)
776
0
            bCopied = lcl_CopyStream(xObjectStream->getInputStream(), xStream->getOutputStream());
777
778
0
        if (bCopied)
779
0
        {
780
0
            xNativeTempFile->setRemoveFile(false);
781
0
            rUrl = xNativeTempFile->getUri();
782
783
0
            xNativeTempFile.clear();
784
785
0
            uno::Reference < ucb::XSimpleFileAccess3 > xSimpleFileAccess(
786
0
                    ucb::SimpleFileAccess::create( xContext ) );
787
788
0
            xSimpleFileAccess->setReadOnly(rUrl, true);
789
0
        }
790
0
        else
791
0
        {
792
0
            xNativeTempFile->setRemoveFile(true);
793
0
        }
794
795
0
        return xStream;
796
0
    }
797
798
    //Dump the objects content to a tempfile, just the "CONTENTS" stream if
799
    //there is one for non-compound documents, otherwise the whole content.
800
    //On success a file is returned which must be removed by the caller
801
    OUString lcl_ExtractObject(const css::uno::Reference< css::uno::XComponentContext >& xContext,
802
        const css::uno::Reference< css::io::XStream >& xObjectStream)
803
0
    {
804
0
        OUString sUrl;
805
806
        // the solution is only active for Unix systems
807
0
#ifndef _WIN32
808
0
        lcl_GetExtractedStream(sUrl, xContext, xObjectStream);
809
#else
810
        (void) xContext;
811
        (void) xObjectStream;
812
#endif
813
0
        return sUrl;
814
0
    }
815
816
    uno::Reference < io::XStream > lcl_ExtractObjectStream( const css::uno::Reference< css::uno::XComponentContext >& xContext,
817
        const css::uno::Reference< css::io::XStream >& xObjectStream )
818
0
    {
819
0
        OUString sUrl;
820
0
        return lcl_GetExtractedStream( sUrl, xContext, xObjectStream );
821
0
    }
822
}
823
824
825
void SAL_CALL OleEmbeddedObject::doVerb( sal_Int32 nVerbID )
826
0
{
827
    // begin wrapping related part ====================
828
0
    uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
829
0
    if ( xWrappedObject.is() )
830
0
    {
831
        // the object was converted to OOo embedded object, the current implementation is now only a wrapper
832
0
        xWrappedObject->doVerb(embed::EmbedVerbs::MS_OLEVERB_OPEN); // open content in the window not in-place
833
0
        return;
834
0
    }
835
    // end wrapping related part ====================
836
837
0
    ::osl::ResettableMutexGuard aGuard( m_aMutex );
838
0
    if ( m_bDisposed )
839
0
        throw lang::DisposedException(); // TODO
840
841
0
    if ( m_nObjectState == -1 )
842
0
        throw embed::WrongStateException( u"The object has no persistence!"_ustr,
843
0
                                        static_cast< ::cppu::OWeakObject* >(this) );
844
845
#ifdef _WIN32
846
    if ( m_pOleComponent )
847
    {
848
        sal_Int32 nOldState = m_nObjectState;
849
850
        // TODO/LATER detect target state here and do a notification
851
        // StateChangeNotification_Impl( sal_True, nOldState, nNewState );
852
        if ( m_nObjectState == embed::EmbedStates::LOADED )
853
        {
854
            // if the target object is in loaded state
855
            // it must be switched to running state to execute verb
856
            ExecUnlocked([this]() { changeState(embed::EmbedStates::RUNNING); }, aGuard);
857
        }
858
859
        try {
860
            if ( !m_pOleComponent )
861
                throw uno::RuntimeException("Null reference to OLE component");
862
863
            // ==== the STAMPIT related solution =============================
864
            m_aVerbExecutionController.StartControlExecution();
865
866
            ExecUnlocked(
867
                [nVerbID, p = m_pOleComponent, name = m_aContainerName]()
868
                {
869
                    p->ExecuteVerb(nVerbID);
870
                    p->SetHostName(name);
871
                },
872
                aGuard);
873
874
            // ==== the STAMPIT related solution =============================
875
            bool bModifiedOnExecution = m_aVerbExecutionController.EndControlExecution_WasModified();
876
877
            // this workaround is implemented for STAMPIT object
878
            // if object was modified during verb execution it is saved here
879
            if ( bModifiedOnExecution && m_pOleComponent->IsDirty() )
880
                SaveObject_Impl();
881
882
        }
883
        catch( uno::Exception& )
884
        {
885
            // ==== the STAMPIT related solution =============================
886
            m_aVerbExecutionController.EndControlExecution_WasModified();
887
888
            StateChangeNotification_Impl( false, nOldState, m_nObjectState, aGuard );
889
            throw;
890
        }
891
892
    }
893
    else
894
#endif
895
0
    {
896
0
        if ( nVerbID != -9 )
897
0
        {
898
899
0
            throw embed::UnreachableStateException();
900
0
        }
901
902
        // the workaround verb to show the object in case no server is available
903
904
        // if it is possible, the object will be converted to OOo format
905
0
        if ( !m_bTriedConversion )
906
0
        {
907
0
            m_bTriedConversion = true;
908
0
            if ( TryToConvertToOOo( m_xObjectStream ) )
909
0
            {
910
0
                aGuard.clear();
911
0
                changeState( embed::EmbedStates::ACTIVE );
912
0
                return;
913
0
            }
914
0
        }
915
916
0
        if ( !m_xOwnView.is() && m_xObjectStream.is() && m_aFilterName != "Text" )
917
0
        {
918
0
            try {
919
0
                uno::Reference< io::XSeekable > xSeekable( m_xObjectStream, uno::UNO_QUERY );
920
0
                if ( xSeekable.is() )
921
0
                    xSeekable->seek( 0 );
922
923
0
                m_xOwnView = new OwnView_Impl( m_xContext, m_xObjectStream->getInputStream() );
924
0
            }
925
0
            catch( uno::RuntimeException& )
926
0
            {
927
0
                throw;
928
0
            }
929
0
            catch (uno::Exception const&)
930
0
            {
931
0
                TOOLS_WARN_EXCEPTION("embeddedobj.ole", "OleEmbeddedObject::doVerb: -9 fallback path:");
932
0
            }
933
0
        }
934
935
        // it may be the OLE Storage, try to extract stream
936
0
        if ( !m_xOwnView.is() && m_xObjectStream.is() && m_aFilterName == "Text" )
937
0
        {
938
0
            uno::Reference< io::XStream > xStream = lcl_ExtractObjectStream( m_xContext, m_xObjectStream );
939
940
0
            if ( TryToConvertToOOo( xStream ) )
941
0
            {
942
0
                aGuard.clear();
943
0
                changeState( embed::EmbedStates::ACTIVE );
944
0
                return;
945
0
            }
946
0
        }
947
948
0
        if (!m_xOwnView.is() || !m_xOwnView->Open())
949
0
        {
950
            //Make a RO copy and see if the OS can find something to at
951
            //least display the content for us
952
0
            if (m_aTempDumpURL.isEmpty())
953
0
                m_aTempDumpURL = lcl_ExtractObject(m_xContext, m_xObjectStream);
954
955
0
            if (m_aTempDumpURL.isEmpty())
956
0
                throw embed::UnreachableStateException();
957
958
0
            uno::Reference< css::system::XSystemShellExecute > xSystemShellExecute(
959
0
                css::system::SystemShellExecute::create( m_xContext ) );
960
0
            xSystemShellExecute->execute(m_aTempDumpURL, OUString(), css::system::SystemShellExecuteFlags::URIS_ONLY);
961
962
0
        }
963
964
0
    }
965
0
}
966
967
968
uno::Sequence< embed::VerbDescriptor > SAL_CALL OleEmbeddedObject::getSupportedVerbs()
969
0
{
970
    // begin wrapping related part ====================
971
0
    uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
972
0
    if ( xWrappedObject.is() )
973
0
    {
974
        // the object was converted to OOo embedded object, the current implementation is now only a wrapper
975
0
        return xWrappedObject->getSupportedVerbs();
976
0
    }
977
    // end wrapping related part ====================
978
979
0
    osl::ClearableMutexGuard aGuard(m_aMutex);
980
0
    if ( m_bDisposed )
981
0
        throw lang::DisposedException(); // TODO
982
983
0
    if ( m_nObjectState == -1 )
984
0
        throw embed::WrongStateException( u"The object has no persistence!"_ustr,
985
0
                                        static_cast< ::cppu::OWeakObject* >(this) );
986
#ifdef _WIN32
987
    if ( m_pOleComponent )
988
    {
989
        // registry could be used in this case
990
        // if ( m_nObjectState == embed::EmbedStates::LOADED )
991
        // {
992
        //  // the list of supported verbs can be retrieved only when object is in running state
993
        //  throw embed::NeedsRunningStateException(); // TODO:
994
        // }
995
996
        aGuard.clear();
997
        return m_pOleComponent->GetVerbList();
998
    }
999
    else
1000
#endif
1001
0
    {
1002
        // tdf#140079 Claim support for the OleEmbeddedObject::doVerb -9 fallback.
1003
        // So in SfxViewFrame::GetState_Impl in case SID_OBJECT hasVerbs is not
1004
        // empty, so that the doVerb attempt with -9 fallback is attempted
1005
0
        uno::Sequence<embed::VerbDescriptor> aRet(1);
1006
0
        aRet.getArray()[0].VerbID = -9;
1007
0
        return aRet;
1008
0
    }
1009
0
}
1010
1011
1012
void SAL_CALL OleEmbeddedObject::setClientSite(
1013
                const uno::Reference< embed::XEmbeddedClient >& xClient )
1014
0
{
1015
    // begin wrapping related part ====================
1016
0
    uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
1017
0
    if ( xWrappedObject.is() )
1018
0
    {
1019
        // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1020
0
        xWrappedObject->setClientSite( xClient );
1021
0
        return;
1022
0
    }
1023
    // end wrapping related part ====================
1024
1025
0
    ::osl::MutexGuard aGuard( m_aMutex );
1026
0
    if ( m_bDisposed )
1027
0
        throw lang::DisposedException(); // TODO
1028
1029
0
    if ( m_xClientSite != xClient)
1030
0
    {
1031
0
        if ( m_nObjectState != embed::EmbedStates::LOADED && m_nObjectState != embed::EmbedStates::RUNNING )
1032
0
            throw embed::WrongStateException(
1033
0
                                    u"The client site can not be set currently!"_ustr,
1034
0
                                    static_cast< ::cppu::OWeakObject* >(this) );
1035
1036
0
        m_xClientSite = xClient;
1037
0
    }
1038
0
}
1039
1040
1041
uno::Reference< embed::XEmbeddedClient > SAL_CALL OleEmbeddedObject::getClientSite()
1042
0
{
1043
    // begin wrapping related part ====================
1044
0
    uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
1045
0
    if ( xWrappedObject.is() )
1046
0
    {
1047
        // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1048
0
        return xWrappedObject->getClientSite();
1049
0
    }
1050
    // end wrapping related part ====================
1051
1052
0
    ::osl::MutexGuard aGuard( m_aMutex );
1053
0
    if ( m_bDisposed )
1054
0
        throw lang::DisposedException(); // TODO
1055
1056
0
    if ( m_nObjectState == -1 )
1057
0
        throw embed::WrongStateException( u"The object has no persistence!"_ustr,
1058
0
                                        static_cast< ::cppu::OWeakObject* >(this) );
1059
1060
0
    return m_xClientSite;
1061
0
}
1062
1063
1064
void SAL_CALL OleEmbeddedObject::update()
1065
0
{
1066
    // begin wrapping related part ====================
1067
0
    uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
1068
0
    if ( xWrappedObject.is() )
1069
0
    {
1070
        // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1071
0
        xWrappedObject->update();
1072
0
        return;
1073
0
    }
1074
    // end wrapping related part ====================
1075
1076
0
    ::osl::MutexGuard aGuard( m_aMutex );
1077
0
    if ( m_bDisposed )
1078
0
        throw lang::DisposedException(); // TODO
1079
1080
0
    if ( m_nObjectState == -1 )
1081
0
        throw embed::WrongStateException( u"The object has no persistence!"_ustr,
1082
0
                                        static_cast< ::cppu::OWeakObject* >(this) );
1083
1084
0
    if ( m_nUpdateMode == embed::EmbedUpdateModes::EXPLICIT_UPDATE )
1085
0
    {
1086
        // TODO: update view representation
1087
0
    }
1088
0
    else
1089
0
    {
1090
        // the object must be up to date
1091
0
        SAL_WARN_IF( m_nUpdateMode != embed::EmbedUpdateModes::ALWAYS_UPDATE, "embeddedobj.ole", "Unknown update mode!" );
1092
0
    }
1093
0
}
1094
1095
1096
void SAL_CALL OleEmbeddedObject::setUpdateMode( sal_Int32 nMode )
1097
0
{
1098
    // begin wrapping related part ====================
1099
0
    uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
1100
0
    if ( xWrappedObject.is() )
1101
0
    {
1102
        // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1103
0
        xWrappedObject->setUpdateMode( nMode );
1104
0
        return;
1105
0
    }
1106
    // end wrapping related part ====================
1107
1108
0
    ::osl::MutexGuard aGuard( m_aMutex );
1109
0
    if ( m_bDisposed )
1110
0
        throw lang::DisposedException(); // TODO
1111
1112
0
    if ( m_nObjectState == -1 )
1113
0
        throw embed::WrongStateException( u"The object has no persistence!"_ustr,
1114
0
                                       static_cast< ::cppu::OWeakObject* >(this) );
1115
1116
0
    OSL_ENSURE( nMode == embed::EmbedUpdateModes::ALWAYS_UPDATE
1117
0
                    || nMode == embed::EmbedUpdateModes::EXPLICIT_UPDATE,
1118
0
                "Unknown update mode!" );
1119
0
    m_nUpdateMode = nMode;
1120
0
}
1121
1122
1123
sal_Int64 SAL_CALL OleEmbeddedObject::getStatus( sal_Int64
1124
    nAspect
1125
)
1126
0
{
1127
    // begin wrapping related part ====================
1128
0
    uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
1129
0
    if ( xWrappedObject.is() )
1130
0
    {
1131
        // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1132
0
        return xWrappedObject->getStatus( nAspect );
1133
0
    }
1134
    // end wrapping related part ====================
1135
1136
0
    osl::ResettableMutexGuard aGuard(m_aMutex);
1137
0
    if ( m_bDisposed )
1138
0
        throw lang::DisposedException(); // TODO
1139
1140
0
    if ( m_nObjectState == -1 )
1141
0
        throw embed::WrongStateException( u"The object must be in running state!"_ustr,
1142
0
                                    static_cast< ::cppu::OWeakObject* >(this) );
1143
1144
0
    sal_Int64 nResult = 0;
1145
1146
#ifdef _WIN32
1147
    if ( m_bGotStatus && m_nStatusAspect == nAspect )
1148
        nResult = m_nStatus;
1149
    else if ( m_pOleComponent )
1150
    {
1151
        m_nStatus = ExecUnlocked([p = m_pOleComponent, nAspect] { return p->GetMiscStatus(nAspect); }, aGuard);
1152
        m_nStatusAspect = nAspect;
1153
        m_bGotStatus = true;
1154
        nResult = m_nStatus;
1155
    }
1156
#endif
1157
1158
    // this implementation needs size to be provided after object loading/creating to work in optimal way
1159
0
    return ( nResult | embed::EmbedMisc::EMBED_NEEDSSIZEONLOAD );
1160
0
}
1161
1162
1163
void SAL_CALL OleEmbeddedObject::setContainerName( const OUString& sName )
1164
0
{
1165
    // begin wrapping related part ====================
1166
0
    uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
1167
0
    if ( xWrappedObject.is() )
1168
0
    {
1169
        // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1170
0
        xWrappedObject->setContainerName( sName );
1171
0
        return;
1172
0
    }
1173
    // end wrapping related part ====================
1174
1175
0
    ::osl::MutexGuard aGuard( m_aMutex );
1176
0
    if ( m_bDisposed )
1177
0
        throw lang::DisposedException(); // TODO
1178
1179
0
    m_aContainerName = sName;
1180
0
}
1181
1182
1183
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */