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