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

CreateProcessWithLogonW

関数
指定のユーザー資格情報でログオンして新しいプロセスを作成する。
DLLADVAPI32.dll呼出規約winapiSetLastErrorあり対応OSWindows XP 以降

シグネチャ

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

BOOL CreateProcessWithLogonW(
    LPCWSTR lpUsername,
    LPCWSTR lpDomain,   // optional
    LPCWSTR lpPassword,
    CREATE_PROCESS_LOGON_FLAGS dwLogonFlags,
    LPCWSTR lpApplicationName,   // optional
    LPWSTR lpCommandLine,   // optional
    PROCESS_CREATION_FLAGS dwCreationFlags,
    void* lpEnvironment,   // optional
    LPCWSTR lpCurrentDirectory,   // optional
    STARTUPINFOW* lpStartupInfo,
    PROCESS_INFORMATION* lpProcessInformation
);

パラメーター

名前方向説明
lpUsernameLPCWSTRin

ユーザーの名前。これはログオンするユーザーアカウントの名前です。UPN 形式 user@DNS_domain_name を使用する場合、lpDomain パラメーターは NULL でなければなりません。

ユーザーアカウントは、ローカルコンピューター上で「ローカル ログオン」権限を持っている必要があります。この権限は、ワークステーションおよびサーバーではすべてのユーザーに付与されますが、ドメインコントローラーでは管理者のみに付与されます。

lpDomainLPCWSTRinoptionallpUsername アカウントを含むアカウントデータベースを持つドメインまたはサーバーの名前。このパラメーターが NULL の場合、ユーザー名は UPN 形式で指定する必要があります。
lpPasswordLPCWSTRinlpUsername アカウントの平文パスワード。
dwLogonFlagsCREATE_PROCESS_LOGON_FLAGSin

ログオンオプション。このパラメーターには 0(ゼロ)または次のいずれかの値を指定できます。

意味
LOGON_WITH_PROFILE
0x00000001
ログオンした後、HKEY_USERS レジストリキーにユーザープロファイルを読み込みます。関数はプロファイルが読み込まれた後に戻ります。プロファイルの読み込みには時間がかかる場合があるため、HKEY_CURRENT_USER レジストリキー内の情報にアクセスする必要がある場合にのみこの値を使用することをお勧めします。

Windows Server 2003: プロファイルは、子プロセスを作成したかどうかにかかわらず、新しいプロセスが終了した後にアンロードされます。

Windows XP: プロファイルは、新しいプロセスと、それが作成したすべての子プロセスが終了した後にアンロードされます。

LOGON_NETCREDENTIALS_ONLY
0x00000002
ログオンしますが、指定された資格情報をネットワーク上でのみ使用します。新しいプロセスは呼び出し元と同じトークンを使用しますが、システムは LSA 内に新しいログオンセッションを作成し、プロセスは指定された資格情報を既定の資格情報として使用します。

この値は、ローカルとリモートで異なる資格情報セットを使用するプロセスを作成するために使用できます。これは、信頼関係が存在しないドメイン間のシナリオで役立ちます。

システムは指定された資格情報を検証しません。したがって、プロセスは起動できますが、ネットワークリソースにアクセスできない場合があります。

lpApplicationNameLPCWSTRinoptional

実行するモジュールの名前。このモジュールは Windows ベースのアプリケーションにできます。ローカルコンピューターで適切なサブシステムが利用可能であれば、他の種類のモジュール(例えば MS-DOS や OS/2)にすることもできます。

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

lpApplicationName パラメーターは NULL にすることができ、その場合モジュール名は lpCommandLine 文字列の最初の空白区切りトークンでなければなりません。スペースを含む長いファイル名を使用する場合は、引用符付き文字列を使用してファイル名の終わりと引数の始まりを示してください。そうしないとファイル名があいまいになります。

たとえば、次の文字列はさまざまに解釈される可能性があります。

"c:\program files\sub dir\program name"

システムは次の順序で各候補を解釈しようとします。

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

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

lpCommandLineLPWSTRinoutoptional

実行するコマンドライン。この文字列の最大長は 1024 文字です。lpApplicationNameNULL の場合、lpCommandLine のモジュール名部分は MAX_PATH 文字に制限されます。

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

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

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

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

  1. アプリケーションが読み込まれたディレクトリ。
  2. 親プロセスの現在のディレクトリ。
  3. 32 ビット Windows システムディレクトリ。このディレクトリのパスを取得するには GetSystemDirectory 関数を使用します。
  4. 16 ビット Windows システムディレクトリ。このディレクトリのパスを取得する関数はありませんが、検索対象になります。
  5. Windows ディレクトリ。このディレクトリのパスを取得するには GetWindowsDirectory 関数を使用します。
  6. PATH 環境変数に列挙されているディレクトリ。この関数は、App Paths レジストリキーで指定されたアプリケーションごとのパスは検索しないことに注意してください。このアプリケーションごとのパスを検索シーケンスに含めるには、ShellExecute 関数を使用します。
システムは、ファイル名を引数から分離するために、コマンドライン文字列に null 文字を追加します。これにより、内部処理のために元の文字列が 2 つの文字列に分割されます。
dwCreationFlagsPROCESS_CREATION_FLAGSin

プロセスの作成方法を制御するフラグ。CREATE_DEFAULT_ERROR_MODECREATE_NEW_CONSOLECREATE_NEW_PROCESS_GROUP の各フラグは既定で有効になっています。値の一覧については、Process Creation Flags を参照してください。

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

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

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

新しいプロセスの環境ブロックへのポインター。このパラメーターが NULL の場合、新しいプロセスは lpUsername で指定されたユーザーのプロファイルから作成された環境を使用します。

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

name=value

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

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

ANSI 環境ブロックは 2 つの 0(ゼロ)バイトで終端されます。1 つは最後の文字列用、もう 1 つはブロックを終端するためのものです。Unicode 環境ブロックは 4 つのゼロバイトで終端されます。2 つは最後の文字列用、もう 2 つはブロックを終端するためのものです。

特定のユーザーの環境ブロックのコピーを取得するには、 CreateEnvironmentBlock 関数を使用します。

lpCurrentDirectoryLPCWSTRinoptional

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

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

lpStartupInfoSTARTUPINFOW*in

STARTUPINFO 構造体へのポインター。

アプリケーションは、WinSta0\Default であっても、指定されたウィンドウステーションおよびデスクトップに対して、指定されたユーザーアカウントの権限を追加する必要があります。

lpDesktop メンバーが NULL または空の文字列の場合、新しいプロセスは親プロセスのデスクトップとウィンドウステーションを継承します。 アプリケーションは、継承されたウィンドウステーションおよびデスクトップに対して、指定されたユーザーアカウントの権限を追加する必要があります。

Windows XP: CreateProcessWithLogonW は、継承されたウィンドウステーションおよびデスクトップに対して、指定されたユーザーアカウントの権限を追加します。

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

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

新しいプロセスの識別情報(プロセスへのハンドルを含む)を受け取る PROCESS_INFORMATION 構造体へのポインター。

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

戻り値の型: BOOL

公式ドキュメント

新しいプロセスとそのプライマリスレッドを作成します。作成された新しいプロセスは、指定された資格情報(ユーザー、ドメイン、パスワード)のセキュリティコンテキストで、指定された実行可能ファイルを実行します。オプションで、指定されたユーザーのユーザープロファイルを読み込むこともできます。

戻り値

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

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

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

解説(Remarks)

既定では、 CreateProcessWithLogonW は指定されたユーザープロファイルを HKEY_USERS レジストリキーに読み込みません。つまり、HKEY_CURRENT_USER レジストリキー内の情報へのアクセスは、通常の対話型ログオンと一致する結果を生成しない可能性があります。CreateProcessWithLogonW を呼び出す前に、LOGON_WITH_PROFILE を使用するか、 LoadUserProfile 関数を呼び出して、ユーザーレジストリハイブを HKEY_USERS に読み込むのは、ご自身の責任です。

lpEnvironment パラメーターが NULL の場合、新しいプロセスは lpUserName で指定されたユーザーのプロファイルから作成された環境ブロックを使用します。HOMEDRIVE および HOMEPATH 変数が設定されていない場合、CreateProcessWithLogonW は、ユーザーの作業ディレクトリのドライブとパスを使用するように環境ブロックを変更します。

作成されると、新しいプロセスおよびスレッドのハンドルはフルアクセス権(PROCESS_ALL_ACCESS および THREAD_ALL_ACCESS)を受け取ります。いずれのハンドルについても、セキュリティ記述子が提供されていない場合、そのハンドルはその種類のオブジェクトハンドルを必要とする任意の関数で使用できます。セキュリティ記述子が提供されている場合、ハンドルの以降のすべての使用について、アクセスが許可される前にアクセスチェックが実行されます。アクセスが拒否された場合、要求元プロセスはそのハンドルを使用してプロセスまたはスレッドへのアクセスを得ることができません。

セキュリティトークンを取得するには、 PROCESS_INFORMATION 構造体内のプロセスハンドルを OpenProcessToken 関数に渡します。

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

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

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

CreateProcessWithLogonW は、指定されたディレクトリと実行可能イメージに、ターゲットユーザーのセキュリティコンテキストでアクセスします。実行可能イメージがネットワーク上にあり、パスにネットワークドライブ文字が指定されている場合、ネットワークドライブ文字はログオンごとに割り当てられる可能性があるため、ターゲットユーザーは利用できません。ネットワークドライブ文字が指定されている場合、この関数は失敗します。実行可能イメージがネットワーク上にある場合は、UNC パスを使用してください。

この関数で作成して同時に実行できる子プロセスの数には制限があります。たとえば Windows XP では、この制限は MAXIMUM_WAIT_OBJECTS*4 です。ただし、システム全体のクォータ制限により、これほど多くのプロセスを作成できない場合があります。

Windows XP with SP2、Windows Server 2003 以降: 「LocalSystem」アカウントで実行されているプロセスから CreateProcessWithLogonW を呼び出すことはできません。この関数は呼び出し元トークン内のログオン SID を使用しますが、「LocalSystem」アカウントのトークンにはこの SID が含まれていないためです。代替手段として、CreateProcessAsUser および LogonUser 関数を使用してください。

この関数を使用するアプリケーションをコンパイルするには、_WIN32_WINNT を 0x0500 以降として定義します。詳細については、 Using the Windows Headers を参照してください。

セキュリティに関する注意

lpApplicationName パラメーターは NULL にすることができ、その場合実行可能ファイル名は lpCommandLine 内の最初の空白区切り文字列でなければなりません。実行可能ファイル名またはパス名にスペースが含まれている場合、関数がスペースを解析する方法が原因で、別の実行可能ファイルが実行されるリスクがあります。次の例は避けてください。「MyApp.exe」の代わりに「Program.exe」が存在すればそれを実行しようとするためです。
LPTSTR szCmdline[]=_tcsdup(TEXT("C:\\Program Files\\MyApp"));
CreateProcessWithLogonW(..., szCmdline, ...)

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

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

LPTSTR szCmdline[]=_tcsdup(TEXT("\"C:\\Program Files\\MyApp\""));
CreateProcessWithLogonW(..., szCmdline, ...)

次の例は、この関数の呼び出し方法を示しています。


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

void DisplayError(LPWSTR pszAPI)
{
    LPVOID lpvMessageBuffer;

    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 
        FORMAT_MESSAGE_FROM_SYSTEM,
        NULL, GetLastError(), 
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
        (LPWSTR)&lpvMessageBuffer, 0, NULL);

    //
    //... now display this string
    //
    wprintf(L"ERROR: API        = %s.\n", pszAPI);
    wprintf(L"       error code = %d.\n", GetLastError());
    wprintf(L"       message    = %s.\n", (LPWSTR)lpvMessageBuffer);

    //
    // Free the buffer allocated by the system
    //
    LocalFree(lpvMessageBuffer);

    ExitProcess(GetLastError());
}

void wmain(int argc, WCHAR *argv[])
{
    DWORD     dwSize;
    HANDLE    hToken;
    LPVOID    lpvEnv;
    PROCESS_INFORMATION pi = {0};
    STARTUPINFO         si = {0};
    WCHAR               szUserProfile[256] = L"";

    si.cb = sizeof(STARTUPINFO);
    
    if (argc != 4)
    {
        wprintf(L"Usage: %s [user@domain] [password] [cmd]", argv[0]);
        wprintf(L"\n\n");
        return;
    }

    //
    // TO DO: change NULL to '.' to use local account database
    //
    if (!LogonUser(argv[1], NULL, argv[2], LOGON32_LOGON_INTERACTIVE, 
            LOGON32_PROVIDER_DEFAULT, &hToken))
        DisplayError(L"LogonUser");

    if (!CreateEnvironmentBlock(&lpvEnv, hToken, TRUE))
        DisplayError(L"CreateEnvironmentBlock");

    dwSize = sizeof(szUserProfile)/sizeof(WCHAR);

    if (!GetUserProfileDirectory(hToken, szUserProfile, &dwSize))
        DisplayError(L"GetUserProfileDirectory");

    //
    // TO DO: change NULL to '.' to use local account database
    //
    if (!CreateProcessWithLogonW(argv[1], NULL, argv[2], 
            LOGON_WITH_PROFILE, NULL, argv[3], 
            CREATE_UNICODE_ENVIRONMENT, lpvEnv, szUserProfile, 
            &si, &pi))
        DisplayError(L"CreateProcessWithLogonW");

    if (!DestroyEnvironmentBlock(lpvEnv))
        DisplayError(L"DestroyEnvironmentBlock");

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

各言語での呼び出し定義

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

BOOL CreateProcessWithLogonW(
    LPCWSTR lpUsername,
    LPCWSTR lpDomain,   // optional
    LPCWSTR lpPassword,
    CREATE_PROCESS_LOGON_FLAGS dwLogonFlags,
    LPCWSTR lpApplicationName,   // optional
    LPWSTR lpCommandLine,   // optional
    PROCESS_CREATION_FLAGS dwCreationFlags,
    void* lpEnvironment,   // optional
    LPCWSTR lpCurrentDirectory,   // optional
    STARTUPINFOW* lpStartupInfo,
    PROCESS_INFORMATION* lpProcessInformation
);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("ADVAPI32.dll", SetLastError = true, ExactSpelling = true)]
static extern bool CreateProcessWithLogonW(
    [MarshalAs(UnmanagedType.LPWStr)] string lpUsername,   // LPCWSTR
    [MarshalAs(UnmanagedType.LPWStr)] string lpDomain,   // LPCWSTR optional
    [MarshalAs(UnmanagedType.LPWStr)] string lpPassword,   // LPCWSTR
    uint dwLogonFlags,   // CREATE_PROCESS_LOGON_FLAGS
    [MarshalAs(UnmanagedType.LPWStr)] string lpApplicationName,   // LPCWSTR optional
    [MarshalAs(UnmanagedType.LPWStr)] System.Text.StringBuilder lpCommandLine,   // LPWSTR optional, in/out
    uint dwCreationFlags,   // PROCESS_CREATION_FLAGS
    IntPtr lpEnvironment,   // void* optional
    [MarshalAs(UnmanagedType.LPWStr)] string lpCurrentDirectory,   // LPCWSTR optional
    IntPtr lpStartupInfo,   // STARTUPINFOW*
    IntPtr lpProcessInformation   // PROCESS_INFORMATION* out
);
<DllImport("ADVAPI32.dll", SetLastError:=True, ExactSpelling:=True)>
Public Shared Function CreateProcessWithLogonW(
    <MarshalAs(UnmanagedType.LPWStr)> lpUsername As String,   ' LPCWSTR
    <MarshalAs(UnmanagedType.LPWStr)> lpDomain As String,   ' LPCWSTR optional
    <MarshalAs(UnmanagedType.LPWStr)> lpPassword As String,   ' LPCWSTR
    dwLogonFlags As UInteger,   ' CREATE_PROCESS_LOGON_FLAGS
    <MarshalAs(UnmanagedType.LPWStr)> lpApplicationName As String,   ' LPCWSTR optional
    <MarshalAs(UnmanagedType.LPWStr)> lpCommandLine As System.Text.StringBuilder,   ' LPWSTR optional, in/out
    dwCreationFlags As UInteger,   ' PROCESS_CREATION_FLAGS
    lpEnvironment As IntPtr,   ' void* optional
    <MarshalAs(UnmanagedType.LPWStr)> lpCurrentDirectory As String,   ' LPCWSTR optional
    lpStartupInfo As IntPtr,   ' STARTUPINFOW*
    lpProcessInformation As IntPtr   ' PROCESS_INFORMATION* out
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
' lpUsername : LPCWSTR
' lpDomain : LPCWSTR optional
' lpPassword : LPCWSTR
' dwLogonFlags : CREATE_PROCESS_LOGON_FLAGS
' lpApplicationName : LPCWSTR optional
' lpCommandLine : LPWSTR optional, in/out
' dwCreationFlags : PROCESS_CREATION_FLAGS
' lpEnvironment : void* optional
' lpCurrentDirectory : LPCWSTR optional
' lpStartupInfo : STARTUPINFOW*
' lpProcessInformation : PROCESS_INFORMATION* out
Declare PtrSafe Function CreateProcessWithLogonW Lib "advapi32" ( _
    ByVal lpUsername As LongPtr, _
    ByVal lpDomain As LongPtr, _
    ByVal lpPassword As LongPtr, _
    ByVal dwLogonFlags As Long, _
    ByVal lpApplicationName As LongPtr, _
    ByVal lpCommandLine As LongPtr, _
    ByVal dwCreationFlags As Long, _
    ByVal lpEnvironment As LongPtr, _
    ByVal lpCurrentDirectory As LongPtr, _
    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

CreateProcessWithLogonW = ctypes.windll.advapi32.CreateProcessWithLogonW
CreateProcessWithLogonW.restype = wintypes.BOOL
CreateProcessWithLogonW.argtypes = [
    wintypes.LPCWSTR,  # lpUsername : LPCWSTR
    wintypes.LPCWSTR,  # lpDomain : LPCWSTR optional
    wintypes.LPCWSTR,  # lpPassword : LPCWSTR
    wintypes.DWORD,  # dwLogonFlags : CREATE_PROCESS_LOGON_FLAGS
    wintypes.LPCWSTR,  # lpApplicationName : LPCWSTR optional
    wintypes.LPWSTR,  # lpCommandLine : LPWSTR optional, in/out
    wintypes.DWORD,  # dwCreationFlags : PROCESS_CREATION_FLAGS
    ctypes.POINTER(None),  # lpEnvironment : void* optional
    wintypes.LPCWSTR,  # lpCurrentDirectory : LPCWSTR optional
    ctypes.c_void_p,  # lpStartupInfo : STARTUPINFOW*
    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('ADVAPI32.dll')
CreateProcessWithLogonW = Fiddle::Function.new(
  lib['CreateProcessWithLogonW'],
  [
    Fiddle::TYPE_VOIDP,  # lpUsername : LPCWSTR
    Fiddle::TYPE_VOIDP,  # lpDomain : LPCWSTR optional
    Fiddle::TYPE_VOIDP,  # lpPassword : LPCWSTR
    -Fiddle::TYPE_INT,  # dwLogonFlags : CREATE_PROCESS_LOGON_FLAGS
    Fiddle::TYPE_VOIDP,  # lpApplicationName : LPCWSTR optional
    Fiddle::TYPE_VOIDP,  # lpCommandLine : LPWSTR optional, in/out
    -Fiddle::TYPE_INT,  # dwCreationFlags : PROCESS_CREATION_FLAGS
    Fiddle::TYPE_VOIDP,  # lpEnvironment : void* optional
    Fiddle::TYPE_VOIDP,  # lpCurrentDirectory : LPCWSTR optional
    Fiddle::TYPE_VOIDP,  # lpStartupInfo : STARTUPINFOW*
    Fiddle::TYPE_VOIDP,  # lpProcessInformation : PROCESS_INFORMATION* out
  ],
  Fiddle::TYPE_INT)
#[link(name = "advapi32")]
extern "system" {
    fn CreateProcessWithLogonW(
        lpUsername: *const u16,  // LPCWSTR
        lpDomain: *const u16,  // LPCWSTR optional
        lpPassword: *const u16,  // LPCWSTR
        dwLogonFlags: u32,  // CREATE_PROCESS_LOGON_FLAGS
        lpApplicationName: *const u16,  // LPCWSTR optional
        lpCommandLine: *mut u16,  // LPWSTR optional, in/out
        dwCreationFlags: u32,  // PROCESS_CREATION_FLAGS
        lpEnvironment: *mut (),  // void* optional
        lpCurrentDirectory: *const u16,  // LPCWSTR optional
        lpStartupInfo: *mut STARTUPINFOW,  // STARTUPINFOW*
        lpProcessInformation: *mut PROCESS_INFORMATION  // PROCESS_INFORMATION* 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 CreateProcessWithLogonW([MarshalAs(UnmanagedType.LPWStr)] string lpUsername, [MarshalAs(UnmanagedType.LPWStr)] string lpDomain, [MarshalAs(UnmanagedType.LPWStr)] string lpPassword, uint dwLogonFlags, [MarshalAs(UnmanagedType.LPWStr)] string lpApplicationName, [MarshalAs(UnmanagedType.LPWStr)] System.Text.StringBuilder lpCommandLine, uint dwCreationFlags, IntPtr lpEnvironment, [MarshalAs(UnmanagedType.LPWStr)] string lpCurrentDirectory, IntPtr lpStartupInfo, IntPtr lpProcessInformation);
"@
$api = Add-Type -MemberDefinition $sig -Name 'ADVAPI32_CreateProcessWithLogonW' -Namespace Win32 -PassThru
# $api::CreateProcessWithLogonW(lpUsername, lpDomain, lpPassword, dwLogonFlags, lpApplicationName, lpCommandLine, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation)
#uselib "ADVAPI32.dll"
#func global CreateProcessWithLogonW "CreateProcessWithLogonW" sptr, sptr, sptr, sptr, sptr, sptr, sptr, sptr, sptr, sptr, sptr
; CreateProcessWithLogonW lpUsername, lpDomain, lpPassword, dwLogonFlags, lpApplicationName, varptr(lpCommandLine), dwCreationFlags, lpEnvironment, lpCurrentDirectory, varptr(lpStartupInfo), varptr(lpProcessInformation)   ; 戻り値は stat
; lpUsername : LPCWSTR -> "sptr"
; lpDomain : LPCWSTR optional -> "sptr"
; lpPassword : LPCWSTR -> "sptr"
; dwLogonFlags : CREATE_PROCESS_LOGON_FLAGS -> "sptr"
; lpApplicationName : LPCWSTR optional -> "sptr"
; lpCommandLine : LPWSTR optional, in/out -> "sptr"
; dwCreationFlags : PROCESS_CREATION_FLAGS -> "sptr"
; lpEnvironment : void* optional -> "sptr"
; lpCurrentDirectory : LPCWSTR optional -> "sptr"
; lpStartupInfo : STARTUPINFOW* -> "sptr"
; lpProcessInformation : PROCESS_INFORMATION* out -> "sptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。
出力引数:
#uselib "ADVAPI32.dll"
#cfunc global CreateProcessWithLogonW "CreateProcessWithLogonW" wstr, wstr, wstr, int, wstr, var, int, sptr, wstr, var, var
; res = CreateProcessWithLogonW(lpUsername, lpDomain, lpPassword, dwLogonFlags, lpApplicationName, lpCommandLine, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation)
; lpUsername : LPCWSTR -> "wstr"
; lpDomain : LPCWSTR optional -> "wstr"
; lpPassword : LPCWSTR -> "wstr"
; dwLogonFlags : CREATE_PROCESS_LOGON_FLAGS -> "int"
; lpApplicationName : LPCWSTR optional -> "wstr"
; lpCommandLine : LPWSTR optional, in/out -> "var"
; dwCreationFlags : PROCESS_CREATION_FLAGS -> "int"
; lpEnvironment : void* optional -> "sptr"
; lpCurrentDirectory : LPCWSTR optional -> "wstr"
; lpStartupInfo : STARTUPINFOW* -> "var"
; lpProcessInformation : PROCESS_INFORMATION* out -> "var"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
出力引数:
; BOOL CreateProcessWithLogonW(LPCWSTR lpUsername, LPCWSTR lpDomain, LPCWSTR lpPassword, CREATE_PROCESS_LOGON_FLAGS dwLogonFlags, LPCWSTR lpApplicationName, LPWSTR lpCommandLine, PROCESS_CREATION_FLAGS dwCreationFlags, void* lpEnvironment, LPCWSTR lpCurrentDirectory, STARTUPINFOW* lpStartupInfo, PROCESS_INFORMATION* lpProcessInformation)
#uselib "ADVAPI32.dll"
#cfunc global CreateProcessWithLogonW "CreateProcessWithLogonW" wstr, wstr, wstr, int, wstr, var, int, intptr, wstr, var, var
; res = CreateProcessWithLogonW(lpUsername, lpDomain, lpPassword, dwLogonFlags, lpApplicationName, lpCommandLine, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation)
; lpUsername : LPCWSTR -> "wstr"
; lpDomain : LPCWSTR optional -> "wstr"
; lpPassword : LPCWSTR -> "wstr"
; dwLogonFlags : CREATE_PROCESS_LOGON_FLAGS -> "int"
; lpApplicationName : LPCWSTR optional -> "wstr"
; lpCommandLine : LPWSTR optional, in/out -> "var"
; dwCreationFlags : PROCESS_CREATION_FLAGS -> "int"
; lpEnvironment : void* optional -> "intptr"
; lpCurrentDirectory : LPCWSTR optional -> "wstr"
; lpStartupInfo : STARTUPINFOW* -> "var"
; lpProcessInformation : PROCESS_INFORMATION* out -> "var"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
import (
	"golang.org/x/sys/windows"
	"unsafe"
)

var (
	advapi32 = windows.NewLazySystemDLL("ADVAPI32.dll")
	procCreateProcessWithLogonW = advapi32.NewProc("CreateProcessWithLogonW")
)

// lpUsername (LPCWSTR), lpDomain (LPCWSTR optional), lpPassword (LPCWSTR), dwLogonFlags (CREATE_PROCESS_LOGON_FLAGS), lpApplicationName (LPCWSTR optional), lpCommandLine (LPWSTR optional, in/out), dwCreationFlags (PROCESS_CREATION_FLAGS), lpEnvironment (void* optional), lpCurrentDirectory (LPCWSTR optional), lpStartupInfo (STARTUPINFOW*), lpProcessInformation (PROCESS_INFORMATION* out)
r1, _, err := procCreateProcessWithLogonW.Call(
	uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(lpUsername))),
	uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(lpDomain))),
	uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(lpPassword))),
	uintptr(dwLogonFlags),
	uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(lpApplicationName))),
	uintptr(lpCommandLine),
	uintptr(dwCreationFlags),
	uintptr(lpEnvironment),
	uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(lpCurrentDirectory))),
	uintptr(lpStartupInfo),
	uintptr(lpProcessInformation),
)
_ = err  // syscall.Errno (valid when the call sets last-error)
_ = r1   // BOOL
function CreateProcessWithLogonW(
  lpUsername: PWideChar;   // LPCWSTR
  lpDomain: PWideChar;   // LPCWSTR optional
  lpPassword: PWideChar;   // LPCWSTR
  dwLogonFlags: DWORD;   // CREATE_PROCESS_LOGON_FLAGS
  lpApplicationName: PWideChar;   // LPCWSTR optional
  lpCommandLine: PWideChar;   // LPWSTR optional, in/out
  dwCreationFlags: DWORD;   // PROCESS_CREATION_FLAGS
  lpEnvironment: Pointer;   // void* optional
  lpCurrentDirectory: PWideChar;   // LPCWSTR optional
  lpStartupInfo: Pointer;   // STARTUPINFOW*
  lpProcessInformation: Pointer   // PROCESS_INFORMATION* out
): BOOL; stdcall;
  external 'ADVAPI32.dll' name 'CreateProcessWithLogonW';
result := DllCall("ADVAPI32\CreateProcessWithLogonW"
    , "WStr", lpUsername   ; LPCWSTR
    , "WStr", lpDomain   ; LPCWSTR optional
    , "WStr", lpPassword   ; LPCWSTR
    , "UInt", dwLogonFlags   ; CREATE_PROCESS_LOGON_FLAGS
    , "WStr", lpApplicationName   ; LPCWSTR optional
    , "Ptr", lpCommandLine   ; LPWSTR optional, in/out
    , "UInt", dwCreationFlags   ; PROCESS_CREATION_FLAGS
    , "Ptr", lpEnvironment   ; void* optional
    , "WStr", lpCurrentDirectory   ; LPCWSTR optional
    , "Ptr", lpStartupInfo   ; STARTUPINFOW*
    , "Ptr", lpProcessInformation   ; PROCESS_INFORMATION* out
    , "Int")   ; return: BOOL
●CreateProcessWithLogonW(lpUsername, lpDomain, lpPassword, dwLogonFlags, lpApplicationName, lpCommandLine, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation) = DLL("ADVAPI32.dll", "bool CreateProcessWithLogonW(char*, char*, char*, dword, char*, char*, dword, void*, char*, void*, void*)")
# 呼び出し: CreateProcessWithLogonW(lpUsername, lpDomain, lpPassword, dwLogonFlags, lpApplicationName, lpCommandLine, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation)
# lpUsername : LPCWSTR -> "char*"
# lpDomain : LPCWSTR optional -> "char*"
# lpPassword : LPCWSTR -> "char*"
# dwLogonFlags : CREATE_PROCESS_LOGON_FLAGS -> "dword"
# lpApplicationName : LPCWSTR optional -> "char*"
# lpCommandLine : LPWSTR optional, in/out -> "char*"
# dwCreationFlags : PROCESS_CREATION_FLAGS -> "dword"
# lpEnvironment : void* optional -> "void*"
# lpCurrentDirectory : LPCWSTR optional -> "char*"
# lpStartupInfo : STARTUPINFOW* -> "void*"
# lpProcessInformation : PROCESS_INFORMATION* out -> "void*"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。
const std = @import("std");

extern "advapi32" fn CreateProcessWithLogonW(
    lpUsername: [*c]const u16, // LPCWSTR
    lpDomain: [*c]const u16, // LPCWSTR optional
    lpPassword: [*c]const u16, // LPCWSTR
    dwLogonFlags: u32, // CREATE_PROCESS_LOGON_FLAGS
    lpApplicationName: [*c]const u16, // LPCWSTR optional
    lpCommandLine: [*c]u16, // LPWSTR optional, in/out
    dwCreationFlags: u32, // PROCESS_CREATION_FLAGS
    lpEnvironment: ?*anyopaque, // void* optional
    lpCurrentDirectory: [*c]const u16, // LPCWSTR optional
    lpStartupInfo: [*c]STARTUPINFOW, // STARTUPINFOW*
    lpProcessInformation: [*c]PROCESS_INFORMATION // PROCESS_INFORMATION* out
) callconv(std.os.windows.WINAPI) i32;
proc CreateProcessWithLogonW(
    lpUsername: WideCString,  # LPCWSTR
    lpDomain: WideCString,  # LPCWSTR optional
    lpPassword: WideCString,  # LPCWSTR
    dwLogonFlags: uint32,  # CREATE_PROCESS_LOGON_FLAGS
    lpApplicationName: WideCString,  # LPCWSTR optional
    lpCommandLine: ptr uint16,  # LPWSTR optional, in/out
    dwCreationFlags: uint32,  # PROCESS_CREATION_FLAGS
    lpEnvironment: pointer,  # void* optional
    lpCurrentDirectory: WideCString,  # LPCWSTR optional
    lpStartupInfo: ptr STARTUPINFOW,  # STARTUPINFOW*
    lpProcessInformation: ptr PROCESS_INFORMATION  # PROCESS_INFORMATION* out
): int32 {.importc: "CreateProcessWithLogonW", stdcall, dynlib: "ADVAPI32.dll".}
pragma(lib, "advapi32");
extern(Windows)
int CreateProcessWithLogonW(
    const(wchar)* lpUsername,   // LPCWSTR
    const(wchar)* lpDomain,   // LPCWSTR optional
    const(wchar)* lpPassword,   // LPCWSTR
    uint dwLogonFlags,   // CREATE_PROCESS_LOGON_FLAGS
    const(wchar)* lpApplicationName,   // LPCWSTR optional
    wchar* lpCommandLine,   // LPWSTR optional, in/out
    uint dwCreationFlags,   // PROCESS_CREATION_FLAGS
    void* lpEnvironment,   // void* optional
    const(wchar)* lpCurrentDirectory,   // LPCWSTR optional
    STARTUPINFOW* lpStartupInfo,   // STARTUPINFOW*
    PROCESS_INFORMATION* lpProcessInformation   // PROCESS_INFORMATION* out
);
ccall((:CreateProcessWithLogonW, "ADVAPI32.dll"), stdcall, Int32,
      (Cwstring, Cwstring, Cwstring, UInt32, Cwstring, Ptr{UInt16}, UInt32, Ptr{Cvoid}, Cwstring, Ptr{STARTUPINFOW}, Ptr{PROCESS_INFORMATION}),
      lpUsername, lpDomain, lpPassword, dwLogonFlags, lpApplicationName, lpCommandLine, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation)
# lpUsername : LPCWSTR -> Cwstring
# lpDomain : LPCWSTR optional -> Cwstring
# lpPassword : LPCWSTR -> Cwstring
# dwLogonFlags : CREATE_PROCESS_LOGON_FLAGS -> UInt32
# lpApplicationName : LPCWSTR optional -> Cwstring
# lpCommandLine : LPWSTR optional, in/out -> Ptr{UInt16}
# dwCreationFlags : PROCESS_CREATION_FLAGS -> UInt32
# lpEnvironment : void* optional -> Ptr{Cvoid}
# lpCurrentDirectory : LPCWSTR optional -> Cwstring
# lpStartupInfo : STARTUPINFOW* -> Ptr{STARTUPINFOW}
# lpProcessInformation : PROCESS_INFORMATION* out -> Ptr{PROCESS_INFORMATION}
# stdcall は 32bit のみ意味を持つ(x64 では無視)。
local ffi = require("ffi")
ffi.cdef[[
int32_t CreateProcessWithLogonW(
    const uint16_t* lpUsername,
    const uint16_t* lpDomain,
    const uint16_t* lpPassword,
    uint32_t dwLogonFlags,
    const uint16_t* lpApplicationName,
    uint16_t* lpCommandLine,
    uint32_t dwCreationFlags,
    void* lpEnvironment,
    const uint16_t* lpCurrentDirectory,
    void* lpStartupInfo,
    void* lpProcessInformation);
]]
local advapi32 = ffi.load("advapi32")
-- advapi32.CreateProcessWithLogonW(lpUsername, lpDomain, lpPassword, dwLogonFlags, lpApplicationName, lpCommandLine, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation)
-- lpUsername : LPCWSTR
-- lpDomain : LPCWSTR optional
-- lpPassword : LPCWSTR
-- dwLogonFlags : CREATE_PROCESS_LOGON_FLAGS
-- lpApplicationName : LPCWSTR optional
-- lpCommandLine : LPWSTR optional, in/out
-- dwCreationFlags : PROCESS_CREATION_FLAGS
-- lpEnvironment : void* optional
-- lpCurrentDirectory : LPCWSTR optional
-- lpStartupInfo : STARTUPINFOW*
-- lpProcessInformation : PROCESS_INFORMATION* out
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
const koffi = require('koffi');
const lib = koffi.load('ADVAPI32.dll');
const CreateProcessWithLogonW = lib.func('__stdcall', 'CreateProcessWithLogonW', 'int32_t', ['str16', 'str16', 'str16', 'uint32_t', 'str16', 'uint16_t *', 'uint32_t', 'void *', 'str16', 'void *', 'void *']);
// CreateProcessWithLogonW(lpUsername, lpDomain, lpPassword, dwLogonFlags, lpApplicationName, lpCommandLine, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation)
// lpUsername : LPCWSTR -> 'str16'
// lpDomain : LPCWSTR optional -> 'str16'
// lpPassword : LPCWSTR -> 'str16'
// dwLogonFlags : CREATE_PROCESS_LOGON_FLAGS -> 'uint32_t'
// lpApplicationName : LPCWSTR optional -> 'str16'
// lpCommandLine : LPWSTR optional, in/out -> 'uint16_t *'
// dwCreationFlags : PROCESS_CREATION_FLAGS -> 'uint32_t'
// lpEnvironment : void* optional -> 'void *'
// lpCurrentDirectory : LPCWSTR optional -> 'str16'
// lpStartupInfo : STARTUPINFOW* -> 'void *'
// lpProcessInformation : PROCESS_INFORMATION* out -> 'void *'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。
const lib = Deno.dlopen("ADVAPI32.dll", {
  CreateProcessWithLogonW: { parameters: ["buffer", "buffer", "buffer", "u32", "buffer", "buffer", "u32", "pointer", "buffer", "pointer", "pointer"], result: "i32" },
});
// lib.symbols.CreateProcessWithLogonW(lpUsername, lpDomain, lpPassword, dwLogonFlags, lpApplicationName, lpCommandLine, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation)
// lpUsername : LPCWSTR -> "buffer"
// lpDomain : LPCWSTR optional -> "buffer"
// lpPassword : LPCWSTR -> "buffer"
// dwLogonFlags : CREATE_PROCESS_LOGON_FLAGS -> "u32"
// lpApplicationName : LPCWSTR optional -> "buffer"
// lpCommandLine : LPWSTR optional, in/out -> "buffer"
// dwCreationFlags : PROCESS_CREATION_FLAGS -> "u32"
// lpEnvironment : void* optional -> "pointer"
// lpCurrentDirectory : LPCWSTR optional -> "buffer"
// lpStartupInfo : STARTUPINFOW* -> "pointer"
// lpProcessInformation : PROCESS_INFORMATION* out -> "pointer"
// 文字列引数は "buffer"(NUL 終端のバイト列を Uint8Array で渡す)。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。
<?php
$ffi = FFI::cdef(<<<C
int32_t CreateProcessWithLogonW(
    const uint16_t* lpUsername,
    const uint16_t* lpDomain,
    const uint16_t* lpPassword,
    uint32_t dwLogonFlags,
    const uint16_t* lpApplicationName,
    uint16_t* lpCommandLine,
    uint32_t dwCreationFlags,
    void* lpEnvironment,
    const uint16_t* lpCurrentDirectory,
    void* lpStartupInfo,
    void* lpProcessInformation);
C, "ADVAPI32.dll");
// $ffi->CreateProcessWithLogonW(lpUsername, lpDomain, lpPassword, dwLogonFlags, lpApplicationName, lpCommandLine, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation);
// lpUsername : LPCWSTR
// lpDomain : LPCWSTR optional
// lpPassword : LPCWSTR
// dwLogonFlags : CREATE_PROCESS_LOGON_FLAGS
// lpApplicationName : LPCWSTR optional
// lpCommandLine : LPWSTR optional, in/out
// dwCreationFlags : PROCESS_CREATION_FLAGS
// lpEnvironment : void* optional
// lpCurrentDirectory : LPCWSTR optional
// lpStartupInfo : STARTUPINFOW*
// 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 Advapi32 extends StdCallLibrary {
    Advapi32 INSTANCE = Native.load("advapi32", Advapi32.class);
    boolean CreateProcessWithLogonW(
        WString lpUsername,   // LPCWSTR
        WString lpDomain,   // LPCWSTR optional
        WString lpPassword,   // LPCWSTR
        int dwLogonFlags,   // CREATE_PROCESS_LOGON_FLAGS
        WString lpApplicationName,   // LPCWSTR optional
        char[] lpCommandLine,   // LPWSTR optional, in/out
        int dwCreationFlags,   // PROCESS_CREATION_FLAGS
        Pointer lpEnvironment,   // void* optional
        WString lpCurrentDirectory,   // LPCWSTR optional
        Pointer lpStartupInfo,   // STARTUPINFOW*
        Pointer lpProcessInformation   // PROCESS_INFORMATION* out
    );
}
@[Link("advapi32")]
lib LibADVAPI32
  fun CreateProcessWithLogonW = CreateProcessWithLogonW(
    lpUsername : UInt16*,   # LPCWSTR
    lpDomain : UInt16*,   # LPCWSTR optional
    lpPassword : UInt16*,   # LPCWSTR
    dwLogonFlags : UInt32,   # CREATE_PROCESS_LOGON_FLAGS
    lpApplicationName : UInt16*,   # LPCWSTR optional
    lpCommandLine : UInt16*,   # LPWSTR optional, in/out
    dwCreationFlags : UInt32,   # PROCESS_CREATION_FLAGS
    lpEnvironment : Void*,   # void* optional
    lpCurrentDirectory : UInt16*,   # LPCWSTR optional
    lpStartupInfo : STARTUPINFOW*,   # STARTUPINFOW*
    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 CreateProcessWithLogonWNative = Int32 Function(Pointer<Utf16>, Pointer<Utf16>, Pointer<Utf16>, Uint32, Pointer<Utf16>, Pointer<Utf16>, Uint32, Pointer<Void>, Pointer<Utf16>, Pointer<Void>, Pointer<Void>);
typedef CreateProcessWithLogonWDart = int Function(Pointer<Utf16>, Pointer<Utf16>, Pointer<Utf16>, int, Pointer<Utf16>, Pointer<Utf16>, int, Pointer<Void>, Pointer<Utf16>, Pointer<Void>, Pointer<Void>);
final CreateProcessWithLogonW = DynamicLibrary.open('ADVAPI32.dll')
    .lookupFunction<CreateProcessWithLogonWNative, CreateProcessWithLogonWDart>('CreateProcessWithLogonW');
// lpUsername : LPCWSTR -> Pointer<Utf16>
// lpDomain : LPCWSTR optional -> Pointer<Utf16>
// lpPassword : LPCWSTR -> Pointer<Utf16>
// dwLogonFlags : CREATE_PROCESS_LOGON_FLAGS -> Uint32
// lpApplicationName : LPCWSTR optional -> Pointer<Utf16>
// lpCommandLine : LPWSTR optional, in/out -> Pointer<Utf16>
// dwCreationFlags : PROCESS_CREATION_FLAGS -> Uint32
// lpEnvironment : void* optional -> Pointer<Void>
// lpCurrentDirectory : LPCWSTR optional -> Pointer<Utf16>
// lpStartupInfo : STARTUPINFOW* -> Pointer<Void>
// lpProcessInformation : PROCESS_INFORMATION* out -> Pointer<Void>
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。
{$mode objfpc}{$H+}
function CreateProcessWithLogonW(
  lpUsername: PWideChar;   // LPCWSTR
  lpDomain: PWideChar;   // LPCWSTR optional
  lpPassword: PWideChar;   // LPCWSTR
  dwLogonFlags: DWORD;   // CREATE_PROCESS_LOGON_FLAGS
  lpApplicationName: PWideChar;   // LPCWSTR optional
  lpCommandLine: PWideChar;   // LPWSTR optional, in/out
  dwCreationFlags: DWORD;   // PROCESS_CREATION_FLAGS
  lpEnvironment: Pointer;   // void* optional
  lpCurrentDirectory: PWideChar;   // LPCWSTR optional
  lpStartupInfo: Pointer;   // STARTUPINFOW*
  lpProcessInformation: Pointer   // PROCESS_INFORMATION* out
): BOOL; stdcall;
  external 'ADVAPI32.dll' name 'CreateProcessWithLogonW';
import Foreign
import Foreign.C.Types
import Foreign.C.String

foreign import stdcall safe "CreateProcessWithLogonW"
  c_CreateProcessWithLogonW :: CWString -> CWString -> CWString -> Word32 -> CWString -> CWString -> Word32 -> Ptr () -> CWString -> Ptr () -> Ptr () -> IO CInt
-- lpUsername : LPCWSTR -> CWString
-- lpDomain : LPCWSTR optional -> CWString
-- lpPassword : LPCWSTR -> CWString
-- dwLogonFlags : CREATE_PROCESS_LOGON_FLAGS -> Word32
-- lpApplicationName : LPCWSTR optional -> CWString
-- lpCommandLine : LPWSTR optional, in/out -> CWString
-- dwCreationFlags : PROCESS_CREATION_FLAGS -> Word32
-- lpEnvironment : void* optional -> Ptr ()
-- lpCurrentDirectory : LPCWSTR optional -> CWString
-- lpStartupInfo : STARTUPINFOW* -> Ptr ()
-- lpProcessInformation : PROCESS_INFORMATION* out -> Ptr ()
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。
open Ctypes
open Foreign

let createprocesswithlogonw =
  foreign "CreateProcessWithLogonW"
    ((ptr uint16_t) @-> (ptr uint16_t) @-> (ptr uint16_t) @-> uint32_t @-> (ptr uint16_t) @-> (ptr uint16_t) @-> uint32_t @-> (ptr void) @-> (ptr uint16_t) @-> (ptr void) @-> (ptr void) @-> returning int32_t)
(* lpUsername : LPCWSTR -> (ptr uint16_t) *)
(* lpDomain : LPCWSTR optional -> (ptr uint16_t) *)
(* lpPassword : LPCWSTR -> (ptr uint16_t) *)
(* dwLogonFlags : CREATE_PROCESS_LOGON_FLAGS -> uint32_t *)
(* lpApplicationName : LPCWSTR optional -> (ptr uint16_t) *)
(* lpCommandLine : LPWSTR optional, in/out -> (ptr uint16_t) *)
(* dwCreationFlags : PROCESS_CREATION_FLAGS -> uint32_t *)
(* lpEnvironment : void* optional -> (ptr void) *)
(* lpCurrentDirectory : LPCWSTR optional -> (ptr uint16_t) *)
(* lpStartupInfo : STARTUPINFOW* -> (ptr void) *)
(* lpProcessInformation : PROCESS_INFORMATION* out -> (ptr void) *)
(* foreign は cdecl 前提。x64 Windows では WINAPI と一致。構造体は ctypes structure を定義のこと。 *)
(cffi:define-foreign-library advapi32 (t "ADVAPI32.dll"))
(cffi:use-foreign-library advapi32)

(cffi:defcfun ("CreateProcessWithLogonW" create-process-with-logon-w :convention :stdcall) :int32
  (lp-username (:string :encoding :utf-16le))   ; LPCWSTR
  (lp-domain (:string :encoding :utf-16le))   ; LPCWSTR optional
  (lp-password (:string :encoding :utf-16le))   ; LPCWSTR
  (dw-logon-flags :uint32)   ; CREATE_PROCESS_LOGON_FLAGS
  (lp-application-name (:string :encoding :utf-16le))   ; LPCWSTR optional
  (lp-command-line :pointer)   ; LPWSTR optional, in/out
  (dw-creation-flags :uint32)   ; PROCESS_CREATION_FLAGS
  (lp-environment :pointer)   ; void* optional
  (lp-current-directory (:string :encoding :utf-16le))   ; LPCWSTR optional
  (lp-startup-info :pointer)   ; STARTUPINFOW*
  (lp-process-information :pointer))   ; PROCESS_INFORMATION* out
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $CreateProcessWithLogonW = Win32::API::More->new('ADVAPI32',
    'BOOL CreateProcessWithLogonW(LPCWSTR lpUsername, LPCWSTR lpDomain, LPCWSTR lpPassword, DWORD dwLogonFlags, LPCWSTR lpApplicationName, LPWSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPVOID lpStartupInfo, LPVOID lpProcessInformation)');
# my $ret = $CreateProcessWithLogonW->Call($lpUsername, $lpDomain, $lpPassword, $dwLogonFlags, $lpApplicationName, $lpCommandLine, $dwCreationFlags, $lpEnvironment, $lpCurrentDirectory, $lpStartupInfo, $lpProcessInformation);
# lpUsername : LPCWSTR -> LPCWSTR
# lpDomain : LPCWSTR optional -> LPCWSTR
# lpPassword : LPCWSTR -> LPCWSTR
# dwLogonFlags : CREATE_PROCESS_LOGON_FLAGS -> DWORD
# lpApplicationName : LPCWSTR optional -> LPCWSTR
# lpCommandLine : LPWSTR optional, in/out -> LPWSTR
# dwCreationFlags : PROCESS_CREATION_FLAGS -> DWORD
# lpEnvironment : void* optional -> LPVOID
# lpCurrentDirectory : LPCWSTR optional -> LPCWSTR
# lpStartupInfo : STARTUPINFOW* -> LPVOID
# lpProcessInformation : PROCESS_INFORMATION* out -> LPVOID
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。

関連項目

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