Post by Fabio Siciliano on Nov 19, 2020 16:03:12 GMT -5
Hi folks,
To enumerate processes in almost all Windows versions I first take a system snapshot by calling "CreateToolhelp32Snapshot" (kernel32) and then browse them by calling "Process32First" (kernel32) out of a loop and "Process32Next" (kernel32) in loop and, finally "CloseHandle" (kernel32) to free the system snapshot.
Sadly enough, this method is not available in Windows NT, because the "CreateToolhelp32Snapshot" function is missing in that Windows version.
So, to enumerate processes in Windows NT I must call the "EnumProcesses" (psapi) function which, BTW, is also available in Windows 10.
The very bad news is that the first required parameter of that function is a preallocated array (to receive the list of PIDs) and, so far, I was completely unable to make it work.
Here you can find a list of WEB articles I read to find a solution.
API replacement for 'CreateToolhelp32Snapshot' in Win NT
www.vbforums.com/showthread.php?201134-API-replacement-for-CreateToolhelp32Snapshot-in-Win-NT
Enhancing Liberty Basic [Array Handling] (AKA: The memory Article) by Dennis McKinney (dlm81854@iquest.net)
www.libertybasicuniversity.com/lbnews/nl99/3.htm
Enumerate Processes
www.delphibasics.info/home/delphibasicssnippets/enumerateprocesses
EnumProcesses function (psapi.h)
docs.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-enumprocesses
Enumerating All Processes
docs.microsoft.com/en-us/windows/win32/psapi/enumerating-all-processes
How To Enumerate Applications Using Win32 APIs
programtip.com/en/art-135708
And here below you can find my sample program using the "EnumProcesses" (psapi) function.
Obviously it does not work: "EnumProcesses" (psapi) returns ZERO and then "GetLastError" (kernel32) returns 998 (invalid address memory location).
Any idea?
Thank you in advance,
Fabio
To enumerate processes in almost all Windows versions I first take a system snapshot by calling "CreateToolhelp32Snapshot" (kernel32) and then browse them by calling "Process32First" (kernel32) out of a loop and "Process32Next" (kernel32) in loop and, finally "CloseHandle" (kernel32) to free the system snapshot.
Sadly enough, this method is not available in Windows NT, because the "CreateToolhelp32Snapshot" function is missing in that Windows version.
So, to enumerate processes in Windows NT I must call the "EnumProcesses" (psapi) function which, BTW, is also available in Windows 10.
The very bad news is that the first required parameter of that function is a preallocated array (to receive the list of PIDs) and, so far, I was completely unable to make it work.
Here you can find a list of WEB articles I read to find a solution.
API replacement for 'CreateToolhelp32Snapshot' in Win NT
www.vbforums.com/showthread.php?201134-API-replacement-for-CreateToolhelp32Snapshot-in-Win-NT
Enhancing Liberty Basic [Array Handling] (AKA: The memory Article) by Dennis McKinney (dlm81854@iquest.net)
www.libertybasicuniversity.com/lbnews/nl99/3.htm
Enumerate Processes
www.delphibasics.info/home/delphibasicssnippets/enumerateprocesses
EnumProcesses function (psapi.h)
docs.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-enumprocesses
Enumerating All Processes
docs.microsoft.com/en-us/windows/win32/psapi/enumerating-all-processes
How To Enumerate Applications Using Win32 APIs
programtip.com/en/art-135708
And here below you can find my sample program using the "EnumProcesses" (psapi) function.
Obviously it does not work: "EnumProcesses" (psapi) returns ZERO and then "GetLastError" (kernel32) returns 998 (invalid address memory location).
'** myEnumProcesses4WinNT by Fabio Siciliano, 19/11/2020
'** Last update: 19/11/2020
'** character constants
global nul$, ht$, lf$, cr$, cr2$, dq$, bullet$, ul$, nl$, nl2$, eol$, indent$, yuml$
'** character constants settings
nul$ = chr$(0) : ht$ = chr$(9) : lf$ = chr$(10) : cr$ = chr$(13) : cr2$ = cr$; cr$ : dq$ = chr$(34) : bullet$ = chr$(149) : yuml$ = chr$(255)
ul$ = space$(5); bullet$; space$(3) : nl$ = cr$; lf$ : nl2$ = nl$; nl$ : eol$ = space$(9) : indent$ = space$(7)
'** general globals
global myApp$, myAppName$, caption$ : caption$ = "myEnumProcesses4WinNT 1.0"; cr$ : titlebar$ = trim$(caption$)
'** EnumProcesses (psapi)
' struct lpidProcess, pidProcess as ulong
' struct lpcbNeeded, cbNeeded as ulong
'** FormatMessageA (kernel32)
struct lpSource, lpSource as long
struct Arguments, Arguments as long
'** PID element
struct sPID, PID as ulong
elements = 255 : dim structArray(elements)
[retry]
redim structArray(elements)
sizeofsPID = len(sPID.struct)
memBlockSize = (elements + 1) * sizeofsPID
hSArray = GlobalAlloc(_GMEM_MOVEABLE, memBlockSize)
ptrSarray = GlobalLock(hSArray)
for i = 0 to elements
dest = ptrSarray + (i * sizeofsPID)
calldll #kernel32, "RtlMoveMemory", dest as long, sPID as ptr, sizeofsPID as long, ret as void
structArray(i) = dest
next i
lpidProcess = ptrSarray
cb = memBlockSize
print "*** TEST - BEGIN ***"
print
print "EnumProcesses", "lpidProcess", "cb", "lpcbNeeded"
open "psapi.dll" for dll as #psapi
calldll #psapi, "EnumProcesses", lpidProcess as ulong, cb as ulong, lpcbNeeded as ulong, r as long
if r then
if lpcbNeeded.cbNeeded.struct = cb then elements = elements + 1 : goto [retry]
print r,, lpidProcess, cb, lpcbNeeded
else
calldll #kernel32, "GetLastError", rc as long
r$ = "EnumProcesses (kernel32) = "; rc
notice caption$; formatMessage$(r$, rc)
print r,, lpidProcess, cb, lpcbNeeded
goto [exit]
end if
print
print "PID", "index", "value"
for i = 0 to elements
print "PID "; i, structArray(i)
next i
[exit]
print
print "*** TEST - END ***"
close #psapi
ret = GlobalFree(hSArray)
end
[formatMessage]
function formatMessage$(source$, rc)
dwFlags = _FORMAT_MESSAGE_FROM_SYSTEM or _FORMAT_MESSAGE_ALLOCATE_BUFFER
dwMessageId = rc
calldll #kernel32, "FormatMessageA", _
dwFlags as long, _
lpSource as struct, _
dwMessageId as long, _
dwLanguageId as long, _
lpBuffer$ as ptr, _
nSize as long, _
Arguments as struct, _
r as long
dwFlags = _FORMAT_MESSAGE_FROM_SYSTEM
nSize = r + 1
lpBuffer$ = space$(nSize) + nul$
calldll #kernel32, "FormatMessageA", _
dwFlags as long, _
lpSource as struct, _
dwMessageId as long, _
dwLanguageId as long, _
lpBuffer$ as ptr, _
nSize as long, _
Arguments as struct, _
r as long
if r then
formatMessage$ = source$; cr2$; trim$(lpBuffer$)
else
formatMessage$ = translate$("No further info is available"); "."
end if
lpBuffer$ = ""
end function
[GlobalAlloc]
function GlobalAlloc(type, dwBytes)
calldll #kernel32, "GlobalAlloc", type as long, dwBytes as ulong, GlobalAlloc as long
end function
[GlobalFree]
function GlobalFree(hMem)
calldll #kernel32, "GlobalFree", hMem as ulong, GlobalFree as long
end function
[GlobalLock]
function GlobalLock(hMem)
calldll #kernel32, "GlobalLock", hMem as long, GlobalLock as long
end function
[translate]
function translate$(text$)
translate$ = text$
end function
Any idea?
Thank you in advance,
Fabio