バインドリンクAPIの概要
バインドリンクライブラリでは、管理者ユーザーがバインドフィルタ(ミニ・フィルタ bindflt.sys)を使ってファイルシステムの名前空間をローカルの仮想パスにバインドすることができます。 バインドリンクは、ローカル仮想パスからローカルまたはリモートバッキングパスへのファイルシステムのリダイレクトを提供します。 彼らは主に二種類のシナリオを可能にすることができる:第一に、ネットワーク共有を通じてリモートファイルをローカルに現れるようにし、アプリケーションの互換性を向上させることができ、第二に、アプリケーションが異なる位置のファイルが、潜在的に異なる名前とディレクトリ構造のファイルをコピーせずに新しい位置に現れるようにするシナリオを可能にします。 バインド・リンクはアプリケーションにとって透過的であり、既存のすべてのAPIはこのリダイレクトを意識することなく動作します。 仮想パスに物理的なファイルまたはディレクトリは作成されず、バインドリンクは下位パスのファイルとディレクトリのセキュリティ記述子と権限を仮想パスに拡張します。
使用方法
APIセットは2つの関連機能で構成されています:
- CreateBindLink-このAPIを使うと、管理者は仮想パスとバッキングパスの間にバインドリンクを作成することができます。
- RemoveBindLinkRemoveBindLink-このAPIを使用すると、CreateBindLinkを呼び出して以前に作成されたリンクを削除することができます。
これらの関数の使用例については、バインドリンクの例を参照してください。
バインドリンクの作成
バインドリンクはアプリケーションに透明であり、これらのリンクが存在する間、すべての操作がバックパスに適用されました。 結果とでぃては、DeleteFileまたはRemoveDirectoryはバッキングパスに作用し、バッキングパスは事実上削除されるが、リンクは削除されません。 このAPIは、ユーザーが管理者権限を持っていない場合、仮想パスまたはバッキングパスを開く権限を持っていない場合、バッキングパスが存在しない場合、仮想パスに別のリンクが存在する場合、またはリンクの設定中に内部障害が発生した場合に失敗します。 具体的には、管理ユーザーは、フィルター(FilterAttachへのアクセス許可)を添付し、フィルターポート(FilterConnectCommunicationPortのアクセス許可)に接続し、バックパスのルートにアクセスできなければならず、そうでなければ、ERROR_ACCESS_DENIEDでAPIが失敗します。
リンク設定後に削除されたバッキング・パスへのリンクをアプリがたどろうとすると、アプリにはERROR_FILE_NOT_FOUND*が表示されます。 後でバッキングパスを再度作成すると、リンクはこの新しいバッキングパスに適用されます。 リンクが存在する間にファイルがvirtualPathに作成された場合、リンクが存在しても物理的にバッキングパスに作成されれば、virtualPathに表示されます。 リンクが削除されると、ファイルはバッキングパスにのみ表示され、virtualPathには表示されなくなります。 これは、以下に説明するすべての種類のリンクに適用されています。
仮想パスがディスク上に存在するかどうかに応じて、結果リンクはアンカーのないリンクまたはシャドウリンクになります。
アンカーレスリンク
アンカーレスリンクとは、リンク作成前のディスク上に仮想パスが存在しない場合に作成されるバインドリンクであります。 このような種類のリンクが生成されると、仮想パスはメモリー内で合成され、ファイルシステムの一般パスのように現れます。 注意、このようなバインドリンクを作成するには、仮想パスの親がディスク上のディレクトリまたは以前に作成されたリンクとして存在しなければなりません。 例えば、C:\Foo\Barを仮想パスとして使用するには、C:\Fooはディスク上のディレクトリであるか、以前に別のリンクの仮想パスとして作成されていなければなりません。 ボリュームには親が存在しないため、存在しないボリュームへのアンカーレスリンクは存在しません。 例えば、仮想パス "Z: "でバインドリンクを作成しても、すでに "Z "という名前のボリュームがなければ失敗します。
シャドーリンク
シャドウ・リンクとは、リンクが作成される前にボリューム上に仮想パスが存在するリンクのことです。 このような仮想パスを使用してリンクを作成すると、仮想パスの内容は隠され、バッキングパスの内容は仮想パスで見えるようになります。 次に例を示します。
- C:\Fooは、Cat.txtとDog.txtの2つのファイルでディスクに存在します
- C:\Barは、Cow.txtとMouse.txtの2つのファイルとともにディスク内に存在します
C:\Fooを仮想パス、C:\Barをバックパスとしてリンクを作成すると、Cow.txtとMouse.txtがすべてのユーザーに表示され、Cat.txtとDog.txtはリンクが削除されるまで非表示になります。
次の図のもう一つの例は、シャドウリンクとアンカーレスリンクを区別するのに役立ちます。
c:\Fooを列挙するユーザーは、図に示されたバインドリンクが作成される前に、そのディレクトリとその既存の内容を見つけます。 リンク作成後、c:\Fooを列挙すると、C:\Foo\BarとCow.txtが表示されます。 C:\Fooはリンクの有無にかかわらずディスク上に存在するため、C:\Fooと\\Remote\Targetの間のリンクはシャドウリンクであります。
c: \Fooを列挙しているユーザは、2番目のバインドリンクが作成される前にc:˶FooBarを見ることはできません。 C:\FooBarは、C:\FooBarとC:\ターゲット2間のリンクが追加された後にのみ表示されるため、純粋に仮想であるため、C:\FooBarとC:\ターゲット2間のリンクはアンカーレスリンクです。
注意、どちらのタイプのリンクにも、バックパスのセキュリティ記述子が適用されます。
特定のフラグを渡すことで、ユーザーのニーズに合わせてデフォルトの動作を変更することができます。
CREATE_BIND_LINK_FLAG_MERGED フラグ
マージされたリンクは、仮想パス内の既存のコンテンツがバッキングパスとマージされることを除いて、シャドウリンクと同じです。 このようなリンクを作成するには、CREATE_BIND_LINK_FLAG_MERGEDフラグを使用してください。
先ほどのシャドーリンクの例に、このフラグを加えてもう一度考えてみよう。
次に例を示します。
- C:\Fooは、Cat.txtとDog.txtの2つのファイルでディスクに存在します
- C:\Barは、Cow.txtとMouse.txtの2つのファイルとともにディスク内に存在します
C:\Fooを仮想パスとし、CREATE_BIND_LINK_FLAG_MERGEDフラグをバックパスとしてリンクを作成すると、C:\FooパスはCat.txt、Dog.txt、Cow.txt、Mouse.txtが表示されます。
マージリンクは、仮想パスがディレクトリである場合にのみ適用されることを覚えておくことが重要です。 あるファイルがバッキングパスと仮想パスの両方に存在する場合、バッキングパス内のファイルが優先される--つまり、仮想パス内のファイルはマスクされます。 これは、仮想パス内のすべてのディレクトリに対して再帰的に適用されます。 マージはディレクトリに適用されるため、virtualPathとbackingPathの両方が同じレベルで同じ名前のディレクトリを持つ場合、リンクの結果としてそのディレクトリがマージされます。 リンクがマージされていない場合、backingPathのディレクトリが優先され、virtualPathのディレクトリがオーバーライドされますよ マージされたリンクが存在するときに、マージされたパスにファイルが作成されていた場合、そのファイルは物理的にbackingPathに作成され(バインドリンクの場合と同様)、virtualPathにある同名のファイルを上書きします。
次のディレクトリ構造と二つの異なるリンクを考えてみましょう
- c:\Foo\Sub\Foo_sub.txt
- c:\Bar\Sub\Bar_sub.txt.
c:\Fooがマージなしでc:\Barにリンクされている場合、c:\Foo\SubはBar_sub.txtしか表示されません。 しかし、c:\Fooがマージでc:\Barにリンクされている場合、c:\Foo\SubはFoo_sub.txtとBar_sub.txtの両方を表示します。
バインドリンクはパスベースのリンクであるため、リンクが作成された後にバッキングパスにあるファイルが置き換わったり、変更されたり、削除/再作成されたりした場合、仮想パスはリンクがたどられている時点で存在するファイルを指すことになります。 これは、ファイルが開かれた時点でリンクが解決されるために発生します。 したがって、バックパスにあるファイルがリンクによって仮想パスにあるファイルをマスクし、バックパスにあるファイルが削除されたとすれば、そのファイルを開いてほしいという後続の要請によってそのファイルが仮想パスで開かれることになります。
CREATE_BIND_LINK_FLAG_READ_ONLYフラグ
読み取り専用リンクとは、バッキングパスに存在するファイルに仮想パスを通してアクセスした場合、システム上のユーザーがそのファイルに変更を加えることができないようにするバインドリンクのことです。 これは、バックパス上のファイルを変更する権限を持ったユーザーがバックパスを通じてアクセスしてもそのファイルを変更できるが、仮想パスを通じてアクセスする場合は変更できないという意味です。 通常、対応する仮想パスへのアクセス許可はこのように適用されるが、CREATE_BIND_LINK_FLAG_READ_ONLYフラグの場合、書き込み許可はオフになります。 これにより、アプリケーションはファイルがCREATE_BIND_LINK_FLAG_READ_ONLYであることを確認することができます。
読み取り専用制限は、ディスク上のバッキング・パスに存在するファイルにのみ適用されることに注意してください。 リンクがマージされ、元々バーチャル・ディレクトリ・パスにあったファイルが表示されている場合、それらは変更可能なままです。
次に例を示します。
- C:\Fooは、Cat.txtファイルとともにディスク上に存在します
- C:\Barは、Cow.txtファイルとともにディスク上に存在します
仮想パスをC:\Foo、バックパスをC:\Barとしてリンクを作成し、そのリンクを読み取り専用にしてマージした場合、C:\FooにはCat.txtとCow.txtの両方が表示されますが、Cat.txtは変更可能でCow.txtは変更できません。
加えて、このAPIは他にもいくつかのリンクシナリオをサポートしています。 これらについては以降のセクションで説明します。
ネストされたリンク
バインドリンクはネストすることができます。 これは、仮想パスの祖先または子孫コンポーネントも、独自のリンクの仮想パスになれることを意味します。
後続の循環リンクには制限がないことに注意してください。
上記の「ネストされたバインドリンク」図のリンクとリンクの順序を考慮してください。
仮想パス:C:\Foo\Barでリンクが作成された場合、C:\Fooを仮想パスとして使用して別のリンクを作成することができ、さらに、仮想パスとしてC:\Foo\Bazを使用して別のリンクを作成することができます。
次に例を示します。
- C:\ターゲットは、Cat.txtファイルとともにディスクないに存在します
- C:\Target2は、Dog.txtファイルとともにディスク上に存在します
- C:\Fooはディレクトリバーがあるディスク上に存在します
C:\FooバーがC:\ターゲット(リンク1)にリンクされていて、C:\FooがC:\ターゲット2(リンク2)にリンクされている場合、バーは独自のリンクの仮想パスであるため、ユーザー列挙C:\Fooには、Dog.txtとディレクトリバーが表示されるます。 その後、C:\Foo\BazがC:\Target2(リンク3)にリンクされている場合、Bazは独自のリンクの仮想パスであるため、ユーザー列挙のc:\Foo\Barは、Cat.txtとディレクトリBazを見ることになります。
追加バインリンクシナリオ
次の点は重要であり、リンクまたはリンクセットの結果を決定する際には常に一緒に考慮しなければなりません。
バッキングパスは常に優先され、同じ名前を持つエンティティが仮想パスに存在する場合、またはリンクによって優先されます。 これはあらゆる種類のバインド・リンクに適用されます。
例えば、次のリンクを考えてください。
c:\Fooはc:\Targetにリンクされているが、c:\Targetはファイルです。
その場合、c:\Fooはアンカーのないリンクのc:\Targetを含むファイルのように見えます。 c:\Fooがローカルに存在するディレクトリ(シャドウリンク)であっても、リンクとバッキングパスが存在すれば、上記のリンクはc:\Fooがファイルに見えるようになります。
リンクが競合する場合は、最近作成されたリンクが優先されます。 ただし、最も最近のリンクは、以前のリンクを隠すことはできません。
別の例として、次のリンクを参照します。 二番目のリンクは、ネームスペースの見方を変えます。
- リンク1:c:\Fooはc:\Targetにリンクされていますが、c:\Targetはディレクトリです。 c:\Targetはファイルバーがあります
- リンク2:c:\Foo\Barはc:\Target2にリンクされていますが、ここでターゲッ2は、Cat.txtファイルを含むディレクトリです
この場合、リンク1が作成された後、c:\Fooはファイルバーを持つようになます。 しかし、Lリンク2の後、c:\FooはディレクトリバーにCat.txtファイルを表示します。 同様に、c:\Target2がファイルであれば、c:\Foo\BarはC:\Target2の内容を含むファイルになります
一方、下図のようにリンクの順序が反転した場合、c:\Foo\Barはc:\Target2からCat.txtを示すディレクトリとして継続して現れます。 バッキングパスは、仮想パスの下にあるアイテムよりも優先されるが、仮想パスのルートそのものよりも優先されることはありません。
- リンク1:c:\Foo\Barはc:\Target2にリンクされていますが、ここでTarget2は、Cat.txtファイルを含むディレクトリです
- リンク2:c:\Fooはc:\Targetにリンクされていますが、c:\Targetはディレクトリでです。 c:\Targetはファイルバーがあります
リンクが正常に作成されるためには、仮想パスの親がローカルに存在しますか、前のリンクのbackingPathから表示されるか、リンク内の仮想パスそのものである必要があります。
例えば、c:\Fooがc:\Targetに先にリンクされていて、c:\Foo\Bazがバックパスにリンクされている場合、次のいずれかの条件によってc:\Foo\Bazが存在する場合、c:\Foo\Bazからのリンクは成功します:
- c:\Foo\Barはローカルに存在し、前のリンクの例外により、c:\Foo\Barはc:\Targetによってシャドウされません(次のセクションの例外を参照してください)。または
- c:\Foo\Barは以前のリンクのおかげで存在します(例:c:\Targetがディレクトリバーを持っている場合)または
- c:\Foo\Barは、別のリンク内の仮想パスそのものです(c:\Foo\Bar ==>何が)
Note
これはネストされたアンカーのないリンクが、最も深いリンクが最後に作成された状態で作成されなければならないことを意味します。 しかし、シャドウリンクは、仮想パスがすでにディスク上に存在するため、そのような制限はありません。
同じ順序で作成された次のリンクを考慮してください。
- C:\FooはC:\Targetにリンクされます
- C:\Foo\Barはc:\Target2にリンクされます
リンクの作成は、バッキングパスの動作には影響しません。 したがって、仮想ディレクトリバーはc:\Targetではなくc:\Fooに表示されています。 リンクテーブルは次のようにみえます:
- C:\Foo --> c:\Target、C:\Foo\Bar --> c:\Target2 ですがではありません
- C:\Foo -->c:\Target、c:\Target\Bar-->c:\Target2
バインドリンクの例外事項
オプションで、作成されるリンクの範囲を制限するための例外を指定することができます。 例外パスは、リンクが適用されない仮想パスの子孫です。 例外パスはファイルでもディレクトリでもよいが、仮想パスの子孫でなければなりません。 APIは、リンクが作成されているときに例外パスにアクセスできることを要求します。 例外は、例外パスのすべての子孫に適用されます。 次に例を示します。
- C:\Fooはディスク内に存在し、ディレクトリバーとディレクトリBazを含みます
- C:\Foo\BarはCat.txtを含みます
- C:\Foo\BazはDog.txtを含みます
- C:\Targetはディスク上に存在し、Cow.txtファイルを含みます
C:\FooからC:\TargetへのリンクがC:\Foo\Bazを除いて作成された場合、ユーザーは次のように表示されます:
- C:\Fooには、C:\TargetのCow.txtファイルと、Dog.txtとともにBazディレクトリが含まれます。 リンクによってシャドウされているため、C:\Foo\Barは表示されません。
以下の図は、上記のシナリオを表しています。
最後に、バインドリンクの例外はアンカーレスリンクには適用されない。なぜなら、アンカーレス仮想パスは定義上子孫を持たず、したがって適格なパスを持たないからです。 アンカーのないリンクに例外を渡そうとすると、APIはエラーを返します。