Win32 API 日本語リファレンス
ホームSecurity.Cryptography › CryptExportKey

CryptExportKey

関数
暗号鍵を保護されたキーBLOB形式でエクスポートする。
DLLADVAPI32.dll呼出規約winapiSetLastErrorあり対応OSWindows XP 以降

シグネチャ

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

BOOL CryptExportKey(
    UINT_PTR hKey,
    UINT_PTR hExpKey,
    DWORD dwBlobType,
    CRYPT_KEY_FLAGS dwFlags,
    BYTE* pbData,   // optional
    DWORD* pdwDataLen
);

パラメーター

名前方向説明
hKeyUINT_PTRinエクスポートする鍵のハンドル。
hExpKeyUINT_PTRin

宛先ユーザーの暗号鍵のハンドル。エクスポートされる key BLOB 内の鍵データは、この鍵を使用して暗号化されます。これにより、宛先ユーザーだけが key BLOB を利用できるようになります。hExpKeyhKey は、いずれも同じ CSP に由来している必要があります。

ほとんどの場合、これは宛先ユーザーの key exchange public key です。ただし、一部の CSP の特定のプロトコルでは、この目的のために宛先ユーザーに属するセッション鍵を使用する必要があります。

dwBlobType で指定された key BLOB の種類が PUBLICKEYBLOB の場合、このパラメーターは使用されず、ゼロに設定する必要があります。

dwBlobType で指定された key BLOB の種類が PRIVATEKEYBLOB の場合、これは通常、key BLOB の暗号化に使用するセッション鍵のハンドルです。一部の CSP ではこのパラメーターをゼロにできますが、その場合、アプリケーションは private key BLOB を保護するために手動で暗号化する必要があります。

Microsoft の cryptographic service providers がこのパラメーターにどのように応答するかを確認するには、 Microsoft Cryptographic Service Providersprivate key BLOB のセクションを参照してください。

注意 一部の CSP は、操作の結果としてこのパラメーターを変更する場合があります。その後この鍵を他の目的で使用するアプリケーションは、CryptDuplicateKey 関数を呼び出して、複製された鍵ハンドルを作成する必要があります。ハンドルの使用が終わったら、CryptDestroyKey 関数を呼び出して解放してください。
dwBlobTypeDWORDin

pbData にエクスポートする key BLOB の種類を指定します。これは、 Cryptographic Key Storage and Exchange で説明されている次の定数のいずれかである必要があります。

意味
OPAQUEKEYBLOB
Schannel CSP やその他のベンダー固有の形式でセッション鍵を格納するために使用します。OPAQUEKEYBLOB は転送不可で、その BLOB を生成した CSP 内で使用する必要があります。
PRIVATEKEYBLOB
public/private key pairs を転送するために使用します。
PUBLICKEYBLOB
公開鍵を転送するために使用します。
SIMPLEBLOB
セッション鍵を転送するために使用します。
PLAINTEXTKEYBLOB
使用中の CSP がサポートする任意の鍵をエクスポートするために使用する PLAINTEXTKEYBLOB です。
SYMMETRICWRAPKEYBLOB
別の対称鍵でラップされた symmetric key をエクスポートおよびインポートするために使用します。実際にラップされた鍵は、IETF RFC 3217 標準で指定された形式です。
dwFlagsCRYPT_KEY_FLAGSin

関数の追加オプションを指定します。このパラメーターには、ゼロ、または次の値の 1 つ以上の組み合わせを指定できます。

意味
CRYPT_BLOB_VER3
0x00000080
このフラグを指定すると、関数は BLOB 型のバージョン 3 をエクスポートします。
CRYPT_DESTROYKEY
0x00000004
このフラグは、OPAQUEKEYBLOB 内の元の鍵を破棄します。このフラグは Schannel CSP でのみ使用できます。
CRYPT_OAEP
0x00000040
このフラグを指定すると、SIMPLEBLOB のエクスポート時に RSA の暗号化と復号で PKCS #1 バージョン 2 形式が作成されます。
CRYPT_SSL2_FALLBACK
0x00000002
RSA 暗号化ブロックの padding の最初の 8 バイトを、ランダムデータではなく 0x03 に設定する必要があります。これはバージョンロールバック攻撃を防ぐもので、SSL3 仕様で説明されています。このフラグは Schannel CSP でのみ使用できます。
CRYPT_Y_ONLY
0x00000001
このフラグは使用されません。
pbDataBYTE*outoptional

key BLOB データを受け取るバッファーへのポインター。この BLOB の形式は、dwBlobType パラメーターで要求された BLOB 型によって異なります。PRIVATEKEYBLOB、PUBLICKEYBLOB、SIMPLEBLOB の形式については、 Base Provider Key BLOBs を参照してください。

このパラメーターが NULL の場合、必要なバッファーサイズが pdwDataLen パラメーターが指す値に格納されます。詳細については、 Retrieving Data of Unknown Length を参照してください。

pdwDataLenDWORD*inout

DWORD 値へのポインター。呼び出し時には、pbData パラメーターが指すバッファーのサイズ (バイト単位) を格納します。関数が戻るとき、この値にはバッファーに格納されたバイト数が入ります。

注意 バッファーで返されたデータを処理する際、アプリケーションは返されたデータの実際のサイズを使用する必要があります。実際のサイズは、入力で指定したバッファーのサイズよりわずかに小さい場合があります。入力時には、起こり得る最大の出力データが収まるように、通常はバッファーサイズを十分に大きく指定します。出力時には、このパラメーターが指す変数が、バッファーにコピーされたデータの実際のサイズを反映するように更新されます。
pbData バッファーに必要なサイズを取得するには、pbDataNULL を渡します。必要なバッファーサイズが、このパラメーターが指す値に格納されます。

戻り値の型: BOOL

公式ドキュメント

暗号化サービスプロバイダー (CSP) から暗号鍵または鍵ペアを安全な方法でエクスポートします。

戻り値

関数が成功した場合、ゼロ以外 (TRUE) を返します。

関数が失敗した場合、ゼロ (FALSE) を返します。拡張エラー情報を取得するには、 GetLastError を呼び出します。

"NTE" で始まるエラーコードは、使用中の特定の CSP によって生成されます。次の表に、考えられるエラーコードの一部を示します。

戻り値 説明
ERROR_INVALID_HANDLE
いずれかのパラメーターが無効なハンドルを指定しています。
ERROR_INVALID_PARAMETER
いずれかのパラメーターが無効な値を含んでいます。これは多くの場合、無効なポインターです。
ERROR_MORE_DATA
pbData パラメーターで指定されたバッファーが、返されるデータを保持するのに十分な大きさでない場合、関数は ERROR_MORE_DATA コードを設定し、必要なバッファーサイズ (バイト単位) を pdwDataLen が指す変数に格納します。
NTE_BAD_DATA
エクスポートする公開鍵で動作するアルゴリズムがこの CSP でサポートされていないか、自分の公開鍵以外のもので暗号化されたセッション鍵をエクスポートしようとしました。
NTE_BAD_FLAGS
dwFlags パラメーターがゼロ以外です。
NTE_BAD_KEY
hKeyhExpKey で指定された鍵の一方または両方が無効です。
NTE_BAD_KEY_STATE
鍵をエクスポートする権限がありません。つまり、hKey の鍵が作成された際に CRYPT_EXPORTABLE フラグが指定されていませんでした。
NTE_BAD_PUBLIC_KEY
dwBlobType で指定された key BLOB の種類が PUBLICKEYBLOB ですが、hExpKey に公開鍵ハンドルが含まれていません。
NTE_BAD_TYPE
dwBlobType パラメーターが不明な BLOB 型を指定しています。
NTE_BAD_UID
hKey の鍵が作成された際に指定された CSP コンテキストが見つかりません。
NTE_NO_KEY
セッション鍵をエクスポートしようとしていますが、hExpKey パラメーターが公開鍵を指定していません。

解説(Remarks)

PLAINTEXTKEYBLOB を使用する DES 鍵の組み合わせのいずれについても、パリティビットを含む完全な鍵サイズのみをエクスポートできます。次の鍵サイズがサポートされています。

アルゴリズム サポートされる鍵サイズ
CALG_DES 64 ビット
CALG_3DES_112 128 ビット
CALG_3DES 192 ビット

次の例は、暗号鍵または鍵ペアをより安全な方法でエクスポートする方法を示しています。この例では、暗号コンテキストが既に取得されており、エクスポート用の公開鍵が利用可能であることを前提としています。この関数を使用するための完全なコンテキストを含む例については、 Example C Program: Signing a Hash and Verifying the Hash Signature を参照してください。この関数を使用する別の例については、Example C Program: Exporting a Session Key を参照してください。

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

BOOL GetExportedKey(
    HCRYPTKEY hKey, 
    DWORD dwBlobType,
    LPBYTE *ppbKeyBlob, 
    LPDWORD pdwBlobLen)
{
    DWORD dwBlobLength;
    *ppbKeyBlob = NULL;
    *pdwBlobLen = 0;

    // Export the public key. Here the public key is exported to a 
    // PUBLICKEYBLOB. This BLOB can be written to a file and
    // sent to another user.

    if(CryptExportKey(   
        hKey,    
        NULL,    
        dwBlobType,
        0,    
        NULL, 
        &dwBlobLength)) 
    {
        printf("Size of the BLOB for the public key determined. \n");
    }
    else
    {
        printf("Error computing BLOB length.\n");
        return FALSE;
    }

    // Allocate memory for the pbKeyBlob.
    if(*ppbKeyBlob = (LPBYTE)malloc(dwBlobLength)) 
    {
        printf("Memory has been allocated for the BLOB. \n");
    }
    else
    {
        printf("Out of memory. \n");
        return FALSE;
    }

    // Do the actual exporting into the key BLOB.
    if(CryptExportKey(   
        hKey, 
        NULL,    
        dwBlobType,    
        0,    
        *ppbKeyBlob,    
        &dwBlobLength))
    {
        printf("Contents have been written to the BLOB. \n");
        *pdwBlobLen = dwBlobLength;
    }
    else
    {
        printf("Error exporting key.\n");
        free(*ppbKeyBlob);
        *ppbKeyBlob = NULL;

        return FALSE;
    }

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

各言語での呼び出し定義

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

BOOL CryptExportKey(
    UINT_PTR hKey,
    UINT_PTR hExpKey,
    DWORD dwBlobType,
    CRYPT_KEY_FLAGS dwFlags,
    BYTE* pbData,   // optional
    DWORD* pdwDataLen
);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("ADVAPI32.dll", SetLastError = true, ExactSpelling = true)]
static extern bool CryptExportKey(
    UIntPtr hKey,   // UINT_PTR
    UIntPtr hExpKey,   // UINT_PTR
    uint dwBlobType,   // DWORD
    uint dwFlags,   // CRYPT_KEY_FLAGS
    IntPtr pbData,   // BYTE* optional, out
    ref uint pdwDataLen   // DWORD* in/out
);
<DllImport("ADVAPI32.dll", SetLastError:=True, ExactSpelling:=True)>
Public Shared Function CryptExportKey(
    hKey As UIntPtr,   ' UINT_PTR
    hExpKey As UIntPtr,   ' UINT_PTR
    dwBlobType As UInteger,   ' DWORD
    dwFlags As UInteger,   ' CRYPT_KEY_FLAGS
    pbData As IntPtr,   ' BYTE* optional, out
    ByRef pdwDataLen As UInteger   ' DWORD* in/out
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
' hKey : UINT_PTR
' hExpKey : UINT_PTR
' dwBlobType : DWORD
' dwFlags : CRYPT_KEY_FLAGS
' pbData : BYTE* optional, out
' pdwDataLen : DWORD* in/out
Declare PtrSafe Function CryptExportKey Lib "advapi32" ( _
    ByVal hKey As LongPtr, _
    ByVal hExpKey As LongPtr, _
    ByVal dwBlobType As Long, _
    ByVal dwFlags As Long, _
    ByVal pbData As LongPtr, _
    ByRef pdwDataLen As Long) As Long
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。
import ctypes
from ctypes import wintypes

CryptExportKey = ctypes.windll.advapi32.CryptExportKey
CryptExportKey.restype = wintypes.BOOL
CryptExportKey.argtypes = [
    ctypes.c_size_t,  # hKey : UINT_PTR
    ctypes.c_size_t,  # hExpKey : UINT_PTR
    wintypes.DWORD,  # dwBlobType : DWORD
    wintypes.DWORD,  # dwFlags : CRYPT_KEY_FLAGS
    ctypes.POINTER(ctypes.c_ubyte),  # pbData : BYTE* optional, out
    ctypes.POINTER(wintypes.DWORD),  # pdwDataLen : DWORD* in/out
]
# GetLastError: use ctypes.GetLastError() (or ctypes.WinDLL(use_last_error=True))
require 'fiddle'
require 'fiddle/import'

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

var (
	advapi32 = windows.NewLazySystemDLL("ADVAPI32.dll")
	procCryptExportKey = advapi32.NewProc("CryptExportKey")
)

// hKey (UINT_PTR), hExpKey (UINT_PTR), dwBlobType (DWORD), dwFlags (CRYPT_KEY_FLAGS), pbData (BYTE* optional, out), pdwDataLen (DWORD* in/out)
r1, _, err := procCryptExportKey.Call(
	uintptr(hKey),
	uintptr(hExpKey),
	uintptr(dwBlobType),
	uintptr(dwFlags),
	uintptr(pbData),
	uintptr(pdwDataLen),
)
_ = err  // syscall.Errno (valid when the call sets last-error)
_ = r1   // BOOL
function CryptExportKey(
  hKey: NativeUInt;   // UINT_PTR
  hExpKey: NativeUInt;   // UINT_PTR
  dwBlobType: DWORD;   // DWORD
  dwFlags: DWORD;   // CRYPT_KEY_FLAGS
  pbData: Pointer;   // BYTE* optional, out
  pdwDataLen: Pointer   // DWORD* in/out
): BOOL; stdcall;
  external 'ADVAPI32.dll' name 'CryptExportKey';
result := DllCall("ADVAPI32\CryptExportKey"
    , "UPtr", hKey   ; UINT_PTR
    , "UPtr", hExpKey   ; UINT_PTR
    , "UInt", dwBlobType   ; DWORD
    , "UInt", dwFlags   ; CRYPT_KEY_FLAGS
    , "Ptr", pbData   ; BYTE* optional, out
    , "Ptr", pdwDataLen   ; DWORD* in/out
    , "Int")   ; return: BOOL
●CryptExportKey(hKey, hExpKey, dwBlobType, dwFlags, pbData, pdwDataLen) = DLL("ADVAPI32.dll", "bool CryptExportKey(int, int, dword, dword, void*, void*)")
# 呼び出し: CryptExportKey(hKey, hExpKey, dwBlobType, dwFlags, pbData, pdwDataLen)
# hKey : UINT_PTR -> "int"
# hExpKey : UINT_PTR -> "int"
# dwBlobType : DWORD -> "dword"
# dwFlags : CRYPT_KEY_FLAGS -> "dword"
# pbData : BYTE* optional, out -> "void*"
# pdwDataLen : DWORD* in/out -> "void*"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。
const std = @import("std");

extern "advapi32" fn CryptExportKey(
    hKey: usize, // UINT_PTR
    hExpKey: usize, // UINT_PTR
    dwBlobType: u32, // DWORD
    dwFlags: u32, // CRYPT_KEY_FLAGS
    pbData: [*c]u8, // BYTE* optional, out
    pdwDataLen: [*c]u32 // DWORD* in/out
) callconv(std.os.windows.WINAPI) i32;
proc CryptExportKey(
    hKey: uint,  # UINT_PTR
    hExpKey: uint,  # UINT_PTR
    dwBlobType: uint32,  # DWORD
    dwFlags: uint32,  # CRYPT_KEY_FLAGS
    pbData: ptr uint8,  # BYTE* optional, out
    pdwDataLen: ptr uint32  # DWORD* in/out
): int32 {.importc: "CryptExportKey", stdcall, dynlib: "ADVAPI32.dll".}
pragma(lib, "advapi32");
extern(Windows)
int CryptExportKey(
    size_t hKey,   // UINT_PTR
    size_t hExpKey,   // UINT_PTR
    uint dwBlobType,   // DWORD
    uint dwFlags,   // CRYPT_KEY_FLAGS
    ubyte* pbData,   // BYTE* optional, out
    uint* pdwDataLen   // DWORD* in/out
);
ccall((:CryptExportKey, "ADVAPI32.dll"), stdcall, Int32,
      (Csize_t, Csize_t, UInt32, UInt32, Ptr{UInt8}, Ptr{UInt32}),
      hKey, hExpKey, dwBlobType, dwFlags, pbData, pdwDataLen)
# hKey : UINT_PTR -> Csize_t
# hExpKey : UINT_PTR -> Csize_t
# dwBlobType : DWORD -> UInt32
# dwFlags : CRYPT_KEY_FLAGS -> UInt32
# pbData : BYTE* optional, out -> Ptr{UInt8}
# pdwDataLen : DWORD* in/out -> Ptr{UInt32}
# stdcall は 32bit のみ意味を持つ(x64 では無視)。
local ffi = require("ffi")
ffi.cdef[[
int32_t CryptExportKey(
    uintptr_t hKey,
    uintptr_t hExpKey,
    uint32_t dwBlobType,
    uint32_t dwFlags,
    uint8_t* pbData,
    uint32_t* pdwDataLen);
]]
local advapi32 = ffi.load("advapi32")
-- advapi32.CryptExportKey(hKey, hExpKey, dwBlobType, dwFlags, pbData, pdwDataLen)
-- hKey : UINT_PTR
-- hExpKey : UINT_PTR
-- dwBlobType : DWORD
-- dwFlags : CRYPT_KEY_FLAGS
-- pbData : BYTE* optional, out
-- pdwDataLen : DWORD* in/out
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
const koffi = require('koffi');
const lib = koffi.load('ADVAPI32.dll');
const CryptExportKey = lib.func('__stdcall', 'CryptExportKey', 'int32_t', ['uintptr_t', 'uintptr_t', 'uint32_t', 'uint32_t', 'uint8_t *', 'uint32_t *']);
// CryptExportKey(hKey, hExpKey, dwBlobType, dwFlags, pbData, pdwDataLen)
// hKey : UINT_PTR -> 'uintptr_t'
// hExpKey : UINT_PTR -> 'uintptr_t'
// dwBlobType : DWORD -> 'uint32_t'
// dwFlags : CRYPT_KEY_FLAGS -> 'uint32_t'
// pbData : BYTE* optional, out -> 'uint8_t *'
// pdwDataLen : DWORD* in/out -> 'uint32_t *'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。
const lib = Deno.dlopen("ADVAPI32.dll", {
  CryptExportKey: { parameters: ["usize", "usize", "u32", "u32", "pointer", "pointer"], result: "i32" },
});
// lib.symbols.CryptExportKey(hKey, hExpKey, dwBlobType, dwFlags, pbData, pdwDataLen)
// hKey : UINT_PTR -> "usize"
// hExpKey : UINT_PTR -> "usize"
// dwBlobType : DWORD -> "u32"
// dwFlags : CRYPT_KEY_FLAGS -> "u32"
// pbData : BYTE* optional, out -> "pointer"
// pdwDataLen : DWORD* in/out -> "pointer"
// 文字列引数は "buffer"(NUL 終端のバイト列を Uint8Array で渡す)。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。
<?php
$ffi = FFI::cdef(<<<C
int32_t CryptExportKey(
    size_t hKey,
    size_t hExpKey,
    uint32_t dwBlobType,
    uint32_t dwFlags,
    uint8_t* pbData,
    uint32_t* pdwDataLen);
C, "ADVAPI32.dll");
// $ffi->CryptExportKey(hKey, hExpKey, dwBlobType, dwFlags, pbData, pdwDataLen);
// hKey : UINT_PTR
// hExpKey : UINT_PTR
// dwBlobType : DWORD
// dwFlags : CRYPT_KEY_FLAGS
// pbData : BYTE* optional, out
// pdwDataLen : DWORD* 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 Advapi32 extends StdCallLibrary {
    Advapi32 INSTANCE = Native.load("advapi32", Advapi32.class);
    boolean CryptExportKey(
        long hKey,   // UINT_PTR
        long hExpKey,   // UINT_PTR
        int dwBlobType,   // DWORD
        int dwFlags,   // CRYPT_KEY_FLAGS
        byte[] pbData,   // BYTE* optional, out
        IntByReference pdwDataLen   // DWORD* in/out
    );
}
@[Link("advapi32")]
lib LibADVAPI32
  fun CryptExportKey = CryptExportKey(
    hKey : LibC::SizeT,   # UINT_PTR
    hExpKey : LibC::SizeT,   # UINT_PTR
    dwBlobType : UInt32,   # DWORD
    dwFlags : UInt32,   # CRYPT_KEY_FLAGS
    pbData : UInt8*,   # BYTE* optional, out
    pdwDataLen : UInt32*   # DWORD* 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 CryptExportKeyNative = Int32 Function(UintPtr, UintPtr, Uint32, Uint32, Pointer<Uint8>, Pointer<Uint32>);
typedef CryptExportKeyDart = int Function(int, int, int, int, Pointer<Uint8>, Pointer<Uint32>);
final CryptExportKey = DynamicLibrary.open('ADVAPI32.dll')
    .lookupFunction<CryptExportKeyNative, CryptExportKeyDart>('CryptExportKey');
// hKey : UINT_PTR -> UintPtr
// hExpKey : UINT_PTR -> UintPtr
// dwBlobType : DWORD -> Uint32
// dwFlags : CRYPT_KEY_FLAGS -> Uint32
// pbData : BYTE* optional, out -> Pointer<Uint8>
// pdwDataLen : DWORD* in/out -> Pointer<Uint32>
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。
{$mode objfpc}{$H+}
function CryptExportKey(
  hKey: NativeUInt;   // UINT_PTR
  hExpKey: NativeUInt;   // UINT_PTR
  dwBlobType: DWORD;   // DWORD
  dwFlags: DWORD;   // CRYPT_KEY_FLAGS
  pbData: Pointer;   // BYTE* optional, out
  pdwDataLen: Pointer   // DWORD* in/out
): BOOL; stdcall;
  external 'ADVAPI32.dll' name 'CryptExportKey';
import Foreign
import Foreign.C.Types
import Foreign.C.String

foreign import stdcall safe "CryptExportKey"
  c_CryptExportKey :: CUIntPtr -> CUIntPtr -> Word32 -> Word32 -> Ptr Word8 -> Ptr Word32 -> IO CInt
-- hKey : UINT_PTR -> CUIntPtr
-- hExpKey : UINT_PTR -> CUIntPtr
-- dwBlobType : DWORD -> Word32
-- dwFlags : CRYPT_KEY_FLAGS -> Word32
-- pbData : BYTE* optional, out -> Ptr Word8
-- pdwDataLen : DWORD* in/out -> Ptr Word32
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。
open Ctypes
open Foreign

let cryptexportkey =
  foreign "CryptExportKey"
    (size_t @-> size_t @-> uint32_t @-> uint32_t @-> (ptr uint8_t) @-> (ptr uint32_t) @-> returning int32_t)
(* hKey : UINT_PTR -> size_t *)
(* hExpKey : UINT_PTR -> size_t *)
(* dwBlobType : DWORD -> uint32_t *)
(* dwFlags : CRYPT_KEY_FLAGS -> uint32_t *)
(* pbData : BYTE* optional, out -> (ptr uint8_t) *)
(* pdwDataLen : DWORD* in/out -> (ptr uint32_t) *)
(* foreign は cdecl 前提。x64 Windows では WINAPI と一致。構造体は ctypes structure を定義のこと。 *)
(cffi:define-foreign-library advapi32 (t "ADVAPI32.dll"))
(cffi:use-foreign-library advapi32)

(cffi:defcfun ("CryptExportKey" crypt-export-key :convention :stdcall) :int32
  (h-key :uint64)   ; UINT_PTR
  (h-exp-key :uint64)   ; UINT_PTR
  (dw-blob-type :uint32)   ; DWORD
  (dw-flags :uint32)   ; CRYPT_KEY_FLAGS
  (pb-data :pointer)   ; BYTE* optional, out
  (pdw-data-len :pointer))   ; DWORD* in/out
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $CryptExportKey = Win32::API::More->new('ADVAPI32',
    'BOOL CryptExportKey(WPARAM hKey, WPARAM hExpKey, DWORD dwBlobType, DWORD dwFlags, LPVOID pbData, LPVOID pdwDataLen)');
# my $ret = $CryptExportKey->Call($hKey, $hExpKey, $dwBlobType, $dwFlags, $pbData, $pdwDataLen);
# hKey : UINT_PTR -> WPARAM
# hExpKey : UINT_PTR -> WPARAM
# dwBlobType : DWORD -> DWORD
# dwFlags : CRYPT_KEY_FLAGS -> DWORD
# pbData : BYTE* optional, out -> LPVOID
# pdwDataLen : DWORD* in/out -> LPVOID
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。

関連項目

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