LibreOffice Module embeddedobj (master) 1
olepersist.cxx
Go to the documentation of this file.
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 <oleembobj.hxx>
21#include "olepersist.hxx"
22#include <com/sun/star/embed/EmbedStates.hpp>
23#include <com/sun/star/embed/EmbedVerbs.hpp>
24#include <com/sun/star/embed/EntryInitModes.hpp>
25#include <com/sun/star/embed/WrongStateException.hpp>
26#include <com/sun/star/embed/XStorage.hpp>
27#include <com/sun/star/embed/XTransactedObject.hpp>
28#include <com/sun/star/embed/ElementModes.hpp>
29#include <com/sun/star/embed/EmbedUpdateModes.hpp>
30#include <com/sun/star/embed/Aspects.hpp>
31#include <com/sun/star/embed/XOptimizedStorage.hpp>
32#include <com/sun/star/lang/XComponent.hpp>
33#include <com/sun/star/lang/DisposedException.hpp>
34#include <com/sun/star/container/XNameAccess.hpp>
35#include <com/sun/star/container/XNameContainer.hpp>
36#include <com/sun/star/io/TempFile.hpp>
37#include <com/sun/star/io/XSeekable.hpp>
38#include <com/sun/star/io/XTruncate.hpp>
39#include <com/sun/star/beans/XPropertySet.hpp>
40#include <com/sun/star/packages/WrongPasswordException.hpp>
41#include <com/sun/star/ucb/SimpleFileAccess.hpp>
42#include <com/sun/star/io/IOException.hpp>
43
47#include <osl/diagnose.h>
48#include <osl/thread.hxx>
49#include <rtl/ref.hxx>
50#include <sal/log.hxx>
51
52#include <closepreventer.hxx>
53
54#if defined(_WIN32)
55#include "olecomponent.hxx"
56#endif
57
58using namespace ::com::sun::star;
59using namespace ::comphelper;
60
61
62bool KillFile_Impl( const OUString& aURL, const uno::Reference< uno::XComponentContext >& xContext )
63{
64 if ( !xContext.is() )
65 return false;
66
67 bool bRet = false;
68
69 try
70 {
71 uno::Reference < ucb::XSimpleFileAccess3 > xAccess(
72 ucb::SimpleFileAccess::create( xContext ) );
73
74 xAccess->kill( aURL );
75 bRet = true;
76 }
77 catch( const uno::Exception& )
78 {
79 }
80
81 return bRet;
82}
83
84
85OUString GetNewTempFileURL_Impl( const uno::Reference< uno::XComponentContext >& xContext )
86{
87 SAL_WARN_IF( !xContext.is(), "embeddedobj.ole", "No factory is provided!" );
88
89 OUString aResult;
90
91 uno::Reference < io::XTempFile > xTempFile(
92 io::TempFile::create(xContext),
93 uno::UNO_SET_THROW );
94
95 try {
96 xTempFile->setRemoveFile( false );
97 aResult = xTempFile->getUri();
98 }
99 catch ( const uno::Exception& )
100 {
101 }
102
103 if ( aResult.isEmpty() )
104 throw uno::RuntimeException("Cannot create tempfile.");
105
106 return aResult;
107}
108
109
110OUString GetNewFilledTempFile_Impl( const uno::Reference< io::XInputStream >& xInStream,
111 const uno::Reference< uno::XComponentContext >& xContext )
112{
113 OSL_ENSURE( xInStream.is() && xContext.is(), "Wrong parameters are provided!" );
114
115 OUString aResult = GetNewTempFileURL_Impl( xContext );
116
117 if ( !aResult.isEmpty() )
118 {
119 try {
120 uno::Reference < ucb::XSimpleFileAccess3 > xTempAccess(
121 ucb::SimpleFileAccess::create( xContext ) );
122
123 uno::Reference< io::XOutputStream > xTempOutStream = xTempAccess->openFileWrite( aResult );
124 if ( !xTempOutStream.is() )
125 throw io::IOException(); // TODO:
126 // copy stream contents to the file
127 ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xTempOutStream );
128 xTempOutStream->closeOutput();
129 xTempOutStream.clear();
130 }
131 catch( const packages::WrongPasswordException& )
132 {
133 KillFile_Impl( aResult, xContext );
134 throw io::IOException(); //TODO:
135 }
136 catch( const io::IOException& )
137 {
138 KillFile_Impl( aResult, xContext );
139 throw;
140 }
141 catch( const uno::RuntimeException& )
142 {
143 KillFile_Impl( aResult, xContext );
144 throw;
145 }
146 catch( const uno::Exception& )
147 {
148 KillFile_Impl( aResult, xContext );
149 aResult.clear();
150 }
151 }
152
153 return aResult;
154}
155#ifdef _WIN32
158static OUString GetNewFilledTempFile_Impl( const uno::Reference< embed::XOptimizedStorage >& xParentStorage, const OUString& aEntryName, const uno::Reference< uno::XComponentContext >& xContext )
159{
160 OUString aResult;
161
162 try
163 {
164 uno::Reference < io::XTempFile > xTempFile(
165 io::TempFile::create(xContext),
166 uno::UNO_SET_THROW );
167
168 xParentStorage->copyStreamElementData( aEntryName, xTempFile );
169
170 xTempFile->setRemoveFile( false );
171 aResult = xTempFile->getUri();
172 }
173 catch( const uno::RuntimeException& )
174 {
175 throw;
176 }
177 catch( const uno::Exception& )
178 {
179 }
180
181 if ( aResult.isEmpty() )
182 throw io::IOException();
183
184 return aResult;
185}
186
187
188static void SetStreamMediaType_Impl( const uno::Reference< io::XStream >& xStream, const OUString& aMediaType )
189{
190 uno::Reference< beans::XPropertySet > xPropSet( xStream, uno::UNO_QUERY_THROW );
191 xPropSet->setPropertyValue("MediaType", uno::Any( aMediaType ) );
192}
193#endif
194
195static void LetCommonStoragePassBeUsed_Impl( const uno::Reference< io::XStream >& xStream )
196{
197 uno::Reference< beans::XPropertySet > xPropSet( xStream, uno::UNO_QUERY_THROW );
198 xPropSet->setPropertyValue("UseCommonStoragePasswordEncryption",
199 uno::Any( true ) );
200}
201#ifdef _WIN32
202
203void VerbExecutionController::StartControlExecution()
204{
205 osl::MutexGuard aGuard( m_aVerbExecutionMutex );
206
207 // the class is used to detect STAMPIT object, that can never be active
208 if ( !m_bVerbExecutionInProgress && !m_bWasEverActive )
209 {
210 m_bVerbExecutionInProgress = true;
211 m_nVerbExecutionThreadIdentifier = osl::Thread::getCurrentIdentifier();
212 m_bChangedOnVerbExecution = false;
213 }
214}
215
216
217bool VerbExecutionController::EndControlExecution_WasModified()
218{
219 osl::MutexGuard aGuard( m_aVerbExecutionMutex );
220
221 bool bResult = false;
222 if ( m_bVerbExecutionInProgress && m_nVerbExecutionThreadIdentifier == osl::Thread::getCurrentIdentifier() )
223 {
224 bResult = m_bChangedOnVerbExecution;
225 m_bVerbExecutionInProgress = false;
226 }
227
228 return bResult;
229}
230
231
232void VerbExecutionController::ModificationNotificationIsDone()
233{
234 osl::MutexGuard aGuard( m_aVerbExecutionMutex );
235
236 if ( m_bVerbExecutionInProgress && osl::Thread::getCurrentIdentifier() == m_nVerbExecutionThreadIdentifier )
237 m_bChangedOnVerbExecution = true;
238}
239#endif
240
242{
243 osl::MutexGuard aGuard( m_aVerbExecutionMutex );
246}
247
248
250{
251 osl::MutexGuard aGuard( m_aVerbExecutionMutex );
252 if ( m_nNotificationLock > 0 )
254}
255
256
257uno::Reference< io::XStream > OleEmbeddedObject::GetNewFilledTempStream_Impl( const uno::Reference< io::XInputStream >& xInStream )
258{
259 SAL_WARN_IF( !xInStream.is(), "embeddedobj.ole", "Wrong parameter is provided!" );
260
261 uno::Reference < io::XStream > xTempFile(
262 io::TempFile::create(m_xContext),
263 uno::UNO_QUERY_THROW );
264
265 uno::Reference< io::XOutputStream > xTempOutStream = xTempFile->getOutputStream();
266 if ( !xTempOutStream.is() )
267 throw io::IOException(); // TODO:
268 ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xTempOutStream );
269 xTempOutStream->flush();
270 return xTempFile;
271}
272
273
274uno::Reference< io::XStream > OleEmbeddedObject::TryToGetAcceptableFormat_Impl( const uno::Reference< io::XStream >& xStream )
275{
276 // TODO/LATER: Actually this should be done by a centralized component ( may be a graphical filter )
277 if ( !m_xContext.is() )
278 throw uno::RuntimeException();
279
280 uno::Reference< io::XInputStream > xInStream = xStream->getInputStream();
281 if ( !xInStream.is() )
282 throw uno::RuntimeException();
283
284 uno::Reference< io::XSeekable > xSeek( xStream, uno::UNO_QUERY_THROW );
285 xSeek->seek( 0 );
286
287 uno::Sequence< sal_Int8 > aData( 8 );
288 sal_Int32 nRead = xInStream->readBytes( aData, 8 );
289 xSeek->seek( 0 );
290
291 if ( ( nRead >= 2 && aData[0] == 'B' && aData[1] == 'M' )
292 || ( nRead >= 4 && aData[0] == 1 && aData[1] == 0 && aData[2] == 9 && aData[3] == 0 ) )
293 {
294 // it should be a bitmap or a Metafile
295 return xStream;
296 }
297
298
299 sal_uInt32 nHeaderOffset = 0;
300 if ( ( nRead >= 8 && aData[0] == -1 && aData[1] == -1 && aData[2] == -1 && aData[3] == -1 )
301 && ( aData[4] == 2 || aData[4] == 3 || aData[4] == 14 ) && aData[5] == 0 && aData[6] == 0 && aData[7] == 0 )
302 {
303 nHeaderOffset = 40;
304 xSeek->seek( 8 );
305
306 // TargetDevice might be used in future, currently the cache has specified NULL
307 uno::Sequence< sal_Int8 > aHeadData( 4 );
308 nRead = xInStream->readBytes( aHeadData, 4 );
309 sal_uInt32 nLen = 0;
310 if ( nRead == 4 && aHeadData.getLength() == 4 )
311 nLen = ( ( ( static_cast<sal_uInt32>(aHeadData[3]) * 0x100 + static_cast<sal_uInt32>(aHeadData[2]) ) * 0x100 ) + static_cast<sal_uInt32>(aHeadData[1]) ) * 0x100 + static_cast<sal_uInt32>(aHeadData[0]);
312 if ( nLen > 4 )
313 {
314 xInStream->skipBytes( nLen - 4 );
315 nHeaderOffset += nLen - 4;
316 }
317
318 }
319 else if ( nRead > 4 )
320 {
321 // check whether the first bytes represent the size
322 sal_uInt32 nSize = 0;
323 for ( sal_Int32 nInd = 3; nInd >= 0; nInd-- )
324 nSize = ( nSize << 8 ) + static_cast<sal_uInt8>(aData[nInd]);
325
326 if ( nSize == xSeek->getLength() - 4 )
327 nHeaderOffset = 4;
328 }
329
330 if ( nHeaderOffset )
331 {
332 // this is either a bitmap or a metafile clipboard format, retrieve the pure stream
333 uno::Reference < io::XStream > xResult(
334 io::TempFile::create(m_xContext),
335 uno::UNO_QUERY_THROW );
336 uno::Reference < io::XSeekable > xResultSeek( xResult, uno::UNO_QUERY_THROW );
337 uno::Reference < io::XOutputStream > xResultOut = xResult->getOutputStream();
338 uno::Reference < io::XInputStream > xResultIn = xResult->getInputStream();
339 if ( !xResultOut.is() || !xResultIn.is() )
340 throw uno::RuntimeException();
341
342 xSeek->seek( nHeaderOffset ); // header size for these formats
344 xResultOut->closeOutput();
345 xResultSeek->seek( 0 );
346 xSeek->seek( 0 );
347
348 return xResult;
349 }
350
351 return uno::Reference< io::XStream >();
352}
353
354
355void OleEmbeddedObject::InsertVisualCache_Impl( const uno::Reference< io::XStream >& xTargetStream,
356 const uno::Reference< io::XStream >& xCachedVisualRepresentation )
357{
358 OSL_ENSURE( xTargetStream.is() && xCachedVisualRepresentation.is(), "Invalid arguments!" );
359
360 if ( !xTargetStream.is() || !xCachedVisualRepresentation.is() )
361 throw uno::RuntimeException();
362
363 uno::Sequence< uno::Any > aArgs{ uno::Any(xTargetStream),
364 uno::Any(true) }; // do not create copy
365
366 uno::Reference< container::XNameContainer > xNameContainer(
367 m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
368 "com.sun.star.embed.OLESimpleStorage",
369 aArgs, m_xContext ),
370 uno::UNO_QUERY_THROW );
371
372 uno::Reference< io::XSeekable > xCachedSeek( xCachedVisualRepresentation, uno::UNO_QUERY_THROW );
373 xCachedSeek->seek( 0 );
374
375 uno::Reference < io::XStream > xTempFile(
376 io::TempFile::create(m_xContext),
377 uno::UNO_QUERY_THROW );
378
379 uno::Reference< io::XSeekable > xTempSeek( xTempFile, uno::UNO_QUERY_THROW );
380 uno::Reference< io::XOutputStream > xTempOutStream = xTempFile->getOutputStream();
381 if ( !xTempOutStream.is() )
382 throw io::IOException(); // TODO:
383
384 // the OlePres stream must have additional header
385 // TODO/LATER: might need to be extended in future (actually makes sense only for SO7 format)
386 uno::Reference< io::XInputStream > xInCacheStream = xCachedVisualRepresentation->getInputStream();
387 if ( !xInCacheStream.is() )
388 throw uno::RuntimeException();
389
390 // write 0xFFFFFFFF at the beginning
391 uno::Sequence< sal_Int8 > aData( 4 );
392 auto pData = aData.getArray();
393 * reinterpret_cast<sal_uInt32*>(pData) = 0xFFFFFFFF;
394
395 xTempOutStream->writeBytes( aData );
396
397 // write clipboard format
398 uno::Sequence< sal_Int8 > aSigData( 2 );
399 xInCacheStream->readBytes( aSigData, 2 );
400 if ( aSigData.getLength() < 2 )
401 throw io::IOException();
402
403 if ( aSigData[0] == 'B' && aSigData[1] == 'M' )
404 {
405 // it's a bitmap
406 pData[0] = 0x02; pData[1] = 0; pData[2] = 0; pData[3] = 0;
407 }
408 else
409 {
410 // treat it as a metafile
411 pData[0] = 0x03; pData[1] = 0; pData[2] = 0; pData[3] = 0;
412 }
413 xTempOutStream->writeBytes( aData );
414
415 // write job related information
416 pData[0] = 0x04; pData[1] = 0; pData[2] = 0; pData[3] = 0;
417 xTempOutStream->writeBytes( aData );
418
419 // write aspect
420 pData[0] = 0x01; pData[1] = 0; pData[2] = 0; pData[3] = 0;
421 xTempOutStream->writeBytes( aData );
422
423 // write l-index
424 * reinterpret_cast<sal_uInt32*>(pData) = 0xFFFFFFFF;
425 xTempOutStream->writeBytes( aData );
426
427 // write adv. flags
428 pData[0] = 0x02; pData[1] = 0; pData[2] = 0; pData[3] = 0;
429 xTempOutStream->writeBytes( aData );
430
431 // write compression
432 * reinterpret_cast<sal_uInt32*>(pData) = 0x0;
433 xTempOutStream->writeBytes( aData );
434
435 // get the size
436 awt::Size aSize = getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
437 sal_Int32 nIndex = 0;
438
439 // write width
440 for ( nIndex = 0; nIndex < 4; nIndex++ )
441 {
442 pData[nIndex] = static_cast<sal_Int8>( aSize.Width % 0x100 );
443 aSize.Width /= 0x100;
444 }
445 xTempOutStream->writeBytes( aData );
446
447 // write height
448 for ( nIndex = 0; nIndex < 4; nIndex++ )
449 {
450 pData[nIndex] = static_cast<sal_Int8>( aSize.Height % 0x100 );
451 aSize.Height /= 0x100;
452 }
453 xTempOutStream->writeBytes( aData );
454
455 // write garbage, it will be overwritten by the size
456 xTempOutStream->writeBytes( aData );
457
458 // write first bytes that was used to detect the type
459 xTempOutStream->writeBytes( aSigData );
460
461 // write the rest of the stream
462 ::comphelper::OStorageHelper::CopyInputToOutput( xInCacheStream, xTempOutStream );
463
464 // write the size of the stream
465 sal_Int64 nLength = xTempSeek->getLength() - 40;
466 if ( nLength < 0 || nLength >= 0xFFFFFFFF )
467 {
468 SAL_WARN( "embeddedobj.ole", "Length is not acceptable!" );
469 return;
470 }
471 for ( sal_Int32 nInd = 0; nInd < 4; nInd++ )
472 {
473 pData[nInd] = static_cast<sal_Int8>( static_cast<sal_uInt64>(nLength) % 0x100 );
474 nLength /= 0x100;
475 }
476 xTempSeek->seek( 36 );
477 xTempOutStream->writeBytes( aData );
478
479 xTempOutStream->flush();
480
481 xTempSeek->seek( 0 );
482 if ( xCachedSeek.is() )
483 xCachedSeek->seek( 0 );
484
485 // insert the result file as replacement image
486 OUString aCacheName = "\002OlePres000";
487 if ( xNameContainer->hasByName( aCacheName ) )
488 xNameContainer->replaceByName( aCacheName, uno::Any( xTempFile ) );
489 else
490 xNameContainer->insertByName( aCacheName, uno::Any( xTempFile ) );
491
492 uno::Reference< embed::XTransactedObject > xTransacted( xNameContainer, uno::UNO_QUERY_THROW );
493 xTransacted->commit();
494}
495
496
497void OleEmbeddedObject::RemoveVisualCache_Impl( const uno::Reference< io::XStream >& xTargetStream )
498{
499 OSL_ENSURE( xTargetStream.is(), "Invalid argument!" );
500 if ( !xTargetStream.is() )
501 throw uno::RuntimeException();
502
503 uno::Sequence< uno::Any > aArgs{ uno::Any(xTargetStream),
504 uno::Any(true) }; // do not create copy
505 uno::Reference< container::XNameContainer > xNameContainer(
506 m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
507 "com.sun.star.embed.OLESimpleStorage",
508 aArgs, m_xContext ),
509 uno::UNO_QUERY_THROW );
510
511 for ( sal_uInt8 nInd = 0; nInd < 10; nInd++ )
512 {
513 OUString aStreamName = "\002OlePres00" + OUString::number( nInd );
514 if ( xNameContainer->hasByName( aStreamName ) )
515 xNameContainer->removeByName( aStreamName );
516 }
517
518 uno::Reference< embed::XTransactedObject > xTransacted( xNameContainer, uno::UNO_QUERY_THROW );
519 xTransacted->commit();
520}
521
522
524{
526 m_bVisReplInStream = bExists;
527}
528
529
531{
533 {
535 SetVisReplInStream( true );
536 else
537 {
538 SAL_INFO( "embeddedobj.ole", "embeddedobj (mv76033) OleEmbeddedObject::HasVisualReplInStream, analyzing" );
539
540 uno::Reference< io::XInputStream > xStream;
541
542 OSL_ENSURE( !m_pOleComponent || !m_aTempURL.isEmpty(), "The temporary file must exist if there is a component!" );
543 if ( !m_aTempURL.isEmpty() )
544 {
545 try
546 {
547 // open temporary file for reading
548 uno::Reference < ucb::XSimpleFileAccess3 > xTempAccess(
549 ucb::SimpleFileAccess::create( m_xContext ) );
550
551 xStream = xTempAccess->openFileRead( m_aTempURL );
552 }
553 catch( const uno::Exception& )
554 {}
555 }
556
557 if ( !xStream.is() )
558 xStream = m_xObjectStream->getInputStream();
559
560 if ( xStream.is() )
561 {
562 bool bExists = false;
563
564 uno::Sequence< uno::Any > aArgs{ uno::Any(xStream),
565 uno::Any(true) }; // do not create copy
566 uno::Reference< container::XNameContainer > xNameContainer(
567 m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
568 "com.sun.star.embed.OLESimpleStorage",
569 aArgs, m_xContext ),
570 uno::UNO_QUERY );
571
572 if ( xNameContainer.is() )
573 {
574 for ( sal_uInt8 nInd = 0; nInd < 10 && !bExists; nInd++ )
575 {
576 OUString aStreamName = "\002OlePres00" + OUString::number( nInd );
577 try
578 {
579 bExists = xNameContainer->hasByName( aStreamName );
580 }
581 catch( const uno::Exception& )
582 {}
583 }
584 }
585
586 SetVisReplInStream( bExists );
587 }
588 }
589 }
590
591 return m_bVisReplInStream;
592}
593
594
596 const uno::Reference< io::XStream >& xStream,
597 bool bAllowToRepair50 )
598 noexcept
599{
600 uno::Reference< io::XStream > xResult;
601
602 if ( xStream.is() )
603 {
604 SAL_INFO( "embeddedobj.ole", "embeddedobj (mv76033) OleEmbeddedObject::TryToRetrieveCachedVisualRepresentation, retrieving" );
605
606 uno::Reference< container::XNameContainer > xNameContainer;
607 uno::Sequence< uno::Any > aArgs{ uno::Any(xStream),
608 uno::Any(true) }; // do not create copy
609 try
610 {
611 xNameContainer.set(
612 m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
613 "com.sun.star.embed.OLESimpleStorage",
614 aArgs, m_xContext ),
615 uno::UNO_QUERY );
616 }
617 catch( const uno::Exception& )
618 {}
619
620 if ( xNameContainer.is() )
621 {
622 for ( sal_uInt8 nInd = 0; nInd < 10; nInd++ )
623 {
624 OUString aStreamName = "\002OlePres00" + OUString::number( nInd );
625 uno::Reference< io::XStream > xCachedCopyStream;
626 try
627 {
628 if ( ( xNameContainer->getByName( aStreamName ) >>= xCachedCopyStream ) && xCachedCopyStream.is() )
629 {
630 xResult = TryToGetAcceptableFormat_Impl( xCachedCopyStream );
631 if ( xResult.is() )
632 break;
633 }
634 }
635 catch( const uno::Exception& )
636 {}
637
638 if ( nInd == 0 )
639 {
640 // to be compatible with the old versions Ole10Native is checked after OlePress000
641 aStreamName = "\001Ole10Native";
642 try
643 {
644 if ( ( xNameContainer->getByName( aStreamName ) >>= xCachedCopyStream ) && xCachedCopyStream.is() )
645 {
646 xResult = TryToGetAcceptableFormat_Impl( xCachedCopyStream );
647 if ( xResult.is() )
648 break;
649 }
650 }
651 catch( const uno::Exception& )
652 {}
653 }
654 }
655
656 try
657 {
658 if ( bAllowToRepair50 && !xResult.is() )
659 {
660 OUString aOrigContName( "Ole-Object" );
661 if ( xNameContainer->hasByName( aOrigContName ) )
662 {
663 uno::Reference< embed::XClassifiedObject > xClassified( xNameContainer, uno::UNO_QUERY_THROW );
664 if ( MimeConfigurationHelper::ClassIDsEqual( xClassified->getClassID(), MimeConfigurationHelper::GetSequenceClassID( SO3_OUT_CLASSID ) ) )
665 {
666 // this is an OLE object wrongly stored in 5.0 format
667 // this object must be repaired since SO7 has done it
668
669 uno::Reference< io::XOutputStream > xOutputStream = xStream->getOutputStream();
670 uno::Reference< io::XTruncate > xTruncate( xOutputStream, uno::UNO_QUERY_THROW );
671
672 uno::Reference< io::XInputStream > xOrigInputStream;
673 if ( ( xNameContainer->getByName( aOrigContName ) >>= xOrigInputStream )
674 && xOrigInputStream.is() )
675 {
676 // the provided input stream must be based on temporary medium and must be independent
677 // from the stream the storage is based on
678 uno::Reference< io::XSeekable > xOrigSeekable( xOrigInputStream, uno::UNO_QUERY );
679 if ( xOrigSeekable.is() )
680 xOrigSeekable->seek( 0 );
681
682 uno::Reference< lang::XComponent > xNameContDisp( xNameContainer, uno::UNO_QUERY_THROW );
683 xNameContDisp->dispose(); // free the original stream
684
685 xTruncate->truncate();
686 ::comphelper::OStorageHelper::CopyInputToOutput( xOrigInputStream, xOutputStream );
687 xOutputStream->flush();
688
689 if ( xStream == m_xObjectStream )
690 {
691 if ( !m_aTempURL.isEmpty() )
692 {
693 // this is the own stream, so the temporary URL must be cleaned if it exists
694 KillFile_Impl( m_aTempURL, m_xContext );
695 m_aTempURL.clear();
696 }
697
698#ifdef _WIN32
699 // retry to create the component after recovering
700 GetRidOfComponent();
701
702 try
703 {
704 CreateOleComponentAndLoad_Impl();
705 m_aClassID = m_pOleComponent->GetCLSID(); // was not set during construction
706 }
707 catch( const uno::Exception& )
708 {
709 GetRidOfComponent();
710 }
711#endif
712 }
713
714 xResult = TryToRetrieveCachedVisualRepresentation_Impl( xStream );
715 }
716 }
717 }
718 }
719 }
720 catch( const uno::Exception& )
721 {}
722 }
723 }
724
725 return xResult;
726}
727
728
729void OleEmbeddedObject::SwitchOwnPersistence( const uno::Reference< embed::XStorage >& xNewParentStorage,
730 const uno::Reference< io::XStream >& xNewObjectStream,
731 const OUString& aNewName )
732{
733 if ( xNewParentStorage == m_xParentStorage && aNewName == m_aEntryName )
734 {
735 SAL_WARN_IF( xNewObjectStream != m_xObjectStream, "embeddedobj.ole", "The streams must be the same!" );
736 return;
737 }
738
739 uno::Reference<io::XSeekable> xNewSeekable(xNewObjectStream, uno::UNO_QUERY);
740 if (xNewSeekable.is() && xNewSeekable->getLength() == 0)
741 {
742 uno::Reference<io::XSeekable> xOldSeekable(m_xObjectStream, uno::UNO_QUERY);
743 if (xOldSeekable.is() && xOldSeekable->getLength() > 0)
744 {
745 SAL_WARN("embeddedobj.ole", "OleEmbeddedObject::SwitchOwnPersistence(stream version): "
746 "empty new stream, reusing old one");
747 uno::Reference<io::XInputStream> xInput = m_xObjectStream->getInputStream();
748 uno::Reference<io::XOutputStream> xOutput = xNewObjectStream->getOutputStream();
749 xOldSeekable->seek(0);
751 xNewSeekable->seek(0);
752 }
753 }
754
755 try {
756 uno::Reference< lang::XComponent > xComponent( m_xObjectStream, uno::UNO_QUERY );
757 OSL_ENSURE( !m_xObjectStream.is() || xComponent.is(), "Wrong stream implementation!" );
758 if ( xComponent.is() )
759 xComponent->dispose();
760 }
761 catch ( const uno::Exception& )
762 {
763 }
764
765 m_xObjectStream = xNewObjectStream;
766 m_xParentStorage = xNewParentStorage;
767 m_aEntryName = aNewName;
768}
769
770
771void OleEmbeddedObject::SwitchOwnPersistence( const uno::Reference< embed::XStorage >& xNewParentStorage,
772 const OUString& aNewName )
773{
774 if ( xNewParentStorage == m_xParentStorage && aNewName == m_aEntryName )
775 return;
776
777 sal_Int32 nStreamMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE;
778
779 uno::Reference< io::XStream > xNewOwnStream = xNewParentStorage->openStreamElement( aNewName, nStreamMode );
780
781 uno::Reference<io::XSeekable> xNewSeekable (xNewOwnStream, uno::UNO_QUERY);
782 if (xNewSeekable.is() && xNewSeekable->getLength() == 0)
783 {
784 uno::Reference<io::XSeekable> xOldSeekable(m_xObjectStream, uno::UNO_QUERY);
785 if (xOldSeekable.is() && xOldSeekable->getLength() > 0)
786 {
787 SAL_WARN("embeddedobj.ole", "OleEmbeddedObject::SwitchOwnPersistence: empty new stream, reusing old one");
788 uno::Reference<io::XInputStream> xInput = m_xObjectStream->getInputStream();
789 uno::Reference<io::XOutputStream> xOutput = xNewOwnStream->getOutputStream();
791 xNewSeekable->seek(0);
792 }
793 }
794
795 SAL_WARN_IF( !xNewOwnStream.is(), "embeddedobj.ole", "The method can not return empty reference!" );
796
797 SwitchOwnPersistence( xNewParentStorage, xNewOwnStream, aNewName );
798}
799
800#ifdef _WIN32
801
802bool OleEmbeddedObject::SaveObject_Impl()
803{
804 bool bResult = false;
805
806 if ( m_xClientSite.is() )
807 {
808 try
809 {
810 m_xClientSite->saveObject();
811 bResult = true;
812 }
813 catch( const uno::Exception& )
814 {
815 }
816 }
817
818 return bResult;
819}
820
821
822bool OleEmbeddedObject::OnShowWindow_Impl( bool bShow )
823{
824 osl::ClearableMutexGuard aGuard(m_aMutex);
825
826 bool bResult = false;
827
828 SAL_WARN_IF( m_nObjectState == -1, "embeddedobj.ole", "The object has no persistence!" );
829 SAL_WARN_IF( m_nObjectState == embed::EmbedStates::LOADED, "embeddedobj.ole", "The object get OnShowWindow in loaded state!" );
830 if ( m_nObjectState == -1 || m_nObjectState == embed::EmbedStates::LOADED )
831 return false;
832
833 // the object is either activated or deactivated
834 sal_Int32 nOldState = m_nObjectState;
835 if ( bShow && m_nObjectState == embed::EmbedStates::RUNNING )
836 {
837 m_nObjectState = embed::EmbedStates::ACTIVE;
838 m_aVerbExecutionController.ObjectIsActive();
839
840 aGuard.clear();
841 StateChangeNotification_Impl( false, nOldState, m_nObjectState );
842 }
843 else if ( !bShow && m_nObjectState == embed::EmbedStates::ACTIVE )
844 {
845 m_nObjectState = embed::EmbedStates::RUNNING;
846 aGuard.clear();
847 StateChangeNotification_Impl( false, nOldState, m_nObjectState );
848 }
849
850 if ( m_xClientSite.is() )
851 {
852 try
853 {
854 m_xClientSite->visibilityChanged( bShow );
855 bResult = true;
856 }
857 catch( const uno::Exception& )
858 {
859 }
860 }
861
862 return bResult;
863}
864
865
866void OleEmbeddedObject::OnIconChanged_Impl()
867{
868 // TODO/LATER: currently this notification seems to be impossible
869 // MakeEventListenerNotification_Impl( OUString( "OnIconChanged" ) );
870}
871
872
873void OleEmbeddedObject::OnViewChanged_Impl()
874{
875 if ( m_bDisposed )
876 throw lang::DisposedException();
877
878 // For performance reasons the notification currently is ignored, STAMPIT object is the exception,
879 // it can never be active and never call SaveObject, so it is the only way to detect that it is changed
880
881 // ==== the STAMPIT related solution =============================
882 // the following variable is used to detect whether the object was modified during verb execution
883 m_aVerbExecutionController.ModificationNotificationIsDone();
884
885 // The following things are controlled by VerbExecutionController:
886 // - if the verb execution is in progress and the view is changed the object will be stored
887 // after the execution, so there is no need to send the notification.
888 // - the STAMPIT object can never be active.
889 if (m_aVerbExecutionController.CanDoNotification() &&
890 m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE &&
891 (MimeConfigurationHelper::ClassIDsEqual(m_aClassID, MimeConfigurationHelper::GetSequenceClassID(0x852ee1c9, 0x9058, 0x44ba, 0x8c, 0x6c, 0x0c, 0x5f, 0xc6, 0x6b, 0xdb, 0x8d)) ||
892 MimeConfigurationHelper::ClassIDsEqual(m_aClassID, MimeConfigurationHelper::GetSequenceClassID(0xcf1b4491, 0xbea3, 0x4c9f, 0xa7, 0x0f, 0x22, 0x1b, 0x1e, 0xca, 0xef, 0x3e)))
893 )
894 {
895 // The view is changed while the object is in running state, save the new object
897 SaveObject_Impl();
898 MakeEventListenerNotification_Impl( "OnVisAreaChanged" );
899 }
900
901}
902
903
904void OleEmbeddedObject::OnClosed_Impl()
905{
906 if ( m_bDisposed )
907 throw lang::DisposedException();
908
909 if ( m_nObjectState != embed::EmbedStates::LOADED )
910 {
911 sal_Int32 nOldState = m_nObjectState;
912 m_nObjectState = embed::EmbedStates::LOADED;
913 StateChangeNotification_Impl( false, nOldState, m_nObjectState );
914 }
915}
916
917
918OUString OleEmbeddedObject::CreateTempURLEmpty_Impl()
919{
920 SAL_WARN_IF( !m_aTempURL.isEmpty(), "embeddedobj.ole", "The object has already the temporary file!" );
922
923 return m_aTempURL;
924}
925
926
927OUString OleEmbeddedObject::GetTempURL_Impl()
928{
929 if ( m_aTempURL.isEmpty() )
930 {
931 SAL_INFO( "embeddedobj.ole", "embeddedobj (mv76033) OleEmbeddedObject::GetTempURL_Impl, tempfile creation" );
932
933 // if there is no temporary file, it will be created from the own entry
934 uno::Reference< embed::XOptimizedStorage > xOptParStorage( m_xParentStorage, uno::UNO_QUERY );
935 if ( xOptParStorage.is() )
936 {
938 }
939 else if ( m_xObjectStream.is() )
940 {
941 // load object from the stream
942 uno::Reference< io::XInputStream > xInStream = m_xObjectStream->getInputStream();
943 if ( !xInStream.is() )
944 throw io::IOException(); // TODO: access denied
945
947 }
948 }
949
950 return m_aTempURL;
951}
952
953
954void OleEmbeddedObject::CreateOleComponent_Impl(
955 rtl::Reference<OleComponent> const & pOleComponent )
956{
957 if ( !m_pOleComponent )
958 {
959 m_pOleComponent = pOleComponent ? pOleComponent : new OleComponent( m_xContext, this );
960
961 if ( !m_xClosePreventer.is() )
963
964 m_pOleComponent->addCloseListener( m_xClosePreventer );
965 }
966}
967
968
969void OleEmbeddedObject::CreateOleComponentAndLoad_Impl(
970 rtl::Reference<OleComponent> const & pOleComponent )
971{
972 if ( !m_pOleComponent )
973 {
974 if ( !m_xObjectStream.is() )
975 throw uno::RuntimeException();
976
977 CreateOleComponent_Impl( pOleComponent );
978
979 // after the loading the object can appear as a link
980 // will be detected later by olecomponent
981
982 GetTempURL_Impl();
983 if ( m_aTempURL.isEmpty() )
984 throw uno::RuntimeException(); // TODO
985
986 m_pOleComponent->LoadEmbeddedObject( m_aTempURL );
987 }
988}
989
990
991void OleEmbeddedObject::CreateOleComponentFromClipboard_Impl( OleComponent* pOleComponent )
992{
993 if ( !m_pOleComponent )
994 {
995 if ( !m_xObjectStream.is() )
996 throw uno::RuntimeException();
997
998 CreateOleComponent_Impl( pOleComponent );
999
1000 // after the loading the object can appear as a link
1001 // will be detected later by olecomponent
1002 m_pOleComponent->CreateObjectFromClipboard();
1003 }
1004}
1005
1006
1007uno::Reference< io::XOutputStream > OleEmbeddedObject::GetStreamForSaving()
1008{
1009 if ( !m_xObjectStream.is() )
1010 throw uno::RuntimeException(); //TODO:
1011
1012 uno::Reference< io::XOutputStream > xOutStream = m_xObjectStream->getOutputStream();
1013 if ( !xOutStream.is() )
1014 throw io::IOException(); //TODO: access denied
1015
1016 uno::Reference< io::XTruncate > xTruncate( xOutStream, uno::UNO_QUERY_THROW );
1017 xTruncate->truncate();
1018
1019 return xOutStream;
1020}
1021
1022
1023void OleEmbeddedObject::StoreObjectToStream( uno::Reference< io::XOutputStream > const & xOutStream )
1024{
1025 // this method should be used only on windows
1026 if ( m_pOleComponent )
1027 m_pOleComponent->StoreOwnTmpIfNecessary();
1028
1029 // now all the changes should be in temporary location
1030 if ( m_aTempURL.isEmpty() )
1031 throw uno::RuntimeException();
1032
1033 // open temporary file for reading
1034 uno::Reference < ucb::XSimpleFileAccess3 > xTempAccess(
1035 ucb::SimpleFileAccess::create( m_xContext ) );
1036
1037 uno::Reference< io::XInputStream > xTempInStream = xTempAccess->openFileRead( m_aTempURL );
1038 SAL_WARN_IF( !xTempInStream.is(), "embeddedobj.ole", "The object's temporary file can not be reopened for reading!" );
1039
1040 // TODO: use bStoreVisReplace
1041
1042 if ( !xTempInStream.is() )
1043 {
1044 throw io::IOException(); // TODO:
1045 }
1046
1047 // write all the contents to XOutStream
1048 uno::Reference< io::XTruncate > xTrunc( xOutStream, uno::UNO_QUERY_THROW );
1049 xTrunc->truncate();
1050
1051 ::comphelper::OStorageHelper::CopyInputToOutput( xTempInStream, xOutStream );
1052
1053 // TODO: should the view replacement be in the stream ???
1054 // probably it must be specified on storing
1055}
1056#endif
1057
1059 const uno::Reference< embed::XStorage >& xStorage,
1060 const OUString& sEntName,
1061 const uno::Sequence< beans::PropertyValue >& lObjArgs,
1062 bool bSaveAs )
1063{
1064 // TODO: use lObjArgs
1065 // TODO: exchange StoreVisualReplacement by SO file format version?
1066
1067 if ( m_nObjectState == -1 )
1068 {
1069 // the object is still not loaded
1070 throw embed::WrongStateException( "Can't store object without persistence!",
1071 static_cast< ::cppu::OWeakObject* >(this) );
1072 }
1073
1075 throw embed::WrongStateException(
1076 "The object waits for saveCompleted() call!",
1077 static_cast< ::cppu::OWeakObject* >(this) );
1078
1079 OSL_ENSURE( m_xParentStorage.is() && m_xObjectStream.is(), "The object has no valid persistence!" );
1080
1081 bool bVisReplIsStored = false;
1082
1083 bool bTryOptimization = false;
1084 bool bStoreVis = m_bStoreVisRepl;
1085 uno::Reference< io::XStream > xCachedVisualRepresentation;
1086 for ( beans::PropertyValue const & prop : lObjArgs )
1087 {
1088 if ( prop.Name == "StoreVisualReplacement" )
1089 prop.Value >>= bStoreVis;
1090 else if ( prop.Name == "VisualReplacement" )
1091 prop.Value >>= xCachedVisualRepresentation;
1092 else if ( prop.Name == "CanTryOptimization" )
1093 prop.Value >>= bTryOptimization;
1094 }
1095
1096 // ignore visual representation provided from outside if it should not be stored
1097 if ( !bStoreVis )
1098 xCachedVisualRepresentation.clear();
1099
1100 if ( bStoreVis && !HasVisReplInStream() && !xCachedVisualRepresentation.is() )
1101 throw io::IOException(); // TODO: there is no cached visual representation and nothing is provided from outside
1102
1103 // if the representation is provided from outside it should be copied to a local stream
1104 bool bNeedLocalCache = xCachedVisualRepresentation.is();
1105
1106 uno::Reference< io::XStream > xTargetStream;
1107
1108 bool bStoreLoaded = false;
1109 if ( m_nObjectState == embed::EmbedStates::LOADED
1110#ifdef _WIN32
1111 // if the object was NOT modified after storing it can be just copied
1112 // as if it was in loaded state
1113 || ( m_pOleComponent && !m_pOleComponent->IsDirty() )
1114#endif
1115 )
1116 {
1117 bool bOptimizedCopyingDone = false;
1118
1119 if ( bTryOptimization && bStoreVis == HasVisReplInStream() )
1120 {
1121 try
1122 {
1123 uno::Reference< embed::XOptimizedStorage > xSourceOptStor( m_xParentStorage, uno::UNO_QUERY_THROW );
1124 uno::Reference< embed::XOptimizedStorage > xTargetOptStor( xStorage, uno::UNO_QUERY_THROW );
1125 xSourceOptStor->copyElementDirectlyTo( m_aEntryName, xTargetOptStor, sEntName );
1126 bOptimizedCopyingDone = true;
1127 }
1128 catch( const uno::Exception& )
1129 {
1130 }
1131 }
1132
1133 if ( !bOptimizedCopyingDone )
1134 {
1135 // if optimized copying fails a normal one should be tried
1136 m_xParentStorage->copyElementTo( m_aEntryName, xStorage, sEntName );
1137 }
1138
1139 // the locally retrieved representation is always preferable
1140 // since the object is in loaded state the representation is unchanged
1142 {
1143 xCachedVisualRepresentation = m_xCachedVisualRepresentation;
1144 bNeedLocalCache = false;
1145 }
1146
1147 bVisReplIsStored = HasVisReplInStream();
1148 bStoreLoaded = true;
1149 }
1150#ifdef _WIN32
1151 else if ( m_pOleComponent )
1152 {
1153 xTargetStream =
1154 xStorage->openStreamElement( sEntName, embed::ElementModes::READWRITE );
1155 if ( !xTargetStream.is() )
1156 throw io::IOException(); //TODO: access denied
1157
1158 SetStreamMediaType_Impl( xTargetStream, "application/vnd.sun.star.oleobject" );
1159 uno::Reference< io::XOutputStream > xOutStream = xTargetStream->getOutputStream();
1160 if ( !xOutStream.is() )
1161 throw io::IOException(); //TODO: access denied
1162
1163 StoreObjectToStream( xOutStream );
1164 bVisReplIsStored = true;
1165
1166 if ( bSaveAs )
1167 {
1168 // no need to do it on StoreTo since in this case the replacement is in the stream
1169 // and there is no need to cache it even if it is thrown away because the object
1170 // is not changed by StoreTo action
1171
1172 uno::Reference< io::XStream > xTmpCVRepresentation =
1174
1175 // the locally retrieved representation is always preferable
1176 if ( xTmpCVRepresentation.is() )
1177 {
1178 xCachedVisualRepresentation = xTmpCVRepresentation;
1179 bNeedLocalCache = false;
1180 }
1181 }
1182 }
1183#endif
1184 else if (true) // loplugin:flatten
1185 {
1186 throw io::IOException(); // TODO
1187 }
1188
1189 if ( !xTargetStream.is() )
1190 {
1191 xTargetStream =
1192 xStorage->openStreamElement( sEntName, embed::ElementModes::READWRITE );
1193 if ( !xTargetStream.is() )
1194 throw io::IOException(); //TODO: access denied
1195 }
1196
1197 LetCommonStoragePassBeUsed_Impl( xTargetStream );
1198
1199 if ( bStoreVis != bVisReplIsStored )
1200 {
1201 if ( bStoreVis )
1202 {
1203 if ( !xCachedVisualRepresentation.is() )
1204 xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( xTargetStream );
1205
1206 SAL_WARN_IF( !xCachedVisualRepresentation.is(), "embeddedobj.ole", "No representation is available!" );
1207
1208 // the following copying will be done in case it is SaveAs anyway
1209 // if it is not SaveAs the seekable access is not required currently
1210 // TODO/LATER: may be required in future
1211 if ( bSaveAs )
1212 {
1213 uno::Reference< io::XSeekable > xCachedSeek( xCachedVisualRepresentation, uno::UNO_QUERY );
1214 if ( !xCachedSeek.is() )
1215 {
1216 xCachedVisualRepresentation
1217 = GetNewFilledTempStream_Impl( xCachedVisualRepresentation->getInputStream() );
1218 bNeedLocalCache = false;
1219 }
1220 }
1221
1222 InsertVisualCache_Impl( xTargetStream, xCachedVisualRepresentation );
1223 }
1224 else
1225 {
1226 // the removed representation could be cached by this method
1227 if ( !xCachedVisualRepresentation.is() )
1228 xCachedVisualRepresentation = TryToRetrieveCachedVisualRepresentation_Impl( xTargetStream );
1229
1230 if (!m_bStreamReadOnly)
1231 RemoveVisualCache_Impl(xTargetStream);
1232 }
1233 }
1234
1235 if ( bSaveAs )
1236 {
1237 m_bWaitSaveCompleted = true;
1238 m_xNewObjectStream = xTargetStream;
1239 m_xNewParentStorage = xStorage;
1240 m_aNewEntryName = sEntName;
1241 m_bNewVisReplInStream = bStoreVis;
1242 m_bStoreLoaded = bStoreLoaded;
1243
1244 if ( xCachedVisualRepresentation.is() )
1245 {
1246 if ( bNeedLocalCache )
1247 m_xNewCachedVisRepl = GetNewFilledTempStream_Impl( xCachedVisualRepresentation->getInputStream() );
1248 else
1249 m_xNewCachedVisRepl = xCachedVisualRepresentation;
1250 }
1251
1252 // TODO: register listeners for storages above, in case they are disposed
1253 // an exception will be thrown on saveCompleted( true )
1254 }
1255 else
1256 {
1257 uno::Reference< lang::XComponent > xComp( xTargetStream, uno::UNO_QUERY );
1258 if ( xComp.is() )
1259 {
1260 try {
1261 xComp->dispose();
1262 } catch( const uno::Exception& )
1263 {
1264 }
1265 }
1266 }
1267}
1268
1269
1271 const uno::Reference< embed::XStorage >& xStorage,
1272 const OUString& sEntName,
1273 sal_Int32 nEntryConnectionMode,
1274 const uno::Sequence< beans::PropertyValue >& lArguments,
1275 const uno::Sequence< beans::PropertyValue >& lObjArgs )
1276{
1277 // begin wrapping related part ====================
1278 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1279 if ( xWrappedObject.is() )
1280 {
1281 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1282 xWrappedObject->setPersistentEntry( xStorage, sEntName, nEntryConnectionMode, lArguments, lObjArgs );
1283 return;
1284 }
1285 // end wrapping related part ====================
1286
1287 // TODO: use lObjArgs
1288
1289 // the type of the object must be already set
1290 // a kind of typedetection should be done in the factory;
1291 // the only exception is object initialized from a stream,
1292 // the class ID will be detected from the stream
1293
1294 ::osl::MutexGuard aGuard( m_aMutex );
1295 if ( m_bDisposed )
1296 throw lang::DisposedException(); // TODO
1297
1298 if ( !xStorage.is() )
1299 throw lang::IllegalArgumentException( "No parent storage is provided!",
1300 static_cast< ::cppu::OWeakObject* >(this),
1301 1 );
1302
1303 if ( sEntName.isEmpty() )
1304 throw lang::IllegalArgumentException( "Empty element name is provided!",
1305 static_cast< ::cppu::OWeakObject* >(this),
1306 2 );
1307
1308 // May be LOADED should be forbidden here ???
1309 if ( ( m_nObjectState != -1 || nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
1310 && ( m_nObjectState == -1 || nEntryConnectionMode != embed::EntryInitModes::NO_INIT ) )
1311 {
1312 // if the object is not loaded
1313 // it can not get persistent representation without initialization
1314
1315 // if the object is loaded
1316 // it can switch persistent representation only without initialization
1317
1318 throw embed::WrongStateException(
1319 "Can't change persistent representation of activated object!",
1320 static_cast< ::cppu::OWeakObject* >(this) );
1321 }
1322
1324 {
1325 if ( nEntryConnectionMode != embed::EntryInitModes::NO_INIT )
1326 throw embed::WrongStateException(
1327 "The object waits for saveCompleted() call!",
1328 static_cast< ::cppu::OWeakObject* >(this) );
1329 saveCompleted( m_xParentStorage != xStorage || m_aEntryName != sEntName );
1330 }
1331
1332 uno::Reference< container::XNameAccess > xNameAccess( xStorage, uno::UNO_QUERY_THROW );
1333
1334 // detect entry existence
1335 bool bElExists = xNameAccess->hasByName( sEntName );
1336
1337 m_bReadOnly = false;
1338 for ( beans::PropertyValue const & prop : lArguments )
1339 if ( prop.Name == "ReadOnly" )
1340 prop.Value >>= m_bReadOnly;
1341
1342#ifdef _WIN32
1343 sal_Int32 nStorageMode = m_bReadOnly ? embed::ElementModes::READ : embed::ElementModes::READWRITE;
1344#endif
1345
1346 SwitchOwnPersistence( xStorage, sEntName );
1347
1348 for ( beans::PropertyValue const & prop : lObjArgs )
1349 if ( prop.Name == "StoreVisualReplacement" )
1350 prop.Value >>= m_bStoreVisRepl;
1351
1352#ifdef _WIN32
1353 if ( nEntryConnectionMode == embed::EntryInitModes::DEFAULT_INIT )
1354 {
1355 if ( m_bFromClipboard )
1356 {
1357 // the object should be initialized from clipboard
1358 // impossibility to initialize the object means error here
1359 CreateOleComponentFromClipboard_Impl();
1360 m_aClassID = m_pOleComponent->GetCLSID(); // was not set during construction
1361 m_pOleComponent->RunObject();
1362 m_nObjectState = embed::EmbedStates::RUNNING;
1363 }
1364 else if ( bElExists )
1365 {
1366 // load object from the stream
1367 // after the loading the object can appear as a link
1368 // will be detected by olecomponent
1369 try
1370 {
1371 CreateOleComponentAndLoad_Impl();
1372 m_aClassID = m_pOleComponent->GetCLSID(); // was not set during construction
1373 }
1374 catch( const uno::Exception& )
1375 {
1376 // TODO/LATER: detect classID of the object if possible
1377 // means that the object inprocess server could not be successfully instantiated
1379 }
1380
1381 m_nObjectState = embed::EmbedStates::LOADED;
1382 }
1383 else
1384 {
1385 // create a new object
1386 CreateOleComponent_Impl();
1387 m_pOleComponent->CreateNewEmbeddedObject( m_aClassID );
1388 m_pOleComponent->RunObject();
1389 m_nObjectState = embed::EmbedStates::RUNNING;
1390 }
1391 }
1392 else
1393 {
1394 if ( ( nStorageMode & embed::ElementModes::READWRITE ) != embed::ElementModes::READWRITE )
1395 throw io::IOException();
1396
1397 if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
1398 {
1399 // the document just already changed its stream to store to;
1400 // the links to OLE documents switch their persistence in the same way
1401 // as normal embedded objects
1402 }
1403 else if ( nEntryConnectionMode == embed::EntryInitModes::TRUNCATE_INIT )
1404 {
1405 // create a new object, that will be stored in specified stream
1406 CreateOleComponent_Impl();
1407
1408 m_pOleComponent->CreateNewEmbeddedObject( m_aClassID );
1409 m_pOleComponent->RunObject();
1410 m_nObjectState = embed::EmbedStates::RUNNING;
1411 }
1412 else if ( nEntryConnectionMode == embed::EntryInitModes::MEDIA_DESCRIPTOR_INIT )
1413 {
1414 // use URL ( may be content or stream later ) from MediaDescriptor to initialize object
1415 OUString aURL;
1416 for ( beans::PropertyValue const & prop : lArguments )
1417 if ( prop.Name == "URL" )
1418 prop.Value >>= aURL;
1419
1420 if ( aURL.isEmpty() )
1421 throw lang::IllegalArgumentException(
1422 "Empty URL is provided in the media descriptor!",
1423 static_cast< ::cppu::OWeakObject* >(this),
1424 4 );
1425
1426 CreateOleComponent_Impl();
1427
1428 // TODO: the m_bIsLink value must be set already
1429 if ( !m_bIsLink )
1430 m_pOleComponent->CreateObjectFromFile( aURL );
1431 else
1432 m_pOleComponent->CreateLinkFromFile( aURL );
1433
1434 m_pOleComponent->RunObject();
1435 m_aClassID = m_pOleComponent->GetCLSID(); // was not set during construction
1436
1437 m_nObjectState = embed::EmbedStates::RUNNING;
1438 }
1439 //else if ( nEntryConnectionMode == embed::EntryInitModes::TRANSFERABLE_INIT )
1440 //{
1441 //TODO:
1442 //}
1443 else
1444 throw lang::IllegalArgumentException( "Wrong connection mode is provided!",
1445 static_cast< ::cppu::OWeakObject* >(this),
1446 3 );
1447 }
1448#else
1449 // On Unix the OLE object can not do anything except storing itself somewhere
1450 if ( nEntryConnectionMode == embed::EntryInitModes::DEFAULT_INIT && bElExists )
1451 {
1452 // TODO/LATER: detect classID of the object
1453 // can be a real problem for the links
1454
1455 m_nObjectState = embed::EmbedStates::LOADED;
1456 }
1457 else if ( nEntryConnectionMode == embed::EntryInitModes::NO_INIT )
1458 {
1459 // do nothing, the object has already switched it's persistence
1460 }
1461 else
1462 throw lang::IllegalArgumentException( "Wrong connection mode is provided!",
1463 static_cast< ::cppu::OWeakObject* >(this),
1464 3 );
1465
1466#endif
1467}
1468
1469
1470void SAL_CALL OleEmbeddedObject::storeToEntry( const uno::Reference< embed::XStorage >& xStorage,
1471 const OUString& sEntName,
1472 const uno::Sequence< beans::PropertyValue >& lArguments,
1473 const uno::Sequence< beans::PropertyValue >& lObjArgs )
1474{
1475 // begin wrapping related part ====================
1476 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1477 if ( xWrappedObject.is() )
1478 {
1479 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1480 xWrappedObject->storeToEntry( xStorage, sEntName, lArguments, lObjArgs );
1481 return;
1482 }
1483 // end wrapping related part ====================
1484
1485 ::osl::MutexGuard aGuard( m_aMutex );
1486 if ( m_bDisposed )
1487 throw lang::DisposedException(); // TODO
1488
1490
1491 StoreToLocation_Impl( xStorage, sEntName, lObjArgs, false );
1492
1493 // TODO: should the listener notification be done?
1494}
1495
1496
1497void SAL_CALL OleEmbeddedObject::storeAsEntry( const uno::Reference< embed::XStorage >& xStorage,
1498 const OUString& sEntName,
1499 const uno::Sequence< beans::PropertyValue >& lArguments,
1500 const uno::Sequence< beans::PropertyValue >& lObjArgs )
1501{
1502 // begin wrapping related part ====================
1503 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1504 if ( xWrappedObject.is() )
1505 {
1506 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1507 xWrappedObject->storeAsEntry( xStorage, sEntName, lArguments, lObjArgs );
1508 return;
1509 }
1510 // end wrapping related part ====================
1511
1512 ::osl::MutexGuard aGuard( m_aMutex );
1513 if ( m_bDisposed )
1514 throw lang::DisposedException(); // TODO
1515
1517
1518 StoreToLocation_Impl( xStorage, sEntName, lObjArgs, true );
1519
1520 // TODO: should the listener notification be done here or in saveCompleted?
1521}
1522
1523
1525{
1526 // begin wrapping related part ====================
1527 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1528 if ( xWrappedObject.is() )
1529 {
1530 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1531 xWrappedObject->saveCompleted( bUseNew );
1532 return;
1533 }
1534 // end wrapping related part ====================
1535
1536 osl::ClearableMutexGuard aGuard(m_aMutex);
1537 if ( m_bDisposed )
1538 throw lang::DisposedException(); // TODO
1539
1540 if ( m_nObjectState == -1 )
1541 {
1542 // the object is still not loaded
1543 throw embed::WrongStateException( "Can't store object without persistence!",
1544 static_cast< ::cppu::OWeakObject* >(this) );
1545 }
1546
1547 // it is allowed to call saveCompleted( false ) for nonstored objects
1548 if ( !m_bWaitSaveCompleted && !bUseNew )
1549 return;
1550
1551 SAL_WARN_IF( !m_bWaitSaveCompleted, "embeddedobj.ole", "Unexpected saveCompleted() call!" );
1552 if ( !m_bWaitSaveCompleted )
1553 throw io::IOException(); // TODO: illegal call
1554
1555 OSL_ENSURE( m_xNewObjectStream.is() && m_xNewParentStorage.is() , "Internal object information is broken!" );
1556 if ( !m_xNewObjectStream.is() || !m_xNewParentStorage.is() )
1557 throw uno::RuntimeException(); // TODO: broken internal information
1558
1559 if ( bUseNew )
1560 {
1565 }
1566 else
1567 {
1568 // close remembered stream
1569 try {
1570 uno::Reference< lang::XComponent > xComponent( m_xNewObjectStream, uno::UNO_QUERY );
1571 SAL_WARN_IF( !xComponent.is(), "embeddedobj.ole", "Wrong storage implementation!" );
1572 if ( xComponent.is() )
1573 xComponent->dispose();
1574 }
1575 catch ( const uno::Exception& )
1576 {
1577 }
1578 }
1579
1580 bool bStoreLoaded = m_bStoreLoaded;
1581
1582 m_xNewObjectStream.clear();
1583 m_xNewParentStorage.clear();
1584 m_aNewEntryName.clear();
1585 m_bWaitSaveCompleted = false;
1586 m_bNewVisReplInStream = false;
1587 m_xNewCachedVisRepl.clear();
1588 m_bStoreLoaded = false;
1589
1590 if ( bUseNew && m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded
1591 && m_nObjectState != embed::EmbedStates::LOADED )
1592 {
1593 // the object replacement image should be updated, so the cached size as well
1594 m_bHasCachedSize = false;
1595 try
1596 {
1597 // the call will cache the size in case of success
1598 // probably it might need to be done earlier, while the object is in active state
1599 getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
1600 }
1601 catch( const uno::Exception& )
1602 {}
1603 }
1604
1605 aGuard.clear();
1606 if ( bUseNew )
1607 {
1608 MakeEventListenerNotification_Impl( "OnSaveAsDone");
1609
1610 // the object can be changed only on windows
1611 // the notification should be done only if the object is not in loaded state
1612 if ( m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded )
1613 {
1614 MakeEventListenerNotification_Impl( "OnVisAreaChanged");
1615 }
1616 }
1617}
1618
1619
1621{
1622 // begin wrapping related part ====================
1623 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1624 if ( xWrappedObject.is() )
1625 {
1626 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1627 return xWrappedObject->hasEntry();
1628 }
1629 // end wrapping related part ====================
1630
1631 ::osl::MutexGuard aGuard( m_aMutex );
1632 if ( m_bDisposed )
1633 throw lang::DisposedException(); // TODO
1634
1636 throw embed::WrongStateException(
1637 "The object waits for saveCompleted() call!",
1638 static_cast< ::cppu::OWeakObject* >(this) );
1639
1640 if ( m_xObjectStream.is() )
1641 return true;
1642
1643 return false;
1644}
1645
1646
1648{
1649 // begin wrapping related part ====================
1650 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1651 if ( xWrappedObject.is() )
1652 {
1653 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1654 return xWrappedObject->getEntryName();
1655 }
1656 // end wrapping related part ====================
1657
1658 ::osl::MutexGuard aGuard( m_aMutex );
1659 if ( m_bDisposed )
1660 throw lang::DisposedException(); // TODO
1661
1662 if ( m_nObjectState == -1 )
1663 {
1664 // the object is still not loaded
1665 throw embed::WrongStateException( "The object persistence is not initialized!",
1666 static_cast< ::cppu::OWeakObject* >(this) );
1667 }
1668
1670 throw embed::WrongStateException(
1671 "The object waits for saveCompleted() call!",
1672 static_cast< ::cppu::OWeakObject* >(this) );
1673
1674 return m_aEntryName;
1675}
1676
1677
1679{
1680 // begin wrapping related part ====================
1681 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1682 if ( xWrappedObject.is() )
1683 {
1684 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1685 xWrappedObject->storeOwn();
1686 return;
1687 }
1688 // end wrapping related part ====================
1689
1690 // during switching from Activated to Running and from Running to Loaded states the object will
1691 // ask container to store the object, the container has to make decision
1692 // to do so or not
1693
1694 osl::ClearableMutexGuard aGuard(m_aMutex);
1695 if ( m_bDisposed )
1696 throw lang::DisposedException(); // TODO
1697
1699
1700 if ( m_nObjectState == -1 )
1701 {
1702 // the object is still not loaded
1703 throw embed::WrongStateException( "Can't store object without persistence!",
1704 static_cast< ::cppu::OWeakObject* >(this) );
1705 }
1706
1708 throw embed::WrongStateException(
1709 "The object waits for saveCompleted() call!",
1710 static_cast< ::cppu::OWeakObject* >(this) );
1711
1712 if ( m_bReadOnly )
1713 throw io::IOException(); // TODO: access denied
1714
1716
1717 bool bStoreLoaded = true;
1718
1719#ifdef _WIN32
1720 if ( m_nObjectState != embed::EmbedStates::LOADED && m_pOleComponent && m_pOleComponent->IsDirty() )
1721 {
1722 bStoreLoaded = false;
1723
1724 OSL_ENSURE( m_xParentStorage.is() && m_xObjectStream.is(), "The object has no valid persistence!" );
1725
1726 if ( !m_xObjectStream.is() )
1727 throw io::IOException(); //TODO: access denied
1728
1729 SetStreamMediaType_Impl( m_xObjectStream, "application/vnd.sun.star.oleobject" );
1730 uno::Reference< io::XOutputStream > xOutStream = m_xObjectStream->getOutputStream();
1731 if ( !xOutStream.is() )
1732 throw io::IOException(); //TODO: access denied
1733
1734 // TODO: does this work for links too?
1735 StoreObjectToStream( GetStreamForSaving() );
1736
1737 // the replacement is changed probably, and it must be in the object stream
1738 if ( !m_pOleComponent->IsWorkaroundActive() )
1740 SetVisReplInStream( true );
1741 }
1742#endif
1743
1745 {
1746 if ( m_bStoreVisRepl )
1747 {
1748 // the m_xCachedVisualRepresentation must be set or it should be already stored
1751 else
1752 {
1754 SAL_WARN_IF( !m_xCachedVisualRepresentation.is(), "embeddedobj.ole", "No representation is available!" );
1755 }
1756 }
1757 else
1758 {
1762 }
1763
1765 }
1766
1767 if ( m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded )
1768 {
1769 // the object replacement image should be updated, so the cached size as well
1770 m_bHasCachedSize = false;
1771 try
1772 {
1773 // the call will cache the size in case of success
1774 // probably it might need to be done earlier, while the object is in active state
1775 getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
1776 }
1777 catch( const uno::Exception& )
1778 {}
1779 }
1780
1781 aGuard.clear();
1782
1784
1785 // the object can be changed only on Windows
1786 // the notification should be done only if the object is not in loaded state
1787 if ( m_pOleComponent && m_nUpdateMode == embed::EmbedUpdateModes::ALWAYS_UPDATE && !bStoreLoaded )
1788 MakeEventListenerNotification_Impl( "OnVisAreaChanged");
1789}
1790
1791
1793{
1794 // begin wrapping related part ====================
1795 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1796 if ( xWrappedObject.is() )
1797 {
1798 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1799 return xWrappedObject->isReadonly();
1800 }
1801 // end wrapping related part ====================
1802
1803 ::osl::MutexGuard aGuard( m_aMutex );
1804 if ( m_bDisposed )
1805 throw lang::DisposedException(); // TODO
1806
1807 if ( m_nObjectState == -1 )
1808 {
1809 // the object is still not loaded
1810 throw embed::WrongStateException( "The object persistence is not initialized!",
1811 static_cast< ::cppu::OWeakObject* >(this) );
1812 }
1813
1815 throw embed::WrongStateException(
1816 "The object waits for saveCompleted() call!",
1817 static_cast< ::cppu::OWeakObject* >(this) );
1818
1819 return m_bReadOnly;
1820}
1821
1822
1824 const uno::Sequence< beans::PropertyValue >& lArguments,
1825 const uno::Sequence< beans::PropertyValue >& lObjArgs )
1826{
1827 // begin wrapping related part ====================
1828 uno::Reference< embed::XEmbedPersist > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1829 if ( xWrappedObject.is() )
1830 {
1831 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1832 xWrappedObject->reload( lArguments, lObjArgs );
1833 return;
1834 }
1835 // end wrapping related part ====================
1836
1837 // TODO: use lObjArgs
1838
1839 ::osl::MutexGuard aGuard( m_aMutex );
1840 if ( m_bDisposed )
1841 throw lang::DisposedException(); // TODO
1842
1843 if ( m_nObjectState == -1 )
1844 {
1845 // the object is still not loaded
1846 throw embed::WrongStateException( "The object persistence is not initialized!",
1847 static_cast< ::cppu::OWeakObject* >(this) );
1848 }
1849
1851 throw embed::WrongStateException(
1852 "The object waits for saveCompleted() call!",
1853 static_cast< ::cppu::OWeakObject* >(this) );
1854
1855 // TODO:
1856 // throw away current document
1857 // load new document from current storage
1858 // use meaningful part of lArguments
1859}
1860
1861
1862void SAL_CALL OleEmbeddedObject::breakLink( const uno::Reference< embed::XStorage >& xStorage,
1863 const OUString& sEntName )
1864{
1865 // begin wrapping related part ====================
1866 uno::Reference< embed::XLinkageSupport > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1867 if ( xWrappedObject.is() )
1868 {
1869 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1870 xWrappedObject->breakLink( xStorage, sEntName );
1871 return;
1872 }
1873 // end wrapping related part ====================
1874
1875 ::osl::MutexGuard aGuard( m_aMutex );
1876 if ( m_bDisposed )
1877 throw lang::DisposedException(); // TODO
1878
1879 if ( !xStorage.is() )
1880 throw lang::IllegalArgumentException( "No parent storage is provided!",
1881 static_cast< ::cppu::OWeakObject* >(this),
1882 1 );
1883
1884 if ( sEntName.isEmpty() )
1885 throw lang::IllegalArgumentException( "Empty element name is provided!",
1886 static_cast< ::cppu::OWeakObject* >(this),
1887 2 );
1888
1889 // TODO: The object must be at least in Running state;
1890 if ( !m_bIsLink || m_nObjectState == -1 || !m_pOleComponent )
1891 {
1892 // it must be a linked initialized object
1893 throw embed::WrongStateException(
1894 "The object is not a valid linked object!",
1895 static_cast< ::cppu::OWeakObject* >(this) );
1896 }
1897
1898 if ( m_bReadOnly )
1899 throw io::IOException(); // TODO: Access denied
1900
1902 throw embed::WrongStateException(
1903 "The object waits for saveCompleted() call!",
1904 static_cast< ::cppu::OWeakObject* >(this) );
1905
1906
1907#ifdef _WIN32
1908 // TODO: create an object based on the link
1909
1910 // disconnect the old temporary URL
1911 OUString aOldTempURL = m_aTempURL;
1912 m_aTempURL.clear();
1913
1914 rtl::Reference<OleComponent> pNewOleComponent = new OleComponent(m_xContext, this);
1915 try {
1916 pNewOleComponent->InitEmbeddedCopyOfLink(m_pOleComponent);
1917 }
1918 catch (const uno::Exception&)
1919 {
1920 if (!m_aTempURL.isEmpty())
1922 m_aTempURL = aOldTempURL;
1923 throw;
1924 }
1925
1926 try {
1928 }
1929 catch (const uno::Exception&)
1930 {
1931 if (!m_aTempURL.isEmpty())
1933 m_aTempURL = aOldTempURL;
1934 throw;
1935 }
1936
1937 KillFile_Impl(aOldTempURL, m_xContext);
1938
1939 CreateOleComponent_Impl(pNewOleComponent);
1940
1941 if (m_xParentStorage != xStorage || !m_aEntryName.equals(sEntName))
1942 SwitchOwnPersistence(xStorage, sEntName);
1943
1944 if (m_nObjectState != embed::EmbedStates::LOADED)
1945 {
1946 // TODO: should we activate the new object if the link was activated?
1947
1948 const sal_Int32 nTargetState = m_nObjectState;
1949 m_nObjectState = embed::EmbedStates::LOADED;
1950
1951 if (nTargetState == embed::EmbedStates::RUNNING)
1952 m_pOleComponent->RunObject(); // the object already was in running state, the server must be installed
1953 else // nTargetState == embed::EmbedStates::ACTIVE
1954 {
1955 m_pOleComponent->RunObject(); // the object already was in running state, the server must be installed
1956 m_pOleComponent->ExecuteVerb(embed::EmbedVerbs::MS_OLEVERB_OPEN);
1957 }
1958
1959 m_nObjectState = nTargetState;
1960 }
1961
1962 m_bIsLink = false;
1963 m_aLinkURL.clear();
1964#else // ! _WIN32
1965 throw io::IOException(); //TODO:
1966#endif // _WIN32
1967}
1968
1969
1971{
1972 // begin wrapping related part ====================
1973 uno::Reference< embed::XLinkageSupport > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1974 if ( xWrappedObject.is() )
1975 {
1976 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1977 return xWrappedObject->isLink();
1978 }
1979 // end wrapping related part ====================
1980
1981 ::osl::MutexGuard aGuard( m_aMutex );
1982 if ( m_bDisposed )
1983 throw lang::DisposedException(); // TODO
1984
1985 return m_bIsLink;
1986}
1987
1988
1990{
1991 // begin wrapping related part ====================
1992 uno::Reference< embed::XLinkageSupport > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
1993 if ( xWrappedObject.is() )
1994 {
1995 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
1996 return xWrappedObject->getLinkURL();
1997 }
1998 // end wrapping related part ====================
1999
2000 ::osl::MutexGuard aGuard( m_aMutex );
2001 if ( m_bDisposed )
2002 throw lang::DisposedException(); // TODO
2003
2005 throw embed::WrongStateException(
2006 "The object waits for saveCompleted() call!",
2007 static_cast< ::cppu::OWeakObject* >(this) );
2008
2009 if ( !m_bIsLink )
2010 throw embed::WrongStateException(
2011 "The object is not a link object!",
2012 static_cast< ::cppu::OWeakObject* >(this) );
2013
2014 // TODO: probably the link URL can be retrieved from OLE
2015
2016 return m_aLinkURL;
2017}
2018
2019/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< XComponentContext > m_xContext
Reference< XInputStream > xStream
css::uno::Reference< css::embed::XEmbeddedClient > m_xClientSite
Definition: oleembobj.hxx:141
css::uno::Reference< css::io::XStream > TryToGetAcceptableFormat_Impl(const css::uno::Reference< css::io::XStream > &xStream)
Definition: olepersist.cxx:274
OUString m_aNewEntryName
Definition: oleembobj.hxx:150
css::uno::Reference< css::io::XStream > m_xCachedVisualRepresentation
Definition: oleembobj.hxx:155
void StoreToLocation_Impl(const css::uno::Reference< css::embed::XStorage > &xStorage, const OUString &sEntName, const css::uno::Sequence< css::beans::PropertyValue > &lObjArgs, bool bSaveAs)
virtual css::awt::Size SAL_CALL getVisualAreaSize(sal_Int64 nAspect) override
Definition: olevisual.cxx:158
css::uno::Reference< css::io::XStream > TryToRetrieveCachedVisualRepresentation_Impl(const css::uno::Reference< css::io::XStream > &xStream, bool bAllowRepair50=false) noexcept
Definition: olepersist.cxx:595
virtual OUString SAL_CALL getLinkURL() override
css::uno::Reference< css::io::XStream > GetNewFilledTempStream_Impl(const css::uno::Reference< css::io::XInputStream > &xInStream)
Definition: olepersist.cxx:257
virtual void SAL_CALL storeOwn() override
css::uno::Reference< css::util::XCloseListener > m_xClosePreventer
Definition: oleembobj.hxx:145
void RemoveVisualCache_Impl(const css::uno::Reference< css::io::XStream > &xTargetStream)
Definition: olepersist.cxx:497
css::uno::Reference< css::embed::XStorage > m_xParentStorage
Definition: oleembobj.hxx:180
css::uno::Reference< css::io::XStream > m_xNewCachedVisRepl
Definition: oleembobj.hxx:149
virtual sal_Bool SAL_CALL hasEntry() override
void MakeEventListenerNotification_Impl(const OUString &aEventName)
Definition: olemisc.cxx:157
css::uno::Reference< css::io::XStream > m_xNewObjectStream
Definition: oleembobj.hxx:152
::osl::Mutex m_aMutex
Definition: oleembobj.hxx:123
virtual OUString SAL_CALL getEntryName() override
css::uno::Sequence< sal_Int8 > m_aClassID
Definition: oleembobj.hxx:138
virtual void SAL_CALL storeAsEntry(const css::uno::Reference< css::embed::XStorage > &xStorage, const OUString &sEntName, const css::uno::Sequence< css::beans::PropertyValue > &lArguments, const css::uno::Sequence< css::beans::PropertyValue > &lObjArgs) override
OUString m_aLinkURL
Definition: oleembobj.hxx:184
OUString m_aEntryName
Definition: oleembobj.hxx:179
bool m_bNewVisReplInStream
Definition: oleembobj.hxx:148
void SetVisReplInStream(bool bExists)
Definition: olepersist.cxx:523
virtual sal_Bool SAL_CALL isReadonly() override
virtual sal_Bool SAL_CALL isLink() override
virtual void SAL_CALL setPersistentEntry(const css::uno::Reference< css::embed::XStorage > &xStorage, const OUString &sEntName, sal_Int32 nEntryConnectionMode, const css::uno::Sequence< css::beans::PropertyValue > &lArguments, const css::uno::Sequence< css::beans::PropertyValue > &lObjArgs) override
void InsertVisualCache_Impl(const css::uno::Reference< css::io::XStream > &xTargetStream, const css::uno::Reference< css::io::XStream > &xCachedVisualRepresentation)
Definition: olepersist.cxx:355
rtl::Reference< OleComponent > m_pOleComponent
Definition: oleembobj.hxx:125
bool m_bVisReplInitialized
Definition: oleembobj.hxx:156
void SwitchOwnPersistence(const css::uno::Reference< css::embed::XStorage > &xNewParentStorage, const css::uno::Reference< css::io::XStream > &xNewObjectStream, const OUString &aNewName)
friend class OleComponent
Definition: oleembobj.hxx:121
css::uno::Reference< css::uno::XComponentContext > m_xContext
Definition: oleembobj.hxx:136
VerbExecutionController m_aVerbExecutionController
Definition: oleembobj.hxx:198
virtual void SAL_CALL storeToEntry(const css::uno::Reference< css::embed::XStorage > &xStorage, const OUString &sEntName, const css::uno::Sequence< css::beans::PropertyValue > &lArguments, const css::uno::Sequence< css::beans::PropertyValue > &lObjArgs) override
css::uno::Reference< css::io::XStream > m_xObjectStream
Definition: oleembobj.hxx:181
virtual void SAL_CALL saveCompleted(sal_Bool bUseNew) override
void GetRidOfComponent()
Definition: olemisc.cxx:224
css::uno::Reference< css::embed::XStorage > m_xNewParentStorage
Definition: oleembobj.hxx:151
virtual void SAL_CALL reload(const css::uno::Sequence< css::beans::PropertyValue > &lArguments, const css::uno::Sequence< css::beans::PropertyValue > &lObjArgs) override
sal_Int32 m_nObjectState
Definition: oleembobj.hxx:132
css::uno::Reference< css::embed::XEmbeddedObject > m_xWrappedObject
Definition: oleembobj.hxx:201
OUString m_aTempURL
Definition: oleembobj.hxx:192
sal_Int32 m_nUpdateMode
Definition: oleembobj.hxx:134
bool HasVisReplInStream()
Definition: olepersist.cxx:530
virtual void SAL_CALL breakLink(const css::uno::Reference< css::embed::XStorage > &xStorage, const OUString &sEntName) override
bool m_bStreamReadOnly
If it is allowed to modify entries in the stream of the OLE storage.
Definition: oleembobj.hxx:208
::osl::Mutex m_aVerbExecutionMutex
Definition: oleembobj.hxx:50
sal_Int32 m_nNotificationLock
Definition: oleembobj.hxx:52
static void CopyInputToOutput(const css::uno::Reference< css::io::XInputStream > &xInput, const css::uno::Reference< css::io::XOutputStream > &xOutput)
#define SO3_OUT_CLASSID
URL aURL
sal_Int32 nIndex
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
std::unique_ptr< sal_Int32[]> pData
constexpr OUStringLiteral aData
OUString GetNewTempFileURL_Impl(const uno::Reference< uno::XComponentContext > &xContext)
Definition: olepersist.cxx:85
bool KillFile_Impl(const OUString &aURL, const uno::Reference< uno::XComponentContext > &xContext)
Definition: olepersist.cxx:62
static void LetCommonStoragePassBeUsed_Impl(const uno::Reference< io::XStream > &xStream)
Definition: olepersist.cxx:195
OUString GetNewFilledTempFile_Impl(const uno::Reference< io::XInputStream > &xInStream, const uno::Reference< uno::XComponentContext > &xContext)
Definition: olepersist.cxx:110
unsigned char sal_uInt8
#define SAL_MAX_INT32
unsigned char sal_Bool
signed char sal_Int8
sal_Int32 nLength