Branch data Line data Source code
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 : :
21 : : #include <sot/storinfo.hxx>
22 : : #include <osl/file.hxx>
23 : : #include <tools/tempfile.hxx>
24 : : #include <tools/string.hxx>
25 : : #include <tools/fsys.hxx>
26 : : #include <tools/stream.hxx>
27 : : #include <tools/debug.hxx>
28 : :
29 : : #include "sot/stg.hxx"
30 : : #include "stgelem.hxx"
31 : : #include "stgcache.hxx"
32 : : #include "stgstrms.hxx"
33 : : #include "stgdir.hxx"
34 : : #include "stgio.hxx"
35 : : #include "stgole.hxx"
36 : :
37 : : static long nTmpCount = 0;
38 : :
39 : : // The internal open mode is STREAM_READ | STREAM_TRUNC, which is silly
40 : : // by itself. It inhibits the checking of sharing modes and is used
41 : : // during CopyTo() and MoveTo() for opening a stream in read mode
42 : : // although it may be open in DENYALL mode
43 : :
44 : : #define INTERNAL_MODE ( STREAM_READ | STREAM_TRUNC )
45 : :
46 : : ///////////////////////// class StorageBase //////////////////////////////
47 : :
48 [ - + ]: 598 : TYPEINIT0( StorageBase );
49 [ # # ][ # # ]: 0 : TYPEINIT1( BaseStorageStream, StorageBase );
50 [ - + ][ - + ]: 598 : TYPEINIT1( BaseStorage, StorageBase );
51 : :
52 : 3901 : StorageBase::StorageBase()
53 : 3901 : : m_bAutoCommit( sal_False )
54 : : {
55 : 3901 : m_nMode = STREAM_READ;
56 : 3901 : m_nError = SVSTREAM_OK;
57 : 3901 : }
58 : :
59 : 3895 : StorageBase::~StorageBase()
60 : : {
61 [ - + ]: 3895 : }
62 : :
63 : : // The following three methods are declared as const, since they
64 : : // may be called from within a const method.
65 : :
66 : 4237422 : sal_uLong StorageBase::GetError() const
67 : : {
68 : 4237422 : sal_uLong n = m_nError;
69 : 4237422 : ((StorageBase*) this)->m_nError = SVSTREAM_OK;
70 : 4237422 : return n;
71 : : }
72 : :
73 : 3286 : void StorageBase::SetError( sal_uLong n ) const
74 : : {
75 [ + + ]: 3286 : if( !m_nError )
76 : 3269 : ((StorageBase*) this)->m_nError = n;
77 : 3286 : }
78 : :
79 : 2624 : void StorageBase::ResetError() const
80 : : {
81 : 2624 : ((StorageBase*) this)->m_nError = SVSTREAM_OK;
82 : 2624 : }
83 : :
84 : : // Retrieve the underlying SvStream for info purposes
85 : :
86 : 0 : const SvStream* OLEStorageBase::GetSvStream_Impl() const
87 : : {
88 [ # # ]: 0 : return pIo ? pIo->GetStrm() : NULL;
89 : : }
90 : :
91 : 3836 : OLEStorageBase::OLEStorageBase( StgIo* p, StgDirEntry* pe, StreamMode& nMode )
92 : 3836 : : nStreamMode( nMode ), pIo( p ), pEntry( pe )
93 : : {
94 [ + - ]: 3836 : if ( p )
95 : 3836 : p->IncRef();
96 [ + + ]: 3836 : if( pe )
97 : 3355 : pe->nRefCnt++;
98 : 3836 : }
99 : :
100 : 3830 : OLEStorageBase::~OLEStorageBase()
101 : : {
102 [ + + ]: 3830 : if( pEntry )
103 : : {
104 : : DBG_ASSERT( pEntry->nRefCnt, "RefCount unter 0" );
105 [ + + ]: 3698 : if( !--pEntry->nRefCnt )
106 : : {
107 [ - + ]: 3689 : if( pEntry->bZombie )
108 [ # # ]: 0 : delete pEntry;
109 : : else
110 : 3689 : pEntry->Close();
111 : : }
112 : :
113 : 3698 : pEntry = NULL;
114 : : }
115 : :
116 : :
117 [ + - ][ + + ]: 3830 : if( pIo && !pIo->DecRef() )
[ + + ]
118 : : {
119 [ + - ]: 360 : delete pIo;
120 : 360 : pIo = NULL;
121 : : }
122 : 3830 : }
123 : :
124 : : // Validate the instance for I/O
125 : :
126 : 4260994 : sal_Bool OLEStorageBase::Validate_Impl( sal_Bool bWrite ) const
127 : : {
128 [ + - ][ + + ]: 4260994 : if( pIo
[ + + ][ + - ]
[ + + ][ - + ]
[ # # ]
129 : : && pIo->pTOC
130 : : && pEntry
131 : 4260858 : && !pEntry->bInvalid
132 : 3514 : && ( !bWrite || !pEntry->bDirect || ( nStreamMode & STREAM_WRITE ) ) )
133 : 4260858 : return sal_True;
134 : 4260994 : return sal_False;
135 : : }
136 : :
137 : 5849 : sal_Bool OLEStorageBase::ValidateMode_Impl( StreamMode m, StgDirEntry* p ) const
138 : : {
139 [ + + ]: 5849 : if( m == INTERNAL_MODE )
140 : 942 : return sal_True;
141 [ + + ][ - + ]: 4907 : sal_uInt16 nCurMode = ( p && p->nRefCnt ) ? p->nMode : 0xFFFF;
142 [ + + ]: 4907 : if( ( m & 3 ) == STREAM_READ )
143 : : {
144 : : // only SHARE_DENYWRITE or SHARE_DENYALL allowed
145 [ + + ][ - + ]: 3153 : if( ( ( m & STREAM_SHARE_DENYWRITE )
[ + - ][ + - ]
146 : : && ( nCurMode & STREAM_SHARE_DENYWRITE ) )
147 : : || ( ( m & STREAM_SHARE_DENYALL )
148 : : && ( nCurMode & STREAM_SHARE_DENYALL ) ) )
149 : 3153 : return sal_True;
150 : : }
151 : : else
152 : : {
153 : : // only SHARE_DENYALL allowed
154 : : // storages open in r/o mode are OK, since only
155 : : // the commit may fail
156 [ + - ][ + - ]: 1754 : if( ( m & STREAM_SHARE_DENYALL )
157 : : && ( nCurMode & STREAM_SHARE_DENYALL ) )
158 : 1754 : return sal_True;
159 : : }
160 : 5849 : return sal_False;
161 : : }
162 : :
163 : :
164 : : //////////////////////// class StorageStream /////////////////////////////
165 : :
166 [ + - ][ # # ]: 1820 : TYPEINIT1( StorageStream, BaseStorageStream );
167 : :
168 : 3351 : StorageStream::StorageStream( StgIo* p, StgDirEntry* q, StreamMode m )
169 : 3351 : : OLEStorageBase( p, q, m_nMode ), nPos( 0L )
170 : : {
171 : : // The dir entry may be 0; this means that the stream is invalid.
172 [ + - ][ + + ]: 3351 : if( q && p )
173 : : {
174 [ + + ]: 6463 : if( q->nRefCnt == 1 )
175 : : {
176 : 3227 : q->nMode = m;
177 [ + - ]: 3227 : q->OpenStream( *p );
178 : : }
179 : : }
180 : : else
181 : 115 : m &= ~STREAM_READWRITE;
182 : 3351 : m_nMode = m;
183 : 3351 : }
184 : :
185 [ + - ]: 3351 : StorageStream::~StorageStream()
186 : : {
187 : : // Do an auto-commit if the entry is open in direct mode
188 [ + + ]: 3351 : if( m_bAutoCommit )
189 [ + - ]: 3155 : Commit();
190 [ + + ][ + - ]: 3351 : if( pEntry && pEntry->nRefCnt && pEntry->bDirect && (m_nMode & STREAM_WRITE) )
[ + + ][ + + ]
191 [ + - ]: 9 : pEntry->Commit();
192 [ - + ]: 6702 : }
193 : :
194 : 455 : sal_Bool StorageStream::Equals( const BaseStorageStream& rStream ) const
195 : : {
196 [ + - ][ + - ]: 455 : const StorageStream* pOther = PTR_CAST( StorageStream, &rStream );
197 [ + - ][ - + ]: 455 : return pOther && ( pOther->pEntry == pEntry );
198 : : }
199 : :
200 : 2244264 : sal_uLong StorageStream::Read( void* pData, sal_uLong nSize )
201 : : {
202 [ + + ]: 2244264 : if( Validate() )
203 : : {
204 : 2244154 : pEntry->Seek( nPos );
205 : 2244154 : nSize = pEntry->Read( pData, (sal_Int32) nSize );
206 : 2244154 : pIo->MoveError( *this );
207 : 2244154 : nPos += nSize;
208 : : }
209 : : else
210 : 110 : nSize = 0L;
211 : 2244264 : return nSize;
212 : : }
213 : :
214 : 2040 : sal_uLong StorageStream::Write( const void* pData, sal_uLong nSize )
215 : : {
216 [ + - ]: 2040 : if( Validate( sal_True ) )
217 : : {
218 : 2040 : pEntry->Seek( nPos );
219 : 2040 : nSize = pEntry->Write( pData, (sal_Int32) nSize );
220 : 2040 : pIo->MoveError( *this );
221 : 2040 : nPos += nSize;
222 : : }
223 : : else
224 : 0 : nSize = 0L;
225 : 2040 : return nSize;
226 : : }
227 : :
228 : 1985654 : sal_uLong StorageStream::Seek( sal_uLong n )
229 : : {
230 [ + + ]: 1985654 : if( Validate() )
231 : 1985642 : return nPos = pEntry->Seek( n );
232 : : else
233 : 1985654 : return n;
234 : : }
235 : :
236 : 432 : void StorageStream::Flush()
237 : : {
238 : : // Flushing means committing, since streams are never transacted
239 : 432 : Commit();
240 : 432 : }
241 : :
242 : 473 : sal_Bool StorageStream::SetSize( sal_uLong nNewSize )
243 : : {
244 [ + - ]: 473 : if( Validate( sal_True ) )
245 : : {
246 : 473 : sal_Bool b = pEntry->SetSize( (sal_Int32) nNewSize );
247 : 473 : pIo->MoveError( *this );
248 : 473 : return b;
249 : : }
250 : : else
251 : 473 : return sal_False;
252 : : }
253 : :
254 : 15273 : sal_uLong StorageStream::GetSize() const
255 : : {
256 [ + - ]: 15273 : if( Validate() )
257 : 15273 : return pEntry->GetSize();
258 : 15273 : return 0;
259 : : }
260 : :
261 : 4521 : sal_Bool StorageStream::Commit()
262 : : {
263 [ - + ]: 4521 : if( !Validate() )
264 : 0 : return sal_False;
265 [ + + ]: 4521 : if( !( m_nMode & STREAM_WRITE ) )
266 : : {
267 : 1902 : SetError( SVSTREAM_ACCESS_DENIED );
268 : 1902 : return sal_False;
269 : : }
270 : : else
271 : : {
272 : 2619 : pEntry->Commit();
273 : 2619 : pIo->MoveError( *this );
274 : 4521 : return Good();
275 : : }
276 : : }
277 : :
278 : 0 : sal_Bool StorageStream::Revert()
279 : : {
280 : 0 : sal_Bool bResult = sal_False;
281 : :
282 [ # # ]: 0 : if ( Validate() )
283 : : {
284 : 0 : pEntry->Revert();
285 : 0 : pIo->MoveError( *this );
286 : 0 : bResult = Good();
287 : : }
288 : :
289 : 0 : return bResult;
290 : : }
291 : :
292 : 455 : sal_Bool StorageStream::CopyTo( BaseStorageStream* pDest )
293 : : {
294 [ + - ][ + - ]: 455 : if( !Validate() || !pDest || !pDest->Validate( sal_True ) || Equals( *pDest ) )
[ + - ][ - + ]
[ - + ]
295 : 0 : return sal_False;
296 : 455 : pEntry->Copy( *pDest );
297 : 455 : pDest->Commit();
298 : 455 : pIo->MoveError( *this );
299 : 455 : SetError( pDest->GetError() );
300 [ + - ][ + - ]: 455 : return sal_Bool( Good() && pDest->Good() );
301 : : }
302 : :
303 : 0 : const SvStream* StorageStream::GetSvStream() const
304 : : {
305 : 0 : return GetSvStream_Impl();
306 : : }
307 : :
308 : 4253135 : sal_Bool StorageStream::Validate( sal_Bool bValidate ) const
309 : : {
310 : 4253135 : sal_Bool bRet = Validate_Impl( bValidate );
311 [ + + ]: 4253135 : if ( !bRet )
312 : 122 : SetError( SVSTREAM_ACCESS_DENIED );
313 : 4253135 : return bRet;
314 : : }
315 : :
316 : 0 : sal_Bool StorageStream::ValidateMode( StreamMode nMode ) const
317 : : {
318 : 0 : sal_Bool bRet = ValidateMode_Impl( nMode, NULL );
319 [ # # ]: 0 : if ( !bRet )
320 : 0 : SetError( SVSTREAM_ACCESS_DENIED );
321 : 0 : return bRet;
322 : : }
323 : :
324 : : ///////////////////////// class SvStorageInfo //////////////////////////////
325 : :
326 [ + - ]: 3162 : SvStorageInfo::SvStorageInfo( const StgDirEntry& rE )
327 : : {
328 [ + - ]: 3162 : rE.aEntry.GetName( aName );
329 : 3162 : bStorage = sal_Bool( rE.aEntry.GetType() == STG_STORAGE );
330 : 3162 : bStream = sal_Bool( rE.aEntry.GetType() == STG_STREAM );
331 [ + + ]: 3162 : nSize = bStorage ? 0 : rE.aEntry.GetSize();
332 : 3162 : }
333 : :
334 : : /////////////////////////// class Storage ////////////////////////////////
335 : :
336 : 9 : sal_Bool Storage::IsStorageFile( const String & rFileName )
337 : : {
338 [ + - ]: 9 : StgIo aIo;
339 [ + - ][ + - ]: 9 : if( aIo.Open( rFileName, STREAM_STD_READ ) )
340 [ + - ]: 9 : return aIo.Load();
341 [ + - ]: 9 : return sal_False;
342 : : }
343 : :
344 : 1623 : sal_Bool Storage::IsStorageFile( SvStream* pStream )
345 : : {
346 : 1623 : sal_Bool bRet = sal_False;
347 : :
348 [ + - ]: 1623 : if ( pStream )
349 : : {
350 [ + - ]: 1623 : StgHeader aHdr;
351 : 1623 : sal_uLong nPos = pStream->Tell();
352 [ + + ][ + - ]: 1623 : bRet = ( aHdr.Load( *pStream ) && aHdr.Check() );
[ + - ][ + - ]
353 : :
354 : : // It's not a stream error if it is too small for a OLE storage header
355 [ - + ]: 1623 : if ( pStream->GetErrorCode() == ERRCODE_IO_CANTSEEK )
356 [ # # ]: 0 : pStream->ResetError();
357 [ + - ]: 1623 : pStream->Seek( nPos );
358 : : }
359 : :
360 : 1623 : return bRet;
361 : : }
362 : :
363 : : // Open the storage file. If writing is permitted and the file is not
364 : : // a storage file, initialize it.
365 : :
366 [ + + ][ - + ]: 1113 : TYPEINIT1( Storage, BaseStorage );
367 : :
368 : 0 : Storage::Storage( const String& rFile, StreamMode m, sal_Bool bDirect )
369 [ # # ][ # # ]: 0 : : OLEStorageBase( new StgIo, NULL, m_nMode ), aName( rFile ), bIsRoot( sal_False )
[ # # ]
370 : : {
371 : 0 : sal_Bool bTemp = sal_False;
372 [ # # ]: 0 : if( !aName.Len() )
373 : : {
374 : : // no name = temporary name!
375 [ # # ][ # # ]: 0 : aName = TempFile::CreateTempName();
[ # # ]
376 : 0 : bTemp = sal_True;
377 : : }
378 : : // the root storage creates the I/O system
379 : 0 : m_nMode = m;
380 [ # # ][ # # ]: 0 : if( pIo->Open( aName, m ) )
381 : : {
382 [ # # ]: 0 : Init( sal_Bool( ( m & ( STREAM_TRUNC | STREAM_NOCREATE ) ) == STREAM_TRUNC ) );
383 [ # # ]: 0 : if( pEntry )
384 : : {
385 : 0 : pEntry->bDirect = bDirect;
386 : 0 : pEntry->nMode = m;
387 : 0 : pEntry->bTemp = bTemp;
388 : : }
389 : : }
390 : : else
391 : : {
392 [ # # ]: 0 : pIo->MoveError( *this );
393 : 0 : pEntry = NULL;
394 : : }
395 : 0 : }
396 : :
397 : : // Create a storage on a given stream.
398 : :
399 : 366 : Storage::Storage( SvStream& r, sal_Bool bDirect )
400 [ + - ][ + - ]: 366 : : OLEStorageBase( new StgIo, NULL, m_nMode ), bIsRoot( sal_False )
[ + - ]
401 : : {
402 : 366 : m_nMode = STREAM_READ;
403 [ + + ]: 366 : if( r.IsWritable() )
404 : 360 : m_nMode = STREAM_READ | STREAM_WRITE;
405 [ + - ]: 366 : if( r.GetError() == SVSTREAM_OK )
406 : : {
407 [ + - ]: 366 : pIo->SetStrm( &r, sal_False );
408 [ + - ]: 366 : sal_uLong nSize = r.Seek( STREAM_SEEK_TO_END );
409 [ + - ]: 366 : r.Seek( 0L );
410 : : // Initializing is OK if the stream is empty
411 [ + - ]: 366 : Init( sal_Bool( nSize == 0 ) );
412 [ + + ]: 366 : if( pEntry )
413 : : {
414 : 349 : pEntry->bDirect = bDirect;
415 : 349 : pEntry->nMode = m_nMode;
416 : : }
417 [ + - ]: 366 : pIo->MoveError( *this );
418 : : }
419 : : else
420 : : {
421 [ # # ]: 0 : SetError( r.GetError() );
422 : 0 : pEntry = NULL;
423 : : }
424 : 366 : }
425 : :
426 : :
427 : 0 : Storage::Storage( UCBStorageStream& rStrm, sal_Bool bDirect )
428 [ # # ][ # # ]: 0 : : OLEStorageBase( new StgIo, NULL, m_nMode ), bIsRoot( sal_False )
[ # # ]
429 : : {
430 : 0 : m_nMode = STREAM_READ;
431 : :
432 [ # # ][ # # ]: 0 : if ( rStrm.GetError() != SVSTREAM_OK )
433 : : {
434 [ # # ][ # # ]: 0 : SetError( rStrm.GetError() );
435 : 0 : pEntry = NULL;
436 : 0 : return;
437 : : }
438 : :
439 [ # # ]: 0 : SvStream* pStream = rStrm.GetModifySvStream();
440 [ # # ]: 0 : if ( !pStream )
441 : : {
442 : : OSL_FAIL( "UCBStorageStream can not provide SvStream implementation!\n" );
443 [ # # ]: 0 : SetError( SVSTREAM_GENERALERROR );
444 : 0 : pEntry = NULL;
445 : 0 : return;
446 : : }
447 : :
448 [ # # ]: 0 : if( pStream->IsWritable() )
449 : 0 : m_nMode = STREAM_READ | STREAM_WRITE;
450 : :
451 [ # # ]: 0 : pIo->SetStrm( &rStrm );
452 : :
453 [ # # ]: 0 : sal_uLong nSize = pStream->Seek( STREAM_SEEK_TO_END );
454 [ # # ]: 0 : pStream->Seek( 0L );
455 : : // Initializing is OK if the stream is empty
456 [ # # ]: 0 : Init( sal_Bool( nSize == 0 ) );
457 [ # # ]: 0 : if( pEntry )
458 : : {
459 : 0 : pEntry->bDirect = bDirect;
460 : 0 : pEntry->nMode = m_nMode;
461 : : }
462 : :
463 [ # # ]: 0 : pIo->MoveError( *this );
464 : : }
465 : :
466 : :
467 : : // Perform common code for both ctors above.
468 : :
469 : 366 : void Storage::Init( sal_Bool bCreate )
470 : : {
471 : 366 : pEntry = NULL;
472 : 366 : sal_Bool bHdrLoaded = sal_False;
473 : 366 : bIsRoot = sal_True;
474 : :
475 : : OSL_ENSURE( pIo, "The pointer may not be empty at this point!" );
476 [ + - ][ + - ]: 366 : if( pIo->Good() && pIo->GetStrm() )
[ + - ]
477 : : {
478 : 366 : sal_uLong nSize = pIo->GetStrm()->Seek( STREAM_SEEK_TO_END );
479 : 366 : pIo->GetStrm()->Seek( 0L );
480 [ + + ]: 366 : if( nSize )
481 : : {
482 : 291 : bHdrLoaded = pIo->Load();
483 [ + - ][ + + ]: 291 : if( !bHdrLoaded && !bCreate )
484 : : {
485 : : // File is not a storage and not empty; do not destroy!
486 : 17 : SetError( SVSTREAM_FILEFORMAT_ERROR );
487 : 366 : return;
488 : : }
489 : : }
490 : : }
491 : : // file is a storage, empty or should be overwritten
492 : 349 : pIo->ResetError();
493 : : // we have to set up the data structures, since
494 : : // the file is empty
495 [ + + ]: 349 : if( !bHdrLoaded )
496 : 75 : pIo->Init();
497 [ + - ][ + - ]: 349 : if( pIo->Good() && pIo->pTOC )
[ + - ]
498 : : {
499 : 349 : pEntry = pIo->pTOC->GetRoot();
500 : 349 : pEntry->nRefCnt++;
501 : : }
502 : : }
503 : :
504 : : // Internal ctor
505 : :
506 : 119 : Storage::Storage( StgIo* p, StgDirEntry* q, StreamMode m )
507 [ + - ]: 119 : : OLEStorageBase( p, q, m_nMode ), bIsRoot( sal_False )
508 : : {
509 [ + - ]: 119 : if( q )
510 [ + - ]: 119 : q->aEntry.GetName( aName );
511 : : else
512 : 0 : m &= ~STREAM_READWRITE;
513 : 119 : m_nMode = m;
514 [ + - ][ + - ]: 119 : if( q && q->nRefCnt == 1 )
515 : 119 : q->nMode = m;
516 : 119 : }
517 : :
518 [ + - ][ + - ]: 479 : Storage::~Storage()
519 : : {
520 : : // Invalidate all open substorages
521 [ + + ]: 479 : if( m_bAutoCommit )
522 [ + - ]: 94 : Commit();
523 [ + + ]: 479 : if( pEntry )
524 : : {
525 : : // Do an auto-commit if the entry is open in direct mode
526 [ + - ][ + + ]: 462 : if( pEntry->nRefCnt && pEntry->bDirect && (m_nMode & STREAM_WRITE) )
[ + - ]
527 [ + - ]: 9 : Commit();
528 [ + - ]: 462 : if( pEntry->nRefCnt == 1 )
529 [ + - ]: 462 : pEntry->Invalidate();
530 : : }
531 : : // close the stream is root storage
532 [ + + ]: 479 : if( bIsRoot )
533 [ + - ]: 366 : pIo->Close();
534 : : // remove the file if temporary root storage
535 [ + + ][ + + ]: 479 : if( bIsRoot && pEntry && pEntry->bTemp )
[ - + ]
536 : : {
537 [ # # ][ # # ]: 0 : osl::File::remove( GetName() );
[ # # ]
538 : : }
539 [ - + ]: 958 : }
540 : :
541 : 54 : const String& Storage::GetName() const
542 : : {
543 [ + + ][ + - ]: 54 : if( !bIsRoot && Validate() )
[ + + ]
544 : 45 : pEntry->aEntry.GetName( ((Storage*) this)->aName );
545 : 54 : return aName;
546 : : }
547 : :
548 : : // Fill in the info list for this storage
549 : :
550 : 405 : void Storage::FillInfoList( SvStorageInfoList* pList ) const
551 : : {
552 [ + + ][ + - ]: 405 : if( Validate() && pList )
[ + + ]
553 : : {
554 [ + - ]: 397 : StgIterator aIter( *pEntry );
555 [ + - ]: 397 : StgDirEntry* p = aIter.First();
556 [ + + ]: 3559 : while( p )
557 : : {
558 [ + - ]: 3162 : if( !p->bInvalid )
559 : : {
560 [ + - ]: 3162 : SvStorageInfo aInfo( *p );
561 [ + - ][ + - ]: 3162 : pList->push_back( aInfo );
562 : : }
563 [ + - ]: 3162 : p = aIter.Next();
564 : : }
565 : : }
566 : 405 : }
567 : :
568 : : // Open or create a substorage
569 : :
570 : 0 : BaseStorage* Storage::OpenUCBStorage( const String& rName, StreamMode m, sal_Bool bDirect )
571 : : {
572 : : OSL_FAIL("Not supported!");
573 : 0 : return OpenStorage( rName, m, bDirect );
574 : : }
575 : :
576 : 16 : BaseStorage* Storage::OpenOLEStorage( const String& rName, StreamMode m, sal_Bool bDirect )
577 : : {
578 : 16 : return OpenStorage( rName, m, bDirect );
579 : : }
580 : :
581 : 119 : BaseStorage* Storage::OpenStorage( const String& rName, StreamMode m, sal_Bool bDirect )
582 : : {
583 [ + - ][ - + ]: 119 : if( !Validate() || !ValidateMode( m ) )
[ - + ]
584 [ # # ]: 0 : return new Storage( pIo, NULL, m );
585 [ - + ][ # # ]: 119 : if( bDirect && !pEntry->bDirect )
586 : 0 : bDirect = sal_False;
587 : :
588 : 119 : StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
589 [ + + ]: 119 : if( !p )
590 : : {
591 [ + - ]: 38 : if( !( m & STREAM_NOCREATE ) )
592 : : {
593 : 38 : sal_Bool bTemp = sal_False;
594 : : // create a new storage
595 [ + - ]: 38 : String aNewName = rName;
596 [ - + ]: 38 : if( !aNewName.Len() )
597 : : {
598 [ # # ]: 0 : aNewName.AssignAscii( "Temp Stg " );
599 [ # # ][ # # ]: 0 : aNewName.Append( String::CreateFromInt32( ++nTmpCount ) );
[ # # ]
600 : 0 : bTemp = sal_True;
601 : : }
602 [ + - ]: 38 : p = pIo->pTOC->Create( *pEntry, aNewName, STG_STORAGE );
603 [ + - ]: 38 : if( p )
604 [ + - ]: 38 : p->bTemp = bTemp;
605 : : }
606 [ - + ]: 38 : if( !p )
607 : : pIo->SetError( ( m & STREAM_WRITE )
608 [ # # ]: 0 : ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
609 : : }
610 [ - + ]: 81 : else if( !ValidateMode( m, p ) )
611 : 0 : p = NULL;
612 [ + - ][ - + ]: 119 : if( p && p->aEntry.GetType() != STG_STORAGE )
[ - + ]
613 : : {
614 : 0 : pIo->SetError( SVSTREAM_FILE_NOT_FOUND );
615 : 0 : p = NULL;
616 : : }
617 : :
618 : : // Either direct or transacted mode is supported
619 [ + - ][ + - ]: 119 : if( p && pEntry->nRefCnt == 1 )
620 : 119 : p->bDirect = bDirect;
621 : :
622 : : // Dont check direct conflict if opening readonly
623 [ + - ][ + + ]: 119 : if( p && (m & STREAM_WRITE ))
624 : : {
625 [ - + ]: 100 : if( p->bDirect != bDirect )
626 : 0 : SetError( SVSTREAM_ACCESS_DENIED );
627 : : }
628 [ + - ]: 119 : Storage* pStg = new Storage( pIo, p, m );
629 : 119 : pIo->MoveError( *pStg );
630 [ + + ]: 119 : if( m & STREAM_WRITE ) pStg->m_bAutoCommit = sal_True;
631 : 119 : return pStg;
632 : : }
633 : :
634 : : // Open a stream
635 : :
636 : 3351 : BaseStorageStream* Storage::OpenStream( const String& rName, StreamMode m, sal_Bool,
637 : : const rtl::OString*
638 : : #ifdef DBG_UTIL
639 : : pB
640 : : #endif
641 : : )
642 : : {
643 : : DBG_ASSERT(!pB, "Encryption not supported");
644 : :
645 [ + + ][ - + ]: 3351 : if( !Validate() || !ValidateMode( m ) )
[ + + ]
646 [ + - ]: 6 : return new StorageStream( pIo, NULL, m );
647 : 3345 : StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
648 : 3345 : sal_Bool bTemp = sal_False;
649 [ + + ]: 3345 : if( !p )
650 : : {
651 [ + + ]: 1041 : if( !( m & STREAM_NOCREATE ) )
652 : : {
653 : : // create a new stream
654 : : // make a name if the stream is temporary (has no name)
655 [ + - ]: 932 : String aNewName( rName );
656 [ - + ]: 932 : if( !aNewName.Len() )
657 : : {
658 [ # # ]: 0 : aNewName.AssignAscii( "Temp Strm " );
659 [ # # ][ # # ]: 0 : aNewName.Append( String::CreateFromInt32( ++nTmpCount ) );
[ # # ]
660 : 0 : bTemp = sal_True;
661 : : }
662 [ + - ][ + - ]: 932 : p = pIo->pTOC->Create( *pEntry, aNewName, STG_STREAM );
663 : : }
664 [ + + ]: 1041 : if( !p )
665 : : pIo->SetError( ( m & STREAM_WRITE )
666 [ - + ]: 109 : ? SVSTREAM_CANNOT_MAKE : SVSTREAM_FILE_NOT_FOUND );
667 : : }
668 [ - + ]: 2304 : else if( !ValidateMode( m, p ) )
669 : 0 : p = NULL;
670 [ + + ][ - + ]: 3345 : if( p && p->aEntry.GetType() != STG_STREAM )
[ - + ]
671 : : {
672 : 0 : pIo->SetError( SVSTREAM_FILE_NOT_FOUND );
673 : 0 : p = NULL;
674 : : }
675 [ + + ]: 3345 : if( p )
676 : : {
677 : 3236 : p->bTemp = bTemp;
678 : 3236 : p->bDirect = pEntry->bDirect;
679 : : }
680 [ + - ]: 3345 : StorageStream* pStm = new StorageStream( pIo, p, m );
681 [ + + ][ + + ]: 3345 : if( p && !p->bDirect )
682 : 3155 : pStm->SetAutoCommit( sal_True );
683 : 3345 : pIo->MoveError( *pStm );
684 : 3351 : return pStm;
685 : : }
686 : :
687 : : // Delete a stream or substorage by setting the temp bit.
688 : :
689 : 9 : sal_Bool Storage::Remove( const String& rName )
690 : : {
691 [ - + ]: 9 : if( !Validate( sal_True ) )
692 : 0 : return sal_False;
693 : 9 : StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
694 [ + - ]: 9 : if( p )
695 : : {
696 : 9 : p->Invalidate( sal_True );
697 : 9 : return sal_True;
698 : : }
699 : : else
700 : : {
701 : 0 : SetError( SVSTREAM_FILE_NOT_FOUND );
702 : 9 : return sal_False;
703 : : }
704 : : }
705 : :
706 : : // Rename a storage element
707 : :
708 : 0 : sal_Bool Storage::Rename( const String& rOld, const String& rNew )
709 : : {
710 [ # # ]: 0 : if( Validate( sal_True ) )
711 : : {
712 : 0 : sal_Bool b = pIo->pTOC->Rename( *pEntry, rOld, rNew );
713 : 0 : pIo->MoveError( *this );
714 : 0 : return b;
715 : : }
716 : : else
717 : 0 : return sal_False;
718 : : }
719 : :
720 : : // Copy one element
721 : :
722 : 471 : sal_Bool Storage::CopyTo( const String& rElem, BaseStorage* pDest, const String& rNew )
723 : : {
724 [ + - ][ + - ]: 471 : if( !Validate() || !pDest || !pDest->Validate( sal_True ) )
[ - + ][ - + ]
725 : 0 : return sal_False;
726 : 471 : StgDirEntry* pElem = pIo->pTOC->Find( *pEntry, rElem );
727 [ + - ]: 471 : if( pElem )
728 : : {
729 [ + + ]: 471 : if( pElem->aEntry.GetType() == STG_STORAGE )
730 : : {
731 : : // copy the entire storage
732 : 16 : BaseStorage* p1 = OpenStorage( rElem, INTERNAL_MODE );
733 : 16 : BaseStorage* p2 = pDest->OpenOLEStorage( rNew, STREAM_WRITE | STREAM_SHARE_DENYALL, pEntry->bDirect );
734 : :
735 [ + - ]: 16 : if ( p2 )
736 : : {
737 : 16 : sal_uLong nTmpErr = p2->GetError();
738 [ + - ]: 16 : if( !nTmpErr )
739 : : {
740 : 16 : p2->SetClassId( p1->GetClassId() );
741 : 16 : p1->CopyTo( p2 );
742 : 16 : SetError( p1->GetError() );
743 : :
744 : 16 : nTmpErr = p2->GetError();
745 [ + - ]: 16 : if( !nTmpErr )
746 : 16 : p2->Commit();
747 : : else
748 : 0 : pDest->SetError( nTmpErr );
749 : : }
750 : : else
751 : 0 : pDest->SetError( nTmpErr );
752 : : }
753 : :
754 [ + - ]: 16 : delete p1;
755 [ + - ]: 16 : delete p2;
756 [ + - ][ + - ]: 16 : return sal_Bool( Good() && pDest->Good() );
757 : : }
758 : : else
759 : : {
760 : : // stream copy
761 : 455 : BaseStorageStream* p1 = OpenStream( rElem, INTERNAL_MODE );
762 : 455 : BaseStorageStream* p2 = pDest->OpenStream( rNew, STREAM_WRITE | STREAM_SHARE_DENYALL, pEntry->bDirect );
763 : :
764 [ + - ]: 455 : if ( p2 )
765 : : {
766 : 455 : sal_uLong nTmpErr = p2->GetError();
767 [ + - ]: 455 : if( !nTmpErr )
768 : : {
769 : 455 : p1->CopyTo( p2 );
770 : 455 : SetError( p1->GetError() );
771 : :
772 : 455 : nTmpErr = p2->GetError();
773 [ + - ]: 455 : if( !nTmpErr )
774 : 455 : p2->Commit();
775 : : else
776 : 0 : pDest->SetError( nTmpErr );
777 : : }
778 : : else
779 : 0 : pDest->SetError( nTmpErr );
780 : : }
781 : :
782 [ + - ]: 455 : delete p1;
783 [ + - ]: 455 : delete p2;
784 [ + - ][ + - ]: 455 : return sal_Bool( Good() && pDest->Good() );
785 : : }
786 : : }
787 : 0 : SetError( SVSTREAM_FILE_NOT_FOUND );
788 : 471 : return sal_False;
789 : : }
790 : :
791 : 54 : sal_Bool Storage::CopyTo( BaseStorage* pDest ) const
792 : : {
793 [ + - ][ + - ]: 54 : if( !Validate() || !pDest || !pDest->Validate( sal_True ) || Equals( *pDest ) )
[ + - ][ + - ]
[ + - ][ + - ]
[ - + ][ - + ]
794 : : {
795 [ # # ]: 0 : SetError( SVSTREAM_ACCESS_DENIED );
796 : 0 : return sal_False;
797 : : }
798 : 54 : Storage* pThis = (Storage*) this;
799 [ + - ][ + - ]: 54 : pDest->SetClassId( GetClassId() );
800 [ + - ]: 54 : pDest->SetDirty();
801 [ + - ]: 54 : SvStorageInfoList aList;
802 [ + - ]: 54 : FillInfoList( &aList );
803 : 54 : sal_Bool bRes = sal_True;
804 [ + + ][ + - ]: 525 : for( size_t i = 0; i < aList.size() && bRes; i++ )
[ + + ]
805 : : {
806 : 471 : SvStorageInfo& rInfo = aList[ i ];
807 [ + - ]: 471 : bRes = pThis->CopyTo( rInfo.GetName(), pDest, rInfo.GetName() );
808 : : }
809 [ - + ]: 54 : if( !bRes )
810 [ # # ][ # # ]: 0 : SetError( pDest->GetError() );
811 [ + - ][ + - ]: 54 : return sal_Bool( Good() && pDest->Good() );
812 : : }
813 : :
814 : : // Move one element
815 : :
816 : 0 : sal_Bool Storage::MoveTo( const String& rElem, BaseStorage* pODest, const String& rNew )
817 : : {
818 [ # # ][ # # ]: 0 : if( !Validate() || !pODest || !pODest->Validate( sal_True ) || Equals( *pODest ) )
[ # # ][ # # ]
[ # # ]
819 : : {
820 : 0 : SetError( SVSTREAM_ACCESS_DENIED );
821 : 0 : return sal_False;
822 : : }
823 : :
824 : 0 : StgDirEntry* pElem = pIo->pTOC->Find( *pEntry, rElem );
825 [ # # ]: 0 : if( pElem )
826 : : {
827 : : // Simplest case: both storages share the same file
828 : : sal_Bool bRes;
829 [ # # ][ # # ]: 0 : Storage *pOther = PTR_CAST( Storage, pODest );
830 [ # # ][ # # ]: 0 : if( pOther && pIo == pOther->pIo && rElem == rNew )
[ # # ][ # # ]
831 : : {
832 : 0 : Storage *p = (Storage*) pODest;
833 : 0 : Storage *pDest = p;
834 : : // both storages are conventional storages, use implementation dependent code
835 [ # # ]: 0 : if( !pElem->IsContained( pDest->pEntry ) )
836 : : {
837 : : // cyclic move
838 : 0 : SetError( SVSTREAM_ACCESS_DENIED );
839 : 0 : return sal_False;
840 : : }
841 : 0 : bRes = pIo->pTOC->Move( *pEntry, *pDest->pEntry, rNew );
842 [ # # ]: 0 : if( !bRes )
843 : : {
844 : 0 : pIo->MoveError( *this );
845 : 0 : pDest->pIo->MoveError( *pDest );
846 : 0 : sal_uLong nErr = GetError();
847 [ # # ]: 0 : if( !nErr )
848 : 0 : nErr = pDest->GetError();
849 : 0 : SetError( nErr );
850 : 0 : pDest->SetError( nErr );
851 : : }
852 : : }
853 : : else
854 : : {
855 : 0 : bRes = CopyTo( rElem, pODest, rNew );
856 [ # # ]: 0 : if( bRes )
857 : 0 : bRes = Remove( rElem );
858 : : }
859 [ # # ]: 0 : if( !bRes )
860 : 0 : SetError( pIo->GetError() );
861 : 0 : return bRes;
862 : : }
863 : 0 : SetError( SVSTREAM_FILE_NOT_FOUND );
864 : 0 : return sal_False;
865 : : }
866 : :
867 : 757 : sal_Bool Storage::IsStorage( const String& rName ) const
868 : : {
869 [ + - ]: 757 : if( Validate() )
870 : : {
871 : 757 : StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
872 [ + - ]: 757 : if( p )
873 : 757 : return sal_Bool( p->aEntry.GetType() == STG_STORAGE );
874 : : }
875 : 757 : return sal_False;
876 : : }
877 : :
878 : 98 : sal_Bool Storage::IsStream( const String& rName ) const
879 : : {
880 [ + - ]: 98 : if( Validate() )
881 : : {
882 : 98 : StgDirEntry* p = pIo->pTOC->Find( *pEntry, rName );
883 [ + + ]: 98 : if( p )
884 : 79 : return sal_Bool( p->aEntry.GetType() == STG_STREAM );
885 : : }
886 : 98 : return sal_False;
887 : : }
888 : :
889 : 1819 : sal_Bool Storage::IsContained( const String& rName ) const
890 : : {
891 [ + - ]: 1819 : if( Validate() )
892 : 1819 : return sal_Bool( pIo->pTOC->Find( *pEntry, rName ) != NULL );
893 : : else
894 : 1819 : return sal_False;
895 : : }
896 : :
897 : : // Commit all sub-elements within this storage. If this is
898 : : // the root, commit the FAT, the TOC and the header as well.
899 : :
900 : 194 : sal_Bool Storage::Commit()
901 : : {
902 : 194 : sal_Bool bRes = sal_True;
903 [ - + ]: 194 : if( !Validate() )
904 : 0 : return sal_False;
905 [ - + ]: 194 : if( !( m_nMode & STREAM_WRITE ) )
906 : : {
907 : 0 : SetError( SVSTREAM_ACCESS_DENIED );
908 : 0 : return sal_False;
909 : : }
910 : : else
911 : : {
912 : : // Also commit the sub-streams and Storages
913 [ + - ]: 194 : StgIterator aIter( *pEntry );
914 [ + - ][ + - ]: 1794 : for( StgDirEntry* p = aIter.First(); p && bRes; p = aIter.Next() )
[ + + ][ + - ]
[ + + ]
915 [ + - ]: 1600 : bRes = p->Commit();
916 [ + - ][ + + ]: 194 : if( bRes && bIsRoot )
917 : : {
918 [ + - ]: 84 : bRes = pEntry->Commit();
919 [ + - ]: 84 : if( bRes )
920 [ + - ]: 84 : bRes = pIo->CommitAll();
921 : : }
922 [ + - ]: 194 : pIo->MoveError( *this );
923 : : }
924 : 194 : return bRes;
925 : : }
926 : :
927 : 0 : sal_Bool Storage::Revert()
928 : : {
929 : 0 : return sal_True;
930 : : }
931 : :
932 : : ///////////////////////////// OLE Support ////////////////////////////////
933 : :
934 : : // Set the storage type
935 : :
936 : 12 : void Storage::SetClass( const SvGlobalName & rClass,
937 : : sal_uLong nOriginalClipFormat,
938 : : const String & rUserTypeName )
939 : : {
940 [ + - ]: 12 : if( Validate( sal_True ) )
941 : : {
942 : : // set the class name in the root entry
943 [ + - ]: 12 : pEntry->aEntry.SetClassId( (const ClsId&) rClass.GetCLSID() );
944 : 12 : pEntry->SetDirty();
945 : : // then create the streams
946 [ + - ]: 12 : StgCompObjStream aCompObj( *this, sal_True );
947 : 12 : aCompObj.GetClsId() = (const ClsId&) rClass.GetCLSID();
948 : 12 : aCompObj.GetCbFormat() = nOriginalClipFormat;
949 [ + - ]: 12 : aCompObj.GetUserName() = rUserTypeName;
950 [ + - ][ - + ]: 12 : if( !aCompObj.Store() )
951 [ # # ]: 0 : SetError( aCompObj.GetError() );
952 : : else
953 : : {
954 [ + - ]: 12 : StgOleStream aOle( *this, STREAM_WRITE );
955 [ + - ][ - + ]: 12 : if( !aOle.Store() )
956 [ # # ][ + - ]: 12 : SetError( aOle.GetError() );
957 [ + - ]: 12 : }
958 : : }
959 : : else
960 : 0 : SetError( SVSTREAM_ACCESS_DENIED );
961 : 12 : }
962 : :
963 : 0 : void Storage::SetConvertClass( const SvGlobalName & rConvertClass,
964 : : sal_uLong nOriginalClipFormat,
965 : : const String & rUserTypeName )
966 : : {
967 [ # # ]: 0 : if( Validate( sal_True ) )
968 : : {
969 [ # # ]: 0 : SetClass( rConvertClass, nOriginalClipFormat, rUserTypeName );
970 : : // plus the convert flag:
971 [ # # ]: 0 : StgOleStream aOle( *this, sal_True );
972 : 0 : aOle.GetFlags() |= 4;
973 [ # # ][ # # ]: 0 : if( !aOle.Store() )
974 [ # # ][ # # ]: 0 : SetError( aOle.GetError() );
975 : : }
976 : 0 : }
977 : :
978 : 18 : SvGlobalName Storage::GetClassName()
979 : : {
980 [ + - ]: 18 : StgCompObjStream aCompObj( *this, sal_False );
981 [ + - ][ + - ]: 18 : if( aCompObj.Load() )
982 [ + - ]: 18 : return SvGlobalName( (const CLSID&) aCompObj.GetClsId() );
983 [ # # ]: 0 : pIo->ResetError();
984 : :
985 [ # # ]: 0 : if ( pEntry )
986 [ # # ]: 0 : return SvGlobalName( (const CLSID&) pEntry->aEntry.GetClassId() );
987 : :
988 [ # # ][ + - ]: 18 : return SvGlobalName();
989 : : }
990 : :
991 : 63 : sal_uLong Storage::GetFormat()
992 : : {
993 [ + - ]: 63 : StgCompObjStream aCompObj( *this, sal_False );
994 [ + - ][ + - ]: 63 : if( aCompObj.Load() )
995 : 63 : return aCompObj.GetCbFormat();
996 [ # # ]: 0 : pIo->ResetError();
997 [ + - ]: 63 : return 0;
998 : : }
999 : :
1000 : 0 : String Storage::GetUserName()
1001 : : {
1002 [ # # ]: 0 : StgCompObjStream aCompObj( *this, sal_False );
1003 [ # # ][ # # ]: 0 : if( aCompObj.Load() )
1004 [ # # ]: 0 : return aCompObj.GetUserName();
1005 [ # # ]: 0 : pIo->ResetError();
1006 [ # # ][ # # ]: 0 : return String();
1007 : : }
1008 : :
1009 : 0 : sal_Bool Storage::ShouldConvert()
1010 : : {
1011 [ # # ]: 0 : StgOleStream aOle( *this, sal_False );
1012 [ # # ][ # # ]: 0 : if( aOle.Load() )
1013 : 0 : return sal_Bool( ( aOle.GetFlags() & 4 ) != 0 );
1014 : : else
1015 : : {
1016 [ # # ]: 0 : pIo->ResetError();
1017 : 0 : return sal_False;
1018 [ # # ]: 0 : }
1019 : : }
1020 : :
1021 : 6 : sal_Bool Storage::ValidateFAT()
1022 : : {
1023 [ + - ]: 6 : Link aLink = StgIo::GetErrorLink();
1024 [ + - ]: 6 : ErrCode nErr = pIo->ValidateFATs();
1025 [ + - ]: 6 : StgIo::SetErrorLink( aLink );
1026 : 6 : return nErr == ERRCODE_NONE;
1027 : : }
1028 : :
1029 : 54 : void Storage::SetDirty()
1030 : : {
1031 [ + - ]: 54 : if ( pEntry )
1032 : 54 : pEntry->SetDirty();
1033 : 54 : }
1034 : :
1035 : 70 : void Storage::SetClassId( const ClsId& rId )
1036 : : {
1037 [ + - ]: 70 : if ( pEntry )
1038 : 70 : pEntry->aEntry.SetClassId( rId );
1039 : 70 : }
1040 : :
1041 : 70 : const ClsId& Storage::GetClassId() const
1042 : : {
1043 [ + - ]: 70 : if ( pEntry )
1044 : 70 : return pEntry->aEntry.GetClassId();
1045 : :
1046 : : static ClsId aDummyId = {0,0,0,0,0,0,0,0,0,0,0};
1047 : 70 : return aDummyId;
1048 : : }
1049 : :
1050 : 0 : const SvStream* Storage::GetSvStream() const
1051 : : {
1052 : 0 : return GetSvStream_Impl();
1053 : : }
1054 : :
1055 : 7859 : sal_Bool Storage::Validate( sal_Bool bValidate ) const
1056 : : {
1057 : 7859 : sal_Bool bRet = Validate_Impl( bValidate );
1058 [ + + ]: 7859 : if ( !bRet )
1059 : 14 : SetError( SVSTREAM_ACCESS_DENIED );
1060 : 7859 : return bRet;
1061 : : }
1062 : :
1063 : 3464 : sal_Bool Storage::ValidateMode( StreamMode nMode ) const
1064 : : {
1065 : 3464 : sal_Bool bRet = ValidateMode_Impl( nMode );
1066 [ - + ]: 3464 : if ( !bRet )
1067 : 0 : SetError( SVSTREAM_ACCESS_DENIED );
1068 : 3464 : return bRet;
1069 : : }
1070 : :
1071 : 2385 : sal_Bool Storage::ValidateMode( StreamMode nMode, StgDirEntry* p ) const
1072 : : {
1073 : 2385 : sal_Bool bRet = ValidateMode_Impl( nMode, p );
1074 [ - + ]: 2385 : if ( !bRet )
1075 : 0 : SetError( SVSTREAM_ACCESS_DENIED );
1076 : 2385 : return bRet;
1077 : : }
1078 : :
1079 : 54 : sal_Bool Storage::Equals( const BaseStorage& rStorage ) const
1080 : : {
1081 [ + - ][ + - ]: 54 : const Storage* pOther = PTR_CAST( Storage, &rStorage );
1082 [ + - ][ - + ]: 54 : return pOther && ( pOther->pEntry == pEntry );
1083 : : }
1084 : :
1085 : :
1086 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|