diff options
Diffstat (limited to 'shell/source/win32/shlxthandler/ooofilt/ooofilt.cxx')
-rw-r--r-- | shell/source/win32/shlxthandler/ooofilt/ooofilt.cxx | 956 |
1 files changed, 956 insertions, 0 deletions
diff --git a/shell/source/win32/shlxthandler/ooofilt/ooofilt.cxx b/shell/source/win32/shlxthandler/ooofilt/ooofilt.cxx new file mode 100644 index 000000000..c45c69930 --- /dev/null +++ b/shell/source/win32/shlxthandler/ooofilt/ooofilt.cxx @@ -0,0 +1,956 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +// File: ooofilt.cxx +// Contents: Filter Implementation for OpenOffice.Org Document using +// Indexing Service +// Summary: The LibreOffice filter reads OpenOffice.org XML files (with +// the extension .sxw .sxi, etc) and ODF files and extract +// their content, author, keywords,subject,comments and title +// to be filtered. + +// Platform: Windows 2000, Windows XP + +#include <contentreader.hxx> +#include <metainforeader.hxx> +#include <registry.hxx> +#include <fileextensions.hxx> + + +// Include file Purpose +// windows.h Win32 declarations +// string.h string wstring declarations +// filter.h IFilter interface declarations +// filterr.h FACILITY_ITF error definitions for IFilter +// ntquery.h Indexing Service declarations +// assert.h assertion function. +// ooofilt.hxx LibreOffice filter declarations +// propspec.hxx PROPSPEC + + +#if !defined WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include <windows.h> + +#include <string.h> +#include <filter.h> +#include <filterr.h> +#include <ntquery.h> +#include <assert.h> +#include "ooofilt.hxx" +#include <objidl.h> +#include <stdio.h> +#include "propspec.hxx" + +#include <stream_helper.hxx> + +#include <olectl.h> // declarations of DllRegisterServer/DllUnregisterServer + +//C------------------------------------------------------------------------- +// Class: COooFilter +// Summary: Implements LibreOffice filter class + +//M------------------------------------------------------------------------- +// Method: COooFilter::COooFilter +// Summary: Class constructor +// Arguments: void +// Purpose: Manages global instance count + +COooFilter::COooFilter() : + m_lRefs(1), + m_pContentReader(nullptr), + m_pMetaInfoReader(nullptr), + m_eState(FilterState::FilteringContent), + m_ulUnicodeBufferLen(0), + m_ulUnicodeCharsRead(0), + m_ulPropertyNum(0), + m_ulCurrentPropertyNum(0), + m_ulChunkID(1), + m_fContents(false), + m_fEof(false), + m_ChunkPosition(0), + m_cAttributes(0), + m_pAttributes(nullptr), + m_pStream(nullptr) + +{ + InterlockedIncrement( &g_lInstances ); +} +//M------------------------------------------------------------------------- +// Method: COooFilter::~COooFilter +// Summary: Class destructor +// Arguments: void +// Purpose: Manages global instance count and file handle + +COooFilter::~COooFilter() +{ + delete [] m_pAttributes; + delete m_pContentReader; + delete m_pMetaInfoReader; + delete m_pStream; + + InterlockedDecrement( &g_lInstances ); +} + +//M------------------------------------------------------------------------- +// Method: COooFilter::QueryInterface (IUnknown::QueryInterface) +// Summary: Queries for requested interface // Arguments: riid +// [in] Reference IID of requested interface +// ppvObject +// [out] Address that receives requested interface pointer +// Returns: S_OK +// Interface is supported +// E_NOINTERFACE +// Interface is not supported + +HRESULT STDMETHODCALLTYPE COooFilter::QueryInterface( + REFIID riid, + void ** ppvObject) +{ + IUnknown *pUnkTemp = nullptr; + if ( IID_IFilter == riid ) + pUnkTemp = static_cast<IFilter *>(this); + else if ( IID_IPersistFile == riid ) + pUnkTemp = static_cast<IPersistFile *>(this); + else if ( IID_IPersist == riid ) + pUnkTemp = static_cast<IPersistFile *>(this); + else if (IID_IPersistStream == riid) + pUnkTemp = static_cast<IPersistStream *>(this); + else if ( IID_IUnknown == riid ) + pUnkTemp = static_cast<IPersistFile *>(this); + else + { + *ppvObject = nullptr; + return E_NOINTERFACE; + } + *ppvObject = pUnkTemp; + pUnkTemp->AddRef(); + return S_OK; +} +//M------------------------------------------------------------------------- +// Method: COooFilter::AddRef (IUnknown::AddRef) +// Summary: Increments interface refcount +// Arguments: void +// Returns: Value of incremented interface refcount + +ULONG STDMETHODCALLTYPE COooFilter::AddRef() +{ + return InterlockedIncrement( &m_lRefs ); +} +//M------------------------------------------------------------------------- +// Method: COooFilter::Release (IUnknown::Release) +// Summary: Decrements interface refcount, deleting if unreferenced +// Arguments: void +// Returns: Value of decremented interface refcount + +ULONG STDMETHODCALLTYPE COooFilter::Release() +{ + ULONG ulTmp = InterlockedDecrement( &m_lRefs ); + + if ( 0 == ulTmp ) + delete this; + return ulTmp; +} +//M------------------------------------------------------------------------- +// Method: COooFilter::Init (IFilter::Init) +// Summary: Initializes LibreOffice filter instance +// Arguments: grfFlags +// [in] Flags for filter behavior +// cAttributes +// [in] Number attributes in array aAttributes +// aAttributes +// [in] Array of requested attribute strings +// pFlags +// [out] Pointer to return flags for additional properties +// Returns: S_OK +// Initialization succeeded +// E_FAIL +// File not previously loaded +// E_INVALIDARG +// Count and contents of attributes do not agree +// FILTER_E_ACCESS +// Unable to access file to be filtered +// FILTER_E_PASSWORD +// (not implemented) + +const int COUNT_ATTRIBUTES = 5; + +SCODE STDMETHODCALLTYPE COooFilter::Init( + ULONG grfFlags, + ULONG cAttributes, + FULLPROPSPEC const * aAttributes, + ULONG * pFlags) +{ + // Enumerate OLE properties, since any NTFS file can have them + *pFlags = IFILTER_FLAGS_OLE_PROPERTIES; + try + { + m_fContents = false; + m_ulPropertyNum = 0; + m_ulCurrentPropertyNum = 0; + if ( m_cAttributes > 0 ) + { + delete[] m_pAttributes; + m_pAttributes = nullptr; + m_cAttributes = 0; + } + if( 0 < cAttributes ) + { + // Filter properties specified in aAttributes + if ( nullptr == aAttributes ) + return E_INVALIDARG; + m_pAttributes = new CFullPropSpec[cAttributes]; + m_cAttributes = cAttributes; + // Is caller want to filter contents? + CFullPropSpec const *pAttrib = reinterpret_cast<CFullPropSpec const *>(aAttributes); + ULONG ulNumAttr; + for ( ulNumAttr = 0 ; ulNumAttr < cAttributes; ulNumAttr++ ) + { + if ( pAttrib[ulNumAttr].IsPropertyPropid() && + pAttrib[ulNumAttr].GetPropertyPropid() == PID_STG_CONTENTS && + pAttrib[ulNumAttr].GetPropSet() == guidStorage ) + { + m_fContents = true; + } + // save the requested properties. + m_pAttributes[ulNumAttr] = pAttrib[ulNumAttr]; + } + } + else if ( grfFlags & IFILTER_INIT_APPLY_INDEX_ATTRIBUTES ) + { + // Filter contents and all pseudo-properties + m_fContents = true; + + m_pAttributes = new CFullPropSpec[COUNT_ATTRIBUTES]; + m_cAttributes = COUNT_ATTRIBUTES; + m_pAttributes[0].SetPropSet( FMTID_SummaryInformation ); + m_pAttributes[0].SetProperty( PIDSI_AUTHOR ); + m_pAttributes[1].SetPropSet( FMTID_SummaryInformation ); + m_pAttributes[1].SetProperty( PIDSI_TITLE ); + m_pAttributes[2].SetPropSet( FMTID_SummaryInformation ); + m_pAttributes[2].SetProperty( PIDSI_SUBJECT ); + m_pAttributes[3].SetPropSet( FMTID_SummaryInformation ); + m_pAttributes[3].SetProperty( PIDSI_KEYWORDS ); + m_pAttributes[4].SetPropSet( FMTID_SummaryInformation ); + m_pAttributes[4].SetProperty( PIDSI_COMMENTS ); + } + else if ( 0 == grfFlags ) + { + // Filter only contents + m_fContents = true; + } + else + m_fContents = false; + // Re-initialize + if ( m_fContents ) + { + m_fEof = false; + m_eState = FilterState::FilteringContent; + m_ulUnicodeCharsRead = 0; + m_ChunkPosition = 0; + } + else + { + m_fEof = true; + m_eState = FilterState::FilteringProperty; + } + m_ulChunkID = 1; + } + catch (const std::exception&) + { + return E_FAIL; + } + + return S_OK; +} +//M------------------------------------------------------------------------- +// Method: COooFilter::GetChunk (IFilter::GetChunk) +// Summary: Gets the next chunk +// Arguments: ppStat +// [out] Pointer to description of current chunk +// Returns: S_OK +// Chunk was successfully retrieved +// E_FAIL +// Character conversion failed +// FILTER_E_ACCESS +// General access failure occurred +// FILTER_E_END_OF_CHUNKS +// Previous chunk was the last chunk +// FILTER_E_EMBEDDING_UNAVAILABLE +// (not implemented) +// FILTER_E_LINK_UNAVAILABLE +// (not implemented) +// FILTER_E_PASSWORD +// (not implemented) + +SCODE STDMETHODCALLTYPE COooFilter::GetChunk(STAT_CHUNK * pStat) +{ + for(;;) + { + switch ( m_eState ) + { + case FilterState::FilteringContent: + { + if( m_ChunkPosition == m_pContentReader ->getChunkBuffer().size() ) + { + m_ulUnicodeBufferLen=0; + m_fEof = true; + } + + if ( !m_fContents || m_fEof ) + { + m_eState = FilterState::FilteringProperty; + continue; + } + m_pwsBuffer = m_pContentReader -> getChunkBuffer()[m_ChunkPosition].second; + m_ulUnicodeBufferLen = static_cast<ULONG>(m_pwsBuffer.length()); + DWORD ChunkLCID = LocaleSetToLCID( m_pContentReader -> getChunkBuffer()[m_ChunkPosition].first ); + // Set chunk description + pStat->idChunk = m_ulChunkID; + pStat->breakType = CHUNK_NO_BREAK; + pStat->flags = CHUNK_TEXT; + pStat->locale = ChunkLCID; + pStat->attribute.guidPropSet = guidStorage; + pStat->attribute.psProperty.ulKind = PRSPEC_PROPID; + pStat->attribute.psProperty.propid = PID_STG_CONTENTS; + pStat->idChunkSource = m_ulChunkID; + pStat->cwcStartSource = 0; + pStat->cwcLenSource = 0; + m_ulUnicodeCharsRead = 0; + m_ulChunkID++; + m_ChunkPosition++; + return S_OK; + } + case FilterState::FilteringProperty: + { + if ( m_cAttributes == 0 ) + return FILTER_E_END_OF_CHUNKS; + while( !( ( m_pAttributes[m_ulPropertyNum].IsPropertyPropid() ) && + ( m_pAttributes[m_ulPropertyNum].GetPropSet() == FMTID_SummaryInformation ) )|| + ( ( m_pAttributes[m_ulPropertyNum].GetPropertyPropid() != PIDSI_AUTHOR ) && + ( m_pAttributes[m_ulPropertyNum].GetPropertyPropid() != PIDSI_TITLE ) && + ( m_pAttributes[m_ulPropertyNum].GetPropertyPropid() != PIDSI_SUBJECT ) && + ( m_pAttributes[m_ulPropertyNum].GetPropertyPropid() != PIDSI_KEYWORDS ) && + ( m_pAttributes[m_ulPropertyNum].GetPropertyPropid() != PIDSI_COMMENTS ) ) ) + { + if ( m_ulPropertyNum < m_cAttributes ) + m_ulPropertyNum++; + else + break; + } + if ( m_ulPropertyNum == m_cAttributes) + return FILTER_E_END_OF_CHUNKS; + else + { + // Set chunk description + pStat->idChunk = m_ulChunkID; + pStat->breakType = CHUNK_EOS; + pStat->flags = CHUNK_VALUE; + pStat->locale = GetSystemDefaultLCID(); + pStat->attribute.guidPropSet = FMTID_SummaryInformation; + pStat->attribute.psProperty.ulKind = PRSPEC_PROPID; + pStat->attribute.psProperty.propid = m_pAttributes[m_ulPropertyNum].GetPropertyPropid(); + pStat->idChunkSource = m_ulChunkID; + pStat->cwcStartSource = 0; + pStat->cwcLenSource = 0; + m_ulCurrentPropertyNum = m_ulPropertyNum; + m_ulPropertyNum++; + m_ulChunkID++; + return S_OK; + } + } + }//switch(...) + }//for(;;) +} +//M------------------------------------------------------------------------- +// Method: COooFilter::GetText (IFilter::GetText) +// Summary: Retrieves UNICODE text for index +// Arguments: pcwcBuffer +// [in] Pointer to size of UNICODE buffer +// [out] Pointer to count of UNICODE characters returned +// awcBuffer +// [out] Pointer to buffer to receive UNICODE text +// Returns: S_OK +// Text successfully retrieved, but text remains in chunk +// FILTER_E_NO_MORE_TEXT +// All of the text in the current chunk has been returned +// FILTER_S_LAST_TEXT +// Next call to GetText will return FILTER_E_NO_MORE_TEXT + +SCODE STDMETHODCALLTYPE COooFilter::GetText(ULONG * pcwcBuffer, WCHAR * awcBuffer) +{ + switch ( m_eState ) + { + case FilterState::FilteringProperty: + return FILTER_E_NO_TEXT; + case FilterState::FilteringContent: + { + if ( !m_fContents || 0 == m_ulUnicodeBufferLen ) + { + *pcwcBuffer = 0; + return FILTER_E_NO_MORE_TEXT; + } + // Copy UNICODE characters in chunk buffer to output UNICODE buffer + ULONG ulToCopy = min( *pcwcBuffer, m_ulUnicodeBufferLen - m_ulUnicodeCharsRead ); + wmemcpy( awcBuffer, m_pwsBuffer.c_str() + m_ulUnicodeCharsRead, ulToCopy ); + ZeroMemory( + awcBuffer + ulToCopy, (*pcwcBuffer - ulToCopy) * sizeof (WCHAR)); + m_ulUnicodeCharsRead += ulToCopy; + *pcwcBuffer = ulToCopy; + if ( m_ulUnicodeBufferLen == m_ulUnicodeCharsRead ) + { + m_ulUnicodeCharsRead = 0; + m_ulUnicodeBufferLen = 0; + return FILTER_S_LAST_TEXT; + } + return S_OK; + } + } + return E_FAIL; // Should not happen! +} +//M------------------------------------------------------------------------- +// Method: GetMetaInfoNameFromPropertyId +// Summary: helper function to convert PropertyID into respective +// MetaInfo names. +// Arguments: ulPropID +// [in] property ID +// Returns: corresponding metainfo names. + + +static ::std::wstring GetMetaInfoNameFromPropertyId( ULONG ulPropID ) +{ + switch ( ulPropID ) + { + case PIDSI_AUTHOR: return META_INFO_AUTHOR; + case PIDSI_TITLE: return META_INFO_TITLE; + case PIDSI_SUBJECT: return META_INFO_SUBJECT; + case PIDSI_KEYWORDS: return META_INFO_KEYWORDS; + case PIDSI_COMMENTS: return META_INFO_DESCRIPTION; + default: return EMPTY_STRING; + } +} +//M------------------------------------------------------------------------- +// Method: COooFilter::GetValue (IFilter::GetValue) +// Summary: Retrieves properties for index +// Arguments: ppPropValue +// [out] Address that receives pointer to property value +// Returns: FILTER_E_NO_VALUES +// Always +// FILTER_E_NO_MORE_VALUES +// (not implemented) + + +SCODE STDMETHODCALLTYPE COooFilter::GetValue(PROPVARIANT ** ppPropValue) +{ + if (m_eState == FilterState::FilteringContent) + return FILTER_E_NO_VALUES; + else // m_eState == FilteringProperty + { + if ( m_cAttributes == 0 || ( m_ulCurrentPropertyNum == m_ulPropertyNum ) ) + return FILTER_E_NO_MORE_VALUES; + PROPVARIANT *pPropVar = static_cast<PROPVARIANT *>(CoTaskMemAlloc( sizeof (PROPVARIANT) )); + if ( pPropVar == nullptr ) + return E_OUTOFMEMORY; + ::std::wstring wsTagName= GetMetaInfoNameFromPropertyId( m_pAttributes[m_ulCurrentPropertyNum].GetPropertyPropid() ); + if ( wsTagName == EMPTY_STRING ) + return FILTER_E_NO_VALUES; + ::std::wstring wsTagData = m_pMetaInfoReader->getTagData(wsTagName); + pPropVar->vt = VT_LPWSTR; + size_t cw = wsTagData.length() + 1; // reserve one for the '\0' + pPropVar->pwszVal = static_cast<WCHAR*>( CoTaskMemAlloc(cw*sizeof(WCHAR)) ); + if (pPropVar->pwszVal == nullptr) + { + CoTaskMemFree(pPropVar); + return E_OUTOFMEMORY; + } + wmemcpy(pPropVar->pwszVal, wsTagData.c_str(), cw); + *ppPropValue = pPropVar; + m_ulCurrentPropertyNum = m_ulPropertyNum; + return S_OK; + } +} +//M------------------------------------------------------------------------- +// Method: COooFilter::BindRegion (IFilter::BindRegion) +// Summary: Creates moniker or other interface for indicated text +// Arguments: origPos +// [in] Description of text location and extent +// riid +// [in] Reference IID of specified interface +// ppunk +// [out] Address that receives requested interface pointer +// Returns: E_NOTIMPL +// Always +// FILTER_W_REGION_CLIPPED +// (not implemented) + + +SCODE STDMETHODCALLTYPE COooFilter::BindRegion( + FILTERREGION /*origPos*/, + REFIID /*riid*/, + void ** /*ppunk*/) +{ + // BindRegion is currently reserved for future use + return E_NOTIMPL; +} +//M------------------------------------------------------------------------- +// Method: COooFilter::GetClassID (IPersist::GetClassID) +// Summary: Retrieves the class id of the filter class +// Arguments: pClassID +// [out] Pointer to the class ID of the filter +// Returns: S_OK +// Always +// E_FAIL +// (not implemented) + +HRESULT STDMETHODCALLTYPE COooFilter::GetClassID(CLSID * pClassID) +{ + *pClassID = CLSID_COooFilter; + return S_OK; +} +//M------------------------------------------------------------------------- +// Method: COooFilter::IsDirty (IPersistFile::IsDirty) +// Summary: Checks whether file has changed since last save +// Arguments: void +// Returns: S_FALSE +// Always +// S_OK +// (not implemented) + +HRESULT STDMETHODCALLTYPE COooFilter::IsDirty() +{ + // File is opened read-only and never changes + return S_FALSE; +} +//M------------------------------------------------------------------------- +// Method: COooFilter::Load (IPersistFile::Load) +// Summary: Opens and initializes the specified file +// Arguments: pszFileName +// [in] Pointer to zero-terminated string +// of absolute path of file to open +// dwMode +// [in] Access mode to open the file +// Returns: S_OK +// File was successfully loaded +// E_OUTOFMEMORY +// File could not be loaded due to insufficient memory +// E_FAIL +// (not implemented) + +HRESULT STDMETHODCALLTYPE COooFilter::Load(LPCOLESTR pszFileName, DWORD /*dwMode*/) +{ + // Load just sets the filename for GetChunk to read and ignores the mode + m_pwszFileName = getShortPathName( pszFileName ); + + // Open the file previously specified in call to IPersistFile::Load and get content. + try + { + delete m_pMetaInfoReader; + m_pMetaInfoReader = new CMetaInfoReader(m_pwszFileName); + + delete m_pContentReader; + m_pContentReader = new CContentReader(m_pwszFileName, m_pMetaInfoReader->getDefaultLocale()); + } + catch (const std::exception&) + { + return E_FAIL; + } + return S_OK; +} +//M------------------------------------------------------------------------- +// Method: COooFilter::Save (IPersistFile::Save) +// Summary: Saves a copy of the current file being filtered +// Arguments: pszFileName +// [in] Pointer to zero-terminated string of +// absolute path of where to save file +// fRemember +// [in] Whether the saved copy is made the current file +// Returns: E_FAIL +// Always +// S_OK +// (not implemented) + +HRESULT STDMETHODCALLTYPE COooFilter::Save(LPCOLESTR /*pszFileName*/, BOOL /*fRemember*/) +{ + // File is opened read-only; saving it is an error + return E_FAIL; +} +//M------------------------------------------------------------------------- +// Method: COooFilter::SaveCompleted (IPersistFile::SaveCompleted) +// Summary: Determines whether a file save is completed +// Arguments: pszFileName +// [in] Pointer to zero-terminated string of +// absolute path where file was previously saved +// Returns: S_OK +// Always + +HRESULT STDMETHODCALLTYPE COooFilter::SaveCompleted(LPCOLESTR /*pszFileName*/) +{ + // File is opened read-only, so "save" is always finished + return S_OK; +} + +//M------------------------------------------------------------------------- +// Method: COooFilter::Load (IPersistStream::Load) +// Summary: Initializes an object from the stream where it was previously saved +// Arguments: pStm +// [in] Pointer to stream from which object should be loaded +// Returns: S_OK +// E_OUTOFMEMORY +// E_FAIL + +HRESULT STDMETHODCALLTYPE COooFilter::Load(IStream *pStm) +{ + m_pStream = new BufferStream(pStm); + try + { + delete m_pMetaInfoReader; + m_pMetaInfoReader = new CMetaInfoReader(m_pStream); + + delete m_pContentReader; + m_pContentReader = new CContentReader(m_pStream, m_pMetaInfoReader->getDefaultLocale()); + } + catch (const std::exception&) + { + return E_FAIL; + } + return S_OK; +} + +//M------------------------------------------------------------------------- +// Method: COooFilter::GetSizeMax (IPersistStream::GetSizeMax) +// Summary: Returns the size in bytes of the stream needed to save the object. +// Arguments: pcbSize +// [out] Pointer to a 64 bit unsigned int indicating the size needed +// Returns: E_NOTIMPL + +HRESULT STDMETHODCALLTYPE COooFilter::GetSizeMax(ULARGE_INTEGER * /*pcbSize*/) +{ + return E_NOTIMPL; +} + +//M------------------------------------------------------------------------- +// Method: COooFilter::Save (IPersistStream::Save) +// Summary: Save object to specified stream +// Arguments: pStm +// [in] Pointer to stream +// fClearDirty +// [in] Indicates whether to clear dirty flag +// Returns: E_NOTIMPL + +HRESULT STDMETHODCALLTYPE COooFilter::Save(IStream * /*pStm*/, BOOL ) +{ + return E_NOTIMPL; +} + +//M------------------------------------------------------------------------- +// Method: COooFilter::GetCurFile (IPersistFile::GetCurFile) +// Summary: Returns a copy of the current file name +// Arguments: ppszFileName +// [out] Address to receive pointer to zero-terminated +// string for absolute path to current file +// Returns: S_OK +// A valid absolute path was successfully returned +// S_FALSE +// (not implemented) +// E_OUTOFMEMORY +// Operation failed due to insufficient memory +// E_FAIL +// Operation failed due to some reason +// other than insufficient memory + +HRESULT STDMETHODCALLTYPE COooFilter::GetCurFile(LPOLESTR * ppszFileName) +{ + if ( EMPTY_STRING == m_pwszFileName ) + return E_FAIL; + else + *ppszFileName = const_cast<LPWSTR>(m_pwszFileName.c_str()); + return S_OK; +} + +//M------------------------------------------------------------------------- +// Method: COooFilterCF::COooFilterCF +// Summary: Class factory constructor +// Arguments: void +// Purpose: Manages global instance count + +COooFilterCF::COooFilterCF() : + m_lRefs(1) +{ + InterlockedIncrement( &g_lInstances ); +} +//M------------------------------------------------------------------------- +// Method: COooFilterCF::~COooFilterCF +// Summary: Class factory destructor +// Arguments: void +// Purpose: Manages global instance count + +COooFilterCF::~COooFilterCF() +{ + InterlockedDecrement( &g_lInstances ); +} +//M------------------------------------------------------------------------- +// Method: COooFilterCF::QueryInterface (IUnknown::QueryInterface) +// Summary: Queries for requested interface +// Arguments: riid +// [in] Reference IID of requested interface +// ppvObject +// [out] Address that receives requested interface pointer +// Returns: S_OK +// Interface is supported +// E_NOINTERFACE +// Interface is not supported + +HRESULT STDMETHODCALLTYPE COooFilterCF::QueryInterface(REFIID riid, void ** ppvObject) +{ + IUnknown *pUnkTemp; + + if ( IID_IClassFactory == riid ) + pUnkTemp = this; + else if ( IID_IUnknown == riid ) + pUnkTemp = this; + else + { + *ppvObject = nullptr; + return E_NOINTERFACE; + } + *ppvObject = pUnkTemp; + pUnkTemp->AddRef(); + return S_OK; +} +//M------------------------------------------------------------------------- +// Method: COooFilterCF::AddRef (IUnknown::AddRef) +// Summary: Increments interface refcount +// Arguments: void +// Returns: Value of incremented interface refcount + +ULONG STDMETHODCALLTYPE COooFilterCF::AddRef() +{ + return InterlockedIncrement( &m_lRefs ); +} +//M------------------------------------------------------------------------- +// Method: COooFilterCF::Release (IUnknown::Release) +// Summary: Decrements interface refcount, deleting if unreferenced +// Arguments: void +// Returns: Value of decremented refcount + +ULONG STDMETHODCALLTYPE COooFilterCF::Release() +{ + ULONG ulTmp = InterlockedDecrement( &m_lRefs ); + + if ( 0 == ulTmp ) + delete this; + return ulTmp; +} +//M------------------------------------------------------------------------- +// Method: COooFilterCF::CreateInstance (IClassFactory::CreateInstance) +// Summary: Creates new LibreOffice filter object +// Arguments: pUnkOuter +// [in] Pointer to IUnknown interface of aggregating object +// riid +// [in] Reference IID of requested interface +// ppvObject +// [out] Address that receives requested interface pointer +// Returns: S_OK +// LibreOffice filter object was successfully created +// CLASS_E_NOAGGREGATION +// pUnkOuter parameter was non-NULL +// E_NOINTERFACE +// (not implemented) +// E_OUTOFMEMORY +// LibreOffice filter object could not be created +// due to insufficient memory +// E_UNEXPECTED +// Unsuccessful due to an unexpected condition + +HRESULT STDMETHODCALLTYPE COooFilterCF::CreateInstance( + IUnknown * pUnkOuter, + REFIID riid, + void * * ppvObject) +{ + COooFilter *pIUnk = nullptr; + if ( nullptr != pUnkOuter ) + return CLASS_E_NOAGGREGATION; + pIUnk = new COooFilter(); + if ( SUCCEEDED( pIUnk->QueryInterface( riid , ppvObject ) ) ) + { + // Release extra refcount from QueryInterface + pIUnk->Release(); + } + else + { + delete pIUnk; + return E_UNEXPECTED; + } + return S_OK; +} + +//M------------------------------------------------------------------------- +// Method: COooFilterCF::LockServer (IClassFactory::LockServer) +// Summary: Forces/allows filter class to remain loaded/be unloaded +// Arguments: fLock +// [in] TRUE to lock, FALSE to unlock +// Returns: S_OK +// Always +// E_FAIL +// (not implemented) +// E_OUTOFMEMORY +// (not implemented) +// E_UNEXPECTED +// (not implemented) + +HRESULT STDMETHODCALLTYPE COooFilterCF::LockServer(BOOL fLock) +{ + if( fLock ) + InterlockedIncrement( &g_lInstances ); + else + InterlockedDecrement( &g_lInstances ); + return S_OK; +} +//+------------------------------------------------------------------------- +// DLL: ooofilt.dll +// Summary: Implements Dynamic Link Library functions for LibreOffice filter + +//F------------------------------------------------------------------------- +// Function: DllMain +// Summary: Called from C-Runtime on process/thread attach/detach +// Arguments: hInstance +// [in] Handle to the DLL +// fdwReason +// [in] Reason for calling DLL entry point +// lpReserve +// [in] Details of DLL initialization and cleanup +// Returns: TRUE +// Always + +extern "C" BOOL WINAPI DllMain( + HINSTANCE hInstance, + DWORD fdwReason, + LPVOID /*lpvReserved*/ +) +{ + if ( DLL_PROCESS_ATTACH == fdwReason ) + DisableThreadLibraryCalls( hInstance ); + return TRUE; +} +//F------------------------------------------------------------------------- +// Function: DllGetClassObject +// Summary: Create LibreOffice filter class factory object +// Arguments: cid +// [in] Class ID of class that class factory creates +// iid +// [in] Reference IID of requested class factory interface +// ppvObj +// [out] Address that receives requested interface pointer +// Returns: S_OK +// Class factory object was created successfully +// CLASS_E_CLASSNOTAVAILABLE +// DLL does not support the requested class +// E_INVALIDARG +// (not implemented +// E_OUTOFMEMORY +// Insufficient memory to create the class factory object +// E_UNEXPECTED +// Unsuccessful due to an unexpected condition + +extern "C" HRESULT STDMETHODCALLTYPE DllGetClassObject( + REFCLSID cid, + REFIID iid, + LPVOID * ppvObj +) +{ + COooFilterCF* pImpl = nullptr; + IUnknown *pResult = nullptr; + + if ( CLSID_COooFilter == cid ) + { + pImpl = new COooFilterCF; + pResult = pImpl; + } + else + return CLASS_E_CLASSNOTAVAILABLE; + if( SUCCEEDED( pResult->QueryInterface( iid, ppvObj ) ) ) + // Release extra refcount from QueryInterface + pResult->Release(); + else + { + delete pImpl; + return E_UNEXPECTED; + } + return S_OK; +} +//F------------------------------------------------------------------------- +// Function: DllCanUnloadNow +// Summary: Indicates whether it is possible to unload DLL +// Arguments: void +// Returns: S_OK +// DLL can be unloaded now +// S_FALSE +// DLL must remain loaded + +extern "C" HRESULT STDMETHODCALLTYPE DllCanUnloadNow() +{ + if ( 0 >= g_lInstances ) + return S_OK; + else + return S_FALSE; +} +//F------------------------------------------------------------------------- +// Function: DllRegisterServer +// DllUnregisterServer +// Summary: Registers and unregisters DLL server +// Returns: DllRegisterServer +// S_OK +// Registration was successful +// SELFREG_E_CLASS +// Registration was unsuccessful +// SELFREG_E_TYPELIB +// (not implemented) +// E_OUTOFMEMORY +// (not implemented) +// E_UNEXPECTED +// (not implemented) +// DllUnregisterServer +// S_OK +// Unregistration was successful +// S_FALSE +// Unregistration was successful, but other +// entries still exist for the DLL's classes +// SELFREG_E_CLASS +// (not implemented) +// SELFREG_E_TYPELIB +// (not implemented) +// E_OUTOFMEMORY +// (not implemented) +// E_UNEXPECTED +// (not implemented) + +STDAPI DllRegisterServer() +{ + return S_OK; +} + + +STDAPI DllUnregisterServer() +{ + return S_OK; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |