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