yoy.be "Why-o-Why"

CreateProcessAsUser/CreateProcessWithLogon

2005-09-28 10:10  i269  delphi  [permalink]

Pre-Windows 2000 versions have a function call CreateProcessAsUser available, but this requires the SeTcbPrivilege, which only the local Administrator account have (and the local SYSTEM account, but not user accounts in the Administrators group). So this first method only works with the local administrator account:
procedure SetPrivilege(th:THandle;pn:string);
var
  tp:TTokenPrivileges;
  tpc:cardinal;
begin
  tpc:=0;
  tp.PrivilegeCount:=1;
  tp.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED;
  if not(LookupPrivilegeValue('',PChar(pn),tp.Privileges[0].Luid)) then RaiseLastOSError;
  if not(AdjustTokenPrivileges(th,false,tp,SizeOf(tp),nil,tpc)) then RaiseLastOSError;
end;
 
procedure RunAs(Logon,Pwd,Domain,App:string);
var
  th:THandle;
  si:TStartupInfo;
  pi:TProcessInformation;
begin
  if not(OpenProcessToken(GetCurrentProcess,
    TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY or TOKEN_ASSIGN_PRIMARY,th)) then RaiseLastOSError;
 
  SetPrivilege(th,'SeTcbPrivilege');
  SetPrivilege(th,'SeAssignPrimaryTokenPrivilege');
  SetPrivilege(th,'SeIncreaseQuotaPrivilege');
 
  CloseHandle(th);
 
  if not(LogonUser(
    PChar(Logon),PChar(Domain),PChar(Pwd),
    LOGON32_LOGON_INTERACTIVE,LOGON32_PROVIDER_DEFAULT,th)) then RaiseLastOSError;
 
  try
 
    ZeroMemory(@si,sizeof(si));
    si.cb:=sizeof(si);
    si.dwFlags:=STARTF_USESHOWWINDOW;
    si.wShowWindow:=SW_NORMAL;
    ZeroMemory(@pi,sizeof(pi));
 
    if not(CreateProcessAsUserW(th,nil,PWideChar(WideString(App)),
      nil,nil,false,0,nil,nil,si,pi)) then RaiseLastOSError;
 
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
 
  finally
    CloseHandle(th);
  end;
end;
Since Windows 2000, advapi32.dll also has a CreateProcessWithLogonW function call, which doesn't require you to have the SeTcbPrivilege. Using this call, the above code can be condesed to this: (Delphi 6 doesn't have this function call declared, so the declaration is included here)
function CreateProcessWithLogonW(
  lpUsername: PWideChar;lpDomain: PWideChar;lpPassword: PWideChar;
  dwLogonFlags: DWORD; lpApplicationName: PWideChar;
  lpCommandLine: PWideChar; dwCreationFlags: DWORD; lpEnvironment: Pointer; lpCurrentDirectory: PWideChar;
  const lpStartupInfo: TStartupInfo; var lpProcessInformation: TProcessInformation): BOOL; stdcall;

const
  LOGON_WITH_PROFILE              =$00000001;
  LOGON_NETCREDENTIALS_ONLY       =$00000002;
  LOGON_ZERO_PASSWORD_BUFFER      =$80000000;

function
CreateProcessWithLogonW; external 'advapi32.dll' name 'CreateProcessWithLogonW';



procedure
RunAs(Logon,Pwd,Domain,App:string);
var
  si:TStartupInfo;
  pi:TProcessInformation;
begin
  ZeroMemory(@si,sizeof(si));
  si.cb:=sizeof(si);
  si.dwFlags:=STARTF_USESHOWWINDOW;
  si.wShowWindow:=SW_NORMAL;
  ZeroMemory(@pi,sizeof(pi));

  if not(CreateProcessWithLogonW(
    PWideChar(WideString(Logon)),
    PWideChar(WideString(Domain)),
    PWideChar(WideString(Pwd)),LOGON_WITH_PROFILE,nil,
    PWideChar(WideString(App)),
    0,nil,nil,si,pi)) then RaiseLastOSError;

CloseHandle(pi.hThread);
  CloseHandle(pi.hProcess);
end;

twitter reddit linkedin facebook