mirror of
https://github.com/reactos/reactos.git
synced 2024-08-27 21:58:49 +00:00
![Hermès Bélusca-Maïto](/assets/img/avatar_default.png)
CORE-15901 This fixes display reset transition when an external module acquired INBV ownership and then released it, similarly to what was done in commit0ad65796
for VIDEOPRT. For this a backup screenbuffer is used to store the contents of the screen just before an INBV screen acquire transition, and these contents are restored when it is detected that INBV ownership has been released. Also, the active text font associated with the active console code-page is restored, as well as the cursor state and shape. In addition, any user of BLUE.SYS is now required to explicitly issue a new IOCTL_CONSOLE_RESET_SCREEN to either enable or disable the screen. This allows avoiding nasty unwanted screen mode switches when a handle to the \Device\BlueScreen device is opened but no screen mode switch was actually wanted - This "fixes" this annoyance on ReactOS and Windows, when these are running witha VGA-compatible video driver and one wants to look at properties of the \Device\BlueScreen device using Sysinternals' WinObj. Following this, we don't need to check anymore for explicit INBV ownership by issuing calls to InbvCheckDisplayOwnership(), but instead we check whether the screen has beeen manually enabled using the aforementioned IOCTL. This partly supersedes commit8b553a4b
, and allows fixing the second bug, namely that if we start ReactOS without the /NOGUIBOOT option (and thus, INBV is active during boot), USETUP would not show up anything because BLUE.SYS wouldn't display anything on screen. See CORE-15901. [USETUP][CONSRV] Call IOCTL_CONSOLE_RESET_SCREEN to tell BlueScreen device to enable the screen.
690 lines
19 KiB
C
690 lines
19 KiB
C
/*
|
|
* ReactOS kernel
|
|
* Copyright (C) 2002 ReactOS Team
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS text-mode setup
|
|
* FILE: base/setup/usetup/console.c
|
|
* PURPOSE: Console support functions
|
|
* PROGRAMMER:
|
|
*/
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
#include <usetup.h>
|
|
/* Blue Driver Header */
|
|
#include <blue/ntddblue.h>
|
|
#include "keytrans.h"
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
/* DATA **********************************************************************/
|
|
|
|
static BOOLEAN InputQueueEmpty;
|
|
static BOOLEAN WaitForInput;
|
|
static KEYBOARD_INPUT_DATA InputDataQueue; // Only one element!
|
|
static IO_STATUS_BLOCK InputIosb;
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
BOOL
|
|
WINAPI
|
|
AllocConsole(VOID)
|
|
{
|
|
NTSTATUS Status;
|
|
UNICODE_STRING ScreenName = RTL_CONSTANT_STRING(L"\\??\\BlueScreen");
|
|
UNICODE_STRING KeyboardName = RTL_CONSTANT_STRING(L"\\Device\\KeyboardClass0");
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
ULONG Enable;
|
|
|
|
/* Open the screen */
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&ScreenName,
|
|
0,
|
|
NULL,
|
|
NULL);
|
|
Status = NtOpenFile(&StdOutput,
|
|
FILE_ALL_ACCESS,
|
|
&ObjectAttributes,
|
|
&IoStatusBlock,
|
|
FILE_OPEN,
|
|
FILE_SYNCHRONOUS_IO_ALERT);
|
|
if (!NT_SUCCESS(Status))
|
|
return FALSE;
|
|
|
|
/* Enable it */
|
|
Enable = TRUE;
|
|
Status = NtDeviceIoControlFile(StdOutput,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
IOCTL_CONSOLE_RESET_SCREEN,
|
|
&Enable,
|
|
sizeof(Enable),
|
|
NULL,
|
|
0);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
NtClose(StdOutput);
|
|
return FALSE;
|
|
}
|
|
|
|
/* Open the keyboard */
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&KeyboardName,
|
|
0,
|
|
NULL,
|
|
NULL);
|
|
Status = NtOpenFile(&StdInput,
|
|
FILE_ALL_ACCESS,
|
|
&ObjectAttributes,
|
|
&IoStatusBlock,
|
|
FILE_OPEN,
|
|
0);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
NtClose(StdOutput);
|
|
return FALSE;
|
|
}
|
|
|
|
/* Reset the queue state */
|
|
InputQueueEmpty = TRUE;
|
|
WaitForInput = FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
AttachConsole(
|
|
IN DWORD dwProcessId)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
FreeConsole(VOID)
|
|
{
|
|
/* Reset the queue state */
|
|
InputQueueEmpty = TRUE;
|
|
WaitForInput = FALSE;
|
|
|
|
if (StdInput != INVALID_HANDLE_VALUE)
|
|
NtClose(StdInput);
|
|
|
|
if (StdOutput != INVALID_HANDLE_VALUE)
|
|
NtClose(StdOutput);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
WriteConsole(
|
|
IN HANDLE hConsoleOutput,
|
|
IN const VOID *lpBuffer,
|
|
IN DWORD nNumberOfCharsToWrite,
|
|
OUT LPDWORD lpNumberOfCharsWritten,
|
|
IN LPVOID lpReserved)
|
|
{
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
NTSTATUS Status;
|
|
|
|
Status = NtWriteFile(hConsoleOutput,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
(PVOID)lpBuffer,
|
|
nNumberOfCharsToWrite,
|
|
NULL,
|
|
NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
return FALSE;
|
|
|
|
*lpNumberOfCharsWritten = IoStatusBlock.Information;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
HANDLE
|
|
WINAPI
|
|
GetStdHandle(
|
|
IN DWORD nStdHandle)
|
|
{
|
|
switch (nStdHandle)
|
|
{
|
|
case STD_INPUT_HANDLE:
|
|
return StdInput;
|
|
case STD_OUTPUT_HANDLE:
|
|
return StdOutput;
|
|
default:
|
|
return INVALID_HANDLE_VALUE;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
FlushConsoleInputBuffer(
|
|
IN HANDLE hConsoleInput)
|
|
{
|
|
NTSTATUS Status;
|
|
LARGE_INTEGER Offset, Timeout;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
KEYBOARD_INPUT_DATA InputData;
|
|
|
|
/* Cancel any pending read */
|
|
if (WaitForInput)
|
|
NtCancelIoFile(hConsoleInput, &IoStatusBlock);
|
|
|
|
/* Reset the queue state */
|
|
InputQueueEmpty = TRUE;
|
|
WaitForInput = FALSE;
|
|
|
|
/* Flush the keyboard buffer */
|
|
do
|
|
{
|
|
Offset.QuadPart = 0;
|
|
Status = NtReadFile(hConsoleInput,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
&InputData,
|
|
sizeof(InputData),
|
|
&Offset,
|
|
NULL);
|
|
if (Status == STATUS_PENDING)
|
|
{
|
|
Timeout.QuadPart = -100;
|
|
Status = NtWaitForSingleObject(hConsoleInput, FALSE, &Timeout);
|
|
if (Status == STATUS_TIMEOUT)
|
|
{
|
|
NtCancelIoFile(hConsoleInput, &IoStatusBlock);
|
|
return TRUE;
|
|
}
|
|
}
|
|
} while (NT_SUCCESS(Status));
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
PeekConsoleInput(
|
|
IN HANDLE hConsoleInput,
|
|
OUT PINPUT_RECORD lpBuffer,
|
|
IN DWORD nLength,
|
|
OUT LPDWORD lpNumberOfEventsRead)
|
|
{
|
|
NTSTATUS Status;
|
|
LARGE_INTEGER Offset, Timeout;
|
|
KEYBOARD_INPUT_DATA InputData;
|
|
|
|
if (InputQueueEmpty)
|
|
{
|
|
/* Read the keyboard for an event, without waiting */
|
|
if (!WaitForInput)
|
|
{
|
|
Offset.QuadPart = 0;
|
|
Status = NtReadFile(hConsoleInput,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&InputIosb,
|
|
&InputDataQueue,
|
|
sizeof(InputDataQueue),
|
|
&Offset,
|
|
NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
return FALSE;
|
|
if (Status == STATUS_PENDING)
|
|
{
|
|
/* No input yet, we will have to wait next time */
|
|
*lpNumberOfEventsRead = 0;
|
|
WaitForInput = TRUE;
|
|
return TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* We already tried to read from the keyboard and are
|
|
* waiting for data, check whether something showed up.
|
|
*/
|
|
Timeout.QuadPart = -100; // Wait just a little bit.
|
|
Status = NtWaitForSingleObject(hConsoleInput, FALSE, &Timeout);
|
|
if (Status == STATUS_TIMEOUT)
|
|
{
|
|
/* Nothing yet, continue waiting next time */
|
|
*lpNumberOfEventsRead = 0;
|
|
WaitForInput = TRUE;
|
|
return TRUE;
|
|
}
|
|
WaitForInput = FALSE;
|
|
if (!NT_SUCCESS(Status))
|
|
return FALSE;
|
|
}
|
|
|
|
/* We got something in the queue */
|
|
InputQueueEmpty = FALSE;
|
|
WaitForInput = FALSE;
|
|
}
|
|
|
|
/* Fetch from the queue but keep it inside */
|
|
InputData = InputDataQueue;
|
|
|
|
lpBuffer->EventType = KEY_EVENT;
|
|
Status = IntTranslateKey(hConsoleInput, &InputData, &lpBuffer->Event.KeyEvent);
|
|
if (!NT_SUCCESS(Status))
|
|
return FALSE;
|
|
|
|
*lpNumberOfEventsRead = 1;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
ReadConsoleInput(
|
|
IN HANDLE hConsoleInput,
|
|
OUT PINPUT_RECORD lpBuffer,
|
|
IN DWORD nLength,
|
|
OUT LPDWORD lpNumberOfEventsRead)
|
|
{
|
|
NTSTATUS Status;
|
|
LARGE_INTEGER Offset;
|
|
KEYBOARD_INPUT_DATA InputData;
|
|
|
|
if (InputQueueEmpty)
|
|
{
|
|
/* Read the keyboard and wait for an event, skipping the queue */
|
|
if (!WaitForInput)
|
|
{
|
|
Offset.QuadPart = 0;
|
|
Status = NtReadFile(hConsoleInput,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&InputIosb,
|
|
&InputDataQueue,
|
|
sizeof(InputDataQueue),
|
|
&Offset,
|
|
NULL);
|
|
if (Status == STATUS_PENDING)
|
|
{
|
|
/* Block and wait for input */
|
|
WaitForInput = TRUE;
|
|
Status = NtWaitForSingleObject(hConsoleInput, FALSE, NULL);
|
|
WaitForInput = FALSE;
|
|
Status = InputIosb.Status;
|
|
}
|
|
if (!NT_SUCCESS(Status))
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* We already tried to read from the keyboard and are
|
|
* waiting for data, block and wait for input.
|
|
*/
|
|
Status = NtWaitForSingleObject(hConsoleInput, FALSE, NULL);
|
|
WaitForInput = FALSE;
|
|
Status = InputIosb.Status;
|
|
if (!NT_SUCCESS(Status))
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/* Fetch from the queue and empty it */
|
|
InputData = InputDataQueue;
|
|
InputQueueEmpty = TRUE;
|
|
|
|
lpBuffer->EventType = KEY_EVENT;
|
|
Status = IntTranslateKey(hConsoleInput, &InputData, &lpBuffer->Event.KeyEvent);
|
|
if (!NT_SUCCESS(Status))
|
|
return FALSE;
|
|
|
|
*lpNumberOfEventsRead = 1;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
WriteConsoleOutputCharacterA(
|
|
HANDLE hConsoleOutput,
|
|
IN LPCSTR lpCharacter,
|
|
IN DWORD nLength,
|
|
IN COORD dwWriteCoord,
|
|
OUT LPDWORD lpNumberOfCharsWritten)
|
|
{
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
PCHAR Buffer;
|
|
COORD *pCoord;
|
|
PCHAR pText;
|
|
NTSTATUS Status;
|
|
|
|
Buffer = (CHAR*)RtlAllocateHeap(ProcessHeap,
|
|
0,
|
|
nLength + sizeof(COORD));
|
|
pCoord = (COORD *)Buffer;
|
|
pText = (PCHAR)(pCoord + 1);
|
|
|
|
*pCoord = dwWriteCoord;
|
|
memcpy(pText, lpCharacter, nLength);
|
|
|
|
Status = NtDeviceIoControlFile(hConsoleOutput,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER,
|
|
NULL,
|
|
0,
|
|
Buffer,
|
|
nLength + sizeof(COORD));
|
|
|
|
RtlFreeHeap(ProcessHeap, 0, Buffer);
|
|
if (!NT_SUCCESS(Status))
|
|
return FALSE;
|
|
|
|
*lpNumberOfCharsWritten = IoStatusBlock.Information;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
WriteConsoleOutputCharacterW(
|
|
HANDLE hConsoleOutput,
|
|
IN LPCWSTR lpCharacter,
|
|
IN DWORD nLength,
|
|
IN COORD dwWriteCoord,
|
|
OUT LPDWORD lpNumberOfCharsWritten)
|
|
{
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
PCHAR Buffer;
|
|
COORD *pCoord;
|
|
PCHAR pText;
|
|
NTSTATUS Status;
|
|
// ULONG i;
|
|
|
|
UNICODE_STRING UnicodeString;
|
|
OEM_STRING OemString;
|
|
ULONG OemLength;
|
|
|
|
UnicodeString.Length = nLength * sizeof(WCHAR);
|
|
UnicodeString.MaximumLength = nLength * sizeof(WCHAR);
|
|
UnicodeString.Buffer = (PWSTR)lpCharacter;
|
|
|
|
OemLength = RtlUnicodeStringToOemSize(&UnicodeString);
|
|
|
|
|
|
Buffer = (CHAR*)RtlAllocateHeap(ProcessHeap,
|
|
0,
|
|
OemLength + sizeof(COORD));
|
|
// nLength + sizeof(COORD));
|
|
if (Buffer== NULL)
|
|
return FALSE;
|
|
|
|
pCoord = (COORD *)Buffer;
|
|
pText = (PCHAR)(pCoord + 1);
|
|
|
|
*pCoord = dwWriteCoord;
|
|
|
|
OemString.Length = 0;
|
|
OemString.MaximumLength = OemLength;
|
|
OemString.Buffer = pText;
|
|
|
|
Status = RtlUnicodeStringToOemString(&OemString,
|
|
&UnicodeString,
|
|
FALSE);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
/* FIXME: use real unicode->oem conversion */
|
|
// for (i = 0; i < nLength; i++)
|
|
// pText[i] = (CHAR)lpCharacter[i];
|
|
|
|
Status = NtDeviceIoControlFile(hConsoleOutput,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER,
|
|
NULL,
|
|
0,
|
|
Buffer,
|
|
nLength + sizeof(COORD));
|
|
|
|
done:
|
|
RtlFreeHeap(ProcessHeap, 0, Buffer);
|
|
if (!NT_SUCCESS(Status))
|
|
return FALSE;
|
|
|
|
*lpNumberOfCharsWritten = IoStatusBlock.Information;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
FillConsoleOutputAttribute(
|
|
IN HANDLE hConsoleOutput,
|
|
IN WORD wAttribute,
|
|
IN DWORD nLength,
|
|
IN COORD dwWriteCoord,
|
|
OUT LPDWORD lpNumberOfAttrsWritten)
|
|
{
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
OUTPUT_ATTRIBUTE Buffer;
|
|
NTSTATUS Status;
|
|
|
|
Buffer.wAttribute = wAttribute;
|
|
Buffer.nLength = nLength;
|
|
Buffer.dwCoord = dwWriteCoord;
|
|
|
|
Status = NtDeviceIoControlFile(hConsoleOutput,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE,
|
|
&Buffer,
|
|
sizeof(OUTPUT_ATTRIBUTE),
|
|
&Buffer,
|
|
sizeof(OUTPUT_ATTRIBUTE));
|
|
if (!NT_SUCCESS(Status))
|
|
return FALSE;
|
|
|
|
*lpNumberOfAttrsWritten = Buffer.dwTransfered;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
FillConsoleOutputCharacterA(
|
|
IN HANDLE hConsoleOutput,
|
|
IN CHAR cCharacter,
|
|
IN DWORD nLength,
|
|
IN COORD dwWriteCoord,
|
|
OUT LPDWORD lpNumberOfCharsWritten)
|
|
{
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
OUTPUT_CHARACTER Buffer;
|
|
NTSTATUS Status;
|
|
|
|
Buffer.cCharacter = cCharacter;
|
|
Buffer.nLength = nLength;
|
|
Buffer.dwCoord = dwWriteCoord;
|
|
|
|
Status = NtDeviceIoControlFile(hConsoleOutput,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER,
|
|
&Buffer,
|
|
sizeof(OUTPUT_CHARACTER),
|
|
&Buffer,
|
|
sizeof(OUTPUT_CHARACTER));
|
|
if (!NT_SUCCESS(Status))
|
|
return FALSE;
|
|
|
|
*lpNumberOfCharsWritten = Buffer.dwTransfered;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
GetConsoleScreenBufferInfo(
|
|
IN HANDLE hConsoleOutput,
|
|
OUT PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo)
|
|
{
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
NTSTATUS Status;
|
|
|
|
Status = NtDeviceIoControlFile(hConsoleOutput,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO,
|
|
NULL,
|
|
0,
|
|
lpConsoleScreenBufferInfo,
|
|
sizeof(CONSOLE_SCREEN_BUFFER_INFO));
|
|
return NT_SUCCESS(Status);
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
SetConsoleCursorInfo(
|
|
IN HANDLE hConsoleOutput,
|
|
IN const CONSOLE_CURSOR_INFO *lpConsoleCursorInfo)
|
|
{
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
NTSTATUS Status;
|
|
|
|
Status = NtDeviceIoControlFile(hConsoleOutput,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
IOCTL_CONSOLE_SET_CURSOR_INFO,
|
|
(PCONSOLE_CURSOR_INFO)lpConsoleCursorInfo,
|
|
sizeof(CONSOLE_CURSOR_INFO),
|
|
NULL,
|
|
0);
|
|
return NT_SUCCESS(Status);
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
SetConsoleCursorPosition(
|
|
IN HANDLE hConsoleOutput,
|
|
IN COORD dwCursorPosition)
|
|
{
|
|
CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
NTSTATUS Status;
|
|
|
|
Status = GetConsoleScreenBufferInfo(hConsoleOutput, &ConsoleScreenBufferInfo);
|
|
if (!NT_SUCCESS(Status))
|
|
return FALSE;
|
|
|
|
ConsoleScreenBufferInfo.dwCursorPosition.X = dwCursorPosition.X;
|
|
ConsoleScreenBufferInfo.dwCursorPosition.Y = dwCursorPosition.Y;
|
|
|
|
Status = NtDeviceIoControlFile(hConsoleOutput,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO,
|
|
&ConsoleScreenBufferInfo,
|
|
sizeof(CONSOLE_SCREEN_BUFFER_INFO),
|
|
NULL,
|
|
0);
|
|
return NT_SUCCESS(Status);
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
SetConsoleTextAttribute(
|
|
IN HANDLE hConsoleOutput,
|
|
IN WORD wAttributes)
|
|
{
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
NTSTATUS Status;
|
|
|
|
Status = NtDeviceIoControlFile(hConsoleOutput,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE,
|
|
&wAttributes,
|
|
sizeof(USHORT),
|
|
NULL,
|
|
0);
|
|
return NT_SUCCESS(Status);
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
SetConsoleOutputCP(
|
|
IN UINT wCodepage)
|
|
{
|
|
HANDLE hConsoleOutput;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
NTSTATUS Status;
|
|
|
|
hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
|
|
Status = NtDeviceIoControlFile(hConsoleOutput,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatusBlock,
|
|
IOCTL_CONSOLE_LOADFONT,
|
|
&wCodepage,
|
|
sizeof(ULONG),
|
|
NULL,
|
|
0);
|
|
return NT_SUCCESS(Status);
|
|
}
|
|
|
|
|
|
/* EOF */
|