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 if ( p ) 107 p->IncRef(); 108 if( pe ) 109 pe->nRefCnt++; 110 } 111 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 138 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 149 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 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 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 206 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 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 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 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 248 void StorageStream::Flush() 249 { 250 // Flushing means committing, since streams are never transacted 251 Commit(); 252 } 253 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 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 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 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 308 const SvStream* StorageStream::GetSvStream() const 309 { 310 return GetSvStream_Impl(); 311 } 312 313 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 321 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 329 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 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 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 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 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 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 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 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 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 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 554 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 563 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 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 594 BaseStorage* Storage::OpenOLEStorage( const String& rName, StreamMode m, sal_Bool bDirect ) 595 { 596 return OpenStorage( rName, m, bDirect ); 597 } 598 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 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 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 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 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 misterious !!! 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 821 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 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 904 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 915 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 926 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 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 964 sal_Bool Storage::Revert() 965 { 966 return sal_True; 967 } 968 969 ///////////////////////////// OLE Support //////////////////////////////// 970 971 // Set the storage type 972 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 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 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 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 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 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 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 1066 void Storage::SetDirty() 1067 { 1068 if ( pEntry ) 1069 pEntry->SetDirty(); 1070 } 1071 1072 void Storage::SetClassId( const ClsId& rId ) 1073 { 1074 if ( pEntry ) 1075 pEntry->aEntry.SetClassId( rId ); 1076 } 1077 1078 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 1087 const SvStream* Storage::GetSvStream() const 1088 { 1089 return GetSvStream_Impl(); 1090 } 1091 1092 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 1100 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 1108 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 1116 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