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