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