From 349e167caed3b1f5c66170736f2053c661f76301 Mon Sep 17 00:00:00 2001 From: Hartmut Birr Date: Sun, 14 Nov 2004 18:47:10 +0000 Subject: [PATCH] - Implemented waitable console handles. - Removed a fake event after a input event to empty the queue in CsrReadInputEvent. svn path=/trunk/; revision=11653 --- reactos/include/csrss/csrss.h | 12 +++ reactos/lib/kernel32/misc/console.c | 20 +++- reactos/lib/kernel32/synch/wait.c | 130 ++++++++++---------------- reactos/subsys/csrss/api/process.c | 21 ++++- reactos/subsys/csrss/include/api.h | 3 +- reactos/subsys/csrss/init.c | 3 +- reactos/subsys/csrss/win32csr/conio.c | 53 ++++++++--- 7 files changed, 136 insertions(+), 106 deletions(-) diff --git a/reactos/include/csrss/csrss.h b/reactos/include/csrss/csrss.h index f423df598a0..b50bc6df937 100644 --- a/reactos/include/csrss/csrss.h +++ b/reactos/include/csrss/csrss.h @@ -606,6 +606,15 @@ typedef struct { } CSRSS_SET_CONSOLE_OUTPUT_CP_REPLY, *PCSRSS_SET_CONSOLE_OUTPUT_CP_REPLY; +typedef struct +{ +} CSRSS_GET_INPUT_WAIT_HANDLE_REQUEST, *PCSRSS_GET_INPUT_WAIT_HANDLE_REQUEST; + +typedef struct +{ + HANDLE InputWaitHandle; +} CSRSS_GET_INPUT_WAIT_HANDLE_REPLY, *PCSRSS_GET_INPUT_WAIT_HANDLE_REPLY; + #define CSRSS_MAX_WRITE_CONSOLE_REQUEST \ (MAX_MESSAGE_DATA - sizeof(ULONG) - sizeof(CSRSS_WRITE_CONSOLE_REQUEST)) @@ -677,6 +686,7 @@ typedef struct #define CSRSS_SET_CONSOLE_CP (0x32) #define CSRSS_GET_CONSOLE_OUTPUT_CP (0x33) #define CSRSS_SET_CONSOLE_OUTPUT_CP (0x34) +#define CSRSS_GET_INPUT_WAIT_HANDLE (0x35) /* Keep in sync with definition below. */ #define CSRSS_REQUEST_HEADER_SIZE (LPC_MESSAGE_BASE_SIZE + sizeof(ULONG)) @@ -741,6 +751,7 @@ typedef struct CSRSS_SET_CONSOLE_CP_REQUEST SetConsoleCodePage; CSRSS_GET_CONSOLE_OUTPUT_CP_REQUEST GetConsoleOutputCodePage; CSRSS_SET_CONSOLE_OUTPUT_CP_REQUEST SetConsoleOutputCodePage; + CSRSS_GET_INPUT_WAIT_HANDLE_REQUEST GetConsoleInputWaitHandle; } Data; }; }; @@ -795,6 +806,7 @@ typedef struct CSRSS_SET_CONSOLE_CP_REPLY SetConsoleCodePage; CSRSS_GET_CONSOLE_OUTPUT_CP_REPLY GetConsoleOutputCodePage; CSRSS_SET_CONSOLE_OUTPUT_CP_REPLY SetConsoleOutputCodePage; + CSRSS_GET_INPUT_WAIT_HANDLE_REPLY GetConsoleInputWaitHandle; } Data; }; }; diff --git a/reactos/lib/kernel32/misc/console.c b/reactos/lib/kernel32/misc/console.c index af1ece6198f..382b8debe32 100644 --- a/reactos/lib/kernel32/misc/console.c +++ b/reactos/lib/kernel32/misc/console.c @@ -1,4 +1,4 @@ -/* $Id: console.c,v 1.82 2004/11/02 20:42:05 weiden Exp $ +/* $Id: console.c,v 1.83 2004/11/14 18:47:09 hbirr Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -559,7 +559,7 @@ GetConsoleHardwareState (HANDLE hConsole, /* - * @unimplemented + * @implemented */ DWORD STDCALL GetConsoleInputWaitHandle (VOID) @@ -567,9 +567,19 @@ GetConsoleInputWaitHandle (VOID) * Undocumented */ { - DPRINT1("GetConsoleInputWaitHandle() UNIMPLEMENTED!\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + CSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + + Request.Type = CSRSS_GET_INPUT_WAIT_HANDLE; + Status = CsrClientCallServer(&Request, &Reply, sizeof(CSRSS_API_REQUEST), + sizeof(CSRSS_API_REPLY)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status)) + { + SetLastErrorByStatus(Status); + return 0; + } + return (DWORD) Reply.Data.GetConsoleInputWaitHandle.InputWaitHandle; } diff --git a/reactos/lib/kernel32/synch/wait.c b/reactos/lib/kernel32/synch/wait.c index 8fc39175f2e..725d667e50a 100644 --- a/reactos/lib/kernel32/synch/wait.c +++ b/reactos/lib/kernel32/synch/wait.c @@ -1,4 +1,4 @@ -/* $Id: wait.c,v 1.30 2004/10/02 10:19:38 hbirr Exp $ +/* $Id: wait.c,v 1.31 2004/11/14 18:47:10 hbirr Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -19,38 +19,8 @@ /* FUNCTIONS ****************************************************************/ -/* - * Thread that waits for a console handle. Console handles only fire when - * they're readable. - */ - -DWORD STDCALL WaitForConsoleHandleThread( PVOID ConHandle ) { - DWORD AmtRead = 0; - INPUT_RECORD Buffer[1]; - do { - PeekConsoleInputA( ConHandle, Buffer, 1, &AmtRead ); - if( !AmtRead ) Sleep( 100 ); - } while( AmtRead == 0 ); - - return 0; -} - -/* - * Return a waitable object given a console handle - */ -DWORD GetWaiterForConsoleHandle( HANDLE ConHandle, PHANDLE Waitable ) { - DWORD ThreadId; - HANDLE WaitableHandle = CreateThread( 0, - 0, - WaitForConsoleHandleThread, - ConHandle, - 0, - &ThreadId ); - - *Waitable = WaitableHandle; - - return WaitableHandle ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; -} +DWORD STDCALL +GetConsoleInputWaitHandle (VOID); /* * @implemented @@ -76,7 +46,6 @@ WaitForSingleObjectEx(HANDLE hHandle, PLARGE_INTEGER TimePtr; LARGE_INTEGER Time; NTSTATUS Status; - BOOL CloseWaitHandle = FALSE; /* Get real handle */ switch ((ULONG)hHandle) @@ -97,15 +66,18 @@ WaitForSingleObjectEx(HANDLE hHandle, /* Check for console handle */ if (IsConsoleHandle(hHandle)) { - if (VerifyConsoleIoHandle(hHandle)) + if (!VerifyConsoleIoHandle(hHandle)) { - Status = GetWaiterForConsoleHandle( hHandle, &hHandle ); - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus (Status); - return FALSE; - } - CloseWaitHandle = TRUE; + SetLastError (ERROR_INVALID_HANDLE); + return WAIT_FAILED; + } + + hHandle = (HANDLE)GetConsoleInputWaitHandle(); + if (hHandle == NULL || hHandle == INVALID_HANDLE_VALUE) + { + SetLastError (ERROR_INVALID_HANDLE); + return WAIT_FAILED; + } } @@ -123,12 +95,6 @@ WaitForSingleObjectEx(HANDLE hHandle, (BOOLEAN) bAlertable, TimePtr); - if (CloseWaitHandle) - { - TerminateThread(hHandle, 0); - NtClose(hHandle); - } - if (HIWORD(Status)) { SetLastErrorByStatus (Status); @@ -169,24 +135,27 @@ WaitForMultipleObjectsEx(DWORD nCount, PLARGE_INTEGER TimePtr; LARGE_INTEGER Time; PHANDLE HandleBuffer; - DWORD i,j; + HANDLE Handle[3]; + DWORD i; NTSTATUS Status; - PBOOL FreeThisHandle; DPRINT("nCount %lu\n", nCount); - HandleBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, nCount * (sizeof(HANDLE) + sizeof(BOOL)) ); - FreeThisHandle = (PBOOL)(&HandleBuffer[nCount]); - - if (HandleBuffer == NULL) + if (nCount > 3) { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return WAIT_FAILED; + HandleBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, nCount * sizeof(HANDLE)); + if (HandleBuffer == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return WAIT_FAILED; + } + } + else + { + HandleBuffer = Handle; } - for (i = 0; i < nCount; i++) { - FreeThisHandle[i] = FALSE; switch ((DWORD)lpHandles[i]) { case STD_INPUT_HANDLE: @@ -209,24 +178,24 @@ WaitForMultipleObjectsEx(DWORD nCount, /* Check for console handle */ if (IsConsoleHandle(HandleBuffer[i])) { - if (VerifyConsoleIoHandle(HandleBuffer[i])) - { - Status = GetWaiterForConsoleHandle( HandleBuffer[i], - &HandleBuffer[i] ); - if (!NT_SUCCESS(Status)) - { - /* We'll leak some handles unless we close the already - created handles */ - for (j = 0; j < i; j++) - if (FreeThisHandle[j]) - NtClose(HandleBuffer[j]); - - SetLastErrorByStatus (Status); - RtlFreeHeap(GetProcessHeap(),0,HandleBuffer); - return FALSE; - } - - FreeThisHandle[i] = TRUE; + if (!VerifyConsoleIoHandle(HandleBuffer[i])) + { + if (HandleBuffer != Handle) + { + RtlFreeHeap(GetProcessHeap(),0,HandleBuffer); + } + SetLastError (ERROR_INVALID_HANDLE); + return WAIT_FAILED; + } + HandleBuffer[i] = (HANDLE)GetConsoleInputWaitHandle(); + if (HandleBuffer[i] == NULL || HandleBuffer[i] == INVALID_HANDLE_VALUE) + { + if (HandleBuffer != Handle) + { + RtlFreeHeap(GetProcessHeap(),0,HandleBuffer); + } + SetLastError (ERROR_INVALID_HANDLE); + return WAIT_FAILED; } } } @@ -246,16 +215,11 @@ WaitForMultipleObjectsEx(DWORD nCount, bWaitAll ? WaitAll : WaitAny, (BOOLEAN)bAlertable, TimePtr); - - for (i = 0; i < nCount; i++) - if (FreeThisHandle[i]) + if (HandleBuffer != Handle) { - TerminateThread(HandleBuffer[i], 0); - NtClose(HandleBuffer[i]); + RtlFreeHeap(RtlGetProcessHeap(), 0, HandleBuffer); } - RtlFreeHeap(RtlGetProcessHeap(), 0, HandleBuffer); - if (Status == STATUS_TIMEOUT) { return WAIT_TIMEOUT; diff --git a/reactos/subsys/csrss/api/process.c b/reactos/subsys/csrss/api/process.c index fef95841023..75d6dc14d96 100644 --- a/reactos/subsys/csrss/api/process.c +++ b/reactos/subsys/csrss/api/process.c @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.35 2004/06/27 12:21:31 weiden Exp $ +/* $Id: process.c,v 1.36 2004/11/14 18:47:10 hbirr Exp $ * * reactos/subsys/csrss/api/process.c * @@ -425,4 +425,23 @@ CSR_API(CsrDuplicateHandle) return Reply->Status; } +CSR_API(CsrGetInputWaitHandle) +{ + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - LPC_MESSAGE_BASE_SIZE; + + if (ProcessData == NULL) + { + + Reply->Data.GetConsoleInputWaitHandle.InputWaitHandle = INVALID_HANDLE_VALUE; + Reply->Status = STATUS_INVALID_PARAMETER; + } + else + { + Reply->Data.GetConsoleInputWaitHandle.InputWaitHandle = ProcessData->ConsoleEvent; + Reply->Status = STATUS_SUCCESS; + } + return Reply->Status; +} + /* EOF */ diff --git a/reactos/subsys/csrss/include/api.h b/reactos/subsys/csrss/include/api.h index aac6096faac..cfc9749e135 100644 --- a/reactos/subsys/csrss/include/api.h +++ b/reactos/subsys/csrss/include/api.h @@ -1,4 +1,4 @@ -/* $Id: api.h,v 1.6 2004/07/12 20:09:34 gvg Exp $ +/* $Id: api.h,v 1.7 2004/11/14 18:47:10 hbirr Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -124,6 +124,7 @@ CSR_API(CsrGetOutputHandle); CSR_API(CsrCloseHandle); CSR_API(CsrVerifyHandle); CSR_API(CsrDuplicateHandle); +CSR_API(CsrGetInputWaitHandle); /* api/user.c */ CSR_API(CsrRegisterServicesProcess); diff --git a/reactos/subsys/csrss/init.c b/reactos/subsys/csrss/init.c index ac08b1e4bdf..a2012eba090 100644 --- a/reactos/subsys/csrss/init.c +++ b/reactos/subsys/csrss/init.c @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.29 2004/07/12 20:09:34 gvg Exp $ +/* $Id: init.c,v 1.30 2004/11/14 18:47:10 hbirr Exp $ * * reactos/subsys/csrss/init.c * @@ -214,6 +214,7 @@ CSRSS_API_DEFINITION NativeDefinitions[] = CSRSS_DEFINE_API(CSRSS_CLOSE_HANDLE, CsrCloseHandle), CSRSS_DEFINE_API(CSRSS_VERIFY_HANDLE, CsrVerifyHandle), CSRSS_DEFINE_API(CSRSS_DUPLICATE_HANDLE, CsrDuplicateHandle), + CSRSS_DEFINE_API(CSRSS_GET_INPUT_WAIT_HANDLE, CsrGetInputWaitHandle), { 0, 0, 0, NULL } }; diff --git a/reactos/subsys/csrss/win32csr/conio.c b/reactos/subsys/csrss/win32csr/conio.c index c50f1ed6c10..24332dcfd7a 100644 --- a/reactos/subsys/csrss/win32csr/conio.c +++ b/reactos/subsys/csrss/win32csr/conio.c @@ -1,4 +1,4 @@ -/* $Id: conio.c,v 1.16 2004/11/02 20:42:06 weiden Exp $ +/* $Id: conio.c,v 1.17 2004/11/14 18:47:10 hbirr Exp $ * * reactos/subsys/csrss/win32csr/conio.c * @@ -186,7 +186,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console) SecurityAttributes.lpSecurityDescriptor = NULL; SecurityAttributes.bInheritHandle = TRUE; - Console->ActiveEvent = CreateEventW(&SecurityAttributes, FALSE, FALSE, NULL); + Console->ActiveEvent = CreateEventW(&SecurityAttributes, TRUE, FALSE, NULL); if (NULL == Console->ActiveEvent) { RtlFreeUnicodeString(&Console->Title); @@ -559,6 +559,11 @@ CSR_API(CsrReadConsole) { /* remove input event from queue */ CurrentEntry = RemoveHeadList(&Console->InputEvents); + if (IsListEmpty(&Console->InputEvents)) + { + CHECKPOINT; + ResetEvent(Console->ActiveEvent); + } Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); /* only pay attention to valid ascii chars, on key down */ @@ -1650,7 +1655,6 @@ CSR_API(CsrFillOutputChar) ConioUnlockConsole(Console); } - Reply->Data.FillOutputReply.NrCharactersWritten = Written; return Reply->Status; } @@ -1675,17 +1679,29 @@ CSR_API(CsrReadInputEvent) } /* only get input if there is any */ - while (Console->InputEvents.Flink != &Console->InputEvents && ! Done) + CurrentEntry = Console->InputEvents.Flink; + while (CurrentEntry != &Console->InputEvents) { - CurrentEntry = RemoveHeadList(&Console->InputEvents); Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); - Done = !Input->Fake; - Reply->Data.ReadInputReply.Input = Input->InputEvent; + CurrentEntry = CurrentEntry->Flink; - if (Request->Data.ReadInputRequest.Unicode == FALSE) + if (Done && !Input->Fake) { - ConioInputEventToAnsi(Console, &Reply->Data.ReadInputReply.Input); /* FIXME */ - } + Reply->Data.ReadInputReply.MoreEvents = TRUE; + break; + } + + RemoveEntryList(&Input->ListEntry); + + if (!Done && !Input->Fake) + { + Reply->Data.ReadInputReply.Input = Input->InputEvent; + if (Request->Data.ReadInputRequest.Unicode == FALSE) + { + ConioInputEventToAnsi(Console, &Reply->Data.ReadInputReply.Input); + } + Done = TRUE; + } if (Input->InputEvent.EventType == KEY_EVENT) { @@ -1698,18 +1714,24 @@ CSR_API(CsrReadInputEvent) Console->WaitingChars--; } HeapFree(Win32CsrApiHeap, 0, Input); - - Reply->Data.ReadInputReply.MoreEvents = (Console->InputEvents.Flink != &Console->InputEvents); - Status = STATUS_SUCCESS; - Console->EarlyReturn = FALSE; /* clear early return */ } - if (! Done) + if (Done) + { + Status = STATUS_SUCCESS; + Console->EarlyReturn = FALSE; + } + else { Status = STATUS_PENDING; Console->EarlyReturn = TRUE; /* mark for early return */ } + if (IsListEmpty(&Console->InputEvents)) + { + ResetEvent(Console->ActiveEvent); + } + ConioUnlockConsole(Console); return Reply->Status = Status; @@ -2373,6 +2395,7 @@ CSR_API(CsrFlushInputBuffer) /* Destroy the event */ HeapFree(Win32CsrApiHeap, 0, Input); } + ResetEvent(Console->ActiveEvent); Console->WaitingChars=0; ConioUnlockConsole(Console);