- Implemented waitable console handles.

- Removed a fake event after a input event to empty the queue in CsrReadInputEvent.

svn path=/trunk/; revision=11653
This commit is contained in:
Hartmut Birr 2004-11-14 18:47:10 +00:00
parent 26b8d50a75
commit 349e167cae
7 changed files with 136 additions and 106 deletions

View file

@ -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;
};
};

View file

@ -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;
}

View file

@ -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;
SetLastError (ERROR_INVALID_HANDLE);
return WAIT_FAILED;
}
CloseWaitHandle = TRUE;
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 (nCount > 3)
{
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]))
if (!VerifyConsoleIoHandle(HandleBuffer[i]))
{
Status = GetWaiterForConsoleHandle( HandleBuffer[i],
&HandleBuffer[i] );
if (!NT_SUCCESS(Status))
if (HandleBuffer != Handle)
{
/* 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;
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,15 +215,10 @@ 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);
}
if (Status == STATUS_TIMEOUT)
{

View file

@ -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 */

View file

@ -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);

View file

@ -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 }
};

View file

@ -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,16 +1679,28 @@ 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 (Done && !Input->Fake)
{
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); /* FIXME */
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);