File: | home/maarten/src/libreoffice/core/include/tools/ref.hxx |
Warning: | line 97, column 56 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 <sfx2/docfile.hxx> | ||||
21 | #include <sfx2/docfilt.hxx> | ||||
22 | #include <sfx2/sfxsids.hrc> | ||||
23 | #include <filter/msfilter/msoleexp.hxx> | ||||
24 | #include <svx/svxerr.hxx> | ||||
25 | #include <unotools/fltrcfg.hxx> | ||||
26 | #include <unotools/streamwrap.hxx> | ||||
27 | #include <sot/storage.hxx> | ||||
28 | #include <comphelper/sequenceashashmap.hxx> | ||||
29 | #include <comphelper/processfactory.hxx> | ||||
30 | |||||
31 | #include <com/sun/star/packages/XPackageEncryption.hpp> | ||||
32 | #include <com/sun/star/uno/XComponentContext.hpp> | ||||
33 | |||||
34 | #include <sdpptwrp.hxx> | ||||
35 | #include <DrawDocShell.hxx> | ||||
36 | #include <sfx2/frame.hxx> | ||||
37 | |||||
38 | using namespace ::com::sun::star::uno; | ||||
39 | using namespace ::com::sun::star::beans; | ||||
40 | using namespace ::com::sun::star::task; | ||||
41 | using namespace ::com::sun::star::frame; | ||||
42 | |||||
43 | typedef sal_Bool ( *ExportPPTPointer )( const std::vector< css::beans::PropertyValue >&, tools::SvRef<SotStorage> const&, | ||||
44 | Reference< XModel > const &, | ||||
45 | Reference< XStatusIndicator > const &, | ||||
46 | SvMemoryStream*, sal_uInt32 nCnvrtFlags ); | ||||
47 | |||||
48 | typedef sal_Bool ( *ImportPPTPointer )( SdDrawDocument*, SvStream&, SotStorage&, SfxMedium& ); | ||||
49 | |||||
50 | typedef sal_Bool ( *SaveVBAPointer )( SfxObjectShell&, SvMemoryStream*& ); | ||||
51 | |||||
52 | #ifdef DISABLE_DYNLOADING | ||||
53 | |||||
54 | extern "C" sal_Bool ExportPPT( const std::vector< css::beans::PropertyValue >&, tools::SvRef<SotStorage> const&, | ||||
55 | Reference< XModel > const &, | ||||
56 | Reference< XStatusIndicator > const &, | ||||
57 | SvMemoryStream*, sal_uInt32 nCnvrtFlags ); | ||||
58 | |||||
59 | extern "C" sal_Bool ImportPPT( SdDrawDocument*, SvStream&, SotStorage&, SfxMedium& ); | ||||
60 | |||||
61 | extern "C" sal_Bool SaveVBA( SfxObjectShell&, SvMemoryStream*& ); | ||||
62 | |||||
63 | #endif | ||||
64 | |||||
65 | |||||
66 | SdPPTFilter::SdPPTFilter( SfxMedium& rMedium, ::sd::DrawDocShell& rDocShell ) : | ||||
67 | SdFilter( rMedium, rDocShell ), | ||||
68 | pBas ( nullptr ) | ||||
69 | { | ||||
70 | } | ||||
71 | |||||
72 | SdPPTFilter::~SdPPTFilter() | ||||
73 | { | ||||
74 | delete pBas; // deleting the compressed basic storage | ||||
75 | } | ||||
76 | |||||
77 | static void lcl_getListOfStreams(SotStorage * pStorage, comphelper::SequenceAsHashMap& aStreamsData, const OUString& sPrefix) | ||||
78 | { | ||||
79 | SvStorageInfoList aElements; | ||||
80 | pStorage->FillInfoList(&aElements); | ||||
81 | for (const auto & aElement : aElements) | ||||
82 | { | ||||
83 | OUString sStreamFullName = sPrefix.getLength() ? sPrefix + "/" + aElement.GetName() : aElement.GetName(); | ||||
84 | if (aElement.IsStorage()) | ||||
85 | { | ||||
86 | tools::SvRef<SotStorage> xSubStorage = pStorage->OpenSotStorage(aElement.GetName(), StreamMode::STD_READ | StreamMode::SHARE_DENYALL); | ||||
87 | lcl_getListOfStreams(xSubStorage.get(), aStreamsData, sStreamFullName); | ||||
88 | } | ||||
89 | else | ||||
90 | { | ||||
91 | // Read stream | ||||
92 | tools::SvRef<SotStorageStream> rStream = pStorage->OpenSotStream(aElement.GetName(), StreamMode::READ | StreamMode::SHARE_DENYALL); | ||||
93 | if (rStream.is()) | ||||
94 | { | ||||
95 | sal_Int32 nStreamSize = rStream->GetSize(); | ||||
96 | Sequence< sal_Int8 > oData; | ||||
97 | oData.realloc(nStreamSize); | ||||
98 | sal_Int32 nReadBytes = rStream->ReadBytes(oData.getArray(), nStreamSize); | ||||
99 | if (nStreamSize == nReadBytes) | ||||
100 | aStreamsData[sStreamFullName] <<= oData; | ||||
101 | } | ||||
102 | } | ||||
103 | } | ||||
104 | } | ||||
105 | |||||
106 | static tools::SvRef<SotStorage> lcl_DRMDecrypt(const SfxMedium& rMedium, const tools::SvRef<SotStorage>& rStorage, std::shared_ptr<SvStream>& rNewStorageStrm) | ||||
107 | { | ||||
108 | tools::SvRef<SotStorage> aNewStorage; | ||||
109 | |||||
110 | // We have DRM encrypted storage. We should try to decrypt it first, if we can | ||||
111 | Sequence< Any > aArguments; | ||||
112 | Reference<XComponentContext> xComponentContext(comphelper::getProcessComponentContext()); | ||||
113 | Reference< css::packages::XPackageEncryption > xPackageEncryption( | ||||
114 | xComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext( | ||||
115 | "com.sun.star.comp.oox.crypto.DRMDataSpace", aArguments, xComponentContext), UNO_QUERY); | ||||
116 | |||||
117 | if (!xPackageEncryption.is()) | ||||
118 | { | ||||
119 | // We do not know how to decrypt this | ||||
120 | return aNewStorage; | ||||
121 | } | ||||
122 | |||||
123 | comphelper::SequenceAsHashMap aStreamsData; | ||||
124 | lcl_getListOfStreams(rStorage.get(), aStreamsData, ""); | ||||
125 | |||||
126 | try { | ||||
127 | Sequence<NamedValue> aStreams = aStreamsData.getAsConstNamedValueList(); | ||||
128 | if (!xPackageEncryption->readEncryptionInfo(aStreams)) | ||||
129 | { | ||||
130 | // We failed with decryption | ||||
131 | return aNewStorage; | ||||
132 | } | ||||
133 | |||||
134 | tools::SvRef<SotStorageStream> rContentStream = rStorage->OpenSotStream("\011DRMContent", StreamMode::READ | StreamMode::SHARE_DENYALL); | ||||
135 | if (!rContentStream.is()) | ||||
136 | { | ||||
137 | return aNewStorage; | ||||
138 | } | ||||
139 | |||||
140 | rNewStorageStrm = std::make_shared<SvMemoryStream>(); | ||||
141 | |||||
142 | Reference<css::io::XInputStream > xInputStream(new utl::OSeekableInputStreamWrapper(rContentStream.get(), false)); | ||||
143 | Reference<css::io::XOutputStream > xDecryptedStream(new utl::OSeekableOutputStreamWrapper(*rNewStorageStrm)); | ||||
144 | |||||
145 | if (!xPackageEncryption->decrypt(xInputStream, xDecryptedStream)) | ||||
146 | { | ||||
147 | // We failed with decryption | ||||
148 | return aNewStorage; | ||||
149 | } | ||||
150 | |||||
151 | rNewStorageStrm->Seek(0); | ||||
152 | |||||
153 | // Further reading is done from new document | ||||
154 | aNewStorage = new SotStorage(*rNewStorageStrm); | ||||
155 | |||||
156 | // Set the media descriptor data | ||||
157 | Sequence<NamedValue> aEncryptionData = xPackageEncryption->createEncryptionData(""); | ||||
158 | rMedium.GetItemSet()->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA(5000 + 1722), makeAny(aEncryptionData))); | ||||
159 | } | ||||
160 | catch (const std::exception&) | ||||
161 | { | ||||
162 | return aNewStorage; | ||||
163 | } | ||||
164 | |||||
165 | return aNewStorage; | ||||
166 | } | ||||
167 | |||||
168 | bool SdPPTFilter::Import() | ||||
169 | { | ||||
170 | bool bRet = false; | ||||
171 | std::shared_ptr<SvStream> aDecryptedStorageStrm; | ||||
172 | tools::SvRef<SotStorage> pStorage = new SotStorage( mrMedium.GetInStream(), false ); | ||||
173 | if( !pStorage->GetError() ) | ||||
174 | { | ||||
175 | /* check if there is a dualstorage, then the | ||||
176 | document is probably a PPT95 containing PPT97 */ | ||||
177 | tools::SvRef<SotStorage> xDualStorage; | ||||
178 | OUString sDualStorage( "PP97_DUALSTORAGE" ); | ||||
179 | if ( pStorage->IsContained( sDualStorage ) ) | ||||
180 | { | ||||
181 | xDualStorage = pStorage->OpenSotStorage( sDualStorage, StreamMode::STD_READ ); | ||||
182 | pStorage = xDualStorage; | ||||
183 | } | ||||
184 | if (pStorage->IsContained("\011DRMContent")) | ||||
185 | { | ||||
186 | // Document is DRM encrypted | ||||
187 | pStorage = lcl_DRMDecrypt(mrMedium, pStorage, aDecryptedStorageStrm); | ||||
188 | } | ||||
189 | std::unique_ptr<SvStream> pDocStream(pStorage->OpenSotStream( "PowerPoint Document" , StreamMode::STD_READ )); | ||||
190 | if( pDocStream ) | ||||
191 | { | ||||
192 | pDocStream->SetVersion( pStorage->GetVersion() ); | ||||
193 | pDocStream->SetCryptMaskKey(pStorage->GetKey()); | ||||
194 | |||||
195 | if ( pStorage->IsStream( "EncryptedSummary" ) ) | ||||
196 | mrMedium.SetError(ERRCODE_SVX_READ_FILTER_PPOINTErrCode( ErrCodeArea::Svx, ErrCodeClass::Read, 17)); | ||||
197 | else | ||||
198 | { | ||||
199 | #ifdef DISABLE_DYNLOADING | ||||
200 | ImportPPTPointer pPPTImport = ImportPPT; | ||||
201 | #else | ||||
202 | ImportPPTPointer pPPTImport = reinterpret_cast< ImportPPTPointer >( | ||||
203 | SdFilter::GetLibrarySymbol(mrMedium.GetFilter()->GetUserData(), "ImportPPT")); | ||||
204 | #endif | ||||
205 | |||||
206 | if ( pPPTImport ) | ||||
207 | bRet = pPPTImport( &mrDocument, *pDocStream, *pStorage, mrMedium ); | ||||
208 | |||||
209 | if ( !bRet ) | ||||
210 | mrMedium.SetError(SVSTREAM_WRONGVERSIONErrCode( ErrCodeArea::Io, ErrCodeClass::Version, 20 )); | ||||
211 | } | ||||
212 | } | ||||
213 | } | ||||
214 | |||||
215 | return bRet; | ||||
216 | } | ||||
217 | |||||
218 | bool SdPPTFilter::Export() | ||||
219 | { | ||||
220 | bool bRet = false; | ||||
221 | |||||
222 | if( mxModel.is() ) | ||||
| |||||
223 | { | ||||
224 | #ifdef DISABLE_DYNLOADING | ||||
225 | ExportPPTPointer PPTExport = ExportPPT; | ||||
226 | #else | ||||
227 | ExportPPTPointer PPTExport = reinterpret_cast< ExportPPTPointer >( | ||||
228 | SdFilter::GetLibrarySymbol(mrMedium.GetFilter()->GetUserData(), "ExportPPT")); | ||||
229 | #endif | ||||
230 | |||||
231 | if( PPTExport) | ||||
232 | { | ||||
233 | sal_uInt32 nCnvrtFlags = 0; | ||||
234 | const SvtFilterOptions& rFilterOptions = SvtFilterOptions::Get(); | ||||
235 | if ( rFilterOptions.IsMath2MathType() ) | ||||
236 | nCnvrtFlags |= OLE_STARMATH_2_MATHTYPE0x0001; | ||||
237 | if ( rFilterOptions.IsWriter2WinWord() ) | ||||
238 | nCnvrtFlags |= OLE_STARWRITER_2_WINWORD0x0002; | ||||
239 | if ( rFilterOptions.IsCalc2Excel() ) | ||||
240 | nCnvrtFlags |= OLE_STARCALC_2_EXCEL0x0004; | ||||
241 | if ( rFilterOptions.IsImpress2PowerPoint() ) | ||||
242 | nCnvrtFlags |= OLE_STARIMPRESS_2_POWERPOINT0x0008; | ||||
243 | if ( rFilterOptions.IsEnablePPTPreview() ) | ||||
244 | nCnvrtFlags |= 0x8000; | ||||
245 | |||||
246 | CreateStatusIndicator(); | ||||
247 | |||||
248 | //OUString sBaseURI( "BaseURI"); | ||||
249 | std::vector< PropertyValue > aProperties; | ||||
250 | PropertyValue aProperty; | ||||
251 | aProperty.Name = "BaseURI"; | ||||
252 | aProperty.Value <<= mrMedium.GetBaseURL( true ); | ||||
253 | aProperties.push_back( aProperty ); | ||||
254 | |||||
255 | SvStream * pOutputStrm = mrMedium.GetOutStream(); | ||||
256 | |||||
257 | Sequence< NamedValue > aEncryptionData; | ||||
258 | Reference< css::packages::XPackageEncryption > xPackageEncryption; | ||||
259 | const SfxUnoAnyItem* pEncryptionDataItem = SfxItemSet::GetItem<SfxUnoAnyItem>(mrMedium.GetItemSet(), SID_ENCRYPTIONDATA(5000 + 1722), false); | ||||
260 | std::shared_ptr<SvStream> pMediaStrm; | ||||
261 | if (pEncryptionDataItem
| ||||
262 | { | ||||
263 | ::comphelper::SequenceAsHashMap aHashData(aEncryptionData); | ||||
264 | OUString sCryptoType = aHashData.getUnpackedValueOrDefault("CryptoType", OUString()); | ||||
265 | |||||
266 | if (sCryptoType.getLength()) | ||||
267 | { | ||||
268 | Reference<XComponentContext> xComponentContext(comphelper::getProcessComponentContext()); | ||||
269 | Sequence<Any> aArguments{ | ||||
270 | makeAny(NamedValue("Binary", makeAny(true))) }; | ||||
271 | xPackageEncryption.set( | ||||
272 | xComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext( | ||||
273 | "com.sun.star.comp.oox.crypto." + sCryptoType, aArguments, xComponentContext), UNO_QUERY); | ||||
274 | |||||
275 | if (xPackageEncryption.is()) | ||||
276 | { | ||||
277 | // We have an encryptor. Export document into memory stream and encrypt it later | ||||
278 | pMediaStrm = std::make_shared<SvMemoryStream>(); | ||||
279 | pOutputStrm = pMediaStrm.get(); | ||||
280 | |||||
281 | // Temp removal of EncryptionData to avoid password protection triggering | ||||
282 | mrMedium.GetItemSet()->ClearItem(SID_ENCRYPTIONDATA(5000 + 1722)); | ||||
283 | } | ||||
284 | } | ||||
285 | } | ||||
286 | |||||
287 | tools::SvRef<SotStorage> xStorRef = new SotStorage(pOutputStrm, false); | ||||
288 | |||||
289 | if (xStorRef.is()) | ||||
290 | { | ||||
291 | bRet = PPTExport(aProperties, xStorRef, mxModel, mxStatusIndicator, pBas, nCnvrtFlags); | ||||
292 | xStorRef->Commit(); | ||||
293 | |||||
294 | if (xPackageEncryption.is()) | ||||
295 | { | ||||
296 | // Perform DRM encryption | ||||
297 | pOutputStrm->Seek(0); | ||||
298 | |||||
299 | xPackageEncryption->setupEncryption(aEncryptionData); | ||||
300 | |||||
301 | Reference<css::io::XInputStream > xInputStream(new utl::OSeekableInputStreamWrapper(pOutputStrm, false)); | ||||
302 | Sequence<NamedValue> aStreams = xPackageEncryption->encrypt(xInputStream); | ||||
303 | |||||
304 | tools::SvRef<SotStorage> xEncryptedRootStrg = new SotStorage(mrMedium.GetOutStream(), false); | ||||
305 | for (const NamedValue & aStreamData : std::as_const(aStreams)) | ||||
306 | { | ||||
307 | // To avoid long paths split and open substorages recursively | ||||
308 | // Splitting paths manually, since comphelper::string::split is trimming special characters like \0x01, \0x09 | ||||
309 | tools::SvRef<SotStorage> pStorage = xEncryptedRootStrg.get(); | ||||
310 | OUString sFileName; | ||||
311 | sal_Int32 idx = 0; | ||||
312 | do | ||||
313 | { | ||||
314 | OUString sPathElem = aStreamData.Name.getToken(0, L'/', idx); | ||||
315 | if (!sPathElem.isEmpty()) | ||||
316 | { | ||||
317 | if (idx < 0) | ||||
318 | { | ||||
319 | sFileName = sPathElem; | ||||
320 | } | ||||
321 | else | ||||
322 | { | ||||
323 | pStorage = pStorage->OpenSotStorage(sPathElem); | ||||
324 | } | ||||
325 | } | ||||
326 | } while (pStorage && idx >= 0); | ||||
327 | |||||
328 | if (!pStorage) | ||||
329 | { | ||||
330 | bRet = false; | ||||
331 | break; | ||||
332 | } | ||||
333 | |||||
334 | tools::SvRef<SotStorageStream> pStream = pStorage->OpenSotStream(sFileName); | ||||
335 | if (!pStream) | ||||
336 | { | ||||
337 | bRet = false; | ||||
338 | break; | ||||
339 | } | ||||
340 | Sequence<sal_Int8> aStreamContent; | ||||
341 | aStreamData.Value >>= aStreamContent; | ||||
342 | size_t nBytesWritten = pStream->WriteBytes(aStreamContent.getArray(), aStreamContent.getLength()); | ||||
343 | if (nBytesWritten != static_cast<size_t>(aStreamContent.getLength())) | ||||
344 | { | ||||
345 | bRet = false; | ||||
346 | break; | ||||
347 | } | ||||
348 | } | ||||
349 | xEncryptedRootStrg->Commit(); | ||||
350 | |||||
351 | // Restore encryption data | ||||
352 | mrMedium.GetItemSet()->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA(5000 + 1722), makeAny(aEncryptionData))); | ||||
353 | } | ||||
354 | } | ||||
355 | } | ||||
356 | } | ||||
357 | |||||
358 | return bRet; | ||||
359 | } | ||||
360 | |||||
361 | void SdPPTFilter::PreSaveBasic() | ||||
362 | { | ||||
363 | const SvtFilterOptions& rFilterOptions = SvtFilterOptions::Get(); | ||||
364 | if( rFilterOptions.IsLoadPPointBasicStorage() ) | ||||
365 | { | ||||
366 | #ifdef DISABLE_DYNLOADING | ||||
367 | SaveVBAPointer pSaveVBA= SaveVBA; | ||||
368 | #else | ||||
369 | SaveVBAPointer pSaveVBA = reinterpret_cast< SaveVBAPointer >( | ||||
370 | SdFilter::GetLibrarySymbol(mrMedium.GetFilter()->GetUserData(), "SaveVBA")); | ||||
371 | #endif | ||||
372 | if( pSaveVBA ) | ||||
373 | pSaveVBA( static_cast<SfxObjectShell&>(mrDocShell), pBas ); | ||||
374 | } | ||||
375 | } | ||||
376 | |||||
377 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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 | #ifndef INCLUDED_TOOLS_REF_HXX | |||
20 | #define INCLUDED_TOOLS_REF_HXX | |||
21 | ||||
22 | #include <sal/config.h> | |||
23 | #include <cassert> | |||
24 | #include <tools/toolsdllapi.h> | |||
25 | #include <utility> | |||
26 | ||||
27 | /** | |||
28 | This implements similar functionality to boost::intrusive_ptr | |||
29 | */ | |||
30 | ||||
31 | namespace tools { | |||
32 | ||||
33 | /** T must be a class that extends SvRefBase */ | |||
34 | template<typename T> class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SvRef final { | |||
35 | public: | |||
36 | SvRef(): pObj(nullptr) {} | |||
37 | ||||
38 | SvRef(SvRef&& rObj) noexcept | |||
39 | { | |||
40 | pObj = rObj.pObj; | |||
41 | rObj.pObj = nullptr; | |||
42 | } | |||
43 | ||||
44 | SvRef(SvRef const & rObj): pObj(rObj.pObj) | |||
45 | { | |||
46 | if (pObj != nullptr) pObj->AddNextRef(); | |||
47 | } | |||
48 | ||||
49 | SvRef(T * pObjP): pObj(pObjP) | |||
50 | { | |||
51 | if (pObj != nullptr) pObj->AddFirstRef(); | |||
52 | } | |||
53 | ||||
54 | ~SvRef() | |||
55 | { | |||
56 | if (pObj != nullptr) pObj->ReleaseRef(); | |||
57 | } | |||
58 | ||||
59 | void clear() | |||
60 | { | |||
61 | if (pObj != nullptr) { | |||
62 | T * pRefObj = pObj; | |||
63 | pObj = nullptr; | |||
64 | pRefObj->ReleaseRef(); | |||
65 | } | |||
66 | } | |||
67 | ||||
68 | SvRef & operator =(SvRef const & rObj) | |||
69 | { | |||
70 | if (rObj.pObj != nullptr) { | |||
71 | rObj.pObj->AddNextRef(); | |||
72 | } | |||
73 | T * pRefObj = pObj; | |||
74 | pObj = rObj.pObj; | |||
75 | if (pRefObj != nullptr) { | |||
76 | pRefObj->ReleaseRef(); | |||
77 | } | |||
78 | return *this; | |||
79 | } | |||
80 | ||||
81 | SvRef & operator =(SvRef && rObj) | |||
82 | { | |||
83 | if (pObj != nullptr) { | |||
84 | pObj->ReleaseRef(); | |||
85 | } | |||
86 | pObj = rObj.pObj; | |||
87 | rObj.pObj = nullptr; | |||
88 | return *this; | |||
89 | } | |||
90 | ||||
91 | bool is() const { return pObj != nullptr; } | |||
92 | ||||
93 | explicit operator bool() const { return is(); } | |||
94 | ||||
95 | T * get() const { return pObj; } | |||
96 | ||||
97 | T * operator ->() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail ("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 97, __extension__ __PRETTY_FUNCTION__)); return pObj; } | |||
| ||||
98 | ||||
99 | T & operator *() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail ("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 99, __extension__ __PRETTY_FUNCTION__)); return *pObj; } | |||
100 | ||||
101 | bool operator ==(const SvRef<T> &rhs) const { return pObj == rhs.pObj; } | |||
102 | bool operator !=(const SvRef<T> &rhs) const { return !(*this == rhs); } | |||
103 | ||||
104 | private: | |||
105 | T * pObj; | |||
106 | }; | |||
107 | ||||
108 | /** | |||
109 | * This implements similar functionality to std::make_shared. | |||
110 | */ | |||
111 | template<typename T, typename... Args> | |||
112 | SvRef<T> make_ref(Args&& ... args) | |||
113 | { | |||
114 | return SvRef<T>(new T(std::forward<Args>(args)...)); | |||
115 | } | |||
116 | ||||
117 | } | |||
118 | ||||
119 | /** Classes that want to be referenced-counted via SvRef<T>, should extend this base class */ | |||
120 | class TOOLS_DLLPUBLIC__attribute__ ((visibility("default"))) SvRefBase | |||
121 | { | |||
122 | // work around a clang 3.5 optimization bug: if the bNoDelete is *first* | |||
123 | // it mis-compiles "if (--nRefCount == 0)" and never deletes any object | |||
124 | unsigned int nRefCount : 31; | |||
125 | // the only reason this is not bool is because MSVC cannot handle mixed type bitfields | |||
126 | unsigned int bNoDelete : 1; | |||
127 | ||||
128 | protected: | |||
129 | virtual ~SvRefBase() COVERITY_NOEXCEPT_FALSE; | |||
130 | ||||
131 | public: | |||
132 | SvRefBase() : nRefCount(0), bNoDelete(1) {} | |||
133 | SvRefBase(const SvRefBase &) : nRefCount(0), bNoDelete(1) {} | |||
134 | ||||
135 | SvRefBase & operator=(const SvRefBase &) { return *this; } | |||
136 | ||||
137 | void RestoreNoDelete() | |||
138 | { bNoDelete = 1; } | |||
139 | ||||
140 | void AddNextRef() | |||
141 | { | |||
142 | assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) && "Do not add refs to dead objects") ? void (0) : __assert_fail ("nRefCount < (1 << 30) && \"Do not add refs to dead objects\"" , "/home/maarten/src/libreoffice/core/include/tools/ref.hxx", 142, __extension__ __PRETTY_FUNCTION__)); | |||
143 | ++nRefCount; | |||
144 | } | |||
145 | ||||
146 | void AddFirstRef() | |||
147 | { | |||
148 | assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) && "Do not add refs to dead objects") ? void (0) : __assert_fail ("nRefCount < (1 << 30) && \"Do not add refs to dead objects\"" , "/home/maarten/src/libreoffice/core/include/tools/ref.hxx", 148, __extension__ __PRETTY_FUNCTION__)); | |||
149 | if( bNoDelete ) | |||
150 | bNoDelete = 0; | |||
151 | ++nRefCount; | |||
152 | } | |||
153 | ||||
154 | void ReleaseRef() | |||
155 | { | |||
156 | assert( nRefCount >= 1)(static_cast <bool> (nRefCount >= 1) ? void (0) : __assert_fail ("nRefCount >= 1", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 156, __extension__ __PRETTY_FUNCTION__)); | |||
157 | if( --nRefCount == 0 && !bNoDelete) | |||
158 | { | |||
159 | // I'm not sure about the original purpose of this line, but right now | |||
160 | // it serves the purpose that anything that attempts to do an AddRef() | |||
161 | // after an object is deleted will trip an assert. | |||
162 | nRefCount = 1 << 30; | |||
163 | delete this; | |||
164 | } | |||
165 | } | |||
166 | ||||
167 | unsigned int GetRefCount() const | |||
168 | { return nRefCount; } | |||
169 | }; | |||
170 | ||||
171 | template<typename T> | |||
172 | class SvCompatWeakBase; | |||
173 | ||||
174 | /** SvCompatWeakHdl acts as an intermediary between SvCompatWeakRef<T> and T. | |||
175 | */ | |||
176 | template<typename T> | |||
177 | class SvCompatWeakHdl final : public SvRefBase | |||
178 | { | |||
179 | friend class SvCompatWeakBase<T>; | |||
180 | T* _pObj; | |||
181 | ||||
182 | SvCompatWeakHdl( T* pObj ) : _pObj( pObj ) {} | |||
183 | ||||
184 | public: | |||
185 | void ResetWeakBase( ) { _pObj = nullptr; } | |||
186 | T* GetObj() { return _pObj; } | |||
187 | }; | |||
188 | ||||
189 | /** We only have one place that extends this, in include/sfx2/frame.hxx, class SfxFrame. | |||
190 | Its function is to notify the SvCompatWeakHdl when an SfxFrame object is deleted. | |||
191 | */ | |||
192 | template<typename T> | |||
193 | class SvCompatWeakBase | |||
194 | { | |||
195 | tools::SvRef< SvCompatWeakHdl<T> > _xHdl; | |||
196 | ||||
197 | public: | |||
198 | /** Does not use initializer due to compiler warnings, | |||
199 | because the lifetime of the _xHdl object can exceed the lifetime of this class. | |||
200 | */ | |||
201 | SvCompatWeakBase( T* pObj ) { _xHdl = new SvCompatWeakHdl<T>( pObj ); } | |||
202 | ||||
203 | ~SvCompatWeakBase() { _xHdl->ResetWeakBase(); } | |||
204 | ||||
205 | SvCompatWeakHdl<T>* GetHdl() { return _xHdl.get(); } | |||
206 | }; | |||
207 | ||||
208 | /** We only have one weak reference in LO, in include/sfx2/frame.hxx, class SfxFrameWeak. | |||
209 | */ | |||
210 | template<typename T> | |||
211 | class SAL_WARN_UNUSED__attribute__((warn_unused)) SvCompatWeakRef | |||
212 | { | |||
213 | tools::SvRef< SvCompatWeakHdl<T> > _xHdl; | |||
214 | public: | |||
215 | SvCompatWeakRef( ) {} | |||
216 | SvCompatWeakRef( T* pObj ) | |||
217 | { if( pObj ) _xHdl = pObj->GetHdl(); } | |||
218 | #if defined(__COVERITY__) | |||
219 | ~SvCompatWeakRef() COVERITY_NOEXCEPT_FALSE {} | |||
220 | #endif | |||
221 | SvCompatWeakRef& operator = ( T * pObj ) | |||
222 | { _xHdl = pObj ? pObj->GetHdl() : nullptr; return *this; } | |||
223 | bool is() const | |||
224 | { return _xHdl.is() && _xHdl->GetObj(); } | |||
225 | explicit operator bool() const { return is(); } | |||
226 | T* operator -> () const | |||
227 | { return _xHdl.is() ? _xHdl->GetObj() : nullptr; } | |||
228 | operator T* () const | |||
229 | { return _xHdl.is() ? _xHdl->GetObj() : nullptr; } | |||
230 | }; | |||
231 | ||||
232 | #endif | |||
233 | ||||
234 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |