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