こらー

SoftEther 2.0 で、ユーザーインターフェイスを多言語に対応させるために、内部の文字列表現を Unicode にして書いていた。これで Windows NT 系で動作させている場合はマルチランゲージ対応完璧である。
Windows は大半の文字列を処理する (指定する) API で、Unicode 版、ANSI 版の 2 つの関数名が用意されている。たとえば SetWindowTextA と SetWindowTextW のように。
開発者が SetWindowText と書くと、UNICODE マクロが定義されていない場合は SetWindowTextA が使用され、定義されている場合は SetWindowTextW が指定されるようになる。

Windows 9x 系にも、これら A (ANSI) 系と W (Unicode) 系の 2 つの API がほぼすべて揃っている (DLL でエクスポートされている)。
これまでの私の理解では、

というようになっていた。
しかし、どうやらそうではないということに最近気がついた。
Windows 9x 系の API 関数は、ほぼすべて A 系と W 系がエクスポートされているが、W 系関数を呼び出すと A 系関数に変換されてうまく実行される場合と、何もせずに必ずエラーを返すようになっている場合の 2 種類の API があるらしい。
実は SoftEther 2.0 のインターフェイスWindows Me 上で動作させるために頑張っていたときのことである。いくつかの UnicodeAPIWindows Me 上でも正しく動作した (恐らく内部で ANSI 文字列に変換されて動いている) のだが、動かない (常にエラーを返す) ものもあった。
どうやら、API によって動くものと動かないものがあるらしい。

Microsoft の解説では、これまで ANSI 系文字列に対応していた、国際化非対応のプログラムも、Win32 API の慣習に従って正しく書いていると、_UNICODE マクロを定義するだけで自動的に国際化対応版としてコンパイルできる♪ というものがあったと思うのだが、どうもそうではないようだ。_UNICODE マクロを付けると UnicodeAPI が呼び出されるようになり、Windows NT 系で動作させている場合は自動的に Unicode 対応ユーザーインターフェイスプログラムとして動作できるようになるが、Windows Me / 98 上では一部の API が動かなくなるようである。
Platform SDK のドキュメントでは、ほとんどの API について
UnicodeWindows NT/2000 は Unicode 版と ANSI 版を実装
などと統一的書かれているが、Windows 9x 上で呼び出すことができるかどうかは明記されていない。恐らく、呼び出させる保証は無いのだろう。しかし、わかっているのであれば、どの W 系 APIWindows 9x 内では自動的に A 系に変換されて呼び出せるラッパーが実装されていて、どの API が実装されていないか、といった情報リストがあれば助かるのだが…… と思った。
この仕様のため、結局すべての UI 系 API 呼び出しの部分を、NT 上で実行している場合とそうでない場合に分岐させて独自に Unicode / ANSI 文字列変換を行うように書き換えた。結構、苦労した。