Win32のFindExecutableでイタイ目にあった

FindExecutableというWin32APIがあって、こいつの動きに随分と痛い目にあったのでメモを残す。
ちなみにここで触れられている、最初のスペースまでしか取得できないなバグとは別のはまり方をした。知ってる人には当たり前なのかも知れないけれど。
MSDNの説明によると

指定されたファイル名に関連付けられている実行可能(.EXE)ファイルの名前とハンドルを取得します。
HINSTANCE FindExecutable(
  LPCTSTR lpFile,       // ファイル名文字列へのポインタ
  LPCTSTR lpDirectory,  // 既定ディレクトリ文字列へのポインタ
  LPTSTR lpResult       // 返される実行可能ファイル文字列を
                        // 保持するバッファへのポインタ
);

とあるが、じゃあWindowsで「ファイル名に関連付けられた実行可能ファイル」ってなんだろう?
例えば、ローカルPCに保存された拡張子.htmlのファイルをダブルクリックする、何が起こるだろうか?
IEが開く場合もあれば、Operaが起動する人もいるだろうし、notepad.exeが開く人もいるかも知れない。
ダブルクリックしたら、notepad.exe(メモ帳)でhtmlファイルのソースが見える設定で(XPだとアイコンがIEのままの状態で)このAPIを使うとどうなるか。
この状態で、FindExecutableの引数に aaaa.html というファイルを渡すと、notepad.exeのフルパスが得られるか(間にスペースはない)というと、そうはいかない。e_c_e_tの環境ではiexplore.exeが取れて焦った。
で、この謎を解くには、関連付けの仕組みを理解する必要がある。
WindowsXPや2000(Vistaや7は未確認)では「関連付け」はこういう3段階の構造となっている

A エクスプローラの設定 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.html
B ユーザの関連付け HKEY_CURRENT_USER\Software\Classes\.html
C システムの関連付け HKEY_LOCAL_MACHINE\SOFTWARE\Classes\.html

エクスプローラでダブルクリックしたら、Aの設定が動く。
FindExecutableはBの設定を読むらしい。つまり、エクスプローラの設定は見ない。


細かい話になると、BやCはここからファイルタイプを探して、ファイルタイプに関連されたProgIDのプログラムがshellのopenコマンドにわり付く。このopenに割ついた実行ファイルのフルパス(と引数)がFindExecutableの返り値になるらしい。
実際には、BとCとが合体した設定が、HKEY_CLASS_ROOTの下に入っているので、確認はそこを使ったほうが便利。
あぁ、レジストリの話だから自己責任でね。