⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 conio.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
               || '\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 + -