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

  1. //+-------------------------------------------------------------------------
  2. //
  3. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  4. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  5. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  6. // PARTICULAR PURPOSE.
  7. //
  8. // Copyright (c) 1998-1999 Microsoft Corporation. All Rights Reserved.
  9. //
  10. // File: smpfilt.cxx
  11. //
  12. // Contents: Sample filter Implementation for Indexing Service
  13. //
  14. // Summary: The sample filter reads unformated text files (with the
  15. // extension .smp) using the current thread's ANSI code page
  16. // and outputs UNICODE text for the current locale.
  17. //
  18. // It accepts as input only single-byte-character text files,
  19. // and not multibyte-character or UNICODE text files.
  20. //
  21. // Platform: Windows 2000
  22. //
  23. //--------------------------------------------------------------------------
  24. //+-------------------------------------------------------------------------
  25. //
  26. // Include file Purpose
  27. //
  28. // windows.h Win32 declarations
  29. // filter.h IFilter interface declarations
  30. // filterr.h FACILITY_ITF error definitions for IFilter
  31. // ntquery.h Indexing Service declarations
  32. // filtreg.hxx DLL registration and unregistration macros
  33. // smpfilt.hxx Sample filter declarations
  34. //
  35. //--------------------------------------------------------------------------
  36. #include <windows.h>
  37. #include <filter.h>
  38. #include <filterr.h>
  39. #include <ntquery.h>
  40. #include "filtreg.hxx"
  41. #include "smpfilt.hxx"
  42. //F-------------------------------------------------------------------------
  43. //
  44. // Function: GetDefaultCodepage
  45. //
  46. // Summary: Returns the codepage associated with the current default
  47. // locale, or CP_ACP if one can't be found.
  48. //
  49. // Returns: Codepage
  50. //
  51. //--------------------------------------------------------------------------
  52. ULONG GetDefaultCodepage()
  53. {
  54. ULONG codepage;
  55. int cwc = GetLocaleInfo( GetSystemDefaultLCID(),
  56. LOCALE_RETURN_NUMBER |
  57. LOCALE_IDEFAULTANSICODEPAGE,
  58. (WCHAR *) &codepage,
  59. sizeof ULONG / sizeof WCHAR );
  60. // If an error occurred, return the Ansi code page
  61. if ( 0 == cwc )
  62. return CP_ACP;
  63. return codepage;
  64. }
  65. //C-------------------------------------------------------------------------
  66. //
  67. // Class: CSmpFilter
  68. //
  69. // Summary: Implements sample filter class
  70. //
  71. //--------------------------------------------------------------------------
  72. //M-------------------------------------------------------------------------
  73. //
  74. // Method: CSmpFilter::CSmpFilter
  75. //
  76. // Summary: Class constructor
  77. //
  78. // Arguments: void
  79. //
  80. // Purpose: Manages global instance count
  81. //
  82. //--------------------------------------------------------------------------
  83. CSmpFilter::CSmpFilter() :
  84. m_hFile(INVALID_HANDLE_VALUE),
  85. m_lRefs(1),
  86. m_pwszFileName(0),
  87. m_ulBufferLen(0),
  88. m_ulCharsRead(0),
  89. m_ulChunkID(1),
  90. m_fContents(FALSE),
  91. m_fEof(FALSE),
  92. m_ulCodePage( GetDefaultCodepage() )
  93. {
  94. InterlockedIncrement( &g_lInstances );
  95. }
  96. //M-------------------------------------------------------------------------
  97. //
  98. // Method: CSmpFilter::~CSmpFilter
  99. //
  100. // Summary: Class destructor
  101. //
  102. // Arguments: void
  103. //
  104. // Purpose: Manages global instance count and file handle
  105. //
  106. //--------------------------------------------------------------------------
  107. CSmpFilter::~CSmpFilter()
  108. {
  109. delete [] m_pwszFileName;
  110. if ( INVALID_HANDLE_VALUE != m_hFile )
  111. CloseHandle( m_hFile );
  112. InterlockedDecrement( &g_lInstances );
  113. }
  114. //M-------------------------------------------------------------------------
  115. //
  116. // Method: CSmpFilter::QueryInterface (IUnknown::QueryInterface)
  117. //
  118. // Summary: Queries for requested interface
  119. //
  120. // Arguments: riid
  121. // [in] Reference IID of requested interface
  122. // ppvObject
  123. // [out] Address that receives requested interface pointer
  124. //
  125. // Returns: S_OK
  126. // Interface is supported
  127. // E_NOINTERFACE
  128. // Interface is not supported
  129. //
  130. //--------------------------------------------------------------------------
  131. SCODE STDMETHODCALLTYPE CSmpFilter::QueryInterface(
  132. REFIID riid,
  133. void ** ppvObject
  134. )
  135. {
  136. IUnknown *pUnkTemp = 0;
  137. if ( IID_IFilter == riid )
  138. pUnkTemp = (IUnknown *)(IFilter *)this;
  139. else if ( IID_IPersistFile == riid )
  140. pUnkTemp = (IUnknown *)(IPersistFile *)this;
  141. else if ( IID_IPersist == riid )
  142. pUnkTemp = (IUnknown *)(IPersist *)(IPersistFile *)this;
  143. else if ( IID_IUnknown == riid )
  144. pUnkTemp = (IUnknown *)(IPersist *)(IPersistFile *)this;
  145. else
  146. {
  147. *ppvObject = NULL;
  148. return E_NOINTERFACE;
  149. }
  150. *ppvObject = (void *)pUnkTemp;
  151. pUnkTemp->AddRef();
  152. return S_OK;
  153. }
  154. //M-------------------------------------------------------------------------
  155. //
  156. // Method: CSmpFilter::AddRef (IUnknown::AddRef)
  157. //
  158. // Summary: Increments interface refcount
  159. //
  160. // Arguments: void
  161. //
  162. // Returns: Value of incremented interface refcount
  163. //
  164. //--------------------------------------------------------------------------
  165. ULONG STDMETHODCALLTYPE CSmpFilter::AddRef()
  166. {
  167. return InterlockedIncrement( &m_lRefs );
  168. }
  169. //M-------------------------------------------------------------------------
  170. //
  171. // Method: CSmpFilter::Release (IUnknown::Release)
  172. //
  173. // Summary: Decrements interface refcount, deleting if unreferenced
  174. //
  175. // Arguments: void
  176. //
  177. // Returns: Value of decremented interface refcount
  178. //
  179. //--------------------------------------------------------------------------
  180. ULONG STDMETHODCALLTYPE CSmpFilter::Release()
  181. {
  182. ULONG ulTmp = InterlockedDecrement( &m_lRefs );
  183. if ( 0 == ulTmp )
  184. delete this;
  185. return ulTmp;
  186. }
  187. //M-------------------------------------------------------------------------
  188. //
  189. // Method: CSmpFilter::Init (IFilter::Init)
  190. //
  191. // Summary: Initializes sample filter instance
  192. //
  193. // Arguments: grfFlags
  194. // [in] Flags for filter behavior
  195. // cAttributes
  196. // [in] Number attributes in array aAttributes
  197. // aAttributes
  198. // [in] Array of requested attribute strings
  199. // pFlags
  200. // [out] Pointer to return flags for additional properties
  201. //
  202. // Returns: S_OK
  203. // Initialization succeeded
  204. // E_FAIL
  205. // File not previously loaded
  206. // E_INVALIDARG
  207. // Count and contents of attributes do not agree
  208. // FILTER_E_ACCESS
  209. // Unable to access file to be filtered
  210. // FILTER_E_PASSWORD
  211. // (not implemented)
  212. //
  213. //--------------------------------------------------------------------------
  214. SCODE STDMETHODCALLTYPE CSmpFilter::Init(
  215. ULONG grfFlags,
  216. ULONG cAttributes,
  217. FULLPROPSPEC const * aAttributes,
  218. ULONG * pFlags
  219. )
  220. {
  221. // Ignore flags for text canonicalization (text is unformatted)
  222. // Check for proper attributes request and recognize only "contents"
  223. if( 0 < cAttributes )
  224. {
  225. ULONG ulNumAttr;
  226. if ( 0 == aAttributes )
  227. return E_INVALIDARG;
  228. for ( ulNumAttr = 0 ; ulNumAttr < cAttributes; ulNumAttr++ )
  229. {
  230. if ( guidStorage == aAttributes[ulNumAttr].guidPropSet &&
  231. PID_STG_CONTENTS == aAttributes[ulNumAttr].psProperty.propid )
  232. break;
  233. }
  234. if ( ulNumAttr < cAttributes )
  235. m_fContents = TRUE;
  236. else
  237. m_fContents = FALSE;
  238. }
  239. else if ( 0 == grfFlags ||
  240. (grfFlags & IFILTER_INIT_APPLY_INDEX_ATTRIBUTES) )
  241. m_fContents = TRUE;
  242. else
  243. m_fContents = FALSE;
  244. m_fEof = FALSE;
  245. // Open the file previously specified in call to IPersistFile::Load
  246. if ( 0 != m_pwszFileName )
  247. {
  248. if ( INVALID_HANDLE_VALUE != m_hFile )
  249. {
  250. CloseHandle( m_hFile );
  251. m_hFile = INVALID_HANDLE_VALUE;
  252. }
  253. m_hFile = CreateFile(
  254. m_pwszFileName,
  255. GENERIC_READ,
  256. FILE_SHARE_READ | FILE_SHARE_DELETE,
  257. 0,
  258. OPEN_EXISTING,
  259. FILE_ATTRIBUTE_NORMAL,
  260. 0
  261. );
  262. if ( INVALID_HANDLE_VALUE == m_hFile )
  263. return FILTER_E_ACCESS;
  264. }
  265. else
  266. return E_FAIL;
  267. // Enumerate OLE properties, since any NTFS file can have them
  268. *pFlags = IFILTER_FLAGS_OLE_PROPERTIES;
  269. // Re-initialize
  270. m_ulChunkID = 1;
  271. m_ulCharsRead = 0;
  272. return S_OK;
  273. }
  274. //M-------------------------------------------------------------------------
  275. //
  276. // Method: CSmpFilter::GetChunk (IFilter::GetChunk)
  277. //
  278. // Summary: Gets the next chunk (text only)
  279. //
  280. // Note: GetChunk accepts as input only single-byte-character text
  281. // files, and not multibyte-character or UNICODE text files.
  282. //
  283. // Arguments: ppStat
  284. // [out] Pointer to description of current chunk
  285. // Returns: S_OK
  286. // Chunk was successfully retrieved
  287. // E_FAIL
  288. // Character conversion failed
  289. // FILTER_E_ACCESS
  290. // General access failure occurred
  291. // FILTER_E_END_OF_CHUNKS
  292. // Previous chunk was the last chunk
  293. // FILTER_E_EMBEDDING_UNAVAILABLE
  294. // (not implemented)
  295. // FILTER_E_LINK_UNAVAILABLE
  296. // (not implemented)
  297. // FILTER_E_PASSWORD
  298. // (not implemented)
  299. //
  300. //--------------------------------------------------------------------------
  301. SCODE STDMETHODCALLTYPE CSmpFilter::GetChunk(
  302. STAT_CHUNK * pStat
  303. )
  304. {
  305. if ( INVALID_HANDLE_VALUE == m_hFile )
  306. return FILTER_E_ACCESS;
  307. // Read characters from single-byte file
  308. char cszBuffer[TEXT_FILTER_CHUNK_SIZE];
  309. if ( !ReadFile(
  310. m_hFile,
  311. cszBuffer,
  312. TEXT_FILTER_CHUNK_SIZE,
  313. &m_ulBufferLen,
  314. NULL
  315. ) )
  316. return FILTER_E_ACCESS;
  317. else if( 0 == m_ulBufferLen )
  318. m_fEof = TRUE;
  319. if ( !m_fContents || m_fEof )
  320. return FILTER_E_END_OF_CHUNKS;
  321. // Convert single-byte characters to UNICODE
  322. //
  323. // This conversion assumes a one-to-one conversion:
  324. // one input single-byte character to
  325. // one output multibyte (UNICODE) character
  326. //
  327. // This is typically not the general case with multibyte
  328. // characters, and a general case needs to handle the possible
  329. // difference of pre- and post-conversion buffer lengths
  330. if ( !MultiByteToWideChar(
  331. m_ulCodePage,
  332. MB_COMPOSITE,
  333. cszBuffer,
  334. m_ulBufferLen,
  335. m_wcsBuffer,
  336. TEXT_FILTER_CHUNK_SIZE
  337. ) )
  338. return E_FAIL;
  339. // Set chunk description
  340. pStat->idChunk = m_ulChunkID;
  341. pStat->breakType = CHUNK_NO_BREAK;
  342. pStat->flags = CHUNK_TEXT;
  343. pStat->locale = GetSystemDefaultLCID();
  344. pStat->attribute.guidPropSet = guidStorage;
  345. pStat->attribute.psProperty.ulKind = PRSPEC_PROPID;
  346. pStat->attribute.psProperty.propid = PID_STG_CONTENTS;
  347. pStat->idChunkSource = m_ulChunkID;
  348. pStat->cwcStartSource = 0;
  349. pStat->cwcLenSource = 0;
  350. m_ulCharsRead = 0;
  351. m_ulChunkID++;
  352. return S_OK;
  353. }
  354. //M-------------------------------------------------------------------------
  355. //
  356. // Method: CSmpFilter::GetText (IFilter::GetText)
  357. //
  358. // Summary: Retrieves UNICODE text for index
  359. //
  360. // Arguments: pcwcBuffer
  361. // [in] Pointer to size of UNICODE buffer
  362. // [out] Pointer to count of UNICODE characters returned
  363. // awcBuffer
  364. // [out] Pointer to buffer to receive UNICODE text
  365. //
  366. // Returns: S_OK
  367. // Text successfully retrieved, but text remains in chunk
  368. // FILTER_E_NO_MORE_TEXT
  369. // All of the text in the current chunk has been returned
  370. // FILTER_S_LAST_TEXT
  371. // Next call to GetText will return FILTER_E_NO_MORE_TEXT
  372. //
  373. //--------------------------------------------------------------------------
  374. SCODE STDMETHODCALLTYPE CSmpFilter::GetText(
  375. ULONG * pcwcBuffer,
  376. WCHAR * awcBuffer
  377. )
  378. {
  379. if ( !m_fContents || 0 == m_ulBufferLen )
  380. {
  381. *pcwcBuffer = 0;
  382. return FILTER_E_NO_MORE_TEXT;
  383. }
  384. // Copy characters in chunk buffer to output UNICODE buffer
  385. //
  386. // This copy assumes a one-to-one conversion in GetChunk
  387. // of input single-byte characters (each 1 byte long)
  388. // to output UNICODE characters (each 2 bytes long)
  389. ULONG ulToCopy = min( *pcwcBuffer, m_ulBufferLen - m_ulCharsRead );
  390. memcpy( awcBuffer, m_wcsBuffer + m_ulCharsRead, 2*ulToCopy );
  391. m_ulCharsRead += ulToCopy;
  392. *pcwcBuffer = ulToCopy;
  393. if ( m_ulBufferLen == m_ulCharsRead )
  394. {
  395. m_ulCharsRead = 0;
  396. m_ulBufferLen = 0;
  397. return FILTER_S_LAST_TEXT;
  398. }
  399. return S_OK;
  400. }
  401. //M-------------------------------------------------------------------------
  402. //
  403. // Method: CSmpFilter::GetValue (IFilter::GetValue)
  404. //
  405. // Summary: Retrieves properites for index
  406. //
  407. // Arguments: ppPropValue
  408. // [out] Address that receives pointer to property value
  409. //
  410. // Returns: FILTER_E_NO_VALUES
  411. // Always
  412. // FILTER_E_NO_MORE_VALUES
  413. // (not implemented)
  414. //
  415. //--------------------------------------------------------------------------
  416. SCODE STDMETHODCALLTYPE CSmpFilter::GetValue(
  417. PROPVARIANT ** ppPropValue
  418. )
  419. {
  420. // Sample filter does not retieve any properties
  421. return FILTER_E_NO_VALUES;
  422. }
  423. //M-------------------------------------------------------------------------
  424. //
  425. // Method: CSmpFilter::BindRegion (IFilter::BindRegion)
  426. //
  427. // Summary: Creates moniker or other interface for indicated text
  428. //
  429. // Arguments: origPos
  430. // [in] Description of text location and extent
  431. // riid
  432. // [in] Reference IID of specified interface
  433. // ppunk
  434. // [out] Address that receives requested interface pointer
  435. //
  436. // Returns: E_NOTIMPL
  437. // Always
  438. // FILTER_W_REGION_CLIPPED
  439. // (not implemented)
  440. //
  441. //--------------------------------------------------------------------------
  442. SCODE STDMETHODCALLTYPE CSmpFilter::BindRegion(
  443. FILTERREGION origPos,
  444. REFIID riid,
  445. void ** ppunk
  446. )
  447. {
  448. // BindRegion is currently reserved for future use
  449. return E_NOTIMPL;
  450. }
  451. //M-------------------------------------------------------------------------
  452. //
  453. // Method: CSmpFilter::GetClassID (IPersist::GetClassID)
  454. //
  455. // Summary: Retrieves the class id of the filter class
  456. //
  457. // Arguments: pClassID
  458. // [out] Pointer to the class ID of the filter
  459. //
  460. // Returns: S_OK
  461. // Always
  462. // E_FAIL
  463. // (not implemented)
  464. //
  465. //--------------------------------------------------------------------------
  466. SCODE STDMETHODCALLTYPE CSmpFilter::GetClassID(
  467. CLSID * pClassID
  468. )
  469. {
  470. *pClassID = CLSID_CSmpFilter;
  471. return S_OK;
  472. }
  473. //M-------------------------------------------------------------------------
  474. //
  475. // Method: CSmpFilter::IsDirty (IPersistFile::IsDirty)
  476. //
  477. // Summary: Checks whether file has changed since last save
  478. //
  479. // Arguments: void
  480. //
  481. // Returns: S_FALSE
  482. // Always
  483. // S_OK
  484. // (not implemented)
  485. //
  486. //--------------------------------------------------------------------------
  487. SCODE STDMETHODCALLTYPE CSmpFilter::IsDirty()
  488. {
  489. // File is opened read-only and never changes
  490. return S_FALSE;
  491. }
  492. //M-------------------------------------------------------------------------
  493. //
  494. // Method: CSmpFilter::Load (IPersistFile::Load)
  495. //
  496. // Summary: Opens and initializes the specified file
  497. //
  498. // Arguments: pszFileName
  499. // [in] Pointer to zero-terminated string
  500. // of absolute path of file to open
  501. // dwMode
  502. // [in] Access mode to open the file
  503. //
  504. // Returns: S_OK
  505. // File was successfully loaded
  506. // E_OUTOFMEMORY
  507. // File could not be loaded due to insufficient memory
  508. // E_FAIL
  509. // (not implemented)
  510. //
  511. //--------------------------------------------------------------------------
  512. SCODE STDMETHODCALLTYPE CSmpFilter::Load(
  513. LPCWSTR pszFileName,
  514. DWORD dwMode
  515. )
  516. {
  517. // Load just sets the filename for GetChunk to read and ignores the mode
  518. ULONG ulChars = wcslen( pszFileName ) + 1;
  519. delete [] m_pwszFileName;
  520. m_pwszFileName = new WCHAR [ulChars];
  521. if ( 0 != m_pwszFileName )
  522. wcscpy( m_pwszFileName, pszFileName );
  523. else
  524. return E_OUTOFMEMORY;
  525. return S_OK;
  526. }
  527. //M-------------------------------------------------------------------------
  528. //
  529. // Method: CSmpFilter::Save (IPersistFile::Save)
  530. //
  531. // Summary: Saves a copy of the current file being filtered
  532. //
  533. // Arguments: pszFileName
  534. // [in] Pointer to zero-terminated string of
  535. // absolute path of where to save file
  536. // fRemember
  537. // [in] Whether the saved copy is made the current file
  538. //
  539. // Returns: E_FAIL
  540. // Always
  541. // S_OK
  542. // (not implemented)
  543. //
  544. //--------------------------------------------------------------------------
  545. SCODE STDMETHODCALLTYPE CSmpFilter::Save(
  546. LPCWSTR pszFileName,
  547. BOOL fRemember
  548. )
  549. {
  550. // File is opened read-only; saving it is an error
  551. return E_FAIL;
  552. }
  553. //M-------------------------------------------------------------------------
  554. //
  555. // Method: CSmpFilter::SaveCompleted (IPersistFile::SaveCompleted)
  556. //
  557. // Summary: Determines whether a file save is completed
  558. //
  559. // Arguments: pszFileName
  560. // [in] Pointer to zero-terminated string of
  561. // absolute path where file was previously saved
  562. //
  563. // Returns: S_OK
  564. // Always
  565. //
  566. //--------------------------------------------------------------------------
  567. SCODE STDMETHODCALLTYPE CSmpFilter::SaveCompleted(
  568. LPCWSTR pszFileName
  569. )
  570. {
  571. // File is opened read-only, so "save" is always finished
  572. return S_OK;
  573. }
  574. //M-------------------------------------------------------------------------
  575. //
  576. // Method: CSmpFilter::GetCurFile (IPersistFile::GetCurFile)
  577. //
  578. // Summary: Returns a copy of the current file name
  579. //
  580. // Arguments: ppszFileName
  581. // [out] Address to receive pointer to zero-terminated
  582. // string for absolute path to current file
  583. //
  584. // Returns: S_OK
  585. // A valid absolute path was successfully returned
  586. // S_FALSE
  587. // (not implemented)
  588. // E_OUTOFMEMORY
  589. // Operation failed due to insufficient memory
  590. // E_FAIL
  591. // Operation failed due to some reason
  592. // other than insufficient memory
  593. //
  594. //--------------------------------------------------------------------------
  595. SCODE STDMETHODCALLTYPE CSmpFilter::GetCurFile(
  596. LPWSTR * ppszFileName
  597. )
  598. {
  599. if ( 0 == m_pwszFileName )
  600. return E_FAIL;
  601. ULONG ulChars = wcslen( m_pwszFileName ) + 1;
  602. *ppszFileName = (WCHAR *)CoTaskMemAlloc( ulChars * sizeof WCHAR );
  603. if ( 0 != *ppszFileName )
  604. wcscpy( *ppszFileName, m_pwszFileName );
  605. else
  606. return E_OUTOFMEMORY;
  607. return S_OK;
  608. }
  609. //C-------------------------------------------------------------------------
  610. //
  611. // Class: CSmpFilterCF
  612. //
  613. // Summary: Implements class factory for sample filter
  614. //
  615. //--------------------------------------------------------------------------
  616. //M-------------------------------------------------------------------------
  617. //
  618. // Method: CSmpFilterCF::CSmpFilterCF
  619. //
  620. // Summary: Class factory constructor
  621. //
  622. // Arguments: void
  623. //
  624. // Purpose: Manages global instance count
  625. //
  626. //--------------------------------------------------------------------------
  627. CSmpFilterCF::CSmpFilterCF() :
  628. m_lRefs(1)
  629. {
  630. InterlockedIncrement( &g_lInstances );
  631. }
  632. //M-------------------------------------------------------------------------
  633. //
  634. // Method: CSmpFilterCF::~CSmpFilterCF
  635. //
  636. // Summary: Class factory destructor
  637. //
  638. // Arguments: void
  639. //
  640. // Purpose: Manages global instance count
  641. //
  642. //--------------------------------------------------------------------------
  643. CSmpFilterCF::~CSmpFilterCF()
  644. {
  645. InterlockedDecrement( &g_lInstances );
  646. }
  647. //M-------------------------------------------------------------------------
  648. //
  649. // Method: CSmpFilterCF::QueryInterface (IUnknown::QueryInterface)
  650. //
  651. // Summary: Queries for requested interface
  652. //
  653. // Arguments: riid
  654. // [in] Reference IID of requested interface
  655. // ppvObject
  656. // [out] Address that receives requested interface pointer
  657. //
  658. // Returns: S_OK
  659. // Interface is supported
  660. // E_NOINTERFACE
  661. // Interface is not supported
  662. //
  663. //--------------------------------------------------------------------------
  664. SCODE STDMETHODCALLTYPE CSmpFilterCF::QueryInterface(
  665. REFIID riid,
  666. void ** ppvObject
  667. )
  668. {
  669. IUnknown *pUnkTemp;
  670. if ( IID_IClassFactory == riid )
  671. pUnkTemp = (IUnknown *)(IClassFactory *)this;
  672. else if ( IID_IUnknown == riid )
  673. pUnkTemp = (IUnknown *)this;
  674. else
  675. {
  676. *ppvObject = NULL;
  677. return E_NOINTERFACE;
  678. }
  679. *ppvObject = (void *)pUnkTemp;
  680. pUnkTemp->AddRef();
  681. return S_OK;
  682. }
  683. //M-------------------------------------------------------------------------
  684. //
  685. // Method: CSmpFilterCF::AddRef (IUknown::AddRef)
  686. //
  687. // Summary: Increments interface refcount
  688. //
  689. // Arguments: void
  690. //
  691. // Returns: Value of incremented interface refcount
  692. //
  693. //--------------------------------------------------------------------------
  694. ULONG STDMETHODCALLTYPE CSmpFilterCF::AddRef()
  695. {
  696. return InterlockedIncrement( &m_lRefs );
  697. }
  698. //M-------------------------------------------------------------------------
  699. //
  700. // Method: CSmpFilterCF::Release (IUnknown::Release)
  701. //
  702. // Summary: Decrements interface refcount, deleting if unreferenced
  703. //
  704. // Arguments: void
  705. //
  706. // Returns: Value of decremented refcount
  707. //
  708. //--------------------------------------------------------------------------
  709. ULONG STDMETHODCALLTYPE CSmpFilterCF::Release()
  710. {
  711. ULONG ulTmp = InterlockedDecrement( &m_lRefs );
  712. if ( 0 == ulTmp )
  713. delete this;
  714. return ulTmp;
  715. }
  716. //M-------------------------------------------------------------------------
  717. //
  718. // Method: CSmpFilterCF::CreateInstance (IClassFactory::CreateInstance)
  719. //
  720. // Summary: Creates new sample filter object
  721. //
  722. // Arguments: pUnkOuter
  723. // [in] Pointer to IUnknown interface of aggregating object
  724. // riid
  725. // [in] Reference IID of requested interface
  726. // ppvObject
  727. // [out] Address that receives requested interface pointer
  728. //
  729. // Returns: S_OK
  730. // Sample filter object was successfully created
  731. // CLASS_E_NOAGGREGATION
  732. // pUnkOuter parameter was non-NULL
  733. // E_NOINTERFACE
  734. // (not implemented)
  735. // E_OUTOFMEMORY
  736. // Sample filter object could not be created
  737. // due to insufficient memory
  738. // E_UNEXPECTED
  739. // Unsuccessful due to an unexpected condition
  740. //
  741. //--------------------------------------------------------------------------
  742. SCODE STDMETHODCALLTYPE CSmpFilterCF::CreateInstance(
  743. IUnknown * pUnkOuter,
  744. REFIID riid,
  745. void * * ppvObject
  746. )
  747. {
  748. CSmpFilter *pIUnk = 0;
  749. if ( 0 != pUnkOuter )
  750. return CLASS_E_NOAGGREGATION;
  751. pIUnk = new CSmpFilter();
  752. if ( 0 != pIUnk )
  753. {
  754. if ( SUCCEEDED( pIUnk->QueryInterface( riid , ppvObject ) ) )
  755. {
  756. // Release extra refcount from QueryInterface
  757. pIUnk->Release();
  758. }
  759. else
  760. {
  761. delete pIUnk;
  762. return E_UNEXPECTED;
  763. }
  764. }
  765. else
  766. return E_OUTOFMEMORY;
  767. return S_OK;
  768. }
  769. //M-------------------------------------------------------------------------
  770. //
  771. // Method: CSmpFilterCF::LockServer (IClassFactory::LockServer)
  772. //
  773. // Summary: Forces/allows filter class to remain loaded/be unloaded
  774. //
  775. // Arguments: fLock
  776. // [in] TRUE to lock, FALSE to unlock
  777. //
  778. // Returns: S_OK
  779. // Always
  780. // E_FAIL
  781. // (not implemented)
  782. // E_OUTOFMEMORY
  783. // (not implemented)
  784. // E_UNEXPECTED
  785. // (not implemented)
  786. //
  787. //--------------------------------------------------------------------------
  788. SCODE STDMETHODCALLTYPE CSmpFilterCF::LockServer(
  789. BOOL fLock
  790. )
  791. {
  792. if( fLock )
  793. InterlockedIncrement( &g_lInstances );
  794. else
  795. InterlockedDecrement( &g_lInstances );
  796. return S_OK;
  797. }
  798. //+-------------------------------------------------------------------------
  799. //
  800. // DLL: SmpFilt.dll
  801. //
  802. // Summary: Implements Dynamic Link Library functions for sample filter
  803. //
  804. //--------------------------------------------------------------------------
  805. //F-------------------------------------------------------------------------
  806. //
  807. // Function: DllMain
  808. //
  809. // Summary: Called from C-Runtime on process/thread attach/detach
  810. //
  811. // Arguments: hInstance
  812. // [in] Handle to the DLL
  813. // fdwReason
  814. // [in] Reason for calling DLL entry point
  815. // lpReserved
  816. // [in] Details of DLL initialization and cleanup
  817. //
  818. // Returns: TRUE
  819. // Always
  820. //
  821. //--------------------------------------------------------------------------
  822. extern "C" BOOL WINAPI DllMain(
  823. HINSTANCE hInstance,
  824. DWORD fdwReason,
  825. LPVOID lpvReserved
  826. )
  827. {
  828. if ( DLL_PROCESS_ATTACH == fdwReason )
  829. DisableThreadLibraryCalls( hInstance );
  830. return TRUE;
  831. }
  832. //F-------------------------------------------------------------------------
  833. //
  834. // Function: DllGetClassObject
  835. //
  836. // Summary: Create sample filter class factory object
  837. //
  838. // Arguments: cid
  839. // [in] Class ID of class that class factory creates
  840. // iid
  841. // [in] Reference IID of requested class factory interface
  842. // ppvObj
  843. // [out] Address that receives requested interface pointer
  844. //
  845. // Returns: S_OK
  846. // Class factory object was created successfully
  847. // CLASS_E_CLASSNOTAVAILABLE
  848. // DLL does not support the requested class
  849. // E_INVALIDARG
  850. // (not implemented)
  851. // E_OUTOFMEMORY
  852. // Insufficient memory to create the class factory object
  853. // E_UNEXPECTED
  854. // Unsuccessful due to an unexpected condition
  855. //
  856. //--------------------------------------------------------------------------
  857. extern "C" SCODE STDMETHODCALLTYPE DllGetClassObject(
  858. REFCLSID cid,
  859. REFIID iid,
  860. void ** ppvObj
  861. )
  862. {
  863. IUnknown *pResult = 0;
  864. if ( CLSID_CSmpFilter == cid )
  865. pResult = (IUnknown *) new CSmpFilterCF;
  866. else
  867. return CLASS_E_CLASSNOTAVAILABLE;
  868. if ( 0 != pResult )
  869. {
  870. if( SUCCEEDED( pResult->QueryInterface( iid, ppvObj ) ) )
  871. // Release extra refcount from QueryInterface
  872. pResult->Release();
  873. else
  874. {
  875. delete pResult;
  876. return E_UNEXPECTED;
  877. }
  878. }
  879. else
  880. return E_OUTOFMEMORY;
  881. return S_OK;
  882. }
  883. //F-------------------------------------------------------------------------
  884. //
  885. // Function: DllCanUnloadNow
  886. //
  887. // Summary: Indicates whether it is possible to unload DLL
  888. //
  889. // Arguments: void
  890. //
  891. // Returns: S_OK
  892. // DLL can be unloaded now
  893. // S_FALSE
  894. // DLL must remain loaded
  895. //
  896. //--------------------------------------------------------------------------
  897. extern "C" SCODE STDMETHODCALLTYPE DllCanUnloadNow(
  898. void
  899. )
  900. {
  901. if ( 0 >= g_lInstances )
  902. return S_OK;
  903. else
  904. return S_FALSE;
  905. }
  906. //F-------------------------------------------------------------------------
  907. //
  908. // Function: DllRegisterServer
  909. // DllUnregisterServer
  910. //
  911. // Summary: Registers and unregisters DLL server
  912. //
  913. // The registration procedure uses a set of macros
  914. // developed for use within the Indexing Service code.
  915. // The macros are in the included filtreg.hxx.
  916. //
  917. // Returns: DllRegisterServer
  918. // S_OK
  919. // Registration was successful
  920. // SELFREG_E_CLASS
  921. // Registration was unsuccessful
  922. // SELFREG_E_TYPELIB
  923. // (not implemented)
  924. // E_OUTOFMEMORY
  925. // (not implemented)
  926. // E_UNEXPECTED
  927. // (not implemented)
  928. // DllUnregisterServer
  929. // S_OK
  930. // Unregistration was successful
  931. // S_FALSE
  932. // Unregistration was successful, but other
  933. // entries still exist for the DLL's classes
  934. // SELFREG_E_CLASS
  935. // (not implemented)
  936. // SELFREG_E_TYPELIB
  937. // (not implemented)
  938. // E_OUTOFMEMORY
  939. // (not implemented)
  940. // E_UNEXPECTED
  941. // (not implemented)
  942. //
  943. //--------------------------------------------------------------------------
  944. //+-------------------------------------------------------------------------
  945. //
  946. // These structures define the registry keys for the registration process.
  947. //
  948. //--------------------------------------------------------------------------
  949. SClassEntry const asmpClasses[] =
  950. {
  951. { L".smp",
  952. L"SmpFilt.Document",
  953. L"Sample Filter Document",
  954. L"{8B0E5E72-3C30-11d1-8C0D-00AA00C26CD4}",
  955. L"Sample Filter Document"
  956. }
  957. };
  958. SHandlerEntry const smpHandler =
  959. {
  960. L"{8B0E5E73-3C30-11d1-8C0D-00AA00C26CD4}",
  961. L"SmpFilt Persistent Handler",
  962. L"{8B0E5E70-3C30-11d1-8C0D-00AA00C26CD4}"
  963. };
  964. SFilterEntry const smpFilter =
  965. {
  966. L"{8B0E5E70-3C30-11d1-8C0D-00AA00C26CD4}",
  967. L"Sample Filter",
  968. L"smpfilt.dll",
  969. L"Both"
  970. };
  971. //+-------------------------------------------------------------------------
  972. //
  973. // This macro defines the registration/unregistration routines for the DLL.
  974. //
  975. //--------------------------------------------------------------------------
  976. DEFINE_DLLREGISTERFILTER( smpHandler, smpFilter, asmpClasses )