CreateProcessWithTokenW, fonction (winbase.h)
Crée un processus et son thread principal. Le nouveau processus s’exécute dans le contexte de sécurité du jeton spécifié. Il peut éventuellement charger le profil utilisateur pour l’utilisateur spécifié.
Le processus qui appelle CreateProcessWithTokenW doit avoir le privilège SE_IMPERSONATE_NAME. Si cette fonction échoue avec ERROR_PRIVILEGE_NOT_HELD (1314), utilisez plutôt la fonction CreateProcessAsUser ou CreateProcessWithLogonW . En règle générale, le processus qui appelle
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. 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 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
);
Paramètres
[in] hToken
Handle du jeton principal qui représente un utilisateur. Le handle doit avoir les droits d’accès TOKEN_QUERY, TOKEN_DUPLICATE et TOKEN_ASSIGN_PRIMARY. Pour plus d’informations, consultez Droits d’accès pour les objets Access-Token. 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 le paramètre lpApplicationName ou 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.
Terminal Services : Le processus de l’appelant s’exécute toujours dans la session de l’appelant, et non dans la session spécifiée dans le jeton. Pour exécuter un processus dans la session spécifiée dans le jeton, utilisez la fonction CreateProcessAsUser.
[in] dwLogonFlags
Option d’ouverture de session. Ce paramètre peut être égal à zéro ou à l’une des valeurs suivantes.
[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 elle peut spécifier un nom partiel. Dans le cas d’un nom partiel, la fonction utilise le lecteur actuel et le répertoire actif pour compléter 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 des espaces blancs 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ù le nom de fichier se termine et où 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.
[in, out, optional] lpCommandLine
Ligne de commande à exécuter.
La longueur maximale de cette chaîne est de 1 024 caractères. Si lpApplicationName a la valeur NULL, la partie nom du module de lpCommandLine est limitée à MAX_PATH caractères.
La fonction 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 entraîner 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 n’ont pas la valeur NULL, *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 arguments argc et 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 des espaces blancs 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ù le nom de fichier se termine et où 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 de répertoire, le système recherche le fichier exécutable dans l’ordre suivant :
- Répertoire à partir duquel l’application a été chargée.
- Répertoire actif du processus parent.
- Répertoire système Windows 32 bits. Utilisez la fonction GetSystemDirectory pour obtenir le chemin d’accès de ce répertoire.
- Répertoire système Windows 16 bits. Aucune fonction n’obtient le chemin d’accès de ce répertoire, mais elle fait l’objet d’une recherche.
- Répertoire Windows. Utilisez la fonction GetWindowsDirectory 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 la clé de Registre Chemins d’accès aux applications. Pour inclure ce chemin par application dans la séquence de recherche, utilisez la fonction ShellExecute .
[in] dwCreationFlags
Indicateurs qui contrôlent la façon dont le processus est créé. Les indicateurs CREATE_DEFAULT_ERROR_MODE, CREATE_NEW_CONSOLE et CREATE_NEW_PROCESS_GROUP sont activés par défaut. 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 indicateur de classe de priorité n’est spécifié, la classe de priorité est NORMAL_PRIORITY_CLASS par défaut, 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 obtient le mode d’erreur par défaut, crée une console et crée un groupe de processus.
- Le bloc d’environnement du nouveau processus est supposé contenir des caractères ANSI (pour plus d’informations, consultez le paramètre lpEnvironment ).
- Une application Windows 16 bits s’exécute sur une machine VIRTUAL DOS (VDM) partagée.
[in, optional] lpEnvironment
Pointeur vers un bloc d’environnement pour le nouveau processus. Si ce paramètre a la valeur NULL, le nouveau processus utilise un environnement créé à partir du profil de l’utilisateur spécifié par lpUsername.
Un bloc d’environnement se compose d’un bloc de chaînes terminées par null. Chaque chaîne se présente sous la forme suivante :
Nom=Valeur
É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.
Un bloc d’environnement ANSI se termine par deux octets zéro : un pour la dernière chaîne, un autre pour terminer le bloc. Un bloc d’environnement Unicode est terminé par quatre octets zéro : deux pour la dernière chaîne et deux autres pour terminer le bloc.
Pour récupérer une copie du bloc d’environnement pour un utilisateur spécifique, utilisez la fonction CreateEnvironmentBlock .
[in, optional] lpCurrentDirectory
Chemin d’accès complet au répertoire actif pour le processus. La chaîne peut également spécifier un chemin UNC.
Si ce paramètre est NULL, le nouveau processus a le même lecteur et le même répertoire actifs 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 .
Si le membre lpDesktop a la valeur NULL ou une chaîne vide, le nouveau processus hérite du bureau et de la station de fenêtre de son processus parent. La fonction ajoute l’autorisation pour le compte d’utilisateur spécifié à la station de fenêtre et au bureau hérités. Sinon, si ce membre spécifie un bureau, il incombe à l’application d’ajouter l’autorisation pour le compte d’utilisateur spécifié à la station de fenêtre et au bureau spécifiés, même pour WinSta0\Default.
Les handles dans STARTUPINFO ou STARTUPINFOEX doivent être fermés avec CloseHandle lorsqu’ils ne sont plus nécessaires.
[out] lpProcessInformation
Pointeur vers une structure de PROCESS_INFORMATION qui reçoit des informations d’identification pour le nouveau processus, y compris un handle pour le processus.
Les handles dans PROCESS_INFORMATION doivent être fermés avec la fonction CloseHandle lorsqu’ils ne sont plus nécessaires.
Valeur retournée
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étaillées sur l’erreur, appelez GetLastError.
Notez que la fonction retourne avant la fin de l’initialisation du processus. Si une DLL requise ne peut pas être trouvée ou ne parvient pas à s’initialiser, le processus est arrêté. Pour obtenir la status d’arrêt d’un processus, appelez GetExitCodeProcess.
Remarques
Par défaut, CreateProcessWithTokenW ne charge pas le profil de l’utilisateur spécifié dans la clé de Registre HKEY_USERS . Cela signifie que l’accès aux informations dans la clé de Registre HKEY_CURRENT_USER peut ne pas produire de résultats cohérents avec une ouverture de session interactive normale. Il vous incombe de charger la ruche du Registre de l’utilisateur dans HKEY_USERS en utilisant LOGON_WITH_PROFILE ou en appelant la fonction LoadUserProfile avant d’appeler cette fonction.
Si le paramètre lpEnvironment est NULL, le nouveau processus utilise un bloc d’environnement créé à partir du profil de l’utilisateur spécifié par lpUserName. Si les variables HOMEDRIVE et HOMEPATH ne sont pas définies, CreateProcessWithTokenW modifie le bloc d’environnement pour utiliser le lecteur et le chemin d’accès du répertoire de travail de l’utilisateur.
Une fois créés, les nouveaux handles de processus et de thread reçoivent des droits d’accès complets (PROCESS_ALL_ACCESS et THREAD_ALL_ACCESS). Pour l’un ou l’autre handle, si aucun descripteur de sécurité n’est fourni, le handle peut être utilisé dans n’importe quelle fonction qui nécessite un handle d’objet de ce type. Lorsqu’un descripteur de sécurité est fourni, un case activée d’accès est effectué sur toutes les utilisations ultérieures du handle avant l’octroi de l’accès. Si l’accès est refusé, le processus demandeur ne peut pas utiliser le handle pour accéder au processus ou au thread.
Pour récupérer un jeton de sécurité, passez le handle de processus dans la structure PROCESS_INFORMATION à la fonction OpenProcessToken .
Un identificateur de processus est affecté au processus. L’identificateur est valide jusqu’à l’arrêt du processus. Il peut être utilisé pour identifier le processus, ou spécifié dans la fonction OpenProcess pour ouvrir un handle au processus. Un identificateur de thread est également affecté au thread initial du processus. Il peut être spécifié dans la fonction OpenThread pour ouvrir un handle au thread. L’identificateur est valide jusqu’à ce que le thread se termine et peut être utilisé pour identifier le thread de manière unique dans le système. Ces identificateurs sont retournés dans PROCESS_INFORMATION.
Le thread appelant peut utiliser la fonction WaitForInputIdle pour attendre que le nouveau processus ait terminé son initialisation et qu’il attende une entrée utilisateur sans aucune entrée en attente. Cela peut être utile pour la synchronisation entre les processus parents et enfants, car CreateProcessWithTokenW 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 meilleure façon d’arrêter un processus consiste à utiliser la fonction ExitProcess , car cette fonction envoie une notification d’arrêt proche à 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 d’arrêt de thread des DLL jointes). Pour plus d’informations, consultez Fin d’un processus.
Pour compiler une application qui utilise cette fonction, définissez _WIN32_WINNT comme 0x0500 ou version ultérieure. Pour plus d’informations, consultez Utilisation des en-têtes Windows.
Remarques sur la sécurité
Le paramètre lpApplicationName peut être NULL, auquel cas le nom de l’exécutable doit être la première chaîne délimitée par des espaces blancs dans lpCommandLine. Si le nom de l’exécutable ou du chemin contient un espace, il existe un risque qu’un autre exécutable soit 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 = L"C:\\Program Files\\MyApp";
CreateProcessWithTokenW(/*...*/, szCmdline, /*...*/);
Si un utilisateur malveillant devait créer une application appelée « Program.exe » sur un système, tout programme qui appelle incorrectement CreateProcessWithTokenW à 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 transmettez null pour lpApplicationName, utilisez des guillemets autour du chemin d’accès exécutable dans lpCommandLine, comme indiqué dans l’exemple ci-dessous.
LPTSTR szCmdline = L"\"C:\\Program Files\\MyApp\"";
CreateProcessWithTokenW(/*...*/, szCmdline, /*...*/);
Configuration requise
Condition requise | Valeur |
---|---|
Client minimal pris en charge | Windows Vista [applications de bureau uniquement] |
Serveur minimal pris en charge | Windows Server 2003 [applications de bureau uniquement] |
Plateforme cible | Windows |
En-tête | winbase.h (inclure Windows.h) |
Bibliothèque | Advapi32.lib |
DLL | Advapi32.dll |