How to get process id from SYSTEM_PROCESS_INFORMATION struct? - windows

I am iterating on all the processes in the system using:
Get the first process using "NtQuerySystemInformation(SystemProcessInformation, buffer, buffer_size, NULL)".
Get the next processes using "NextEntryOffset" in SYSTEM_PROCESS_INFORMATION whose format is at https://learn.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntqueryinformationprocess.
and I want to filter these processes based on their PID. How do I get the PID from SYSTEM_PROCESS_INFORMATION struct is not clear to me. There is a field called "UniqueProcessId" which gives a HANDLE to the process but after passing it to "GetProcessId" I get error code 6 which means process handle is not correct.
Any suggestions on finding either the process handle or pid from SYSTEM_PROCESS_INFORMATION are welcome.
Thanks in advance.

Most of the NT api will contain the following statement:
[Nt*** may be altered or unavailable in future versions of Windows.]
In your case, you can use the following methods instead of NtQuerySystemInformation to retrieve the process of the system:
CreateToolhelp32Snapshot + Process32First/Process32Next
EnumProcesses
WTSEnumerateProcesses
WTSEnumerateProcessesEx(WTS_ANY_SESSION)

Related

Trying to implement `signal.CTRL_C_EVENT` in Python3.6

I'm reading about signals and am attempting to implement signal.CTRL_C_EVENT
From what I"m understanding, if the user presses CTRC + C while the program is running, a signal will be sent to kill a program. I can specify the program as a parameter?
My attempt to test out the usage:
import sys
import signal
import time
import os
os.kill('python.exe', signal.CTRL_C_EVENT)
while(1):
print ("Wait...")
time.sleep(10)
However, it seems I need a pid number and 'python.exe' doesn't work. I looked under processes and I can't seem to find a PID number. I did see a PID column under services, but there were so many services -- I couldn't find a python one.
So how do I find PID number?
Also, does signal_CTRL_C_EVENT always have to be used within os.kill?
Can It be used for other purposes?
Thank you.
Windows doesn't implement Unix signals, so Python fakes os.kill. Unfortunately its implementation is confusing. It should have been split up into os.kill and os.killpg, but we're stuck with an implementation that mixes the two. To send Ctrl+C or Ctrl+Break, you need to use os.kill as if it were really os.killpg.
When its signal argument is either CTRL_C_EVENT (0) or CTRL_BREAK_EVENT (1), os.kill calls WinAPI GenerateConsoleCtrlEvent. This instructs the console (i.e. the conhost.exe instance that's hosting the console window of the current process) to send the event to a given process group ID (PGID). Group ID 0 is special cased to broadcast the event to all processes attached to the console. Otherwise
a process group ID is the ID of the lead process in a process group. Every process is either created as the leader of a new group or inherits the group of its parent. A new group can be created via the CreateProcess creation flag CREATE_NEW_PROCESS_GROUP.
If either calling GenerateConsoleCtrlEvent fails (e.g. the current process isn't attached to a console) or the signal argument isn't one of the above-mentioned control events, then os.kill instead attempts to open a handle for the given process ID (PID) with terminate access and call WinAPI TerminateProcess. This function is like sending a SIGKILL signal in Unix, but with a variable exit code. Note the confusion in that it operates on an individual process (i.e. kill), not a process group (i.e. killpg).
Windows doesn't provide a function to get the group ID of a process, so generally the only way to get a valid PGID is to create the process yourself. You can pass the CREATE_NEW_PROCESS_GROUP flag to subprocess.Popen via its creationflags parameter. Then you can send Ctrl+Break to the child process and all of its children that are in the same group, but only if it's a console process that's attached to the same console as your current process, i.e. it won't work if you also also use any of these flags: CREATE_NEW_CONSOLE, CREATE_NO_WINDOW, or DETACHED_PROCESS. Also, Ctrl+C is disabled in such a process, unless the child manually enables it via WinAPI SetConsoleCtrlHandler.
Only use os.kill(os.getpid(), signal.CTRL_C_EVENT) when you know for certain that your current process was started as the lead process of a group. Otherwise the behavior is undefined, and in practice it works like sending to process group ID 0.
You can get pid via os.getpid()
os.kill(os.getpid(), signal.CTRL_C_EVENT)

Get process info making request inside TDI filter driver

I'm starting to write a TDI filter driver, and one of the things I'd like to know is which process is generating the requests. I'm guessing the info is available somewhere in the (mostly undocumented) structures. For example, I currently get the IP address and port inside TDI_CONNECT event like this:
stackIrp = IoGetCurrentIrpStackLocation(irp);
connectRequest = (TDI_REQUEST_KERNEL_CONNECT*) &stackIrp->Parameters;
transportAddr = (TRANSPORT_ADDRESS*) connectRequest->RequestConnectionInformation->RemoteAddress;
taAddr = (TA_ADDRESS*) transportAddr->Address;
ipAddr = (TDI_ADDRESS_IP*) taAddr->Address;
Do I end up just getting a socket handle and I have to work backwards to get process info, or do I get a process ID somewhere?
Ultimately I'd like to know the process info (EXE name, handle, etc), but also will need to know the Windows user that owns the session the process is running in... because yah, I'm writing yet another website filtering app, and like all of the others it needs to allow for different options per user.
You may use the 'IoGetRequestorProcessId' routine, which described at http://msdn.microsoft.com/en-us/library/windows/hardware/ff548391(v=vs.85).aspx, to get an unique 32-bit ULONG process id for the thread that originally request a given I/O operation.
After you get the process id, you can retrieve the process information, such as EXE name, modules, execution path and something else in a user-mode application.

CreateProcess returns non 0 but GetExitCodeProcess() returns 128

I am creating an application that will start another process using CreateProcess(). And in the parent process I will use GetExitCodeProcess() to check whether the process active or not.
Here CreateProcess() is successful (returned a non negative value) but GetExitCodeProcess() returns 128 (There are no child processes to wait for). I am not seeing any trace of the child process started(usually some debugs). It happens intermittently.
Any idea what really happened to the child process?. Where we get more information (in system/application event logs?).
Please guide me.
Thanks,
Naga
Thanks for your comments.
I have found the following MSDN articles that gives the same symptoms and resolution for the problem.
Cmd.exe, Perl.exe, or other console-mode applications may fail to initialize properly and terminate prematurely when launched by a service using the CreateProcess() or CreateProcessAsUser() APIs. The calling process has no way of knowing that the launched console-mode application has terminated prematurely.
In some instances, calling GetExitCode() against the failed process indicates the following exit code:
128L ERROR_WAIT_NO_CHILDREN - There are no child processes to wait for.
http://support.microsoft.com/kb/156484
http://support.microsoft.com/kb/142676/EN-US
http://support.microsoft.com/kb/175687/EN-US
Thanks,
Naga

Win32 determine process ID

I want to create a process in Win32 .NET can I determine FOR the OS which PID the application will get ?
Update:
1) I am asking it because I have a problem in which I have 2 .NET application (the same ones) that I have each one of them got parameter ID and I want using a script (using the parameter) to decide which is the one and get it's PID
2) I want to know it from out side not from the .NET Process. I need for a script
You can never determine what PID a process will get. You can only determine what PID a process did get after you start the process.
In .Net you can do the following
var newProcess = Process.Start(someExeFile);
var id = newProcess.Id
In Win32 the CreateProcess function will return an PROCESS_INFORMATION struct as an out parameter of the function. It has the new PID as one of it's members (dwProcessId)
http://msdn.microsoft.com/en-us/library/ms684873(VS.85).aspx

Win32: Get message notification of other application's close/exit

My application needs to monitor all other running applications on the system. Is there some way I could get notified on exit of every application exe?
The methods I could find:
1) Use PSAPI functions to get the list of running exes at frequent intervals. At each poll compare with the previous list to find which application/process has exited.
Disadvantage: Requires constant polling, will take CPU time.
2) Set a global hook for WM_CLOSE message: Using this I would be able to get a notification when any application gets closed through the close button on the title bar
Disadvantage:
(-)Not all the applications are generating a WM_CLOSE message(Ex: Total Video Player Exe)
(-)If the application was closed through the "Exit" menu or button (e.g. File->Exit) , I can't trap that message
Is there any other better way that I missed? Please advise.
Get a list of PIDs using PSAPI.
Then get a handle on each process using OpenProcess().
Use WaitForMultipleObjects() to be signalled when one of the processes exits.
You could try the RegisterShellHookWindow() API and filter for HSHELL_WINDOWCREATED and HSHELL_WINDOWDESTROYED messages.
Of course, that will only get you notified about applications that have a window.
I recently ran into this problem and found a solution so wanted to share with you all. It all correct the way we should obtain handle to the process. Instead of WaitForSingleOBject though, I would recommend to use RegisterWaitForSingle object function. With this function you are giving a callback function and whenever the process exits, your callback function will be called. This is better than calling WaitForSingleObject in a thread. Calling WaitForSingleObject in your code by itself will cause your code to wait until the process exits. Here is an example of how to call it:
RegisterWaitForSingleObject(&waitHandle, processHandle, ProcessTerminatedCallback, param, INFINITE, WT_EXECUTEONLYONCE);
Where:
[out]waitHandle - new handle created for you. Please note that you cannot use this handle to call CloseHandle, but you can wait on it, if you want to.
[in] processHandle - handle to the process that you are supposed to obtain yourself
[in] ProcessTerminatedCallback - the callback function that will be called when the process exits
[in] param - LPVOID parameter that will be passed to the callback
[in] INFINITE - either wait infinitely or for a specified time, look up MSDN for more info
[in] WM_EXECUTEONLYONCE - will call the callback function only once. look up MSDN for more info
> Is there any other better way that I missed?
Yes, plenty. See on Win32 group (system notifications, without any hook)

Resources