WriteFileEx
関数シグネチャ
// KERNEL32.dll
#include <windows.h>
BOOL WriteFileEx(
HANDLE hFile,
const BYTE* lpBuffer, // optional
DWORD nNumberOfBytesToWrite,
OVERLAPPED* lpOverlapped,
LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);パラメーター
| 名前 | 型 | 方向 | 説明 |
|---|---|---|---|
| hFile | HANDLE | in | ファイルまたは I/O デバイス (たとえば、ファイル、ファイルストリーム、物理ディスク、ボリューム、コンソールバッファー、テープドライブ、ソケット、通信リソース、メールスロット、パイプなど) へのハンドル。 このパラメーターには、CreateFile 関数で FILE_FLAG_OVERLAPPED フラグを指定して開いた任意のハンドル、または socket もしくは accept 関数が返すソケットハンドルを指定できます。 このハンドルに I/O 完了ポートを関連付けないでください。詳細については、「解説」セクションを参照してください。 また、このハンドルには GENERIC_WRITE アクセス権が必要です。アクセス権の詳細については、ファイルのセキュリティとアクセス権を参照してください。 |
| lpBuffer | BYTE* | inoptional | ファイルまたはデバイスに書き込むデータを格納したバッファーへのポインター。 このバッファーは、書き込み操作の間ずっと有効なまま保持する必要があります。呼び出し元は、書き込み操作が完了するまでこのバッファーを使用してはなりません。 |
| nNumberOfBytesToWrite | DWORD | in | ファイルまたはデバイスに書き込むバイト数。 値 0 は、null 書き込み操作を指定します。null 書き込み操作の動作は、基になるファイルシステムによって異なります。 ネットワーク越しのパイプ書き込み操作は、1 回の書き込みあたり 65,535 バイトに制限されます。パイプの詳細については、「解説」セクションを参照してください。 |
| lpOverlapped | OVERLAPPED* | inout | オーバーラップ (非同期) 書き込み操作中に使用するデータを提供する OVERLAPPED データ構造体へのポインター。 バイトオフセットをサポートするファイルでは、書き込みを開始するバイトオフセットを指定する必要があります。このオフセットは、OVERLAPPED 構造体の Offset および OffsetHigh メンバーを設定することで指定します。バイトオフセットをサポートしないファイルまたはデバイスでは、Offset および OffsetHigh は無視されます。 ファイルの末尾に書き込むには、OVERLAPPED 構造体の Offset メンバーと OffsetHigh メンバーの両方を WriteFileEx 関数は、OVERLAPPED 構造体の hEvent メンバーを無視します。アプリケーションは、WriteFileEx 呼び出しのコンテキストにおいて、このメンバーを独自の目的で自由に使用できます。WriteFileEx は、lpCompletionRoutine が指す完了ルーチンを呼び出すか、その呼び出しをキューに入れることで書き込み操作の完了を通知するため、イベントハンドルを必要としません。 WriteFileEx 関数は、OVERLAPPED 構造体の Internal および InternalHigh メンバーを使用します。これらのメンバーの値を変更してはなりません。 OVERLAPPED データ構造体は、書き込み操作の間ずっと有効なまま保持する必要があります。書き込み操作の完了待ちの間にスコープ外になり得る変数であってはなりません。 |
| lpCompletionRoutine | LPOVERLAPPED_COMPLETION_ROUTINE | in | 書き込み操作が完了し、かつ呼び出し元スレッドがアラータブルな待機状態にあるときに呼び出される完了ルーチンへのポインター。この完了ルーチンの詳細については、FileIOCompletionRoutineを参照してください。 |
戻り値の型: BOOL
公式ドキュメント
指定したファイルまたは入出力 (I/O) デバイスにデータを書き込みます。完了状態は非同期的に報告され、書き込みが完了またはキャンセルされ、かつ呼び出し元スレッドがアラータブルな待機状態にあるときに、指定された完了ルーチンが呼び出されます。
戻り値
関数が成功すると、戻り値は 0 以外になります。
関数が失敗すると、戻り値は 0 になります。拡張エラー情報を取得するには、GetLastError を呼び出します。
WriteFileEx 関数が成功すると、呼び出し元スレッドには非同期 I/O 操作 (ファイルへのオーバーラップ書き込み操作) が保留中になります。この I/O 操作が完了し、かつ呼び出し元スレッドがアラータブルな待機状態でブロックされていると、オペレーティングシステムは lpCompletionRoutine が指す関数を呼び出し、待機は戻りコード WAIT_IO_COMPLETION で完了します。
関数が成功してファイル書き込み操作が完了しても、呼び出し元スレッドがアラータブルな待機状態にない場合、システムは *lpCompletionRoutine への呼び出しをキューに入れ、呼び出し元スレッドがアラータブルな待機状態に入るまでその呼び出しを保留します。アラータブルな待機状態とオーバーラップ入出力操作の詳細については、同期についてを参照してください。
解説(Remarks)
WriteFileEx を使用する場合は、関数が「成功」を返したときでも GetLastError を確認し、成功 ではあるものの把握しておきたい何らかの結果を伴う状況がないかをチェックしてください。たとえば、WriteFileEx の呼び出し時にバッファーオーバーフローが発生すると TRUE が返されますが、GetLastError は ERROR_MORE_DATA でそのオーバーフローを報告します。関数呼び出しが成功し、警告となる状況がない場合、GetLastError は ERROR_SUCCESS を返します。
WriteFileEx 関数は、hFile パラメーターが I/O 完了ポートに関連付けられている場合に失敗します。この種類のハンドルを使用して書き込みを行うには、WriteFile 関数を使用してください。
WriteFileEx 関数は、未処理の非同期 I/O 要求が多すぎる場合に失敗することがあります。そのような失敗が発生した場合、GetLastError は ERROR_INVALID_USER_BUFFER または ERROR_NOT_ENOUGH_MEMORY を返すことがあります。
保留中のすべての非同期 I/O 操作をキャンセルするには、次のいずれかを使用します。
- CancelIo: この関数は、指定したファイルハンドルに対して呼び出し元スレッドが発行した操作のみをキャンセルします。
- CancelIoEx: この関数は、指定したファイルハンドルに対して各スレッドが発行したすべての操作をキャンセルします。
保留中の同期 I/O 操作をキャンセルするには、CancelSynchronousIo を使用します。
キャンセルされた I/O 操作は、エラー ERROR_OPERATION_ABORTED で完了します。
hFile で指定したファイルの一部が別のプロセスによってロックされており、指定した書き込み操作がそのロックされた部分と重なる場合、WriteFileEx は失敗します。
ファイルへの書き込みでは、書き込みに使用したすべてのハンドルが閉じられるまで、最終書き込み時刻は完全には更新されません。したがって、正確な最終書き込み時刻を保証するには、ファイルへの書き込み後すぐにファイルハンドルを閉じてください。
書き込み操作がバッファーを使用している間に出力バッファーにアクセスすると、そのバッファーから書き込まれるデータが破損する可能性があります。アプリケーションは、書き込み操作が完了するまで、その書き込み操作が使用している出力バッファーへの書き込み、再割り当て、または解放を行ってはなりません。
リモートファイルの場合、タイムスタンプが正しく更新されないことがある点に注意してください。一貫した結果を得るには、バッファリングなしの I/O を使用してください。
システムは書き込みバイト数 0 を null 書き込み操作の指定として解釈し、WriteFile はファイルの切り詰めや拡張を行いません。ファイルを切り詰めたり拡張したりするには、SetEndOfFile 関数を使用します。
アプリケーションは、WaitForSingleObjectEx、WaitForMultipleObjectsEx、MsgWaitForMultipleObjectsEx、SignalObjectAndWait、および SleepEx 関数を使用してアラータブルな待機状態に入ります。アラータブルな待機状態とオーバーラップ I/O 操作の詳細については、同期についてを参照してください。
マウントされたファイルシステムを持つボリュームに直接書き込む場合は、まずそのボリュームへの排他アクセスを取得する必要があります。そうしないと、アプリケーションの書き込みがファイルシステム側からの他の変更と競合し、ボリュームの内容が不整合な状態になるおそれがあるため、データ破損やシステムの不安定化を引き起こす危険があります。これらの問題を防ぐため、Windows Vista 以降では次の変更が加えられています。
- ボリュームハンドルへの書き込みは、そのボリュームにマウントされたファイルシステムがない場合、または次のいずれかの条件が真である場合に成功します。
- 書き込み先のセクターがブートセクターである。
- 書き込み先のセクターがファイルシステム空間の外側にある。
- FSCTL_LOCK_VOLUME または FSCTL_DISMOUNT_VOLUME を使用して、ボリュームを明示的にロックまたはマウント解除している。
- ボリュームに実際のファイルシステムがない。(言い換えると、RAW ファイルシステムがマウントされている。)
- ディスクハンドルへの書き込みは、次のいずれかの条件が真である場合に成功します。
- 書き込み先のセクターがどのボリュームのエクステントにも含まれない。
- 書き込み先のセクターはマウントされたボリューム内に含まれるが、FSCTL_LOCK_VOLUME または FSCTL_DISMOUNT_VOLUME を使用してそのボリュームを明示的にロックまたはマウント解除している。
- 書き込み先のセクターが、RAW 以外にマウントされたファイルシステムを持たないボリューム内に含まれる。
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 公式リファレンス: 英語 (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 方式にも切替可。#uselib "KERNEL32.dll" #cfunc global WriteFileEx "WriteFileEx" sptr, sptr, int, sptr, sptr ; res = WriteFileEx(hFile, varptr(lpBuffer), nNumberOfBytesToWrite, varptr(lpOverlapped), lpCompletionRoutine) ; hFile : HANDLE -> "sptr" ; lpBuffer : BYTE* optional -> "sptr" ; nNumberOfBytesToWrite : DWORD -> "int" ; lpOverlapped : OVERLAPPED* in/out -> "sptr" ; lpCompletionRoutine : LPOVERLAPPED_COMPLETION_ROUTINE -> "sptr" ; ※出力/バッファ引数はポインタ方式(token=sptr / 呼び出しは 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 方式にも切替可。; BOOL WriteFileEx(HANDLE hFile, BYTE* lpBuffer, DWORD nNumberOfBytesToWrite, OVERLAPPED* lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) #uselib "KERNEL32.dll" #cfunc global WriteFileEx "WriteFileEx" intptr, intptr, int, intptr, intptr ; res = WriteFileEx(hFile, varptr(lpBuffer), nNumberOfBytesToWrite, varptr(lpOverlapped), lpCompletionRoutine) ; hFile : HANDLE -> "intptr" ; lpBuffer : BYTE* optional -> "intptr" ; nNumberOfBytesToWrite : DWORD -> "int" ; lpOverlapped : OVERLAPPED* in/out -> "intptr" ; lpCompletionRoutine : LPOVERLAPPED_COMPLETION_ROUTINE -> "intptr" ; ※出力/バッファ引数はポインタ方式(token=intptr / 呼び出しは 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 // BOOLfunction 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 を使用してください。関連項目
- f WriteFile — ファイルやデバイスにデータを書き込む。