直前のエントリーの MAX_PATH はなぜ 260? 夜の間に盛り上がっておりました。
ってことで正解です。まずはパート分解してみましょう。
260 == 3+256+1 == 3+(255+1)+1 です。さらに分解すると (2+1)+(255+1)+1 まで分解できます。これが最小単位ですね。
で、もう一つ忘れてはならないのは、この定義名が「古く」から存在しているということ。
そのために、わざわざエントリーでWindows 3.1 のヘルプの話を出していたのですね。
当時のSDKとかあれば、もうちょっと違うんですが...さすがにそれはキープしていないので...w
まずは、最後の1。
これは、C形式の文字列の終端記号を意味する '\0' の領域です。
コメントいただいた方々はさすがに歴戦の猛者ばかりなので、これはすぐにわかった模様。
とはいえ、これも DOSや Not Windows な環境では含まないのが流儀なので、注意しておきたいところの一つです。
ちょうどいい機会なので、書いておきますが、Windows の API で文字列長といえば、原則として \0 を含むサイズとなります。
そうではない場合、ドキュメントに書かれていますので、注意しておきましょう。
これで一番嵌ったのは、lstrcpyn API。C-Runtime の strncpy は、\0 を含まない長さを渡しますが、lstrcpyn は含む長さを渡します。書き換えるとなると、100%嵌る落とし穴の一つです。注意しましょうw
次は最初の3。
これは、ドライブレター+ルートを示すディレクトリ区切り文字ですね。なので、分解すると2+1とすることもできます。
この部分は面白みも何もないですねw
最後は、255+1。
まずは、255。こちらは、ディレクトリエントリの最大文字列長です。さすがにみなさんお気づきでした。というか最初からここは問題にはなっていなかったw
ちなみに、DOS の時代(今はショートパスです)は、8+3。ファイル名になるエントリーの場合は、'.' が「必須」なので、8 + 3 ですが、ディレクトリの場合は、'.'を入れなくてもよい(DOS3か4のあたりでの拡張)事になっているので、'.' を入れずに11か、'.'をいれて8+3になります。
9+2 とか 10+1 という組み合わせはできません。
で、最後の1。
これは、ディレクトリ区切り文字分です。なぜ?という声が聞こえてきそうですが、Win32 の MAX_PATH は最初から互換性のためだけに用意されています。なので本当のパス文字列には最大長は定義されていません。
とはいえ、有効長は必要だし、互換性も必要になる(FATシステムでは、最大長があるので)、そのためには何らかの有効サイズを表現しなければならない。
互換性で必要なサイズ(FATシステム=DOSファイルシステムエンジン)は、144文字以上です。どう計算しても合わないのですが... WIN31WH.HLP にはっきりと書かれています(末尾に該当箇所のヘルプの文言を抜粋)。もちろんドライブレターも含まれます。
これと、現行ファイルシステム(もちろんNTFSのことです。Fat32はまだありませんでしたからw)で表現できる最低サイズの最小公倍数をとったのではないか?と思われます。
また、\で終わっていれば、それはファイルではないことが目視で確認することができます。そのためデバッグ中にファイルシステムを参照する必要もありません。このあたりにも理由はあると思います。
NT 3.1 が作られていた当時の開発体制を考慮すれば、これくらいは考えていて当たり前のはずです。偉大なお方が陣頭指揮とってたんですからね。
惜しむらくは、MAX_PATH ではなくて、本当の意味は MIN_PATH であるということですね。こちらはもう思いっきり互換性維持という大人の事情が働いているのだと思いますw
なお、GetOpenFileName を出したのは、ただのおまけです。なんでヒットしないのかなぁ?と思ったらリテラルだったと...w<それが言いたかっただけw
ということで、おまけのリファレンスです。
API は、GetSystemDirectory にしました。今のものは、MSDNライブラリを見てください。これはあくまでも当時の日本語ヘルプですので。
--WIN31WH.HLP--
UINT GetWindowsDirectory(lpszSysPath, cbSysPath)
LPSTR lpszSysPath; /* Windowsディレクトリのバッファのアドレス */
UINT cbSysPath; /* ディレクトリ バッファのサイズ */
GetWindowsDirectory関数は、Windowsディレクトリのパス名を取得します。Windowsディレクトリには、Windowsアプリケーション、初期化ファイル、ヘルプ ファイルなどのファイルがあります。
パラメータ 説明
lpszSysPath パス名を格納する、NULLで終了する文字列を受け取るバッファを指すポインタです。
cbSysPath バッファの最大サイズをバイト単位で指定します。長いパス名を受け取れるように、バッファのサイズを144バイト以上確保するようにしてください。
--
--API32WH.HLP--
UINT GetSystemDirectory(lpszSysPath, cchSysPath)
Lptstr Lpszsyspath; /* システム ディレクトリのバッファのアドレス */
Uint Cchsyspath; /* ディレクトリ バッファのサイズ */
GetSystemDirectory関数は、 Windowsのシステム ディレクトリのパスを取得します。システム ディレクトリには、 Windowsライブラリ、 ドライバ、 フォントなどのファイルがあります。
パラメータ 説明
lpszSysPath パスを含む、 NULLで終わる文字列を受け取るバッファを指すポインタです。このパスは、 システム ディレクトリがルート ディレクトリであるとき以外は円記号で終わりません。たとえば、 WINDOWS\SYSTEMというシステム ディレクトリがCドライブにある場合、 この関数によって取得されるシステム ディレクトリのパスは、 C:\WINDOWS\SYSTEMになります。
cchSysPath バッファの最大サイズを文字単位で指定します。この値は少なくともMAX_PATHに設定されていなくてはなりません。
--