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