2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/consrv/coninput.c
5 * PURPOSE: Console I/O functions
9 /* INCLUDES *******************************************************************/
13 #include "tuiconsole.h"
19 /* GLOBALS ********************************************************************/
21 #define ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar) \
22 WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
24 #define ConsoleInputAnsiCharToUnicodeChar(Console, dWChar, sChar) \
25 MultiByteToWideChar((Console)->CodePage, 0, (sChar), 1, (dWChar), 1)
28 typedef struct _GET_INPUT_INFO
30 PCONSOLE_PROCESS_DATA ProcessData
;
31 PCSRSS_CONSOLE Console
;
32 } GET_INPUT_INFO
, *PGET_INPUT_INFO
;
35 /* PRIVATE FUNCTIONS **********************************************************/
38 ConioInputEventToAnsi(PCSRSS_CONSOLE Console
, PINPUT_RECORD InputEvent
)
40 if (InputEvent
->EventType
== KEY_EVENT
)
42 WCHAR UnicodeChar
= InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
;
43 InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
= 0;
44 ConsoleInputUnicodeCharToAnsiChar(Console
,
45 &InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
,
50 static NTSTATUS FASTCALL
51 ConioProcessChar(PCSRSS_CONSOLE Console
,
52 PINPUT_RECORD InputEvent
)
54 ConsoleInput
*ConInRec
;
56 /* Check for pause or unpause */
57 if (InputEvent
->EventType
== KEY_EVENT
&& InputEvent
->Event
.KeyEvent
.bKeyDown
)
59 WORD vk
= InputEvent
->Event
.KeyEvent
.wVirtualKeyCode
;
60 if (!(Console
->PauseFlags
& PAUSED_FROM_KEYBOARD
))
62 DWORD cks
= InputEvent
->Event
.KeyEvent
.dwControlKeyState
;
63 if (Console
->Mode
& ENABLE_LINE_INPUT
&&
64 (vk
== VK_PAUSE
|| (vk
== 'S' &&
65 (cks
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
)) &&
66 !(cks
& (LEFT_ALT_PRESSED
| RIGHT_ALT_PRESSED
)))))
68 ConioPause(Console
, PAUSED_FROM_KEYBOARD
);
69 return STATUS_SUCCESS
;
74 if ((vk
< VK_SHIFT
|| vk
> VK_CAPITAL
) && vk
!= VK_LWIN
&&
75 vk
!= VK_RWIN
&& vk
!= VK_NUMLOCK
&& vk
!= VK_SCROLL
)
77 ConioUnpause(Console
, PAUSED_FROM_KEYBOARD
);
78 return STATUS_SUCCESS
;
83 /* add event to the queue */
84 ConInRec
= RtlAllocateHeap(ConSrvHeap
, 0, sizeof(ConsoleInput
));
86 return STATUS_INSUFFICIENT_RESOURCES
;
87 ConInRec
->InputEvent
= *InputEvent
;
88 InsertTailList(&Console
->InputEvents
, &ConInRec
->ListEntry
);
90 SetEvent(Console
->ActiveEvent
);
91 CsrNotifyWait(&Console
->ReadWaitQueue
,
96 return STATUS_SUCCESS
;
100 ConioGetShiftState(PBYTE KeyState
)
104 if (KeyState
[VK_CAPITAL
] & 1)
105 ssOut
|= CAPSLOCK_ON
;
107 if (KeyState
[VK_NUMLOCK
] & 1)
110 if (KeyState
[VK_SCROLL
] & 1)
111 ssOut
|= SCROLLLOCK_ON
;
113 if (KeyState
[VK_SHIFT
] & 0x80)
114 ssOut
|= SHIFT_PRESSED
;
116 if (KeyState
[VK_LCONTROL
] & 0x80)
117 ssOut
|= LEFT_CTRL_PRESSED
;
118 if (KeyState
[VK_RCONTROL
] & 0x80)
119 ssOut
|= RIGHT_CTRL_PRESSED
;
121 if (KeyState
[VK_LMENU
] & 0x80)
122 ssOut
|= LEFT_ALT_PRESSED
;
123 if (KeyState
[VK_RMENU
] & 0x80)
124 ssOut
|= RIGHT_ALT_PRESSED
;
130 ConioProcessKey(MSG
*msg
, PCSRSS_CONSOLE Console
, BOOL TextMode
)
132 static BYTE KeyState
[256] = { 0 };
133 /* MSDN mentions that you should use the last virtual key code received
134 * when putting a virtual key identity to a WM_CHAR message since multiple
135 * or translated keys may be involved. */
136 static UINT LastVirtualKey
= 0;
141 UINT VirtualScanCode
;
144 BOOLEAN Fake
; // synthesized, not a real event
145 BOOLEAN NotChar
; // message should not be used to return a character
148 VirtualScanCode
= (msg
->lParam
>> 16) & 0xff;
149 Down
= msg
->message
== WM_KEYDOWN
|| msg
->message
== WM_CHAR
||
150 msg
->message
== WM_SYSKEYDOWN
|| msg
->message
== WM_SYSCHAR
;
152 GetKeyboardState(KeyState
);
153 ShiftState
= ConioGetShiftState(KeyState
);
155 if (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
)
157 VirtualKeyCode
= LastVirtualKey
;
158 UnicodeChar
= msg
->wParam
;
165 VirtualKeyCode
= msg
->wParam
;
166 RetChars
= ToUnicodeEx(VirtualKeyCode
,
173 UnicodeChar
= (1 == RetChars
? Chars
[0] : 0);
176 er
.EventType
= KEY_EVENT
;
177 er
.Event
.KeyEvent
.bKeyDown
= Down
;
178 er
.Event
.KeyEvent
.wRepeatCount
= RepeatCount
;
179 er
.Event
.KeyEvent
.uChar
.UnicodeChar
= UnicodeChar
;
180 er
.Event
.KeyEvent
.dwControlKeyState
= ShiftState
;
181 er
.Event
.KeyEvent
.wVirtualKeyCode
= VirtualKeyCode
;
182 er
.Event
.KeyEvent
.wVirtualScanCode
= VirtualScanCode
;
186 if (0 != (ShiftState
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
187 && VK_TAB
== VirtualKeyCode
)
191 TuiSwapConsole(ShiftState
& SHIFT_PRESSED
? -1 : 1);
196 else if (VK_MENU
== VirtualKeyCode
&& ! Down
)
198 if (TuiSwapConsole(0))
206 if ((ShiftState
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
) || KeyState
[VK_MENU
] & 0x80) &&
207 (VirtualKeyCode
== VK_ESCAPE
|| VirtualKeyCode
== VK_TAB
|| VirtualKeyCode
== VK_SPACE
))
209 DefWindowProcW( msg
->hwnd
, msg
->message
, msg
->wParam
, msg
->lParam
);
216 DPRINT1("No Active Console!\n");
220 Fake
= UnicodeChar
&&
221 (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
&&
222 msg
->message
!= WM_KEYUP
&& msg
->message
!= WM_SYSKEYUP
);
223 NotChar
= (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
);
225 LastVirtualKey
= msg
->wParam
;
227 DPRINT("CONSRV: %s %s %s %s %02x %02x '%lc' %04x\n",
228 Down
? "down" : "up ",
229 (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
) ?
231 Fake
? "fake" : "real",
232 NotChar
? "notc" : "char",
235 (UnicodeChar
>= L
' ') ? UnicodeChar
: L
'.',
241 /* process Ctrl-C and Ctrl-Break */
242 if (Console
->Mode
& ENABLE_PROCESSED_INPUT
&&
243 er
.Event
.KeyEvent
.bKeyDown
&&
244 ((er
.Event
.KeyEvent
.wVirtualKeyCode
== VK_PAUSE
) ||
245 (er
.Event
.KeyEvent
.wVirtualKeyCode
== 'C')) &&
246 (er
.Event
.KeyEvent
.dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
) || KeyState
[VK_CONTROL
] & 0x80))
248 PCONSOLE_PROCESS_DATA current
;
249 PLIST_ENTRY current_entry
;
251 DPRINT1("Console_Api Ctrl-C\n");
253 current_entry
= Console
->ProcessList
.Flink
;
254 while (current_entry
!= &Console
->ProcessList
)
256 current
= CONTAINING_RECORD(current_entry
, CONSOLE_PROCESS_DATA
, ConsoleLink
);
257 current_entry
= current_entry
->Flink
;
258 ConioConsoleCtrlEvent((DWORD
)CTRL_C_EVENT
, current
);
260 if (Console
->LineBuffer
&& !Console
->LineComplete
)
262 /* Line input is in progress; end it */
263 Console
->LinePos
= Console
->LineSize
= 0;
264 Console
->LineComplete
= TRUE
;
269 if (0 != (er
.Event
.KeyEvent
.dwControlKeyState
270 & (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
271 && (VK_UP
== er
.Event
.KeyEvent
.wVirtualKeyCode
272 || VK_DOWN
== er
.Event
.KeyEvent
.wVirtualKeyCode
))
274 if (er
.Event
.KeyEvent
.bKeyDown
)
276 /* scroll up or down */
277 if (VK_UP
== er
.Event
.KeyEvent
.wVirtualKeyCode
)
279 /* only scroll up if there is room to scroll up into */
280 if (Console
->ActiveBuffer
->CurrentY
!= Console
->ActiveBuffer
->MaxY
- 1)
282 Console
->ActiveBuffer
->VirtualY
= (Console
->ActiveBuffer
->VirtualY
+
283 Console
->ActiveBuffer
->MaxY
- 1) %
284 Console
->ActiveBuffer
->MaxY
;
285 Console
->ActiveBuffer
->CurrentY
++;
290 /* only scroll down if there is room to scroll down into */
291 if (Console
->ActiveBuffer
->CurrentY
!= 0)
293 Console
->ActiveBuffer
->VirtualY
= (Console
->ActiveBuffer
->VirtualY
+ 1) %
294 Console
->ActiveBuffer
->MaxY
;
295 Console
->ActiveBuffer
->CurrentY
--;
298 ConioDrawConsole(Console
);
302 ConioProcessChar(Console
, &er
);
306 WaitBeforeReading(IN PGET_INPUT_INFO InputInfo
,
307 IN PCSR_API_MESSAGE ApiMessage
,
308 IN CSR_WAIT_FUNCTION WaitFunction OPTIONAL
,
309 IN BOOL CreateWaitBlock OPTIONAL
)
313 PGET_INPUT_INFO CapturedInputInfo
;
315 CapturedInputInfo
= HeapAlloc(ConSrvHeap
, 0, sizeof(GET_INPUT_INFO
));
316 if (!CapturedInputInfo
) return STATUS_NO_MEMORY
;
318 memmove(CapturedInputInfo
, InputInfo
, sizeof(GET_INPUT_INFO
));
320 if (!CsrCreateWait(&InputInfo
->Console
->ReadWaitQueue
,
322 CsrGetClientThread(),
327 HeapFree(ConSrvHeap
, 0, CapturedInputInfo
);
328 return STATUS_NO_MEMORY
;
333 return STATUS_PENDING
;
337 ReadInputBuffer(IN PGET_INPUT_INFO InputInfo
,
339 IN PCSR_API_MESSAGE ApiMessage
,
340 IN BOOL CreateWaitBlock OPTIONAL
);
342 // Wait function CSR_WAIT_FUNCTION
344 ReadInputBufferThread(IN PLIST_ENTRY WaitList
,
345 IN PCSR_THREAD WaitThread
,
346 IN PCSR_API_MESSAGE WaitApiMessage
,
347 IN PVOID WaitContext
,
348 IN PVOID WaitArgument1
,
349 IN PVOID WaitArgument2
,
353 PCONSOLE_GETINPUT GetInputRequest
= &((PCONSOLE_API_MESSAGE
)WaitApiMessage
)->Data
.GetInputRequest
;
354 PGET_INPUT_INFO InputInfo
= (PGET_INPUT_INFO
)WaitContext
;
356 Status
= ReadInputBuffer(InputInfo
,
357 GetInputRequest
->bRead
,
361 if (Status
!= STATUS_PENDING
)
363 WaitApiMessage
->Status
= Status
;
364 HeapFree(ConSrvHeap
, 0, InputInfo
);
367 return (Status
== STATUS_PENDING
? FALSE
: TRUE
);
371 ReadInputBuffer(IN PGET_INPUT_INFO InputInfo
,
372 IN BOOL Wait
, // TRUE --> Read ; FALSE --> Peek
373 IN PCSR_API_MESSAGE ApiMessage
,
374 IN BOOL CreateWaitBlock OPTIONAL
)
376 if (IsListEmpty(&InputInfo
->Console
->InputEvents
))
380 return WaitBeforeReading(InputInfo
,
382 ReadInputBufferThread
,
387 /* No input available and we don't wait, so we return success */
388 return STATUS_SUCCESS
;
393 PCONSOLE_GETINPUT GetInputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetInputRequest
;
394 PLIST_ENTRY CurrentInput
;
396 ULONG Length
= GetInputRequest
->Length
;
397 PINPUT_RECORD InputRecord
= GetInputRequest
->InputRecord
;
399 /* Only get input if there is any */
400 CurrentInput
= InputInfo
->Console
->InputEvents
.Flink
;
402 while ( CurrentInput
!= &InputInfo
->Console
->InputEvents
&&
403 GetInputRequest
->InputsRead
< Length
)
405 Input
= CONTAINING_RECORD(CurrentInput
, ConsoleInput
, ListEntry
);
407 GetInputRequest
->InputsRead
++;
408 *InputRecord
= Input
->InputEvent
;
410 if (GetInputRequest
->Unicode
== FALSE
)
412 ConioInputEventToAnsi(InputInfo
->Console
, InputRecord
);
416 CurrentInput
= CurrentInput
->Flink
;
418 if (Wait
) // TRUE --> Read, we remove inputs from the buffer ; FALSE --> Peek, we keep inputs.
420 RemoveEntryList(&Input
->ListEntry
);
421 HeapFree(ConSrvHeap
, 0, Input
);
425 if (IsListEmpty(&InputInfo
->Console
->InputEvents
))
427 ResetEvent(InputInfo
->Console
->ActiveEvent
);
430 /* We read all the inputs available, we return success */
431 return STATUS_SUCCESS
;
436 ReadChars(IN PGET_INPUT_INFO InputInfo
,
437 IN PCSR_API_MESSAGE ApiMessage
,
438 IN BOOL CreateWaitBlock OPTIONAL
);
440 // Wait function CSR_WAIT_FUNCTION
442 ReadCharsThread(IN PLIST_ENTRY WaitList
,
443 IN PCSR_THREAD WaitThread
,
444 IN PCSR_API_MESSAGE WaitApiMessage
,
445 IN PVOID WaitContext
,
446 IN PVOID WaitArgument1
,
447 IN PVOID WaitArgument2
,
451 PGET_INPUT_INFO InputInfo
= (PGET_INPUT_INFO
)WaitContext
;
453 Status
= ReadChars(InputInfo
,
457 if (Status
!= STATUS_PENDING
)
459 WaitApiMessage
->Status
= Status
;
460 HeapFree(ConSrvHeap
, 0, InputInfo
);
463 return (Status
== STATUS_PENDING
? FALSE
: TRUE
);
467 ReadChars(IN PGET_INPUT_INFO InputInfo
,
468 IN PCSR_API_MESSAGE ApiMessage
,
469 IN BOOL CreateWaitBlock OPTIONAL
)
471 BOOL WaitForMoreToRead
= TRUE
; // TRUE : Wait if more to read ; FALSE : Don't wait.
473 PCONSOLE_READCONSOLE ReadConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ReadConsoleRequest
;
474 PLIST_ENTRY CurrentEntry
;
476 PCHAR Buffer
= (PCHAR
)ReadConsoleRequest
->Buffer
;
477 PWCHAR UnicodeBuffer
= (PWCHAR
)Buffer
;
478 ULONG nNumberOfCharsToRead
= ReadConsoleRequest
->NrCharactersToRead
;
480 /* We haven't read anything (yet) */
482 if (InputInfo
->Console
->Mode
& ENABLE_LINE_INPUT
)
484 if (InputInfo
->Console
->LineBuffer
== NULL
)
486 /* Starting a new line */
487 InputInfo
->Console
->LineMaxSize
= max(256, nNumberOfCharsToRead
);
488 InputInfo
->Console
->LineBuffer
= HeapAlloc(ConSrvHeap
, 0, InputInfo
->Console
->LineMaxSize
* sizeof(WCHAR
));
489 if (InputInfo
->Console
->LineBuffer
== NULL
)
491 return STATUS_NO_MEMORY
;
493 InputInfo
->Console
->LineComplete
= FALSE
;
494 InputInfo
->Console
->LineUpPressed
= FALSE
;
495 InputInfo
->Console
->LineInsertToggle
= 0;
496 InputInfo
->Console
->LineWakeupMask
= ReadConsoleRequest
->CtrlWakeupMask
;
497 InputInfo
->Console
->LineSize
= ReadConsoleRequest
->NrCharactersRead
;
498 InputInfo
->Console
->LinePos
= InputInfo
->Console
->LineSize
;
501 * Pre-filling the buffer is only allowed in the Unicode API,
502 * so we don't need to worry about ANSI <-> Unicode conversion.
504 memcpy(InputInfo
->Console
->LineBuffer
, Buffer
, InputInfo
->Console
->LineSize
* sizeof(WCHAR
));
505 if (InputInfo
->Console
->LineSize
== InputInfo
->Console
->LineMaxSize
)
507 InputInfo
->Console
->LineComplete
= TRUE
;
508 InputInfo
->Console
->LinePos
= 0;
512 /* If we don't have a complete line yet, process the pending input */
513 while ( !InputInfo
->Console
->LineComplete
&&
514 !IsListEmpty(&InputInfo
->Console
->InputEvents
) )
516 /* Remove input event from queue */
517 CurrentEntry
= RemoveHeadList(&InputInfo
->Console
->InputEvents
);
518 if (IsListEmpty(&InputInfo
->Console
->InputEvents
))
520 ResetEvent(InputInfo
->Console
->ActiveEvent
);
522 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
524 /* Only pay attention to key down */
525 if (KEY_EVENT
== Input
->InputEvent
.EventType
526 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
528 LineInputKeyDown(InputInfo
->Console
, &Input
->InputEvent
.Event
.KeyEvent
);
529 ReadConsoleRequest
->ControlKeyState
= Input
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
;
531 HeapFree(ConSrvHeap
, 0, Input
);
534 /* Check if we have a complete line to read from */
535 if (InputInfo
->Console
->LineComplete
)
537 while ( ReadConsoleRequest
->NrCharactersRead
< nNumberOfCharsToRead
&&
538 InputInfo
->Console
->LinePos
!= InputInfo
->Console
->LineSize
)
540 WCHAR Char
= InputInfo
->Console
->LineBuffer
[InputInfo
->Console
->LinePos
++];
542 if (ReadConsoleRequest
->Unicode
)
544 UnicodeBuffer
[ReadConsoleRequest
->NrCharactersRead
] = Char
;
548 ConsoleInputUnicodeCharToAnsiChar(InputInfo
->Console
,
549 &Buffer
[ReadConsoleRequest
->NrCharactersRead
],
553 ReadConsoleRequest
->NrCharactersRead
++;
556 if (InputInfo
->Console
->LinePos
== InputInfo
->Console
->LineSize
)
558 /* Entire line has been read */
559 HeapFree(ConSrvHeap
, 0, InputInfo
->Console
->LineBuffer
);
560 InputInfo
->Console
->LineBuffer
= NULL
;
563 WaitForMoreToRead
= FALSE
;
568 /* Character input */
569 while ( ReadConsoleRequest
->NrCharactersRead
< nNumberOfCharsToRead
&&
570 !IsListEmpty(&InputInfo
->Console
->InputEvents
) )
572 /* Remove input event from queue */
573 CurrentEntry
= RemoveHeadList(&InputInfo
->Console
->InputEvents
);
574 if (IsListEmpty(&InputInfo
->Console
->InputEvents
))
576 ResetEvent(InputInfo
->Console
->ActiveEvent
);
578 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
580 /* Only pay attention to valid ascii chars, on key down */
581 if (KEY_EVENT
== Input
->InputEvent
.EventType
582 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
583 && Input
->InputEvent
.Event
.KeyEvent
.uChar
.UnicodeChar
!= L
'\0')
585 WCHAR Char
= Input
->InputEvent
.Event
.KeyEvent
.uChar
.UnicodeChar
;
587 if (ReadConsoleRequest
->Unicode
)
589 UnicodeBuffer
[ReadConsoleRequest
->NrCharactersRead
] = Char
;
593 ConsoleInputUnicodeCharToAnsiChar(InputInfo
->Console
,
594 &Buffer
[ReadConsoleRequest
->NrCharactersRead
],
598 ReadConsoleRequest
->NrCharactersRead
++;
600 /* Did read something */
601 WaitForMoreToRead
= FALSE
;
603 HeapFree(ConSrvHeap
, 0, Input
);
607 /* We haven't completed a read, so start a wait */
608 if (WaitForMoreToRead
== TRUE
)
610 return WaitBeforeReading(InputInfo
,
615 else /* We read all what we wanted, we return success */
617 return STATUS_SUCCESS
;
622 /* PUBLIC APIS ****************************************************************/
624 CSR_API(SrvGetConsoleInput
)
627 PCONSOLE_GETINPUT GetInputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetInputRequest
;
628 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
629 PCSRSS_CONSOLE Console
;
630 GET_INPUT_INFO InputInfo
;
632 DPRINT("SrvGetConsoleInput\n");
634 if (!CsrValidateMessageBuffer(ApiMessage
,
635 (PVOID
*)&GetInputRequest
->InputRecord
,
636 GetInputRequest
->Length
,
637 sizeof(INPUT_RECORD
)))
639 return STATUS_INVALID_PARAMETER
;
642 Status
= ConioLockConsole(ProcessData
, GetInputRequest
->InputHandle
, &Console
, GENERIC_READ
);
643 if(!NT_SUCCESS(Status
)) return Status
;
645 GetInputRequest
->InputsRead
= 0;
647 InputInfo
.ProcessData
= ProcessData
; // ConsoleGetPerProcessData(CsrGetClientThread()->Process);
648 InputInfo
.Console
= Console
;
650 Status
= ReadInputBuffer(&InputInfo
,
651 GetInputRequest
->bRead
,
655 ConioUnlockConsole(Console
);
657 if (Status
== STATUS_PENDING
)
658 *ReplyCode
= CsrReplyPending
;
663 CSR_API(SrvWriteConsoleInput
)
666 PCONSOLE_WRITEINPUT WriteInputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteInputRequest
;
667 PINPUT_RECORD InputRecord
;
668 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
669 PCSRSS_CONSOLE Console
;
673 DPRINT("SrvWriteConsoleInput\n");
675 if (!CsrValidateMessageBuffer(ApiMessage
,
676 (PVOID
*)&WriteInputRequest
->InputRecord
,
677 WriteInputRequest
->Length
,
678 sizeof(INPUT_RECORD
)))
680 return STATUS_INVALID_PARAMETER
;
683 Status
= ConioLockConsole(ProcessData
, WriteInputRequest
->InputHandle
, &Console
, GENERIC_WRITE
);
684 if (!NT_SUCCESS(Status
)) return Status
;
686 InputRecord
= WriteInputRequest
->InputRecord
;
687 Length
= WriteInputRequest
->Length
;
689 for (i
= 0; i
< Length
&& NT_SUCCESS(Status
); i
++)
691 if (!WriteInputRequest
->Unicode
&&
692 InputRecord
->EventType
== KEY_EVENT
)
694 CHAR AsciiChar
= InputRecord
->Event
.KeyEvent
.uChar
.AsciiChar
;
695 ConsoleInputAnsiCharToUnicodeChar(Console
,
696 &InputRecord
->Event
.KeyEvent
.uChar
.UnicodeChar
,
700 Status
= ConioProcessChar(Console
, InputRecord
++);
703 ConioUnlockConsole(Console
);
705 WriteInputRequest
->Length
= i
;
710 CSR_API(SrvReadConsole
)
713 PCONSOLE_READCONSOLE ReadConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ReadConsoleRequest
;
714 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
715 PCSRSS_CONSOLE Console
;
716 GET_INPUT_INFO InputInfo
;
718 DPRINT("SrvReadConsole\n");
720 if (!CsrValidateMessageBuffer(ApiMessage
,
721 (PVOID
*)&ReadConsoleRequest
->Buffer
,
722 ReadConsoleRequest
->BufferSize
,
725 return STATUS_INVALID_PARAMETER
;
728 // if (Request->Data.ReadConsoleRequest.NrCharactersRead * sizeof(WCHAR) > nNumberOfCharsToRead * CharSize)
729 if (ReadConsoleRequest
->NrCharactersRead
> ReadConsoleRequest
->NrCharactersToRead
)
731 return STATUS_INVALID_PARAMETER
;
734 Status
= ConioLockConsole(ProcessData
, ReadConsoleRequest
->InputHandle
, &Console
, GENERIC_READ
);
735 if (!NT_SUCCESS(Status
)) return Status
;
737 ReadConsoleRequest
->NrCharactersRead
= 0;
739 InputInfo
.ProcessData
= ProcessData
; // ConsoleGetPerProcessData(CsrGetClientThread()->Process);
740 InputInfo
.Console
= Console
;
742 Status
= ReadChars(&InputInfo
,
746 ConioUnlockConsole(Console
);
748 if (Status
== STATUS_PENDING
)
749 *ReplyCode
= CsrReplyPending
;
754 CSR_API(SrvFlushConsoleInputBuffer
)
757 PCONSOLE_FLUSHINPUTBUFFER FlushInputBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.FlushInputBufferRequest
;
758 PLIST_ENTRY CurrentEntry
;
759 PCSRSS_CONSOLE Console
;
762 DPRINT("SrvFlushConsoleInputBuffer\n");
764 Status
= ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
765 FlushInputBufferRequest
->InputHandle
,
768 if(!NT_SUCCESS(Status
)) return Status
;
770 /* Discard all entries in the input event queue */
771 while (!IsListEmpty(&Console
->InputEvents
))
773 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
774 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
775 /* Destroy the event */
776 HeapFree(ConSrvHeap
, 0, Input
);
778 ResetEvent(Console
->ActiveEvent
);
780 ConioUnlockConsole(Console
);
782 return STATUS_SUCCESS
;
785 CSR_API(SrvGetConsoleNumberOfInputEvents
)
788 PCONSOLE_GETNUMINPUTEVENTS GetNumInputEventsRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetNumInputEventsRequest
;
789 PCSRSS_CONSOLE Console
;
790 PLIST_ENTRY CurrentInput
;
793 DPRINT("SrvGetConsoleNumberOfInputEvents\n");
795 Status
= ConioLockConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), GetNumInputEventsRequest
->InputHandle
, &Console
, GENERIC_READ
);
796 if (!NT_SUCCESS(Status
)) return Status
;
798 CurrentInput
= Console
->InputEvents
.Flink
;
801 /* If there are any events ... */
802 while (CurrentInput
!= &Console
->InputEvents
)
804 CurrentInput
= CurrentInput
->Flink
;
808 ConioUnlockConsole(Console
);
810 GetNumInputEventsRequest
->NumInputEvents
= NumEvents
;
812 return STATUS_SUCCESS
;