Win32 API 日本語リファレンス
ホームStorage.FileSystem › WriteFileEx

WriteFileEx

関数
完了ルーチンを使い非同期でファイルに書き込む。
DLLKERNEL32.dll呼出規約winapiSetLastErrorあり対応OSWindows XP 以降

シグネチャ

// KERNEL32.dll
#include <windows.h>

BOOL WriteFileEx(
    HANDLE hFile,
    const BYTE* lpBuffer,   // optional
    DWORD nNumberOfBytesToWrite,
    OVERLAPPED* lpOverlapped,
    LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);

パラメーター

名前方向説明
hFileHANDLEin

ファイルまたは I/O デバイス (たとえば、ファイル、ファイルストリーム、物理ディスク、ボリューム、コンソールバッファー、テープドライブ、ソケット、通信リソース、メールスロット、パイプなど) へのハンドル。

このパラメーターには、CreateFile 関数で FILE_FLAG_OVERLAPPED フラグを指定して開いた任意のハンドル、または socket もしくは accept 関数が返すソケットハンドルを指定できます。

このハンドルに I/O 完了ポートを関連付けないでください。詳細については、「解説」セクションを参照してください。

また、このハンドルには GENERIC_WRITE アクセス権が必要です。アクセス権の詳細については、ファイルのセキュリティとアクセス権を参照してください。

lpBufferBYTE*inoptional

ファイルまたはデバイスに書き込むデータを格納したバッファーへのポインター。

このバッファーは、書き込み操作の間ずっと有効なまま保持する必要があります。呼び出し元は、書き込み操作が完了するまでこのバッファーを使用してはなりません。

nNumberOfBytesToWriteDWORDin

ファイルまたはデバイスに書き込むバイト数。

値 0 は、null 書き込み操作を指定します。null 書き込み操作の動作は、基になるファイルシステムによって異なります。

ネットワーク越しのパイプ書き込み操作は、1 回の書き込みあたり 65,535 バイトに制限されます。パイプの詳細については、「解説」セクションを参照してください。

lpOverlappedOVERLAPPED*inout

オーバーラップ (非同期) 書き込み操作中に使用するデータを提供する OVERLAPPED データ構造体へのポインター。

バイトオフセットをサポートするファイルでは、書き込みを開始するバイトオフセットを指定する必要があります。このオフセットは、OVERLAPPED 構造体の Offset および OffsetHigh メンバーを設定することで指定します。バイトオフセットをサポートしないファイルまたはデバイスでは、Offset および OffsetHigh は無視されます。

ファイルの末尾に書き込むには、OVERLAPPED 構造体の Offset メンバーと OffsetHigh メンバーの両方を 0xFFFFFFFF に指定します。これは、以前に CreateFile 関数を呼び出して FILE_APPEND_DATA アクセスで hFile を開いた場合と機能的に同等です。

WriteFileEx 関数は、OVERLAPPED 構造体の hEvent メンバーを無視します。アプリケーションは、WriteFileEx 呼び出しのコンテキストにおいて、このメンバーを独自の目的で自由に使用できます。WriteFileEx は、lpCompletionRoutine が指す完了ルーチンを呼び出すか、その呼び出しをキューに入れることで書き込み操作の完了を通知するため、イベントハンドルを必要としません。

WriteFileEx 関数は、OVERLAPPED 構造体の Internal および InternalHigh メンバーを使用します。これらのメンバーの値を変更してはなりません。

OVERLAPPED データ構造体は、書き込み操作の間ずっと有効なまま保持する必要があります。書き込み操作の完了待ちの間にスコープ外になり得る変数であってはなりません。

lpCompletionRoutineLPOVERLAPPED_COMPLETION_ROUTINEin書き込み操作が完了し、かつ呼び出し元スレッドがアラータブルな待機状態にあるときに呼び出される完了ルーチンへのポインター。この完了ルーチンの詳細については、FileIOCompletionRoutineを参照してください。

戻り値の型: BOOL

公式ドキュメント

指定したファイルまたは入出力 (I/O) デバイスにデータを書き込みます。完了状態は非同期的に報告され、書き込みが完了またはキャンセルされ、かつ呼び出し元スレッドがアラータブルな待機状態にあるときに、指定された完了ルーチンが呼び出されます。

戻り値

関数が成功すると、戻り値は 0 以外になります。

関数が失敗すると、戻り値は 0 になります。拡張エラー情報を取得するには、GetLastError を呼び出します。

WriteFileEx 関数が成功すると、呼び出し元スレッドには非同期 I/O 操作 (ファイルへのオーバーラップ書き込み操作) が保留中になります。この I/O 操作が完了し、かつ呼び出し元スレッドがアラータブルな待機状態でブロックされていると、オペレーティングシステムは lpCompletionRoutine が指す関数を呼び出し、待機は戻りコード WAIT_IO_COMPLETION で完了します。

関数が成功してファイル書き込み操作が完了しても、呼び出し元スレッドがアラータブルな待機状態にない場合、システムは *lpCompletionRoutine への呼び出しをキューに入れ、呼び出し元スレッドがアラータブルな待機状態に入るまでその呼び出しを保留します。アラータブルな待機状態とオーバーラップ入出力操作の詳細については、同期についてを参照してください。

解説(Remarks)

WriteFileEx を使用する場合は、関数が「成功」を返したときでも GetLastError を確認し、成功 ではあるものの把握しておきたい何らかの結果を伴う状況がないかをチェックしてください。たとえば、WriteFileEx の呼び出し時にバッファーオーバーフローが発生すると TRUE が返されますが、GetLastErrorERROR_MORE_DATA でそのオーバーフローを報告します。関数呼び出しが成功し、警告となる状況がない場合、GetLastErrorERROR_SUCCESS を返します。

WriteFileEx 関数は、hFile パラメーターが I/O 完了ポートに関連付けられている場合に失敗します。この種類のハンドルを使用して書き込みを行うには、WriteFile 関数を使用してください。

WriteFileEx 関数は、未処理の非同期 I/O 要求が多すぎる場合に失敗することがあります。そのような失敗が発生した場合、GetLastErrorERROR_INVALID_USER_BUFFER または ERROR_NOT_ENOUGH_MEMORY を返すことがあります。

保留中のすべての非同期 I/O 操作をキャンセルするには、次のいずれかを使用します。

保留中の同期 I/O 操作をキャンセルするには、CancelSynchronousIo を使用します。

キャンセルされた I/O 操作は、エラー ERROR_OPERATION_ABORTED で完了します。

hFile で指定したファイルの一部が別のプロセスによってロックされており、指定した書き込み操作がそのロックされた部分と重なる場合、WriteFileEx は失敗します。

ファイルへの書き込みでは、書き込みに使用したすべてのハンドルが閉じられるまで、最終書き込み時刻は完全には更新されません。したがって、正確な最終書き込み時刻を保証するには、ファイルへの書き込み後すぐにファイルハンドルを閉じてください。

書き込み操作がバッファーを使用している間に出力バッファーにアクセスすると、そのバッファーから書き込まれるデータが破損する可能性があります。アプリケーションは、書き込み操作が完了するまで、その書き込み操作が使用している出力バッファーへの書き込み、再割り当て、または解放を行ってはなりません。

リモートファイルの場合、タイムスタンプが正しく更新されないことがある点に注意してください。一貫した結果を得るには、バッファリングなしの I/O を使用してください。

システムは書き込みバイト数 0 を null 書き込み操作の指定として解釈し、WriteFile はファイルの切り詰めや拡張を行いません。ファイルを切り詰めたり拡張したりするには、SetEndOfFile 関数を使用します。

アプリケーションは、WaitForSingleObjectExWaitForMultipleObjectsExMsgWaitForMultipleObjectsExSignalObjectAndWait、および SleepEx 関数を使用してアラータブルな待機状態に入ります。アラータブルな待機状態とオーバーラップ I/O 操作の詳細については、同期についてを参照してください。

マウントされたファイルシステムを持つボリュームに直接書き込む場合は、まずそのボリュームへの排他アクセスを取得する必要があります。そうしないと、アプリケーションの書き込みがファイルシステム側からの他の変更と競合し、ボリュームの内容が不整合な状態になるおそれがあるため、データ破損やシステムの不安定化を引き起こす危険があります。これらの問題を防ぐため、Windows Vista 以降では次の変更が加えられています。

FILE_FLAG_NO_BUFFERING を使用して CreateFile で開いたファイルを正しく扱うには、厳格な要件があります。詳細については、ファイルバッファリングを参照してください。

Windows 8 および Windows Server 2012 では、この関数は次のテクノロジでサポートされています。

テクノロジ サポート
Server Message Block (SMB) 3.0 プロトコル あり
SMB 3.0 透過的フェールオーバー (TFO) あり
スケールアウトファイル共有 (SO) を使用した SMB 3.0 あり
クラスター共有ボリュームファイルシステム (CsvFS) あり
回復性ファイルシステム (ReFS) あり

トランザクション操作

ファイルハンドルにトランザクションがバインドされている場合、ファイル書き込みはトランザクション処理されます。詳細については、トランザクション NTFS についてを参照してください。

例については、完了ルーチンを使用した名前付きパイプサーバーを参照してください。

出典・ライセンス: 上記「公式ドキュメント」の内容は Microsoft の Win32 API ドキュメント(MicrosoftDocs/sdk-api)を日本語に翻訳・改変したものです。© Microsoft Corporation. CC BY 4.0 で提供。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)

各言語での呼び出し定義

// KERNEL32.dll
#include <windows.h>

BOOL WriteFileEx(
    HANDLE hFile,
    const BYTE* lpBuffer,   // optional
    DWORD nNumberOfBytesToWrite,
    OVERLAPPED* lpOverlapped,
    LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("KERNEL32.dll", SetLastError = true, ExactSpelling = true)]
static extern bool WriteFileEx(
    IntPtr hFile,   // HANDLE
    IntPtr lpBuffer,   // BYTE* optional
    uint nNumberOfBytesToWrite,   // DWORD
    IntPtr lpOverlapped,   // OVERLAPPED* in/out
    IntPtr lpCompletionRoutine   // LPOVERLAPPED_COMPLETION_ROUTINE
);
<DllImport("KERNEL32.dll", SetLastError:=True, ExactSpelling:=True)>
Public Shared Function WriteFileEx(
    hFile As IntPtr,   ' HANDLE
    lpBuffer As IntPtr,   ' BYTE* optional
    nNumberOfBytesToWrite As UInteger,   ' DWORD
    lpOverlapped As IntPtr,   ' OVERLAPPED* in/out
    lpCompletionRoutine As IntPtr   ' LPOVERLAPPED_COMPLETION_ROUTINE
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
' hFile : HANDLE
' lpBuffer : BYTE* optional
' nNumberOfBytesToWrite : DWORD
' lpOverlapped : OVERLAPPED* in/out
' lpCompletionRoutine : LPOVERLAPPED_COMPLETION_ROUTINE
Declare PtrSafe Function WriteFileEx Lib "kernel32" ( _
    ByVal hFile As LongPtr, _
    ByVal lpBuffer As LongPtr, _
    ByVal nNumberOfBytesToWrite As Long, _
    ByVal lpOverlapped As LongPtr, _
    ByVal lpCompletionRoutine As LongPtr) As Long
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。
import ctypes
from ctypes import wintypes

WriteFileEx = ctypes.windll.kernel32.WriteFileEx
WriteFileEx.restype = wintypes.BOOL
WriteFileEx.argtypes = [
    wintypes.HANDLE,  # hFile : HANDLE
    ctypes.POINTER(ctypes.c_ubyte),  # lpBuffer : BYTE* optional
    wintypes.DWORD,  # nNumberOfBytesToWrite : DWORD
    ctypes.c_void_p,  # lpOverlapped : OVERLAPPED* in/out
    ctypes.c_void_p,  # lpCompletionRoutine : LPOVERLAPPED_COMPLETION_ROUTINE
]
# GetLastError: use ctypes.GetLastError() (or ctypes.WinDLL(use_last_error=True))
require 'fiddle'
require 'fiddle/import'

lib = Fiddle.dlopen('KERNEL32.dll')
WriteFileEx = Fiddle::Function.new(
  lib['WriteFileEx'],
  [
    Fiddle::TYPE_VOIDP,  # hFile : HANDLE
    Fiddle::TYPE_VOIDP,  # lpBuffer : BYTE* optional
    -Fiddle::TYPE_INT,  # nNumberOfBytesToWrite : DWORD
    Fiddle::TYPE_VOIDP,  # lpOverlapped : OVERLAPPED* in/out
    Fiddle::TYPE_VOIDP,  # lpCompletionRoutine : LPOVERLAPPED_COMPLETION_ROUTINE
  ],
  Fiddle::TYPE_INT)
#[link(name = "kernel32")]
extern "system" {
    fn WriteFileEx(
        hFile: *mut core::ffi::c_void,  // HANDLE
        lpBuffer: *const u8,  // BYTE* optional
        nNumberOfBytesToWrite: u32,  // DWORD
        lpOverlapped: *mut OVERLAPPED,  // OVERLAPPED* in/out
        lpCompletionRoutine: *const core::ffi::c_void  // LPOVERLAPPED_COMPLETION_ROUTINE
    ) -> i32;
}
// crates: windows-sys provides ready-made bindings for this API.
$sig = @"
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("KERNEL32.dll", SetLastError = true)]
public static extern bool WriteFileEx(IntPtr hFile, IntPtr lpBuffer, uint nNumberOfBytesToWrite, IntPtr lpOverlapped, IntPtr lpCompletionRoutine);
"@
$api = Add-Type -MemberDefinition $sig -Name 'KERNEL32_WriteFileEx' -Namespace Win32 -PassThru
# $api::WriteFileEx(hFile, lpBuffer, nNumberOfBytesToWrite, lpOverlapped, lpCompletionRoutine)
#uselib "KERNEL32.dll"
#func global WriteFileEx "WriteFileEx" sptr, sptr, sptr, sptr, sptr
; WriteFileEx hFile, varptr(lpBuffer), nNumberOfBytesToWrite, varptr(lpOverlapped), lpCompletionRoutine   ; 戻り値は stat
; hFile : HANDLE -> "sptr"
; lpBuffer : BYTE* optional -> "sptr"
; nNumberOfBytesToWrite : DWORD -> "sptr"
; lpOverlapped : OVERLAPPED* in/out -> "sptr"
; lpCompletionRoutine : LPOVERLAPPED_COMPLETION_ROUTINE -> "sptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。
出力引数:
#uselib "KERNEL32.dll"
#cfunc global WriteFileEx "WriteFileEx" sptr, var, int, var, sptr
; res = WriteFileEx(hFile, lpBuffer, nNumberOfBytesToWrite, lpOverlapped, lpCompletionRoutine)
; hFile : HANDLE -> "sptr"
; lpBuffer : BYTE* optional -> "var"
; nNumberOfBytesToWrite : DWORD -> "int"
; lpOverlapped : OVERLAPPED* in/out -> "var"
; lpCompletionRoutine : LPOVERLAPPED_COMPLETION_ROUTINE -> "sptr"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
出力引数:
; BOOL WriteFileEx(HANDLE hFile, BYTE* lpBuffer, DWORD nNumberOfBytesToWrite, OVERLAPPED* lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
#uselib "KERNEL32.dll"
#cfunc global WriteFileEx "WriteFileEx" intptr, var, int, var, intptr
; res = WriteFileEx(hFile, lpBuffer, nNumberOfBytesToWrite, lpOverlapped, lpCompletionRoutine)
; hFile : HANDLE -> "intptr"
; lpBuffer : BYTE* optional -> "var"
; nNumberOfBytesToWrite : DWORD -> "int"
; lpOverlapped : OVERLAPPED* in/out -> "var"
; lpCompletionRoutine : LPOVERLAPPED_COMPLETION_ROUTINE -> "intptr"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
import (
	"golang.org/x/sys/windows"
	"unsafe"
)

var (
	kernel32 = windows.NewLazySystemDLL("KERNEL32.dll")
	procWriteFileEx = kernel32.NewProc("WriteFileEx")
)

// hFile (HANDLE), lpBuffer (BYTE* optional), nNumberOfBytesToWrite (DWORD), lpOverlapped (OVERLAPPED* in/out), lpCompletionRoutine (LPOVERLAPPED_COMPLETION_ROUTINE)
r1, _, err := procWriteFileEx.Call(
	uintptr(hFile),
	uintptr(lpBuffer),
	uintptr(nNumberOfBytesToWrite),
	uintptr(lpOverlapped),
	uintptr(lpCompletionRoutine),
)
_ = err  // syscall.Errno (valid when the call sets last-error)
_ = r1   // BOOL
function WriteFileEx(
  hFile: THandle;   // HANDLE
  lpBuffer: Pointer;   // BYTE* optional
  nNumberOfBytesToWrite: DWORD;   // DWORD
  lpOverlapped: Pointer;   // OVERLAPPED* in/out
  lpCompletionRoutine: Pointer   // LPOVERLAPPED_COMPLETION_ROUTINE
): BOOL; stdcall;
  external 'KERNEL32.dll' name 'WriteFileEx';
result := DllCall("KERNEL32\WriteFileEx"
    , "Ptr", hFile   ; HANDLE
    , "Ptr", lpBuffer   ; BYTE* optional
    , "UInt", nNumberOfBytesToWrite   ; DWORD
    , "Ptr", lpOverlapped   ; OVERLAPPED* in/out
    , "Ptr", lpCompletionRoutine   ; LPOVERLAPPED_COMPLETION_ROUTINE
    , "Int")   ; return: BOOL
●WriteFileEx(hFile, lpBuffer, nNumberOfBytesToWrite, lpOverlapped, lpCompletionRoutine) = DLL("KERNEL32.dll", "bool WriteFileEx(void*, void*, dword, void*, void*)")
# 呼び出し: WriteFileEx(hFile, lpBuffer, nNumberOfBytesToWrite, lpOverlapped, lpCompletionRoutine)
# hFile : HANDLE -> "void*"
# lpBuffer : BYTE* optional -> "void*"
# nNumberOfBytesToWrite : DWORD -> "dword"
# lpOverlapped : OVERLAPPED* in/out -> "void*"
# lpCompletionRoutine : LPOVERLAPPED_COMPLETION_ROUTINE -> "void*"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。
const std = @import("std");

extern "kernel32" fn WriteFileEx(
    hFile: ?*anyopaque, // HANDLE
    lpBuffer: [*c]u8, // BYTE* optional
    nNumberOfBytesToWrite: u32, // DWORD
    lpOverlapped: [*c]OVERLAPPED, // OVERLAPPED* in/out
    lpCompletionRoutine: ?*anyopaque // LPOVERLAPPED_COMPLETION_ROUTINE
) callconv(std.os.windows.WINAPI) i32;
proc WriteFileEx(
    hFile: pointer,  # HANDLE
    lpBuffer: ptr uint8,  # BYTE* optional
    nNumberOfBytesToWrite: uint32,  # DWORD
    lpOverlapped: ptr OVERLAPPED,  # OVERLAPPED* in/out
    lpCompletionRoutine: pointer  # LPOVERLAPPED_COMPLETION_ROUTINE
): int32 {.importc: "WriteFileEx", stdcall, dynlib: "KERNEL32.dll".}
pragma(lib, "kernel32");
extern(Windows)
int WriteFileEx(
    void* hFile,   // HANDLE
    ubyte* lpBuffer,   // BYTE* optional
    uint nNumberOfBytesToWrite,   // DWORD
    OVERLAPPED* lpOverlapped,   // OVERLAPPED* in/out
    void* lpCompletionRoutine   // LPOVERLAPPED_COMPLETION_ROUTINE
);
ccall((:WriteFileEx, "KERNEL32.dll"), stdcall, Int32,
      (Ptr{Cvoid}, Ptr{UInt8}, UInt32, Ptr{OVERLAPPED}, Ptr{Cvoid}),
      hFile, lpBuffer, nNumberOfBytesToWrite, lpOverlapped, lpCompletionRoutine)
# hFile : HANDLE -> Ptr{Cvoid}
# lpBuffer : BYTE* optional -> Ptr{UInt8}
# nNumberOfBytesToWrite : DWORD -> UInt32
# lpOverlapped : OVERLAPPED* in/out -> Ptr{OVERLAPPED}
# lpCompletionRoutine : LPOVERLAPPED_COMPLETION_ROUTINE -> Ptr{Cvoid}
# stdcall は 32bit のみ意味を持つ(x64 では無視)。
local ffi = require("ffi")
ffi.cdef[[
int32_t WriteFileEx(
    void* hFile,
    uint8_t* lpBuffer,
    uint32_t nNumberOfBytesToWrite,
    void* lpOverlapped,
    void* lpCompletionRoutine);
]]
local kernel32 = ffi.load("kernel32")
-- kernel32.WriteFileEx(hFile, lpBuffer, nNumberOfBytesToWrite, lpOverlapped, lpCompletionRoutine)
-- hFile : HANDLE
-- lpBuffer : BYTE* optional
-- nNumberOfBytesToWrite : DWORD
-- lpOverlapped : OVERLAPPED* in/out
-- lpCompletionRoutine : LPOVERLAPPED_COMPLETION_ROUTINE
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
const koffi = require('koffi');
const lib = koffi.load('KERNEL32.dll');
const WriteFileEx = lib.func('__stdcall', 'WriteFileEx', 'int32_t', ['void *', 'uint8_t *', 'uint32_t', 'void *', 'void *']);
// WriteFileEx(hFile, lpBuffer, nNumberOfBytesToWrite, lpOverlapped, lpCompletionRoutine)
// hFile : HANDLE -> 'void *'
// lpBuffer : BYTE* optional -> 'uint8_t *'
// nNumberOfBytesToWrite : DWORD -> 'uint32_t'
// lpOverlapped : OVERLAPPED* in/out -> 'void *'
// lpCompletionRoutine : LPOVERLAPPED_COMPLETION_ROUTINE -> 'void *'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。
// コールバック(関数ポインタ)は koffi.proto/koffi.register で型を定義して渡す(素の void* では JS 関数を渡せない)。
const lib = Deno.dlopen("KERNEL32.dll", {
  WriteFileEx: { parameters: ["pointer", "pointer", "u32", "pointer", "pointer"], result: "i32" },
});
// lib.symbols.WriteFileEx(hFile, lpBuffer, nNumberOfBytesToWrite, lpOverlapped, lpCompletionRoutine)
// hFile : HANDLE -> "pointer"
// lpBuffer : BYTE* optional -> "pointer"
// nNumberOfBytesToWrite : DWORD -> "u32"
// lpOverlapped : OVERLAPPED* in/out -> "pointer"
// lpCompletionRoutine : LPOVERLAPPED_COMPLETION_ROUTINE -> "pointer"
// 文字列引数は "buffer"(NUL 終端のバイト列を Uint8Array で渡す)。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。
<?php
$ffi = FFI::cdef(<<<C
int32_t WriteFileEx(
    void* hFile,
    uint8_t* lpBuffer,
    uint32_t nNumberOfBytesToWrite,
    void* lpOverlapped,
    void* lpCompletionRoutine);
C, "KERNEL32.dll");
// $ffi->WriteFileEx(hFile, lpBuffer, nNumberOfBytesToWrite, lpOverlapped, lpCompletionRoutine);
// hFile : HANDLE
// lpBuffer : BYTE* optional
// nNumberOfBytesToWrite : DWORD
// lpOverlapped : OVERLAPPED* in/out
// lpCompletionRoutine : LPOVERLAPPED_COMPLETION_ROUTINE
// 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
// WINAPI(stdcall): x64 では呼出規約が統一されるため問題なし。x86 では __stdcall 対応のラッパが必要な場合あり。
import com.sun.jna.*;
import com.sun.jna.ptr.*;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;

public interface Kernel32 extends StdCallLibrary {
    Kernel32 INSTANCE = Native.load("kernel32", Kernel32.class);
    boolean WriteFileEx(
        Pointer hFile,   // HANDLE
        byte[] lpBuffer,   // BYTE* optional
        int nNumberOfBytesToWrite,   // DWORD
        Pointer lpOverlapped,   // OVERLAPPED* in/out
        Callback lpCompletionRoutine   // LPOVERLAPPED_COMPLETION_ROUTINE
    );
}
@[Link("kernel32")]
lib LibKERNEL32
  fun WriteFileEx = WriteFileEx(
    hFile : Void*,   # HANDLE
    lpBuffer : UInt8*,   # BYTE* optional
    nNumberOfBytesToWrite : UInt32,   # DWORD
    lpOverlapped : OVERLAPPED*,   # OVERLAPPED* in/out
    lpCompletionRoutine : Void*   # LPOVERLAPPED_COMPLETION_ROUTINE
  ) : Int32
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。
import 'dart:ffi';
import 'package:ffi/ffi.dart';

typedef WriteFileExNative = Int32 Function(Pointer<Void>, Pointer<Uint8>, Uint32, Pointer<Void>, Pointer<Void>);
typedef WriteFileExDart = int Function(Pointer<Void>, Pointer<Uint8>, int, Pointer<Void>, Pointer<Void>);
final WriteFileEx = DynamicLibrary.open('KERNEL32.dll')
    .lookupFunction<WriteFileExNative, WriteFileExDart>('WriteFileEx');
// hFile : HANDLE -> Pointer<Void>
// lpBuffer : BYTE* optional -> Pointer<Uint8>
// nNumberOfBytesToWrite : DWORD -> Uint32
// lpOverlapped : OVERLAPPED* in/out -> Pointer<Void>
// lpCompletionRoutine : LPOVERLAPPED_COMPLETION_ROUTINE -> Pointer<Void>
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。
{$mode objfpc}{$H+}
function WriteFileEx(
  hFile: THandle;   // HANDLE
  lpBuffer: Pointer;   // BYTE* optional
  nNumberOfBytesToWrite: DWORD;   // DWORD
  lpOverlapped: Pointer;   // OVERLAPPED* in/out
  lpCompletionRoutine: Pointer   // LPOVERLAPPED_COMPLETION_ROUTINE
): BOOL; stdcall;
  external 'KERNEL32.dll' name 'WriteFileEx';
import Foreign
import Foreign.C.Types
import Foreign.C.String

foreign import stdcall safe "WriteFileEx"
  c_WriteFileEx :: Ptr () -> Ptr Word8 -> Word32 -> Ptr () -> Ptr () -> IO CInt
-- hFile : HANDLE -> Ptr ()
-- lpBuffer : BYTE* optional -> Ptr Word8
-- nNumberOfBytesToWrite : DWORD -> Word32
-- lpOverlapped : OVERLAPPED* in/out -> Ptr ()
-- lpCompletionRoutine : LPOVERLAPPED_COMPLETION_ROUTINE -> Ptr ()
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。
open Ctypes
open Foreign

let writefileex =
  foreign "WriteFileEx"
    ((ptr void) @-> (ptr uint8_t) @-> uint32_t @-> (ptr void) @-> (ptr void) @-> returning int32_t)
(* hFile : HANDLE -> (ptr void) *)
(* lpBuffer : BYTE* optional -> (ptr uint8_t) *)
(* nNumberOfBytesToWrite : DWORD -> uint32_t *)
(* lpOverlapped : OVERLAPPED* in/out -> (ptr void) *)
(* lpCompletionRoutine : LPOVERLAPPED_COMPLETION_ROUTINE -> (ptr void) *)
(* foreign は cdecl 前提。x64 Windows では WINAPI と一致。構造体は ctypes structure を定義のこと。 *)
(cffi:define-foreign-library kernel32 (t "KERNEL32.dll"))
(cffi:use-foreign-library kernel32)

(cffi:defcfun ("WriteFileEx" write-file-ex :convention :stdcall) :int32
  (h-file :pointer)   ; HANDLE
  (lp-buffer :pointer)   ; BYTE* optional
  (n-number-of-bytes-to-write :uint32)   ; DWORD
  (lp-overlapped :pointer)   ; OVERLAPPED* in/out
  (lp-completion-routine :pointer))   ; LPOVERLAPPED_COMPLETION_ROUTINE
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $WriteFileEx = Win32::API::More->new('KERNEL32',
    'BOOL WriteFileEx(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPVOID lpOverlapped, LPVOID lpCompletionRoutine)');
# my $ret = $WriteFileEx->Call($hFile, $lpBuffer, $nNumberOfBytesToWrite, $lpOverlapped, $lpCompletionRoutine);
# hFile : HANDLE -> HANDLE
# lpBuffer : BYTE* optional -> LPVOID
# nNumberOfBytesToWrite : DWORD -> DWORD
# lpOverlapped : OVERLAPPED* in/out -> LPVOID
# lpCompletionRoutine : LPOVERLAPPED_COMPLETION_ROUTINE -> LPVOID
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。
# コールバック(関数ポインタ)は Perl sub を直接渡せません。Win32::API::Callback を使用してください。

関連項目

類似 API
使用する型