WindowsXP からは DLL の検索順序が変わり、それまで簡単だった DLL のすり替えが少し難しくなった。
レジストリを書き換えることで以前の検索順序にする事はできるものの、これを行ってしまうと他のソフトの動作にも支障をきたす可能性があるため別なアプローチで行う方が望ましい。
CreateRemoteThread を使うと任意のプロセスに対してスレッドを注入できる。これを使うと比較的簡単に API フックが実現できるのだが、DirectX は COM が中心になっているためにAPIの差し替えを後々行ってもその効果が現れるタイミングが非常に少ない(インターフェイスを再取得するシーンがくるまでは以前のポインタを使いまわすため)。
なので CreateRemoteThread を使って注入する場合には恐らく CreateProcess でプロセスを立ち上げる時にメインスレッドを一旦サスペンド状態で立ち上げた後、スレッドを注入して API の置換をしなければいけないような気がする(試してないけど!)。
また、CreateRemoteThread はどうも Win9x 系ではサポートされていないらしい。手元には Win9x 系のマシンもないし対応は必須要件ではないけども、すり替え用の dsound.dll は Win9x 系でも動くように作ったつもりなので、せっかくだから CreateRemoteThread は使わずに動くようにしておきたい。
で、これらを踏まえた上で動くものを作るためにはそれなりに泥臭い処理が必要になる事がわかってきたのでそのメモのためにここに書いておく。
この処理でとても参考になったのは
gdi++ での API フック手順。
gdi++ でも最初の手順はやはり CreateProcess でメインスレッドをサスペンド状態にして立ち上げる。そして CreateRemoteThread を使うのではなく、
exe のエントリポイントのコードを直接書き換えて目的の DLL をロードする処理を注入する。そのプロセス上で DLL がアタッチされてしまえば、後は普通に API フックを行えばいい。
gdi++ の場合はフックした API の元の実装を呼んでいる間に呼ばれる別のフック中のAPIの呼び出しも監視する必要があるために関数本体を書き換えているが、今回の場合はそこまで深い監視は必要ないはずなのでもう少しシンプルなフックだけでいけそうだ。
と、思う。