Função CreateProcessWithTokenW (winbase.h)

Cria um novo processo e seu thread primário. O novo processo é executado no contexto de segurança do token especificado. Opcionalmente, ele pode carregar o perfil de usuário para o usuário especificado.

O processo que chama CreateProcessWithTokenW deve ter o privilégio SE_IMPERSONATE_NAME. Se essa função falhar com ERROR_PRIVILEGE_NOT_HELD (1314), use a função CreateProcessAsUser ou CreateProcessWithLogonW . Normalmente, o processo que chama
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. CreateProcessWithLogonW não requer privilégios especiais, mas a conta de usuário especificada deve ter permissão para fazer logon interativamente. Geralmente, é melhor usar CreateProcessWithLogonW para criar um processo com credenciais alternativas.

Sintaxe

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

Parâmetros

[in] 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 esteja representando um cliente crie um processo que tenha o contexto de segurança do cliente.

Serviços de Terminal: O processo do chamador sempre é executado na sessão do chamador, não na sessão especificada no token. Para executar um processo na sessão especificada no token, use a função CreateProcessAsUser.

[in] dwLogonFlags

A opção de logon. Esse parâmetro pode ser zero ou um dos valores a seguir.

Valor Significado
LOGON_WITH_PROFILE
0x00000001
Faça logon e carregue o perfil do usuário na chave do registro HKEY_USERS . A função retorna depois que o perfil é carregado. Carregar o perfil pode ser demorado, portanto, é melhor usar esse valor somente se você precisar acessar as informações na chave do Registro HKEY_CURRENT_USER .

Windows Server 2003: O perfil é descarregado depois que o novo processo é encerrado, independentemente de ter criado processos filho.

LOGON_NETCREDENTIALS_ONLY
0x00000002
Faça logon, mas use as credenciais especificadas apenas na rede. O novo processo usa o mesmo token que o chamador, mas o sistema cria uma nova sessão de logon no LSA e o processo usa as credenciais especificadas como as credenciais padrão.

Esse valor pode ser usado para criar um processo que usa um conjunto diferente de credenciais localmente do que remotamente. Isso é útil em cenários entre domínios em que não há relação de confiança.

O sistema não valida as credenciais especificadas. Portanto, o processo pode ser iniciado, mas pode não ter acesso aos recursos de rede.

[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 as 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.

[in, out, optional] lpCommandLine

A linha de comando a ser executada.

O comprimento máximo dessa cadeia de caracteres é de 1024 caracteres. Se lpApplicationName for NULL, a parte do nome do módulo de lpCommandLine será limitada a MAX_PATH caracteres.

A função 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 não forem 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 as 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 período (.) 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 procurará 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 caminhos do 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] dwCreationFlags

Os sinalizadores que controlam como o processo é criado. Os sinalizadores CREATE_DEFAULT_ERROR_MODE, CREATE_NEW_CONSOLE e CREATE_NEW_PROCESS_GROUP são habilitados por padrão. 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 igual a 0:

  • O processo obtém o modo de erro padrão, cria um novo console e cria um novo grupo de processos.
  • 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á um ambiente criado a partir do perfil do usuário especificado por lpUsername.

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=Valor

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.

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 e mais dois para encerrar o bloco.

Para recuperar uma cópia do bloco de ambiente para um usuário específico, 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 .

Se o membro lpDesktop for NULL ou uma cadeia de caracteres vazia, o novo processo herdará a área de trabalho e a estação de janela de seu processo pai. A função adiciona permissão para a conta de usuário especificada à estação de janela herdada e à área de trabalho. Caso contrário, se esse membro especificar uma área de trabalho, será responsabilidade do aplicativo adicionar permissão para a conta de usuário especificada à estação de janela especificada e à área de trabalho, mesmo para WinSta0\Default.

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

Importante Se o membro dwFlags da estrutura STARTUPINFOespecificar STARTF_USESTDHANDLES, os campos de identificador padrão serão copiados inalterados para o processo filho sem validação. O chamador é responsável por garantir que esses campos contenham valores de identificador válidos. 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 para o novo processo, incluindo um identificador para o processo.

Os identificadores no PROCESS_INFORMATION devem ser fechados com a função 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

Por padrão, CreateProcessWithTokenW não carrega o perfil do usuário especificado na chave do registro HKEY_USERS . Isso significa que o acesso a informações no HKEY_CURRENT_USER chave do Registro pode não produzir resultados consistentes com um logon interativo normal. É sua responsabilidade carregar o hive do registro do usuário em HKEY_USERS usando LOGON_WITH_PROFILE ou chamando a função LoadUserProfile antes de chamar essa função.

Se o parâmetro lpEnvironment for NULL, o novo processo usará um bloco de ambiente criado a partir do perfil do usuário especificado por lpUserName. Se as variáveis HOMEDRIVE e HOMEPATH não estiverem definidas, CreateProcessWithTokenW modificará o bloco de ambiente para usar a unidade e o caminho do diretório de trabalho do usuário.

Quando criados, os novos identificadores de processo e thread recebem direitos de acesso total (PROCESS_ALL_ACCESS e THREAD_ALL_ACCESS). Para qualquer um dos identificadores, se um descritor de segurança não for fornecido, o identificador poderá ser usado em qualquer função que exija um identificador de objeto desse tipo. Quando um descritor de segurança é fornecido, um marcar de acesso é executado em todos os usos subsequentes do identificador antes que o acesso seja concedido. Se o acesso for negado, o processo de solicitação não poderá usar o identificador para obter acesso ao processo ou thread.

Para recuperar um token de segurança, passe o identificador de processo na estrutura PROCESS_INFORMATION para a função OpenProcessToken .

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 em 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 CreateProcessWithTokenW 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.

Para compilar um aplicativo que usa essa função, defina _WIN32_WINNT como 0x0500 ou posterior. Para obter mais informações, consulte Usando os cabeçalhos do Windows.

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 = L"C:\\Program Files\\MyApp";
	CreateProcessWithTokenW(/*...*/, szCmdline, /*...*/);

Se um usuário mal-intencionado criar um aplicativo chamado "Program.exe" em um sistema, qualquer programa que chame CreateProcessWithTokenW 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 = L"\"C:\\Program Files\\MyApp\"";
	CreateProcessWithTokenW(/*...*/, szCmdline, /*...*/);

Requisitos

Requisito Valor
Cliente mínimo com suporte Windows Vista [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 winbase.h (inclua Windows.h)
Biblioteca Advapi32.lib
DLL Advapi32.dll

Confira também

CloseHandle

CreateEnvironmentBlock

ExitProcess

GetEnvironmentStrings

Getexitcodeprocess

Openprocess

PROCESS_INFORMATION

Funções de thread e processo

Processos

STARTUPINFO

SetErrorMode

Waitforinputidle