Repository: microsoft/terminal
File: src/server/ProcessList.cpp (C++)

Code before:
    auto it = _processes.crbegin();
    const auto end = _processes.crend();

    for (; it != end; ++it)
    {
        *pProcessList++ = (*it)->dwProcessId;
    }

    *pcProcessList = _processes.size();
    return S_OK;
}

// Routine Description
// - Retrieves TERMINATION_RECORD structures for all processes known in the list (limited if necessary by parameter for group ID)
// - This is designed to copy the data so the global lock can be released while sending control information to attached processes.
// Arguments:
// - dwLimitingProcessId - Optional (0 if unused). Will restrict the return to only processes containing this group ID.
// - fCtrlClose - True if we're about to send a Ctrl Close command to the process. Will increment termination attempt count.
// - prgRecords - Pointer to callee allocated array of termination records. CALLER MUST FREE.
// - pcRecords - Length of records in prgRecords.
// Return Value:
// - S_OK if prgRecords was filled successfully or if no records were found that matched.
// - E_OUTOFMEMORY in a low memory situation.
[[nodiscard]] HRESULT ConsoleProcessList::GetTerminationRecordsByGroupId(const DWORD dwLimitingProcessId,
                                                                         const bool fCtrlClose,
                                                                         std::vector<ConsoleProcessTerminationRecord>& termRecords) const
{
    assert(ServiceLocator::LocateGlobals().getConsoleInformation().IsConsoleLocked());

    try
    {
        termRecords.clear();

        // Dig through known processes looking for a match
        for (const auto& p : _processes)
        {
            // If no limit was specified OR if we have a match, generate a new termination record.
            if (!dwLimitingProcessId ||
                p->_ulProcessGroupId == dwLimitingProcessId)
            {
                // If we're hard closing the window, increment the counter.
                if (fCtrlClose)
                {
                    p->_ulTerminateCount++;
                }

                wil::unique_handle process;
                // If the duplicate failed, the best we can do is to skip including the process in the list and hope it goes away.
                LOG_IF_WIN32_BOOL_FALSE(DuplicateHandle(GetCurrentProcess(),
                                                        p->_hProcess.get(),
                                                        GetCurrentProcess(),

Review comment (suggestion):
```suggestion
                                                                         _Out_ std::vector<ConsoleProcessTerminationRecord>& termRecords) const
```
nit: if you want to match the SAL annotations

Code after:
// Return Value:
// - S_OK if buffer was filled successfully and resulting count of items is in pcProcessList.
// - E_NOT_SUFFICIENT_BUFFER if the buffer given was too small. Refer to pcProcessList for size requirement.
[[nodiscard]] HRESULT ConsoleProcessList::GetProcessList(_Inout_updates_(*pcProcessList) DWORD* pProcessList,
                                                         _Inout_ size_t* const pcProcessList) const
{
    assert(ServiceLocator::LocateGlobals().getConsoleInformation().IsConsoleLocked());

    if (*pcProcessList < _processes.size())
    {
        *pcProcessList = _processes.size();
        return E_NOT_SUFFICIENT_BUFFER;
    }

    // Some applications, when reading the process list through the GetConsoleProcessList API,
    // are expecting the returned list of attached process IDs to be from newest to oldest.
    // As such, we have to put the newest process into the head of the list.
    auto it = _processes.crbegin();
    const auto end = _processes.crend();

    for (; it != end; ++it)
    {
        *pProcessList++ = (*it)->dwProcessId;
    }

    *pcProcessList = _processes.size();
    return S_OK;
}

// Routine Description
// - Retrieves TERMINATION_RECORD structures for all processes known in the list (limited if necessary by parameter for group ID)
// - This is designed to copy the data so the global lock can be released while sending control information to attached processes.
// Arguments:
// - dwLimitingProcessId - Optional (0 if unused). Will restrict the return to only processes containing this group ID.
// - fCtrlClose - True if we're about to send a Ctrl Close command to the process. Will increment termination attempt count.
// - prgRecords - Pointer to callee allocated array of termination records. CALLER MUST FREE.
// - pcRecords - Length of records in prgRecords.
// Return Value:
// - S_OK if prgRecords was filled successfully or if no records were found that matched.
// - E_OUTOFMEMORY in a low memory situation.
[[nodiscard]] HRESULT ConsoleProcessList::GetTerminationRecordsByGroupId(const DWORD dwLimitingProcessId,
                                                                         const bool fCtrlClose,
                                                                         _Out_ std::vector<ConsoleProcessTerminationRecord>& termRecords) const
{
    assert(ServiceLocator::LocateGlobals().getConsoleInformation().IsConsoleLocked());

    try
    {
        termRecords.clear();

        // Dig through known processes looking for a match