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

📄 console.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
}


/*
 * @implemented
 */
BOOL STDCALL
CloseConsoleHandle(HANDLE Handle)
     /*
      * Undocumented
      */
{
  CSR_API_MESSAGE Request; ULONG CsrRequest;
  
  NTSTATUS Status;

  if (IsConsoleHandle (Handle) == FALSE)
    {
      SetLastError (ERROR_INVALID_PARAMETER);
      return FALSE;
    }

  CsrRequest = MAKE_CSR_API(CLOSE_HANDLE, CSR_NATIVE);
  Request.Data.CloseHandleRequest.Handle = Handle;
  Status = CsrClientCallServer(&Request,
			       NULL,
			       CsrRequest,
			       sizeof(CSR_API_MESSAGE));
  if (!NT_SUCCESS(Status))
    {
       SetLastErrorByStatus(Status);
       return FALSE;
    }

  return TRUE;
}

/*
 * @implemented
 */
HANDLE STDCALL
GetStdHandle(DWORD nStdHandle)
     /*
      * FUNCTION: Get a handle for the standard input, standard output
      * and a standard error device.
      * ARGUMENTS:
      *       nStdHandle - Specifies the device for which to return the handle.
      * RETURNS: If the function succeeds, the return value is the handle
      * of the specified device. Otherwise the value is INVALID_HANDLE_VALUE.
      */
{
  PRTL_USER_PROCESS_PARAMETERS Ppb;

  Ppb = NtCurrentPeb()->ProcessParameters;
  switch (nStdHandle)
    {
      case STD_INPUT_HANDLE:
	return Ppb->StandardInput;

      case STD_OUTPUT_HANDLE:
	return Ppb->StandardOutput;

      case STD_ERROR_HANDLE:
	return Ppb->StandardError;
    }

  SetLastError (ERROR_INVALID_PARAMETER);
  return INVALID_HANDLE_VALUE;
}


/*
 * @implemented
 */
BOOL WINAPI
SetStdHandle(DWORD nStdHandle,
	     HANDLE hHandle)
     /*
      * FUNCTION: Set the handle for the standard input, standard output or
      * the standard error device.
      * ARGUMENTS:
      *        nStdHandle - Specifies the handle to be set.
      *        hHandle - The handle to set.
      * RETURNS: TRUE if the function succeeds, FALSE otherwise.
      */
{
  PRTL_USER_PROCESS_PARAMETERS Ppb;

  /* no need to check if hHandle == INVALID_HANDLE_VALUE */

  Ppb = NtCurrentPeb()->ProcessParameters;

  switch (nStdHandle)
    {
      case STD_INPUT_HANDLE:
	Ppb->StandardInput = hHandle;
	return TRUE;

      case STD_OUTPUT_HANDLE:
	Ppb->StandardOutput = hHandle;
	return TRUE;

      case STD_ERROR_HANDLE:
	Ppb->StandardError = hHandle;
	return TRUE;
    }

  /* windows for whatever reason sets the last error to ERROR_INVALID_HANDLE here */
  SetLastError (ERROR_INVALID_HANDLE);
  return FALSE;
}


static BOOL
IntWriteConsole(HANDLE hConsoleOutput,
                PVOID lpBuffer,
                DWORD nNumberOfCharsToWrite,
                LPDWORD lpNumberOfCharsWritten,
                LPVOID lpReserved,
                BOOL bUnicode)
{
  PCSR_API_MESSAGE Request; 
  ULONG CsrRequest;
  NTSTATUS Status;
  USHORT nChars;
  ULONG SizeBytes, CharSize;
  DWORD Written = 0;

  CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
  Request = RtlAllocateHeap(RtlGetProcessHeap(), 0, 
                            max(sizeof(CSR_API_MESSAGE), 
                                CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE) 
                                  + min(nNumberOfCharsToWrite, CSRSS_MAX_WRITE_CONSOLE / CharSize) * CharSize));
  if (Request == NULL)
  {
    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
    return FALSE;
  }

  CsrRequest = MAKE_CSR_API(WRITE_CONSOLE, CSR_CONSOLE);

  while(nNumberOfCharsToWrite > 0)
  {
    Request->Data.WriteConsoleRequest.ConsoleHandle = hConsoleOutput;
    Request->Data.WriteConsoleRequest.Unicode = bUnicode;

    nChars = min(nNumberOfCharsToWrite, CSRSS_MAX_WRITE_CONSOLE / CharSize);
    Request->Data.WriteConsoleRequest.NrCharactersToWrite = nChars;

    SizeBytes = nChars * CharSize;

    memcpy(Request->Data.WriteConsoleRequest.Buffer, lpBuffer, SizeBytes);

    Status = CsrClientCallServer(Request,
                                 NULL,
                                 CsrRequest,
                                 max(sizeof(CSR_API_MESSAGE), CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE) + SizeBytes));

    if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request->Status))
    {
      RtlFreeHeap(RtlGetProcessHeap(), 0, Request);
      SetLastErrorByStatus(Status);
      return FALSE;
    }

    nNumberOfCharsToWrite -= nChars;
    lpBuffer = (PVOID)((ULONG_PTR)lpBuffer + (ULONG_PTR)SizeBytes);
    Written += Request->Data.WriteConsoleRequest.NrCharactersWritten;
  }

  if(lpNumberOfCharsWritten != NULL)
  {
    *lpNumberOfCharsWritten = Written;
  }
  RtlFreeHeap(RtlGetProcessHeap(), 0, Request);

  return TRUE;
}


/*--------------------------------------------------------------
 *	WriteConsoleA
 *
 * @implemented
 */
BOOL STDCALL
WriteConsoleA(HANDLE hConsoleOutput,
	      CONST VOID *lpBuffer,
	      DWORD nNumberOfCharsToWrite,
	      LPDWORD lpNumberOfCharsWritten,
	      LPVOID lpReserved)
{
  return IntWriteConsole(hConsoleOutput,
                         (PVOID)lpBuffer,
                         nNumberOfCharsToWrite,
                         lpNumberOfCharsWritten,
                         lpReserved,
                         FALSE);
}


/*--------------------------------------------------------------
 *	WriteConsoleW
 *
 * @implemented
 */
BOOL STDCALL
WriteConsoleW(
	HANDLE		 hConsoleOutput,
	CONST VOID	*lpBuffer,
	DWORD		 nNumberOfCharsToWrite,
	LPDWORD		 lpNumberOfCharsWritten,
	LPVOID		 lpReserved
	)
{
  return IntWriteConsole(hConsoleOutput,
                         (PVOID)lpBuffer,
                         nNumberOfCharsToWrite,
                         lpNumberOfCharsWritten,
                         lpReserved,
                         TRUE);
}


static BOOL
IntReadConsole(HANDLE hConsoleInput,
               PVOID lpBuffer,
               DWORD nNumberOfCharsToRead,
               LPDWORD lpNumberOfCharsRead,
               PCONSOLE_READCONSOLE_CONTROL lpReserved,
               BOOL bUnicode)
{
  PCSR_API_MESSAGE Request; 
  ULONG CsrRequest;
  NTSTATUS Status;
  ULONG CharSize, CharsRead = 0;

  CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
  Request = RtlAllocateHeap(RtlGetProcessHeap(), 0,
                            max(sizeof(CSR_API_MESSAGE),
                                CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE) 
                                  + min(nNumberOfCharsToRead, CSRSS_MAX_READ_CONSOLE / CharSize) * CharSize));
  if (Request == NULL)
  {
    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
    return FALSE;
  }

  Request->Status = STATUS_SUCCESS;
  CsrRequest = MAKE_CSR_API(READ_CONSOLE, CSR_CONSOLE);

  do
  {
    if(Request->Status == STATUS_PENDING)
    {
      Status = NtWaitForSingleObject(Request->Data.ReadConsoleRequest.EventHandle, FALSE, 0);
      if(!NT_SUCCESS(Status))
      {
        DPRINT1("Wait for console input failed!\n");
        break;
      }
    }

    Request->Data.ReadConsoleRequest.ConsoleHandle = hConsoleInput;
    Request->Data.ReadConsoleRequest.Unicode = bUnicode;
    Request->Data.ReadConsoleRequest.NrCharactersToRead = min(nNumberOfCharsToRead, CSRSS_MAX_READ_CONSOLE / CharSize);
    Request->Data.ReadConsoleRequest.nCharsCanBeDeleted = CharsRead;
    Status = CsrClientCallServer(Request,
                                 NULL,
                                 CsrRequest,
                                 max(sizeof(CSR_API_MESSAGE), 
                                     CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE) 
                                       + Request->Data.ReadConsoleRequest.NrCharactersToRead * CharSize));

    if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request->Status))
    {
      DPRINT1("CSR returned error in ReadConsole\n");
      RtlFreeHeap(RtlGetProcessHeap(), 0, Request);
      SetLastErrorByStatus(Status);
      return FALSE;
    }

    nNumberOfCharsToRead -= Request->Data.ReadConsoleRequest.NrCharactersRead;
    memcpy((PVOID)((ULONG_PTR)lpBuffer + (ULONG_PTR)(CharsRead * CharSize)),
           Request->Data.ReadConsoleRequest.Buffer,
           Request->Data.ReadConsoleRequest.NrCharactersRead * CharSize);
    CharsRead += Request->Data.ReadConsoleRequest.NrCharactersRead;

    if(Request->Status == STATUS_NOTIFY_CLEANUP)
    {
      if(CharsRead > 0)
      {
        CharsRead--;
        nNumberOfCharsToRead++;
      }
      Request->Status = STATUS_PENDING;
    }
  } while(Request->Status == STATUS_PENDING && nNumberOfCharsToRead > 0);

  if(lpNumberOfCharsRead != NULL)
  {
    *lpNumberOfCharsRead = CharsRead;
  }

  RtlFreeHeap(RtlGetProcessHeap(), 0, Request);

  return TRUE;
}


/*--------------------------------------------------------------
 *	ReadConsoleA
 *
 * @implemented
 */
BOOL STDCALL
ReadConsoleA(HANDLE hConsoleInput,
             LPVOID lpBuffer,
             DWORD nNumberOfCharsToRead,
             LPDWORD lpNumberOfCharsRead,
             PCONSOLE_READCONSOLE_CONTROL pInputControl)
{
  return IntReadConsole(hConsoleInput,
                        lpBuffer,
                        nNumberOfCharsToRead,
                        lpNumberOfCharsRead,
                        pInputControl,
                        FALSE);
}


/*--------------------------------------------------------------
 *	ReadConsoleW
 *
 * @implemented
 */
BOOL STDCALL
ReadConsoleW(HANDLE hConsoleInput,
             LPVOID lpBuffer,
             DWORD nNumberOfCharsToRead,
             LPDWORD lpNumberOfCharsRead,
             PCONSOLE_READCONSOLE_CONTROL pInputControl)
{
  return IntReadConsole(hConsoleInput,
                        lpBuffer,
                        nNumberOfCharsToRead,
                        lpNumberOfCharsRead,
                        pInputControl,
                        TRUE);
}


/*--------------------------------------------------------------
 *	AllocConsole
 *
 * @implemented
 */
BOOL STDCALL AllocConsole(VOID)
{
   CSR_API_MESSAGE Request; ULONG CsrRequest;
   
   NTSTATUS Status;
   HANDLE hStdError;

   if(NtCurrentPeb()->ProcessParameters->ConsoleHandle)
   {
	DPRINT("AllocConsole: Allocate duplicate console to the same Process\n");
	SetLastErrorByStatus (STATUS_OBJECT_NAME_EXISTS);
	return FALSE;
   }

   Request.Data.AllocConsoleRequest.CtrlDispatcher = ConsoleControlDispatcher;
   Request.Data.AllocConsoleRequest.ConsoleNeeded = TRUE;

   CsrRequest = MAKE_CSR_API(ALLOC_CONSOLE, CSR_CONSOLE);
   Status = CsrClientCallServer( &Request, NULL, CsrRequest, sizeof( CSR_API_MESSAGE ) );
   if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Request.Status ) )
      {
	 SetLastErrorByStatus ( Status );
	 return FALSE;
      }
   NtCurrentPeb()->ProcessParameters->ConsoleHandle = Request.Data.AllocConsoleRequest.Console;
   SetStdHandle( STD_INPUT_HANDLE, Request.Data.AllocConsoleRequest.InputHandle );
   SetStdHandle( STD_OUTPUT_HANDLE, Request.Data.AllocConsoleRequest.OutputHandle );
   hStdError = DuplicateConsoleHandle(Request.Data.AllocConsoleRequest.OutputHandle,
                                      0,
				      TRUE,
				      DUPLICATE_SAME_ACCESS);
   SetStdHandle( STD_ERROR_HANDLE, hStdError );
   return TRUE;
}


/*--------------------------------------------------------------
 *	FreeConsole
 *
 * @implemented
 */
BOOL STDCALL FreeConsole(VOID)
{
    // AG: I'm not sure if this is correct (what happens to std handles?)
    // but I just tried to reverse what AllocConsole() does...

   CSR_API_MESSAGE Request; ULONG CsrRequest;
   
   NTSTATUS Status;

   CsrRequest = MAKE_CSR_API(FREE_CONSOLE, CSR_CONSOLE);
   Status = CsrClientCallServer( &Request, NULL, CsrRequest, sizeof( CSR_API_MESSAGE ) );
   if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Request.Status ) )
      {
	 SetLastErrorByStatus ( Status );
	 return FALSE;
      }

   return TRUE;
}


/*--------------------------------------------------------------
 *	GetConsoleScreenBufferInfo
 *
 * @implemented
 */
BOOL
STDCALL
GetConsoleScreenBufferInfo(
    HANDLE hConsoleOutput,
    PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo
    )
{
   CSR_API_MESSAGE Request; ULONG CsrRequest;
   
   NTSTATUS Status;

   CsrRequest = MAKE_CSR_API(SCREEN_BUFFER_INFO, CSR_CONSOLE);
   Request.Data.ScreenBufferInfoRequest.ConsoleHandle = hConsoleOutput;
   Status = CsrClientCallServer( &Request, NULL, CsrRequest, sizeof( CSR_API_MESSAGE ) );
   if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Request.Status ) )
      {
	 SetLastErrorByStatus ( Status );
	 return FALSE;
      }
   *lpConsoleScreenBufferInfo = Request.Data.ScreenBufferInfoRequest.Info;
   return TRUE;
}


/*--------------------------------------------------------------
 *	SetConsoleCursorPosition
 *
 * @implemented
 */
BOOL
STDCALL
SetConsoleCursorPosition(
    HANDLE hConsoleOutput,
    COORD dwCursorPosition
    )
{
   CSR_API_MESSAGE Request; ULONG CsrRequest;
   
   NTSTATUS Status;

   CsrRequest = MAKE_CSR_API(SET_CURSOR, CSR_CONSOLE);
   Request.Data.SetCursorRequest.ConsoleHandle = hConsoleOutput;
   Request.Data.SetCursorRequest.Position = dwCursorPosition;
   Status = CsrClientCallServer( &Request, NULL, CsrRequest, sizeof( CSR_API_MESSAGE ) );
   if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Request.Status ) )
      {
	 SetLastErrorByStatus ( Status );
	 return FALSE;
      }
   return TRUE;
}


static BOOL
IntFillConsoleOutputCharacter(HANDLE hConsoleOutput,
                              PVOID cCharacter,
                              DWORD nLength,
                              COORD dwWriteCoord,
                              LPDWORD lpNumberOfCharsWritten,
                              BOOL bUnicode)
{
  CSR_API_MESSAGE Request; ULONG CsrRequest;
  
  NTSTATUS Status;

  CsrRequest = MAKE_CSR_API(FILL_OUTPUT, CSR_CONSOLE);
  Request.Data.FillOutputRequest.ConsoleHandle = hConsoleOutput;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -