I understand it is possible to query a running process to get the user
name that is is 'running under' on NT/W2K. Does anyone know how to do
this?
J
From within the process itself it's as easy as calling GetUserName(). From
outside the process it's a bit more difficult and involves using the various
security API functions to examine the process (or thread) token.
best regards,
Marcel van Brakel
Hi,
Its from outside the process I need to obtain the UserName. I have
tried various samples I found on the Web (GetTokenPrivilages etc.), but
keep getting various errors like...
- No such login session exists
- Unable to get user info from LUID
- The Local Security Authority cannot be contacted
As these errors have happened with a number of different samples from
different places, I am wondering if I need to have anything special
running? (I am using NT)
J
Here's a complete command line application that works on my Win2K system for
most running processes. Just lauch it and specify the PID of the process as
it's sole argument (written and tested with Delphi 6 only). I've only tried
it when logged on as an administrator with the debug privilege assigned (it
will probably fail for processes running under a different account if you
don't have it assigned to your user account). Please note that this will
only return the username the process was running under when it was launched,
it completely ignores impersonation. I don't remember any method to obtain
that information other than from within the process itself (thinking
CreateRemoteThread might help with that).
best regards,
Marcel van Brakel
program psuser;
{$APPTYPE CONSOLE}
uses
Windows,
SysUtils,
AclApi;
function EnableProcessPrivilege(const Enable: Boolean; const Privilege:
string): Boolean;
const
PrivAttrs: array [Boolean] of DWORD = (0, SE_PRIVILEGE_ENABLED);
var
Token: THandle;
ReturnLength: Cardinal;
TokenPriv: TTokenPrivileges;
begin
Result := False;
if OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES, Token)
then
begin
TokenPriv.PrivilegeCount := 1;
LookupPrivilegeValue(nil, PChar(Privilege),
TokenPriv.Privileges[0].Luid);
TokenPriv.Privileges[0].Attributes := PrivAttrs[Enable];
AdjustTokenPrivileges(Token, False, TokenPriv, SizeOf(TokenPriv), nil,
ReturnLength);
Result := GetLastError = ERROR_SUCCESS;
CloseHandle(Token);
end;
end;
function LookupAccountBySid(Sid: PSID): string;
var
Name, RefDomain: string;
NameSize, RefDomainSize: DWORD;
Use: Cardinal;
begin
NameSize := 0;
RefDomainSize := 0;
LookupAccountSid(nil, Sid, nil, NameSize, nil, RefDomainSize, Use);
SetLength(Name, NameSize);
SetLength(RefDomain, RefDomainSize);
LookupAccountSid(nil, Sid, PChar(Name), NameSize, PChar(RefDomain),
RefDomainSize, Use);
Result := PChar(RefDomain) + '/' + PChar(Name);
end;
procedure QueryTokenInformation(Token: THandle; InformationClass:
TTokenInformationClass; var Buffer: Pointer);
var
B: BOOL;
Length: DWORD;
begin
Buffer := nil;
Length := 0;
B := GetTokenInformation(Token, InformationClass, Buffer, Length, Length);
while (not B) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) do
begin
ReallocMem(Buffer, Length);
B := GetTokenInformation(Token, InformationClass, Buffer, Length,
Length);
end;
if not B then
begin
FreeMem(Buffer);
Buffer := nil;
raise Exception.Create('Unable to get token information');
end;
end;
type
PTokenUser = ^TTokenUser;
TTokenUser = record
User: TSidAndAttributes;
end;
function GetProcessUser(const PID: Longword): string;
var
Token, Handle: THandle;
User: PTokenUser;
begin
Handle := OpenProcess(PROCESS_QUERY_INFORMATION, False, PID);
if Handle <> 0 then
begin
if OpenProcessToken(Handle, TOKEN_QUERY, Token) then
begin
QueryTokenInformation(Token, TokenUser, Pointer(User));
Result := LookupAccountBySid(User.User.Sid);
CloseHandle(Token);
end;
CloseHandle(Handle);
end;
end;
begin
EnableProcessPrivilege(True, 'SeDebugPrivilege');
if ParamCount = 1 then
begin
WriteLn(GetProcessUser(StrToInt(ParamStr(1))));
end
else WriteLn('Usage: psuser <PID>');
end.
FreeMem(User); // sorry forgot
> CloseHandle(Token);
> end;
> CloseHandle(Handle);
> end;
> end;
best regards,
Marcel van Brakel
Hi,
> > Its from outside the process I need to obtain the UserName. I have
> > tried various samples I found on the Web (GetTokenPrivilages etc.), but
> > keep getting various errors like...
>
> Here's a complete command line application that works on my Win2K system for
> most running processes. Just lauch it and specify the PID of the process as
> it's sole argument
Thanks, that seams to do what I want.
Many thanks
J