Función CreateProcessAsUserA (processthreadsapi.h)
Crea un nuevo proceso y su subproceso principal. El nuevo proceso se ejecuta en el contexto de seguridad del usuario representado por el token especificado.
Normalmente, el proceso que llama a la función CreateProcessAsUser debe tener el privilegio SE_INCREASE_QUOTA_NAME y puede requerir el privilegio SE_ASSIGNPRIMARYTOKEN_NAME si el token no es asignable. Si se produce un error en esta función con ERROR_PRIVILEGE_NOT_HELD (1314), use la función CreateProcessWithLogonW en su lugar. CreateProcessWithLogonW no requiere privilegios especiales, pero se debe permitir que la cuenta de usuario especificada inicie sesión de forma interactiva. Por lo general, es mejor usar CreateProcessWithLogonW para crear un proceso con credenciales alternativas.
Sintaxis
BOOL CreateProcessAsUserA(
[in, optional] HANDLE hToken,
[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
);
Parámetros
[in, optional] hToken
Identificador del token principal que representa a un usuario. El identificador debe tener los derechos de acceso TOKEN_QUERY, TOKEN_DUPLICATEy TOKEN_ASSIGN_PRIMARY. Para obtener más información, vea Derechos de acceso para Access-Token Objetos. El usuario representado por el token debe tener acceso de lectura y ejecución a la aplicación especificada por el lpApplicationName
Para obtener un token principal que represente al usuario especificado, llame a la función logonUser de
Si hToken es una versión restringida del token principal del autor de la llamada, no se requiere el privilegio SE_ASSIGNPRIMARYTOKEN_NAME. Si los privilegios necesarios aún no están habilitados, CreateProcessAsUser los habilita durante la llamada. Para obtener más información, vea En ejecución con privilegios especiales.
Terminal Services: El proceso se ejecuta en la sesión especificada en el token. De forma predeterminada, esta es la misma sesión que llamó a LogonUser. Para cambiar la sesión, use la función SetTokenInformation.
[in, optional] lpApplicationName
Nombre del módulo que se va a ejecutar. Este módulo puede ser una aplicación basada en Windows. Puede ser algún otro tipo de módulo (por ejemplo, MS-DOS o OS/2) si el subsistema adecuado está disponible en el equipo local.
La cadena puede especificar la ruta de acceso completa y el nombre de archivo del módulo que se va a ejecutar o puede especificar un nombre parcial. En el caso de un nombre parcial, la función usa la unidad actual y el directorio actual para completar la especificación. La función no usará la ruta de acceso de búsqueda. Este parámetro debe incluir la extensión de nombre de archivo; no se supone ninguna extensión predeterminada.
El parámetro lpApplicationName
c:\program.exec:\program files\sub.exec:\program files\sub dir\program.exec:\program files\sub dir\program name.exe Si el módulo ejecutable es una aplicación de 16 bits, lpApplicationName debe ser NULL y la cadena a la que apunta lpCommandLine debe especificar el módulo ejecutable así como sus argumentos. De forma predeterminada, todas las aplicaciones basadas en Windows de 16 bits creadas por createProcessAsUser se ejecutan en un VDM independiente (equivalente a CREATE_SEPARATE_WOW_VDM en CreateProcess).
[in, out, optional] lpCommandLine
Línea de comandos que se va a ejecutar. La longitud máxima de esta cadena es de 32 000 caracteres. Si lpApplicationName es NULL, la parte del nombre del módulo de lpCommandLine se limita a MAX_PATH caracteres.
La versión Unicode de esta función, CreateProcessAsUserW, puede modificar el contenido de esta cadena. Por lo tanto, este parámetro no puede ser un puntero a la memoria de solo lectura (como un const variable o una cadena literal). Si este parámetro es una cadena constante, la función puede provocar una infracción de acceso.
El parámetro lpCommandLine puede ser NULL. En ese caso, la función usa la cadena a la que apunta lpApplicationName como línea de comandos.
Si tanto lpApplicationName como lpCommandLine no sonNULL, *lpApplicationName especifica el módulo que se va a ejecutar y *lpCommandLine especifica la línea de comandos. El nuevo proceso puede usar GetCommandLine para recuperar toda la línea de comandos. Los procesos de consola escritos en C pueden usar el argc de
Si lpApplicationName es null, el primer token delimitado por espacios en blanco de la línea de comandos especifica el nombre del módulo. Si usa un nombre de archivo largo que contiene un espacio, use cadenas entre comillas para indicar dónde finaliza el nombre de archivo y los argumentos comienzan (vea la explicación del parámetro lpApplicationName). Si el nombre de archivo no contiene una extensión, se anexa .exe. Por lo tanto, si la extensión de nombre de archivo es .com, este parámetro debe incluir la extensión .com. Si el nombre de archivo finaliza en un punto (.) sin extensión, o si el nombre de archivo contiene una ruta de acceso, .exe no se anexa. Si el nombre de archivo no contiene una ruta de acceso de directorio, el sistema busca el archivo ejecutable en la siguiente secuencia:
- Directorio desde el que se cargó la aplicación.
- Directorio actual del proceso primario.
- Directorio del sistema de Windows de 32 bits. Use la función GetSystemDirectory para obtener la ruta de acceso de este directorio.
- Directorio del sistema de Windows de 16 bits. No hay ninguna función que obtenga la ruta de acceso de este directorio, pero se busca.
- Directorio de Windows. Use la función GetWindowsDirectory para obtener la ruta de acceso de este directorio.
- Directorios que aparecen en la variable de entorno PATH. Tenga en cuenta que esta función no busca la ruta de acceso por aplicación especificada por las rutas de acceso de aplicación clave del Registro. Para incluir esta ruta de acceso por aplicación en la secuencia de búsqueda, use la función shellExecute
.
[in, optional] lpProcessAttributes
Puntero a una estructura de SECURITY_ATTRIBUTES que especifica un descriptor de seguridad para el nuevo objeto de proceso y determina si los procesos secundarios pueden heredar el identificador devuelto al proceso. Si lpProcessAttributes es null o lpSecurityDescriptor es NULL, el proceso obtiene un descriptor de seguridad predeterminado y el identificador no se puede heredar. El descriptor de seguridad predeterminado es el del usuario al que se hace referencia en el parámetro hToken. Es posible que este descriptor de seguridad no permita el acceso al autor de la llamada, en cuyo caso es posible que el proceso no se vuelva a abrir después de ejecutarlo. El identificador de proceso es válido y seguirá teniendo derechos de acceso completos.
[in, optional] lpThreadAttributes
Puntero a una estructura de SECURITY_ATTRIBUTES que especifica un descriptor de seguridad para el nuevo objeto de subproceso y determina si los procesos secundarios pueden heredar el identificador devuelto al subproceso. Si lpThreadAttributes es NULL o lpSecurityDescriptor es NULL, el subproceso obtiene un descriptor de seguridad predeterminado y el identificador no se puede heredar. El descriptor de seguridad predeterminado es el del usuario al que se hace referencia en el parámetro hToken. Este descriptor de seguridad puede no permitir el acceso al autor de la llamada.
[in] bInheritHandles
Si este parámetro es TRUE, el nuevo proceso hereda cada identificador que se pueda heredar en el proceso de llamada. Si el parámetro es FALSE, no se heredan los identificadores. Tenga en cuenta que los identificadores heredados tienen el mismo valor y derechos de acceso que los identificadores originales. Para obtener más información sobre los identificadores heredables, vea Comentarios.
Terminal Services: no se pueden heredar identificadores entre sesiones. Además, si este parámetro es TRUE, debe crear el proceso en la misma sesión que el autor de la llamada.
procesos de luz de proceso protegido (PPL): La herencia de identificadores genéricos se bloquea cuando un proceso PPL crea un proceso que no es PPL, ya que PROCESS_DUP_HANDLE no se permite desde un proceso que no sea PPL a un proceso PPL. Consulte de seguridad y acceso de procesos de
[in] dwCreationFlags
Marcas que controlan la clase de prioridad y la creación del proceso. Para obtener una lista de valores, consulte Marcas de creación de procesos.
Este parámetro también controla la clase de prioridad del nuevo proceso, que se usa para determinar las prioridades de programación de los subprocesos del proceso. Para obtener una lista de valores, vea GetPriorityClass. Si no se especifica ninguna de las marcas de clase de prioridad, la clase de prioridad tiene como valor predeterminado NORMAL_PRIORITY_CLASS a menos que la clase de prioridad del proceso de creación sea IDLE_PRIORITY_CLASS o BELOW_NORMAL_PRIORITY_CLASS. En este caso, el proceso secundario recibe la clase de prioridad predeterminada del proceso de llamada.
Si el parámetro dwCreationFlags tiene un valor de 0:
- El proceso hereda el modo de error del autor de la llamada y la consola del elemento primario.
- Se supone que el bloque de entorno del nuevo proceso contiene caracteres ANSI (consulte parámetro lpEnvironment para obtener información adicional).
- Una aplicación basada en Windows de 16 bits se ejecuta en una máquina Virtual DOS (VDM) compartida.
[in, optional] lpEnvironment
Puntero a un bloque de entorno para el nuevo proceso. Si este parámetro es NULL, el nuevo proceso usa el entorno del proceso de llamada.
Un bloque de entorno consta de un bloque terminado en null de cadenas terminadas en NULL. Cada cadena tiene el formato siguiente:
nombre=valor\0
Dado que el signo igual se usa como separador, no debe usarse en el nombre de una variable de entorno.
Un bloque de entorno puede contener caracteres Unicode o ANSI. Si el bloque de entorno al que apunta lpEnvironment contiene caracteres Unicode, asegúrese de que dwCreationFlags incluye CREATE_UNICODE_ENVIRONMENT.
La versión ANSI de esta función, createProcessAsUserA produce un error si el tamaño total del bloque de entorno para el proceso supera los 32 767 caracteres.
Tenga en cuenta que un bloque de entorno ANSI finaliza en dos bytes cero: uno para la última cadena, uno más para finalizar el bloque. Un bloque de entorno Unicode finaliza en cuatro bytes cero: dos para la última cadena, dos más para finalizar el bloque.
Windows Server 2003 y Windows XP: Si el tamaño de la variable de entorno de sistema y usuario combinado supera los 8192 bytes, el proceso creado por CreateProcessAsUser ya no se ejecuta con el bloque de entorno pasado a la función por el proceso primario. En su lugar, el proceso secundario se ejecuta con el bloque de entorno devuelto por la función CreateEnvironmentBlock.
Para recuperar una copia del bloque de entorno para un usuario determinado, use la función createEnvironmentBlock
[in, optional] lpCurrentDirectory
Ruta de acceso completa al directorio actual del proceso. La cadena también puede especificar una ruta de acceso UNC.
Si este parámetro es NULL, el nuevo proceso tendrá la misma unidad y directorio actuales que el proceso de llamada. (Esta característica se proporciona principalmente para los shells que necesitan iniciar una aplicación y especificar su unidad inicial y directorio de trabajo).
[in] lpStartupInfo
Puntero a una estructura de STARTUPINFO o STARTUPINFOEX.
El usuario debe tener acceso total a la estación de ventana y al escritorio especificados. Si desea que el proceso sea interactivo, especifique winsta0\default. Si el miembro lpDesktop es NULL, el nuevo proceso hereda la estación de escritorio y ventana de su proceso primario. Si este miembro es una cadena vacía, "", el nuevo proceso se conecta a una estación de ventanas mediante las reglas descritas en Conexión de proceso a una estación de ventanas.
Para establecer atributos extendidos, use una estructura de
Los identificadores de STARTUPINFO o STARTUPINFOEX deben cerrarse con CloseHandle cuando ya no sean necesarios.
[out] lpProcessInformation
Puntero a una estructura de PROCESS_INFORMATION que recibe información de identificación sobre el nuevo proceso.
Los identificadores de PROCESS_INFORMATION deben cerrarse con closeHandle cuando ya no sean necesarios.
Valor devuelto
Si la función se ejecuta correctamente, el valor devuelto es distinto de cero.
Si se produce un error en la función, el valor devuelto es cero. Para obtener información de error extendida, llame a GetLastError.
Tenga en cuenta que la función devuelve antes de que el proceso haya terminado de inicializarse. Si no se puede encontrar un archivo DLL necesario o no se puede inicializar, se finaliza el proceso. Para obtener el estado de finalización de un proceso, llame a GetExitCodeProcess.
Observaciones
CreateProcessAsUser debe poder abrir el token principal del proceso de llamada con los derechos de acceso TOKEN_DUPLICATE y TOKEN_IMPERSONATE.
De forma predeterminada, CreateProcessAsUser crea el nuevo proceso en una estación de ventana no interactiva con un escritorio que no está visible y no puede recibir la entrada del usuario. Para habilitar la interacción del usuario con el nuevo proceso, debe especificar el nombre de la estación de ventana interactiva predeterminada y el escritorio, "winsta0\default", en el miembro lpDesktop de la estructura STARTUPINFO. Además, antes de llamar a CreateProcessAsUser, debe cambiar la lista de control de acceso discrecional (DACL) de la estación de ventana interactiva predeterminada y el escritorio predeterminado. Las DACL de la estación de ventana y el escritorio deben conceder acceso al usuario o a la sesión de inicio de sesión representada por el parámetro hToken.
CreateProcessAsUser no carga el perfil del usuario especificado en la clave del Registro de HKEY_USERS. Por lo tanto, para acceder a la información de la clave del Registro de HKEY_CURRENT_USER, debe cargar la información del perfil del usuario en HKEY_USERS con la función LoadUserProfile antes de llamar a CreateProcessAsUser. Asegúrese de llamar a unloadUserProfile después de que se cierre el nuevo proceso.
Si el parámetro lpEnvironment de
Las funciones CreateProcessWithLogonW y CreateProcessWithTokenW son similares a CreateProcessAsUser, excepto que el autor de la llamada no necesita llamar a la función LogonUser para autenticar al usuario y obtener un token.
CreateProcessAsUser permite acceder al directorio y a la imagen ejecutable especificadas en el contexto de seguridad del autor de la llamada o del usuario de destino. De forma predeterminada, CreateProcessAsUser accede al directorio y a la imagen ejecutable en el contexto de seguridad del autor de la llamada. En este caso, si el autor de la llamada no tiene acceso al directorio y a la imagen ejecutable, se produce un error en la función. Para acceder al directorio y la imagen ejecutable mediante el contexto de seguridad del usuario de destino, especifique hToken en una llamada a la función ImpersonateLoggedOnUser antes de llamar a CreateProcessAsUser.
Al proceso se le asigna un identificador de proceso. El identificador es válido hasta que finaliza el proceso. Se puede usar para identificar el proceso o especificarse en la función OpenProcess para abrir un identificador para el proceso. Al subproceso inicial del proceso también se le asigna un identificador de subproceso. Se puede especificar en la función OpenThread para abrir un identificador en el subproceso. El identificador es válido hasta que finaliza el subproceso y se puede usar para identificar de forma única el subproceso dentro del sistema. Estos identificadores se devuelven en la estructura PROCESS_INFORMATION.
El subproceso de llamada puede usar la función WaitForInputIdle para esperar hasta que el nuevo proceso haya terminado su inicialización y esté esperando la entrada del usuario sin entrada pendiente. Esto puede ser útil para la sincronización entre los procesos primarios y secundarios, ya que createProcessAsUser devuelve sin esperar a que el nuevo proceso finalice su inicialización. Por ejemplo, el proceso de creación usaría WaitForInputIdle antes de intentar encontrar una ventana asociada al nuevo proceso.
La manera preferida de apagar un proceso es mediante el uso de la función exitProcess
De forma predeterminada, pasar TRUE como valor del parámetro bInheritHandles hace que el nuevo proceso herede todos los identificadores heredados.
Esto puede ser problemático para las aplicaciones que crean procesos a partir de varios subprocesos simultáneamente pero desean que cada proceso herede distintos identificadores.
Las aplicaciones pueden usar la función UpdateProcThreadAttributeList
Comentarios de seguridad de
El parámetro lpApplicationName LPTSTR szCmdline[] = _tcsdup(TEXT("C:\\Program Files\\MyApp"));
CreateProcessAsUser(hToken, NULL, szCmdline, /*...*/ );
Si un usuario malintencionado creara una aplicación denominada "Program.exe" en un sistema, cualquier programa que llame incorrectamente a CreateProcessAsUser mediante el directorio Archivos de programa ejecutará esta aplicación en lugar de la aplicación deseada.
Para evitar este problema, no pase NULL para lpApplicationName. Si pasa NULL para lpApplicationName, use comillas alrededor de la ruta de acceso ejecutable en lpCommandLine, como se muestra en el ejemplo siguiente.
LPTSTR szCmdline[] = _tcsdup(TEXT("\"C:\\Program Files\\MyApp\""));
CreateProcessAsUser(hToken, NULL, szCmdline, /*...*/);
Ejemplos
Para obtener un ejemplo, vea Iniciar un proceso de cliente interactivo.
Nota
El encabezado processthreadsapi.h define CreateProcessAsUser como alias que selecciona automáticamente la versión ANSI o Unicode de esta función en función de la definición de la constante de preprocesador UNICODE. La combinación del uso del alias neutral de codificación con código que no es neutral de codificación puede dar lugar a errores de coincidencia que dan lugar a errores de compilación o tiempo de ejecución. Para obtener más información, vea Conventions for Function Prototypes.
Requisitos
Requisito | Valor |
---|---|
cliente mínimo admitido | Windows XP [solo aplicaciones de escritorio] |
servidor mínimo admitido | Windows Server 2003 [solo aplicaciones de escritorio] |
de la plataforma de destino de |
Windows |
encabezado de |
processthreadsapi.h (incluya Windows.h) |
biblioteca de |
Advapi32.lib |
DLL de |
Advapi32.dll |
Consulte también
funciones de proceso y subproceso de