Bindlink API 概觀
Bindlink 連結庫可讓系統管理員使用者透過系結篩選器將文件系統命名空間系結至本機虛擬路徑(迷你篩選bindflt.sys)。 系結連結提供從本機 虛擬路徑 到本機或遠端 支援路徑的檔案系統重新導向。 他們主要可以啟用兩種案例:第一,他們可以透過網路共用讓遠端檔案出現在本機,以改善應用程式相容性,其次,它們可讓應用程式想要不同位置的檔案出現在新位置的案例,而可能有不同的名稱和目錄結構,而不需要複製檔案。 系結連結對應用程式和所有現有的 API 都是透明的,不需要知道此重新導向。 虛擬路徑不會建立實體檔案或目錄,而且系結連結會延伸虛擬路徑支援路徑中檔案和目錄的安全性描述元和許可權。
使用方式
一組 API 是由 2 個相關函式所組成:
- CreateBindLink – 此 API 可讓系統管理員在虛擬路徑與支援路徑之間建立系結連結。
- RemoveBindLink – 此 API 可讓使用者移除先前透過呼叫 CreateBindLink 所建立的連結。
如需這些函式的範例使用方式,請參閱 Bindlink 範例。
建立系結連結
系結連結對應用程式而言是透明的,雖然這些連結存在,但所有作業都會套用至支持路徑。 因此, DeleteFile 或 RemoveDirectory 會處理備份路徑,有效地刪除備份路徑,但無法刪除連結。 如果使用者沒有 管理員 istrator 許可權,如果使用者沒有開啟虛擬路徑或支援路徑的許可權,如果備份路徑不存在、虛擬路徑存在另一個連結,或設定連結時發生內部失敗,則此 API 將會失敗。 具體來說,系統管理員使用者應該能夠附加篩選條件(FilterAttach 的許可權)、連線到篩選埠(Filter 連線 CommunicationPort 的許可權),以及存取支援路徑的根目錄,否則 API 將會失敗並ERROR_ACCESS_DENIED。
如果應用程式嘗試遵循連結設定後已刪除之備份路徑的連結,應用程式將會看到 ERROR_FILE_NOT_FOUND*。 稍後如果再次建立備份路徑,鏈接現在會套用至這個新的備份路徑。 如果在連結存在時,在 virtualPath 上建立檔案,則會在 virtualPath 上顯示,如果連結存在,但實際建立於備份路徑。 拿掉連結時,檔案只會出現在備份路徑,而且不再顯示在 virtualPath。 這適用於以下所述的所有連結類型。
視虛擬路徑是否存在於磁碟上而定,產生的連結會是無錨點連結或陰影連結。
無錨點連結
無錨點連結是在建立連結之前,虛擬路徑不存在於磁碟上時所建立的系結連結。 建立這類連結時,虛擬路徑會合成記憶體內部,並像文件系統中的一般路徑一樣出現。 請注意,若要建立這類系結連結,虛擬路徑的父系必須以磁碟上的目錄或先前建立的連結的形式存在。 例如,若要使用 C:\Foo\Bar 做為虛擬路徑,C:\Foo 必須是磁碟上的目錄,或先前建立為另一個鏈接的虛擬路徑。 由於磁碟區沒有父系,因此無法有沒有錨點連結至不存在的磁碟區。 例如,如果還沒有名為 “Z” 的磁碟區,使用虛擬路徑 “Z:” 建立系結連結將會失敗。
陰影連結
陰影連結是建立連結之前磁碟區上存在虛擬路徑的陰影連結。 當這類虛擬路徑用來建立連結時,虛擬路徑的內容會隱藏,而備份路徑的內容會在虛擬路徑上顯示。 例如:
- C:\Foo 存在於磁碟上,有兩個檔案Cat.txt和Dog.txt
- C:\Bar 存在於磁碟上,有兩個檔案Cow.txt和Mouse.txt
使用 C:\Foo 建立鏈接作為虛擬路徑,並將 C:\Bar 當做備份路徑建立時,C:\Foo 路徑接著會顯示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 的使用者不會在第二個系結連結建立之前看到 c:\Foo\Bar。 由於 C:\Foo\Bar 只有在新增 c:\Foo\Bar 與 C:\Target2 之間的鏈接之後才會顯示,因此它完全是虛擬的,因此 c:\Foo\Bar 與 C:\Target2 之間的連結是無錨點連結。
請注意,針對這兩種類型的連結,會套用支援路徑的安全性描述元。
某些旗標可以傳入,以變更預設行為,以符合使用者的需求。
CREATE_BIND_LINK_FLAG_MERGED旗標
合併的連結就像陰影連結,但虛擬路徑中現有的內容會與備份路徑合併。 若要建立這類連結, 應該使用CREATE_BIND_LINK_FLAG_MERGED 旗標。
讓我們再次考慮陰影連結的先前範例,並新增此旗標。
例如:
- C:\Foo 存在於磁碟上,有兩個檔案Cat.txt和Dog.txt
- C:\Bar 存在於磁碟上,有兩個檔案Cow.txt和Mouse.txt
使用 C:\Foo 建立鏈接作為虛擬路徑,而 C:\Bar 作為旗標 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 做為備份路徑,且鏈接標示為只讀和合併時,Cat.txt和Cow.txt都會顯示在 C:\Foo,不過,Cat.txt將無法修改,而Cow.txt將無法修改。
此外,此 API 支援數個其他連結案例。 下列各節將說明這些內容。
巢狀連結
系結連結可以是巢狀連結。 這表示虛擬路徑的上階或子系元件也可以是其本身連結的虛擬路徑。
請注意,對隨後的迴圈鏈接沒有任何限制。
請考慮上方「巢狀系結連結」圖表中的連結和連結順序。
如果使用虛擬路徑建立連結:C:\Foo\Bar,可以使用 C:\Foo 建立另一個鏈接作為其虛擬路徑,而另一個連結可以使用 C:\Foo\Bar\Baz 作為其虛擬路徑來建立。
例如:
- C:\Target 存在於具有檔案Cat.txt的磁碟上
- C:\Target2 存在於具有檔案Dog.txt的磁碟上
- C:\Foo 存在於具有目錄列的磁碟上
如果 C:\Foo\Bar 連結到 C:\Target (Link1),然後 C:\Foo 連結到 C:\Target2 (Link2),則列舉 C:\Foo 的使用者會看到Dog.txt和目錄列,因為 Bar 是其本身連結的虛擬路徑。 接著,如果 C:\Foo\Bar\Baz 連結到 C:\Target2 (Link3),則列舉 c:\Foo\Bar 的使用者會看到Cat.txt和目錄 Baz,因為 Baz 是其本身鏈接的虛擬路徑。
其他系結連結案例
下列幾點很重要,在決定連結或一組連結的結果時,應該一起考慮:
如果具有相同名稱的實體存在於虛擬路徑或連結中,則備份路徑一律優先並覆寫。 這適用於所有類型的系結連結。
例如,請考慮下列連結:
c:\Foo 會連結至 c:\Target,其中 c:\Target 是檔案。
在此情況下,c:\Foo 看起來就像是具有無錨點連結之 c:\Target 內容的檔案。 即使 c:\Foo 是存在於本機的目錄(陰影連結),如果鏈接和備份路徑存在,上述連結會讓 c:\Foo 看起來像檔案。
發生衝突連結時,最近建立的鏈接優先。 不過,最新的鏈接無法隱藏先前的連結。
另一個範例會考慮下列連結。 第二個連結會變更命名空間的檢視。
- Link1:c:\Foo 會連結至 c:\Target,其中 c:\Target 是目錄。 c:\Target 有檔案列
- Link2:c:\Foo\Bar 連結到 c:\Target2,其中 Target2 是包含檔案的目錄Cat.txt
在此情況下,建立Link1之後,c:\Foo 會有檔案列。 不過,在Link2之後,c:\Foo 會顯示目錄列,其中包含檔案Cat.txt。 同樣地,如果 c:\Target2 是檔案,c:\Foo\Bar 會是包含 C:\Target2 內容的檔案
另一方面,如果鏈接的順序已反轉,如下所示,c:\Foo\Bar 會繼續顯示為顯示 c:\Target2 Cat.txt的目錄。 支援路徑的優先順序高於虛擬路徑下的專案,但它們不會優先於虛擬路徑根本身。
- Link1:c:\Foo\Bar 連結至 c:\Target2,其中 Target2 是包含檔案的目錄Cat.txt
- Link2:c:\Foo 會連結至 c:\Target,其中 c:\Target 是目錄。 c:\Target 有檔案列
若要成功建立連結,虛擬路徑的父系應該存在於本機,或因上一個連結中的backingPath而出現,或成為連結中的虛擬路徑本身。
例如,如果 c:\Foo 先連結至 c:\Target,然後 c:\Foo\Bar\Baz 鏈接至支持路徑,則 c:\Foo\Bar\Baz 的鏈接會因為下列其中一個條件而成功:
- c:\Foo\Bar 存在於本機,且上一個連結中的例外狀況可確保 c:\Foo\Bar 未受到 c:\Target 遮蔽(請參閱下一節中的例外狀況) 或
- c:\Foo\Bar 會藉由上一個連結存在 (例如,如果 c:\Target 有目錄列) 或
- c:\Foo\Bar 是另一個連結中的虛擬路徑本身 (c:\Foo\Bar ==> 某件事)
注意
這表示必須建立巢狀無錨點鏈接,最後建立最深層連結。 不過,陰影鏈接沒有這類限制,因為虛擬路徑已存在於磁碟上。
請考慮以相同順序建立的下列連結:
- C:\Foo 連結至 C:\Target
- C:\Foo\Bar 連結至 c:\Target2
建立連結不會影響備份路徑的行為。 因此,虛擬目錄列會顯示在 c:\Foo 中,而不是在 c:\Target 中。 連結資料表看起來會像這樣:
- C:\Foo --> c:\Target、C:\Foo\Bar --> c:\Target2 和 not
- 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 會傳回錯誤。