最近の記事
- 4/24 - 優先順位
- 3/17 - vbNullString と 空文字列 ""
- 3/15 - InputBox 関数の戻り値
- 3/13 - 紙と Excel と VBA
- 3/9 - 未だに Visual Basic 6
- 11/14 - ぼて閉鎖
- 11/9 - 関数オブジェクトの呼び出し
- 9/7 - メソッドとしての関数オブジェクト
- 8/18 - コンストラクタとしての関数オブジェクト
- 8/4 - オブジェクトの生成
Entering Passive Mode
次世代の Windows OS となる、Windows Vista や、
Longhorn Server(コードネーム)では、
いよいよ真のシンボリックリンクが登場する。
シンボリックリンクは、UNIX 系のそれとほぼ同様の機能だ。
Vista では、CreateSymbolicLink API が登場し、
OS で正式にサポートされた機能として実装される。
Vista のエクスプローラは、正式にリンクを採用したため、
昨日説明したような問題が起きないような設計になっている。
マウントポイントやシンボリックリンクを削除しても、
リンク先が削除されるようなことは起こらないのだ。
マウントポイント機能は、
使い方次第では非常に便利である。
ディスクを複数のパーティションに分けている場合、
システムドライブに空き容量が不足しても
マウントポイント機能を使えば、
ドライブにある適当なディレクトリの実体を、
別のボリュームに置くことができる。
ボリュームマウントポイントの場合は、
Windows で正式にサポートされているため、
GUI によって設定することもできるが、
別のボリューム全体がマウントされることになる。
今日はディレクトリジャンクションを作成してみる。
そのものズバリの API は存在しないので、
リパースデータバッファを自分で用意し、
DeviceIOControl を使って設定することになる。
========== part of mountpoint.c ==========
HRESULT MountPointCreate(const wchar_t *mountPointPath, const wchar_t *target) {
unsigned short pathByteLength;
char dataBuffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
MOUNT_POINT_INFO *info = (MOUNT_POINT_INFO *)dataBuffer;
パス名で何日か脱線していたが、
改めてボリュームマウントポイントに戻ろう。
ボリュームマウントポイントは、
ファイルシステムのディレクトリに対して、
リパースポイント機能を使うことで実現していた。
リパースポイント属性を持つディレクトリには、
リパースデータバッファという追加情報が保存されている。
リパースデータバッファには種類があるが、
ボリュームマウントポイントは、
IO_REPARSE_TAG_MOUNT_POINT という種類であり、
データとしてリンク先を表すデバイスパスが記録されていた。
実際に拡張表現を試してみよう。
サンプルとして、Windows フォルダ内にある、
win.ini にアクセスしてみよう。
エクスプローラのアドレスバーや、
ファイルを開く汎用コモンダイアログでは、
拡張パス表現に対する対応をしているが、
コマンドプロンプトや「ファイルを指定して実行」は、
そのような制限がないため、入力して試すことが可能だ。
いよいよ、保留にしていたパスについて考えてみる。
GetVolumeNameForVolumeMountPoint が返却したパスは、
以下のような形式であった。
\\?\Volume{f08e7d20-64f1-11db-b10d-001125868411}\
実は、これもファイルのパス表現なのである。
最初に \\ と並んでいるので、UNC パスにも見えるが、
「?」というサーバに接続するわけではない。
では、上記のパスはどのように解釈されるのか。
昨日のもう 1 つのパスはもう少し保留しておき、
ファイルのパス表現について考えてみよう。
パソコン利用者やプログラマに単に「パス」と言えば、
こちらのファイルパス表現のことを指す。
これは、C:\~ や \\server\share\~、..\ などの、
一般的によく見る表現のことである
通常は、このパス表記を使ってファイルにアクセスする。
プログラマがファイルを利用する場合、
パスを指定してプログラミング言語固有の機構を使うが、
これは、Windows の基幹 API を呼び出す。
ファイルの場合、通常 CreateFile API である事が多い。
昨日、マウントポイントのバッファの内容を直接取り出したが、
そのリンク先のパスは、以下のようになっていた。
\??\Volume{f08e7d20-64f1-11db-b10d-001125868411}\
だが、これを GetVolumeNameForVolumeMountPoint で
取り出すと以下のようになる。
\\?\Volume{f08e7d20-64f1-11db-b10d-001125868411}\
一見同じに見えるが、接頭辞が異なっている。
これらはどう違い、どんな意味をもっているのだろうか。
では、実際にリパースデータバッファを取得し、
マウントポイントのリンク先を取得してみよう。
========== 1st half of mountpoint.c ==========
#define UNICODE
#define STRICT
#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x0500
リパースタグなどの特殊なデータにアクセスする場合、
デバイスドライバに対して制御コードを送り、
データ構造を直接扱う必要がある。
Windows には、DeviceIoControl という API があり、
これを使うことで、デバイスドライバの制御が可能である。
リパースポイントの情報を得るためには、
対象のディレクトリハンドルに対して、
FSCTL_GET_REPARSE_POINT という制御コードを送る。
そうすれば、その結果としてリパースポイントの情報が、
リパースデータバッファと呼ばれる構造で返却される。