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