// Copyright (c) Microsoft Corporation. // Licensed under the MIT license. #include "precomp.h" #include "ApiDispatchers.h" #include "../host/globals.h" #include "../host/handle.h" #include "../host/server.h" #include "../host/telemetry.hpp" #include "../host/ntprivapi.hpp" #include "../interactivity/inc/ServiceLocator.hpp" using Microsoft::Console::Interactivity::ServiceLocator; [[nodiscard]] HRESULT ApiDispatchers::ServerDeprecatedApi(_Inout_ CONSOLE_API_MSG* const m, _Inout_ BOOL* const /*pbReplyPending*/) { // log if we hit a deprecated API. RETURN_HR_MSG(E_NOTIMPL, "Deprecated API attempted: 0x%08x", m->Descriptor.Function); } [[nodiscard]] HRESULT ApiDispatchers::ServerGetConsoleProcessList(_Inout_ CONSOLE_API_MSG* const m, _Inout_ BOOL* const /*pbReplyPending*/) { const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); PCONSOLE_GETCONSOLEPROCESSLIST_MSG const a = &m->u.consoleMsgL3.GetConsoleProcessList; Telemetry::Instance().LogApiCall(Telemetry::ApiCall::GetConsoleProcessList); PVOID Buffer; ULONG BufferSize; RETURN_IF_FAILED(m->GetOutputBuffer(&Buffer, &BufferSize)); a->dwProcessCount = BufferSize / sizeof(ULONG); LockConsole(); auto Unlock = wil::scope_exit([&] { UnlockConsole(); }); /* * If there's not enough space in the array to hold all the pids, we'll * inform the user of that by returning a number > than a->dwProcessCount * (but we still return S_OK). */ LPDWORD lpdwProcessList = (PDWORD)Buffer; size_t cProcessList = a->dwProcessCount; if (SUCCEEDED(gci.ProcessHandleList.GetProcessList(lpdwProcessList, &cProcessList))) { m->SetReplyInformation(cProcessList * sizeof(ULONG)); } a->dwProcessCount = (ULONG)cProcessList; return S_OK; } [[nodiscard]] HRESULT ApiDispatchers::ServerGetConsoleLangId(_Inout_ CONSOLE_API_MSG* const m, _Inout_ BOOL* const /*pbReplyPending*/) { CONSOLE_LANGID_MSG* const a = &m->u.consoleMsgL1.GetConsoleLangId; Telemetry::Instance().LogApiCall(Telemetry::ApiCall::GetConsoleLangId); // TODO: MSFT: 9115192 - This should probably just ask through GetOutputCP and convert it ourselves on this side. return m->_pApiRoutines->GetConsoleLangIdImpl(a->LangId); } [[nodiscard]] HRESULT ApiDispatchers::ServerGenerateConsoleCtrlEvent(_Inout_ CONSOLE_API_MSG* const m, _Inout_ BOOL* const /*pbReplyPending*/) { CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); CONSOLE_CTRLEVENT_MSG* const a = &m->u.consoleMsgL2.GenerateConsoleCtrlEvent; Telemetry::Instance().LogApiCall(Telemetry::ApiCall::GenerateConsoleCtrlEvent); LockConsole(); auto Unlock = wil::scope_exit([&] { UnlockConsole(); }); // Make sure the process group id is valid. if (a->ProcessGroupId != 0) { ConsoleProcessHandle* ProcessHandle; ProcessHandle = gci.ProcessHandleList.FindProcessByGroupId(a->ProcessGroupId); if (ProcessHandle == nullptr) { ULONG ProcessId = a->ProcessGroupId; // We didn't find a process with that group ID. // Let's see if the process with that ID exists and has a parent that is a member of this console. RETURN_IF_NTSTATUS_FAILED((NtPrivApi::s_GetProcessParentId(&ProcessId))); ProcessHandle = gci.ProcessHandleList.FindProcessInList(ProcessId); RETURN_HR_IF_NULL(E_INVALIDARG, ProcessHandle); RETURN_IF_FAILED(gci.ProcessHandleList.AllocProcessData(a->ProcessGroupId, 0, a->ProcessGroupId, ProcessHandle, nullptr)); } } gci.LimitingProcessId = a->ProcessGroupId; HandleCtrlEvent(a->CtrlEvent); return S_OK; }