update dev300-m58
[ooovba.git] / sot / source / sdstor / stgelem.cxx
blob7ef25910f289a3b1211fc0f4c6ebe4a8087a1ab4
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: stgelem.cxx,v $
10 * $Revision: 1.12.6.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sot.hxx"
34 #include <string.h> // memset(), memcpy()
35 #include <rtl/ustring.hxx>
36 #include <com/sun/star/lang/Locale.hpp>
37 #include <unotools/charclass.hxx>
38 #include "stg.hxx"
39 #include "stgelem.hxx"
40 #include "stgcache.hxx"
41 #include "stgstrms.hxx"
42 #include "stgdir.hxx"
43 #include "stgio.hxx"
45 static BYTE cStgSignature[ 8 ] = { 0xD0,0xCF,0x11,0xE0,0xA1,0xB1,0x1A,0xE1 };
47 ////////////////////////////// struct ClsId /////////////////////////////
49 SvStream& operator >>( SvStream& r, ClsId& rId )
51 r >> rId.n1
52 >> rId.n2
53 >> rId.n3
54 >> rId.n4
55 >> rId.n5
56 >> rId.n6
57 >> rId.n7
58 >> rId.n8
59 >> rId.n9
60 >> rId.n10
61 >> rId.n11;
62 return r;
65 SvStream& operator <<( SvStream& r, const ClsId& rId )
67 return
68 r << (INT32) rId.n1
69 << (INT16) rId.n2
70 << (INT16) rId.n3
71 << (UINT8) rId.n4
72 << (UINT8) rId.n5
73 << (UINT8) rId.n6
74 << (UINT8) rId.n7
75 << (UINT8) rId.n8
76 << (UINT8) rId.n9
77 << (UINT8) rId.n10
78 << (UINT8) rId.n11;
81 ///////////////////////////// class StgHeader ////////////////////////////
83 StgHeader::StgHeader()
85 memset( this, 0, sizeof( StgHeader ) );
88 void StgHeader::Init()
90 memset( this, 0, sizeof( StgHeader ) );
91 memcpy( cSignature, cStgSignature, 8 );
92 nVersion = 0x0003003B;
93 nByteOrder = 0xFFFE;
94 nPageSize = 9; // 512 bytes
95 nDataPageSize = 6; // 64 bytes
96 nThreshold = 4096;
97 nDataFATSize = 0;
98 nMasterChain = STG_EOF;
99 SetTOCStart( STG_EOF );
100 SetDataFATStart( STG_EOF );
101 for( short i = 0; i < 109; i++ )
102 SetFATPage( i, STG_FREE );
105 BOOL StgHeader::Load( StgIo& rIo )
107 SvStream& r = *rIo.GetStrm();
108 Load( r );
109 return rIo.Good();
112 BOOL StgHeader::Load( SvStream& r )
114 r.Seek( 0L );
115 r.Read( cSignature, 8 );
116 r >> aClsId // 08 Class ID
117 >> nVersion // 1A version number
118 >> nByteOrder // 1C Unicode byte order indicator
119 >> nPageSize // 1E 1 << nPageSize = block size
120 >> nDataPageSize; // 20 1 << this size == data block size
121 r.SeekRel( 10 );
122 r >> nFATSize // 2C total number of FAT pages
123 >> nTOCstrm // 30 starting page for the TOC stream
124 >> nReserved // 34
125 >> nThreshold // 38 minimum file size for big data
126 >> nDataFAT // 3C page # of 1st data FAT block
127 >> nDataFATSize // 40 # of data FATpages
128 >> nMasterChain // 44 chain to the next master block
129 >> nMaster; // 48 # of additional master blocks
130 for( short i = 0; i < 109; i++ )
131 r >> nMasterFAT[ i ];
132 return r.GetErrorCode() == ERRCODE_NONE;
135 BOOL StgHeader::Store( StgIo& rIo )
137 if( !bDirty )
138 return TRUE;
139 SvStream& r = *rIo.GetStrm();
140 r.Seek( 0L );
141 r.Write( cSignature, 8 + 16 );
142 r << nVersion // 1A version number
143 << nByteOrder // 1C Unicode byte order indicator
144 << nPageSize // 1E 1 << nPageSize = block size
145 << nDataPageSize // 20 1 << this size == data block size
146 << (INT32) 0 << (INT32) 0 << (INT16) 0
147 << nFATSize // 2C total number of FAT pages
148 << nTOCstrm // 30 starting page for the TOC stream
149 << nReserved // 34
150 << nThreshold // 38 minimum file size for big data
151 << nDataFAT // 3C page # of 1st data FAT block
152 << nDataFATSize // 40 # of data FAT pages
153 << nMasterChain // 44 chain to the next master block
154 << nMaster; // 48 # of additional master blocks
155 for( short i = 0; i < 109; i++ )
156 r << nMasterFAT[ i ];
157 bDirty = !rIo.Good();
158 return BOOL( !bDirty );
161 static bool lcl_wontoverflow(short shift)
163 return shift >= 0 && shift < (short)sizeof(short) * 8 - 1;
166 // Perform thorough checks also on unknown variables
167 BOOL StgHeader::Check()
169 return BOOL( memcmp( cSignature, cStgSignature, 8 ) == 0
170 && (short) ( nVersion >> 16 ) == 3 )
171 && lcl_wontoverflow(nPageSize)
172 && lcl_wontoverflow(nDataPageSize);
175 INT32 StgHeader::GetFATPage( short n ) const
177 if( n >= 0 && n < 109 )
178 return nMasterFAT[ n ];
179 else
180 return STG_EOF;
183 void StgHeader::SetFATPage( short n, INT32 nb )
185 if( n >= 0 && n < 109 )
187 if( nMasterFAT[ n ] != nb )
188 bDirty = TRUE, nMasterFAT[ n ] = nb;
192 void StgHeader::SetClassId( const ClsId& r )
194 if( memcmp( &aClsId, &r, sizeof( ClsId ) ) )
195 bDirty = TRUE, memcpy( &aClsId, &r, sizeof( ClsId ) );
198 void StgHeader::SetTOCStart( INT32 n )
200 if( n != nTOCstrm ) bDirty = TRUE, nTOCstrm = n;
203 void StgHeader::SetDataFATStart( INT32 n )
205 if( n != nDataFAT ) bDirty = TRUE, nDataFAT = n;
208 void StgHeader::SetDataFATSize( INT32 n )
210 if( n != nDataFATSize ) bDirty = TRUE, nDataFATSize = n;
213 void StgHeader::SetFATSize( INT32 n )
215 if( n != nFATSize ) bDirty = TRUE, nFATSize = n;
218 void StgHeader::SetFATChain( INT32 n )
220 if( n != nMasterChain )
221 bDirty = TRUE, nMasterChain = n;
224 void StgHeader::SetMasters( INT32 n )
226 if( n != nMaster ) bDirty = TRUE, nMaster = n;
229 ///////////////////////////// class StgEntry /////////////////////////////
231 // This class is only a wrapper around teh dir entry structure
232 // which retrieves and sets data.
234 // The name must be smaller than 32 chars. Conversion into Unicode
235 // is easy, since the 1st 256 characters of the Windows ANSI set
236 // equal the 1st 256 Unicode characters.
238 void ToUnicode_Impl( String& rName )
240 rName.Erase( 32 );
241 rName.Convert( ::GetSystemCharSet(), CHARSET_ANSI );
242 // brute force is OK
243 BYTE* p = (BYTE*) rName.GetCharStr();
244 for( USHORT i = 0; i < rName.Len(); i++, p++ )
246 // check each character and substitute blanks for illegal ones
247 BYTE cChar = *p;
248 if( cChar == '!' || cChar == ':' || cChar == '\\' || cChar == '/' )
249 *p = ' ';
254 static void FromUnicode( String& rName )
256 rName.Convert( CHARSET_ANSI, ::GetSystemCharSet() );
259 BOOL StgEntry::Init()
261 memset( this, 0, sizeof (StgEntry) - sizeof( String ) );
262 SetLeaf( STG_LEFT, STG_FREE );
263 SetLeaf( STG_RIGHT, STG_FREE );
264 SetLeaf( STG_CHILD, STG_FREE );
265 SetLeaf( STG_DATA, STG_EOF );
266 return TRUE;
269 static String ToUpperUnicode( const String & rStr )
271 // I don't know the locale, so en_US is hopefully fine
273 com.sun.star.lang.Locale aLocale;
274 aLocale.Language = OUString::createFromAscii( "en" );
275 aLocale.Country = OUString::createFromAscii( "US" );
277 static rtl::OUString aEN=rtl::OUString::createFromAscii( "en" );
278 static rtl::OUString aUS=rtl::OUString::createFromAscii( "US" );
279 static CharClass aCC( com::sun::star::lang::Locale( aEN, aUS, rtl::OUString() ) );
280 return aCC.toUpper( rStr, 0, rStr.Len() );
284 BOOL StgEntry::SetName( const String& rName )
286 // I don't know the locale, so en_US is hopefully fine
287 aName = ToUpperUnicode( rName );
288 aName.Erase( 31 );
290 int i;
291 for( i = 0; i < aName.Len() && i < 32; i++ )
292 nName[ i ] = rName.GetChar( sal_uInt16( i ));
293 while( i < 32 )
294 nName[ i++ ] = 0;
295 nNameLen = ( aName.Len() + 1 ) << 1;
296 return TRUE;
299 INT32 StgEntry::GetLeaf( StgEntryRef eRef ) const
301 INT32 n = -1;
302 switch( eRef )
304 case STG_LEFT: n = nLeft; break;
305 case STG_RIGHT: n = nRight; break;
306 case STG_CHILD: n = nChild; break;
307 case STG_DATA: n = nPage1; break;
309 return n;
312 void StgEntry::SetLeaf( StgEntryRef eRef, INT32 nPage )
314 switch( eRef )
316 case STG_LEFT: nLeft = nPage; break;
317 case STG_RIGHT: nRight = nPage; break;
318 case STG_CHILD: nChild = nPage; break;
319 case STG_DATA: nPage1 = nPage; break;
323 const INT32* StgEntry::GetTime( StgEntryTime eTime ) const
325 return( eTime == STG_MODIFIED ) ? nMtime : nAtime;
328 void StgEntry::SetTime( StgEntryTime eTime, INT32* pTime )
330 if( eTime == STG_MODIFIED )
331 nMtime[ 0 ] = *pTime++, nMtime[ 1 ] = *pTime;
332 else
333 nAtime[ 0 ] = *pTime++, nAtime[ 1 ] = *pTime;
336 void StgEntry::SetClassId( const ClsId& r )
338 memcpy( &aClsId, &r, sizeof( ClsId ) );
341 void StgEntry::GetName( String& rName ) const
343 UINT16 n = nNameLen;
344 if( n )
345 n = ( n >> 1 ) - 1;
346 rName = String( nName, n );
349 // Compare two entries. Do this case-insensitive.
351 short StgEntry::Compare( const StgEntry& r ) const
354 short nRes = r.nNameLen - nNameLen;
355 if( !nRes ) return strcmp( r.aName, aName );
356 else return nRes;
358 sal_Int32 nRes = r.nNameLen - nNameLen;
359 if( !nRes )
360 nRes = r.aName.CompareTo( aName );
361 return (short)nRes;
362 //return aName.CompareTo( r.aName );
365 // These load/store operations are a bit more complicated,
366 // since they have to copy their contents into a packed structure.
368 BOOL StgEntry::Load( const void* pFrom )
370 SvMemoryStream r( (sal_Char*) pFrom, 128, STREAM_READ );
371 for( short i = 0; i < 32; i++ )
372 r >> nName[ i ]; // 00 name as WCHAR
373 r >> nNameLen // 40 size of name in bytes including 00H
374 >> cType // 42 entry type
375 >> cFlags // 43 0 or 1 (tree balance?)
376 >> nLeft // 44 left node entry
377 >> nRight // 48 right node entry
378 >> nChild // 4C 1st child entry if storage
379 >> aClsId // 50 class ID (optional)
380 >> nFlags // 60 state flags(?)
381 >> nMtime[ 0 ] // 64 modification time
382 >> nMtime[ 1 ] // 64 modification time
383 >> nAtime[ 0 ] // 6C creation and access time
384 >> nAtime[ 1 ] // 6C creation and access time
385 >> nPage1 // 74 starting block (either direct or translated)
386 >> nSize // 78 file size
387 >> nUnknown; // 7C unknown
389 UINT16 n = nNameLen;
390 if( n )
391 n = ( n >> 1 ) - 1;
392 if( n > 31 || (nSize < 0 && cType != STG_STORAGE) )
394 // the size makes no sence for the substorage
395 // TODO/LATER: actually the size should be an unsigned value, but in this case it would mean a stream of more than 2Gb
396 return FALSE;
399 aName = String( nName, n );
400 // I don't know the locale, so en_US is hopefully fine
401 aName = ToUpperUnicode( aName );
402 aName.Erase( 31 );
404 return TRUE;
407 void StgEntry::Store( void* pTo )
409 SvMemoryStream r( (sal_Char *)pTo, 128, STREAM_WRITE );
410 for( short i = 0; i < 32; i++ )
411 r << nName[ i ]; // 00 name as WCHAR
412 r << nNameLen // 40 size of name in bytes including 00H
413 << cType // 42 entry type
414 << cFlags // 43 0 or 1 (tree balance?)
415 << nLeft // 44 left node entry
416 << nRight // 48 right node entry
417 << nChild // 4C 1st child entry if storage;
418 << aClsId // 50 class ID (optional)
419 << nFlags // 60 state flags(?)
420 << nMtime[ 0 ] // 64 modification time
421 << nMtime[ 1 ] // 64 modification time
422 << nAtime[ 0 ] // 6C creation and access time
423 << nAtime[ 1 ] // 6C creation and access time
424 << nPage1 // 74 starting block (either direct or translated)
425 << nSize // 78 file size
426 << nUnknown; // 7C unknown