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