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