Author: hbelusca Date: Sat Dec 8 00:39:24 2012 New Revision: 57817
URL: http://svn.reactos.org/svn/reactos?rev=57817&view=rev Log: [KERNEL32] - Simplify IntGetConsoleInput and IntReadConsole.
[CONSRV] - Implement event waiting for reading console input buffer with CSR wait blocks. This replaces the event-based waiting which, after being moved from client-side (kernel32) to server-side (see r57721), made all consoles hang when one of them was waiting for new input.
TODO: Dereference all the waits in Console->ReadWaitQueue.
Modified: branches/ros-csrss/dll/win32/kernel32/client/console/readwrite.c branches/ros-csrss/include/reactos/subsys/win/conmsg.h branches/ros-csrss/win32ss/user/consrv/coninput.c branches/ros-csrss/win32ss/user/consrv/conio.h branches/ros-csrss/win32ss/user/consrv/console.c
Modified: branches/ros-csrss/dll/win32/kernel32/client/console/readwrite.c URL: http://svn.reactos.org/svn/reactos/branches/ros-csrss/dll/win32/kernel32/cli... ============================================================================== --- branches/ros-csrss/dll/win32/kernel32/client/console/readwrite.c [iso-8859-1] (original) +++ branches/ros-csrss/dll/win32/kernel32/client/console/readwrite.c [iso-8859-1] Sat Dec 8 00:39:24 2012 @@ -57,6 +57,7 @@ ReadConsoleRequest->BufferSize, (PVOID*)&ReadConsoleRequest->Buffer);
+ /* Set up the data to send to the Console Server */ ReadConsoleRequest->ConsoleHandle = hConsoleInput; ReadConsoleRequest->Unicode = bUnicode; ReadConsoleRequest->NrCharactersToRead = (WORD)nNumberOfCharsToRead; @@ -71,31 +72,42 @@ ReadConsoleRequest->CtrlWakeupMask = pInputControl->dwCtrlWakeupMask; }
+ /* Call the server */ Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, CaptureBuffer, CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepReadConsole), sizeof(CSRSS_READ_CONSOLE)); - if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = ApiMessage.Status)) + + /* Check for success */ + if (NT_SUCCESS(Status) || NT_SUCCESS(Status = ApiMessage.Status)) + { + memcpy(lpBuffer, + ReadConsoleRequest->Buffer, + ReadConsoleRequest->NrCharactersRead * CharSize); + + if (lpNumberOfCharsRead != NULL) + *lpNumberOfCharsRead = ReadConsoleRequest->NrCharactersRead; + + if (pInputControl && pInputControl->nLength == sizeof(CONSOLE_READCONSOLE_CONTROL)) + pInputControl->dwControlKeyState = ReadConsoleRequest->ControlKeyState; + } + else { DPRINT1("CSR returned error in ReadConsole\n"); - CsrFreeCaptureBuffer(CaptureBuffer); - BaseSetLastNTError(Status); - return FALSE; - } - - memcpy(lpBuffer, - ReadConsoleRequest->Buffer, - ReadConsoleRequest->NrCharactersRead * CharSize); - - if (lpNumberOfCharsRead != NULL) - *lpNumberOfCharsRead = ReadConsoleRequest->NrCharactersRead; - - if (pInputControl && pInputControl->nLength == sizeof(CONSOLE_READCONSOLE_CONTROL)) - pInputControl->dwControlKeyState = ReadConsoleRequest->ControlKeyState; + + if (lpNumberOfCharsRead != NULL) + *lpNumberOfCharsRead = 0; + + /* Error out */ + BaseSetLastNTError(Status /* ApiMessage.Status */); + }
CsrFreeCaptureBuffer(CaptureBuffer);
- return TRUE; + /* Return TRUE or FALSE */ + // return TRUE; + return (ReadConsoleRequest->NrCharactersRead > 0); + // return NT_SUCCESS(ApiMessage.Status); }
@@ -142,10 +154,7 @@ GetConsoleInputRequest->ConsoleHandle = hConsoleInput; GetConsoleInputRequest->Unicode = bUnicode; GetConsoleInputRequest->bRead = bRead; - if (bRead == TRUE) - { - GetConsoleInputRequest->InputsRead = 0; - } + GetConsoleInputRequest->InputsRead = 0; GetConsoleInputRequest->Length = nLength;
/* Call the server */ @@ -155,9 +164,30 @@ sizeof(CSRSS_GET_CONSOLE_INPUT)); DPRINT("Server returned: %x\n", ApiMessage.Status);
-/** For Read only ** - if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = ApiMessage.Status)) - { + /* Check for success */ + if (NT_SUCCESS(Status) || NT_SUCCESS(Status = ApiMessage.Status)) + { + /* Return the number of events read */ + DPRINT("Events read: %lx\n", GetConsoleInputRequest->InputsRead); + + if (lpNumberOfEventsRead != NULL) + *lpNumberOfEventsRead = GetConsoleInputRequest->InputsRead; + + /* Copy into the buffer */ + DPRINT("Copying to buffer\n"); + RtlCopyMemory(lpBuffer, + GetConsoleInputRequest->InputRecord, + sizeof(INPUT_RECORD) * GetConsoleInputRequest->InputsRead); + } + else + { + if (lpNumberOfEventsRead != NULL) + *lpNumberOfEventsRead = 0; + + /* Error out */ + BaseSetLastNTError(ApiMessage.Status); + +/********* // BaseSetLastNTError(Status); ???? if (GetConsoleInputRequest->InputsRead == 0) { @@ -170,75 +200,15 @@ /* FIXME - fail gracefully in case we already read at least one record? */ // break; } - } -**/ - - /** - ** TODO: !! Simplify the function !! - **/ - if (bRead == TRUE) // ReadConsoleInput call. - { - /* Check for success */ - if (NT_SUCCESS(Status) || NT_SUCCESS(Status = ApiMessage.Status)) - { - /* Return the number of events read */ - DPRINT("Events read: %lx\n", GetConsoleInputRequest->InputsRead/*Length*/); - - if (lpNumberOfEventsRead != NULL) - *lpNumberOfEventsRead = GetConsoleInputRequest->InputsRead/*Length*/; - - /* Copy into the buffer */ - DPRINT("Copying to buffer\n"); - RtlCopyMemory(lpBuffer, - GetConsoleInputRequest->InputRecord, - sizeof(INPUT_RECORD) * GetConsoleInputRequest->InputsRead/*Length*/); - } - else - { - if (lpNumberOfEventsRead != NULL) - *lpNumberOfEventsRead = 0; - - /* Error out */ - BaseSetLastNTError(ApiMessage.Status); - } - - /* Release the capture buffer */ - CsrFreeCaptureBuffer(CaptureBuffer); - - return (GetConsoleInputRequest->InputsRead > 0); - } - else // PeekConsoleInput call. - { - /* Check for success */ - if (NT_SUCCESS(Status) || NT_SUCCESS(ApiMessage.Status)) - { - /* Return the number of events read */ - DPRINT("Events read: %lx\n", GetConsoleInputRequest->Length); - - if (lpNumberOfEventsRead != NULL) - *lpNumberOfEventsRead = GetConsoleInputRequest->Length; - - /* Copy into the buffer */ - DPRINT("Copying to buffer\n"); - RtlCopyMemory(lpBuffer, - GetConsoleInputRequest->InputRecord, - sizeof(INPUT_RECORD) * GetConsoleInputRequest->Length); - } - else - { - if (lpNumberOfEventsRead != NULL) - *lpNumberOfEventsRead = 0; - - /* Error out */ - BaseSetLastNTError(ApiMessage.Status); - } - - /* Release the capture buffer */ - CsrFreeCaptureBuffer(CaptureBuffer); - - /* Return TRUE or FALSE */ - return NT_SUCCESS(ApiMessage.Status); - } +*********/ + } + + /* Release the capture buffer */ + CsrFreeCaptureBuffer(CaptureBuffer); + + /* Return TRUE or FALSE */ + return (GetConsoleInputRequest->InputsRead > 0); + // return NT_SUCCESS(ApiMessage.Status); }
Modified: branches/ros-csrss/include/reactos/subsys/win/conmsg.h URL: http://svn.reactos.org/svn/reactos/branches/ros-csrss/include/reactos/subsys... ============================================================================== --- branches/ros-csrss/include/reactos/subsys/win/conmsg.h [iso-8859-1] (original) +++ branches/ros-csrss/include/reactos/subsys/win/conmsg.h [iso-8859-1] Sat Dec 8 00:39:24 2012 @@ -147,7 +147,6 @@ BOOL Unicode; WORD NrCharactersToRead; WORD NrCharactersRead; - HANDLE EventHandle;
UNICODE_STRING ExeName; DWORD CtrlWakeupMask; @@ -326,14 +325,10 @@ BOOL Unicode; BOOL bRead; // TRUE --> Read ; FALSE --> Peek
- DWORD Length; - INPUT_RECORD* InputRecord; - - /** For Read **/ ULONG InputsRead; - // INPUT_RECORD Input; - BOOL MoreEvents; - HANDLE Event; + + ULONG Length; + PINPUT_RECORD InputRecord; } CSRSS_GET_CONSOLE_INPUT, *PCSRSS_GET_CONSOLE_INPUT;
typedef struct
Modified: branches/ros-csrss/win32ss/user/consrv/coninput.c URL: http://svn.reactos.org/svn/reactos/branches/ros-csrss/win32ss/user/consrv/co... ============================================================================== --- branches/ros-csrss/win32ss/user/consrv/coninput.c [iso-8859-1] (original) +++ branches/ros-csrss/win32ss/user/consrv/coninput.c [iso-8859-1] Sat Dec 8 00:39:24 2012 @@ -25,6 +25,13 @@ MultiByteToWideChar((Console)->CodePage, 0, (sChar), 1, (dWChar), 1)
+typedef struct _GET_INPUT_INFO +{ + PCONSOLE_PROCESS_DATA ProcessData; + PCSRSS_CONSOLE Console; +} GET_INPUT_INFO, *PGET_INPUT_INFO; + + /* PRIVATE FUNCTIONS **********************************************************/
static VOID FASTCALL @@ -79,7 +86,13 @@ return STATUS_INSUFFICIENT_RESOURCES; ConInRec->InputEvent = *InputEvent; InsertTailList(&Console->InputEvents, &ConInRec->ListEntry); + SetEvent(Console->ActiveEvent); + CsrNotifyWait(&Console->ReadWaitQueue, + WaitAny, + NULL, + NULL); + return STATUS_SUCCESS; }
@@ -289,6 +302,322 @@ ConioProcessChar(Console, &er); }
+static NTSTATUS +WaitBeforeReading(IN PGET_INPUT_INFO InputInfo, + IN PCSR_API_MESSAGE ApiMessage, + IN CSR_WAIT_FUNCTION WaitFunction OPTIONAL, + IN BOOL CreateWaitBlock OPTIONAL) +{ + if (CreateWaitBlock) + { + PGET_INPUT_INFO CapturedInputInfo; + + CapturedInputInfo = HeapAlloc(ConSrvHeap, 0, sizeof(GET_INPUT_INFO)); + if (!CapturedInputInfo) return STATUS_NO_MEMORY; + + memmove(CapturedInputInfo, InputInfo, sizeof(GET_INPUT_INFO)); + + if (!CsrCreateWait(&InputInfo->Console->ReadWaitQueue, + WaitFunction, + CsrGetClientThread(), + ApiMessage, + CapturedInputInfo, + NULL)) + { + HeapFree(ConSrvHeap, 0, CapturedInputInfo); + return STATUS_NO_MEMORY; + } + } + + /* Wait for input */ + return STATUS_PENDING; +} + +static NTSTATUS +ReadInputBuffer(IN PGET_INPUT_INFO InputInfo, + IN BOOL Wait, + IN PCSR_API_MESSAGE ApiMessage, + IN BOOL CreateWaitBlock OPTIONAL); + +// Wait function CSR_WAIT_FUNCTION +static BOOLEAN +ReadInputBufferThread(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; + PCSRSS_GET_CONSOLE_INPUT GetConsoleInputRequest = &((PCONSOLE_API_MESSAGE)WaitApiMessage)->Data.GetConsoleInputRequest; + PGET_INPUT_INFO InputInfo = (PGET_INPUT_INFO)WaitContext; + + Status = ReadInputBuffer(InputInfo, + GetConsoleInputRequest->bRead, + WaitApiMessage, + FALSE); + + if (Status != STATUS_PENDING) + { + WaitApiMessage->Status = Status; + HeapFree(ConSrvHeap, 0, InputInfo); + } + + return (Status == STATUS_PENDING ? FALSE : TRUE); +} + +static NTSTATUS +ReadInputBuffer(IN PGET_INPUT_INFO InputInfo, + IN BOOL Wait, // TRUE --> Read ; FALSE --> Peek + IN PCSR_API_MESSAGE ApiMessage, + IN BOOL CreateWaitBlock OPTIONAL) +{ + if (IsListEmpty(&InputInfo->Console->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 + { + PCSRSS_GET_CONSOLE_INPUT GetConsoleInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleInputRequest; + PLIST_ENTRY CurrentInput; + ConsoleInput* Input; + ULONG Length = GetConsoleInputRequest->Length; + PINPUT_RECORD InputRecord = GetConsoleInputRequest->InputRecord; + + /* Only get input if there is any */ + CurrentInput = InputInfo->Console->InputEvents.Flink; + + while ( CurrentInput != &InputInfo->Console->InputEvents && + GetConsoleInputRequest->InputsRead < Length ) + { + Input = CONTAINING_RECORD(CurrentInput, ConsoleInput, ListEntry); + + GetConsoleInputRequest->InputsRead++; + *InputRecord = Input->InputEvent; + + if (GetConsoleInputRequest->Unicode == FALSE) + { + ConioInputEventToAnsi(InputInfo->Console, InputRecord); + } + + InputRecord++; + CurrentInput = CurrentInput->Flink; + + if (Wait) // TRUE --> Read, we remove inputs from the buffer ; FALSE --> Peek, we keep inputs. + { + RemoveEntryList(&Input->ListEntry); + HeapFree(ConSrvHeap, 0, Input); + } + } + + if (IsListEmpty(&InputInfo->Console->InputEvents)) + { + ResetEvent(InputInfo->Console->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; + + Status = ReadChars(InputInfo, + WaitApiMessage, + FALSE); + + if (Status != STATUS_PENDING) + { + WaitApiMessage->Status = Status; + HeapFree(ConSrvHeap, 0, 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. + + PCSRSS_READ_CONSOLE ReadConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleRequest; + 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 (InputInfo->Console->Mode & ENABLE_LINE_INPUT) + { + if (InputInfo->Console->LineBuffer == NULL) + { + /* Starting a new line */ + InputInfo->Console->LineMaxSize = max(256, nNumberOfCharsToRead); + InputInfo->Console->LineBuffer = HeapAlloc(ConSrvHeap, 0, InputInfo->Console->LineMaxSize * sizeof(WCHAR)); + if (InputInfo->Console->LineBuffer == NULL) + { + return STATUS_NO_MEMORY; + } + InputInfo->Console->LineComplete = FALSE; + InputInfo->Console->LineUpPressed = FALSE; + InputInfo->Console->LineInsertToggle = 0; + InputInfo->Console->LineWakeupMask = ReadConsoleRequest->CtrlWakeupMask; + InputInfo->Console->LineSize = ReadConsoleRequest->NrCharactersRead; + InputInfo->Console->LinePos = InputInfo->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(InputInfo->Console->LineBuffer, Buffer, InputInfo->Console->LineSize * sizeof(WCHAR)); + if (InputInfo->Console->LineSize == InputInfo->Console->LineMaxSize) + { + InputInfo->Console->LineComplete = TRUE; + InputInfo->Console->LinePos = 0; + } + } + + /* If we don't have a complete line yet, process the pending input */ + while ( !InputInfo->Console->LineComplete && + !IsListEmpty(&InputInfo->Console->InputEvents) ) + { + /* Remove input event from queue */ + CurrentEntry = RemoveHeadList(&InputInfo->Console->InputEvents); + if (IsListEmpty(&InputInfo->Console->InputEvents)) + { + ResetEvent(InputInfo->Console->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(InputInfo->Console, &Input->InputEvent.Event.KeyEvent); + ReadConsoleRequest->ControlKeyState = Input->InputEvent.Event.KeyEvent.dwControlKeyState; + } + HeapFree(ConSrvHeap, 0, Input); + } + + /* Check if we have a complete line to read from */ + if (InputInfo->Console->LineComplete) + { + while ( ReadConsoleRequest->NrCharactersRead < nNumberOfCharsToRead && + InputInfo->Console->LinePos != InputInfo->Console->LineSize ) + { + WCHAR Char = InputInfo->Console->LineBuffer[InputInfo->Console->LinePos++]; + + if (ReadConsoleRequest->Unicode) + { + UnicodeBuffer[ReadConsoleRequest->NrCharactersRead] = Char; + } + else + { + ConsoleInputUnicodeCharToAnsiChar(InputInfo->Console, + &Buffer[ReadConsoleRequest->NrCharactersRead], + &Char); + } + + ReadConsoleRequest->NrCharactersRead++; + } + + if (InputInfo->Console->LinePos == InputInfo->Console->LineSize) + { + /* Entire line has been read */ + HeapFree(ConSrvHeap, 0, InputInfo->Console->LineBuffer); + InputInfo->Console->LineBuffer = NULL; + } + + WaitForMoreToRead = FALSE; + } + } + else + { + /* Character input */ + while ( ReadConsoleRequest->NrCharactersRead < nNumberOfCharsToRead && + !IsListEmpty(&InputInfo->Console->InputEvents) ) + { + /* Remove input event from queue */ + CurrentEntry = RemoveHeadList(&InputInfo->Console->InputEvents); + if (IsListEmpty(&InputInfo->Console->InputEvents)) + { + ResetEvent(InputInfo->Console->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(InputInfo->Console, + &Buffer[ReadConsoleRequest->NrCharactersRead], + &Char); + } + + ReadConsoleRequest->NrCharactersRead++; + + /* Did read something */ + WaitForMoreToRead = FALSE; + } + HeapFree(ConSrvHeap, 0, Input); + } + } + + /* We haven't completed a read, so start a wait */ + if (WaitForMoreToRead == TRUE) + { + return WaitBeforeReading(InputInfo, + ApiMessage, + ReadCharsThread, + CreateWaitBlock); + } + else /* We read all what we wanted, we return success */ + { + return STATUS_SUCCESS; + } +} +
/* PUBLIC APIS ****************************************************************/
@@ -298,16 +627,9 @@ PCSRSS_GET_CONSOLE_INPUT GetConsoleInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleInputRequest; PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process); PCSRSS_CONSOLE Console; - PLIST_ENTRY CurrentInput; - ConsoleInput* Input; - - DWORD Length; - PINPUT_RECORD InputRecord; + GET_INPUT_INFO InputInfo;
DPRINT("SrvGetConsoleInput\n"); - - Status = ConioLockConsole(ProcessData, GetConsoleInputRequest->ConsoleHandle, &Console, GENERIC_READ); - if(!NT_SUCCESS(Status)) return Status;
if (!CsrValidateMessageBuffer(ApiMessage, (PVOID*)&GetConsoleInputRequest->InputRecord, @@ -317,130 +639,23 @@ return STATUS_INVALID_PARAMETER; }
- InputRecord = GetConsoleInputRequest->InputRecord; - Length = GetConsoleInputRequest->Length; - -/* - if (!Win32CsrValidateBuffer(ProcessData->Process, InputRecord, Length, sizeof(INPUT_RECORD))) - { - ConioUnlockConsole(Console); - return STATUS_ACCESS_VIOLATION; - } -*/ - - if (GetConsoleInputRequest->bRead) // Read input. - { - GetConsoleInputRequest->Event = ProcessData->ConsoleEvent; - - while (Length > 0) - { - BOOLEAN Done = FALSE; - - // GetConsoleInputRequest->Event = ProcessData->ConsoleEvent; - - /* only get input if there is any */ - CurrentInput = Console->InputEvents.Flink; - while (CurrentInput != &Console->InputEvents) - { - Input = CONTAINING_RECORD(CurrentInput, ConsoleInput, ListEntry); - CurrentInput = CurrentInput->Flink; - - if (Done) - { - GetConsoleInputRequest->MoreEvents = TRUE; - break; - } - - RemoveEntryList(&Input->ListEntry); - - if (!Done) - { - GetConsoleInputRequest->InputsRead++; - *InputRecord = Input->InputEvent; - /* HACK */ Length--; - - // GetConsoleInputRequest->Input = Input->InputEvent; - if (GetConsoleInputRequest->Unicode == FALSE) - { - // ConioInputEventToAnsi(Console, &GetConsoleInputRequest->Input); - ConioInputEventToAnsi(Console, InputRecord); - } - - InputRecord++; - Done = TRUE; - } - - HeapFree(ConSrvHeap, 0, Input); - } - - if (Done) - Status = STATUS_SUCCESS; - else - Status = STATUS_PENDING; - - if (IsListEmpty(&Console->InputEvents)) - { - ResetEvent(Console->ActiveEvent); - } - - if (Status == STATUS_PENDING) - { - if (GetConsoleInputRequest->InputsRead == 0) - { - Status = NtWaitForSingleObject(GetConsoleInputRequest->Event, FALSE, 0); - if (!NT_SUCCESS(Status)) - { - // BaseSetLastNTError(Status); - break; - } - } - else - { - /* nothing more to read (waiting for more input??), let's just bail */ - break; - } - } - else // Status != STATUS_PENDING ; == STATUS_SUCCESS - { - if (!GetConsoleInputRequest->MoreEvents) - { - /* nothing more to read, bail */ - break; - } - } - } - } - else // Peek input. - { - UINT NumInputs = 0; - - if (!IsListEmpty(&Console->InputEvents)) - { - CurrentInput = Console->InputEvents.Flink; - - while (CurrentInput != &Console->InputEvents && NumInputs < Length) - { - Input = CONTAINING_RECORD(CurrentInput, ConsoleInput, ListEntry); - - ++NumInputs; - *InputRecord = Input->InputEvent; - - if (GetConsoleInputRequest->Unicode == FALSE) - { - ConioInputEventToAnsi(Console, InputRecord); - } - - InputRecord++; - CurrentInput = CurrentInput->Flink; - } - } - - GetConsoleInputRequest->Length = NumInputs; - - Status = STATUS_SUCCESS; - } + Status = ConioLockConsole(ProcessData, GetConsoleInputRequest->ConsoleHandle, &Console, GENERIC_READ); + if(!NT_SUCCESS(Status)) return Status; + + GetConsoleInputRequest->InputsRead = 0; + + InputInfo.ProcessData = ProcessData; // ConsoleGetPerProcessData(CsrGetClientThread()->Process); + InputInfo.Console = Console; + + Status = ReadInputBuffer(&InputInfo, + GetConsoleInputRequest->bRead, + ApiMessage, + TRUE);
ConioUnlockConsole(Console); + + if (Status == STATUS_PENDING) + *ReplyCode = CsrReplyPending;
return Status; } @@ -471,14 +686,6 @@ InputRecord = WriteConsoleInputRequest->InputRecord; Length = WriteConsoleInputRequest->Length;
-/* - if (!Win32CsrValidateBuffer(ProcessData->Process, InputRecord, Length, sizeof(INPUT_RECORD))) - { - ConioUnlockConsole(Console); - return STATUS_ACCESS_VIOLATION; - } -*/ - for (i = 0; i < Length && NT_SUCCESS(Status); i++) { if (!WriteConsoleInputRequest->Unicode && @@ -504,20 +711,11 @@ { NTSTATUS Status; PCSRSS_READ_CONSOLE ReadConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleRequest; - PLIST_ENTRY CurrentEntry; - ConsoleInput *Input; - PCHAR Buffer; - PWCHAR UnicodeBuffer; - ULONG i = 0; - ULONG nNumberOfCharsToRead, CharSize; PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process); PCSRSS_CONSOLE Console; + GET_INPUT_INFO InputInfo;
DPRINT("SrvReadConsole\n"); - - CharSize = (ReadConsoleRequest->Unicode ? sizeof(WCHAR) : sizeof(CHAR)); - - nNumberOfCharsToRead = ReadConsoleRequest->NrCharactersToRead;
if (!CsrValidateMessageBuffer(ApiMessage, (PVOID*)&ReadConsoleRequest->Buffer, @@ -527,154 +725,28 @@ return STATUS_INVALID_PARAMETER; }
- Buffer = (PCHAR)ReadConsoleRequest->Buffer; - UnicodeBuffer = (PWCHAR)Buffer; - -/* - if (!Win32CsrValidateBuffer(ProcessData->Process, Buffer, nNumberOfCharsToRead, CharSize)) - return STATUS_ACCESS_VIOLATION; -*/ - - Status = ConioLockConsole(ProcessData, ReadConsoleRequest->ConsoleHandle, - &Console, GENERIC_READ); + // if (Request->Data.ReadConsoleRequest.NrCharactersRead * sizeof(WCHAR) > nNumberOfCharsToRead * CharSize) + if (ReadConsoleRequest->NrCharactersRead > ReadConsoleRequest->NrCharactersToRead) + { + return STATUS_INVALID_PARAMETER; + } + + Status = ConioLockConsole(ProcessData, ReadConsoleRequest->ConsoleHandle, &Console, GENERIC_READ); if (!NT_SUCCESS(Status)) return Status;
- Status = STATUS_SUCCESS; - ReadConsoleRequest->EventHandle = ProcessData->ConsoleEvent; - -/*** HACK: Enclosing do { ... } while (...) loop coming from kernel32 ***/ -do -{ + ReadConsoleRequest->NrCharactersRead = 0; + + InputInfo.ProcessData = ProcessData; // ConsoleGetPerProcessData(CsrGetClientThread()->Process); + InputInfo.Console = Console; + + Status = ReadChars(&InputInfo, + ApiMessage, + TRUE); + + ConioUnlockConsole(Console); + if (Status == STATUS_PENDING) - { - Status = NtWaitForSingleObject(ReadConsoleRequest->EventHandle, - FALSE, - 0); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Wait for console input failed!\n"); - break; - } - } -/******/ - - if (ReadConsoleRequest->NrCharactersRead * sizeof(WCHAR) > nNumberOfCharsToRead * CharSize) - { - // return STATUS_INVALID_PARAMETER; - Status = STATUS_INVALID_PARAMETER; - break; - // goto done; - } - - // ReadConsoleRequest->EventHandle = ProcessData->ConsoleEvent; - - Status = STATUS_PENDING; /* we haven't read anything (yet) */ - if (Console->Mode & ENABLE_LINE_INPUT) - { - if (Console->LineBuffer == NULL) - { - /* Starting a new line */ - Console->LineMaxSize = max(256, nNumberOfCharsToRead); - Console->LineBuffer = HeapAlloc(ConSrvHeap, 0, Console->LineMaxSize * sizeof(WCHAR)); - if (Console->LineBuffer == NULL) - { - Status = STATUS_NO_MEMORY; - goto done; - } - 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 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(&Console->InputEvents)) - { - /* remove input event from queue */ - CurrentEntry = RemoveHeadList(&Console->InputEvents); - if (IsListEmpty(&Console->InputEvents)) - { - ResetEvent(Console->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; - } - HeapFree(ConSrvHeap, 0, Input); - } - - /* Check if we have a complete line to read from */ - if (Console->LineComplete) - { - while (i < nNumberOfCharsToRead && Console->LinePos != Console->LineSize) - { - WCHAR Char = Console->LineBuffer[Console->LinePos++]; - if (ReadConsoleRequest->Unicode) - UnicodeBuffer[i++] = Char; - else - ConsoleInputUnicodeCharToAnsiChar(Console, &Buffer[i++], &Char); - } - if (Console->LinePos == Console->LineSize) - { - /* Entire line has been read */ - HeapFree(ConSrvHeap, 0, Console->LineBuffer); - Console->LineBuffer = NULL; - } - Status = STATUS_SUCCESS; - } - } - else - { - /* Character input */ - while (i < nNumberOfCharsToRead && !IsListEmpty(&Console->InputEvents)) - { - /* remove input event from queue */ - CurrentEntry = RemoveHeadList(&Console->InputEvents); - if (IsListEmpty(&Console->InputEvents)) - { - ResetEvent(Console->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[i++] = Char; - else - ConsoleInputUnicodeCharToAnsiChar(Console, &Buffer[i++], &Char); - Status = STATUS_SUCCESS; /* did read something */ - } - HeapFree(ConSrvHeap, 0, Input); - } - } -done: - ReadConsoleRequest->NrCharactersRead = i; - -/******/ -} -while (Status == STATUS_PENDING); -/*** HACK: Enclosing do { ... } while (...) loop coming from kernel32 ***/ - - ConioUnlockConsole(Console); + *ReplyCode = CsrReplyPending;
return Status; }
Modified: branches/ros-csrss/win32ss/user/consrv/conio.h URL: http://svn.reactos.org/svn/reactos/branches/ros-csrss/win32ss/user/consrv/co... ============================================================================== --- branches/ros-csrss/win32ss/user/consrv/conio.h [iso-8859-1] (original) +++ branches/ros-csrss/win32ss/user/consrv/conio.h [iso-8859-1] Sat Dec 8 00:39:24 2012 @@ -53,6 +53,9 @@ CRITICAL_SECTION Lock; struct tagCSRSS_CONSOLE *Prev, *Next; /* Next and Prev consoles in console wheel */ HANDLE ActiveEvent; + + LIST_ENTRY ReadWaitQueue; /* List head for the queue of read wait blocks */ + LIST_ENTRY InputEvents; /* List head for input event queue */ PWCHAR LineBuffer; /* current line being input, in line buffered mode */ WORD LineMaxSize; /* maximum size of line in characters (including CR+LF) */
Modified: branches/ros-csrss/win32ss/user/consrv/console.c URL: http://svn.reactos.org/svn/reactos/branches/ros-csrss/win32ss/user/consrv/co... ============================================================================== --- branches/ros-csrss/win32ss/user/consrv/console.c [iso-8859-1] (original) +++ branches/ros-csrss/win32ss/user/consrv/console.c [iso-8859-1] Sat Dec 8 00:39:24 2012 @@ -114,6 +114,7 @@ Console->Mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT; InitializeListHead(&Console->BufferList); Console->ActiveBuffer = NULL; + InitializeListHead(&Console->ReadWaitQueue); InitializeListHead(&Console->InputEvents); InitializeListHead(&Console->HistoryBuffers); Console->CodePage = GetOEMCP(); @@ -423,6 +424,8 @@ ConsoleInput *Event;
DPRINT("ConioDeleteConsole\n"); + + /* TODO: Dereference all the waits in Console->ReadWaitQueue */
/* Drain input event queue */ while (Console->InputEvents.Flink != &Console->InputEvents)