xref: /aoo41x/main/sfx2/source/doc/oleprops.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sfx2.hxx"
30 
31 #include "oleprops.hxx"
32 
33 #include <comphelper/types.hxx>
34 #include <tools/debug.hxx>
35 #include <tools/datetime.hxx>
36 #include <rtl/tencinfo.h>
37 
38 // ============================================================================
39 
40 
41 // ============================================================================
42 
43 #define VERSION 11
44 #define STREAM_BUFFER_SIZE 2048
45 
46 // usings
47 using ::rtl::OUString;
48 using ::com::sun::star::uno::Any;
49 using ::com::sun::star::uno::makeAny;
50 
51 using namespace ::com::sun::star;
52 
53 #define TIMESTAMP_INVALID_DATETIME    	( DateTime ( Date ( 1, 1, 1601 ), Time ( 0, 0, 0 ) ) )	/// Invalid value for date and time to create invalid instance of TimeStamp.
54 #define TIMESTAMP_INVALID_UTILDATETIME  ( util::DateTime ( 0, 0, 0, 0, 1, 1, 1601 ) )	/// Invalid value for date and time to create invalid instance of TimeStamp.
55 
56 static
57 bool operator==(const util::DateTime &i_rLeft, const util::DateTime &i_rRight)
58 {
59     return i_rLeft.Year             == i_rRight.Year
60         && i_rLeft.Month            == i_rRight.Month
61         && i_rLeft.Day              == i_rRight.Day
62         && i_rLeft.Hours            == i_rRight.Hours
63         && i_rLeft.Minutes          == i_rRight.Minutes
64         && i_rLeft.Seconds          == i_rRight.Seconds
65         && i_rLeft.HundredthSeconds == i_rRight.HundredthSeconds;
66 }
67 
68 // ============================================================================
69 
70 /** Property representing a signed 32-bit integer value. */
71 class SfxOleInt32Property : public SfxOlePropertyBase
72 {
73 public:
74     explicit            SfxOleInt32Property( sal_Int32 nPropId, sal_Int32 nValue = 0 );
75 
76     inline sal_Int32    GetValue() const { return mnValue; }
77     inline void         SetValue( sal_Int32 nValue ) { mnValue = nValue; }
78 
79 private:
80     virtual void        ImplLoad( SvStream& rStrm );
81     virtual void        ImplSave( SvStream& rStrm );
82 
83 private:
84     sal_Int32           mnValue;
85 };
86 
87 // ============================================================================
88 
89 /** Property representing a floating-point value. */
90 class SfxOleDoubleProperty : public SfxOlePropertyBase
91 {
92 public:
93     explicit            SfxOleDoubleProperty( sal_Int32 nPropId, double fValue = 0.0 );
94 
95     inline double       GetValue() const { return mfValue; }
96     inline void         SetValue( double fValue ) { mfValue = fValue; }
97 
98 private:
99     virtual void        ImplLoad( SvStream& rStrm );
100     virtual void        ImplSave( SvStream& rStrm );
101 
102 private:
103     double              mfValue;
104 };
105 
106 // ============================================================================
107 
108 /** Property representing a boolean value. */
109 class SfxOleBoolProperty : public SfxOlePropertyBase
110 {
111 public:
112     explicit            SfxOleBoolProperty( sal_Int32 nPropId, bool bValue = false );
113 
114     inline bool         GetValue() const { return mbValue; }
115     inline void         SetValue( bool bValue ) { mbValue = bValue; }
116 
117 private:
118     virtual void        ImplLoad( SvStream& rStrm );
119     virtual void        ImplSave( SvStream& rStrm );
120 
121 private:
122     bool                mbValue;
123 };
124 
125 // ============================================================================
126 
127 /** Base class for properties that contain a single string value. */
128 class SfxOleStringPropertyBase : public SfxOlePropertyBase, public SfxOleStringHelper
129 {
130 public:
131     explicit            SfxOleStringPropertyBase(
132                             sal_Int32 nPropId, sal_Int32 nPropType,
133                             const SfxOleTextEncoding& rTextEnc );
134     explicit            SfxOleStringPropertyBase(
135                             sal_Int32 nPropId, sal_Int32 nPropType,
136                             const SfxOleTextEncoding& rTextEnc, const String& rValue );
137     explicit            SfxOleStringPropertyBase(
138                             sal_Int32 nPropId, sal_Int32 nPropType,
139                             rtl_TextEncoding eTextEnc );
140     explicit            SfxOleStringPropertyBase(
141                             sal_Int32 nPropId, sal_Int32 nPropType,
142                             rtl_TextEncoding eTextEnc, const String& rValue );
143 
144     inline const String& GetValue() const { return maValue; }
145     inline void         SetValue( const String& rValue ) { maValue = rValue; }
146 
147 private:
148     String              maValue;
149 };
150 
151 // ============================================================================
152 
153 /** Property representing a bytestring value. */
154 class SfxOleString8Property : public SfxOleStringPropertyBase
155 {
156 public:
157     explicit            SfxOleString8Property(
158                             sal_Int32 nPropId, const SfxOleTextEncoding& rTextEnc );
159     explicit            SfxOleString8Property(
160                             sal_Int32 nPropId, const SfxOleTextEncoding& rTextEnc,
161                             const String& rValue );
162 
163 private:
164     virtual void        ImplLoad( SvStream& rStrm );
165     virtual void        ImplSave( SvStream& rStrm );
166 };
167 
168 // ============================================================================
169 
170 /** Property representing a Unicode string value. */
171 class SfxOleString16Property : public SfxOleStringPropertyBase
172 {
173 public:
174     explicit            SfxOleString16Property( sal_Int32 nPropId );
175     explicit            SfxOleString16Property( sal_Int32 nPropId, const String& rValue );
176 
177 private:
178     virtual void        ImplLoad( SvStream& rStrm );
179     virtual void        ImplSave( SvStream& rStrm );
180 };
181 
182 // ============================================================================
183 
184 /** Property representing a filetime value as defined by the Windows API. */
185 class SfxOleFileTimeProperty : public SfxOlePropertyBase
186 {
187 public:
188     explicit            SfxOleFileTimeProperty( sal_Int32 nPropId );
189     /** @param rDateTime  Date and time as LOCAL time. */
190     explicit            SfxOleFileTimeProperty( sal_Int32 nPropId, const util::DateTime& rDateTime );
191 
192     /** Returns the time value as LOCAL time. */
193     inline const util::DateTime& GetValue() const { return maDateTime; }
194     /** @param rDateTime  Date and time as LOCAL time. */
195     inline void         SetValue( const util::DateTime& rDateTime ) { maDateTime = rDateTime; }
196 
197 private:
198     virtual void        ImplLoad( SvStream& rStrm );
199     virtual void        ImplSave( SvStream& rStrm );
200 
201 private:
202     util::DateTime      maDateTime;
203 };
204 
205 // ============================================================================
206 
207 /** Property representing a thumbnail picture.
208 
209     Currently, only saving this property is implemented.
210  */
211 class SfxOleThumbnailProperty : public SfxOlePropertyBase
212 {
213 public:
214     explicit            SfxOleThumbnailProperty( sal_Int32 nPropId,
215                             const uno::Sequence<sal_uInt8> & i_rData);
216 
217     inline bool         IsValid() const { return mData.getLength() > 0; }
218 
219 private:
220     virtual void        ImplLoad( SvStream& rStrm );
221     virtual void        ImplSave( SvStream& rStrm );
222 
223 private:
224     uno::Sequence<sal_uInt8>    mData;
225 };
226 
227 // ============================================================================
228 
229 /** Property representing a BLOB (which presumably stands for binary large
230     object).
231 
232     Currently, only saving this property is implemented.
233  */
234 class SfxOleBlobProperty : public SfxOlePropertyBase
235 {
236 public:
237     explicit            SfxOleBlobProperty( sal_Int32 nPropId,
238                             const uno::Sequence<sal_uInt8> & i_rData);
239     inline bool         IsValid() const { return mData.getLength() > 0; }
240 
241 private:
242     virtual void        ImplLoad( SvStream& rStrm );
243     virtual void        ImplSave( SvStream& rStrm );
244 
245 private:
246     uno::Sequence<sal_uInt8>    mData;
247 };
248 
249 // ============================================================================
250 
251 sal_uInt16 SfxOleTextEncoding::GetCodePage() const
252 {
253     sal_uInt16 nCodePage = IsUnicode() ? CODEPAGE_UNICODE :
254         static_cast< sal_uInt16 >( rtl_getWindowsCodePageFromTextEncoding( *mxTextEnc ) );
255     return (nCodePage == CODEPAGE_UNKNOWN) ? CODEPAGE_UTF8 : nCodePage;
256 }
257 
258 void SfxOleTextEncoding::SetCodePage( sal_uInt16 nCodePage )
259 {
260     if( nCodePage == CODEPAGE_UNICODE )
261         SetUnicode();
262     else
263     {
264         rtl_TextEncoding eTextEnc = rtl_getTextEncodingFromWindowsCodePage( nCodePage );
265         if( eTextEnc != RTL_TEXTENCODING_DONTKNOW )
266             *mxTextEnc = eTextEnc;
267     }
268 }
269 
270 // ----------------------------------------------------------------------------
271 
272 String SfxOleStringHelper::LoadString8( SvStream& rStrm ) const
273 {
274     return IsUnicode() ? ImplLoadString16( rStrm ) : ImplLoadString8( rStrm );
275 }
276 
277 void SfxOleStringHelper::SaveString8( SvStream& rStrm, const String& rValue ) const
278 {
279     if( IsUnicode() )
280         ImplSaveString16( rStrm, rValue );
281     else
282         ImplSaveString8( rStrm, rValue );
283 }
284 
285 String SfxOleStringHelper::LoadString16( SvStream& rStrm ) const
286 {
287     return ImplLoadString16( rStrm );
288 }
289 
290 void SfxOleStringHelper::SaveString16( SvStream& rStrm, const String& rValue ) const
291 {
292     ImplSaveString16( rStrm, rValue );
293 }
294 
295 String SfxOleStringHelper::ImplLoadString8( SvStream& rStrm ) const
296 {
297     String aValue;
298     // read size field (signed 32-bit)
299     sal_Int32 nSize;
300     rStrm >> nSize;
301     // size field includes trailing NUL character
302     DBG_ASSERT( (0 < nSize) && (nSize <= 0xFFFF), "SfxOleStringHelper::ImplLoadString8 - invalid string" );
303     if( (0 < nSize) && (nSize <= 0xFFFF) )
304     {
305         // load character buffer
306         ::std::vector< sal_Char > aBuffer( static_cast< size_t >( nSize + 1 ), 0 );
307         rStrm.Read( &aBuffer.front(), static_cast< sal_Size >( nSize ) );
308         // create string from encoded character array
309         aValue = String( &aBuffer.front(), GetTextEncoding() );
310     }
311     return aValue;
312 }
313 
314 String SfxOleStringHelper::ImplLoadString16( SvStream& rStrm ) const
315 {
316     String aValue;
317     // read size field (signed 32-bit), may be buffer size or character count
318     sal_Int32 nSize;
319     rStrm >> nSize;
320     DBG_ASSERT( (0 < nSize) && (nSize <= 0xFFFF), "SfxOleStringHelper::ImplLoadString16 - invalid string" );
321     // size field includes trailing NUL character
322     if( (0 < nSize) && (nSize <= 0xFFFF) )
323     {
324         // load character buffer
325         ::std::vector< sal_Unicode > aBuffer;
326         aBuffer.reserve( static_cast< size_t >( nSize + 1 ) );
327         sal_uInt16 cChar;
328         for( sal_Int32 nIdx = 0; nIdx < nSize; ++nIdx )
329         {
330             rStrm >> cChar;
331             aBuffer.push_back( static_cast< sal_Unicode >( cChar ) );
332         }
333         // stream is always padded to 32-bit boundary, skip 2 bytes on odd character count
334         if( (nSize & 1) == 1 )
335             rStrm.SeekRel( 2 );
336         // create string from character array
337         aBuffer.push_back( 0 );
338         aValue = String( &aBuffer.front() );
339     }
340     return aValue;
341 }
342 
343 void SfxOleStringHelper::ImplSaveString8( SvStream& rStrm, const String& rValue ) const
344 {
345     // encode to byte string
346     ByteString aEncoded( rValue, GetTextEncoding() );
347     // write size field (including trailing NUL character)
348     sal_Int32 nSize = static_cast< sal_Int32 >( aEncoded.Len() + 1 );
349     rStrm << nSize;
350     // write character array with trailing NUL character
351     rStrm.Write( aEncoded.GetBuffer(), aEncoded.Len() );
352     rStrm << sal_uInt8( 0 );
353 }
354 
355 void SfxOleStringHelper::ImplSaveString16( SvStream& rStrm, const String& rValue ) const
356 {
357     // write size field (including trailing NUL character)
358     sal_Int32 nSize = static_cast< sal_Int32 >( rValue.Len() + 1 );
359     rStrm << nSize;
360     // write character array with trailing NUL character
361     for( xub_StrLen nIdx = 0; nIdx < rValue.Len(); ++nIdx )
362         rStrm << static_cast< sal_uInt16 >( rValue.GetChar( nIdx ) );
363     rStrm << sal_uInt16( 0 );
364     // stream is always padded to 32-bit boundary, add 2 bytes on odd character count
365     if( (nSize & 1) == 1 )
366         rStrm << sal_uInt16( 0 );
367 }
368 
369 // ----------------------------------------------------------------------------
370 
371 SfxOleObjectBase::~SfxOleObjectBase()
372 {
373 }
374 
375 ErrCode SfxOleObjectBase::Load( SvStream& rStrm )
376 {
377     mnErrCode = ERRCODE_NONE;
378     ImplLoad( rStrm );
379     SetError( rStrm.GetErrorCode() );
380     return GetError();
381 }
382 
383 ErrCode SfxOleObjectBase::Save( SvStream& rStrm )
384 {
385     mnErrCode = ERRCODE_NONE;
386     ImplSave( rStrm );
387     SetError( rStrm.GetErrorCode() );
388     return GetError();
389 }
390 
391 void SfxOleObjectBase::LoadObject( SvStream& rStrm, SfxOleObjectBase& rObj )
392 {
393     SetError( rObj.Load( rStrm ) );
394 }
395 
396 void SfxOleObjectBase::SaveObject( SvStream& rStrm, SfxOleObjectBase& rObj )
397 {
398     SetError( rObj.Save( rStrm ) );
399 }
400 
401 // ----------------------------------------------------------------------------
402 
403 SfxOleCodePageProperty::SfxOleCodePageProperty() :
404     SfxOlePropertyBase( PROPID_CODEPAGE, PROPTYPE_INT16 )
405 {
406 }
407 
408 void SfxOleCodePageProperty::ImplLoad( SvStream& rStrm )
409 {
410     // property type is signed int16, but we use always unsigned int16 for codepages
411     sal_uInt16 nCodePage;
412     rStrm >> nCodePage;
413     SetCodePage( nCodePage );
414 }
415 
416 void SfxOleCodePageProperty::ImplSave( SvStream& rStrm )
417 {
418     // property type is signed int16, but we use always unsigned int16 for codepages
419     rStrm << GetCodePage();
420 }
421 
422 // ----------------------------------------------------------------------------
423 
424 SfxOleInt32Property::SfxOleInt32Property( sal_Int32 nPropId, sal_Int32 nValue ) :
425     SfxOlePropertyBase( nPropId, PROPTYPE_INT32 ),
426     mnValue( nValue )
427 {
428 }
429 
430 void SfxOleInt32Property::ImplLoad( SvStream& rStrm )
431 {
432     rStrm >> mnValue;
433 }
434 
435 void SfxOleInt32Property::ImplSave( SvStream& rStrm )
436 {
437     rStrm << mnValue;
438 }
439 
440 // ----------------------------------------------------------------------------
441 
442 SfxOleDoubleProperty::SfxOleDoubleProperty( sal_Int32 nPropId, double fValue ) :
443     SfxOlePropertyBase( nPropId, PROPTYPE_DOUBLE ),
444     mfValue( fValue )
445 {
446 }
447 
448 void SfxOleDoubleProperty::ImplLoad( SvStream& rStrm )
449 {
450     rStrm >> mfValue;
451 }
452 
453 void SfxOleDoubleProperty::ImplSave( SvStream& rStrm )
454 {
455     rStrm << mfValue;
456 }
457 
458 // ----------------------------------------------------------------------------
459 
460 SfxOleBoolProperty::SfxOleBoolProperty( sal_Int32 nPropId, bool bValue ) :
461     SfxOlePropertyBase( nPropId, PROPTYPE_BOOL ),
462     mbValue( bValue )
463 {
464 }
465 
466 void SfxOleBoolProperty::ImplLoad( SvStream& rStrm )
467 {
468     sal_Int16 nValue;
469     rStrm >> nValue;
470     mbValue = nValue != 0;
471 }
472 
473 void SfxOleBoolProperty::ImplSave( SvStream& rStrm )
474 {
475     rStrm << static_cast< sal_Int16 >( mbValue ? -1 : 0 );
476 }
477 
478 // ----------------------------------------------------------------------------
479 
480 SfxOleStringPropertyBase::SfxOleStringPropertyBase(
481         sal_Int32 nPropId, sal_Int32 nPropType, const SfxOleTextEncoding& rTextEnc ) :
482     SfxOlePropertyBase( nPropId, nPropType ),
483     SfxOleStringHelper( rTextEnc )
484 {
485 }
486 
487 SfxOleStringPropertyBase::SfxOleStringPropertyBase(
488         sal_Int32 nPropId, sal_Int32 nPropType, const SfxOleTextEncoding& rTextEnc, const String& rValue ) :
489     SfxOlePropertyBase( nPropId, nPropType ),
490     SfxOleStringHelper( rTextEnc ),
491     maValue( rValue )
492 {
493 }
494 
495 SfxOleStringPropertyBase::SfxOleStringPropertyBase(
496         sal_Int32 nPropId, sal_Int32 nPropType, rtl_TextEncoding eTextEnc ) :
497     SfxOlePropertyBase( nPropId, nPropType ),
498     SfxOleStringHelper( eTextEnc )
499 {
500 }
501 
502 SfxOleStringPropertyBase::SfxOleStringPropertyBase(
503         sal_Int32 nPropId, sal_Int32 nPropType, rtl_TextEncoding eTextEnc, const String& rValue ) :
504     SfxOlePropertyBase( nPropId, nPropType ),
505     SfxOleStringHelper( eTextEnc ),
506     maValue( rValue )
507 {
508 }
509 
510 // ----------------------------------------------------------------------------
511 
512 SfxOleString8Property::SfxOleString8Property(
513         sal_Int32 nPropId, const SfxOleTextEncoding& rTextEnc ) :
514     SfxOleStringPropertyBase( nPropId, PROPTYPE_STRING8, rTextEnc )
515 {
516 }
517 
518 SfxOleString8Property::SfxOleString8Property(
519         sal_Int32 nPropId, const SfxOleTextEncoding& rTextEnc, const String& rValue ) :
520     SfxOleStringPropertyBase( nPropId, PROPTYPE_STRING8, rTextEnc, rValue )
521 {
522 }
523 
524 void SfxOleString8Property::ImplLoad( SvStream& rStrm )
525 {
526     SetValue( LoadString8( rStrm ) );
527 }
528 
529 void SfxOleString8Property::ImplSave( SvStream& rStrm )
530 {
531     SaveString8( rStrm, GetValue() );
532 }
533 
534 // ----------------------------------------------------------------------------
535 
536 SfxOleString16Property::SfxOleString16Property( sal_Int32 nPropId ) :
537     SfxOleStringPropertyBase( nPropId, PROPTYPE_STRING16, RTL_TEXTENCODING_UCS2 )
538 {
539 }
540 
541 SfxOleString16Property::SfxOleString16Property( sal_Int32 nPropId, const String& rValue ) :
542     SfxOleStringPropertyBase( nPropId, PROPTYPE_STRING16, RTL_TEXTENCODING_UCS2, rValue )
543 {
544 }
545 
546 void SfxOleString16Property::ImplLoad( SvStream& rStrm )
547 {
548     SetValue( LoadString16( rStrm ) );
549 }
550 
551 void SfxOleString16Property::ImplSave( SvStream& rStrm )
552 {
553     SaveString16( rStrm, GetValue() );
554 }
555 
556 // ----------------------------------------------------------------------------
557 
558 SfxOleFileTimeProperty::SfxOleFileTimeProperty( sal_Int32 nPropId ) :
559     SfxOlePropertyBase( nPropId, PROPTYPE_FILETIME )
560 {
561 }
562 
563 SfxOleFileTimeProperty::SfxOleFileTimeProperty( sal_Int32 nPropId, const util::DateTime& rDateTime ) :
564     SfxOlePropertyBase( nPropId, PROPTYPE_FILETIME ),
565     maDateTime( rDateTime )
566 {
567 }
568 
569 void SfxOleFileTimeProperty::ImplLoad( SvStream& rStrm )
570 {
571     sal_uInt32 nLower, nUpper;
572     rStrm >> nLower >> nUpper;
573     ::DateTime aDateTime = DateTime::CreateFromWin32FileDateTime( nLower, nUpper );
574     // note: editing duration is stored as offset to TIMESTAMP_INVALID_DATETIME
575     //       of course we should not convert the time zone of a duration!
576     // heuristic to detect editing durations (which we assume to be < 1 year):
577     // check only the year, not the entire date
578 	if ( aDateTime.GetYear() != TIMESTAMP_INVALID_DATETIME.GetYear() )
579 		aDateTime.ConvertToLocalTime();
580     maDateTime.Year    = aDateTime.GetYear();
581     maDateTime.Month   = aDateTime.GetMonth();
582     maDateTime.Day     = aDateTime.GetDay();
583     maDateTime.Hours   = aDateTime.GetHour();
584     maDateTime.Minutes = aDateTime.GetMin();
585     maDateTime.Seconds = aDateTime.GetSec();
586     maDateTime.HundredthSeconds = aDateTime.Get100Sec();
587 }
588 
589 void SfxOleFileTimeProperty::ImplSave( SvStream& rStrm )
590 {
591     DateTime aDateTimeUtc(
592             Date(
593                 static_cast< sal_uInt16 >( maDateTime.Day ),
594                 static_cast< sal_uInt16 >( maDateTime.Month ),
595                 static_cast< sal_uInt16 >( maDateTime.Year ) ),
596             Time(
597                 static_cast< sal_uIntPtr >( maDateTime.Hours ),
598                 static_cast< sal_uIntPtr >( maDateTime.Minutes ),
599                 static_cast< sal_uIntPtr >( maDateTime.Seconds ),
600                 static_cast< sal_uIntPtr >( maDateTime.HundredthSeconds ) ) );
601     // invalid time stamp is not converted to UTC
602     // heuristic to detect editing durations (which we assume to be < 1 year):
603     // check only the year, not the entire date
604     if( aDateTimeUtc.IsValid()
605         && aDateTimeUtc.GetYear() != TIMESTAMP_INVALID_DATETIME.GetYear() ) {
606             aDateTimeUtc.ConvertToUTC();
607     }
608     sal_uInt32 nLower, nUpper;
609     aDateTimeUtc.GetWin32FileDateTime( nLower, nUpper );
610     rStrm << nLower << nUpper;
611 }
612 
613 // ----------------------------------------------------------------------------
614 
615 SfxOleThumbnailProperty::SfxOleThumbnailProperty(
616         sal_Int32 nPropId, const uno::Sequence<sal_uInt8> & i_rData) :
617     SfxOlePropertyBase( nPropId, PROPTYPE_CLIPFMT ),
618     mData(i_rData)
619 {
620 }
621 
622 void SfxOleThumbnailProperty::ImplLoad( SvStream& )
623 {
624     DBG_ERRORFILE( "SfxOleThumbnailProperty::ImplLoad - not implemented" );
625     SetError( SVSTREAM_INVALID_ACCESS );
626 }
627 
628 void SfxOleThumbnailProperty::ImplSave( SvStream& rStrm )
629 {
630     /*  Type        Contents
631         -----------------------------------------------------------------------
632         int32       size of following data
633         int32       clipboard format tag (see below)
634         byte[]      clipboard data (see below)
635 
636         Clipboard format tag:
637             -1 = Windows clipboard format
638             -2 = Macintosh clipboard format
639             -3 = GUID that contains a format identifier (FMTID)
640             >0 = custom clipboard format name plus data (see msdn site below)
641             0  = no data
642 
643         References:
644         http://msdn.microsoft.com/library/default.asp?url=/library/en-us/stg/stg/propvariant.asp
645         http://jakarta.apache.org/poi/hpsf/thumbnails.html
646         http://linux.com.hk/docs/poi/org/apache/poi/hpsf/Thumbnail.html
647         http://sparks.discreet.com/knowledgebase/public/solutions/ExtractThumbnailImg.htm
648      */
649     if( IsValid() )
650     {
651         // clipboard size: clip_format_tag + data_format_tag + bitmap_len
652         sal_Int32 nClipSize = static_cast< sal_Int32 >( 4 + 4 + mData.getLength() );
653         rStrm << nClipSize << CLIPFMT_WIN << CLIPDATAFMT_DIB;
654         rStrm.Write( mData.getConstArray(), mData.getLength() );
655     }
656     else
657     {
658         DBG_ERRORFILE( "SfxOleThumbnailProperty::ImplSave - invalid thumbnail property" );
659         SetError( SVSTREAM_INVALID_ACCESS );
660     }
661 }
662 
663 // ----------------------------------------------------------------------------
664 
665 SfxOleBlobProperty::SfxOleBlobProperty( sal_Int32 nPropId,
666         const uno::Sequence<sal_uInt8> & i_rData) :
667     SfxOlePropertyBase( nPropId, PROPTYPE_BLOB ),
668     mData(i_rData)
669 {
670 }
671 
672 void SfxOleBlobProperty::ImplLoad( SvStream& )
673 {
674     DBG_ERRORFILE( "SfxOleBlobProperty::ImplLoad - not implemented" );
675     SetError( SVSTREAM_INVALID_ACCESS );
676 }
677 
678 void SfxOleBlobProperty::ImplSave( SvStream& rStrm )
679 {
680     if (IsValid()) {
681         rStrm.Write( mData.getConstArray(), mData.getLength() );
682     } else {
683         DBG_ERRORFILE( "SfxOleBlobProperty::ImplSave - invalid BLOB property" );
684         SetError( SVSTREAM_INVALID_ACCESS );
685     }
686 }
687 
688 // ----------------------------------------------------------------------------
689 
690 SfxOleDictionaryProperty::SfxOleDictionaryProperty( const SfxOleTextEncoding& rTextEnc ) :
691     SfxOlePropertyBase( PROPID_DICTIONARY, 0 ),
692     SfxOleStringHelper( rTextEnc )
693 {
694 }
695 
696 const String& SfxOleDictionaryProperty::GetPropertyName( sal_Int32 nPropId ) const
697 {
698     SfxOlePropNameMap::const_iterator aIt = maPropNameMap.find( nPropId );
699     return (aIt == maPropNameMap.end()) ? String::EmptyString() : aIt->second;
700 }
701 
702 void SfxOleDictionaryProperty::SetPropertyName( sal_Int32 nPropId, const String& rPropName )
703 {
704     maPropNameMap[ nPropId ] = rPropName;
705     // dictionary property contains number of pairs in property type field
706     SetPropType( static_cast< sal_Int32 >( maPropNameMap.size() ) );
707 }
708 
709 void SfxOleDictionaryProperty::ImplLoad( SvStream& rStrm )
710 {
711     // dictionary property contains number of pairs in property type field
712     sal_Int32 nNameCount = GetPropType();
713     // read property ID/name pairs
714     maPropNameMap.clear();
715     for( sal_Int32 nIdx = 0; (nIdx < nNameCount) && (rStrm.GetErrorCode() == SVSTREAM_OK) && !rStrm.IsEof(); ++nIdx )
716     {
717         sal_Int32 nPropId;
718         rStrm >> nPropId;
719         // name always stored as byte string
720         maPropNameMap[ nPropId ] = LoadString8( rStrm );
721     }
722 }
723 
724 void SfxOleDictionaryProperty::ImplSave( SvStream& rStrm )
725 {
726     // write property ID/name pairs
727     for( SfxOlePropNameMap::const_iterator aIt = maPropNameMap.begin(), aEnd = maPropNameMap.end(); aIt != aEnd; ++aIt )
728     {
729         rStrm << aIt->first;
730         // name always stored as byte string
731         SaveString8( rStrm, aIt->second );
732     }
733 }
734 
735 // ----------------------------------------------------------------------------
736 
737 SfxOleSection::SfxOleSection( bool bSupportsDict ) :
738     maDictProp( maCodePageProp ),
739     mnStartPos( 0 ),
740     mbSupportsDict( bSupportsDict )
741 {
742 }
743 
744 SfxOlePropertyRef SfxOleSection::GetProperty( sal_Int32 nPropId ) const
745 {
746     SfxOlePropertyRef xProp;
747     SfxOlePropMap::const_iterator aIt = maPropMap.find( nPropId );
748     if( aIt != maPropMap.end() )
749         xProp = aIt->second;
750     return xProp;
751 }
752 
753 bool SfxOleSection::GetInt32Value( sal_Int32& rnValue, sal_Int32 nPropId ) const
754 {
755     SfxOlePropertyRef xProp = GetProperty( nPropId );
756     const SfxOleInt32Property* pProp =
757         dynamic_cast< const SfxOleInt32Property* >( xProp.get() );
758     if( pProp )
759         rnValue = pProp->GetValue();
760     return pProp != 0;
761 }
762 
763 bool SfxOleSection::GetDoubleValue( double& rfValue, sal_Int32 nPropId ) const
764 {
765     SfxOlePropertyRef xProp = GetProperty( nPropId );
766     const SfxOleDoubleProperty* pProp =
767         dynamic_cast< const SfxOleDoubleProperty* >( xProp.get() );
768     if( pProp )
769         rfValue = pProp->GetValue();
770     return pProp != 0;
771 }
772 
773 bool SfxOleSection::GetBoolValue( bool& rbValue, sal_Int32 nPropId ) const
774 {
775     SfxOlePropertyRef xProp = GetProperty( nPropId );
776     const SfxOleBoolProperty* pProp =
777         dynamic_cast< const SfxOleBoolProperty* >( xProp.get() );
778     if( pProp )
779         rbValue = pProp->GetValue();
780     return pProp != 0;
781 }
782 
783 bool SfxOleSection::GetStringValue( String& rValue, sal_Int32 nPropId ) const
784 {
785     SfxOlePropertyRef xProp = GetProperty( nPropId );
786     const SfxOleStringPropertyBase* pProp =
787         dynamic_cast< const SfxOleStringPropertyBase* >( xProp.get() );
788     if( pProp )
789         rValue = pProp->GetValue();
790     return pProp != 0;
791 }
792 
793 bool SfxOleSection::GetFileTimeValue( util::DateTime& rValue, sal_Int32 nPropId ) const
794 {
795     SfxOlePropertyRef xProp = GetProperty( nPropId );
796     const SfxOleFileTimeProperty* pProp =
797         dynamic_cast< const SfxOleFileTimeProperty* >( xProp.get() );
798     if( pProp )
799 	{
800 		if ( pProp->GetValue() == TIMESTAMP_INVALID_UTILDATETIME )
801 			rValue = util::DateTime();
802 		else
803 			rValue = pProp->GetValue();
804 	}
805     return pProp != 0;
806 }
807 
808 void SfxOleSection::SetProperty( SfxOlePropertyRef xProp )
809 {
810     if( xProp.get() )
811         maPropMap[ xProp->GetPropId() ] = xProp;
812 }
813 
814 void SfxOleSection::SetInt32Value( sal_Int32 nPropId, sal_Int32 nValue )
815 {
816     SetProperty( SfxOlePropertyRef( new SfxOleInt32Property( nPropId, nValue ) ) );
817 }
818 
819 void SfxOleSection::SetDoubleValue( sal_Int32 nPropId, double fValue )
820 {
821     SetProperty( SfxOlePropertyRef( new SfxOleDoubleProperty( nPropId, fValue ) ) );
822 }
823 
824 void SfxOleSection::SetBoolValue( sal_Int32 nPropId, bool bValue )
825 {
826     SetProperty( SfxOlePropertyRef( new SfxOleBoolProperty( nPropId, bValue ) ) );
827 }
828 
829 bool SfxOleSection::SetStringValue( sal_Int32 nPropId, const String& rValue, bool bSkipEmpty )
830 {
831     bool bInserted = !bSkipEmpty || (rValue.Len() > 0);
832     if( bInserted )
833         SetProperty( SfxOlePropertyRef( new SfxOleString8Property( nPropId, maCodePageProp, rValue ) ) );
834     return bInserted;
835 }
836 
837 void SfxOleSection::SetFileTimeValue( sal_Int32 nPropId, const util::DateTime& rValue )
838 {
839 	if ( rValue.Year == 0 || rValue.Month == 0 || rValue.Day == 0 )
840 	    SetProperty( SfxOlePropertyRef( new SfxOleFileTimeProperty( nPropId, TIMESTAMP_INVALID_UTILDATETIME ) ) );
841 	else
842 	    SetProperty( SfxOlePropertyRef( new SfxOleFileTimeProperty( nPropId, rValue ) ) );
843 }
844 
845 void SfxOleSection::SetThumbnailValue( sal_Int32 nPropId,
846     const uno::Sequence<sal_uInt8> & i_rData)
847 {
848     SfxOleThumbnailProperty* pThumbnail = new SfxOleThumbnailProperty( nPropId, i_rData );
849     SfxOlePropertyRef xProp( pThumbnail );  // take ownership
850     if( pThumbnail->IsValid() )
851         SetProperty( xProp );
852 }
853 
854 void SfxOleSection::SetBlobValue( sal_Int32 nPropId,
855     const uno::Sequence<sal_uInt8> & i_rData)
856 {
857     SfxOleBlobProperty* pBlob( new SfxOleBlobProperty( nPropId, i_rData ) );
858     SfxOlePropertyRef xProp( pBlob );
859     if( pBlob->IsValid() ) {
860         SetProperty( xProp );
861     }
862 }
863 
864 Any SfxOleSection::GetAnyValue( sal_Int32 nPropId ) const
865 {
866     Any aValue;
867     sal_Int32 nInt32 = 0;
868     double fDouble = 0.0;
869     bool bBool = false;
870     String aString;
871     ::com::sun::star::util::DateTime aApiDateTime;
872 
873     if( GetInt32Value( nInt32, nPropId ) )
874         aValue <<= nInt32;
875     else if( GetDoubleValue( fDouble, nPropId ) )
876         aValue <<= fDouble;
877     else if( GetBoolValue( bBool, nPropId ) )
878         ::comphelper::setBOOL( aValue, bBool ? sal_True : sal_False );
879     else if( GetStringValue( aString, nPropId ) )
880         aValue <<= OUString( aString );
881     else if( GetFileTimeValue( aApiDateTime, nPropId ) )
882     {
883         aValue <<= aApiDateTime;
884     }
885     return aValue;
886 }
887 
888 bool SfxOleSection::SetAnyValue( sal_Int32 nPropId, const Any& rValue )
889 {
890     bool bInserted = true;
891     sal_Int32 nInt32 = 0;
892     double fDouble = 0.0;
893     OUString aString;
894     ::com::sun::star::util::DateTime aApiDateTime;
895 
896     if( rValue.getValueType() == ::getBooleanCppuType() )
897         SetBoolValue( nPropId, ::comphelper::getBOOL( rValue ) == sal_True );
898     else if( rValue >>= nInt32 )
899         SetInt32Value( nPropId, nInt32 );
900     else if( rValue >>= fDouble )
901         SetDoubleValue( nPropId, fDouble );
902     else if( rValue >>= aString )
903         bInserted = SetStringValue( nPropId, aString );
904     else if( rValue >>= aApiDateTime )
905     {
906         SetFileTimeValue( nPropId, aApiDateTime );
907     }
908     else
909         bInserted = false;
910     return bInserted;
911 }
912 
913 const String& SfxOleSection::GetPropertyName( sal_Int32 nPropId ) const
914 {
915     return maDictProp.GetPropertyName( nPropId );
916 }
917 
918 void SfxOleSection::SetPropertyName( sal_Int32 nPropId, const String& rPropName )
919 {
920     maDictProp.SetPropertyName( nPropId, rPropName );
921 }
922 
923 void SfxOleSection::GetPropertyIds( ::std::vector< sal_Int32 >& rPropIds ) const
924 {
925     rPropIds.clear();
926     for( SfxOlePropMap::const_iterator aIt = maPropMap.begin(), aEnd = maPropMap.end(); aIt != aEnd; ++aIt )
927         rPropIds.push_back( aIt->first );
928 }
929 
930 sal_Int32 SfxOleSection::GetFreePropertyId() const
931 {
932     return maPropMap.empty() ? PROPID_FIRSTCUSTOM : (maPropMap.rbegin()->first + 1);
933 }
934 
935 void SfxOleSection::ImplLoad( SvStream& rStrm )
936 {
937     // read section header
938     mnStartPos = rStrm.Tell();
939     sal_uInt32 nSize;
940     sal_Int32 nPropCount;
941     rStrm >> nSize >> nPropCount;
942 
943     // read property ID/position pairs
944     typedef ::std::map< sal_Int32, sal_uInt32 > SfxOlePropPosMap;
945     SfxOlePropPosMap aPropPosMap;
946     for( sal_Int32 nPropIdx = 0; (nPropIdx < nPropCount) && (rStrm.GetErrorCode() == SVSTREAM_OK) && !rStrm.IsEof(); ++nPropIdx )
947     {
948         sal_Int32 nPropId;
949         sal_uInt32 nPropPos;
950         rStrm >> nPropId >> nPropPos;
951         aPropPosMap[ nPropId ] = nPropPos;
952     }
953 
954     // read codepage property
955     SfxOlePropPosMap::iterator aCodePageIt = aPropPosMap.find( PROPID_CODEPAGE );
956     if( (aCodePageIt != aPropPosMap.end()) && SeekToPropertyPos( rStrm, aCodePageIt->second ) )
957     {
958         // codepage property must be of type signed int-16
959         sal_Int32 nPropType;
960         rStrm >> nPropType;
961         if( nPropType == PROPTYPE_INT16 )
962             LoadObject( rStrm, maCodePageProp );
963         // remove property position
964         aPropPosMap.erase( aCodePageIt );
965     }
966 
967     // read dictionary property
968     SfxOlePropPosMap::iterator aDictIt = aPropPosMap.find( PROPID_DICTIONARY );
969     if( (aDictIt != aPropPosMap.end()) && SeekToPropertyPos( rStrm, aDictIt->second ) )
970     {
971         // #i66214# #i66428# applications may write broken dictionary properties in wrong sections
972         if( mbSupportsDict )
973         {
974             // dictionary property contains number of pairs in property type field
975             sal_Int32 nNameCount;
976             rStrm >> nNameCount;
977             maDictProp.SetNameCount( nNameCount );
978             LoadObject( rStrm, maDictProp );
979         }
980         // always remove position of dictionary property (do not try to read it again below)
981         aPropPosMap.erase( aDictIt );
982     }
983 
984     // read other properties
985     maPropMap.clear();
986     for( SfxOlePropPosMap::const_iterator aIt = aPropPosMap.begin(), aEnd = aPropPosMap.end(); aIt != aEnd; ++aIt )
987         if( SeekToPropertyPos( rStrm, aIt->second ) )
988             LoadProperty( rStrm, aIt->first );
989 }
990 
991 void SfxOleSection::ImplSave( SvStream& rStrm )
992 {
993     /*  Always export with UTF-8 encoding. All dependent properties (bytestring
994         and dictionary) will be updated automatically. */
995     maCodePageProp.SetTextEncoding( RTL_TEXTENCODING_UTF8 );
996 
997     // write section header
998     mnStartPos = rStrm.Tell();
999     sal_Int32 nPropCount = static_cast< sal_Int32 >( maPropMap.size() + 1 );
1000     if( maDictProp.HasPropertyNames() )
1001         ++nPropCount;
1002     rStrm << sal_uInt32( 0 ) << nPropCount;
1003 
1004     // write placeholders for property ID/position pairs
1005     sal_Size nPropPosPos = rStrm.Tell();
1006     rStrm.SeekRel( static_cast< sal_sSize >( 8 * nPropCount ) );
1007 
1008     // write dictionary property
1009     if( maDictProp.HasPropertyNames() )
1010         SaveProperty( rStrm, maDictProp, nPropPosPos );
1011     // write codepage property
1012     SaveProperty( rStrm, maCodePageProp, nPropPosPos );
1013     // write other properties
1014     for( SfxOlePropMap::const_iterator aIt = maPropMap.begin(), aEnd = maPropMap.end(); aIt != aEnd; ++aIt )
1015         SaveProperty( rStrm, *aIt->second, nPropPosPos );
1016 
1017     // write section size (first field in section header)
1018     rStrm.Seek( STREAM_SEEK_TO_END );
1019     sal_uInt32 nSectSize = static_cast< sal_uInt32 >( rStrm.Tell() - mnStartPos );
1020     rStrm.Seek( mnStartPos );
1021     rStrm << nSectSize;
1022 }
1023 
1024 bool SfxOleSection::SeekToPropertyPos( SvStream& rStrm, sal_uInt32 nPropPos ) const
1025 {
1026     rStrm.Seek( static_cast< sal_Size >( mnStartPos + nPropPos ) );
1027     return rStrm.GetErrorCode() == SVSTREAM_OK;
1028 }
1029 
1030 void SfxOleSection::LoadProperty( SvStream& rStrm, sal_Int32 nPropId )
1031 {
1032     // property data type
1033     sal_Int32 nPropType;
1034     rStrm >> nPropType;
1035     // create empty property object
1036     SfxOlePropertyRef xProp;
1037     switch( nPropType )
1038     {
1039         case PROPTYPE_INT32:
1040             xProp.reset( new SfxOleInt32Property( nPropId ) );
1041         break;
1042         case PROPTYPE_DOUBLE:
1043             xProp.reset( new SfxOleDoubleProperty( nPropId ) );
1044         break;
1045         case PROPTYPE_BOOL:
1046             xProp.reset( new SfxOleBoolProperty( nPropId ) );
1047         break;
1048         case PROPTYPE_STRING8:
1049             xProp.reset( new SfxOleString8Property( nPropId, maCodePageProp ) );
1050         break;
1051         case PROPTYPE_STRING16:
1052             xProp.reset( new SfxOleString16Property( nPropId ) );
1053         break;
1054         case PROPTYPE_FILETIME:
1055             xProp.reset( new SfxOleFileTimeProperty( nPropId ) );
1056         break;
1057     }
1058     // load property contents
1059     if( xProp.get() )
1060     {
1061         SetError( xProp->Load( rStrm ) );
1062         maPropMap[ nPropId ] = xProp;
1063     }
1064 }
1065 
1066 void SfxOleSection::SaveProperty( SvStream& rStrm, SfxOlePropertyBase& rProp, sal_Size& rnPropPosPos )
1067 {
1068     rStrm.Seek( STREAM_SEEK_TO_END );
1069     sal_uInt32 nPropPos = static_cast< sal_uInt32 >( rStrm.Tell() - mnStartPos );
1070     // property data type
1071     rStrm << rProp.GetPropType();
1072     // write property contents
1073     SaveObject( rStrm, rProp );
1074     // align to 32-bit
1075     while( (rStrm.Tell() & 3) != 0 )
1076         rStrm << sal_uInt8( 0 );
1077     // write property ID/position pair
1078     rStrm.Seek( rnPropPosPos );
1079     rStrm << rProp.GetPropId() << nPropPos;
1080     rnPropPosPos = rStrm.Tell();
1081 }
1082 
1083 // ----------------------------------------------------------------------------
1084 
1085 ErrCode SfxOlePropertySet::LoadPropertySet( SotStorage* pStrg, const String& rStrmName )
1086 {
1087     if( pStrg )
1088     {
1089         SotStorageStreamRef xStrm = pStrg->OpenSotStream( rStrmName, STREAM_STD_READ );
1090         if( xStrm.Is() && (xStrm->GetError() == SVSTREAM_OK) )
1091         {
1092             xStrm->SetBufferSize( STREAM_BUFFER_SIZE );
1093             Load( *xStrm );
1094         }
1095         else
1096             SetError( ERRCODE_IO_ACCESSDENIED );
1097     }
1098     else
1099         SetError( ERRCODE_IO_ACCESSDENIED );
1100     return GetError();
1101 }
1102 
1103 ErrCode SfxOlePropertySet::SavePropertySet( SotStorage* pStrg, const String& rStrmName )
1104 {
1105     if( pStrg )
1106     {
1107         SotStorageStreamRef xStrm = pStrg->OpenSotStream( rStrmName, STREAM_TRUNC | STREAM_STD_WRITE );
1108         if( xStrm.Is() )
1109             Save( *xStrm );
1110         else
1111             SetError( ERRCODE_IO_ACCESSDENIED );
1112     }
1113     else
1114         SetError( ERRCODE_IO_ACCESSDENIED );
1115     return GetError();
1116 }
1117 
1118 SfxOleSectionRef SfxOlePropertySet::GetSection( SfxOleSectionType eSection ) const
1119 {
1120     return GetSection( GetSectionGuid( eSection ) );
1121 }
1122 
1123 SfxOleSectionRef SfxOlePropertySet::GetSection( const SvGlobalName& rSectionGuid ) const
1124 {
1125     SfxOleSectionRef xSection;
1126     SfxOleSectionMap::const_iterator aIt = maSectionMap.find( rSectionGuid );
1127     if( aIt != maSectionMap.end() )
1128         xSection = aIt->second;
1129     return xSection;
1130 }
1131 
1132 SfxOleSection& SfxOlePropertySet::AddSection( SfxOleSectionType eSection )
1133 {
1134     return AddSection( GetSectionGuid( eSection ) );
1135 }
1136 
1137 SfxOleSection& SfxOlePropertySet::AddSection( const SvGlobalName& rSectionGuid )
1138 {
1139     SfxOleSectionRef xSection = GetSection( rSectionGuid );
1140     if( !xSection )
1141     {
1142         // #i66214# #i66428# applications may write broken dictionary properties in wrong sections
1143         bool bSupportsDict = rSectionGuid == GetSectionGuid( SECTION_CUSTOM );
1144         xSection.reset( new SfxOleSection( bSupportsDict ) );
1145         maSectionMap[ rSectionGuid ] = xSection;
1146     }
1147     return *xSection;
1148 }
1149 
1150 void SfxOlePropertySet::ImplLoad( SvStream& rStrm )
1151 {
1152     // read property set header
1153     sal_uInt16 nByteOrder;
1154     sal_uInt16 nVersion;
1155     sal_uInt16 nOsMinor;
1156     sal_uInt16 nOsType;
1157     SvGlobalName aGuid;
1158     sal_Int32 nSectCount;
1159     rStrm >> nByteOrder >> nVersion >> nOsMinor >> nOsType >> aGuid >> nSectCount;
1160 
1161     // read sections
1162     sal_Size nSectPosPos = rStrm.Tell();
1163     for( sal_Int32 nSectIdx = 0; (nSectIdx < nSectCount) && (rStrm.GetErrorCode() == SVSTREAM_OK) && !rStrm.IsEof(); ++nSectIdx )
1164     {
1165         // read section guid/position pair
1166         rStrm.Seek( nSectPosPos );
1167         SvGlobalName aSectGuid;
1168         sal_uInt32 nSectPos;
1169         rStrm >> aSectGuid >> nSectPos;
1170         nSectPosPos = rStrm.Tell();
1171         // read section
1172         rStrm.Seek( static_cast< sal_Size >( nSectPos ) );
1173         if( rStrm.GetErrorCode() == SVSTREAM_OK )
1174             LoadObject( rStrm, AddSection( aSectGuid ) );
1175     }
1176 }
1177 
1178 void SfxOlePropertySet::ImplSave( SvStream& rStrm )
1179 {
1180     // write property set header
1181     SvGlobalName aGuid;
1182     sal_Int32 nSectCount = static_cast< sal_Int32 >( maSectionMap.size() );
1183     rStrm   << sal_uInt16( 0xFFFE )     // byte order
1184             << sal_uInt16( 0 )          // version
1185             << sal_uInt16( 1 )          // OS minor version
1186             << sal_uInt16( 2 )          // OS type always windows for text encoding
1187             << aGuid                    // unused guid
1188             << nSectCount;              // number of sections
1189 
1190     // write placeholders for section guid/position pairs
1191     sal_Size nSectPosPos = rStrm.Tell();
1192     rStrm.SeekRel( static_cast< sal_sSize >( 20 * nSectCount ) );
1193 
1194     // write sections
1195     for( SfxOleSectionMap::const_iterator aIt = maSectionMap.begin(), aEnd = maSectionMap.end(); aIt != aEnd; ++aIt )
1196     {
1197         SfxOleSection& rSection = *aIt->second;
1198         rStrm.Seek( STREAM_SEEK_TO_END );
1199         sal_uInt32 nSectPos = static_cast< sal_uInt32 >( rStrm.Tell() );
1200         // write the section
1201         SaveObject( rStrm, rSection );
1202         // write section guid/position pair
1203         rStrm.Seek( nSectPosPos );
1204         rStrm << aIt->first << nSectPos;
1205         nSectPosPos = rStrm.Tell();
1206     }
1207 }
1208 
1209 const SvGlobalName& SfxOlePropertySet::GetSectionGuid( SfxOleSectionType eSection )
1210 {
1211     static const SvGlobalName saGlobalGuid(  0xF29F85E0, 0x4FF9, 0x1068, 0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9 );
1212     static const SvGlobalName saBuiltInGuid( 0xD5CDD502, 0x2E9C, 0x101B, 0x93, 0x97, 0x08, 0x00, 0x2B, 0x2C, 0xF9, 0xAE );
1213     static const SvGlobalName saCustomGuid(  0xD5CDD505, 0x2E9C, 0x101B, 0x93, 0x97, 0x08, 0x00, 0x2B, 0x2C, 0xF9, 0xAE );
1214     static const SvGlobalName saEmptyGuid;
1215     switch( eSection )
1216     {
1217         case SECTION_GLOBAL:    return saGlobalGuid;
1218         case SECTION_BUILTIN:   return saBuiltInGuid;
1219         case SECTION_CUSTOM:    return saCustomGuid;
1220         default:    DBG_ERRORFILE( "SfxOlePropertySet::GetSectionGuid - unknown section type" );
1221     }
1222     return saEmptyGuid;
1223 }
1224 
1225 // ============================================================================
1226 
1227 //} // namespace
1228