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