Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1740 lines
59 KiB

/*++
Copyright (c) 1985 - 1999, Microsoft Corporation
Module Name:
directio.c
Abstract:
This file implements the NT console direct I/O API
Author:
Therese Stowell (thereses) 6-Nov-1990
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#if defined(FE_SB)
#define WWSB_FE
#include "dispatch.h" // get the FE_ prototypes
#undef WWSB_FE
#pragma alloc_text(FE_TEXT, FE_TranslateInputToOem)
#pragma alloc_text(FE_TEXT, FE_TranslateInputToUnicode)
#pragma alloc_text(FE_TEXT, FE_TranslateOutputToOem)
#pragma alloc_text(FE_TEXT, FE_TranslateOutputToOemUnicode)
#pragma alloc_text(FE_TEXT, FE_TranslateOutputToUnicode)
#pragma alloc_text(FE_TEXT, FE_TranslateOutputToAnsiUnicode)
#endif
#if defined(FE_SB)
ULONG
SB_TranslateInputToOem
#else
NTSTATUS
TranslateInputToOem
#endif
(
IN PCONSOLE_INFORMATION Console,
IN OUT PINPUT_RECORD InputRecords,
IN ULONG NumRecords
)
{
ULONG i;
DBGCHARS(("TranslateInputToOem\n"));
for (i=0;i<NumRecords;i++) {
if (InputRecords[i].EventType == KEY_EVENT) {
InputRecords[i].Event.KeyEvent.uChar.AsciiChar = WcharToChar(
Console->CP, InputRecords[i].Event.KeyEvent.uChar.UnicodeChar);
}
}
#if defined(FE_SB)
return NumRecords;
#else
return STATUS_SUCCESS;
#endif
}
#if defined(FE_SB)
ULONG
FE_TranslateInputToOem(
IN PCONSOLE_INFORMATION Console,
IN OUT PINPUT_RECORD InputRecords,
IN ULONG NumRecords, // in : ASCII byte count
IN ULONG UnicodeLength, // in : Number of events (char count)
OUT PINPUT_RECORD DbcsLeadInpRec
)
{
ULONG i,j;
PINPUT_RECORD TmpInpRec;
BYTE AsciiDbcs[2];
ULONG NumBytes;
ASSERT(NumRecords >= UnicodeLength);
TmpInpRec = ConsoleHeapAlloc(TMP_DBCS_TAG, NumRecords*sizeof(INPUT_RECORD));
if (TmpInpRec == NULL)
return 0;
memcpy(TmpInpRec,InputRecords,NumRecords*sizeof(INPUT_RECORD));
AsciiDbcs[1] = 0;
for (i=0,j=0; i<UnicodeLength; i++,j++) {
if (TmpInpRec[i].EventType == KEY_EVENT) {
if (IsConsoleFullWidth(Console->hDC,
Console->CP,TmpInpRec[i].Event.KeyEvent.uChar.UnicodeChar)) {
NumBytes = sizeof(AsciiDbcs);
ConvertToOem(Console->CP,
&TmpInpRec[i].Event.KeyEvent.uChar.UnicodeChar,
1,
&AsciiDbcs[0],
NumBytes
);
if (IsDBCSLeadByteConsole(AsciiDbcs[0],&Console->CPInfo)) {
if (j < NumRecords-1) { // -1 is safe DBCS in buffer
InputRecords[j] = TmpInpRec[i];
InputRecords[j].Event.KeyEvent.uChar.UnicodeChar = 0;
InputRecords[j].Event.KeyEvent.uChar.AsciiChar = AsciiDbcs[0];
j++;
InputRecords[j] = TmpInpRec[i];
InputRecords[j].Event.KeyEvent.uChar.UnicodeChar = 0;
InputRecords[j].Event.KeyEvent.uChar.AsciiChar = AsciiDbcs[1];
AsciiDbcs[1] = 0;
}
else if (j == NumRecords-1) {
InputRecords[j] = TmpInpRec[i];
InputRecords[j].Event.KeyEvent.uChar.UnicodeChar = 0;
InputRecords[j].Event.KeyEvent.uChar.AsciiChar = AsciiDbcs[0];
j++;
break;
}
else {
AsciiDbcs[1] = 0;
break;
}
}
else {
InputRecords[j] = TmpInpRec[i];
InputRecords[j].Event.KeyEvent.uChar.UnicodeChar = 0;
InputRecords[j].Event.KeyEvent.uChar.AsciiChar = AsciiDbcs[0];
AsciiDbcs[1] = 0;
}
}
else {
InputRecords[j] = TmpInpRec[i];
ConvertToOem(Console->CP,
&InputRecords[j].Event.KeyEvent.uChar.UnicodeChar,
1,
&InputRecords[j].Event.KeyEvent.uChar.AsciiChar,
1
);
}
}
}
if (DbcsLeadInpRec) {
if (AsciiDbcs[1]) {
*DbcsLeadInpRec = TmpInpRec[i];
DbcsLeadInpRec->Event.KeyEvent.uChar.AsciiChar = AsciiDbcs[1];
}
else {
RtlZeroMemory(DbcsLeadInpRec,sizeof(INPUT_RECORD));
}
}
ConsoleHeapFree(TmpInpRec);
return j;
}
#endif
#if defined(FE_SB)
ULONG
SB_TranslateInputToUnicode
#else
NTSTATUS
TranslateInputToUnicode
#endif
(
IN PCONSOLE_INFORMATION Console,
IN OUT PINPUT_RECORD InputRecords,
IN ULONG NumRecords
)
{
ULONG i;
DBGCHARS(("TranslateInputToUnicode\n"));
for (i=0;i<NumRecords;i++) {
if (InputRecords[i].EventType == KEY_EVENT) {
#if defined(FE_SB)
InputRecords[i].Event.KeyEvent.uChar.UnicodeChar = SB_CharToWchar(
Console->CP, InputRecords[i].Event.KeyEvent.uChar.AsciiChar);
#else
InputRecords[i].Event.KeyEvent.uChar.UnicodeChar = CharToWchar(
Console->CP, InputRecords[i].Event.KeyEvent.uChar.AsciiChar);
#endif
}
}
#if defined(FE_SB)
return i;
#else
return STATUS_SUCCESS;
#endif
}
#if defined(FE_SB)
ULONG
FE_TranslateInputToUnicode(
IN PCONSOLE_INFORMATION Console,
IN OUT PINPUT_RECORD InputRecords,
IN ULONG NumRecords,
IN OUT PINPUT_RECORD DBCSLeadByte
)
{
ULONG i,j;
INPUT_RECORD AsciiDbcs[2];
CHAR Strings[2];
WCHAR UnicodeDbcs[2];
PWCHAR Uni;
ULONG NumBytes;
if (DBCSLeadByte->Event.KeyEvent.uChar.AsciiChar) {
AsciiDbcs[0] = *DBCSLeadByte;
Strings[0] = DBCSLeadByte->Event.KeyEvent.uChar.AsciiChar;
}
else{
RtlZeroMemory(AsciiDbcs,sizeof(AsciiDbcs));
}
for (i=j=0; i<NumRecords; i++) {
if (InputRecords[i].EventType == KEY_EVENT) {
if (AsciiDbcs[0].Event.KeyEvent.uChar.AsciiChar) {
AsciiDbcs[1] = InputRecords[i];
Strings[1] = InputRecords[i].Event.KeyEvent.uChar.AsciiChar;
NumBytes = sizeof(Strings);
NumBytes = ConvertInputToUnicode(Console->CP,
&Strings[0],
NumBytes,
&UnicodeDbcs[0],
NumBytes);
Uni = &UnicodeDbcs[0];
while (NumBytes--) {
InputRecords[j] = AsciiDbcs[0];
InputRecords[j].Event.KeyEvent.uChar.UnicodeChar = *Uni++;
j++;
}
RtlZeroMemory(AsciiDbcs,sizeof(AsciiDbcs));
if (DBCSLeadByte->Event.KeyEvent.uChar.AsciiChar)
RtlZeroMemory(DBCSLeadByte,sizeof(INPUT_RECORD));
}
else if (IsDBCSLeadByteConsole(InputRecords[i].Event.KeyEvent.uChar.AsciiChar,&Console->CPInfo)) {
if (i < NumRecords-1) {
AsciiDbcs[0] = InputRecords[i];
Strings[0] = InputRecords[i].Event.KeyEvent.uChar.AsciiChar;
}
else {
*DBCSLeadByte = InputRecords[i];
break;
}
}
else {
CHAR c;
InputRecords[j] = InputRecords[i];
c = InputRecords[i].Event.KeyEvent.uChar.AsciiChar;
ConvertInputToUnicode(Console->CP,
&c,
1,
&InputRecords[j].Event.KeyEvent.uChar.UnicodeChar,
1);
j++;
}
}
else {
InputRecords[j++] = InputRecords[i];
}
}
return j;
}
#endif
BOOLEAN
DirectReadWaitRoutine(
IN PLIST_ENTRY WaitQueue,
IN PCSR_THREAD WaitingThread,
IN PCSR_API_MSG WaitReplyMessage,
IN PVOID WaitParameter,
IN PVOID SatisfyParameter1,
IN PVOID SatisfyParameter2,
IN ULONG WaitFlags
)
/*++
Routine Description:
This routine is called to complete a direct read that blocked in
ReadInputBuffer. The context of the read was saved in the DirectReadData
structure. This routine is called when events have been written to
the input buffer. It is called in the context of the writing thread.
Arguments:
WaitQueue - Pointer to queue containing wait block.
WaitingThread - Pointer to waiting thread.
WaitReplyMessage - Pointer to reply message to return to dll when
read is completed.
DirectReadData - Context of read.
SatisfyParameter1 - Unused.
SatisfyParameter2 - Unused.
WaitFlags - Flags indicating status of wait.
Return Value:
--*/
{
PCONSOLE_GETCONSOLEINPUT_MSG a;
PINPUT_RECORD Buffer;
NTSTATUS Status;
PCONSOLE_INFORMATION Console;
PDIRECT_READ_DATA DirectReadData;
PHANDLE_DATA HandleData;
BOOLEAN RetVal = TRUE;
#if defined(FE_SB)
BOOLEAN fAddDbcsLead = FALSE;
PDWORD nLength;
#endif
a = (PCONSOLE_GETCONSOLEINPUT_MSG)&WaitReplyMessage->u.ApiMessageData;
DirectReadData = (PDIRECT_READ_DATA) WaitParameter;
Status = DereferenceIoHandleNoCheck(DirectReadData->ProcessData,
DirectReadData->HandleIndex,
&HandleData
);
ASSERT (NT_SUCCESS(Status));
if (!NT_SUCCESS(Status)) {
return TRUE;
}
//
// see if this routine was called by CloseInputHandle. if it
// was, see if this wait block corresponds to the dying handle.
// if it doesn't, just return.
//
if (SatisfyParameter1 != NULL &&
SatisfyParameter1 != HandleData) {
return FALSE;
}
//
// if ctrl-c or ctrl-break was seen, ignore it.
//
if ((ULONG_PTR)SatisfyParameter2 & (CONSOLE_CTRL_C_SEEN | CONSOLE_CTRL_BREAK_SEEN)) {
return FALSE;
}
Console = DirectReadData->Console;
#if defined(FE_SB)
if (CONSOLE_IS_DBCS_CP(Console) && !a->Unicode) {
if (HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte.Event.KeyEvent.uChar.AsciiChar) {
if (a->NumRecords == 1) {
Buffer = &a->Record[0];
*Buffer = HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte;
if (!(a->Flags & CONSOLE_READ_NOREMOVE))
RtlZeroMemory(&HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte,sizeof(INPUT_RECORD));
return TRUE;
}
}
}
#endif
//
// this routine should be called by a thread owning the same
// lock on the same console as we're reading from.
//
try {
LockReadCount(HandleData);
ASSERT(HandleData->InputReadData->ReadCount);
HandleData->InputReadData->ReadCount -= 1;
UnlockReadCount(HandleData);
//
// see if called by CsrDestroyProcess or CsrDestroyThread
// via CsrNotifyWaitBlock. if so, just decrement the ReadCount
// and return.
//
if (WaitFlags & CSR_PROCESS_TERMINATING) {
Status = STATUS_THREAD_IS_TERMINATING;
leave;
}
//
// We must see if we were woken up because the handle is being
// closed. if so, we decrement the read count. if it goes to
// zero, we wake up the close thread. otherwise, we wake up any
// other thread waiting for data.
//
if (HandleData->InputReadData->InputHandleFlags & HANDLE_CLOSING) {
ASSERT (SatisfyParameter1 == HandleData);
Status = STATUS_ALERTED;
leave;
}
//
// if we get to here, this routine was called either by the input
// thread or a write routine. both of these callers grab the
// current console lock.
//
//
// this routine should be called by a thread owning the same
// lock on the same console as we're reading from.
//
ASSERT (ConsoleLocked(Console));
//
// if the read buffer is contained within the message, we need to
// reset the buffer pointer because the message copied from the
// stack to heap space when the wait block was created.
//
if (a->NumRecords <= INPUT_RECORD_BUFFER_SIZE) {
Buffer = a->Record;
} else {
Buffer = a->BufPtr;
}
#if defined(FE_SB)
if (CONSOLE_IS_DBCS_CP(Console) ) {
Console->ReadConInpNumBytesUnicode = a->NumRecords;
if (!a->Unicode) {
/*
* ASCII : a->NumRecords is ASCII byte count
*/
if (HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte.Event.KeyEvent.uChar.AsciiChar) {
/*
* Saved DBCS Traling byte
*/
if (Console->ReadConInpNumBytesUnicode != 1) {
Console->ReadConInpNumBytesUnicode--;
Buffer++;
fAddDbcsLead = TRUE;
nLength = &Console->ReadConInpNumBytesUnicode;
}
else {
ASSERT(Console->ReadConInpNumBytesUnicode==1);
}
}
else {
nLength = &Console->ReadConInpNumBytesUnicode;
}
}
else {
nLength = &a->NumRecords;
}
}
else {
nLength = &a->NumRecords;
}
Status = ReadInputBuffer(DirectReadData->InputInfo,
Buffer,
nLength,
!!(a->Flags & CONSOLE_READ_NOREMOVE),
!(a->Flags & CONSOLE_READ_NOWAIT),
FALSE,
Console,
HandleData,
WaitReplyMessage,
DirectReadWaitRoutine,
&DirectReadData,
sizeof(DirectReadData),
TRUE,
a->Unicode
);
#else
Status = ReadInputBuffer(DirectReadData->InputInfo,
Buffer,
&a->NumRecords,
!!(a->Flags & CONSOLE_READ_NOREMOVE),
!(a->Flags & CONSOLE_READ_NOWAIT),
FALSE,
Console,
HandleData,
WaitReplyMessage,
DirectReadWaitRoutine,
&DirectReadData,
sizeof(DirectReadData),
TRUE
);
#endif
if (Status == CONSOLE_STATUS_WAIT) {
RetVal = FALSE;
}
} finally {
//
// if the read was completed (status != wait), free the direct read
// data.
//
if (Status != CONSOLE_STATUS_WAIT) {
if (Status == STATUS_SUCCESS && !a->Unicode) {
#if defined(FE_SB)
if (CONSOLE_IS_DBCS_CP(Console) ) {
if (fAddDbcsLead &&
HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte.Event.KeyEvent.uChar.AsciiChar) {
a->NumRecords--;
}
a->NumRecords = FE_TranslateInputToOem(
Console,
Buffer,
a->NumRecords,
Console->ReadConInpNumBytesUnicode,
a->Flags & CONSOLE_READ_NOREMOVE ?
NULL :
&HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte);
if (fAddDbcsLead &&
HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte.Event.KeyEvent.uChar.AsciiChar) {
*(Buffer-1) = HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte;
if (!(a->Flags & CONSOLE_READ_NOREMOVE))
RtlZeroMemory(&HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte,sizeof(INPUT_RECORD));
a->NumRecords++;
Buffer--;
}
}
else {
TranslateInputToOem(Console,
Buffer,
a->NumRecords,
Console->ReadConInpNumBytesUnicode,
a->Flags & CONSOLE_READ_NOREMOVE ?
NULL :
&HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte
);
}
#else
TranslateInputToOem(Console,
Buffer,
a->NumRecords
);
#endif
}
WaitReplyMessage->ReturnValue = Status;
ConsoleHeapFree(DirectReadData);
}
}
return RetVal;
//
// satisfy the unreferenced parameter warnings.
//
UNREFERENCED_PARAMETER(WaitQueue);
UNREFERENCED_PARAMETER(WaitingThread);
UNREFERENCED_PARAMETER(SatisfyParameter2);
}
ULONG
SrvGetConsoleInput(
IN OUT PCSR_API_MSG m,
IN OUT PCSR_REPLY_STATUS ReplyStatus
)
/*++
Routine Description:
This routine reads or peeks input events. In both cases, the events
are copied to the user's buffer. In the read case they are removed
from the input buffer and in the peek case they are not.
Arguments:
m - message containing api parameters
ReplyStatus - Indicates whether to reply to the dll port.
Return Value:
--*/
{
PCONSOLE_GETCONSOLEINPUT_MSG a = (PCONSOLE_GETCONSOLEINPUT_MSG)&m->u.ApiMessageData;
PCONSOLE_INFORMATION Console;
PHANDLE_DATA HandleData;
NTSTATUS Status;
PINPUT_RECORD Buffer;
DIRECT_READ_DATA DirectReadData;
#ifdef FE_SB
BOOLEAN fAddDbcsLead = FALSE;
PDWORD nLength;
#endif
if (a->Flags & ~CONSOLE_READ_VALID) {
return (ULONG)STATUS_INVALID_PARAMETER;
}
Status = ApiPreamble(a->ConsoleHandle,
&Console
);
if (!NT_SUCCESS(Status)) {
return Status;
}
Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
a->InputHandle,
CONSOLE_INPUT_HANDLE,
GENERIC_READ,
&HandleData
);
if (!NT_SUCCESS(Status)) {
a->NumRecords = 0;
} else {
if (a->NumRecords <= INPUT_RECORD_BUFFER_SIZE) {
Buffer = a->Record;
} else {
Buffer = a->BufPtr;
if (!CsrValidateMessageBuffer(m, &a->BufPtr, a->NumRecords, sizeof(*Buffer))) {
UnlockConsole(Console);
return STATUS_INVALID_PARAMETER;
}
}
//
// if we're reading, wait for data. if we're peeking, don't.
//
DirectReadData.InputInfo = HandleData->Buffer.InputBuffer;
DirectReadData.Console = Console;
DirectReadData.ProcessData = CONSOLE_PERPROCESSDATA();
DirectReadData.HandleIndex = HANDLE_TO_INDEX(a->InputHandle);
#if defined(FE_SB)
if (CONSOLE_IS_DBCS_CP(Console) ) {
Console->ReadConInpNumBytesUnicode = a->NumRecords;
if (!a->Unicode) {
/*
* ASCII : a->NumRecords is ASCII byte count
*/
if (HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte.Event.KeyEvent.uChar.AsciiChar) {
/*
* Saved DBCS Traling byte
*/
*Buffer = HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte;
if (!(a->Flags & CONSOLE_READ_NOREMOVE))
RtlZeroMemory(&HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte,sizeof(INPUT_RECORD));
if (Console->ReadConInpNumBytesUnicode == 1) {
UnlockConsole(Console);
return STATUS_SUCCESS;
}
else {
Console->ReadConInpNumBytesUnicode--;
Buffer++;
fAddDbcsLead = TRUE;
nLength = &Console->ReadConInpNumBytesUnicode;
}
}
else {
nLength = &Console->ReadConInpNumBytesUnicode;
}
}
else {
nLength = &a->NumRecords;
}
}
else {
nLength = &a->NumRecords;
}
Status = ReadInputBuffer(HandleData->Buffer.InputBuffer,
Buffer,
nLength,
!!(a->Flags & CONSOLE_READ_NOREMOVE),
!(a->Flags & CONSOLE_READ_NOWAIT),
FALSE,
Console,
HandleData,
m,
DirectReadWaitRoutine,
&DirectReadData,
sizeof(DirectReadData),
FALSE,
a->Unicode
);
if (Status == CONSOLE_STATUS_WAIT) {
*ReplyStatus = CsrReplyPending;
} else if (!a->Unicode) {
a->NumRecords = TranslateInputToOem(Console,
Buffer,
fAddDbcsLead ?
a->NumRecords-1 :
a->NumRecords,
Console->ReadConInpNumBytesUnicode,
a->Flags & CONSOLE_READ_NOREMOVE ?
NULL :
&HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte
);
if (fAddDbcsLead)
{
a->NumRecords++;
Buffer--;
}
}
#else
Status = ReadInputBuffer(HandleData->Buffer.InputBuffer,
Buffer,
&a->NumRecords,
!!(a->Flags & CONSOLE_READ_NOREMOVE),
!(a->Flags & CONSOLE_READ_NOWAIT),
FALSE,
Console,
HandleData,
m,
DirectReadWaitRoutine,
&DirectReadData,
sizeof(DirectReadData),
FALSE
);
if (Status == CONSOLE_STATUS_WAIT) {
*ReplyStatus = CsrReplyPending;
} else if (!a->Unicode) {
TranslateInputToOem(Console,
Buffer,
a->NumRecords
);
}
#endif
}
UnlockConsole(Console);
return Status;
}
ULONG
SrvWriteConsoleInput(
IN OUT PCSR_API_MSG m,
IN OUT PCSR_REPLY_STATUS ReplyStatus
)
{
PCONSOLE_WRITECONSOLEINPUT_MSG a = (PCONSOLE_WRITECONSOLEINPUT_MSG)&m->u.ApiMessageData;
PCONSOLE_INFORMATION Console;
PHANDLE_DATA HandleData;
NTSTATUS Status;
PINPUT_RECORD Buffer;
Status = ApiPreamble(a->ConsoleHandle,
&Console
);
if (!NT_SUCCESS(Status)) {
return Status;
}
Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
a->InputHandle,
CONSOLE_INPUT_HANDLE,
GENERIC_WRITE,
&HandleData
);
if (!NT_SUCCESS(Status)) {
a->NumRecords = 0;
} else {
if (a->NumRecords <= INPUT_RECORD_BUFFER_SIZE) {
Buffer = a->Record;
} else {
Buffer = a->BufPtr;
if (!CsrValidateMessageBuffer(m, &a->BufPtr, a->NumRecords, sizeof(*Buffer))) {
UnlockConsole(Console);
return STATUS_INVALID_PARAMETER;
}
}
if (!a->Unicode) {
#if defined(FE_SB)
a->NumRecords = TranslateInputToUnicode(Console,
Buffer,
a->NumRecords,
&HandleData->Buffer.InputBuffer->WriteConInpDbcsLeadByte[0]
);
#else
TranslateInputToUnicode(Console,
Buffer,
a->NumRecords
);
#endif
}
if (a->Append) {
a->NumRecords = WriteInputBuffer(Console,
HandleData->Buffer.InputBuffer,
Buffer,
a->NumRecords
);
} else {
a->NumRecords = PrependInputBuffer(Console,
HandleData->Buffer.InputBuffer,
Buffer,
a->NumRecords
);
}
}
UnlockConsole(Console);
return((ULONG) Status);
UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message
}
NTSTATUS
SB_TranslateOutputToOem
(
IN PCONSOLE_INFORMATION Console,
IN OUT PCHAR_INFO OutputBuffer,
IN COORD Size
)
// this is used when the app reads oem from the output buffer
// the app wants real OEM characters. We have real Unicode or UnicodeOem.
{
SHORT i,j;
UINT Codepage;
DBGCHARS(("SB_TranslateOutputToOem(Console=%lx, OutputBuffer=%lx)\n",
Console, OutputBuffer));
j = Size.X * Size.Y;
if ((Console->CurrentScreenBuffer->Flags & CONSOLE_OEMFONT_DISPLAY) &&
((Console->FullScreenFlags & CONSOLE_FULLSCREEN) == 0)) {
#if defined(FE_SB)
if (CONSOLE_IS_DBCS_ENABLED() &&
Console->OutputCP != WINDOWSCP ) {
Codepage = USACP;
}
else
#endif
// we have UnicodeOem characters
Codepage = WINDOWSCP;
} else {
// we have real Unicode characters
Codepage = Console->OutputCP; // BUG FIX by KazuM Jun.2.97
}
for (i=0;i<j;i++,OutputBuffer++) {
OutputBuffer->Char.AsciiChar = WcharToChar(Codepage,
OutputBuffer->Char.UnicodeChar);
}
return STATUS_SUCCESS;
}
#if defined(FE_SB)
NTSTATUS
FE_TranslateOutputToOem(
IN PCONSOLE_INFORMATION Console,
IN OUT PCHAR_INFO OutputBuffer,
IN COORD Size
)
// this is used when the app reads oem from the output buffer
// the app wants real OEM characters. We have real Unicode or UnicodeOem.
{
SHORT i,j;
UINT Codepage;
PCHAR_INFO TmpBuffer,SaveBuffer;
CHAR AsciiDbcs[2];
ULONG NumBytes;
DBGCHARS(("FE_TranslateOutputToOem(Console=%lx, OutputBuffer=%lx)\n",
Console, OutputBuffer));
SaveBuffer = TmpBuffer =
ConsoleHeapAlloc(TMP_DBCS_TAG, Size.X * Size.Y * sizeof(CHAR_INFO) * 2);
if (TmpBuffer == NULL) {
return STATUS_NO_MEMORY;
}
if ((Console->CurrentScreenBuffer->Flags & CONSOLE_OEMFONT_DISPLAY) &&
((Console->FullScreenFlags & CONSOLE_FULLSCREEN) == 0)) {
if (CONSOLE_IS_DBCS_ENABLED() &&
Console->OutputCP != WINDOWSCP ) {
Codepage = USACP;
}
else
// we have UnicodeOem characters
Codepage = WINDOWSCP;
} else {
// we have real Unicode characters
Codepage = Console->OutputCP;
}
memcpy(TmpBuffer,OutputBuffer,Size.X * Size.Y * sizeof(CHAR_INFO));
for (i=0; i < Size.Y; i++) {
for (j=0; j < Size.X; j++) {
if (TmpBuffer->Attributes & COMMON_LVB_LEADING_BYTE) {
if (j < Size.X-1) { // -1 is safe DBCS in buffer
j++;
NumBytes = sizeof(AsciiDbcs);
NumBytes = ConvertOutputToOem(Codepage,
&TmpBuffer->Char.UnicodeChar,
1,
&AsciiDbcs[0],
NumBytes);
OutputBuffer->Char.AsciiChar = AsciiDbcs[0];
OutputBuffer->Attributes = TmpBuffer->Attributes;
OutputBuffer++;
TmpBuffer++;
OutputBuffer->Char.AsciiChar = AsciiDbcs[1];
OutputBuffer->Attributes = TmpBuffer->Attributes;
OutputBuffer++;
TmpBuffer++;
}
else {
OutputBuffer->Char.AsciiChar = ' ';
OutputBuffer->Attributes = TmpBuffer->Attributes & ~COMMON_LVB_SBCSDBCS;
OutputBuffer++;
TmpBuffer++;
}
}
else if (!(TmpBuffer->Attributes & COMMON_LVB_SBCSDBCS)){
ConvertOutputToOem(Codepage,
&TmpBuffer->Char.UnicodeChar,
1,
&OutputBuffer->Char.AsciiChar,
1);
OutputBuffer->Attributes = TmpBuffer->Attributes;
OutputBuffer++;
TmpBuffer++;
}
}
}
ConsoleHeapFree(SaveBuffer);
return STATUS_SUCCESS;
}
#endif
NTSTATUS
SB_TranslateOutputToOemUnicode
(
IN PCONSOLE_INFORMATION Console,
IN OUT PCHAR_INFO OutputBuffer,
IN COORD Size
)
// this is used when the app reads unicode from the output buffer
{
SHORT i,j;
DBGCHARS(("SB_TranslateOutputToOemUnicode\n"));
j = Size.X * Size.Y;
for (i=0;i<j;i++,OutputBuffer++) {
FalseUnicodeToRealUnicode(&OutputBuffer->Char.UnicodeChar,
1,
Console->OutputCP
);
}
return STATUS_SUCCESS;
}
#if defined(FE_SB)
NTSTATUS
FE_TranslateOutputToOemUnicode(
IN PCONSOLE_INFORMATION Console,
IN OUT PCHAR_INFO OutputBuffer,
IN COORD Size,
IN BOOL fRemoveDbcsMark
)
// this is used when the app reads unicode from the output buffer
{
SHORT i,j;
DBGCHARS(("FE_TranslateOutputToOemUnicode\n"));
j = Size.X * Size.Y;
if (fRemoveDbcsMark)
RemoveDbcsMarkCell(OutputBuffer,OutputBuffer,j);
for (i=0;i<j;i++,OutputBuffer++) {
FalseUnicodeToRealUnicode(&OutputBuffer->Char.UnicodeChar,
1,
Console->OutputCP
);
}
return STATUS_SUCCESS;
}
#endif
NTSTATUS
SB_TranslateOutputToUnicode
(
IN PCONSOLE_INFORMATION Console,
IN OUT PCHAR_INFO OutputBuffer,
IN COORD Size
)
// this is used when the app writes oem to the output buffer
// we want UnicodeOem or Unicode in the buffer, depending on font & fullscreen
{
SHORT i,j;
UINT Codepage;
DBGCHARS(("SB_TranslateOutputToUnicode %lx %lx (%lx,%lx)\n",
Console, OutputBuffer, Size.X, Size.Y));
j = Size.X * Size.Y;
if ((Console->CurrentScreenBuffer->Flags & CONSOLE_OEMFONT_DISPLAY) &&
((Console->FullScreenFlags & CONSOLE_FULLSCREEN) == 0)) {
#if defined(FE_SB)
if (CONSOLE_IS_DBCS_ENABLED() &&
(Console->OutputCP != WINDOWSCP) ) {
Codepage = USACP;
}
else
#endif
// we want UnicodeOem characters
Codepage = WINDOWSCP;
} else {
// we want real Unicode characters
Codepage = Console->OutputCP; // BUG FIX by KazuM Jun.2.97
}
for (i = 0; i < j; i++, OutputBuffer++) {
#if defined(FE_SB)
OutputBuffer->Char.UnicodeChar = SB_CharToWchar(
Codepage, OutputBuffer->Char.AsciiChar);
#else
OutputBuffer->Char.UnicodeChar = CharToWchar(
Codepage, OutputBuffer->Char.AsciiChar);
#endif
}
return STATUS_SUCCESS;
}
#if defined(FE_SB)
NTSTATUS
FE_TranslateOutputToUnicode(
IN PCONSOLE_INFORMATION Console,
IN OUT PCHAR_INFO OutputBuffer,
IN COORD Size
)
// this is used when the app writes oem to the output buffer
// we want UnicodeOem or Unicode in the buffer, depending on font & fullscreen
{
SHORT i,j;
UINT Codepage;
CHAR AsciiDbcs[2];
WCHAR UnicodeDbcs[2];
DBGCHARS(("FE_TranslateOutputToUnicode %lx %lx (%lx,%lx)\n",
Console, OutputBuffer, Size.X, Size.Y));
if ((Console->CurrentScreenBuffer->Flags & CONSOLE_OEMFONT_DISPLAY) &&
((Console->FullScreenFlags & CONSOLE_FULLSCREEN) == 0)) {
if (CONSOLE_IS_DBCS_ENABLED() &&
(Console->OutputCP != WINDOWSCP) ) {
Codepage = USACP;
}
else
// we want UnicodeOem characters
Codepage = WINDOWSCP;
} else {
// we want real Unicode characters
Codepage = Console->OutputCP;
}
for (i=0; i < Size.Y; i++) {
for (j=0; j < Size.X; j++) {
OutputBuffer->Attributes &= ~COMMON_LVB_SBCSDBCS;
if (IsDBCSLeadByteConsole(OutputBuffer->Char.AsciiChar,&Console->OutputCPInfo)) {
if (j < Size.X-1) { // -1 is safe DBCS in buffer
j++;
AsciiDbcs[0] = OutputBuffer->Char.AsciiChar;
AsciiDbcs[1] = (OutputBuffer+1)->Char.AsciiChar;
ConvertOutputToUnicode(Codepage,
&AsciiDbcs[0],
2,
&UnicodeDbcs[0],
2);
OutputBuffer->Char.UnicodeChar = UnicodeDbcs[0];
OutputBuffer->Attributes |= COMMON_LVB_LEADING_BYTE;
OutputBuffer++;
OutputBuffer->Char.UnicodeChar = UNICODE_DBCS_PADDING;
OutputBuffer->Attributes &= ~COMMON_LVB_SBCSDBCS;
OutputBuffer->Attributes |= COMMON_LVB_TRAILING_BYTE;
OutputBuffer++;
}
else {
OutputBuffer->Char.UnicodeChar = UNICODE_SPACE;
OutputBuffer++;
}
}
else {
CHAR c;
c=OutputBuffer->Char.AsciiChar;
ConvertOutputToUnicode(Codepage,
&c,
1,
&OutputBuffer->Char.UnicodeChar,
1);
OutputBuffer++;
}
}
}
return STATUS_SUCCESS;
}
#endif
NTSTATUS
SB_TranslateOutputToAnsiUnicode (
IN PCONSOLE_INFORMATION Console,
IN OUT PCHAR_INFO OutputBuffer,
IN COORD Size
)
// this is used when the app writes unicode to the output buffer
{
SHORT i,j;
DBGCHARS(("TranslateOutputToAnsiUnicode\n"));
j = Size.X * Size.Y;
for (i=0;i<j;i++,OutputBuffer++) {
RealUnicodeToFalseUnicode(&OutputBuffer->Char.UnicodeChar,
1,
Console->OutputCP
);
}
return STATUS_SUCCESS;
}
NTSTATUS
FE_TranslateOutputToAnsiUnicodeInternal(
IN PCONSOLE_INFORMATION Console,
IN OUT PCHAR_INFO OutputBuffer,
IN COORD Size,
IN OUT PCHAR_INFO OutputBufferR,
IN BOOL fRealUnicodeToFalseUnicode
)
// this is used when the app writes unicode to the output buffer
{
SHORT i,j;
DBGCHARS(("TranslateOutputToAnsiUnicode\n"));
for (i=0; i < Size.Y; i++) {
for (j=0; j < Size.X; j++) {
WCHAR wch = OutputBuffer->Char.UnicodeChar;
if (fRealUnicodeToFalseUnicode) {
RealUnicodeToFalseUnicode(&OutputBuffer->Char.UnicodeChar,
1,
Console->OutputCP
);
}
if (OutputBufferR) {
OutputBufferR->Attributes = OutputBuffer->Attributes & ~COMMON_LVB_SBCSDBCS;
if (IsConsoleFullWidth(Console->hDC,
Console->OutputCP,OutputBuffer->Char.UnicodeChar)) {
if (j == Size.X-1){
OutputBufferR->Char.UnicodeChar = UNICODE_SPACE;
}
else{
OutputBufferR->Char.UnicodeChar = OutputBuffer->Char.UnicodeChar;
OutputBufferR->Attributes |= COMMON_LVB_LEADING_BYTE;
OutputBufferR++;
OutputBufferR->Char.UnicodeChar = UNICODE_DBCS_PADDING;
OutputBufferR->Attributes = OutputBuffer->Attributes & ~COMMON_LVB_SBCSDBCS;
OutputBufferR->Attributes |= COMMON_LVB_TRAILING_BYTE;
}
}
else{
OutputBufferR->Char.UnicodeChar = OutputBuffer->Char.UnicodeChar;
}
OutputBufferR++;
}
if (IsConsoleFullWidth(Console->hDC,
Console->OutputCP,
wch)) {
if (j != Size.X-1){
j++;
}
}
OutputBuffer++;
}
}
return STATUS_SUCCESS;
}
NTSTATUS
FE_TranslateOutputToAnsiUnicode(
IN PCONSOLE_INFORMATION Console,
IN OUT PCHAR_INFO OutputBuffer,
IN COORD Size,
IN OUT PCHAR_INFO OutputBufferR
)
// this is used when the app writes unicode to the output buffer
{
return FE_TranslateOutputToAnsiUnicodeInternal(Console,
OutputBuffer,
Size,
OutputBufferR,
TRUE
);
}
NTSTATUS
TranslateOutputToPaddingUnicode(
IN PCONSOLE_INFORMATION Console,
IN OUT PCHAR_INFO OutputBuffer,
IN COORD Size,
IN OUT PCHAR_INFO OutputBufferR
)
{
return FE_TranslateOutputToAnsiUnicodeInternal(Console,
OutputBuffer,
Size,
OutputBufferR,
FALSE
);
}
ULONG
SrvReadConsoleOutput(
IN OUT PCSR_API_MSG m,
IN OUT PCSR_REPLY_STATUS ReplyStatus
)
{
PCONSOLE_READCONSOLEOUTPUT_MSG a = (PCONSOLE_READCONSOLEOUTPUT_MSG)&m->u.ApiMessageData;
PCONSOLE_INFORMATION Console;
PHANDLE_DATA HandleData;
NTSTATUS Status;
PCHAR_INFO Buffer;
DBGOUTPUT(("SrvReadConsoleOutput\n"));
Status = ApiPreamble(a->ConsoleHandle,
&Console
);
if (!NT_SUCCESS(Status)) {
return Status;
}
Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
a->OutputHandle,
CONSOLE_OUTPUT_HANDLE,
GENERIC_READ,
&HandleData
);
if (!NT_SUCCESS(Status)) {
//
// a region of zero size is indicated by the right and bottom
// coordinates being less than the left and top.
//
a->CharRegion.Right = (USHORT) (a->CharRegion.Left-1);
a->CharRegion.Bottom = (USHORT) (a->CharRegion.Top-1);
}
else {
COORD BufferSize;
BufferSize.X = (SHORT)(a->CharRegion.Right - a->CharRegion.Left + 1);
BufferSize.Y = (SHORT)(a->CharRegion.Bottom - a->CharRegion.Top + 1);
if ((BufferSize.X == 1) && (BufferSize.Y == 1)) {
Buffer = &a->Char;
}
else {
Buffer = a->BufPtr;
if (!CsrValidateMessageBuffer(m, &a->BufPtr, BufferSize.X * BufferSize.Y, sizeof(*Buffer))) {
UnlockConsole(Console);
return STATUS_INVALID_PARAMETER;
}
}
Status = ReadScreenBuffer(HandleData->Buffer.ScreenBuffer,
Buffer,
&a->CharRegion
);
if (!a->Unicode) {
TranslateOutputToOem(Console,
Buffer,
BufferSize
);
} else if ((Console->CurrentScreenBuffer->Flags & CONSOLE_OEMFONT_DISPLAY) &&
!(Console->FullScreenFlags & CONSOLE_FULLSCREEN)) {
TranslateOutputToOemUnicode(Console,
Buffer,
BufferSize
#if defined(FE_SB)
,
TRUE
#endif
);
}
}
UnlockConsole(Console);
return Status;
UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message
}
ULONG
SrvWriteConsoleOutput(
IN OUT PCSR_API_MSG m,
IN OUT PCSR_REPLY_STATUS ReplyStatus
)
{
PCONSOLE_WRITECONSOLEOUTPUT_MSG a = (PCONSOLE_WRITECONSOLEOUTPUT_MSG)&m->u.ApiMessageData;
PSCREEN_INFORMATION ScreenBufferInformation;
PCONSOLE_INFORMATION Console;
PHANDLE_DATA HandleData;
NTSTATUS Status;
PCHAR_INFO Buffer;
#if defined(FE_SB)
PCHAR_INFO TransBuffer = NULL;
#endif
DBGOUTPUT(("SrvWriteConsoleOutput\n"));
Status = ApiPreamble(a->ConsoleHandle,
&Console
);
if (!NT_SUCCESS(Status)) {
return Status;
}
Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
a->OutputHandle,
CONSOLE_OUTPUT_HANDLE,
GENERIC_WRITE,
&HandleData
);
if (!NT_SUCCESS(Status)) {
//
// a region of zero size is indicated by the right and bottom
// coordinates being less than the left and top.
//
a->CharRegion.Right = (USHORT) (a->CharRegion.Left-1);
a->CharRegion.Bottom = (USHORT) (a->CharRegion.Top-1);
} else {
COORD BufferSize;
ULONG NumBytes;
BufferSize.X = (SHORT)(a->CharRegion.Right - a->CharRegion.Left + 1);
BufferSize.Y = (SHORT)(a->CharRegion.Bottom - a->CharRegion.Top + 1);
NumBytes = BufferSize.X * BufferSize.Y * sizeof(*Buffer);
if ((BufferSize.X == 1) && (BufferSize.Y == 1)) {
Buffer = &a->Char;
} else if (a->ReadVM) {
Buffer = ConsoleHeapAlloc(TMP_TAG, NumBytes);
if (Buffer == NULL) {
UnlockConsole(Console);
return (ULONG)STATUS_NO_MEMORY;
}
Status = NtReadVirtualMemory(CONSOLE_CLIENTPROCESSHANDLE(),
a->BufPtr,
Buffer,
NumBytes,
NULL
);
if (!NT_SUCCESS(Status)) {
ConsoleHeapFree(Buffer);
UnlockConsole(Console);
return (ULONG)STATUS_NO_MEMORY;
}
} else {
Buffer = a->BufPtr;
if (!CsrValidateMessageBuffer(m, &a->BufPtr, NumBytes, sizeof(BYTE))) {
UnlockConsole(Console);
return STATUS_INVALID_PARAMETER;
}
}
ScreenBufferInformation = HandleData->Buffer.ScreenBuffer;
if (!a->Unicode) {
TranslateOutputToUnicode(Console,
Buffer,
BufferSize
);
#if defined(FE_SB)
Status = WriteScreenBuffer(ScreenBufferInformation,
Buffer,
&a->CharRegion
);
#endif
} else if ((Console->CurrentScreenBuffer->Flags & CONSOLE_OEMFONT_DISPLAY) &&
((Console->FullScreenFlags & CONSOLE_FULLSCREEN) == 0)) {
#if defined(FE_SB)
if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) {
TransBuffer = ConsoleHeapAlloc(TMP_DBCS_TAG, (BufferSize.Y * BufferSize.X) * 2 * sizeof(CHAR_INFO));
if (TransBuffer == NULL) {
UnlockConsole(Console);
return (ULONG)STATUS_NO_MEMORY;
}
FE_TranslateOutputToAnsiUnicode(Console,
Buffer,
BufferSize,
&TransBuffer[0]
);
Status = WriteScreenBuffer(ScreenBufferInformation,
&TransBuffer[0],
&a->CharRegion
);
ConsoleHeapFree(TransBuffer);
} else {
SB_TranslateOutputToAnsiUnicode(Console,
Buffer,
BufferSize
);
Status = WriteScreenBuffer(ScreenBufferInformation,
Buffer,
&a->CharRegion
);
}
#else
TranslateOutputToAnsiUnicode(Console,
Buffer,
BufferSize
);
#endif
}
#if defined(FE_SB)
else
#endif
Status = WriteScreenBuffer(ScreenBufferInformation,
Buffer,
&a->CharRegion
);
if (a->ReadVM) {
ConsoleHeapFree(Buffer);
}
if (NT_SUCCESS(Status)) {
//
// cause screen to be updated
//
#if defined(FE_SB)
if (CONSOLE_IS_DBCS_OUTPUTCP(Console) &&
Console->Flags & CONSOLE_JUST_VDM_UNREGISTERED ){
int MouseRec;
MouseRec = Console->InputBuffer.InputMode;
Console->InputBuffer.InputMode &= ~ENABLE_MOUSE_INPUT;
Console->CurrentScreenBuffer->BufferInfo.TextInfo.Flags &= ~TEXT_VALID_HINT;
WriteToScreen(ScreenBufferInformation,&a->CharRegion );
Console->CurrentScreenBuffer->BufferInfo.TextInfo.Flags |= TEXT_VALID_HINT;
Console->InputBuffer.InputMode = MouseRec;
}
else
#endif
WriteToScreen(ScreenBufferInformation,
&a->CharRegion
);
}
}
UnlockConsole(Console);
return Status;
UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message
}
ULONG
SrvReadConsoleOutputString(
IN OUT PCSR_API_MSG m,
IN OUT PCSR_REPLY_STATUS ReplyStatus
)
{
NTSTATUS Status;
PCONSOLE_INFORMATION Console;
PHANDLE_DATA HandleData;
PVOID Buffer;
PCONSOLE_READCONSOLEOUTPUTSTRING_MSG a = (PCONSOLE_READCONSOLEOUTPUTSTRING_MSG)&m->u.ApiMessageData;
ULONG nSize;
Status = ApiPreamble(a->ConsoleHandle,
&Console
);
if (!NT_SUCCESS(Status)) {
return Status;
}
Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
a->OutputHandle,
CONSOLE_OUTPUT_HANDLE,
GENERIC_READ,
&HandleData
);
if (!NT_SUCCESS(Status)) {
//
// a region of zero size is indicated by the right and bottom
// coordinates being less than the left and top.
//
a->NumRecords = 0;
} else {
if (a->StringType == CONSOLE_ASCII)
nSize = sizeof(CHAR);
else
nSize = sizeof(WORD);
if ((a->NumRecords*nSize) > sizeof(a->String)) {
Buffer = a->BufPtr;
if (!CsrValidateMessageBuffer(m, &a->BufPtr, a->NumRecords, nSize)) {
UnlockConsole(Console);
return STATUS_INVALID_PARAMETER;
}
}
else {
Buffer = a->String;
}
Status = ReadOutputString(HandleData->Buffer.ScreenBuffer,
Buffer,
a->ReadCoord,
a->StringType,
&a->NumRecords
);
}
UnlockConsole(Console);
return Status;
UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message
}
ULONG
SrvWriteConsoleOutputString(
IN OUT PCSR_API_MSG m,
IN OUT PCSR_REPLY_STATUS ReplyStatus
)
{
PCONSOLE_WRITECONSOLEOUTPUTSTRING_MSG a = (PCONSOLE_WRITECONSOLEOUTPUTSTRING_MSG)&m->u.ApiMessageData;
NTSTATUS Status;
PCONSOLE_INFORMATION Console;
PHANDLE_DATA HandleData;
PVOID Buffer;
ULONG nSize;
Status = ApiPreamble(a->ConsoleHandle,
&Console
);
if (!NT_SUCCESS(Status)) {
return Status;
}
Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
a->OutputHandle,
CONSOLE_OUTPUT_HANDLE,
GENERIC_WRITE,
&HandleData
);
if (!NT_SUCCESS(Status)) {
a->NumRecords = 0;
} else {
if (a->WriteCoord.X < 0 ||
a->WriteCoord.Y < 0) {
Status = STATUS_INVALID_PARAMETER;
} else {
if (a->StringType == CONSOLE_ASCII)
nSize = sizeof(CHAR);
else
nSize = sizeof(WORD);
if ((a->NumRecords*nSize) > sizeof(a->String)) {
Buffer = a->BufPtr;
if (!CsrValidateMessageBuffer(m, &a->BufPtr, a->NumRecords, nSize)) {
UnlockConsole(Console);
return STATUS_INVALID_PARAMETER;
}
}
else {
Buffer = a->String;
}
Status = WriteOutputString(HandleData->Buffer.ScreenBuffer,
Buffer,
a->WriteCoord,
a->StringType,
&a->NumRecords,
NULL
);
}
}
UnlockConsole(Console);
return Status;
UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message
}
ULONG
SrvFillConsoleOutput(
IN OUT PCSR_API_MSG m,
IN OUT PCSR_REPLY_STATUS ReplyStatus
)
{
PCONSOLE_FILLCONSOLEOUTPUT_MSG a = (PCONSOLE_FILLCONSOLEOUTPUT_MSG)&m->u.ApiMessageData;
NTSTATUS Status;
PCONSOLE_INFORMATION Console;
PHANDLE_DATA HandleData;
Status = ApiPreamble(a->ConsoleHandle,
&Console
);
if (!NT_SUCCESS(Status)) {
return Status;
}
Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
a->OutputHandle,
CONSOLE_OUTPUT_HANDLE,
GENERIC_WRITE,
&HandleData
);
if (!NT_SUCCESS(Status)) {
a->Length = 0;
} else {
Status = FillOutput(HandleData->Buffer.ScreenBuffer,
a->Element,
a->WriteCoord,
a->ElementType,
&a->Length
);
}
UnlockConsole(Console);
return Status;
UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message
}
ULONG
SrvCreateConsoleScreenBuffer(
IN OUT PCSR_API_MSG m,
IN OUT PCSR_REPLY_STATUS ReplyStatus
)
/*++
Routine Description:
This routine creates a screen buffer and returns a handle to it.
Arguments:
ApiMessageData - Points to parameter structure.
Return Value:
--*/
{
PCONSOLE_CREATESCREENBUFFER_MSG a = (PCONSOLE_CREATESCREENBUFFER_MSG)&m->u.ApiMessageData;
NTSTATUS Status;
PCONSOLE_INFORMATION Console;
HANDLE Handle;
PHANDLE_DATA HandleData;
PCONSOLE_SHARE_ACCESS ShareAccess;
CHAR_INFO Fill;
COORD WindowSize;
PSCREEN_INFORMATION ScreenInfo;
PCONSOLE_PER_PROCESS_DATA ProcessData;
ULONG HandleType;
int FontIndex;
DBGOUTPUT(("SrvCreateConsoleScreenBuffer\n"));
/*
* Verify that the Flags value is legit, or malicious code could make us
* fault. Windows Bug #209416.
*/
if (a->Flags != CONSOLE_TEXTMODE_BUFFER &&
a->Flags != CONSOLE_GRAPHICS_BUFFER) {
return STATUS_INVALID_PARAMETER;
}
Status = ApiPreamble(a->ConsoleHandle,
&Console
);
if (!NT_SUCCESS(Status)) {
return Status;
}
if (a->Flags & CONSOLE_GRAPHICS_BUFFER) {
if (!CsrValidateMessageBuffer(m, &a->GraphicsBufferInfo.lpBitMapInfo, a->GraphicsBufferInfo.dwBitMapInfoLength, sizeof(BYTE))) {
UnlockConsole(Console);
return STATUS_INVALID_PARAMETER;
}
}
try {
Handle = INVALID_HANDLE_VALUE;
ProcessData = CONSOLE_PERPROCESSDATA();
HandleType = (a->Flags & CONSOLE_GRAPHICS_BUFFER) ?
CONSOLE_GRAPHICS_OUTPUT_HANDLE : CONSOLE_OUTPUT_HANDLE;
if (a->InheritHandle)
HandleType |= CONSOLE_INHERITABLE;
Status = AllocateIoHandle(ProcessData,
HandleType,
&Handle
);
if (!NT_SUCCESS(Status)) {
leave;
}
Status = DereferenceIoHandleNoCheck(ProcessData,
Handle,
&HandleData
);
ASSERT (NT_SUCCESS(Status));
if (!NT_SUCCESS(Status)) {
leave;
}
//
// create new screen buffer
//
Fill.Char.UnicodeChar = (WCHAR)' ';
Fill.Attributes = Console->CurrentScreenBuffer->Attributes;
WindowSize.X = (SHORT)CONSOLE_WINDOW_SIZE_X(Console->CurrentScreenBuffer);
WindowSize.Y = (SHORT)CONSOLE_WINDOW_SIZE_Y(Console->CurrentScreenBuffer);
FontIndex = FindCreateFont(CON_FAMILY(Console),
CON_FACENAME(Console),
CON_FONTSIZE(Console),
CON_FONTWEIGHT(Console),
CON_FONTCODEPAGE(Console)
);
Status = CreateScreenBuffer(&ScreenInfo,WindowSize,
FontIndex,
WindowSize,
Fill,Fill,Console,
a->Flags,&a->GraphicsBufferInfo,
&a->lpBitmap,&a->hMutex,
CURSOR_SMALL_SIZE,
NULL);
if (!NT_SUCCESS(Status)) {
leave;
}
InitializeOutputHandle(HandleData,ScreenInfo);
ShareAccess = &ScreenInfo->ShareAccess;
Status = ConsoleAddShare(a->DesiredAccess,
a->ShareMode,
ShareAccess,
HandleData
);
if (!NT_SUCCESS(Status)) {
HandleData->Buffer.ScreenBuffer->RefCount--;
FreeScreenBuffer(ScreenInfo);
leave;
}
InsertScreenBuffer(Console, ScreenInfo);
a->Handle = INDEX_TO_HANDLE(Handle);
} finally {
if (!NT_SUCCESS(Status) && Handle != INVALID_HANDLE_VALUE) {
FreeIoHandle(ProcessData,
Handle
);
}
UnlockConsole(Console);
}
return Status;
UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message
}