Win32 API 日本語リファレンス
ホームFoundation › DuplicateHandle

DuplicateHandle

関数
オブジェクトハンドルの複製を作成する。
DLLKERNEL32.dll呼出規約winapiSetLastErrorあり対応OSWindows 2000 以降

シグネチャ

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

BOOL DuplicateHandle(
    HANDLE hSourceProcessHandle,
    HANDLE hSourceHandle,
    HANDLE hTargetProcessHandle,
    HANDLE* lpTargetHandle,
    DWORD dwDesiredAccess,
    BOOL bInheritHandle,
    DUPLICATE_HANDLE_OPTIONS dwOptions
);

パラメーター

名前方向説明
hSourceProcessHandleHANDLEin

複製対象のハンドルを保持しているプロセスへのハンドルです。

このハンドルには PROCESS_DUP_HANDLE アクセス権が必要です。詳細については、 Process Security and Access Rights を参照してください。

hSourceHandleHANDLEin

複製対象のハンドルです。これは、ソースプロセスのコンテキストにおいて有効な、開いているオブジェクトハンドルです。ハンドルを複製できるオブジェクトの一覧については、後述の「解説」セクションを参照してください。

hSourceHandleGetCurrentProcess または GetCurrentThread によって返された擬似ハンドルである場合、hSourceProcessHandle には DuplicateHandle を呼び出すプロセスへのハンドルを指定する必要があります。

hTargetProcessHandleHANDLEin

複製されたハンドルを受け取るプロセスへのハンドルです。このハンドルには PROCESS_DUP_HANDLE アクセス権が必要です。

このパラメーターは省略可能であり、OptionsDUPLICATE_CLOSE_SOURCE フラグが設定されている場合は NULL を指定できます。

lpTargetHandleHANDLE*out

複製されたハンドルを受け取る変数へのポインターです。このハンドル値は、ターゲットプロセスのコンテキストにおいて有効です。

hSourceHandleGetCurrentProcess または GetCurrentThread によって返された擬似ハンドルである場合、DuplicateHandle はそれをそれぞれプロセスまたはスレッドへの実際のハンドルに変換します。

lpTargetHandleNULL の場合、関数はハンドルを複製しますが、複製されたハンドル値を呼び出し元に返しません。この動作は、本関数の以前のバージョンとの後方互換性のためにのみ存在します。ターゲットプロセスが終了するまでシステムリソースを消費し続けることになるため、この機能は使用しないでください。

このパラメーターは、hTargetProcessHandleNULL の場合は無視されます。

dwDesiredAccessDWORDin

新しいハンドルに対して要求されるアクセス権です。各オブジェクトタイプに対して指定できるフラグについては、後述の「解説」セクションを参照してください。

このパラメーターは、dwOptions パラメーターに DUPLICATE_SAME_ACCESS フラグが指定されている場合は無視されます。それ以外の場合、指定できるフラグは、ハンドルを複製するオブジェクトのタイプによって異なります。

このパラメーターは、hTargetProcessHandleNULL の場合は無視されます。

bInheritHandleBOOLin

ハンドルが継承可能かどうかを示す変数です。TRUE の場合、複製されたハンドルは、ターゲットプロセスによって作成される新しいプロセスに継承されます。FALSE の場合、新しいハンドルは継承されません。

このパラメーターは、hTargetProcessHandleNULL の場合は無視されます。

dwOptionsDUPLICATE_HANDLE_OPTIONSin

省略可能なアクションです。このパラメーターには 0、または次の値の任意の組み合わせを指定できます。

意味
DUPLICATE_CLOSE_SOURCE
0x00000001
ソースハンドルを閉じます。これは、返されるエラー状態にかかわらず実行されます。
DUPLICATE_SAME_ACCESS
0x00000002
dwDesiredAccess パラメーターを無視します。複製されたハンドルは、ソースハンドルと同じアクセス権を持ちます。

戻り値の型: BOOL

公式ドキュメント

オブジェクトのハンドルを複製します。

戻り値

関数が成功した場合、戻り値は 0 以外の値になります。

関数が失敗した場合、戻り値は 0 になります。拡張エラー情報を取得するには、 GetLastError を呼び出してください。

解説(Remarks)

複製されたハンドルは、元のハンドルと同じオブジェクトを参照します。したがって、オブジェクトに対する変更は両方のハンドルに反映されます。たとえば、ファイルハンドルを複製した場合、現在のファイル位置は常に両方のハンドルで同じになります。ファイルハンドルごとに異なるファイル位置を持たせるには、CreateFile 関数を使用して、同じファイルへのアクセスを共有するファイルハンドルを作成してください。

DuplicateHandle は、ソースプロセスまたはターゲットプロセス(あるいはソースとターゲットの両方を兼ねるプロセス)のいずれからでも呼び出すことができます。たとえば、プロセスは DuplicateHandle を使用して、継承可能なハンドルから継承不可能な複製を作成したり、元のハンドルとは異なるアクセス権を持つハンドルを作成したりできます。

ソースプロセスは、 GetCurrentProcess 関数を使用して自身へのハンドルを取得します。このハンドルは擬似ハンドルですが、DuplicateHandle はこれを実際のプロセスハンドルに変換します。ターゲットプロセスのハンドルを取得するには、何らかのプロセス間通信(たとえば名前付きパイプや共有メモリ)を使用して、プロセス識別子をソースプロセスに伝える必要がある場合があります。ソースプロセスは、この識別子を OpenProcess 関数で使用して、ターゲットプロセスへのハンドルを取得できます。

DuplicateHandle を呼び出すプロセスがターゲットプロセスでもない場合、ソースプロセスはプロセス間通信を使用して、複製されたハンドルの値をターゲットプロセスに渡す必要があります。

DuplicateHandle は、32 ビットプロセスと 64 ビットプロセスの間でハンドルを複製するために使用できます。生成されるハンドルは、ターゲットプロセスで動作するように適切なサイズになります。詳細については、Process Interoperability を参照してください。

DuplicateHandle は、次のタイプのオブジェクトに対するハンドルを複製できます。

オブジェクト 説明
アクセストークン ハンドルは、 CreateRestrictedTokenDuplicateTokenDuplicateTokenExOpenProcessToken、または OpenThreadToken 関数によって返されます。
変更通知 ハンドルは、FindFirstChangeNotification 関数によって返されます。
通信デバイス ハンドルは、 CreateFile 関数によって返されます。
コンソール入力 ハンドルは、CONIN$ を指定した場合に CreateFile 関数によって、または STD_INPUT_HANDLE を指定した場合に GetStdHandle 関数によって返されます。コンソールハンドルは、同じプロセス内で使用する場合にのみ複製できます。
コンソール画面バッファー ハンドルは、CONOUT$ を指定した場合に CreateFile 関数によって、または STD_OUTPUT_HANDLE を指定した場合に GetStdHandle 関数によって返されます。コンソールハンドルは、同じプロセス内で使用する場合にのみ複製できます。
デスクトップ ハンドルは、 GetThreadDesktop 関数によって返されます。
イベント ハンドルは、 CreateEvent または OpenEvent 関数によって返されます。
ファイル ハンドルは、 CreateFile 関数によって返されます。
ファイルマッピング ハンドルは、 CreateFileMapping 関数によって返されます。
ジョブ ハンドルは、 CreateJobObject 関数によって返されます。
メールスロット ハンドルは、 CreateMailslot 関数によって返されます。
ミューテックス ハンドルは、 CreateMutex または [OpenMutex](../synchapi/nf-synchapi-openmutexw.md) 関数によって返されます。
パイプ 名前付きパイプハンドルは、 CreateNamedPipe または CreateFile 関数によって返されます。匿名パイプハンドルは、 CreatePipe 関数によって返されます。
プロセス ハンドルは、 CreateProcessGetCurrentProcess、または OpenProcess 関数によって返されます。
レジストリキー ハンドルは、 RegCreateKeyRegCreateKeyExRegOpenKey、または RegOpenKeyEx 関数によって返されます。なお、 RegConnectRegistry 関数によって返されるレジストリキーハンドルは、 DuplicateHandle の呼び出しでは使用できません。
セマフォ ハンドルは、 CreateSemaphore または OpenSemaphore 関数によって返されます。
スレッド ハンドルは、 CreateProcessCreateThreadCreateRemoteThread、または GetCurrentThread 関数によって返されます。
タイマー ハンドルは、 CreateWaitableTimerW または OpenWaitableTimerW 関数によって返されます。
トランザクション ハンドルは、CreateTransaction 関数によって返されます。
ウィンドウステーション ハンドルは、 GetProcessWindowStation 関数によって返されます。

次のオブジェクトに対するハンドルの複製には、 DuplicateHandle を使用しないでください。

dwDesiredAccess パラメーターは、新しいハンドルのアクセス権を指定します。すべてのオブジェクトは standard access rights をサポートします。オブジェクトは、そのタイプに応じて追加のアクセス権をサポートする場合もあります。詳細については、次のトピックを参照してください。 場合によっては、新しいハンドルが元のハンドルよりも多くのアクセス権を持つことができます。ただし、別の場合には、 DuplicateHandle は元のハンドルよりも多くのアクセス権を持つハンドルを作成できません。たとえば、GENERIC_READ アクセス権で作成されたファイルハンドルを、GENERIC_READGENERIC_WRITE の両方のアクセス権を持つように複製することはできません。

通常、ターゲットプロセスは、複製されたハンドルの使用が終わった時点でそのハンドルを閉じます。ソースプロセスから複製されたハンドルを閉じるには、次のパラメーターを指定して DuplicateHandle を呼び出します。

次の例では、ミューテックスを作成し、そのミューテックスへのハンドルを複製して、別のスレッドに渡します。ハンドルを複製することで参照カウントが増加するため、両方のスレッドがハンドルを閉じるまでミューテックスオブジェクトが破棄されないことが保証されます。

#include <windows.h>

DWORD CALLBACK ThreadProc(PVOID pvParam);

int main()
{
    HANDLE hMutex = CreateMutex(NULL, FALSE, NULL);
    HANDLE hMutexDup, hThread;
    DWORD dwThreadId;

    DuplicateHandle(GetCurrentProcess(), 
                    hMutex, 
                    GetCurrentProcess(),
                    &hMutexDup, 
                    0,
                    FALSE,
                    DUPLICATE_SAME_ACCESS);

    hThread = CreateThread(NULL, 0, ThreadProc, 
        (LPVOID) hMutexDup, 0, &dwThreadId);

    // Perform work here, closing the handle when finished with the
    // mutex. If the reference count is zero, the object is destroyed.
    CloseHandle(hMutex);

    // Wait for the worker thread to terminate and clean up.
    WaitForSingleObject(hThread, INFINITE);
    CloseHandle(hThread);
    return 0;
}

DWORD CALLBACK ThreadProc(PVOID pvParam)
{
    HANDLE hMutex = (HANDLE)pvParam;

    // Perform work here, closing the handle when finished with the
    // mutex. If the reference count is zero, the object is destroyed.
    CloseHandle(hMutex);
    return 0;
}
出典・ライセンス: 上記「公式ドキュメント」の内容は Microsoft の Win32 API ドキュメント(MicrosoftDocs/sdk-api)を日本語に翻訳・改変したものです。© Microsoft Corporation. CC BY 4.0 で提供。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)

各言語での呼び出し定義

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

BOOL DuplicateHandle(
    HANDLE hSourceProcessHandle,
    HANDLE hSourceHandle,
    HANDLE hTargetProcessHandle,
    HANDLE* lpTargetHandle,
    DWORD dwDesiredAccess,
    BOOL bInheritHandle,
    DUPLICATE_HANDLE_OPTIONS dwOptions
);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("KERNEL32.dll", SetLastError = true, ExactSpelling = true)]
static extern bool DuplicateHandle(
    IntPtr hSourceProcessHandle,   // HANDLE
    IntPtr hSourceHandle,   // HANDLE
    IntPtr hTargetProcessHandle,   // HANDLE
    IntPtr lpTargetHandle,   // HANDLE* out
    uint dwDesiredAccess,   // DWORD
    bool bInheritHandle,   // BOOL
    uint dwOptions   // DUPLICATE_HANDLE_OPTIONS
);
<DllImport("KERNEL32.dll", SetLastError:=True, ExactSpelling:=True)>
Public Shared Function DuplicateHandle(
    hSourceProcessHandle As IntPtr,   ' HANDLE
    hSourceHandle As IntPtr,   ' HANDLE
    hTargetProcessHandle As IntPtr,   ' HANDLE
    lpTargetHandle As IntPtr,   ' HANDLE* out
    dwDesiredAccess As UInteger,   ' DWORD
    bInheritHandle As Boolean,   ' BOOL
    dwOptions As UInteger   ' DUPLICATE_HANDLE_OPTIONS
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
' hSourceProcessHandle : HANDLE
' hSourceHandle : HANDLE
' hTargetProcessHandle : HANDLE
' lpTargetHandle : HANDLE* out
' dwDesiredAccess : DWORD
' bInheritHandle : BOOL
' dwOptions : DUPLICATE_HANDLE_OPTIONS
Declare PtrSafe Function DuplicateHandle Lib "kernel32" ( _
    ByVal hSourceProcessHandle As LongPtr, _
    ByVal hSourceHandle As LongPtr, _
    ByVal hTargetProcessHandle As LongPtr, _
    ByVal lpTargetHandle As LongPtr, _
    ByVal dwDesiredAccess As Long, _
    ByVal bInheritHandle As Long, _
    ByVal dwOptions As Long) As Long
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。
import ctypes
from ctypes import wintypes

DuplicateHandle = ctypes.windll.kernel32.DuplicateHandle
DuplicateHandle.restype = wintypes.BOOL
DuplicateHandle.argtypes = [
    wintypes.HANDLE,  # hSourceProcessHandle : HANDLE
    wintypes.HANDLE,  # hSourceHandle : HANDLE
    wintypes.HANDLE,  # hTargetProcessHandle : HANDLE
    ctypes.c_void_p,  # lpTargetHandle : HANDLE* out
    wintypes.DWORD,  # dwDesiredAccess : DWORD
    wintypes.BOOL,  # bInheritHandle : BOOL
    wintypes.DWORD,  # dwOptions : DUPLICATE_HANDLE_OPTIONS
]
# GetLastError: use ctypes.GetLastError() (or ctypes.WinDLL(use_last_error=True))
require 'fiddle'
require 'fiddle/import'

lib = Fiddle.dlopen('KERNEL32.dll')
DuplicateHandle = Fiddle::Function.new(
  lib['DuplicateHandle'],
  [
    Fiddle::TYPE_VOIDP,  # hSourceProcessHandle : HANDLE
    Fiddle::TYPE_VOIDP,  # hSourceHandle : HANDLE
    Fiddle::TYPE_VOIDP,  # hTargetProcessHandle : HANDLE
    Fiddle::TYPE_VOIDP,  # lpTargetHandle : HANDLE* out
    -Fiddle::TYPE_INT,  # dwDesiredAccess : DWORD
    Fiddle::TYPE_INT,  # bInheritHandle : BOOL
    -Fiddle::TYPE_INT,  # dwOptions : DUPLICATE_HANDLE_OPTIONS
  ],
  Fiddle::TYPE_INT)
#[link(name = "kernel32")]
extern "system" {
    fn DuplicateHandle(
        hSourceProcessHandle: *mut core::ffi::c_void,  // HANDLE
        hSourceHandle: *mut core::ffi::c_void,  // HANDLE
        hTargetProcessHandle: *mut core::ffi::c_void,  // HANDLE
        lpTargetHandle: *mut *mut core::ffi::c_void,  // HANDLE* out
        dwDesiredAccess: u32,  // DWORD
        bInheritHandle: i32,  // BOOL
        dwOptions: u32  // DUPLICATE_HANDLE_OPTIONS
    ) -> 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 DuplicateHandle(IntPtr hSourceProcessHandle, IntPtr hSourceHandle, IntPtr hTargetProcessHandle, IntPtr lpTargetHandle, uint dwDesiredAccess, bool bInheritHandle, uint dwOptions);
"@
$api = Add-Type -MemberDefinition $sig -Name 'KERNEL32_DuplicateHandle' -Namespace Win32 -PassThru
# $api::DuplicateHandle(hSourceProcessHandle, hSourceHandle, hTargetProcessHandle, lpTargetHandle, dwDesiredAccess, bInheritHandle, dwOptions)
#uselib "KERNEL32.dll"
#func global DuplicateHandle "DuplicateHandle" sptr, sptr, sptr, sptr, sptr, sptr, sptr
; DuplicateHandle hSourceProcessHandle, hSourceHandle, hTargetProcessHandle, lpTargetHandle, dwDesiredAccess, bInheritHandle, dwOptions   ; 戻り値は stat
; hSourceProcessHandle : HANDLE -> "sptr"
; hSourceHandle : HANDLE -> "sptr"
; hTargetProcessHandle : HANDLE -> "sptr"
; lpTargetHandle : HANDLE* out -> "sptr"
; dwDesiredAccess : DWORD -> "sptr"
; bInheritHandle : BOOL -> "sptr"
; dwOptions : DUPLICATE_HANDLE_OPTIONS -> "sptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。
#uselib "KERNEL32.dll"
#cfunc global DuplicateHandle "DuplicateHandle" sptr, sptr, sptr, sptr, int, int, int
; res = DuplicateHandle(hSourceProcessHandle, hSourceHandle, hTargetProcessHandle, lpTargetHandle, dwDesiredAccess, bInheritHandle, dwOptions)
; hSourceProcessHandle : HANDLE -> "sptr"
; hSourceHandle : HANDLE -> "sptr"
; hTargetProcessHandle : HANDLE -> "sptr"
; lpTargetHandle : HANDLE* out -> "sptr"
; dwDesiredAccess : DWORD -> "int"
; bInheritHandle : BOOL -> "int"
; dwOptions : DUPLICATE_HANDLE_OPTIONS -> "int"
; BOOL DuplicateHandle(HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle, HANDLE* lpTargetHandle, DWORD dwDesiredAccess, BOOL bInheritHandle, DUPLICATE_HANDLE_OPTIONS dwOptions)
#uselib "KERNEL32.dll"
#cfunc global DuplicateHandle "DuplicateHandle" intptr, intptr, intptr, intptr, int, int, int
; res = DuplicateHandle(hSourceProcessHandle, hSourceHandle, hTargetProcessHandle, lpTargetHandle, dwDesiredAccess, bInheritHandle, dwOptions)
; hSourceProcessHandle : HANDLE -> "intptr"
; hSourceHandle : HANDLE -> "intptr"
; hTargetProcessHandle : HANDLE -> "intptr"
; lpTargetHandle : HANDLE* out -> "intptr"
; dwDesiredAccess : DWORD -> "int"
; bInheritHandle : BOOL -> "int"
; dwOptions : DUPLICATE_HANDLE_OPTIONS -> "int"
import (
	"golang.org/x/sys/windows"
	"unsafe"
)

var (
	kernel32 = windows.NewLazySystemDLL("KERNEL32.dll")
	procDuplicateHandle = kernel32.NewProc("DuplicateHandle")
)

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

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

typedef DuplicateHandleNative = Int32 Function(Pointer<Void>, Pointer<Void>, Pointer<Void>, Pointer<Void>, Uint32, Int32, Uint32);
typedef DuplicateHandleDart = int Function(Pointer<Void>, Pointer<Void>, Pointer<Void>, Pointer<Void>, int, int, int);
final DuplicateHandle = DynamicLibrary.open('KERNEL32.dll')
    .lookupFunction<DuplicateHandleNative, DuplicateHandleDart>('DuplicateHandle');
// hSourceProcessHandle : HANDLE -> Pointer<Void>
// hSourceHandle : HANDLE -> Pointer<Void>
// hTargetProcessHandle : HANDLE -> Pointer<Void>
// lpTargetHandle : HANDLE* out -> Pointer<Void>
// dwDesiredAccess : DWORD -> Uint32
// bInheritHandle : BOOL -> Int32
// dwOptions : DUPLICATE_HANDLE_OPTIONS -> Uint32
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。
{$mode objfpc}{$H+}
function DuplicateHandle(
  hSourceProcessHandle: THandle;   // HANDLE
  hSourceHandle: THandle;   // HANDLE
  hTargetProcessHandle: THandle;   // HANDLE
  lpTargetHandle: Pointer;   // HANDLE* out
  dwDesiredAccess: DWORD;   // DWORD
  bInheritHandle: BOOL;   // BOOL
  dwOptions: DWORD   // DUPLICATE_HANDLE_OPTIONS
): BOOL; stdcall;
  external 'KERNEL32.dll' name 'DuplicateHandle';
import Foreign
import Foreign.C.Types
import Foreign.C.String

foreign import stdcall safe "DuplicateHandle"
  c_DuplicateHandle :: Ptr () -> Ptr () -> Ptr () -> Ptr () -> Word32 -> CInt -> Word32 -> IO CInt
-- hSourceProcessHandle : HANDLE -> Ptr ()
-- hSourceHandle : HANDLE -> Ptr ()
-- hTargetProcessHandle : HANDLE -> Ptr ()
-- lpTargetHandle : HANDLE* out -> Ptr ()
-- dwDesiredAccess : DWORD -> Word32
-- bInheritHandle : BOOL -> CInt
-- dwOptions : DUPLICATE_HANDLE_OPTIONS -> Word32
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。
open Ctypes
open Foreign

let duplicatehandle =
  foreign "DuplicateHandle"
    ((ptr void) @-> (ptr void) @-> (ptr void) @-> (ptr void) @-> uint32_t @-> int32_t @-> uint32_t @-> returning int32_t)
(* hSourceProcessHandle : HANDLE -> (ptr void) *)
(* hSourceHandle : HANDLE -> (ptr void) *)
(* hTargetProcessHandle : HANDLE -> (ptr void) *)
(* lpTargetHandle : HANDLE* out -> (ptr void) *)
(* dwDesiredAccess : DWORD -> uint32_t *)
(* bInheritHandle : BOOL -> int32_t *)
(* dwOptions : DUPLICATE_HANDLE_OPTIONS -> uint32_t *)
(* foreign は cdecl 前提。x64 Windows では WINAPI と一致。構造体は ctypes structure を定義のこと。 *)
(cffi:define-foreign-library kernel32 (t "KERNEL32.dll"))
(cffi:use-foreign-library kernel32)

(cffi:defcfun ("DuplicateHandle" duplicate-handle :convention :stdcall) :int32
  (h-source-process-handle :pointer)   ; HANDLE
  (h-source-handle :pointer)   ; HANDLE
  (h-target-process-handle :pointer)   ; HANDLE
  (lp-target-handle :pointer)   ; HANDLE* out
  (dw-desired-access :uint32)   ; DWORD
  (b-inherit-handle :int32)   ; BOOL
  (dw-options :uint32))   ; DUPLICATE_HANDLE_OPTIONS
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $DuplicateHandle = Win32::API::More->new('KERNEL32',
    'BOOL DuplicateHandle(HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle, HANDLE lpTargetHandle, DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwOptions)');
# my $ret = $DuplicateHandle->Call($hSourceProcessHandle, $hSourceHandle, $hTargetProcessHandle, $lpTargetHandle, $dwDesiredAccess, $bInheritHandle, $dwOptions);
# hSourceProcessHandle : HANDLE -> HANDLE
# hSourceHandle : HANDLE -> HANDLE
# hTargetProcessHandle : HANDLE -> HANDLE
# lpTargetHandle : HANDLE* out -> HANDLE
# dwDesiredAccess : DWORD -> DWORD
# bInheritHandle : BOOL -> BOOL
# dwOptions : DUPLICATE_HANDLE_OPTIONS -> DWORD
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。

関連項目

公式の関連項目
使用する型