Criar Processo com Usuário Alternativo

15/04/2003

0

Caros Srs.

Estamos desenvolvendo um serviço para Windows 2k e XP que necessita executar processos utilizando usuários diferentes do usuário atualmente logado. Aparentemente, a API mais adequada seria a

CreateProcessWithLogonW

Entretanto, não estamos conseguindo fazer o logon do usuário. Segundo o GetLasError, retorna ´nome de usuário ou senha inválidos´.

Alguém tem alguma experiência no assunto?

[]´s


Mmartinho

Mmartinho

Responder

Posts

15/04/2003

Mmartinho

// Autor: Marcus Martinho
// Observações:
// 1. Crie um novo projeto, com um formulário principal,
// e um botão ´TButton´, associando ao evento a função
// Exct_Prcss_Com_Logon
//
// 2. Esta função se baseia na nova API introduzida nas
// versões do Windows (2000 e XP) CreateProcessWithLogonW.
// É necessário declará-la na UNIT, pois nenhuma biblioteca do
// Delphi a possui.
//
// PS: desculpem a mistura de inglês com português.

unit uExct_Prcss_Logon;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

const
LOGON_WITH_PROFILE = $00000001;
{$EXTERNALSYM LOGON_WITH_PROFILE}

SE_CREATE_TOKEN_NAME = ´SeCreateTokenPrivilege´;
SE_ASSIGNPRIMARYTOKEN_NAME = ´SeAssignPrimaryTokenPrivilege´;
SE_LOCK_MEMORY_NAME = ´SeLockMemoryPrivilege´;
SE_INCREASE_QUOTA_NAME = ´SeIncreaseQuotaPrivilege´;
SE_UNSOLICITED_INPUT_NAME = ´SeUnsolicitedInputPrivilege´;
SE_MACHINE_ACCOUNT_NAME = ´SeMachineAccountPrivilege´;
SE_TCB_NAME = ´SeTcbPrivilege´;
SE_SECURITY_NAME = ´SeSecurityPrivilege´;
SE_TAKE_OWNERSHIP_NAME = ´SeTakeOwnershipPrivilege´;
SE_LOAD_DRIVER_NAME = ´SeLoadDriverPrivilege´;
SE_SYSTEM_PROFILE_NAME = ´SeSystemProfilePrivilege´;
SE_SYSTEMTIME_NAME = ´SeSystemtimePrivilege´;
SE_PROF_SINGLE_PROCESS_NAME = ´SeProfileSingleProcessPrivilege´;
SE_INC_BASE_PRIORITY_NAME = ´SeIncreaseBasePriorityPrivilege´;
SE_CREATE_PAGEFILE_NAME = ´SeCreatePagefilePrivilege´;
SE_CREATE_PERMANENT_NAME = ´SeCreatePermanentPrivilege´;
SE_BACKUP_NAME = ´SeBackupPrivilege´;
SE_RESTORE_NAME = ´SeRestorePrivilege´;
SE_SHUTDOWN_NAME = ´SeShutdownPrivilege´;
SE_DEBUG_NAME = ´SeDebugPrivilege´;
SE_AUDIT_NAME = ´SeAuditPrivilege´;
SE_SYSTEM_ENVIRONMENT_NAME = ´SeSystemEnvironmentPrivilege´;
SE_CHANGE_NOTIFY_NAME = ´SeChangeNotifyPrivilege´;
SE_REMOTE_SHUTDOWN_NAME = ´SeRemoteShutdownPrivilege´;

function CreateProcessWithLogonW( lpUsername : LPCWSTR ;
lpDomain : LPCWSTR ;
lpPassword : LPCWSTR ;
dwLogonFlags : DWORD ;
lpApplicationName : LPCWSTR ;
lpCommandLine : LPCWSTR ;
dwCreationFlags : DWORD ;
lpEnvironment : Pointer ;
lpCurrentDirectory : LPCWSTR ;
const lpStartupInfo : TStartupInfo ;
var lpProcessInfo : TProcessInformation ) : BOOL; stdcall;
{$EXTERNALSYM CreateProcessWithLogonW}

type
TLoginCommand = record
CommandLine , // Linha de comando que passamos para o novo processo
pwstr , // Senha
NewDomain , // Novo domínio a logar
NewUser : String; // Novo usuário a logar
end; // record

TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
function Exct_Prcss_Com_Logon(LgnCmd: TLoginCommand): Boolean;
function GetPrivilegeDisplayName(const PrivilegeName: String): String;
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

function CreateProcessWithLogonW; external advapi32 name ´CreateProcessWithLogonW´;

function TForm1.GetPrivilegeDisplayName(const PrivilegeName: String): String;
var dw, li: DWord;
begin
Result := EmptyStr;
dw := 0;
li := 0; // li:= dword(MAKELANGID(LANG_DEFAULT, LANG_USER));

if not LookupPrivilegeDisplayName(nil, PChar(PrivilegeName), PChar(Result), dw, li) then
dw := 256;

SetLength(Result, dw+1);

if LookupPrivilegeDisplayName(nil, PChar(PrivilegeName), PChar(Result), dw, li) then
SetLength(Result, StrLen(PChar(Result)))
else
Result:= EmptyStr;
end;

function TForm1.Exct_Prcss_Com_Logon(LgnCmd : TLoginCommand) : Boolean;
var CurUser , // Usuário atual
CurDomain : String; // Domínio atual
startUpInfo : TStartupInfo;
procInfo : TProcessInformation; // Informações do processo filho do CreateProcessAsUser
NTversion : TOSVersionInfo;
Executou : Boolean;
nwUsr ,
nwDomain ,
psw ,
CmdLine ,
flPath : LPCWSTR;
begin

FillChar(startUpInfo, SizeOf(startUpInfo), 0);

with startUpInfo do
begin
cb := SizeOf(startUpInfo);
end;

try
// Conversão de String para WideChar...
with LgnCmd do
begin
GetMem(nwUsr , Length(NewUser) * SizeOf(WideChar) + 1);
GetMem(nwDomain, Length(NewDomain) * SizeOf(WideChar) + 1);
GetMem(psw , Length(pwstr) * SizeOf(WideChar) + 1);
GetMem(CmdLine , Length(CommandLine) * SizeOf(WideChar) + 1);
GetMem(flPath , Length(ExtractFilePath(CommandLine)) * SizeOf(WideChar) + 1);

StringToWideChar(NewUser , nwUsr , Length(NewUser) * SizeOf(WideChar) + 1);
StringToWideChar(NewDomain , nwDomain , Length(NewDomain) * SizeOf(WideChar) + 1);
StringToWideChar(pwstr , psw , Length(pwstr) * SizeOf(WideChar) + 1);
StringToWideChar(CommandLine , CmdLine , Length(CommandLine) * SizeOf(WideChar) + 1);
StringToWideChar(ExtractFilePath(CommandLine), flPath , Length(ExtractFilePath(CommandLine)) * SizeOf(WideChar) + 1);
end;

// Cria o processo filho...
if not CreateProcessWithLogonW( nwUsr, // lpUsername
nwDomain, // lpDomain
psw, // lpPassword
LOGON_WITH_PROFILE, // dwLogonFlags
CmdLine, // lpApplicationName
CmdLine, // lpCommandLine
CREATE_DEFAULT_ERROR_MODE, // dwCreationFlags
nil, // lpEnvironment
flPath, // lpCurrentDirectory
startUpInfo, // lpStartupInfo
procInfo ) then // lpProcessInfo
begin
case GetLastError of
ERROR_PRIVILEGE_NOT_HELD:
ShowMessage( ´ERRO: Faltando (um dos) seguintes privilégios para usuário ´ +
LgnCmd.NewDomain + ´\´ + LgnCmd.NewUser + ´: ´ +
GetPrivilegeDisplayName(SE_ASSIGNPRIMARYTOKEN_NAME) + ´, ou ´ +
GetPrivilegeDisplayName(SE_INCREASE_QUOTA_NAME) );
ERROR_FILE_NOT_FOUND:
ShowMessage(´ERRO: Comando ´´´ + LgnCmd.CommandLine + ´´´ não encontrado´ );
else
ShowMessage(´ERRO: Exct_Prcss_Com_Logon falhou´);
end; // case

Executou := False;
end
else
Executou := True;

if Executou then
begin
ShowMessage( ´Processo ´ + ExtractFileName(LgnCmd.CommandLine) +
´ executando com usuário ´ +
LgnCmd.NewDomain + ´\´ + LgnCmd.NewUser );

CloseHandle(procInfo.hThread);
CloseHandle(procInfo.hProcess);
Result := True;
end
else
Result := False;

finally
if nwUsr <> nil then FreeMem(nwUsr);
if nwDomain <> nil then FreeMem(nwDomain);
if psw <> nil then FreeMem(psw);
if CmdLine <> nil then FreeMem(CmdLine);
if flPath <> nil then FreeMem(flPath);
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var LgnCmd : TLoginCommand;
begin
with LgnCmd do
begin
CommandLine := ´C:\WINDOWS\system32\notepad.exe´; // Nome do processo (incluindo o caminho) a ser executado
pwstr := ´escort1.6´; // Senha do usuário a ser usado para executar o processo Nm_Processo...
NewDomain := ´NTBK_MMARTINHO´; // Domínio a que pertence o usuário a ser usado para executar o processo Nm_Processo...
NewUser := ´Marcus Martinho´; // Nome do usuário a ser usado para executar o processo Nm_Processo...
end;

if Exct_Prcss_Com_Logon(LgnCmd) then
ShowMessage(´Processo Executou com sucesso´)
else
ShowMessage(´Execução do processo falhou´);
end;

end.


Responder

Assista grátis a nossa aula inaugural

Assitir aula

Saiba por que programar é uma questão de
sobrevivência e como aprender sem riscos

Assistir agora

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar