Coverage Report

Created: 2025-12-08 09:28

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