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

📄 conio.c

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