📄 conio.c
字号:
{
if (tmp.left == Subtraction->left)
{
Subtraction->left = tmp.right;
}
else if (tmp.right == Subtraction->right)
{
Subtraction->right = tmp.left;
}
}
else if ((tmp.left == Subtraction->left) && (tmp.right == Subtraction->right))
{
if (tmp.top == Subtraction->top)
{
Subtraction->top = tmp.bottom;
}
else if (tmp.bottom == Subtraction->bottom)
{
Subtraction->bottom = tmp.top;
}
}
}
return TRUE;
}
static VOID FASTCALL
ConioCopyRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer,
RECT *SrcRegion,
RECT *DstRegion)
{
SHORT SrcY, DstY;
DWORD SrcOffset;
DWORD DstOffset;
DWORD BytesPerLine;
LONG i;
DstY = DstRegion->top;
BytesPerLine = ConioRectWidth(DstRegion) * 2;
SrcY = (SrcRegion->top + ScreenBuffer->ShowY) % ScreenBuffer->MaxY;
DstY = (DstRegion->top + ScreenBuffer->ShowY) % ScreenBuffer->MaxY;
SrcOffset = (SrcY * ScreenBuffer->MaxX + SrcRegion->left + ScreenBuffer->ShowX) * 2;
DstOffset = (DstY * ScreenBuffer->MaxX + DstRegion->left + ScreenBuffer->ShowX) * 2;
for (i = SrcRegion->top; i <= SrcRegion->bottom; i++)
{
RtlCopyMemory(
&ScreenBuffer->Buffer[DstOffset],
&ScreenBuffer->Buffer[SrcOffset],
BytesPerLine);
if (++DstY == ScreenBuffer->MaxY)
{
DstY = 0;
DstOffset = (DstRegion->left + ScreenBuffer->ShowX) * 2;
}
else
{
DstOffset += ScreenBuffer->MaxX * 2;
}
if (++SrcY == ScreenBuffer->MaxY)
{
SrcY = 0;
SrcOffset = (SrcRegion->left + ScreenBuffer->ShowX) * 2;
}
else
{
SrcOffset += ScreenBuffer->MaxX * 2;
}
}
}
static VOID FASTCALL
ConioFillRegion(PCSRSS_CONSOLE Console,
PCSRSS_SCREEN_BUFFER ScreenBuffer,
RECT *Region,
CHAR_INFO *CharInfo,
BOOL bUnicode)
{
SHORT X, Y;
DWORD Offset;
DWORD Delta;
LONG i;
CHAR Char;
if(bUnicode)
ConsoleUnicodeCharToAnsiChar(Console, &Char, &CharInfo->Char.UnicodeChar);
else
Char = CharInfo->Char.AsciiChar;
Y = (Region->top + ScreenBuffer->ShowY) % ScreenBuffer->MaxY;
Offset = (Y * ScreenBuffer->MaxX + Region->left + ScreenBuffer->ShowX) * 2;
Delta = (ScreenBuffer->MaxX - ConioRectWidth(Region)) * 2;
for (i = Region->top; i <= Region->bottom; i++)
{
for (X = Region->left; X <= Region->right; X++)
{
SET_CELL_BUFFER(ScreenBuffer, Offset, Char, CharInfo->Attributes);
}
if (++Y == ScreenBuffer->MaxY)
{
Y = 0;
Offset = (Region->left + ScreenBuffer->ShowX) * 2;
}
else
{
Offset += Delta;
}
}
}
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;
ConsoleUnicodeCharToAnsiChar(Console,
&InputEvent->Event.KeyEvent.uChar.AsciiChar,
&UnicodeChar);
}
}
CSR_API(CsrWriteConsole)
{
NTSTATUS Status;
PCHAR Buffer;
PCSRSS_SCREEN_BUFFER Buff;
PCSRSS_CONSOLE Console;
DWORD Written = 0;
ULONG Length;
ULONG CharSize = (Request->Data.WriteConsoleRequest.Unicode ? sizeof(WCHAR) : sizeof(CHAR));
DPRINT("CsrWriteConsole\n");
if (Request->Header.u1.s1.TotalLength
< CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE)
+ (Request->Data.WriteConsoleRequest.NrCharactersToWrite * CharSize))
{
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 Request->Status = 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))
{
return Request->Status = Status;
}
if(Request->Data.WriteConsoleRequest.Unicode)
{
Length = WideCharToMultiByte(Console->CodePage, 0,
(PWCHAR)Request->Data.WriteConsoleRequest.Buffer,
Request->Data.WriteConsoleRequest.NrCharactersToWrite,
NULL, 0, NULL, NULL);
Buffer = RtlAllocateHeap(GetProcessHeap(), 0, Length);
if (Buffer)
{
WideCharToMultiByte(Console->CodePage, 0,
(PWCHAR)Request->Data.WriteConsoleRequest.Buffer,
Request->Data.WriteConsoleRequest.NrCharactersToWrite,
Buffer, Length, NULL, NULL);
}
else
{
Status = STATUS_NO_MEMORY;
}
}
else
{
Buffer = (PCHAR)Request->Data.WriteConsoleRequest.Buffer;
}
if (Buffer)
{
Status = ConioLockScreenBuffer(ProcessData, Request->Data.WriteConsoleRequest.ConsoleHandle, &Buff);
if (NT_SUCCESS(Status))
{
Request->Status = ConioWriteConsole(Console, Buff, Buffer,
Request->Data.WriteConsoleRequest.NrCharactersToWrite, TRUE);
if (NT_SUCCESS(Status))
{
Written = Request->Data.WriteConsoleRequest.NrCharactersToWrite;
}
ConioUnlockScreenBuffer(Buff);
}
if (Request->Data.WriteConsoleRequest.Unicode)
{
RtlFreeHeap(GetProcessHeap(), 0, Buffer);
}
}
if (NULL != Console)
{
ConioUnlockConsole(Console);
}
Request->Data.WriteConsoleRequest.NrCharactersWritten = Written;
return Request->Status = Status;
}
VOID STDCALL
ConioDeleteScreenBuffer(Object_t *Object)
{
PCSRSS_SCREEN_BUFFER Buffer = (PCSRSS_SCREEN_BUFFER) Object;
DeleteCriticalSection(&Buffer->Header.Lock);
HeapFree(Win32CsrApiHeap, 0, Buffer->Buffer);
HeapFree(Win32CsrApiHeap, 0, Buffer);
}
VOID FASTCALL
ConioDrawConsole(PCSRSS_CONSOLE Console)
{
RECT Region;
ConioInitRect(&Region, 0, 0, Console->Size.Y - 1, Console->Size.X - 1);
ConioDrawRegion(Console, &Region);
}
VOID STDCALL
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);
}
#if 0 // FIXME
if (0 == InterlockedDecrement(&Console->ActiveBuffer->Header.ReferenceCount))
{
ConioDeleteScreenBuffer((Object_t *) Console->ActiveBuffer);
}
#endif
Console->ActiveBuffer = NULL;
ConioCleanupConsole(Console);
CloseHandle(Console->ActiveEvent);
DeleteCriticalSection(&Console->Header.Lock);
RtlFreeUnicodeString(&Console->Title);
HeapFree(Win32CsrApiHeap, 0, Console);
}
VOID STDCALL
CsrInitConsoleSupport(VOID)
{
DPRINT("CSR: CsrInitConsoleSupport()\n");
/* Should call LoadKeyboardLayout */
}
static VOID FASTCALL
ConioProcessChar(PCSRSS_CONSOLE Console,
ConsoleInput *KeyEventRecord)
{
BOOL updown;
BOOL bClientWake = FALSE;
ConsoleInput *TempInput;
/* process Ctrl-C and Ctrl-Break */
if (Console->Mode & ENABLE_PROCESSED_INPUT &&
KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown &&
((KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_PAUSE) ||
(KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == 'C')) &&
(KeyEventRecord->InputEvent.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, KeyEventRecord);
return;
}
if (0 != (KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState
& (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
&& (VK_UP == KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode
|| VK_DOWN == KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode))
{
if (KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown)
{
/* scroll up or down */
if (NULL == Console)
{
DPRINT1("No Active Console!\n");
HeapFree(Win32CsrApiHeap, 0, KeyEventRecord);
return;
}
if (VK_UP == KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode)
{
/* only scroll up if there is room to scroll up into */
if (Console->ActiveBuffer->ShowY != ((Console->ActiveBuffer->CurrentY + 1) %
Console->ActiveBuffer->MaxY))
{
Console->ActiveBuffer->ShowY = (Console->ActiveBuffer->ShowY +
Console->ActiveBuffer->MaxY - 1) %
Console->ActiveBuffer->MaxY;
}
}
else if (Console->ActiveBuffer->ShowY != Console->ActiveBuffer->CurrentY)
/* only scroll down if there is room to scroll down into */
{
if (Console->ActiveBuffer->ShowY % Console->ActiveBuffer->MaxY !=
Console->ActiveBuffer->CurrentY)
{
if (((Console->ActiveBuffer->CurrentY + 1) % Console->ActiveBuffer->MaxY) !=
(Console->ActiveBuffer->ShowY + Console->ActiveBuffer->MaxY) %
Console->ActiveBuffer->MaxY)
{
Console->ActiveBuffer->ShowY = (Console->ActiveBuffer->ShowY + 1) %
Console->ActiveBuffer->MaxY;
}
}
}
ConioDrawConsole(Console);
}
HeapFree(Win32CsrApiHeap, 0, KeyEventRecord);
return;
}
if (NULL == Console)
{
DPRINT1("No Active Console!\n");
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++;
}
bClientWake = TRUE;
SetEvent(Console->ActiveEvent);
}
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -