やっと原因が分かった。
源ノ角ゴシックや源ノ明朝のSuper OTC版(言語・ウエイト全部入り)のフォント名が長すぎて、.NET Frameworkがバグっていた。 アンインストールして、Region-specific Subset OTFを入れ直しましょう。
moraダウンローダー
moraという音楽配信サイトがある。 クールごとにアニソンをまとめたページがあって便利。 DRMフリー。 過去にはダウンロードは10回までという制限があったが、(明記はされていないものの)今はこの制限も無くなったっぽい。
専用のmoraダウンローダーがある。 これを使うと、複数の曲をまとめてダウンロードすることができ、ファイル名を変えてフォルダ分けして保存してくれる。
今期のアニソンを買ってダウンロードしようとしたら、「moraダウンローダーは動作を停止しました」と出てきて起動しなくて困った。
源ノ角ゴシックと源ノ明朝
「げんのかくごしっく」「げんのみんちょう」と読む。Adobeが配布しているOSSフォント。
フリーなのにウェイトが多くて楽しい。 1個のフォントをソフトウェア処理で太字にするのは素人で、プロは最初から太さを変えて作られたフォントを使うらしい。
ダウンロードページ(ゴシック、明朝)に行くと、種類が色々あってどれをダウンロードして良いのか迷う。 最近のOSにしか対応していないが、Super OTCというのをダウンロードすれば、1ファイルで言語もウェイトも全て揃う。
これが間違いの元だった……。
フォントをインストールすると、レジストリのHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts
に次の2個の値が追加される。長さはどちらも259文字。
源ノ角ゴシック ExtraLight & Source Han Sans K ExtraLight & Source Han Sans SC ExtraLight & Source Han Sans TC ExtraLight & 源ノ角ゴシック Light & Source Han Sans K Light & Source Han Sans SC Light & Source Han Sans TC Light & 源ノ角ゴシック Normal & Source Han Sans K Normal & Sou
源ノ明朝 ExtraLight & Source Han Serif K ExtraLight & Source Han Serif SC ExtraLight & Source Han Serif TC ExtraLight & 源ノ明朝 Light & Source Han Serif K Light & Source Han Serif SC Light & Source Han Serif TC Light & 源ノ明朝 & Source Han Serif K & Source Han Serif SC
中身を見ると、倍くらいの長さのフォント名を書きたがっているように見えるので、どこかで切り捨てられているらしい。
Adobeがこのフォント名にしているならば文句を言いたいけれど、セットになったフォントの名前を&
で連結してレジストリの値名にしているのはWindowsだろうか?
調べ方
moraダウンローダーは黙って落ちるので、何も情報は得られない。 .NETだから普通にデバッグはできないし、どうするのだろうと思ったけど、便利なソフトがあった。
逆アセンブル、逆コンパイル等のソースコード解析作業ではなく、moraダウンローダーがスルーしている例外を調べる目的で使う。 分かりにくいけど「build passing」のバッジからビルド済みのバイナリがダウンロードできる。
このソフト上で実行すると例外が発生したときに、例外の中身が見られる。
$exception
変数のInnerException
を順番に見ていくと大元の原因が分かる。
レジストリが何とかで落ちているので、あとはSysinternals SuiteのProcess Monitorを使うと、レジストリにどのような操作をしているかが分かる。 長さ512(たぶんバイトなので256文字)のバッファで読もうとしてエラーが返っていた。 惜しい。 あと4文字長ければ……。
RegEnumValueがERROR_MORE_DATA
を返しているだけなので、バッファーオーバーフローなどではなく、細工されたフォントをインストールしてmoraダウンローダーを起動するとシステムを乗っ取られるとかはない。
詳細
https://github.com/kusano/mora_not_run
.NET Frameworkの3.5以下の版には、RegistryKey.GetValueが256文字以上の値の名前を列挙できないというバグがあるらしい。 そんな制約は書いてないぞ。
試しに.NET Framework 2.0でウィンドウを作ってみたけれど、フォントの一覧は読みにいかなかったので、何がトリガーなのか分からない。
moraダウンローダーは.NET Frameworkを使っているだけなので、対応するなら.NET Frameworkのバージョンを上げるしかなさそう。
Registry Element Size Limits (Windows)
MSDNを見てみると、値の名前の最大長は16,383文字。
過去には(ANSIだけど)260文字という制約があったこともあるらしい。
フォント名が259文字に切り詰められていたのは、260文字までしか対応していない環境やソフトを意識してのことだろうか。
比べてみると最大長が256文字のRegistryKey.GetValue
は雑。
ちなみに、Windowsのレジストリエディタは260文字以上の長い値名を表示することはできたけれど、長い値名を設定しようとすると259文字に切り詰められた。
おまけ
moraダウンローダー以外のアプリが28e89a9f-e67d-3028-aa1b-e5ebcde6f3c8
というMutexを作成していると同様に落ちる。
↑のフォントのレジストリを列挙するプログラムでは、ついでにこのMutexを作成しているので、確認ができる。
たぶん、同時起動抑制とかに使っているのだと思う。
この文字列がmoraダウンローダーのGUIDならば何の問題も無いのだけど、これは.NET Framework 2.0のSystem.Reflection.Assembly
のGUID。
何か勘違いをしている?
あと、moraダウンローダーを起動して、最初の1曲目のダウンロードが「エラーコード:21003」で失敗するという問題がある。
サポートに訊いたら、「プロキシ設定やネットワーク通信状況に起因した問題である可能性」と言われたけど、最初の1曲目は常に失敗するし、Twitterを検索しても似たようなことを言っている人がいるし、ネットワークの問題などではないのでは。ついでに直してほしい。