デバイスツリー

昨日、マウントポイントのバッファの内容を直接取り出したが、
そのリンク先のパスは、以下のようになっていた。

\??\Volume{f08e7d20-64f1-11db-b10d-001125868411}\

だが、これを GetVolumeNameForVolumeMountPoint で
取り出すと以下のようになる。

\\?\Volume{f08e7d20-64f1-11db-b10d-001125868411}\

一見同じに見えるが、接頭辞が異なっている。
これらはどう違い、どんな意味をもっているのだろうか。

今日は、前者について考えよう。
これはリパースポイントから取得した生のパス文字列であり、
デバイスを示す絶対パス表現である。

デバイスパスは、Windows のデバイスオブジェクトの
名前空間上のパスを示している。
デバイスは階層化されているため、
ファイルシステムと同じように \ で区切って階層を示す。

例えば、\Device\Harddisk0\Partition1 は、
最初のハードディスクの最初のパーティションのデバイスを表し、
\FileSystem\Ntfs は、NTFS ドライバを表している。
これは、UNIX 系の /dev ファイルシステムに似ている。

上記の Device や FileSystem はルート直下の名前空間で、
これはディレクトリのような位置づけである。

これらデバイスパスは、通常はあまり使わないが、
デバイスドライバなど、低水準のコードを書く際には、
デバイスを示す際に必要になる。

さて、ルートには「??」という仮想的な名前空間が存在する。

?? は、DOS 名前空間(DOS デバイス名前空間)と呼ばれ、
主に MS-DOS との互換性を色濃く残す部分である。
これは通常のファイルシステムパスや、
高水準のファイルアクセス API への橋渡しをしている。

?? の中には、NUL, COM1, AUX, C:, D: などが存在する。
そう、この空間にあるデバイス名は、
MS-DOS デバイスと呼ばれる特別なデバイスなのだ。

Windows のデバイス名は階層化されているが、
MS-DOS デバイス名は階層化できない。
そのため、?? 名前空間の中には、
その他の名前空間に存在するデバイスへの
リンクが格納されている。

例えば、NUL のデバイスパスは、\??\NUL であるが、
これは、\Device\Null へのリンクとなっている。
UNIX では /dev/null なので非常に良く似ている。

また、俺の環境では、\??\C: は、
\Device\HarddiskVolume1 へのリンクであり、
\??\Q: は、\Device\CdRom0 へのリンクとなっている。

冒頭で示したパスが指しているのも、この名前空間だ。
Volume{f08e7d20-64f1-11db-b10d-001125868411} は、
俺の環境では、\Device\CdRom3 へのリンクとなっている。

昨日取得したリパースポイントのデータは、
ファイルシステムに存在する低水準のデータであるため、
示すリンク先が、デバイスパスで格納されていた訳だ。

これらデバイスパスを調べるのは大変だが、
Sysinternals が無料で公開している、
winobj というツールを使うと、
オブジェクトの階層構造を視覚的に見ることができる。

■ Sysinternals Freeware - WinObj
http://www.sysinternals.com/Utilities/WinObj.html

今日解説した ?? 名前空間にあるリンクを写真に示す。
写真で開いているのは ?? ではなく GLOBAL?? だが、
?? 空間には、GLOBAL?? の内容が含まれているので、
ほとんど同じと考えて構わない。