mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 18:15:58 +00:00
[KERNEL32]
Remove a spurious cast, and add a note for the pInputControl parameter of ReadConsole. [CONSRV] - Move some input/output console function helpers to condrv. - The way we notify for the presence of new input data, or for console pausing/unpausing, should be reconsidered (who should do this? The console driver? The active front-end?) svn path=/trunk/; revision=59345
This commit is contained in:
parent
9f8ca2b24b
commit
98b3cac350
6 changed files with 475 additions and 382 deletions
|
@ -60,11 +60,17 @@ IntReadConsole(HANDLE hConsoleInput,
|
|||
/* Set up the data to send to the Console Server */
|
||||
ReadConsoleRequest->InputHandle = hConsoleInput;
|
||||
ReadConsoleRequest->Unicode = bUnicode;
|
||||
ReadConsoleRequest->NrCharactersToRead = (WORD)nNumberOfCharsToRead;
|
||||
ReadConsoleRequest->NrCharactersToRead = nNumberOfCharsToRead;
|
||||
ReadConsoleRequest->NrCharactersRead = 0;
|
||||
ReadConsoleRequest->CtrlWakeupMask = 0;
|
||||
if (pInputControl && pInputControl->nLength == sizeof(CONSOLE_READCONSOLE_CONTROL))
|
||||
{
|
||||
/*
|
||||
* From MSDN (ReadConsole function), the description
|
||||
* for pInputControl says:
|
||||
* "This parameter requires Unicode input by default.
|
||||
* For ANSI mode, set this parameter to NULL."
|
||||
*/
|
||||
ReadConsoleRequest->NrCharactersRead = pInputControl->nInitialChars;
|
||||
memcpy(ReadConsoleRequest->Buffer,
|
||||
lpBuffer,
|
||||
|
|
|
@ -167,8 +167,8 @@ typedef struct
|
|||
HANDLE InputHandle;
|
||||
|
||||
BOOL Unicode;
|
||||
WORD NrCharactersToRead;
|
||||
WORD NrCharactersRead;
|
||||
ULONG NrCharactersToRead;
|
||||
ULONG NrCharactersRead;
|
||||
|
||||
UNICODE_STRING ExeName;
|
||||
DWORD CtrlWakeupMask;
|
||||
|
|
|
@ -43,17 +43,9 @@ typedef struct ConsoleInput_t
|
|||
INPUT_RECORD InputEvent;
|
||||
} ConsoleInput;
|
||||
|
||||
typedef struct _GET_INPUT_INFO
|
||||
{
|
||||
PCSR_THREAD CallingThread; // The thread which called the input API.
|
||||
PVOID HandleEntry; // The handle data associated with the wait thread.
|
||||
PCONSOLE_INPUT_BUFFER InputBuffer; // The input buffer corresponding to the handle.
|
||||
} GET_INPUT_INFO, *PGET_INPUT_INFO;
|
||||
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
#if 0
|
||||
static VOID FASTCALL
|
||||
ConioInputEventToAnsi(PCONSOLE Console, PINPUT_RECORD InputEvent)
|
||||
{
|
||||
|
@ -66,7 +58,6 @@ ConioInputEventToAnsi(PCONSOLE Console, PINPUT_RECORD InputEvent)
|
|||
&UnicodeChar);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
NTSTATUS FASTCALL
|
||||
ConioProcessInputEvent(PCONSOLE Console,
|
||||
|
@ -211,13 +202,231 @@ ConDrvProcessKey(IN PCONSOLE Console,
|
|||
|
||||
/* PUBLIC SERVER APIS *********************************************************/
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvReadConsole(IN PCONSOLE Console,
|
||||
IN PCONSOLE_INPUT_BUFFER InputBuffer,
|
||||
IN BOOLEAN Unicode,
|
||||
OUT PVOID Buffer,
|
||||
IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl,
|
||||
IN ULONG NumCharsToRead,
|
||||
OUT PULONG NumCharsRead OPTIONAL)
|
||||
{
|
||||
// STATUS_PENDING : Wait if more to read ; STATUS_SUCCESS : Don't wait.
|
||||
NTSTATUS Status = STATUS_PENDING;
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
ConsoleInput *Input;
|
||||
ULONG i = ReadControl->nInitialChars;
|
||||
|
||||
if (Console == NULL || InputBuffer == NULL || /* Buffer == NULL || */
|
||||
ReadControl == NULL || ReadControl->nLength != sizeof(CONSOLE_READCONSOLE_CONTROL))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Validity checks */
|
||||
ASSERT(Console == InputBuffer->Header.Console);
|
||||
ASSERT( (Buffer != NULL && NumCharsToRead >= 0) ||
|
||||
(Buffer == NULL && NumCharsToRead == 0) );
|
||||
|
||||
/* We haven't read anything (yet) */
|
||||
|
||||
if (InputBuffer->Mode & ENABLE_LINE_INPUT)
|
||||
{
|
||||
if (Console->LineBuffer == NULL)
|
||||
{
|
||||
/* Starting a new line */
|
||||
Console->LineMaxSize = (WORD)max(256, NumCharsToRead);
|
||||
|
||||
Console->LineBuffer = ConsoleAllocHeap(0, Console->LineMaxSize * sizeof(WCHAR));
|
||||
if (Console->LineBuffer == NULL) return STATUS_NO_MEMORY;
|
||||
|
||||
Console->LineComplete = FALSE;
|
||||
Console->LineUpPressed = FALSE;
|
||||
Console->LineInsertToggle = 0;
|
||||
Console->LineWakeupMask = ReadControl->dwCtrlWakeupMask;
|
||||
Console->LineSize = ReadControl->nInitialChars;
|
||||
Console->LinePos = Console->LineSize;
|
||||
|
||||
/*
|
||||
* Pre-filling the buffer is only allowed in the Unicode API,
|
||||
* so we don't need to worry about ANSI <-> Unicode conversion.
|
||||
*/
|
||||
memcpy(Console->LineBuffer, Buffer, Console->LineSize * sizeof(WCHAR));
|
||||
if (Console->LineSize == Console->LineMaxSize)
|
||||
{
|
||||
Console->LineComplete = TRUE;
|
||||
Console->LinePos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we don't have a complete line yet, process the pending input */
|
||||
while (!Console->LineComplete && !IsListEmpty(&InputBuffer->InputEvents))
|
||||
{
|
||||
/* Remove input event from queue */
|
||||
CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents);
|
||||
if (IsListEmpty(&InputBuffer->InputEvents))
|
||||
{
|
||||
ResetEvent(InputBuffer->ActiveEvent);
|
||||
}
|
||||
Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
|
||||
|
||||
/* Only pay attention to key down */
|
||||
if (Input->InputEvent.EventType == KEY_EVENT &&
|
||||
Input->InputEvent.Event.KeyEvent.bKeyDown)
|
||||
{
|
||||
LineInputKeyDown(Console, &Input->InputEvent.Event.KeyEvent);
|
||||
ReadControl->dwControlKeyState = Input->InputEvent.Event.KeyEvent.dwControlKeyState;
|
||||
}
|
||||
ConsoleFreeHeap(Input);
|
||||
}
|
||||
|
||||
/* Check if we have a complete line to read from */
|
||||
if (Console->LineComplete)
|
||||
{
|
||||
while (i < NumCharsToRead && Console->LinePos != Console->LineSize)
|
||||
{
|
||||
WCHAR Char = Console->LineBuffer[Console->LinePos++];
|
||||
|
||||
if (Unicode)
|
||||
{
|
||||
((PWCHAR)Buffer)[i] = Char;
|
||||
}
|
||||
else
|
||||
{
|
||||
ConsoleInputUnicodeCharToAnsiChar(Console, &((PCHAR)Buffer)[i], &Char);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
if (Console->LinePos == Console->LineSize)
|
||||
{
|
||||
/* Entire line has been read */
|
||||
ConsoleFreeHeap(Console->LineBuffer);
|
||||
Console->LineBuffer = NULL;
|
||||
}
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Character input */
|
||||
while (i < NumCharsToRead && !IsListEmpty(&InputBuffer->InputEvents))
|
||||
{
|
||||
/* Remove input event from queue */
|
||||
CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents);
|
||||
if (IsListEmpty(&InputBuffer->InputEvents))
|
||||
{
|
||||
ResetEvent(InputBuffer->ActiveEvent);
|
||||
}
|
||||
Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
|
||||
|
||||
/* Only pay attention to valid ASCII chars, on key down */
|
||||
if (Input->InputEvent.EventType == KEY_EVENT &&
|
||||
Input->InputEvent.Event.KeyEvent.bKeyDown &&
|
||||
Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar != L'\0')
|
||||
{
|
||||
WCHAR Char = Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar;
|
||||
|
||||
if (Unicode)
|
||||
{
|
||||
((PWCHAR)Buffer)[i] = Char;
|
||||
}
|
||||
else
|
||||
{
|
||||
ConsoleInputUnicodeCharToAnsiChar(Console, &((PCHAR)Buffer)[i], &Char);
|
||||
}
|
||||
++i;
|
||||
|
||||
/* Did read something */
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
ConsoleFreeHeap(Input);
|
||||
}
|
||||
}
|
||||
|
||||
if (NumCharsRead) *NumCharsRead = i;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvGetConsoleInput(IN PCONSOLE Console,
|
||||
IN PCONSOLE_INPUT_BUFFER InputBuffer,
|
||||
IN BOOLEAN WaitForMoreEvents,
|
||||
IN BOOLEAN Unicode,
|
||||
OUT PINPUT_RECORD InputRecord,
|
||||
IN ULONG NumEventsToRead,
|
||||
OUT PULONG NumEventsRead OPTIONAL)
|
||||
{
|
||||
PLIST_ENTRY CurrentInput;
|
||||
ConsoleInput* Input;
|
||||
ULONG i = 0;
|
||||
|
||||
if (Console == NULL || InputBuffer == NULL /* || InputRecord == NULL */)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* Validity checks */
|
||||
ASSERT(Console == InputBuffer->Header.Console);
|
||||
ASSERT( (InputRecord != NULL && NumEventsToRead >= 0) ||
|
||||
(InputRecord == NULL && NumEventsToRead == 0) );
|
||||
|
||||
// Do NOT do that !! Use the existing number of events already read, if any...
|
||||
// if (NumEventsRead) *NumEventsRead = 0;
|
||||
|
||||
if (IsListEmpty(&InputBuffer->InputEvents))
|
||||
{
|
||||
/*
|
||||
* No input is available. Wait for more input if requested,
|
||||
* otherwise, we don't wait, so we return success.
|
||||
*/
|
||||
return (WaitForMoreEvents ? STATUS_PENDING : STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
/* Only get input if there is any */
|
||||
CurrentInput = InputBuffer->InputEvents.Flink;
|
||||
if (NumEventsRead) i = *NumEventsRead; // We will read the remaining events...
|
||||
|
||||
while ((CurrentInput != &InputBuffer->InputEvents) && (i < NumEventsToRead))
|
||||
{
|
||||
Input = CONTAINING_RECORD(CurrentInput, ConsoleInput, ListEntry);
|
||||
|
||||
*InputRecord = Input->InputEvent;
|
||||
|
||||
if (!Unicode)
|
||||
{
|
||||
ConioInputEventToAnsi(InputBuffer->Header.Console, InputRecord);
|
||||
}
|
||||
|
||||
++InputRecord;
|
||||
++i;
|
||||
CurrentInput = CurrentInput->Flink;
|
||||
|
||||
if (WaitForMoreEvents) // TRUE --> Read, we remove inputs from the buffer ; FALSE --> Peek, we keep inputs.
|
||||
{
|
||||
RemoveEntryList(&Input->ListEntry);
|
||||
ConsoleFreeHeap(Input);
|
||||
}
|
||||
}
|
||||
|
||||
if (NumEventsRead) *NumEventsRead = i;
|
||||
|
||||
if (IsListEmpty(&InputBuffer->InputEvents))
|
||||
{
|
||||
ResetEvent(InputBuffer->ActiveEvent);
|
||||
}
|
||||
|
||||
/* We read all the inputs available, we return success */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvWriteConsoleInput(IN PCONSOLE Console,
|
||||
IN PCONSOLE_INPUT_BUFFER InputBuffer,
|
||||
IN BOOLEAN Unicode,
|
||||
IN PINPUT_RECORD InputRecord,
|
||||
IN ULONG NumEventsToWrite,
|
||||
OUT PULONG NumEventsWritten)
|
||||
OUT PULONG NumEventsWritten OPTIONAL)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
ULONG i;
|
||||
|
@ -230,9 +439,10 @@ ConDrvWriteConsoleInput(IN PCONSOLE Console,
|
|||
ASSERT( (InputRecord != NULL && NumEventsToWrite >= 0) ||
|
||||
(InputRecord == NULL && NumEventsToWrite == 0) );
|
||||
|
||||
if (NumEventsWritten) *NumEventsWritten = 0;
|
||||
// Do NOT do that !! Use the existing number of events already written, if any...
|
||||
// if (NumEventsWritten) *NumEventsWritten = 0;
|
||||
|
||||
for (i = 0; i < NumEventsToWrite && NT_SUCCESS(Status); ++i)
|
||||
for (i = (NumEventsWritten ? *NumEventsWritten : 0); i < NumEventsToWrite && NT_SUCCESS(Status); ++i)
|
||||
{
|
||||
if (InputRecord->EventType == KEY_EVENT && !Unicode)
|
||||
{
|
||||
|
|
|
@ -751,9 +751,77 @@ ConDrvWriteConsoleOutput(IN PCONSOLE Console,
|
|||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvWriteConsole(IN PCONSOLE Console)
|
||||
ConDrvWriteConsole(IN PCONSOLE Console,
|
||||
IN PTEXTMODE_SCREEN_BUFFER ScreenBuffer,
|
||||
IN BOOLEAN Unicode,
|
||||
IN PVOID StringBuffer,
|
||||
IN ULONG NumCharsToWrite,
|
||||
OUT PULONG NumCharsWritten OPTIONAL)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PWCHAR Buffer = NULL;
|
||||
ULONG Written = 0;
|
||||
ULONG Length;
|
||||
|
||||
if (Console == NULL || ScreenBuffer == NULL /* || StringBuffer == NULL */)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* Validity checks */
|
||||
ASSERT(Console == ScreenBuffer->Header.Console);
|
||||
ASSERT( (StringBuffer != NULL && NumCharsToWrite >= 0) ||
|
||||
(StringBuffer == NULL && NumCharsToWrite == 0) );
|
||||
|
||||
// if (Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION))
|
||||
if (Console->PauseFlags && Console->UnpauseEvent != NULL)
|
||||
{
|
||||
return STATUS_PENDING;
|
||||
}
|
||||
|
||||
if (Unicode)
|
||||
{
|
||||
Buffer = StringBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
Length = MultiByteToWideChar(Console->OutputCodePage, 0,
|
||||
(PCHAR)StringBuffer,
|
||||
NumCharsToWrite,
|
||||
NULL, 0);
|
||||
Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length * sizeof(WCHAR));
|
||||
if (Buffer)
|
||||
{
|
||||
MultiByteToWideChar(Console->OutputCodePage, 0,
|
||||
(PCHAR)StringBuffer,
|
||||
NumCharsToWrite,
|
||||
(PWCHAR)Buffer, Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
if (Buffer)
|
||||
{
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Status = ConioWriteConsole(Console,
|
||||
ScreenBuffer,
|
||||
Buffer,
|
||||
NumCharsToWrite,
|
||||
TRUE);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Written = NumCharsToWrite;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Unicode) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
|
||||
}
|
||||
|
||||
if (NumCharsWritten) *NumCharsWritten = Written;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
|
|
|
@ -31,15 +31,6 @@
|
|||
ConSrvReleaseObject(&(Buff)->Header, (IsConsoleLocked))
|
||||
|
||||
|
||||
#define ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar) \
|
||||
WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
|
||||
|
||||
typedef struct ConsoleInput_t
|
||||
{
|
||||
LIST_ENTRY ListEntry;
|
||||
INPUT_RECORD InputEvent;
|
||||
} ConsoleInput;
|
||||
|
||||
typedef struct _GET_INPUT_INFO
|
||||
{
|
||||
PCSR_THREAD CallingThread; // The thread which called the input API.
|
||||
|
@ -50,19 +41,6 @@ typedef struct _GET_INPUT_INFO
|
|||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
static VOID FASTCALL
|
||||
ConioInputEventToAnsi(PCONSOLE Console, PINPUT_RECORD InputEvent)
|
||||
{
|
||||
if (InputEvent->EventType == KEY_EVENT)
|
||||
{
|
||||
WCHAR UnicodeChar = InputEvent->Event.KeyEvent.uChar.UnicodeChar;
|
||||
InputEvent->Event.KeyEvent.uChar.UnicodeChar = 0;
|
||||
ConsoleInputUnicodeCharToAnsiChar(Console,
|
||||
&InputEvent->Event.KeyEvent.uChar.AsciiChar,
|
||||
&UnicodeChar);
|
||||
}
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
WaitBeforeReading(IN PGET_INPUT_INFO InputInfo,
|
||||
IN PCSR_API_MESSAGE ApiMessage,
|
||||
|
@ -94,6 +72,120 @@ WaitBeforeReading(IN PGET_INPUT_INFO InputInfo,
|
|||
return STATUS_PENDING;
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
ReadChars(IN PGET_INPUT_INFO InputInfo,
|
||||
IN PCSR_API_MESSAGE ApiMessage,
|
||||
IN BOOL CreateWaitBlock OPTIONAL);
|
||||
|
||||
// Wait function CSR_WAIT_FUNCTION
|
||||
static BOOLEAN
|
||||
ReadCharsThread(IN PLIST_ENTRY WaitList,
|
||||
IN PCSR_THREAD WaitThread,
|
||||
IN PCSR_API_MESSAGE WaitApiMessage,
|
||||
IN PVOID WaitContext,
|
||||
IN PVOID WaitArgument1,
|
||||
IN PVOID WaitArgument2,
|
||||
IN ULONG WaitFlags)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PGET_INPUT_INFO InputInfo = (PGET_INPUT_INFO)WaitContext;
|
||||
|
||||
PVOID InputHandle = WaitArgument2;
|
||||
|
||||
DPRINT("ReadCharsThread - WaitContext = 0x%p, WaitArgument1 = 0x%p, WaitArgument2 = 0x%p, WaitFlags = %lu\n", WaitContext, WaitArgument1, WaitArgument2, WaitFlags);
|
||||
|
||||
/*
|
||||
* If we are notified of the process termination via a call
|
||||
* to CsrNotifyWaitBlock triggered by CsrDestroyProcess or
|
||||
* CsrDestroyThread, just return.
|
||||
*/
|
||||
if (WaitFlags & CsrProcessTerminating)
|
||||
{
|
||||
Status = STATUS_THREAD_IS_TERMINATING;
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Somebody is closing a handle to this input buffer,
|
||||
* by calling ConSrvCloseHandleEntry.
|
||||
* See whether we are linked to that handle (ie. we
|
||||
* are a waiter for this handle), and if so, return.
|
||||
* Otherwise, ignore the call and continue waiting.
|
||||
*/
|
||||
if (InputHandle != NULL)
|
||||
{
|
||||
Status = (InputHandle == InputInfo->HandleEntry ? STATUS_ALERTED
|
||||
: STATUS_PENDING);
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we go there, that means we are notified for some new input.
|
||||
* The console is therefore already locked.
|
||||
*/
|
||||
Status = ReadChars(InputInfo,
|
||||
WaitApiMessage,
|
||||
FALSE);
|
||||
|
||||
Quit:
|
||||
if (Status != STATUS_PENDING)
|
||||
{
|
||||
WaitApiMessage->Status = Status;
|
||||
ConsoleFreeHeap(InputInfo);
|
||||
}
|
||||
|
||||
return (Status == STATUS_PENDING ? FALSE : TRUE);
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvReadConsole(IN PCONSOLE Console,
|
||||
IN PCONSOLE_INPUT_BUFFER InputBuffer,
|
||||
IN BOOLEAN Unicode,
|
||||
OUT PVOID Buffer,
|
||||
IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl,
|
||||
IN ULONG NumCharsToRead,
|
||||
OUT PULONG NumCharsRead OPTIONAL);
|
||||
static NTSTATUS
|
||||
ReadChars(IN PGET_INPUT_INFO InputInfo,
|
||||
IN PCSR_API_MESSAGE ApiMessage,
|
||||
IN BOOL CreateWaitBlock OPTIONAL)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_READCONSOLE ReadConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleRequest;
|
||||
PCONSOLE_INPUT_BUFFER InputBuffer = InputInfo->InputBuffer;
|
||||
CONSOLE_READCONSOLE_CONTROL ReadControl;
|
||||
|
||||
ReadControl.nLength = sizeof(CONSOLE_READCONSOLE_CONTROL);
|
||||
ReadControl.nInitialChars = ReadConsoleRequest->NrCharactersRead;
|
||||
ReadControl.dwCtrlWakeupMask = ReadConsoleRequest->CtrlWakeupMask;
|
||||
ReadControl.dwControlKeyState = ReadConsoleRequest->ControlKeyState;
|
||||
|
||||
Status = ConDrvReadConsole(InputBuffer->Header.Console,
|
||||
InputBuffer,
|
||||
ReadConsoleRequest->Unicode,
|
||||
ReadConsoleRequest->Buffer,
|
||||
&ReadControl,
|
||||
ReadConsoleRequest->NrCharactersToRead,
|
||||
&ReadConsoleRequest->NrCharactersRead);
|
||||
|
||||
ReadConsoleRequest->ControlKeyState = ReadControl.dwControlKeyState;
|
||||
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
/* We haven't completed a read, so start a wait */
|
||||
return WaitBeforeReading(InputInfo,
|
||||
ApiMessage,
|
||||
ReadCharsThread,
|
||||
CreateWaitBlock);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We read all what we wanted, we return the error code we were given */
|
||||
return Status;
|
||||
// return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
ReadInputBuffer(IN PGET_INPUT_INFO InputInfo,
|
||||
IN BOOL Wait,
|
||||
|
@ -162,292 +254,47 @@ Quit:
|
|||
return (Status == STATUS_PENDING ? FALSE : TRUE);
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvGetConsoleInput(IN PCONSOLE Console,
|
||||
IN PCONSOLE_INPUT_BUFFER InputBuffer,
|
||||
IN BOOLEAN WaitForMoreEvents,
|
||||
IN BOOLEAN Unicode,
|
||||
OUT PINPUT_RECORD InputRecord,
|
||||
IN ULONG NumEventsToRead,
|
||||
OUT PULONG NumEventsRead);
|
||||
static NTSTATUS
|
||||
ReadInputBuffer(IN PGET_INPUT_INFO InputInfo,
|
||||
IN BOOL Wait, // TRUE --> Read ; FALSE --> Peek
|
||||
IN PCSR_API_MESSAGE ApiMessage,
|
||||
IN BOOL CreateWaitBlock OPTIONAL)
|
||||
{
|
||||
PCONSOLE_INPUT_BUFFER InputBuffer = InputInfo->InputBuffer;
|
||||
|
||||
if (IsListEmpty(&InputBuffer->InputEvents))
|
||||
{
|
||||
if (Wait)
|
||||
{
|
||||
return WaitBeforeReading(InputInfo,
|
||||
ApiMessage,
|
||||
ReadInputBufferThread,
|
||||
CreateWaitBlock);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No input available and we don't wait, so we return success */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PCONSOLE_GETINPUT GetInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetInputRequest;
|
||||
PLIST_ENTRY CurrentInput;
|
||||
ConsoleInput* Input;
|
||||
ULONG Length = GetInputRequest->Length;
|
||||
PINPUT_RECORD InputRecord = GetInputRequest->InputRecord;
|
||||
|
||||
/* Only get input if there is any */
|
||||
CurrentInput = InputBuffer->InputEvents.Flink;
|
||||
|
||||
while ( CurrentInput != &InputBuffer->InputEvents &&
|
||||
GetInputRequest->InputsRead < Length )
|
||||
{
|
||||
Input = CONTAINING_RECORD(CurrentInput, ConsoleInput, ListEntry);
|
||||
|
||||
GetInputRequest->InputsRead++;
|
||||
*InputRecord = Input->InputEvent;
|
||||
|
||||
if (GetInputRequest->Unicode == FALSE)
|
||||
{
|
||||
ConioInputEventToAnsi(InputBuffer->Header.Console, InputRecord);
|
||||
}
|
||||
|
||||
InputRecord++;
|
||||
CurrentInput = CurrentInput->Flink;
|
||||
|
||||
if (Wait) // TRUE --> Read, we remove inputs from the buffer ; FALSE --> Peek, we keep inputs.
|
||||
{
|
||||
RemoveEntryList(&Input->ListEntry);
|
||||
ConsoleFreeHeap(Input);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsListEmpty(&InputBuffer->InputEvents))
|
||||
{
|
||||
ResetEvent(InputBuffer->ActiveEvent);
|
||||
}
|
||||
|
||||
/* We read all the inputs available, we return success */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
ReadChars(IN PGET_INPUT_INFO InputInfo,
|
||||
IN PCSR_API_MESSAGE ApiMessage,
|
||||
IN BOOL CreateWaitBlock OPTIONAL);
|
||||
|
||||
// Wait function CSR_WAIT_FUNCTION
|
||||
static BOOLEAN
|
||||
ReadCharsThread(IN PLIST_ENTRY WaitList,
|
||||
IN PCSR_THREAD WaitThread,
|
||||
IN PCSR_API_MESSAGE WaitApiMessage,
|
||||
IN PVOID WaitContext,
|
||||
IN PVOID WaitArgument1,
|
||||
IN PVOID WaitArgument2,
|
||||
IN ULONG WaitFlags)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PGET_INPUT_INFO InputInfo = (PGET_INPUT_INFO)WaitContext;
|
||||
|
||||
PVOID InputHandle = WaitArgument2;
|
||||
|
||||
DPRINT("ReadCharsThread - WaitContext = 0x%p, WaitArgument1 = 0x%p, WaitArgument2 = 0x%p, WaitFlags = %lu\n", WaitContext, WaitArgument1, WaitArgument2, WaitFlags);
|
||||
|
||||
/*
|
||||
* If we are notified of the process termination via a call
|
||||
* to CsrNotifyWaitBlock triggered by CsrDestroyProcess or
|
||||
* CsrDestroyThread, just return.
|
||||
*/
|
||||
if (WaitFlags & CsrProcessTerminating)
|
||||
{
|
||||
Status = STATUS_THREAD_IS_TERMINATING;
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Somebody is closing a handle to this input buffer,
|
||||
* by calling ConSrvCloseHandleEntry.
|
||||
* See whether we are linked to that handle (ie. we
|
||||
* are a waiter for this handle), and if so, return.
|
||||
* Otherwise, ignore the call and continue waiting.
|
||||
*/
|
||||
if (InputHandle != NULL)
|
||||
{
|
||||
Status = (InputHandle == InputInfo->HandleEntry ? STATUS_ALERTED
|
||||
: STATUS_PENDING);
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we go there, that means we are notified for some new input.
|
||||
* The console is therefore already locked.
|
||||
*/
|
||||
Status = ReadChars(InputInfo,
|
||||
WaitApiMessage,
|
||||
FALSE);
|
||||
|
||||
Quit:
|
||||
if (Status != STATUS_PENDING)
|
||||
{
|
||||
WaitApiMessage->Status = Status;
|
||||
ConsoleFreeHeap(InputInfo);
|
||||
}
|
||||
|
||||
return (Status == STATUS_PENDING ? FALSE : TRUE);
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
ReadChars(IN PGET_INPUT_INFO InputInfo,
|
||||
IN PCSR_API_MESSAGE ApiMessage,
|
||||
IN BOOL CreateWaitBlock OPTIONAL)
|
||||
{
|
||||
BOOL WaitForMoreToRead = TRUE; // TRUE : Wait if more to read ; FALSE : Don't wait.
|
||||
|
||||
PCONSOLE_READCONSOLE ReadConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleRequest;
|
||||
PCONSOLE_GETINPUT GetInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetInputRequest;
|
||||
PCONSOLE_INPUT_BUFFER InputBuffer = InputInfo->InputBuffer;
|
||||
PCONSOLE Console = InputBuffer->Header.Console;
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
ConsoleInput *Input;
|
||||
PCHAR Buffer = (PCHAR)ReadConsoleRequest->Buffer;
|
||||
PWCHAR UnicodeBuffer = (PWCHAR)Buffer;
|
||||
ULONG nNumberOfCharsToRead = ReadConsoleRequest->NrCharactersToRead;
|
||||
|
||||
/* We haven't read anything (yet) */
|
||||
// GetInputRequest->InputsRead = 0;
|
||||
|
||||
if (InputBuffer->Mode & ENABLE_LINE_INPUT)
|
||||
{
|
||||
if (Console->LineBuffer == NULL)
|
||||
{
|
||||
/* Starting a new line */
|
||||
Console->LineMaxSize = (WORD)max(256, nNumberOfCharsToRead);
|
||||
Console->LineBuffer = ConsoleAllocHeap(0, Console->LineMaxSize * sizeof(WCHAR));
|
||||
if (Console->LineBuffer == NULL)
|
||||
{
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
Console->LineComplete = FALSE;
|
||||
Console->LineUpPressed = FALSE;
|
||||
Console->LineInsertToggle = 0;
|
||||
Console->LineWakeupMask = ReadConsoleRequest->CtrlWakeupMask;
|
||||
Console->LineSize = ReadConsoleRequest->NrCharactersRead;
|
||||
Console->LinePos = Console->LineSize;
|
||||
|
||||
/*
|
||||
* Pre-filling the buffer is only allowed in the Unicode API,
|
||||
* so we don't need to worry about ANSI <-> Unicode conversion.
|
||||
*/
|
||||
memcpy(Console->LineBuffer, Buffer, Console->LineSize * sizeof(WCHAR));
|
||||
if (Console->LineSize == Console->LineMaxSize)
|
||||
{
|
||||
Console->LineComplete = TRUE;
|
||||
Console->LinePos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we don't have a complete line yet, process the pending input */
|
||||
while ( !Console->LineComplete &&
|
||||
!IsListEmpty(&InputBuffer->InputEvents) )
|
||||
{
|
||||
/* Remove input event from queue */
|
||||
CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents);
|
||||
if (IsListEmpty(&InputBuffer->InputEvents))
|
||||
{
|
||||
ResetEvent(InputBuffer->ActiveEvent);
|
||||
}
|
||||
Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
|
||||
|
||||
/* Only pay attention to key down */
|
||||
if (KEY_EVENT == Input->InputEvent.EventType
|
||||
&& Input->InputEvent.Event.KeyEvent.bKeyDown)
|
||||
{
|
||||
LineInputKeyDown(Console, &Input->InputEvent.Event.KeyEvent);
|
||||
ReadConsoleRequest->ControlKeyState = Input->InputEvent.Event.KeyEvent.dwControlKeyState;
|
||||
}
|
||||
ConsoleFreeHeap(Input);
|
||||
}
|
||||
|
||||
/* Check if we have a complete line to read from */
|
||||
if (Console->LineComplete)
|
||||
{
|
||||
while ( ReadConsoleRequest->NrCharactersRead < nNumberOfCharsToRead &&
|
||||
Console->LinePos != Console->LineSize )
|
||||
{
|
||||
WCHAR Char = Console->LineBuffer[Console->LinePos++];
|
||||
|
||||
if (ReadConsoleRequest->Unicode)
|
||||
{
|
||||
UnicodeBuffer[ReadConsoleRequest->NrCharactersRead] = Char;
|
||||
}
|
||||
else
|
||||
{
|
||||
ConsoleInputUnicodeCharToAnsiChar(Console,
|
||||
&Buffer[ReadConsoleRequest->NrCharactersRead],
|
||||
&Char);
|
||||
}
|
||||
|
||||
ReadConsoleRequest->NrCharactersRead++;
|
||||
}
|
||||
|
||||
if (Console->LinePos == Console->LineSize)
|
||||
{
|
||||
/* Entire line has been read */
|
||||
ConsoleFreeHeap(Console->LineBuffer);
|
||||
Console->LineBuffer = NULL;
|
||||
}
|
||||
|
||||
WaitForMoreToRead = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Character input */
|
||||
while ( ReadConsoleRequest->NrCharactersRead < nNumberOfCharsToRead &&
|
||||
!IsListEmpty(&InputBuffer->InputEvents) )
|
||||
{
|
||||
/* Remove input event from queue */
|
||||
CurrentEntry = RemoveHeadList(&InputBuffer->InputEvents);
|
||||
if (IsListEmpty(&InputBuffer->InputEvents))
|
||||
{
|
||||
ResetEvent(InputBuffer->ActiveEvent);
|
||||
}
|
||||
Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
|
||||
|
||||
/* Only pay attention to valid ascii chars, on key down */
|
||||
if (KEY_EVENT == Input->InputEvent.EventType
|
||||
&& Input->InputEvent.Event.KeyEvent.bKeyDown
|
||||
&& Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar != L'\0')
|
||||
{
|
||||
WCHAR Char = Input->InputEvent.Event.KeyEvent.uChar.UnicodeChar;
|
||||
|
||||
if (ReadConsoleRequest->Unicode)
|
||||
{
|
||||
UnicodeBuffer[ReadConsoleRequest->NrCharactersRead] = Char;
|
||||
}
|
||||
else
|
||||
{
|
||||
ConsoleInputUnicodeCharToAnsiChar(Console,
|
||||
&Buffer[ReadConsoleRequest->NrCharactersRead],
|
||||
&Char);
|
||||
}
|
||||
|
||||
ReadConsoleRequest->NrCharactersRead++;
|
||||
|
||||
/* Did read something */
|
||||
WaitForMoreToRead = FALSE;
|
||||
}
|
||||
ConsoleFreeHeap(Input);
|
||||
}
|
||||
}
|
||||
|
||||
/* We haven't completed a read, so start a wait */
|
||||
if (WaitForMoreToRead == TRUE)
|
||||
Status = ConDrvGetConsoleInput(InputBuffer->Header.Console,
|
||||
InputBuffer,
|
||||
Wait,
|
||||
GetInputRequest->Unicode,
|
||||
GetInputRequest->InputRecord,
|
||||
GetInputRequest->Length,
|
||||
&GetInputRequest->InputsRead);
|
||||
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
/* We haven't completed a read, so start a wait */
|
||||
return WaitBeforeReading(InputInfo,
|
||||
ApiMessage,
|
||||
ReadCharsThread,
|
||||
ReadInputBufferThread,
|
||||
CreateWaitBlock);
|
||||
}
|
||||
else /* We read all what we wanted, we return success */
|
||||
else
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
/* We read all what we wanted, we return the error code we were given */
|
||||
return Status;
|
||||
// return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -481,7 +328,8 @@ CSR_API(SrvReadConsole)
|
|||
Status = ConSrvGetInputBufferAndHandleEntry(ProcessData, ReadConsoleRequest->InputHandle, &InputBuffer, &HandleEntry, GENERIC_READ, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
ReadConsoleRequest->NrCharactersRead = 0;
|
||||
// This member is set by the caller (IntReadConsole in kernel32)
|
||||
// ReadConsoleRequest->NrCharactersRead = 0;
|
||||
|
||||
InputInfo.CallingThread = CsrGetClientThread();
|
||||
InputInfo.HandleEntry = HandleEntry;
|
||||
|
@ -493,8 +341,7 @@ CSR_API(SrvReadConsole)
|
|||
|
||||
ConSrvReleaseInputBuffer(InputBuffer, TRUE);
|
||||
|
||||
if (Status == STATUS_PENDING)
|
||||
*ReplyCode = CsrReplyPending;
|
||||
if (Status == STATUS_PENDING) *ReplyCode = CsrReplyPending;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
@ -518,11 +365,11 @@ CSR_API(SrvGetConsoleInput)
|
|||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
GetInputRequest->InputsRead = 0;
|
||||
|
||||
Status = ConSrvGetInputBufferAndHandleEntry(ProcessData, GetInputRequest->InputHandle, &InputBuffer, &HandleEntry, GENERIC_READ, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
GetInputRequest->InputsRead = 0;
|
||||
|
||||
InputInfo.CallingThread = CsrGetClientThread();
|
||||
InputInfo.HandleEntry = HandleEntry;
|
||||
InputInfo.InputBuffer = InputBuffer;
|
||||
|
@ -534,8 +381,7 @@ CSR_API(SrvGetConsoleInput)
|
|||
|
||||
ConSrvReleaseInputBuffer(InputBuffer, TRUE);
|
||||
|
||||
if (Status == STATUS_PENDING)
|
||||
*ReplyCode = CsrReplyPending;
|
||||
if (Status == STATUS_PENDING) *ReplyCode = CsrReplyPending;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
@ -546,13 +392,13 @@ ConDrvWriteConsoleInput(IN PCONSOLE Console,
|
|||
IN BOOLEAN Unicode,
|
||||
IN PINPUT_RECORD InputRecord,
|
||||
IN ULONG NumEventsToWrite,
|
||||
OUT PULONG NumEventsWritten);
|
||||
OUT PULONG NumEventsWritten OPTIONAL);
|
||||
CSR_API(SrvWriteConsoleInput)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_WRITEINPUT WriteInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteInputRequest;
|
||||
PCONSOLE_INPUT_BUFFER InputBuffer;
|
||||
ULONG NumEventsWritten = 0;
|
||||
ULONG NumEventsWritten;
|
||||
|
||||
DPRINT("SrvWriteConsoleInput\n");
|
||||
|
||||
|
@ -569,6 +415,7 @@ CSR_API(SrvWriteConsoleInput)
|
|||
&InputBuffer, GENERIC_WRITE, TRUE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
NumEventsWritten = 0;
|
||||
Status = ConDrvWriteConsoleInput(InputBuffer->Header.Console,
|
||||
InputBuffer,
|
||||
WriteInputRequest->Unicode,
|
||||
|
|
|
@ -314,30 +314,39 @@ Quit:
|
|||
return (Status == STATUS_PENDING ? FALSE : TRUE);
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
ConDrvWriteConsole(IN PCONSOLE Console,
|
||||
IN PTEXTMODE_SCREEN_BUFFER ScreenBuffer,
|
||||
IN BOOLEAN Unicode,
|
||||
IN PVOID StringBuffer,
|
||||
IN ULONG NumCharsToWrite,
|
||||
OUT PULONG NumCharsWritten OPTIONAL);
|
||||
static NTSTATUS
|
||||
DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
|
||||
IN PCSR_THREAD ClientThread,
|
||||
IN BOOL CreateWaitBlock OPTIONAL)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
NTSTATUS Status;
|
||||
PCONSOLE_WRITECONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest;
|
||||
PCONSOLE Console;
|
||||
PTEXTMODE_SCREEN_BUFFER Buff;
|
||||
PVOID Buffer;
|
||||
DWORD Written = 0;
|
||||
ULONG Length;
|
||||
PTEXTMODE_SCREEN_BUFFER ScreenBuffer;
|
||||
|
||||
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(ClientThread->Process), WriteConsoleRequest->OutputHandle, &Buff, GENERIC_WRITE, FALSE);
|
||||
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(ClientThread->Process),
|
||||
WriteConsoleRequest->OutputHandle,
|
||||
&ScreenBuffer, GENERIC_WRITE, FALSE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
Console = Buff->Header.Console;
|
||||
Status = ConDrvWriteConsole(ScreenBuffer->Header.Console,
|
||||
ScreenBuffer,
|
||||
WriteConsoleRequest->Unicode,
|
||||
WriteConsoleRequest->Buffer,
|
||||
WriteConsoleRequest->NrCharactersToWrite,
|
||||
&WriteConsoleRequest->NrCharactersWritten);
|
||||
|
||||
// if (Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION))
|
||||
if (Console->PauseFlags && Console->UnpauseEvent != NULL)
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
if (CreateWaitBlock)
|
||||
{
|
||||
if (!CsrCreateWait(&Console->WriteWaitQueue,
|
||||
if (!CsrCreateWait(&ScreenBuffer->Header.Console->WriteWaitQueue,
|
||||
WriteConsoleThread,
|
||||
ClientThread,
|
||||
ApiMessage,
|
||||
|
@ -345,63 +354,17 @@ DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
|
|||
NULL))
|
||||
{
|
||||
/* Fail */
|
||||
ConSrvReleaseScreenBuffer(Buff, FALSE);
|
||||
return STATUS_NO_MEMORY;
|
||||
Status = STATUS_NO_MEMORY;
|
||||
goto Quit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait until we un-pause the console */
|
||||
Status = STATUS_PENDING;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (WriteConsoleRequest->Unicode)
|
||||
{
|
||||
Buffer = WriteConsoleRequest->Buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
Length = MultiByteToWideChar(Console->OutputCodePage, 0,
|
||||
(PCHAR)WriteConsoleRequest->Buffer,
|
||||
WriteConsoleRequest->NrCharactersToWrite,
|
||||
NULL, 0);
|
||||
Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length * sizeof(WCHAR));
|
||||
if (Buffer)
|
||||
{
|
||||
MultiByteToWideChar(Console->OutputCodePage, 0,
|
||||
(PCHAR)WriteConsoleRequest->Buffer,
|
||||
WriteConsoleRequest->NrCharactersToWrite,
|
||||
(PWCHAR)Buffer, Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
if (Buffer)
|
||||
{
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Status = ConioWriteConsole(Console,
|
||||
Buff,
|
||||
Buffer,
|
||||
WriteConsoleRequest->NrCharactersToWrite,
|
||||
TRUE);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Written = WriteConsoleRequest->NrCharactersToWrite;
|
||||
}
|
||||
}
|
||||
|
||||
if (!WriteConsoleRequest->Unicode)
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
|
||||
}
|
||||
|
||||
WriteConsoleRequest->NrCharactersWritten = Written;
|
||||
// Status = STATUS_PENDING;
|
||||
}
|
||||
|
||||
ConSrvReleaseScreenBuffer(Buff, FALSE);
|
||||
Quit:
|
||||
ConSrvReleaseScreenBuffer(ScreenBuffer, FALSE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -509,8 +472,7 @@ CSR_API(SrvWriteConsole)
|
|||
CsrGetClientThread(),
|
||||
TRUE);
|
||||
|
||||
if (Status == STATUS_PENDING)
|
||||
*ReplyCode = CsrReplyPending;
|
||||
if (Status == STATUS_PENDING) *ReplyCode = CsrReplyPending;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue