私は怠け者なので、テスト プログラムは作成しませんでしたが、長いパス ( よりも長い) や特殊なファイル名 (など) を問題なく処理する優れたFar Managerを使用してテストしました。MAX_PATHconprn
ちょうど 255 文字の文字列 ("12345678901234...012345") を作成し、ネストされたディレクトリの作成を開始しました。幸いなことに、Far の「ディレクトリの作成」機能は、スラッシュで区切られた文字列を使用して「ネストされたディレクトリを作成する」ことを意味するため、内部エディターで文字列をコピー & ペーストして準備することで、ほんの数ステップでそれを行うことができました。
私が作成できた最長のパスは、「C:\」から数えて32739文字でした (つまり、Far によって追加された「\\?\」は含まれません)。ディレクトリまたはファイルを 1 文字だけ追加して作成しようとすると、「ファイル名または拡張子が長すぎます」というエラーが表示されます。そのディレクトリに入ろうとすると、同じエラーが発生します。
編集: デバッガーでしばらく過ごしました。Win32 API レベルで何が起こるかを次に示します。
- 制限を 1 文字超えるファイルを作成しようとしています
CreateFileW文字列 "\\?\C:\123[...]012345" を使用したfar 呼び出しは、 32744ワイド文字の長さです (終端のゼロは数えません)。
CreateFileWいくつかの追加チェックを行い、null で終わる文字列をUNICODE_STRING(Length=65488, MaximumLength=65490)に変換し、OBJECT_ATTRIBUTES構造体を準備します。
CreateFileW次に、命令の単なるラッパーであるNtCreateFileinを呼び出します。ntdll.dllsyscall
NtCreateFile0xC0000106 ( ) を返しますSTATUS_NAME_TOO_LONG。
- 次に、そのステータス値が ( を使用して
RtlNtStatusToDosError) Win32 エラー 206 ( ERROR_FILENAME_EXCED_RANGE) に変換されます。
カーネル内で何が起こっているかは調べませんでしたが、それも調べることができたと思います。
EDIT2 : WinObj を実行したところ、システムC:に へのシンボリック リンクがあることがわかりました\Device\HarddiskVolume1。この文字列の長さは23 文字です。\C:に渡された文字列の を置き換えるNtCreateFileと、32744 - 3 + 23 = 32764文字になります。終端のゼロと合わせて、これには 65530 バイトが必要です。まだ制限 (0xFFFF=65535) に達していないので、セッション名や名前空間名など、何か余分なものが追加されていると思います。
EDIT3:カーネルを通過した後:
NtCreateFile通話IopCreateFile
IopCreateFile通話ObOpenObjectByName
ObOpenObjectByName通話ObpLookupObjectName
ObpLookupObjectNameObpDosDevicesShortNamePrefix( )のチェック"\??\"-> 成功
"C:"プレフィックスをスキップし、残りの部分をとに分割します"\1234..."
"C:"への呼び出しで解決しますObpLookupDirectoryEntry
- 次に、検索したディレクトリ エントリ ( ==と== 3 を使用)と名前の残りの部分を
ObpParseSymbolicLink渡します。_OBJECT_SYMBOLIC_LINKLinkTarget"\Device\HarddiskVolume1"DosDeviceDriveIndex
次に、次のようなことを行います(ReactOS によって忠実に再現されています):
TargetPath = &SymlinkObject->LinkTarget;
TempLength = TargetPath->Length;
TotalLength = TempLength + RemainingName->Length;
if (LengthUsed > 0xFFF0)
return STATUS_NAME_TOO_LONG;
私たちの場合、46 + 65476 = 65522 (0xfff2) で、制限をわずかに超えています。
ということで、謎が解けました(願わくば!)。
PS すべて Windows 7 x64 SP1 でテスト済み。