CPP: How to wait on a job object?

This is the sample code in CPP to show how to wait on a job object. In the documentation:

 

The state of a job object is set to signaled when all of its processes are terminated because the specified end-of-job time limit has been exceeded. Use WaitForSingleObject or WaitForSingleObjectEx to monitor the job object for this event.

 

If the processes terminate normally, then the job object is not signaled. To detect when all processes in a job have terminated, you need to associate the job with a completion port, and then listen on the I/O completion port for the JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO notification.

=================================

#define UNICODE

#define _UNICODE

#define STRICT

#include
<windows.h>

#include
<stdio.h>

#include
<atlbase.h>

#include <atlalloc.h>

#include
<shlwapi.h>

 

int __cdecl wmain(int argc, PWSTR argv[])

{

   
CHandle Job(CreateJobObject(nullptr, nullptr));

    if(!Job) {

       
wprintf(L"Could not create job object, error %dn", GetLastError());

       
return 0;

    }

 

   
CHandle IOPort(CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 1));

    if(!IOPort) {

       
wprintf(L"Could not create IO completion port, error %dn",GetLastError());

       
return 0;

    }

 

   
JOBOBJECT_ASSOCIATE_COMPLETION_PORT Port;

   
Port.CompletionKey = Job;

   
Port.CompletionPort = IOPort;

    if(!SetInformationJobObject(Job, JobObjectAssociateCompletionPortInformation,&Port, sizeof(Port))) {

       
wprintf(L"Could not associate job with IO completion port, error %dn", GetLastError());

       
return 0;

    }

 

   
PROCESS_INFORMATION ProcessInformation;

   
STARTUPINFO StartupInfo = { sizeof(StartupInfo) };

   
PWSTR CommandLine = PathGetArgs(GetCommandLine());

 

    if(!CreateProcess(nullptr, CommandLine, nullptr, nullptr, FALSE,CREATE_SUSPENDED, nullptr, nullptr, &StartupInfo, &ProcessInformation))
{

       
wprintf(L"Could not run process, error %dn", GetLastError());

       
return 0;

    }

 

    if(!AssignProcessToJobObject(Job, ProcessInformation.hProcess)) {

       
wprintf(L"Could not assign process to job, error %dn",
GetLastError());

       
return 0;

    }

 

   
ResumeThread(ProcessInformation.hThread);

   
CloseHandle(ProcessInformation.hThread);

   
CloseHandle(ProcessInformation.hProcess);

 

   
DWORD CompletionCode;

   
ULONG_PTR CompletionKey;

   
LPOVERLAPPED Overlapped;

 

   
while (GetQueuedCompletionStatus(IOPort, &CompletionCode,&CompletionKey, &Overlapped, INFINITE) && CompletionCode !=JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO) {

       
wprintf(L"Still waiting...n");

    }

 

   
wprintf(L"All donen");

 

   
return 0;

}