Like handles to threads and synchronization objects, handles to processes can be shared. Several different processes might possess handles to any one process. As usual, you can’t simply pass a handle directly from one process to another. You must instead rely on one of several transfer mechanisms to perform the conversion that makes a handle valid in a new address space.
One mechanism is inheritance. If you tell CreateProcess to let the child inherit handles, the child receives copies of all the inheritable handles in its own object table. Children cannot use the handles there directly—they must still receive the handle on their command line or through a pipe—but inheritance makes the handle valid when it reaches the child process. If you pass a child a handle it has not already inherited, the handle will not work.
Inheritance helps in passing handles only between related processes. To create a handle that can be passed to any other process, related or unrelated, call DuplicateHandle. You saw that function in Chapter 14. Given the original handle and a source and destination process, DuplicateHandle creates a new handle valid in the destination process. DuplicateHandle also allows you to modify the attributes of a handle you want to keep. If, for example, you want only one of several children to inherit a particular handle, you create the first child, allowing inheritance, and then call DuplicateHandle to make a noninheritable copy. Close the original inheritable handle and keep only the copy. Subsequent children will not inherit it.
NOTE
The AnonPipe demo program, discussed later in this chapter, uses DuplicateHandle to control inheritance. Look for the StartProcess procedure in the demo, which is included on the CD accompanying this book.
Another command allows any process to open a handle to any other process.
HANDLE OpenProcess(
DWORD fdwAccess, // desired access privileges
BOOL bInherit, // TRUE for children to inherit the handle
DWORD dwProcessId ); // number identifying the process
NOTE
Under Windows NT, you can open a process only if the security descriptor of your own process endows you with sufficient clearance. Security privileges do not apply under Windows 98.
OpenProcess requires you to identify the process by its ID number. Normally, you know the number only if you created the process or if the process itself, or one of its relatives, passes you the number (through a pipe or a DDE conversation, for example).
It is possible to generate a list of ID numbers for all the currently running processes, but the task is not trivial. It involves enumerating information stored in the system registry under the HKEY_PERFORMANCE_DATA key (see Chapter 17 for more information about the registry). The online help file contains sample code showing how to search the registry with RegEnumKey, RegEnumValue, and RegQueryInfoKey. The structure of the HKEY_PERFORMANCE_DATA key is documented in Winperf.H. The SDK comes with the source code for its Process Viewer utility (see Figure 14.4 in Chapter 14); it enumerates threads and processes.