次の方法で共有


CreateProcessAsUserW 関数 (processthreadsapi.h)

新しいプロセスとそのプライマリ スレッドを作成します。 新しいプロセスは、指定されたトークンによって表されるユーザーのセキュリティ コンテキストで実行されます。

通常、CreateProcessAsUser 関数を呼び出すプロセスには SE_INCREASE_QUOTA_NAME 特権が必要であり、トークンが割り当てできない場合は SE_ASSIGNPRIMARYTOKEN_NAME 特権が必要になる場合があります。 この関数が ERROR_PRIVILEGE_NOT_HELD (1314) で失敗した場合は、代わりに createProcessWithLogonW 関数 使用します。 CreateProcessWithLogonW 特別な特権は必要ありませんが、指定されたユーザー アカウントは対話形式でログオンできるようにする必要があります。 一般に、CreateProcessWithLogonW 使用して、代替資格情報を使用してプロセスを作成することをお勧めします。

構文

BOOL CreateProcessAsUserW(
  [in, optional]      HANDLE                hToken,
  [in, optional]      LPCWSTR               lpApplicationName,
  [in, out, optional] LPWSTR                lpCommandLine,
  [in, optional]      LPSECURITY_ATTRIBUTES lpProcessAttributes,
  [in, optional]      LPSECURITY_ATTRIBUTES lpThreadAttributes,
  [in]                BOOL                  bInheritHandles,
  [in]                DWORD                 dwCreationFlags,
  [in, optional]      LPVOID                lpEnvironment,
  [in, optional]      LPCWSTR               lpCurrentDirectory,
  [in]                LPSTARTUPINFOW        lpStartupInfo,
  [out]               LPPROCESS_INFORMATION lpProcessInformation
);

パラメーター

[in, optional] hToken

ユーザーを表すプライマリ トークンのハンドル。 ハンドルには、TOKEN_QUERYTOKEN_DUPLICATE、および TOKEN_ASSIGN_PRIMARY アクセス権が必要です。 詳細については、「Access-Token オブジェクトのアクセス権を する」を参照してください。 トークンによって表されるユーザーは、lpApplicationName または lpCommandLine パラメーターで指定されたアプリケーションへの読み取りおよび実行アクセス権を持っている必要があります。

指定したユーザーを表すプライマリ トークンを取得するには、LogonUser 関数を呼び出します。 または、DuplicateTokenEx 関数を呼び出して、偽装トークンをプライマリ トークンに変換することもできます。 これにより、クライアントを偽装しているサーバー アプリケーションは、クライアントのセキュリティ コンテキストを持つプロセスを作成できます。

hToken が呼び出し元のプライマリ トークンの制限付きバージョンである場合、SE_ASSIGNPRIMARYTOKEN_NAME 特権は必要ありません。 必要な権限がまだ有効になっていない場合は、CreateProcessAsUser 呼び出しの間有効になります。 詳細については、「特別な特権を使用した実行 」を参照してください。

ターミナル サービス: トークンで指定されたセッションでプロセスが実行されます。 既定では、これは LogonUser呼び出したのと同じセッションです。 セッションを変更するには、SetTokenInformation 関数を使用します。

[in, optional] lpApplicationName

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

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

lpApplicationName パラメーターは、NULLできます。 その場合、モジュール名は、lpCommandLine 文字列内の最初の空白で区切られたトークンである必要があります。 スペースを含む長いファイル名を使用している場合は、引用符で囲まれた文字列を使用して、ファイル名の末尾と引数の開始位置を示します。それ以外の場合、ファイル名はあいまいです。 たとえば、"c:\program files\sub dir\program name" という文字列を考えてみます。 この文字列は、さまざまな方法で解釈できます。 システムは、次の順序で可能性を解釈しようとします。

c:\program.exec:\program files\sub.exec:\program files\sub dir\program.exec:\program files\sub dir\program name.exe 実行可能モジュールが 16 ビット アプリケーションの場合は、lpApplicationName NULL、および lpCommandLine が指す文字列 、実行可能モジュールとその引数を指定する必要があります。 既定では、CreateProcessAsUser によって作成されたすべての 16 ビット Windows ベースのアプリケーションは、個別の VDM で実行されます (CreateProcessCREATE_SEPARATE_WOW_VDM と同じです)。

[in, out, optional] lpCommandLine

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

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

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

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

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

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

[in, optional] lpProcessAttributes

新しいプロセス オブジェクトのセキュリティ記述子を指定し、子プロセスが返されたハンドルをプロセスに継承できるかどうかを判断する SECURITY_ATTRIBUTES 構造体へのポインター。 lpProcessAttributes が NULL 、または lpSecurityDescriptor が NULL場合、プロセスは既定のセキュリティ記述子を取得し、ハンドルを継承できません。 既定のセキュリティ記述子は、hToken パラメーターで参照されているユーザーのセキュリティ記述子です。 このセキュリティ記述子は、呼び出し元へのアクセスを許可しない場合があります。その場合、実行後にプロセスを再度開くことができない可能性があります。 プロセス ハンドルは有効であり、引き続きフル アクセス権を持ちます。

[in, optional] lpThreadAttributes

新しいスレッド オブジェクトのセキュリティ記述子を指定し、子プロセスが返されたハンドルをスレッドに継承できるかどうかを判断する、SECURITY_ATTRIBUTES 構造体へのポインター。 lpThreadAttributes が NULL 場合、または lpSecurityDescriptor が NULL場合、スレッドは既定のセキュリティ記述子を取得し、ハンドルを継承できません。 既定のセキュリティ記述子は、hToken パラメーターで参照されているユーザーのセキュリティ記述子です。 このセキュリティ記述子は、呼び出し元へのアクセスを許可しない場合があります。

[in] bInheritHandles

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

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

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

[in] dwCreationFlags

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

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

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

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

[in, optional] lpEnvironment

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

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

名前=\0

等号は区切り記号として使用されるため、環境変数の名前には使用しないでください。

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

この関数の ANSI バージョン CreateProcessAsUserA、プロセスの環境ブロックの合計サイズが 32,767 文字を超えると失敗します。

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

Windows Server 2003 および Windows XP: ユーザーとシステム環境変数の組み合わせのサイズが 8192 バイトを超える場合、CreateProcessAsUser によって作成されたプロセス、親プロセスによって関数に渡された環境ブロックで実行されなくなります。 代わりに、子プロセスは、CreateEnvironmentBlock 関数によって返される環境ブロックで実行されます。

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

[in, optional] lpCurrentDirectory

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

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

[in] lpStartupInfo

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

ユーザーは、指定されたウィンドウ ステーションとデスクトップの両方にフル アクセスできる必要があります。 プロセスを対話形式にする場合は、winsta0\default を指定します。 lpDesktop メンバーが NULL の場合、新しいプロセスは親プロセスのデスクトップステーションとウィンドウステーションを継承します。 このメンバーが空の文字列 "" の場合、新しいプロセスは、「ウィンドウ ステーションへの接続の処理 に関するページで説明されている規則を使用してウィンドウ ステーションに接続します。

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

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

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

[out] lpProcessInformation

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

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

戻り値

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

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

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

備考

CreateProcessAsUser は、TOKEN_DUPLICATETOKEN_IMPERSONATE アクセス権を使用して呼び出し元プロセスのプライマリ トークンを開くことができる必要があります。

既定では、CreateProcessAsUser は、表示されず、ユーザー入力を受信できないデスクトップを使用して、非対話型ウィンドウ ステーションに新しいプロセスを作成します。 新しいプロセスとのユーザー操作を有効にするには、STARTUPINFO 構造体の lpDesktop メンバーに、既定の対話型ウィンドウ ステーションとデスクトップの名前 "winsta0\default" を指定する必要があります。 さらに、CreateProcessAsUser呼び出す前に、既定の対話型ウィンドウ ステーションと既定のデスクトップの両方の随意アクセス制御リスト (DACL) を変更する必要があります。 ウィンドウ ステーションとデスクトップの DACL は、hToken パラメーターで表されるユーザーまたはログオン セッションへのアクセス権を付与する必要があります。

CreateProcessAsUser 、指定したユーザーのプロファイルが HKEY_USERS レジストリ キーに読み込まれません。 そのため、HKEY_CURRENT_USER レジストリ キーの情報にアクセスするには、CreateProcessAsUserを呼び出す前に、LoadUserProfile 関数を使用してユーザーのプロファイル情報 HKEY_USERS に読み込む必要があります。 新しいプロセスが終了した後、UnloadUserProfile を必ず呼び出してください。

lpEnvironment パラメーターが NULL の場合、新しいプロセスは呼び出し元プロセスの環境を継承します。 CreateProcessAsUser では、hTokenで表されるユーザーに固有の環境変数を含むように環境ブロック 自動的に変更されることはありません。 たとえば、lpEnvironment が NULL の場合、USERNAME 変数と USERDOMAIN 変数 呼び出し元プロセスから継承されます。 新しいプロセス用に環境ブロックを準備し、lpEnvironmentで指定するのはユーザーの責任です。

CreateProcessWithLogonW 関数と createProcessWithTokenW 関数 は、CreateProcessAsUserに似ていますが、呼び出し元はユーザーを認証してトークンを取得するために LogonUser 関数を呼び出す必要はありません。

CreateProcessAsUser を使用すると、呼び出し元またはターゲット ユーザーのセキュリティ コンテキストで、指定されたディレクトリと実行可能イメージにアクセスできます。 既定では、CreateProcessAsUser は、呼び出し元のセキュリティ コンテキスト内のディレクトリと実行可能イメージにアクセスします。 この場合、呼び出し元がディレクトリと実行可能イメージにアクセスできない場合、関数は失敗します。 ターゲット ユーザーのセキュリティ コンテキストを使用してディレクトリと実行可能イメージにアクセスするには、CreateProcessAsUserを呼び出す前に、ImpersonateLoggedOnUser 関数の呼び出しで hToken 指定します。

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

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

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

既定では、bInheritHandles パラメーターの値として true 渡すと、継承可能なすべてのハンドルが新しいプロセスによって継承されます。 これは、複数のスレッドから同時にプロセスを作成するが、各プロセスが異なるハンドルを継承することを望むアプリケーションでは問題になる可能性があります。 アプリケーションでは、UpdateProcThreadAttributeList 関数を PROC_THREAD_ATTRIBUTE_HANDLE_LIST パラメーターと共に使用して、特定のプロセスによって継承されるハンドルの一覧を提供できます。

セキュリティに関する備考

lpApplicationName パラメーターには NULL を指定できます。この場合、実行可能ファイル名は、lpCommandLineの最初 空白で区切られた文字列である必要があります。 実行可能ファイルまたはパス名にスペースがある場合、関数がスペースを解析する方法により、別の実行可能ファイルが実行される可能性があります。 次の例は、関数が "MyApp.exe" ではなく "Program.exe" (存在する場合) を実行しようとするため、危険です。
	LPTSTR szCmdline[] = _tcsdup(TEXT("C:\\Program Files\\MyApp"));
	CreateProcessAsUser(hToken, NULL, szCmdline, /*...*/ );

悪意のあるユーザーが "Program.exe" という名前のアプリケーションをシステムに作成した場合、Program Files ディレクトリを使用 CreateProcessAsUser を誤って呼び出すプログラムは、目的のアプリケーションではなく、このアプリケーションを実行します。

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

	LPTSTR szCmdline[] = _tcsdup(TEXT("\"C:\\Program Files\\MyApp\""));
	CreateProcessAsUser(hToken, NULL, szCmdline, /*...*/);

PowerShell: CreateProcessAsUser 関数を使用して PowerShell バージョン 2.0 でコマンドレットを実装すると、このコマンドレットはファンインとファンアウトの両方のリモート セッションで正しく動作します。 ただし、セキュリティシナリオによっては、CreateProcessAsUser で実装されたコマンドレットは、ファンイン リモート セッションの PowerShell バージョン 3.0 でのみ正しく動作します。クライアントセキュリティ特権が不十分なため、ファンアウトリモートセッションは失敗します。 PowerShell バージョン 3.0 でファンインとファンアウトの両方のリモート セッションに対して機能するコマンドレットを実装するには、CreateProcess 関数を使用します。

例については、「対話型クライアント プロセスの開始 」を参照してください。

手記

processthreadsapi.h ヘッダーは、Unicode プリプロセッサ定数の定義に基づいて、この関数の ANSI または Unicode バージョンを自動的に選択するエイリアスとして CreateProcessAsUser を定義します。 エンコードに依存しないエイリアスをエンコードに依存しないコードと組み合わせて使用すると、コンパイルエラーやランタイム エラーが発生する不一致が発生する可能性があります。 詳細については、「関数プロトタイプの 規則」を参照してください。

必要条件

要件 価値
サポートされる最小クライアント Windows XP [デスクトップ アプリのみ]
サポートされる最小サーバー Windows Server 2003 [デスクトップ アプリのみ]
ターゲット プラットフォーム の ウィンドウズ
ヘッダー processthreadsapi.h (Windows.h を含む)
ライブラリ Advapi32.lib
DLL Advapi32.dll

関連項目

CloseHandle の

CreateEnvironmentBlock の

CreateProcess の

CreateProcessWithLogonW の

ExitProcess の

GetEnvironmentStrings の

GetExitCodeProcess の

GetStartupInfo の

ImpersonateLoggedOnUser

LoadUserProfile の

PROCESS_INFORMATION

プロセス関数とスレッド関数の

プロセスの

SECURITY_ATTRIBUTES

SHCreateProcessAsUserW を する

STARTUPINFO を する

STARTUPINFOEX を する

SetErrorMode の

WaitForInputIdle の