📄 conio.c
字号:
|| '\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;
}
else
{
SetEvent(Console->ActiveEvent);
}
}
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++; */
if (bClientWake || 0 == (Console->Mode & ENABLE_LINE_INPUT))
{
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 STDCALL
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)
{
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)
{
/* FIXME - convert to ascii */
ConioProcessChar(Console, ConInRec);
}
else
{
HeapFree(Win32CsrApiHeap, 0, ConInRec);
}
}
CSR_API(CsrGetScreenBufferInfo)
{
NTSTATUS Status;
PCSRSS_SCREEN_BUFFER Buff;
PCONSOLE_SCREEN_BUFFER_INFO pInfo;
DPRINT("CsrGetScreenBufferInfo\n");
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
Status = ConioLockScreenBuffer(ProcessData, Request->Data.ScreenBufferInfoRequest.ConsoleHandle, &Buff);
if (! NT_SUCCESS(Status))
{
return Request->Status = Status;
}
pInfo = &Request->Data.ScreenBufferInfoRequest.Info;
pInfo->dwSize.X = Buff->MaxX;
pInfo->dwSize.Y = Buff->MaxY;
pInfo->dwCursorPosition.X = Buff->CurrentX - Buff->ShowX;
pInfo->dwCursorPosition.Y = (Buff->CurrentY + Buff->MaxY - Buff->ShowY) % Buff->MaxY;
pInfo->wAttributes = Buff->DefaultAttrib;
pInfo->srWindow.Left = 0;
pInfo->srWindow.Right = Buff->MaxX - 1;
pInfo->srWindow.Top = 0;
pInfo->srWindow.Bottom = Buff->MaxY - 1;
pInfo->dwMaximumWindowSize.X = Buff->MaxX;
pInfo->dwMaximumWindowSize.Y = Buff->MaxY;
ConioUnlockScreenBuffer(Buff);
Request->Status = STATUS_SUCCESS;
return Request->Status;
}
CSR_API(CsrSetCursor)
{
NTSTATUS Status;
PCSRSS_CONSOLE Console;
PCSRSS_SCREEN_BUFFER Buff;
LONG OldCursorX, OldCursorY;
LONG NewCursorX, NewCursorY;
DPRINT("CsrSetCursor\n");
Status = ConioConsoleFromProcessData(ProcessData, &Console);
if (! NT_SUCCESS(Status))
{
return Request->Status = Status;
}
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetCursorRequest.ConsoleHandle, &Buff);
if (! NT_SUCCESS(Status))
{
if (NULL != Console)
{
ConioUnlockConsole(Console);
}
return Request->Status = Status;
}
NewCursorX = Request->Data.SetCursorRequest.Position.X;
NewCursorY = Request->Data.SetCursorRequest.Position.Y;
if (NewCursorX < 0 || NewCursorX >= Buff->MaxX ||
NewCursorY < 0 || NewCursorY >= Buff->MaxY)
{
ConioUnlockScreenBuffer(Buff);
if (NULL != Console)
{
ConioUnlockConsole(Console);
}
return Request->Status = STATUS_INVALID_PARAMETER;
}
ConioPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, &OldCursorX, &OldCursorY);
Buff->CurrentX = NewCursorX + Buff->ShowX;
Buff->CurrentY = (NewCursorY + Buff->ShowY) % Buff->MaxY;
if (NULL != Console && Buff == Console->ActiveBuffer)
{
if (! ConioSetScreenInfo(Console, Buff, OldCursorX, OldCursorY))
{
ConioUnlockScreenBuffer(Buff);
if (NULL != Console)
{
ConioUnlockConsole(Console);
}
return Request->Status = STATUS_UNSUCCESSFUL;
}
}
ConioUnlockScreenBuffer(Buff);
if (NULL != Console)
{
ConioUnlockConsole(Console);
}
return Request->Status = STATUS_SUCCESS;
}
static VOID FASTCALL
ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff, RECT *UpdateRect, COORD *Start, UINT Length)
{
if (Buff->MaxX <= Start->X + Length)
{
UpdateRect->left = 0;
}
else
{
UpdateRect->left = Start->X;
}
if (Buff->MaxX <= Start->X + Length)
{
UpdateRect->right = Buff->MaxX - 1;
}
else
{
UpdateRect->right = Start->X + Length - 1;
}
UpdateRect->top = Start->Y;
UpdateRect->bottom = Start->Y+ (Start->X + Length - 1) / Buff->MaxX;
if (Buff->MaxY <= UpdateRect->bottom)
{
UpdateRect->bottom = Buff->MaxY - 1;
}
}
CSR_API(CsrWriteConsoleOutputChar)
{
NTSTATUS Status;
PCHAR String, tmpString = NULL;
PBYTE Buffer;
PCSRSS_CONSOLE Console;
PCSRSS_SCREEN_BUFFER Buff;
DWORD X, Y, Length, CharSize, Written = 0;
RECT UpdateRect;
DPRINT("CsrWriteConsoleOutputChar\n");
CharSize = (Request->Data.WriteConsoleOutputCharRequest.Unicode ? sizeof(WCHAR) : sizeof(CHAR));
if (Request->Header.u1.s1.TotalLength
< CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR)
+ (Request->Data.WriteConsoleOutputCharRequest.Length * 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))
{
if(Request->Data.WriteConsoleOutputCharRequest.Unicode)
{
Length = WideCharToMultiByte(Console->CodePage, 0,
(PWCHAR)Request->Data.WriteConsoleOutputCharRequest.String,
Request->Data.WriteConsoleOutputCharRequest.Length,
NULL, 0, NULL, NULL);
tmpString = String = RtlAllocateHeap(GetProcessHeap(), 0, Length);
if (String)
{
WideCharToMultiByte(Console->CodePage, 0,
(PWCHAR)Request->Data.WriteConsoleOutputCharRequest.String,
Request->Data.WriteConsoleOutputCharRequest.Length,
String, Length, NULL, NULL);
}
else
{
Status = STATUS_NO_MEMORY;
}
}
else
{
String = (PCHAR)Request->Data.WriteConsoleOutputCharRequest.String;
}
if (String)
{
Status = ConioLockScreenBuffer(ProcessData,
Request->Data.WriteConsoleOutputCharRequest.ConsoleHandle,
&Buff);
if (NT_SUCCESS(Status))
{
X = Request->Data.WriteConsoleOutputCharRequest.Coord.X + Buff->ShowX;
Y = (Request->Data.WriteConsoleOutputCharRequest.Coord.Y + Buff->ShowY) % Buff->MaxY;
Length = Request->Data.WriteConsoleOutputCharRequest.Length;
Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X)];
while (Length--)
{
*Buffer = *String++;
Written++;
Buffer += 2;
if (++X == Buff->MaxX)
{
if (++Y == Buff->MaxY)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -