Partager via


CreateProcessAsUserW, fonction (processthreadsapi.h)

Crée un processus et son thread principal. Le nouveau processus s’exécute dans le contexte de sécurité de l’utilisateur représenté par le jeton spécifié.

En règle générale, le processus qui appelle la fonction CreateProcessAsUser doit avoir le privilège SE_INCREASE_QUOTA_NAME et peut nécessiter le privilège SE_ASSIGNPRIMARYTOKEN_NAME si le jeton n’est pas assignable. Si cette fonction échoue avec ERROR_PRIVILEGE_NOT_HELD (1314), utilisez la fonction CreateProcessWithLogonW à la place. CreateProcessWithLogonW ne nécessite aucun privilège spécial, mais le compte d’utilisateur spécifié doit être autorisé à se connecter de manière interactive. En règle générale, il est préférable d’utiliser CreateProcessWithLogonW pour créer un processus avec d’autres informations d’identification.

Syntaxe

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

Paramètres

[in, optional] hToken

Handle vers le jeton principal qui représente un utilisateur. Le handle doit disposer des droits d’accès TOKEN_QUERY, TOKEN_DUPLICATEet TOKEN_ASSIGN_PRIMARY. Pour plus d’informations, consultez Droits d’accès pour Access-Token Objets. L’utilisateur représenté par le jeton doit disposer d’un accès en lecture et en exécution à l’application spécifiée par l' lpApplicationName ou le paramètre lpCommandLine.

Pour obtenir un jeton principal qui représente l’utilisateur spécifié, appelez la fonction LogonUser. Vous pouvez également appeler la fonction DuplicateTokenEx pour convertir un jeton d’emprunt d’identité en jeton principal. Cela permet à une application serveur qui emprunte l’identité d’un client de créer un processus qui a le contexte de sécurité du client.

Si hToken est une version restreinte du jeton principal de l’appelant, le privilège SE_ASSIGNPRIMARYTOKEN_NAME n’est pas nécessaire. Si les privilèges nécessaires ne sont pas déjà activés, CreateProcessAsUser les active pendant la durée de l’appel. Pour plus d’informations, consultez Exécution avec des privilèges spéciaux.

Terminal Services : Le processus est exécuté dans la session spécifiée dans le jeton. Par défaut, il s’agit de la même session que celle appelée LogonUser. Pour modifier la session, utilisez la fonction SetTokenInformation.

[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 :

c :\program.exec :\program files\sub.exec :\program files\sub dir\program.exec :\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. Par défaut, toutes les applications Windows 16 bits créées par CreateProcessAsUser sont exécutées dans un VDM distinct (équivalent à CREATE_SEPARATE_WOW_VDM dans CreateProcess).

[in, out, optional] lpCommandLine

Ligne de commande à exécuter. La longueur maximale de cette chaîne est de 32 000 caractères. 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, CreateProcessAsUserW, 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 les deux lpApplicationName et lpCommandLine ne sont pasNULL, *lpApplicationName spécifie le module à exécuter, et *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 est NULL, le premier jeton délimité par l’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 :

  1. Répertoire à partir duquel l’application a chargé.
  2. Répertoire actif du processus parent.
  3. Répertoire système Windows 32 bits. Utilisez la fonction GetSystemDirectory pour obtenir le chemin d’accès de ce répertoire.
  4. 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.
  5. Répertoire Windows. Utilisez la fonction GetWindowsDirectory pour obtenir le chemin d’accès de ce répertoire.
  6. 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 d’accès par application dans la séquence de recherche, utilisez la fonction ShellExecute .
Le système ajoute un caractère Null à 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 spécifie un descripteur de sécurité pour le nouvel objet de processus et détermine si les processus enfants peuvent hériter du handle retourné au processus. Si lpProcessAttributes est NULL ou lpSecurityDescriptor est NULL, le processus obtient un descripteur de sécurité par défaut et le handle ne peut pas être hérité. Le descripteur de sécurité par défaut est celui de l’utilisateur référencé dans le paramètre hToken. Ce descripteur de sécurité peut ne pas autoriser l’accès pour l’appelant, auquel cas le processus ne peut pas être rouvert après son exécution. Le handle de processus est valide et continuera d’avoir des droits d’accès complets.

[in, optional] lpThreadAttributes

Pointeur vers une structure SECURITY_ATTRIBUTES qui spécifie un descripteur de sécurité pour le nouvel objet thread et détermine si les processus enfants peuvent hériter du handle retourné au thread. Si lpThreadAttributes est NULL ou lpSecurityDescriptor est NULL, le thread obtient un descripteur de sécurité par défaut et le handle ne peut pas être hérité. Le descripteur de sécurité par défaut est celui de l’utilisateur référencé dans le paramètre hToken. Ce descripteur de sécurité peut ne pas autoriser l’accès pour l’appelant.

[in] bInheritHandles

Si ce paramètre est 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 est 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

[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 un 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, CreateProcessAsUserA é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.

Windows Server 2003 et Windows XP : Si la taille de la variable d’environnement utilisateur et système combinée dépasse 8192 octets, le processus créé par CreateProcessAsUser ne s’exécute plus avec le bloc d’environnement passé à la fonction par le processus parent. Au lieu de cela, le processus enfant s’exécute avec le bloc d’environnement retourné par la fonction CreateEnvironmentBlock.

Pour récupérer une copie du bloc d’environnement pour un utilisateur donné, utilisez la fonction CreateEnvironmentBlock.

[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 a la valeur NULL, le nouveau processus aura le même lecteur actuel et le même répertoire 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.

L’utilisateur doit avoir un accès complet à la fois à la station de fenêtre et au bureau spécifiés. Si vous souhaitez que le processus soit interactif, spécifiez winsta0\default. Si le membre lpDesktop a la valeur NULL, le nouveau processus hérite de la station de bureau et de la fenêtre de son processus parent. Si ce membre est une chaîne vide, « », le nouveau processus se connecte à une station de fenêtre à l’aide des règles décrites dans Traiter la connexion à une station de fenêtre.

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 de 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

CreateProcessAsUser doit être en mesure d’ouvrir le jeton principal du processus appelant avec les droits d’accès TOKEN_DUPLICATE et TOKEN_IMPERSONATE.

Par défaut, CreateProcessAsUser crée le nouveau processus sur une station de fenêtre non interactive avec un bureau qui n’est pas visible et ne peut pas recevoir d’entrée utilisateur. Pour activer l’interaction utilisateur avec le nouveau processus, vous devez spécifier le nom de la station de fenêtre interactive et du bureau par défaut, « winsta0\default », dans le membre lpDesktop de la structure STARTUPINFO. En outre, avant d’appeler CreateProcessAsUser, vous devez modifier la liste de contrôle d’accès discrétionnaire (DACL) de la station de fenêtre interactive par défaut et du bureau par défaut. Les DLL pour la station de fenêtre et le bureau doivent accorder l’accès à l’utilisateur ou à la session d’ouverture de session représentée par le paramètre hToken.

createProcessAsUser ne charge pas le profil de l’utilisateur spécifié dans la clé de Registre HKEY_USERS. Par conséquent, pour accéder aux informations de la clé de Registre HKEY_CURRENT_USER, vous devez charger les informations de profil de l’utilisateur dans HKEY_USERS avec la fonction LoadUserProfile avant d’appeler CreateProcessAsUser. Veillez à appeler UnloadUserProfile après la sortie du nouveau processus.

Si le paramètre lpEnvironment a la valeur NULL, le nouveau processus hérite de l’environnement du processus appelant. CreateProcessAsUser ne modifie pas automatiquement le bloc d’environnement pour inclure des variables d’environnement spécifiques à l’utilisateur représenté par hToken. Par exemple, les variables USERNAME et USERDOMAIN sont héritées du processus appelant si lpEnvironment a la valeur NULL. Il vous incombe de préparer le bloc d’environnement pour le nouveau processus et de le spécifier dans lpEnvironment.

Les fonctions CreateProcessWithLogonW et CreateProcessWithTokenW sont similaires à CreateProcessAsUser, sauf que l’appelant n’a pas besoin d’appeler la fonction LogonUser pour authentifier l’utilisateur et obtenir un jeton.

CreateProcessAsUser vous permet d’accéder au répertoire et à l’image exécutable spécifiés dans le contexte de sécurité de l’appelant ou de l’utilisateur cible. Par défaut, CreateProcessAsUser accède au répertoire et à l’image exécutable dans le contexte de sécurité de l’appelant. Dans ce cas, si l’appelant n’a pas accès au répertoire et à l’image exécutable, la fonction échoue. Pour accéder au répertoire et à l’image exécutable à l’aide du contexte de sécurité de l’utilisateur cible, spécifiez hToken dans un appel à la fonction ImpersonateLoggedOnUser avant d’appeler CreateProcessAsUser.

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 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 CreateProcessAsUser 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.

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 sur la sécurité

Le paramètre lpApplicationName peut être NULL, auquel cas le nom exécutable doit être la première chaîne délimitée par un espace blanc dans 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"));
	CreateProcessAsUser(hToken, NULL, szCmdline, /*...*/ );

Si un utilisateur malveillant devait créer une application appelée «Program.exe» sur un système, tout programme qui appelle incorrectement CreateProcessAsUser à 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\""));
	CreateProcessAsUser(hToken, NULL, szCmdline, /*...*/);

PowerShell : Lorsque la fonction CreateProcessAsUser est utilisée pour implémenter une applet de commande dans PowerShell version 2.0, l’applet de commande fonctionne correctement pour les sessions à distance fan-in et fan-out. Toutefois, en raison de certains scénarios de sécurité, une applet de commande implémentée avec CreateProcessAsUser fonctionne correctement dans PowerShell version 3.0 pour les sessions à distance de fan-in ; Les sessions distantes fan-out échouent en raison de privilèges de sécurité client insuffisants. Pour implémenter une applet de commande qui fonctionne à la fois pour les sessions à distance fan-in et fan out dans PowerShell version 3.0, utilisez la fonction CreateProcess.

Exemples

Pour obtenir un exemple, consultez Démarrage d’un processus client interactif.

Note

L’en-tête processthreadsapi.h définit CreateProcessAsUser comme 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 uniquement]
serveur minimum pris en charge Windows Server 2003 [applications de bureau uniquement]
plateforme cible Windows
d’en-tête processthreadsapi.h (include Windows.h)
bibliothèque Advapi32.lib
DLL Advapi32.dll

Voir aussi

closeHandle

CreateEnvironmentBlock

CreateProcess

CreateProcessWithLogonW

ExitProcess

GetEnvironmentStrings

GetExitCodeProcess

getStartupInfo

ImpersonateLoggedOnUser

LoadUserProfile

PROCESS_INFORMATION

processus et fonctions de thread

processus

SECURITY_ATTRIBUTES

SHCreateProcessAsUserW

STARTUPINFO

STARTUPINFOEX

SetErrorMode

WaitForInputIdle