Compartilhar via


Função CreateProcessAsUserA (processthreadsapi.h)

Cria um novo processo e seu thread primário. O novo processo é executado no contexto de segurança do usuário representado pelo token especificado.

Normalmente, o processo que chama a função CreateProcessAsUser deve ter o privilégio SE_INCREASE_QUOTA_NAME e pode exigir o privilégio SE_ASSIGNPRIMARYTOKEN_NAME se o token não for atribuível. Se essa função falhar com ERROR_PRIVILEGE_NOT_HELD (1314), use a função CreateProcessWithLogonW . CreateProcessWithLogonW não requer privilégios especiais, mas a conta de usuário especificada deve ter permissão para fazer logon interativamente. Em geral, é melhor usar CreateProcessWithLogonW para criar um processo com credenciais alternativas.

Sintaxe

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

Um identificador para o token primário que representa um usuário. O identificador deve ter os direitos de acesso TOKEN_QUERY, TOKEN_DUPLICATE e TOKEN_ASSIGN_PRIMARY . Para obter mais informações, consulte Direitos de acesso para objetos Access-Token. O usuário representado pelo token deve ter acesso de leitura e execução ao aplicativo especificado pelo lpApplicationName ou pelo parâmetro lpCommandLine .

Para obter um token primário que representa o usuário especificado, chame a função LogonUser . Como alternativa, você pode chamar a função DuplicateTokenEx para converter um token de representação em um token primário. Isso permite que um aplicativo de servidor que representa um cliente crie um processo que tenha o contexto de segurança do cliente.

Se hToken for uma versão restrita do token primário do chamador, o privilégio SE_ASSIGNPRIMARYTOKEN_NAME não será necessário. Se os privilégios necessários ainda não estiverem habilitados, CreateProcessAsUser os habilitará durante a chamada. Para obter mais informações, confira Executar com privilégios especiais.

Serviços de Terminal: O processo é executado na sessão especificada no token. Por padrão, essa é a mesma sessão chamada LogonUser. Para alterar a sessão, use a função SetTokenInformation .

[in, optional] lpApplicationName

O nome do módulo a ser executado. Este módulo pode ser um aplicativo baseado no Windows. Pode ser algum outro tipo de módulo (por exemplo, MS-DOS ou OS/2) se o subsistema apropriado estiver disponível no computador local.

A cadeia de caracteres pode especificar o caminho completo e o nome do arquivo do módulo a ser executado ou pode especificar um nome parcial. No caso de um nome parcial, a função usa a unidade atual e o diretório atual para concluir a especificação. A função não usará o caminho de pesquisa. Esse parâmetro deve incluir a extensão de nome de arquivo; nenhuma extensão padrão é assumida.

O parâmetro lpApplicationName pode ser NULL. Nesse caso, o nome do módulo deve ser o primeiro token delimitado por espaço em branco na cadeia de caracteres lpCommandLine . Se você estiver usando um nome de arquivo longo que contenha um espaço, use cadeias de caracteres entre aspas para indicar onde o nome do arquivo termina e os argumentos começam; caso contrário, o nome do arquivo é ambíguo. Por exemplo, considere a cadeia de caracteres "c:\program files\sub dir\program name". Essa cadeia de caracteres pode ser interpretada de várias maneiras. O sistema tenta interpretar as possibilidades na seguinte ordem:

c:\program.exec:\program files\sub.exec:\program files\sub dir\program.exec:\program files\sub dir\program name.exe Se o módulo executável for um aplicativo de 16 bits, lpApplicationName deverá ser NULL e a cadeia de caracteres apontada por lpCommandLine deverá especificar o módulo executável, bem como seus argumentos. Por padrão, todos os aplicativos baseados no Windows de 16 bits criados por CreateProcessAsUser são executados em uma VDM separada (equivalente a CREATE_SEPARATE_WOW_VDM em CreateProcess).

[in, out, optional] lpCommandLine

A linha de comando a ser executada. O comprimento máximo dessa cadeia de caracteres é de 32 mil caracteres. Se lpApplicationName for NULL, a parte do nome do módulo de lpCommandLine será limitada a MAX_PATH caracteres.

A versão Unicode dessa função, CreateProcessAsUserW, pode modificar o conteúdo dessa cadeia de caracteres. Portanto, esse parâmetro não pode ser um ponteiro para memória somente leitura (como uma variável const ou uma cadeia de caracteres literal). Se esse parâmetro for uma cadeia de caracteres constante, a função poderá causar uma violação de acesso.

O parâmetro lpCommandLine pode ser NULL. Nesse caso, a função usa a cadeia de caracteres apontada por lpApplicationName como a linha de comando.

Se lpApplicationName e lpCommandLine forem não NULL, *lpApplicationName especificará o módulo a ser executado e *lpCommandLine especificará a linha de comando. O novo processo pode usar GetCommandLine para recuperar toda a linha de comando. Os processos de console escritos em C podem usar os argumentos argc e argv para analisar a linha de comando. Como argv[0] é o nome do módulo, os programadores C geralmente repetem o nome do módulo como o primeiro token na linha de comando.

Se lpApplicationName for NULL, o primeiro token delimitado por espaço em branco da linha de comando especificará o nome do módulo. Se você estiver usando um nome de arquivo longo que contenha um espaço, use cadeias de caracteres entre aspas para indicar onde o nome do arquivo termina e os argumentos começam (consulte a explicação para o parâmetro lpApplicationName ). Se o nome do arquivo não contiver uma extensão, .exe será acrescentado. Portanto, se a extensão de nome de arquivo for .com, esse parâmetro deverá incluir a extensão .com. Se o nome do arquivo terminar em um ponto (.) sem extensão ou se o nome do arquivo contiver um caminho, .exe não será acrescentado. Se o nome do arquivo não contiver um caminho de diretório, o sistema pesquisará o arquivo executável na seguinte sequência:

  1. O diretório do qual o aplicativo foi carregado.
  2. O diretório atual para o processo pai.
  3. O diretório do sistema Windows de 32 bits. Use a função GetSystemDirectory para obter o caminho desse diretório.
  4. O diretório do sistema Windows de 16 bits. Não há nenhuma função que obtenha o caminho desse diretório, mas ela é pesquisada.
  5. O diretório do Windows. Use a função GetWindowsDirectory para obter o caminho desse diretório.
  6. Os diretórios listados na variável de ambiente PATH. Observe que essa função não pesquisa o caminho por aplicativo especificado pela chave do Registro de Caminhos de Aplicativo . Para incluir esse caminho por aplicativo na sequência de pesquisa, use a função ShellExecute .
O sistema adiciona um caractere nulo à cadeia de caracteres de linha de comando para separar o nome do arquivo dos argumentos. Isso divide a cadeia de caracteres original em duas cadeias de caracteres para processamento interno.

[in, optional] lpProcessAttributes

Um ponteiro para uma estrutura SECURITY_ATTRIBUTES que especifica um descritor de segurança para o novo objeto de processo e determina se os processos filho podem herdar o identificador retornado para o processo. Se lpProcessAttributes for NULL ou lpSecurityDescriptor for NULL, o processo obterá um descritor de segurança padrão e o identificador não poderá ser herdado. O descritor de segurança padrão é o do usuário referenciado no parâmetro hToken . Esse descritor de segurança pode não permitir o acesso para o chamador, caso em que o processo pode não ser aberto novamente após a execução. O identificador do processo é válido e continuará a ter direitos de acesso total.

[in, optional] lpThreadAttributes

Um ponteiro para uma estrutura SECURITY_ATTRIBUTES que especifica um descritor de segurança para o novo objeto de thread e determina se os processos filho podem herdar o identificador retornado para o thread. Se lpThreadAttributes for NULL ou lpSecurityDescriptor for NULL, o thread obterá um descritor de segurança padrão e o identificador não poderá ser herdado. O descritor de segurança padrão é o do usuário referenciado no parâmetro hToken . Esse descritor de segurança pode não permitir o acesso para o chamador.

[in] bInheritHandles

Se esse parâmetro for TRUE, cada identificador herdável no processo de chamada será herdado pelo novo processo. Se o parâmetro for FALSE, os identificadores não serão herdados. Observe que os identificadores herdados têm o mesmo valor e direitos de acesso que os identificadores originais. Para obter discussões adicionais sobre identificadores herdáveis, consulte Comentários.

Serviços de Terminal: Você não pode herdar identificadores entre sessões. Além disso, se esse parâmetro for TRUE, você deverá criar o processo na mesma sessão que o chamador.

Processos PPL (Protected Process Light): A herança de identificador genérico é bloqueada quando um processo PPL cria um processo não PPL, pois PROCESS_DUP_HANDLE não é permitido de um processo não PPL para um processo PPL. Confira Direitos de acesso e segurança do processo

[in] dwCreationFlags

Os sinalizadores que controlam a classe de prioridade e a criação do processo. Para obter uma lista de valores, consulte Sinalizadores de criação de processo.

Esse parâmetro também controla a classe de prioridade do novo processo, que é usada para determinar as prioridades de agendamento dos threads do processo. Para obter uma lista de valores, consulte GetPriorityClass. Se nenhum dos sinalizadores de classe de prioridade for especificado, a classe de prioridade usará como padrão NORMAL_PRIORITY_CLASS , a menos que a classe de prioridade do processo de criação seja IDLE_PRIORITY_CLASS ou BELOW_NORMAL_PRIORITY_CLASS. Nesse caso, o processo filho recebe a classe de prioridade padrão do processo de chamada.

Se o parâmetro dwCreationFlags tiver um valor de 0:

  • O processo herda o modo de erro do chamador e o console do pai.
  • Supõe-se que o bloco de ambiente do novo processo contenha caracteres ANSI (consulte o parâmetro lpEnvironment para obter informações adicionais).
  • Um aplicativo baseado no Windows de 16 bits é executado em uma VDM (máquina virtual dos DOS) compartilhada.

[in, optional] lpEnvironment

Um ponteiro para um bloco de ambiente para o novo processo. Se esse parâmetro for NULL, o novo processo usará o ambiente do processo de chamada.

Um bloco de ambiente consiste em um bloco encerrado em nulo de cadeias de caracteres terminadas em nulo. Cada cadeia de caracteres está no seguinte formato:

Nome=value\0

Como o sinal de igual é usado como separador, ele não deve ser usado no nome de uma variável de ambiente.

Um bloco de ambiente pode conter caracteres Unicode ou ANSI. Se o bloco de ambiente apontado por lpEnvironment contiver caracteres Unicode, verifique se dwCreationFlags inclui CREATE_UNICODE_ENVIRONMENT.

A versão ANSI dessa função, CreateProcessAsUserA , falhará se o tamanho total do bloco de ambiente do processo exceder 32.767 caracteres.

Observe que um bloco de ambiente ANSI é encerrado por dois bytes zero: um para a última cadeia de caracteres, outro para encerrar o bloco. Um bloco de ambiente Unicode é encerrado por quatro bytes zero: dois para a última cadeia de caracteres, mais dois para encerrar o bloco.

Windows Server 2003 e Windows XP: Se o tamanho da variável de ambiente de usuário e sistema combinada exceder 8192 bytes, o processo criado por CreateProcessAsUser não será mais executado com o bloco de ambiente passado para a função pelo processo pai. Em vez disso, o processo filho é executado com o bloco de ambiente retornado pela função CreateEnvironmentBlock .

Para recuperar uma cópia do bloco de ambiente para um determinado usuário, use a função CreateEnvironmentBlock .

[in, optional] lpCurrentDirectory

O caminho completo para o diretório atual do processo. A cadeia de caracteres também pode especificar um caminho UNC.

Se este parâmetro for NULL, o novo processo terá a mesma unidade e diretório atual que o processo de chamada. (Esse recurso é fornecido principalmente para shells que precisam iniciar um aplicativo e especificar sua unidade inicial e diretório de trabalho.)

[in] lpStartupInfo

Um ponteiro para uma estrutura STARTUPINFO ou STARTUPINFOEX .

O usuário deve ter acesso total à estação de janela especificada e à área de trabalho. Se você quiser que o processo seja interativo, especifique winsta0\default. Se o membro lpDesktop for NULL, o novo processo herdará a área de trabalho e a estação de janela de seu processo pai. Se esse membro for uma cadeia de caracteres vazia, "", o novo processo se conectará a uma estação de janela usando as regras descritas em Processar Conexão com uma Estação de Janela.

Para definir atributos estendidos, use uma estrutura STARTUPINFOEX e especifique EXTENDED_STARTUPINFO_PRESENT no parâmetro dwCreationFlags .

Os identificadores em STARTUPINFO ou STARTUPINFOEX devem ser fechados com CloseHandle quando não forem mais necessários.

Importante O chamador é responsável por garantir que os campos de identificador padrão em STARTUPINFO contenham valores de identificador válidos. Esses campos são copiados inalterados para o processo filho sem validação, mesmo quando o membro dwFlags especifica STARTF_USESTDHANDLES. Valores incorretos podem fazer com que o processo filho se comporte mal ou falhe. Use a ferramenta de verificação de runtime do Verificador de Aplicativos para detectar identificadores inválidos.
 

[out] lpProcessInformation

Um ponteiro para uma estrutura PROCESS_INFORMATION que recebe informações de identificação sobre o novo processo.

Os identificadores em PROCESS_INFORMATION devem ser fechados com CloseHandle quando não forem mais necessários.

Valor retornado

Se a função for bem-sucedida, o valor retornado será diferente de zero.

Se a função falhar, o valor retornado será zero. Para obter informações de erro estendidas, chame GetLastError.

Observe que a função retorna antes que o processo termine a inicialização. Se uma DLL necessária não puder ser localizada ou falhar ao inicializar, o processo será encerrado. Para obter a status de encerramento de um processo, chame GetExitCodeProcess.

Comentários

CreateProcessAsUser deve ser capaz de abrir o token primário do processo de chamada com os direitos de acesso TOKEN_DUPLICATE e TOKEN_IMPERSONATE .

Por padrão, CreateProcessAsUser cria o novo processo em uma estação de janela nãointerativa com uma área de trabalho que não está visível e não pode receber entrada do usuário. Para habilitar a interação do usuário com o novo processo, você deve especificar o nome da estação de janela interativa padrão e da área de trabalho, "winsta0\default", no membro lpDesktop da estrutura STARTUPINFO . Além disso, antes de chamar CreateProcessAsUser, você deve alterar a DACL (lista de controle de acesso discricionário) da estação de janela interativa padrão e da área de trabalho padrão. Os DACLs da estação de janela e da área de trabalho devem conceder acesso ao usuário ou à sessão de logon representada pelo parâmetro hToken .

CreateProcessAsUser não carrega o perfil do usuário especificado na chave do registro HKEY_USERS . Portanto, para acessar as informações na chave do registro HKEY_CURRENT_USER , você deve carregar as informações de perfil do usuário em HKEY_USERS com a função LoadUserProfile antes de chamar CreateProcessAsUser. Certifique-se de chamar UnloadUserProfile após a saída do novo processo.

Se o parâmetro lpEnvironment for NULL, o novo processo herdará o ambiente do processo de chamada. CreateProcessAsUser não modifica automaticamente o bloco de ambiente para incluir variáveis de ambiente específicas ao usuário representado pelo hToken. Por exemplo, as variáveis USERNAME e USERDOMAIN serão herdadas do processo de chamada se lpEnvironment for NULL. É sua responsabilidade preparar o bloco de ambiente para o novo processo e especificá-lo em lpEnvironment.

As funções CreateProcessWithLogonW e CreateProcessWithTokenW são semelhantes a CreateProcessAsUser, exceto que o chamador não precisa chamar a função LogonUser para autenticar o usuário e obter um token.

CreateProcessAsUser permite que você acesse o diretório especificado e a imagem executável no contexto de segurança do chamador ou do usuário de destino. Por padrão, CreateProcessAsUser acessa o diretório e a imagem executável no contexto de segurança do chamador. Nesse caso, se o chamador não tiver acesso ao diretório e à imagem executável, a função falhará. Para acessar o diretório e a imagem executável usando o contexto de segurança do usuário de destino, especifique hToken em uma chamada para a função ImpersonateLoggedOnUser antes de chamar CreateProcessAsUser.

O processo recebe um identificador de processo. O identificador é válido até que o processo seja encerrado. Ele pode ser usado para identificar o processo ou especificado na função OpenProcess para abrir um identificador para o processo. O thread inicial no processo também recebe um identificador de thread. Ele pode ser especificado na função OpenThread para abrir um identificador para o thread. O identificador é válido até que o thread seja encerrado e possa ser usado para identificar exclusivamente o thread dentro do sistema. Esses identificadores são retornados na estrutura PROCESS_INFORMATION .

O thread de chamada pode usar a função WaitForInputIdle para aguardar até que o novo processo termine sua inicialização e esteja aguardando a entrada do usuário sem nenhuma entrada pendente. Isso pode ser útil para sincronização entre processos pai e filho, pois CreateProcessAsUser retorna sem esperar que o novo processo conclua sua inicialização. Por exemplo, o processo de criação usaria WaitForInputIdle antes de tentar encontrar uma janela associada ao novo processo.

A maneira preferencial de encerrar um processo é usando a função ExitProcess , pois essa função envia uma notificação de encerramento aproximado para todas as DLLs anexadas ao processo. Outros meios de desligar um processo não notificam as DLLs anexadas. Observe que quando um thread chama ExitProcess, outros threads do processo são encerrados sem a oportunidade de executar qualquer código adicional (incluindo o código de encerramento de thread de DLLs anexadas). Para obter mais informações, consulte Encerrando um processo.

Por padrão, passar TRUE como o valor do parâmetro bInheritHandles faz com que todos os identificadores herdáveis sejam herdados pelo novo processo. Isso pode ser problemático para aplicativos que criam processos de vários threads simultaneamente, mas desejam que cada processo herde identificadores diferentes. Os aplicativos podem usar a função UpdateProcThreadAttributeList com o parâmetro PROC_THREAD_ATTRIBUTE_HANDLE_LIST para fornecer uma lista de identificadores a serem herdados por um processo específico.

Comentários de segurança

O parâmetro lpApplicationName pode ser NULL, nesse caso, o nome executável deve ser a primeira cadeia de caracteres delimitada por espaço em branco em lpCommandLine. Se o nome do executável ou caminho tiver um espaço nele, há o risco de que um executável diferente possa ser executado devido à maneira como a função analisa espaços. O exemplo a seguir é perigoso porque a função tentará executar "Program.exe", se existir, em vez de "MyApp.exe".
	LPTSTR szCmdline[] = _tcsdup(TEXT("C:\\Program Files\\MyApp"));
	CreateProcessAsUser(hToken, NULL, szCmdline, /*...*/ );

Se um usuário mal-intencionado criar um aplicativo chamado "Program.exe" em um sistema, qualquer programa que chame CreateProcessAsUser incorretamente usando o diretório Arquivos de Programas executará esse aplicativo em vez do aplicativo pretendido.

Para evitar esse problema, não passe NULL para lpApplicationName. Se você passar NULL para lpApplicationName, use aspas ao redor do caminho executável em lpCommandLine, conforme mostrado no exemplo abaixo.

	LPTSTR szCmdline[] = _tcsdup(TEXT("\"C:\\Program Files\\MyApp\""));
	CreateProcessAsUser(hToken, NULL, szCmdline, /*...*/);

Powershell: Quando a função CreateProcessAsUser é usada para implementar um cmdlet no PowerShell versão 2.0, o cmdlet opera corretamente para sessões remotas fan-in e fan-out. Por causa de determinados cenários de segurança, no entanto, um cmdlet implementado com CreateProcessAsUser só funciona corretamente no PowerShell versão 3.0 para sessões remotas fan-in; As sessões remotas de fan-out falharão devido a privilégios de segurança de cliente insuficientes. Para implementar um cmdlet que funciona para sessões remotas fan-in e fan-out no PowerShell versão 3.0, use a função CreateProcess .

Exemplos

Para obter um exemplo, consulte Iniciando um processo de cliente interativo.

Observação

O cabeçalho processthreadsapi.h define CreateProcessAsUser como um alias que seleciona automaticamente a versão ANSI ou Unicode dessa função com base na definição da constante de pré-processador UNICODE. Misturar o uso do alias neutro de codificação com código que não seja neutro em codificação pode levar a incompatibilidades que resultam em erros de compilação ou de runtime. Para obter mais informações, consulte Convenções para protótipos de função.

Requisitos

Requisito Valor
Cliente mínimo com suporte Windows XP [somente aplicativos da área de trabalho]
Servidor mínimo com suporte Windows Server 2003 [somente aplicativos da área de trabalho]
Plataforma de Destino Windows
Cabeçalho processthreadsapi.h (inclua Windows.h)
Biblioteca Advapi32.lib
DLL Advapi32.dll

Confira também

CloseHandle

CreateEnvironmentBlock

CreateProcess

CreateProcessWithLogonW

ExitProcess

GetEnvironmentStrings

Getexitcodeprocess

GetStartupInfo

Impersonateloggedonuser

LoadUserProfile

PROCESS_INFORMATION

Funções de thread e processo

Processos

SECURITY_ATTRIBUTES

SHCreateProcessAsUserW

STARTUPINFO

STARTUPINFOEX

SetErrorMode

Waitforinputidle