Funzione CreateProcessWithTokenW (winbase.h)
Crea un nuovo processo e il relativo thread primario. Il nuovo processo viene eseguito nel contesto di sicurezza del token specificato. Facoltativamente, è possibile caricare il profilo utente per l'utente specificato.
Il processo che chiama CreateProcessWithTokenW deve avere il privilegio di SE_IMPERSONATE_NAME. Se questa funzione ha esito negativo con ERROR_PRIVILEGE_NOT_HELD (1314), usare invece la funzione CreateProcessAsUser o CreateProcessWithLogonW . In genere, il processo che chiama
CreateProcessAsUser deve avere il privilegio SE_INCREASE_QUOTA_NAME e può richiedere il privilegio SE_ASSIGNPRIMARYTOKEN_NAME se il token non è assegnabile. CreateProcessWithLogonW non richiede privilegi speciali, ma l'account utente specificato deve essere autorizzato ad accedere in modo interattivo. In genere, è consigliabile usare CreateProcessWithLogonW per creare un processo con credenziali alternative.
Sintassi
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
);
Parametri
[in] hToken
Handle al token primario che rappresenta un utente. L'handle deve avere i diritti di accesso TOKEN_QUERY, TOKEN_DUPLICATE e TOKEN_ASSIGN_PRIMARY. Per altre informazioni, vedere Diritti di accesso per gli oggetti Access-Token. L'utente rappresentato dal token deve avere accesso in lettura ed eseguire l'accesso all'applicazione specificata dal parametro lpApplicationName o lpCommandLine .
Per ottenere un token primario che rappresenta l'utente specificato, chiamare la funzione LogonUser . In alternativa, è possibile chiamare la funzione DuplicateTokenEx per convertire un token di rappresentazione in un token primario. Ciò consente a un'applicazione server che rappresenta un client di creare un processo con il contesto di sicurezza del client.
Servizi terminal: Il processo del chiamante viene sempre eseguito nella sessione del chiamante, non nella sessione specificata nel token. Per eseguire un processo nella sessione specificata nel token, usare la funzione CreateProcessAsUser.
[in] dwLogonFlags
Opzione di accesso. Questo parametro può essere zero o uno dei valori seguenti.
[in, optional] lpApplicationName
Nome del modulo da eseguire. Questo modulo può essere un'applicazione basata su Windows. Può essere un altro tipo di modulo, ad esempio MS-DOS o OS/2, se il sottosistema appropriato è disponibile nel computer locale.
La stringa può specificare il percorso completo e il nome del file del modulo da eseguire oppure può specificare un nome parziale. Nel caso di un nome parziale, la funzione usa l'unità corrente e la directory corrente per completare la specifica. La funzione non userà il percorso di ricerca. Questo parametro deve includere l'estensione del nome file; non si presuppone alcuna estensione predefinita.
Il parametro lpApplicationName può essere NULL. In tal caso, il nome del modulo deve essere il primo token delimitato da spazi vuoti nella stringa lpCommandLine . Se si usa un nome di file lungo che contiene uno spazio, usare stringhe con virgolette per indicare dove termina il nome del file e gli argomenti iniziano; in caso contrario, il nome del file è ambiguo. Si consideri ad esempio la stringa "c:\program files\sub dir\program name". Questa stringa può essere interpretata in diversi modi. Il sistema tenta di interpretare le possibilità nell'ordine seguente:
c:\program.exec:\program files\sub.exec:\program files\sub dir\program.exec:\program files \sub dir\program name.exe Se il modulo eseguibile è un'applicazione a 16 bit, lpApplicationName deve essere NULL e la stringa puntata a lpCommandLine deve specificare il modulo eseguibile e i relativi argomenti.
[in, out, optional] lpCommandLine
Riga di comando da eseguire.
La lunghezza massima di questa stringa è di 1024 caratteri. Se lpApplicationName è NULL, la parte del nome del modulo di lpCommandLine è limitata a MAX_PATH caratteri.
La funzione può modificare il contenuto di questa stringa. Pertanto, questo parametro non può essere un puntatore alla memoria di sola lettura,ad esempio una variabile const o una stringa letterale. Se questo parametro è una stringa costante, la funzione può causare una violazione di accesso.
Il parametro lpCommandLine può essere NULL. In questo caso, la funzione usa la stringa puntata da lpApplicationName come riga di comando.
Se sia lpApplicationName che lpCommandLine non sono NULL, *lpApplicationName specifica il modulo da eseguire e *lpCommandLine specifica la riga di comando. Il nuovo processo può usare GetCommandLine per recuperare l'intera riga di comando. I processi della console scritti in C possono usare gli argomenti argc e argv per analizzare la riga di comando. Poiché argv[0] è il nome del modulo, i programmatori C ripetano in genere il nome del modulo come primo token nella riga di comando.
Se lpApplicationName è NULL, il primo token delimitato da spazi vuoti della riga di comando specifica il nome del modulo. Se si usa un nome di file lungo contenente uno spazio, usare stringhe virgolette per indicare dove termina il nome del file e gli argomenti iniziano (vedere la spiegazione per il parametro lpApplicationName ). Se il nome del file non contiene un'estensione, .exe viene aggiunto. Pertanto, se l'estensione del nome file è .com, questo parametro deve includere l'estensione .com. Se il nome del file termina in un punto (.) senza estensione o se il nome del file contiene un percorso, .exe non viene aggiunto. Se il nome del file non contiene un percorso di directory, il sistema cerca il file eseguibile nella sequenza seguente:
- Directory da cui è stata caricata l'applicazione.
- Directory corrente per il processo padre.
- Directory di sistema Windows a 32 bit. Usare la funzione GetSystemDirectory per ottenere il percorso di questa directory.
- Directory di sistema Windows a 16 bit. Non esiste alcuna funzione che ottiene il percorso di questa directory, ma viene eseguita la ricerca.
- La directory Windows. Usare la funzione GetWindowsDirectory per ottenere il percorso di questa directory.
- Directory elencate nella variabile di ambiente PATH. Si noti che questa funzione non cerca il percorso per applicazione specificato dalla chiave del Registro di sistema Percorsi app . Per includere questo percorso per applicazione nella sequenza di ricerca, usare la funzione ShellExecute .
[in] dwCreationFlags
Flag che controllano la modalità di creazione del processo. I flag CREATE_DEFAULT_ERROR_MODE, CREATE_NEW_CONSOLE e CREATE_NEW_PROCESS_GROUP sono abilitati per impostazione predefinita. Per un elenco di valori, vedere Flag di creazione dei processi.
Questo parametro controlla anche la classe priorità del nuovo processo, usata per determinare le priorità di pianificazione dei thread del processo. Per un elenco di valori, vedere GetPriorityClass. Se non viene specificato alcun flag di classe priorità, la classe priorità viene predefinita per NORMAL_PRIORITY_CLASS a meno che la classe di priorità del processo di creazione non sia IDLE_PRIORITY_CLASS o BELOW_NORMAL_PRIORITY_CLASS. In questo caso, il processo figlio riceve la classe di priorità predefinita del processo chiamante.
Se il parametro dwCreationFlags ha un valore pari a 0:
- Il processo ottiene la modalità di errore predefinita, crea una nuova console e crea un nuovo gruppo di processi.
- Si presuppone che il blocco di ambiente per il nuovo processo contenga caratteri ANSI (vedere il parametro lpEnvironment per altre informazioni).
- Un'applicazione basata su Windows a 16 bit viene eseguita in una macchina virtuale virtuale condivisa (VDM).
[in, optional] lpEnvironment
Puntatore a un blocco di ambiente per il nuovo processo. Se questo parametro è NULL, il nuovo processo usa un ambiente creato dal profilo dell'utente specificato da lpUsername.
Un blocco di ambiente è costituito da un blocco con terminazione Null di stringhe con terminazione Null. Ogni stringa è nel formato seguente:
Nome=Valore
Poiché il segno di uguale (=) viene usato come separatore, non deve essere usato nel nome di una variabile di ambiente.
Un blocco di ambiente può contenere caratteri Unicode o ANSI. Se il blocco di ambiente a cui punta lpEnvironment contiene caratteri Unicode, assicurarsi che dwCreationFlags includa CREATE_UNICODE_ENVIRONMENT.
Un blocco di ambiente ANSI viene terminato da due byte zero: uno per l'ultima stringa, uno per terminare il blocco. Un blocco di ambiente Unicode viene terminato da quattro byte zero: due per l'ultima stringa e altre due per terminare il blocco.
Per recuperare una copia del blocco di ambiente per un utente specifico, usare la funzione CreateEnvironmentBlock .
[in, optional] lpCurrentDirectory
Percorso completo della directory corrente per il processo. La stringa può anche specificare un percorso UNC.
Se questo parametro è NULL, il nuovo processo avrà la stessa unità e la stessa directory correnti del processo chiamante. Questa funzionalità viene fornita principalmente per le shell che devono avviare un'applicazione e specificare l'unità iniziale e la directory di lavoro.
[in] lpStartupInfo
Puntatore a una struttura STARTUPINFO o STARTUPINFOEX .
Se il membro lpDesktop è NULL o una stringa vuota, il nuovo processo eredita il desktop e la stazione finestra del processo padre. La funzione aggiunge l'autorizzazione per l'account utente specificato alla stazione della finestra ereditata e al desktop. In caso contrario, se questo membro specifica un desktop, è responsabilità dell'applicazione aggiungere l'autorizzazione per l'account utente specificato alla stazione della finestra e al desktop specificati, anche per WinSta0\Default.
Gli handle in STARTUPINFO o STARTUPINFOEX devono essere chiusi con CloseHandle quando non sono più necessari.
[out] lpProcessInformation
Puntatore a una struttura PROCESS_INFORMATION che riceve informazioni di identificazione per il nuovo processo, incluso un handle per il processo.
Gli handle in PROCESS_INFORMATION devono essere chiusi con la funzione CloseHandle quando non sono più necessari.
Valore restituito
Se la funzione ha esito positivo, il valore restituito è diverso da zero.
Se la funzione ha esito negativo, il valore restituito è zero. Per informazioni dettagliate sull'errore, chiamare GetLastError.
Si noti che la funzione viene restituita prima che il processo abbia terminato l'inizializzazione. Se non è possibile individuare o non inizializzare una DLL necessaria, il processo viene terminato. Per ottenere lo stato di terminazione di un processo, chiamare GetExitCodeProcess.
Commenti
Per impostazione predefinita, CreateProcessWithTokenW non carica il profilo dell'utente specificato nella chiave del Registro di sistema HKEY_USERS . Ciò significa che l'accesso alle informazioni nella chiave del Registro di sistema HKEY_CURRENT_USER potrebbe non produrre risultati coerenti con un normale accesso interattivo. È responsabilità dell'utente caricare l'hive del Registro di sistema dell'utente in HKEY_USERS usando LOGON_WITH_PROFILE oppure chiamando la funzione LoadUserProfile prima di chiamare questa funzione.
Se il parametro lpEnvironment è NULL, il nuovo processo usa un blocco di ambiente creato dal profilo dell'utente specificato da lpUserName. Se le variabili HOMEDRIVE e HOMEPATH non sono impostate, CreateProcessWithTokenW modifica il blocco di ambiente per usare l'unità e il percorso della directory di lavoro dell'utente.
Al momento della creazione, il nuovo processo e gli handle di thread ricevono diritti di accesso completi (PROCESS_ALL_ACCESS e THREAD_ALL_ACCESS). Per entrambi gli handle, se non viene fornito un descrittore di sicurezza, l'handle può essere usato in qualsiasi funzione che richiede un handle oggetto di tale tipo. Quando viene fornito un descrittore di sicurezza, viene eseguito un controllo di accesso su tutti gli usi successivi dell'handle prima che venga concesso l'accesso. Se l'accesso viene negato, il processo di richiesta non può usare l'handle per ottenere l'accesso al processo o al thread.
Per recuperare un token di sicurezza, passare l'handle di processo nella struttura PROCESS_INFORMATION alla funzione OpenProcessToken .
Al processo viene assegnato un identificatore di processo. L'identificatore è valido fino al termine del processo. Può essere usato per identificare il processo o specificato nella funzione OpenProcess per aprire un handle per il processo. Al thread iniziale nel processo viene assegnato anche un identificatore di thread. Può essere specificato nella funzione OpenThread per aprire un handle al thread. L'identificatore è valido fino al termine del thread e può essere usato per identificare in modo univoco il thread all'interno del sistema. Questi identificatori vengono restituiti in PROCESS_INFORMATION.
Il thread chiamante può usare la funzione WaitForInputIdle per attendere il completamento dell'inizializzazione del nuovo processo ed è in attesa dell'input dell'utente senza input in sospeso. Ciò può essere utile per la sincronizzazione tra processi padre e figlio, perché CreateProcessWithTokenW restituisce senza attendere il completamento dell'inizializzazione del nuovo processo. Ad esempio, il processo di creazione usa WaitForInputIdle prima di cercare una finestra associata al nuovo processo.
Il modo preferito per arrestare un processo consiste nell'usare la funzione ExitProcess , perché questa funzione invia una notifica relativa all'avvicinamento della terminazione a tutte le DLL collegate al processo. Altri mezzi per arrestare un processo non notificano le DLL associate. Si noti che quando un thread chiama ExitProcess, gli altri thread del processo vengono terminati senza la possibilità di eseguire codice aggiuntivo (incluso il codice di terminazione del thread delle DLL collegate). Per altre informazioni, vedere Terminazione di un processo.
Per compilare un'applicazione che usa questa funzione, definire _WIN32_WINNT come 0x0500 o versione successiva. Per altre informazioni, vedere Uso delle intestazioni di Windows.
Osservazioni sulla sicurezza
Il parametro lpApplicationName può essere NULL, nel qual caso il nome eseguibile deve essere la prima stringa delimitata da spazi vuoti in lpCommandLine. Se il nome dell'eseguibile o del percorso contiene uno spazio, esiste il rischio che sia possibile eseguire un file eseguibile diverso a causa del modo in cui la funzione analizza gli spazi. L'esempio seguente è pericoloso perché la funzione tenterà di eseguire "Program.exe", se esistente, anziché "MyApp.exe". LPTSTR szCmdline = L"C:\\Program Files\\MyApp";
CreateProcessWithTokenW(/*...*/, szCmdline, /*...*/);
Se un utente malintenzionato dovesse creare un'applicazione denominata "Program.exe" in un sistema, qualsiasi programma che chiama erroneamente CreateProcessWithTokenW usando la directory Programmi eseguirà questa applicazione anziché l'applicazione desiderata.
Per evitare questo problema, non passare NULL per lpApplicationName. Se si passa NULL per lpApplicationName, usare le virgolette intorno al percorso eseguibile in lpCommandLine, come illustrato nell'esempio seguente.
LPTSTR szCmdline = L"\"C:\\Program Files\\MyApp\"";
CreateProcessWithTokenW(/*...*/, szCmdline, /*...*/);
Requisiti
Requisito | Valore |
---|---|
Client minimo supportato | Windows Vista [solo app desktop] |
Server minimo supportato | Windows Server 2003 [solo app desktop] |
Piattaforma di destinazione | Windows |
Intestazione | winbase.h (include Windows.h) |
Libreria | Advapi32.lib |
DLL | Advapi32.dll |