とりあえず 今の版を filedisk-wk002.zipとして置いておく。
これはあくまで、移植のサンプル。実用として使うなら、オリジナルもしくは、上位版の CrossCrypt を使うことをお勧めする。
ただ、FileDisk を使うなら、中にある fdsetup.exe を使うと、MSYS で使えるようになる。MSYS を常用しているなら fdsetup.exe は便利かも知れない。
移植のまとめ
Windows Device Driver Programming Part 1、Part 2 という解説ページが非常に参考になった。
デバッグに便利だったツールは、
- ServiWin --- ドライバーを開始したり停止したりできる。状態を見るためにも必須。
- DebugView --- DbgPrint だけが、MinGW でのデバッグ手段。メッセージをキャプチャーして表示するプログラムで必須。
- DIP.zip (↑ 解説ページより) --- ドライバーを Install したり Uninstall したりできるツール。reboot しなくて良いので便利。
(オリジナル DIP (Driver Install Program) は、Install するとサービスを自動でスタートするようになってきてテストには不向きなので、手動になるように手を入れたものを filedisk-wk002.zip に添付)
ソースコードの修正ポイント (コンパイルまで)
- MinGW では、/mingw/include/ddk に DDK 関連のインクルードファイルが集まっている。だいたいは揃っている。足りない define は、ググるなり、オリジナルの DDK のヘッダを見るなりして補う。
- カーネルから call される関数は DDKAPI の アトリビュートが必要。warning が出るので、対処する。
- define されていることが期待されているものがいくつかある模様。_NTDDK_ もたぶんその一つ。コンパイルオプションで明示的に define する。
リンク
- 成功したリンクオプションは以下のもの
-static
-Wl,--subsystem,native -Wl,--image-base,0x10000 \
-Wl,--entry,_DriverEntry@8
-nostartfiles -nostdlib -lntoskrnl - ただし、足りないものがある。仕方がないので、オリジナルの DDK の ntoskrnl.lib から取り出す。
方法は、足りないものを call する stub0.o を作り、
ld -r -o stub.o stub0.o ntoskrnl.lib
ちなみに Windows Server 2003 DDK は、無償で ダウンロードできる。これをいったんインストールすれば、ntoskrnl.lib を取り出すことができる。
これをベースに何をしたいか
実をいうと、オリジナルの FILEDISK もかなり便利。ファイルを 仮想ディスクとして見せるだけでなく、-cd オプションをつけることにより、iso ファイルの マウントもできる。さらに、CrossCrypt になると暗号化もサポートしている。
それはそれで良いのだが、qemu 用の仮想ディスクフォーマットである qcow2 を 仮想ディスクに見せるものを(実験的にでも)作ってみたい。理由は copy-on-write の機能があるので、ランダムな Write を 再配置して性能を上げられるかも知れないから。暗号化もできるし、スナップショットも作れるので、便利で高速なものになるかも知れない。
というわけで、filedisk を qcow2 とくっつけてみようと思う。
メモ: filedisk の構造
DDKAPI をつけた関数は全部で 6個それらについて簡単に
DriveEntry() -- ドライバの初期化関数 (以下の関数を登録)
FileDiskCreateClose() -- Create/Close 共通関数
( 実はなにもしない )
FileDiskReadWrite() -- Read/Write 共通関数
(I/O スレッドに投げる)
FileDiskDeviceControl() -- ioctl (これも I/O スレッドに投げる)
FileDiskUnload() -- 終了関数
FileDiskThread() -- I/O スレッド
(キューイングされたリクエストを順番に処理)
IRP_MJ_READ:
buffer をアロケート( ExAllocatePool(PagedPool,))
ZwReadFile (同期 read )
buffer をコピー
buffer を 開放 (ExFreePool)
IRP_MJ_WRITE:
ZwWriteFile
IRP_MJ_DEVICE_CONTROL:
OCTL_FILE_DISK_OPEN_FILE:
ZwCreateFile()
IOCTL_FILE_DISK_CLOSE_FILE:
ZwClose()
FileDiskThread がほぼすべての処理をする。処理をする際は、キューから取り出して、同期 Read/Write を行う。
非同期の要素がなく、非常に簡単な構造。せめて、Write のバッファリングぐらいしたいもの。IRP_MJ_FLUSH_BUFFERS というのがあるから、それで バッファリングしたデータを書くようにすれば良いのだろう。