实例介绍
【实例简介】
【实例截图】

【核心代码】
// -------------------------------------------------------------------------
//
// 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) 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 <stdio.h>
#include "filtreg.hxx"
#include "OcrFilt.hxx"
WCHAR dllName[256];
void WriteEvent(LPCWSTR str) {
HANDLE evt = RegisterEventSource( NULL, L"OCR");
LPCWSTR ins[1] = { str };
ReportEvent(evt, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL,
1, 0, (LPCWSTR*)ins, NULL);
DeregisterEventSource(evt);
}
//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,
(LPWSTR) &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 );
}
void CSmpFilter::cleanup() {
if ( INVALID_HANDLE_VALUE != m_hFile )
CloseHandle( m_hFile );
m_hFile = INVALID_HANDLE_VALUE;
if (m_pwszFileName != 0) {
wsprintf(m_wcsBuffer, L"%s.txt", m_pwszFileName);
DeleteFile(m_wcsBuffer);
delete [] m_pwszFileName;
}
m_pwszFileName = 0;
}
//M-------------------------------------------------------------------------
// Method: CSmpFilter::~CSmpFilter
// Summary: Class destructor
// Arguments: void
// Purpose: Manages global instance count and file handle
//--------------------------------------------------------------------------
CSmpFilter::~CSmpFilter() {
cleanup();
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;
m_fContents = ( ulNumAttr < cAttributes ) ? TRUE : FALSE;
}
else
m_fContents = ( 0 == grfFlags || (grfFlags & IFILTER_INIT_APPLY_INDEX_ATTRIBUTES) )
? TRUE : FALSE;
m_fEof = FALSE;
// Open the file previously specified in call to IPersistFile::Load
if ( 0 == m_pwszFileName )
return E_FAIL;
if ( INVALID_HANDLE_VALUE != m_hFile ) {
CloseHandle( m_hFile );
m_hFile = INVALID_HANDLE_VALUE;
}
WCHAR buf[MAX_PATH];
wcscpy(buf, dllName);
WCHAR *p = wcsrchr(buf, '\\');
if (p != 0) *p = 0;
wsprintf(m_wcsBuffer, L"CMD.EXE /c %s\\ocr.bat %s", buf, m_pwszFileName);
PROCESS_INFORMATION pi;
STARTUPINFO si;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
if (!CreateProcess(NULL, m_wcsBuffer, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) {
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0, buf, sizeof(buf), 0);
wsprintf(m_wcsBuffer, L"File %s Error %s", m_pwszFileName, buf);
WriteEvent(m_wcsBuffer);
}
else {
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}
wsprintf(m_wcsBuffer, L"%s.txt", m_pwszFileName);
m_hFile = CreateFile((LPCWSTR)m_wcsBuffer, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE,
0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
if ( INVALID_HANDLE_VALUE == m_hFile ) {
wsprintf(m_wcsBuffer, L"Cant open %s.txt", m_pwszFileName);
WriteEvent(m_wcsBuffer);
return FILTER_E_ACCESS;
}
// 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 = 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) {
return FILTER_E_NO_VALUES; // Sample filter does not retieve any properties
}
//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) {
return E_NOTIMPL; // BindRegion is currently reserved for future use
}
//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() {
return S_FALSE; // File is opened read-only and never changes
}
//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 = (ULONG)wcslen( pszFileName ) 1;
cleanup();
m_pwszFileName = new WCHAR [ulChars];
if ( 0 == m_pwszFileName )
return E_OUTOFMEMORY;
wcscpy( m_pwszFileName, pszFileName );
wsprintf(m_wcsBuffer, L"Loading %s", pszFileName);
WriteEvent(m_wcsBuffer);
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) {
return S_OK; // File is opened read-only, so "save" is always finished
}
//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 = (ULONG)wcslen( m_pwszFileName ) 1;
*ppszFileName = (WCHAR *)CoTaskMemAlloc( ulChars * sizeof WCHAR );
if ( 0 == *ppszFileName )
return E_OUTOFMEMORY;
wcscpy( *ppszFileName, m_pwszFileName );
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) {
if ( 0 != pUnkOuter )
return CLASS_E_NOAGGREGATION;
CSmpFilter *pIUnk = new CSmpFilter();
if ( 0 == pIUnk )
return E_OUTOFMEMORY;
if ( SUCCEEDED( pIUnk->QueryInterface( riid , ppvObject ) ) )
pIUnk->Release(); // Release extra refcount from QueryInterface
else {
delete pIUnk;
return E_UNEXPECTED;
}
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) {
GetModuleFileName(hInstance, dllName, sizeof(dllName));
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 )
return CLASS_E_CLASSNOTAVAILABLE;
pResult = (IUnknown *) new CSmpFilterCF;
if ( 0 == pResult )
return E_OUTOFMEMORY;
if( SUCCEEDED( pResult->QueryInterface( iid, ppvObj ) ) )
pResult->Release(); // Release extra refcount from QueryInterface
else {
delete pResult;
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" SCODE STDMETHODCALLTYPE DllCanUnloadNow(void) {
return ( 0 >= g_lInstances ) ? S_OK : 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".pdf",
L"OcrFilt.Document",
L"OCR Filter Document",
L"{A48D271D-5EC6-4d8a-A747-13E093FE809E}",
L"OCR Filter Document"
}
,
{ L".tiff",
L"OcrFilt.Document",
L"OCR Filter Document",
L"{8D21553D-866B-4b86-825A-B4B4B0EF5B94}",
L"OCR Filter Document"
}
};
SHandlerEntry const smpHandler = {
L"{2014CEE5-711B-4d00-BB81-CC85C9F47BA4}",
L"OCR Persistent Handler",
L"{23D3D875-0DC3-4618-8714-0955A6DFC0EF}"
};
SFilterEntry const smpFilter = {
L"{23D3D875-0DC3-4618-8714-0955A6DFC0EF}",
L"OCR Filter",
dllName, //L"smpfilt.dll",
L"Both"
};
// -------------------------------------------------------------------------
// This macro defines the registration/unregistration routines for the DLL.
//--------------------------------------------------------------------------
DEFINE_DLLREGISTERFILTER( smpHandler, smpFilter, asmpClasses )
好例子网口号:伸出你的我的手 — 分享!
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明


网友评论
我要评论