Funzione CreateProcessA (processthreadsapi.h)
Crea un nuovo processo e il relativo thread primario. Il nuovo processo viene eseguito nel contesto di sicurezza del processo chiamante.
Se il processo chiamante rappresenta un altro utente, il nuovo processo usa il token per il processo chiamante, non il token di rappresentazione. Per eseguire il nuovo processo nel contesto di sicurezza dell'utente rappresentato dal token di rappresentazione, usare la funzione CreateProcessAsUser o CreateProcessWithLogonW .
Sintassi
BOOL CreateProcessA(
[in, optional] LPCSTR lpApplicationName,
[in, out, optional] LPSTR lpCommandLine,
[in, optional] LPSECURITY_ATTRIBUTES lpProcessAttributes,
[in, optional] LPSECURITY_ATTRIBUTES lpThreadAttributes,
[in] BOOL bInheritHandles,
[in] DWORD dwCreationFlags,
[in, optional] LPVOID lpEnvironment,
[in, optional] LPCSTR lpCurrentDirectory,
[in] LPSTARTUPINFOA lpStartupInfo,
[out] LPPROCESS_INFORMATION lpProcessInformation
);
Parametri
[in, optional] lpApplicationName
Nome del modulo da eseguire. Questo modulo può essere un'applicazione basata su Windows. Può trattarsi di 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 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 viene utilizzata 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 utilizza un nome di file lungo contenente uno spazio, utilizzare stringhe tra 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.exe
- c:\program files\sub.exe
- c:\programmi\dir\program.exesecondario
- c:\programmi\sub dir\program name.exe
Se il modulo eseguibile è un'applicazione a 16 bit, lpApplicationName deve essere NULL e la stringa a cui punta lpCommandLine deve specificare il modulo eseguibile e i relativi argomenti.
Per eseguire un file batch, è necessario avviare l'interprete dei comandi; impostare lpApplicationName su cmd.exe e impostare lpCommandLine sui seguenti argomenti: /c più il nome del file batch.
Importante
Il team di progettazione MSRC consiglia di farlo. Per altri dettagli, vedere MS14-019 - Correzione di un hijack binario tramite .cmd o .bat file .
[in, out, optional] lpCommandLine
Riga di comando da eseguire.
La lunghezza massima di questa stringa è di 32.767 caratteri, incluso il carattere Di terminazione Unicode null. Se lpApplicationName è NULL, la parte del nome del modulo di lpCommandLine è limitata a MAX_PATH caratteri.
La versione Unicode di questa funzione , CreateProcessW, 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 tal caso, la funzione usa la stringa a cui punta lpApplicationName come riga di comando.
Se sia lpApplicationName che lpCommandLine sono diversi da NULL, la stringa con terminazione Null a cui punta lpApplicationName specifica il modulo da eseguire e la stringa con terminazione Null a cui punta 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 in genere ripetono 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 che contiene uno spazio, usare stringhe tra 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 accodato. Pertanto, se l'estensione del nome file è .com, questo parametro deve includere l'estensione .com. Se il nome del file termina con un punto (.) senza estensione o se il nome del file contiene un percorso, .exe non viene accodato. Se il nome 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. Il nome di questa directory è System.
- 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 esegue la ricerca nel 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, optional] lpProcessAttributes
Puntatore a una struttura SECURITY_ATTRIBUTES che determina se l'handle restituito al nuovo oggetto processo può essere ereditato dai processi figlio. Se lpProcessAttributes è NULL, l'handle non può essere ereditato.
Il membro lpSecurityDescriptor della struttura specifica un descrittore di sicurezza per il nuovo processo. Se lpProcessAttributes è NULL o lpSecurityDescriptor è NULL, il processo ottiene un descrittore di sicurezza predefinito. Gli ACL nel descrittore di sicurezza predefinito per un processo provengono dal token primario dell'autore. Windows XP: Gli ACL nel descrittore di sicurezza predefinito per un processo provengono dal token primario o di rappresentazione del creatore. Questo comportamento è cambiato con Windows XP con SP2 e Windows Server 2003.
[in, optional] lpThreadAttributes
Puntatore a una struttura SECURITY_ATTRIBUTES che determina se l'handle restituito al nuovo oggetto thread può essere ereditato dai processi figlio. Se lpThreadAttributes è NULL, l'handle non può essere ereditato.
Il membro lpSecurityDescriptor della struttura specifica un descrittore di sicurezza per il thread principale. Se lpThreadAttributes è NULL o lpSecurityDescriptor è NULL, il thread ottiene un descrittore di sicurezza predefinito. Gli ACL nel descrittore di sicurezza predefinito per un thread provengono dal token di processo. Windows XP: Gli ACL nel descrittore di sicurezza predefinito per un thread provengono dal token primario o di rappresentazione del creatore. Questo comportamento è cambiato con Windows XP con SP2 e Windows Server 2003.
[in] bInheritHandles
Se questo parametro è TRUE, ogni handle ereditabile nel processo chiamante viene ereditato dal nuovo processo. Se il parametro è FALSE, gli handle non vengono ereditati. Si noti che gli handle ereditati hanno lo stesso valore e gli stessi diritti di accesso degli handle originali. Per altre informazioni sugli handle ereditabili, vedere Osservazioni.
Servizi terminal: Non è possibile ereditare handle tra le sessioni. Inoltre, se questo parametro è TRUE, è necessario creare il processo nella stessa sessione del chiamante.
Processi PPL (Protected Process Light): L'ereditarietà dell'handle generico viene bloccata quando un processo PPL crea un processo non PPL perché PROCESS_DUP_HANDLE non è consentito da un processo non PPL a un processo PPL. Vedere Sicurezza dei processi e diritti di accesso
Windows 7: STD_INPUT_HANDLE, STD_OUTPUT_HANDLE e STD_ERROR_HANDLE vengono ereditati, anche quando il parametro è FALSE.
[in] dwCreationFlags
Flag che controllano la classe priority e la creazione del processo. Per un elenco di valori, vedere Flag di creazione del processo.
Questo parametro controlla anche la classe di priorità del nuovo processo, che viene usata per determinare le priorità di pianificazione dei thread del processo. Per un elenco di valori, vedere GetPriorityClass. Se non viene specificato alcun flag della classe di priorità, per impostazione predefinita la classe priority viene 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 eredita sia la modalità di errore del chiamante che la console dell'elemento padre.
- 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 dos virtuale condivisa (VDM).
[in, optional] lpEnvironment
Puntatore al blocco dell'ambiente per il nuovo processo. Se questo parametro è NULL, il nuovo processo usa l'ambiente del processo chiamante.
Un blocco di ambiente è costituito da un blocco con terminazione Null di stringhe con terminazione Null. Ogni stringa è nel formato seguente:
Nome=value\0
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.
La versione ANSI di questa funzione, CreateProcessA ha esito negativo se la dimensione totale del blocco di ambiente per il processo supera i 32.767 caratteri.
Si noti che 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, altre due per terminare il blocco.
[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 .
Per impostare gli attributi estesi, usare una struttura STARTUPINFOEX e specificare EXTENDED_STARTUPINFO_PRESENT nel parametro dwCreationFlags .
Gli handle in STARTUPINFO o STARTUPINFOEX devono essere chiusi con CloseHandle quando non sono più necessari.
Importante
Il chiamante è responsabile di garantire che i campi handle standard in STARTUPINFO contengano valori di handle validi. Questi campi vengono copiati invariati nel processo figlio senza convalida, anche quando il membro dwFlags specifica STARTF_USESTDHANDLES. I valori non corretti possono causare errori di comportamento o arresto anomalo del processo figlio. Usare lo strumento di verifica del runtime application verifier per rilevare handle non validi.
[out] lpProcessInformation
Puntatore a una struttura di PROCESS_INFORMATION che riceve informazioni di identificazione sul nuovo processo.
Gli handle in PROCESS_INFORMATION devono essere chiusi con 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
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 nella struttura PROCESS_INFORMATION .
Il nome dell'eseguibile nella riga di comando fornito dal sistema operativo a un processo non è necessariamente identico a quello nella riga di comando assegnato dal processo chiamante alla funzione CreateProcess . Il sistema operativo può anteporre un percorso completo a un nome eseguibile fornito senza un percorso completo.
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é CreateProcess viene restituito 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.
Un processo padre può modificare direttamente le variabili di ambiente di un processo figlio durante la creazione del processo. Questa è l'unica situazione in cui un processo può modificare direttamente le impostazioni di ambiente di un altro processo. Per altre informazioni, vedere Modifica delle variabili di ambiente.
Se un'applicazione fornisce un blocco di ambiente, le informazioni sulla directory correnti delle unità di sistema non vengono propagate automaticamente al nuovo processo. Ad esempio, esiste una variabile di ambiente denominata =C: il cui valore è la directory corrente nell'unità C. Un'applicazione deve passare manualmente le informazioni sulla directory corrente al nuovo processo. A tale scopo, l'applicazione deve creare in modo esplicito queste stringhe di variabili di ambiente, ordinarle in ordine alfabetico (perché il sistema usa un ambiente ordinato) e inserirle nel blocco di ambiente. In genere, si troveranno all'inizio del blocco di ambiente, a causa dell'ordinamento dei blocchi dell'ambiente.
Un modo per ottenere le informazioni sulla directory corrente per un'unità X consiste nell'effettuare la chiamata seguente: . GetFullPathName("X:", ...)
In questo modo si evita che un'applicazione abbia la necessità di analizzare il blocco di ambiente. Se il percorso completo restituito è X:, non è necessario passare tale valore come dati dell'ambiente, poiché la directory radice è la directory corrente predefinita per l'unità X di un nuovo processo.
Quando viene creato un processo con CREATE_NEW_PROCESS_GROUP specificato, viene eseguita una chiamata implicita a SetConsoleCtrlHandler(NULL,TRUE) per conto del nuovo processo; ciò significa che il nuovo processo ha CTRL+C disabilitato. In questo modo le shell gestiscono autonomamente CTRL+C e passano selettivamente tale segnale ai sotto-processi. CTRL+INTERR non è disabilitato e può essere usato per interrompere il gruppo di processi/processi.
Per impostazione predefinita, passando TRUE come valore del parametro bInheritHandles , tutti gli handle ereditabili vengono ereditati dal nuovo processo. Questo problema può essere problematico per le applicazioni che creano processi da più thread contemporaneamente, ma desiderano che ogni processo erediti handle diversi. Le applicazioni possono usare la funzione UpdateProcThreadAttributeList con il parametro PROC_THREAD_ATTRIBUTE_HANDLE_LIST per fornire un elenco di handle da ereditare da un processo specifico.
Osservazioni sulla sicurezza
Il primo parametro, lpApplicationName, può essere NULL, nel qual caso il nome eseguibile deve trovarsi nella stringa delimitata da spazi vuoti a cui punta 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 = _tcsdup(TEXT("C:\\Program Files\\MyApp -L -S"));
CreateProcess(NULL, szCmdline, /* ... */);
Se un utente malintenzionato dovesse creare un'applicazione denominata "Program.exe" in un sistema, qualsiasi programma che chiama erroneamente CreateProcess 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[] = _tcsdup(TEXT("\"C:\\Program Files\\MyApp\" -L -S"));
CreateProcess(NULL, szCmdline, /*...*/);
Esempio
Per un esempio, vedere Creazione di processi.
Nota
L'intestazione processthreadsapi.h definisce CreateProcess come alias che seleziona automaticamente la versione ANSI o Unicode di questa funzione in base alla definizione della costante del preprocessore UNICODE. La combinazione dell'utilizzo dell'alias indipendente dalla codifica con il codice che non è indipendente dalla codifica può causare mancate corrispondenze che generano errori di compilazione o di runtime. Per altre informazioni, vedere Convenzioni per i prototipi di funzioni.
Requisiti
Requisito | Valore |
---|---|
Client minimo supportato | Windows XP [app desktop | App UWP] |
Server minimo supportato | Windows Server 2003 [app desktop | App UWP] |
Piattaforma di destinazione | Windows |
Intestazione | processthreadsapi.h (include Windows.h in Windows Server 2003, Windows Vista, Windows 7, Windows Server 2008 Windows Server 2008 R2) |
Libreria | Kernel32.lib |
DLL | Kernel32.dll |