📄 console.c
字号:
}
/*
* @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 + -