createProcessWithTokenW 函式 (winbase.h)

建立新的進程及其主要線程。 新的進程會在指定之令牌的安全性內容中執行。 它可以選擇性地載入指定使用者的使用者配置檔。

呼叫 CreateProcessWithTokenW 的程式必須具有SE_IMPERSONATE_NAME許可權。 如果此函式因 ERROR_PRIVILEGE_NOT_HELD (1314) 而失敗,請改用 CreateProcessAsUserCreateProcessWithLogonW 函式。 一般而言,呼叫的進程
CreateProcessAsUser 必須具有SE_INCREASE_QUOTA_NAME許可權,而且如果無法指派令牌,可能需要SE_ASSIGNPRIMARYTOKEN_NAME許可權。 CreateProcessWithLogonW 不需要特殊許可權,但必須允許指定的用戶帳戶以互動方式登入。 一般而言,最好使用 CreateProcessWithLogonW 來建立具有替代認證的進程。

語法

BOOL CreateProcessWithTokenW(
  [in]                HANDLE                hToken,
  [in]                DWORD                 dwLogonFlags,
  [in, optional]      LPCWSTR               lpApplicationName,
  [in, out, optional] LPWSTR                lpCommandLine,
  [in]                DWORD                 dwCreationFlags,
  [in, optional]      LPVOID                lpEnvironment,
  [in, optional]      LPCWSTR               lpCurrentDirectory,
  [in]                LPSTARTUPINFOW        lpStartupInfo,
  [out]               LPPROCESS_INFORMATION lpProcessInformation
);

參數

[in] hToken

代表使用者之主要令牌的句柄。 句柄必須具有TOKEN_QUERY、TOKEN_DUPLICATE和TOKEN_ASSIGN_PRIMARY訪問許可權。 如需詳細資訊,請參閱 Access-Token 對象的訪問許可權。 令牌所代表的用戶必須具有 lpApplicationNamelpCommandLine 參數所指定之應用程式的讀取和執行存取權。

若要取得代表指定使用者的主要令牌,請呼叫 LogonUser函 式。 或者,您可以呼叫 DuplicateTokenEx 函 式,將模擬令牌轉換成主要令牌。 這可讓模擬用戶端的伺服器應用程式建立具有用戶端安全性內容的進程。

終端機服務: 呼叫端的進程一律會在呼叫端的會話中執行,而不是在令牌中指定的會話中執行。 若要在令牌中指定的會話中執行進程,請使用 CreateProcessAsUser 函式。

[in] dwLogonFlags

登入選項。 此參數可以是零或下列其中一個值。

意義
LOGON_WITH_PROFILE
0x00000001
登入,然後在 HKEY_USERS 登錄機碼中載入使用者的配置檔。 函式會在載入配置檔之後傳回。 載入配置檔可能很耗時,因此只有在您必須存取 HKEY_CURRENT_USER 登錄機碼中的資訊時,才最好使用此值。

Windows Server 2003: 不論配置檔是否已建立子進程,配置檔都會在終止新進程之後卸除。

LOGON_NETCREDENTIALS_ONLY
0x00000002
登入,但只在網路上使用指定的認證。 新進程會使用與呼叫端相同的令牌,但系統會在 LSA 內建立新的登入工作階段,而進程會使用指定的認證作為預設認證。

這個值可用來在本機建立一組與遠端不同的認證的程式。 這在網域間沒有信任關係的情況下很有用。

系統不會驗證指定的認證。 因此,進程可以啟動,但可能無法存取網路資源。

[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 指向的字符串應該指定可執行文件模組及其自變數。

[in, out, optional] lpCommandLine

要執行的命令行。

此字串的最大長度為1024個字元。 如果 lpApplicationNameNULL,lpCommandLine 的模組名稱部分限制為MAX_PATH個字元。

函式可以修改此字串的內容。 因此,此參數不能是唯讀記憶體 (指標,例如 const 變數或常值字串) 。 如果此參數是常數位符串,函式可能會造成存取違規。

lpCommandLine 參數可以是 NULL。 在此情況下,函式會使用 lpApplicationName 指向的字串作為命令行。

如果 lpApplicationNamelpCommandLine 都是非 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 字元新增至命令行字串,以分隔檔名與自變數。 這會將原始字串分割成兩個字串以供內部處理。

[in] dwCreationFlags

控制進程建立方式的旗標。 默認會啟用CREATE_DEFAULT_ERROR_MODE、CREATE_NEW_CONSOLE和CREATE_NEW_PROCESS_GROUP旗標。 如需值清單,請參閱 進程建立旗標

此參數也會控制新進程的優先順序類別,用來判斷進程線程的排程優先順序。 如需值清單,請參閱 GetPriorityClass。 如果未指定任何優先順序類別旗標,除非建立程式的優先順序類別IDLE_PRIORITY_CLASS或BELOW_NORMAL_PRIORITY_CLASS,否則優先順序類別預設為NORMAL_PRIORITY_CLASS。 在此情況下,子進程會收到呼叫進程的預設優先順序類別。

如果 dwCreationFlags 參數的值為 0:

  • 進程會取得預設錯誤模式、建立新的控制台,並建立新的進程群組。
  • 假設新進程的環境區塊包含 ANSI 字元, (請參閱 lpEnvironment 參數以取得) 的其他資訊。
  • 以 16 位 Windows 為基礎的應用程式會在共用的 Virtual DOS 機器中執行, (VDM) 。

[in, optional] lpEnvironment

新進程的環境區塊指標。 如果此參數為 NULL,新進程會使用從 lpUsername 所指定使用者的設定檔建立的環境。

環境區塊是由 Null 終止字串的 Null 終止區塊所組成。 每個字串的格式如下:

名字=價值

因為等號 (=) 做為分隔符,所以不能用在環境變數的名稱中。

環境區塊可以包含 Unicode 或 ANSI 字元。 如果 lpEnvironment 指向的環境區塊包含 Unicode 字元,請確定 dwCreationFlags 包含CREATE_UNICODE_ENVIRONMENT。

ANSI 環境區塊會以兩個零位元節終止:一個用於最後一個字元串,另一個則是終止區塊。 Unicode 環境區塊會以四個零位元節終止:最後一個字元串的兩個字節,另外兩個則會終止區塊。

若要擷取特定用戶的環境區塊複本,請使用 CreateEnvironmentBlock 函式。

[in, optional] lpCurrentDirectory

進程目前目錄的完整路徑。 字串也可以指定 UNC 路徑。

如果此參數為 Null,新處理序會有與呼叫處理序相同的目前磁碟機和目錄。 (這項功能主要提供給需要啟動應用程式的殼層,並指定其初始磁碟驅動器和工作目錄。)

[in] lpStartupInfo

STARTUPINFOSTARTUPINFOEX 結構的指標。

如果 lpDesktop 成員為 NULL 或空字串,新進程會繼承其父進程的桌面和視窗月臺。 函式會將指定用戶帳戶的許可權新增至繼承的視窗月臺和桌面。 否則,如果此成員指定桌面,則應用程式會負責將指定使用者帳戶的許可權新增至指定的視窗月臺和桌面,甚至是 WinSta0\Default。

在 STARTUPINFOSTARTUPINFOEX 中的句柄不再需要時,必須使用 CloseHandle 關閉。

重要如果 STARTUPINFO 結構的 dwFlags 成員指定STARTF_USESTDHANDLES,則標準句柄欄位會保持不變地複製到子進程,而不需要驗證。 呼叫端負責確保這些欄位包含有效的句柄值。 不正確的值可能會導致子進程錯誤或當機。 使用 應用程式驗證器 運行時間驗證工具來偵測無效的句柄。
 

[out] lpProcessInformation

PROCESS_INFORMATION結構的指標,可接收新進程的識別資訊,包括進程的句柄。

PROCESS_INFORMATION中的句柄在不再需要時,必須使用 CloseHandle 函式關閉。

傳回值

如果函式成功,則傳回非零的值。

如果此函式失敗,則傳回值為零。 若要取得擴充的錯誤資訊,請呼叫 GetLastError

請注意,函式會在進程完成初始化之前傳回。 如果找不到必要的 DLL 或無法初始化,進程就會終止。 若要取得進程的終止狀態,請呼叫 GetExitCodeProcess

備註

根據預設, CreateProcessWithTokenW 不會將指定的使用者配置檔載入 HKEY_USERS 登錄機碼。 這表示 存取HKEY_CURRENT_USER 登錄機碼中的資訊,可能不會產生與一般互動式登錄一致的結果。 您必須負責使用 LOGON_WITH_PROFILE 或呼叫 LoadUserProfile 函式,再呼叫此函式,將使用者的登錄區載入HKEY_USERS

如果 lpEnvironment 參數為 NULL,新進程會使用從 lpUserName 所指定使用者的配置檔建立的環境區塊。 如果未設定 HOMEDRIVE 和 HOMEPATH 變數, CreateProcessWithTokenW 會修改環境區塊,以使用使用者工作目錄的磁碟驅動器和路徑。

建立時,新的進程和線程句柄會收到完整的訪問許可權 (PROCESS_ALL_ACCESS 和THREAD_ALL_ACCESS) 。 針對任一句柄,如果未提供安全描述項,句柄就可用於任何需要該類型之物件句柄的函式中。 提供安全性描述項時,會在授與存取權之前,對句柄的所有後續使用執行存取檢查。 如果拒絕存取,則要求進程無法使用句柄來存取進程或線程。

若要擷取安全性令牌,請將 PROCESS_INFORMATION 結構中的進程句柄傳遞至 OpenProcessToken 函式。

進程會指派進程標識碼。 標識元有效,直到進程終止為止。 它可用來識別進程,或在 OpenProcess 函式中指定,以開啟進程的句柄。 進程中的初始線程也會指派線程標識碼。 您可以在 OpenThread 函式中指定它,以開啟線程的句柄。 標識元有效,直到線程終止為止,而且可用來唯一識別系統中的線程。 這些標識碼會在 PROCESS_INFORMATION中傳回。

呼叫線程可以使用 WaitForInputIdle 函 式,等到新進程完成初始化,並等候使用者輸入,而沒有擱置的輸入。 這適用於父進程與子進程之間的同步處理,因為 CreateProcessWithTokenW 會傳回,而不需要等待新進程完成其初始化。 例如,建立進程會先使用 WaitForInputIdle ,再嘗試尋找與新進程相關聯的視窗。

關閉行程的慣用方式是使用 ExitProcess 函式,因為此函式會將接近終止的通知傳送至附加至進程的所有 DLL。 關閉進程的其他方法不會通知附加的 DLL。 請注意,當線程呼叫 ExitProcess 時,進程的其他線程會終止,而不會有機會執行任何其他程式碼 (包括附加 DLL 的線程終止程式代碼) 。 如需詳細資訊,請參閱 終止進程

若要編譯使用此函式的應用程式,請將_WIN32_WINNT定義為0x0500或更新版本。 如需詳細資訊,請參閱 使用 Windows 標頭

安全性備註

lpApplicationName 參數可以是 NULL,在此情況下,可執行檔名稱必須是 lpCommandLine 中的第一個空格符分隔字串。 如果可執行檔或路徑名稱有空格,可能會因為函式剖析空格的方式而執行不同的可執行檔。 下列範例很危險,因為函式會在存在時嘗試執行 「Program.exe」,而不是 「MyApp.exe」。
	LPTSTR szCmdline = L"C:\\Program Files\\MyApp";
	CreateProcessWithTokenW(/*...*/, szCmdline, /*...*/);

如果惡意使用者必須在系統上建立名為 「Program.exe」 的應用程式,則使用 Program Files 目錄不正確地呼叫 CreateProcessWithTokenW 的任何程式都會執行此應用程式,而不是預期的應用程式。

若要避免這個問題,請勿傳遞 lpApplicationName 的 NULL。 如果您為 lpApplicationName 傳遞 NULL,請在 lpCommandLine 的可執行文件路徑周圍使用引號,如下列範例所示。

	LPTSTR szCmdline = L"\"C:\\Program Files\\MyApp\"";
	CreateProcessWithTokenW(/*...*/, szCmdline, /*...*/);

規格需求

需求
最低支援的用戶端 Windows Vista [僅限傳統型應用程式]
最低支援的伺服器 Windows Server 2003 [僅限桌面應用程式]
目標平台 Windows
標頭 winbase.h (包含 Windows.h)
程式庫 Advapi32.lib
Dll Advapi32.dll

另請參閱

CloseHandle

CreateEnvironmentBlock

ExitProcess

GetEnvironmentStrings

GetExitCodeProcess

OpenProcess

PROCESS_INFORMATION

處理序和執行緒函式

程序

STARTUPINFO

SetErrorMode

WaitForInputIdle