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