Windows Search の IFilter

# 概要

Windows で全文検索を実装しようと思った際に触れる事があると思われるのがこちらの IFilter です:

[IFilter (filter.h) - Win32 apps | Microsoft Docs](https://docs.microsoft.com/en-us/windows/win32/api/filter/nn-filter-ifilter)

> Scans documents for text and properties (also called attributes). It extracts chunks of text from these documents, filtering out embedded formatting and retaining information about the position of the text.

テキストの塊の抽出を可能にします。

それを可能にするためのフレームワークが IFilter interface を中心とする技術です。IFilter は只のインターフェイスであるため、誰かが実装して DLL ファイルを提供する必要があります。それらはフィルターハンドラーとして Windows シェルへ統合されて [LoadIFilter](https://docs.microsoft.com/en-us/windows/win32/api/ntquery/nf-ntquery-loadifilter) API によってインスタンスを作成できます。



参考: [ファイルの種類のハンドラー - Win32 apps | Microsoft Docs](https://docs.microsoft.com/ja-jp/windows/win32/shell/fa-file-extensions)

イメージを掴むために、どんな感じのデータが出てくるのか… 可視化しました:

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364126/056203ee-b375-a0e5-3a8e-c1cda03c2145.png)

※ IFilter は DLL 側での実装になりますので、exe 側の 32-bit / 64-bit のプラットフォーム選択による影響を受けます。具体的な例として 64-bit Windows では Microsoft Filter Pack 2.0 の 64-bit 版しかインストールすることができず、WOW64 による 32-bit 環境で使用できる IFilter はインストールされません。

## コード例

取得については雑ですが… つぎのような疑似コードでとってこられるようです:

```
IFilter::Init(...);

while (0 == IFilter::GetChunk(...)) {
  if (flags & CHUNK_TEXT) {
    while (0 == IFilter::GetText(...)) {
      ..
    }
  }
  if (flags & CHUNK_VALUE) {
    while (0 == IFilter::GetValue(...)) {
      ..
    }
  }
}
```

GetText は UTF-16 の文字列、GetValue は PROPVARIANT が得られます。

`{F29F85E0-4FF9-1068-AB91-08002B27B3D9},2` から `Title` を持ってきた根拠は、表 [[MS-WSP]: Common Open Properties | Microsoft Docs](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wsp/2dbe759c-c955-4770-a545-e46d7f6332ed) をもとにしています。

参考までに、いくつかのフィルターから取得した情報をメモいたします:

※ メモで載せているデータは正常なものばかりですが、IFilter の実装と、入力ファイルの組み合わせによっては異常値を観測する場合があります。例えば xls では、長い文字列を格納しているセルについて、後方で文字化けするケースを確認しています。文字化けによって無効なサロゲートペアの組み合わせが生成されたりすると、UTF-8 への変換時に特異なデータが流出する可能性があります。

## PDF

|attribute|propType|locale|contents|
|---|---|--:|---|
|{F29F85E0-4FF9-1068-AB91-08002B27B3D9},2|Title|1041|Microsoft Word - 文書 12|
|{F29F85E0-4FF9-1068-AB91-08002B27B3D9},4|Author|1041|KU|
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},19|Search.Contents|1041|PDF サンプル#1|
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},19|Search.Contents|1041|PDF サンプル#2|
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},19|Search.Contents|1041|PDF サンプル#3|

## xls

|attribute|propType|locale|contents|
|---|---|--:|---|
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},19|Search.Contents|0|Sheet3 Sheet2 Sheet1 ABC abc あいうえおアイウエオ 123.00|

## ppt

|attribute|propType|locale|contents|
|---|---|--:|---|
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},19|Search.Contents|1041|ここにテキスト |
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},19|Search.Contents|1033|* * |
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},19|Search.Contents|1041||

## doc

|attribute|propType|locale|contents|
|---|---|--:|---|
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},19|Search.Contents|1041|あいうえお アイウエオ ABC abc 123|

## zip

|attribute|propType|locale|contents|
|---|---|--:|---|
|{560C36C0-503A-11CF-BAA1-00004C752A9A},urn:schemas.microsoft.com:container:child||0|1重要系2003 Microsoft Word 文書.doc|
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},140724603453459||1041|あいうえお アイウエオ ABC abc 123|
|{560C36C0-503A-11CF-BAA1-00004C752A9A},urn:schemas.microsoft.com:container:child||0|1重要系 動作チェック用テストデータ.pdf|
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},140724603453459||1041|PDF Portable Document Format|
|{560C36C0-503A-11CF-BAA1-00004C752A9A},urn:schemas.microsoft.com:container:child||0|1重要系2003 Microsoft Excel ワークシート.xls|
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},140724603453459||0|Sheet3 Sheet2 Sheet1 ABC abc あいうえお アイウエオ 123.00|
|{560C36C0-503A-11CF-BAA1-00004C752A9A},urn:schemas.microsoft.com:container:child||0|1重要系2003 Microsoft PowerPoint プレゼンテーション.ppt|
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},140724603453459||1041|ここにテキスト|
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},140724603453459||1033|* * |
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},140724603453459||1041||

## csv

|attribute|propType|locale|contents|
|---|---|--:|---|
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},19|Search.Contents|0|動作チェック用テストデータ.txt|

## eml

|attribute|propType|locale|contents|
|---|---|--:|---|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},To||0|動作チェック用テストデータ|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},X-MimeOLE||0|Produced By Microsoft MimeOLE V6.00.2800.1506|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},Cc||0|動作チェック用テストデータ|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},5||0|動作チェック用テストデータ|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},6||0|動作チェック用テストデータ <test>|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},12||0|2005/08/17:06:36:21.000|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},X-Priority||0|3|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},X-MSMail-Priority||0|Normal|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},MIME-Version||0|1|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},par:content-type:charset||0|iso-2022-jp|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},Content-Type||0|text/plain|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},Content-Transfer-Encoding||0|7bit|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},att:pri-content-type||0|text|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},att:sub-content-type||0|plain|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},60||0|0|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},53||0|2005/08/17:06:36:21.000|
|{D1B5D3F0-C0B3-11CF-9A92-00A0C908DBF1},ROBOTS||0|boundary|
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},140728898420755||0|動作チェック用テストデータ.eml|
|{D1B5D3F0-C0B3-11CF-9A92-00A0C908DBF1},ROBOTS||0|boundary|

## htm

|attribute|propType|locale|contents|
|---|---|--:|---|
|{C82BF596-B831-11D0-B733-00AA00A1EBD2},4||1041|932|
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},19|Search.Contents|1041||
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},19|Search.Contents|1041||
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},19|Search.Contents|1041||
|{F29F85E0-4FF9-1068-AB91-08002B27B3D9},2|Title|1041|Untitled Page|
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},19|Search.Contents|1041||
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},19|Search.Contents|1041||
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},140724603453459||1041|      動作チェック用テストデータ.htm  |
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},140724603453459||1041||
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},140724603453459||1041||

## mht

|attribute|propType|locale|contents|
|---|---|--:|---|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},X-MimeOLE||0|Produced By Microsoft MimeOLE V6.00.2800.1506|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},5||0|動作チェック用テストデータ.mht|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},6||0|<Microsoft Internet Explorer 5 で保存する>|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},12||0|2005/08/17:06:50:53.000|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},MIME-Version||0|1|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},par:content-type:charset||0|shift_jis|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},Content-Type||0|text/html|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},Content-Transfer-Encoding||0|quoted-printable|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},att:pri-content-type||0|text|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},att:sub-content-type||0|html|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},Content-Location||0|file://C:\Documents%20and%20Settings\Administrator\デスクトップ\動作チェック用テストデータ.html|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},60||0|0|
|{AA568EEC-E0E5-11CF-8FDA-00AA00A14F93},53||0|2005/08/17:06:50:53.000|
|{D1B5D3F0-C0B3-11CF-9A92-00A0C908DBF1},ROBOTS||0|boundary|
|{C82BF596-B831-11D0-B733-00AA00A1EBD2},4||1041|932|
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},19|Search.Contents|1041||
|{F29F85E0-4FF9-1068-AB91-08002B27B3D9},2|Title|1041|動作チェック用テストデータ.mht|
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},19|Search.Contents|1041||
|{D1B5D3F0-C0B3-11CF-9A92-00A0C908DBF1},CONTENT-TYPE||1041|text/html; charset=shift_jis|
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},140724603453459||1041||
|{D1B5D3F0-C0B3-11CF-9A92-00A0C908DBF1},GENERATOR||1041|MSHTML 6.00.2800.1515|
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},19|Search.Contents|1041||
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},140724603453459||1041|動作チェック用テストデータ.mht |
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},140724603453459||1041||
|{D1B5D3F0-C0B3-11CF-9A92-00A0C908DBF1},ROBOTS||1041|boundary|

## txt

|attribute|propType|locale|contents|
|---|---|--:|---|
|{B725F130-47EF-101A-A5F1-02608C9EEBAC},19|Search.Contents|1041|動作チェック用テストデータ.txt|