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.

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