出くわしたのは偶然、発生は必然。


 RegCon 新版(v2.3 現状では未リリース)に付加していたレジストリ状態チェックシステムが反応した。Registr!pのレジストリ解析エンジンを搭載し、再構成前後で幽霊キーの有無をチェックするのである。ただし、問題があっても修復はしない(できない)。

 何度と無く RegCon を掛けてきて(しかも同じ版)、このとき初めて警告が出たのである。何かの操作の中で幽霊キーを発生させる動きがあったに違いない。
 自分に思い当たるのは、RegConまたはRegCleanの頻繁なる実施である。これらが原因だと困るなぁと思いつつ、幽霊キーの存在するレジストリを Registr!p で解析してみた。
...
2. Key Check-sum Check
Good : 340
Bad : 2
.DEFAULT\Software\Microsoft\Windows\CurrentVersion\Applets\Volume Control\SigmaTel Audio\ボリューム コン\
.DEFAULT\Software\Microsoft\Windows\CurrentVersion\Applets\Volume Control\SigmaTel Audio\モノラル出力\
GhostKey: 2
.DEFAULT\Software\Microsoft\Windows\CurrentVersion\Applets\Volume Control\SigmaTel Audio\録音コントローソ
.DEFAULT\Software\Microsoft\Windows\CurrentVersion\Applets\Volume Control\SigmaTel Audio\録音コントローソ
...

 サウンドのプロパティの設定のところに障害が発生したようだ。

 過去のレジストリのバックアップを見ていくと、上のレジストリパスのうち、SigmaTel Audioのキー以下は、ずっと存在していなかった時期がある。最初は存在せず、サウンドのプロパティウインドウを開いたときに生成されるのかも知れない。
 もともと無かったものであれば、削除しても問題はない。問題のキーを削除して、再現性を調べてみる。

 上のようにSigmaTel Audioのキーを消した(存在しない)状態で、サウンドのプロパティを設定してみる。レジストリエディタは閉じないでそのままにしておく。

 レジストリエディタのレジストリツリーをF5キーで最新の状態にしてみるとキーが増えており、「録音コントロ...」をクリックしてみると、エラーとなった。

 この状態で無理矢理「録音」に関するプロパティを設定したらどうなるだろう?
 プロパティウインドウでチェックボックスにチェックを入れてOKをクリックし、再び窓を開いてみると、当然、設定情報は保存されてなかったが、レジストリの方には同名のキーが増えてしまった。さらに、同名のキーも幽霊化していた。

 さて奇妙なのは「ボリューム コン」という名のキーである。おそらく「ボリュームコントロール」とか、そんな名前が正しいところなのだろうが、なにゆえこのような中途半端な状態で収まっているのか。しかもこのキーは幽霊ではない。直下の「モノラル出力」キーも正常なキーであり、どちらも含まれているレジストリデータにアクセスできる。

 これらから推測するに、SigmaTel Audio以下にレジストリキーを作成する際のキー名称文字列の転送ロジックに原因がありそうである。つまり、キー名称を転送するときに文字列長を正しく指定できていないために、転送後の文字列が欠けてしまったり、さらには2バイト文字が先の1バイトしか転送されないという中途半端な現象も引き起こしているのではないか、ということだ。

 レジストリをもっと詳しく解析してみよう。 Registr!p の詳細解析レポートを作成する。
 できたレポートからには、実に奇妙で、かつ衝撃的な証拠が現れていた。

 青字がレジストリキーの長さ(16進数)、赤字がキー名のバイナリダンプである。データの性格からして毎回同じ名前のレジストリキーにアクセスする必要があるわけで、だとすれば、毎回同じレジストリキー名を使って設定しているに違いないにも関わらず、幽霊化した2つのレジストリキーのダンプ長が違うとはどういうことだろうか。文字列の途中に null が混じるのもおかしい。null は文字列の終わりを表すが、他のキーを見てもらえば分かるように、文字列終わり文字の null は含まずにレジストリに格納されるのが通常である。幽霊化したキー名の本当の名前は「録音コントロー云々...」と思われるが、化けた「ル」の文字コードをレジストリアクセスAPIが解釈したときに幽霊化したとは考えにくい。なぜなら、「モノラ出力」キーは正常に格納できているのだから。

 レジストリキーを作るときに問題が起きていると思うのだが、Win32 API リファレンスよりレジストリキー作成関数の仕様を抜粋してみると、

LONG RegCreateKeyEx(

HKEY hKey,
LPCTSTR lpszSubKey,
DWORD dwReserved,
LPTSTR lpszClass,
DWORD fdwOptions,
REGSAM samDesired,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
PHKEY phkResult,
LPDWORD lpdwDisposition
);


// handle of an open key
// address of subkey name
// reserved
// address of class string
// special options flag
// desired security access
// address of key security structure
// address of buffer for opened handle
// address of disposition value buffer

赤字の変数で作成したいレジストリキーの名前を設定する。名称文字列の長さを指定する変数はないので、lpszSubKey が示す文字列の中身が、キー作成前に既に壊れているのだと思われる。変なトコロに null があるとか、null が無いとか。この推論の裏付けはRegMonExというレジストリアクセスモニタで得られた。

 キーの存在を確認するところで既に化けたキー名を使って調べている(1)。それが存在しないのでキーを作成しているが、何故か成功し(2)、データを格納できている。後で同じレジストリキーを開こうとしているが、化け方が同じため、いちおう成功している(3)。キーを開くのに成功した場合には幽霊キーが増えることはないのだが、ならば2つの「録音コントロー」キーが存在した事実はどうなるのか。有り得るとすれば、文字の化け方が不定だということだ。この例の場合は偶々化け方が同じだった、というわけだ。null までがキー名として設定されるということは、キー名を格納している変数をスタックに確保している(dymanic変数)とか、そのような根因ではないだろうか。

 長々と説明してきたが、要は、SigmaTel Audio 日本語ドライバの、レジストリアクセスに関するロジックにバグがある可能性が高い、ということだ。


 ああ、こんな解析に時間を費やしているわけにはいかないのに。だが、幽霊キーが、レジストリ再構成以外で作成される瞬間を初めて見られたので、良しとするかな。
 そうそう、とりあえず、RegConもRegCleanも無実であり、それも良しとしよう。




indexへ戻ります