私は怠け者なので、テスト プログラムは作成しませんでしたが、長いパス ( よりも長い) や特殊なファイル名 (など) を問題なく処理する優れたFar Managerを使用してテストしました。MAX_PATH
con
prn
ちょうど 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
次に、命令の単なるラッパーであるNtCreateFile
inを呼び出します。ntdll.dll
syscall
NtCreateFile
0xC0000106 ( ) を返します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
ObpLookupObjectName
ObpDosDevicesShortNamePrefix
( )のチェック"\??\"
-> 成功
"C:"
プレフィックスをスキップし、残りの部分をとに分割します"\1234..."
"C:"
への呼び出しで解決しますObpLookupDirectoryEntry
- 次に、検索したディレクトリ エントリ ( ==と== 3 を使用)と名前の残りの部分を
ObpParseSymbolicLink
渡します。_OBJECT_SYMBOLIC_LINK
LinkTarget
"\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 でテスト済み。