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

WriteFile

関数
ファイルやデバイスにデータを書き込む。
DLLKERNEL32.dll呼出規約winapiSetLastErrorあり対応OSWindows XP 以降

シグネチャ

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

BOOL WriteFile(
    HANDLE hFile,
    const BYTE* lpBuffer,   // optional
    DWORD nNumberOfBytesToWrite,
    DWORD* lpNumberOfBytesWritten,   // optional
    OVERLAPPED* lpOverlapped   // optional
);

パラメーター

名前方向説明
hFileHANDLEin

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

hFile パラメーターは書き込みアクセスを指定して作成されている必要があります。詳細については、Generic Access Rights および File Security and Access Rights を参照してください。

非同期書き込み操作の場合、hFileFILE_FLAG_OVERLAPPED フラグを使用して CreateFile 関数で開いた任意のハンドル、または socket 関数や accept 関数が返したソケットハンドルにできます。

lpBufferBYTE*inoptional

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

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

nNumberOfBytesToWriteDWORDin

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

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

Windows Server 2003 および Windows XP: ネットワーク経由のパイプ書き込み操作は、1 回の書き込みあたりのサイズが制限されます。この上限はプラットフォームによって異なります。x86 プラットフォームでは 63.97 MB、x64 プラットフォームでは 31.97 MB、Itanium では 63.95 MB です。パイプの詳細については、「解説」セクションを参照してください。

lpNumberOfBytesWrittenDWORD*outoptional

同期的な hFile パラメーターを使用する場合に、書き込まれたバイト数を受け取る変数へのポインターです。WriteFile は、何らかの処理やエラーチェックを行う前にこの値を 0 に設定します。これが非同期操作である場合は、誤った結果を避けるためこのパラメーターには NULL を使用してください。

このパラメーターは、lpOverlapped パラメーターが NULL でない場合にのみ NULL にできます。

Windows 7: このパラメーターを NULL にすることはできません。

詳細については、「解説」セクションを参照してください。

lpOverlappedOVERLAPPED*inoutoptional

hFile パラメーターが FILE_FLAG_OVERLAPPED を指定して開かれた場合は OVERLAPPED 構造体へのポインターが必須です。それ以外の場合、このパラメーターは NULL にできます。

バイトオフセットをサポートする hFile では、このパラメーターを使用する場合、ファイルまたはデバイスへの書き込みを開始するバイトオフセットを指定する必要があります。このオフセットは、OVERLAPPED 構造体の Offset メンバーと OffsetHigh メンバーを設定して指定します。バイトオフセットをサポートしない hFile では、OffsetOffsetHigh は無視されます。

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

lpOverlappedFILE_FLAG_OVERLAPPED のさまざまな組み合わせの詳細については、「解説」セクションおよび Synchronization and File Position セクションを参照してください。

戻り値の型: BOOL

公式ドキュメント

指定したファイルまたは入出力 (I/O) デバイスにデータを書き込みます。

戻り値

関数が成功した場合、戻り値は 0 以外 (TRUE) です。

関数が失敗した場合、または非同期に完了している場合、戻り値は 0 (FALSE) です。拡張エラー情報を取得するには、GetLastError 関数を呼び出してください。

メモ

GetLastError コード ERROR_IO_PENDING は失敗ではありません。これは書き込み操作が非同期での完了を保留中であることを示します。詳細については、解説を参照してください。

解説(Remarks)

WriteFile 関数は、次のいずれかの条件が発生したときに戻ります。

WriteFile 関数は、未完了の非同期 I/O 要求が多すぎる場合に ERROR_INVALID_USER_BUFFER または ERROR_NOT_ENOUGH_MEMORY で失敗することがあります。

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

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

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

WriteFile 関数は ERROR_NOT_ENOUGH_QUOTA で失敗することがあります。これは、呼び出し元プロセスのバッファーをページロックできなかったことを意味します。詳細については、SetProcessWorkingSetSize を参照してください。

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

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

書き込み操作がバッファーを使用している間に出力バッファーにアクセスすると、そのバッファーから書き込まれるデータが破損する可能性があります。アプリケーションは、書き込み操作が完了するまで、その書き込み操作が使用している出力バッファーへの書き込み、再割り当て、または解放を行ってはなりません。これは特に非同期ファイルハンドルを使用する場合に問題になりやすいです。同期ファイルハンドルと非同期ファイルハンドルに関する追加情報は、後述の Synchronization and File Position セクションおよび Synchronous and Asynchronous I/O にあります。

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

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

コンソール出力へのハンドルを使用した WriteFile によって、画面バッファーに文字を書き込むことができます。関数の正確な動作はコンソールモードによって決まります。データは現在のカーソル位置に書き込まれます。カーソル位置は書き込み操作後に更新されます。コンソールハンドルの詳細については、CreateFile を参照してください。

通信デバイスへの書き込み時、WriteFile の動作は、SetCommTimeouts 関数および GetCommTimeouts 関数を使用して設定・取得される現在の通信タイムアウトによって決まります。タイムアウト値を設定し忘れると、予測不能な結果が発生する可能性があります。通信タイムアウトの詳細については、COMMTIMEOUTS を参照してください。

単一セクターの書き込みはアトミックですが、複数セクターの書き込みは、トランザクションを使用している場合 (つまり、作成したハンドルがトランザクションハンドルである場合。たとえば CreateFileTransacted を使用して作成したハンドル) を除き、アトミックであることは保証されません。キャッシュされた複数セクター書き込みは、必ずしもすぐにディスクに書き込まれるとは限りません。そのため、複数セクター書き込み全体がキャッシュ遅延の可能性なくディスクに書き込まれるようにするには、CreateFileFILE_FLAG_WRITE_THROUGH を指定してください。

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

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

hFileFILE_FLAG_OVERLAPPED を指定して開かれた場合、次の条件が有効になります。

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

テクノロジ サポート
Server Message Block (SMB) 3.0 プロトコル あり
SMB 3.0 トランスペアレントフェールオーバー (TFO) あり
SMB 3.0 スケールアウトファイル共有 (SO) あり
クラスターの共有ボリュームファイルシステム (CsvFS) あり
復元性のあるファイルシステム (ReFS) あり

Synchronization and File Position

hFileFILE_FLAG_OVERLAPPED を指定して開かれている場合は非同期ファイルハンドルであり、それ以外の場合は同期ファイルハンドルです。前述のとおり、OVERLAPPED 構造体の使用規則はそれぞれで少し異なります。

メモ

ファイルまたはデバイスが非同期 I/O 用に開かれている場合、そのハンドルを使用した WriteFile などの関数の後続呼び出しは通常ただちに戻りますが、ブロックされた実行に関しては同期的に動作することもあります。詳細については、Asynchronous disk I/O appears as synchronous on Windows を参照してください。

非同期ファイルハンドルを扱う際の考慮事項:

同期ファイルハンドルを扱う際の考慮事項:

詳細については、CreateFile および Synchronous and Asynchronous I/O を参照してください。

Pipes

匿名パイプが使用されており、読み取りハンドルが閉じられている場合、WriteFile がそのパイプの対応する書き込みハンドルを使用して書き込もうとすると、関数は FALSE を返し、GetLastErrorERROR_BROKEN_PIPE を返します。

アプリケーションが WriteFile 関数を使用してパイプに書き込むときにパイプバッファーが満杯である場合、書き込み操作はただちには完了しないことがあります。書き込み操作は、読み取り操作 (ReadFile 関数を使用) によってパイプ用のシステムバッファー領域がさらに利用可能になったときに完了します。

バッファー領域が不足しているノンブロッキングのバイトモードパイプハンドルに書き込む場合、WriteFile*lpNumberOfBytesWritten < nNumberOfBytesToWriteTRUE を返します。

パイプの詳細については、Pipes を参照してください。

Transacted Operations

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

Examples

いくつかの例については、Creating and Using a Temporary File および Opening a File for Reading or Writing を参照してください。

次の C++ の例は、バッファリングなしのファイル書き込みでセクターを整列させる方法を示しています。Size 変数は、ファイルに書き込もうとしている元のデータブロックのサイズです。バッファリングなしのファイル I/O に関する追加の規則については、File Buffering を参照してください。

#include <windows.h>

#define ROUND_UP_SIZE(Value,Pow2) ((SIZE_T) ((((ULONG)(Value)) + (Pow2) - 1) & (~(((LONG)(Pow2)) - 1))))
#define ROUND_UP_PTR(Ptr,Pow2)  ((void *) ((((ULONG_PTR)(Ptr)) + (Pow2) - 1) & (~(((LONG_PTR)(Pow2)) - 1))))

int main()
{
   // Sample data
   unsigned long bytesPerSector = 65536; // obtained from the GetFreeDiskSpace function.
   unsigned long size = 15536; // Buffer size of your data to write.
   
   // Ensure you have one more sector than Size would require.
   size_t sizeNeeded = bytesPerSector + ROUND_UP_SIZE(size, bytesPerSector);
   
   // Replace this statement with any allocation routine.
   auto buffer = new uint8_t[sizeNeeded];
   
   // Actual alignment happens here.
   auto bufferAligned = ROUND_UP_PTR(buffer, bytesPerSector);

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

各言語での呼び出し定義

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

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

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

lib = Fiddle.dlopen('KERNEL32.dll')
WriteFile = Fiddle::Function.new(
  lib['WriteFile'],
  [
    Fiddle::TYPE_VOIDP,  # hFile : HANDLE
    Fiddle::TYPE_VOIDP,  # lpBuffer : BYTE* optional
    -Fiddle::TYPE_INT,  # nNumberOfBytesToWrite : DWORD
    Fiddle::TYPE_VOIDP,  # lpNumberOfBytesWritten : DWORD* optional, out
    Fiddle::TYPE_VOIDP,  # lpOverlapped : OVERLAPPED* optional, in/out
  ],
  Fiddle::TYPE_INT)
#[link(name = "kernel32")]
extern "system" {
    fn WriteFile(
        hFile: *mut core::ffi::c_void,  // HANDLE
        lpBuffer: *const u8,  // BYTE* optional
        nNumberOfBytesToWrite: u32,  // DWORD
        lpNumberOfBytesWritten: *mut u32,  // DWORD* optional, out
        lpOverlapped: *mut OVERLAPPED  // OVERLAPPED* optional, in/out
    ) -> 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 WriteFile(IntPtr hFile, IntPtr lpBuffer, uint nNumberOfBytesToWrite, IntPtr lpNumberOfBytesWritten, IntPtr lpOverlapped);
"@
$api = Add-Type -MemberDefinition $sig -Name 'KERNEL32_WriteFile' -Namespace Win32 -PassThru
# $api::WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped)
#uselib "KERNEL32.dll"
#func global WriteFile "WriteFile" sptr, sptr, sptr, sptr, sptr
; WriteFile hFile, varptr(lpBuffer), nNumberOfBytesToWrite, varptr(lpNumberOfBytesWritten), varptr(lpOverlapped)   ; 戻り値は stat
; hFile : HANDLE -> "sptr"
; lpBuffer : BYTE* optional -> "sptr"
; nNumberOfBytesToWrite : DWORD -> "sptr"
; lpNumberOfBytesWritten : DWORD* optional, out -> "sptr"
; lpOverlapped : OVERLAPPED* optional, in/out -> "sptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。
出力引数:
#uselib "KERNEL32.dll"
#cfunc global WriteFile "WriteFile" sptr, var, int, var, var
; res = WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped)
; hFile : HANDLE -> "sptr"
; lpBuffer : BYTE* optional -> "var"
; nNumberOfBytesToWrite : DWORD -> "int"
; lpNumberOfBytesWritten : DWORD* optional, out -> "var"
; lpOverlapped : OVERLAPPED* optional, in/out -> "var"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
出力引数:
; BOOL WriteFile(HANDLE hFile, BYTE* lpBuffer, DWORD nNumberOfBytesToWrite, DWORD* lpNumberOfBytesWritten, OVERLAPPED* lpOverlapped)
#uselib "KERNEL32.dll"
#cfunc global WriteFile "WriteFile" intptr, var, int, var, var
; res = WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped)
; hFile : HANDLE -> "intptr"
; lpBuffer : BYTE* optional -> "var"
; nNumberOfBytesToWrite : DWORD -> "int"
; lpNumberOfBytesWritten : DWORD* optional, out -> "var"
; lpOverlapped : OVERLAPPED* optional, in/out -> "var"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
import (
	"golang.org/x/sys/windows"
	"unsafe"
)

var (
	kernel32 = windows.NewLazySystemDLL("KERNEL32.dll")
	procWriteFile = kernel32.NewProc("WriteFile")
)

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

extern "kernel32" fn WriteFile(
    hFile: ?*anyopaque, // HANDLE
    lpBuffer: [*c]u8, // BYTE* optional
    nNumberOfBytesToWrite: u32, // DWORD
    lpNumberOfBytesWritten: [*c]u32, // DWORD* optional, out
    lpOverlapped: [*c]OVERLAPPED // OVERLAPPED* optional, in/out
) callconv(std.os.windows.WINAPI) i32;
proc WriteFile(
    hFile: pointer,  # HANDLE
    lpBuffer: ptr uint8,  # BYTE* optional
    nNumberOfBytesToWrite: uint32,  # DWORD
    lpNumberOfBytesWritten: ptr uint32,  # DWORD* optional, out
    lpOverlapped: ptr OVERLAPPED  # OVERLAPPED* optional, in/out
): int32 {.importc: "WriteFile", stdcall, dynlib: "KERNEL32.dll".}
pragma(lib, "kernel32");
extern(Windows)
int WriteFile(
    void* hFile,   // HANDLE
    ubyte* lpBuffer,   // BYTE* optional
    uint nNumberOfBytesToWrite,   // DWORD
    uint* lpNumberOfBytesWritten,   // DWORD* optional, out
    OVERLAPPED* lpOverlapped   // OVERLAPPED* optional, in/out
);
ccall((:WriteFile, "KERNEL32.dll"), stdcall, Int32,
      (Ptr{Cvoid}, Ptr{UInt8}, UInt32, Ptr{UInt32}, Ptr{OVERLAPPED}),
      hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped)
# hFile : HANDLE -> Ptr{Cvoid}
# lpBuffer : BYTE* optional -> Ptr{UInt8}
# nNumberOfBytesToWrite : DWORD -> UInt32
# lpNumberOfBytesWritten : DWORD* optional, out -> Ptr{UInt32}
# lpOverlapped : OVERLAPPED* optional, in/out -> Ptr{OVERLAPPED}
# stdcall は 32bit のみ意味を持つ(x64 では無視)。
local ffi = require("ffi")
ffi.cdef[[
int32_t WriteFile(
    void* hFile,
    uint8_t* lpBuffer,
    uint32_t nNumberOfBytesToWrite,
    uint32_t* lpNumberOfBytesWritten,
    void* lpOverlapped);
]]
local kernel32 = ffi.load("kernel32")
-- kernel32.WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped)
-- hFile : HANDLE
-- lpBuffer : BYTE* optional
-- nNumberOfBytesToWrite : DWORD
-- lpNumberOfBytesWritten : DWORD* optional, out
-- lpOverlapped : OVERLAPPED* optional, in/out
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
const koffi = require('koffi');
const lib = koffi.load('KERNEL32.dll');
const WriteFile = lib.func('__stdcall', 'WriteFile', 'int32_t', ['void *', 'uint8_t *', 'uint32_t', 'uint32_t *', 'void *']);
// WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped)
// hFile : HANDLE -> 'void *'
// lpBuffer : BYTE* optional -> 'uint8_t *'
// nNumberOfBytesToWrite : DWORD -> 'uint32_t'
// lpNumberOfBytesWritten : DWORD* optional, out -> 'uint32_t *'
// lpOverlapped : OVERLAPPED* optional, in/out -> 'void *'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。
const lib = Deno.dlopen("KERNEL32.dll", {
  WriteFile: { parameters: ["pointer", "pointer", "u32", "pointer", "pointer"], result: "i32" },
});
// lib.symbols.WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped)
// hFile : HANDLE -> "pointer"
// lpBuffer : BYTE* optional -> "pointer"
// nNumberOfBytesToWrite : DWORD -> "u32"
// lpNumberOfBytesWritten : DWORD* optional, out -> "pointer"
// lpOverlapped : OVERLAPPED* optional, in/out -> "pointer"
// 文字列引数は "buffer"(NUL 終端のバイト列を Uint8Array で渡す)。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。
<?php
$ffi = FFI::cdef(<<<C
int32_t WriteFile(
    void* hFile,
    uint8_t* lpBuffer,
    uint32_t nNumberOfBytesToWrite,
    uint32_t* lpNumberOfBytesWritten,
    void* lpOverlapped);
C, "KERNEL32.dll");
// $ffi->WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped);
// hFile : HANDLE
// lpBuffer : BYTE* optional
// nNumberOfBytesToWrite : DWORD
// lpNumberOfBytesWritten : DWORD* optional, out
// lpOverlapped : OVERLAPPED* optional, in/out
// 構造体/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 WriteFile(
        Pointer hFile,   // HANDLE
        byte[] lpBuffer,   // BYTE* optional
        int nNumberOfBytesToWrite,   // DWORD
        IntByReference lpNumberOfBytesWritten,   // DWORD* optional, out
        Pointer lpOverlapped   // OVERLAPPED* optional, in/out
    );
}
@[Link("kernel32")]
lib LibKERNEL32
  fun WriteFile = WriteFile(
    hFile : Void*,   # HANDLE
    lpBuffer : UInt8*,   # BYTE* optional
    nNumberOfBytesToWrite : UInt32,   # DWORD
    lpNumberOfBytesWritten : UInt32*,   # DWORD* optional, out
    lpOverlapped : OVERLAPPED*   # OVERLAPPED* optional, in/out
  ) : Int32
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。
import 'dart:ffi';
import 'package:ffi/ffi.dart';

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

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

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

(cffi:defcfun ("WriteFile" write-file :convention :stdcall) :int32
  (h-file :pointer)   ; HANDLE
  (lp-buffer :pointer)   ; BYTE* optional
  (n-number-of-bytes-to-write :uint32)   ; DWORD
  (lp-number-of-bytes-written :pointer)   ; DWORD* optional, out
  (lp-overlapped :pointer))   ; OVERLAPPED* optional, in/out
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $WriteFile = Win32::API::More->new('KERNEL32',
    'BOOL WriteFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPVOID lpNumberOfBytesWritten, LPVOID lpOverlapped)');
# my $ret = $WriteFile->Call($hFile, $lpBuffer, $nNumberOfBytesToWrite, $lpNumberOfBytesWritten, $lpOverlapped);
# hFile : HANDLE -> HANDLE
# lpBuffer : BYTE* optional -> LPVOID
# nNumberOfBytesToWrite : DWORD -> DWORD
# lpNumberOfBytesWritten : DWORD* optional, out -> LPVOID
# lpOverlapped : OVERLAPPED* optional, in/out -> LPVOID
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。

関連項目

類似 API
使用する型