"APIで学ぶWindows徹底理解"のPart16 - Part21までの読書メモです。
この読書メモのスタンス、およびサンプルコードの入手については以下を参照して下さい。
読書メモ/「APIで学ぶWindows徹底理解」
本PartではVC++の機能を中心に解説されており、該当MSDNは全て、下記ナビゲーション以下に存在する。
"MSDN Library" > "Development Tools and Languages" > "Visual Studio 2010" > "Visual Studio" > "Visual Studio Languages" > "Visual C++"
他サンプル:
本読書メモ、オリジナルサンプルコード。
コンパイル方法:
cl 16_01_MessageBoxA.cpp user32.lib cl 16_02_MessageBoxW.cpp user32.lib
SJIS, UNICODEの二種類の文字列を、一方はMessageBoxA()で表示し、もう一方はMessageBoxW()で表示する。当然MessageBoxA()ではUNICODE文字列が文字化けし、MessageBoxW()ではSJIS文字列が文字化けする。
本読書メモ、オリジナルサンプルコード。
コンパイル方法:
cl /D _UNICODE /Fe16_03_gtrm_unicode_u.exe 16_03_gtrm_unicode.cpp cl /Fe16_03_gtrm_unicode_nou.exe 16_03_gtrm_unicode.cpp
C RunTime Library (CRT) の汎用テキストマッピング機能を確認するサンプル。"/D _UNICODE"付でコンパイルしたのはUNICODE対応、網一方はUNICODE非対応となる。実行すると_getts_s()で入力待ちになる。適当な文字列を入力すると、入力された文字列とその文字「数」を表示する。日本語(全角文字列)を入力した場合、"/D _UNICODE"有無で「数」のカウントが変わり、またバッファサイズも変わる。
本書173p, リスト2, 3のVC++移植版+簡略化版。
コンパイル方法:
rc fonttest.rc cl /D UNICODE /D _UNICODE /Fefonttest_u.exe fonttest.cpp \ user32.lib comdlg32.lib gdi32.lib fonttest.res cl /Fefonttest_nou.exe fonttest.cpp \ user32.lib comdlg32.lib gdi32.lib fonttest.res
実行するとメニュー付のウインドウが表示される。UNICODE対応版では最初からウインドウ内の左上に「フォント表示の実験」という文字列が表示されるが、UNICODE非対応版では文字化けしてしまっている。メニューから"Font" -> "ChooseFont"をクリックすると、フォント選択ダイアログボックスが表示される。適当にフォントを選択すると、フォント名がメッセージボックスで表示される。ウインドウ内の適当な場所を左クリックすると、その場所に選択されたフォントで「フォント表示の実験」という文字列がTextOut()で描画される。
アセンブラレベルでのSEH実装について詳しく知りたい:
※上のリンクにも含まれていますが、下記の小山圭介氏のWebサイトもおすすめです。
「APIで学ぶWindows徹底理解」と併せて読むか、更に発展的な内容を調査する時に参照したいWebサイトです。
本書180p, リスト6のVC++移植版。
コンパイル方法:
cl /c 18_01_seh_by_asm.cpp ... ...\18_01_seh_by_asm.cpp(57) : warning C4733: \ インライン asm は 'FS:0' に割り当てています : \ ハンドラは安全なハンドラとして登録されていません。 ...\18_01_seh_by_asm.cpp(80) : warning C4733: \ インライン asm は 'FS:0' に割り当てています : \ ハンドラは安全なハンドラとして登録されていません。 link /SAFESEH:NO 18_01_seh_by_asm.obj
"__try", "__except"キーワードの機能をインラインアセンブラで手動実装したサンプル。warning C4733についてはセキュリティ上の警告であり、本来は避けるべきFS:[0]の操作をしているので表示されて当然である。もちろんサンプルコードの趣旨として、この警告は無視して構わない。
FS:[0]をインラインアセンブラなどで操作し、手動でSEH情報を書き換える手法は容易に各種BufferOverflowと合わせたコードインジェクション攻撃に発展する。これを防ぐ為、有効なハンドラの一覧(テーブル)をイメージ中に埋め込み、例外ハンドラ実行時にこの一覧に載っているハンドラかチェックする仕組みがある。このチェック機能を有効にするのがリンカ(link.exe)の"/SAFESEH"オプションである。
本来であればマクロアセンブラの ".SAFESEH handler" 疑似命令を組み合わせ、安全なハンドラを指定するのが正攻法であると思われるが、今回は簡略の為あえて "/SAFESEH:NO" をリンカオプションに指定し、例外ハンドラのチェックをスキップさせた。
本書182p, リスト7のVC++移植版。
コンパイル方法:
cl /c 18_02_seh_by_asm2.cpp (... 同様に warning C4733 が表示されるが、無視する。 ...) link /SAFESEH:NO 18_02_seh_by_asm2.obj
例外ハンドラで例外に対処した後、実行再開位置をEIP, EBP, ESPの操作を通じて変更するサンプル。
本書188p, リスト7のVC++移植版。
コンパイル方法:
cl 19_01.cpp ..\PrintErrorMsg.obj
ファイル先頭から50MBを非同期に読み込むサンプル。試す場合は、読み込むサイズ(ソース中でdefine)を変えてみたり、FDDから読み込ませてみるとよい。
本書191p, リスト10のVC++移植版。
コンパイル方法:
cl 19_02.cpp ..\PrintErrorMsg.obj
ReadFileEx()を使ったサンプル。
Windowsでのデバイスドライバ開発全般:
デバイスドライバ開発初心者向け:
WDK付属サンプルの "src\input\kbfiltr" と類似している為、そちらを参照のこと。