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