Win32 API 日本語リファレンス
ホームSystem.Threading › CreateProcessA

CreateProcessA

関数
新しいプロセスとそのプライマリスレッドを作成する(ANSI版)。
DLLKERNEL32.dll文字セットANSI (-A)呼出規約winapiSetLastErrorあり対応OSWindows XP 以降

シグネチャ

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

BOOL CreateProcessA(
    LPCSTR lpApplicationName,   // optional
    LPSTR lpCommandLine,   // optional
    SECURITY_ATTRIBUTES* lpProcessAttributes,   // optional
    SECURITY_ATTRIBUTES* lpThreadAttributes,   // optional
    BOOL bInheritHandles,
    PROCESS_CREATION_FLAGS dwCreationFlags,
    void* lpEnvironment,   // optional
    LPCSTR lpCurrentDirectory,   // optional
    STARTUPINFOA* lpStartupInfo,
    PROCESS_INFORMATION* lpProcessInformation
);

パラメーター

名前方向説明
lpApplicationNameLPCSTRinoptional

実行するモジュールの名前です。このモジュールは Windows ベースのアプリケーションでもかまいません。ローカルコンピューターに適切なサブシステムが存在する場合は、他の種類のモジュール(たとえば MS-DOS や OS/2)でもかまいません。

この文字列には、実行するモジュールのフルパスとファイル名を指定することも、部分的な名前を指定することもできます。部分的な名前の場合、関数は現在のドライブと現在のディレクトリを使用して指定を補完します。この関数は検索パスを使用しません。このパラメーターにはファイル名の拡張子を含める必要があります。既定の拡張子は想定されません。

lpApplicationName パラメーターは NULL にできます。その場合、モジュール名は lpCommandLine 文字列の中で空白で区切られた最初のトークンでなければなりません。空白を含む長いファイル名を使用する場合は、引用符で囲んだ文字列を使用してファイル名の終わりと引数の始まりを示してください。そうしないと、ファイル名があいまいになります。たとえば、文字列 "c:\program files\sub dir\program name" について考えます。この文字列は複数の方法で解釈できます。システムは次の順序で可能性を解釈しようとします。

  1. c:\program.exe
  2. c:\program files\sub.exe
  3. c:\program files\sub dir\program.exe
  4. c:\program files\sub dir\program name.exe

実行可能モジュールが 16 ビットアプリケーションの場合、lpApplicationNameNULL とし、lpCommandLine が指す文字列で実行可能モジュールとその引数を指定する必要があります。

バッチファイルを実行するには、コマンドインタープリターを起動する必要があります。lpApplicationName に cmd.exe を設定し、lpCommandLine に次の引数を設定します。/c に続けてバッチファイルの名前を指定します。

重要

MSRC エンジニアリングチームはこの方法を推奨していません。詳細については、MS14-019 – Fixing a binary hijacking via .cmd or .bat file を参照してください。

lpCommandLineLPSTRinoutoptional

実行するコマンドラインです。

この文字列の最大長は、Unicode の終端 null 文字を含めて 32,767 文字です。lpApplicationNameNULL の場合、lpCommandLine のモジュール名部分は MAX_PATH 文字に制限されます。

この関数の Unicode 版である CreateProcessW は、この文字列の内容を変更することがあります。そのため、このパラメーターは読み取り専用メモリ(const 変数やリテラル文字列など)へのポインターにすることはできません。このパラメーターが定数文字列の場合、関数がアクセス違反を引き起こすことがあります。

lpCommandLine パラメーターは NULL にできます。その場合、関数は lpApplicationName が指す文字列をコマンドラインとして使用します。

lpApplicationNamelpCommandLine の両方が NULL 以外の場合、lpApplicationName が指す null 終端文字列が実行するモジュールを指定し、lpCommandLine が指す null 終端文字列がコマンドラインを指定します。新しいプロセスは GetCommandLine を使用してコマンドライン全体を取得できます。C で記述されたコンソールプロセスは、argc および argv 引数を使用してコマンドラインを解析できます。argv[0] はモジュール名であるため、C のプログラマーは通常、モジュール名をコマンドラインの最初のトークンとして繰り返します。

lpApplicationName が NULL の場合、コマンドラインの空白で区切られた最初のトークンがモジュール名を指定します。空白を含む長いファイル名を使用する場合は、引用符で囲んだ文字列を使用してファイル名の終わりと引数の始まりを示してください(lpApplicationName パラメーターの説明を参照)。ファイル名に拡張子が含まれていない場合は、.exe が付加されます。したがって、ファイル名の拡張子が .com の場合、このパラメーターには .com 拡張子を含める必要があります。ファイル名が拡張子なしのピリオド(.)で終わる場合、またはファイル名にパスが含まれている場合は、.exe は付加されません。ファイル名にディレクトリパスが含まれていない場合、システムは次の順序で実行可能ファイルを検索します。

  • アプリケーションがロードされたディレクトリ。
  • 親プロセスの現在のディレクトリ。
  • 32 ビット Windows システムディレクトリ。このディレクトリのパスを取得するには、GetSystemDirectoryA 関数を使用します。
  • 16 ビット Windows システムディレクトリ。このディレクトリのパスを取得する関数はありませんが、このディレクトリも検索されます。このディレクトリの名前は System です。
  • Windows ディレクトリ。このディレクトリのパスを取得するには、GetWindowsDirectoryA 関数を使用します。
  • PATH 環境変数に列挙されているディレクトリ。この関数は、App Paths レジストリキーで指定されたアプリケーションごとのパスは検索しないことに注意してください。このアプリケーションごとのパスを検索シーケンスに含めるには、ShellExecute 関数を使用します。

システムは、ファイル名を引数から分離するために、コマンドライン文字列に終端 null 文字を追加します。これにより、内部処理のために元の文字列が 2 つの文字列に分割されます。

lpProcessAttributesSECURITY_ATTRIBUTES*inoptional

新しいプロセスオブジェクトに対して返されるハンドルを子プロセスが継承できるかどうかを決定する SECURITY_ATTRIBUTES 構造体へのポインターです。lpProcessAttributesNULL の場合、ハンドルは継承できません。

構造体の lpSecurityDescriptor メンバーは、新しいプロセスのセキュリティ記述子を指定します。lpProcessAttributes が NULL であるか lpSecurityDescriptorNULL の場合、プロセスには既定のセキュリティ記述子が割り当てられます。プロセスの既定のセキュリティ記述子内の ACL は、作成元のプライマリトークンに由来します。Windows XP: プロセスの既定のセキュリティ記述子内の ACL は、作成元のプライマリトークンまたは偽装トークンに由来します。この動作は Windows XP with SP2 および Windows Server 2003 で変更されました。

lpThreadAttributesSECURITY_ATTRIBUTES*inoptional新しいスレッドのセキュリティ記述子を指定し、返されるハンドルを子プロセスが継承できるかどうかを決定する SECURITY_ATTRIBUTES 構造体へのポインターです。lpThreadAttributes が NULL の場合、スレッドには既定のセキュリティ記述子が割り当てられ、ハンドルは継承できません。スレッドの既定のセキュリティ記述子内のアクセス制御リスト(ACL)は、作成元のプライマリトークンに由来します。
bInheritHandlesBOOLin

このパラメーターが TRUE の場合、呼び出し元プロセス内の継承可能な各ハンドルが新しいプロセスによって継承されます。パラメーターが FALSE の場合、ハンドルは継承されません。継承されたハンドルは、元のハンドルと同じ値とアクセス権を持つことに注意してください。 継承可能なハンドルに関する詳細な説明については、「解説」を参照してください。

ターミナルサービス: セッションをまたいでハンドルを継承することはできません。さらに、このパラメーターが TRUE の場合、呼び出し元と同じセッションでプロセスを作成する必要があります。

Protected Process Light (PPL) プロセス: 非 PPL プロセスから PPL プロセスへの PROCESS_DUP_HANDLE は許可されないため、PPL プロセスが非 PPL プロセスを作成する場合、汎用ハンドルの継承はブロックされます。プロセスのセキュリティとアクセス権を参照してください。

Windows 7: STD_INPUT_HANDLESTD_OUTPUT_HANDLESTD_ERROR_HANDLE は、パラメーターが FALSE の場合でも継承されます。

dwCreationFlagsPROCESS_CREATION_FLAGSin

優先度クラスとプロセスの作成を制御するフラグです。値の一覧については、Process Creation Flags を参照してください。

このパラメーターは、新しいプロセスの優先度クラスも制御します。優先度クラスは、プロセスのスレッドのスケジューリング優先度を決定するために使用されます。値の一覧については、GetPriorityClass を参照してください。優先度クラスフラグがいずれも指定されていない場合、作成元プロセスの優先度クラスが IDLE_PRIORITY_CLASS または BELOW_NORMAL_PRIORITY_CLASS でない限り、優先度クラスは既定で NORMAL_PRIORITY_CLASS になります。これらの場合、子プロセスは呼び出し元プロセスの既定の優先度クラスを受け取ります。

dwCreationFlags パラメーターの値が 0 の場合:

  • プロセスは呼び出し元のエラーモードと親のコンソールの両方を継承します。
  • 新しいプロセスの環境ブロックには ANSI 文字が含まれていると見なされます(詳細については lpEnvironment パラメーターを参照)。
  • 16 ビット Windows ベースのアプリケーションは、共有仮想 DOS マシン(VDM)で実行されます。
lpEnvironmentvoid*inoptional

新しいプロセスの環境ブロックへのポインターです。このパラメーターが NULL の場合、新しいプロセスは呼び出し元プロセスの環境を使用します。

環境ブロックは、null 終端文字列の null 終端ブロックで構成されます。各文字列は次の形式です。

name=value\0

等号は区切り文字として使用されるため、環境変数の名前には使用できません。

環境ブロックには Unicode 文字または ANSI 文字のいずれかを含めることができます。lpEnvironment が指す環境ブロックに Unicode 文字が含まれている場合は、dwCreationFlagsCREATE_UNICODE_ENVIRONMENT を含めるようにしてください。

この関数の ANSI 版である CreateProcessA は、プロセスの環境ブロックの合計サイズが 32,767 文字を超えると失敗します。

ANSI 環境ブロックは 2 つのゼロバイトで終端されることに注意してください。1 つは最後の文字列用、もう 1 つはブロックを終端するためのものです。Unicode 環境ブロックは 4 つのゼロバイトで終端されます。2 つは最後の文字列用、もう 2 つはブロックを終端するためのものです。

lpCurrentDirectoryLPCSTRinoptional

プロセスの現在のディレクトリのフルパスです。この文字列は UNC パスを指定することもできます。

このパラメーターが NULL の場合、新しいプロセスは呼び出し元プロセスと同じ現在のドライブとディレクトリを持ちます。(この機能は主に、アプリケーションを起動して初期ドライブと作業ディレクトリを指定する必要があるシェル向けに提供されています。)

lpStartupInfoSTARTUPINFOA*in

STARTUPINFO または STARTUPINFOEX 構造体へのポインターです。

拡張属性を設定するには、STARTUPINFOEX 構造体を使用し、dwCreationFlags パラメーターに EXTENDED_STARTUPINFO_PRESENT を指定します。

STARTUPINFO または STARTUPINFOEX 内のハンドルは、不要になったら CloseHandle で閉じる必要があります。

重要

呼び出し元は、STARTUPINFO の標準ハンドルフィールドに有効なハンドル値が含まれていることを保証する責任があります。これらのフィールドは、dwFlags メンバーが STARTF_USESTDHANDLES を指定している場合でも、検証されずに変更されないまま子プロセスにコピーされます。正しくない値は、子プロセスの誤動作やクラッシュを引き起こす可能性があります。無効なハンドルを検出するには、Application Verifier ランタイム検証ツールを使用してください。

lpProcessInformationPROCESS_INFORMATION*out

新しいプロセスに関する識別情報を受け取る PROCESS_INFORMATION 構造体へのポインターです。

PROCESS_INFORMATION 内のハンドルは、不要になったら CloseHandle で閉じる必要があります。

戻り値の型: BOOL

公式ドキュメント

新しいプロセスとそのプライマリスレッドを作成します。新しいプロセスは、呼び出し元プロセスのセキュリティコンテキストで実行されます。(ANSI)

戻り値

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

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

この関数は、プロセスの初期化が完了する前に戻ることに注意してください。必要な DLL が見つからないか初期化に失敗した場合、プロセスは終了します。プロセスの終了ステータスを取得するには、GetExitCodeProcess を呼び出します。

解説(Remarks)

プロセスにはプロセス識別子が割り当てられます。この識別子は、プロセスが終了するまで有効です。これはプロセスを識別するために使用でき、また OpenProcess 関数で指定してプロセスへのハンドルを開くこともできます。プロセス内の最初のスレッドにもスレッド識別子が割り当てられます。これは OpenThread 関数で指定してスレッドへのハンドルを開くことができます。この識別子はスレッドが終了するまで有効であり、システム内でスレッドを一意に識別するために使用できます。これらの識別子は PROCESS_INFORMATION 構造体で返されます。

オペレーティングシステムがプロセスに提供するコマンドライン内の実行可能ファイルの名前は、呼び出し元プロセスが CreateProcess 関数に与えるコマンドライン内のものと必ずしも同一ではありません。オペレーティングシステムは、完全修飾パスなしで提供された実行可能ファイル名に完全修飾パスを付加することがあります。

呼び出し元スレッドは、WaitForInputIdle 関数を使用して、新しいプロセスが初期化を完了し、保留中の入力がない状態でユーザー入力を待機するまで待つことができます。CreateProcess は新しいプロセスの初期化が完了するのを待たずに戻るため、これは親プロセスと子プロセス間の同期に役立ちます。たとえば、作成元プロセスは、新しいプロセスに関連付けられたウィンドウを探そうとする前に WaitForInputIdle を使用します。

プロセスをシャットダウンする推奨される方法は、ExitProcess 関数を使用することです。この関数は、プロセスにアタッチされているすべての DLL に終了が近づいていることの通知を送信するためです。プロセスをシャットダウンする他の方法では、アタッチされている DLL に通知されません。スレッドが ExitProcess を呼び出すと、プロセスの他のスレッドは追加のコード(アタッチされている DLL のスレッド終了コードを含む)を実行する機会なしに終了することに注意してください。詳細については、プロセスの終了を参照してください。

親プロセスは、プロセスの作成中に子プロセスの環境変数を直接変更できます。これは、プロセスが別のプロセスの環境設定を直接変更できる唯一の状況です。詳細については、環境変数の変更を参照してください。

アプリケーションが環境ブロックを提供する場合、システムドライブの現在のディレクトリ情報は新しいプロセスに自動的には伝播されません。たとえば、=C: という名前の環境変数があり、その値はドライブ C の現在のディレクトリです。アプリケーションは、現在のディレクトリ情報を新しいプロセスに手動で渡す必要があります。そのためには、アプリケーションはこれらの環境変数文字列を明示的に作成し、アルファベット順にソートして(システムはソート済みの環境を使用するため)、環境ブロックに格納する必要があります。通常、環境ブロックのソート順序により、これらは環境ブロックの先頭に配置されます。

ドライブ X の現在のディレクトリ情報を取得する 1 つの方法は、次の呼び出しを行うことです。GetFullPathName("X:", ...)。これにより、アプリケーションが環境ブロックをスキャンする必要がなくなります。返される完全パスが X:\ の場合、ルートディレクトリは新しいプロセスのドライブ X の既定の現在のディレクトリであるため、その値を環境データとして渡す必要はありません。

CREATE_NEW_PROCESS_GROUP を指定してプロセスを作成すると、新しいプロセスの代わりに SetConsoleCtrlHandler(NULL,TRUE) への暗黙の呼び出しが行われます。つまり、新しいプロセスでは CTRL+C が無効になります。これにより、シェルが CTRL+C を自身で処理し、そのシグナルをサブプロセスに選択的に渡すことができます。CTRL+BREAK は無効化されず、プロセスまたはプロセスグループを中断するために使用できます。

既定では、bInheritHandles パラメーターの値として TRUE を渡すと、継承可能なすべてのハンドルが新しいプロセスによって継承されます。これは、複数のスレッドから同時にプロセスを作成し、なおかつ各プロセスに異なるハンドルを継承させたいアプリケーションでは問題になることがあります。

アプリケーションは、UpdateProcThreadAttributeList 関数を PROC_THREAD_ATTRIBUTE_HANDLE_LIST パラメーターとともに使用して、特定のプロセスによって継承されるハンドルのリストを提供できます。

セキュリティに関する解説

最初のパラメーター lpApplicationNameNULL にできます。その場合、実行可能ファイル名は lpCommandLine が指す空白で区切られた文字列内になければなりません。実行可能ファイルまたはパス名に空白が含まれている場合、関数の空白の解析方法により、別の実行可能ファイルが実行されるリスクがあります。次の例は危険です。関数は "MyApp.exe" の代わりに、"Program.exe" が存在すればそれを実行しようとするためです。

    LPTSTR szCmdline = _tcsdup(TEXT("C:\\Program Files\\MyApp -L -S"));
    CreateProcess(NULL, szCmdline, /* ... */);

悪意のあるユーザーがシステム上に "Program.exe" というアプリケーションを作成した場合、Program Files ディレクトリを使用して CreateProcess を不正に呼び出すプログラムは、意図したアプリケーションの代わりにこのアプリケーションを実行します。

この問題を回避するには、lpApplicationNameNULL を渡さないでください。lpApplicationNameNULL を渡す場合は、次の例に示すように、lpCommandLine 内の実行可能ファイルのパスを引用符で囲んでください。

    LPTSTR szCmdline[] = _tcsdup(TEXT("\"C:\\Program Files\\MyApp\" -L -S"));
    CreateProcess(NULL, szCmdline, /*...*/);

例については、プロセスの作成を参照してください。

メモ

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

出典・ライセンス: 上記「公式ドキュメント」の内容は 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>

BOOL CreateProcessA(
    LPCSTR lpApplicationName,   // optional
    LPSTR lpCommandLine,   // optional
    SECURITY_ATTRIBUTES* lpProcessAttributes,   // optional
    SECURITY_ATTRIBUTES* lpThreadAttributes,   // optional
    BOOL bInheritHandles,
    PROCESS_CREATION_FLAGS dwCreationFlags,
    void* lpEnvironment,   // optional
    LPCSTR lpCurrentDirectory,   // optional
    STARTUPINFOA* lpStartupInfo,
    PROCESS_INFORMATION* lpProcessInformation
);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("KERNEL32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
static extern bool CreateProcessA(
    [MarshalAs(UnmanagedType.LPStr)] string lpApplicationName,   // LPCSTR optional
    [MarshalAs(UnmanagedType.LPStr)] System.Text.StringBuilder lpCommandLine,   // LPSTR optional, in/out
    IntPtr lpProcessAttributes,   // SECURITY_ATTRIBUTES* optional
    IntPtr lpThreadAttributes,   // SECURITY_ATTRIBUTES* optional
    bool bInheritHandles,   // BOOL
    uint dwCreationFlags,   // PROCESS_CREATION_FLAGS
    IntPtr lpEnvironment,   // void* optional
    [MarshalAs(UnmanagedType.LPStr)] string lpCurrentDirectory,   // LPCSTR optional
    IntPtr lpStartupInfo,   // STARTUPINFOA*
    IntPtr lpProcessInformation   // PROCESS_INFORMATION* out
);
<DllImport("KERNEL32.dll", CharSet:=CharSet.Ansi, SetLastError:=True, ExactSpelling:=True)>
Public Shared Function CreateProcessA(
    <MarshalAs(UnmanagedType.LPStr)> lpApplicationName As String,   ' LPCSTR optional
    <MarshalAs(UnmanagedType.LPStr)> lpCommandLine As System.Text.StringBuilder,   ' LPSTR optional, in/out
    lpProcessAttributes As IntPtr,   ' SECURITY_ATTRIBUTES* optional
    lpThreadAttributes As IntPtr,   ' SECURITY_ATTRIBUTES* optional
    bInheritHandles As Boolean,   ' BOOL
    dwCreationFlags As UInteger,   ' PROCESS_CREATION_FLAGS
    lpEnvironment As IntPtr,   ' void* optional
    <MarshalAs(UnmanagedType.LPStr)> lpCurrentDirectory As String,   ' LPCSTR optional
    lpStartupInfo As IntPtr,   ' STARTUPINFOA*
    lpProcessInformation As IntPtr   ' PROCESS_INFORMATION* out
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
' lpApplicationName : LPCSTR optional
' lpCommandLine : LPSTR optional, in/out
' lpProcessAttributes : SECURITY_ATTRIBUTES* optional
' lpThreadAttributes : SECURITY_ATTRIBUTES* optional
' bInheritHandles : BOOL
' dwCreationFlags : PROCESS_CREATION_FLAGS
' lpEnvironment : void* optional
' lpCurrentDirectory : LPCSTR optional
' lpStartupInfo : STARTUPINFOA*
' lpProcessInformation : PROCESS_INFORMATION* out
Declare PtrSafe Function CreateProcessA Lib "kernel32" ( _
    ByVal lpApplicationName As String, _
    ByVal lpCommandLine As String, _
    ByVal lpProcessAttributes As LongPtr, _
    ByVal lpThreadAttributes As LongPtr, _
    ByVal bInheritHandles As Long, _
    ByVal dwCreationFlags As Long, _
    ByVal lpEnvironment As LongPtr, _
    ByVal lpCurrentDirectory As String, _
    ByVal lpStartupInfo As LongPtr, _
    ByVal lpProcessInformation As LongPtr) As Long
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。
import ctypes
from ctypes import wintypes

CreateProcessA = ctypes.windll.kernel32.CreateProcessA
CreateProcessA.restype = wintypes.BOOL
CreateProcessA.argtypes = [
    wintypes.LPCSTR,  # lpApplicationName : LPCSTR optional
    wintypes.LPSTR,  # lpCommandLine : LPSTR optional, in/out
    ctypes.c_void_p,  # lpProcessAttributes : SECURITY_ATTRIBUTES* optional
    ctypes.c_void_p,  # lpThreadAttributes : SECURITY_ATTRIBUTES* optional
    wintypes.BOOL,  # bInheritHandles : BOOL
    wintypes.DWORD,  # dwCreationFlags : PROCESS_CREATION_FLAGS
    ctypes.POINTER(None),  # lpEnvironment : void* optional
    wintypes.LPCSTR,  # lpCurrentDirectory : LPCSTR optional
    ctypes.c_void_p,  # lpStartupInfo : STARTUPINFOA*
    ctypes.c_void_p,  # lpProcessInformation : PROCESS_INFORMATION* out
]
# GetLastError: use ctypes.GetLastError() (or ctypes.WinDLL(use_last_error=True))
require 'fiddle'
require 'fiddle/import'

lib = Fiddle.dlopen('KERNEL32.dll')
CreateProcessA = Fiddle::Function.new(
  lib['CreateProcessA'],
  [
    Fiddle::TYPE_VOIDP,  # lpApplicationName : LPCSTR optional
    Fiddle::TYPE_VOIDP,  # lpCommandLine : LPSTR optional, in/out
    Fiddle::TYPE_VOIDP,  # lpProcessAttributes : SECURITY_ATTRIBUTES* optional
    Fiddle::TYPE_VOIDP,  # lpThreadAttributes : SECURITY_ATTRIBUTES* optional
    Fiddle::TYPE_INT,  # bInheritHandles : BOOL
    -Fiddle::TYPE_INT,  # dwCreationFlags : PROCESS_CREATION_FLAGS
    Fiddle::TYPE_VOIDP,  # lpEnvironment : void* optional
    Fiddle::TYPE_VOIDP,  # lpCurrentDirectory : LPCSTR optional
    Fiddle::TYPE_VOIDP,  # lpStartupInfo : STARTUPINFOA*
    Fiddle::TYPE_VOIDP,  # lpProcessInformation : PROCESS_INFORMATION* out
  ],
  Fiddle::TYPE_INT)
#[link(name = "kernel32")]
extern "system" {
    fn CreateProcessA(
        lpApplicationName: *const u8,  // LPCSTR optional
        lpCommandLine: *mut u8,  // LPSTR optional, in/out
        lpProcessAttributes: *mut SECURITY_ATTRIBUTES,  // SECURITY_ATTRIBUTES* optional
        lpThreadAttributes: *mut SECURITY_ATTRIBUTES,  // SECURITY_ATTRIBUTES* optional
        bInheritHandles: i32,  // BOOL
        dwCreationFlags: u32,  // PROCESS_CREATION_FLAGS
        lpEnvironment: *mut (),  // void* optional
        lpCurrentDirectory: *const u8,  // LPCSTR optional
        lpStartupInfo: *mut STARTUPINFOA,  // STARTUPINFOA*
        lpProcessInformation: *mut PROCESS_INFORMATION  // PROCESS_INFORMATION* out
    ) -> i32;
}
// crates: windows-sys provides ready-made bindings for this API.
$sig = @"
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("KERNEL32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern bool CreateProcessA([MarshalAs(UnmanagedType.LPStr)] string lpApplicationName, [MarshalAs(UnmanagedType.LPStr)] System.Text.StringBuilder lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, [MarshalAs(UnmanagedType.LPStr)] string lpCurrentDirectory, IntPtr lpStartupInfo, IntPtr lpProcessInformation);
"@
$api = Add-Type -MemberDefinition $sig -Name 'KERNEL32_CreateProcessA' -Namespace Win32 -PassThru
# $api::CreateProcessA(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation)
#uselib "KERNEL32.dll"
#func global CreateProcessA "CreateProcessA" sptr, sptr, sptr, sptr, sptr, sptr, sptr, sptr, sptr, sptr
; CreateProcessA lpApplicationName, varptr(lpCommandLine), varptr(lpProcessAttributes), varptr(lpThreadAttributes), bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, varptr(lpStartupInfo), varptr(lpProcessInformation)   ; 戻り値は stat
; lpApplicationName : LPCSTR optional -> "sptr"
; lpCommandLine : LPSTR optional, in/out -> "sptr"
; lpProcessAttributes : SECURITY_ATTRIBUTES* optional -> "sptr"
; lpThreadAttributes : SECURITY_ATTRIBUTES* optional -> "sptr"
; bInheritHandles : BOOL -> "sptr"
; dwCreationFlags : PROCESS_CREATION_FLAGS -> "sptr"
; lpEnvironment : void* optional -> "sptr"
; lpCurrentDirectory : LPCSTR optional -> "sptr"
; lpStartupInfo : STARTUPINFOA* -> "sptr"
; lpProcessInformation : PROCESS_INFORMATION* out -> "sptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。
出力引数:
#uselib "KERNEL32.dll"
#cfunc global CreateProcessA "CreateProcessA" str, var, var, var, int, int, sptr, str, var, var
; res = CreateProcessA(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation)
; lpApplicationName : LPCSTR optional -> "str"
; lpCommandLine : LPSTR optional, in/out -> "var"
; lpProcessAttributes : SECURITY_ATTRIBUTES* optional -> "var"
; lpThreadAttributes : SECURITY_ATTRIBUTES* optional -> "var"
; bInheritHandles : BOOL -> "int"
; dwCreationFlags : PROCESS_CREATION_FLAGS -> "int"
; lpEnvironment : void* optional -> "sptr"
; lpCurrentDirectory : LPCSTR optional -> "str"
; lpStartupInfo : STARTUPINFOA* -> "var"
; lpProcessInformation : PROCESS_INFORMATION* out -> "var"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
出力引数:
; BOOL CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, SECURITY_ATTRIBUTES* lpProcessAttributes, SECURITY_ATTRIBUTES* lpThreadAttributes, BOOL bInheritHandles, PROCESS_CREATION_FLAGS dwCreationFlags, void* lpEnvironment, LPCSTR lpCurrentDirectory, STARTUPINFOA* lpStartupInfo, PROCESS_INFORMATION* lpProcessInformation)
#uselib "KERNEL32.dll"
#cfunc global CreateProcessA "CreateProcessA" str, var, var, var, int, int, intptr, str, var, var
; res = CreateProcessA(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation)
; lpApplicationName : LPCSTR optional -> "str"
; lpCommandLine : LPSTR optional, in/out -> "var"
; lpProcessAttributes : SECURITY_ATTRIBUTES* optional -> "var"
; lpThreadAttributes : SECURITY_ATTRIBUTES* optional -> "var"
; bInheritHandles : BOOL -> "int"
; dwCreationFlags : PROCESS_CREATION_FLAGS -> "int"
; lpEnvironment : void* optional -> "intptr"
; lpCurrentDirectory : LPCSTR optional -> "str"
; lpStartupInfo : STARTUPINFOA* -> "var"
; lpProcessInformation : PROCESS_INFORMATION* out -> "var"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
import (
	"golang.org/x/sys/windows"
	"unsafe"
)

var (
	kernel32 = windows.NewLazySystemDLL("KERNEL32.dll")
	procCreateProcessA = kernel32.NewProc("CreateProcessA")
)

// lpApplicationName (LPCSTR optional), lpCommandLine (LPSTR optional, in/out), lpProcessAttributes (SECURITY_ATTRIBUTES* optional), lpThreadAttributes (SECURITY_ATTRIBUTES* optional), bInheritHandles (BOOL), dwCreationFlags (PROCESS_CREATION_FLAGS), lpEnvironment (void* optional), lpCurrentDirectory (LPCSTR optional), lpStartupInfo (STARTUPINFOA*), lpProcessInformation (PROCESS_INFORMATION* out)
r1, _, err := procCreateProcessA.Call(
	uintptr(unsafe.Pointer(windows.BytePtrFromString(lpApplicationName))),
	uintptr(lpCommandLine),
	uintptr(lpProcessAttributes),
	uintptr(lpThreadAttributes),
	uintptr(bInheritHandles),
	uintptr(dwCreationFlags),
	uintptr(lpEnvironment),
	uintptr(unsafe.Pointer(windows.BytePtrFromString(lpCurrentDirectory))),
	uintptr(lpStartupInfo),
	uintptr(lpProcessInformation),
)
_ = err  // syscall.Errno (valid when the call sets last-error)
_ = r1   // BOOL
function CreateProcessA(
  lpApplicationName: PAnsiChar;   // LPCSTR optional
  lpCommandLine: PAnsiChar;   // LPSTR optional, in/out
  lpProcessAttributes: Pointer;   // SECURITY_ATTRIBUTES* optional
  lpThreadAttributes: Pointer;   // SECURITY_ATTRIBUTES* optional
  bInheritHandles: BOOL;   // BOOL
  dwCreationFlags: DWORD;   // PROCESS_CREATION_FLAGS
  lpEnvironment: Pointer;   // void* optional
  lpCurrentDirectory: PAnsiChar;   // LPCSTR optional
  lpStartupInfo: Pointer;   // STARTUPINFOA*
  lpProcessInformation: Pointer   // PROCESS_INFORMATION* out
): BOOL; stdcall;
  external 'KERNEL32.dll' name 'CreateProcessA';
result := DllCall("KERNEL32\CreateProcessA"
    , "AStr", lpApplicationName   ; LPCSTR optional
    , "Ptr", lpCommandLine   ; LPSTR optional, in/out
    , "Ptr", lpProcessAttributes   ; SECURITY_ATTRIBUTES* optional
    , "Ptr", lpThreadAttributes   ; SECURITY_ATTRIBUTES* optional
    , "Int", bInheritHandles   ; BOOL
    , "UInt", dwCreationFlags   ; PROCESS_CREATION_FLAGS
    , "Ptr", lpEnvironment   ; void* optional
    , "AStr", lpCurrentDirectory   ; LPCSTR optional
    , "Ptr", lpStartupInfo   ; STARTUPINFOA*
    , "Ptr", lpProcessInformation   ; PROCESS_INFORMATION* out
    , "Int")   ; return: BOOL
●CreateProcessA(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation) = DLL("KERNEL32.dll", "bool CreateProcessA(char*, char*, void*, void*, bool, dword, void*, char*, void*, void*)")
# 呼び出し: CreateProcessA(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation)
# lpApplicationName : LPCSTR optional -> "char*"
# lpCommandLine : LPSTR optional, in/out -> "char*"
# lpProcessAttributes : SECURITY_ATTRIBUTES* optional -> "void*"
# lpThreadAttributes : SECURITY_ATTRIBUTES* optional -> "void*"
# bInheritHandles : BOOL -> "bool"
# dwCreationFlags : PROCESS_CREATION_FLAGS -> "dword"
# lpEnvironment : void* optional -> "void*"
# lpCurrentDirectory : LPCSTR optional -> "char*"
# lpStartupInfo : STARTUPINFOA* -> "void*"
# lpProcessInformation : PROCESS_INFORMATION* out -> "void*"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。
const std = @import("std");

extern "kernel32" fn CreateProcessA(
    lpApplicationName: [*c]const u8, // LPCSTR optional
    lpCommandLine: [*c]u8, // LPSTR optional, in/out
    lpProcessAttributes: [*c]SECURITY_ATTRIBUTES, // SECURITY_ATTRIBUTES* optional
    lpThreadAttributes: [*c]SECURITY_ATTRIBUTES, // SECURITY_ATTRIBUTES* optional
    bInheritHandles: i32, // BOOL
    dwCreationFlags: u32, // PROCESS_CREATION_FLAGS
    lpEnvironment: ?*anyopaque, // void* optional
    lpCurrentDirectory: [*c]const u8, // LPCSTR optional
    lpStartupInfo: [*c]STARTUPINFOA, // STARTUPINFOA*
    lpProcessInformation: [*c]PROCESS_INFORMATION // PROCESS_INFORMATION* out
) callconv(std.os.windows.WINAPI) i32;
proc CreateProcessA(
    lpApplicationName: cstring,  # LPCSTR optional
    lpCommandLine: ptr char,  # LPSTR optional, in/out
    lpProcessAttributes: ptr SECURITY_ATTRIBUTES,  # SECURITY_ATTRIBUTES* optional
    lpThreadAttributes: ptr SECURITY_ATTRIBUTES,  # SECURITY_ATTRIBUTES* optional
    bInheritHandles: int32,  # BOOL
    dwCreationFlags: uint32,  # PROCESS_CREATION_FLAGS
    lpEnvironment: pointer,  # void* optional
    lpCurrentDirectory: cstring,  # LPCSTR optional
    lpStartupInfo: ptr STARTUPINFOA,  # STARTUPINFOA*
    lpProcessInformation: ptr PROCESS_INFORMATION  # PROCESS_INFORMATION* out
): int32 {.importc: "CreateProcessA", stdcall, dynlib: "KERNEL32.dll".}
pragma(lib, "kernel32");
extern(Windows)
int CreateProcessA(
    const(char)* lpApplicationName,   // LPCSTR optional
    char* lpCommandLine,   // LPSTR optional, in/out
    SECURITY_ATTRIBUTES* lpProcessAttributes,   // SECURITY_ATTRIBUTES* optional
    SECURITY_ATTRIBUTES* lpThreadAttributes,   // SECURITY_ATTRIBUTES* optional
    int bInheritHandles,   // BOOL
    uint dwCreationFlags,   // PROCESS_CREATION_FLAGS
    void* lpEnvironment,   // void* optional
    const(char)* lpCurrentDirectory,   // LPCSTR optional
    STARTUPINFOA* lpStartupInfo,   // STARTUPINFOA*
    PROCESS_INFORMATION* lpProcessInformation   // PROCESS_INFORMATION* out
);
ccall((:CreateProcessA, "KERNEL32.dll"), stdcall, Int32,
      (Cstring, Ptr{UInt8}, Ptr{SECURITY_ATTRIBUTES}, Ptr{SECURITY_ATTRIBUTES}, Int32, UInt32, Ptr{Cvoid}, Cstring, Ptr{STARTUPINFOA}, Ptr{PROCESS_INFORMATION}),
      lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation)
# lpApplicationName : LPCSTR optional -> Cstring
# lpCommandLine : LPSTR optional, in/out -> Ptr{UInt8}
# lpProcessAttributes : SECURITY_ATTRIBUTES* optional -> Ptr{SECURITY_ATTRIBUTES}
# lpThreadAttributes : SECURITY_ATTRIBUTES* optional -> Ptr{SECURITY_ATTRIBUTES}
# bInheritHandles : BOOL -> Int32
# dwCreationFlags : PROCESS_CREATION_FLAGS -> UInt32
# lpEnvironment : void* optional -> Ptr{Cvoid}
# lpCurrentDirectory : LPCSTR optional -> Cstring
# lpStartupInfo : STARTUPINFOA* -> Ptr{STARTUPINFOA}
# lpProcessInformation : PROCESS_INFORMATION* out -> Ptr{PROCESS_INFORMATION}
# stdcall は 32bit のみ意味を持つ(x64 では無視)。
local ffi = require("ffi")
ffi.cdef[[
int32_t CreateProcessA(
    const char* lpApplicationName,
    char* lpCommandLine,
    void* lpProcessAttributes,
    void* lpThreadAttributes,
    int32_t bInheritHandles,
    uint32_t dwCreationFlags,
    void* lpEnvironment,
    const char* lpCurrentDirectory,
    void* lpStartupInfo,
    void* lpProcessInformation);
]]
local kernel32 = ffi.load("kernel32")
-- kernel32.CreateProcessA(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation)
-- lpApplicationName : LPCSTR optional
-- lpCommandLine : LPSTR optional, in/out
-- lpProcessAttributes : SECURITY_ATTRIBUTES* optional
-- lpThreadAttributes : SECURITY_ATTRIBUTES* optional
-- bInheritHandles : BOOL
-- dwCreationFlags : PROCESS_CREATION_FLAGS
-- lpEnvironment : void* optional
-- lpCurrentDirectory : LPCSTR optional
-- lpStartupInfo : STARTUPINFOA*
-- lpProcessInformation : PROCESS_INFORMATION* out
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
const koffi = require('koffi');
const lib = koffi.load('KERNEL32.dll');
const CreateProcessA = lib.func('__stdcall', 'CreateProcessA', 'int32_t', ['str', 'char *', 'void *', 'void *', 'int32_t', 'uint32_t', 'void *', 'str', 'void *', 'void *']);
// CreateProcessA(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation)
// lpApplicationName : LPCSTR optional -> 'str'
// lpCommandLine : LPSTR optional, in/out -> 'char *'
// lpProcessAttributes : SECURITY_ATTRIBUTES* optional -> 'void *'
// lpThreadAttributes : SECURITY_ATTRIBUTES* optional -> 'void *'
// bInheritHandles : BOOL -> 'int32_t'
// dwCreationFlags : PROCESS_CREATION_FLAGS -> 'uint32_t'
// lpEnvironment : void* optional -> 'void *'
// lpCurrentDirectory : LPCSTR optional -> 'str'
// lpStartupInfo : STARTUPINFOA* -> 'void *'
// lpProcessInformation : PROCESS_INFORMATION* out -> 'void *'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。
const lib = Deno.dlopen("KERNEL32.dll", {
  CreateProcessA: { parameters: ["buffer", "buffer", "pointer", "pointer", "i32", "u32", "pointer", "buffer", "pointer", "pointer"], result: "i32" },
});
// lib.symbols.CreateProcessA(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation)
// lpApplicationName : LPCSTR optional -> "buffer"
// lpCommandLine : LPSTR optional, in/out -> "buffer"
// lpProcessAttributes : SECURITY_ATTRIBUTES* optional -> "pointer"
// lpThreadAttributes : SECURITY_ATTRIBUTES* optional -> "pointer"
// bInheritHandles : BOOL -> "i32"
// dwCreationFlags : PROCESS_CREATION_FLAGS -> "u32"
// lpEnvironment : void* optional -> "pointer"
// lpCurrentDirectory : LPCSTR optional -> "buffer"
// lpStartupInfo : STARTUPINFOA* -> "pointer"
// lpProcessInformation : PROCESS_INFORMATION* out -> "pointer"
// 文字列は "buffer"。ANSI(-A) は new TextEncoder() で UTF-8/ANSI バイト列(末尾に \x00)を渡す。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。
<?php
$ffi = FFI::cdef(<<<C
int32_t CreateProcessA(
    const char* lpApplicationName,
    char* lpCommandLine,
    void* lpProcessAttributes,
    void* lpThreadAttributes,
    int32_t bInheritHandles,
    uint32_t dwCreationFlags,
    void* lpEnvironment,
    const char* lpCurrentDirectory,
    void* lpStartupInfo,
    void* lpProcessInformation);
C, "KERNEL32.dll");
// $ffi->CreateProcessA(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation);
// lpApplicationName : LPCSTR optional
// lpCommandLine : LPSTR optional, in/out
// lpProcessAttributes : SECURITY_ATTRIBUTES* optional
// lpThreadAttributes : SECURITY_ATTRIBUTES* optional
// bInheritHandles : BOOL
// dwCreationFlags : PROCESS_CREATION_FLAGS
// lpEnvironment : void* optional
// lpCurrentDirectory : LPCSTR optional
// lpStartupInfo : STARTUPINFOA*
// lpProcessInformation : PROCESS_INFORMATION* out
// 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
// WINAPI(stdcall): x64 では呼出規約が統一されるため問題なし。x86 では __stdcall 対応のラッパが必要な場合あり。
import com.sun.jna.*;
import com.sun.jna.ptr.*;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;

public interface Kernel32 extends StdCallLibrary {
    Kernel32 INSTANCE = Native.load("kernel32", Kernel32.class, W32APIOptions.ASCII_OPTIONS);
    boolean CreateProcessA(
        String lpApplicationName,   // LPCSTR optional
        byte[] lpCommandLine,   // LPSTR optional, in/out
        Pointer lpProcessAttributes,   // SECURITY_ATTRIBUTES* optional
        Pointer lpThreadAttributes,   // SECURITY_ATTRIBUTES* optional
        boolean bInheritHandles,   // BOOL
        int dwCreationFlags,   // PROCESS_CREATION_FLAGS
        Pointer lpEnvironment,   // void* optional
        String lpCurrentDirectory,   // LPCSTR optional
        Pointer lpStartupInfo,   // STARTUPINFOA*
        Pointer lpProcessInformation   // PROCESS_INFORMATION* out
    );
}
@[Link("kernel32")]
lib LibKERNEL32
  fun CreateProcessA = CreateProcessA(
    lpApplicationName : UInt8*,   # LPCSTR optional
    lpCommandLine : UInt8*,   # LPSTR optional, in/out
    lpProcessAttributes : SECURITY_ATTRIBUTES*,   # SECURITY_ATTRIBUTES* optional
    lpThreadAttributes : SECURITY_ATTRIBUTES*,   # SECURITY_ATTRIBUTES* optional
    bInheritHandles : Int32,   # BOOL
    dwCreationFlags : UInt32,   # PROCESS_CREATION_FLAGS
    lpEnvironment : Void*,   # void* optional
    lpCurrentDirectory : UInt8*,   # LPCSTR optional
    lpStartupInfo : STARTUPINFOA*,   # STARTUPINFOA*
    lpProcessInformation : PROCESS_INFORMATION*   # PROCESS_INFORMATION* out
  ) : Int32
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。
import 'dart:ffi';
import 'package:ffi/ffi.dart';

typedef CreateProcessANative = Int32 Function(Pointer<Utf8>, Pointer<Utf8>, Pointer<Void>, Pointer<Void>, Int32, Uint32, Pointer<Void>, Pointer<Utf8>, Pointer<Void>, Pointer<Void>);
typedef CreateProcessADart = int Function(Pointer<Utf8>, Pointer<Utf8>, Pointer<Void>, Pointer<Void>, int, int, Pointer<Void>, Pointer<Utf8>, Pointer<Void>, Pointer<Void>);
final CreateProcessA = DynamicLibrary.open('KERNEL32.dll')
    .lookupFunction<CreateProcessANative, CreateProcessADart>('CreateProcessA');
// lpApplicationName : LPCSTR optional -> Pointer<Utf8>
// lpCommandLine : LPSTR optional, in/out -> Pointer<Utf8>
// lpProcessAttributes : SECURITY_ATTRIBUTES* optional -> Pointer<Void>
// lpThreadAttributes : SECURITY_ATTRIBUTES* optional -> Pointer<Void>
// bInheritHandles : BOOL -> Int32
// dwCreationFlags : PROCESS_CREATION_FLAGS -> Uint32
// lpEnvironment : void* optional -> Pointer<Void>
// lpCurrentDirectory : LPCSTR optional -> Pointer<Utf8>
// lpStartupInfo : STARTUPINFOA* -> Pointer<Void>
// lpProcessInformation : PROCESS_INFORMATION* out -> Pointer<Void>
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。
{$mode objfpc}{$H+}
function CreateProcessA(
  lpApplicationName: PAnsiChar;   // LPCSTR optional
  lpCommandLine: PAnsiChar;   // LPSTR optional, in/out
  lpProcessAttributes: Pointer;   // SECURITY_ATTRIBUTES* optional
  lpThreadAttributes: Pointer;   // SECURITY_ATTRIBUTES* optional
  bInheritHandles: BOOL;   // BOOL
  dwCreationFlags: DWORD;   // PROCESS_CREATION_FLAGS
  lpEnvironment: Pointer;   // void* optional
  lpCurrentDirectory: PAnsiChar;   // LPCSTR optional
  lpStartupInfo: Pointer;   // STARTUPINFOA*
  lpProcessInformation: Pointer   // PROCESS_INFORMATION* out
): BOOL; stdcall;
  external 'KERNEL32.dll' name 'CreateProcessA';
import Foreign
import Foreign.C.Types
import Foreign.C.String

foreign import stdcall safe "CreateProcessA"
  c_CreateProcessA :: CString -> CString -> Ptr () -> Ptr () -> CInt -> Word32 -> Ptr () -> CString -> Ptr () -> Ptr () -> IO CInt
-- lpApplicationName : LPCSTR optional -> CString
-- lpCommandLine : LPSTR optional, in/out -> CString
-- lpProcessAttributes : SECURITY_ATTRIBUTES* optional -> Ptr ()
-- lpThreadAttributes : SECURITY_ATTRIBUTES* optional -> Ptr ()
-- bInheritHandles : BOOL -> CInt
-- dwCreationFlags : PROCESS_CREATION_FLAGS -> Word32
-- lpEnvironment : void* optional -> Ptr ()
-- lpCurrentDirectory : LPCSTR optional -> CString
-- lpStartupInfo : STARTUPINFOA* -> Ptr ()
-- lpProcessInformation : PROCESS_INFORMATION* out -> Ptr ()
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。
open Ctypes
open Foreign

let createprocessa =
  foreign "CreateProcessA"
    (string @-> string @-> (ptr void) @-> (ptr void) @-> int32_t @-> uint32_t @-> (ptr void) @-> string @-> (ptr void) @-> (ptr void) @-> returning int32_t)
(* lpApplicationName : LPCSTR optional -> string *)
(* lpCommandLine : LPSTR optional, in/out -> string *)
(* lpProcessAttributes : SECURITY_ATTRIBUTES* optional -> (ptr void) *)
(* lpThreadAttributes : SECURITY_ATTRIBUTES* optional -> (ptr void) *)
(* bInheritHandles : BOOL -> int32_t *)
(* dwCreationFlags : PROCESS_CREATION_FLAGS -> uint32_t *)
(* lpEnvironment : void* optional -> (ptr void) *)
(* lpCurrentDirectory : LPCSTR optional -> string *)
(* lpStartupInfo : STARTUPINFOA* -> (ptr void) *)
(* lpProcessInformation : PROCESS_INFORMATION* out -> (ptr void) *)
(* foreign は cdecl 前提。x64 Windows では WINAPI と一致。構造体は ctypes structure を定義のこと。 *)
(cffi:define-foreign-library kernel32 (t "KERNEL32.dll"))
(cffi:use-foreign-library kernel32)

(cffi:defcfun ("CreateProcessA" create-process-a :convention :stdcall) :int32
  (lp-application-name :string)   ; LPCSTR optional
  (lp-command-line :pointer)   ; LPSTR optional, in/out
  (lp-process-attributes :pointer)   ; SECURITY_ATTRIBUTES* optional
  (lp-thread-attributes :pointer)   ; SECURITY_ATTRIBUTES* optional
  (b-inherit-handles :int32)   ; BOOL
  (dw-creation-flags :uint32)   ; PROCESS_CREATION_FLAGS
  (lp-environment :pointer)   ; void* optional
  (lp-current-directory :string)   ; LPCSTR optional
  (lp-startup-info :pointer)   ; STARTUPINFOA*
  (lp-process-information :pointer))   ; PROCESS_INFORMATION* out
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $CreateProcessA = Win32::API::More->new('KERNEL32',
    'BOOL CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPVOID lpProcessAttributes, LPVOID lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPVOID lpStartupInfo, LPVOID lpProcessInformation)');
# my $ret = $CreateProcessA->Call($lpApplicationName, $lpCommandLine, $lpProcessAttributes, $lpThreadAttributes, $bInheritHandles, $dwCreationFlags, $lpEnvironment, $lpCurrentDirectory, $lpStartupInfo, $lpProcessInformation);
# lpApplicationName : LPCSTR optional -> LPCSTR
# lpCommandLine : LPSTR optional, in/out -> LPSTR
# lpProcessAttributes : SECURITY_ATTRIBUTES* optional -> LPVOID
# lpThreadAttributes : SECURITY_ATTRIBUTES* optional -> LPVOID
# bInheritHandles : BOOL -> BOOL
# dwCreationFlags : PROCESS_CREATION_FLAGS -> DWORD
# lpEnvironment : void* optional -> LPVOID
# lpCurrentDirectory : LPCSTR optional -> LPCSTR
# lpStartupInfo : STARTUPINFOA* -> LPVOID
# lpProcessInformation : PROCESS_INFORMATION* out -> LPVOID
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。

関連項目

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