Raymond Chen describes a technique using a helper process to precisely control which handles are inherited by a new process, avoiding accidental inheritance from other components in the same process.
<p>Some time ago, I wrote about <a title="Programmatically controlling which handles are inherited by new processes in Win32" href="https://devblogs.microsoft.com/oldnewthing/20111216-00/?p=8873"> programmatically controlling which handles are inherited by new processes in Win32</a> by using the <code>PROC_<wbr />THREAD_<wbr />ATTRIBUTE_<wbr />HANDLE_<wbr />LIST</code> to limit exactly which handles are inherited. That way, when you create a new process, you have precise control over which handles get inherited and don’t accidentally inherit handles created by unrelated components in your process.</p>
<p>A collegue of mine pointed out that you still have the reverse problem: Since handles must be marked as inheritable for them to participate in <code>PROC_<wbr />THREAD_<wbr />ATTRIBUTE_<wbr />HANDLE_<wbr />LIST</code>, if another thread calls <code>CreateProcess</code> with <code>bInheritHandles</code> = <code>TRUE</code> but without using <code>PROC_<wbr />THREAD_<wbr />ATTRIBUTE_<wbr />HANDLE_<wbr />LIST</code>, then they will accidentally inherit all of <i>your</i> handles.</p>
<p>This problem could have been avoided if the <code>PROC_<wbr />THREAD_<wbr />ATTRIBUTE_<wbr />HANDLE_<wbr />LIST</code> allowed you to include non-inheritable handles, in which case they would be non-inheritable by normal <code>CreateProcess</code> but inheritable if explicitly opted back in. But alas, that’s not how it was designed.</p>
<p>Instead, you can create a helper process. All this helper process does is wait for the main process to exit, and then exit itself.</p>
<pre>WaitForSingleObject(hMainProcess, INFINITE);
ExitProcess(0);
</pre>
<p>This process doesn’t sound like it’s doing anything useful, and it’s not. But what makes it useful is not what it’s doing but rather what is done <i>to</i> it.</p>
<p>The components in the main process create their handles as non-inheritable. When they wants to create a process with specific inherited handles, they duplicate the desired handles into the helper process (as inheritable), and then build a <code>PROC_<wbr />THREAD_<wbr />ATTRIBUTE_<wbr />HANDLE_<wbr />LIST</code> that lists those duplicates as handles to inherit. They also use the <code>PROC_<wbr />THREAD_<wbr />ATTRIBUTE_<wbr />PARENT_<wbr />PROCESS</code> to specify that the <i>helper</i> process is the parent process that the handles should be inherited from. Then they pass those thread attributes to <code>CreateProcess</code>, and the new process will inherit exactly those handles. Then they clean up by closing the handles in the helper process with the help of <code>DuplicateHandle</code> and <code>DUPLICATE_<wbr />CLOSE_<wbr />SOURCE</code>.</p>
<p>Notice that multiple threads can simultaneously be operating on the helper process in this way, so you need only one helper process to service all your handle-inheritance-control needs.</p>
<p>This avoids the accidental inheritance problem because the handles that belong to the components in the main process are still marked non-inheritable, so any other code in the main process that does a <code>CreateProcess</code> will not inherit them.</p>
<p>The post <a href="https://devblogs.microsoft.com/oldnewthing/20260511-00/?p=112313">Additional notes on controlling which handles are inherited by <CODE>Create­Process</CODE></a> appeared first on <a href="https://devblogs.microsoft.com/oldnewthing">The Old New Thing</a>.</p>
# Additional notes on controlling which handles are inherited by CreateProcess - The Old New Thing
Source: [https://devblogs.microsoft.com/oldnewthing/20260511-00?p=112313](https://devblogs.microsoft.com/oldnewthing/20260511-00?p=112313)
Some time ago, I wrote about[programmatically controlling which handles are inherited by new processes in Win32](https://devblogs.microsoft.com/oldnewthing/20111216-00/?p=8873)by using the`PROC\_THREAD\_ATTRIBUTE\_HANDLE\_LIST`to limit exactly which handles are inherited\. That way, when you create a new process, you have precise control over which handles get inherited and don’t accidentally inherit handles created by unrelated components in your process\.
A collegue of mine pointed out that you still have the reverse problem: Since handles must be marked as inheritable for them to participate in`PROC\_THREAD\_ATTRIBUTE\_HANDLE\_LIST`, if another thread calls`CreateProcess`with`bInheritHandles`=`TRUE`but without using`PROC\_THREAD\_ATTRIBUTE\_HANDLE\_LIST`, then they will accidentally inherit all of*your*handles\.
This problem could have been avoided if the`PROC\_THREAD\_ATTRIBUTE\_HANDLE\_LIST`allowed you to include non\-inheritable handles, in which case they would be non\-inheritable by normal`CreateProcess`but inheritable if explicitly opted back in\. But alas, that’s not how it was designed\.
Instead, you can create a helper process\. All this helper process does is wait for the main process to exit, and then exit itself\.
```
WaitForSingleObject(hMainProcess, INFINITE);
ExitProcess(0);
```
This process doesn’t sound like it’s doing anything useful, and it’s not\. But what makes it useful is not what it’s doing but rather what is done*to*it\.
The components in the main process create their handles as non\-inheritable\. When they wants to create a process with specific inherited handles, they duplicate the desired handles into the helper process \(as inheritable\), and then build a`PROC\_THREAD\_ATTRIBUTE\_HANDLE\_LIST`that lists those duplicates as handles to inherit\. They also use the`PROC\_THREAD\_ATTRIBUTE\_PARENT\_PROCESS`to specify that the*helper*process is the parent process that the handles should be inherited from\. Then they pass those thread attributes to`CreateProcess`, and the new process will inherit exactly those handles\. Then they clean up by closing the handles in the helper process with the help of`DuplicateHandle`and`DUPLICATE\_CLOSE\_SOURCE`\.
Notice that multiple threads can simultaneously be operating on the helper process in this way, so you need only one helper process to service all your handle\-inheritance\-control needs\.
This avoids the accidental inheritance problem because the handles that belong to the components in the main process are still marked non\-inheritable, so any other code in the main process that does a`CreateProcess`will not inherit them\.
### Category
### Topics
## Author

Raymond has been involved in the evolution of Windows for more than 30 years\. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie\-jeebies\. The Web site spawned a book, coincidentally also titled The Old New Thing \(Addison Wesley 2007\)\. He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information\.
A blog post proposing a redesign of the System.Diagnostics.Process class in .NET to separate properties valid only for started processes into a new class, aiming to reduce API confusion.
Raymond Chen discusses a historical Windows compatibility issue where some 16-bit programs abused window class extra bytes to store private data, and how Microsoft blocked the loophole for 32-bit and 64-bit programs while maintaining backward compatibility.
This blog post presents a C++ helper class using the Windows Implementation Library (WIL) to manage LPPROC_THREAD_ATTRIBUTE_LIST allocations with RAII, offering both throwing and non-throwing variants.
Raymond Chen continues his series on building an agile Windows Runtime delegate in C++/WinRT, comparing how C++/WinRT, C++/CX, and WRL handle non-marshalable delegates and agile reference creation.
This article from Microsoft's Old New Thing blog explains the rationale behind best practices for Windows kernel callback functions, particularly why blocking or waiting on work items defeats their purpose, using a cautionary tale about drivers causing system hangs.