From b8b8819c7b169e6a345fea6ace8fdd441ff8053c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Sun, 10 Nov 2013 20:20:57 +0000 Subject: [PATCH] [KERNEL32][CONSRV] Implement ReadConsoleInputExA/W, which are a generalization of ReadConsoleInputA/W and PeekConsoleInputA/W. They allow you to read console input events by either waiting (or not) for their presence, and to remove them from the console input list (or not). Those functions are the read-equivalent of WriteConsoleInputVDMA/W. Used in Windows' NTVDM (guess why ;) ). svn path=/trunk/; revision=60920 --- .../win32/kernel32/client/console/readwrite.c | 54 ++++++++++++++----- reactos/include/psdk/wincon.h | 28 ++++++++++ reactos/include/reactos/subsys/win/conmsg.h | 8 ++- .../user/winsrv/consrv/condrv/coninput.c | 4 +- reactos/win32ss/user/winsrv/consrv/coninput.c | 40 ++++++-------- .../win32ss/user/winsrv/consrv/conoutput.c | 12 ++--- 6 files changed, 94 insertions(+), 52 deletions(-) diff --git a/reactos/dll/win32/kernel32/client/console/readwrite.c b/reactos/dll/win32/kernel32/client/console/readwrite.c index e8003a4f1ad..d42f8d0a9cb 100644 --- a/reactos/dll/win32/kernel32/client/console/readwrite.c +++ b/reactos/dll/win32/kernel32/client/console/readwrite.c @@ -120,11 +120,11 @@ IntReadConsole(HANDLE hConsoleInput, static BOOL IntGetConsoleInput(HANDLE hConsoleInput, - BOOL bRead, PINPUT_RECORD lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsRead, - BOOL bUnicode) + WORD wFlags, + BOOLEAN bUnicode) { NTSTATUS Status; CONSOLE_API_MESSAGE ApiMessage; @@ -158,10 +158,10 @@ IntGetConsoleInput(HANDLE hConsoleInput, /* Set up the data to send to the Console Server */ GetInputRequest->InputHandle = hConsoleInput; - GetInputRequest->Unicode = bUnicode; - GetInputRequest->bRead = bRead; GetInputRequest->InputsRead = 0; GetInputRequest->Length = nLength; + GetInputRequest->wFlags = wFlags; + GetInputRequest->Unicode = bUnicode; /* Call the server */ Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, @@ -825,10 +825,10 @@ PeekConsoleInputW(HANDLE hConsoleInput, LPDWORD lpNumberOfEventsRead) { return IntGetConsoleInput(hConsoleInput, - FALSE, lpBuffer, nLength, lpNumberOfEventsRead, + CONSOLE_READ_KEEPEVENT | CONSOLE_READ_CONTINUE, TRUE); } @@ -846,10 +846,10 @@ PeekConsoleInputA(HANDLE hConsoleInput, LPDWORD lpNumberOfEventsRead) { return IntGetConsoleInput(hConsoleInput, - FALSE, lpBuffer, nLength, lpNumberOfEventsRead, + CONSOLE_READ_KEEPEVENT | CONSOLE_READ_CONTINUE, FALSE); } @@ -867,10 +867,10 @@ ReadConsoleInputW(HANDLE hConsoleInput, LPDWORD lpNumberOfEventsRead) { return IntGetConsoleInput(hConsoleInput, - TRUE, lpBuffer, nLength, lpNumberOfEventsRead, + 0, TRUE); } @@ -888,29 +888,55 @@ ReadConsoleInputA(HANDLE hConsoleInput, LPDWORD lpNumberOfEventsRead) { return IntGetConsoleInput(hConsoleInput, - TRUE, lpBuffer, nLength, lpNumberOfEventsRead, + 0, FALSE); } +/*-------------------------------------------------------------- + * ReadConsoleInputExW + * + * @implemented + */ BOOL WINAPI -ReadConsoleInputExW(HANDLE hConsole, LPVOID lpBuffer, DWORD dwLen, LPDWORD Unknown1, DWORD Unknown2) +ReadConsoleInputExW(HANDLE hConsoleInput, + PINPUT_RECORD lpBuffer, + DWORD nLength, + LPDWORD lpNumberOfEventsRead, + WORD wFlags) { - STUB; - return FALSE; + return IntGetConsoleInput(hConsoleInput, + lpBuffer, + nLength, + lpNumberOfEventsRead, + wFlags, + TRUE); } +/*-------------------------------------------------------------- + * ReadConsoleInputExA + * + * @implemented + */ BOOL WINAPI -ReadConsoleInputExA(HANDLE hConsole, LPVOID lpBuffer, DWORD dwLen, LPDWORD Unknown1, DWORD Unknown2) +ReadConsoleInputExA(HANDLE hConsoleInput, + PINPUT_RECORD lpBuffer, + DWORD nLength, + LPDWORD lpNumberOfEventsRead, + WORD wFlags) { - STUB; - return FALSE; + return IntGetConsoleInput(hConsoleInput, + lpBuffer, + nLength, + lpNumberOfEventsRead, + wFlags, + FALSE); } diff --git a/reactos/include/psdk/wincon.h b/reactos/include/psdk/wincon.h index db8c1a56cea..18e377ac989 100644 --- a/reactos/include/psdk/wincon.h +++ b/reactos/include/psdk/wincon.h @@ -108,6 +108,12 @@ extern "C" { #define HISTORY_NO_DUP_FLAG 0x0001 #endif +/* + * Read input flags + */ +#define CONSOLE_READ_KEEPEVENT 0x0001 +#define CONSOLE_READ_CONTINUE 0x0002 + /* * Event types */ @@ -436,6 +442,7 @@ COORD WINAPI GetLargestConsoleWindowSize(_In_ HANDLE); BOOL WINAPI GetNumberOfConsoleInputEvents(_In_ HANDLE, _Out_ PDWORD); BOOL WINAPI GetNumberOfConsoleMouseButtons(_Out_ PDWORD); +_Success_(return != 0) BOOL WINAPI PeekConsoleInputA( _In_ HANDLE hConsoleInput, @@ -443,6 +450,7 @@ WINAPI PeekConsoleInputA( _In_ DWORD nLength, _Out_ LPDWORD lpNumberOfEventsRead); +_Success_(return != 0) BOOL WINAPI PeekConsoleInputW( @@ -489,6 +497,26 @@ ReadConsoleInputW( _In_ DWORD nLength, _Out_ _Deref_out_range_(<= , nLength) LPDWORD lpNumberOfEventsRead); +_Success_(return != 0) +BOOL +WINAPI +ReadConsoleInputExA( + _In_ HANDLE hConsoleInput, + _Out_writes_to_(nLength, *lpNumberOfEventsRead) PINPUT_RECORD lpBuffer, + _In_ DWORD nLength, + _Out_ _Deref_out_range_(<= , nLength) LPDWORD lpNumberOfEventsRead, + _In_ WORD wFlags); + +_Success_(return != 0) +BOOL +WINAPI +ReadConsoleInputExW( + _In_ HANDLE hConsoleInput, + _Out_writes_to_(nLength, *lpNumberOfEventsRead) PINPUT_RECORD lpBuffer, + _In_ DWORD nLength, + _Out_ _Deref_out_range_(<= , nLength) LPDWORD lpNumberOfEventsRead, + _In_ WORD wFlags); + BOOL WINAPI ReadConsoleOutputAttribute( diff --git a/reactos/include/reactos/subsys/win/conmsg.h b/reactos/include/reactos/subsys/win/conmsg.h index 357e79fe8e4..7409fd23d43 100644 --- a/reactos/include/reactos/subsys/win/conmsg.h +++ b/reactos/include/reactos/subsys/win/conmsg.h @@ -469,13 +469,11 @@ typedef struct typedef struct { HANDLE InputHandle; - BOOL Unicode; - BOOL bRead; // TRUE --> Read ; FALSE --> Peek - ULONG InputsRead; - - ULONG Length; PINPUT_RECORD InputRecord; + ULONG Length; + WORD wFlags; + BOOLEAN Unicode; } CONSOLE_GETINPUT, *PCONSOLE_GETINPUT; typedef struct diff --git a/reactos/win32ss/user/winsrv/consrv/condrv/coninput.c b/reactos/win32ss/user/winsrv/consrv/condrv/coninput.c index b09e4afe637..8a9329de1bb 100644 --- a/reactos/win32ss/user/winsrv/consrv/condrv/coninput.c +++ b/reactos/win32ss/user/winsrv/consrv/condrv/coninput.c @@ -376,6 +376,7 @@ ConDrvReadConsole(IN PCONSOLE Console, NTSTATUS NTAPI ConDrvGetConsoleInput(IN PCONSOLE Console, IN PCONSOLE_INPUT_BUFFER InputBuffer, + IN BOOLEAN KeepEvents, IN BOOLEAN WaitForMoreEvents, IN BOOLEAN Unicode, OUT PINPUT_RECORD InputRecord, @@ -425,7 +426,8 @@ ConDrvGetConsoleInput(IN PCONSOLE Console, ++i; CurrentInput = CurrentInput->Flink; - if (WaitForMoreEvents) // TRUE --> Read, we remove inputs from the buffer ; FALSE --> Peek, we keep inputs. + /* Remove the events from the queue if needed */ + if (!KeepEvents) { RemoveEntryList(&Input->ListEntry); ConsoleFreeHeap(Input); diff --git a/reactos/win32ss/user/winsrv/consrv/coninput.c b/reactos/win32ss/user/winsrv/consrv/coninput.c index bf1982dda06..ee383d76462 100644 --- a/reactos/win32ss/user/winsrv/consrv/coninput.c +++ b/reactos/win32ss/user/winsrv/consrv/coninput.c @@ -45,7 +45,7 @@ static NTSTATUS WaitBeforeReading(IN PGET_INPUT_INFO InputInfo, IN PCSR_API_MESSAGE ApiMessage, IN CSR_WAIT_FUNCTION WaitFunction OPTIONAL, - IN BOOL CreateWaitBlock OPTIONAL) + IN BOOLEAN CreateWaitBlock OPTIONAL) { if (CreateWaitBlock) { @@ -74,7 +74,7 @@ WaitBeforeReading(IN PGET_INPUT_INFO InputInfo, static NTSTATUS ReadChars(IN PGET_INPUT_INFO InputInfo, IN PCSR_API_MESSAGE ApiMessage, - IN BOOL CreateWaitBlock OPTIONAL); + IN BOOLEAN CreateWaitBlock OPTIONAL); // Wait function CSR_WAIT_FUNCTION static BOOLEAN @@ -123,9 +123,7 @@ ReadCharsThread(IN PLIST_ENTRY WaitList, * If we go there, that means we are notified for some new input. * The console is therefore already locked. */ - Status = ReadChars(InputInfo, - WaitApiMessage, - FALSE); + Status = ReadChars(InputInfo, WaitApiMessage, FALSE); Quit: if (Status != STATUS_PENDING) @@ -148,7 +146,7 @@ ConDrvReadConsole(IN PCONSOLE Console, static NTSTATUS ReadChars(IN PGET_INPUT_INFO InputInfo, IN PCSR_API_MESSAGE ApiMessage, - IN BOOL CreateWaitBlock OPTIONAL) + IN BOOLEAN CreateWaitBlock OPTIONAL) { NTSTATUS Status; PCONSOLE_READCONSOLE ReadConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleRequest; @@ -188,9 +186,8 @@ ReadChars(IN PGET_INPUT_INFO InputInfo, static NTSTATUS ReadInputBuffer(IN PGET_INPUT_INFO InputInfo, - IN BOOL Wait, IN PCSR_API_MESSAGE ApiMessage, - IN BOOL CreateWaitBlock OPTIONAL); + IN BOOLEAN CreateWaitBlock OPTIONAL); // Wait function CSR_WAIT_FUNCTION static BOOLEAN @@ -204,7 +201,6 @@ ReadInputBufferThread(IN PLIST_ENTRY WaitList, IN ULONG WaitFlags) { NTSTATUS Status; - PCONSOLE_GETINPUT GetInputRequest = &((PCONSOLE_API_MESSAGE)WaitApiMessage)->Data.GetInputRequest; PGET_INPUT_INFO InputInfo = (PGET_INPUT_INFO)WaitContext; PVOID InputHandle = WaitArgument2; @@ -240,10 +236,7 @@ ReadInputBufferThread(IN PLIST_ENTRY WaitList, * If we go there, that means we are notified for some new input. * The console is therefore already locked. */ - Status = ReadInputBuffer(InputInfo, - GetInputRequest->bRead, - WaitApiMessage, - FALSE); + Status = ReadInputBuffer(InputInfo, WaitApiMessage, FALSE); Quit: if (Status != STATUS_PENDING) @@ -258,16 +251,16 @@ Quit: NTSTATUS NTAPI ConDrvGetConsoleInput(IN PCONSOLE Console, IN PCONSOLE_INPUT_BUFFER InputBuffer, + IN BOOLEAN KeepEvents, IN BOOLEAN WaitForMoreEvents, IN BOOLEAN Unicode, OUT PINPUT_RECORD InputRecord, IN ULONG NumEventsToRead, - OUT PULONG NumEventsRead); + OUT PULONG NumEventsRead OPTIONAL); static NTSTATUS ReadInputBuffer(IN PGET_INPUT_INFO InputInfo, - IN BOOL Wait, // TRUE --> Read ; FALSE --> Peek IN PCSR_API_MESSAGE ApiMessage, - IN BOOL CreateWaitBlock OPTIONAL) + IN BOOLEAN CreateWaitBlock OPTIONAL) { NTSTATUS Status; PCONSOLE_GETINPUT GetInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetInputRequest; @@ -277,7 +270,8 @@ ReadInputBuffer(IN PGET_INPUT_INFO InputInfo, Status = ConDrvGetConsoleInput(InputBuffer->Header.Console, InputBuffer, - Wait, + (GetInputRequest->wFlags & CONSOLE_READ_KEEPEVENT) != 0, + (GetInputRequest->wFlags & CONSOLE_READ_CONTINUE ) == 0, GetInputRequest->Unicode, GetInputRequest->InputRecord, GetInputRequest->Length, @@ -336,9 +330,7 @@ CSR_API(SrvReadConsole) InputInfo.HandleEntry = HandleEntry; InputInfo.InputBuffer = InputBuffer; - Status = ReadChars(&InputInfo, - ApiMessage, - TRUE); + Status = ReadChars(&InputInfo, ApiMessage, TRUE); ConSrvReleaseInputBuffer(InputBuffer, TRUE); @@ -358,6 +350,9 @@ CSR_API(SrvGetConsoleInput) DPRINT("SrvGetConsoleInput\n"); + if (GetInputRequest->wFlags & ~(CONSOLE_READ_KEEPEVENT | CONSOLE_READ_CONTINUE)) + return STATUS_INVALID_PARAMETER; + if (!CsrValidateMessageBuffer(ApiMessage, (PVOID*)&GetInputRequest->InputRecord, GetInputRequest->Length, @@ -375,10 +370,7 @@ CSR_API(SrvGetConsoleInput) InputInfo.HandleEntry = HandleEntry; InputInfo.InputBuffer = InputBuffer; - Status = ReadInputBuffer(&InputInfo, - GetInputRequest->bRead, - ApiMessage, - TRUE); + Status = ReadInputBuffer(&InputInfo, ApiMessage, TRUE); ConSrvReleaseInputBuffer(InputBuffer, TRUE); diff --git a/reactos/win32ss/user/winsrv/consrv/conoutput.c b/reactos/win32ss/user/winsrv/consrv/conoutput.c index e7ea3846af1..e8c55c7b188 100644 --- a/reactos/win32ss/user/winsrv/consrv/conoutput.c +++ b/reactos/win32ss/user/winsrv/consrv/conoutput.c @@ -323,7 +323,7 @@ CSR_API(SrvSetConsoleActiveScreenBuffer) static NTSTATUS DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage, IN PCSR_THREAD ClientThread, - IN BOOL CreateWaitBlock OPTIONAL); + IN BOOLEAN CreateWaitBlock OPTIONAL); // Wait function CSR_WAIT_FUNCTION static BOOLEAN @@ -351,9 +351,7 @@ WriteConsoleThread(IN PLIST_ENTRY WaitList, goto Quit; } - Status = DoWriteConsole(WaitApiMessage, - WaitThread, - FALSE); + Status = DoWriteConsole(WaitApiMessage, WaitThread, FALSE); Quit: if (Status != STATUS_PENDING) @@ -374,7 +372,7 @@ ConDrvWriteConsole(IN PCONSOLE Console, static NTSTATUS DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage, IN PCSR_THREAD ClientThread, - IN BOOL CreateWaitBlock OPTIONAL) + IN BOOLEAN CreateWaitBlock OPTIONAL) { NTSTATUS Status; PCONSOLE_WRITECONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest; @@ -517,9 +515,7 @@ CSR_API(SrvWriteConsole) return STATUS_INVALID_PARAMETER; } - Status = DoWriteConsole(ApiMessage, - CsrGetClientThread(), - TRUE); + Status = DoWriteConsole(ApiMessage, CsrGetClientThread(), TRUE); if (Status == STATUS_PENDING) *ReplyCode = CsrReplyPending;