ソフトウェア

WindowsのドライブレターはA~Z以外も実は使える


Windowsのファイルシステムを語る上で、ドライブレターは最も特徴的なものの一つです。コマンドプロンプトやエクスプローラーといったツールでディレクトリ構造の頂点に位置するドライブレターは、あまりコンピューターに詳しくない人でも、よくわからないけれどなじみ深いものだと思われます。そんなドライブレターは通常「A」から「Z」までのアルファベットを割り当てますが、実はアルファベット以外の文字も割り当てることができる、と開発者のRyan Liptak氏によって詳しく解説されていました。

Windows drive letters are not limited to A-Z - ryanliptak.com
https://www.ryanliptak.com/blog/windows-drive-letters-are-not-limited-to-a-z/

ドライブレターにアルファベット以外の文字を割り当てることができることを最も簡単に確認できる方法は、substコマンドを使用する方法です。例えば、「C:\foo\bar」というファイルが存在する場合に、以下のコマンドをコマンドプロンプト上で実行したとします。

subst +: C:\foo

コマンドが正常に実行されると、「C:\foo\」がドライブ「+」として機能するようになり、「+:\」ディレクトリにアクセスできるようになります。

> cd /D +:\

+:\> tree .
Folder PATH listing
Volume serial number is 00000001 12AB:23BC
+:\
└───bar

これだけだと単なる豆知識ですが、何故このようなことができるのかについて深掘りすると、Windowsの内部動作をより理解できるようになります。

そもそもドライブレターとは何なのかを知る上で重要なのが、一般的に知られているWindowsのパスは「Win32名前空間パス」である、ということです。つまり、先程の例で挙げた「C:\foo」のようなパスはWin32パスなのです。しかし、NtCreateFileのようなWindows NT系の低レベルAPIは直接Win32パスを受け取りません。そこでCreateFileWのような高レベルAPIによって変換されたNT名前空間パスを渡されます。パスがどう変換されたかを標準で用意された仕組みだけで知ることはできませんが、NtTraceのような外部コマンドを使用することで確認は可能です。

NtCreateFile( FileHandle=0x40c07ff640 [0xb8], DesiredAccess=SYNCHRONIZE|GENERIC_READ|0x80, ObjectAttributes="\??\C:\foo", IoStatusBlock=0x40c07ff648 [0/1], AllocationSize=null, FileAttributes=0, ShareAccess=7, CreateDisposition=1, CreateOptions=0x4000, EaBuffer=null, EaLength=0 ) => 0
NtClose( Handle=0xb8 ) => 0

上記の出力は、NtCreateFileに渡される際に、「C:\foo」というWin32名前空間パスが、「\??\C:\foo」というNT名前空間パスに変換されていることを示します。

さらにドライブレターの正体を探るためには、オブジェクトマネージャーについて知る必要があります。オブジェクトマネージャーはWindowsの名前付きオブジェクトを管理しており、WinObjツールを使用することで管理内容を参照することができます。


NT名前空間パス「\??\C:\foo」の「\??」部分はオブジェクトマネージャーが管理する特別な仮想フォルダとなっています。上記の例では、「C:」というオブジェクトは「GLOBAL??」の中にあり、その実態は「\Device\HarddiskVolume4」というデバイスであることがわかります。つまりこの場合、「\??\C:\foo」は最終的に「\Device\HarddiskVolume4\foo」として解決されることになります。ここで重要なのは、「\??\C:\foo」というパスはそもそも\Device\HarddiskVolume4\foo」を参照する一つの方法に過ぎない、という点です。例えば、「Volume{18123456-abcd-efab-cdef-1234abcdabcd}」といったGUIDによって生成された名前付きオブジェクトが「\Device\HarddiskVolume4」のシンボリックリンクだったら、「\??\Volume{18123456-abcd-efab-cdef-1234abcdabcd}\foo」というパスも「\??\C:\foo」と同等なわけです。

つまり本質的に、「C:」という名前付きオブジェクトは何ら特別なものではなく、オブジェクトマネージャーから見れば数あるシンボリックリンクの一つに過ぎない、ということです。

本題に戻り、「ドライブレターとは何か」という質問について、Ryan氏は「本質的にはWin32パスをNTパスに変換する際に生まれた慣習に過ぎません」と結論しています。それ故、「C:\foo」と「+:\foo」が全く同じ挙動を示す、ということになります。

> paths.exe C:\foo
path type: .DriveAbsolute
  nt path: \??\C:\foo

> paths.exe +:\foo
path type: .DriveAbsolute
  nt path: \??\+:\foo

ただし、一部のWindowsコンポーネントはドライブレターに関する柔軟性を完全にはサポートしていません。例えば、ファイルエクスプローラーはAからZ以外のドライブレターを持つドライブを表示できず、PowerShellも同様です。


また、どんな文字でもドライブレターとして使用できるかというと、そうでもありません。ドライブレターには非ASCII文字も使用可能です。

> subst €: C:\foo

> cd /D €:\

€:\> tree .
Folder PATH listing
Volume serial number is 000000DE 12AB:23BC
€:\
└───bar

ただ、非ASCII文字であっても、大文字と小文字は区別されません。

> subst Λ: C:\foo

> cd /D λ:\

λ:\> tree .
Folder PATH listing
Volume serial number is 000000DE 12AB:23BC
λ:\
└───bar

さらに、使用可能な文字は16ビットのWTF-16コード単位に制限されます。つまり、文字コードがU+FFFF以内でなければなりません。範囲外の文字をドライブレターに設定しようとすると、substコマンドの場合は「Invalid parameterU+FFFF」とエラーを出力します。

なお、非ASCII文字をドライブレターにした場合、以下の様な問題が発生することを確認したとのこと。

・プログラムがシステムのAPIを使用せずにパスを扱っている場合、非ASCII文字をドライブレターにした絶対パスを認識しない可能性が高い
・エンコーディングがWTF-16かWTF-8かで絶対パスが異なって認識される
SetVolumeMountPointW APIの「不具合」によりドライブレターの上位バイトが切り捨てられてしまい、例えば「€(U+20AC)」を指定してマウントポイントを作成してもWinObjツールで見ると「¬(u+00AC)」になってしまう


これらの現象についてRyan氏は、「非ASCIIのドライブレターは誰も考えたことのないエッジケースであるというのも納得できます」と述べています。

この記事のタイトルとURLをコピーする

・関連記事
MicrosoftがWindows Subsystem for Linux(WSL)をオープンソース化してコードをGitHubに公開 - GIGAZINE

ニンテンドーゲームキューブでWindows NTとDOOMを動かすことに成功 - GIGAZINE

Windows NT系はUNIX系と比較して設計上のどういう点が先進的だったのか? - GIGAZINE

Windowsで表示されるブルースクリーンの生みの親は誰なのか? - GIGAZINE

3Dパイプや迷路のスクリーンセーバーはどういった理由で採用されたのか? - GIGAZINE

in ソフトウェア, Posted by log1c_sh

You can read the machine translated English article Windows drive letters can actually be an….