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