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

CryptAcquireContextW

関数
暗号化サービスプロバイダーのコンテキストハンドルを取得する(Unicode版)。
DLLADVAPI32.dll文字セットUnicode (-W)呼出規約winapiSetLastErrorあり対応OSWindows XP 以降

シグネチャ

// ADVAPI32.dll  (Unicode / -W)
#include <windows.h>

BOOL CryptAcquireContextW(
    UINT_PTR* phProv,
    LPCWSTR szContainer,   // optional
    LPCWSTR szProvider,   // optional
    DWORD dwProvType,
    DWORD dwFlags
);

パラメーター

名前方向説明
phProvUINT_PTR*outCSP のハンドルへのポインター。CSP の使用が完了したら、CryptReleaseContext 関数を呼び出してハンドルを解放します。
szContainerLPCWSTRinoptional

キーコンテナー名。これは、CSP に対してキーコンテナーを識別する null 終端文字列です。この名前は、キーの格納方法とは独立しています。一部の CSP はキーコンテナーを内部 (ハードウェア内) に格納し、一部はシステムレジストリを使用し、その他はファイルシステムを使用します。ほとんどの場合、dwFlagsCRYPT_VERIFYCONTEXT に設定されている場合、pszContainerNULL に設定する必要があります。ただし、スマートカード CSP などのハードウェアベースの CSP では、指定したコンテナー内の公開されている情報にアクセスできます。

pszContainer パラメーターの使用方法の詳細については、「解説」を参照してください。

szProviderLPCWSTRinoptional

使用する CSP の名前を含む null 終端文字列。

このパラメーターが NULL の場合、ユーザーの既定のプロバイダーが使用されます。詳細については、 Cryptographic Service Provider Contexts を参照してください。利用可能な暗号化プロバイダーの一覧については、 Cryptographic Provider Names を参照してください。

アプリケーションは、CryptGetProvParam 関数を使用して dwParam パラメーターで PP_NAME CSP 値を読み取ることにより、使用中の CSP の名前を取得できます。

既定の CSP はオペレーティングシステムのリリース間で変わる場合があります。異なるオペレーティングシステムプラットフォーム間での相互運用性を確保するため、既定の CSP を使用するのではなく、このパラメーターを使用して CSP を明示的に設定する必要があります。

dwProvTypeDWORDin取得するプロバイダーの種類を指定します。定義済みのプロバイダーの種類については、 Cryptographic Provider Types で説明されています。
dwFlagsDWORDin

次のフラグの 1 つ以上。なお、ほとんどのアプリケーションでは、デジタル署名の作成やメッセージの復号化が必要な場合を除き、CRYPT_VERIFYCONTEXT フラグを設定する必要があります。

意味
CRYPT_VERIFYCONTEXT
呼び出し元は、永続化された秘密キーへのアクセスを必要としません。一時的なキーを使用するアプリ、または ハッシュ暗号化デジタル署名の検証のみを実行するアプリは、このフラグを設定する必要があります。秘密キーへのアクセスが必要なのは、署名を作成するアプリケーションまたはメッセージを復号化するアプリケーションのみです (これらはこのフラグを設定しないでください)。

ファイルベースの CSP の場合、このフラグが設定されているときは、pszContainer パラメーターを NULL に設定する必要があります。アプリケーションは、公開/秘密キーペアの永続化された秘密キーにアクセスできません。このフラグが設定されている場合、一時的な公開/秘密キーペアを作成できますが、永続化されません。

スマートカード CSP などのハードウェアベースの CSP の場合、pszContainer パラメーターが NULL または空白であれば、このフラグはキーへのアクセスが一切不要であり、ユーザーに UI を表示しないことを意味します。この形式は、CSP に接続してその機能を照会するために使用され、実際にそのキーを使用するためではありません。 pszContainer パラメーターが NULL でも空白でもない場合、このフラグは指定したコンテナー内の公開されている情報のみへのアクセスが必要であることを意味します。CSP は PIN を要求しないはずです。秘密情報へのアクセスの試み (たとえば CryptSignHash 関数) は失敗します。

CryptAcquireContext が呼び出されると、多くの CSP はキーコンテナー内の秘密キーへのアクセスを許可する前に、所有ユーザーからの入力を必要とします。たとえば、秘密キーが暗号化されている場合、使用する前にユーザーからのパスワードが必要です。ただし、CRYPT_VERIFYCONTEXT フラグが指定されている場合、秘密キーへのアクセスは不要であり、ユーザーインターフェイスを省略できます。

CRYPT_NEWKEYSET
pszContainer で指定された名前を持つ新しいキーコンテナーを作成します。pszContainerNULL の場合、既定の名前を持つキーコンテナーが作成されます。
CRYPT_MACHINE_KEYSET
既定では、キーおよびキーコンテナーはユーザーキーとして格納されます。Base Provider の場合、これはユーザーキーコンテナーがユーザーのプロファイルに格納されることを意味します。管理者がこのフラグなしで作成したキーコンテナーには、そのキーコンテナーを作成したユーザーと管理者権限を持つユーザーのみがアクセスできます。

Windows XP: 管理者がこのフラグなしで作成したキーコンテナーには、そのキーコンテナーを作成したユーザーとローカルシステムアカウントのみがアクセスできます。

管理者ではないユーザーがこのフラグなしで作成したキーコンテナーには、そのキーコンテナーを作成したユーザーとローカルシステムアカウントのみがアクセスできます。

CRYPT_MACHINE_KEYSET フラグは、他のすべてのフラグと組み合わせて、対象のキーコンテナーがコンピューターキーコンテナーであり、CSP がそのように扱うことを示すことができます。Base Provider の場合、これはキーがキーコンテナーを作成したコンピューター上にローカルに格納されることを意味します。キーコンテナーをコンピューターコンテナーにする場合は、そのコンピューターコンテナーを参照する CryptAcquireContext へのすべての呼び出しで CRYPT_MACHINE_KEYSET フラグを使用する必要があります。管理者が CRYPT_MACHINE_KEYSET で作成したキーコンテナーには、 CryptSetProvParam を使用してコンテナーへのアクセス権が付与されない限り、その作成者と管理者権限を持つユーザーのみがアクセスできます。

Windows XP: 管理者が CRYPT_MACHINE_KEYSET で作成したキーコンテナーには、 CryptSetProvParam を使用してコンテナーへのアクセス権が付与されない限り、その作成者とローカルシステムアカウントのみがアクセスできます。

管理者ではないユーザーが CRYPT_MACHINE_KEYSET で作成したキーコンテナーには、 CryptSetProvParam を使用してコンテナーへのアクセス権が付与されない限り、その作成者とローカルシステムアカウントのみがアクセスできます。

CRYPT_MACHINE_KEYSET フラグは、対話的にログオンしなかったサービスアカウントまたはユーザーアカウントからユーザーがアクセスする場合に役立ちます。キーコンテナーが作成されるとき、ほとんどの CSP は公開/秘密キーペアを自動的には作成しません。これらのキーは、 CryptGenKey 関数を使用して別の手順として作成する必要があります。

CRYPT_DELETEKEYSET
pszContainer で指定されたキーコンテナーを削除します。pszContainerNULL の場合、既定の名前を持つキーコンテナーが削除されます。キーコンテナー内のすべてのキーペアも破棄されます。

このフラグが設定されている場合、phProv で返される値は未定義であり、したがって、その後 CryptReleaseContext 関数を呼び出す必要はありません。

CRYPT_SILENT
アプリケーションは、このコンテキストに対して CSP がユーザーインターフェイス (UI) を一切表示しないことを要求します。CSP が動作するために UI を表示する必要がある場合、呼び出しは失敗し、最後のエラーとして NTE_SILENT_CONTEXT エラーコードが設定されます。さらに、CRYPT_SILENT フラグで取得したコンテキストを使用して CRYPT_USER_PROTECTED フラグ付きで CryptGenKey を呼び出した場合、その呼び出しは失敗し、CSP は NTE_SILENT_CONTEXT を設定します。

CRYPT_SILENT は、CSP が UI を表示できないアプリケーションでの使用を想定しています。

CRYPT_DEFAULT_CONTAINER_OPTIONAL
ハッシュおよび対称キー操作に使用できるが、PIN を使用したスマートカードへの認証を必要とする操作には使用できない、スマートカード CSP のコンテキストを取得します。この種類のコンテキストは、CryptSetProvParam を使用して PIN を設定するなど、空のスマートカードに対して操作を実行するために最もよく使用されます。このフラグはスマートカード CSP でのみ使用できます。

Windows Server 2003 および Windows XP: このフラグはサポートされていません。

戻り値の型: BOOL

公式ドキュメント

特定の暗号化サービスプロバイダー (CSP) 内にある特定のキーコンテナーへのハンドルを取得するために使用します。返されたこのハンドルは、選択した CSP を使用する CryptoAPI 関数の呼び出しで使用されます。(Unicode)

戻り値

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

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

NTE を接頭辞とするエラーコードは、使用している特定の CSP によって生成されます。Winerror.h で定義されている考えられるエラーコードの一部を次に示します。

戻り値/値 説明
ERROR_BUSY
107L
一部の CSP は、CRYPT_DELETEKEYSET フラグ値が設定されており、別のスレッドまたはプロセスがこのキーコンテナーを使用している場合に、このエラーを設定します。
ERROR_FILE_NOT_FOUND
2L
ユーザーのプロファイルが読み込まれておらず、見つかりません。これは、アプリケーションがユーザー (たとえば IUSR_ComputerName アカウント) を偽装している場合に発生します。
ERROR_INVALID_PARAMETER
87L
いずれかのパラメーターに無効な値が含まれています。これは多くの場合、無効なポインターです。
ERROR_NOT_ENOUGH_MEMORY
8L
操作中にオペレーティングシステムのメモリが不足しました。
NTE_BAD_FLAGS
0x80090009L
dwFlags パラメーターに無効な値が含まれています。
NTE_BAD_KEY_STATE
0x8009000BL
秘密キーが暗号化されてから、ユーザーパスワードが変更されました。
NTE_BAD_KEYSET
0x80090016L
キーコンテナーを開けませんでした。このエラーの一般的な原因は、キーコンテナーが存在しないことです。キーコンテナーを作成するには、CRYPT_NEWKEYSET フラグを使用して CryptAcquireContext を呼び出します。このエラーコードは、既存のキーコンテナーへのアクセスが拒否されたことを示す場合もあります。コンテナーへのアクセス権は、 CryptSetProvParam を使用してキーセットの作成者が付与できます。
NTE_BAD_KEYSET_PARAM
0x8009001FL
pszContainer または pszProvider パラメーターに無効な値が設定されています。
NTE_BAD_PROV_TYPE
0x80090014L
dwProvType パラメーターの値が範囲外です。すべてのプロバイダーの種類は 1 から 999 までの範囲内である必要があります。
NTE_BAD_SIGNATURE
0x80090006L
プロバイダー DLL の署名を検証できませんでした。DLL またはデジタル署名が改ざんされています。
NTE_EXISTS
0x8009000FL
dwFlags パラメーターが CRYPT_NEWKEYSET ですが、キーコンテナーが既に存在します。
NTE_KEYSET_ENTRY_BAD
0x8009001AL
pszContainer キーコンテナーは見つかりましたが、破損しています。
NTE_KEYSET_NOT_DEF
0x80090019L
要求されたプロバイダーが存在しません。
NTE_NO_MEMORY
0x8009000EL
操作中に CSP のメモリが不足しました。
NTE_PROV_DLL_NOT_FOUND
0x8009001EL
プロバイダー DLL ファイルが存在しないか、現在のパス上にありません。
NTE_PROV_TYPE_ENTRY_BAD
0x80090018L
dwProvType で指定されたプロバイダーの種類が破損しています。このエラーは、ユーザーの既定の CSP リストまたはコンピューターの既定の CSP リストのいずれかに関連する可能性があります。
NTE_PROV_TYPE_NO_MATCH
0x8009001BL
dwProvType で指定されたプロバイダーの種類が、見つかったプロバイダーの種類と一致しません。なお、このエラーは pszProvider が実際の CSP 名を指定している場合にのみ発生します。
NTE_PROV_TYPE_NOT_DEF
0x80090017L
dwProvType で指定されたプロバイダーの種類のエントリが存在しません。
NTE_PROVIDER_DLL_FAIL
0x8009001DL
プロバイダー DLL ファイルを読み込めなかったか、初期化に失敗しました。
NTE_SIGNATURE_FILE_BAD
0x8009001CL
署名を検証する前の、DLL ファイルイメージの読み込み中にエラーが発生しました。

解説(Remarks)

pszContainer パラメーターは、キーを保持するために使用するコンテナーの名前を指定します。各コンテナーには 1 つのキーを格納できます。キーを作成するときに既存のコンテナーの名前を指定すると、新しいキーは以前のキーを上書きします。

CSP 名とキーコンテナー名の組み合わせは、システム上の単一のキーを一意に識別します。あるアプリケーションが、別のアプリケーションが使用中のキーコンテナーを変更しようとすると、予測できない動作が発生する可能性があります。

pszContainer パラメーターを NULL に設定すると、既定のキーコンテナー名が使用されます。Microsoft ソフトウェア CSP がこの方法で呼び出されると、CryptAcquireContext 関数が呼び出されるたびに新しいコンテナーが作成されます。ただし、この点については CSP によって動作が異なる場合があります。特に、CSP が、その CSP にアクセスするすべてのアプリケーションで共有される単一の既定のコンテナーを持つ場合があります。したがって、アプリケーションは秘密キーを格納するために既定のキーコンテナーを使用してはなりません。代わりに、dwFlags パラメーターに CRYPT_VERIFYCONTEXT フラグを渡してキーの格納を防止するか、別のアプリケーションで使用される可能性が低いアプリケーション固有のコンテナーを使用してください。

アプリケーションは、 CryptGetProvParam 関数を使用して PP_CONTAINER 値を読み取ることにより、使用中のキーコンテナーの名前を取得できます。

パフォーマンス上の理由から、永続化されたキーが不要なすべての状況では、pszContainer パラメーターを NULL に、dwFlags パラメーターを CRYPT_VERIFYCONTEXT に設定することをお勧めします。特に、次のシナリオでは pszContainer パラメーターを NULL に、dwFlags パラメーターを CRYPT_VERIFYCONTEXT に設定することを検討してください。

秘密キー操作を実行する予定がある場合、コンテキストを取得する最善の方法は、コンテナーを開いてみることです。この試みが NTE_BAD_KEYSET で失敗した場合は、CRYPT_NEWKEYSET フラグを使用してコンテナーを作成します。

次の例は、暗号化コンテキストと、キーコンテナー内の公開/秘密キーペアへのアクセスを取得する方法を示しています。要求されたキーコンテナーが存在しない場合は、作成されます。

この例の完全なコンテキストを含む例については、Example C Program: Creating a Key Container and Generating Keys を参照してください。その他の例については、 Example C Program: Using CryptAcquireContext を参照してください。

//-------------------------------------------------------------------
// Declare and initialize variables.

HCRYPTPROV hCryptProv = NULL;        // handle for a cryptographic
                                     // provider context
LPCSTR UserName = "MyKeyContainer";  // name of the key container
                                     // to be used
//-------------------------------------------------------------------
// Attempt to acquire a context and a key
// container. The context will use the default CSP
// for the RSA_FULL provider type. DwFlags is set to zero
// to attempt to open an existing key container.

if(CryptAcquireContext(
   &hCryptProv,               // handle to the CSP
   UserName,                  // container name 
   NULL,                      // use the default provider
   PROV_RSA_FULL,             // provider type
   0))                        // flag values
{
    printf("A cryptographic context with the %s key container \n", 
  UserName);
    printf("has been acquired.\n\n");
}
else
{ 
//-------------------------------------------------------------------
// An error occurred in acquiring the context. This could mean
// that the key container requested does not exist. In this case,
// the function can be called again to attempt to create a new key 
// container. Error codes are defined in Winerror.h.
 if (GetLastError() == NTE_BAD_KEYSET)
 {
   if(CryptAcquireContext(
      &hCryptProv, 
      UserName, 
      NULL, 
      PROV_RSA_FULL, 
      CRYPT_NEWKEYSET)) 
    {
      printf("A new key container has been created.\n");
    }
    else
    {
      printf("Could not create a new key container.\n");
      exit(1);
    }
  }
  else
  {
      printf("A cryptographic service handle could not be "
          "acquired.\n");
      exit(1);
   }
  
} // End of else.
//-------------------------------------------------------------------
// A cryptographic context and a key container are available. Perform
// any functions that require a cryptographic provider handle.

//-------------------------------------------------------------------
// When the handle is no longer needed, it must be released.

if (CryptReleaseContext(hCryptProv,0))
{
  printf("The handle has been released.\n");
}
else
{
  printf("The handle could not be released.\n");
}
メモ

wincrypt.h ヘッダーは、UNICODE プリプロセッサー定数の定義に基づいて、この関数の ANSI 版または Unicode 版を自動的に選択するエイリアスとして CryptAcquireContext を定義しています。エンコードニュートラルなエイリアスの使用を、エンコードニュートラルではないコードと混在させると、不一致が生じてコンパイルエラーまたは実行時エラーが発生する可能性があります。詳細については、Conventions for Function Prototypes を参照してください。

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

各言語での呼び出し定義

// ADVAPI32.dll  (Unicode / -W)
#include <windows.h>

BOOL CryptAcquireContextW(
    UINT_PTR* phProv,
    LPCWSTR szContainer,   // optional
    LPCWSTR szProvider,   // optional
    DWORD dwProvType,
    DWORD dwFlags
);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("ADVAPI32.dll", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
static extern bool CryptAcquireContextW(
    out UIntPtr phProv,   // UINT_PTR* out
    [MarshalAs(UnmanagedType.LPWStr)] string szContainer,   // LPCWSTR optional
    [MarshalAs(UnmanagedType.LPWStr)] string szProvider,   // LPCWSTR optional
    uint dwProvType,   // DWORD
    uint dwFlags   // DWORD
);
<DllImport("ADVAPI32.dll", CharSet:=CharSet.Unicode, SetLastError:=True, ExactSpelling:=True)>
Public Shared Function CryptAcquireContextW(
    <Out> ByRef phProv As UIntPtr,   ' UINT_PTR* out
    <MarshalAs(UnmanagedType.LPWStr)> szContainer As String,   ' LPCWSTR optional
    <MarshalAs(UnmanagedType.LPWStr)> szProvider As String,   ' LPCWSTR optional
    dwProvType As UInteger,   ' DWORD
    dwFlags As UInteger   ' DWORD
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
' phProv : UINT_PTR* out
' szContainer : LPCWSTR optional
' szProvider : LPCWSTR optional
' dwProvType : DWORD
' dwFlags : DWORD
Declare PtrSafe Function CryptAcquireContextW Lib "advapi32" ( _
    ByRef phProv As LongPtr, _
    ByVal szContainer As LongPtr, _
    ByVal szProvider As LongPtr, _
    ByVal dwProvType As Long, _
    ByVal dwFlags As Long) As Long
' Unicode(W): 文字列は ByVal As LongPtr とし StrPtr(unicodeStr) を渡す
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。
import ctypes
from ctypes import wintypes

CryptAcquireContextW = ctypes.windll.advapi32.CryptAcquireContextW
CryptAcquireContextW.restype = wintypes.BOOL
CryptAcquireContextW.argtypes = [
    ctypes.POINTER(ctypes.c_size_t),  # phProv : UINT_PTR* out
    wintypes.LPCWSTR,  # szContainer : LPCWSTR optional
    wintypes.LPCWSTR,  # szProvider : LPCWSTR optional
    wintypes.DWORD,  # dwProvType : DWORD
    wintypes.DWORD,  # dwFlags : DWORD
]
# GetLastError: use ctypes.GetLastError() (or ctypes.WinDLL(use_last_error=True))
require 'fiddle'
require 'fiddle/import'

lib = Fiddle.dlopen('ADVAPI32.dll')
CryptAcquireContextW = Fiddle::Function.new(
  lib['CryptAcquireContextW'],
  [
    Fiddle::TYPE_VOIDP,  # phProv : UINT_PTR* out
    Fiddle::TYPE_VOIDP,  # szContainer : LPCWSTR optional
    Fiddle::TYPE_VOIDP,  # szProvider : LPCWSTR optional
    -Fiddle::TYPE_INT,  # dwProvType : DWORD
    -Fiddle::TYPE_INT,  # dwFlags : DWORD
  ],
  Fiddle::TYPE_INT)
# Wide strings: pass str.encode("UTF-16LE") + "\x00\x00"
#[link(name = "advapi32")]
extern "system" {
    fn CryptAcquireContextW(
        phProv: *mut usize,  // UINT_PTR* out
        szContainer: *const u16,  // LPCWSTR optional
        szProvider: *const u16,  // LPCWSTR optional
        dwProvType: u32,  // DWORD
        dwFlags: u32  // DWORD
    ) -> i32;
}
// crates: windows-sys provides ready-made bindings for this API.
$sig = @"
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("ADVAPI32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool CryptAcquireContextW(out UIntPtr phProv, [MarshalAs(UnmanagedType.LPWStr)] string szContainer, [MarshalAs(UnmanagedType.LPWStr)] string szProvider, uint dwProvType, uint dwFlags);
"@
$api = Add-Type -MemberDefinition $sig -Name 'ADVAPI32_CryptAcquireContextW' -Namespace Win32 -PassThru
# $api::CryptAcquireContextW(phProv, szContainer, szProvider, dwProvType, dwFlags)
#uselib "ADVAPI32.dll"
#func global CryptAcquireContextW "CryptAcquireContextW" wptr, wptr, wptr, wptr, wptr
; CryptAcquireContextW varptr(phProv), szContainer, szProvider, dwProvType, dwFlags   ; 戻り値は stat
; phProv : UINT_PTR* out -> "wptr"
; szContainer : LPCWSTR optional -> "wptr"
; szProvider : LPCWSTR optional -> "wptr"
; dwProvType : DWORD -> "wptr"
; dwFlags : DWORD -> "wptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。
出力引数:
#uselib "ADVAPI32.dll"
#cfunc global CryptAcquireContextW "CryptAcquireContextW" var, wstr, wstr, int, int
; res = CryptAcquireContextW(phProv, szContainer, szProvider, dwProvType, dwFlags)
; phProv : UINT_PTR* out -> "var"
; szContainer : LPCWSTR optional -> "wstr"
; szProvider : LPCWSTR optional -> "wstr"
; dwProvType : DWORD -> "int"
; dwFlags : DWORD -> "int"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
出力引数:
; BOOL CryptAcquireContextW(UINT_PTR* phProv, LPCWSTR szContainer, LPCWSTR szProvider, DWORD dwProvType, DWORD dwFlags)
#uselib "ADVAPI32.dll"
#cfunc global CryptAcquireContextW "CryptAcquireContextW" var, wstr, wstr, int, int
; res = CryptAcquireContextW(phProv, szContainer, szProvider, dwProvType, dwFlags)
; phProv : UINT_PTR* out -> "var"
; szContainer : LPCWSTR optional -> "wstr"
; szProvider : LPCWSTR optional -> "wstr"
; dwProvType : DWORD -> "int"
; dwFlags : DWORD -> "int"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
import (
	"golang.org/x/sys/windows"
	"unsafe"
)

var (
	advapi32 = windows.NewLazySystemDLL("ADVAPI32.dll")
	procCryptAcquireContextW = advapi32.NewProc("CryptAcquireContextW")
)

// phProv (UINT_PTR* out), szContainer (LPCWSTR optional), szProvider (LPCWSTR optional), dwProvType (DWORD), dwFlags (DWORD)
r1, _, err := procCryptAcquireContextW.Call(
	uintptr(phProv),
	uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(szContainer))),
	uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(szProvider))),
	uintptr(dwProvType),
	uintptr(dwFlags),
)
_ = err  // syscall.Errno (valid when the call sets last-error)
_ = r1   // BOOL
function CryptAcquireContextW(
  phProv: Pointer;   // UINT_PTR* out
  szContainer: PWideChar;   // LPCWSTR optional
  szProvider: PWideChar;   // LPCWSTR optional
  dwProvType: DWORD;   // DWORD
  dwFlags: DWORD   // DWORD
): BOOL; stdcall;
  external 'ADVAPI32.dll' name 'CryptAcquireContextW';
result := DllCall("ADVAPI32\CryptAcquireContextW"
    , "Ptr", phProv   ; UINT_PTR* out
    , "WStr", szContainer   ; LPCWSTR optional
    , "WStr", szProvider   ; LPCWSTR optional
    , "UInt", dwProvType   ; DWORD
    , "UInt", dwFlags   ; DWORD
    , "Int")   ; return: BOOL
●CryptAcquireContextW(phProv, szContainer, szProvider, dwProvType, dwFlags) = DLL("ADVAPI32.dll", "bool CryptAcquireContextW(void*, char*, char*, dword, dword)")
# 呼び出し: CryptAcquireContextW(phProv, szContainer, szProvider, dwProvType, dwFlags)
# phProv : UINT_PTR* out -> "void*"
# szContainer : LPCWSTR optional -> "char*"
# szProvider : LPCWSTR optional -> "char*"
# dwProvType : DWORD -> "dword"
# dwFlags : DWORD -> "dword"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。
# ※-W(Unicode)関数。なでしこ1はANSIのため -A 版の利用を推奨。
const std = @import("std");

extern "advapi32" fn CryptAcquireContextW(
    phProv: [*c]usize, // UINT_PTR* out
    szContainer: [*c]const u16, // LPCWSTR optional
    szProvider: [*c]const u16, // LPCWSTR optional
    dwProvType: u32, // DWORD
    dwFlags: u32 // DWORD
) callconv(std.os.windows.WINAPI) i32;
// Unicode(-W): UTF-16LE のヌル終端バッファ([*c]const u16)を渡す。
proc CryptAcquireContextW(
    phProv: ptr uint,  # UINT_PTR* out
    szContainer: WideCString,  # LPCWSTR optional
    szProvider: WideCString,  # LPCWSTR optional
    dwProvType: uint32,  # DWORD
    dwFlags: uint32  # DWORD
): int32 {.importc: "CryptAcquireContextW", stdcall, dynlib: "ADVAPI32.dll".}
# Unicode(-W): WideCString は newWideCString("...") で生成。
pragma(lib, "advapi32");
extern(Windows)
int CryptAcquireContextW(
    size_t* phProv,   // UINT_PTR* out
    const(wchar)* szContainer,   // LPCWSTR optional
    const(wchar)* szProvider,   // LPCWSTR optional
    uint dwProvType,   // DWORD
    uint dwFlags   // DWORD
);
ccall((:CryptAcquireContextW, "ADVAPI32.dll"), stdcall, Int32,
      (Ptr{Csize_t}, Cwstring, Cwstring, UInt32, UInt32),
      phProv, szContainer, szProvider, dwProvType, dwFlags)
# phProv : UINT_PTR* out -> Ptr{Csize_t}
# szContainer : LPCWSTR optional -> Cwstring
# szProvider : LPCWSTR optional -> Cwstring
# dwProvType : DWORD -> UInt32
# dwFlags : DWORD -> UInt32
# stdcall は 32bit のみ意味を持つ(x64 では無視)。
# Unicode(-W): Cwstring には transcode(UInt16, "...") 等で UTF-16 を渡す。
local ffi = require("ffi")
ffi.cdef[[
int32_t CryptAcquireContextW(
    uintptr_t* phProv,
    const uint16_t* szContainer,
    const uint16_t* szProvider,
    uint32_t dwProvType,
    uint32_t dwFlags);
]]
local advapi32 = ffi.load("advapi32")
-- advapi32.CryptAcquireContextW(phProv, szContainer, szProvider, dwProvType, dwFlags)
-- phProv : UINT_PTR* out
-- szContainer : LPCWSTR optional
-- szProvider : LPCWSTR optional
-- dwProvType : DWORD
-- dwFlags : DWORD
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
-- Unicode(-W): uint16_t* には UTF-16LE のバッファ(ffi.new("uint16_t[?]", ...))を渡す。
const koffi = require('koffi');
const lib = koffi.load('ADVAPI32.dll');
const CryptAcquireContextW = lib.func('__stdcall', 'CryptAcquireContextW', 'int32_t', ['uintptr_t *', 'str16', 'str16', 'uint32_t', 'uint32_t']);
// CryptAcquireContextW(phProv, szContainer, szProvider, dwProvType, dwFlags)
// phProv : UINT_PTR* out -> 'uintptr_t *'
// szContainer : LPCWSTR optional -> 'str16'
// szProvider : LPCWSTR optional -> 'str16'
// dwProvType : DWORD -> 'uint32_t'
// dwFlags : DWORD -> 'uint32_t'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。
const lib = Deno.dlopen("ADVAPI32.dll", {
  CryptAcquireContextW: { parameters: ["pointer", "buffer", "buffer", "u32", "u32"], result: "i32" },
});
// lib.symbols.CryptAcquireContextW(phProv, szContainer, szProvider, dwProvType, dwFlags)
// phProv : UINT_PTR* out -> "pointer"
// szContainer : LPCWSTR optional -> "buffer"
// szProvider : LPCWSTR optional -> "buffer"
// dwProvType : DWORD -> "u32"
// dwFlags : DWORD -> "u32"
// 文字列は "buffer"。Unicode(-W) は new TextEncoder() ではなく UTF-16LE のバイト列(末尾に \x00\x00)を Uint8Array で渡す。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。
<?php
$ffi = FFI::cdef(<<<C
int32_t CryptAcquireContextW(
    size_t* phProv,
    const uint16_t* szContainer,
    const uint16_t* szProvider,
    uint32_t dwProvType,
    uint32_t dwFlags);
C, "ADVAPI32.dll");
// $ffi->CryptAcquireContextW(phProv, szContainer, szProvider, dwProvType, dwFlags);
// phProv : UINT_PTR* out
// szContainer : LPCWSTR optional
// szProvider : LPCWSTR optional
// dwProvType : DWORD
// dwFlags : DWORD
// 構造体/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, W32APIOptions.UNICODE_OPTIONS);
    boolean CryptAcquireContextW(
        LongByReference phProv,   // UINT_PTR* out
        WString szContainer,   // LPCWSTR optional
        WString szProvider,   // LPCWSTR optional
        int dwProvType,   // DWORD
        int dwFlags   // DWORD
    );
}
// Unicode(-W): WString(入力)/char[](出力)で UTF-16 をマーシャリング。
@[Link("advapi32")]
lib LibADVAPI32
  fun CryptAcquireContextW = CryptAcquireContextW(
    phProv : LibC::SizeT*,   # UINT_PTR* out
    szContainer : UInt16*,   # LPCWSTR optional
    szProvider : UInt16*,   # LPCWSTR optional
    dwProvType : UInt32,   # DWORD
    dwFlags : UInt32   # DWORD
  ) : Int32
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。
import 'dart:ffi';
import 'package:ffi/ffi.dart';

typedef CryptAcquireContextWNative = Int32 Function(Pointer<UintPtr>, Pointer<Utf16>, Pointer<Utf16>, Uint32, Uint32);
typedef CryptAcquireContextWDart = int Function(Pointer<UintPtr>, Pointer<Utf16>, Pointer<Utf16>, int, int);
final CryptAcquireContextW = DynamicLibrary.open('ADVAPI32.dll')
    .lookupFunction<CryptAcquireContextWNative, CryptAcquireContextWDart>('CryptAcquireContextW');
// phProv : UINT_PTR* out -> Pointer<UintPtr>
// szContainer : LPCWSTR optional -> Pointer<Utf16>
// szProvider : LPCWSTR optional -> Pointer<Utf16>
// dwProvType : DWORD -> Uint32
// dwFlags : DWORD -> Uint32
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。
{$mode objfpc}{$H+}
function CryptAcquireContextW(
  phProv: Pointer;   // UINT_PTR* out
  szContainer: PWideChar;   // LPCWSTR optional
  szProvider: PWideChar;   // LPCWSTR optional
  dwProvType: DWORD;   // DWORD
  dwFlags: DWORD   // DWORD
): BOOL; stdcall;
  external 'ADVAPI32.dll' name 'CryptAcquireContextW';
import Foreign
import Foreign.C.Types
import Foreign.C.String

foreign import stdcall safe "CryptAcquireContextW"
  c_CryptAcquireContextW :: Ptr CUIntPtr -> CWString -> CWString -> Word32 -> Word32 -> IO CInt
-- phProv : UINT_PTR* out -> Ptr CUIntPtr
-- szContainer : LPCWSTR optional -> CWString
-- szProvider : LPCWSTR optional -> CWString
-- dwProvType : DWORD -> Word32
-- dwFlags : DWORD -> Word32
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。
open Ctypes
open Foreign

let cryptacquirecontextw =
  foreign "CryptAcquireContextW"
    ((ptr size_t) @-> (ptr uint16_t) @-> (ptr uint16_t) @-> uint32_t @-> uint32_t @-> returning int32_t)
(* phProv : UINT_PTR* out -> (ptr size_t) *)
(* szContainer : LPCWSTR optional -> (ptr uint16_t) *)
(* szProvider : LPCWSTR optional -> (ptr uint16_t) *)
(* dwProvType : DWORD -> uint32_t *)
(* dwFlags : DWORD -> uint32_t *)
(* foreign は cdecl 前提。x64 Windows では WINAPI と一致。構造体は ctypes structure を定義のこと。 *)
(cffi:define-foreign-library advapi32 (t "ADVAPI32.dll"))
(cffi:use-foreign-library advapi32)

(cffi:defcfun ("CryptAcquireContextW" crypt-acquire-context-w :convention :stdcall) :int32
  (ph-prov :pointer)   ; UINT_PTR* out
  (sz-container (:string :encoding :utf-16le))   ; LPCWSTR optional
  (sz-provider (:string :encoding :utf-16le))   ; LPCWSTR optional
  (dw-prov-type :uint32)   ; DWORD
  (dw-flags :uint32))   ; DWORD
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $CryptAcquireContextW = Win32::API::More->new('ADVAPI32',
    'BOOL CryptAcquireContextW(LPVOID phProv, LPCWSTR szContainer, LPCWSTR szProvider, DWORD dwProvType, DWORD dwFlags)');
# my $ret = $CryptAcquireContextW->Call($phProv, $szContainer, $szProvider, $dwProvType, $dwFlags);
# phProv : UINT_PTR* out -> LPVOID
# szContainer : LPCWSTR optional -> LPCWSTR
# szProvider : LPCWSTR optional -> LPCWSTR
# dwProvType : DWORD -> DWORD
# dwFlags : DWORD -> DWORD
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。
# Unicode(-W): LPCWSTR/LPWSTR は Win32::API が UTF-16 変換を行う。

関連項目

文字セット違い
公式の関連項目