mirror of
https://github.com/reactos/reactos.git
synced 2024-11-11 01:04:11 +00:00
912ce51ae6
Sync with trunk head (r48826) svn path=/branches/cmake-bringup/; revision=48831
848 lines
26 KiB
C
848 lines
26 KiB
C
/*
|
|
* reactos/subsys/csrss/win32csr/conio.c
|
|
*
|
|
* Console I/O functions
|
|
*
|
|
* ReactOS Operating System
|
|
*/
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
#define NDEBUG
|
|
#include "w32csr.h"
|
|
#include <debug.h>
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
NTSTATUS FASTCALL
|
|
ConioConsoleFromProcessData(PCSRSS_PROCESS_DATA ProcessData, PCSRSS_CONSOLE *Console)
|
|
{
|
|
PCSRSS_CONSOLE ProcessConsole;
|
|
|
|
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
|
ProcessConsole = ProcessData->Console;
|
|
|
|
if (!ProcessConsole)
|
|
{
|
|
*Console = NULL;
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
|
return STATUS_INVALID_HANDLE;
|
|
}
|
|
|
|
InterlockedIncrement(&ProcessConsole->ReferenceCount);
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
|
EnterCriticalSection(&(ProcessConsole->Lock));
|
|
*Console = ProcessConsole;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
VOID FASTCALL
|
|
ConioConsoleCtrlEventTimeout(DWORD Event, PCSRSS_PROCESS_DATA ProcessData, DWORD Timeout)
|
|
{
|
|
HANDLE Thread;
|
|
|
|
DPRINT("ConioConsoleCtrlEvent Parent ProcessId = %x\n", ProcessData->ProcessId);
|
|
|
|
if (ProcessData->CtrlDispatcher)
|
|
{
|
|
|
|
Thread = CreateRemoteThread(ProcessData->Process, NULL, 0,
|
|
(LPTHREAD_START_ROUTINE) ProcessData->CtrlDispatcher,
|
|
UlongToPtr(Event), 0, NULL);
|
|
if (NULL == Thread)
|
|
{
|
|
DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
|
|
return;
|
|
}
|
|
WaitForSingleObject(Thread, Timeout);
|
|
CloseHandle(Thread);
|
|
}
|
|
}
|
|
|
|
VOID FASTCALL
|
|
ConioConsoleCtrlEvent(DWORD Event, PCSRSS_PROCESS_DATA ProcessData)
|
|
{
|
|
ConioConsoleCtrlEventTimeout(Event, ProcessData, 0);
|
|
}
|
|
|
|
static NTSTATUS WINAPI
|
|
CsrInitConsole(PCSRSS_CONSOLE Console, BOOL Visible)
|
|
{
|
|
NTSTATUS Status;
|
|
SECURITY_ATTRIBUTES SecurityAttributes;
|
|
PCSRSS_SCREEN_BUFFER NewBuffer;
|
|
BOOL GuiMode;
|
|
|
|
Console->Title.MaximumLength = Console->Title.Length = 0;
|
|
Console->Title.Buffer = NULL;
|
|
|
|
//FIXME
|
|
RtlCreateUnicodeString(&Console->Title, L"Command Prompt");
|
|
|
|
Console->ReferenceCount = 0;
|
|
Console->LineBuffer = NULL;
|
|
Console->Header.Type = CONIO_CONSOLE_MAGIC;
|
|
Console->Header.Console = Console;
|
|
Console->Mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT;
|
|
InitializeListHead(&Console->BufferList);
|
|
Console->ActiveBuffer = NULL;
|
|
InitializeListHead(&Console->InputEvents);
|
|
InitializeListHead(&Console->HistoryBuffers);
|
|
Console->CodePage = GetOEMCP();
|
|
Console->OutputCodePage = GetOEMCP();
|
|
|
|
SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
|
|
SecurityAttributes.lpSecurityDescriptor = NULL;
|
|
SecurityAttributes.bInheritHandle = TRUE;
|
|
|
|
Console->ActiveEvent = CreateEventW(&SecurityAttributes, TRUE, FALSE, NULL);
|
|
if (NULL == Console->ActiveEvent)
|
|
{
|
|
RtlFreeUnicodeString(&Console->Title);
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
Console->PrivateData = NULL;
|
|
InitializeCriticalSection(&Console->Lock);
|
|
|
|
GuiMode = DtbgIsDesktopVisible();
|
|
|
|
/* allocate console screen buffer */
|
|
NewBuffer = HeapAlloc(Win32CsrApiHeap, HEAP_ZERO_MEMORY, sizeof(CSRSS_SCREEN_BUFFER));
|
|
if (NULL == NewBuffer)
|
|
{
|
|
RtlFreeUnicodeString(&Console->Title);
|
|
DeleteCriticalSection(&Console->Lock);
|
|
CloseHandle(Console->ActiveEvent);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
/* init screen buffer with defaults */
|
|
NewBuffer->CursorInfo.bVisible = TRUE;
|
|
NewBuffer->CursorInfo.dwSize = CSR_DEFAULT_CURSOR_SIZE;
|
|
/* make console active, and insert into console list */
|
|
Console->ActiveBuffer = (PCSRSS_SCREEN_BUFFER) NewBuffer;
|
|
|
|
if (! GuiMode)
|
|
{
|
|
Status = TuiInitConsole(Console);
|
|
if (! NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Failed to open text-mode console, switching to gui-mode\n");
|
|
GuiMode = TRUE;
|
|
}
|
|
}
|
|
if (GuiMode)
|
|
{
|
|
Status = GuiInitConsole(Console, Visible);
|
|
if (! NT_SUCCESS(Status))
|
|
{
|
|
HeapFree(Win32CsrApiHeap,0, NewBuffer);
|
|
RtlFreeUnicodeString(&Console->Title);
|
|
DeleteCriticalSection(&Console->Lock);
|
|
CloseHandle(Console->ActiveEvent);
|
|
DPRINT1("GuiInitConsole: failed\n");
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
Status = CsrInitConsoleScreenBuffer(Console, NewBuffer);
|
|
if (! NT_SUCCESS(Status))
|
|
{
|
|
ConioCleanupConsole(Console);
|
|
RtlFreeUnicodeString(&Console->Title);
|
|
DeleteCriticalSection(&Console->Lock);
|
|
CloseHandle(Console->ActiveEvent);
|
|
HeapFree(Win32CsrApiHeap, 0, NewBuffer);
|
|
DPRINT1("CsrInitConsoleScreenBuffer: failed\n");
|
|
return Status;
|
|
}
|
|
|
|
/* copy buffer contents to screen */
|
|
ConioDrawConsole(Console);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
CSR_API(CsrAllocConsole)
|
|
{
|
|
PCSRSS_CONSOLE Console;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
BOOLEAN NewConsole = FALSE;
|
|
|
|
DPRINT("CsrAllocConsole\n");
|
|
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
|
|
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
|
|
if (ProcessData->Console)
|
|
{
|
|
DPRINT1("Process already has a console\n");
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
/* If we don't need a console, then get out of here */
|
|
if (!Request->Data.AllocConsoleRequest.ConsoleNeeded)
|
|
{
|
|
DPRINT("No console needed\n");
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/* If we already have one, then don't create a new one... */
|
|
if (!Request->Data.AllocConsoleRequest.Console ||
|
|
Request->Data.AllocConsoleRequest.Console != ProcessData->ParentConsole)
|
|
{
|
|
/* Allocate a console structure */
|
|
NewConsole = TRUE;
|
|
Console = HeapAlloc(Win32CsrApiHeap, HEAP_ZERO_MEMORY, sizeof(CSRSS_CONSOLE));
|
|
if (NULL == Console)
|
|
{
|
|
DPRINT1("Not enough memory for console\n");
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
/* initialize list head */
|
|
InitializeListHead(&Console->ProcessList);
|
|
/* insert process data required for GUI initialization */
|
|
InsertHeadList(&Console->ProcessList, &ProcessData->ProcessEntry);
|
|
/* Initialize the Console */
|
|
Status = CsrInitConsole(Console, Request->Data.AllocConsoleRequest.Visible);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Console init failed\n");
|
|
HeapFree(Win32CsrApiHeap, 0, Console);
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
|
return Status;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Reuse our current console */
|
|
Console = Request->Data.AllocConsoleRequest.Console;
|
|
}
|
|
|
|
/* Set the Process Console */
|
|
ProcessData->Console = Console;
|
|
|
|
/* Return it to the caller */
|
|
Request->Data.AllocConsoleRequest.Console = Console;
|
|
|
|
/* Add a reference count because the process is tied to the console */
|
|
_InterlockedIncrement(&Console->ReferenceCount);
|
|
|
|
if (NewConsole || !ProcessData->bInheritHandles)
|
|
{
|
|
/* Insert the Objects */
|
|
Status = Win32CsrInsertObject(ProcessData,
|
|
&Request->Data.AllocConsoleRequest.InputHandle,
|
|
&Console->Header,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
TRUE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE);
|
|
if (! NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Failed to insert object\n");
|
|
ConioDeleteConsole((Object_t *) Console);
|
|
ProcessData->Console = 0;
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
|
return Status;
|
|
}
|
|
|
|
Status = Win32CsrInsertObject(ProcessData,
|
|
&Request->Data.AllocConsoleRequest.OutputHandle,
|
|
&Console->ActiveBuffer->Header,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
TRUE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Failed to insert object\n");
|
|
ConioDeleteConsole((Object_t *) Console);
|
|
Win32CsrReleaseObject(ProcessData,
|
|
Request->Data.AllocConsoleRequest.InputHandle);
|
|
ProcessData->Console = 0;
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
/* Duplicate the Event */
|
|
if (!DuplicateHandle(GetCurrentProcess(),
|
|
ProcessData->Console->ActiveEvent,
|
|
ProcessData->Process,
|
|
&ProcessData->ConsoleEvent,
|
|
EVENT_ALL_ACCESS,
|
|
FALSE,
|
|
0))
|
|
{
|
|
DPRINT1("DuplicateHandle() failed: %d\n", GetLastError);
|
|
ConioDeleteConsole((Object_t *) Console);
|
|
if (NewConsole || !ProcessData->bInheritHandles)
|
|
{
|
|
Win32CsrReleaseObject(ProcessData,
|
|
Request->Data.AllocConsoleRequest.OutputHandle);
|
|
Win32CsrReleaseObject(ProcessData,
|
|
Request->Data.AllocConsoleRequest.InputHandle);
|
|
}
|
|
ProcessData->Console = 0;
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
|
return Status;
|
|
}
|
|
|
|
/* Set the Ctrl Dispatcher */
|
|
ProcessData->CtrlDispatcher = Request->Data.AllocConsoleRequest.CtrlDispatcher;
|
|
DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData->CtrlDispatcher);
|
|
|
|
if (!NewConsole)
|
|
{
|
|
/* Insert into the list if it has not been added */
|
|
InsertHeadList(&ProcessData->Console->ProcessList, &ProcessData->ProcessEntry);
|
|
}
|
|
|
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
CSR_API(CsrFreeConsole)
|
|
{
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
|
|
return Win32CsrReleaseConsole(ProcessData);
|
|
}
|
|
|
|
VOID WINAPI
|
|
ConioDeleteConsole(Object_t *Object)
|
|
{
|
|
PCSRSS_CONSOLE Console = (PCSRSS_CONSOLE) Object;
|
|
ConsoleInput *Event;
|
|
|
|
DPRINT("ConioDeleteConsole\n");
|
|
|
|
/* Drain input event queue */
|
|
while (Console->InputEvents.Flink != &Console->InputEvents)
|
|
{
|
|
Event = (ConsoleInput *) Console->InputEvents.Flink;
|
|
Console->InputEvents.Flink = Console->InputEvents.Flink->Flink;
|
|
Console->InputEvents.Flink->Flink->Blink = &Console->InputEvents;
|
|
HeapFree(Win32CsrApiHeap, 0, Event);
|
|
}
|
|
|
|
ConioCleanupConsole(Console);
|
|
if (Console->LineBuffer)
|
|
RtlFreeHeap(Win32CsrApiHeap, 0, Console->LineBuffer);
|
|
while (!IsListEmpty(&Console->HistoryBuffers))
|
|
HistoryDeleteBuffer((struct tagHISTORY_BUFFER *)Console->HistoryBuffers.Flink);
|
|
|
|
ConioDeleteScreenBuffer(Console->ActiveBuffer);
|
|
if (!IsListEmpty(&Console->BufferList))
|
|
{
|
|
DPRINT1("BUG: screen buffer list not empty\n");
|
|
}
|
|
|
|
CloseHandle(Console->ActiveEvent);
|
|
if (Console->UnpauseEvent) CloseHandle(Console->UnpauseEvent);
|
|
DeleteCriticalSection(&Console->Lock);
|
|
RtlFreeUnicodeString(&Console->Title);
|
|
IntDeleteAllAliases(Console->Aliases);
|
|
HeapFree(Win32CsrApiHeap, 0, Console);
|
|
}
|
|
|
|
VOID WINAPI
|
|
CsrInitConsoleSupport(VOID)
|
|
{
|
|
DPRINT("CSR: CsrInitConsoleSupport()\n");
|
|
|
|
/* Should call LoadKeyboardLayout */
|
|
}
|
|
|
|
VOID FASTCALL
|
|
ConioPause(PCSRSS_CONSOLE Console, UINT Flags)
|
|
{
|
|
Console->PauseFlags |= Flags;
|
|
if (!Console->UnpauseEvent)
|
|
Console->UnpauseEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
}
|
|
|
|
VOID FASTCALL
|
|
ConioUnpause(PCSRSS_CONSOLE Console, UINT Flags)
|
|
{
|
|
Console->PauseFlags &= ~Flags;
|
|
if (Console->PauseFlags == 0 && Console->UnpauseEvent)
|
|
{
|
|
SetEvent(Console->UnpauseEvent);
|
|
CloseHandle(Console->UnpauseEvent);
|
|
Console->UnpauseEvent = NULL;
|
|
}
|
|
}
|
|
|
|
CSR_API(CsrSetConsoleMode)
|
|
{
|
|
NTSTATUS Status;
|
|
PCSRSS_CONSOLE Console;
|
|
PCSRSS_SCREEN_BUFFER Buff;
|
|
|
|
DPRINT("CsrSetConsoleMode\n");
|
|
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
Status = Win32CsrLockObject(ProcessData,
|
|
Request->Data.SetConsoleModeRequest.ConsoleHandle,
|
|
(Object_t **) &Console, GENERIC_WRITE, 0);
|
|
if (! NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
Buff = (PCSRSS_SCREEN_BUFFER)Console;
|
|
if (CONIO_CONSOLE_MAGIC == Console->Header.Type)
|
|
{
|
|
Console->Mode = Request->Data.SetConsoleModeRequest.Mode & CONSOLE_INPUT_MODE_VALID;
|
|
}
|
|
else if (CONIO_SCREEN_BUFFER_MAGIC == Console->Header.Type)
|
|
{
|
|
Buff->Mode = Request->Data.SetConsoleModeRequest.Mode & CONSOLE_OUTPUT_MODE_VALID;
|
|
}
|
|
else
|
|
{
|
|
Status = STATUS_INVALID_HANDLE;
|
|
}
|
|
|
|
Win32CsrUnlockObject((Object_t *)Console);
|
|
|
|
return Status;
|
|
}
|
|
|
|
CSR_API(CsrGetConsoleMode)
|
|
{
|
|
NTSTATUS Status;
|
|
PCSRSS_CONSOLE Console;
|
|
PCSRSS_SCREEN_BUFFER Buff; /* gee, I really wish I could use an anonymous union here */
|
|
|
|
DPRINT("CsrGetConsoleMode\n");
|
|
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
Status = Win32CsrLockObject(ProcessData, Request->Data.GetConsoleModeRequest.ConsoleHandle,
|
|
(Object_t **) &Console, GENERIC_READ, 0);
|
|
if (! NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
Status = STATUS_SUCCESS;
|
|
Buff = (PCSRSS_SCREEN_BUFFER) Console;
|
|
if (CONIO_CONSOLE_MAGIC == Console->Header.Type)
|
|
{
|
|
Request->Data.GetConsoleModeRequest.ConsoleMode = Console->Mode;
|
|
}
|
|
else if (CONIO_SCREEN_BUFFER_MAGIC == Buff->Header.Type)
|
|
{
|
|
Request->Data.GetConsoleModeRequest.ConsoleMode = Buff->Mode;
|
|
}
|
|
else
|
|
{
|
|
Status = STATUS_INVALID_HANDLE;
|
|
}
|
|
|
|
Win32CsrUnlockObject((Object_t *)Console);
|
|
return Status;
|
|
}
|
|
|
|
CSR_API(CsrSetTitle)
|
|
{
|
|
NTSTATUS Status;
|
|
PCSRSS_CONSOLE Console;
|
|
PWCHAR Buffer;
|
|
|
|
DPRINT("CsrSetTitle\n");
|
|
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
if (!Win32CsrValidateBuffer(ProcessData, Request->Data.SetTitleRequest.Title,
|
|
Request->Data.SetTitleRequest.Length, 1))
|
|
{
|
|
return STATUS_ACCESS_VIOLATION;
|
|
}
|
|
|
|
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
|
if(NT_SUCCESS(Status))
|
|
{
|
|
Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Request->Data.SetTitleRequest.Length);
|
|
if (Buffer)
|
|
{
|
|
/* copy title to console */
|
|
RtlFreeUnicodeString(&Console->Title);
|
|
Console->Title.Buffer = Buffer;
|
|
Console->Title.Length = Console->Title.MaximumLength = Request->Data.SetTitleRequest.Length;
|
|
memcpy(Console->Title.Buffer, Request->Data.SetTitleRequest.Title, Console->Title.Length);
|
|
if (! ConioChangeTitle(Console))
|
|
{
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
else
|
|
{
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Status = STATUS_NO_MEMORY;
|
|
}
|
|
ConioUnlockConsole(Console);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
CSR_API(CsrGetTitle)
|
|
{
|
|
NTSTATUS Status;
|
|
PCSRSS_CONSOLE Console;
|
|
DWORD Length;
|
|
|
|
DPRINT("CsrGetTitle\n");
|
|
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
|
|
if (!Win32CsrValidateBuffer(ProcessData, Request->Data.GetTitleRequest.Title,
|
|
Request->Data.GetTitleRequest.Length, 1))
|
|
{
|
|
return STATUS_ACCESS_VIOLATION;
|
|
}
|
|
|
|
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
|
if (! NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Can't get console\n");
|
|
return Status;
|
|
}
|
|
|
|
/* Copy title of the console to the user title buffer */
|
|
if (Request->Data.GetTitleRequest.Length >= sizeof(WCHAR))
|
|
{
|
|
Length = min(Request->Data.GetTitleRequest.Length - sizeof(WCHAR), Console->Title.Length);
|
|
memcpy(Request->Data.GetTitleRequest.Title, Console->Title.Buffer, Length);
|
|
Request->Data.GetTitleRequest.Title[Length / sizeof(WCHAR)] = L'\0';
|
|
}
|
|
|
|
Request->Data.GetTitleRequest.Length = Console->Title.Length;
|
|
|
|
ConioUnlockConsole(Console);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/**********************************************************************
|
|
* HardwareStateProperty
|
|
*
|
|
* DESCRIPTION
|
|
* Set/Get the value of the HardwareState and switch
|
|
* between direct video buffer ouput and GDI windowed
|
|
* output.
|
|
* ARGUMENTS
|
|
* Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
|
|
* object. We use the same object to Request.
|
|
* NOTE
|
|
* ConsoleHwState has the correct size to be compatible
|
|
* with NT's, but values are not.
|
|
*/
|
|
static NTSTATUS FASTCALL
|
|
SetConsoleHardwareState (PCSRSS_CONSOLE Console, DWORD ConsoleHwState)
|
|
{
|
|
DPRINT1("Console Hardware State: %d\n", ConsoleHwState);
|
|
|
|
if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED == ConsoleHwState)
|
|
||(CONSOLE_HARDWARE_STATE_DIRECT == ConsoleHwState))
|
|
{
|
|
if (Console->HardwareState != ConsoleHwState)
|
|
{
|
|
/* TODO: implement switching from full screen to windowed mode */
|
|
/* TODO: or back; now simply store the hardware state */
|
|
Console->HardwareState = ConsoleHwState;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
return STATUS_INVALID_PARAMETER_3; /* Client: (handle, set_get, [mode]) */
|
|
}
|
|
|
|
CSR_API(CsrHardwareStateProperty)
|
|
{
|
|
PCSRSS_CONSOLE Console;
|
|
NTSTATUS Status;
|
|
|
|
DPRINT("CsrHardwareStateProperty\n");
|
|
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
|
|
Status = ConioLockConsole(ProcessData,
|
|
Request->Data.ConsoleHardwareStateRequest.ConsoleHandle,
|
|
&Console,
|
|
GENERIC_READ);
|
|
if (! NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
|
|
return Status;
|
|
}
|
|
|
|
switch (Request->Data.ConsoleHardwareStateRequest.SetGet)
|
|
{
|
|
case CONSOLE_HARDWARE_STATE_GET:
|
|
Request->Data.ConsoleHardwareStateRequest.State = Console->HardwareState;
|
|
break;
|
|
|
|
case CONSOLE_HARDWARE_STATE_SET:
|
|
DPRINT("Setting console hardware state.\n");
|
|
Status = SetConsoleHardwareState(Console, Request->Data.ConsoleHardwareStateRequest.State);
|
|
break;
|
|
|
|
default:
|
|
Status = STATUS_INVALID_PARAMETER_2; /* Client: (handle, [set_get], mode) */
|
|
break;
|
|
}
|
|
|
|
ConioUnlockConsole(Console);
|
|
|
|
return Status;
|
|
}
|
|
|
|
CSR_API(CsrGetConsoleWindow)
|
|
{
|
|
PCSRSS_CONSOLE Console;
|
|
NTSTATUS Status;
|
|
|
|
DPRINT("CsrGetConsoleWindow\n");
|
|
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
|
|
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
|
if (! NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
Request->Data.GetConsoleWindowRequest.WindowHandle = Console->hWindow;
|
|
ConioUnlockConsole(Console);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
CSR_API(CsrSetConsoleIcon)
|
|
{
|
|
PCSRSS_CONSOLE Console;
|
|
NTSTATUS Status;
|
|
|
|
DPRINT("CsrSetConsoleIcon\n");
|
|
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
|
|
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
|
if (! NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
Status = (ConioChangeIcon(Console, Request->Data.SetConsoleIconRequest.WindowIcon)
|
|
? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
|
|
ConioUnlockConsole(Console);
|
|
|
|
return Status;
|
|
}
|
|
|
|
CSR_API(CsrGetConsoleCodePage)
|
|
{
|
|
PCSRSS_CONSOLE Console;
|
|
NTSTATUS Status;
|
|
|
|
DPRINT("CsrGetConsoleCodePage\n");
|
|
|
|
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
|
if (! NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
Request->Data.GetConsoleCodePage.CodePage = Console->CodePage;
|
|
ConioUnlockConsole(Console);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
CSR_API(CsrSetConsoleCodePage)
|
|
{
|
|
PCSRSS_CONSOLE Console;
|
|
NTSTATUS Status;
|
|
|
|
DPRINT("CsrSetConsoleCodePage\n");
|
|
|
|
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
|
if (! NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
|
|
if (IsValidCodePage(Request->Data.SetConsoleCodePage.CodePage))
|
|
{
|
|
Console->CodePage = Request->Data.SetConsoleCodePage.CodePage;
|
|
ConioUnlockConsole(Console);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
ConioUnlockConsole(Console);
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
CSR_API(CsrGetConsoleOutputCodePage)
|
|
{
|
|
PCSRSS_CONSOLE Console;
|
|
NTSTATUS Status;
|
|
|
|
DPRINT("CsrGetConsoleOutputCodePage\n");
|
|
|
|
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
|
if (! NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
Request->Data.GetConsoleOutputCodePage.CodePage = Console->OutputCodePage;
|
|
ConioUnlockConsole(Console);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
CSR_API(CsrSetConsoleOutputCodePage)
|
|
{
|
|
PCSRSS_CONSOLE Console;
|
|
NTSTATUS Status;
|
|
|
|
DPRINT("CsrSetConsoleOutputCodePage\n");
|
|
|
|
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
|
if (! NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
|
|
if (IsValidCodePage(Request->Data.SetConsoleOutputCodePage.CodePage))
|
|
{
|
|
Console->OutputCodePage = Request->Data.SetConsoleOutputCodePage.CodePage;
|
|
ConioUnlockConsole(Console);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
ConioUnlockConsole(Console);
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
CSR_API(CsrGetProcessList)
|
|
{
|
|
PDWORD Buffer;
|
|
PCSRSS_CONSOLE Console;
|
|
PCSRSS_PROCESS_DATA current;
|
|
PLIST_ENTRY current_entry;
|
|
ULONG nItems = 0;
|
|
NTSTATUS Status;
|
|
|
|
DPRINT("CsrGetProcessList\n");
|
|
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
|
|
Buffer = Request->Data.GetProcessListRequest.ProcessId;
|
|
if (!Win32CsrValidateBuffer(ProcessData, Buffer, Request->Data.GetProcessListRequest.nMaxIds, sizeof(DWORD)))
|
|
return STATUS_ACCESS_VIOLATION;
|
|
|
|
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
|
if (! NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
for (current_entry = Console->ProcessList.Flink;
|
|
current_entry != &Console->ProcessList;
|
|
current_entry = current_entry->Flink)
|
|
{
|
|
current = CONTAINING_RECORD(current_entry, CSRSS_PROCESS_DATA, ProcessEntry);
|
|
if (++nItems <= Request->Data.GetProcessListRequest.nMaxIds)
|
|
{
|
|
*Buffer++ = HandleToUlong(current->ProcessId);
|
|
}
|
|
}
|
|
|
|
ConioUnlockConsole(Console);
|
|
|
|
Request->Data.GetProcessListRequest.nProcessIdsTotal = nItems;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
CSR_API(CsrGenerateCtrlEvent)
|
|
{
|
|
PCSRSS_CONSOLE Console;
|
|
PCSRSS_PROCESS_DATA current;
|
|
PLIST_ENTRY current_entry;
|
|
DWORD Group;
|
|
NTSTATUS Status;
|
|
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
|
|
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
|
if (! NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
Group = Request->Data.GenerateCtrlEvent.ProcessGroup;
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
for (current_entry = Console->ProcessList.Flink;
|
|
current_entry != &Console->ProcessList;
|
|
current_entry = current_entry->Flink)
|
|
{
|
|
current = CONTAINING_RECORD(current_entry, CSRSS_PROCESS_DATA, ProcessEntry);
|
|
if (Group == 0 || current->ProcessGroup == Group)
|
|
{
|
|
ConioConsoleCtrlEvent(Request->Data.GenerateCtrlEvent.Event, current);
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
}
|
|
|
|
ConioUnlockConsole(Console);
|
|
|
|
return Status;
|
|
}
|
|
|
|
CSR_API(CsrGetConsoleSelectionInfo)
|
|
{
|
|
NTSTATUS Status;
|
|
PCSRSS_CONSOLE Console;
|
|
|
|
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
|
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
|
|
|
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
memset(&Request->Data.GetConsoleSelectionInfo.Info, 0, sizeof(CONSOLE_SELECTION_INFO));
|
|
if (Console->Selection.dwFlags != 0)
|
|
Request->Data.GetConsoleSelectionInfo.Info = Console->Selection;
|
|
ConioUnlockConsole(Console);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
/* EOF */
|