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