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 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 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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 //----------------------------------------------- 265 void VerbExecutionController::LockNotification() 266 { 267 osl::MutexGuard aGuard( m_aVerbExecutionMutex ); 268 if ( m_nNotificationLock < SAL_MAX_INT32 ) 269 m_nNotificationLock++; 270 } 271 272 //----------------------------------------------- 273 void VerbExecutionController::UnlockNotification() 274 { 275 osl::MutexGuard aGuard( m_aVerbExecutionMutex ); 276 if ( m_nNotificationLock > 0 ) 277 m_nNotificationLock--; 278 } 279 280 //----------------------------------------------- 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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 //------------------------------------------------------ 629 void OleEmbeddedObject::SetVisReplInStream( sal_Bool bExists ) 630 { 631 m_bVisReplInitialized = sal_True; 632 m_bVisReplInStream = bExists; 633 } 634 635 //------------------------------------------------------ 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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 //---------------------------------------------- 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 //---------------------------------------------- 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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 //---------------------------------------------- 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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 persistent representation without initialization 1421 1422 // if the object is loaded 1423 // it can switch persistent representation only without initialization 1424 1425 throw embed::WrongStateException( 1426 ::rtl::OUString::createFromAscii( "Can't change persistent 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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 //------------------------------------------------------ 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