こんにちは、なおき~です。 皆さんは、職場や自宅では、どの Windows OS を使用されていますでしょうか? 先日、知人から 64 ビットの Windows OS は、アプリケーションの互換性が心配だし、デバイス ドライバがあるかどうかわからないので、敷居が高いと言われました。 Windows Vista のリリース直後に 64 ビットに移行してしまった私としては、既に気にならないのですが、移行するときは、アプリケーションの互換性やデバイス ドライバの有無は、少なからず心配になりましたので、知人の心配も尤だと思います。 デバイス ドライバを開発されている方の立場からすると、過去に開発したデバイス ドライバの互換性が気になると思いますし、最近では、 Windows 7 のリリースされるのが、気になるのではないかと思います。また、 Windows 7 だけでなく、 Windows Server 2008 R2 もリリースされると思います。 特に、 Windows Server 2008 R2 は、 32 ビット版は提供されず、 64 ビット版のみになり、サーバーの Windows OS は、完全に 64 ビットになります。 対して、ノート PC もデスクトップ PC も、 4GB 以上のメモリを搭載 PC が増えてきて、クライアント側も、ひしひしと 64 ビット化を感じます。 ユーザ モードのアプリケーションは、 WOW64 (Windows 32-bit on Windows 64-bit ) という機能のおかげで、 32 ビットでも動作します。 しかしながら、デバイス ドライバは、 64 ビット版の Windows OS では、ユーザ モードやカーネル モードに関わらず、 64 ビットである必要があります。 64 ビット化が近づきながらも、 32 ビット版の Windows OS も、まだまだ現役という現状は、 32 ビットと 64 ビットのデバイス ドライバを開発する必要があると思います。 2 つもデバイス ドライバを開発しなければいけないのか!と思われるかもしれませんが、開発自体は、そんなに大変ではありません。 何故ならば、ほぼソース コードレベルで互換が可能であるということです。つまり、 x86 ・ x64 ・ ia64 それぞれの Build Environment で build すれば、ほとんど終了してしまうのです。 しかし、ソース コード レベルで互換が可能ということは、過去に開発した全ての 32 ビットのデバイス ドライバに対して、ソース コード レベルで互換性を保証しているわけではありません。意識して、コーディングすれば、ソース コード レベルの互換が可能ということです。また、 100% のソース コードの互換ではなく、若干 考慮しなければいけないところもあります。 とはいっても、ソース コードの互換が可能なぐらいの差異なので、過去に開発した 32 ビットのデバイス ドライバも比較的 容易に移行できるのではないかと思います。 まず、よく使用するデータ型は、このようになっており、ポインター型は、全て 64 ビット長になります。 データ型 ビット数 LONG, INT 32 ビット符号付き ULONG,UINT,DWORD 32 ビット符号なし LONG32, INT32 32 ビット符号付き LONG64, INT64 64 ビット符号付き ULONG32,UINT32,DWORD32 32 ビット符号なし ULONG64,UINT64,DWORD64 64 ビット符号なし データ型で、よくある問題として、 -1 を 0xFFFFFFFF とコーディングしたり、 0×80000000 以上のアドレスは、カーネル アドレスと判定するなど、 32 ビット長に依存しているコーディングです。 こういったのは、 -1 にするなど、ビット長に依存しないようにコーディングするか、ヘッダ ファイルに定数を定義するなどの工夫が必要になります。 また、定数を定義する場合に、 _WIN64 や _IA64_ や _AMD64_ を使用すると、 Build Environment で適切に定義してくれるので便利だと思います。 なお、このようなコーディングは、デバイス ドライバのみならず、ユーザ アプリケーションでも必要な一般的な考慮点で、ユーザ モードのデバイス ドライバは、このような一般的な考慮点のみで、ほぼ 64 ビットに移行できると思います。 強いて言えば、プリンタ ドライバの場合、 32 ビットのユーザ アプリケーションから呼び出される場合、 SPLWOW64.EXE 経由で呼び出されるため、プロセス空間が、ユーザ アプリケーションではない点です。ただ、通常 プリンタ ドライバは、動作するプロセス空間を認識する必要がないので、問題にならないと思いますが、もし、何らかの事情で、プロセスを意識しているコードがあったとしたら、変更が必要かもしれません。 対してまして、カーネル モードのデバイス ドライバの代表的な考慮点は、 32 ビットのユーザ アプリケーションから、 DeviceIoControl() が呼ばれる場合の実装だと思います。 DeviceIoControl() で指定する InputBuffer や OutputBuffer の構造体は、 IOCTL に依存します。 IOCTL が、デバイス ドライバが管理していると同様に、 InputBuffer や OutputBuffer の構造体も管理する必要があります。そのため、 32 ビットのユーザ アプリケーションから、 DeviceIoControl() が呼ばれたら、 32 ビット用の構造体に変更する必要があります。 WDK のサンプル コード (%BASEDIR%src srcstorageclassclasspnpclass.c) にわかりやすい例があるので、そのコードを抜粋してみます。 ClassDeviceControl() という関数で、 IOCTL_SCSI_PASS_THROUGH と IOCTL_SCSI_PASS_THROUGH_DIRECT という IOCTL のハンドリングをしています。 _WIN64 の場合のみ、 32 ビットのプロセスから呼ばれたかどうかを IoIs32bitProcess() という関数で確認しています。もし、 32 ビットのプロセスから呼ばれたのであれば、 SCSI_PASS_THROUGH 32 という構造体でサイズチェックをしています。 ———- 抜粋 ———- #if defined (_WIN64) if ( IoIs32bitProcess (Irp)) { if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSI_PASS_THROUGH 32 )){ Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; ClassReleaseRemoveLock(DeviceObject, Irp); ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT); status = STATUS_INVALID_PARAMETER; goto SetStatusAndReturn; } } else #endif { if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSI_PASS_THROUGH)) { Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; ClassReleaseRemoveLock(DeviceObject, Irp); ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT); status = STATUS_INVALID_PARAMETER; goto SetStatusAndReturn; } } ———- 抜粋 ———- build するだけで、終了すると書きましたが、実際に本格的な 64 ビット化する場合は、ソース コードをちょっと変更して re-build するだけでなく、テストをしたり、ドライバ署名をしたりと色々と必要になるので、軽い気持ちで、 64 ビット化することはできないと思いますが、将来的な 64 ビット化に備えて、過去に開発したデバイス ドライバや現在 開発しているデバイス ドライバを 64 ビットの Build Environment で re-build してみたり、ソース コードを調整してみたり、少しずつ準備をされるとよいと思います。 なお、細かなチェックリストは、 WHDC のサイトに公開されているので、本格的な移行際には、このチェックリストを活用していただくのがいいと思います。 64 ビット Microsoft Windows ドライバー用のチェックリスト http://www.microsoft.com/japan/whdc/driver/kernel/64bit_chklist.mspx ちなみに、 64 ビットの Dump ファイルの調査は、少々厄介かもしれません。なにせ、引数が レジスタ 渡 し になってしまったので、 32 ビットのようにお気軽に引数を確認することができません。 ETW ト ー レス など、他のトラブルシューティングの方法を充実させなければいけないかもしれません。 トラブルシューティングについては、いずれ紹介したいと思います。 それでは、また~