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

FindFirstFileExA

関数
詳細オプション付きで最初の一致ファイルを検索する(ANSI版)。
DLLKERNEL32.dll文字セットANSI (-A)呼出規約winapiSetLastErrorあり対応OSWindows XP 以降

シグネチャ

// KERNEL32.dll  (ANSI / -A)
#include <windows.h>

HANDLE FindFirstFileExA(
    LPCSTR lpFileName,
    FINDEX_INFO_LEVELS fInfoLevelId,
    void* lpFindFileData,
    FINDEX_SEARCH_OPS fSearchOp,
    void* lpSearchFilter,   // optional
    FIND_FIRST_EX_FLAGS dwAdditionalFlags
);

パラメーター

名前方向説明
lpFileNameLPCSTRin

ディレクトリまたはパス、およびファイル名。ファイル名にはワイルドカード文字 (例: アスタリスク (*) や疑問符 (?)) を含めることができます。

このパラメーターを NULL、無効な文字列 (例: 空文字列 や終端の null 文字が欠落した文字列)、または末尾が円記号 (\) で終わる文字列にしないでください。

文字列がワイルドカード、ピリオド、またはディレクトリ名で終わる場合、ユーザーはルートおよびパス上の すべてのサブディレクトリへのアクセス権を持っている必要があります。

既定では、名前は MAX_PATH 文字に制限されます。この制限を 32,767 ワイド文字に拡張するには、パスの先頭に "\\?\" を付加します。詳細については、ファイル、パス、名前空間の名前付けを参照してください。

ヒント

Windows 10 バージョン 1607 以降では、"\\?\" を付加せずに MAX_PATH の制限を解除するようオプトインできます。詳細については、ファイル、パス、名前空間の名前付け の「最大パス長の制限」セクションを参照してください。

fInfoLevelIdFINDEX_INFO_LEVELSin

返されるデータの情報レベル。

このパラメーターは FINDEX_INFO_LEVELS 列挙体の値のいずれかです。

lpFindFileDatavoid*out

ファイルデータを受け取るバッファーへのポインター。

ポインターの型は、fInfoLevelId パラメーターで指定された情報レベルによって決まります。

fSearchOpFINDEX_SEARCH_OPSin

ワイルドカード一致とは異なる、実行するフィルター処理の種類。

このパラメーターは FINDEX_SEARCH_OPS 列挙体の値のいずれかです。

lpSearchFiltervoid*optional

指定された fSearchOp が構造化された検索情報を必要とする場合の、検索条件への ポインター。

現時点では、サポートされている fSearchOp 値のいずれも拡張検索情報を必要としません。 したがって、このポインターは NULL でなければなりません。

dwAdditionalFlagsFIND_FIRST_EX_FLAGSin

検索を制御する追加のフラグを指定します。

意味
FIND_FIRST_EX_CASE_SENSITIVE
1
検索で大文字と小文字を区別します。
FIND_FIRST_EX_LARGE_FETCH
2
ディレクトリクエリにより大きなバッファーを使用します。これにより検索操作のパフォーマンスが向上する場合があります。

Windows Server 2008、Windows Vista、Windows Server 2003、Windows XP: この値は Windows Server 2008 R2 および Windows 7 までサポートされません。

FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY
4
結果を物理的にディスク上に存在するファイルに限定します。このフラグは、ファイル仮想化フィルターが存在する場合にのみ意味を持ちます。

戻り値の型: HANDLE

公式ドキュメント

指定された名前と属性に一致するファイルまたはサブディレクトリをディレクトリ内で検索します。(FindFirstFileExA)

戻り値

関数が成功した場合、戻り値は FindNextFile または FindClose への後続の呼び出しで使用される検索ハンドルであり、 lpFindFileData パラメーターには最初に見つかったファイルまたはディレクトリに関する情報が格納されます。

関数が失敗した場合、または lpFileName パラメーターの検索文字列に一致するファイルが見つからなかった場合、 戻り値は INVALID_HANDLE_VALUE となり、lpFindFileData の内容は 不定です。拡張エラー情報を取得するには、 GetLastError 関数を呼び出します。

解説(Remarks)

FindFirstFileEx 関数は検索ハンドルを開き、 指定されたパターンに一致する名前を持つ、ファイルシステムが最初に見つけたファイルに関する情報を返します。これは、同じファイル名文字列パターンを指定したときに ディレクトリ一覧アプリケーション (dir コマンドなど) で最初に表示されるファイルまたはディレクトリと一致する場合もあれば、一致しない場合もあります。これは FindFirstFileEx が検索結果の並べ替えを一切行わないためです。 詳細については、FindNextFile を参照してください。

以下のリストは、その他の検索特性の一部を示しています。

注意 まれなケースや高負荷のシステムでは、この関数を呼び出した時点で NTFS ファイルシステム上のファイル属性情報が 最新でない場合があります。最新の NTFS ファイルシステムのファイル属性を確実に取得するには、 GetFileInformationByHandle 関数を呼び出してください。
基になるファイルシステムが、ディレクトリフィルター処理以外の指定された種類のフィルター処理をサポートしていない場合、 FindFirstFileEx はエラー ERROR_NOT_SUPPORTED で失敗します。アプリケーションは FINDEX_SEARCH_OPS 型の FileExSearchNameMatch を使用し、独自のフィルター処理を実行する必要があります。

検索ハンドルが確立されたら、それを FindNextFile 関数で使用して、同じフィルター処理を実行しながら同じパターンに一致する他の ファイルを検索します。検索ハンドルが不要になったら、 FindClose 関数を使用して閉じる必要があります。

前述のとおり、FindFirstFileExlpFileName 入力文字列で末尾の円記号 (\) を使用することはできません。 そのため、ルートディレクトリを検索する方法は明確でないかもしれません。ルートディレクトリのファイルを表示したり属性を取得したりする場合は、 次の選択肢が適用されます。

注意 文字列 "\\?\" を先頭に付加しても、ルートディレクトリへのアクセスは許可されません。

ネットワーク共有では、次の形式の lpFileName を使用できます: "\\server\service\*"。ただし、共有自体を指す lpFileName は使用できません。 たとえば、"\\server\service" は無効です。

ルートディレクトリではないディレクトリを調べるには、末尾の円記号を付けずにそのディレクトリへのパスを使用します。 たとえば、"C:\Windows" という引数は、"C:\Windows" 内のディレクトリやファイルではなく、ディレクトリ "C:\Windows" 自体に関する情報を返します。 "C:\Windows" 内のファイルおよびディレクトリを調べるには、lpFileName として "C:\Windows\*" を使用します。

次の呼び出し:

FindFirstFileEx( lpFileName, 
                 FindExInfoStandard, 
                 lpFindData, 
                 FindExSearchNameMatch, 
                 NULL, 
                 0 );

は、次の呼び出しと同等です:

FindFirstFile( lpFileName, lpFindData );

結果を照会してからその情報に基づいて操作するまでの間に、他のスレッドまたはプロセスがこの名前のファイルを作成または削除する可能性があることに注意してください。 これがアプリケーションにとって潜在的な懸念となる場合、考えられる解決策の 1 つは、CreateFile 関数を CREATE_NEW (ファイルが存在する場合に失敗) または OPEN_EXISTING (ファイルが存在しない場合に失敗) とともに使用することです。

ディレクトリ内のすべてのファイルを一覧表示する 32 ビットアプリケーションを作成しており、そのアプリケーションが 64 ビットコンピューターで実行される可能性がある場合は、FindFirstFileEx を呼び出す前に Wow64DisableWow64FsRedirection を呼び出し、 FindNextFile への最後の呼び出しの後に Wow64RevertWow64FsRedirection を呼び出す必要があります。詳細については、 File System Redirector を参照してください。

パスがシンボリックリンクを指している場合、 WIN32_FIND_DATA バッファーには、ターゲットではなくシンボリックリンク自体に関する 情報が格納されます。

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

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

次のコードは FindFirstFileEx の最小限の使用例を示しています。このプログラムは、 FindFirstFile トピックの例と同等です。

#include <windows.h>
#include <tchar.h>
#include <stdio.h>

void _tmain(int argc, TCHAR *argv[])
{
   WIN32_FIND_DATA FindFileData;
   HANDLE hFind;

   if( argc != 2 )
   {
      _tprintf(TEXT("Usage: %s [target_file]\n"), argv[0]);
      return;
   }

   _tprintf (TEXT("Target file is %s\n"), argv[1]);
   hFind = FindFirstFileEx(argv[1], FindExInfoStandard, &FindFileData,
             FindExSearchNameMatch, NULL, 0);
   if (hFind == INVALID_HANDLE_VALUE) 
   {
      printf ("FindFirstFileEx failed (%d)\n", GetLastError());
      return;
   } 
   else 
   {
      _tprintf (TEXT("The first file found is %s\n"), 
                FindFileData.cFileName);
      FindClose(hFind);
   }
}
メモ

fileapi.h ヘッダーは、UNICODE プリプロセッサ定数の定義に基づいて、この関数の ANSI 版または Unicode 版を自動的に選択するエイリアスとして FindFirstFileEx を定義します。エンコーディング中立のエイリアスの使用を、エンコーディング中立でないコードと混在させると、コンパイルエラーまたは実行時エラーを引き起こす不一致につながる可能性があります。詳細については、関数プロトタイプの規則を参照してください。

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

各言語での呼び出し定義

// KERNEL32.dll  (ANSI / -A)
#include <windows.h>

HANDLE FindFirstFileExA(
    LPCSTR lpFileName,
    FINDEX_INFO_LEVELS fInfoLevelId,
    void* lpFindFileData,
    FINDEX_SEARCH_OPS fSearchOp,
    void* lpSearchFilter,   // optional
    FIND_FIRST_EX_FLAGS dwAdditionalFlags
);
[DllImport("KERNEL32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
static extern IntPtr FindFirstFileExA(
    [MarshalAs(UnmanagedType.LPStr)] string lpFileName,   // LPCSTR
    int fInfoLevelId,   // FINDEX_INFO_LEVELS
    IntPtr lpFindFileData,   // void* out
    int fSearchOp,   // FINDEX_SEARCH_OPS
    IntPtr lpSearchFilter,   // void* optional
    uint dwAdditionalFlags   // FIND_FIRST_EX_FLAGS
);
<DllImport("KERNEL32.dll", CharSet:=CharSet.Ansi, SetLastError:=True, ExactSpelling:=True)>
Public Shared Function FindFirstFileExA(
    <MarshalAs(UnmanagedType.LPStr)> lpFileName As String,   ' LPCSTR
    fInfoLevelId As Integer,   ' FINDEX_INFO_LEVELS
    lpFindFileData As IntPtr,   ' void* out
    fSearchOp As Integer,   ' FINDEX_SEARCH_OPS
    lpSearchFilter As IntPtr,   ' void* optional
    dwAdditionalFlags As UInteger   ' FIND_FIRST_EX_FLAGS
) As IntPtr
End Function
' lpFileName : LPCSTR
' fInfoLevelId : FINDEX_INFO_LEVELS
' lpFindFileData : void* out
' fSearchOp : FINDEX_SEARCH_OPS
' lpSearchFilter : void* optional
' dwAdditionalFlags : FIND_FIRST_EX_FLAGS
Declare PtrSafe Function FindFirstFileExA Lib "kernel32" ( _
    ByVal lpFileName As String, _
    ByVal fInfoLevelId As Long, _
    ByVal lpFindFileData As LongPtr, _
    ByVal fSearchOp As Long, _
    ByVal lpSearchFilter As LongPtr, _
    ByVal dwAdditionalFlags As Long) As LongPtr
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。
import ctypes
from ctypes import wintypes

FindFirstFileExA = ctypes.windll.kernel32.FindFirstFileExA
FindFirstFileExA.restype = ctypes.c_void_p
FindFirstFileExA.argtypes = [
    wintypes.LPCSTR,  # lpFileName : LPCSTR
    ctypes.c_int,  # fInfoLevelId : FINDEX_INFO_LEVELS
    ctypes.POINTER(None),  # lpFindFileData : void* out
    ctypes.c_int,  # fSearchOp : FINDEX_SEARCH_OPS
    ctypes.POINTER(None),  # lpSearchFilter : void* optional
    wintypes.DWORD,  # dwAdditionalFlags : FIND_FIRST_EX_FLAGS
]
# GetLastError: use ctypes.GetLastError() (or ctypes.WinDLL(use_last_error=True))
require 'fiddle'
require 'fiddle/import'

lib = Fiddle.dlopen('KERNEL32.dll')
FindFirstFileExA = Fiddle::Function.new(
  lib['FindFirstFileExA'],
  [
    Fiddle::TYPE_VOIDP,  # lpFileName : LPCSTR
    Fiddle::TYPE_INT,  # fInfoLevelId : FINDEX_INFO_LEVELS
    Fiddle::TYPE_VOIDP,  # lpFindFileData : void* out
    Fiddle::TYPE_INT,  # fSearchOp : FINDEX_SEARCH_OPS
    Fiddle::TYPE_VOIDP,  # lpSearchFilter : void* optional
    -Fiddle::TYPE_INT,  # dwAdditionalFlags : FIND_FIRST_EX_FLAGS
  ],
  Fiddle::TYPE_VOIDP)
#[link(name = "kernel32")]
extern "system" {
    fn FindFirstFileExA(
        lpFileName: *const u8,  // LPCSTR
        fInfoLevelId: i32,  // FINDEX_INFO_LEVELS
        lpFindFileData: *mut (),  // void* out
        fSearchOp: i32,  // FINDEX_SEARCH_OPS
        lpSearchFilter: *mut (),  // void* optional
        dwAdditionalFlags: u32  // FIND_FIRST_EX_FLAGS
    ) -> *mut core::ffi::c_void;
}
// crates: windows-sys provides ready-made bindings for this API.
$sig = @"
[DllImport("KERNEL32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern IntPtr FindFirstFileExA([MarshalAs(UnmanagedType.LPStr)] string lpFileName, int fInfoLevelId, IntPtr lpFindFileData, int fSearchOp, IntPtr lpSearchFilter, uint dwAdditionalFlags);
"@
$api = Add-Type -MemberDefinition $sig -Name 'KERNEL32_FindFirstFileExA' -Namespace Win32 -PassThru
# $api::FindFirstFileExA(lpFileName, fInfoLevelId, lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags)
#uselib "KERNEL32.dll"
#func global FindFirstFileExA "FindFirstFileExA" sptr, sptr, sptr, sptr, sptr, sptr
; FindFirstFileExA lpFileName, fInfoLevelId, lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags   ; 戻り値は stat
; lpFileName : LPCSTR -> "sptr"
; fInfoLevelId : FINDEX_INFO_LEVELS -> "sptr"
; lpFindFileData : void* out -> "sptr"
; fSearchOp : FINDEX_SEARCH_OPS -> "sptr"
; lpSearchFilter : void* optional -> "sptr"
; dwAdditionalFlags : FIND_FIRST_EX_FLAGS -> "sptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。
#uselib "KERNEL32.dll"
#cfunc global FindFirstFileExA "FindFirstFileExA" str, int, sptr, int, sptr, int
; res = FindFirstFileExA(lpFileName, fInfoLevelId, lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags)
; lpFileName : LPCSTR -> "str"
; fInfoLevelId : FINDEX_INFO_LEVELS -> "int"
; lpFindFileData : void* out -> "sptr"
; fSearchOp : FINDEX_SEARCH_OPS -> "int"
; lpSearchFilter : void* optional -> "sptr"
; dwAdditionalFlags : FIND_FIRST_EX_FLAGS -> "int"
; HANDLE FindFirstFileExA(LPCSTR lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, void* lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, void* lpSearchFilter, FIND_FIRST_EX_FLAGS dwAdditionalFlags)
#uselib "KERNEL32.dll"
#cfunc global FindFirstFileExA "FindFirstFileExA" str, int, intptr, int, intptr, int
; res = FindFirstFileExA(lpFileName, fInfoLevelId, lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags)
; lpFileName : LPCSTR -> "str"
; fInfoLevelId : FINDEX_INFO_LEVELS -> "int"
; lpFindFileData : void* out -> "intptr"
; fSearchOp : FINDEX_SEARCH_OPS -> "int"
; lpSearchFilter : void* optional -> "intptr"
; dwAdditionalFlags : FIND_FIRST_EX_FLAGS -> "int"
import (
	"golang.org/x/sys/windows"
	"unsafe"
)

var (
	kernel32 = windows.NewLazySystemDLL("KERNEL32.dll")
	procFindFirstFileExA = kernel32.NewProc("FindFirstFileExA")
)

// lpFileName (LPCSTR), fInfoLevelId (FINDEX_INFO_LEVELS), lpFindFileData (void* out), fSearchOp (FINDEX_SEARCH_OPS), lpSearchFilter (void* optional), dwAdditionalFlags (FIND_FIRST_EX_FLAGS)
r1, _, err := procFindFirstFileExA.Call(
	uintptr(unsafe.Pointer(windows.BytePtrFromString(lpFileName))),
	uintptr(fInfoLevelId),
	uintptr(lpFindFileData),
	uintptr(fSearchOp),
	uintptr(lpSearchFilter),
	uintptr(dwAdditionalFlags),
)
_ = err  // syscall.Errno (valid when the call sets last-error)
_ = r1   // HANDLE
function FindFirstFileExA(
  lpFileName: PAnsiChar;   // LPCSTR
  fInfoLevelId: Integer;   // FINDEX_INFO_LEVELS
  lpFindFileData: Pointer;   // void* out
  fSearchOp: Integer;   // FINDEX_SEARCH_OPS
  lpSearchFilter: Pointer;   // void* optional
  dwAdditionalFlags: DWORD   // FIND_FIRST_EX_FLAGS
): THandle; stdcall;
  external 'KERNEL32.dll' name 'FindFirstFileExA';
result := DllCall("KERNEL32\FindFirstFileExA"
    , "AStr", lpFileName   ; LPCSTR
    , "Int", fInfoLevelId   ; FINDEX_INFO_LEVELS
    , "Ptr", lpFindFileData   ; void* out
    , "Int", fSearchOp   ; FINDEX_SEARCH_OPS
    , "Ptr", lpSearchFilter   ; void* optional
    , "UInt", dwAdditionalFlags   ; FIND_FIRST_EX_FLAGS
    , "Ptr")   ; return: HANDLE
●FindFirstFileExA(lpFileName, fInfoLevelId, lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags) = DLL("KERNEL32.dll", "void* FindFirstFileExA(char*, int, void*, int, void*, dword)")
# 呼び出し: FindFirstFileExA(lpFileName, fInfoLevelId, lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags)
# lpFileName : LPCSTR -> "char*"
# fInfoLevelId : FINDEX_INFO_LEVELS -> "int"
# lpFindFileData : void* out -> "void*"
# fSearchOp : FINDEX_SEARCH_OPS -> "int"
# lpSearchFilter : void* optional -> "void*"
# dwAdditionalFlags : FIND_FIRST_EX_FLAGS -> "dword"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。
const std = @import("std");

extern "kernel32" fn FindFirstFileExA(
    lpFileName: [*c]const u8, // LPCSTR
    fInfoLevelId: i32, // FINDEX_INFO_LEVELS
    lpFindFileData: ?*anyopaque, // void* out
    fSearchOp: i32, // FINDEX_SEARCH_OPS
    lpSearchFilter: ?*anyopaque, // void* optional
    dwAdditionalFlags: u32 // FIND_FIRST_EX_FLAGS
) callconv(std.os.windows.WINAPI) ?*anyopaque;
proc FindFirstFileExA(
    lpFileName: cstring,  # LPCSTR
    fInfoLevelId: int32,  # FINDEX_INFO_LEVELS
    lpFindFileData: pointer,  # void* out
    fSearchOp: int32,  # FINDEX_SEARCH_OPS
    lpSearchFilter: pointer,  # void* optional
    dwAdditionalFlags: uint32  # FIND_FIRST_EX_FLAGS
): pointer {.importc: "FindFirstFileExA", stdcall, dynlib: "KERNEL32.dll".}
pragma(lib, "kernel32");
extern(Windows)
void* FindFirstFileExA(
    const(char)* lpFileName,   // LPCSTR
    int fInfoLevelId,   // FINDEX_INFO_LEVELS
    void* lpFindFileData,   // void* out
    int fSearchOp,   // FINDEX_SEARCH_OPS
    void* lpSearchFilter,   // void* optional
    uint dwAdditionalFlags   // FIND_FIRST_EX_FLAGS
);
ccall((:FindFirstFileExA, "KERNEL32.dll"), stdcall, Ptr{Cvoid},
      (Cstring, Int32, Ptr{Cvoid}, Int32, Ptr{Cvoid}, UInt32),
      lpFileName, fInfoLevelId, lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags)
# lpFileName : LPCSTR -> Cstring
# fInfoLevelId : FINDEX_INFO_LEVELS -> Int32
# lpFindFileData : void* out -> Ptr{Cvoid}
# fSearchOp : FINDEX_SEARCH_OPS -> Int32
# lpSearchFilter : void* optional -> Ptr{Cvoid}
# dwAdditionalFlags : FIND_FIRST_EX_FLAGS -> UInt32
# stdcall は 32bit のみ意味を持つ(x64 では無視)。
local ffi = require("ffi")
ffi.cdef[[
void* FindFirstFileExA(
    const char* lpFileName,
    int32_t fInfoLevelId,
    void* lpFindFileData,
    int32_t fSearchOp,
    void* lpSearchFilter,
    uint32_t dwAdditionalFlags);
]]
local kernel32 = ffi.load("kernel32")
-- kernel32.FindFirstFileExA(lpFileName, fInfoLevelId, lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags)
-- lpFileName : LPCSTR
-- fInfoLevelId : FINDEX_INFO_LEVELS
-- lpFindFileData : void* out
-- fSearchOp : FINDEX_SEARCH_OPS
-- lpSearchFilter : void* optional
-- dwAdditionalFlags : FIND_FIRST_EX_FLAGS
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
const koffi = require('koffi');
const lib = koffi.load('KERNEL32.dll');
const FindFirstFileExA = lib.func('__stdcall', 'FindFirstFileExA', 'void *', ['str', 'int32_t', 'void *', 'int32_t', 'void *', 'uint32_t']);
// FindFirstFileExA(lpFileName, fInfoLevelId, lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags)
// lpFileName : LPCSTR -> 'str'
// fInfoLevelId : FINDEX_INFO_LEVELS -> 'int32_t'
// lpFindFileData : void* out -> 'void *'
// fSearchOp : FINDEX_SEARCH_OPS -> 'int32_t'
// lpSearchFilter : void* optional -> 'void *'
// dwAdditionalFlags : FIND_FIRST_EX_FLAGS -> 'uint32_t'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。
const lib = Deno.dlopen("KERNEL32.dll", {
  FindFirstFileExA: { parameters: ["buffer", "i32", "pointer", "i32", "pointer", "u32"], result: "pointer" },
});
// lib.symbols.FindFirstFileExA(lpFileName, fInfoLevelId, lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags)
// lpFileName : LPCSTR -> "buffer"
// fInfoLevelId : FINDEX_INFO_LEVELS -> "i32"
// lpFindFileData : void* out -> "pointer"
// fSearchOp : FINDEX_SEARCH_OPS -> "i32"
// lpSearchFilter : void* optional -> "pointer"
// dwAdditionalFlags : FIND_FIRST_EX_FLAGS -> "u32"
// 文字列は "buffer"。ANSI(-A) は new TextEncoder() で UTF-8/ANSI バイト列(末尾に \x00)を渡す。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。
<?php
$ffi = FFI::cdef(<<<C
void* FindFirstFileExA(
    const char* lpFileName,
    int32_t fInfoLevelId,
    void* lpFindFileData,
    int32_t fSearchOp,
    void* lpSearchFilter,
    uint32_t dwAdditionalFlags);
C, "KERNEL32.dll");
// $ffi->FindFirstFileExA(lpFileName, fInfoLevelId, lpFindFileData, fSearchOp, lpSearchFilter, dwAdditionalFlags);
// lpFileName : LPCSTR
// fInfoLevelId : FINDEX_INFO_LEVELS
// lpFindFileData : void* out
// fSearchOp : FINDEX_SEARCH_OPS
// lpSearchFilter : void* optional
// dwAdditionalFlags : FIND_FIRST_EX_FLAGS
// 構造体/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, W32APIOptions.ASCII_OPTIONS);
    Pointer FindFirstFileExA(
        String lpFileName,   // LPCSTR
        int fInfoLevelId,   // FINDEX_INFO_LEVELS
        Pointer lpFindFileData,   // void* out
        int fSearchOp,   // FINDEX_SEARCH_OPS
        Pointer lpSearchFilter,   // void* optional
        int dwAdditionalFlags   // FIND_FIRST_EX_FLAGS
    );
}
@[Link("kernel32")]
lib LibKERNEL32
  fun FindFirstFileExA = FindFirstFileExA(
    lpFileName : UInt8*,   # LPCSTR
    fInfoLevelId : Int32,   # FINDEX_INFO_LEVELS
    lpFindFileData : Void*,   # void* out
    fSearchOp : Int32,   # FINDEX_SEARCH_OPS
    lpSearchFilter : Void*,   # void* optional
    dwAdditionalFlags : UInt32   # FIND_FIRST_EX_FLAGS
  ) : Void*
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。
import 'dart:ffi';
import 'package:ffi/ffi.dart';

typedef FindFirstFileExANative = Pointer<Void> Function(Pointer<Utf8>, Int32, Pointer<Void>, Int32, Pointer<Void>, Uint32);
typedef FindFirstFileExADart = Pointer<Void> Function(Pointer<Utf8>, int, Pointer<Void>, int, Pointer<Void>, int);
final FindFirstFileExA = DynamicLibrary.open('KERNEL32.dll')
    .lookupFunction<FindFirstFileExANative, FindFirstFileExADart>('FindFirstFileExA');
// lpFileName : LPCSTR -> Pointer<Utf8>
// fInfoLevelId : FINDEX_INFO_LEVELS -> Int32
// lpFindFileData : void* out -> Pointer<Void>
// fSearchOp : FINDEX_SEARCH_OPS -> Int32
// lpSearchFilter : void* optional -> Pointer<Void>
// dwAdditionalFlags : FIND_FIRST_EX_FLAGS -> Uint32
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。
{$mode objfpc}{$H+}
function FindFirstFileExA(
  lpFileName: PAnsiChar;   // LPCSTR
  fInfoLevelId: Integer;   // FINDEX_INFO_LEVELS
  lpFindFileData: Pointer;   // void* out
  fSearchOp: Integer;   // FINDEX_SEARCH_OPS
  lpSearchFilter: Pointer;   // void* optional
  dwAdditionalFlags: DWORD   // FIND_FIRST_EX_FLAGS
): THandle; stdcall;
  external 'KERNEL32.dll' name 'FindFirstFileExA';
import Foreign
import Foreign.C.Types
import Foreign.C.String

foreign import stdcall safe "FindFirstFileExA"
  c_FindFirstFileExA :: CString -> Int32 -> Ptr () -> Int32 -> Ptr () -> Word32 -> IO (Ptr ())
-- lpFileName : LPCSTR -> CString
-- fInfoLevelId : FINDEX_INFO_LEVELS -> Int32
-- lpFindFileData : void* out -> Ptr ()
-- fSearchOp : FINDEX_SEARCH_OPS -> Int32
-- lpSearchFilter : void* optional -> Ptr ()
-- dwAdditionalFlags : FIND_FIRST_EX_FLAGS -> Word32
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。
open Ctypes
open Foreign

let findfirstfileexa =
  foreign "FindFirstFileExA"
    (string @-> int32_t @-> (ptr void) @-> int32_t @-> (ptr void) @-> uint32_t @-> returning (ptr void))
(* lpFileName : LPCSTR -> string *)
(* fInfoLevelId : FINDEX_INFO_LEVELS -> int32_t *)
(* lpFindFileData : void* out -> (ptr void) *)
(* fSearchOp : FINDEX_SEARCH_OPS -> int32_t *)
(* lpSearchFilter : void* optional -> (ptr void) *)
(* dwAdditionalFlags : FIND_FIRST_EX_FLAGS -> uint32_t *)
(* foreign は cdecl 前提。x64 Windows では WINAPI と一致。構造体は ctypes structure を定義のこと。 *)
(cffi:define-foreign-library kernel32 (t "KERNEL32.dll"))
(cffi:use-foreign-library kernel32)

(cffi:defcfun ("FindFirstFileExA" find-first-file-ex-a :convention :stdcall) :pointer
  (lp-file-name :string)   ; LPCSTR
  (f-info-level-id :int32)   ; FINDEX_INFO_LEVELS
  (lp-find-file-data :pointer)   ; void* out
  (f-search-op :int32)   ; FINDEX_SEARCH_OPS
  (lp-search-filter :pointer)   ; void* optional
  (dw-additional-flags :uint32))   ; FIND_FIRST_EX_FLAGS
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $FindFirstFileExA = Win32::API::More->new('KERNEL32',
    'HANDLE FindFirstFileExA(LPCSTR lpFileName, int fInfoLevelId, LPVOID lpFindFileData, int fSearchOp, LPVOID lpSearchFilter, DWORD dwAdditionalFlags)');
# my $ret = $FindFirstFileExA->Call($lpFileName, $fInfoLevelId, $lpFindFileData, $fSearchOp, $lpSearchFilter, $dwAdditionalFlags);
# lpFileName : LPCSTR -> LPCSTR
# fInfoLevelId : FINDEX_INFO_LEVELS -> int
# lpFindFileData : void* out -> LPVOID
# fSearchOp : FINDEX_SEARCH_OPS -> int
# lpSearchFilter : void* optional -> LPVOID
# dwAdditionalFlags : FIND_FIRST_EX_FLAGS -> DWORD
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。

関連項目

文字セット違い
類似 API
公式の関連項目
使用する型