mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
- 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:
parent
26b8d50a75
commit
349e167cae
7 changed files with 136 additions and 106 deletions
|
@ -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;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue