1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ooofilt.cxx,v $
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_shell.hxx"
34 //--------------------------------------------------------------------------
37 // Contents: Filter Implementation for OpenOffice.Org Document using
40 // Summary: The OpenOffice.org filter reads OpenOffice.org files (with the
41 // extension .sxw .sxi, etc) and extract their content, author,
42 // keywords,subject,comments and title to be filtered.
44 // Platform: Windows 2000, Windows XP
46 //--------------------------------------------------------------------------
47 #include "internal/contentreader.hxx"
48 #include "internal/metainforeader.hxx"
49 //#include "internal/utilities.hxx"
50 #include "internal/registry.hxx"
51 #include "internal/fileextensions.hxx"
53 //--------------------------------------------------------------------------
55 // Include file Purpose
57 // windows.h Win32 declarations
58 // string.h string wstring declarations
59 // filter.h IFilter interface declarations
60 // filterr.h FACILITY_ITF error definitions for IFilter
61 // ntquery.h Indexing Service declarations
62 // assert.h assertion function.
63 // ooofilt.hxx OpenOffice.org filter declarations
64 // propspec.hxx PROPSPEC
66 //--------------------------------------------------------------------------
69 #pragma warning(push, 1)
80 #include "ooofilt.hxx"
83 #include "propspec.hxx"
90 //C-------------------------------------------------------------------------
94 // Summary: Implements OpenOffice.org filter class
96 //--------------------------------------------------------------------------
97 //M-------------------------------------------------------------------------
99 // Method: COooFilter::COooFilter
101 // Summary: Class constructor
105 // Purpose: Manages global instance count
107 //--------------------------------------------------------------------------
108 COooFilter::COooFilter() :
110 m_pContentReader(NULL
),
111 m_pMetaInfoReader(NULL
),
112 m_eState(FilteringContent
),
113 m_ulUnicodeBufferLen(0),
114 m_ulUnicodeCharsRead(0),
116 m_ulCurrentPropertyNum(0),
126 InterlockedIncrement( &g_lInstances
);
128 //M-------------------------------------------------------------------------
130 // Method: COooFilter::~COooFilter
132 // Summary: Class destructor
136 // Purpose: Manages global instance count and file handle
138 //--------------------------------------------------------------------------
139 COooFilter::~COooFilter()
141 delete [] m_pAttributes
;
143 if (m_pContentReader
)
144 delete m_pContentReader
;
145 if (m_pMetaInfoReader
)
146 delete m_pMetaInfoReader
;
148 InterlockedDecrement( &g_lInstances
);
151 //M-------------------------------------------------------------------------
153 // Method: COooFilter::QueryInterface (IUnknown::QueryInterface)
155 // Summary: Queries for requested interface
158 // [in] Reference IID of requested interface
160 // [out] Address that receives requested interface pointer
163 // Interface is supported
165 // Interface is not supported
167 //--------------------------------------------------------------------------
168 SCODE STDMETHODCALLTYPE
COooFilter::QueryInterface(
172 IUnknown
*pUnkTemp
= 0;
173 if ( IID_IFilter
== riid
)
174 pUnkTemp
= (IUnknown
*)(IFilter
*)this;
175 else if ( IID_IPersistFile
== riid
)
176 pUnkTemp
= (IUnknown
*)(IPersistFile
*)this;
177 else if ( IID_IPersist
== riid
)
178 pUnkTemp
= (IUnknown
*)(IPersist
*)(IPersistFile
*)this;
179 else if (IID_IPersistStream
== riid
)
180 pUnkTemp
= (IUnknown
*)(IPersistStream
*)this;
181 else if ( IID_IUnknown
== riid
)
182 pUnkTemp
= (IUnknown
*)(IPersist
*)(IPersistFile
*)this;
186 return E_NOINTERFACE
;
188 *ppvObject
= (void *)pUnkTemp
;
192 //M-------------------------------------------------------------------------
194 // Method: COooFilter::AddRef (IUnknown::AddRef)
196 // Summary: Increments interface refcount
200 // Returns: Value of incremented interface refcount
202 //--------------------------------------------------------------------------
203 ULONG STDMETHODCALLTYPE
COooFilter::AddRef()
205 return InterlockedIncrement( &m_lRefs
);
207 //M-------------------------------------------------------------------------
209 // Method: COooFilter::Release (IUnknown::Release)
211 // Summary: Decrements interface refcount, deleting if unreferenced
215 // Returns: Value of decremented interface refcount
217 //--------------------------------------------------------------------------
218 ULONG STDMETHODCALLTYPE
COooFilter::Release()
220 ULONG ulTmp
= InterlockedDecrement( &m_lRefs
);
226 //M-------------------------------------------------------------------------
228 // Method: COooFilter::Init (IFilter::Init)
230 // Summary: Initializes OpenOffice.org filter instance
232 // Arguments: grfFlags
233 // [in] Flags for filter behavior
235 // [in] Number attributes in array aAttributes
237 // [in] Array of requested attribute strings
239 // [out] Pointer to return flags for additional properties
242 // Initialization succeeded
244 // File not previously loaded
246 // Count and contents of attributes do not agree
248 // Unable to access file to be filtered
252 //--------------------------------------------------------------------------
253 const int COUNT_ATTRIBUTES
= 5;
255 SCODE STDMETHODCALLTYPE
COooFilter::Init(
258 FULLPROPSPEC
const * aAttributes
,
261 // Enumerate OLE properties, since any NTFS file can have them
262 *pFlags
= IFILTER_FLAGS_OLE_PROPERTIES
;
267 m_ulCurrentPropertyNum
= 0;
268 if ( m_cAttributes
> 0 )
270 delete[] m_pAttributes
;
274 if( 0 < cAttributes
)
276 // Filter properties specified in aAttributes
277 if ( 0 == aAttributes
)
279 m_pAttributes
= new CFullPropSpec
[cAttributes
];
280 m_cAttributes
= cAttributes
;
281 // Is caller want to filter contents?
282 CFullPropSpec
*pAttrib
= (CFullPropSpec
*) aAttributes
;
284 for ( ulNumAttr
= 0 ; ulNumAttr
< cAttributes
; ulNumAttr
++ )
286 if ( pAttrib
[ulNumAttr
].IsPropertyPropid() &&
287 pAttrib
[ulNumAttr
].GetPropertyPropid() == PID_STG_CONTENTS
&&
288 pAttrib
[ulNumAttr
].GetPropSet() == guidStorage
)
292 // save the requested properties.
293 m_pAttributes
[ulNumAttr
] = pAttrib
[ulNumAttr
];
296 else if ( grfFlags
& IFILTER_INIT_APPLY_INDEX_ATTRIBUTES
)
298 // Filter contents and all pseudo-properties
301 m_pAttributes
= new CFullPropSpec
[COUNT_ATTRIBUTES
];
302 m_cAttributes
= COUNT_ATTRIBUTES
;
303 m_pAttributes
[0].SetPropSet( FMTID_SummaryInformation
);
304 m_pAttributes
[0].SetProperty( PIDSI_AUTHOR
);
305 m_pAttributes
[1].SetPropSet( FMTID_SummaryInformation
);
306 m_pAttributes
[1].SetProperty( PIDSI_TITLE
);
307 m_pAttributes
[2].SetPropSet( FMTID_SummaryInformation
);
308 m_pAttributes
[2].SetProperty( PIDSI_SUBJECT
);
309 m_pAttributes
[3].SetPropSet( FMTID_SummaryInformation
);
310 m_pAttributes
[3].SetProperty( PIDSI_KEYWORDS
);
311 m_pAttributes
[4].SetPropSet( FMTID_SummaryInformation
);
312 m_pAttributes
[4].SetProperty( PIDSI_COMMENTS
);
314 else if ( 0 == grfFlags
)
316 // Filter only contents
325 m_eState
= FilteringContent
;
326 m_ulUnicodeCharsRead
= 0;
332 m_eState
= FilteringProperty
;
336 catch (const std::exception
&)
343 //M-------------------------------------------------------------------------
345 // Method: COooFilter::GetChunk (IFilter::GetChunk)
347 // Summary: Gets the next chunk
350 // [out] Pointer to description of current chunk
352 // Chunk was successfully retrieved
354 // Character conversion failed
356 // General access failure occurred
357 // FILTER_E_END_OF_CHUNKS
358 // Previous chunk was the last chunk
359 // FILTER_E_EMBEDDING_UNAVAILABLE
361 // FILTER_E_LINK_UNAVAILABLE
366 //--------------------------------------------------------------------------
367 SCODE STDMETHODCALLTYPE
COooFilter::GetChunk(STAT_CHUNK
* pStat
)
373 case FilteringContent
:
375 // Read Unicodes from buffer.
376 if( m_ChunkPosition
== m_pContentReader
->getChunkBuffer().size() )
378 m_ulUnicodeBufferLen
=0;
382 if ( !m_fContents
|| m_fEof
)
384 m_eState
= FilteringProperty
;
387 m_pwsBuffer
= m_pContentReader
-> getChunkBuffer()[m_ChunkPosition
].second
;
388 m_ulUnicodeBufferLen
= m_pwsBuffer
.length();
389 DWORD ChunkLCID
= LocaleSetToLCID( m_pContentReader
-> getChunkBuffer()[m_ChunkPosition
].first
);
390 // Set chunk description
391 pStat
->idChunk
= m_ulChunkID
;
392 pStat
->breakType
= CHUNK_NO_BREAK
;
393 pStat
->flags
= CHUNK_TEXT
;
394 pStat
->locale
= ChunkLCID
;
395 pStat
->attribute
.guidPropSet
= guidStorage
;
396 pStat
->attribute
.psProperty
.ulKind
= PRSPEC_PROPID
;
397 pStat
->attribute
.psProperty
.propid
= PID_STG_CONTENTS
;
398 pStat
->idChunkSource
= m_ulChunkID
;
399 pStat
->cwcStartSource
= 0;
400 pStat
->cwcLenSource
= 0;
401 m_ulUnicodeCharsRead
= 0;
406 case FilteringProperty
:
408 if ( m_cAttributes
== 0 )
409 return FILTER_E_END_OF_CHUNKS
;
410 while( !( ( m_pAttributes
[m_ulPropertyNum
].IsPropertyPropid() ) &&
411 ( m_pAttributes
[m_ulPropertyNum
].GetPropSet() == FMTID_SummaryInformation
) )||
412 ( ( m_pAttributes
[m_ulPropertyNum
].GetPropertyPropid() != PIDSI_AUTHOR
) &&
413 ( m_pAttributes
[m_ulPropertyNum
].GetPropertyPropid() != PIDSI_TITLE
) &&
414 ( m_pAttributes
[m_ulPropertyNum
].GetPropertyPropid() != PIDSI_SUBJECT
) &&
415 ( m_pAttributes
[m_ulPropertyNum
].GetPropertyPropid() != PIDSI_KEYWORDS
) &&
416 ( m_pAttributes
[m_ulPropertyNum
].GetPropertyPropid() != PIDSI_COMMENTS
) ) )
418 if ( m_ulPropertyNum
< m_cAttributes
)
423 if ( m_ulPropertyNum
== m_cAttributes
)
424 return FILTER_E_END_OF_CHUNKS
;
427 // Set chunk description
428 pStat
->idChunk
= m_ulChunkID
;
429 pStat
->breakType
= CHUNK_EOS
;
430 pStat
->flags
= CHUNK_VALUE
;
431 pStat
->locale
= GetSystemDefaultLCID();
432 pStat
->attribute
.guidPropSet
= FMTID_SummaryInformation
;
433 pStat
->attribute
.psProperty
.ulKind
= PRSPEC_PROPID
;
434 pStat
->attribute
.psProperty
.propid
= m_pAttributes
[m_ulPropertyNum
].GetPropertyPropid();
435 pStat
->idChunkSource
= m_ulChunkID
;
436 pStat
->cwcStartSource
= 0;
437 pStat
->cwcLenSource
= 0;
438 m_ulCurrentPropertyNum
= m_ulPropertyNum
;
449 //M-------------------------------------------------------------------------
451 // Method: COooFilter::GetText (IFilter::GetText)
453 // Summary: Retrieves UNICODE text for index
455 // Arguments: pcwcBuffer
456 // [in] Pointer to size of UNICODE buffer
457 // [out] Pointer to count of UNICODE characters returned
459 // [out] Pointer to buffer to receive UNICODE text
462 // Text successfully retrieved, but text remains in chunk
463 // FILTER_E_NO_MORE_TEXT
464 // All of the text in the current chunk has been returned
465 // FILTER_S_LAST_TEXT
466 // Next call to GetText will return FILTER_E_NO_MORE_TEXT
468 //--------------------------------------------------------------------------
469 SCODE STDMETHODCALLTYPE
COooFilter::GetText(ULONG
* pcwcBuffer
, WCHAR
* awcBuffer
)
473 case FilteringProperty
:
474 return FILTER_E_NO_TEXT
;
475 case FilteringContent
:
477 if ( !m_fContents
|| 0 == m_ulUnicodeBufferLen
)
480 return FILTER_E_NO_MORE_TEXT
;
482 // Copy UNICODE characters in chunk buffer to output UNICODE buffer
483 ULONG ulToCopy
= min( *pcwcBuffer
, m_ulUnicodeBufferLen
- m_ulUnicodeCharsRead
);
484 ZeroMemory(awcBuffer
, sizeof(awcBuffer
));
485 wmemcpy( awcBuffer
, m_pwsBuffer
.c_str() + m_ulUnicodeCharsRead
, ulToCopy
);
486 m_ulUnicodeCharsRead
+= ulToCopy
;
487 *pcwcBuffer
= ulToCopy
;
488 if ( m_ulUnicodeBufferLen
== m_ulUnicodeCharsRead
)
490 m_ulUnicodeCharsRead
= 0;
491 m_ulUnicodeBufferLen
= 0;
492 return FILTER_S_LAST_TEXT
;
500 //M-------------------------------------------------------------------------
502 // Method: GetMetaInfoNameFromPropertyId
504 // Summary: helper function to convert PropertyID into respective
507 // Arguments: ulPropID
510 // Returns: corresponding metainfo names.
512 //--------------------------------------------------------------------------
514 ::std::wstring
GetMetaInfoNameFromPropertyId( ULONG ulPropID
)
518 case PIDSI_AUTHOR
: return META_INFO_AUTHOR
;
519 case PIDSI_TITLE
: return META_INFO_TITLE
;
520 case PIDSI_SUBJECT
: return META_INFO_SUBJECT
;
521 case PIDSI_KEYWORDS
: return META_INFO_KEYWORDS
;
522 case PIDSI_COMMENTS
: return META_INFO_DESCRIPTION
;
523 default: return EMPTY_STRING
;
526 //M-------------------------------------------------------------------------
528 // Method: COooFilter::GetValue (IFilter::GetValue)
530 // Summary: Retrieves properites for index
532 // Arguments: ppPropValue
533 // [out] Address that receives pointer to property value
535 // Returns: FILTER_E_NO_VALUES
537 // FILTER_E_NO_MORE_VALUES
540 //--------------------------------------------------------------------------
542 SCODE STDMETHODCALLTYPE
COooFilter::GetValue(PROPVARIANT
** ppPropValue
)
544 if (m_eState
== FilteringContent
)
545 return FILTER_E_NO_VALUES
;
546 else if (m_eState
== FilteringProperty
)
548 if ( m_cAttributes
== 0 || ( m_ulCurrentPropertyNum
== m_ulPropertyNum
) )
549 return FILTER_E_NO_MORE_VALUES
;
550 PROPVARIANT
*pPropVar
= (PROPVARIANT
*) CoTaskMemAlloc( sizeof (PROPVARIANT
) );
552 return E_OUTOFMEMORY
;
553 ::std::wstring wsTagName
= GetMetaInfoNameFromPropertyId( m_pAttributes
[m_ulCurrentPropertyNum
].GetPropertyPropid() );
554 if ( wsTagName
== EMPTY_STRING
)
555 return FILTER_E_NO_VALUES
;
556 ::std::wstring wsTagData
= m_pMetaInfoReader
->getTagData(wsTagName
);
557 pPropVar
->vt
= VT_LPWSTR
;
558 size_t cw
= wsTagData
.length() + 1; // reserve one for the '\0'
559 pPropVar
->pwszVal
= static_cast<WCHAR
*>( CoTaskMemAlloc(cw
*sizeof(WCHAR
)) );
560 if (pPropVar
->pwszVal
== 0)
562 CoTaskMemFree(pPropVar
);
563 return E_OUTOFMEMORY
;
565 wmemcpy(pPropVar
->pwszVal
, wsTagData
.c_str(), cw
);
566 *ppPropValue
= pPropVar
;
567 m_ulCurrentPropertyNum
= m_ulPropertyNum
;
573 //M-------------------------------------------------------------------------
575 // Method: COooFilter::BindRegion (IFilter::BindRegion)
577 // Summary: Creates moniker or other interface for indicated text
579 // Arguments: origPos
580 // [in] Description of text location and extent
582 // [in] Reference IID of specified interface
584 // [out] Address that receives requested interface pointer
586 // Returns: E_NOTIMPL
588 // FILTER_W_REGION_CLIPPED
591 //--------------------------------------------------------------------------
593 SCODE STDMETHODCALLTYPE
COooFilter::BindRegion(
594 FILTERREGION
/*origPos*/,
598 // BindRegion is currently reserved for future use
601 //M-------------------------------------------------------------------------
603 // Method: COooFilter::GetClassID (IPersist::GetClassID)
605 // Summary: Retrieves the class id of the filter class
607 // Arguments: pClassID
608 // [out] Pointer to the class ID of the filter
614 //--------------------------------------------------------------------------
615 SCODE STDMETHODCALLTYPE
COooFilter::GetClassID(CLSID
* pClassID
)
617 *pClassID
= CLSID_COooFilter
;
620 //M-------------------------------------------------------------------------
622 // Method: COooFilter::IsDirty (IPersistFile::IsDirty)
624 // Summary: Checks whether file has changed since last save
633 //--------------------------------------------------------------------------
634 SCODE STDMETHODCALLTYPE
COooFilter::IsDirty()
636 // File is opened read-only and never changes
639 //M-------------------------------------------------------------------------
641 // Method: COooFilter::Load (IPersistFile::Load)
643 // Summary: Opens and initializes the specified file
645 // Arguments: pszFileName
646 // [in] Pointer to zero-terminated string
647 // of absolute path of file to open
649 // [in] Access mode to open the file
652 // File was successfully loaded
654 // File could not be loaded due to insufficient memory
658 //--------------------------------------------------------------------------
659 SCODE STDMETHODCALLTYPE
COooFilter::Load(LPCWSTR pszFileName
, DWORD
/*dwMode*/)
661 // Load just sets the filename for GetChunk to read and ignores the mode
662 m_pwszFileName
= pszFileName
;
663 // Open the file previously specified in call to IPersistFile::Load and get content.
666 if (m_pMetaInfoReader
)
667 delete m_pMetaInfoReader
;
668 m_pMetaInfoReader
= new CMetaInfoReader(WStringToString(m_pwszFileName
));
670 if (m_pContentReader
)
671 delete m_pContentReader
;
672 m_pContentReader
= new CContentReader(WStringToString(m_pwszFileName
), m_pMetaInfoReader
->getDefaultLocale());
674 catch (const std::exception
&)
680 //M-------------------------------------------------------------------------
682 // Method: COooFilter::Save (IPersistFile::Save)
684 // Summary: Saves a copy of the current file being filtered
686 // Arguments: pszFileName
687 // [in] Pointer to zero-terminated string of
688 // absolute path of where to save file
690 // [in] Whether the saved copy is made the current file
697 //--------------------------------------------------------------------------
698 SCODE STDMETHODCALLTYPE
COooFilter::Save(LPCWSTR
/*pszFileName*/, BOOL
/*fRemember*/)
700 // File is opened read-only; saving it is an error
703 //M-------------------------------------------------------------------------
705 // Method: COooFilter::SaveCompleted (IPersistFile::SaveCompleted)
707 // Summary: Determines whether a file save is completed
709 // Arguments: pszFileName
710 // [in] Pointer to zero-terminated string of
711 // absolute path where file was previously saved
716 //--------------------------------------------------------------------------
717 SCODE STDMETHODCALLTYPE
COooFilter::SaveCompleted(LPCWSTR
/*pszFileName*/)
719 // File is opened read-only, so "save" is always finished
723 //M-------------------------------------------------------------------------
725 // Method: COooFilter::Load (IPersistStream::Load)
727 // Summary: Initializes an object from the stream where it was previously saved
730 // [in] Pointer to stream from which object should be loaded
738 //--------------------------------------------------------------------------
739 SCODE STDMETHODCALLTYPE
COooFilter::Load(IStream
*pStm
)
742 // These next few lines work around the "Seek pointer" bug found on Vista.
747 ULARGE_INTEGER NewPosition
;
750 hr
= pStm
->Seek (Move
, STREAM_SEEK_SET
, &NewPosition
);
751 hr
= pStm
->Read (buf
, 20, &count
);
753 zlib_filefunc_def z_filefunc
;
754 fill_stream_filefunc (&z_filefunc
);
755 z_filefunc
.opaque
= (void*)pStm
;
761 if (m_pMetaInfoReader
)
762 delete m_pMetaInfoReader
;
763 m_pMetaInfoReader
= new CMetaInfoReader((void*)m_pStream
, &z_filefunc
);
765 if (m_pContentReader
)
766 delete m_pContentReader
;
767 m_pContentReader
= new CContentReader((void*)m_pStream
, m_pMetaInfoReader
->getDefaultLocale(), &z_filefunc
);
769 catch (const std::exception
&)
776 //M-------------------------------------------------------------------------
778 // Method: COooFilter::GetSizeMax (IPersistStream::GetSizeMax)
780 // Summary: Returns the size in bytes of the stream neede to save the object.
782 // Arguments: pcbSize
783 // [out] Pointer to a 64 bit unsigned int indicating the size needed
785 // Returns: E_NOTIMPL
788 //--------------------------------------------------------------------------
789 SCODE STDMETHODCALLTYPE
COooFilter::GetSizeMax(ULARGE_INTEGER
* /*pcbSize*/)
795 //M-------------------------------------------------------------------------
797 // Method: COooFilter::Save (IPersistStream::Save)
799 // Summary: Save object to specified stream
802 // [in] Pointer to stream
805 // [in] Indicates whether to clear dirty flag
807 // Returns: E_NOTIMPL
810 //--------------------------------------------------------------------------
811 SCODE STDMETHODCALLTYPE
COooFilter::Save(IStream
* /*pStm*/, BOOL
)
817 //M-------------------------------------------------------------------------
819 // Method: COooFilter::GetCurFile (IPersistFile::GetCurFile)
821 // Summary: Returns a copy of the current file name
823 // Arguments: ppszFileName
824 // [out] Address to receive pointer to zero-terminated
825 // string for absolute path to current file
828 // A valid absolute path was successfully returned
832 // Operation failed due to insufficient memory
834 // Operation failed due to some reason
835 // other than insufficient memory
837 //-------------------------------------------------------------------------
838 SCODE STDMETHODCALLTYPE
COooFilter::GetCurFile(LPWSTR
* ppszFileName
)
840 if ( EMPTY_STRING
== m_pwszFileName
)
843 *ppszFileName
= (LPWSTR
)m_pwszFileName
.c_str();
847 //M-------------------------------------------------------------------------
849 // Method: COooFilterCF::COooFilterCF
851 // Summary: Class factory constructor
855 // Purpose: Manages global instance count
857 //--------------------------------------------------------------------------
858 COooFilterCF::COooFilterCF() :
861 InterlockedIncrement( &g_lInstances
);
863 //M-------------------------------------------------------------------------
865 // Method: COooFilterCF::~COooFilterCF
867 // Summary: Class factory destructor
871 // Purpose: Manages global instance count
873 //--------------------------------------------------------------------------
874 COooFilterCF::~COooFilterCF()
876 InterlockedDecrement( &g_lInstances
);
878 //M-------------------------------------------------------------------------
880 // Method: COooFilterCF::QueryInterface (IUnknown::QueryInterface)
882 // Summary: Queries for requested interface
885 // [in] Reference IID of requested interface
887 // [out] Address that receives requested interface pointer
890 // Interface is supported
892 // Interface is not supported
894 //--------------------------------------------------------------------------
895 SCODE STDMETHODCALLTYPE
COooFilterCF::QueryInterface(REFIID riid
, void ** ppvObject
)
899 if ( IID_IClassFactory
== riid
)
900 pUnkTemp
= (IUnknown
*)(IClassFactory
*)this;
901 else if ( IID_IUnknown
== riid
)
902 pUnkTemp
= (IUnknown
*)this;
906 return E_NOINTERFACE
;
908 *ppvObject
= (void *)pUnkTemp
;
912 //M-------------------------------------------------------------------------
914 // Method: COooFilterCF::AddRef (IUknown::AddRef)
916 // Summary: Increments interface refcount
920 // Returns: Value of incremented interface refcount
922 //-------------------------------------------------------------------------
923 ULONG STDMETHODCALLTYPE
COooFilterCF::AddRef()
925 return InterlockedIncrement( &m_lRefs
);
927 //M-------------------------------------------------------------------------
929 // Method: COooFilterCF::Release (IUnknown::Release)
931 // Summary: Decrements interface refcount, deleting if unreferenced
935 // Returns: Value of decremented refcount
937 //--------------------------------------------------------------------------
938 ULONG STDMETHODCALLTYPE
COooFilterCF::Release()
940 ULONG ulTmp
= InterlockedDecrement( &m_lRefs
);
946 //M-------------------------------------------------------------------------
948 // Method: COooFilterCF::CreateInstance (IClassFactory::CreateInstance)
950 // Summary: Creates new OpenOffice.org filter object
952 // Arguments: pUnkOuter
953 // [in] Pointer to IUnknown interface of aggregating object
955 // [in] Reference IID of requested interface
957 // [out] Address that receives requested interface pointer
960 // OpenOffice.org filter object was successfully created
961 // CLASS_E_NOAGGREGATION
962 // pUnkOuter parameter was non-NULL
966 // OpenOffice.org filter object could not be created
967 // due to insufficient memory
969 // Unsuccessful due to an unexpected condition
971 //--------------------------------------------------------------------------
972 SCODE STDMETHODCALLTYPE
COooFilterCF::CreateInstance(
973 IUnknown
* pUnkOuter
,
977 COooFilter
*pIUnk
= 0;
978 if ( 0 != pUnkOuter
)
979 return CLASS_E_NOAGGREGATION
;
980 pIUnk
= new COooFilter();
983 if ( SUCCEEDED( pIUnk
->QueryInterface( riid
, ppvObject
) ) )
985 // Release extra refcount from QueryInterface
995 return E_OUTOFMEMORY
;
999 //M-------------------------------------------------------------------------
1001 // Method: COooFilterCF::LockServer (IClassFactory::LockServer)
1003 // Summary: Forces/allows filter class to remain loaded/be unloaded
1006 // [in] TRUE to lock, FALSE to unlock
1011 // (not implemented)
1013 // (not implemented)
1015 // (not implemented)
1017 //--------------------------------------------------------------------------
1018 SCODE STDMETHODCALLTYPE
COooFilterCF::LockServer(BOOL fLock
)
1021 InterlockedIncrement( &g_lInstances
);
1023 InterlockedDecrement( &g_lInstances
);
1026 //+-------------------------------------------------------------------------
1030 // Summary: Implements Dynamic Link Library functions for OpenOffice.org filter
1032 //--------------------------------------------------------------------------
1033 //F-------------------------------------------------------------------------
1035 // Function: DllMain
1037 // Summary: Called from C-Runtime on process/thread attach/detach
1039 // Arguments: hInstance
1040 // [in] Handle to the DLL
1042 // [in] Reason for calling DLL entry point
1044 // [in] Details of DLL initialization and cleanup
1049 //--------------------------------------------------------------------------
1050 extern "C" BOOL WINAPI
DllMain(
1051 HINSTANCE hInstance
,
1053 LPVOID
/*lpvReserved*/
1056 if ( DLL_PROCESS_ATTACH
== fdwReason
)
1057 DisableThreadLibraryCalls( hInstance
);
1060 //F-------------------------------------------------------------------------
1062 // Function: DllGetClassObject
1064 // Summary: Create OpenOffice.org filter class factory object
1067 // [in] Class ID of class that class factory creates
1069 // [in] Reference IID of requested class factory interface
1071 // [out] Address that receives requested interface pointer
1074 // Class factory object was created successfully
1075 // CLASS_E_CLASSNOTAVAILABLE
1076 // DLL does not support the requested class
1080 // Insufficient memory to create the class factory object
1082 // Unsuccessful due to an unexpected condition
1084 //-------------------------------------------------------------------------
1085 extern "C" SCODE STDMETHODCALLTYPE
DllGetClassObject(
1091 IUnknown
*pResult
= 0;
1093 if ( CLSID_COooFilter
== cid
)
1094 pResult
= (IUnknown
*) new COooFilterCF
;
1096 return CLASS_E_CLASSNOTAVAILABLE
;
1099 if( SUCCEEDED( pResult
->QueryInterface( iid
, ppvObj
) ) )
1100 // Release extra refcount from QueryInterface
1105 return E_UNEXPECTED
;
1109 return E_OUTOFMEMORY
;
1112 //F-------------------------------------------------------------------------
1114 // Function: DllCanUnloadNow
1116 // Summary: Indicates whether it is possible to unload DLL
1121 // DLL can be unloaded now
1123 // DLL must remain loaded
1125 //--------------------------------------------------------------------------
1126 extern "C" SCODE STDMETHODCALLTYPE
DllCanUnloadNow()
1128 if ( 0 >= g_lInstances
)
1133 //F-------------------------------------------------------------------------
1135 // Function: DllRegisterServer
1136 // DllUnregisterServer
1138 // Summary: Registers and unregisters DLL server
1140 // Returns: DllRegisterServer
1142 // Registration was successful
1144 // Registration was unsuccessful
1145 // SELFREG_E_TYPELIB
1146 // (not implemented)
1148 // (not implemented)
1150 // (not implemented)
1151 // DllUnregisterServer
1153 // Unregistration was successful
1155 // Unregistration was successful, but other
1156 // entries still exist for the DLL's classes
1158 // (not implemented)
1159 // SELFREG_E_TYPELIB
1160 // (not implemented)
1162 // (not implemented)
1164 // (not implemented)
1166 //--------------------------------------------------------------------------
1169 //F-------------------------------------------------------------------------
1171 // helper functions to register the Indexing Service.
1173 //--------------------------------------------------------------------------
1175 namespace /* private */
1177 const char* GUID_PLACEHOLDER
= "{GUID}";
1178 const char* GUID_PERSIST_PLACEHOLDER
= "{GUIDPERSIST}";
1179 const char* EXTENSION_PLACEHOLDER
= "{EXT}";
1180 const char* FORWARDKEY_PLACEHOLDER
= "{FWDKEY}";
1182 const char* CLSID_GUID_INPROC_ENTRY
= "CLSID\\{GUID}\\InProcServer32";
1183 const char* CLSID_GUID_ENTRY
= "CLSID\\{GUID}";
1184 const char* CLSID_GUID_PERSIST_ADDIN_ENTRY
= "CLSID\\{GUID}\\PersistentAddinsRegistered\\{GUIDPERSIST}";
1185 const char* CLSID_PERSIST_ENTRY
= "CLSID\\{GUID}\\PersistentHandler";
1186 const char* EXT_PERSIST_ENTRY
= "{EXT}\\PersistentHandler";
1188 const char* INDEXING_FILTER_DLLSTOREGISTER
= "SYSTEM\\CurrentControlSet\\Control\\ContentIndex";
1190 //---------------------------
1191 // "String Placeholder" ->
1192 // "String Replacement"
1193 //---------------------------
1195 void SubstitutePlaceholder(std::string
& String
, const std::string
& Placeholder
, const std::string
& Replacement
)
1197 std::string::size_type idx
= String
.find(Placeholder
);
1198 std::string::size_type len
= Placeholder
.length();
1200 while (std::string::npos
!= idx
)
1202 String
.replace(idx
, len
, Replacement
);
1203 idx
= String
.find(Placeholder
);
1207 //----------------------------------------------
1208 // Make the registry entry and set Filter Handler
1209 // HKCR\CLSID\{7BC0E710-5703-45be-A29D-5D46D8B39262} = OpenOffice.org Filter
1210 // InProcServer32 (Default) = Path\ooofilt.dll
1211 // ThreadingModel = Both
1212 //----------------------------------------------
1214 HRESULT
RegisterFilterHandler(const char* FilePath
, const CLSID
& FilterGuid
)
1216 std::string ClsidEntry
= CLSID_GUID_ENTRY
;
1217 SubstitutePlaceholder(ClsidEntry
, GUID_PLACEHOLDER
, ClsidToString(FilterGuid
));
1219 if (!SetRegistryKey(HKEY_CLASSES_ROOT
, ClsidEntry
.c_str(), "", "OpenOffice.org Filter"))
1222 ClsidEntry
= CLSID_GUID_INPROC_ENTRY
;
1223 SubstitutePlaceholder(ClsidEntry
, GUID_PLACEHOLDER
, ClsidToString(FilterGuid
));
1225 if (!SetRegistryKey(HKEY_CLASSES_ROOT
, ClsidEntry
.c_str(), "", FilePath
))
1228 if (!SetRegistryKey(HKEY_CLASSES_ROOT
, ClsidEntry
.c_str(), "ThreadingModel", "Both"))
1234 //----------------------------------------------
1235 // Make the registry entry and set Persistent Handler
1236 // HKCR\CLSID\{7BC0E713-5703-45be-A29D-5D46D8B39262} = OpenOffice.org Persistent Handler
1237 // PersistentAddinsRegistered
1238 // {89BCB740-6119-101A-BCB7-00DD010655AF} = {7BC0E710-5703-45be-A29D-5D46D8B39262}
1239 //----------------------------------------------
1241 HRESULT
RegisterPersistentHandler(const CLSID
& FilterGuid
, const CLSID
& PersistentGuid
)
1243 std::string ClsidEntry_Persist
= CLSID_GUID_ENTRY
;
1244 SubstitutePlaceholder(ClsidEntry_Persist
, GUID_PLACEHOLDER
, ClsidToString(PersistentGuid
));
1247 if (!SetRegistryKey(HKEY_CLASSES_ROOT
, ClsidEntry_Persist
.c_str(), "", "OpenOffice.org Persistent Handler"))
1250 // Add missing entry
1251 std::string ClsidEntry_Persist_Entry
= CLSID_PERSIST_ENTRY
;
1252 SubstitutePlaceholder(ClsidEntry_Persist_Entry
,
1254 ClsidToString(PersistentGuid
));
1256 if (!SetRegistryKey(HKEY_CLASSES_ROOT
, ClsidEntry_Persist_Entry
.c_str(), "", ClsidToString(PersistentGuid
).c_str()));
1259 std::string ClsidEntry_Persist_Addin
= CLSID_GUID_PERSIST_ADDIN_ENTRY
;
1260 SubstitutePlaceholder(ClsidEntry_Persist_Addin
,
1262 ClsidToString(PersistentGuid
));
1263 SubstitutePlaceholder(ClsidEntry_Persist_Addin
,
1264 GUID_PERSIST_PLACEHOLDER
,
1265 ClsidToString(CLSID_PERSISTENT_HANDLER_ADDIN
));
1267 if (!SetRegistryKey(HKEY_CLASSES_ROOT
, ClsidEntry_Persist_Addin
.c_str(), "", ClsidToString(FilterGuid
).c_str() ))
1273 //---------------------------
1274 // Unregister Filter Handler or persistent handler
1275 //---------------------------
1277 HRESULT
UnregisterHandler(const CLSID
& Guid
)
1279 std::string tmp
= "CLSID\\";
1280 tmp
+= ClsidToString(Guid
);
1281 return DeleteRegistryKey(HKEY_CLASSES_ROOT
, tmp
.c_str()) ? S_OK
: E_FAIL
;
1284 //---------------------------
1285 // Register Indexing Service ext and class.
1286 // HKCR\{EXT}\PersistentHandler = {7BC0E713-5703-45be-A29D-5D46D8B39262}
1287 // HKCR\{GUID\PersistentHandler = {7BC0E713-5703-45be-A29D-5D46D8B39262}
1288 //---------------------------
1290 HRESULT
RegisterSearchHandler(const char* ModuleFileName
)
1292 if (FAILED(RegisterFilterHandler(ModuleFileName
, CLSID_FILTER_HANDLER
)))
1295 if (FAILED(RegisterPersistentHandler(CLSID_FILTER_HANDLER
, CLSID_PERSISTENT_HANDLER
)))
1298 std::string sExtPersistEntry
;
1300 for(size_t i
= 0; i
< OOFileExtensionTableSize
; i
++)
1302 // first, register extension.
1303 sExtPersistEntry
= EXT_PERSIST_ENTRY
;
1304 SubstitutePlaceholder(sExtPersistEntry
, EXTENSION_PLACEHOLDER
, OOFileExtensionTable
[i
].ExtensionAnsi
);
1305 if (!SetRegistryKey(HKEY_CLASSES_ROOT
,
1306 sExtPersistEntry
.c_str(),
1308 ClsidToString(CLSID_PERSISTENT_HANDLER
).c_str()))
1311 // second, register class.
1312 char extClassName
[MAX_PATH
];
1313 if (QueryRegistryKey(HKEY_CLASSES_ROOT
, OOFileExtensionTable
[i
].ExtensionAnsi
, "", extClassName
,MAX_PATH
))
1315 ::std::string
extCLSIDName( extClassName
);
1316 extCLSIDName
+= "\\CLSID";
1317 char extCLSID
[MAX_PATH
];
1319 if (QueryRegistryKey( HKEY_CLASSES_ROOT
, extCLSIDName
.c_str(), "", extCLSID
, MAX_PATH
))
1321 std::string ClsidEntry_CLSID_Persist
= CLSID_PERSIST_ENTRY
;
1322 SubstitutePlaceholder(ClsidEntry_CLSID_Persist
,
1326 if (!SetRegistryKey(HKEY_CLASSES_ROOT
,
1327 ClsidEntry_CLSID_Persist
.c_str(),
1329 ClsidToString(CLSID_PERSISTENT_HANDLER
).c_str() ))
1338 // Register Indexing Service ext and class.
1339 HRESULT
UnregisterSearchHandler()
1341 std::string sExtPersistEntry
;
1343 for (size_t i
= 0; i
< OOFileExtensionTableSize
; i
++)
1345 // first, unregister extension
1346 sExtPersistEntry
= EXT_PERSIST_ENTRY
;
1347 SubstitutePlaceholder(sExtPersistEntry
, EXTENSION_PLACEHOLDER
, OOFileExtensionTable
[i
].ExtensionAnsi
);
1348 DeleteRegistryKey(HKEY_CLASSES_ROOT
, sExtPersistEntry
.c_str());
1350 // second, unregister class
1351 char extClassName
[MAX_PATH
];
1352 if (QueryRegistryKey(HKEY_CLASSES_ROOT
, OOFileExtensionTable
[i
].ExtensionAnsi
, "", extClassName
,MAX_PATH
))
1354 ::std::string
extCLSIDName( extClassName
);
1355 extCLSIDName
+= "\\CLSID";
1356 char extCLSID
[MAX_PATH
];
1358 if (QueryRegistryKey( HKEY_CLASSES_ROOT
, extCLSIDName
.c_str(), "", extCLSID
, MAX_PATH
))
1360 std::string ClsidEntry_CLSID_Persist
= CLSID_PERSIST_ENTRY
;
1361 SubstitutePlaceholder(ClsidEntry_CLSID_Persist
,
1365 DeleteRegistryKey(HKEY_CLASSES_ROOT
, ClsidEntry_CLSID_Persist
.c_str());
1370 return ((UnregisterHandler(CLSID_FILTER_HANDLER
)==S_OK
) && (UnregisterHandler(CLSID_PERSISTENT_HANDLER
)==S_OK
))?S_OK
:E_FAIL
;
1373 //---------------------------
1374 // add or remove an entry to DllsToRegister entry of Indexing
1375 // Filter to let Indexing Service register our filter automatically
1377 //---------------------------
1378 HRESULT
AddOrRemoveDllsToRegisterList( const ::std::string
& DllPath
, bool isAdd
)
1380 char DllsToRegisterList
[4096];
1381 if (QueryRegistryKey(HKEY_LOCAL_MACHINE
,
1382 INDEXING_FILTER_DLLSTOREGISTER
,
1387 char * pChar
= DllsToRegisterList
;
1388 for ( ; *pChar
!= '\0' || *(pChar
+1) != '\0'; pChar
++)
1389 if ( *pChar
== '\0')
1394 ::std::string
DllList(DllsToRegisterList
);
1395 if ( ( isAdd
)&&( DllList
.find( DllPath
) == ::std::string::npos
) )
1396 DllList
.append( DllPath
);
1397 else if ( ( !isAdd
)&&( DllList
.find( DllPath
) != ::std::string::npos
) )
1398 DllList
.erase( DllList
.find( DllPath
)-1, DllPath
.length()+1 );
1402 pChar
= DllsToRegisterList
;
1403 for ( size_t nChar
= 0; nChar
< DllList
.length(); pChar
++,nChar
++)
1405 if ( DllList
[nChar
] == ';')
1408 *pChar
= DllList
[nChar
];
1410 *pChar
= *( pChar
+1 ) ='\0';
1413 int rc
= RegCreateKeyExA(HKEY_LOCAL_MACHINE
,
1414 INDEXING_FILTER_DLLSTOREGISTER
,
1417 REG_OPTION_NON_VOLATILE
,
1423 if (ERROR_SUCCESS
== rc
)
1425 rc
= RegSetValueExA( hSubKey
,
1429 reinterpret_cast<const BYTE
*>(DllsToRegisterList
),
1430 DllList
.length() + 2);
1432 RegCloseKey(hSubKey
);
1435 return (ERROR_SUCCESS
== rc
)?S_OK
:E_FAIL
;
1441 } // namespace /* private */
1443 STDAPI
DllRegisterServer()
1446 TCHAR ModuleFileName[MAX_PATH];
1449 GetModuleHandle(MODULE_NAME_FILTER),
1451 sizeof(ModuleFileName));
1456 // register search handler
1458 if (FAILED(RegisterSearchHandler(WStringToString(ModuleFileName).c_str())))
1460 if (FAILED(AddOrRemoveDllsToRegisterList(WStringToString(ModuleFileName).c_str(), true)))
1463 if (FAILED(RegisterSearchHandler(ModuleFileName)))
1465 if (FAILED(AddOrRemoveDllsToRegisterList(ModuleFileName, true)))
1475 //---------------------------
1477 //---------------------------
1479 STDAPI
DllUnregisterServer()
1482 TCHAR ModuleFileName[MAX_PATH];
1485 GetModuleHandle(MODULE_NAME_FILTER),
1487 sizeof(ModuleFileName));
1491 // unregister search handler
1492 if (FAILED(UnregisterSearchHandler()))
1496 if (FAILED(AddOrRemoveDllsToRegisterList(WStringToString(ModuleFileName).c_str(),false)))
1499 if (FAILED(AddOrRemoveDllsToRegisterList(ModuleFileName, false)))
1511 voidpf ZCALLBACK
cb_sopen (voidpf opaque
, const char* filename
, int mode
) {
1515 uLong ZCALLBACK
cb_sread (voidpf opaque
, voidpf stream
, void* buf
, uLong size
) {
1516 unsigned long newsize
;
1519 hr
= ((IStream
*)stream
)->Read (buf
, size
, &newsize
);
1521 return (unsigned long)newsize
;
1528 long ZCALLBACK
cb_sseek (voidpf opaque
, voidpf stream
, uLong offset
, int origin
) {
1529 // IStream::Seek parameters
1533 Move
.QuadPart
= (__int64
)offset
;
1537 dwOrigin
= STREAM_SEEK_CUR
;
1540 dwOrigin
= STREAM_SEEK_END
;
1543 dwOrigin
= STREAM_SEEK_SET
;
1549 hr
= ((IStream
*)stream
)->Seek (Move
, dwOrigin
, NULL
);
1558 long ZCALLBACK
cb_stell (voidpf opaque
, voidpf stream
) {
1559 // IStream::Seek parameters
1562 ULARGE_INTEGER NewPosition
;
1564 NewPosition
.QuadPart
= 0;
1566 hr
= ((IStream
*)stream
)->Seek (Move
, STREAM_SEEK_CUR
, &NewPosition
);
1568 return (long) NewPosition
.QuadPart
;
1575 int ZCALLBACK
cb_sclose (voidpf opaque
, voidpf stream
) {
1579 int ZCALLBACK
cb_serror (voidpf opaque
, voidpf stream
) {
1580 return 0; //RJK - for now
1583 uLong ZCALLBACK
cb_swrite (voidpf opaque
, voidpf stream
, const void* buf
, uLong size
) {
1585 unsigned long writecount
;
1586 hr
= ((IStream
*)stream
)->Write (buf
, size
, &writecount
);
1588 return (unsigned int)writecount
;
1593 void fill_stream_filefunc (zlib_filefunc_def
* pzlib_filefunc_def
) {
1594 pzlib_filefunc_def
->zopen_file
= cb_sopen
;
1595 pzlib_filefunc_def
->zread_file
= cb_sread
;
1596 pzlib_filefunc_def
->zwrite_file
= cb_swrite
;
1597 pzlib_filefunc_def
->ztell_file
= cb_stell
;
1598 pzlib_filefunc_def
->zseek_file
= cb_sseek
;
1599 pzlib_filefunc_def
->zclose_file
= cb_sclose
;
1600 pzlib_filefunc_def
->zerror_file
= cb_serror
;