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

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

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

現象

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

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

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

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

パラメーターが正しくありません。 (ERROR_INVALID_PARAMETER)

実行しているアプリケーションが、この状況で ERROR_ACCESS_DENIED が返され、適切なアクセス権がない場合は、この前提が正しくない可能性があります。

原因

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

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

  • ERROR_UNEXP_NET_ERR
  • ERROR_INVALID_PARAMETER

解決方法

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

詳細

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

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 はネットワーク エラーを返しません。 ネットワーク ファイルの場合、ネットワーク上でいずれかの種類のエラーが発生する可能性ERROR_ACCESS_DENIED のようなファイル アクセス エラーや ERROR_UNEXP_NET_ERR のようなネットワーク エラーを返す場合があります。 この動作は設計上の方法であり、次の 2 つの場所Microsoft Developer Network (MSDN) ライブラリに記載されています。

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

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