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