1109 lines
31 KiB
C++
1109 lines
31 KiB
C++
//+-------------------------------------------------------------------------
|
|
//
|
|
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
|
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
|
// PARTICULAR PURPOSE.
|
|
//
|
|
// Copyright (c) 1998-1999 Microsoft Corporation. All Rights Reserved.
|
|
//
|
|
// File: smpfilt.cxx
|
|
//
|
|
// Contents: Sample filter Implementation for Indexing Service
|
|
//
|
|
// Summary: The sample filter reads unformated text files (with the
|
|
// extension .smp) using the current thread's ANSI code page
|
|
// and outputs UNICODE text for the current locale.
|
|
//
|
|
// It accepts as input only single-byte-character text files,
|
|
// and not multibyte-character or UNICODE text files.
|
|
//
|
|
// Platform: Windows 2000
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Include file Purpose
|
|
//
|
|
// windows.h Win32 declarations
|
|
// filter.h IFilter interface declarations
|
|
// filterr.h FACILITY_ITF error definitions for IFilter
|
|
// ntquery.h Indexing Service declarations
|
|
// filtreg.hxx DLL registration and unregistration macros
|
|
// smpfilt.hxx Sample filter declarations
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include <windows.h>
|
|
#include <filter.h>
|
|
#include <filterr.h>
|
|
#include <ntquery.h>
|
|
#include "filtreg.hxx"
|
|
#include "smpfilt.hxx"
|
|
|
|
//F-------------------------------------------------------------------------
|
|
//
|
|
// Function: GetDefaultCodepage
|
|
//
|
|
// Summary: Returns the codepage associated with the current default
|
|
// locale, or CP_ACP if one can't be found.
|
|
//
|
|
// Returns: Codepage
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
ULONG GetDefaultCodepage()
|
|
{
|
|
ULONG codepage;
|
|
|
|
int cwc = GetLocaleInfo( GetSystemDefaultLCID(),
|
|
LOCALE_RETURN_NUMBER |
|
|
LOCALE_IDEFAULTANSICODEPAGE,
|
|
(WCHAR *) &codepage,
|
|
sizeof ULONG / sizeof WCHAR );
|
|
|
|
// If an error occurred, return the Ansi code page
|
|
|
|
if ( 0 == cwc )
|
|
return CP_ACP;
|
|
|
|
return codepage;
|
|
}
|
|
|
|
//C-------------------------------------------------------------------------
|
|
//
|
|
// Class: CSmpFilter
|
|
//
|
|
// Summary: Implements sample filter class
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
//M-------------------------------------------------------------------------
|
|
//
|
|
// Method: CSmpFilter::CSmpFilter
|
|
//
|
|
// Summary: Class constructor
|
|
//
|
|
// Arguments: void
|
|
//
|
|
// Purpose: Manages global instance count
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
CSmpFilter::CSmpFilter() :
|
|
m_hFile(INVALID_HANDLE_VALUE),
|
|
m_lRefs(1),
|
|
m_pwszFileName(0),
|
|
m_ulBufferLen(0),
|
|
m_ulCharsRead(0),
|
|
m_ulChunkID(1),
|
|
m_fContents(FALSE),
|
|
m_fEof(FALSE),
|
|
m_ulCodePage( GetDefaultCodepage() )
|
|
{
|
|
InterlockedIncrement( &g_lInstances );
|
|
}
|
|
|
|
//M-------------------------------------------------------------------------
|
|
//
|
|
// Method: CSmpFilter::~CSmpFilter
|
|
//
|
|
// Summary: Class destructor
|
|
//
|
|
// Arguments: void
|
|
//
|
|
// Purpose: Manages global instance count and file handle
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
CSmpFilter::~CSmpFilter()
|
|
{
|
|
delete [] m_pwszFileName;
|
|
if ( INVALID_HANDLE_VALUE != m_hFile )
|
|
CloseHandle( m_hFile );
|
|
|
|
InterlockedDecrement( &g_lInstances );
|
|
}
|
|
|
|
//M-------------------------------------------------------------------------
|
|
//
|
|
// Method: CSmpFilter::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
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
SCODE STDMETHODCALLTYPE CSmpFilter::QueryInterface(
|
|
REFIID riid,
|
|
void ** ppvObject
|
|
)
|
|
{
|
|
IUnknown *pUnkTemp = 0;
|
|
|
|
if ( IID_IFilter == riid )
|
|
pUnkTemp = (IUnknown *)(IFilter *)this;
|
|
else if ( IID_IPersistFile == riid )
|
|
pUnkTemp = (IUnknown *)(IPersistFile *)this;
|
|
else if ( IID_IPersist == riid )
|
|
pUnkTemp = (IUnknown *)(IPersist *)(IPersistFile *)this;
|
|
else if ( IID_IUnknown == riid )
|
|
pUnkTemp = (IUnknown *)(IPersist *)(IPersistFile *)this;
|
|
else
|
|
{
|
|
*ppvObject = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
*ppvObject = (void *)pUnkTemp;
|
|
pUnkTemp->AddRef();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//M-------------------------------------------------------------------------
|
|
//
|
|
// Method: CSmpFilter::AddRef (IUnknown::AddRef)
|
|
//
|
|
// Summary: Increments interface refcount
|
|
//
|
|
// Arguments: void
|
|
//
|
|
// Returns: Value of incremented interface refcount
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
ULONG STDMETHODCALLTYPE CSmpFilter::AddRef()
|
|
{
|
|
return InterlockedIncrement( &m_lRefs );
|
|
}
|
|
|
|
//M-------------------------------------------------------------------------
|
|
//
|
|
// Method: CSmpFilter::Release (IUnknown::Release)
|
|
//
|
|
// Summary: Decrements interface refcount, deleting if unreferenced
|
|
//
|
|
// Arguments: void
|
|
//
|
|
// Returns: Value of decremented interface refcount
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
ULONG STDMETHODCALLTYPE CSmpFilter::Release()
|
|
{
|
|
ULONG ulTmp = InterlockedDecrement( &m_lRefs );
|
|
|
|
if ( 0 == ulTmp )
|
|
delete this;
|
|
|
|
return ulTmp;
|
|
}
|
|
|
|
//M-------------------------------------------------------------------------
|
|
//
|
|
// Method: CSmpFilter::Init (IFilter::Init)
|
|
//
|
|
// Summary: Initializes sample 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)
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
SCODE STDMETHODCALLTYPE CSmpFilter::Init(
|
|
ULONG grfFlags,
|
|
ULONG cAttributes,
|
|
FULLPROPSPEC const * aAttributes,
|
|
ULONG * pFlags
|
|
)
|
|
{
|
|
// Ignore flags for text canonicalization (text is unformatted)
|
|
// Check for proper attributes request and recognize only "contents"
|
|
|
|
if( 0 < cAttributes )
|
|
{
|
|
ULONG ulNumAttr;
|
|
|
|
if ( 0 == aAttributes )
|
|
return E_INVALIDARG;
|
|
|
|
for ( ulNumAttr = 0 ; ulNumAttr < cAttributes; ulNumAttr++ )
|
|
{
|
|
if ( guidStorage == aAttributes[ulNumAttr].guidPropSet &&
|
|
PID_STG_CONTENTS == aAttributes[ulNumAttr].psProperty.propid )
|
|
break;
|
|
}
|
|
|
|
if ( ulNumAttr < cAttributes )
|
|
m_fContents = TRUE;
|
|
else
|
|
m_fContents = FALSE;
|
|
}
|
|
else if ( 0 == grfFlags ||
|
|
(grfFlags & IFILTER_INIT_APPLY_INDEX_ATTRIBUTES) )
|
|
m_fContents = TRUE;
|
|
else
|
|
m_fContents = FALSE;
|
|
|
|
m_fEof = FALSE;
|
|
|
|
// Open the file previously specified in call to IPersistFile::Load
|
|
|
|
if ( 0 != m_pwszFileName )
|
|
{
|
|
if ( INVALID_HANDLE_VALUE != m_hFile )
|
|
{
|
|
CloseHandle( m_hFile );
|
|
m_hFile = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
m_hFile = CreateFile(
|
|
m_pwszFileName,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ | FILE_SHARE_DELETE,
|
|
0,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
0
|
|
);
|
|
|
|
if ( INVALID_HANDLE_VALUE == m_hFile )
|
|
return FILTER_E_ACCESS;
|
|
}
|
|
else
|
|
return E_FAIL;
|
|
|
|
// Enumerate OLE properties, since any NTFS file can have them
|
|
|
|
*pFlags = IFILTER_FLAGS_OLE_PROPERTIES;
|
|
|
|
// Re-initialize
|
|
|
|
m_ulChunkID = 1;
|
|
m_ulCharsRead = 0;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//M-------------------------------------------------------------------------
|
|
//
|
|
// Method: CSmpFilter::GetChunk (IFilter::GetChunk)
|
|
//
|
|
// Summary: Gets the next chunk (text only)
|
|
//
|
|
// Note: GetChunk accepts as input only single-byte-character text
|
|
// files, and not multibyte-character or UNICODE text files.
|
|
//
|
|
// 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 CSmpFilter::GetChunk(
|
|
STAT_CHUNK * pStat
|
|
)
|
|
{
|
|
if ( INVALID_HANDLE_VALUE == m_hFile )
|
|
return FILTER_E_ACCESS;
|
|
|
|
// Read characters from single-byte file
|
|
|
|
char cszBuffer[TEXT_FILTER_CHUNK_SIZE];
|
|
|
|
if ( !ReadFile(
|
|
m_hFile,
|
|
cszBuffer,
|
|
TEXT_FILTER_CHUNK_SIZE,
|
|
&m_ulBufferLen,
|
|
NULL
|
|
) )
|
|
return FILTER_E_ACCESS;
|
|
else if( 0 == m_ulBufferLen )
|
|
m_fEof = TRUE;
|
|
|
|
if ( !m_fContents || m_fEof )
|
|
return FILTER_E_END_OF_CHUNKS;
|
|
|
|
// Convert single-byte characters to UNICODE
|
|
//
|
|
// This conversion assumes a one-to-one conversion:
|
|
// one input single-byte character to
|
|
// one output multibyte (UNICODE) character
|
|
//
|
|
// This is typically not the general case with multibyte
|
|
// characters, and a general case needs to handle the possible
|
|
// difference of pre- and post-conversion buffer lengths
|
|
|
|
if ( !MultiByteToWideChar(
|
|
m_ulCodePage,
|
|
MB_COMPOSITE,
|
|
cszBuffer,
|
|
m_ulBufferLen,
|
|
m_wcsBuffer,
|
|
TEXT_FILTER_CHUNK_SIZE
|
|
) )
|
|
return E_FAIL;
|
|
|
|
// Set chunk description
|
|
|
|
pStat->idChunk = m_ulChunkID;
|
|
pStat->breakType = CHUNK_NO_BREAK;
|
|
pStat->flags = CHUNK_TEXT;
|
|
pStat->locale = GetSystemDefaultLCID();
|
|
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_ulCharsRead = 0;
|
|
m_ulChunkID++;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//M-------------------------------------------------------------------------
|
|
//
|
|
// Method: CSmpFilter::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 CSmpFilter::GetText(
|
|
ULONG * pcwcBuffer,
|
|
WCHAR * awcBuffer
|
|
)
|
|
{
|
|
if ( !m_fContents || 0 == m_ulBufferLen )
|
|
{
|
|
*pcwcBuffer = 0;
|
|
return FILTER_E_NO_MORE_TEXT;
|
|
}
|
|
|
|
// Copy characters in chunk buffer to output UNICODE buffer
|
|
//
|
|
// This copy assumes a one-to-one conversion in GetChunk
|
|
// of input single-byte characters (each 1 byte long)
|
|
// to output UNICODE characters (each 2 bytes long)
|
|
|
|
ULONG ulToCopy = min( *pcwcBuffer, m_ulBufferLen - m_ulCharsRead );
|
|
|
|
memcpy( awcBuffer, m_wcsBuffer + m_ulCharsRead, 2*ulToCopy );
|
|
m_ulCharsRead += ulToCopy;
|
|
*pcwcBuffer = ulToCopy;
|
|
|
|
if ( m_ulBufferLen == m_ulCharsRead )
|
|
{
|
|
m_ulCharsRead = 0;
|
|
m_ulBufferLen = 0;
|
|
return FILTER_S_LAST_TEXT;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//M-------------------------------------------------------------------------
|
|
//
|
|
// Method: CSmpFilter::GetValue (IFilter::GetValue)
|
|
//
|
|
// Summary: Retrieves properites 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 CSmpFilter::GetValue(
|
|
PROPVARIANT ** ppPropValue
|
|
)
|
|
{
|
|
// Sample filter does not retieve any properties
|
|
|
|
return FILTER_E_NO_VALUES;
|
|
}
|
|
|
|
//M-------------------------------------------------------------------------
|
|
//
|
|
// Method: CSmpFilter::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 CSmpFilter::BindRegion(
|
|
FILTERREGION origPos,
|
|
REFIID riid,
|
|
void ** ppunk
|
|
)
|
|
{
|
|
// BindRegion is currently reserved for future use
|
|
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//M-------------------------------------------------------------------------
|
|
//
|
|
// Method: CSmpFilter::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)
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
SCODE STDMETHODCALLTYPE CSmpFilter::GetClassID(
|
|
CLSID * pClassID
|
|
)
|
|
{
|
|
*pClassID = CLSID_CSmpFilter;
|
|
return S_OK;
|
|
}
|
|
|
|
//M-------------------------------------------------------------------------
|
|
//
|
|
// Method: CSmpFilter::IsDirty (IPersistFile::IsDirty)
|
|
//
|
|
// Summary: Checks whether file has changed since last save
|
|
//
|
|
// Arguments: void
|
|
//
|
|
// Returns: S_FALSE
|
|
// Always
|
|
// S_OK
|
|
// (not implemented)
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
SCODE STDMETHODCALLTYPE CSmpFilter::IsDirty()
|
|
{
|
|
// File is opened read-only and never changes
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
//M-------------------------------------------------------------------------
|
|
//
|
|
// Method: CSmpFilter::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)
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
SCODE STDMETHODCALLTYPE CSmpFilter::Load(
|
|
LPCWSTR pszFileName,
|
|
DWORD dwMode
|
|
)
|
|
{
|
|
// Load just sets the filename for GetChunk to read and ignores the mode
|
|
|
|
ULONG ulChars = wcslen( pszFileName ) + 1;
|
|
delete [] m_pwszFileName;
|
|
|
|
m_pwszFileName = new WCHAR [ulChars];
|
|
|
|
if ( 0 != m_pwszFileName )
|
|
wcscpy( m_pwszFileName, pszFileName );
|
|
else
|
|
return E_OUTOFMEMORY;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//M-------------------------------------------------------------------------
|
|
//
|
|
// Method: CSmpFilter::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)
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
SCODE STDMETHODCALLTYPE CSmpFilter::Save(
|
|
LPCWSTR pszFileName,
|
|
BOOL fRemember
|
|
)
|
|
{
|
|
// File is opened read-only; saving it is an error
|
|
|
|
return E_FAIL;
|
|
}
|
|
|
|
//M-------------------------------------------------------------------------
|
|
//
|
|
// Method: CSmpFilter::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
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
SCODE STDMETHODCALLTYPE CSmpFilter::SaveCompleted(
|
|
LPCWSTR pszFileName
|
|
)
|
|
{
|
|
// File is opened read-only, so "save" is always finished
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//M-------------------------------------------------------------------------
|
|
//
|
|
// Method: CSmpFilter::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
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
SCODE STDMETHODCALLTYPE CSmpFilter::GetCurFile(
|
|
LPWSTR * ppszFileName
|
|
)
|
|
{
|
|
if ( 0 == m_pwszFileName )
|
|
return E_FAIL;
|
|
|
|
ULONG ulChars = wcslen( m_pwszFileName ) + 1;
|
|
*ppszFileName = (WCHAR *)CoTaskMemAlloc( ulChars * sizeof WCHAR );
|
|
|
|
if ( 0 != *ppszFileName )
|
|
wcscpy( *ppszFileName, m_pwszFileName );
|
|
else
|
|
return E_OUTOFMEMORY;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//C-------------------------------------------------------------------------
|
|
//
|
|
// Class: CSmpFilterCF
|
|
//
|
|
// Summary: Implements class factory for sample filter
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
//M-------------------------------------------------------------------------
|
|
//
|
|
// Method: CSmpFilterCF::CSmpFilterCF
|
|
//
|
|
// Summary: Class factory constructor
|
|
//
|
|
// Arguments: void
|
|
//
|
|
// Purpose: Manages global instance count
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
CSmpFilterCF::CSmpFilterCF() :
|
|
m_lRefs(1)
|
|
{
|
|
InterlockedIncrement( &g_lInstances );
|
|
}
|
|
|
|
//M-------------------------------------------------------------------------
|
|
//
|
|
// Method: CSmpFilterCF::~CSmpFilterCF
|
|
//
|
|
// Summary: Class factory destructor
|
|
//
|
|
// Arguments: void
|
|
//
|
|
// Purpose: Manages global instance count
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
CSmpFilterCF::~CSmpFilterCF()
|
|
{
|
|
InterlockedDecrement( &g_lInstances );
|
|
}
|
|
|
|
//M-------------------------------------------------------------------------
|
|
//
|
|
// Method: CSmpFilterCF::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
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
SCODE STDMETHODCALLTYPE CSmpFilterCF::QueryInterface(
|
|
REFIID riid,
|
|
void ** ppvObject
|
|
)
|
|
{
|
|
IUnknown *pUnkTemp;
|
|
|
|
if ( IID_IClassFactory == riid )
|
|
pUnkTemp = (IUnknown *)(IClassFactory *)this;
|
|
else if ( IID_IUnknown == riid )
|
|
pUnkTemp = (IUnknown *)this;
|
|
else
|
|
{
|
|
*ppvObject = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
*ppvObject = (void *)pUnkTemp;
|
|
pUnkTemp->AddRef();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//M-------------------------------------------------------------------------
|
|
//
|
|
// Method: CSmpFilterCF::AddRef (IUknown::AddRef)
|
|
//
|
|
// Summary: Increments interface refcount
|
|
//
|
|
// Arguments: void
|
|
//
|
|
// Returns: Value of incremented interface refcount
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
ULONG STDMETHODCALLTYPE CSmpFilterCF::AddRef()
|
|
{
|
|
return InterlockedIncrement( &m_lRefs );
|
|
}
|
|
|
|
//M-------------------------------------------------------------------------
|
|
//
|
|
// Method: CSmpFilterCF::Release (IUnknown::Release)
|
|
//
|
|
// Summary: Decrements interface refcount, deleting if unreferenced
|
|
//
|
|
// Arguments: void
|
|
//
|
|
// Returns: Value of decremented refcount
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
ULONG STDMETHODCALLTYPE CSmpFilterCF::Release()
|
|
{
|
|
ULONG ulTmp = InterlockedDecrement( &m_lRefs );
|
|
|
|
if ( 0 == ulTmp )
|
|
delete this;
|
|
|
|
return ulTmp;
|
|
}
|
|
|
|
//M-------------------------------------------------------------------------
|
|
//
|
|
// Method: CSmpFilterCF::CreateInstance (IClassFactory::CreateInstance)
|
|
//
|
|
// Summary: Creates new sample 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
|
|
// Sample filter object was successfully created
|
|
// CLASS_E_NOAGGREGATION
|
|
// pUnkOuter parameter was non-NULL
|
|
// E_NOINTERFACE
|
|
// (not implemented)
|
|
// E_OUTOFMEMORY
|
|
// Sample filter object could not be created
|
|
// due to insufficient memory
|
|
// E_UNEXPECTED
|
|
// Unsuccessful due to an unexpected condition
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
SCODE STDMETHODCALLTYPE CSmpFilterCF::CreateInstance(
|
|
IUnknown * pUnkOuter,
|
|
REFIID riid,
|
|
void * * ppvObject
|
|
)
|
|
{
|
|
CSmpFilter *pIUnk = 0;
|
|
|
|
if ( 0 != pUnkOuter )
|
|
return CLASS_E_NOAGGREGATION;
|
|
|
|
pIUnk = new CSmpFilter();
|
|
|
|
if ( 0 != pIUnk )
|
|
{
|
|
if ( SUCCEEDED( pIUnk->QueryInterface( riid , ppvObject ) ) )
|
|
{
|
|
// Release extra refcount from QueryInterface
|
|
|
|
pIUnk->Release();
|
|
}
|
|
else
|
|
{
|
|
delete pIUnk;
|
|
return E_UNEXPECTED;
|
|
}
|
|
}
|
|
else
|
|
return E_OUTOFMEMORY;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//M-------------------------------------------------------------------------
|
|
//
|
|
// Method: CSmpFilterCF::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)
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
SCODE STDMETHODCALLTYPE CSmpFilterCF::LockServer(
|
|
BOOL fLock
|
|
)
|
|
{
|
|
if( fLock )
|
|
InterlockedIncrement( &g_lInstances );
|
|
else
|
|
InterlockedDecrement( &g_lInstances );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// DLL: SmpFilt.dll
|
|
//
|
|
// Summary: Implements Dynamic Link Library functions for sample 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
|
|
// lpReserved
|
|
// [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 sample 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" SCODE STDMETHODCALLTYPE DllGetClassObject(
|
|
REFCLSID cid,
|
|
REFIID iid,
|
|
void ** ppvObj
|
|
)
|
|
{
|
|
IUnknown *pResult = 0;
|
|
|
|
if ( CLSID_CSmpFilter == cid )
|
|
pResult = (IUnknown *) new CSmpFilterCF;
|
|
else
|
|
return CLASS_E_CLASSNOTAVAILABLE;
|
|
|
|
if ( 0 != pResult )
|
|
{
|
|
if( SUCCEEDED( pResult->QueryInterface( iid, ppvObj ) ) )
|
|
// Release extra refcount from QueryInterface
|
|
pResult->Release();
|
|
else
|
|
{
|
|
delete pResult;
|
|
return E_UNEXPECTED;
|
|
}
|
|
}
|
|
else
|
|
return E_OUTOFMEMORY;
|
|
|
|
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" SCODE STDMETHODCALLTYPE DllCanUnloadNow(
|
|
void
|
|
)
|
|
{
|
|
if ( 0 >= g_lInstances )
|
|
return S_OK;
|
|
else
|
|
return S_FALSE;
|
|
}
|
|
|
|
//F-------------------------------------------------------------------------
|
|
//
|
|
// Function: DllRegisterServer
|
|
// DllUnregisterServer
|
|
//
|
|
// Summary: Registers and unregisters DLL server
|
|
//
|
|
// The registration procedure uses a set of macros
|
|
// developed for use within the Indexing Service code.
|
|
// The macros are in the included filtreg.hxx.
|
|
//
|
|
// 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)
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// These structures define the registry keys for the registration process.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
SClassEntry const asmpClasses[] =
|
|
{
|
|
{ L".smp",
|
|
L"SmpFilt.Document",
|
|
L"Sample Filter Document",
|
|
L"{8B0E5E72-3C30-11d1-8C0D-00AA00C26CD4}",
|
|
L"Sample Filter Document"
|
|
}
|
|
};
|
|
|
|
SHandlerEntry const smpHandler =
|
|
{
|
|
L"{8B0E5E73-3C30-11d1-8C0D-00AA00C26CD4}",
|
|
L"SmpFilt Persistent Handler",
|
|
L"{8B0E5E70-3C30-11d1-8C0D-00AA00C26CD4}"
|
|
};
|
|
|
|
SFilterEntry const smpFilter =
|
|
{
|
|
L"{8B0E5E70-3C30-11d1-8C0D-00AA00C26CD4}",
|
|
L"Sample Filter",
|
|
L"smpfilt.dll",
|
|
L"Both"
|
|
};
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// This macro defines the registration/unregistration routines for the DLL.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DEFINE_DLLREGISTERFILTER( smpHandler, smpFilter, asmpClasses )
|