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/axbinaryreader.hxx" 25cdf0e10cSrcweir 26cdf0e10cSrcweir #include "oox/ole/olehelper.hxx" 27cdf0e10cSrcweir 28cdf0e10cSrcweir namespace oox { 29cdf0e10cSrcweir namespace ole { 30cdf0e10cSrcweir 31cdf0e10cSrcweir // ============================================================================ 32cdf0e10cSrcweir 33cdf0e10cSrcweir using ::rtl::OUString; 34cdf0e10cSrcweir 35cdf0e10cSrcweir // ============================================================================ 36cdf0e10cSrcweir 37cdf0e10cSrcweir namespace { 38cdf0e10cSrcweir 39cdf0e10cSrcweir const sal_uInt32 AX_STRING_SIZEMASK = 0x7FFFFFFF; 40cdf0e10cSrcweir const sal_uInt32 AX_STRING_COMPRESSED = 0x80000000; 41cdf0e10cSrcweir 42cdf0e10cSrcweir } // namespace 43cdf0e10cSrcweir 44cdf0e10cSrcweir // ============================================================================ 45cdf0e10cSrcweir 46cdf0e10cSrcweir AxAlignedInputStream::AxAlignedInputStream( BinaryInputStream& rInStrm ) : 47cdf0e10cSrcweir BinaryStreamBase( false ), 48cdf0e10cSrcweir mpInStrm( &rInStrm ), 49cdf0e10cSrcweir mnStrmPos( 0 ), 50cdf0e10cSrcweir mnStrmSize( rInStrm.getRemaining() ) 51cdf0e10cSrcweir { 52cdf0e10cSrcweir mbEof = mbEof || rInStrm.isEof(); 53cdf0e10cSrcweir } 54cdf0e10cSrcweir 55cdf0e10cSrcweir sal_Int64 AxAlignedInputStream::size() const 56cdf0e10cSrcweir { 57cdf0e10cSrcweir return mpInStrm ? mnStrmSize : -1; 58cdf0e10cSrcweir } 59cdf0e10cSrcweir 60cdf0e10cSrcweir sal_Int64 AxAlignedInputStream::tell() const 61cdf0e10cSrcweir { 62cdf0e10cSrcweir return mpInStrm ? mnStrmPos : -1; 63cdf0e10cSrcweir } 64cdf0e10cSrcweir 65cdf0e10cSrcweir void AxAlignedInputStream::seek( sal_Int64 nPos ) 66cdf0e10cSrcweir { 67cdf0e10cSrcweir mbEof = mbEof || (nPos < mnStrmPos); 68cdf0e10cSrcweir if( !mbEof ) 69cdf0e10cSrcweir skip( static_cast< sal_Int32 >( nPos - mnStrmPos ) ); 70cdf0e10cSrcweir } 71cdf0e10cSrcweir 72cdf0e10cSrcweir void AxAlignedInputStream::close() 73cdf0e10cSrcweir { 74cdf0e10cSrcweir mpInStrm = 0; 75cdf0e10cSrcweir mbEof = true; 76cdf0e10cSrcweir } 77cdf0e10cSrcweir 78cdf0e10cSrcweir sal_Int32 AxAlignedInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize ) 79cdf0e10cSrcweir { 80cdf0e10cSrcweir sal_Int32 nReadSize = 0; 81cdf0e10cSrcweir if( !mbEof ) 82cdf0e10cSrcweir { 83cdf0e10cSrcweir nReadSize = mpInStrm->readData( orData, nBytes, nAtomSize ); 84cdf0e10cSrcweir mnStrmPos += nReadSize; 85cdf0e10cSrcweir mbEof = mpInStrm->isEof(); 86cdf0e10cSrcweir } 87cdf0e10cSrcweir return nReadSize; 88cdf0e10cSrcweir } 89cdf0e10cSrcweir 90cdf0e10cSrcweir sal_Int32 AxAlignedInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize ) 91cdf0e10cSrcweir { 92cdf0e10cSrcweir sal_Int32 nReadSize = 0; 93cdf0e10cSrcweir if( !mbEof ) 94cdf0e10cSrcweir { 95cdf0e10cSrcweir nReadSize = mpInStrm->readMemory( opMem, nBytes, nAtomSize ); 96cdf0e10cSrcweir mnStrmPos += nReadSize; 97cdf0e10cSrcweir mbEof = mpInStrm->isEof(); 98cdf0e10cSrcweir } 99cdf0e10cSrcweir return nReadSize; 100cdf0e10cSrcweir } 101cdf0e10cSrcweir 102cdf0e10cSrcweir void AxAlignedInputStream::skip( sal_Int32 nBytes, size_t nAtomSize ) 103cdf0e10cSrcweir { 104cdf0e10cSrcweir if( !mbEof ) 105cdf0e10cSrcweir { 106cdf0e10cSrcweir mpInStrm->skip( nBytes, nAtomSize ); 107cdf0e10cSrcweir mnStrmPos += nBytes; 108cdf0e10cSrcweir mbEof = mpInStrm->isEof(); 109cdf0e10cSrcweir } 110cdf0e10cSrcweir } 111cdf0e10cSrcweir 112cdf0e10cSrcweir void AxAlignedInputStream::align( size_t nSize ) 113cdf0e10cSrcweir { 114cdf0e10cSrcweir skip( static_cast< sal_Int32 >( (nSize - (mnStrmPos % nSize)) % nSize ) ); 115cdf0e10cSrcweir } 116cdf0e10cSrcweir 117cdf0e10cSrcweir // ============================================================================ 118cdf0e10cSrcweir 119cdf0e10cSrcweir AxFontData::AxFontData() : 120cdf0e10cSrcweir mnFontEffects( 0 ), 121cdf0e10cSrcweir mnFontHeight( 160 ), 122cdf0e10cSrcweir mnFontCharSet( WINDOWS_CHARSET_DEFAULT ), 123cdf0e10cSrcweir mnHorAlign( AX_FONTDATA_LEFT ), 124cdf0e10cSrcweir mbDblUnderline( false ) 125cdf0e10cSrcweir { 126cdf0e10cSrcweir } 127cdf0e10cSrcweir 128cdf0e10cSrcweir sal_Int16 AxFontData::getHeightPoints() const 129cdf0e10cSrcweir { 130cdf0e10cSrcweir /* MSO uses weird font sizes: 131cdf0e10cSrcweir 1pt->30, 2pt->45, 3pt->60, 4pt->75, 5pt->105, 6pt->120, 7pt->135, 132cdf0e10cSrcweir 8pt->165, 9pt->180, 10pt->195, 11pt->225, ... */ 133cdf0e10cSrcweir return getLimitedValue< sal_Int16, sal_Int32 >( (mnFontHeight + 10) / 20, 1, SAL_MAX_INT16 ); 134cdf0e10cSrcweir } 135cdf0e10cSrcweir 136cdf0e10cSrcweir void AxFontData::setHeightPoints( sal_Int16 nPoints ) 137cdf0e10cSrcweir { 138cdf0e10cSrcweir mnFontHeight = getLimitedValue< sal_Int32, sal_Int32 >( ((nPoints * 4 + 1) / 3) * 15, 30, 4294967 ); 139cdf0e10cSrcweir } 140cdf0e10cSrcweir 141cdf0e10cSrcweir bool AxFontData::importBinaryModel( BinaryInputStream& rInStrm ) 142cdf0e10cSrcweir { 143cdf0e10cSrcweir AxBinaryPropertyReader aReader( rInStrm ); 144cdf0e10cSrcweir aReader.readStringProperty( maFontName ); 145cdf0e10cSrcweir aReader.readIntProperty< sal_uInt32 >( mnFontEffects ); 146cdf0e10cSrcweir aReader.readIntProperty< sal_Int32 >( mnFontHeight ); 147cdf0e10cSrcweir aReader.skipIntProperty< sal_Int32 >(); // font offset 148cdf0e10cSrcweir aReader.readIntProperty< sal_uInt8 >( mnFontCharSet ); 149cdf0e10cSrcweir aReader.skipIntProperty< sal_uInt8 >(); // font pitch/family 150cdf0e10cSrcweir aReader.readIntProperty< sal_uInt8 >( mnHorAlign ); 151cdf0e10cSrcweir aReader.skipIntProperty< sal_uInt16 >(); // font weight 152cdf0e10cSrcweir mbDblUnderline = false; 153cdf0e10cSrcweir return aReader.finalizeImport(); 154cdf0e10cSrcweir } 155cdf0e10cSrcweir 156cdf0e10cSrcweir bool AxFontData::importStdFont( BinaryInputStream& rInStrm ) 157cdf0e10cSrcweir { 158cdf0e10cSrcweir StdFontInfo aFontInfo; 159cdf0e10cSrcweir if( OleHelper::importStdFont( aFontInfo, rInStrm, false ) ) 160cdf0e10cSrcweir { 161cdf0e10cSrcweir maFontName = aFontInfo.maName; 162cdf0e10cSrcweir mnFontEffects = 0; 163cdf0e10cSrcweir setFlag( mnFontEffects, AX_FONTDATA_BOLD, aFontInfo.mnWeight >= OLE_STDFONT_BOLD ); 164cdf0e10cSrcweir setFlag( mnFontEffects, AX_FONTDATA_ITALIC, getFlag( aFontInfo.mnFlags, OLE_STDFONT_ITALIC ) ); 165cdf0e10cSrcweir setFlag( mnFontEffects, AX_FONTDATA_UNDERLINE, getFlag( aFontInfo.mnFlags, OLE_STDFONT_UNDERLINE ) ); 166cdf0e10cSrcweir setFlag( mnFontEffects, AX_FONTDATA_STRIKEOUT, getFlag( aFontInfo.mnFlags,OLE_STDFONT_STRIKE ) ); 167cdf0e10cSrcweir mbDblUnderline = false; 168cdf0e10cSrcweir // StdFont stores font height in 1/10,000 of points 169cdf0e10cSrcweir setHeightPoints( getLimitedValue< sal_Int16, sal_Int32 >( aFontInfo.mnHeight / 10000, 0, SAL_MAX_INT16 ) ); 170cdf0e10cSrcweir mnFontCharSet = aFontInfo.mnCharSet; 171cdf0e10cSrcweir mnHorAlign = AX_FONTDATA_LEFT; 172cdf0e10cSrcweir return true; 173cdf0e10cSrcweir } 174cdf0e10cSrcweir return false; 175cdf0e10cSrcweir } 176cdf0e10cSrcweir 177cdf0e10cSrcweir bool AxFontData::importGuidAndFont( BinaryInputStream& rInStrm ) 178cdf0e10cSrcweir { 179cdf0e10cSrcweir OUString aGuid = OleHelper::importGuid( rInStrm ); 180cdf0e10cSrcweir if( aGuid.equalsAscii( AX_GUID_CFONT ) ) 181cdf0e10cSrcweir return importBinaryModel( rInStrm ); 182cdf0e10cSrcweir if( aGuid.equalsAscii( OLE_GUID_STDFONT ) ) 183cdf0e10cSrcweir return importStdFont( rInStrm ); 184cdf0e10cSrcweir return false; 185cdf0e10cSrcweir } 186cdf0e10cSrcweir 187cdf0e10cSrcweir // ============================================================================ 188cdf0e10cSrcweir 189cdf0e10cSrcweir namespace { 190cdf0e10cSrcweir 191cdf0e10cSrcweir bool lclReadString( AxAlignedInputStream& rInStrm, OUString& rValue, sal_uInt32 nSize, bool bArrayString ) 192cdf0e10cSrcweir { 193cdf0e10cSrcweir bool bCompressed = getFlag( nSize, AX_STRING_COMPRESSED ); 194cdf0e10cSrcweir sal_uInt32 nBufSize = nSize & AX_STRING_SIZEMASK; 195cdf0e10cSrcweir // Unicode: simple strings store byte count, array strings store char count 196cdf0e10cSrcweir sal_Int32 nChars = static_cast< sal_Int32 >( nBufSize / ((bCompressed || bArrayString) ? 1 : 2) ); 197cdf0e10cSrcweir bool bValidChars = nChars <= 65536; 198cdf0e10cSrcweir OSL_ENSURE( bValidChars, "lclReadString - string too long" ); 199cdf0e10cSrcweir sal_Int64 nEndPos = rInStrm.tell() + nChars * (bCompressed ? 1 : 2); 200cdf0e10cSrcweir nChars = ::std::min< sal_Int32 >( nChars, 65536 ); 201cdf0e10cSrcweir rValue = rInStrm.readCompressedUnicodeArray( nChars, bCompressed ); 202cdf0e10cSrcweir rInStrm.seek( nEndPos ); 203cdf0e10cSrcweir return bValidChars; 204cdf0e10cSrcweir } 205cdf0e10cSrcweir 206cdf0e10cSrcweir } // namespace 207cdf0e10cSrcweir 208cdf0e10cSrcweir // ---------------------------------------------------------------------------- 209cdf0e10cSrcweir 210cdf0e10cSrcweir AxBinaryPropertyReader::ComplexProperty::~ComplexProperty() 211cdf0e10cSrcweir { 212cdf0e10cSrcweir } 213cdf0e10cSrcweir 214cdf0e10cSrcweir bool AxBinaryPropertyReader::PairProperty::readProperty( AxAlignedInputStream& rInStrm ) 215cdf0e10cSrcweir { 216cdf0e10cSrcweir rInStrm >> mrPairData.first >> mrPairData.second; 217cdf0e10cSrcweir return true; 218cdf0e10cSrcweir } 219cdf0e10cSrcweir 220cdf0e10cSrcweir bool AxBinaryPropertyReader::StringProperty::readProperty( AxAlignedInputStream& rInStrm ) 221cdf0e10cSrcweir { 222cdf0e10cSrcweir return lclReadString( rInStrm, mrValue, mnSize, false ); 223cdf0e10cSrcweir } 224cdf0e10cSrcweir 225cdf0e10cSrcweir bool AxBinaryPropertyReader::StringArrayProperty::readProperty( AxAlignedInputStream& rInStrm ) 226cdf0e10cSrcweir { 227cdf0e10cSrcweir sal_Int64 nEndPos = rInStrm.tell() + mnSize; 228cdf0e10cSrcweir while( rInStrm.tell() < nEndPos ) 229cdf0e10cSrcweir { 230cdf0e10cSrcweir OUString aString; 231cdf0e10cSrcweir if( !lclReadString( rInStrm, aString, rInStrm.readuInt32(), true ) ) 232cdf0e10cSrcweir return false; 233cdf0e10cSrcweir mrArray.push_back( aString ); 234cdf0e10cSrcweir // every array string is aligned on 4 byte boundries 235cdf0e10cSrcweir rInStrm.align( 4 ); 236cdf0e10cSrcweir } 237cdf0e10cSrcweir return true; 238cdf0e10cSrcweir } 239cdf0e10cSrcweir 240cdf0e10cSrcweir bool AxBinaryPropertyReader::GuidProperty::readProperty( AxAlignedInputStream& rInStrm ) 241cdf0e10cSrcweir { 242cdf0e10cSrcweir mrGuid = OleHelper::importGuid( rInStrm ); 243cdf0e10cSrcweir return true; 244cdf0e10cSrcweir } 245cdf0e10cSrcweir 246cdf0e10cSrcweir bool AxBinaryPropertyReader::FontProperty::readProperty( AxAlignedInputStream& rInStrm ) 247cdf0e10cSrcweir { 248cdf0e10cSrcweir return mrFontData.importGuidAndFont( rInStrm ); 249cdf0e10cSrcweir } 250cdf0e10cSrcweir 251cdf0e10cSrcweir bool AxBinaryPropertyReader::PictureProperty::readProperty( AxAlignedInputStream& rInStrm ) 252cdf0e10cSrcweir { 253cdf0e10cSrcweir return OleHelper::importStdPic( mrPicData, rInStrm, true ); 254cdf0e10cSrcweir } 255cdf0e10cSrcweir 256cdf0e10cSrcweir // ---------------------------------------------------------------------------- 257cdf0e10cSrcweir 258cdf0e10cSrcweir AxBinaryPropertyReader::AxBinaryPropertyReader( BinaryInputStream& rInStrm, bool b64BitPropFlags ) : 259cdf0e10cSrcweir maInStrm( rInStrm ), 260cdf0e10cSrcweir mbValid( true ) 261cdf0e10cSrcweir { 262cdf0e10cSrcweir // version and size of property block 263cdf0e10cSrcweir maInStrm.skip( 2 ); 264cdf0e10cSrcweir sal_uInt16 nBlockSize = maInStrm.readValue< sal_uInt16 >(); 265cdf0e10cSrcweir mnPropsEnd = maInStrm.tell() + nBlockSize; 266cdf0e10cSrcweir // flagfield containing existing properties 267cdf0e10cSrcweir if( b64BitPropFlags ) 268cdf0e10cSrcweir maInStrm >> mnPropFlags; 269cdf0e10cSrcweir else 270cdf0e10cSrcweir mnPropFlags = maInStrm.readuInt32(); 271cdf0e10cSrcweir mnNextProp = 1; 272cdf0e10cSrcweir } 273cdf0e10cSrcweir 274cdf0e10cSrcweir void AxBinaryPropertyReader::readBoolProperty( bool& orbValue, bool bReverse ) 275cdf0e10cSrcweir { 276cdf0e10cSrcweir // there is no data, the boolean value is equivalent to the property flag itself 277cdf0e10cSrcweir orbValue = startNextProperty() != bReverse; 278cdf0e10cSrcweir } 279cdf0e10cSrcweir 280cdf0e10cSrcweir void AxBinaryPropertyReader::readPairProperty( AxPairData& orPairData ) 281cdf0e10cSrcweir { 282cdf0e10cSrcweir if( startNextProperty() ) 283cdf0e10cSrcweir maLargeProps.push_back( ComplexPropVector::value_type( new PairProperty( orPairData ) ) ); 284cdf0e10cSrcweir } 285cdf0e10cSrcweir 286cdf0e10cSrcweir void AxBinaryPropertyReader::readStringProperty( OUString& orValue ) 287cdf0e10cSrcweir { 288cdf0e10cSrcweir if( startNextProperty() ) 289cdf0e10cSrcweir { 290cdf0e10cSrcweir sal_uInt32 nSize = maInStrm.readAligned< sal_uInt32 >(); 291cdf0e10cSrcweir maLargeProps.push_back( ComplexPropVector::value_type( new StringProperty( orValue, nSize ) ) ); 292cdf0e10cSrcweir } 293cdf0e10cSrcweir } 294cdf0e10cSrcweir 295cdf0e10cSrcweir void AxBinaryPropertyReader::readStringArrayProperty( AxStringArray& orArray ) 296cdf0e10cSrcweir { 297cdf0e10cSrcweir if( startNextProperty() ) 298cdf0e10cSrcweir { 299cdf0e10cSrcweir sal_uInt32 nSize = maInStrm.readAligned< sal_uInt32 >(); 300cdf0e10cSrcweir maLargeProps.push_back( ComplexPropVector::value_type( new StringArrayProperty( orArray, nSize ) ) ); 301cdf0e10cSrcweir } 302cdf0e10cSrcweir } 303cdf0e10cSrcweir 304cdf0e10cSrcweir void AxBinaryPropertyReader::readGuidProperty( ::rtl::OUString& orGuid ) 305cdf0e10cSrcweir { 306cdf0e10cSrcweir if( startNextProperty() ) 307cdf0e10cSrcweir maLargeProps.push_back( ComplexPropVector::value_type( new GuidProperty( orGuid ) ) ); 308cdf0e10cSrcweir } 309cdf0e10cSrcweir 310cdf0e10cSrcweir void AxBinaryPropertyReader::readFontProperty( AxFontData& orFontData ) 311cdf0e10cSrcweir { 312cdf0e10cSrcweir if( startNextProperty() ) 313cdf0e10cSrcweir { 314cdf0e10cSrcweir sal_Int16 nData = maInStrm.readAligned< sal_Int16 >(); 315cdf0e10cSrcweir if( ensureValid( nData == -1 ) ) 316cdf0e10cSrcweir maStreamProps.push_back( ComplexPropVector::value_type( new FontProperty( orFontData ) ) ); 317cdf0e10cSrcweir } 318cdf0e10cSrcweir } 319cdf0e10cSrcweir 320cdf0e10cSrcweir void AxBinaryPropertyReader::readPictureProperty( StreamDataSequence& orPicData ) 321cdf0e10cSrcweir { 322cdf0e10cSrcweir if( startNextProperty() ) 323cdf0e10cSrcweir { 324cdf0e10cSrcweir sal_Int16 nData = maInStrm.readAligned< sal_Int16 >(); 325cdf0e10cSrcweir if( ensureValid( nData == -1 ) ) 326cdf0e10cSrcweir maStreamProps.push_back( ComplexPropVector::value_type( new PictureProperty( orPicData ) ) ); 327cdf0e10cSrcweir } 328cdf0e10cSrcweir } 329cdf0e10cSrcweir 330cdf0e10cSrcweir bool AxBinaryPropertyReader::finalizeImport() 331cdf0e10cSrcweir { 332cdf0e10cSrcweir // read large properties 333cdf0e10cSrcweir maInStrm.align( 4 ); 334cdf0e10cSrcweir if( ensureValid( mnPropFlags == 0 ) && !maLargeProps.empty() ) 335cdf0e10cSrcweir { 336cdf0e10cSrcweir for( ComplexPropVector::iterator aIt = maLargeProps.begin(), aEnd = maLargeProps.end(); ensureValid() && (aIt != aEnd); ++aIt ) 337cdf0e10cSrcweir { 338cdf0e10cSrcweir ensureValid( (*aIt)->readProperty( maInStrm ) ); 339cdf0e10cSrcweir maInStrm.align( 4 ); 340cdf0e10cSrcweir } 341cdf0e10cSrcweir } 342cdf0e10cSrcweir maInStrm.seek( mnPropsEnd ); 343cdf0e10cSrcweir 344cdf0e10cSrcweir // read stream properties (no stream alignment between properties!) 345cdf0e10cSrcweir if( ensureValid() && !maStreamProps.empty() ) 346cdf0e10cSrcweir for( ComplexPropVector::iterator aIt = maStreamProps.begin(), aEnd = maStreamProps.end(); ensureValid() && (aIt != aEnd); ++aIt ) 347cdf0e10cSrcweir ensureValid( (*aIt)->readProperty( maInStrm ) ); 348cdf0e10cSrcweir 349cdf0e10cSrcweir return mbValid; 350cdf0e10cSrcweir } 351cdf0e10cSrcweir 352cdf0e10cSrcweir bool AxBinaryPropertyReader::ensureValid( bool bCondition ) 353cdf0e10cSrcweir { 354cdf0e10cSrcweir mbValid = mbValid && bCondition && !maInStrm.isEof(); 355cdf0e10cSrcweir return mbValid; 356cdf0e10cSrcweir } 357cdf0e10cSrcweir 358cdf0e10cSrcweir bool AxBinaryPropertyReader::startNextProperty() 359cdf0e10cSrcweir { 360cdf0e10cSrcweir bool bHasProp = getFlag( mnPropFlags, mnNextProp ); 361cdf0e10cSrcweir setFlag( mnPropFlags, mnNextProp, false ); 362cdf0e10cSrcweir mnNextProp <<= 1; 363cdf0e10cSrcweir return ensureValid() && bHasProp; 364cdf0e10cSrcweir } 365cdf0e10cSrcweir 366cdf0e10cSrcweir // ============================================================================ 367cdf0e10cSrcweir 368cdf0e10cSrcweir } // namespace ole 369cdf0e10cSrcweir } // namespace oox 370