I found a trick to nearly have recursive lambdas:
#include <Windows.h>
#include <TlHelp32.h>
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
#include <compare>
#include <functional>
#include <sstream>
#if defined(_MSC_VER)
#pragma warning(disable: 6319) // comma-statement with unused return-value
#endif
using namespace std;
using XHANDLE = unique_ptr<void, decltype([]( void *h ) { h&& h !=
INVALID_HANDLE_VALUE && CloseHandle( h ); }) > ;
template<typename Self, typename ... Args >
void selfHelper( Self &&self, Args &&... args )
{
self( self, forward<Args>( args ) ... );
}
int main( int argc, char ** )
{
try
{
auto throwSysErr = []( char const *what ) { throw system_error(
GetLastError(), system_category(), what ); };
XHANDLE xhSnapshot( CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ) );
xhSnapshot.get() == INVALID_HANDLE_VALUE // MSVC-bug with if in this case
&& (throwSysErr( "can't create toolhelp snapshot" ), 123 );
struct pe_t;
using process_vec = vector<pe_t>;
using process_it = vector<pe_t>::iterator;
struct pe_t
{
PROCESSENTRY32W pe;
bool root;
process_it pFirstChild, pNextSibling;
process_itit ppSibling = lower_bound( pProcesses.begin(),
pProcesses.end(), dwPpId,
[]( process_it pChildProcess, DWORD dwPpId )
{
DWORD dwChildPpId = pChildProcess->pe.th32ParentProcessID;
return dwChildPpId < dwPpId
|| dwChildPpId == dwPpId && !pChildProcess->pe.th32ProcessID;
} );
process_it pSibling;
if( ppSibling == pProcesses.end()
|| (pSibling = *ppSibling)->pe.th32ParentProcessID != dwPpId )
{
pProcess->pFirstChild = processes.end();
continue;
}
pProcess->pFirstChild = pSibling;
for( ; ; )
{
pSibling->root = false;
process_itit ppNextSibling = ppSibling + 1;
process_it pNextSibling;
if( ppNextSibling == pProcesses.end()
|| (pNextSibling = *ppNextSibling)->pe.th32ParentProcessID != dwPpId )
{
pSibling->pNextSibling = processes.end();
break;
}
pSibling->pNextSibling = pNextSibling;
ppSibling = ppNextSibling;
pSibling = *ppSibling;
}
}
wstring strIndent;
wostringstream woss;
process_it pEnd = processes.end();
size_t n = 0;
for( process_it pProcess = processes.begin(); pProcess != pEnd;
++pProcess )
if( pProcess->root )
selfHelper( [&]( auto &&self, process_it pFirst )
{
woss << strIndent;
pe_t &process = *pFirst;
woss << L"\"" << process.pe.szExeFile << " (" <<
process.pe.th32ProcessID << ")" << endl;
process_it pSibling = process.pFirstChild;
if( pSibling == processes.end() )
return;
strIndent.push_back( L'\t' );
do
self( self, pSibling );
while( (pSibling = pSibling->pNextSibling) != pEnd );
strIndent.pop_back();
}, pProcess );