Solved

How do i Retrieve the Process Owner ?

Posted on 2002-03-18
12
474 Views
Last Modified: 2013-11-23
I have the ProcessID of a process, now I'd like to know who is running that process.

I guess i could possibly, Open that process get the ProcessToken, and then use ImpersonateUser to Get it...but it seems like the wrong way to do it.


Target platform is NT/2K/XP
Any ideas ?

0
Comment
Question by:raidos
12 Comments
 
LVL 2

Expert Comment

by:egono
ID: 6876910
listening ...
0
 
LVL 17

Accepted Solution

by:
inthe earned 200 total points
ID: 6877965
hi,

first you must have SeDebugPrivilege enabled then
OpenProcess()
OpenProcessToken()
GetTokenInformation()
LookupAccountSid()

heres an example unit utilizing the above :

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

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;


procedure TForm1.Button1Click(Sender: TObject);
 var
  pID,hProcess:DWord;
  h : hwnd;
 begin   //for a test i used internet explorer
h := FindWindow('IEFrame',nil);
If h <> 0 Then
GetWindowThreadProcessId(h,@pID);  

//now got a test pid ,see who runs it

EnableProcessPrivilege(True, 'SeDebugPrivilege');
Showmessage(GetProcessUser(pID));
end;

end.
//some functions knicked from elsewhere for ease of use//

Regards Barry :)
0
 
LVL 3

Author Comment

by:raidos
ID: 6879202
Looks neat, will try it today...

Any other ways of doing it barry ? =))
0
 
LVL 17

Expert Comment

by:inthe
ID: 6879249
hi,
not that i can think of, most other roads point back to LookupAccountSid(),GetSecurityInfo will give back a pointer to the sID ,to be honest ive not tried any other way.
ps
i was wondering
what method are you using to get the ProcessID?
is this a app thats started remotely or locally?
0
 
LVL 3

Author Comment

by:raidos
ID: 6879664
The app is local and I'm currently using madshis enumStuff unit to get the ProcessId.

I was reading the Win32Api help yesterday and I came to the conclusion that the "ONLY" way to do it is the way you have given code for.

I guess it will work fine but it seems to me that it is a long route to get the tiny bit of information i want...

Have yet to try the code, I will test it as soon as I can..
0
 

Expert Comment

by:DelFreak
ID: 6880021
Listening...
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 3

Author Comment

by:raidos
ID: 6885047
I'm getting a strange error on this line of your code Barry...=/
-->   AdjustTokenPrivileges(Token, False, TokenPriv, SizeOf(TokenPriv), nil, ReturnLength);

Compiler states: Ambiguous overloaded call to 'AdjustTokenPrivileges'

I've tried Ctrl+Space on function name to select which AdjustTokenPrivileges to use, without any luck.

any ideas ?

Using Delphi 5 Btw..
0
 
LVL 3

Author Comment

by:raidos
ID: 6885080
i just tried without setting the tokenprivileges and it seems to work without it....i wonder why...

hmm...maybe they aren't necessary ?
0
 
LVL 17

Expert Comment

by:inthe
ID: 6887957
hi,
the privileges are only nesesary if your not admin or dont have these rights already,if you dont need them you can safly ignore that part.

as for the error im guessing you have WinTypes and or WinProcs in your uses section,just remove them if so as they are replaced by windows unit and this can cause the error you mentioned.
0
 
LVL 17

Expert Comment

by:inthe
ID: 6887982
if above is not the case (you dont have winprocs in uses) then i'd suggest to try changing the function a little :


function EnableProcessPrivilege ( Enable: Boolean; sPrivilegeName: string): Boolean;
var
  TPPrev,TP : TTokenPrivileges;
  Token    : THandle;
  dwRetLen : DWORD;
begin
  result := False;
  OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, Token);
  TP.PrivilegeCount := 1;
  if LookupPrivilegeValue (nil, PChar (sPrivilegeName), TP.Privileges[0].LUID) then
  begin
    if Enable then
      TP.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED
    else
      TP.Privileges[0].Attributes := 0;
      dwRetLen := 0;
    result := AdjustTokenPrivileges (Token, False, TP, SizeOf (TPPrev), TPPrev,dwRetLen)
  end;
  CloseHandle (Token)
end;

be interesting to see if it clears the error.
0
 
LVL 3

Author Comment

by:raidos
ID: 6888145
Ahhhhhh.....The goddamn Wintypes/Winprocs!!!!!

Grrr...

Great work Barry, I'm gonna go through every last unit of mine searching for Winprocs/Wintypes so i NEVER get this error again.

Thanks
0
 
LVL 17

Expert Comment

by:inthe
ID: 6888162
ok no probs :)
0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now