アプリケーションから共有フォルダーにアクセスすると、予期しないエラーが返されます

この記事では、アプリケーションから共有フォルダーにアクセスするときに発生する予期しないエラーの解決策について説明します。

適用対象: Windows Server 2012 R2
元の KB 番号: 2990989

現象

次のような状況で問題が発生します。

  • Windows Server 2008 R2 で共有フォルダーを作成し、そのフォルダーに対してユーザー A の読み取りアクセス許可を付与します。
  • 共有フォルダーにサブフォルダーを作成し、サブフォルダーの親フォルダーからの継承可能なアクセス許可を無効にし、サブフォルダーに対してユーザー A の読み取りアクセス許可を付与しません。
  • ユーザー A としてWindows Server 2012 ベースのサーバーにログオンし、共有フォルダーに対して FindFirstFile を呼び出すアプリケーションを実行します。

このシナリオでは、アプリケーションは失敗します。 さらに、エラー ERROR_ACCESS_DENIEDは期待どおりに返されません。 代わりに、次のいずれかのエラー コードが返されます。

予期しないネットワーク エラーが発生しました。 (ERROR_UNEXP_NET_ERR)

パラメーターが間違っています。 (ERROR_INVALID_PARAMETER)

実行中のアプリケーションが、適切なアクセス権がないことを通知するためにこの状況でERROR_ACCESS_DENIEDが返されると想定している場合は、この想定が正しくない可能性があります。

原因

この問題は、STATUS_ERROR_ACCESS_DENIEDで I/O が失敗する状況で、カーネル モード SMB コンポーネントがSTATUS_UNEXPECTED_NETWORK_ERRORを返すからです。 同時に、SMB コンポーネントは別のスレッドの I/O を要求します。 このスレッドは、STATUS_INVALID_PARAMETERを返すことができます。

SMB コンポーネントから返されるこれらの NT 状態は、NT 状態がファイルまたはフォルダー API に渡されると、次のいずれかの Win32 エラーに変換されます。

  • ERROR_UNEXP_NET_ERR
  • ERROR_INVALID_PARAMETER

解決方法

アプリケーションがこの状況でERROR_ACCESS_DENIEDが返され、アクセス権がない共有フォルダーのサブフォルダーにアクセスするときにERROR_UNEXP_NET_ERRまたはERROR_INVALID_PARAMETERを受け取るかどうかを判断する場合は、ERROR_ACCESS_DENIEDを受信したときと同じ処理を実行することで、この問題を回避できます。

詳細

サブフォルダーを開くとき、Windows Server 2012のクライアント リダイレクターは 2 つの SMB パケットを送信します。 1 つのパケットは "作成" パケットで、もう 1 つは "クエリ ディレクトリ" パケットです。 作成パケットはディレクトリを開き、クエリ ディレクトリ パケットを使用すると、リダイレクターはサブフォルダーに関する情報を特定して、サブフォルダーを正しく処理できます。 パケットの作成は、STATUS_ACCESS_DENIEDで失敗します。 ただし、その後、クエリ ディレクトリ パケットもSTATUS_UNEXPECTED_NETWORK_ERRORで失敗します。 そのため、2 つのエラー コードがあります。 クエリ ディレクトリ アクションは作成後に発生したため、クエリ ディレクトリ エラー コードが返されます。

ERROR_ACCESS_DENIEDが返されるように Windows の設計が変更された場合でも、サーバーのクラッシュ、ネットワーク電源の損失など、実際のネットワーク エラーが発生する可能性があるため、ネットワーク共有にアクセスするアプリケーションは引き続き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などのネットワーク エラーなどのファイル アクセス エラーを返すことができます。 この動作は設計上のものであり、次の 2 つの場所にある Microsoft Developer Network (MSDN) ライブラリに記載されています。

ローカル I/O とネットワーク I/O の違い

ネットワーク I/O 操作の説明