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 #include "oox/ole/vbaproject.hxx" 29 30 #include <com/sun/star/document/XStorageBasedDocument.hpp> 31 #include <com/sun/star/embed/ElementModes.hpp> 32 #include <com/sun/star/embed/XTransactedObject.hpp> 33 #include <com/sun/star/frame/XModel.hpp> 34 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 35 #include <com/sun/star/script/ModuleType.hpp> 36 #include <com/sun/star/script/XLibraryContainer.hpp> 37 #include <com/sun/star/script/vba/XVBACompatibility.hpp> 38 #include <com/sun/star/script/vba/XVBAMacroResolver.hpp> 39 #include <com/sun/star/uno/XComponentContext.hpp> 40 #include <comphelper/configurationhelper.hxx> 41 #include <comphelper/string.hxx> 42 #include <rtl/tencinfo.h> 43 #include <rtl/ustrbuf.h> 44 #include "oox/helper/binaryinputstream.hxx" 45 #include "oox/helper/containerhelper.hxx" 46 #include "oox/helper/propertyset.hxx" 47 #include "oox/helper/textinputstream.hxx" 48 #include "oox/ole/olestorage.hxx" 49 #include "oox/ole/vbacontrol.hxx" 50 #include "oox/ole/vbahelper.hxx" 51 #include "oox/ole/vbainputstream.hxx" 52 #include "oox/ole/vbamodule.hxx" 53 54 namespace oox { 55 namespace ole { 56 57 // ============================================================================ 58 59 using namespace ::com::sun::star::container; 60 using namespace ::com::sun::star::document; 61 using namespace ::com::sun::star::embed; 62 using namespace ::com::sun::star::frame; 63 using namespace ::com::sun::star::io; 64 using namespace ::com::sun::star::lang; 65 using namespace ::com::sun::star::script; 66 using namespace ::com::sun::star::script::vba; 67 using namespace ::com::sun::star::uno; 68 69 using ::comphelper::ConfigurationHelper; 70 using ::rtl::OUString; 71 using ::rtl::OUStringBuffer; 72 73 // ============================================================================ 74 75 namespace { 76 77 bool lclReadConfigItem( const Reference< XInterface >& rxConfigAccess, const OUString& rItemName ) 78 { 79 // some applications do not support all configuration items, assume 'false' in this case 80 try 81 { 82 Any aItem = ConfigurationHelper::readRelativeKey( rxConfigAccess, CREATE_OUSTRING( "Filter/Import/VBA" ), rItemName ); 83 return aItem.has< bool >() && aItem.get< bool >(); 84 } 85 catch( Exception& ) 86 { 87 } 88 return false; 89 } 90 91 } // namespace 92 93 // ---------------------------------------------------------------------------- 94 95 VbaFilterConfig::VbaFilterConfig( const Reference< XComponentContext >& rxContext, const OUString& rConfigCompName ) 96 { 97 OSL_ENSURE( rxContext.is(), "VbaFilterConfig::VbaFilterConfig - missing component context" ); 98 if( rxContext.is() ) try 99 { 100 OSL_ENSURE( rConfigCompName.getLength() > 0, "VbaFilterConfig::VbaFilterConfig - invalid configuration component name" ); 101 OUString aConfigPackage = CREATE_OUSTRING( "org.openoffice.Office." ) + rConfigCompName; 102 Reference< XMultiServiceFactory > xFactory( rxContext->getServiceManager(), UNO_QUERY_THROW ); 103 mxConfigAccess = ConfigurationHelper::openConfig( xFactory, aConfigPackage, ConfigurationHelper::E_READONLY ); 104 } 105 catch( Exception& ) 106 { 107 } 108 OSL_ENSURE( mxConfigAccess.is(), "VbaFilterConfig::VbaFilterConfig - cannot open configuration" ); 109 } 110 111 VbaFilterConfig::~VbaFilterConfig() 112 { 113 } 114 115 bool VbaFilterConfig::isImportVba() const 116 { 117 return lclReadConfigItem( mxConfigAccess, CREATE_OUSTRING( "Load" ) ); 118 } 119 120 bool VbaFilterConfig::isImportVbaExecutable() const 121 { 122 return lclReadConfigItem( mxConfigAccess, CREATE_OUSTRING( "Executable" ) ); 123 } 124 125 bool VbaFilterConfig::isExportVba() const 126 { 127 return lclReadConfigItem( mxConfigAccess, CREATE_OUSTRING( "Save" ) ); 128 } 129 130 // ============================================================================ 131 132 VbaMacroAttacherBase::VbaMacroAttacherBase( const OUString& rMacroName ) : 133 maMacroName( rMacroName ) 134 { 135 OSL_ENSURE( maMacroName.getLength() > 0, "VbaMacroAttacherBase::VbaMacroAttacherBase - empty macro name" ); 136 } 137 138 VbaMacroAttacherBase::~VbaMacroAttacherBase() 139 { 140 } 141 142 void VbaMacroAttacherBase::resolveAndAttachMacro( const Reference< XVBAMacroResolver >& rxResolver ) 143 { 144 try 145 { 146 attachMacro( rxResolver->resolveVBAMacroToScriptURL( maMacroName ) ); 147 } 148 catch( Exception& ) 149 { 150 } 151 } 152 153 // ============================================================================ 154 155 VbaProject::VbaProject( const Reference< XComponentContext >& rxContext, 156 const Reference< XModel >& rxDocModel, const OUString& rConfigCompName ) : 157 VbaFilterConfig( rxContext, rConfigCompName ), 158 mxContext( rxContext ), 159 mxDocModel( rxDocModel ), 160 maPrjName( CREATE_OUSTRING( "Standard" ) ) 161 { 162 OSL_ENSURE( mxContext.is(), "VbaProject::VbaProject - missing component context" ); 163 OSL_ENSURE( mxDocModel.is(), "VbaProject::VbaProject - missing document model" ); 164 mxBasicLib = openLibrary( PROP_BasicLibraries, false ); 165 mxDialogLib = openLibrary( PROP_DialogLibraries, false ); 166 } 167 168 VbaProject::~VbaProject() 169 { 170 } 171 172 void VbaProject::importVbaProject( StorageBase& rVbaPrjStrg, const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr ) 173 { 174 if( rVbaPrjStrg.isStorage() ) 175 { 176 // load the code modules and forms 177 if( isImportVba() ) 178 importVba( rVbaPrjStrg, rGraphicHelper, bDefaultColorBgr ); 179 // copy entire storage into model 180 if( isExportVba() ) 181 copyStorage( rVbaPrjStrg ); 182 } 183 } 184 185 void VbaProject::registerMacroAttacher( const VbaMacroAttacherRef& rxAttacher ) 186 { 187 OSL_ENSURE( rxAttacher.get(), "VbaProject::registerMacroAttacher - unexpected empty reference" ); 188 maMacroAttachers.push_back( rxAttacher ); 189 } 190 191 bool VbaProject::hasModules() const 192 { 193 return mxBasicLib.is() && mxBasicLib->hasElements(); 194 } 195 196 bool VbaProject::hasModule( const OUString& rModuleName ) const 197 { 198 return mxBasicLib.is() && mxBasicLib->hasByName( rModuleName ); 199 } 200 201 bool VbaProject::hasDialogs() const 202 { 203 return mxDialogLib.is() && mxDialogLib->hasElements(); 204 } 205 206 bool VbaProject::hasDialog( const OUString& rDialogName ) const 207 { 208 return mxDialogLib.is() && mxDialogLib->hasByName( rDialogName ); 209 } 210 211 // protected ------------------------------------------------------------------ 212 213 void VbaProject::addDummyModule( const OUString& rName, sal_Int32 nType ) 214 { 215 OSL_ENSURE( rName.getLength() > 0, "VbaProject::addDummyModule - missing module name" ); 216 maDummyModules[ rName ] = nType; 217 } 218 219 void VbaProject::prepareImport() 220 { 221 } 222 223 void VbaProject::finalizeImport() 224 { 225 } 226 227 // private -------------------------------------------------------------------- 228 229 Reference< XLibraryContainer > VbaProject::getLibraryContainer( sal_Int32 nPropId ) 230 { 231 PropertySet aDocProp( mxDocModel ); 232 Reference< XLibraryContainer > xLibContainer( aDocProp.getAnyProperty( nPropId ), UNO_QUERY ); 233 return xLibContainer; 234 } 235 236 Reference< XNameContainer > VbaProject::openLibrary( sal_Int32 nPropId, bool bCreateMissing ) 237 { 238 Reference< XNameContainer > xLibrary; 239 try 240 { 241 Reference< XLibraryContainer > xLibContainer( getLibraryContainer( nPropId ), UNO_SET_THROW ); 242 if( bCreateMissing && !xLibContainer->hasByName( CREATE_OUSTRING( "Standard" ) /*maPrjName*/ ) ) 243 xLibContainer->createLibrary( CREATE_OUSTRING( "Standard" ) /*maPrjName*/ ); 244 xLibrary.set( xLibContainer->getByName( CREATE_OUSTRING( "Standard" ) /*maPrjName*/ ), UNO_QUERY_THROW ); 245 } 246 catch( Exception& ) 247 { 248 } 249 OSL_ENSURE( !bCreateMissing || xLibrary.is(), "VbaProject::openLibrary - cannot create library" ); 250 return xLibrary; 251 } 252 253 Reference< XNameContainer > VbaProject::createBasicLibrary() 254 { 255 if( !mxBasicLib.is() ) 256 mxBasicLib = openLibrary( PROP_BasicLibraries, true ); 257 return mxBasicLib; 258 } 259 260 Reference< XNameContainer > VbaProject::createDialogLibrary() 261 { 262 if( !mxDialogLib.is() ) 263 mxDialogLib = openLibrary( PROP_DialogLibraries, true ); 264 return mxDialogLib; 265 } 266 267 void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr ) 268 { 269 StorageRef xVbaStrg = rVbaPrjStrg.openSubStorage( CREATE_OUSTRING( "VBA" ), false ); 270 OSL_ENSURE( xVbaStrg.get(), "VbaProject::importVba - cannot open 'VBA' substorage" ); 271 if( !xVbaStrg ) 272 return; 273 274 /* Read the 'VBA/dir' stream which contains general settings of the VBA 275 project such as the text encoding used throughout several streams, and 276 a list of all code modules. 277 */ 278 BinaryXInputStream aInStrm( xVbaStrg->openInputStream( CREATE_OUSTRING( "dir" ) ), true ); 279 // VbaInputStream implements decompression 280 VbaInputStream aDirStrm( aInStrm ); 281 OSL_ENSURE( !aDirStrm.isEof(), "VbaProject::importVba - cannot open 'dir' stream" ); 282 if( aDirStrm.isEof() ) 283 return; 284 285 // virtual call, derived classes may do some preparations 286 prepareImport(); 287 288 // read all records of the directory 289 rtl_TextEncoding eTextEnc = RTL_TEXTENCODING_MS_1252; 290 sal_uInt16 nModuleCount = 0; 291 bool bExecutable = isImportVbaExecutable(); 292 293 typedef RefMap< OUString, VbaModule > VbaModuleMap; 294 VbaModuleMap aModules, aModulesByStrm; 295 296 sal_uInt16 nRecId = 0; 297 StreamDataSequence aRecData; 298 while( VbaHelper::readDirRecord( nRecId, aRecData, aDirStrm ) && (nRecId != VBA_ID_PROJECTEND) ) 299 { 300 // create record stream object from imported record data 301 SequenceInputStream aRecStrm( aRecData ); 302 sal_Int32 nRecSize = aRecData.getLength(); 303 switch( nRecId ) 304 { 305 #define OOX_ENSURE_RECORDSIZE( cond ) OSL_ENSURE( cond, "VbaProject::importVba - invalid record size" ) 306 case VBA_ID_PROJECTCODEPAGE: 307 { 308 OOX_ENSURE_RECORDSIZE( nRecSize == 2 ); 309 OSL_ENSURE( aModules.empty(), "VbaProject::importVba - unexpected PROJECTCODEPAGE record" ); 310 rtl_TextEncoding eNewTextEnc = rtl_getTextEncodingFromWindowsCodePage( aRecStrm.readuInt16() ); 311 OSL_ENSURE( eNewTextEnc != RTL_TEXTENCODING_DONTKNOW, "VbaProject::importVba - unknown text encoding" ); 312 if( eNewTextEnc != RTL_TEXTENCODING_DONTKNOW ) 313 eTextEnc = eNewTextEnc; 314 } 315 break; 316 case VBA_ID_PROJECTNAME: 317 { 318 OUString aPrjName = aRecStrm.readCharArrayUC( nRecSize, eTextEnc ); 319 OSL_ENSURE( aPrjName.getLength() > 0, "VbaProject::importVba - invalid project name" ); 320 if( aPrjName.getLength() > 0 ) 321 maPrjName = aPrjName; 322 } 323 break; 324 case VBA_ID_PROJECTMODULES: 325 OOX_ENSURE_RECORDSIZE( nRecSize == 2 ); 326 OSL_ENSURE( aModules.empty(), "VbaProject::importVba - unexpected PROJECTMODULES record" ); 327 aRecStrm >> nModuleCount; 328 break; 329 case VBA_ID_MODULENAME: 330 { 331 OUString aName = aRecStrm.readCharArrayUC( nRecSize, eTextEnc ); 332 OSL_ENSURE( aName.getLength() > 0, "VbaProject::importVba - invalid module name" ); 333 OSL_ENSURE( !aModules.has( aName ), "VbaProject::importVba - multiple modules with the same name" ); 334 VbaModuleMap::mapped_type& rxModule = aModules[ aName ]; 335 rxModule.reset( new VbaModule( mxContext, mxDocModel, aName, eTextEnc, bExecutable ) ); 336 // read all remaining records until the MODULEEND record 337 rxModule->importDirRecords( aDirStrm ); 338 OSL_ENSURE( !aModulesByStrm.has( rxModule->getStreamName() ), "VbaProject::importVba - multiple modules with the same stream name" ); 339 aModulesByStrm[ rxModule->getStreamName() ] = rxModule; 340 } 341 break; 342 #undef OOX_ENSURE_RECORDSIZE 343 } 344 } 345 OSL_ENSURE( nModuleCount == aModules.size(), "VbaProject::importVba - invalid module count" ); 346 347 /* The directory does not contain the real type of the modules, it 348 distinguishes only between 'procedural' and 'document' (the latter 349 includes class and form modules). Now, the exact type of all modules 350 will be read from the 'PROJECT' stream. It consists of text lines in 351 'key=value' format which list the code modules by type. 352 353 - The line 'document=<modulename>/&HXXXXXXXX' declares document 354 modules. These are attached to the Word document (usually called 355 'ThisDocument'), the Excel workbook (usually called 356 'ThisWorkbook'), or single Excel worksheets or chartsheets (usually 357 called 'SheetX' or 'ChartX', X being a decimal number). Of course, 358 users may rename all these modules. The slash character separates 359 an automation server version number (hexadecimal 'XXXXXXXX') from 360 the module name. 361 - The line 'Module=<modulename>' declares common procedural code 362 modules. 363 - The line 'Class=<modulename>' declares a class module. 364 - The line 'BaseClass=<modulename>' declares a code module attached 365 to a user form with the same name. 366 */ 367 BinaryXInputStream aPrjStrm( rVbaPrjStrg.openInputStream( CREATE_OUSTRING( "PROJECT" ) ), true ); 368 OSL_ENSURE( !aPrjStrm.isEof(), "VbaProject::importVba - cannot open 'PROJECT' stream" ); 369 // do not exit if this stream does not exist, but proceed to load the modules below 370 if( !aPrjStrm.isEof() ) 371 { 372 TextInputStream aPrjTextStrm( mxContext, aPrjStrm, eTextEnc ); 373 OUString aKey, aValue; 374 bool bExitLoop = false; 375 while( !bExitLoop && !aPrjTextStrm.isEof() ) 376 { 377 // read a text line from the stream 378 OUString aLine = aPrjTextStrm.readLine().trim(); 379 sal_Int32 nLineLen = aLine.getLength(); 380 // exit if a subsection starts (section name is given in brackets) 381 bExitLoop = (nLineLen >= 2) && (aLine[ 0 ] == '[') && (aLine[ nLineLen - 1 ] == ']'); 382 if( !bExitLoop && VbaHelper::extractKeyValue( aKey, aValue, aLine ) ) 383 { 384 sal_Int32 nType = ModuleType::UNKNOWN; 385 if( aKey.equalsIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "Document" ) ) ) 386 { 387 nType = ModuleType::DOCUMENT; 388 // strip automation server version from module names 389 sal_Int32 nSlashPos = aValue.indexOf( '/' ); 390 if( nSlashPos >= 0 ) 391 aValue = aValue.copy( 0, nSlashPos ); 392 } 393 else if( aKey.equalsIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "Module" ) ) ) 394 nType = ModuleType::NORMAL; 395 else if( aKey.equalsIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "Class" ) ) ) 396 nType = ModuleType::CLASS; 397 else if( aKey.equalsIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "BaseClass" ) ) ) 398 nType = ModuleType::FORM; 399 400 if( (nType != ModuleType::UNKNOWN) && (aValue.getLength() > 0) ) 401 { 402 OSL_ENSURE( aModules.has( aValue ), "VbaProject::importVba - module not found" ); 403 if( VbaModule* pModule = aModules.get( aValue ).get() ) 404 pModule->setType( nType ); 405 } 406 } 407 } 408 } 409 410 // create empty dummy modules 411 VbaModuleMap aDummyModules; 412 for( DummyModuleMap::iterator aIt = maDummyModules.begin(), aEnd = maDummyModules.end(); aIt != aEnd; ++aIt ) 413 { 414 OSL_ENSURE( !aModules.has( aIt->first ) && !aDummyModules.has( aIt->first ), "VbaProject::importVba - multiple modules with the same name" ); 415 VbaModuleMap::mapped_type& rxModule = aDummyModules[ aIt->first ]; 416 rxModule.reset( new VbaModule( mxContext, mxDocModel, aIt->first, eTextEnc, bExecutable ) ); 417 rxModule->setType( aIt->second ); 418 } 419 420 /* Now it is time to load the source code. All modules will be inserted 421 into the Basic library of the document specified by the 'maPrjName' 422 member. Do not create the Basic library, if there are no modules 423 specified. */ 424 if( !aModules.empty() || !aDummyModules.empty() ) try 425 { 426 // get the model factory and the basic library 427 Reference< XMultiServiceFactory > xModelFactory( mxDocModel, UNO_QUERY_THROW ); 428 Reference< XNameContainer > xBasicLib( createBasicLibrary(), UNO_SET_THROW ); 429 430 /* Set library container to VBA compatibility mode. This will create 431 the VBA Globals object and store it in the Basic manager of the 432 document. */ 433 try 434 { 435 Reference< XVBACompatibility >( getLibraryContainer( PROP_BasicLibraries ), UNO_QUERY_THROW )->setVBACompatibilityMode( sal_True ); 436 } 437 catch( Exception& ) 438 { 439 } 440 441 // try to get access to document objects related to code modules 442 Reference< XNameAccess > xDocObjectNA; 443 try 444 { 445 xDocObjectNA.set( xModelFactory->createInstance( CREATE_OUSTRING( "ooo.vba.VBAObjectModuleObjectProvider" ) ), UNO_QUERY ); 446 } 447 catch( Exception& ) 448 { 449 // not all documents support this 450 } 451 452 if( xBasicLib.is() ) 453 { 454 // call Basic source code import for each module, boost::[c]ref enforces pass-by-ref 455 aModules.forEachMem( &VbaModule::createAndImportModule, 456 ::boost::ref( *xVbaStrg ), ::boost::cref( xBasicLib ), 457 ::boost::cref( xDocObjectNA ) ); 458 459 // create empty dummy modules 460 aDummyModules.forEachMem( &VbaModule::createEmptyModule, 461 ::boost::cref( xBasicLib ), ::boost::cref( xDocObjectNA ) ); 462 } 463 } 464 catch( Exception& ) 465 { 466 } 467 468 /* Load the forms. The file format specification requires that a module 469 must exist for every form. We are a bit more tolerant and scan the 470 project storage for all form substorages. This may 'repair' broken VBA 471 storages that misses to mention a module for an existing form. */ 472 ::std::vector< OUString > aElements; 473 rVbaPrjStrg.getElementNames( aElements ); 474 for( ::std::vector< OUString >::iterator aIt = aElements.begin(), aEnd = aElements.end(); aIt != aEnd; ++aIt ) 475 { 476 // try to open the element as storage 477 if( !aIt->equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "VBA" ) ) ) 478 { 479 StorageRef xSubStrg = rVbaPrjStrg.openSubStorage( *aIt, false ); 480 if( xSubStrg.get() ) try 481 { 482 // resolve module name from storage name (which equals the module stream name) 483 VbaModule* pModule = aModulesByStrm.get( *aIt ).get(); 484 OSL_ENSURE( pModule && (pModule->getType() == ModuleType::FORM), 485 "VbaProject::importVba - form substorage without form module" ); 486 OUString aModuleName; 487 if( pModule ) 488 aModuleName = pModule->getName(); 489 490 // create and import the form 491 Reference< XNameContainer > xDialogLib( createDialogLibrary(), UNO_SET_THROW ); 492 VbaUserForm aForm( mxContext, mxDocModel, rGraphicHelper, bDefaultColorBgr ); 493 aForm.importForm( xDialogLib, *xSubStrg, aModuleName, eTextEnc ); 494 } 495 catch( Exception& ) 496 { 497 } 498 } 499 } 500 501 // attach macros to registered objects 502 attachMacros(); 503 // virtual call, derived classes may do some more processing 504 finalizeImport(); 505 } 506 507 void VbaProject::attachMacros() 508 { 509 if( !maMacroAttachers.empty() && mxContext.is() ) try 510 { 511 Reference< XMultiComponentFactory > xFactory( mxContext->getServiceManager(), UNO_SET_THROW ); 512 Sequence< Any > aArgs( 2 ); 513 aArgs[ 0 ] <<= mxDocModel; 514 aArgs[ 1 ] <<= maPrjName; 515 Reference< XVBAMacroResolver > xResolver( xFactory->createInstanceWithArgumentsAndContext( 516 CREATE_OUSTRING( "com.sun.star.script.vba.VBAMacroResolver" ), aArgs, mxContext ), UNO_QUERY_THROW ); 517 maMacroAttachers.forEachMem( &VbaMacroAttacherBase::resolveAndAttachMacro, ::boost::cref( xResolver ) ); 518 } 519 catch( Exception& ) 520 { 521 } 522 } 523 524 void VbaProject::copyStorage( StorageBase& rVbaPrjStrg ) 525 { 526 if( mxContext.is() ) try 527 { 528 Reference< XStorageBasedDocument > xStorageBasedDoc( mxDocModel, UNO_QUERY_THROW ); 529 Reference< XStorage > xDocStorage( xStorageBasedDoc->getDocumentStorage(), UNO_QUERY_THROW ); 530 { 531 const sal_Int32 nOpenMode = ElementModes::SEEKABLE | ElementModes::WRITE | ElementModes::TRUNCATE; 532 Reference< XStream > xDocStream( xDocStorage->openStreamElement( CREATE_OUSTRING( "_MS_VBA_Macros" ), nOpenMode ), UNO_SET_THROW ); 533 OleStorage aDestStorage( mxContext, xDocStream, false ); 534 rVbaPrjStrg.copyStorageToStorage( aDestStorage ); 535 aDestStorage.commit(); 536 } 537 Reference< XTransactedObject >( xDocStorage, UNO_QUERY_THROW )->commit(); 538 } 539 catch( Exception& ) 540 { 541 } 542 } 543 544 // ============================================================================ 545 546 } // namespace ole 547 } // namespace oox 548