Windowsメタファイル(WMF)は、1990年代にMicrosoft Windows向けに設計された画像ファイル形式です。オリジナルのWindowsメタファイル形式はデバイス非依存ではありませんでしたが(配置ヘッダーを使用することで非依存性を高めることは可能でした)、ベクターグラフィックスとビットマップの両方のコンポーネントを含むことができました。SVGファイルと同様の動作をします。WMFファイルは後に、デバイス非依存性を実現した拡張メタファイル(EMFファイル)に置き換えられました。EMFファイル自体も、 EMF+ファイルによってさらに拡張されました。
基本的に、メタファイルには、画面に画像を表示するための描画コマンド、プロパティ定義、グラフィックオブジェクトからなるレコードのリストが格納されます。[ 1 ]使用される描画コマンドは、Microsoft Windows で描画に使用されるGraphics Device Interface (GDI) APIのコマンドと密接に関連しています。
メタファイルには大きく分けて3種類あります。WMFはWindows 3.0で導入された16ビット形式です。これはWord、PowerPoint、PublisherなどのMicrosoft Officeアプリケーションのネイティブベクター形式です。2024年4月現在 Windows Metafile Format仕様の改訂版18が利用可能です。[ 2 ] WMFファイルに取って代わったEMFファイルは、同じ原理で動作しますが、32ビットファイル形式であり、「コメント」レコード内にプライベートデータを埋め込むこともできます。[ 3 ] EMF+はEMFファイルの拡張機能であり、これらのコメントレコードに埋め込まれ、Windows GDI+に似たコマンド、オブジェクト、プロパティを使用して画像やテキストを表現できます。[ 4 ]
オリジナルの16 ビットWMF ファイル形式は、1992 年のWindows 3.1 SDK ドキュメントの第 4 巻[ 5 ]で完全に規定されていました(少なくとも他の巻の個々の関数と構造の説明と組み合わせれば)。しかし、その規定はいくつかの詳細について曖昧でした。これらのマニュアルは、クリック 同意のEULAやその他の特殊なライセンス制限なしに書店で入手可能な印刷書籍として発行されました (ソフトウェア バンドルの一部として購入された場合は、ソフトウェアが EULA の対象となるという一般的な警告のみ)。
時が経つにつれ、その歴史的な仕様の存在はほぼ忘れ去られ、代替実装の中には、既存の WMF ファイルからファイル形式を解明するためにリバースエンジニアリングに頼るものもあったが、これは困難でエラーが発生しやすかった。[ 6 ] 2006 年 9 月、マイクロソフトは、ファイル形式の実装者に対して特許権を主張しないことを約束するMicrosoft Open Specification Promiseの文脈で、より完全な形で WMF ファイル形式仕様を再び公開した。[ 7 ] [ 8 ]
マイクロソフトは後に、WMF ファイルは基本的なデバイス独立性を提供する「配置可能な」ファイル ヘッダーを使用していたにもかかわらず、デバイス独立性に関して実際の問題があったため、WMF ファイルを非推奨にして 32 ビット EMF ファイルを推奨しました。マイクロソフトは、この形式を使用する開発者がメタファイルにアプリケーション、場所、またはスケーリングのコメントを「埋め込んでいる」ことを発見しました。また、さまざまなアプリケーション固有の情報を提供するヘッダーをメタファイルに追加した開発者もおり、重大な互換性の問題を引き起こしていました。[ 9 ]そこで、1992 年にWindows NT 3.1で、マイクロソフトは拡張メタファイル形式 (EMF) [ 10 ]を導入しました。これはWin32 APIをベースとした形式で、デバイス独立性を組み込んでいました。[ 11 ] [ 9 ] これらは NT メタファイルとも呼ばれていました。[ 12 ] Windows XPと GDI+のリリースに伴い、レコードのセットを大幅に増やす必要があったため、マイクロソフトは既存の EMF ファイル形式の拡張機能として EMF+ をリリースしました。[ 10 ] [ 13 ]

WMF、EMF、EMF+ファイルはすべて、再生されてグラフィック出力を生成する一連のレコードで構成されています。一部のレコードは、グラフィックの描画方法を決定するために使用されるグラフィックオブジェクトを指定できるオブジェクトを定義します(たとえば、ペンは線の色と幅を指定します)。これらのオブジェクトはそれぞれメタファイルに格納され、メタファイルの処理中にグラフィックオブジェクトの使用状況を追跡するオブジェクトテーブルに配置されます。オブジェクトテーブルは、メタファイル内で定義されたグラフィックオブジェクト構造へのインデックスの連想配列です。
WMF および EMF ファイルは、EMF ファイル内の EMF+ レコードとは異なる方法でオブジェクト処理を行います。WMF および EMF ファイルが処理される際、オブジェクトが定義されると、レコードはオブジェクト テーブルに読み込まれます。オブジェクトが削除されると、オブジェクトはテーブルから解放され、識別子を再利用できます。特に、オブジェクトはレコード再生中に明示的に選択されるまで使用されません。[ 14 ] [ 15 ]これは EMF+ ファイルとは異なり、EMF+ ファイルもハッシュマップを介して連想配列を使用し、オブジェクトとオブジェクト識別子を記録します。ただし、オブジェクトを削除できる WMF および EMF ファイルとは異なり、既存のオブジェクトと同じインデックスを持つ新しいオブジェクトが作成されると、テーブルのエントリは新しいオブジェクトに置き換えられます。EMF ファイルでは、オブジェクトを使用する前に明示的に選択する必要もありません。[ 16 ]
| Windowsメタファイル | |
|---|---|
| ファイル名拡張子 | .wmf |
| インターネットメディアの 種類 | 画像/wmf [ 10 ] |
| 統一型識別子 (UTI) | com.microsoft.wmf [ 10 ] |
| フォーマットの種類 | ベクターグラフィックス |
| 拡張 | EMF |

WMF ファイルは元々デバイス非依存として設計されていなかったため、ファイルが記録された元のデバイスとは異なる出力デバイスでは再生できませんでした。この問題に対する部分的な解決策はAldus Corporationによって考案され、境界矩形、メタファイル バージョン、メタファイル サイズ、メタファイル内のオブジェクト数、メタファイル内の最大の単一レコードのサイズを追加する「配置可能な」ヘッダー「APM ヘッダー」[ 18 ]が追加されました。 [ 19 ] [ 20 ]これは後にMicrosoftによってWindows 2000からWMF フォーマットに組み込まれました。[ 21 ]
WMF ファイルは、一連のレコードによって構成されており、まず制御レコード (ヘッダー レコード[ 19 ] [ 22 ] 、前述のオプションの配置可能レコード[ 23 ])から始まり、ファイルの終わりレコード[ 19 ] [ 24 ]で終わります。
制御レコードによってカプセル化されるのは、イメージ自体を構成するレコードです。これらのレコードは、再生デバイスコンテキストと呼ばれるものの中で動作します。再生デバイスコンテキストとは、メタファイルがこの出力デバイスに「再生」される際に、デバイスのグラフィカル環境を構成するプロパティとオブジェクトの集合です。[ 25 ]
制御レコード以外のレコードは、大きく分けてビットマップレコード、描画レコード、オブジェクトレコード、状態レコード、エスケープレコードに分類できる。
ビットマップレコードは、ビットマップ画像を管理および出力します。
図面記録はグラフィック出力を生成する。
オブジェクトレコードはグラフィックオブジェクトを作成および管理します。WMF ファイルには、グラフィックオブジェクトと構造オブジェクトの 2 つの大まかなカテゴリのオブジェクトがあります。構造オブジェクトは WMF で明示的に作成または削除されることはなく、代わりに複雑な構造になります。たとえば、BitmapCoreHeader にはデバイス非依存ビットマップの寸法とカラー形式に関する情報が含まれており、[ 52 ]これは DeviceIndependentBitmap オブジェクトの一部です。[ 53 ]一方、グラフィックオブジェクトはグラフィック出力のパラメータを指定し、WMF の再生中に再生デバイスコンテキストを設定します。[ 54 ]
グラフィックオブジェクトには、ブラシ(グラフィックの領域をどのようにペイントするかを定義するブラシのスタイル、色、パターンを定義する)、フォント(テキストの表示方法に影響を与えるプロパティを定義する)、パレット(アプリケーションによって定義されるデバイス非依存の値として色を指定する)、ペン(線のグラフィック属性を指定する)、領域(形状を定義する線分と曲線セグメントを指定する)などがあります。[ 54 ]
ステートレコードは、再生デバイスコンテキストのグラフィックプロパティを管理します。[ 67 ]

エスケープレコードは、WMFレコードタイプとして定義されていないレコードを介してメタファイルの機能を拡張する手段です。各エスケープレコードには、レコード関数、エスケープ関数、および場合によってはエスケープデータが含まれます。
以下のエスケープレコードがWMFファイルを構成します。
アボート エスケープ レコード周辺のエスケープ レコードに重大な脆弱性が見つかりました。このレコードには、アボート プロシージャ コードが格納されています。これは、Windows システム ( CVE - 2005-4560を参照) とWine プロジェクト( CVE - 2006-0106を参照) に影響を与えました。Secunia によると、「この脆弱性は、特別に細工された SETABORTPROC 'Escape' レコードを含む Windows メタファイル ファイル ('.wmf') の処理エラーが原因です。このようなレコードにより、WMF ファイルのレンダリングが失敗したときに任意のユーザー定義関数を実行できます。」 [ 142 ] Windows 3.1 SDK ドキュメントによると、WMF の脆弱性が発見されるずっと前に、SETABORTPROC エスケープは廃止され、Windows 3.1 で同名の関数に置き換えられました。[ 143 ]しかし、廃止されたエスケープ コードは、Windows 3.0 用に作成された (または少なくとも下位互換性のある) 16 ビット プログラムとの互換性のために保持されました。この変更は、マイクロソフトがWindows NT向けにGDIの32ビット版を再実装していた時期とほぼ同時期に発生しており、この脆弱性はおそらくその作業中に発生したものと考えられる。
スティーブ・ギブソンがマイクロソフトが意図的にコードにバックドアを仕込んだと非難した後、 [ 144 ] [ 145 ]マーク・ルシノビッチは反論し、次のように述べた。
...フォーマットが設計された当時は状況が異なっていました。Windows 3.1の「大容量」メモリモデルでは、コードは本質的に場所に依存しず、Windowsはパッチが適用されなかったため、Windowsとアプリケーションの両方がアプリケーション関数をWMFファイルにコピーするだけで、後続の実行セッションで同じアプリケーションによって再生されたときに動作すると想定できました。いずれにせよ、開発者がアプリケーションが中止手順を含むディスク上のメタファイルを作成することを想定していたかどうかは明らかではありません。また、MicrosoftのStephen ToulouseがSteveの主張に対するMicrosoftの反論で指摘したように、1990年代初頭のセキュリティ環境は今日とは大きく異なり、WMFファイルに格納されているものを含め、すべてのコードは本質的に信頼されていました。[ 146 ]
シマンテック・セキュリティ・レスポンス(米国)のピーター・フェリー氏もギブソン氏の意見に異議を唱え、次のように述べている。
ギブソン氏は、SetAbortProc ハンドラを実行するためにスレッドが作成されると主張しました。実際には、ハンドラを実行するためにスレッドは作成されません。これはパーサーによって呼び出されるコールバックであり、パーサーはコールバックが戻るまで待機する必要があります。そうしないと、関数の目的 (印刷を中止する) が失われます。ギブソン氏は、自身の認めているように、ドキュメントを読んでいませんでした (実際には、Microsoft の Web サイトで無料で入手できるにもかかわらず、見つけられなかったと主張しました)。また、デバイス コンテキストが関数ハンドラで使用できないと主張しました。もちろん、デバイス コンテキストは関数ハンドラで使用できます。これは、関数に渡される 2 つのパラメーターの 1 つです (上記を参照) し、印刷を中止するために必要です。最後に、ギブソン氏は、制御フローが Windows に戻れないと主張しました。これは、関数が戻り、スタックに渡されたパラメーターを破棄するだけの問題です。レコードが正しく構成されていれば、Windows は以前と同様にファイルの解析を続行します。...ギブソン氏は、いくつかのことについて推測していたことを認めています。残念ながら、彼の推測は間違っていた。今となっては、私たちはもっとよく分かっていると思う。[ 147 ]
| 拡張メタファイル | |
|---|---|
| ファイル名拡張子 | .emf |
| インターネットメディアの 種類 | 画像/emf [ 10 ] |
| 統一型識別子 (UTI) | com.microsoft.emf [ 10 ] |
| フォーマットの種類 | ベクターグラフィックス |
| 拡張 | WMF |
| 拡張 | EMF+ |

EMF ファイルには 3 つのバージョンのヘッダーがあります。オリジナルのヘッダーは画像のコンテナにすぎず、2 番目と 3 番目のバージョンはオリジナルのヘッダーをカプセル化し、ピクセル フォーマット レコードと OpenGL レコードのサポートを含み、3 番目のバージョンは 2 番目のヘッダー拡張をカプセル化し、メートル法を使用してデバイス表面の距離を測定する機能を追加することで、EMF の精度とスケーラビリティを向上させます。[ 148 ]
各 EMF ヘッダーは EMR_HEADER レコードで始まり、メタファイル イメージが記録されたデバイスの関連プロパティを記録します。元の EMF ヘッダーには 80 バイトのヘッダーとオプションの可変長の説明文字列があります。[ 149 ]他のメタファイルには、元のヘッダーをカプセル化する拡張フィールドが含まれています。EmfMetafileHeaderExtension1は、元の EMF ヘッダーの直後に挿入されるレコードで、ピクセル フォーマット記述子があるかどうか、ヘッダー内の記述子オブジェクトへのオフセット、およびメタファイルにOpenGLレコードが存在するかどうかを指定するフィールドがあります。 [ 150 ]ピクセル フォーマット記述子は、描画サーフェスの機能と、ピクセルがRGBAでエンコードされているか、カラー テーブルへのインデックスであるかを指定します。[ 151 ]EmfMetafileHeaderExtension2は、レコードの直後に挿入されるレコードでEmfMetafileHeaderExtension1、デバイス サーフェスをマイクロメートル単位で測定するための X 値と Y 値を含む 2 つのフィールドがあります。[ 152 ]
WMFファイルと同様に、EMFファイルでもレコードを機能別に分類できます。ただし、EMFファイルにはWMFファイルよりも多くのレコードタイプが存在します。レコードは、制御、ビットマップ、クリッピング、コメント、描画、エスケープ、オブジェクト作成、オブジェクト操作、OpenGL、パスブラケット、状態、変換レコードに分類できます。
Windows XPのリリースに伴い、拡張メタファイルフォーマットプラス拡張機能(EMF+)フォーマットが導入されました。EMF+は、WMF/EMFがGDIへの呼び出しを保存するのと同様の方法で、GDI+ APIへの呼び出しをシリアル化する方法を提供します。
また、圧縮Windowsメタファイル(WMZ)および圧縮Windows拡張メタファイル(EMZ)と呼ばれるWindowsメタファイルの圧縮バージョンもあり、[ 153 ]これらは基本的にそれぞれgzipで圧縮されたWMFおよびEMFファイルです。
WMF形式は、イメージを復元するためにWindows GDIレイヤーによって実行されるように設計されていますが、WMFバイナリファイルにはこのイメージを構成するGDIグラフィックプリミティブの定義が含まれているため、WMFバイナリファイルをレンダリングしたり、他のグラフィック形式に変換したりする代替ライブラリを設計することも可能です。
これらのオペコードは、私がそれが何であるかを知らないため、また既知のドキュメントがないため、未実装です。
<55> セクション 2.3.2.3: Windows NT 3.1、Windows NT 3.5、Windows NT 3.51、および Windows 95: この機能はサポートされていません。