| 560 | } |
| 561 | |
| 562 | std::vector<DWORD> processesInJob(HANDLE h) |
| 563 | { |
| 564 | const int MaxTries = 5; |
| 565 | |
| 566 | // doubled MaxTries times on failure |
| 567 | DWORD maxIds = 100; |
| 568 | |
| 569 | // for logging |
| 570 | DWORD lastCount = 0, lastAssigned = 0; |
| 571 | |
| 572 | for (int tries = 0; tries < MaxTries; ++tries) { |
| 573 | const DWORD idsSize = sizeof(ULONG_PTR) * maxIds; |
| 574 | const DWORD bufferSize = sizeof(JOBOBJECT_BASIC_PROCESS_ID_LIST) + idsSize; |
| 575 | |
| 576 | MallocPtr<void> buffer(std::malloc(bufferSize)); |
| 577 | auto* ids = static_cast<JOBOBJECT_BASIC_PROCESS_ID_LIST*>(buffer.get()); |
| 578 | |
| 579 | const auto r = QueryInformationJobObject(h, JobObjectBasicProcessIdList, ids, |
| 580 | bufferSize, nullptr); |
| 581 | |
| 582 | if (!r) { |
| 583 | const auto e = GetLastError(); |
| 584 | if (e != ERROR_MORE_DATA) { |
| 585 | log::error("failed to get process ids in job, {}", formatSystemMessage(e)); |
| 586 | return {}; |
| 587 | } |
| 588 | } |
| 589 | |
| 590 | if (ids->NumberOfProcessIdsInList >= ids->NumberOfAssignedProcesses) { |
| 591 | std::vector<DWORD> v; |
| 592 | for (DWORD i = 0; i < ids->NumberOfProcessIdsInList; ++i) { |
| 593 | v.push_back(ids->ProcessIdList[i]); |
| 594 | } |
| 595 | |
| 596 | return v; |
| 597 | } |
| 598 | |
| 599 | // try again with a larger buffer |
| 600 | maxIds *= 2; |
| 601 | |
| 602 | // for logging |
| 603 | lastCount = ids->NumberOfProcessIdsInList; |
| 604 | lastAssigned = ids->NumberOfAssignedProcesses; |
| 605 | } |
| 606 | |
| 607 | log::error("failed to get processes in job, can't get a buffer large enough, " |
| 608 | "{}/{} ids", |
| 609 | lastCount, lastAssigned); |
| 610 | |
| 611 | return {}; |
| 612 | } |
| 613 | |
| 614 | void findChildProcesses(Process& parent, std::vector<Process>& processes) |
| 615 | { |
no test coverage detected