[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
This commit is contained in:
Hermès Bélusca-Maïto 2013-11-10 20:20:57 +00:00
parent 1d42828a47
commit b8b8819c7b
6 changed files with 94 additions and 52 deletions

View file

@ -120,11 +120,11 @@ IntReadConsole(HANDLE hConsoleInput,
static static
BOOL BOOL
IntGetConsoleInput(HANDLE hConsoleInput, IntGetConsoleInput(HANDLE hConsoleInput,
BOOL bRead,
PINPUT_RECORD lpBuffer, PINPUT_RECORD lpBuffer,
DWORD nLength, DWORD nLength,
LPDWORD lpNumberOfEventsRead, LPDWORD lpNumberOfEventsRead,
BOOL bUnicode) WORD wFlags,
BOOLEAN bUnicode)
{ {
NTSTATUS Status; NTSTATUS Status;
CONSOLE_API_MESSAGE ApiMessage; CONSOLE_API_MESSAGE ApiMessage;
@ -158,10 +158,10 @@ IntGetConsoleInput(HANDLE hConsoleInput,
/* Set up the data to send to the Console Server */ /* Set up the data to send to the Console Server */
GetInputRequest->InputHandle = hConsoleInput; GetInputRequest->InputHandle = hConsoleInput;
GetInputRequest->Unicode = bUnicode;
GetInputRequest->bRead = bRead;
GetInputRequest->InputsRead = 0; GetInputRequest->InputsRead = 0;
GetInputRequest->Length = nLength; GetInputRequest->Length = nLength;
GetInputRequest->wFlags = wFlags;
GetInputRequest->Unicode = bUnicode;
/* Call the server */ /* Call the server */
Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
@ -825,10 +825,10 @@ PeekConsoleInputW(HANDLE hConsoleInput,
LPDWORD lpNumberOfEventsRead) LPDWORD lpNumberOfEventsRead)
{ {
return IntGetConsoleInput(hConsoleInput, return IntGetConsoleInput(hConsoleInput,
FALSE,
lpBuffer, lpBuffer,
nLength, nLength,
lpNumberOfEventsRead, lpNumberOfEventsRead,
CONSOLE_READ_KEEPEVENT | CONSOLE_READ_CONTINUE,
TRUE); TRUE);
} }
@ -846,10 +846,10 @@ PeekConsoleInputA(HANDLE hConsoleInput,
LPDWORD lpNumberOfEventsRead) LPDWORD lpNumberOfEventsRead)
{ {
return IntGetConsoleInput(hConsoleInput, return IntGetConsoleInput(hConsoleInput,
FALSE,
lpBuffer, lpBuffer,
nLength, nLength,
lpNumberOfEventsRead, lpNumberOfEventsRead,
CONSOLE_READ_KEEPEVENT | CONSOLE_READ_CONTINUE,
FALSE); FALSE);
} }
@ -867,10 +867,10 @@ ReadConsoleInputW(HANDLE hConsoleInput,
LPDWORD lpNumberOfEventsRead) LPDWORD lpNumberOfEventsRead)
{ {
return IntGetConsoleInput(hConsoleInput, return IntGetConsoleInput(hConsoleInput,
TRUE,
lpBuffer, lpBuffer,
nLength, nLength,
lpNumberOfEventsRead, lpNumberOfEventsRead,
0,
TRUE); TRUE);
} }
@ -888,29 +888,55 @@ ReadConsoleInputA(HANDLE hConsoleInput,
LPDWORD lpNumberOfEventsRead) LPDWORD lpNumberOfEventsRead)
{ {
return IntGetConsoleInput(hConsoleInput, return IntGetConsoleInput(hConsoleInput,
TRUE,
lpBuffer, lpBuffer,
nLength, nLength,
lpNumberOfEventsRead, lpNumberOfEventsRead,
0,
FALSE); FALSE);
} }
/*--------------------------------------------------------------
* ReadConsoleInputExW
*
* @implemented
*/
BOOL BOOL
WINAPI 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 IntGetConsoleInput(hConsoleInput,
return FALSE; lpBuffer,
nLength,
lpNumberOfEventsRead,
wFlags,
TRUE);
} }
/*--------------------------------------------------------------
* ReadConsoleInputExA
*
* @implemented
*/
BOOL BOOL
WINAPI 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 IntGetConsoleInput(hConsoleInput,
return FALSE; lpBuffer,
nLength,
lpNumberOfEventsRead,
wFlags,
FALSE);
} }

View file

@ -108,6 +108,12 @@ extern "C" {
#define HISTORY_NO_DUP_FLAG 0x0001 #define HISTORY_NO_DUP_FLAG 0x0001
#endif #endif
/*
* Read input flags
*/
#define CONSOLE_READ_KEEPEVENT 0x0001
#define CONSOLE_READ_CONTINUE 0x0002
/* /*
* Event types * Event types
*/ */
@ -436,6 +442,7 @@ COORD WINAPI GetLargestConsoleWindowSize(_In_ HANDLE);
BOOL WINAPI GetNumberOfConsoleInputEvents(_In_ HANDLE, _Out_ PDWORD); BOOL WINAPI GetNumberOfConsoleInputEvents(_In_ HANDLE, _Out_ PDWORD);
BOOL WINAPI GetNumberOfConsoleMouseButtons(_Out_ PDWORD); BOOL WINAPI GetNumberOfConsoleMouseButtons(_Out_ PDWORD);
_Success_(return != 0)
BOOL BOOL
WINAPI PeekConsoleInputA( WINAPI PeekConsoleInputA(
_In_ HANDLE hConsoleInput, _In_ HANDLE hConsoleInput,
@ -443,6 +450,7 @@ WINAPI PeekConsoleInputA(
_In_ DWORD nLength, _In_ DWORD nLength,
_Out_ LPDWORD lpNumberOfEventsRead); _Out_ LPDWORD lpNumberOfEventsRead);
_Success_(return != 0)
BOOL BOOL
WINAPI WINAPI
PeekConsoleInputW( PeekConsoleInputW(
@ -489,6 +497,26 @@ ReadConsoleInputW(
_In_ DWORD nLength, _In_ DWORD nLength,
_Out_ _Deref_out_range_(<= , nLength) LPDWORD lpNumberOfEventsRead); _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 BOOL
WINAPI WINAPI
ReadConsoleOutputAttribute( ReadConsoleOutputAttribute(

View file

@ -469,13 +469,11 @@ typedef struct
typedef struct typedef struct
{ {
HANDLE InputHandle; HANDLE InputHandle;
BOOL Unicode;
BOOL bRead; // TRUE --> Read ; FALSE --> Peek
ULONG InputsRead; ULONG InputsRead;
ULONG Length;
PINPUT_RECORD InputRecord; PINPUT_RECORD InputRecord;
ULONG Length;
WORD wFlags;
BOOLEAN Unicode;
} CONSOLE_GETINPUT, *PCONSOLE_GETINPUT; } CONSOLE_GETINPUT, *PCONSOLE_GETINPUT;
typedef struct typedef struct

View file

@ -376,6 +376,7 @@ ConDrvReadConsole(IN PCONSOLE Console,
NTSTATUS NTAPI NTSTATUS NTAPI
ConDrvGetConsoleInput(IN PCONSOLE Console, ConDrvGetConsoleInput(IN PCONSOLE Console,
IN PCONSOLE_INPUT_BUFFER InputBuffer, IN PCONSOLE_INPUT_BUFFER InputBuffer,
IN BOOLEAN KeepEvents,
IN BOOLEAN WaitForMoreEvents, IN BOOLEAN WaitForMoreEvents,
IN BOOLEAN Unicode, IN BOOLEAN Unicode,
OUT PINPUT_RECORD InputRecord, OUT PINPUT_RECORD InputRecord,
@ -425,7 +426,8 @@ ConDrvGetConsoleInput(IN PCONSOLE Console,
++i; ++i;
CurrentInput = CurrentInput->Flink; 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); RemoveEntryList(&Input->ListEntry);
ConsoleFreeHeap(Input); ConsoleFreeHeap(Input);

View file

@ -45,7 +45,7 @@ static NTSTATUS
WaitBeforeReading(IN PGET_INPUT_INFO InputInfo, WaitBeforeReading(IN PGET_INPUT_INFO InputInfo,
IN PCSR_API_MESSAGE ApiMessage, IN PCSR_API_MESSAGE ApiMessage,
IN CSR_WAIT_FUNCTION WaitFunction OPTIONAL, IN CSR_WAIT_FUNCTION WaitFunction OPTIONAL,
IN BOOL CreateWaitBlock OPTIONAL) IN BOOLEAN CreateWaitBlock OPTIONAL)
{ {
if (CreateWaitBlock) if (CreateWaitBlock)
{ {
@ -74,7 +74,7 @@ WaitBeforeReading(IN PGET_INPUT_INFO InputInfo,
static NTSTATUS static NTSTATUS
ReadChars(IN PGET_INPUT_INFO InputInfo, ReadChars(IN PGET_INPUT_INFO InputInfo,
IN PCSR_API_MESSAGE ApiMessage, IN PCSR_API_MESSAGE ApiMessage,
IN BOOL CreateWaitBlock OPTIONAL); IN BOOLEAN CreateWaitBlock OPTIONAL);
// Wait function CSR_WAIT_FUNCTION // Wait function CSR_WAIT_FUNCTION
static BOOLEAN static BOOLEAN
@ -123,9 +123,7 @@ ReadCharsThread(IN PLIST_ENTRY WaitList,
* If we go there, that means we are notified for some new input. * If we go there, that means we are notified for some new input.
* The console is therefore already locked. * The console is therefore already locked.
*/ */
Status = ReadChars(InputInfo, Status = ReadChars(InputInfo, WaitApiMessage, FALSE);
WaitApiMessage,
FALSE);
Quit: Quit:
if (Status != STATUS_PENDING) if (Status != STATUS_PENDING)
@ -148,7 +146,7 @@ ConDrvReadConsole(IN PCONSOLE Console,
static NTSTATUS static NTSTATUS
ReadChars(IN PGET_INPUT_INFO InputInfo, ReadChars(IN PGET_INPUT_INFO InputInfo,
IN PCSR_API_MESSAGE ApiMessage, IN PCSR_API_MESSAGE ApiMessage,
IN BOOL CreateWaitBlock OPTIONAL) IN BOOLEAN CreateWaitBlock OPTIONAL)
{ {
NTSTATUS Status; NTSTATUS Status;
PCONSOLE_READCONSOLE ReadConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleRequest; PCONSOLE_READCONSOLE ReadConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleRequest;
@ -188,9 +186,8 @@ ReadChars(IN PGET_INPUT_INFO InputInfo,
static NTSTATUS static NTSTATUS
ReadInputBuffer(IN PGET_INPUT_INFO InputInfo, ReadInputBuffer(IN PGET_INPUT_INFO InputInfo,
IN BOOL Wait,
IN PCSR_API_MESSAGE ApiMessage, IN PCSR_API_MESSAGE ApiMessage,
IN BOOL CreateWaitBlock OPTIONAL); IN BOOLEAN CreateWaitBlock OPTIONAL);
// Wait function CSR_WAIT_FUNCTION // Wait function CSR_WAIT_FUNCTION
static BOOLEAN static BOOLEAN
@ -204,7 +201,6 @@ ReadInputBufferThread(IN PLIST_ENTRY WaitList,
IN ULONG WaitFlags) IN ULONG WaitFlags)
{ {
NTSTATUS Status; NTSTATUS Status;
PCONSOLE_GETINPUT GetInputRequest = &((PCONSOLE_API_MESSAGE)WaitApiMessage)->Data.GetInputRequest;
PGET_INPUT_INFO InputInfo = (PGET_INPUT_INFO)WaitContext; PGET_INPUT_INFO InputInfo = (PGET_INPUT_INFO)WaitContext;
PVOID InputHandle = WaitArgument2; 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. * If we go there, that means we are notified for some new input.
* The console is therefore already locked. * The console is therefore already locked.
*/ */
Status = ReadInputBuffer(InputInfo, Status = ReadInputBuffer(InputInfo, WaitApiMessage, FALSE);
GetInputRequest->bRead,
WaitApiMessage,
FALSE);
Quit: Quit:
if (Status != STATUS_PENDING) if (Status != STATUS_PENDING)
@ -258,16 +251,16 @@ Quit:
NTSTATUS NTAPI NTSTATUS NTAPI
ConDrvGetConsoleInput(IN PCONSOLE Console, ConDrvGetConsoleInput(IN PCONSOLE Console,
IN PCONSOLE_INPUT_BUFFER InputBuffer, IN PCONSOLE_INPUT_BUFFER InputBuffer,
IN BOOLEAN KeepEvents,
IN BOOLEAN WaitForMoreEvents, IN BOOLEAN WaitForMoreEvents,
IN BOOLEAN Unicode, IN BOOLEAN Unicode,
OUT PINPUT_RECORD InputRecord, OUT PINPUT_RECORD InputRecord,
IN ULONG NumEventsToRead, IN ULONG NumEventsToRead,
OUT PULONG NumEventsRead); OUT PULONG NumEventsRead OPTIONAL);
static NTSTATUS static NTSTATUS
ReadInputBuffer(IN PGET_INPUT_INFO InputInfo, ReadInputBuffer(IN PGET_INPUT_INFO InputInfo,
IN BOOL Wait, // TRUE --> Read ; FALSE --> Peek
IN PCSR_API_MESSAGE ApiMessage, IN PCSR_API_MESSAGE ApiMessage,
IN BOOL CreateWaitBlock OPTIONAL) IN BOOLEAN CreateWaitBlock OPTIONAL)
{ {
NTSTATUS Status; NTSTATUS Status;
PCONSOLE_GETINPUT GetInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetInputRequest; PCONSOLE_GETINPUT GetInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetInputRequest;
@ -277,7 +270,8 @@ ReadInputBuffer(IN PGET_INPUT_INFO InputInfo,
Status = ConDrvGetConsoleInput(InputBuffer->Header.Console, Status = ConDrvGetConsoleInput(InputBuffer->Header.Console,
InputBuffer, InputBuffer,
Wait, (GetInputRequest->wFlags & CONSOLE_READ_KEEPEVENT) != 0,
(GetInputRequest->wFlags & CONSOLE_READ_CONTINUE ) == 0,
GetInputRequest->Unicode, GetInputRequest->Unicode,
GetInputRequest->InputRecord, GetInputRequest->InputRecord,
GetInputRequest->Length, GetInputRequest->Length,
@ -336,9 +330,7 @@ CSR_API(SrvReadConsole)
InputInfo.HandleEntry = HandleEntry; InputInfo.HandleEntry = HandleEntry;
InputInfo.InputBuffer = InputBuffer; InputInfo.InputBuffer = InputBuffer;
Status = ReadChars(&InputInfo, Status = ReadChars(&InputInfo, ApiMessage, TRUE);
ApiMessage,
TRUE);
ConSrvReleaseInputBuffer(InputBuffer, TRUE); ConSrvReleaseInputBuffer(InputBuffer, TRUE);
@ -358,6 +350,9 @@ CSR_API(SrvGetConsoleInput)
DPRINT("SrvGetConsoleInput\n"); DPRINT("SrvGetConsoleInput\n");
if (GetInputRequest->wFlags & ~(CONSOLE_READ_KEEPEVENT | CONSOLE_READ_CONTINUE))
return STATUS_INVALID_PARAMETER;
if (!CsrValidateMessageBuffer(ApiMessage, if (!CsrValidateMessageBuffer(ApiMessage,
(PVOID*)&GetInputRequest->InputRecord, (PVOID*)&GetInputRequest->InputRecord,
GetInputRequest->Length, GetInputRequest->Length,
@ -375,10 +370,7 @@ CSR_API(SrvGetConsoleInput)
InputInfo.HandleEntry = HandleEntry; InputInfo.HandleEntry = HandleEntry;
InputInfo.InputBuffer = InputBuffer; InputInfo.InputBuffer = InputBuffer;
Status = ReadInputBuffer(&InputInfo, Status = ReadInputBuffer(&InputInfo, ApiMessage, TRUE);
GetInputRequest->bRead,
ApiMessage,
TRUE);
ConSrvReleaseInputBuffer(InputBuffer, TRUE); ConSrvReleaseInputBuffer(InputBuffer, TRUE);

View file

@ -323,7 +323,7 @@ CSR_API(SrvSetConsoleActiveScreenBuffer)
static NTSTATUS static NTSTATUS
DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage, DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
IN PCSR_THREAD ClientThread, IN PCSR_THREAD ClientThread,
IN BOOL CreateWaitBlock OPTIONAL); IN BOOLEAN CreateWaitBlock OPTIONAL);
// Wait function CSR_WAIT_FUNCTION // Wait function CSR_WAIT_FUNCTION
static BOOLEAN static BOOLEAN
@ -351,9 +351,7 @@ WriteConsoleThread(IN PLIST_ENTRY WaitList,
goto Quit; goto Quit;
} }
Status = DoWriteConsole(WaitApiMessage, Status = DoWriteConsole(WaitApiMessage, WaitThread, FALSE);
WaitThread,
FALSE);
Quit: Quit:
if (Status != STATUS_PENDING) if (Status != STATUS_PENDING)
@ -374,7 +372,7 @@ ConDrvWriteConsole(IN PCONSOLE Console,
static NTSTATUS static NTSTATUS
DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage, DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
IN PCSR_THREAD ClientThread, IN PCSR_THREAD ClientThread,
IN BOOL CreateWaitBlock OPTIONAL) IN BOOLEAN CreateWaitBlock OPTIONAL)
{ {
NTSTATUS Status; NTSTATUS Status;
PCONSOLE_WRITECONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest; PCONSOLE_WRITECONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest;
@ -517,9 +515,7 @@ CSR_API(SrvWriteConsole)
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
Status = DoWriteConsole(ApiMessage, Status = DoWriteConsole(ApiMessage, CsrGetClientThread(), TRUE);
CsrGetClientThread(),
TRUE);
if (Status == STATUS_PENDING) *ReplyCode = CsrReplyPending; if (Status == STATUS_PENDING) *ReplyCode = CsrReplyPending;