I got the following scenario:
Process A create process B, and then B try to get a handle of A with OpenProcess(). I want B to have PROCESS_ALL_ACCESS rights to A.
How should I achieve this?
Thanks.
Probably the easiest way is for the parent to avoid the child having to call OpenProcess at all. Instead, have the parent retrieve a handle to itself (which will automatically have all access) and then call DuplicateHandle with bInheritHandle = true. Then when it creates process B, that handle (with full access to process A) will already be open in the child. Process A simply has to pass the handle to process B, and process B can use it.
Related
I am developing a Windows console application in C++. I need my program to do some operations on another process which I don't have any control over.
But, I have some doubts about a case where the target process might get terminated for some reason (by Task Manager, etc). Is it safe to use a handle to a process which is already terminated?
Note : I stop my operations if one of the functions fails.
HANDLE hProcess = OpenProcess(pid);
if( hProcess != NULL )
{
// Lets suppose process is terminated here
/* Some operations on process using returned handle*/
}
Kernel objects in Windows are reference-counted, with references being represented as handles to objects. Client code can create kernel objects and receive an initial reference (e.g. CreateProcess), increment the reference count on an existing object (e.g. OpenProcess, or DuplicateHandle), and decrement the reference count (CloseHandle). As long as you hold on to a HANDLE, the object referenced by that HANDLE is kept alive.
In case of a process object, that object is valid at least as long as you hold a reference (HANDLE) to it. The fact that a process has been terminated is observable, but doesn't otherwise invalidate or destroy the process object if there are any outstanding references to it.
Specifically this means that you can perform any operations you'd do with a "live" process (one for which the OS is still scheduling threads to execute), such as WaitForSingleObject. In addition you can call GetExitCodeProcess and that call won't return STILL_ACTIVE.
Barring a call to CloseHandle, you are now a stakeholder that has a say in the demise of the process object. It won't go away unless you sign it off. A corollary of this is that you now also control the validity of the PID. It's tied to the process' lifetime, and as long as you hold a reference to it by way of a HANDLE, that PID won't get reused for another process.
In summary, as long as you hold on to a (process) HANDLE you can do whatever.
Given two applications, A and B, B needs to get value from A in a synchronous way.
In other words, taking the object model for inspiration, application B wants to do some kind of myVar = A.getValue() and continue its execution using myVar in the rest of the code.
I have the handle of application A's main form and i know how to send message to it with SendMessage(). This function waits for the message to be proceed and then return an integer that is the result of the execution. But i don't know how to use this mechanism so that B gets back some complex data structure (string or data record).
It seems to me that using the SendMessage return value is not a good idea for many reasons, so is there a way to do that?
It has to be done through Windows Messages (i already know how to do it through pipes and sockets).
Thank you!
PS: i work with Delphi but that has no importance here, unless you are able to give examples in Delphi to illustrate your answer :)
The return value of a message is an LRESULT, that is a pointer sized value. If what you wish to return fits in such a value, that would be the clean way to proceed. Otherwise you need something else.
You say that you must use Windows messages, and that you are sending these messages between different processes. Given those constraints, there is exactly one solution, namely WM_COPYDATA. That is the only Windows message which can marshal custom data across a process boundary.
So the procedure is as follows:
Send a message from process B to process A. Include in that message a window handle from process B.
When process A receives the message, it must send a WM_COPYDATA to the window handle that was sent in stage 1.
Process B can then receive and process the message sent in stage 2.
Note that the WM_COPYDATA message is sent from process A to process B whilst process A is handling the original message. This means that the WM_COPYDATA is received and processed by process B, before the original message from B to A returns. This can be somewhat confusing, but you did state that you wanted to do this entirely with Windows messages.
This can be done by one of your processes performing VirtualAllocEx() to allocate memory in another process and then use Read/WriteProcessMemory to copy data there.
I have two applications. Both of them use the same resources. Lets call these resources "profile resources". Application B cannot be started up until Application A shutsdown. So I have app A running and was trying to shut it down, then launch up with app B path. I explored RegisterApplicationRestart but I could not accomplish it. Is this possible to be done? I'm getting stuck at the point where Application A is shutdown, then I cant run any code to launch back App B.
A can launch B using CreateProcess() before exiting, passing its own process handle to B. Before B accesses the resource, it can wait on A's handle using WaitForSingleObject() or related function. When the handle is signaled, A has fully terminated, so B can close the handle using CloseHandle() and move on as needed.
To pass A's process handle to B, A can either:
open its own process handle using OpenProcess() with GetCurrentProcessId() as the process ID, mark the handle as inheritable using SetHandleInformation(), and then pass the handle value to B as a command-line parameter, setting the bInheritHandles parameter of CreateProcess() to TRUE.
Run B first and have it create an IPC listener (named pipe, mailslot, socket, etc), then A can duplicate its own process handle for B's use via DuplicateHandle() with GetCurrentProcess() as the source handle and B's process handle (from CreateProcess()) as the target process, then send the duplicate handle value to B via IPC.
A simpler technique is to have A pass its own process ID, rather than its process handle, to B as a command-line parameter, then B can use OpenProcess() to open A's process handle. Although this will usually work, it does have a small race condition - before B has a chance to open the process handle, A might terminate and the OS could reuse its process ID for a new unrelated process, thus B would get a handle to, and wait on, the wrong process.
Is there any Win32 API to check if a given handle belongs to the current process?
From a window handle you can use GetWindowThreadProcessId Function to get process id.
From a process handle you get the id with GetProcessId Function.
I don't know how easy is to get a process handle from some other handle. But I believe it'll have to do with kernel objects enumeration.
A handle can "belong" to more than one process (Inherited handles in child process etc)
I note an applications handle when I use the shell function to open it.
I then use that handle to close the application later.
However the user can also close that other application himself.
Can that handle then be reused by windows so that when I use that handle I close a different process.
If it is possible is it likely?
No, you don't have to worry about it. The handle returned by, say, OpenProcess, ShellExecuteEx() or CreateProcess keeps the process object alive. That's how it is possible to call GetExitCodeProcess() to retrieve the exit code after the process is terminated.
The object doesn't get released until the last handle on it is closed. Opposite of earlier advice given in this thread, it is very important that you call CloseHandle() or you'll have a leak.
You can wait on a process handle to figure out when it is exited.
WaitForSingleObject(hProcess, INFINITE);
Once this returns, you know the process has exited and you don't need to close it.