update dev300-m58
[ooovba.git] / shell / source / win32 / shlxthandler / ooofilt / ooofilt.cxx
blobf907306e99757e4ed6a4a24d4f1fbe3de7ffde67
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: ooofilt.cxx,v $
10 * $Revision: 1.8 $
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 //--------------------------------------------------------------------------
35 // File: ooofilt.cxx
37 // Contents: Filter Implementation for OpenOffice.Org Document using
38 // Indexing Service
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 //--------------------------------------------------------------------------
68 #if defined _MSC_VER
69 #pragma warning(push, 1)
70 #endif
71 #include <windows.h>
72 #if defined _MSC_VER
73 #pragma warning(pop)
74 #endif
75 #include <string.h>
76 #include <filter.h>
77 #include <filterr.h>
78 #include <ntquery.h>
79 #include "assert.h"
80 #include "ooofilt.hxx"
81 #include <objidl.h>
82 #include <stdio.h>
83 #include "propspec.hxx"
84 #ifdef __MINGW32__
85 #include <algorithm>
86 using ::std::min;
87 #endif
90 //C-------------------------------------------------------------------------
92 // Class: COooFilter
94 // Summary: Implements OpenOffice.org filter class
96 //--------------------------------------------------------------------------
97 //M-------------------------------------------------------------------------
99 // Method: COooFilter::COooFilter
101 // Summary: Class constructor
103 // Arguments: void
105 // Purpose: Manages global instance count
107 //--------------------------------------------------------------------------
108 COooFilter::COooFilter() :
109 m_lRefs(1),
110 m_pContentReader(NULL),
111 m_pMetaInfoReader(NULL),
112 m_eState(FilteringContent),
113 m_ulUnicodeBufferLen(0),
114 m_ulUnicodeCharsRead(0),
115 m_ulPropertyNum(0),
116 m_ulCurrentPropertyNum(0),
117 m_ulChunkID(1),
118 m_fContents(FALSE),
119 m_fEof(FALSE),
120 m_ChunkPosition(0),
121 m_cAttributes(0),
122 m_pAttributes(0),
123 m_pStream(NULL)
126 InterlockedIncrement( &g_lInstances );
128 //M-------------------------------------------------------------------------
130 // Method: COooFilter::~COooFilter
132 // Summary: Class destructor
134 // Arguments: void
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
157 // Arguments: riid
158 // [in] Reference IID of requested interface
159 // ppvObject
160 // [out] Address that receives requested interface pointer
162 // Returns: S_OK
163 // Interface is supported
164 // E_NOINTERFACE
165 // Interface is not supported
167 //--------------------------------------------------------------------------
168 SCODE STDMETHODCALLTYPE COooFilter::QueryInterface(
169 REFIID riid,
170 void ** ppvObject)
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;
183 else
185 *ppvObject = NULL;
186 return E_NOINTERFACE;
188 *ppvObject = (void *)pUnkTemp;
189 pUnkTemp->AddRef();
190 return S_OK;
192 //M-------------------------------------------------------------------------
194 // Method: COooFilter::AddRef (IUnknown::AddRef)
196 // Summary: Increments interface refcount
198 // Arguments: void
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
213 // Arguments: void
215 // Returns: Value of decremented interface refcount
217 //--------------------------------------------------------------------------
218 ULONG STDMETHODCALLTYPE COooFilter::Release()
220 ULONG ulTmp = InterlockedDecrement( &m_lRefs );
222 if ( 0 == ulTmp )
223 delete this;
224 return ulTmp;
226 //M-------------------------------------------------------------------------
228 // Method: COooFilter::Init (IFilter::Init)
230 // Summary: Initializes OpenOffice.org filter instance
232 // Arguments: grfFlags
233 // [in] Flags for filter behavior
234 // cAttributes
235 // [in] Number attributes in array aAttributes
236 // aAttributes
237 // [in] Array of requested attribute strings
238 // pFlags
239 // [out] Pointer to return flags for additional properties
241 // Returns: S_OK
242 // Initialization succeeded
243 // E_FAIL
244 // File not previously loaded
245 // E_INVALIDARG
246 // Count and contents of attributes do not agree
247 // FILTER_E_ACCESS
248 // Unable to access file to be filtered
249 // FILTER_E_PASSWORD
250 // (not implemented)
252 //--------------------------------------------------------------------------
253 const int COUNT_ATTRIBUTES = 5;
255 SCODE STDMETHODCALLTYPE COooFilter::Init(
256 ULONG grfFlags,
257 ULONG cAttributes,
258 FULLPROPSPEC const * aAttributes,
259 ULONG * pFlags)
261 // Enumerate OLE properties, since any NTFS file can have them
262 *pFlags = IFILTER_FLAGS_OLE_PROPERTIES;
265 m_fContents = FALSE;
266 m_ulPropertyNum = 0;
267 m_ulCurrentPropertyNum = 0;
268 if ( m_cAttributes > 0 )
270 delete[] m_pAttributes;
271 m_pAttributes = 0;
272 m_cAttributes = 0;
274 if( 0 < cAttributes )
276 // Filter properties specified in aAttributes
277 if ( 0 == aAttributes )
278 return E_INVALIDARG;
279 m_pAttributes = new CFullPropSpec[cAttributes];
280 m_cAttributes = cAttributes;
281 // Is caller want to filter contents?
282 CFullPropSpec *pAttrib = (CFullPropSpec *) aAttributes;
283 ULONG ulNumAttr;
284 for ( ulNumAttr = 0 ; ulNumAttr < cAttributes; ulNumAttr++ )
286 if ( pAttrib[ulNumAttr].IsPropertyPropid() &&
287 pAttrib[ulNumAttr].GetPropertyPropid() == PID_STG_CONTENTS &&
288 pAttrib[ulNumAttr].GetPropSet() == guidStorage )
290 m_fContents = TRUE;
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
299 m_fContents = TRUE;
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
317 m_fContents = TRUE;
319 else
320 m_fContents = FALSE;
321 // Re-initialize
322 if ( m_fContents )
324 m_fEof = FALSE;
325 m_eState = FilteringContent;
326 m_ulUnicodeCharsRead = 0;
327 m_ChunkPosition = 0;
329 else
331 m_fEof = TRUE;
332 m_eState = FilteringProperty;
334 m_ulChunkID = 1;
336 catch (const std::exception&)
338 return E_FAIL;
341 return S_OK;
343 //M-------------------------------------------------------------------------
345 // Method: COooFilter::GetChunk (IFilter::GetChunk)
347 // Summary: Gets the next chunk
349 // Arguments: ppStat
350 // [out] Pointer to description of current chunk
351 // Returns: S_OK
352 // Chunk was successfully retrieved
353 // E_FAIL
354 // Character conversion failed
355 // FILTER_E_ACCESS
356 // General access failure occurred
357 // FILTER_E_END_OF_CHUNKS
358 // Previous chunk was the last chunk
359 // FILTER_E_EMBEDDING_UNAVAILABLE
360 // (not implemented)
361 // FILTER_E_LINK_UNAVAILABLE
362 // (not implemented)
363 // FILTER_E_PASSWORD
364 // (not implemented)
366 //--------------------------------------------------------------------------
367 SCODE STDMETHODCALLTYPE COooFilter::GetChunk(STAT_CHUNK * pStat)
369 for(;;)
371 switch ( m_eState )
373 case FilteringContent:
375 // Read Unicodes from buffer.
376 if( m_ChunkPosition == m_pContentReader ->getChunkBuffer().size() )
378 m_ulUnicodeBufferLen=0;
379 m_fEof = TRUE;
382 if ( !m_fContents || m_fEof )
384 m_eState = FilteringProperty;
385 continue;
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;
402 m_ulChunkID++;
403 m_ChunkPosition++;
404 return S_OK;
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 )
419 m_ulPropertyNum++;
420 else
421 break;
423 if ( m_ulPropertyNum == m_cAttributes)
424 return FILTER_E_END_OF_CHUNKS;
425 else
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;
439 m_ulPropertyNum++;
440 m_ulChunkID++;
441 return S_OK;
444 default:
445 return E_FAIL;
446 }//switch(...)
447 }//for(;;)
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
458 // awcBuffer
459 // [out] Pointer to buffer to receive UNICODE text
461 // Returns: S_OK
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)
471 switch ( m_eState )
473 case FilteringProperty:
474 return FILTER_E_NO_TEXT;
475 case FilteringContent:
477 if ( !m_fContents || 0 == m_ulUnicodeBufferLen )
479 *pcwcBuffer = 0;
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;
494 return S_OK;
496 default:
497 return E_FAIL;
500 //M-------------------------------------------------------------------------
502 // Method: GetMetaInfoNameFromPropertyId
504 // Summary: helper function to convert PropertyID into respective
505 // MetaInfo names.
507 // Arguments: ulPropID
508 // [in] property ID
510 // Returns: corresponding metainfo names.
512 //--------------------------------------------------------------------------
514 ::std::wstring GetMetaInfoNameFromPropertyId( ULONG ulPropID )
516 switch ( 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
536 // Always
537 // FILTER_E_NO_MORE_VALUES
538 // (not implemented)
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) );
551 if ( pPropVar == 0 )
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;
568 return S_OK;
570 else
571 return E_FAIL;
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
581 // riid
582 // [in] Reference IID of specified interface
583 // ppunk
584 // [out] Address that receives requested interface pointer
586 // Returns: E_NOTIMPL
587 // Always
588 // FILTER_W_REGION_CLIPPED
589 // (not implemented)
591 //--------------------------------------------------------------------------
593 SCODE STDMETHODCALLTYPE COooFilter::BindRegion(
594 FILTERREGION /*origPos*/,
595 REFIID /*riid*/,
596 void ** /*ppunk*/)
598 // BindRegion is currently reserved for future use
599 return E_NOTIMPL;
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
610 // Returns: S_OK
611 // Always
612 // E_FAIL
613 // (not implemented)
614 //--------------------------------------------------------------------------
615 SCODE STDMETHODCALLTYPE COooFilter::GetClassID(CLSID * pClassID)
617 *pClassID = CLSID_COooFilter;
618 return S_OK;
620 //M-------------------------------------------------------------------------
622 // Method: COooFilter::IsDirty (IPersistFile::IsDirty)
624 // Summary: Checks whether file has changed since last save
626 // Arguments: void
628 // Returns: S_FALSE
629 // Always
630 // S_OK
631 // (not implemented)
633 //--------------------------------------------------------------------------
634 SCODE STDMETHODCALLTYPE COooFilter::IsDirty()
636 // File is opened read-only and never changes
637 return S_FALSE;
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
648 // dwMode
649 // [in] Access mode to open the file
651 // Returns: S_OK
652 // File was successfully loaded
653 // E_OUTOFMEMORY
654 // File could not be loaded due to insufficient memory
655 // E_FAIL
656 // (not implemented)
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&)
676 return E_FAIL;
678 return S_OK;
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
689 // fRemember
690 // [in] Whether the saved copy is made the current file
692 // Returns: E_FAIL
693 // Always
694 // S_OK
695 // (not implemented)
697 //--------------------------------------------------------------------------
698 SCODE STDMETHODCALLTYPE COooFilter::Save(LPCWSTR /*pszFileName*/, BOOL /*fRemember*/)
700 // File is opened read-only; saving it is an error
701 return E_FAIL;
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
713 // Returns: S_OK
714 // Always
716 //--------------------------------------------------------------------------
717 SCODE STDMETHODCALLTYPE COooFilter::SaveCompleted(LPCWSTR /*pszFileName*/)
719 // File is opened read-only, so "save" is always finished
720 return S_OK;
723 //M-------------------------------------------------------------------------
725 // Method: COooFilter::Load (IPersistStream::Load)
727 // Summary: Initializes an object from the stream where it was previously saved
729 // Arguments: pStm
730 // [in] Pointer to stream from which object should be loaded
733 // Returns: S_OK
734 // E_OUTOFMEMORY
735 // E_FAIL
738 //--------------------------------------------------------------------------
739 SCODE STDMETHODCALLTYPE COooFilter::Load(IStream *pStm)
742 // These next few lines work around the "Seek pointer" bug found on Vista.
744 char buf[20];
745 unsigned long count;
746 HRESULT hr;
747 ULARGE_INTEGER NewPosition;
748 LARGE_INTEGER Move;
749 Move.QuadPart = 0;
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;
757 m_pStream = 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&)
771 return E_FAIL;
773 return S_OK;
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*/)
792 return E_NOTIMPL;
795 //M-------------------------------------------------------------------------
797 // Method: COooFilter::Save (IPersistStream::Save)
799 // Summary: Save object to specified stream
801 // Arguments: pStm
802 // [in] Pointer to stream
804 // fClearDirty
805 // [in] Indicates whether to clear dirty flag
807 // Returns: E_NOTIMPL
810 //--------------------------------------------------------------------------
811 SCODE STDMETHODCALLTYPE COooFilter::Save(IStream * /*pStm*/, BOOL )
814 return E_NOTIMPL;
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
827 // Returns: S_OK
828 // A valid absolute path was successfully returned
829 // S_FALSE
830 // (not implemented)
831 // E_OUTOFMEMORY
832 // Operation failed due to insufficient memory
833 // E_FAIL
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 )
841 return E_FAIL;
842 else
843 *ppszFileName = (LPWSTR)m_pwszFileName.c_str();
844 return S_OK;
847 //M-------------------------------------------------------------------------
849 // Method: COooFilterCF::COooFilterCF
851 // Summary: Class factory constructor
853 // Arguments: void
855 // Purpose: Manages global instance count
857 //--------------------------------------------------------------------------
858 COooFilterCF::COooFilterCF() :
859 m_lRefs(1)
861 InterlockedIncrement( &g_lInstances );
863 //M-------------------------------------------------------------------------
865 // Method: COooFilterCF::~COooFilterCF
867 // Summary: Class factory destructor
869 // Arguments: void
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
884 // Arguments: riid
885 // [in] Reference IID of requested interface
886 // ppvObject
887 // [out] Address that receives requested interface pointer
889 // Returns: S_OK
890 // Interface is supported
891 // E_NOINTERFACE
892 // Interface is not supported
894 //--------------------------------------------------------------------------
895 SCODE STDMETHODCALLTYPE COooFilterCF::QueryInterface(REFIID riid, void ** ppvObject)
897 IUnknown *pUnkTemp;
899 if ( IID_IClassFactory == riid )
900 pUnkTemp = (IUnknown *)(IClassFactory *)this;
901 else if ( IID_IUnknown == riid )
902 pUnkTemp = (IUnknown *)this;
903 else
905 *ppvObject = NULL;
906 return E_NOINTERFACE;
908 *ppvObject = (void *)pUnkTemp;
909 pUnkTemp->AddRef();
910 return S_OK;
912 //M-------------------------------------------------------------------------
914 // Method: COooFilterCF::AddRef (IUknown::AddRef)
916 // Summary: Increments interface refcount
918 // Arguments: void
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
933 // Arguments: void
935 // Returns: Value of decremented refcount
937 //--------------------------------------------------------------------------
938 ULONG STDMETHODCALLTYPE COooFilterCF::Release()
940 ULONG ulTmp = InterlockedDecrement( &m_lRefs );
942 if ( 0 == ulTmp )
943 delete this;
944 return ulTmp;
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
954 // riid
955 // [in] Reference IID of requested interface
956 // ppvObject
957 // [out] Address that receives requested interface pointer
959 // Returns: S_OK
960 // OpenOffice.org filter object was successfully created
961 // CLASS_E_NOAGGREGATION
962 // pUnkOuter parameter was non-NULL
963 // E_NOINTERFACE
964 // (not implemented)
965 // E_OUTOFMEMORY
966 // OpenOffice.org filter object could not be created
967 // due to insufficient memory
968 // E_UNEXPECTED
969 // Unsuccessful due to an unexpected condition
971 //--------------------------------------------------------------------------
972 SCODE STDMETHODCALLTYPE COooFilterCF::CreateInstance(
973 IUnknown * pUnkOuter,
974 REFIID riid,
975 void * * ppvObject)
977 COooFilter *pIUnk = 0;
978 if ( 0 != pUnkOuter )
979 return CLASS_E_NOAGGREGATION;
980 pIUnk = new COooFilter();
981 if ( 0 != pIUnk )
983 if ( SUCCEEDED( pIUnk->QueryInterface( riid , ppvObject ) ) )
985 // Release extra refcount from QueryInterface
986 pIUnk->Release();
988 else
990 delete pIUnk;
991 return E_UNEXPECTED;
994 else
995 return E_OUTOFMEMORY;
996 return S_OK;
999 //M-------------------------------------------------------------------------
1001 // Method: COooFilterCF::LockServer (IClassFactory::LockServer)
1003 // Summary: Forces/allows filter class to remain loaded/be unloaded
1005 // Arguments: fLock
1006 // [in] TRUE to lock, FALSE to unlock
1008 // Returns: S_OK
1009 // Always
1010 // E_FAIL
1011 // (not implemented)
1012 // E_OUTOFMEMORY
1013 // (not implemented)
1014 // E_UNEXPECTED
1015 // (not implemented)
1017 //--------------------------------------------------------------------------
1018 SCODE STDMETHODCALLTYPE COooFilterCF::LockServer(BOOL fLock)
1020 if( fLock )
1021 InterlockedIncrement( &g_lInstances );
1022 else
1023 InterlockedDecrement( &g_lInstances );
1024 return S_OK;
1026 //+-------------------------------------------------------------------------
1028 // DLL: ooofilt.dll
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
1041 // fdwReason
1042 // [in] Reason for calling DLL entry point
1043 // lpReserve
1044 // [in] Details of DLL initialization and cleanup
1046 // Returns: TRUE
1047 // Always
1049 //--------------------------------------------------------------------------
1050 extern "C" BOOL WINAPI DllMain(
1051 HINSTANCE hInstance,
1052 DWORD fdwReason,
1053 LPVOID /*lpvReserved*/
1056 if ( DLL_PROCESS_ATTACH == fdwReason )
1057 DisableThreadLibraryCalls( hInstance );
1058 return TRUE;
1060 //F-------------------------------------------------------------------------
1062 // Function: DllGetClassObject
1064 // Summary: Create OpenOffice.org filter class factory object
1066 // Arguments: cid
1067 // [in] Class ID of class that class factory creates
1068 // iid
1069 // [in] Reference IID of requested class factory interface
1070 // ppvObj
1071 // [out] Address that receives requested interface pointer
1073 // Returns: S_OK
1074 // Class factory object was created successfully
1075 // CLASS_E_CLASSNOTAVAILABLE
1076 // DLL does not support the requested class
1077 // E_INVALIDARG
1078 // (not implemented
1079 // E_OUTOFMEMORY
1080 // Insufficient memory to create the class factory object
1081 // E_UNEXPECTED
1082 // Unsuccessful due to an unexpected condition
1084 //-------------------------------------------------------------------------
1085 extern "C" SCODE STDMETHODCALLTYPE DllGetClassObject(
1086 REFCLSID cid,
1087 REFIID iid,
1088 void ** ppvObj
1091 IUnknown *pResult = 0;
1093 if ( CLSID_COooFilter == cid )
1094 pResult = (IUnknown *) new COooFilterCF;
1095 else
1096 return CLASS_E_CLASSNOTAVAILABLE;
1097 if ( 0 != pResult )
1099 if( SUCCEEDED( pResult->QueryInterface( iid, ppvObj ) ) )
1100 // Release extra refcount from QueryInterface
1101 pResult->Release();
1102 else
1104 delete pResult;
1105 return E_UNEXPECTED;
1108 else
1109 return E_OUTOFMEMORY;
1110 return S_OK;
1112 //F-------------------------------------------------------------------------
1114 // Function: DllCanUnloadNow
1116 // Summary: Indicates whether it is possible to unload DLL
1118 // Arguments: void
1120 // Returns: S_OK
1121 // DLL can be unloaded now
1122 // S_FALSE
1123 // DLL must remain loaded
1125 //--------------------------------------------------------------------------
1126 extern "C" SCODE STDMETHODCALLTYPE DllCanUnloadNow()
1128 if ( 0 >= g_lInstances )
1129 return S_OK;
1130 else
1131 return S_FALSE;
1133 //F-------------------------------------------------------------------------
1135 // Function: DllRegisterServer
1136 // DllUnregisterServer
1138 // Summary: Registers and unregisters DLL server
1140 // Returns: DllRegisterServer
1141 // S_OK
1142 // Registration was successful
1143 // SELFREG_E_CLASS
1144 // Registration was unsuccessful
1145 // SELFREG_E_TYPELIB
1146 // (not implemented)
1147 // E_OUTOFMEMORY
1148 // (not implemented)
1149 // E_UNEXPECTED
1150 // (not implemented)
1151 // DllUnregisterServer
1152 // S_OK
1153 // Unregistration was successful
1154 // S_FALSE
1155 // Unregistration was successful, but other
1156 // entries still exist for the DLL's classes
1157 // SELFREG_E_CLASS
1158 // (not implemented)
1159 // SELFREG_E_TYPELIB
1160 // (not implemented)
1161 // E_OUTOFMEMORY
1162 // (not implemented)
1163 // E_UNEXPECTED
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"))
1220 return E_FAIL;
1222 ClsidEntry = CLSID_GUID_INPROC_ENTRY;
1223 SubstitutePlaceholder(ClsidEntry, GUID_PLACEHOLDER, ClsidToString(FilterGuid));
1225 if (!SetRegistryKey(HKEY_CLASSES_ROOT, ClsidEntry.c_str(), "", FilePath))
1226 return E_FAIL;
1228 if (!SetRegistryKey(HKEY_CLASSES_ROOT, ClsidEntry.c_str(), "ThreadingModel", "Both"))
1229 return E_FAIL;
1231 return S_OK;
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"))
1248 return E_FAIL;
1250 // Add missing entry
1251 std::string ClsidEntry_Persist_Entry = CLSID_PERSIST_ENTRY;
1252 SubstitutePlaceholder(ClsidEntry_Persist_Entry,
1253 GUID_PLACEHOLDER,
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,
1261 GUID_PLACEHOLDER,
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() ))
1268 return E_FAIL;
1270 return S_OK;
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)))
1293 return E_FAIL;
1295 if (FAILED(RegisterPersistentHandler(CLSID_FILTER_HANDLER, CLSID_PERSISTENT_HANDLER )))
1296 return E_FAIL;
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(),
1307 "",
1308 ClsidToString(CLSID_PERSISTENT_HANDLER).c_str()))
1309 return E_FAIL;
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,
1323 GUID_PLACEHOLDER,
1324 extCLSID);
1326 if (!SetRegistryKey(HKEY_CLASSES_ROOT,
1327 ClsidEntry_CLSID_Persist.c_str(),
1328 "",
1329 ClsidToString(CLSID_PERSISTENT_HANDLER).c_str() ))
1330 return E_FAIL;
1335 return S_OK;
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,
1362 GUID_PLACEHOLDER,
1363 extCLSID);
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
1376 // each time.
1377 //---------------------------
1378 HRESULT AddOrRemoveDllsToRegisterList( const ::std::string & DllPath, bool isAdd )
1380 char DllsToRegisterList[4096];
1381 if (QueryRegistryKey(HKEY_LOCAL_MACHINE,
1382 INDEXING_FILTER_DLLSTOREGISTER,
1383 "DLLsToRegister",
1384 DllsToRegisterList,
1385 4096))
1387 char * pChar = DllsToRegisterList;
1388 for ( ; *pChar != '\0' || *(pChar +1) != '\0'; pChar++)
1389 if ( *pChar == '\0')
1390 *pChar = ';';
1391 *pChar = ';';
1392 *(pChar+1) = '\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 );
1399 else
1400 return S_OK;
1402 pChar = DllsToRegisterList;
1403 for ( size_t nChar = 0; nChar < DllList.length(); pChar++,nChar++)
1405 if ( DllList[nChar] == ';')
1406 *pChar = '\0';
1407 else
1408 *pChar = DllList[nChar];
1410 *pChar = *( pChar+1 ) ='\0';
1412 HKEY hSubKey;
1413 int rc = RegCreateKeyExA(HKEY_LOCAL_MACHINE,
1414 INDEXING_FILTER_DLLSTOREGISTER,
1416 "",
1417 REG_OPTION_NON_VOLATILE,
1418 KEY_WRITE,
1420 &hSubKey,
1423 if (ERROR_SUCCESS == rc)
1425 rc = RegSetValueExA( hSubKey,
1426 "DLLsToRegister",
1428 REG_MULTI_SZ,
1429 reinterpret_cast<const BYTE*>(DllsToRegisterList),
1430 DllList.length() + 2);
1432 RegCloseKey(hSubKey);
1435 return (ERROR_SUCCESS == rc)?S_OK:E_FAIL;
1438 return S_OK;
1441 } // namespace /* private */
1443 STDAPI DllRegisterServer()
1446 TCHAR ModuleFileName[MAX_PATH];
1448 GetModuleFileName(
1449 GetModuleHandle(MODULE_NAME_FILTER),
1450 ModuleFileName,
1451 sizeof(ModuleFileName));
1453 HRESULT hr = S_OK;
1456 // register search handler
1457 #ifdef UNICODE
1458 if (FAILED(RegisterSearchHandler(WStringToString(ModuleFileName).c_str())))
1459 hr = E_FAIL;
1460 if (FAILED(AddOrRemoveDllsToRegisterList(WStringToString(ModuleFileName).c_str(), true)))
1461 hr = E_FAIL;
1462 #else
1463 if (FAILED(RegisterSearchHandler(ModuleFileName)))
1464 hr = E_FAIL;
1465 if (FAILED(AddOrRemoveDllsToRegisterList(ModuleFileName, true)))
1466 hr = E_FAIL;
1467 #endif
1470 return hr;
1472 return S_OK;
1475 //---------------------------
1477 //---------------------------
1479 STDAPI DllUnregisterServer()
1482 TCHAR ModuleFileName[MAX_PATH];
1484 GetModuleFileName(
1485 GetModuleHandle(MODULE_NAME_FILTER),
1486 ModuleFileName,
1487 sizeof(ModuleFileName));
1489 HRESULT hr = S_OK;
1491 // unregister search handler
1492 if (FAILED(UnregisterSearchHandler()))
1493 hr = E_FAIL;
1495 #ifdef UNICODE
1496 if (FAILED(AddOrRemoveDllsToRegisterList(WStringToString(ModuleFileName).c_str(),false)))
1497 hr = E_FAIL;
1498 #else
1499 if (FAILED(AddOrRemoveDllsToRegisterList(ModuleFileName, false)))
1500 hr = E_FAIL;
1501 #endif
1503 return hr;
1505 return S_OK;
1508 extern "C" {
1510 // IStream callback
1511 voidpf ZCALLBACK cb_sopen (voidpf opaque, const char* filename, int mode) {
1512 return opaque;
1515 uLong ZCALLBACK cb_sread (voidpf opaque, voidpf stream, void* buf, uLong size) {
1516 unsigned long newsize;
1517 HRESULT hr;
1519 hr = ((IStream *)stream)->Read (buf, size, &newsize);
1520 if (hr == S_OK){
1521 return (unsigned long)newsize;
1523 else {
1524 return (uLong)0;
1528 long ZCALLBACK cb_sseek (voidpf opaque, voidpf stream, uLong offset, int origin) {
1529 // IStream::Seek parameters
1530 HRESULT hr;
1531 LARGE_INTEGER Move;
1532 DWORD dwOrigin;
1533 Move.QuadPart = (__int64)offset;
1535 switch (origin) {
1536 case SEEK_CUR:
1537 dwOrigin = STREAM_SEEK_CUR;
1538 break;
1539 case SEEK_END:
1540 dwOrigin = STREAM_SEEK_END;
1541 break;
1542 case SEEK_SET:
1543 dwOrigin = STREAM_SEEK_SET;
1544 break;
1545 default:
1546 return -1;
1549 hr = ((IStream*)stream)->Seek (Move, dwOrigin, NULL);
1550 if (hr == S_OK){
1551 return 0;
1553 else {
1554 return -1;
1558 long ZCALLBACK cb_stell (voidpf opaque, voidpf stream) {
1559 // IStream::Seek parameters
1560 HRESULT hr;
1561 LARGE_INTEGER Move;
1562 ULARGE_INTEGER NewPosition;
1563 Move.QuadPart = 0;
1564 NewPosition.QuadPart = 0;
1566 hr = ((IStream*)stream)->Seek (Move, STREAM_SEEK_CUR, &NewPosition);
1567 if (hr == S_OK){
1568 return (long) NewPosition.QuadPart;
1570 else {
1571 return -1;
1575 int ZCALLBACK cb_sclose (voidpf opaque, voidpf stream) {
1576 return 0;
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) {
1584 HRESULT hr;
1585 unsigned long writecount;
1586 hr = ((IStream*)stream)->Write (buf, size, &writecount);
1587 if (hr == S_OK)
1588 return (unsigned int)writecount;
1589 else
1590 return (uLong)0;
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;