193 lines
12 KiB
C++
193 lines
12 KiB
C++
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT license.
|
|
|
|
#include "precomp.h"
|
|
|
|
#include "ApiSorter.h"
|
|
|
|
#include "ApiDispatchers.h"
|
|
|
|
#include "../host/tracing.hpp"
|
|
|
|
#define CONSOLE_API_STRUCT(Routine, Struct, TraceName) \
|
|
{ \
|
|
Routine, sizeof(Struct), TraceName \
|
|
}
|
|
#define CONSOLE_API_NO_PARAMETER(Routine, TraceName) \
|
|
{ \
|
|
Routine, 0, TraceName \
|
|
}
|
|
|
|
#define CONSOLE_API_DEPRECATED(Struct) \
|
|
{ \
|
|
ApiDispatchers::ServerDeprecatedApi, sizeof(Struct), "Deprecated" \
|
|
}
|
|
#define CONSOLE_API_DEPRECATED_NO_PARAM() \
|
|
{ \
|
|
ApiDispatchers::ServerDeprecatedApi, 0, "Deprecated" \
|
|
}
|
|
|
|
typedef struct _CONSOLE_API_DESCRIPTOR
|
|
{
|
|
PCONSOLE_API_ROUTINE Routine;
|
|
ULONG RequiredSize;
|
|
PCSTR TraceName;
|
|
} CONSOLE_API_DESCRIPTOR, *PCONSOLE_API_DESCRIPTOR;
|
|
|
|
typedef struct _CONSOLE_API_LAYER_DESCRIPTOR
|
|
{
|
|
const CONSOLE_API_DESCRIPTOR* Descriptor;
|
|
ULONG Count;
|
|
} CONSOLE_API_LAYER_DESCRIPTOR, *PCONSOLE_API_LAYER_DESCRIPTOR;
|
|
|
|
const CONSOLE_API_DESCRIPTOR ConsoleApiLayer1[] = {
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerGetConsoleCP, CONSOLE_GETCP_MSG, "GetConsoleCP"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerGetConsoleMode, CONSOLE_MODE_MSG, "GetConsoleMode"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerSetConsoleMode, CONSOLE_MODE_MSG, "SetConsoleMode"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerGetNumberOfInputEvents, CONSOLE_GETNUMBEROFINPUTEVENTS_MSG, "GetNumberOfConsoleInputEvents"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerGetConsoleInput, CONSOLE_GETCONSOLEINPUT_MSG, "GetConsoleInput"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerReadConsole, CONSOLE_READCONSOLE_MSG, "ReadConsole"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerWriteConsole, CONSOLE_WRITECONSOLE_MSG, "WriteConsole"),
|
|
CONSOLE_API_DEPRECATED_NO_PARAM(), // ApiDispatchers::ServerConsoleNotifyLastClose
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerGetConsoleLangId, CONSOLE_LANGID_MSG, "GetConsoleLangId"),
|
|
CONSOLE_API_DEPRECATED(CONSOLE_MAPBITMAP_MSG),
|
|
};
|
|
|
|
const CONSOLE_API_DESCRIPTOR ConsoleApiLayer2[] = {
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerFillConsoleOutput, CONSOLE_FILLCONSOLEOUTPUT_MSG, "FillConsoleOutput"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerGenerateConsoleCtrlEvent, CONSOLE_CTRLEVENT_MSG, "GenerateConsoleCtrlEvent"),
|
|
CONSOLE_API_NO_PARAMETER(ApiDispatchers::ServerSetConsoleActiveScreenBuffer, "SetConsoleActiveScreenBuffer"),
|
|
CONSOLE_API_NO_PARAMETER(ApiDispatchers::ServerFlushConsoleInputBuffer, "FlushConsoleInputBuffer"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerSetConsoleCP, CONSOLE_SETCP_MSG, "SetConsoleCP"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerGetConsoleCursorInfo, CONSOLE_GETCURSORINFO_MSG, "GetConsoleCursorInfo"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerSetConsoleCursorInfo, CONSOLE_SETCURSORINFO_MSG, "SetConsoleCursorInfo"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerGetConsoleScreenBufferInfo, CONSOLE_SCREENBUFFERINFO_MSG, "GetConsoleScreenBufferInfo"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerSetConsoleScreenBufferInfo, CONSOLE_SCREENBUFFERINFO_MSG, "SetConsoleScreenBufferInfo"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerSetConsoleScreenBufferSize, CONSOLE_SETSCREENBUFFERSIZE_MSG, "SetConsoleScreenBufferSize"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerSetConsoleCursorPosition, CONSOLE_SETCURSORPOSITION_MSG, "SetConsoleCursorPosition"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerGetLargestConsoleWindowSize, CONSOLE_GETLARGESTWINDOWSIZE_MSG, "GetLargestConsoleWindowSize"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerScrollConsoleScreenBuffer, CONSOLE_SCROLLSCREENBUFFER_MSG, "ScrollConsoleScreenBuffer"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerSetConsoleTextAttribute, CONSOLE_SETTEXTATTRIBUTE_MSG, "SetConsoleTextAttribute"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerSetConsoleWindowInfo, CONSOLE_SETWINDOWINFO_MSG, "SetConsoleWindowInfo"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerReadConsoleOutputString, CONSOLE_READCONSOLEOUTPUTSTRING_MSG, "ReadConsoleOutputString"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerWriteConsoleInput, CONSOLE_WRITECONSOLEINPUT_MSG, "WriteConsoleInput"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerWriteConsoleOutput, CONSOLE_WRITECONSOLEOUTPUT_MSG, "WriteConsoleOutput"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerWriteConsoleOutputString, CONSOLE_WRITECONSOLEOUTPUTSTRING_MSG, "WriteConsoleOutputString"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerReadConsoleOutput, CONSOLE_READCONSOLEOUTPUT_MSG, "ReadConsoleOutput"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerGetConsoleTitle, CONSOLE_GETTITLE_MSG, "GetConsoleTitle"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerSetConsoleTitle, CONSOLE_SETTITLE_MSG, "SetConsoleTitle"),
|
|
};
|
|
|
|
const CONSOLE_API_DESCRIPTOR ConsoleApiLayer3[] = {
|
|
CONSOLE_API_DEPRECATED(CONSOLE_GETNUMBEROFFONTS_MSG),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerGetConsoleMouseInfo, CONSOLE_GETMOUSEINFO_MSG, "GetNumberOfConsoleMouseButtons"),
|
|
CONSOLE_API_DEPRECATED(CONSOLE_GETFONTINFO_MSG),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerGetConsoleFontSize, CONSOLE_GETFONTSIZE_MSG, "GetConsoleFontSize"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerGetConsoleCurrentFont, CONSOLE_CURRENTFONT_MSG, "GetCurrentConsoleFont"),
|
|
CONSOLE_API_DEPRECATED(CONSOLE_SETFONT_MSG),
|
|
CONSOLE_API_DEPRECATED(CONSOLE_SETICON_MSG),
|
|
CONSOLE_API_DEPRECATED(CONSOLE_INVALIDATERECT_MSG),
|
|
CONSOLE_API_DEPRECATED(CONSOLE_VDM_MSG),
|
|
CONSOLE_API_DEPRECATED(CONSOLE_SETCURSOR_MSG),
|
|
CONSOLE_API_DEPRECATED(CONSOLE_SHOWCURSOR_MSG),
|
|
CONSOLE_API_DEPRECATED(CONSOLE_MENUCONTROL_MSG),
|
|
CONSOLE_API_DEPRECATED(CONSOLE_SETPALETTE_MSG),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerSetConsoleDisplayMode, CONSOLE_SETDISPLAYMODE_MSG, "SetConsoleDisplayMode"),
|
|
CONSOLE_API_DEPRECATED(CONSOLE_REGISTERVDM_MSG),
|
|
CONSOLE_API_DEPRECATED(CONSOLE_GETHARDWARESTATE_MSG),
|
|
CONSOLE_API_DEPRECATED(CONSOLE_SETHARDWARESTATE_MSG),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerGetConsoleDisplayMode, CONSOLE_GETDISPLAYMODE_MSG, "GetConsoleDisplayMode"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerAddConsoleAlias, CONSOLE_ADDALIAS_MSG, "AddConsoleAlias"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerGetConsoleAlias, CONSOLE_GETALIAS_MSG, "GetConsoleAlias"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerGetConsoleAliasesLength, CONSOLE_GETALIASESLENGTH_MSG, "GetConsoleAliasesLength"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerGetConsoleAliasExesLength, CONSOLE_GETALIASEXESLENGTH_MSG, "GetConsoleAliasExesLength"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerGetConsoleAliases, CONSOLE_GETALIASES_MSG, "GetConsoleAliases"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerGetConsoleAliasExes, CONSOLE_GETALIASEXES_MSG, "GetConsoleAliasExes"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerExpungeConsoleCommandHistory, CONSOLE_EXPUNGECOMMANDHISTORY_MSG, "ExpungeConsoleCommandHistory"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerSetConsoleNumberOfCommands, CONSOLE_SETNUMBEROFCOMMANDS_MSG, "SetConsoleNumberOfCommands"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerGetConsoleCommandHistoryLength, CONSOLE_GETCOMMANDHISTORYLENGTH_MSG, "GetConsoleCommandHistoryLength"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerGetConsoleCommandHistory, CONSOLE_GETCOMMANDHISTORY_MSG, "GetConsoleCommandHistory"),
|
|
CONSOLE_API_DEPRECATED(CONSOLE_SETKEYSHORTCUTS_MSG),
|
|
CONSOLE_API_DEPRECATED(CONSOLE_SETMENUCLOSE_MSG),
|
|
CONSOLE_API_DEPRECATED(CONSOLE_GETKEYBOARDLAYOUTNAME_MSG),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerGetConsoleWindow, CONSOLE_GETCONSOLEWINDOW_MSG, "GetConsoleWindow"),
|
|
CONSOLE_API_DEPRECATED(CONSOLE_CHAR_TYPE_MSG),
|
|
CONSOLE_API_DEPRECATED(CONSOLE_LOCAL_EUDC_MSG),
|
|
CONSOLE_API_DEPRECATED(CONSOLE_CURSOR_MODE_MSG),
|
|
CONSOLE_API_DEPRECATED(CONSOLE_CURSOR_MODE_MSG),
|
|
CONSOLE_API_DEPRECATED(CONSOLE_REGISTEROS2_MSG),
|
|
CONSOLE_API_DEPRECATED(CONSOLE_SETOS2OEMFORMAT_MSG),
|
|
CONSOLE_API_DEPRECATED(CONSOLE_NLS_MODE_MSG),
|
|
CONSOLE_API_DEPRECATED(CONSOLE_NLS_MODE_MSG),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerGetConsoleSelectionInfo, CONSOLE_GETSELECTIONINFO_MSG, "GetConsoleSelectionInfo"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerGetConsoleProcessList, CONSOLE_GETCONSOLEPROCESSLIST_MSG, "GetConsoleProcessList"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerGetConsoleHistory, CONSOLE_HISTORY_MSG, "GetConsoleHistory"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerSetConsoleHistory, CONSOLE_HISTORY_MSG, "SetConsoleHistory"),
|
|
CONSOLE_API_STRUCT(ApiDispatchers::ServerSetConsoleCurrentFont, CONSOLE_CURRENTFONT_MSG, "SetConsoleCurrentFont")
|
|
};
|
|
|
|
const CONSOLE_API_LAYER_DESCRIPTOR ConsoleApiLayerTable[] = {
|
|
{ ConsoleApiLayer1, RTL_NUMBER_OF(ConsoleApiLayer1) },
|
|
{ ConsoleApiLayer2, RTL_NUMBER_OF(ConsoleApiLayer2) },
|
|
{ ConsoleApiLayer3, RTL_NUMBER_OF(ConsoleApiLayer3) },
|
|
};
|
|
|
|
// Routine Description:
|
|
// - This routine validates a user IO and dispatches it to the appropriate worker routine.
|
|
// Arguments:
|
|
// - Message - Supplies the message representing the user IO.
|
|
// Return Value:
|
|
// - A pointer to the reply message, if this message is to be completed inline; nullptr if this message will pend now and complete later.
|
|
PCONSOLE_API_MSG ApiSorter::ConsoleDispatchRequest(_Inout_ PCONSOLE_API_MSG Message)
|
|
{
|
|
// Make sure the indices are valid and retrieve the API descriptor.
|
|
ULONG const LayerNumber = (Message->msgHeader.ApiNumber >> 24) - 1;
|
|
ULONG const ApiNumber = Message->msgHeader.ApiNumber & 0xffffff;
|
|
|
|
if ((LayerNumber >= std::size(ConsoleApiLayerTable)) || (ApiNumber >= ConsoleApiLayerTable[LayerNumber].Count))
|
|
{
|
|
Message->SetReplyStatus(STATUS_ILLEGAL_FUNCTION);
|
|
return Message;
|
|
}
|
|
|
|
CONSOLE_API_DESCRIPTOR const* Descriptor = &ConsoleApiLayerTable[LayerNumber].Descriptor[ApiNumber];
|
|
|
|
// Validate the argument size and call the API.
|
|
if ((Message->Descriptor.InputSize < sizeof(CONSOLE_MSG_HEADER)) ||
|
|
(Message->msgHeader.ApiDescriptorSize > sizeof(Message->u)) ||
|
|
(Message->msgHeader.ApiDescriptorSize > Message->Descriptor.InputSize - sizeof(CONSOLE_MSG_HEADER)) ||
|
|
(Message->msgHeader.ApiDescriptorSize < Descriptor->RequiredSize))
|
|
{
|
|
Message->SetReplyStatus(STATUS_ILLEGAL_FUNCTION);
|
|
return Message;
|
|
}
|
|
|
|
BOOL ReplyPending = FALSE;
|
|
Message->Complete.Write.Data = &Message->u;
|
|
Message->Complete.Write.Size = Message->msgHeader.ApiDescriptorSize;
|
|
Message->State.WriteOffset = Message->msgHeader.ApiDescriptorSize;
|
|
Message->State.ReadOffset = Message->msgHeader.ApiDescriptorSize + sizeof(CONSOLE_MSG_HEADER);
|
|
|
|
// Unfortunately, we can't be as clear-cut with our error codes as we'd like since we have some callers that take
|
|
// hard dependencies on NTSTATUS codes that aren't readily expressible as an HRESULT. There's currently only one
|
|
// such known code -- STATUS_BUFFER_TOO_SMALL. There's a conlibk dependency on this being returned from the console
|
|
// alias API.
|
|
NTSTATUS Status = S_OK;
|
|
{
|
|
const auto trace = Tracing::s_TraceApiCall(Status, Descriptor->TraceName);
|
|
Status = (*Descriptor->Routine)(Message, &ReplyPending);
|
|
}
|
|
if (Status != STATUS_BUFFER_TOO_SMALL)
|
|
{
|
|
Status = NTSTATUS_FROM_HRESULT(Status);
|
|
}
|
|
|
|
if (!ReplyPending)
|
|
{
|
|
Message->SetReplyStatus(Status);
|
|
return Message;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|