Partager via


CreateProcessA, fonction (processthreadsapi.h)

Crée un processus et son thread principal. Le nouveau processus s’exécute dans le contexte de sécurité du processus appelant.

Si le processus appelant emprunte l’identité d’un autre utilisateur, le nouveau processus utilise le jeton pour le processus appelant, et non le jeton d’emprunt d’identité. Pour exécuter le nouveau processus dans le contexte de sécurité de l’utilisateur représenté par le jeton d’emprunt d’identité, utilisez la fonction CreateProcessAsUserA ou fonction CreateProcessWithLogonW.

Syntaxe

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
);

Paramètres

[in, optional] lpApplicationName

Nom du module à exécuter. Ce module peut être une application Windows. Il peut s’agir d’un autre type de module (par exemple, MS-DOS ou OS/2) si le sous-système approprié est disponible sur l’ordinateur local.

La chaîne peut spécifier le chemin d’accès complet et le nom de fichier du module à exécuter ou spécifier un nom partiel. Dans le cas d’un nom partiel, la fonction utilise le lecteur actuel et le répertoire actif pour terminer la spécification. La fonction n’utilise pas le chemin de recherche. Ce paramètre doit inclure l’extension de nom de fichier ; aucune extension par défaut n’est supposée.

Le paramètre lpApplicationName peut être NULL. Dans ce cas, le nom du module doit être le premier jeton délimité par un espace blanc dans la chaîne lpCommandLine. Si vous utilisez un nom de fichier long qui contient un espace, utilisez des chaînes entre guillemets pour indiquer où se termine le nom de fichier et les arguments commencent ; sinon, le nom de fichier est ambigu. Par exemple, considérez la chaîne « c :\program files\sub dir\program name ». Cette chaîne peut être interprétée de plusieurs façons. Le système tente d’interpréter les possibilités dans l’ordre suivant :

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

Si le module exécutable est une application 16 bits, lpApplicationName doit être NULL, et la chaîne pointée par lpCommandLine doit spécifier le module exécutable ainsi que ses arguments.

Pour exécuter un fichier de commandes, vous devez démarrer l’interpréteur de commandes ; définissez lpApplicationName sur cmd.exe et définissez lpCommandLine sur les arguments suivants : /c plus le nom du fichier de lots.

Important

L’équipe d’ingénierie MSRC conseille de le faire. Pour plus d’informations, consultez MS14-019 : résolution d’un détournement binaire via .cmd ou .bat fichier.

[in, out, optional] lpCommandLine

Ligne de commande à exécuter.

La longueur maximale de cette chaîne est de 32 767 caractères, y compris le caractère null de fin Unicode. Si lpApplicationName est NULL, la partie nom du module de lpCommandLine est limitée aux caractères MAX_PATH.

La version Unicode de cette fonction, CreateProcessW, peut modifier le contenu de cette chaîne. Par conséquent, ce paramètre ne peut pas être un pointeur vers la mémoire en lecture seule (par exemple, une variable const ou une chaîne littérale). Si ce paramètre est une chaîne constante, la fonction peut provoquer une violation d’accès.

Le paramètre lpCommandLine peut être NULL. Dans ce cas, la fonction utilise la chaîne pointée par lpApplicationName comme ligne de commande.

Si lpApplicationName et lpCommandLine ne sont pasNULL, la chaîne terminée par null pointée par lpApplicationName spécifie le module à exécuter et la chaîne terminée par null pointée par lpCommandLine spécifie la ligne de commande. Le nouveau processus peut utiliser GetCommandLine pour récupérer l’intégralité de la ligne de commande. Les processus de console écrits en C peuvent utiliser les argc et arguments argv pour analyser la ligne de commande. Étant donné que argv[0] est le nom du module, les programmeurs C répètent généralement le nom du module comme premier jeton dans la ligne de commande.

Si lpApplicationName a la valeur NULL, le premier jeton délimité par un espace blanc de la ligne de commande spécifie le nom du module. Si vous utilisez un nom de fichier long qui contient un espace, utilisez des chaînes entre guillemets pour indiquer où se termine le nom de fichier et les arguments commencent (voir l’explication du paramètre lpApplicationName). Si le nom de fichier ne contient pas d’extension, .exe est ajouté. Par conséquent, si l’extension de nom de fichier est .com, ce paramètre doit inclure l’extension .com. Si le nom de fichier se termine par un point (.) sans extension ou si le nom de fichier contient un chemin d’accès, .exe n’est pas ajouté. Si le nom de fichier ne contient pas de chemin d’accès au répertoire, le système recherche le fichier exécutable dans la séquence suivante :

  • Répertoire à partir duquel l’application a chargé.
  • Répertoire actif du processus parent.
  • Répertoire système Windows 32 bits. Utilisez la fonction GetSystemDirectoryA fonction pour obtenir le chemin d’accès de ce répertoire.
  • Répertoire système Windows 16 bits. Il n’existe aucune fonction qui obtient le chemin d’accès de ce répertoire, mais elle est recherchée. Le nom de ce répertoire est System.
  • Répertoire Windows. Utilisez la fonction GetWindowsDirectoryA pour obtenir le chemin d’accès de ce répertoire.
  • Répertoires répertoriés dans la variable d’environnement PATH. Notez que cette fonction ne recherche pas le chemin d’accès par application spécifié par chemins d’accès d’application clé de Registre. Pour inclure ce chemin par application dans la séquence de recherche, utilisez la fonction ShellExecute.

Le système ajoute un caractère null de fin à la chaîne de ligne de commande pour séparer le nom de fichier des arguments. Cela divise la chaîne d’origine en deux chaînes pour le traitement interne.

[in, optional] lpProcessAttributes

Pointeur vers une structure SECURITY_ATTRIBUTES qui détermine si le handle retourné vers le nouvel objet de processus peut être hérité par les processus enfants. Si lpProcessAttributes est NULL, le handle ne peut pas être hérité.

Le lpSecurityDescriptor membre de la structure spécifie un descripteur de sécurité pour le nouveau processus. Si lpProcessAttributes a la valeur NULL ou lpSecurityDescriptor est NULL, le processus obtient un descripteur de sécurité par défaut. Les listes de contrôle d’accès dans le descripteur de sécurité par défaut pour un processus proviennent du jeton principal du créateur. Windows XP : les listes de contrôle d’accès dans le descripteur de sécurité par défaut pour un processus proviennent du jeton principal ou d’emprunt d’identité du créateur. Ce comportement a changé avec Windows XP avec SP2 et Windows Server 2003.

[in, optional] lpThreadAttributes

Pointeur vers une structure SECURITY_ATTRIBUTES qui détermine si le handle retourné vers le nouvel objet thread peut être hérité par les processus enfants. Si lpThreadAttributes a la valeur NULL, le handle ne peut pas être hérité.

Le lpSecurityDescriptor membre de la structure spécifie un descripteur de sécurité pour le thread principal. Si lpThreadAttributes a la valeur NULL ou lpSecurityDescriptor a la valeur NULL, le thread obtient un descripteur de sécurité par défaut. Les listes de contrôle d’accès dans le descripteur de sécurité par défaut d’un thread proviennent du jeton de processus. Windows XP : les listes de contrôle d’accès dans le descripteur de sécurité par défaut d’un thread proviennent du jeton principal ou d’emprunt d’identité du créateur. Ce comportement a changé avec Windows XP avec SP2 et Windows Server 2003.

[in] bInheritHandles

Si ce paramètre a la valeur TRUE, chaque handle pouvant hériter du processus appelant est hérité par le nouveau processus. Si le paramètre est FALSE, les handles ne sont pas hérités. Notez que les handles hérités ont la même valeur et les mêmes droits d’accès que les handles d’origine. Pour plus d’informations sur les handles pouvant être hérités, consultez Remarques.

Services Terminal : Vous ne pouvez pas hériter des handles entre les sessions. En outre, si ce paramètre a la valeur TRUE, vous devez créer le processus dans la même session que l’appelant.

processus PPL (Protected Process Light) : L’héritage de handle générique est bloqué lorsqu’un processus PPL crée un processus non PPL, car PROCESS_DUP_HANDLE n’est pas autorisé d’un processus non PPL à un processus PPL. Consultez des droits d’accès et de sécurité des processus

Windows 7 : STD_INPUT_HANDLE, STD_OUTPUT_HANDLE et STD_ERROR_HANDLE sont hérités, même lorsque le paramètre a la valeur FALSE.

[in] dwCreationFlags

Indicateurs qui contrôlent la classe de priorité et la création du processus. Pour obtenir la liste des valeurs, consultez indicateurs de création de processus.

Ce paramètre contrôle également la classe de priorité du nouveau processus, qui est utilisée pour déterminer les priorités de planification des threads du processus. Pour obtenir la liste des valeurs, consultez GetPriorityClass. Si aucun des indicateurs de classe de priorité n’est spécifié, la classe de priorité est par défaut NORMAL_PRIORITY_CLASS, sauf si la classe de priorité du processus de création est IDLE_PRIORITY_CLASS ou BELOW_NORMAL_PRIORITY_CLASS. Dans ce cas, le processus enfant reçoit la classe de priorité par défaut du processus appelant.

Si le paramètre dwCreationFlags a la valeur 0 :

  • Le processus hérite du mode d’erreur de l’appelant et de la console du parent.
  • Le bloc d’environnement du nouveau processus est supposé contenir des caractères ANSI (consultez paramètre lpEnvironment pour plus d’informations).
  • Une application Windows 16 bits s’exécute dans une machine VIRTUELLE DOS partagée.

[in, optional] lpEnvironment

Pointeur vers le bloc d’environnement pour le nouveau processus. Si ce paramètre est NULL, le nouveau processus utilise l’environnement du processus appelant.

Un bloc d’environnement se compose d’un bloc terminé par null de chaînes terminées par null. Chaque chaîne se présente sous la forme suivante :

nom=valeur\0

Étant donné que le signe égal est utilisé comme séparateur, il ne doit pas être utilisé dans le nom d’une variable d’environnement.

Un bloc d’environnement peut contenir des caractères Unicode ou ANSI. Si le bloc d’environnement pointé par lpEnvironment contient des caractères Unicode, assurez-vous que dwCreationFlags inclut CREATE_UNICODE_ENVIRONMENT.

La version ANSI de cette fonction, CreateProcessA échoue si la taille totale du bloc d’environnement pour le processus dépasse 32 767 caractères.

Notez qu’un bloc d’environnement ANSI est arrêté par deux octets nuls : un pour la dernière chaîne, un autre pour arrêter le bloc. Un bloc d’environnement Unicode est arrêté de quatre octets zéro : deux pour la dernière chaîne, deux autres pour arrêter le bloc.

[in, optional] lpCurrentDirectory

Chemin d’accès complet au répertoire actif du processus. La chaîne peut également spécifier un chemin UNC.

Si ce paramètre est null, le nouveau processus aura le même lecteur et le même répertoire actuels que le processus appelant. (Cette fonctionnalité est fournie principalement pour les interpréteurs de commandes qui doivent démarrer une application et spécifier son lecteur initial et son répertoire de travail.)

[in] lpStartupInfo

Pointeur vers une structure STARTUPINFO ou STARTUPINFOEX.

Pour définir des attributs étendus, utilisez une structure STARTUPINFOEX et spécifiez EXTENDED_STARTUPINFO_PRESENT dans le paramètre dwCreationFlags.

Les handles dans STARTUPINFO ou STARTUPINFOEX doivent être fermés avec closeHandle lorsqu’ils ne sont plus nécessaires.

Important

L’appelant est chargé de s’assurer que les champs de handle standard dans STARTUPINFO contiennent des valeurs de handle valides. Ces champs sont copiés sans validation dans le processus enfant, même lorsque le membre dwFlags spécifie STARTF_USESTDHANDLES. Les valeurs incorrectes peuvent entraîner un comportement incorrect ou un blocage du processus enfant. Utilisez l’outil de vérification d’application runtime pour détecter les handles non valides.

[out] lpProcessInformation

Pointeur vers une structure PROCESS_INFORMATION qui reçoit des informations d’identification sur le nouveau processus.

Les handles dans PROCESS_INFORMATION doivent être fermés avec closeHandle lorsqu’ils ne sont plus nécessaires.

Valeur de retour

Si la fonction réussit, la valeur de retour est différente de zéro.

Si la fonction échoue, la valeur de retour est égale à zéro. Pour obtenir des informations d’erreur étendues, appelez GetLastError.

Notez que la fonction retourne avant la fin de l’initialisation du processus. Si une DLL requise ne peut pas être localisée ou ne parvient pas à initialiser, le processus est arrêté. Pour obtenir l’état d’arrêt d’un processus, appelez GetExitCodeProcess.

Remarques

Le processus est affecté à un identificateur de processus. L’identificateur est valide jusqu’à ce que le processus se termine. Il peut être utilisé pour identifier le processus ou spécifié dans la fonction OpenProcess pour ouvrir un handle au processus. Le thread initial du processus est également affecté à un identificateur de thread. Il peut être spécifié dans la fonction OpenThread pour ouvrir un handle sur le thread. L’identificateur est valide jusqu’à ce que le thread se termine et puisse être utilisé pour identifier de manière unique le thread au sein du système. Ces identificateurs sont retournés dans la structure PROCESS_INFORMATION.

Le nom de l’exécutable dans la ligne de commande que le système d’exploitation fournit à un processus n’est pas nécessairement identique à celui de la ligne de commande que le processus appelant donne à la fonction CreateProcess. Le système d’exploitation peut ajouter un chemin complet à un nom exécutable fourni sans chemin complet.

Le thread appelant peut utiliser la fonction WaitForInputIdle pour attendre que le nouveau processus ait terminé son initialisation et attend l’entrée de l’utilisateur sans entrée en attente. Cela peut être utile pour la synchronisation entre les processus parent et enfant, car CreateProcess retourne sans attendre que le nouveau processus termine son initialisation. Par exemple, le processus de création utilise WaitForInputIdle avant d’essayer de trouver une fenêtre associée au nouveau processus.

La méthode recommandée pour arrêter un processus consiste à utiliser la fonction ExitProcess, car cette fonction envoie une notification d’approche de l’arrêt à toutes les DLL attachées au processus. D’autres moyens d’arrêter un processus ne notifient pas les DLL jointes. Notez que lorsqu’un thread appelle ExitProcess, d’autres threads du processus sont arrêtés sans possibilité d’exécuter de code supplémentaire (y compris le code de terminaison de thread des DLL jointes). Pour plus d’informations, consultez fin d’un processus.

Un processus parent peut modifier directement les variables d’environnement d’un processus enfant lors de la création du processus. Il s’agit de la seule situation où un processus peut modifier directement les paramètres d’environnement d’un autre processus. Pour plus d’informations, consultez modification des variables d’environnement.

Si une application fournit un bloc d’environnement, les informations de répertoire actuelles des lecteurs système ne sont pas propagées automatiquement au nouveau processus. Par exemple, il existe une variable d’environnement nommée =C : dont la valeur est le répertoire actif sur le lecteur C. Une application doit transmettre manuellement les informations d’annuaire actuelles au nouveau processus. Pour ce faire, l’application doit créer explicitement ces chaînes de variables d’environnement, les trier par ordre alphabétique (car le système utilise un environnement trié) et les placer dans le bloc d’environnement. En règle générale, ils vont à l’avant du bloc d’environnement, en raison de l’ordre de tri du bloc d’environnement.

L’une des façons d’obtenir les informations de répertoire actuel d’un lecteur X consiste à effectuer l’appel suivant : GetFullPathName("X:", ...). Cela évite à une application d’analyser le bloc d’environnement. Si le chemin complet retourné est X :, il n’est pas nécessaire de transmettre cette valeur en tant que données d’environnement, car le répertoire racine est le répertoire actif par défaut pour le lecteur X d’un nouveau processus.

Lorsqu’un processus est créé avec CREATE_NEW_PROCESS_GROUP spécifié, un appel implicite à SetConsoleCtrlHandler(NULL,TRUE) est effectué au nom du nouveau processus ; cela signifie que le nouveau processus a désactivé Ctrl+C. Cela permet aux interpréteurs de commandes de gérer eux-mêmes ctrl+C et de transmettre de manière sélective ce signal aux sous-processus. Ctrl+BREAK n’est pas désactivé et peut être utilisé pour interrompre le processus/le groupe de processus.

Par défaut, le passage TRUE comme valeur du paramètre bInheritHandles entraîne l’héritage de tous les handles hérités par le nouveau processus. Cela peut être problématique pour les applications qui créent des processus à partir de plusieurs threads simultanément, mais souhaitent que chaque processus hérite de différents handles.

Les applications peuvent utiliser la fonction UpdateProcThreadAttributeList avec le paramètre PROC_THREAD_ATTRIBUTE_HANDLE_LIST pour fournir une liste de handles à hériter d’un processus particulier.

Remarques de sécurité

Le premier paramètre, lpApplicationName, peut être NULL , auquel cas le nom exécutable doit se trouver dans la chaîne délimitée par lpCommandLine. Si le nom de l’exécutable ou du chemin d’accès y a un espace, il existe un risque qu’un autre exécutable puisse être exécuté en raison de la façon dont la fonction analyse les espaces. L’exemple suivant est dangereux, car la fonction tente d’exécuter «Program.exe», s’il existe, au lieu de «MyApp.exe».

    LPTSTR szCmdline = _tcsdup(TEXT("C:\\Program Files\\MyApp -L -S"));
    CreateProcess(NULL, szCmdline, /* ... */);

Si un utilisateur malveillant devait créer une application appelée «Program.exe» sur un système, tout programme qui appelle incorrectement CreateProcess à l’aide du répertoire Program Files exécutera cette application au lieu de l’application prévue.

Pour éviter ce problème, ne passez pas NULL pour lpApplicationName. Si vous passez NULL pour lpApplicationName, utilisez des guillemets autour du chemin d’accès exécutable dans lpCommandLine, comme illustré dans l’exemple ci-dessous.

    LPTSTR szCmdline[] = _tcsdup(TEXT("\"C:\\Program Files\\MyApp\" -L -S"));
    CreateProcess(NULL, szCmdline, /*...*/);

Exemples

Pour obtenir un exemple, consultez Création de processus.

Note

L’en-tête processthreadsapi.h définit CreateProcess en tant qu’alias qui sélectionne automatiquement la version ANSI ou Unicode de cette fonction en fonction de la définition de la constante de préprocesseur UNICODE. Le mélange de l’utilisation de l’alias neutre en encodage avec du code qui n’est pas neutre en encodage peut entraîner des incompatibilités qui entraînent des erreurs de compilation ou d’exécution. Pour plus d’informations, consultez Conventions pour les prototypes de fonction.

Exigences

Exigence Valeur
client minimum pris en charge Windows XP [applications de bureau | Applications UWP]
serveur minimum pris en charge Windows Server 2003 [applications de bureau | Applications UWP]
plateforme cible Windows
d’en-tête processthreadsapi.h (inclure Windows.h sur Windows Server 2003, Windows Vista, Windows 7, Windows Server 2008 Windows Server 2008 R2)
bibliothèque Kernel32.lib
DLL Kernel32.dll

Voir aussi

closeHandle

ShellExecuteA

CreateProcessAsUser

CreateProcessWithLogonW

ExitProcess

getCommandLine

GetEnvironmentStrings

GetExitCodeProcess

GetFullPathName

getStartupInfo

OpenProcess

PROCESS_INFORMATION

processus et fonctions de thread

processus

SECURITY_ATTRIBUTES

STARTUPINFO

STARTUPINFOEX

SetErrorMode

TerminateProcess

WaitForInputIdle