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
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_DUPLICATEe TOKEN_ASSIGN_PRIMARY. Para obter mais informações, consulte Access Rights for Access-Token Objects. O usuário representado pelo token deve ter acesso de leitura e execução ao aplicativo especificado pelo
Para obter um token primário que represente 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.
Se hToken for uma versão restrita do token primário do chamador, o privilégio de 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, consulte Em execução 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 SO/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
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 deve especificar o módulo executável, bem como seus argumentos. Por padrão, todos os aplicativos baseados no Windows de 16 bits criados pelo 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 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 um const variável 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 foremNULL, *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 especifica 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:
- O diretório do qual o aplicativo foi carregado.
- O diretório atual para o processo pai.
- O diretório do sistema Windows de 32 bits. Use a função GetSystemDirectory para obter o caminho desse diretório.
- 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.
- O diretório do Windows. Use a função GetWindowsDirectory para obter o caminho desse diretório.
- Os diretórios listados na variável de ambiente PATH. Observe que essa função não pesquisa o caminho por aplicativo especificado pelo Caminhos do Aplicativo chave do Registro. Para incluir esse caminho por aplicativo na sequência de pesquisa, use a função ShellExecute.
[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 estiver 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 de SECURITY_ATTRIBUTES que especifica um descritor de segurança para o novo objeto thread e determina se os processos filho podem herdar o identificador retornado para o thread. Se lpThreadAttributes estiver NULL ou lpSecurityDescriptor estiver 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 acesso para o chamador.
[in] bInheritHandles
Se esse parâmetro for VERDADEIRO, cada identificador herdável no processo de chamada será herdado pelo novo processo. Se o parâmetro for FALSE, as alças não serão herdadas. Observe que as alças herdadas 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 de PPL (Protected Process Light): A herança de identificador genérico é bloqueada quando um processo ppl cria um processo não PPL, uma vez que PROCESS_DUP_HANDLE não é permitido de um processo não PPL para um processo PPL. Consulte de 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 será 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 do console do pai.
- Supõe-se que o bloco de ambiente do novo processo contenha caracteres ANSI (consulte lpEnvironment parâmetro 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á na seguinte forma:
nome=valor\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, certifique-se de que dwCreationFlags inclua 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, mais um 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 8.192 bytes, o processo criado pelo 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 esse parâmetro for NULL, o novo processo terá a mesma unidade e diretório atuais 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 de STARTUPINFO
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 lpDesktop membro 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 Process Connection to a Window Station.
Para definir atributos estendidos, use uma estrutura de STARTUPINFOEX
Os identificadores em STARTUPINFO ou STARTUPINFOEX devem ser fechados com CloseHandle quando não forem mais necessários.
[out] lpProcessInformation
Um ponteiro para uma estrutura de PROCESS_INFORMATION que recebe informações de identificação sobre o novo processo.
Os identificadores no PROCESS_INFORMATION devem ser fechados com CloseHandle quando não forem mais necessários.
Valor de retorno
Se a função for bem-sucedida, o valor retornado não será 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 o status de encerramento de um processo, chame GetExitCodeProcess.
Observações
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 a 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
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
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 para o usuário representado por 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 acessar 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
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 tenha terminado 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 preferida de desligar um processo é usando a função ExitProcess, pois essa função envia uma notificação de encerramento de aproximação 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 terminação de thread de DLLs anexadas). Para obter mais informações, consulte Encerrando um processo.
Por padrão, passar verdadeiro como o valor do parâmetro bInheritHandles faz com que todas as alças herdáveis sejam herdadas 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
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 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 incorretamente CreateProcessAsUser 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 de fan-in e fan-out. Por causa de determinados cenários de segurança, no entanto, um cmdlet implementado com CreateProcessAsUser só opera corretamente no PowerShell versão 3.0 para sessões remotas de 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 de 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.
Nota
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 do pré-processador UNICODE. A combinação do uso do alias neutro de codificação com código que não é neutro em codificação pode levar a incompatibilidades que resultam em erros de compilação ou de runtime. Para obter mais informações, consulte Conventions for Function Prototypes.
Requisitos
Requisito | Valor |
---|---|
de cliente com suporte mínimo | Windows XP [somente aplicativos da área de trabalho] |
servidor com suporte mínimo | Windows Server 2003 [somente aplicativos da área de trabalho] |
da Plataforma de Destino |
Windows |
cabeçalho | processthreadsapi.h (inclua Windows.h) |
biblioteca | Advapi32.lib |
de DLL |
Advapi32.dll |
Consulte também
GetEnvironmentStrings
WaitForInputIdle