Author: hbelusca Date: Thu Jun 27 00:20:58 2013 New Revision: 59345 URL: http://svn.reactos.org/svn/reactos?rev=59345&view=rev Log: [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?) Modified: trunk/reactos/dll/win32/kernel32/client/console/readwrite.c trunk/reactos/include/reactos/subsys/win/conmsg.h trunk/reactos/win32ss/user/consrv/condrv/coninput.c trunk/reactos/win32ss/user/consrv/condrv/text.c trunk/reactos/win32ss/user/consrv/coninput.c trunk/reactos/win32ss/user/consrv/conoutput.c Modified: trunk/reactos/dll/win32/kernel32/client/console/readwrite.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/console/readwrite.c?rev=59345&r1=59344&r2=59345&view=diff ============================================================================== --- trunk/reactos/dll/win32/kernel32/client/console/readwrite.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/kernel32/client/console/readwrite.c [iso-8859-1] Thu Jun 27 00:20:58 2013 @@ -60,11 +60,17 @@ /* 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, Modified: trunk/reactos/include/reactos/subsys/win/conmsg.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/subsys/win/conmsg.h?rev=59345&r1=59344&r2=59345&view=diff ============================================================================== --- trunk/reactos/include/reactos/subsys/win/conmsg.h [iso-8859-1] (original) +++ trunk/reactos/include/reactos/subsys/win/conmsg.h [iso-8859-1] Thu Jun 27 00:20:58 2013 @@ -167,8 +167,8 @@ HANDLE InputHandle; BOOL Unicode; - WORD NrCharactersToRead; - WORD NrCharactersRead; + ULONG NrCharactersToRead; + ULONG NrCharactersRead; UNICODE_STRING ExeName; DWORD CtrlWakeupMask; Modified: trunk/reactos/win32ss/user/consrv/condrv/coninput.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/consrv/condrv/coninput.c?rev=59345&r1=59344&r2=59345&view=diff ============================================================================== --- trunk/reactos/win32ss/user/consrv/condrv/coninput.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/user/consrv/condrv/coninput.c [iso-8859-1] Thu Jun 27 00:20:58 2013 @@ -43,17 +43,9 @@ 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 @@ &UnicodeChar); } } -#endif NTSTATUS FASTCALL ConioProcessInputEvent(PCONSOLE Console, @@ -212,12 +203,230 @@ /* 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 @@ ASSERT( (InputRecord != NULL && NumEventsToWrite >= 0) || (InputRecord == NULL && NumEventsToWrite == 0) ); - if (NumEventsWritten) *NumEventsWritten = 0; - - for (i = 0; i < NumEventsToWrite && NT_SUCCESS(Status); ++i) + // Do NOT do that !! Use the existing number of events already written, if any... + // if (NumEventsWritten) *NumEventsWritten = 0; + + for (i = (NumEventsWritten ? *NumEventsWritten : 0); i < NumEventsToWrite && NT_SUCCESS(Status); ++i) { if (InputRecord->EventType == KEY_EVENT && !Unicode) { Modified: trunk/reactos/win32ss/user/consrv/condrv/text.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/consrv/condrv/text.c?rev=59345&r1=59344&r2=59345&view=diff ============================================================================== --- trunk/reactos/win32ss/user/consrv/condrv/text.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/user/consrv/condrv/text.c [iso-8859-1] Thu Jun 27 00:20:58 2013 @@ -751,9 +751,77 @@ } NTSTATUS NTAPI -ConDrvWriteConsole(IN PCONSOLE Console) -{ - return STATUS_NOT_IMPLEMENTED; +ConDrvWriteConsole(IN PCONSOLE Console, + IN PTEXTMODE_SCREEN_BUFFER ScreenBuffer, + IN BOOLEAN Unicode, + IN PVOID StringBuffer, + IN ULONG NumCharsToWrite, + OUT PULONG NumCharsWritten OPTIONAL) +{ + 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 Modified: trunk/reactos/win32ss/user/consrv/coninput.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/consrv/coninput.c?rev=59345&r1=59344&r2=59345&view=diff ============================================================================== --- trunk/reactos/win32ss/user/consrv/coninput.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/user/consrv/coninput.c [iso-8859-1] Thu Jun 27 00:20:58 2013 @@ -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. @@ -49,19 +40,6 @@ /* 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, @@ -95,6 +73,120 @@ } 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, IN PCSR_API_MESSAGE ApiMessage, @@ -162,292 +254,47 @@ 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) { + NTSTATUS Status; + PCONSOLE_GETINPUT GetInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetInputRequest; 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_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) */ - - 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) - { + // GetInputRequest->InputsRead = 0; + + 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 */ - { - return STATUS_SUCCESS; + else + { + /* We read all what we wanted, we return the error code we were given */ + return Status; + // return STATUS_SUCCESS; } } @@ -481,7 +328,8 @@ 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 @@ ConSrvReleaseInputBuffer(InputBuffer, TRUE); - if (Status == STATUS_PENDING) - *ReplyCode = CsrReplyPending; + if (Status == STATUS_PENDING) *ReplyCode = CsrReplyPending; return Status; } @@ -518,10 +365,10 @@ 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; @@ -534,8 +381,7 @@ ConSrvReleaseInputBuffer(InputBuffer, TRUE); - if (Status == STATUS_PENDING) - *ReplyCode = CsrReplyPending; + if (Status == STATUS_PENDING) *ReplyCode = CsrReplyPending; return Status; } @@ -546,13 +392,13 @@ 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 @@ &InputBuffer, GENERIC_WRITE, TRUE); if (!NT_SUCCESS(Status)) return Status; + NumEventsWritten = 0; Status = ConDrvWriteConsoleInput(InputBuffer->Header.Console, InputBuffer, WriteInputRequest->Unicode, Modified: trunk/reactos/win32ss/user/consrv/conoutput.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/consrv/conoutput.c?rev=59345&r1=59344&r2=59345&view=diff ============================================================================== --- trunk/reactos/win32ss/user/consrv/conoutput.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/user/consrv/conoutput.c [iso-8859-1] Thu Jun 27 00:20:58 2013 @@ -314,30 +314,39 @@ 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; - - Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(ClientThread->Process), WriteConsoleRequest->OutputHandle, &Buff, GENERIC_WRITE, FALSE); - if (!NT_SUCCESS(Status)) return Status; - - Console = Buff->Header.Console; - - // if (Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION)) - if (Console->PauseFlags && Console->UnpauseEvent != NULL) + PTEXTMODE_SCREEN_BUFFER ScreenBuffer; + + Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(ClientThread->Process), + WriteConsoleRequest->OutputHandle, + &ScreenBuffer, GENERIC_WRITE, FALSE); + if (!NT_SUCCESS(Status)) return Status; + + Status = ConDrvWriteConsole(ScreenBuffer->Header.Console, + ScreenBuffer, + WriteConsoleRequest->Unicode, + WriteConsoleRequest->Buffer, + WriteConsoleRequest->NrCharactersToWrite, + &WriteConsoleRequest->NrCharactersWritten); + + if (Status == STATUS_PENDING) { if (CreateWaitBlock) { - if (!CsrCreateWait(&Console->WriteWaitQueue, + if (!CsrCreateWait(&ScreenBuffer->Header.Console->WriteWaitQueue, WriteConsoleThread, ClientThread, ApiMessage, @@ -345,63 +354,17 @@ 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; - } - - ConSrvReleaseScreenBuffer(Buff, FALSE); + // Status = STATUS_PENDING; + } + +Quit: + ConSrvReleaseScreenBuffer(ScreenBuffer, FALSE); return Status; } @@ -509,8 +472,7 @@ CsrGetClientThread(), TRUE); - if (Status == STATUS_PENDING) - *ReplyCode = CsrReplyPending; + if (Status == STATUS_PENDING) *ReplyCode = CsrReplyPending; return Status; }