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