Windows2003-3790/windows/core/ntcon/client/stream.c
2020-09-30 16:53:55 +02:00

847 lines
23 KiB
C

/*++
Copyright (c) 1985 - 1999, Microsoft Corporation
Module Name:
stream.c
Abstract:
This module contains the stubs for the console stream API.
Author:
Therese Stowell (thereses) 3-Dec-1990
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#if !defined(BUILD_WOW64)
HANDLE InputWaitHandle = INVALID_HANDLE_VALUE;
HANDLE
APIENTRY
GetConsoleInputWaitHandle( VOID )
{
return InputWaitHandle;
}
#endif //!defined(BUILD_WOW64)
#if !defined(BUILD_WOW6432)
HANDLE
APIENTRY
OpenConsoleWInternal(
IN ULONG HandleType,
IN ULONG DesiredAccess,
IN BOOL InheritHandle,
IN ULONG ShareMode
)
/*++
Routine Description:
Marshals parameters for the ConsolepOpenConsole command.
Arguments:
See the CONSOLE_OPENCONSOLE_MSG structure and OpenConsoleW.
Return Value:
INVALID_HANDLE_VALUE - An error occured.
--*/
{
CONSOLE_API_MSG m;
PCONSOLE_OPENCONSOLE_MSG a = &m.u.OpenConsole;
a->ConsoleHandle = GET_CONSOLE_HANDLE;
a->HandleType = HandleType;
a->DesiredAccess = DesiredAccess;
a->InheritHandle = InheritHandle;
a->ShareMode= ShareMode;
CsrClientCallServer( (PCSR_API_MSG)&m,
NULL,
CSR_MAKE_API_NUMBER( CONSRV_SERVERDLL_INDEX,
ConsolepOpenConsole
),
sizeof( *a )
);
if (!NT_SUCCESS( m.ReturnValue)) {
SET_LAST_NT_ERROR(m.ReturnValue);
return INVALID_HANDLE_VALUE;
}
else {
return a->Handle;
}
}
#endif // !defined(BUILD_WOW6432)
#if !defined(BUILD_WOW64)
HANDLE
APIENTRY
OpenConsoleW(
IN LPWSTR lpConsoleDevice,
IN DWORD dwDesiredAccess,
IN BOOL bInheritHandle,
IN DWORD dwShareMode
)
/*++
Parameters:
lpConsoleDevice - Supplies the console device name to open. "CONIN$"
indicates console input. "CONOUT$" indicates console output. The
caller must have appropriate access to the console for this call to
succeed.
dwDesiredAccess - Supplies the caller's desired access to the console
device.
DesiredAccess Flags:
GENERIC_READ - Read access to the console device is requested. This
allows data to be read from the console device.
GENERIC_WRITE - Write access to the console device is requested. This
allows data to be written to the console device.
bInheritHandle - Supplies a flag that indicates whether or not the
returned handle is to be inherited by a new process
during a CreateProcess. A value of TRUE indicates that the
new process will inherit the handle.
dwShareMode - Supplies a set of flags that indicates how this console
device is to be shared with other openers of the console device. A
value of zero for this parameter indicates no sharing of the console,
or exclusive access to the console is to occur.
ShareMode Flags:
FILE_SHARE_READ - Other open operations may be performed on the
console device for read access.
FILE_SHARE_WRITE - Other open operations may be performed on the
console device for write access.
Return Value:
Not -1 - Returns an open handle to the specified console device.
Subsequent access to the file is controlled by the DesiredAccess
parameter.
0xffffffff - The operation failed. Extended error status is available
using GetLastError.
--*/
{
ULONG HandleType;
try {
if (CompareStringW(LOCALE_INVARIANT,
NORM_IGNORECASE,
lpConsoleDevice,
-1,
CONSOLE_INPUT_STRING,
-1) == CSTR_EQUAL) {
HandleType = CONSOLE_INPUT_HANDLE;
}
else if (CompareStringW(LOCALE_INVARIANT,
NORM_IGNORECASE,
lpConsoleDevice,
-1,
CONSOLE_OUTPUT_STRING,
-1) == CSTR_EQUAL) {
HandleType = CONSOLE_OUTPUT_HANDLE;
}
else {
SET_LAST_ERROR(ERROR_INVALID_PARAMETER);
return INVALID_HANDLE_VALUE;
}
} except( EXCEPTION_EXECUTE_HANDLER ) {
SET_LAST_ERROR(ERROR_INVALID_ACCESS);
return INVALID_HANDLE_VALUE;
}
if (dwDesiredAccess & ~VALID_ACCESSES ||
dwShareMode & ~VALID_SHARE_ACCESSES) {
SET_LAST_ERROR(ERROR_INVALID_PARAMETER);
return INVALID_HANDLE_VALUE;
}
return OpenConsoleWInternal(HandleType,
dwDesiredAccess,
bInheritHandle,
dwShareMode
);
}
#endif // !defined(BUILD_WOW64)
#if !defined(BUILD_WOW6432)
BOOL
APIENTRY
ReadConsoleInternal(
IN HANDLE hConsoleInput,
OUT LPVOID lpBuffer,
IN DWORD nNumberOfCharsToRead,
OUT LPDWORD lpNumberOfCharsRead,
IN OUT LPVOID lpReserved,
IN BOOLEAN Unicode,
IN USHORT ExeNameLength,
IN LPWSTR ExeName
)
/*++
Parameters:
hConsoleInput - Supplies an open handle to "CONIN$" open for GENERIC_READ
or the StdIn handle.
lpBuffer - Supplies the address of a buffer to receive the data read
from the console input.
nNumberOfBytesToRead - Supplies the number of bytes to read from the
input buffer.
lpReserved - Ignore unless 4.0 application, in which case it points
to a CONSOLE_READCONSOLE_CONTROL data structure. UNICODE only.
If !Unicode, then call fails if this parameter is non-NULL
Unicode - TRUE if call from ReadConsoleW, FALSE if ReadConsoleA
Return Value:
NON-NULL - Returns the number of bytes actually read from the input buffer.
FALSE/NULL - The operation failed.
Extended error status is available using GetLastError.
--*/
{
PCSR_CAPTURE_HEADER CaptureBuffer;
CONSOLE_API_MSG m;
PCONSOLE_READCONSOLE_MSG a = &m.u.ReadConsole;
BOOLEAN Dummy;
PCONSOLE_READCONSOLE_CONTROL pInputControl;
NTSTATUS Status;
a->ConsoleHandle = GET_CONSOLE_HANDLE;
a->InputHandle = hConsoleInput;
a->ExeNameLength = ExeNameLength;
RtlCopyMemory(a->Buffer, ExeName, ExeNameLength);
a->Unicode = Unicode;
//
// if ansi, make capture buffer large enough to hold translated
// string. this will make server side code much simpler.
//
a->CaptureBufferSize = a->NumBytes = nNumberOfCharsToRead * sizeof(WCHAR);
if (a->CaptureBufferSize > BUFFER_SIZE) {
CaptureBuffer = CsrAllocateCaptureBuffer( 1,
a->CaptureBufferSize
);
if (CaptureBuffer == NULL) {
SET_LAST_ERROR(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
CsrCaptureMessageBuffer( CaptureBuffer,
NULL,
a->CaptureBufferSize,
(PVOID *) &a->BufPtr
);
}
else {
a->BufPtr = a->Buffer;
CaptureBuffer = NULL;
}
pInputControl = (PCONSOLE_READCONSOLE_CONTROL)lpReserved;
a->InitialNumBytes = 0;
a->CtrlWakeupMask = 0;
a->ControlKeyState = 0;
Status = STATUS_SUCCESS;
try {
if (Unicode &&
ARGUMENT_PRESENT(lpReserved) &&
NtCurrentPeb()->ImageSubsystemMajorVersion >= 4 &&
pInputControl->nLength == sizeof(*pInputControl)
) {
if ((pInputControl->nInitialChars > nNumberOfCharsToRead)) {
Status = STATUS_INVALID_PARAMETER;
} else {
a->InitialNumBytes = pInputControl->nInitialChars * sizeof(WCHAR);
if (pInputControl->nInitialChars != 0) {
RtlCopyMemory( a->BufPtr, lpBuffer, a->InitialNumBytes );
}
a->CtrlWakeupMask = pInputControl->dwCtrlWakeupMask;
}
} else {
pInputControl = NULL;
}
} except( EXCEPTION_EXECUTE_HANDLER ) {
Status = GetExceptionCode();
}
if (!NT_SUCCESS(Status) && pInputControl != NULL) {
if (CaptureBuffer != NULL) {
CsrFreeCaptureBuffer( CaptureBuffer );
}
SET_LAST_NT_ERROR(Status);
return FALSE;
}
CsrClientCallServer( (PCSR_API_MSG)&m,
CaptureBuffer,
CSR_MAKE_API_NUMBER( CONSRV_SERVERDLL_INDEX,
ConsolepReadConsole
),
sizeof( *a )
);
if (NT_SUCCESS( m.ReturnValue )) {
try {
*lpNumberOfCharsRead = a->NumBytes;
if (Unicode) {
*lpNumberOfCharsRead /= sizeof(WCHAR);
if (pInputControl != NULL) {
pInputControl->dwControlKeyState = a->ControlKeyState;
}
}
RtlCopyMemory( lpBuffer, a->BufPtr, a->NumBytes );
} except( EXCEPTION_EXECUTE_HANDLER ) {
if (CaptureBuffer != NULL) {
CsrFreeCaptureBuffer( CaptureBuffer );
}
SET_LAST_ERROR(ERROR_INVALID_ACCESS);
return FALSE;
}
}
if (CaptureBuffer != NULL) {
CsrFreeCaptureBuffer( CaptureBuffer );
}
if (!NT_SUCCESS( m.ReturnValue )) {
SET_LAST_NT_ERROR(m.ReturnValue);
return FALSE;
} else if (m.ReturnValue == STATUS_ALERTED) {
// ctrl-c or ctrl-break
NtYieldExecution();
SET_LAST_ERROR(ERROR_OPERATION_ABORTED);
}
return TRUE;
}
#endif //!defined(BUILD_WOW6432)
#if !defined(BUILD_WOW64)
BOOL
APIENTRY
ReadConsoleA(
IN HANDLE hConsoleInput,
OUT LPVOID lpBuffer,
IN DWORD nNumberOfCharsToRead,
OUT LPDWORD lpNumberOfCharsRead,
IN OUT LPVOID lpReserved
)
{
WCHAR ExeName[BUFFER_SIZE/2];
USHORT ExeNameLength;
ExeNameLength = GetCurrentExeName(ExeName, sizeof(ExeName));
return ReadConsoleInternal(hConsoleInput,
lpBuffer,
nNumberOfCharsToRead,
lpNumberOfCharsRead,
NULL,
FALSE,
ExeNameLength,
ExeName
);
UNREFERENCED_PARAMETER(lpReserved);
}
BOOL
APIENTRY
ReadConsoleW(
IN HANDLE hConsoleInput,
OUT LPVOID lpBuffer,
IN DWORD nNumberOfCharsToRead,
OUT LPDWORD lpNumberOfCharsRead,
IN OUT LPVOID lpReserved
)
{
WCHAR ExeName[BUFFER_SIZE/2];
USHORT ExeNameLength;
ExeNameLength = GetCurrentExeName(ExeName, sizeof(ExeName));
return ReadConsoleInternal(hConsoleInput,
lpBuffer,
nNumberOfCharsToRead,
lpNumberOfCharsRead,
lpReserved,
TRUE,
ExeNameLength,
ExeName
);
UNREFERENCED_PARAMETER(lpReserved);
}
#endif //!defined(BUILD_WOW64)
#if !defined(BUILD_WOW6432)
BOOL
APIENTRY
WriteConsoleInternal(
IN HANDLE hConsoleOutput,
IN CONST VOID *lpBuffer,
IN DWORD nNumberOfCharsToWrite,
OUT LPDWORD lpNumberOfCharsWritten,
IN BOOLEAN Unicode
)
/*++
Parameters:
hFile - Supplies an open handle to to "CONOUT$" open for GENERIC_WRITE
or the StdOut or StdErr handle.
lpBuffer - Supplies the address of the data that is to be written to
the console output.
nNumberOfBytesToWrite - Supplies the number of bytes to write to the
console output.
Return Value:
NON-NULL - Returns the number of bytes actually written to the device.
FALSE/NULL - The operation failed.
Extended error status is available using GetLastError.
--*/
{
PCSR_CAPTURE_HEADER CaptureBuffer;
CONSOLE_API_MSG m;
PCONSOLE_WRITECONSOLE_MSG a = &m.u.WriteConsole;
a->ConsoleHandle = GET_CONSOLE_HANDLE;
a->OutputHandle = hConsoleOutput;
if (Unicode) {
a->NumBytes = nNumberOfCharsToWrite * sizeof(WCHAR);
} else {
a->NumBytes = nNumberOfCharsToWrite;
}
a->Unicode = Unicode;
if (a->NumBytes > BUFFER_SIZE) {
CaptureBuffer = CsrAllocateCaptureBuffer( 1,
a->NumBytes
);
if (CaptureBuffer == NULL) {
SET_LAST_ERROR(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
CsrCaptureMessageBuffer( CaptureBuffer,
(PCHAR) lpBuffer,
a->NumBytes,
(PVOID *) &a->BufPtr
);
a->BufferInMessage = FALSE;
}
else {
a->BufPtr = a->Buffer;
try {
RtlCopyMemory( a->BufPtr, lpBuffer, a->NumBytes);
} except( EXCEPTION_EXECUTE_HANDLER ) {
SET_LAST_ERROR(ERROR_INVALID_ACCESS);
return FALSE;
}
CaptureBuffer = NULL;
a->BufferInMessage = TRUE;
}
CsrClientCallServer( (PCSR_API_MSG)&m,
CaptureBuffer,
CSR_MAKE_API_NUMBER( CONSRV_SERVERDLL_INDEX,
ConsolepWriteConsole
),
sizeof( *a )
);
if (CaptureBuffer != NULL) {
CsrFreeCaptureBuffer( CaptureBuffer );
}
if (!NT_SUCCESS( m.ReturnValue )) {
SET_LAST_NT_ERROR(m.ReturnValue);
return FALSE;
}
try {
*lpNumberOfCharsWritten = a->NumBytes;
if (Unicode) {
*lpNumberOfCharsWritten /= sizeof(WCHAR);
}
} except( EXCEPTION_EXECUTE_HANDLER ) {
SET_LAST_ERROR(ERROR_INVALID_ACCESS);
return FALSE;
}
return TRUE;
}
#endif //!defined(BUILD_WOW6432)
#if !defined(BUILD_WOW64)
BOOL
APIENTRY
WriteConsoleA(
IN HANDLE hConsoleOutput,
IN CONST VOID *lpBuffer,
IN DWORD nNumberOfCharsToWrite,
OUT LPDWORD lpNumberOfCharsWritten,
IN OUT LPVOID lpReserved
)
{
return WriteConsoleInternal(hConsoleOutput,
lpBuffer,
nNumberOfCharsToWrite,
lpNumberOfCharsWritten,
FALSE
);
UNREFERENCED_PARAMETER(lpReserved);
}
BOOL
APIENTRY
WriteConsoleW(
IN HANDLE hConsoleOutput,
IN CONST VOID *lpBuffer,
IN DWORD nNumberOfCharsToWrite,
OUT LPDWORD lpNumberOfCharsWritten,
IN OUT LPVOID lpReserved
)
{
return WriteConsoleInternal(hConsoleOutput,
lpBuffer,
nNumberOfCharsToWrite,
lpNumberOfCharsWritten,
TRUE
);
UNREFERENCED_PARAMETER(lpReserved);
}
#endif //!defined(BUILD_WOW64)
#if !defined(BUILD_WOW6432)
BOOL
APIENTRY
CloseConsoleHandle(
IN HANDLE hConsole
)
/*++
Parameters:
hConsole - An open handle to console input or output.
Return Value:
TRUE - The operation was successful.
FALSE/NULL - The operation failed. Extended error status is available
using GetLastError.
--*/
{
CONSOLE_API_MSG m;
PCONSOLE_CLOSEHANDLE_MSG a = &m.u.CloseHandle;
a->ConsoleHandle = GET_CONSOLE_HANDLE;
a->Handle = hConsole;
CsrClientCallServer( (PCSR_API_MSG)&m,
NULL,
CSR_MAKE_API_NUMBER( CONSRV_SERVERDLL_INDEX,
ConsolepCloseHandle
),
sizeof( *a )
);
if (NT_SUCCESS( m.ReturnValue )) {
return TRUE;
} else {
SET_LAST_NT_ERROR (m.ReturnValue);
return FALSE;
}
}
HANDLE
APIENTRY
DuplicateConsoleHandle(
IN HANDLE hSourceHandle,
IN DWORD dwDesiredAccess,
IN BOOL bInheritHandle,
IN DWORD dwOptions
)
/*++
Parameters:
hSourceHandle - An open handle to the console device.
dwDesiredAccess - The access requested to for the new handle. This
access must be equal to or a proper subset of the granted access
associated with the SourceHandle. This parameter is ignored if
the DUPLICATE_SAME_ACCESS option is specified.
bInheritHandle - Supplies a flag that if TRUE, marks the target
handle as inheritable. If this is the case, then the target
handle will be inherited to new processes each time the target
process creates a new process using CreateProcess.
dwOptions - Specifies optional behaviors for the caller.
Options Flags:
DUPLICATE_CLOSE_SOURCE - The SourceHandle will be closed by
this service prior to returning to the caller. This occurs
regardless of any error status returned.
DUPLICATE_SAME_ACCESS - The DesiredAccess parameter is ignored
and instead the GrantedAccess associated with SourceHandle
is used as the DesiredAccess when creating the TargetHandle.
Return Value:
Not -1 - Returns an open handle to the specified console device.
Subsequent access to the file is controlled by the DesiredAccess
parameter.
0xffffffff - The operation failed. Extended error status is available
using GetLastError.
--*/
{
CONSOLE_API_MSG m;
PCONSOLE_DUPHANDLE_MSG a = &m.u.DuplicateHandle;
if (dwOptions & ~VALID_DUP_OPTIONS) {
SET_LAST_ERROR(ERROR_INVALID_PARAMETER);
return INVALID_HANDLE_VALUE;
}
if (((dwOptions & DUPLICATE_SAME_ACCESS) == 0) &&
(dwDesiredAccess & ~VALID_ACCESSES)) {
SET_LAST_ERROR(ERROR_INVALID_PARAMETER);
return INVALID_HANDLE_VALUE;
}
a->ConsoleHandle = GET_CONSOLE_HANDLE;
a->SourceHandle = hSourceHandle;
a->DesiredAccess = dwDesiredAccess;
a->InheritHandle = (BOOLEAN) bInheritHandle;
a->Options = dwOptions;
CsrClientCallServer( (PCSR_API_MSG)&m,
NULL,
CSR_MAKE_API_NUMBER( CONSRV_SERVERDLL_INDEX,
ConsolepDupHandle
),
sizeof( *a )
);
if (NT_SUCCESS( m.ReturnValue )) {
return a->TargetHandle;
} else {
SET_LAST_NT_ERROR (m.ReturnValue);
return INVALID_HANDLE_VALUE;
}
}
BOOL
APIENTRY
GetConsoleHandleInformation(
IN HANDLE hObject,
OUT LPDWORD lpdwFlags
)
/*++
Parameters:
hObject - An open handle to console input or output.
lpdwFlags - Receives flags for console object.
Return Value:
TRUE - The operation was successful.
FALSE/NULL - The operation failed. Extended error status is available
using GetLastError.
--*/
{
CONSOLE_API_MSG m;
PCONSOLE_GETHANDLEINFORMATION_MSG a = &m.u.GetHandleInformation;
a->ConsoleHandle = GET_CONSOLE_HANDLE;
a->Handle = hObject;
CsrClientCallServer( (PCSR_API_MSG)&m,
NULL,
CSR_MAKE_API_NUMBER( CONSRV_SERVERDLL_INDEX,
ConsolepGetHandleInformation
),
sizeof( *a )
);
if (NT_SUCCESS( m.ReturnValue )) {
try {
*lpdwFlags = a->Flags;
} except( EXCEPTION_EXECUTE_HANDLER ) {
SET_LAST_ERROR(ERROR_INVALID_ACCESS);
return FALSE;
}
return TRUE;
} else {
SET_LAST_NT_ERROR (m.ReturnValue);
return FALSE;
}
}
BOOL
APIENTRY
SetConsoleHandleInformation(
IN HANDLE hObject,
IN DWORD dwMask,
IN DWORD dwFlags
)
/*++
Parameters:
hObject - An open handle to console input or output.
dwMask - Flags to change.
dwFlags - New values for flags.
Return Value:
TRUE - The operation was successful.
FALSE/NULL - The operation failed. Extended error status is available
using GetLastError.
--*/
{
CONSOLE_API_MSG m;
PCONSOLE_SETHANDLEINFORMATION_MSG a = &m.u.SetHandleInformation;
a->ConsoleHandle = GET_CONSOLE_HANDLE;
a->Handle = hObject;
a->Mask = dwMask;
a->Flags = dwFlags;
CsrClientCallServer( (PCSR_API_MSG)&m,
NULL,
CSR_MAKE_API_NUMBER( CONSRV_SERVERDLL_INDEX,
ConsolepSetHandleInformation
),
sizeof( *a )
);
if (NT_SUCCESS( m.ReturnValue )) {
return TRUE;
} else {
SET_LAST_NT_ERROR (m.ReturnValue);
return FALSE;
}
}
BOOL
APIENTRY
VerifyConsoleIoHandle(
IN HANDLE hIoHandle
)
/*++
Parameters:
hIoHandle - Handle to verify
Return Value:
TRUE - handle is a valid console handle.
FALSE - handle is not a valid console handle.
--*/
{
CONSOLE_API_MSG m;
PCONSOLE_VERIFYIOHANDLE_MSG a = &m.u.VerifyConsoleIoHandle;
a->ConsoleHandle = GET_CONSOLE_HANDLE;
a->Handle = hIoHandle;
//
// If this process doesn't have a console handle, bail immediately.
//
if (a->ConsoleHandle == NULL) {
return FALSE;
}
CsrClientCallServer( (PCSR_API_MSG)&m,
NULL,
CSR_MAKE_API_NUMBER( CONSRV_SERVERDLL_INDEX,
ConsolepVerifyIoHandle
),
sizeof( *a )
);
if (NT_SUCCESS( m.ReturnValue )) {
return a->Valid;
} else {
SET_LAST_NT_ERROR (m.ReturnValue);
return FALSE;
}
}
#endif //!defined(BUILD_WOW6432)