2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/winsrv/consrv/coninput.c
5 * PURPOSE: Console Input functions
6 * PROGRAMMERS: Jeffrey Morlan
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
10 /* INCLUDES *******************************************************************/
17 /* GLOBALS ********************************************************************/
19 #define ConSrvGetInputBuffer(ProcessData, Handle, Ptr, Access, LockConsole) \
20 ConSrvGetObject((ProcessData), (Handle), (PCONSOLE_IO_OBJECT*)(Ptr), NULL, \
21 (Access), (LockConsole), INPUT_BUFFER)
22 #define ConSrvGetInputBufferAndHandleEntry(ProcessData, Handle, Ptr, Entry, Access, LockConsole) \
23 ConSrvGetObject((ProcessData), (Handle), (PCONSOLE_IO_OBJECT*)(Ptr), (Entry), \
24 (Access), (LockConsole), INPUT_BUFFER)
25 #define ConSrvReleaseInputBuffer(Buff, IsConsoleLocked) \
26 ConSrvReleaseObject(&(Buff)->Header, (IsConsoleLocked))
33 * "The lpMultiByteStr and lpWideCharStr pointers must not be the same.
34 * If they are the same, the function fails, and GetLastError returns
35 * ERROR_INVALID_PARAMETER."
37 #define ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar) \
38 ASSERT((ULONG_PTR)dChar != (ULONG_PTR)sWChar); \
39 WideCharToMultiByte((Console)->InputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
41 #define ConsoleInputAnsiCharToUnicodeChar(Console, dWChar, sChar) \
42 ASSERT((ULONG_PTR)dWChar != (ULONG_PTR)sChar); \
43 MultiByteToWideChar((Console)->InputCodePage, 0, (sChar), 1, (dWChar), 1)
48 typedef struct _GET_INPUT_INFO
50 PCSR_THREAD CallingThread
; // The thread which called the input API.
51 PVOID HandleEntry
; // The handle data associated with the wait thread.
52 PCONSOLE_INPUT_BUFFER InputBuffer
; // The input buffer corresponding to the handle.
53 } GET_INPUT_INFO
, *PGET_INPUT_INFO
;
56 /* PRIVATE FUNCTIONS **********************************************************/
59 ConioInputEventToAnsi(PCONSOLE Console
, PINPUT_RECORD InputEvent
)
61 if (InputEvent
->EventType
== KEY_EVENT
)
63 WCHAR UnicodeChar
= InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
;
64 InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
= 0;
65 ConsoleInputUnicodeCharToAnsiChar(Console
,
66 &InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
,
72 ConioInputEventToUnicode(PCONSOLE Console
, PINPUT_RECORD InputEvent
)
74 if (InputEvent
->EventType
== KEY_EVENT
)
76 CHAR AsciiChar
= InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
;
77 InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
= 0;
78 ConsoleInputAnsiCharToUnicodeChar(Console
,
79 &InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
,
85 PreprocessInput(PCONSRV_CONSOLE Console
,
86 PINPUT_RECORD InputEvent
,
87 ULONG NumEventsToWrite
)
92 * Loop each event, and for each, check for pause or unpause
93 * and perform adequate behaviour.
95 for (NumEvents
= NumEventsToWrite
; NumEvents
> 0; --NumEvents
)
97 /* Check for pause or unpause */
98 if (InputEvent
->EventType
== KEY_EVENT
&& InputEvent
->Event
.KeyEvent
.bKeyDown
)
100 WORD vk
= InputEvent
->Event
.KeyEvent
.wVirtualKeyCode
;
101 if (!(Console
->PauseFlags
& PAUSED_FROM_KEYBOARD
))
103 DWORD cks
= InputEvent
->Event
.KeyEvent
.dwControlKeyState
;
104 if (Console
->InputBuffer
.Mode
& ENABLE_LINE_INPUT
&&
106 (vk
== 'S' && (cks
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
)) &&
107 !(cks
& (LEFT_ALT_PRESSED
| RIGHT_ALT_PRESSED
)))))
109 ConioPause(Console
, PAUSED_FROM_KEYBOARD
);
112 RtlMoveMemory(InputEvent
,
114 (NumEvents
- 1) * sizeof(INPUT_RECORD
));
121 if ((vk
< VK_SHIFT
|| vk
> VK_CAPITAL
) && vk
!= VK_LWIN
&&
122 vk
!= VK_RWIN
&& vk
!= VK_NUMLOCK
&& vk
!= VK_SCROLL
)
124 ConioUnpause(Console
, PAUSED_FROM_KEYBOARD
);
127 RtlMoveMemory(InputEvent
,
129 (NumEvents
- 1) * sizeof(INPUT_RECORD
));
136 /* Go to the next event */
140 return NumEventsToWrite
;
144 PostprocessInput(PCONSRV_CONSOLE Console
)
146 CsrNotifyWait(&Console
->ReadWaitQueue
,
150 if (!IsListEmpty(&Console
->ReadWaitQueue
))
152 CsrDereferenceWait(&Console
->ReadWaitQueue
);
158 ConDrvWriteConsoleInput(IN PCONSOLE Console
,
159 IN PCONSOLE_INPUT_BUFFER InputBuffer
,
160 IN BOOLEAN AppendToEnd
,
161 IN PINPUT_RECORD InputRecord
,
162 IN ULONG NumEventsToWrite
,
163 OUT PULONG NumEventsWritten OPTIONAL
);
165 ConioAddInputEvents(PCONSOLE Console
,
166 PINPUT_RECORD InputRecords
, // InputEvent
167 ULONG NumEventsToWrite
,
168 PULONG NumEventsWritten
,
171 NTSTATUS Status
= STATUS_SUCCESS
;
173 if (NumEventsWritten
) *NumEventsWritten
= 0;
175 NumEventsToWrite
= PreprocessInput(Console
, InputRecords
, NumEventsToWrite
);
176 if (NumEventsToWrite
== 0) return STATUS_SUCCESS
;
178 // Status = ConDrvAddInputEvents(Console,
184 Status
= ConDrvWriteConsoleInput(Console
,
185 &Console
->InputBuffer
,
191 // if (NT_SUCCESS(Status))
192 if (Status
== STATUS_SUCCESS
) PostprocessInput(Console
);
197 /* FIXME: This function can be called by CONDRV, in ConioResizeBuffer() in text.c */
199 ConioProcessInputEvent(PCONSOLE Console
,
200 PINPUT_RECORD InputEvent
)
202 ULONG NumEventsWritten
;
203 return ConioAddInputEvents(Console
,
212 WaitBeforeReading(IN PGET_INPUT_INFO InputInfo
,
213 IN PCSR_API_MESSAGE ApiMessage
,
214 IN CSR_WAIT_FUNCTION WaitFunction OPTIONAL
,
215 IN BOOLEAN CreateWaitBlock OPTIONAL
)
219 PGET_INPUT_INFO CapturedInputInfo
;
221 CapturedInputInfo
= ConsoleAllocHeap(0, sizeof(GET_INPUT_INFO
));
222 if (!CapturedInputInfo
) return STATUS_NO_MEMORY
;
224 RtlMoveMemory(CapturedInputInfo
, InputInfo
, sizeof(GET_INPUT_INFO
));
226 if (!CsrCreateWait(&InputInfo
->InputBuffer
->Header
.Console
->ReadWaitQueue
,
228 InputInfo
->CallingThread
,
232 ConsoleFreeHeap(CapturedInputInfo
);
233 return STATUS_NO_MEMORY
;
238 return STATUS_PENDING
;
242 ReadChars(IN PGET_INPUT_INFO InputInfo
,
243 IN PCSR_API_MESSAGE ApiMessage
,
244 IN BOOLEAN CreateWaitBlock OPTIONAL
);
246 // Wait function CSR_WAIT_FUNCTION
249 ReadCharsThread(IN PLIST_ENTRY WaitList
,
250 IN PCSR_THREAD WaitThread
,
251 IN PCSR_API_MESSAGE WaitApiMessage
,
252 IN PVOID WaitContext
,
253 IN PVOID WaitArgument1
,
254 IN PVOID WaitArgument2
,
258 PGET_INPUT_INFO InputInfo
= (PGET_INPUT_INFO
)WaitContext
;
260 PVOID InputHandle
= WaitArgument2
;
262 DPRINT("ReadCharsThread - WaitContext = 0x%p, WaitArgument1 = 0x%p, WaitArgument2 = 0x%p, WaitFlags = %lu\n", WaitContext
, WaitArgument1
, WaitArgument2
, WaitFlags
);
265 * If we are notified of the process termination via a call
266 * to CsrNotifyWaitBlock triggered by CsrDestroyProcess or
267 * CsrDestroyThread, just return.
269 if (WaitFlags
& CsrProcessTerminating
)
271 Status
= STATUS_THREAD_IS_TERMINATING
;
276 * Somebody is closing a handle to this input buffer,
277 * by calling ConSrvCloseHandleEntry.
278 * See whether we are linked to that handle (ie. we
279 * are a waiter for this handle), and if so, return.
280 * Otherwise, ignore the call and continue waiting.
282 if (InputHandle
!= NULL
)
284 Status
= (InputHandle
== InputInfo
->HandleEntry
? STATUS_ALERTED
290 * If we go there, that means we are notified for some new input.
291 * The console is therefore already locked.
293 Status
= ReadChars(InputInfo
, WaitApiMessage
, FALSE
);
296 if (Status
!= STATUS_PENDING
)
298 WaitApiMessage
->Status
= Status
;
299 ConsoleFreeHeap(InputInfo
);
302 return (Status
== STATUS_PENDING
? FALSE
: TRUE
);
306 ConDrvReadConsole(IN PCONSOLE Console
,
307 IN PCONSOLE_INPUT_BUFFER InputBuffer
,
308 /**/IN PUNICODE_STRING ExeName
/**/OPTIONAL
/**/,/**/
311 IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl
,
312 IN ULONG NumCharsToRead
,
313 OUT PULONG NumCharsRead OPTIONAL
);
315 ReadChars(IN PGET_INPUT_INFO InputInfo
,
316 IN PCSR_API_MESSAGE ApiMessage
,
317 IN BOOLEAN CreateWaitBlock OPTIONAL
)
320 PCONSOLE_READCONSOLE ReadConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ReadConsoleRequest
;
321 PCONSOLE_INPUT_BUFFER InputBuffer
= InputInfo
->InputBuffer
;
322 CONSOLE_READCONSOLE_CONTROL ReadControl
;
324 UNICODE_STRING ExeName
;
327 ULONG NrCharactersRead
= 0;
328 ULONG CharSize
= (ReadConsoleRequest
->Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
330 /* Compute the executable name, if needed */
331 if (ReadConsoleRequest
->InitialNumBytes
== 0 &&
332 ReadConsoleRequest
->ExeLength
<= sizeof(ReadConsoleRequest
->StaticBuffer
))
334 ExeName
.Length
= ExeName
.MaximumLength
= ReadConsoleRequest
->ExeLength
;
335 ExeName
.Buffer
= (PWCHAR
)ReadConsoleRequest
->StaticBuffer
;
339 ExeName
.Length
= ExeName
.MaximumLength
= 0;
340 ExeName
.Buffer
= NULL
;
343 /* Build the ReadControl structure */
344 ReadControl
.nLength
= sizeof(CONSOLE_READCONSOLE_CONTROL
);
345 ReadControl
.nInitialChars
= ReadConsoleRequest
->InitialNumBytes
/ CharSize
;
346 ReadControl
.dwCtrlWakeupMask
= ReadConsoleRequest
->CtrlWakeupMask
;
347 ReadControl
.dwControlKeyState
= ReadConsoleRequest
->ControlKeyState
;
350 * For optimization purposes, Windows (and hence ReactOS, too, for
351 * compatibility reasons) uses a static buffer if no more than eighty
352 * bytes are read. Otherwise a new buffer is used.
353 * The client-side expects that we know this behaviour.
355 if (ReadConsoleRequest
->CaptureBufferSize
<= sizeof(ReadConsoleRequest
->StaticBuffer
))
358 * Adjust the internal pointer, because its old value points to
359 * the static buffer in the original ApiMessage structure.
361 // ReadConsoleRequest->Buffer = ReadConsoleRequest->StaticBuffer;
362 Buffer
= ReadConsoleRequest
->StaticBuffer
;
366 Buffer
= ReadConsoleRequest
->Buffer
;
369 DPRINT1("Calling ConDrvReadConsole(%wZ)\n", &ExeName
);
370 Status
= ConDrvReadConsole(InputBuffer
->Header
.Console
,
373 ReadConsoleRequest
->Unicode
,
376 ReadConsoleRequest
->NumBytes
/ CharSize
, // NrCharactersToRead
378 DPRINT1("ConDrvReadConsole returned (%d ; Status = 0x%08x)\n",
379 NrCharactersRead
, Status
);
381 // ReadConsoleRequest->ControlKeyState = ReadControl.dwControlKeyState;
383 if (Status
== STATUS_PENDING
)
385 /* We haven't completed a read, so start a wait */
386 return WaitBeforeReading(InputInfo
,
394 * We read all what we wanted. Set the number of bytes read and
395 * return the error code we were given.
397 ReadConsoleRequest
->NumBytes
= NrCharactersRead
* CharSize
;
398 ReadConsoleRequest
->ControlKeyState
= ReadControl
.dwControlKeyState
;
401 // return STATUS_SUCCESS;
406 ReadInputBuffer(IN PGET_INPUT_INFO InputInfo
,
407 IN PCSR_API_MESSAGE ApiMessage
,
408 IN BOOLEAN CreateWaitBlock OPTIONAL
);
410 // Wait function CSR_WAIT_FUNCTION
413 ReadInputBufferThread(IN PLIST_ENTRY WaitList
,
414 IN PCSR_THREAD WaitThread
,
415 IN PCSR_API_MESSAGE WaitApiMessage
,
416 IN PVOID WaitContext
,
417 IN PVOID WaitArgument1
,
418 IN PVOID WaitArgument2
,
422 PGET_INPUT_INFO InputInfo
= (PGET_INPUT_INFO
)WaitContext
;
424 PVOID InputHandle
= WaitArgument2
;
426 DPRINT("ReadInputBufferThread - WaitContext = 0x%p, WaitArgument1 = 0x%p, WaitArgument2 = 0x%p, WaitFlags = %lu\n", WaitContext
, WaitArgument1
, WaitArgument2
, WaitFlags
);
429 * If we are notified of the process termination via a call
430 * to CsrNotifyWaitBlock triggered by CsrDestroyProcess or
431 * CsrDestroyThread, just return.
433 if (WaitFlags
& CsrProcessTerminating
)
435 Status
= STATUS_THREAD_IS_TERMINATING
;
440 * Somebody is closing a handle to this input buffer,
441 * by calling ConSrvCloseHandleEntry.
442 * See whether we are linked to that handle (ie. we
443 * are a waiter for this handle), and if so, return.
444 * Otherwise, ignore the call and continue waiting.
446 if (InputHandle
!= NULL
)
448 Status
= (InputHandle
== InputInfo
->HandleEntry
? STATUS_ALERTED
454 * If we go there, that means we are notified for some new input.
455 * The console is therefore already locked.
457 Status
= ReadInputBuffer(InputInfo
, WaitApiMessage
, FALSE
);
460 if (Status
!= STATUS_PENDING
)
462 WaitApiMessage
->Status
= Status
;
463 ConsoleFreeHeap(InputInfo
);
466 return (Status
== STATUS_PENDING
? FALSE
: TRUE
);
470 ConDrvGetConsoleInput(IN PCONSOLE Console
,
471 IN PCONSOLE_INPUT_BUFFER InputBuffer
,
472 IN BOOLEAN KeepEvents
,
473 IN BOOLEAN WaitForMoreEvents
,
474 OUT PINPUT_RECORD InputRecord
,
475 IN ULONG NumEventsToRead
,
476 OUT PULONG NumEventsRead OPTIONAL
);
478 ReadInputBuffer(IN PGET_INPUT_INFO InputInfo
,
479 IN PCSR_API_MESSAGE ApiMessage
,
480 IN BOOLEAN CreateWaitBlock OPTIONAL
)
483 PCONSOLE_GETINPUT GetInputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetInputRequest
;
484 PCONSOLE_INPUT_BUFFER InputBuffer
= InputInfo
->InputBuffer
;
487 PINPUT_RECORD InputRecord
;
490 * For optimization purposes, Windows (and hence ReactOS, too, for
491 * compatibility reasons) uses a static buffer if no more than five
492 * input records are read. Otherwise a new buffer is used.
493 * The client-side expects that we know this behaviour.
495 if (GetInputRequest
->NumRecords
<= sizeof(GetInputRequest
->RecordStaticBuffer
)/sizeof(INPUT_RECORD
))
498 * Adjust the internal pointer, because its old value points to
499 * the static buffer in the original ApiMessage structure.
501 // GetInputRequest->RecordBufPtr = GetInputRequest->RecordStaticBuffer;
502 InputRecord
= GetInputRequest
->RecordStaticBuffer
;
506 InputRecord
= GetInputRequest
->RecordBufPtr
;
510 Status
= ConDrvGetConsoleInput(InputBuffer
->Header
.Console
,
512 (GetInputRequest
->Flags
& CONSOLE_READ_KEEPEVENT
) != 0,
513 (GetInputRequest
->Flags
& CONSOLE_READ_CONTINUE
) == 0,
515 GetInputRequest
->NumRecords
,
518 if (Status
== STATUS_PENDING
)
520 /* We haven't completed a read, so start a wait */
521 return WaitBeforeReading(InputInfo
,
523 ReadInputBufferThread
,
529 * We read all what we wanted. Set the number of events read and
530 * return the error code we were given.
532 GetInputRequest
->NumRecords
= NumEventsRead
;
534 if (NT_SUCCESS(Status
))
536 /* Now translate everything to ANSI */
537 if (!GetInputRequest
->Unicode
)
539 for (; NumEventsRead
> 0; --NumEventsRead
)
541 ConioInputEventToAnsi(InputBuffer
->Header
.Console
, --InputRecord
);
547 // return STATUS_SUCCESS;
552 /* PUBLIC SERVER APIS *********************************************************/
554 CSR_API(SrvReadConsole
)
557 PCONSOLE_READCONSOLE ReadConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ReadConsoleRequest
;
558 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
560 PCONSOLE_INPUT_BUFFER InputBuffer
;
561 GET_INPUT_INFO InputInfo
;
563 DPRINT("SrvReadConsole\n");
566 * For optimization purposes, Windows (and hence ReactOS, too, for
567 * compatibility reasons) uses a static buffer if no more than eighty
568 * bytes are read. Otherwise a new buffer is used.
569 * The client-side expects that we know this behaviour.
571 if (ReadConsoleRequest
->CaptureBufferSize
<= sizeof(ReadConsoleRequest
->StaticBuffer
))
574 * Adjust the internal pointer, because its old value points to
575 * the static buffer in the original ApiMessage structure.
577 // ReadConsoleRequest->Buffer = ReadConsoleRequest->StaticBuffer;
581 if (!CsrValidateMessageBuffer(ApiMessage
,
582 (PVOID
*)&ReadConsoleRequest
->Buffer
,
583 ReadConsoleRequest
->CaptureBufferSize
,
586 return STATUS_INVALID_PARAMETER
;
590 if (ReadConsoleRequest
->InitialNumBytes
> ReadConsoleRequest
->NumBytes
)
592 return STATUS_INVALID_PARAMETER
;
595 Status
= ConSrvGetInputBufferAndHandleEntry(ProcessData
, ReadConsoleRequest
->InputHandle
, &InputBuffer
, &HandleEntry
, GENERIC_READ
, TRUE
);
596 if (!NT_SUCCESS(Status
)) return Status
;
598 InputInfo
.CallingThread
= CsrGetClientThread();
599 InputInfo
.HandleEntry
= HandleEntry
;
600 InputInfo
.InputBuffer
= InputBuffer
;
602 Status
= ReadChars(&InputInfo
, ApiMessage
, TRUE
);
604 ConSrvReleaseInputBuffer(InputBuffer
, TRUE
);
606 if (Status
== STATUS_PENDING
) *ReplyCode
= CsrReplyPending
;
611 CSR_API(SrvGetConsoleInput
)
614 PCONSOLE_GETINPUT GetInputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetInputRequest
;
615 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
617 PCONSOLE_INPUT_BUFFER InputBuffer
;
618 GET_INPUT_INFO InputInfo
;
620 DPRINT("SrvGetConsoleInput\n");
622 if (GetInputRequest
->Flags
& ~(CONSOLE_READ_KEEPEVENT
| CONSOLE_READ_CONTINUE
))
623 return STATUS_INVALID_PARAMETER
;
626 * For optimization purposes, Windows (and hence ReactOS, too, for
627 * compatibility reasons) uses a static buffer if no more than five
628 * input records are read. Otherwise a new buffer is used.
629 * The client-side expects that we know this behaviour.
631 if (GetInputRequest
->NumRecords
<= sizeof(GetInputRequest
->RecordStaticBuffer
)/sizeof(INPUT_RECORD
))
634 * Adjust the internal pointer, because its old value points to
635 * the static buffer in the original ApiMessage structure.
637 // GetInputRequest->RecordBufPtr = GetInputRequest->RecordStaticBuffer;
641 if (!CsrValidateMessageBuffer(ApiMessage
,
642 (PVOID
*)&GetInputRequest
->RecordBufPtr
,
643 GetInputRequest
->NumRecords
,
644 sizeof(INPUT_RECORD
)))
646 return STATUS_INVALID_PARAMETER
;
650 Status
= ConSrvGetInputBufferAndHandleEntry(ProcessData
, GetInputRequest
->InputHandle
, &InputBuffer
, &HandleEntry
, GENERIC_READ
, TRUE
);
651 if (!NT_SUCCESS(Status
)) return Status
;
653 InputInfo
.CallingThread
= CsrGetClientThread();
654 InputInfo
.HandleEntry
= HandleEntry
;
655 InputInfo
.InputBuffer
= InputBuffer
;
657 Status
= ReadInputBuffer(&InputInfo
, ApiMessage
, TRUE
);
659 ConSrvReleaseInputBuffer(InputBuffer
, TRUE
);
661 if (Status
== STATUS_PENDING
) *ReplyCode
= CsrReplyPending
;
668 ConDrvWriteConsoleInput(IN PCONSOLE Console
,
669 IN PCONSOLE_INPUT_BUFFER InputBuffer
,
670 IN BOOLEAN AppendToEnd
,
671 IN PINPUT_RECORD InputRecord
,
672 IN ULONG NumEventsToWrite
,
673 OUT PULONG NumEventsWritten OPTIONAL
);
675 CSR_API(SrvWriteConsoleInput
)
678 PCONSOLE_WRITEINPUT WriteInputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteInputRequest
;
679 PCONSOLE_INPUT_BUFFER InputBuffer
;
680 ULONG NumEventsWritten
;
682 PINPUT_RECORD InputRecord
;
684 DPRINT("SrvWriteConsoleInput\n");
687 * For optimization purposes, Windows (and hence ReactOS, too, for
688 * compatibility reasons) uses a static buffer if no more than five
689 * input records are written. Otherwise a new buffer is used.
690 * The client-side expects that we know this behaviour.
692 if (WriteInputRequest
->NumRecords
<= sizeof(WriteInputRequest
->RecordStaticBuffer
)/sizeof(INPUT_RECORD
))
695 * Adjust the internal pointer, because its old value points to
696 * the static buffer in the original ApiMessage structure.
698 // WriteInputRequest->RecordBufPtr = WriteInputRequest->RecordStaticBuffer;
699 InputRecord
= WriteInputRequest
->RecordStaticBuffer
;
703 if (!CsrValidateMessageBuffer(ApiMessage
,
704 (PVOID
*)&WriteInputRequest
->RecordBufPtr
,
705 WriteInputRequest
->NumRecords
,
706 sizeof(INPUT_RECORD
)))
708 return STATUS_INVALID_PARAMETER
;
711 InputRecord
= WriteInputRequest
->RecordBufPtr
;
714 Status
= ConSrvGetInputBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
715 WriteInputRequest
->InputHandle
,
716 &InputBuffer
, GENERIC_WRITE
, TRUE
);
717 if (!NT_SUCCESS(Status
))
719 WriteInputRequest
->NumRecords
= 0;
723 /* First translate everything to UNICODE */
724 if (!WriteInputRequest
->Unicode
)
727 for (i
= 0; i
< WriteInputRequest
->NumRecords
; ++i
)
729 ConioInputEventToUnicode(InputBuffer
->Header
.Console
, &InputRecord
[i
]);
733 /* Now, add the events */
734 NumEventsWritten
= 0;
735 Status
= ConioAddInputEvents(InputBuffer
->Header
.Console
,
738 WriteInputRequest
->NumRecords
,
740 WriteInputRequest
->AppendToEnd
);
742 // Status = ConDrvWriteConsoleInput(InputBuffer->Header.Console,
744 // WriteInputRequest->AppendToEnd,
746 // WriteInputRequest->NumRecords,
747 // &NumEventsWritten);
749 WriteInputRequest
->NumRecords
= NumEventsWritten
;
751 ConSrvReleaseInputBuffer(InputBuffer
, TRUE
);
756 ConDrvFlushConsoleInputBuffer(IN PCONSOLE Console
,
757 IN PCONSOLE_INPUT_BUFFER InputBuffer
);
758 CSR_API(SrvFlushConsoleInputBuffer
)
761 PCONSOLE_FLUSHINPUTBUFFER FlushInputBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.FlushInputBufferRequest
;
762 PCONSOLE_INPUT_BUFFER InputBuffer
;
764 DPRINT("SrvFlushConsoleInputBuffer\n");
766 Status
= ConSrvGetInputBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
767 FlushInputBufferRequest
->InputHandle
,
768 &InputBuffer
, GENERIC_WRITE
, TRUE
);
769 if (!NT_SUCCESS(Status
)) return Status
;
771 Status
= ConDrvFlushConsoleInputBuffer(InputBuffer
->Header
.Console
,
774 ConSrvReleaseInputBuffer(InputBuffer
, TRUE
);
779 ConDrvGetConsoleNumberOfInputEvents(IN PCONSOLE Console
,
780 IN PCONSOLE_INPUT_BUFFER InputBuffer
,
781 OUT PULONG NumberOfEvents
);
782 CSR_API(SrvGetConsoleNumberOfInputEvents
)
785 PCONSOLE_GETNUMINPUTEVENTS GetNumInputEventsRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetNumInputEventsRequest
;
786 PCONSOLE_INPUT_BUFFER InputBuffer
;
788 DPRINT("SrvGetConsoleNumberOfInputEvents\n");
790 Status
= ConSrvGetInputBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
791 GetNumInputEventsRequest
->InputHandle
,
792 &InputBuffer
, GENERIC_READ
, TRUE
);
793 if (!NT_SUCCESS(Status
)) return Status
;
795 Status
= ConDrvGetConsoleNumberOfInputEvents(InputBuffer
->Header
.Console
,
797 &GetNumInputEventsRequest
->NumberOfEvents
);
799 ConSrvReleaseInputBuffer(InputBuffer
, TRUE
);