xref: /aoo41x/main/sot/source/sdstor/stg.cxx (revision 046d9d1f)
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