<Return[WXYZ]><Top>

WriteFileEx

Declare Function Api_WriteFileEx& Lib "kernel32" Alias "WriteFileEx" (ByVal hFile&, lpBuffer As Any, ByVal nNumberOfBytesToWrite&, lpOverlapped As OVERLAPPED, ByVal lpCompletionRoutine&)

Declare Function WriteFileEx Lib "kernel32" Alias "WriteFileEx" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpOverlapped As OVERLAPPED, ByVal lpCompletionRoutine As Long) As Long

ファイルにデータを非同期的に書き込む。WriteFile 関数は同期と非同期の両方の操作を想定して設計されているが、WriteFileEx 関数は非同期の操作だけを想定して設計されている。書き込み操作が完了または取り消された時点で、呼び出し側スレッドがアラート可能な待機状態になっている場合、WriteFileEx 関数は指定の完了ルーチンを呼び出して、完了のステータスを非同期で報告する。

パラメータ
hFile
    書き込み対象のファイルのハンドルを指定する。このハンドルは、FILE_FLAG_OVERLAPPED フラグを指定して作成したものでなければ

    ならない。また、GENERIC_WRITE アクセス権も備えていなければならない。
    Windows NT/2000:FILE_FLAG_OVERLAPPED フラグを指定し CreateFile 関数を呼び出して開いた任意のハンドル、または と どちら

    かの関数が返したソケットのハンドルを指定する。
    Windows 95/98:FILE_FLAG_OVERLAPPED フラグを指定し CreateFile 関数を呼び出して開いた通信リソース、または socket と

    accept どちらかの関数が返したソケットのハンドルを指定する。メールスロット、名前付きパイプ、ディスクファイルに対する非同期書き込み

    操作はサポートしていない。
lpBuffer
    書き込むべきデータを保持しているバッファへのポインタを指定する。
    このバッファは、書き込み操作が完了するまで、常に有効な状態にしておかなければならない。また、書き込み操作が完了するまで、呼

    び出し側はこのバッファを使ってはならない。
nNumberOfBytesToWrite
    書き込み対象のバイト数を指定する。
    0 を指定すると、この関数は何の処理も行わない。特に、ファイルを切り捨てることもない。
lpOverlapped
    1 個の 構造体へのポインタを指定する。

    この構造体は、非同期(オーバーラップ)ファイル書き込み操作の際に使われるデータを提供する。
    hFile パラメータで指定したファイルがバイトオフセットの概念をサポートしている場合、開発者は書き込みを開始するバイトオフセットを指定し

    なければならない。OVERLAPPED 構造体の Offset と OffsetHigh の各メンバを設定して、バイトオフセットを指定する。バイトオフセットを

    サポートしないファイルでは、Offset と OffsetHigh の各メンバは無視される。
    WriteFileEx 関数は、OVERLAPPED 構造体の hEvent メンバを無視する。アプリケーションは、WriteFileEx を呼び出すコンテキスト

    で、このメンバをで自由に使ってかまわない。WriteFileEx 関数は、lpCompletionRoutine パラメータで指定された完了ルーチンを呼び出す

    (または呼び出しの指示をキューに入れる)ことによって、書き込み操作の完了を通知するので、イベントのハンドルは必要ない。
    WriteFileEx 関数は、OVERLAPPED 構造体の Internal と InternalHigh の各メンバを使う。開発者は、これらのメンバの値を変更する

    べきではない。
    構造体は、書き込み操作が完了するまで、常に有効な状態にしておかなければならない。非同期書き込み操作が完了せずに未処理のま

    まになっている間に、スコープから外れてしまう変数を指定しないよう注意する。
lpCompletionRoutine
    完了ルーチンへのポインタを指定する。書き込み操作が完了し、かつ、呼び出し側スレッドがアラート可能な待機状態になっている場合、こ

    の完了ルーチンが呼び出される。

戻り値
    関数が成功すると、0 以外の値が返る。
    関数が失敗すると、0 が返る。拡張エラー情報を取得するには、 関数を使う。
    WriteFileEx 関数が成功すると、非同期 I/O(入出力)操作、つまりファイルのオーバーラップ書き込み操作が開始される。この I/O 操

    作が完了した時点で、呼び出し側スレッドがアラート可能な待機状態でブロックされている(その先への進行を妨害されている、つまり待機

    している)場合、システムは、lpCompletionRoutine パラメータで指定した完了ルーチンを呼び出し、待機状態が完了し、WriteFileEx 関

    数の戻り値は、WAIT_IO_COMPLETION になる。
    この関数が成功し、ファイル書き込み操作が完了した時点で、呼び出し側スレッドがアラート可能な待機状態にとどまっていなかった場合、

    システムは *lpCompletionRoutine パラメータで指定された完了ルーチンの呼び出し命令をキューに追加し、呼び出し側スレッドがアラート可

    能な待機状態になるのを待つ。

解説
    WriteFileEx 関数を使う場合、この関数が「成功」を示す値を返していても、それだけでは不十分である。GetLastError 関数を呼び出し

    て、いくつかの条件が「成功」しているだけで、把握するべき他の条件がエラーになっていないかどうかをチェックする。たとえば、

    WriteFileEx を呼び出してバッファオーバーフローが発生した場合、WriteFileEx は成功を示す、0 以外の値(TRUE)を返す。しかし、

    GetLastError は ERROR_MORE_DATA を返して、オーバーフローが発生したことを報告する。WriteFileEx 関数が成功し、待機するべ

    き条件が存在しない場合、GetLastError は ERROR_SUCCESS(操作は成功して完了)を返す。
    FILE_FLAG_NO_BUFFERING フラグを指定してファイルを開いた後、そのファイルの作業を行う場合、アプリケーションは次の各要件を

    満たさなければならない。
    ●ファイルアクセスは、ボリュームのセクタサイズの整数倍のバイトオフセットの位置で開始しなければならない。ボリュームのセクタサイズを判

      断するには、GetDiskFreeSpace 関数を呼び出す。
    ●ファイルアクセスのバイト数を、ボリュームのセクタサイズの整数倍にしなければならない。たとえば、セクタサイズが 512 バイトの場合、512

      バイト、1,024 バイト、2,048 バイトの読み書きはできるが、335 バイト、981 バイト、7,171 バイトなどの読み書きはできない。
    ●読み書き操作用のバッファのアドレス(メモリ内のアドレス)を、ボリュームのセクタサイズの整数倍に整列(セクタ整列)させなければな

      らない。バッファをセクタ整列させる 1 つの方法は、 関数を使ってバッファを割り当てることである。VirtualAlloc 関数が割り当てるメモリ

      は、システムのページサイズの整数倍のアドレスに整列されている。ページサイズとボリュームのセクタサイズは両方とも 2 のべき乗なの

      で、システムのページサイズの整数倍に整列されたメモリは、ボリュームのセクタサイズの整数倍のアドレスにも整列される。
    ほかのプロセスが、hFile パラメータで指定したファイルの一部をロック(共有ロックまたは排他ロック)している場合、WriteFileEx 関数で

    書き込み操作を行うよう指定した範囲がロック済みの領域と重なっていると、この関数は失敗する。
    出力バッファを使って書き込み操作を行っている間にそのバッファにアクセスすると、そのバッファを使って書き込んだデータが壊れることがあ

    る。書き込み操作が完了するまでは、アプリケーションは出力バッファの読み取り、書き込み、再割り当て、解放を行ってはならない。
    未処理の非同期 I/O 要求が大量に残っている場合、WriteFileEx 関数は失敗することがある。このような障害が発生した場合、

    GetLastError 関数は、ERROR_INVALID_USER_BUFFER または ERROR_NOT_ENOUGH_MEMORY を返すことがある。
    未処理のすべての非同期 I/O 操作を取り消すには、CancelIo 関数を使う。この関数は、指定されたファイルハンドルに対して呼び出し側

    プロセスが発行した操作だけを取り消す。取り消された各 I/O 操作は、ERROR_OPERATION_ABORTED エラーを返して終了する。
    フロッピーディスクの入っていないフロッピーディスクドライブへのデータの書き込みを行おうとすると、システムはユーザーに対して、操作を再

    試行するかどうかを尋ねるメッセージボックスを表示する。このメッセージボックスの表示を回避するには、

    SEM_NOOPENFILEERRORBOX を指定して 関数を呼び出す。
    Windows 95/98:通信ポートに対して ReadFileEx 関数や WriteFileEx 関数を実行することはできない。しかし、ReadFile 関数と

    WriteFile 関数を使って非同期通信を行うことができる。