Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1108 lines
31 KiB

//+-------------------------------------------------------------------------
//
// 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 )