本文提供從應用程式存取共享資料夾時所發生的非預期錯誤解決方案。
原始 KB 編號: 2990989
癥狀
試想以下情況:
- 您會在 Windows Server 2008 R2 中建立共用資料夾,然後授與該資料夾的使用者 A 讀取許可權。
- 您可以在共享資料夾上建立子資料夾、停用子資料夾的可繼承許可權,也不會授與子資料夾的使用者 A 讀取許可權。
- 您以使用者 A 身分登入 Windows Server 2012 伺服器,然後執行呼叫 Shared 資料夾 FindFirstFile 的應用程式。
在此案例中,應用程式會失敗。 此外,錯誤碼 ERROR_ACCESS_DENIED 並未如預期傳回。 相反地,會傳回下列其中一個錯誤碼:
發生未預期的網路錯誤。 (ERROR_UNEXP_NET_ERR)
參數不正確。 (ERROR_INVALID_PARAMETER 錯誤:無效的參數)
如果您執行的應用程式假設在此情況下會傳回ERROR_ACCESS_DENIED,表示其沒有適當的訪問許可權,則此假設可能不正確。
原因
發生此問題的原因是,核心模式 SMB 元件在 I/O 應因 STATUS_ERROR_ACCESS_DENIED 而失敗的情況下,卻傳回了 STATUS_UNEXPECTED_NETWORK_ERROR。 同時,SMB 元件在另一個線程中要求 I/O。 此線程可以傳回STATUS_INVALID_PARAMETER。
當 NT 狀態交給檔案或資料夾 API 時,SMB 元件傳回的這些 NT 狀態會轉譯為下列其中一個 Win32 錯誤:
- ERROR_UNEXP_NET_ERR 網路錯誤未預期發生
- ERROR_INVALID_PARAMETER(錯誤:無效的參數)
解決辦法
如果應用程式假設在此情況下會傳回ERROR_ACCESS_DENIED,以判斷它是否具有適當的訪問許可權,並在存取共用資料夾的子資料夾時收到ERROR_UNEXP_NET_ERR或ERROR_INVALID_PARAMETER,而沒有任何訪問許可權,則可以執行與收到ERROR_ACCESS_DENIED時相同的處理來避免此問題。
詳細資訊
開啟子資料夾時,Windows Server 2012 中的用戶端重新導向器會傳送兩個 SMB 封包。 一個封包是「建立」封包,另一個封包是「查詢目錄」封包。 建立封包會開啟目錄,而查詢目錄封包可讓重新導向器判斷子資料夾的相關信息,以便正確處理子資料夾。 建立封包失敗,並出現STATUS_ACCESS_DENIED。 但之後,查詢目錄封包也會因為STATUS_UNEXPECTED_NETWORK_ERROR而失敗。 因此,有兩個錯誤碼。 由於查詢目錄動作發生在建立之後,因此會傳回查詢目錄錯誤碼。
即使 Windows 的設計已變更,以便傳回ERROR_ACCESS_DENIED,存取網路共用的應用程式仍會收到ERROR_UNEXP_NET_ERR,因為可能發生實際的網路錯誤,例如伺服器當機、網路電源遺失等等。
請注意,對本機磁碟驅動器的 I/O 和對網路檔案共用的 I/O 之間存在差異。 雖然應用程式所使用的 API (CreateFile、ReadFile、FindFirstFile 等等)都相同,但執行工作的記憶體系統不同。 當應用程式存取本機檔案時,API 會建立 IRP 並將它傳送至檔案系統驅動程式 (NTFS.SYS),而 I/O 要求最終會傳送至磁碟驅動程式。 當應用程式存取網路共享時,API 會叫用用戶端/伺服器網路協定。 API 會將要求傳送至用戶端重新導向器,然後用戶端重新導向器會建立SMB封包,並將SMB封包傳送至伺服器。 伺服器的服務會接收封包,然後執行 I/O 作業。 I/O 作業完成後,伺服器的服務會將回應SMB封包傳回用戶端重新導向器,而用戶端重新導向器會返回應用程式。
由於這些差異,API 可以傳回不同類型的錯誤。 針對本機檔案,API 不會傳回網路錯誤。 針對網路檔案,API 可以傳回檔案存取錯誤,例如ERROR_ACCESS_DENIED和網路錯誤,例如 ERROR_UNEXP_NET_ERR,因為網路上可能發生任何一種錯誤。 刻意設計的行為,並紀錄在以下兩個位置的 Microsoft 開發人員網路(MSDN)資料庫:
網路 I/O 作業 的描述