How to get the OWNERs name of a process? [Solved]
How to get the OWNERs name of a process? [Solved]
Hi folks,:D
in an attempt to develop a program similar to Windows task-manager, I encountered a problem:
How can I get the owners name (user name) of a running process?
I couldn't find anything helpful in the forum, probably because it is a very specific question. Even google didn't help, except for code examples written in C++ or VB.
Thus far I know how to list all running processes and get their exe-names (thanks to POBSL Process...)
Using PB 4.2 / WindowsXP Pro
in an attempt to develop a program similar to Windows task-manager, I encountered a problem:
How can I get the owners name (user name) of a running process?
I couldn't find anything helpful in the forum, probably because it is a very specific question. Even google didn't help, except for code examples written in C++ or VB.
Thus far I know how to list all running processes and get their exe-names (thanks to POBSL Process...)
Using PB 4.2 / WindowsXP Pro
Last edited by BigJack on Sun Apr 13, 2008 8:04 pm, edited 1 time in total.
Greetings to all the folks back home in the States...
PB4.2 Windows XP SP3
PB4.2 Windows XP SP3
might give some clues:
http://www.purebasic.fr/english/viewtop ... cess+owner
http://www.purebasic.fr/english/viewtop ... r&start=15
But...i've seen some API code somewhere that does this, just have to find it.
http://www.purebasic.fr/english/viewtop ... cess+owner
http://www.purebasic.fr/english/viewtop ... r&start=15
But...i've seen some API code somewhere that does this, just have to find it.
- Fluid Byte
- Addict
- Posts: 2336
- Joined: Fri Jul 21, 2006 4:41 am
- Location: Berlin, Germany
Everything I found on the web uses Windows Management Instrumentation (WMI) to obtain the user names. I haven't found any code doing it natively with API.
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
Code: Select all
; code : KarLKoX
; date : 04/05/2008
; changelog : 1.0 - Initial Release
;
; Note : activate unicode support
#ANYSIZE_ARRAY = 1
#OWNER_SECURITY_INFORMATION = $00000001
Enumeration ; SID_NAME_USE
#SidTypeUser = 1
#SidTypeGroup
#SidTypeDomain
#SidTypeAlias
#SidTypeWellKnownGroup
#SidTypeDeletedAccount
#SidTypeInvalid
#SidTypeUnknown
#SidTypeComputer
#SidTypeLabel
EndEnumeration
Enumeration ; SE_OBJECT_TYPE
#SE_UNKNOWN_OBJECT_TYPE
#SE_FILE_OBJECT
#SE_SERVICE
#SE_PRINTER
#SE_REGISTRY_KEY
#SE_LMSHARE
#SE_KERNEL_OBJECT
#SE_WINDOW_OBJECT
#SE_DS_OBJECT
#SE_DS_OBJECT_ALL
#SE_PROVIDER_DEFINED_OBJECT
EndEnumeration
Structure SID
Revision.b
SubAuthorityCount.b
*IdentifierAuthority.SID_IDENTIFIER_AUTHORITY
SubAuthority.l[#ANYSIZE_ARRAY]
EndStructure
Prototype.l PFNCreateToolhelp32Snapshot(dwFlags.l, th32ProcessID.l)
Prototype.b PFNProcess32First(hSnapshot.l, *lppe.PROCESSENTRY32)
Prototype.b PFNProcess32Next(hSnapshot.l, *lppe.PROCESSENTRY32)
Prototype.b PFNThread32First(hSnapshot.l, *lppe.THREADENTRY32)
Prototype.b PFNThread32Next(hSnapshot.l, *lppe.THREADENTRY32)
Procedure DBG(out.s)
CompilerIf #PB_Compiler_Debugger
Debug out
CompilerEndIf
EndProcedure
Procedure.l GetPidByName(name.s)
Protected hDLL.l, process_name.s
Protected PEntry.PROCESSENTRY32, hTool32.l
Protected pCreateToolhelp32Snapshot.PFNCreateToolhelp32Snapshot
Protected pProcess32First.PFNProcess32First
Protected pProcess32Next.PFNProcess32Next
hDLL = OpenLibrary(#PB_Any,"kernel32.dll")
If hDLL
; get function pointer
pCreateToolhelp32Snapshot = GetFunction(hDLL,"CreateToolhelp32Snapshot")
pProcess32First = GetFunction(hDLL,"Process32FirstW")
pProcess32Next = GetFunction(hDLL,"Process32NextW")
Else
DBG("GetPidByName:: OpenLibrary failed !")
ProcedureReturn 0
EndIf
PEntry\dwSize = SizeOf(PROCESSENTRY32)
hTool32 = pCreateToolhelp32Snapshot(#TH32CS_SNAPPROCESS, 0)
pProcess32First(hTool32, @PEntry)
process_name = Space(#MAX_PATH)
CopyMemory(@PEntry\szExeFile,@process_name,StringByteLength(process_name))
If process_name = name
ProcedureReturn PEntry\th32ProcessID
EndIf
While pProcess32Next(hTool32, @PEntry) > 0
process_name = Space(#MAX_PATH)
CopyMemory(@PEntry\szExeFile,@process_name,StringByteLength(process_name))
If process_name = name
ProcedureReturn PEntry\th32ProcessID
EndIf
Wend
CloseLibrary(hDLL)
CloseHandle_(pCreateToolhelp32Snapshot)
ProcedureReturn 0
EndProcedure
Macro MAKELANGID(p, s)
(s << 10 | p)
EndMacro
; format the errcode to the corresponding message error string
Procedure.s GetLastErrorString(lErrCode.l)
Protected lpMsgBuf.l
Protected out.s = ""
If lErrCode
FormatMessage_(#FORMAT_MESSAGE_ALLOCATE_BUFFER | #FORMAT_MESSAGE_FROM_SYSTEM, #Null, lErrCode, MAKELANGID(#LANG_NEUTRAL, #SUBLANG_DEFAULT), @lpMsgBuf, 0, #Null)
out = PeekS(lpMsgBuf)
LocalFree_(lpMsgBuf)
EndIf
ProcedureReturn out
EndProcedure
Procedure.s getOwnerObject(pid.l)
Protected owner.s
Protected *pSidOwner.SID, *pSD.SECURITY_DESCRIPTOR
Protected dwRtnCode.l, bRtnBool.l
Protected AcctName.s, DomainName.s
Protected dwAcctName.l, dwDomainName.l
Protected eUse.l = #SidTypeUnknown
If pid = #INVALID_HANDLE_VALUE
DBG("Invalid pid !")
ProcedureReturn ""
EndIf
object = OpenProcess_(#READ_CONTROL, #False, pid)
If object = #INVALID_HANDLE_VALUE
DBG("Invalid object handle !")
ProcedureReturn ""
EndIf
If OpenProcessToken_(GetCurrentProcess_(), #TOKEN_QUERY | #TOKEN_ADJUST_PRIVILEGES, @htok) <= 0
DBG("OpenProcessToken failed")
ProcedureReturn ""
EndIf
; allocate memory for the SID structure
*pSidOwner = AllocateMemory(SizeOf(SID))
If *pSidOwner = 0
DBG("Can't allocate memory for the SID structure")
ProcedureReturn ""
EndIf
; allocate memory for the security descriptor structure
*pSD = AllocateMemory(SizeOf(SECURITY_DESCRIPTOR))
If *pSD = 0
DBG("Can't allocate memory for the SECURITY_DESCRIPTOR structure")
ProcedureReturn ""
EndIf
; get the owner SID of the object
dwRtnCode = GetSecurityInfo_(object, #SE_KERNEL_OBJECT, #OWNER_SECURITY_INFORMATION, @*pSidOWner, #Null, #Null, #Null, @*pSD)
; check GetLastError for GetSecurityInfo error condition
If dwRtnCode <> #ERROR_SUCCESS
DBG("GetSecurityInfo error = " + GetLastErrorString(dwRtnCode) )
ProcedureReturn ""
EndIf
; first call to LookupAccoundSid to get the buffer sizes
bRtnBool = LookupAccountSid_(#Null, *pSidOwner, AcctName, @dwAcctName, DomainName, @dwDomainName, @eUse)
; reallocate memory for the buffers
AcctName = Space(dwAcctName)
DomainName = Space(dwDomainName)
; second call to LookupAccountSid to get the account name
bRtnBool = LookupAccountSid_(#Null, *pSidOwner, AcctName, @dwAcctName, DomainName, @dwDomainName, @eUse)
; close the process handle
CloseHandle_(object)
ProcedureReturn AcctName
EndProcedure
Procedure Test()
Protected pid1.l, pid2.l
Protected owner1.s, owner2.s
; should be different
pid1 = GetPidByName("explorer.exe")
pid2 = GetPidByName("lsass.exe")
owner1 = getOwnerObject(pid1)
owner2 = getOwnerObject(pid2)
MessageRequester("Result", "The Owner of explorer.exe is " + owner1 + " and the owner of lsass.exe is " + owner2 )
EndProcedure
Test()
Last edited by KarLKoX on Sat Apr 05, 2008 10:21 pm, edited 1 time in total.
- Fluid Byte
- Addict
- Posts: 2336
- Joined: Fri Jul 21, 2006 4:41 am
- Location: Berlin, Germany
Does it work for you? Although I haven't tested other executables yet I get "Invalid handle" error on both demo .EXE's.
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
- Fluid Byte
- Addict
- Posts: 2336
- Joined: Fri Jul 21, 2006 4:41 am
- Location: Berlin, Germany
Indeed! 
One more thing ...
For "lsass.exe" it says "Administratoren" and the taskmanager says "SYSTEM". That is the same, isn't it?

One more thing ...
For "lsass.exe" it says "Administratoren" and the taskmanager says "SYSTEM". That is the same, isn't it?
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
I've noticed that too, Administrator and System are not the same it turns out. One is an account the other is root level system. Its possible they can both be at the same permission level, but they would still be different and be called Administrator and System. So for "lsass.exe" it might say Administrator because it ran when the administrator logged in with those permissions because the admin long in actually triggered it to run so the admin would be the owner in terms of it running instead of the system running it whereas its a system level access for the process task which would mean that it shows system in task manager. At least from what I can tell.
that make sense? I'm probably wrong or said it wrong, done it before so this would not be the last time
that make sense? I'm probably wrong or said it wrong, done it before so this would not be the last time

without unicode enabled returns the names of the two processes but never gives the owner and gives two errors in the debug
GetSecurityInfo error = The handle is invalid.
GetSecurityInfo error = The handle is invalid.
This is on Vista so it might not like the SECURITY_DESCRIPTOR in some way. With unicode enabled it gives the owner of explorer.exe correctly (owner 1) but never shows the owner for lsass.exe and still gives one error in the debug GetSecurityInfo error = The handle is invalid.
GetSecurityInfo error = The handle is invalid.
GetSecurityInfo error = The handle is invalid.
This is on Vista so it might not like the SECURITY_DESCRIPTOR in some way. With unicode enabled it gives the owner of explorer.exe correctly (owner 1) but never shows the owner for lsass.exe and still gives one error in the debug GetSecurityInfo error = The handle is invalid.
Hi,
here a modified code that running in Ansi/Unicode and
solve the Problem described by SFSyOI on Vista.
here a modified code that running in Ansi/Unicode and
solve the Problem described by SFSyOI on Vista.
Code: Select all
; code : KarLKoX
; date : 04/05/2008
; changelog : 1.0 - Initial Release
;
; Note : activate unicode support
#ANYSIZE_ARRAY = 1
#OWNER_SECURITY_INFORMATION = $00000001
Enumeration ; SID_NAME_USE
#SidTypeUser = 1
#SidTypeGroup
#SidTypeDomain
#SidTypeAlias
#SidTypeWellKnownGroup
#SidTypeDeletedAccount
#SidTypeInvalid
#SidTypeUnknown
#SidTypeComputer
#SidTypeLabel
EndEnumeration
Enumeration ; SE_OBJECT_TYPE
#SE_UNKNOWN_OBJECT_TYPE
#SE_FILE_OBJECT
#SE_SERVICE
#SE_PRINTER
#SE_REGISTRY_KEY
#SE_LMSHARE
#SE_KERNEL_OBJECT
#SE_WINDOW_OBJECT
#SE_DS_OBJECT
#SE_DS_OBJECT_ALL
#SE_PROVIDER_DEFINED_OBJECT
EndEnumeration
Structure SID
Revision.b
SubAuthorityCount.b
*IdentifierAuthority.SID_IDENTIFIER_AUTHORITY
SubAuthority.l[#ANYSIZE_ARRAY]
EndStructure
; ------------------------ Get PID
#TH32CS_SNAPPROCESS = $2
Procedure DBG(out.s)
CompilerIf #PB_Compiler_Debugger
Debug out
CompilerEndIf
EndProcedure
Macro MAKELANGID(p, s)
(s << 10 | p)
EndMacro
; format the errcode to the corresponding message error string
Procedure.s GetLastErrorString(lErrCode.l)
Protected lpMsgBuf.l
Protected out.s = ""
If lErrCode
FormatMessage_(#FORMAT_MESSAGE_ALLOCATE_BUFFER | #FORMAT_MESSAGE_FROM_SYSTEM, #Null, lErrCode, MAKELANGID(#LANG_NEUTRAL, #SUBLANG_DEFAULT), @lpMsgBuf, 0, #Null)
out = PeekS(lpMsgBuf)
LocalFree_(lpMsgBuf)
EndIf
ProcedureReturn out
EndProcedure
Procedure SearchPID(Name.s)
;-http://www.purebasic.fr/german/viewtopic.php?t=10576&postdays=0&postorder=asc&highlight=processentry33&start=10
Protected result.l, Snapshot.l, ProcessFound.l, PN$, Process.PROCESSENTRY32
Process\dwSize = SizeOf(PROCESSENTRY32)
Snapshot = CreateToolhelp32Snapshot_(#TH32CS_SNAPPROCESS, 0)
If Snapshot
ProcessFound = Process32First_(Snapshot, Process)
While ProcessFound
PN$ = UCase(PeekS(@Process\szExeFile, #PB_Any, #PB_Ascii))
If UCase(Name) = GetFilePart(PN$)
ProcedureReturn Process\th32ProcessID
EndIf
ProcessFound = Process32Next_(Snapshot, Process)
Wend
CloseHandle_(Snapshot)
EndIf
ProcedureReturn 0
EndProcedure
Procedure.s getOwnerObject(pid.l)
Protected owner.s
Protected *pSidOwner.SID, *pSD.SECURITY_DESCRIPTOR
Protected dwRtnCode.l, bRtnBool.l
Protected AcctName.s, DomainName.s
Protected dwAcctName.l, dwDomainName.l
Protected eUse.l = #SidTypeUnknown
If pid = #INVALID_HANDLE_VALUE
DBG("Invalid pid !")
ProcedureReturn ""
EndIf
object = OpenProcess_(#READ_CONTROL, #False, pid)
If object = #INVALID_HANDLE_VALUE
DBG("Invalid object handle !")
ProcedureReturn ""
EndIf
If OpenProcessToken_(GetCurrentProcess_(), #TOKEN_QUERY | #TOKEN_ADJUST_PRIVILEGES, @htok) <= 0
DBG("OpenProcessToken failed")
ProcedureReturn ""
EndIf
; allocate memory for the SID structure
*pSidOwner = AllocateMemory(SizeOf(SID))
If *pSidOwner = 0
DBG("Can't allocate memory for the SID structure")
ProcedureReturn ""
EndIf
; allocate memory for the security descriptor structure
*pSD = AllocateMemory(SizeOf(SECURITY_DESCRIPTOR))
If *pSD = 0
DBG("Can't allocate memory for the SECURITY_DESCRIPTOR structure")
ProcedureReturn ""
EndIf
; get the owner SID of the object
dwRtnCode = GetSecurityInfo_(object, #SE_KERNEL_OBJECT, #OWNER_SECURITY_INFORMATION, @*pSidOWner, #Null, #Null, #Null, @*pSD)
; dwRtnCode = GetSecurityInfo_(object, #SE_KERNEL_OBJECT, #OWNER_SECURITY_INFORMATION, @*pSidOWner, #Null, #Null, #Null, @pSD)
; check GetLastError for GetSecurityInfo error condition
If dwRtnCode <> #ERROR_SUCCESS
DBG("GetSecurityInfo error = " + GetLastErrorString(dwRtnCode) )
ProcedureReturn ""
EndIf
; first call to LookupAccoundSid to get the buffer sizes
bRtnBool = LookupAccountSid_(#Null, *pSidOwner, AcctName, @dwAcctName, DomainName, @dwDomainName, @eUse)
; reallocate memory for the buffers
AcctName = Space(dwAcctName)
DomainName = Space(dwDomainName)
; second call to LookupAccountSid to get the account name
bRtnBool = LookupAccountSid_(#Null, *pSidOwner, AcctName, @dwAcctName, DomainName, @dwDomainName, @eUse)
; close the process handle
CloseHandle_(object)
ProcedureReturn AcctName
EndProcedure
Procedure Test()
Protected pid1.l, pid2.l
Protected owner1.s, owner2.s
pid1=SearchPID("explorer.exe")
pid2=SearchPID("lsass.exe")
Debug pid1
Debug pid2
owner1 = getOwnerObject(pid1)
owner2 = getOwnerObject(pid2)
MessageRequester("Result", "The Owner of explorer.exe is " + owner1 + " and the owner of lsass.exe is " + owner2 )
EndProcedure
#SE_DEBUG_NAME="SeDebugPrivilege" ; missing constant
Procedure EnableDebugPrivNT()
;-http://www.purebasic.fr/english/viewtopic.php?t=31161&highlight=enabledebugprivnt
DebugValue.LUID;
tkp.TOKEN_PRIVILEGES
; Retrieve a handle of the access token
If Not OpenProcessToken_(GetCurrentProcess_(),#TOKEN_ADJUST_PRIVILEGES|#TOKEN_QUERY,@hToken)
ProcedureReturn #False;
EndIf
; Enable the SE_DEBUG_NAME privilege
If Not LookupPrivilegeValue_("",#SE_DEBUG_NAME,@DebugValue)
ProcedureReturn #False;
EndIf
NewState.TOKEN_PRIVILEGES
NewState\PrivilegeCount=1
NewState\Privileges[0]\Luid\HighPart=DebugValue\HighPart
NewState\Privileges[0]\Luid\LowPart=DebugValue\LowPart
NewState\Privileges[0]\Attributes=#SE_PRIVILEGE_ENABLED
AdjustTokenPrivileges_(hToken,#False,@NewState,SizeOf(TOKEN_PRIVILEGES),@PreviousState.TOKEN_PRIVILEGES,@ReturnLength)
If GetLastError_()<>#ERROR_SUCCESS
ProcedureReturn #False
EndIf
ProcedureReturn #True
EndProcedure
If EnableDebugPrivNT()
Debug "privilege loaded..."
Test()
Else
Debug "privilege not setted...."
EndIf
PB 5.10 Windows 7 x64 SP1
-
- Always Here
- Posts: 6426
- Joined: Fri Oct 23, 2009 2:33 am
- Location: Wales, UK
- Contact:
Re: How to get the OWNERs name of a process? [Solved]
[PB5.20LTS WinXP x86]
jpd's version reports GetSecurityInfo error = The handle is invalid. with Compiler set to Unicode, but delivers the correct names when set to ASCII. The original KarLKoX code works with Unicode only.
jpd's version reports GetSecurityInfo error = The handle is invalid. with Compiler set to Unicode, but delivers the correct names when set to ASCII. The original KarLKoX code works with Unicode only.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
If it sounds simple, you have not grasped the complexity.