Repository: microsoft/terminal
File: src/interactivity/win32/windowio.cpp (C++)

Code before:
    return Flag;
}

/*
* This routine tells win32k what process we want to use to masquerade as the
* owner of conhost's window. If ProcessData is nullptr that means the root process
* has exited so we need to find any old process to be the owner. If this console
* has no processes attached to it -- it's only being kept alive by references
* via IO handles -- then we'll just set the owner to conhost.exe itself.
*/
VOID SetConsoleWindowOwner(const HWND hwnd, _Inout_opt_ ConsoleProcessHandle* pProcessData)
{
    const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
    FAIL_FAST_IF(!(gci.IsConsoleLocked()));

    DWORD dwProcessId;
    DWORD dwThreadId;
    if (nullptr != pProcessData)
    {
        dwProcessId = pProcessData->dwProcessId;
        dwThreadId = pProcessData->dwThreadId;
    }
    else
    {
        // Find a process to own the console window. If there are none then let's use conhost's.
        pProcessData = gci.ProcessHandleList.GetOldestProcess();
        if (pProcessData != nullptr)
        {
            dwProcessId = pProcessData->dwProcessId;
            dwThreadId = pProcessData->dwThreadId;
            pProcessData->fRootProcess = true;
        }
        else
        {
            dwProcessId = GetCurrentProcessId();
            dwThreadId = GetCurrentThreadId();
        }
    }

    CONSOLEWINDOWOWNER ConsoleOwner;
    ConsoleOwner.hwnd = hwnd;
    ConsoleOwner.ProcessId = dwProcessId;
    ConsoleOwner.ThreadId = dwThreadId;

    // Comment out this line to enable UIA tree to be visible until UIAutomationCore.dll can support our scenario.
    LOG_IF_FAILED(ServiceLocator::LocateConsoleControl<Microsoft::Console::Interactivity::Win32::ConsoleControl>()
                      ->Control(ConsoleControl::ControlType::ConsoleSetWindowOwner,
                                &ConsoleOwner,
                                sizeof(ConsoleOwner)));
}


Review comment (bug):
This is a behavior change: `GetFirstProcess()` used to return the newest process, but I think this was wrong... conhost's PID was the last (= oldest) entry if anything. In fact even the `SetConsoleWindowOwner` documentation says:
> If ProcessData is nullptr that means the root process has exited so we need to find any **_old_** process to be the owner.

So I've chosen to rename this function to better convey its meaning and fix this bug.

Code after:
    return Flag;
}

/*
* This routine tells win32k what process we want to use to masquerade as the
* owner of conhost's window. If ProcessData is nullptr that means the root process
* has exited so we need to find any old process to be the owner. If this console
* has no processes attached to it -- it's only being kept alive by references
* via IO handles -- then we'll just set the owner to conhost.exe itself.
*/
VOID SetConsoleWindowOwner(const HWND hwnd, _Inout_opt_ ConsoleProcessHandle* pProcessData)
{
    const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
    FAIL_FAST_IF(!(gci.IsConsoleLocked()));

    DWORD dwProcessId;
    DWORD dwThreadId;
    if (nullptr != pProcessData)
    {
        dwProcessId = pProcessData->dwProcessId;
        dwThreadId = pProcessData->dwThreadId;
    }
    else
    {
        // Find a process to own the console window. If there are none then let's use conhost's.
        pProcessData = gci.ProcessHandleList.GetRootProcess();
        if (!pProcessData)
        {
            // No root process ID? Pick the oldest existing process.
            pProcessData = gci.ProcessHandleList.GetOldestProcess();
        }

        if (pProcessData != nullptr)
        {
            dwProcessId = pProcessData->dwProcessId;
            dwThreadId = pProcessData->dwThreadId;
            pProcessData->fRootProcess = true;
        }
        else
        {
            dwProcessId = GetCurrentProcessId();
            dwThreadId = GetCurrentThreadId();
        }
    }

    // Comment out this line to enable UIA tree to be visible until UIAutomationCore.dll can support our scenario.
    LOG_IF_NTSTATUS_FAILED(ServiceLocator::LocateConsoleControl()->SetWindowOwner(hwnd, dwProcessId, dwThreadId));
}

// ----------------------------
// Window Message Handlers