次の方法で共有


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

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

元の KB 番号: 2990989

症状

次のシナリオを考えてみましょう。

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

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

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

パラメーターが正しくありません。 (パラメーターが無効です)

実行中のアプリケーションが、この状況で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_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 操作の の説明