Compartilhar via


Função CreateProcessWithLogonW (winbase.h)

Cria um novo processo e seu thread primário. Em seguida, o novo processo executa o arquivo executável especificado no contexto de segurança das credenciais especificadas (usuário, domínio e senha). Opcionalmente, ele pode carregar o perfil do usuário para um usuário especificado.

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

Sintaxe

BOOL CreateProcessWithLogonW(
  [in]                LPCWSTR               lpUsername,
  [in, optional]      LPCWSTR               lpDomain,
  [in]                LPCWSTR               lpPassword,
  [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] lpUsername

O nome do usuário. Esse é o nome da conta de usuário na qual fazer logon. Se você usar o formato UPN, o usuário@DNS_domain_name, o parâmetro lpDomain deverá ser NULL.

A conta de usuário deve ter a permissão Fazer Logon Localmente no computador local. Essa permissão é concedida a todos os usuários em estações de trabalho e servidores, mas somente aos administradores em controladores de domínio.

[in, optional] lpDomain

O nome do domínio ou servidor cujo banco de dados de conta contém a conta lpUsername . Se esse parâmetro for NULL, o nome de usuário deverá ser especificado no formato UPN.

[in] lpPassword

A senha de texto não criptografado para a conta lpUsername .

[in] dwLogonFlags

A opção de logon. Esse parâmetro pode ser 0 (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 ou não processos filho.

Windows XP: O perfil é descarregado após o novo processo e todos os processos filho que ele criou são encerrados.

LOGON_NETCREDENTIALS_ONLY
0x00000002
Faça logon, mas use apenas as credenciais especificadas 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á nenhuma 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. Se for um nome parcial, a função usará a unidade atual e o diretório atual para concluir a especificação. A função não usa 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 e 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, a cadeia de caracteres a seguir pode ser interpretada de maneiras diferentes:

"c:\program files\sub dir\program name"

O sistema tenta interpretar as possibilidades na seguinte ordem:

  1. c:\program.exe files\sub dir\program name
  2. c:\program files\sub.exe dir\program name
  3. c:\program files\sub dir\program.exe name
  4. c:\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 e 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 e 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 normalmente 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 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 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] dwCreationFlags

Os sinalizadores que controlam como o processo é criado. Os sinalizadores CREATE_DEFAULT_ERROR_MODE, CREATE_NEW_CONSOLE e CREATE_NEW_PROCESS_GROUP estã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 de 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 terminado 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 0 (zero): um para a última cadeia de caracteres e 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 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 STARTUPINFO .

O aplicativo deve adicionar permissão para a conta de usuário especificada à estação de janela e à área de trabalho especificadas, mesmo para WinSta0\Default.

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. O aplicativo deve adicionar permissão para a conta de usuário especificada à estação de janela herdada e à área de trabalho.

Windows XP: CreateProcessWithLogonW adiciona permissão para a conta de usuário especificada à estação de janela herdada e à área de trabalho.

Os identificadores no STARTUPINFO 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 em PROCESS_INFORMATION devem ser fechados com a função CloseHandle quando não forem 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 (0). 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, CreateProcessWithLogonW não carrega o perfil de 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 de usuário em HKEY_USERS antes de chamar CreateProcessWithLogonW, usando LOGON_WITH_PROFILE ou chamando a função LoadUserProfile .

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, CreateProcessWithLogonW 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 pode ser 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 tenha concluído 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 CreateProcessWithLogonW 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.

CreateProcessWithLogonW acessa o diretório especificado e a imagem executável no contexto de segurança do usuário de destino. Se a imagem executável estiver em uma rede e uma letra da unidade de rede for especificada no caminho, a letra da unidade de rede não estará disponível para o usuário de destino, pois as letras da unidade de rede poderão ser atribuídas para cada logon. Se uma letra da unidade de rede for especificada, essa função falhará. Se a imagem executável estiver em uma rede, use o caminho UNC.

Há um limite para o número de processos filho que podem ser criados por essa função e executados simultaneamente. Por exemplo, no Windows XP, esse limite é MAXIMUM_WAIT_OBJECTS*4. No entanto, talvez você não consiga criar tantos processos devido aos limites de cota em todo o sistema.

Windows XP com SP2, Windows Server 2003 ou posterior: Você não pode chamar CreateProcessWithLogonW de um processo em execução na conta "LocalSystem", porque a função usa o SID de logon no token de chamador e o token da conta "LocalSystem" não contém esse SID. Como alternativa, use as funções CreateProcessAsUser e LogonUser .

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 e 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. Evite o exemplo a seguir, pois a função tenta executar "Program.exe", se existir, em vez de "MyApp.exe".
LPTSTR szCmdline[]=_tcsdup(TEXT("C:\\Program Files\\MyApp"));
CreateProcessWithLogonW(..., szCmdline, ...)

Se um usuário mal-intencionado criar um aplicativo chamado "Program.exe" em um sistema, qualquer programa que chame CreateProcessWithLogonW incorretamente usando o diretório Arquivos de Programas executará o aplicativo de usuário mal-intencionado 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 a seguir:

LPTSTR szCmdline[]=_tcsdup(TEXT("\"C:\\Program Files\\MyApp\""));
CreateProcessWithLogonW(..., szCmdline, ...)

Exemplos

O exemplo a seguir demonstra como chamar essa função.


#include <windows.h>
#include <stdio.h>
#include <userenv.h>

void DisplayError(LPWSTR pszAPI)
{
    LPVOID lpvMessageBuffer;

    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 
        FORMAT_MESSAGE_FROM_SYSTEM,
        NULL, GetLastError(), 
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
        (LPWSTR)&lpvMessageBuffer, 0, NULL);

    //
    //... now display this string
    //
    wprintf(L"ERROR: API        = %s.\n", pszAPI);
    wprintf(L"       error code = %d.\n", GetLastError());
    wprintf(L"       message    = %s.\n", (LPWSTR)lpvMessageBuffer);

    //
    // Free the buffer allocated by the system
    //
    LocalFree(lpvMessageBuffer);

    ExitProcess(GetLastError());
}

void wmain(int argc, WCHAR *argv[])
{
    DWORD     dwSize;
    HANDLE    hToken;
    LPVOID    lpvEnv;
    PROCESS_INFORMATION pi = {0};
    STARTUPINFO         si = {0};
    WCHAR               szUserProfile[256] = L"";

    si.cb = sizeof(STARTUPINFO);
    
    if (argc != 4)
    {
        wprintf(L"Usage: %s [user@domain] [password] [cmd]", argv[0]);
        wprintf(L"\n\n");
        return;
    }

    //
    // TO DO: change NULL to '.' to use local account database
    //
    if (!LogonUser(argv[1], NULL, argv[2], LOGON32_LOGON_INTERACTIVE, 
            LOGON32_PROVIDER_DEFAULT, &hToken))
        DisplayError(L"LogonUser");

    if (!CreateEnvironmentBlock(&lpvEnv, hToken, TRUE))
        DisplayError(L"CreateEnvironmentBlock");

    dwSize = sizeof(szUserProfile)/sizeof(WCHAR);

    if (!GetUserProfileDirectory(hToken, szUserProfile, &dwSize))
        DisplayError(L"GetUserProfileDirectory");

    //
    // TO DO: change NULL to '.' to use local account database
    //
    if (!CreateProcessWithLogonW(argv[1], NULL, argv[2], 
            LOGON_WITH_PROFILE, NULL, argv[3], 
            CREATE_UNICODE_ENVIRONMENT, lpvEnv, szUserProfile, 
            &si, &pi))
        DisplayError(L"CreateProcessWithLogonW");

    if (!DestroyEnvironmentBlock(lpvEnv))
        DisplayError(L"DestroyEnvironmentBlock");

    CloseHandle(hToken);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
}

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 winbase.h (inclua Windows.h)
Biblioteca Advapi32.lib
DLL Advapi32.dll

Confira também

CloseHandle

CreateEnvironmentBlock

Createprocessasuser

ExitProcess

GetEnvironmentStrings

Getexitcodeprocess

Openprocess

PROCESS_INFORMATION

Funções de thread e processo

Processos

STARTUPINFO

SetErrorMode

Waitforinputidle