mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 20:15:59 +00:00
[WIN32CSR] Split up excessively large and disorganized conio.c into 3 separate files: one for input-related functions, one for output-related functions, and one for general/miscellaneous functions.
svn path=/trunk/; revision=47485
This commit is contained in:
parent
d3d2badfac
commit
46e34b5640
6 changed files with 3228 additions and 3194 deletions
805
reactos/subsystems/win32/csrss/win32csr/coninput.c
Normal file
805
reactos/subsystems/win32/csrss/win32csr/coninput.c
Normal file
|
@ -0,0 +1,805 @@
|
|||
/*
|
||||
* reactos/subsys/csrss/win32csr/conio.c
|
||||
*
|
||||
* Console I/O functions
|
||||
*
|
||||
* ReactOS Operating System
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#define NDEBUG
|
||||
#include "w32csr.h"
|
||||
#include <debug.h>
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
#define ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar) \
|
||||
WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
|
||||
|
||||
#define ConsoleInputAnsiCharToUnicodeChar(Console, dWChar, sChar) \
|
||||
MultiByteToWideChar((Console)->CodePage, 0, (sChar), 1, (dWChar), 1)
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
CSR_API(CsrReadConsole)
|
||||
{
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
ConsoleInput *Input;
|
||||
PUCHAR Buffer;
|
||||
PWCHAR UnicodeBuffer;
|
||||
ULONG i;
|
||||
ULONG nNumberOfCharsToRead, CharSize;
|
||||
PCSRSS_CONSOLE Console;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("CsrReadConsole\n");
|
||||
|
||||
CharSize = (Request->Data.ReadConsoleRequest.Unicode ? sizeof(WCHAR) : sizeof(CHAR));
|
||||
|
||||
/* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */
|
||||
nNumberOfCharsToRead = min(Request->Data.ReadConsoleRequest.NrCharactersToRead, CSRSS_MAX_READ_CONSOLE / CharSize);
|
||||
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
||||
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
||||
|
||||
Buffer = Request->Data.ReadConsoleRequest.Buffer;
|
||||
UnicodeBuffer = (PWCHAR)Buffer;
|
||||
Status = ConioLockConsole(ProcessData, Request->Data.ReadConsoleRequest.ConsoleHandle,
|
||||
&Console, GENERIC_READ);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
Request->Data.ReadConsoleRequest.EventHandle = ProcessData->ConsoleEvent;
|
||||
for (i = 0; i < nNumberOfCharsToRead && Console->InputEvents.Flink != &Console->InputEvents; i++)
|
||||
{
|
||||
/* remove input event from queue */
|
||||
CurrentEntry = RemoveHeadList(&Console->InputEvents);
|
||||
if (IsListEmpty(&Console->InputEvents))
|
||||
{
|
||||
ResetEvent(Console->ActiveEvent);
|
||||
}
|
||||
Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
|
||||
|
||||
/* only pay attention to valid ascii chars, on key down */
|
||||
if (KEY_EVENT == Input->InputEvent.EventType
|
||||
&& Input->InputEvent.Event.KeyEvent.bKeyDown
|
||||
&& Input->InputEvent.Event.KeyEvent.uChar.AsciiChar != '\0')
|
||||
{
|
||||
/*
|
||||
* backspace handling - if we are in charge of echoing it then we handle it here
|
||||
* otherwise we treat it like a normal char.
|
||||
*/
|
||||
if ('\b' == Input->InputEvent.Event.KeyEvent.uChar.AsciiChar && 0
|
||||
!= (Console->Mode & ENABLE_ECHO_INPUT))
|
||||
{
|
||||
/* echo if it has not already been done, and either we or the client has chars to be deleted */
|
||||
if (! Input->Echoed
|
||||
&& (0 != i || Request->Data.ReadConsoleRequest.nCharsCanBeDeleted))
|
||||
{
|
||||
ConioWriteConsole(Console, Console->ActiveBuffer,
|
||||
&Input->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE);
|
||||
}
|
||||
if (0 != i)
|
||||
{
|
||||
i -= 2; /* if we already have something to return, just back it up by 2 */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer */
|
||||
Console->WaitingChars--;
|
||||
ConioUnlockConsole(Console);
|
||||
HeapFree(Win32CsrApiHeap, 0, Input);
|
||||
Request->Data.ReadConsoleRequest.NrCharactersRead = 0;
|
||||
return STATUS_NOTIFY_CLEANUP;
|
||||
|
||||
}
|
||||
Request->Data.ReadConsoleRequest.nCharsCanBeDeleted--;
|
||||
Input->Echoed = TRUE; /* mark as echoed so we don't echo it below */
|
||||
}
|
||||
/* do not copy backspace to buffer */
|
||||
else
|
||||
{
|
||||
if(Request->Data.ReadConsoleRequest.Unicode)
|
||||
ConsoleInputAnsiCharToUnicodeChar(Console, &UnicodeBuffer[i], &Input->InputEvent.Event.KeyEvent.uChar.AsciiChar);
|
||||
else
|
||||
Buffer[i] = Input->InputEvent.Event.KeyEvent.uChar.AsciiChar;
|
||||
}
|
||||
/* echo to screen if enabled and we did not already echo the char */
|
||||
if (0 != (Console->Mode & ENABLE_ECHO_INPUT)
|
||||
&& ! Input->Echoed
|
||||
&& '\r' != Input->InputEvent.Event.KeyEvent.uChar.AsciiChar)
|
||||
{
|
||||
ConioWriteConsole(Console, Console->ActiveBuffer,
|
||||
&Input->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
i--;
|
||||
}
|
||||
Console->WaitingChars--;
|
||||
HeapFree(Win32CsrApiHeap, 0, Input);
|
||||
}
|
||||
Request->Data.ReadConsoleRequest.NrCharactersRead = i;
|
||||
if (0 == i)
|
||||
{
|
||||
Status = STATUS_PENDING; /* we didn't read anything */
|
||||
}
|
||||
else if (0 != (Console->Mode & ENABLE_LINE_INPUT))
|
||||
{
|
||||
if (0 == Console->WaitingLines ||
|
||||
(Request->Data.ReadConsoleRequest.Unicode ? (L'\n' != UnicodeBuffer[i - 1]) : ('\n' != Buffer[i - 1])))
|
||||
{
|
||||
Status = STATUS_PENDING; /* line buffered, didn't get a complete line */
|
||||
}
|
||||
else
|
||||
{
|
||||
Console->WaitingLines--;
|
||||
Status = STATUS_SUCCESS; /* line buffered, did get a complete line */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = STATUS_SUCCESS; /* not line buffered, did read something */
|
||||
}
|
||||
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
Console->EchoCount = nNumberOfCharsToRead - i;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console->EchoCount = 0; /* if the client is no longer waiting on input, do not echo */
|
||||
}
|
||||
|
||||
ConioUnlockConsole(Console);
|
||||
|
||||
if (CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE) + i * CharSize > sizeof(CSR_API_MESSAGE))
|
||||
{
|
||||
Request->Header.u1.s1.TotalLength = CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE) + i * CharSize;
|
||||
Request->Header.u1.s1.DataLength = Request->Header.u1.s1.TotalLength - sizeof(PORT_MESSAGE);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
static VOID FASTCALL
|
||||
ConioInputEventToAnsi(PCSRSS_CONSOLE Console, PINPUT_RECORD InputEvent)
|
||||
{
|
||||
if (InputEvent->EventType == KEY_EVENT)
|
||||
{
|
||||
WCHAR UnicodeChar = InputEvent->Event.KeyEvent.uChar.UnicodeChar;
|
||||
InputEvent->Event.KeyEvent.uChar.UnicodeChar = 0;
|
||||
ConsoleInputUnicodeCharToAnsiChar(Console,
|
||||
&InputEvent->Event.KeyEvent.uChar.AsciiChar,
|
||||
&UnicodeChar);
|
||||
}
|
||||
}
|
||||
|
||||
static VOID FASTCALL
|
||||
ConioProcessChar(PCSRSS_CONSOLE Console,
|
||||
ConsoleInput *KeyEventRecord)
|
||||
{
|
||||
BOOL updown;
|
||||
ConsoleInput *TempInput;
|
||||
|
||||
if (KeyEventRecord->InputEvent.EventType == KEY_EVENT &&
|
||||
KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown)
|
||||
{
|
||||
WORD vk = KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode;
|
||||
if (!(Console->PauseFlags & PAUSED_FROM_KEYBOARD))
|
||||
{
|
||||
DWORD cks = KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState;
|
||||
if (Console->Mode & ENABLE_LINE_INPUT &&
|
||||
(vk == VK_PAUSE || (vk == 'S' &&
|
||||
(cks & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) &&
|
||||
!(cks & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)))))
|
||||
{
|
||||
ConioPause(Console, PAUSED_FROM_KEYBOARD);
|
||||
HeapFree(Win32CsrApiHeap, 0, KeyEventRecord);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((vk < VK_SHIFT || vk > VK_CAPITAL) && vk != VK_LWIN &&
|
||||
vk != VK_RWIN && vk != VK_NUMLOCK && vk != VK_SCROLL)
|
||||
{
|
||||
ConioUnpause(Console, PAUSED_FROM_KEYBOARD);
|
||||
HeapFree(Win32CsrApiHeap, 0, KeyEventRecord);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != (Console->Mode & (ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT)))
|
||||
{
|
||||
switch(KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar)
|
||||
{
|
||||
case '\r':
|
||||
/* first add the \r */
|
||||
KeyEventRecord->InputEvent.EventType = KEY_EVENT;
|
||||
updown = KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown;
|
||||
KeyEventRecord->Echoed = FALSE;
|
||||
KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
|
||||
KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar = '\r';
|
||||
InsertTailList(&Console->InputEvents, &KeyEventRecord->ListEntry);
|
||||
Console->WaitingChars++;
|
||||
KeyEventRecord = HeapAlloc(Win32CsrApiHeap, 0, sizeof(ConsoleInput));
|
||||
if (NULL == KeyEventRecord)
|
||||
{
|
||||
DPRINT1("Failed to allocate KeyEventRecord\n");
|
||||
return;
|
||||
}
|
||||
KeyEventRecord->InputEvent.EventType = KEY_EVENT;
|
||||
KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown = updown;
|
||||
KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode = 0;
|
||||
KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualScanCode = 0;
|
||||
KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar = '\n';
|
||||
KeyEventRecord->Fake = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* add event to the queue */
|
||||
InsertTailList(&Console->InputEvents, &KeyEventRecord->ListEntry);
|
||||
Console->WaitingChars++;
|
||||
/* if line input mode is enabled, only wake the client on enter key down */
|
||||
if (0 == (Console->Mode & ENABLE_LINE_INPUT)
|
||||
|| Console->EarlyReturn
|
||||
|| ('\n' == KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar
|
||||
&& KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown))
|
||||
{
|
||||
if ('\n' == KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar)
|
||||
{
|
||||
Console->WaitingLines++;
|
||||
}
|
||||
}
|
||||
KeyEventRecord->Echoed = FALSE;
|
||||
if (0 != (Console->Mode & (ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT))
|
||||
&& '\b' == KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar
|
||||
&& KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown)
|
||||
{
|
||||
/* walk the input queue looking for a char to backspace */
|
||||
for (TempInput = (ConsoleInput *) Console->InputEvents.Blink;
|
||||
TempInput != (ConsoleInput *) &Console->InputEvents
|
||||
&& (KEY_EVENT == TempInput->InputEvent.EventType
|
||||
|| ! TempInput->InputEvent.Event.KeyEvent.bKeyDown
|
||||
|| '\b' == TempInput->InputEvent.Event.KeyEvent.uChar.AsciiChar);
|
||||
TempInput = (ConsoleInput *) TempInput->ListEntry.Blink)
|
||||
{
|
||||
/* NOP */;
|
||||
}
|
||||
/* if we found one, delete it, otherwise, wake the client */
|
||||
if (TempInput != (ConsoleInput *) &Console->InputEvents)
|
||||
{
|
||||
/* delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue */
|
||||
RemoveEntryList(&TempInput->ListEntry);
|
||||
if (TempInput->Echoed)
|
||||
{
|
||||
ConioWriteConsole(Console, Console->ActiveBuffer,
|
||||
&KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar,
|
||||
1, TRUE);
|
||||
}
|
||||
HeapFree(Win32CsrApiHeap, 0, TempInput);
|
||||
RemoveEntryList(&KeyEventRecord->ListEntry);
|
||||
HeapFree(Win32CsrApiHeap, 0, KeyEventRecord);
|
||||
Console->WaitingChars -= 2;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* echo chars if we are supposed to and client is waiting for some */
|
||||
if (0 != (Console->Mode & ENABLE_ECHO_INPUT) && Console->EchoCount
|
||||
&& KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar
|
||||
&& KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown
|
||||
&& '\r' != KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar)
|
||||
{
|
||||
/* mark the char as already echoed */
|
||||
ConioWriteConsole(Console, Console->ActiveBuffer,
|
||||
&KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar,
|
||||
1, TRUE);
|
||||
Console->EchoCount--;
|
||||
KeyEventRecord->Echoed = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Console->WaitingChars++; */
|
||||
SetEvent(Console->ActiveEvent);
|
||||
}
|
||||
|
||||
static DWORD FASTCALL
|
||||
ConioGetShiftState(PBYTE KeyState)
|
||||
{
|
||||
DWORD ssOut = 0;
|
||||
|
||||
if (KeyState[VK_CAPITAL] & 1)
|
||||
ssOut |= CAPSLOCK_ON;
|
||||
|
||||
if (KeyState[VK_NUMLOCK] & 1)
|
||||
ssOut |= NUMLOCK_ON;
|
||||
|
||||
if (KeyState[VK_SCROLL] & 1)
|
||||
ssOut |= SCROLLLOCK_ON;
|
||||
|
||||
if (KeyState[VK_SHIFT] & 0x80)
|
||||
ssOut |= SHIFT_PRESSED;
|
||||
|
||||
if (KeyState[VK_LCONTROL] & 0x80)
|
||||
ssOut |= LEFT_CTRL_PRESSED;
|
||||
if (KeyState[VK_RCONTROL] & 0x80)
|
||||
ssOut |= RIGHT_CTRL_PRESSED;
|
||||
|
||||
if (KeyState[VK_LMENU] & 0x80)
|
||||
ssOut |= LEFT_ALT_PRESSED;
|
||||
if (KeyState[VK_RMENU] & 0x80)
|
||||
ssOut |= RIGHT_ALT_PRESSED;
|
||||
|
||||
return ssOut;
|
||||
}
|
||||
|
||||
VOID WINAPI
|
||||
ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode)
|
||||
{
|
||||
static BYTE KeyState[256] = { 0 };
|
||||
/* MSDN mentions that you should use the last virtual key code received
|
||||
* when putting a virtual key identity to a WM_CHAR message since multiple
|
||||
* or translated keys may be involved. */
|
||||
static UINT LastVirtualKey = 0;
|
||||
DWORD ShiftState;
|
||||
ConsoleInput *ConInRec;
|
||||
UINT RepeatCount;
|
||||
CHAR AsciiChar;
|
||||
WCHAR UnicodeChar;
|
||||
UINT VirtualKeyCode;
|
||||
UINT VirtualScanCode;
|
||||
BOOL Down = FALSE;
|
||||
INPUT_RECORD er;
|
||||
ULONG ResultSize = 0;
|
||||
|
||||
RepeatCount = 1;
|
||||
VirtualScanCode = (msg->lParam >> 16) & 0xff;
|
||||
Down = msg->message == WM_KEYDOWN || msg->message == WM_CHAR ||
|
||||
msg->message == WM_SYSKEYDOWN || msg->message == WM_SYSCHAR;
|
||||
|
||||
GetKeyboardState(KeyState);
|
||||
ShiftState = ConioGetShiftState(KeyState);
|
||||
|
||||
if (msg->message == WM_CHAR || msg->message == WM_SYSCHAR)
|
||||
{
|
||||
VirtualKeyCode = LastVirtualKey;
|
||||
UnicodeChar = msg->wParam;
|
||||
}
|
||||
else
|
||||
{
|
||||
WCHAR Chars[2];
|
||||
INT RetChars = 0;
|
||||
|
||||
VirtualKeyCode = msg->wParam;
|
||||
RetChars = ToUnicodeEx(VirtualKeyCode,
|
||||
VirtualScanCode,
|
||||
KeyState,
|
||||
Chars,
|
||||
2,
|
||||
0,
|
||||
0);
|
||||
UnicodeChar = (1 == RetChars ? Chars[0] : 0);
|
||||
}
|
||||
|
||||
if (0 == ResultSize)
|
||||
{
|
||||
AsciiChar = 0;
|
||||
}
|
||||
|
||||
er.EventType = KEY_EVENT;
|
||||
er.Event.KeyEvent.bKeyDown = Down;
|
||||
er.Event.KeyEvent.wRepeatCount = RepeatCount;
|
||||
er.Event.KeyEvent.uChar.UnicodeChar = UnicodeChar;
|
||||
er.Event.KeyEvent.dwControlKeyState = ShiftState;
|
||||
er.Event.KeyEvent.wVirtualKeyCode = VirtualKeyCode;
|
||||
er.Event.KeyEvent.wVirtualScanCode = VirtualScanCode;
|
||||
|
||||
if (TextMode)
|
||||
{
|
||||
if (0 != (ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
|
||||
&& VK_TAB == VirtualKeyCode)
|
||||
{
|
||||
if (Down)
|
||||
{
|
||||
TuiSwapConsole(ShiftState & SHIFT_PRESSED ? -1 : 1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else if (VK_MENU == VirtualKeyCode && ! Down)
|
||||
{
|
||||
if (TuiSwapConsole(0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL == Console)
|
||||
{
|
||||
DPRINT1("No Active Console!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ConInRec = HeapAlloc(Win32CsrApiHeap, 0, sizeof(ConsoleInput));
|
||||
|
||||
if (NULL == ConInRec)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ConInRec->InputEvent = er;
|
||||
ConInRec->Fake = UnicodeChar &&
|
||||
(msg->message != WM_CHAR && msg->message != WM_SYSCHAR &&
|
||||
msg->message != WM_KEYUP && msg->message != WM_SYSKEYUP);
|
||||
ConInRec->NotChar = (msg->message != WM_CHAR && msg->message != WM_SYSCHAR);
|
||||
ConInRec->Echoed = FALSE;
|
||||
if (ConInRec->NotChar)
|
||||
LastVirtualKey = msg->wParam;
|
||||
|
||||
DPRINT ("csrss: %s %s %s %s %02x %02x '%c' %04x\n",
|
||||
Down ? "down" : "up ",
|
||||
(msg->message == WM_CHAR || msg->message == WM_SYSCHAR) ?
|
||||
"char" : "key ",
|
||||
ConInRec->Fake ? "fake" : "real",
|
||||
ConInRec->NotChar ? "notc" : "char",
|
||||
VirtualScanCode,
|
||||
VirtualKeyCode,
|
||||
(AsciiChar >= ' ') ? AsciiChar : '.',
|
||||
ShiftState);
|
||||
|
||||
if (ConInRec->Fake && ConInRec->NotChar)
|
||||
{
|
||||
HeapFree(Win32CsrApiHeap, 0, ConInRec);
|
||||
return;
|
||||
}
|
||||
|
||||
/* process Ctrl-C and Ctrl-Break */
|
||||
if (Console->Mode & ENABLE_PROCESSED_INPUT &&
|
||||
er.Event.KeyEvent.bKeyDown &&
|
||||
((er.Event.KeyEvent.wVirtualKeyCode == VK_PAUSE) ||
|
||||
(er.Event.KeyEvent.wVirtualKeyCode == 'C')) &&
|
||||
(er.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)))
|
||||
{
|
||||
PCSRSS_PROCESS_DATA current;
|
||||
PLIST_ENTRY current_entry;
|
||||
DPRINT1("Console_Api Ctrl-C\n");
|
||||
current_entry = Console->ProcessList.Flink;
|
||||
while (current_entry != &Console->ProcessList)
|
||||
{
|
||||
current = CONTAINING_RECORD(current_entry, CSRSS_PROCESS_DATA, ProcessEntry);
|
||||
current_entry = current_entry->Flink;
|
||||
ConioConsoleCtrlEvent((DWORD)CTRL_C_EVENT, current);
|
||||
}
|
||||
HeapFree(Win32CsrApiHeap, 0, ConInRec);
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 != (er.Event.KeyEvent.dwControlKeyState
|
||||
& (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
|
||||
&& (VK_UP == er.Event.KeyEvent.wVirtualKeyCode
|
||||
|| VK_DOWN == er.Event.KeyEvent.wVirtualKeyCode))
|
||||
{
|
||||
if (er.Event.KeyEvent.bKeyDown)
|
||||
{
|
||||
/* scroll up or down */
|
||||
if (VK_UP == er.Event.KeyEvent.wVirtualKeyCode)
|
||||
{
|
||||
/* only scroll up if there is room to scroll up into */
|
||||
if (Console->ActiveBuffer->CurrentY != Console->ActiveBuffer->MaxY - 1)
|
||||
{
|
||||
Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY +
|
||||
Console->ActiveBuffer->MaxY - 1) %
|
||||
Console->ActiveBuffer->MaxY;
|
||||
Console->ActiveBuffer->CurrentY++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* only scroll down if there is room to scroll down into */
|
||||
if (Console->ActiveBuffer->CurrentY != 0)
|
||||
{
|
||||
Console->ActiveBuffer->VirtualY = (Console->ActiveBuffer->VirtualY + 1) %
|
||||
Console->ActiveBuffer->MaxY;
|
||||
Console->ActiveBuffer->CurrentY--;
|
||||
}
|
||||
}
|
||||
ConioDrawConsole(Console);
|
||||
}
|
||||
HeapFree(Win32CsrApiHeap, 0, ConInRec);
|
||||
return;
|
||||
}
|
||||
/* FIXME - convert to ascii */
|
||||
ConioProcessChar(Console, ConInRec);
|
||||
}
|
||||
|
||||
CSR_API(CsrReadInputEvent)
|
||||
{
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PCSRSS_CONSOLE Console;
|
||||
NTSTATUS Status;
|
||||
BOOLEAN Done = FALSE;
|
||||
ConsoleInput *Input;
|
||||
|
||||
DPRINT("CsrReadInputEvent\n");
|
||||
|
||||
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
||||
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
||||
Request->Data.ReadInputRequest.Event = ProcessData->ConsoleEvent;
|
||||
|
||||
Status = ConioLockConsole(ProcessData, Request->Data.ReadInputRequest.ConsoleHandle, &Console, GENERIC_READ);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* only get input if there is any */
|
||||
CurrentEntry = Console->InputEvents.Flink;
|
||||
while (CurrentEntry != &Console->InputEvents)
|
||||
{
|
||||
Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
|
||||
CurrentEntry = CurrentEntry->Flink;
|
||||
|
||||
if (Done && !Input->Fake)
|
||||
{
|
||||
Request->Data.ReadInputRequest.MoreEvents = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
RemoveEntryList(&Input->ListEntry);
|
||||
|
||||
if (!Done && !Input->Fake)
|
||||
{
|
||||
Request->Data.ReadInputRequest.Input = Input->InputEvent;
|
||||
if (Request->Data.ReadInputRequest.Unicode == FALSE)
|
||||
{
|
||||
ConioInputEventToAnsi(Console, &Request->Data.ReadInputRequest.Input);
|
||||
}
|
||||
Done = TRUE;
|
||||
}
|
||||
|
||||
if (Input->InputEvent.EventType == KEY_EVENT)
|
||||
{
|
||||
if (0 != (Console->Mode & ENABLE_LINE_INPUT)
|
||||
&& Input->InputEvent.Event.KeyEvent.bKeyDown
|
||||
&& '\r' == Input->InputEvent.Event.KeyEvent.uChar.AsciiChar)
|
||||
{
|
||||
Console->WaitingLines--;
|
||||
}
|
||||
Console->WaitingChars--;
|
||||
}
|
||||
HeapFree(Win32CsrApiHeap, 0, Input);
|
||||
}
|
||||
|
||||
if (Done)
|
||||
{
|
||||
Status = STATUS_SUCCESS;
|
||||
Console->EarlyReturn = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = STATUS_PENDING;
|
||||
Console->EarlyReturn = TRUE; /* mark for early return */
|
||||
}
|
||||
|
||||
if (IsListEmpty(&Console->InputEvents))
|
||||
{
|
||||
ResetEvent(Console->ActiveEvent);
|
||||
}
|
||||
|
||||
ConioUnlockConsole(Console);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(CsrFlushInputBuffer)
|
||||
{
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PCSRSS_CONSOLE Console;
|
||||
ConsoleInput* Input;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("CsrFlushInputBuffer\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.FlushInputBufferRequest.ConsoleInput,
|
||||
&Console,
|
||||
GENERIC_WRITE);
|
||||
if(! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Discard all entries in the input event queue */
|
||||
while (!IsListEmpty(&Console->InputEvents))
|
||||
{
|
||||
CurrentEntry = RemoveHeadList(&Console->InputEvents);
|
||||
Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
|
||||
/* Destroy the event */
|
||||
HeapFree(Win32CsrApiHeap, 0, Input);
|
||||
}
|
||||
ResetEvent(Console->ActiveEvent);
|
||||
Console->WaitingChars=0;
|
||||
|
||||
ConioUnlockConsole(Console);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(CsrGetNumberOfConsoleInputEvents)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCSRSS_CONSOLE Console;
|
||||
PLIST_ENTRY CurrentItem;
|
||||
DWORD NumEvents;
|
||||
ConsoleInput *Input;
|
||||
|
||||
DPRINT("CsrGetNumberOfConsoleInputEvents\n");
|
||||
|
||||
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
||||
Request->Header.u1.s1.DataLength = Request->Header.u1.s1.TotalLength - sizeof(PORT_MESSAGE);
|
||||
|
||||
Status = ConioLockConsole(ProcessData, Request->Data.GetNumInputEventsRequest.ConsoleHandle, &Console, GENERIC_READ);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
CurrentItem = Console->InputEvents.Flink;
|
||||
NumEvents = 0;
|
||||
|
||||
/* If there are any events ... */
|
||||
while (CurrentItem != &Console->InputEvents)
|
||||
{
|
||||
Input = CONTAINING_RECORD(CurrentItem, ConsoleInput, ListEntry);
|
||||
CurrentItem = CurrentItem->Flink;
|
||||
if (!Input->Fake)
|
||||
{
|
||||
NumEvents++;
|
||||
}
|
||||
}
|
||||
|
||||
ConioUnlockConsole(Console);
|
||||
|
||||
Request->Data.GetNumInputEventsRequest.NumInputEvents = NumEvents;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(CsrPeekConsoleInput)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCSRSS_CONSOLE Console;
|
||||
DWORD Size;
|
||||
DWORD Length;
|
||||
PLIST_ENTRY CurrentItem;
|
||||
PINPUT_RECORD InputRecord;
|
||||
ConsoleInput* Item;
|
||||
UINT NumItems;
|
||||
|
||||
DPRINT("CsrPeekConsoleInput\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.GetNumInputEventsRequest.ConsoleHandle, &Console, GENERIC_READ);
|
||||
if(! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
InputRecord = Request->Data.PeekConsoleInputRequest.InputRecord;
|
||||
Length = Request->Data.PeekConsoleInputRequest.Length;
|
||||
Size = Length * sizeof(INPUT_RECORD);
|
||||
|
||||
if (((PVOID)InputRecord < ProcessData->CsrSectionViewBase)
|
||||
|| (((ULONG_PTR)InputRecord + Size) > ((ULONG_PTR)ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize)))
|
||||
{
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
|
||||
NumItems = 0;
|
||||
|
||||
if (! IsListEmpty(&Console->InputEvents))
|
||||
{
|
||||
CurrentItem = Console->InputEvents.Flink;
|
||||
|
||||
while (CurrentItem != &Console->InputEvents && NumItems < Length)
|
||||
{
|
||||
Item = CONTAINING_RECORD(CurrentItem, ConsoleInput, ListEntry);
|
||||
|
||||
if (Item->Fake)
|
||||
{
|
||||
CurrentItem = CurrentItem->Flink;
|
||||
continue;
|
||||
}
|
||||
|
||||
++NumItems;
|
||||
*InputRecord = Item->InputEvent;
|
||||
|
||||
if (Request->Data.ReadInputRequest.Unicode == FALSE)
|
||||
{
|
||||
ConioInputEventToAnsi(Console, InputRecord);
|
||||
}
|
||||
|
||||
InputRecord++;
|
||||
CurrentItem = CurrentItem->Flink;
|
||||
}
|
||||
}
|
||||
|
||||
ConioUnlockConsole(Console);
|
||||
|
||||
Request->Data.PeekConsoleInputRequest.Length = NumItems;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
CSR_API(CsrWriteConsoleInput)
|
||||
{
|
||||
PINPUT_RECORD InputRecord;
|
||||
PCSRSS_CONSOLE Console;
|
||||
NTSTATUS Status;
|
||||
DWORD Length;
|
||||
DWORD Size;
|
||||
DWORD i;
|
||||
ConsoleInput* Record;
|
||||
|
||||
DPRINT("CsrWriteConsoleInput\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.WriteConsoleInputRequest.ConsoleHandle, &Console, GENERIC_WRITE);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
InputRecord = Request->Data.WriteConsoleInputRequest.InputRecord;
|
||||
Length = Request->Data.WriteConsoleInputRequest.Length;
|
||||
Size = Length * sizeof(INPUT_RECORD);
|
||||
|
||||
if (((PVOID)InputRecord < ProcessData->CsrSectionViewBase)
|
||||
|| (((ULONG_PTR)InputRecord + Size) > ((ULONG_PTR)ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize)))
|
||||
{
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
|
||||
for (i = 0; i < Length; i++)
|
||||
{
|
||||
Record = HeapAlloc(Win32CsrApiHeap, 0, sizeof(ConsoleInput));
|
||||
if (NULL == Record)
|
||||
{
|
||||
ConioUnlockConsole(Console);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
Record->Echoed = FALSE;
|
||||
Record->Fake = FALSE;
|
||||
//Record->InputEvent = *InputRecord++;
|
||||
memcpy(&Record->InputEvent, &InputRecord[i], sizeof(INPUT_RECORD));
|
||||
if (KEY_EVENT == Record->InputEvent.EventType)
|
||||
{
|
||||
/* FIXME - convert from unicode to ascii!! */
|
||||
ConioProcessChar(Console, Record);
|
||||
}
|
||||
}
|
||||
|
||||
ConioUnlockConsole(Console);
|
||||
|
||||
Request->Data.WriteConsoleInputRequest.Length = i;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* EOF */
|
File diff suppressed because it is too large
Load diff
|
@ -118,62 +118,6 @@ typedef struct ConsoleInput_t
|
|||
#define PAUSED_FROM_SCROLLBAR 0x2
|
||||
#define PAUSED_FROM_SELECTION 0x4
|
||||
|
||||
NTSTATUS FASTCALL ConioConsoleFromProcessData(PCSRSS_PROCESS_DATA ProcessData, PCSRSS_CONSOLE *Console);
|
||||
VOID WINAPI ConioDeleteConsole(Object_t *Object);
|
||||
VOID WINAPI ConioDeleteScreenBuffer(PCSRSS_SCREEN_BUFFER Buffer);
|
||||
VOID WINAPI CsrInitConsoleSupport(VOID);
|
||||
VOID FASTCALL ConioPause(PCSRSS_CONSOLE Console, UINT Flags);
|
||||
VOID FASTCALL ConioUnpause(PCSRSS_CONSOLE Console, UINT Flags);
|
||||
void WINAPI ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode);
|
||||
PBYTE FASTCALL ConioCoordToPointer(PCSRSS_SCREEN_BUFFER Buf, ULONG X, ULONG Y);
|
||||
VOID FASTCALL ConioDrawConsole(PCSRSS_CONSOLE Console);
|
||||
VOID FASTCALL ConioConsoleCtrlEvent(DWORD Event, PCSRSS_PROCESS_DATA ProcessData);
|
||||
VOID FASTCALL ConioConsoleCtrlEventTimeout(DWORD Event, PCSRSS_PROCESS_DATA ProcessData,
|
||||
DWORD Timeout);
|
||||
|
||||
/* api/conio.c */
|
||||
CSR_API(CsrWriteConsole);
|
||||
CSR_API(CsrAllocConsole);
|
||||
CSR_API(CsrFreeConsole);
|
||||
CSR_API(CsrReadConsole);
|
||||
CSR_API(CsrConnectProcess);
|
||||
CSR_API(CsrGetScreenBufferInfo);
|
||||
CSR_API(CsrSetCursor);
|
||||
CSR_API(CsrFillOutputChar);
|
||||
CSR_API(CsrReadInputEvent);
|
||||
CSR_API(CsrWriteConsoleOutputChar);
|
||||
CSR_API(CsrWriteConsoleOutputAttrib);
|
||||
CSR_API(CsrFillOutputAttrib);
|
||||
CSR_API(CsrGetCursorInfo);
|
||||
CSR_API(CsrSetCursorInfo);
|
||||
CSR_API(CsrSetTextAttrib);
|
||||
CSR_API(CsrSetConsoleMode);
|
||||
CSR_API(CsrGetConsoleMode);
|
||||
CSR_API(CsrCreateScreenBuffer);
|
||||
CSR_API(CsrSetScreenBuffer);
|
||||
CSR_API(CsrSetTitle);
|
||||
CSR_API(CsrGetTitle);
|
||||
CSR_API(CsrWriteConsoleOutput);
|
||||
CSR_API(CsrFlushInputBuffer);
|
||||
CSR_API(CsrScrollConsoleScreenBuffer);
|
||||
CSR_API(CsrReadConsoleOutputChar);
|
||||
CSR_API(CsrReadConsoleOutputAttrib);
|
||||
CSR_API(CsrGetNumberOfConsoleInputEvents);
|
||||
CSR_API(CsrPeekConsoleInput);
|
||||
CSR_API(CsrReadConsoleOutput);
|
||||
CSR_API(CsrWriteConsoleInput);
|
||||
CSR_API(CsrHardwareStateProperty);
|
||||
CSR_API(CsrGetConsoleWindow);
|
||||
CSR_API(CsrSetConsoleIcon);
|
||||
CSR_API(CsrGetConsoleCodePage);
|
||||
CSR_API(CsrSetConsoleCodePage);
|
||||
CSR_API(CsrGetConsoleOutputCodePage);
|
||||
CSR_API(CsrSetConsoleOutputCodePage);
|
||||
CSR_API(CsrGetProcessList);
|
||||
CSR_API(CsrGenerateCtrlEvent);
|
||||
CSR_API(CsrSetScreenBufferSize);
|
||||
CSR_API(CsrGetConsoleSelectionInfo);
|
||||
|
||||
#define ConioInitScreenBuffer(Console, Buff) (Console)->Vtbl->InitScreenBuffer((Console), (Buff))
|
||||
#define ConioDrawRegion(Console, Region) (Console)->Vtbl->DrawRegion((Console), (Region))
|
||||
#define ConioWriteStream(Console, Block, CurStartX, CurStartY, ScrolledLines, Buffer, Length) \
|
||||
|
@ -189,19 +133,79 @@ CSR_API(CsrGetConsoleSelectionInfo);
|
|||
#define ConioChangeIcon(Console, hWindowIcon) (Console)->Vtbl->ChangeIcon(Console, hWindowIcon)
|
||||
#define ConioResizeBuffer(Console, Buff, Size) (Console)->Vtbl->ResizeBuffer(Console, Buff, Size)
|
||||
|
||||
#define ConioRectHeight(Rect) \
|
||||
(((Rect)->Top) > ((Rect)->Bottom) ? 0 : ((Rect)->Bottom) - ((Rect)->Top) + 1)
|
||||
#define ConioRectWidth(Rect) \
|
||||
(((Rect)->Left) > ((Rect)->Right) ? 0 : ((Rect)->Right) - ((Rect)->Left) + 1)
|
||||
/* console.c */
|
||||
NTSTATUS FASTCALL ConioConsoleFromProcessData(PCSRSS_PROCESS_DATA ProcessData, PCSRSS_CONSOLE *Console);
|
||||
VOID WINAPI ConioDeleteConsole(Object_t *Object);
|
||||
VOID WINAPI CsrInitConsoleSupport(VOID);
|
||||
VOID FASTCALL ConioPause(PCSRSS_CONSOLE Console, UINT Flags);
|
||||
VOID FASTCALL ConioUnpause(PCSRSS_CONSOLE Console, UINT Flags);
|
||||
VOID FASTCALL ConioConsoleCtrlEvent(DWORD Event, PCSRSS_PROCESS_DATA ProcessData);
|
||||
VOID FASTCALL ConioConsoleCtrlEventTimeout(DWORD Event, PCSRSS_PROCESS_DATA ProcessData,
|
||||
DWORD Timeout);
|
||||
CSR_API(CsrAllocConsole);
|
||||
CSR_API(CsrFreeConsole);
|
||||
CSR_API(CsrSetConsoleMode);
|
||||
CSR_API(CsrGetConsoleMode);
|
||||
CSR_API(CsrSetTitle);
|
||||
CSR_API(CsrGetTitle);
|
||||
CSR_API(CsrHardwareStateProperty);
|
||||
CSR_API(CsrGetConsoleWindow);
|
||||
CSR_API(CsrSetConsoleIcon);
|
||||
CSR_API(CsrGetConsoleCodePage);
|
||||
CSR_API(CsrSetConsoleCodePage);
|
||||
CSR_API(CsrGetConsoleOutputCodePage);
|
||||
CSR_API(CsrSetConsoleOutputCodePage);
|
||||
CSR_API(CsrGetProcessList);
|
||||
CSR_API(CsrGenerateCtrlEvent);
|
||||
CSR_API(CsrGetConsoleSelectionInfo);
|
||||
|
||||
/* coninput.c */
|
||||
#define ConioLockConsole(ProcessData, Handle, Ptr, Access) \
|
||||
Win32CsrLockObject((ProcessData), (Handle), (Object_t **)(Ptr), Access, CONIO_CONSOLE_MAGIC)
|
||||
#define ConioUnlockConsole(Console) \
|
||||
Win32CsrUnlockObject((Object_t *) Console)
|
||||
void WINAPI ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode);
|
||||
CSR_API(CsrReadConsole);
|
||||
CSR_API(CsrReadInputEvent);
|
||||
CSR_API(CsrFlushInputBuffer);
|
||||
CSR_API(CsrGetNumberOfConsoleInputEvents);
|
||||
CSR_API(CsrPeekConsoleInput);
|
||||
CSR_API(CsrWriteConsoleInput);
|
||||
|
||||
/* conoutput.c */
|
||||
#define ConioRectHeight(Rect) \
|
||||
(((Rect)->Top) > ((Rect)->Bottom) ? 0 : ((Rect)->Bottom) - ((Rect)->Top) + 1)
|
||||
#define ConioRectWidth(Rect) \
|
||||
(((Rect)->Left) > ((Rect)->Right) ? 0 : ((Rect)->Right) - ((Rect)->Left) + 1)
|
||||
#define ConioLockScreenBuffer(ProcessData, Handle, Ptr, Access) \
|
||||
Win32CsrLockObject((ProcessData), (Handle), (Object_t **)(Ptr), Access, CONIO_SCREEN_BUFFER_MAGIC)
|
||||
#define ConioUnlockScreenBuffer(Buff) \
|
||||
Win32CsrUnlockObject((Object_t *) Buff)
|
||||
PBYTE FASTCALL ConioCoordToPointer(PCSRSS_SCREEN_BUFFER Buf, ULONG X, ULONG Y);
|
||||
VOID FASTCALL ConioDrawConsole(PCSRSS_CONSOLE Console);
|
||||
NTSTATUS FASTCALL ConioWriteConsole(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff,
|
||||
CHAR *Buffer, DWORD Length, BOOL Attrib);
|
||||
NTSTATUS FASTCALL CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buffer);
|
||||
VOID WINAPI ConioDeleteScreenBuffer(PCSRSS_SCREEN_BUFFER Buffer);
|
||||
|
||||
CSR_API(CsrWriteConsole);
|
||||
CSR_API(CsrGetScreenBufferInfo);
|
||||
CSR_API(CsrSetCursor);
|
||||
CSR_API(CsrWriteConsoleOutputChar);
|
||||
CSR_API(CsrFillOutputChar);
|
||||
CSR_API(CsrWriteConsoleOutputAttrib);
|
||||
CSR_API(CsrFillOutputAttrib);
|
||||
CSR_API(CsrGetCursorInfo);
|
||||
CSR_API(CsrSetCursorInfo);
|
||||
CSR_API(CsrSetTextAttrib);
|
||||
CSR_API(CsrCreateScreenBuffer);
|
||||
CSR_API(CsrSetScreenBuffer);
|
||||
CSR_API(CsrWriteConsoleOutput);
|
||||
CSR_API(CsrScrollConsoleScreenBuffer);
|
||||
CSR_API(CsrReadConsoleOutputChar);
|
||||
CSR_API(CsrReadConsoleOutputAttrib);
|
||||
CSR_API(CsrReadConsoleOutput);
|
||||
CSR_API(CsrSetScreenBufferSize);
|
||||
|
||||
/* alias.c */
|
||||
VOID IntDeleteAllAliases(struct tagALIAS_HEADER *RootHeader);
|
||||
|
|
1505
reactos/subsystems/win32/csrss/win32csr/conoutput.c
Normal file
1505
reactos/subsystems/win32/csrss/win32csr/conoutput.c
Normal file
File diff suppressed because it is too large
Load diff
851
reactos/subsystems/win32/csrss/win32csr/console.c
Normal file
851
reactos/subsystems/win32/csrss/win32csr/console.c
Normal file
|
@ -0,0 +1,851 @@
|
|||
/*
|
||||
* 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->WaitingChars = 0;
|
||||
Console->WaitingLines = 0;
|
||||
Console->EchoCount = 0;
|
||||
Console->Header.Type = CONIO_CONSOLE_MAGIC;
|
||||
Console->Header.Console = Console;
|
||||
Console->Mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT;
|
||||
Console->EarlyReturn = FALSE;
|
||||
InitializeListHead(&Console->BufferList);
|
||||
Console->ActiveBuffer = NULL;
|
||||
InitializeListHead(&Console->InputEvents);
|
||||
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);
|
||||
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");
|
||||
|
||||
if (Request->Header.u1.s1.TotalLength
|
||||
< CSR_API_MESSAGE_HEADER_SIZE(CSRSS_SET_TITLE)
|
||||
+ Request->Data.SetTitleRequest.Length)
|
||||
{
|
||||
DPRINT1("Invalid request size\n");
|
||||
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
||||
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
||||
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
||||
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
||||
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);
|
||||
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 */
|
||||
RtlZeroMemory(&Request->Data.GetTitleRequest, sizeof(CSRSS_GET_TITLE));
|
||||
Request->Data.GetTitleRequest.Length = Console->Title.Length;
|
||||
memcpy (Request->Data.GetTitleRequest.Title, Console->Title.Buffer,
|
||||
Console->Title.Length);
|
||||
Length = CSR_API_MESSAGE_HEADER_SIZE(CSRSS_SET_TITLE) + Console->Title.Length;
|
||||
|
||||
ConioUnlockConsole(Console);
|
||||
|
||||
if (Length > sizeof(CSR_API_MESSAGE))
|
||||
{
|
||||
Request->Header.u1.s1.TotalLength = Length;
|
||||
Request->Header.u1.s1.DataLength = Length - sizeof(PORT_MESSAGE);
|
||||
}
|
||||
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;
|
||||
ULONG_PTR Offset;
|
||||
|
||||
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;
|
||||
Offset = (PBYTE)Buffer - (PBYTE)ProcessData->CsrSectionViewBase;
|
||||
if (Offset >= ProcessData->CsrSectionViewSize
|
||||
|| (Request->Data.GetProcessListRequest.nMaxIds * sizeof(DWORD)) > (ProcessData->CsrSectionViewSize - Offset)
|
||||
|| Offset & (sizeof(DWORD) - 1))
|
||||
{
|
||||
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++ = (DWORD)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 */
|
|
@ -17,7 +17,9 @@
|
|||
<library>pseh</library>
|
||||
<pch>w32csr.h</pch>
|
||||
<file>alias.c</file>
|
||||
<file>conio.c</file>
|
||||
<file>coninput.c</file>
|
||||
<file>conoutput.c</file>
|
||||
<file>console.c</file>
|
||||
<file>desktopbg.c</file>
|
||||
<file>dllmain.c</file>
|
||||
<file>exitros.c</file>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue