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