ReactOS  0.4.14-dev-614-gbfd8a84
coninput.c
Go to the documentation of this file.
1 /*
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)
8  */
9 
10 /* INCLUDES *******************************************************************/
11 
12 #include "consrv.h"
13 
14 #define NDEBUG
15 #include <debug.h>
16 
17 /* GLOBALS ********************************************************************/
18 
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))
27 
28 
29 /*
30  * From MSDN:
31  * "The lpMultiByteStr and lpWideCharStr pointers must not be the same.
32  * If they are the same, the function fails, and GetLastError returns
33  * ERROR_INVALID_PARAMETER."
34  */
35 #define ConsoleInputUnicodeToAnsiChar(Console, dChar, sWChar) \
36  ASSERT((ULONG_PTR)dChar != (ULONG_PTR)sWChar); \
37  WideCharToMultiByte((Console)->InputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
38 
39 #define ConsoleInputAnsiToUnicodeChar(Console, dWChar, sChar) \
40  ASSERT((ULONG_PTR)dWChar != (ULONG_PTR)sChar); \
41  MultiByteToWideChar((Console)->InputCodePage, 0, (sChar), 1, (dWChar), 1)
42 
43 
44 typedef struct _GET_INPUT_INFO
45 {
46  PCSR_THREAD CallingThread; // The thread which called the input API.
47  PVOID HandleEntry; // The handle data associated with the wait thread.
48  PCONSOLE_INPUT_BUFFER InputBuffer; // The input buffer corresponding to the handle.
50 
51 
52 /* PRIVATE FUNCTIONS **********************************************************/
53 
54 static VOID
56 {
57  if (InputEvent->EventType == KEY_EVENT)
58  {
59  WCHAR UnicodeChar = InputEvent->Event.KeyEvent.uChar.UnicodeChar;
60  InputEvent->Event.KeyEvent.uChar.UnicodeChar = 0;
62  &InputEvent->Event.KeyEvent.uChar.AsciiChar,
63  &UnicodeChar);
64  }
65 }
66 
67 static VOID
69 {
70  if (InputEvent->EventType == KEY_EVENT)
71  {
72  CHAR AsciiChar = InputEvent->Event.KeyEvent.uChar.AsciiChar;
73  InputEvent->Event.KeyEvent.uChar.AsciiChar = 0;
75  &InputEvent->Event.KeyEvent.uChar.UnicodeChar,
76  &AsciiChar);
77  }
78 }
79 
80 static ULONG
82  PINPUT_RECORD InputEvent,
83  ULONG NumEventsToWrite)
84 {
85  ULONG NumEvents;
86 
87  /*
88  * Loop each event, and for each, check for pause or unpause
89  * and perform adequate behaviour.
90  */
91  for (NumEvents = NumEventsToWrite; NumEvents > 0; --NumEvents)
92  {
93  /* Check for pause or unpause */
94  if (InputEvent->EventType == KEY_EVENT && InputEvent->Event.KeyEvent.bKeyDown)
95  {
96  WORD vk = InputEvent->Event.KeyEvent.wVirtualKeyCode;
97  if (!(Console->PauseFlags & PAUSED_FROM_KEYBOARD))
98  {
99  DWORD cks = InputEvent->Event.KeyEvent.dwControlKeyState;
100  if (Console->InputBuffer.Mode & ENABLE_LINE_INPUT &&
101  (vk == VK_PAUSE ||
102  (vk == 'S' && (cks & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) &&
103  !(cks & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)))))
104  {
106 
107  /* Skip the event */
108  RtlMoveMemory(InputEvent,
109  InputEvent + 1,
110  (NumEvents - 1) * sizeof(INPUT_RECORD));
111  --NumEventsToWrite;
112  continue;
113  }
114  }
115  else
116  {
117  if ((vk < VK_SHIFT || vk > VK_CAPITAL) && vk != VK_LWIN &&
118  vk != VK_RWIN && vk != VK_NUMLOCK && vk != VK_SCROLL)
119  {
121 
122  /* Skip the event */
123  RtlMoveMemory(InputEvent,
124  InputEvent + 1,
125  (NumEvents - 1) * sizeof(INPUT_RECORD));
126  --NumEventsToWrite;
127  continue;
128  }
129  }
130  }
131 
132  /* Go to the next event */
133  ++InputEvent;
134  }
135 
136  return NumEventsToWrite;
137 }
138 
139 static VOID
141 {
142  CsrNotifyWait(&Console->ReadWaitQueue,
143  FALSE,
144  NULL,
145  NULL);
146  if (!IsListEmpty(&Console->ReadWaitQueue))
147  {
148  CsrDereferenceWait(&Console->ReadWaitQueue);
149  }
150 }
151 
152 
156  IN BOOLEAN AppendToEnd,
157  IN PINPUT_RECORD InputRecord,
158  IN ULONG NumEventsToWrite,
159  OUT PULONG NumEventsWritten OPTIONAL);
160 static NTSTATUS
162  PINPUT_RECORD InputRecords, // InputEvent
163  ULONG NumEventsToWrite,
164  PULONG NumEventsWritten,
165  BOOLEAN AppendToEnd)
166 {
168 
169  if (NumEventsWritten) *NumEventsWritten = 0;
170 
171  NumEventsToWrite = PreprocessInput(Console, InputRecords, NumEventsToWrite);
172  if (NumEventsToWrite == 0) return STATUS_SUCCESS;
173 
174  // Status = ConDrvAddInputEvents(Console,
175  // InputRecords,
176  // NumEventsToWrite,
177  // NumEventsWritten,
178  // AppendToEnd);
179 
181  &Console->InputBuffer,
182  AppendToEnd,
183  InputRecords,
184  NumEventsToWrite,
185  NumEventsWritten);
186 
187  // if (NT_SUCCESS(Status))
189 
190  return Status;
191 }
192 
193 /* FIXME: This function can be called by CONDRV, in ConioResizeBuffer() in text.c */
194 NTSTATUS
196  PINPUT_RECORD InputEvent)
197 {
198  ULONG NumEventsWritten;
200  InputEvent,
201  1,
202  &NumEventsWritten,
203  TRUE);
204 }
205 
206 
207 static NTSTATUS
209  IN PCSR_API_MESSAGE ApiMessage,
210  IN CSR_WAIT_FUNCTION WaitFunction OPTIONAL,
211  IN BOOLEAN CreateWaitBlock OPTIONAL)
212 {
213  if (CreateWaitBlock)
214  {
215  PGET_INPUT_INFO CapturedInputInfo;
216  PCONSRV_CONSOLE Console = (PCONSRV_CONSOLE)InputInfo->InputBuffer->Header.Console;
217 
218  CapturedInputInfo = ConsoleAllocHeap(0, sizeof(GET_INPUT_INFO));
219  if (!CapturedInputInfo) return STATUS_NO_MEMORY;
220 
221  RtlMoveMemory(CapturedInputInfo, InputInfo, sizeof(GET_INPUT_INFO));
222 
223  if (!CsrCreateWait(&Console->ReadWaitQueue,
224  WaitFunction,
225  InputInfo->CallingThread,
226  ApiMessage,
227  CapturedInputInfo))
228  {
229  ConsoleFreeHeap(CapturedInputInfo);
230  return STATUS_NO_MEMORY;
231  }
232  }
233 
234  /* Wait for input */
235  return STATUS_PENDING;
236 }
237 
238 static NTSTATUS
239 ReadChars(IN PGET_INPUT_INFO InputInfo,
240  IN PCSR_API_MESSAGE ApiMessage,
241  IN BOOLEAN CreateWaitBlock OPTIONAL);
242 
243 // Wait function CSR_WAIT_FUNCTION
244 static BOOLEAN
245 NTAPI
247  IN PCSR_THREAD WaitThread,
248  IN PCSR_API_MESSAGE WaitApiMessage,
249  IN PVOID WaitContext,
250  IN PVOID WaitArgument1,
251  IN PVOID WaitArgument2,
252  IN ULONG WaitFlags)
253 {
255  PGET_INPUT_INFO InputInfo = (PGET_INPUT_INFO)WaitContext;
256 
257  PVOID InputHandle = WaitArgument2;
258 
259  DPRINT("ReadCharsThread - WaitContext = 0x%p, WaitArgument1 = 0x%p, WaitArgument2 = 0x%p, WaitFlags = %lu\n", WaitContext, WaitArgument1, WaitArgument2, WaitFlags);
260 
261  /*
262  * If we are notified of the process termination via a call
263  * to CsrNotifyWaitBlock triggered by CsrDestroyProcess or
264  * CsrDestroyThread, just return.
265  */
266  if (WaitFlags & CsrProcessTerminating)
267  {
269  goto Quit;
270  }
271 
272  /*
273  * Somebody is closing a handle to this input buffer,
274  * by calling ConSrvCloseHandleEntry.
275  * See whether we are linked to that handle (ie. we
276  * are a waiter for this handle), and if so, return.
277  * Otherwise, ignore the call and continue waiting.
278  */
279  if (InputHandle != NULL)
280  {
281  Status = (InputHandle == InputInfo->HandleEntry ? STATUS_ALERTED
282  : STATUS_PENDING);
283  goto Quit;
284  }
285 
286  /*
287  * If we go there, that means we are notified for some new input.
288  * The console is therefore already locked.
289  */
290  Status = ReadChars(InputInfo, WaitApiMessage, FALSE);
291 
292 Quit:
293  if (Status != STATUS_PENDING)
294  {
295  WaitApiMessage->Status = Status;
296  ConsoleFreeHeap(InputInfo);
297  }
298 
299  return (Status == STATUS_PENDING ? FALSE : TRUE);
300 }
301 
305  IN BOOLEAN Unicode,
306  OUT PVOID Buffer,
307  IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl,
309  IN ULONG NumCharsToRead,
310  OUT PULONG NumCharsRead OPTIONAL);
311 static NTSTATUS
313  IN PCSR_API_MESSAGE ApiMessage,
314  IN BOOLEAN CreateWaitBlock OPTIONAL)
315 {
317  PCONSOLE_READCONSOLE ReadConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleRequest;
318  PCONSOLE_INPUT_BUFFER InputBuffer = InputInfo->InputBuffer;
319  CONSOLE_READCONSOLE_CONTROL ReadControl;
320 
321  UNICODE_STRING ExeName;
322 
323  PVOID Buffer;
324  ULONG NrCharactersRead = 0;
325  ULONG CharSize = (ReadConsoleRequest->Unicode ? sizeof(WCHAR) : sizeof(CHAR));
326 
327  /* Retrieve the executable name, if needed */
328  if (ReadConsoleRequest->InitialNumBytes == 0 &&
329  ReadConsoleRequest->ExeLength <= sizeof(ReadConsoleRequest->StaticBuffer))
330  {
331  ExeName.Length = ExeName.MaximumLength = ReadConsoleRequest->ExeLength;
332  ExeName.Buffer = (PWCHAR)ReadConsoleRequest->StaticBuffer;
333  }
334  else
335  {
336  ExeName.Length = ExeName.MaximumLength = 0;
337  ExeName.Buffer = NULL;
338  }
339 
340  /* Build the ReadControl structure */
341  ReadControl.nLength = sizeof(CONSOLE_READCONSOLE_CONTROL);
342  ReadControl.nInitialChars = ReadConsoleRequest->InitialNumBytes / CharSize;
343  ReadControl.dwCtrlWakeupMask = ReadConsoleRequest->CtrlWakeupMask;
344  ReadControl.dwControlKeyState = ReadConsoleRequest->ControlKeyState;
345 
346  /*
347  * For optimization purposes, Windows (and hence ReactOS, too, for
348  * compatibility reasons) uses a static buffer if no more than eighty
349  * bytes are read. Otherwise a new buffer is used.
350  * The client-side expects that we know this behaviour.
351  */
352  if (ReadConsoleRequest->CaptureBufferSize <= sizeof(ReadConsoleRequest->StaticBuffer))
353  {
354  /*
355  * Adjust the internal pointer, because its old value points to
356  * the static buffer in the original ApiMessage structure.
357  */
358  // ReadConsoleRequest->Buffer = ReadConsoleRequest->StaticBuffer;
359  Buffer = ReadConsoleRequest->StaticBuffer;
360  }
361  else
362  {
363  Buffer = ReadConsoleRequest->Buffer;
364  }
365 
366  DPRINT("Calling ConDrvReadConsole(%wZ)\n", &ExeName);
367  Status = ConDrvReadConsole(InputBuffer->Header.Console,
368  InputBuffer,
369  ReadConsoleRequest->Unicode,
370  Buffer,
371  &ReadControl,
372  &ExeName,
373  ReadConsoleRequest->NumBytes / CharSize, // NrCharactersToRead
374  &NrCharactersRead);
375  DPRINT("ConDrvReadConsole returned (%d ; Status = 0x%08x)\n",
376  NrCharactersRead, Status);
377 
378  // ReadConsoleRequest->ControlKeyState = ReadControl.dwControlKeyState;
379 
380  if (Status == STATUS_PENDING)
381  {
382  /* We haven't completed a read, so start a wait */
383  return WaitBeforeReading(InputInfo,
384  ApiMessage,
386  CreateWaitBlock);
387  }
388  else
389  {
390  /*
391  * We read all what we wanted. Set the number of bytes read and
392  * return the error code we were given.
393  */
394  ReadConsoleRequest->NumBytes = NrCharactersRead * CharSize;
395  ReadConsoleRequest->ControlKeyState = ReadControl.dwControlKeyState;
396 
397  return Status;
398  // return STATUS_SUCCESS;
399  }
400 }
401 
402 static NTSTATUS
404  IN PCSR_API_MESSAGE ApiMessage,
405  IN BOOLEAN CreateWaitBlock OPTIONAL);
406 
407 // Wait function CSR_WAIT_FUNCTION
408 static BOOLEAN
409 NTAPI
411  IN PCSR_THREAD WaitThread,
412  IN PCSR_API_MESSAGE WaitApiMessage,
413  IN PVOID WaitContext,
414  IN PVOID WaitArgument1,
415  IN PVOID WaitArgument2,
416  IN ULONG WaitFlags)
417 {
419  PGET_INPUT_INFO InputInfo = (PGET_INPUT_INFO)WaitContext;
420 
421  PVOID InputHandle = WaitArgument2;
422 
423  DPRINT("ReadInputBufferThread - WaitContext = 0x%p, WaitArgument1 = 0x%p, WaitArgument2 = 0x%p, WaitFlags = %lu\n", WaitContext, WaitArgument1, WaitArgument2, WaitFlags);
424 
425  /*
426  * If we are notified of the process termination via a call
427  * to CsrNotifyWaitBlock triggered by CsrDestroyProcess or
428  * CsrDestroyThread, just return.
429  */
430  if (WaitFlags & CsrProcessTerminating)
431  {
433  goto Quit;
434  }
435 
436  /*
437  * Somebody is closing a handle to this input buffer,
438  * by calling ConSrvCloseHandleEntry.
439  * See whether we are linked to that handle (ie. we
440  * are a waiter for this handle), and if so, return.
441  * Otherwise, ignore the call and continue waiting.
442  */
443  if (InputHandle != NULL)
444  {
445  Status = (InputHandle == InputInfo->HandleEntry ? STATUS_ALERTED
446  : STATUS_PENDING);
447  goto Quit;
448  }
449 
450  /*
451  * If we go there, that means we are notified for some new input.
452  * The console is therefore already locked.
453  */
454  Status = ReadInputBuffer(InputInfo, WaitApiMessage, FALSE);
455 
456 Quit:
457  if (Status != STATUS_PENDING)
458  {
459  WaitApiMessage->Status = Status;
460  ConsoleFreeHeap(InputInfo);
461  }
462 
463  return (Status == STATUS_PENDING ? FALSE : TRUE);
464 }
465 
469  IN BOOLEAN KeepEvents,
470  IN BOOLEAN WaitForMoreEvents,
471  OUT PINPUT_RECORD InputRecord,
472  IN ULONG NumEventsToRead,
473  OUT PULONG NumEventsRead OPTIONAL);
474 static NTSTATUS
476  IN PCSR_API_MESSAGE ApiMessage,
477  IN BOOLEAN CreateWaitBlock OPTIONAL)
478 {
480  PCONSOLE_GETINPUT GetInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetInputRequest;
481  PCONSOLE_INPUT_BUFFER InputBuffer = InputInfo->InputBuffer;
482  ULONG NumEventsRead;
483 
484  PINPUT_RECORD InputRecord;
485 
486  /*
487  * For optimization purposes, Windows (and hence ReactOS, too, for
488  * compatibility reasons) uses a static buffer if no more than five
489  * input records are read. Otherwise a new buffer is used.
490  * The client-side expects that we know this behaviour.
491  */
492  if (GetInputRequest->NumRecords <= sizeof(GetInputRequest->RecordStaticBuffer)/sizeof(INPUT_RECORD))
493  {
494  /*
495  * Adjust the internal pointer, because its old value points to
496  * the static buffer in the original ApiMessage structure.
497  */
498  // GetInputRequest->RecordBufPtr = GetInputRequest->RecordStaticBuffer;
499  InputRecord = GetInputRequest->RecordStaticBuffer;
500  }
501  else
502  {
503  InputRecord = GetInputRequest->RecordBufPtr;
504  }
505 
506  NumEventsRead = 0;
507  Status = ConDrvGetConsoleInput(InputBuffer->Header.Console,
508  InputBuffer,
509  (GetInputRequest->Flags & CONSOLE_READ_KEEPEVENT) != 0,
510  (GetInputRequest->Flags & CONSOLE_READ_CONTINUE ) == 0,
511  InputRecord,
512  GetInputRequest->NumRecords,
513  &NumEventsRead);
514 
515  if (Status == STATUS_PENDING)
516  {
517  /* We haven't completed a read, so start a wait */
518  return WaitBeforeReading(InputInfo,
519  ApiMessage,
521  CreateWaitBlock);
522  }
523  else
524  {
525  /*
526  * We read all what we wanted. Set the number of events read and
527  * return the error code we were given.
528  */
529  GetInputRequest->NumRecords = NumEventsRead;
530 
531  if (NT_SUCCESS(Status))
532  {
533  /* Now translate everything to ANSI */
534  if (!GetInputRequest->Unicode)
535  {
536  for (; NumEventsRead > 0; --NumEventsRead)
537  {
538  ConioInputEventToAnsi(InputBuffer->Header.Console, --InputRecord);
539  }
540  }
541  }
542 
543  return Status;
544  // return STATUS_SUCCESS;
545  }
546 }
547 
548 
549 /* PUBLIC SERVER APIS *********************************************************/
550 
551 CSR_API(SrvReadConsole)
552 {
554  PCONSOLE_READCONSOLE ReadConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadConsoleRequest;
556  PVOID HandleEntry;
558  GET_INPUT_INFO InputInfo;
559 
560  DPRINT("SrvReadConsole\n");
561 
562  /*
563  * For optimization purposes, Windows (and hence ReactOS, too, for
564  * compatibility reasons) uses a static buffer if no more than eighty
565  * bytes are read. Otherwise a new buffer is used.
566  * The client-side expects that we know this behaviour.
567  */
568  if (ReadConsoleRequest->CaptureBufferSize <= sizeof(ReadConsoleRequest->StaticBuffer))
569  {
570  /*
571  * Adjust the internal pointer, because its old value points to
572  * the static buffer in the original ApiMessage structure.
573  */
574  // ReadConsoleRequest->Buffer = ReadConsoleRequest->StaticBuffer;
575  }
576  else
577  {
578  if (!CsrValidateMessageBuffer(ApiMessage,
579  (PVOID*)&ReadConsoleRequest->Buffer,
580  ReadConsoleRequest->CaptureBufferSize,
581  sizeof(BYTE)))
582  {
584  }
585  }
586 
587  if (ReadConsoleRequest->InitialNumBytes > ReadConsoleRequest->NumBytes)
588  {
590  }
591 
592  Status = ConSrvGetInputBufferAndHandleEntry(ProcessData, ReadConsoleRequest->InputHandle, &InputBuffer, &HandleEntry, GENERIC_READ, TRUE);
593  if (!NT_SUCCESS(Status)) return Status;
594 
595  InputInfo.CallingThread = CsrGetClientThread();
596  InputInfo.HandleEntry = HandleEntry;
597  InputInfo.InputBuffer = InputBuffer;
598 
599  Status = ReadChars(&InputInfo, ApiMessage, TRUE);
600 
602 
603  if (Status == STATUS_PENDING) *ReplyCode = CsrReplyPending;
604 
605  return Status;
606 }
607 
608 CSR_API(SrvGetConsoleInput)
609 {
611  PCONSOLE_GETINPUT GetInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetInputRequest;
613  PVOID HandleEntry;
615  GET_INPUT_INFO InputInfo;
616 
617  DPRINT("SrvGetConsoleInput\n");
618 
619  if (GetInputRequest->Flags & ~(CONSOLE_READ_KEEPEVENT | CONSOLE_READ_CONTINUE))
621 
622  /*
623  * For optimization purposes, Windows (and hence ReactOS, too, for
624  * compatibility reasons) uses a static buffer if no more than five
625  * input records are read. Otherwise a new buffer is used.
626  * The client-side expects that we know this behaviour.
627  */
628  if (GetInputRequest->NumRecords <= sizeof(GetInputRequest->RecordStaticBuffer)/sizeof(INPUT_RECORD))
629  {
630  /*
631  * Adjust the internal pointer, because its old value points to
632  * the static buffer in the original ApiMessage structure.
633  */
634  // GetInputRequest->RecordBufPtr = GetInputRequest->RecordStaticBuffer;
635  }
636  else
637  {
638  if (!CsrValidateMessageBuffer(ApiMessage,
639  (PVOID*)&GetInputRequest->RecordBufPtr,
640  GetInputRequest->NumRecords,
641  sizeof(INPUT_RECORD)))
642  {
644  }
645  }
646 
647  Status = ConSrvGetInputBufferAndHandleEntry(ProcessData, GetInputRequest->InputHandle, &InputBuffer, &HandleEntry, GENERIC_READ, TRUE);
648  if (!NT_SUCCESS(Status)) return Status;
649 
650  InputInfo.CallingThread = CsrGetClientThread();
651  InputInfo.HandleEntry = HandleEntry;
652  InputInfo.InputBuffer = InputBuffer;
653 
654  Status = ReadInputBuffer(&InputInfo, ApiMessage, TRUE);
655 
657 
658  if (Status == STATUS_PENDING) *ReplyCode = CsrReplyPending;
659 
660  return Status;
661 }
662 
663 #if 0
667  IN BOOLEAN AppendToEnd,
668  IN PINPUT_RECORD InputRecord,
669  IN ULONG NumEventsToWrite,
670  OUT PULONG NumEventsWritten OPTIONAL);
671 #endif
672 CSR_API(SrvWriteConsoleInput)
673 {
675  PCONSOLE_WRITEINPUT WriteInputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteInputRequest;
677  ULONG NumEventsWritten;
678 
679  PINPUT_RECORD InputRecord;
680 
681  DPRINT("SrvWriteConsoleInput\n");
682 
683  /*
684  * For optimization purposes, Windows (and hence ReactOS, too, for
685  * compatibility reasons) uses a static buffer if no more than five
686  * input records are written. Otherwise a new buffer is used.
687  * The client-side expects that we know this behaviour.
688  */
689  if (WriteInputRequest->NumRecords <= sizeof(WriteInputRequest->RecordStaticBuffer)/sizeof(INPUT_RECORD))
690  {
691  /*
692  * Adjust the internal pointer, because its old value points to
693  * the static buffer in the original ApiMessage structure.
694  */
695  // WriteInputRequest->RecordBufPtr = WriteInputRequest->RecordStaticBuffer;
696  InputRecord = WriteInputRequest->RecordStaticBuffer;
697  }
698  else
699  {
700  if (!CsrValidateMessageBuffer(ApiMessage,
701  (PVOID*)&WriteInputRequest->RecordBufPtr,
702  WriteInputRequest->NumRecords,
703  sizeof(INPUT_RECORD)))
704  {
706  }
707 
708  InputRecord = WriteInputRequest->RecordBufPtr;
709  }
710 
712  WriteInputRequest->InputHandle,
714  if (!NT_SUCCESS(Status))
715  {
716  WriteInputRequest->NumRecords = 0;
717  return Status;
718  }
719 
720  /* First translate everything to UNICODE */
721  if (!WriteInputRequest->Unicode)
722  {
723  ULONG i;
724  for (i = 0; i < WriteInputRequest->NumRecords; ++i)
725  {
726  ConioInputEventToUnicode(InputBuffer->Header.Console, &InputRecord[i]);
727  }
728  }
729 
730  /* Now, add the events */
731  NumEventsWritten = 0;
733  // InputBuffer,
734  InputRecord,
735  WriteInputRequest->NumRecords,
736  &NumEventsWritten,
737  WriteInputRequest->AppendToEnd);
738 
739  // Status = ConDrvWriteConsoleInput(InputBuffer->Header.Console,
740  // InputBuffer,
741  // WriteInputRequest->AppendToEnd,
742  // InputRecord,
743  // WriteInputRequest->NumRecords,
744  // &NumEventsWritten);
745 
746  WriteInputRequest->NumRecords = NumEventsWritten;
747 
749  return Status;
750 }
751 
755 CSR_API(SrvFlushConsoleInputBuffer)
756 {
758  PCONSOLE_FLUSHINPUTBUFFER FlushInputBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.FlushInputBufferRequest;
760 
761  DPRINT("SrvFlushConsoleInputBuffer\n");
762 
764  FlushInputBufferRequest->InputHandle,
766  if (!NT_SUCCESS(Status)) return Status;
767 
769  InputBuffer);
770 
772  return Status;
773 }
774 
778  OUT PULONG NumberOfEvents);
779 CSR_API(SrvGetConsoleNumberOfInputEvents)
780 {
782  PCONSOLE_GETNUMINPUTEVENTS GetNumInputEventsRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetNumInputEventsRequest;
784 
785  DPRINT("SrvGetConsoleNumberOfInputEvents\n");
786 
788  GetNumInputEventsRequest->InputHandle,
790  if (!NT_SUCCESS(Status)) return Status;
791 
793  InputBuffer,
794  &GetNumInputEventsRequest->NumberOfEvents);
795 
797  return Status;
798 }
799 
800 /* EOF */
#define IN
Definition: typedefs.h:38
#define CsrGetClientThread()
Definition: csrsrv.h:77
ULONG NumRecords
Definition: conmsg.h:568
#define TRUE
Definition: types.h:120
VOID ConioUnpause(PCONSRV_CONSOLE Console, UINT Flags)
Definition: console.c:250
WCHAR UnicodeChar
Definition: wincon.h:230
USHORT MaximumLength
Definition: env_spec_w32.h:370
HANDLE InputHandle
Definition: conmsg.h:256
static BOOLEAN NTAPI ReadCharsThread(IN PLIST_ENTRY WaitList, IN PCSR_THREAD WaitThread, IN PCSR_API_MESSAGE WaitApiMessage, IN PVOID WaitContext, IN PVOID WaitArgument1, IN PVOID WaitArgument2, IN ULONG WaitFlags)
Definition: coninput.c:246
PVOID HandleEntry
Definition: coninput.c:47
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_THREAD_IS_TERMINATING
Definition: ntstatus.h:297
WORD vk
Definition: input.c:82
char CHAR
Definition: xmlstorage.h:175
struct _CONSOLE_API_MESSAGE * PCONSOLE_API_MESSAGE
ULONG ControlKeyState
Definition: conmsg.h:268
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI CsrValidateMessageBuffer(IN PCSR_API_MESSAGE ApiMessage, IN PVOID *Buffer, IN ULONG ElementCount, IN ULONG ElementSize)
Definition: api.c:1315
#define PAUSED_FROM_KEYBOARD
Definition: conio_winsrv.h:126
HANDLE InputHandle
Definition: conmsg.h:576
struct _GET_INPUT_INFO GET_INPUT_INFO
#define ConsoleAllocHeap(Flags, Size)
Definition: heap.h:14
DWORD dwControlKeyState
Definition: wincon.h:233
PCSR_THREAD CallingThread
Definition: coninput.c:46
union _KEY_EVENT_RECORD::@3176 uChar
static VOID ConioInputEventToUnicode(PCONSOLE Console, PINPUT_RECORD InputEvent)
Definition: coninput.c:68
#define VK_LWIN
Definition: winuser.h:2210
uint16_t * PWCHAR
Definition: typedefs.h:54
_In_ PVOID Parameter
Definition: ldrtypes.h:241
#define PCONSRV_CONSOLE
Definition: conio.h:27
#define STATUS_ALERTED
Definition: ntstatus.h:80
union _INPUT_RECORD::@3177 Event
INPUT_RECORD RecordStaticBuffer[5]
Definition: conmsg.h:566
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
HANDLE InputHandle
Definition: conmsg.h:565
BOOLEAN NTAPI CsrNotifyWait(IN PLIST_ENTRY WaitList, IN BOOLEAN NotifyAll, IN PVOID WaitArgument1, IN PVOID WaitArgument2)
Definition: wait.c:388
CHAR StaticBuffer[80]
Definition: conmsg.h:260
CHAR InputBuffer[80]
Definition: conmgr.c:33
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:263
WORD wVirtualKeyCode
Definition: wincon.h:227
static VOID ConioInputEventToAnsi(PCONSOLE Console, PINPUT_RECORD InputEvent)
Definition: coninput.c:55
NTSTATUS NTAPI ConDrvFlushConsoleInputBuffer(IN PCONSOLE Console, IN PCONSOLE_INPUT_BUFFER InputBuffer)
Definition: coninput.c:352
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
ULONG CtrlWakeupMask
Definition: conmsg.h:267
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define GENERIC_WRITE
Definition: nt_native.h:90
CSR_API(SrvReadConsole)
Definition: coninput.c:551
#define KEY_EVENT
Definition: wincon.h:122
static NTSTATUS WaitBeforeReading(IN PGET_INPUT_INFO InputInfo, IN PCSR_API_MESSAGE ApiMessage, IN CSR_WAIT_FUNCTION WaitFunction OPTIONAL, IN BOOLEAN CreateWaitBlock OPTIONAL)
Definition: coninput.c:208
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
ULONG CaptureBufferSize
Definition: conmsg.h:264
void DPRINT(...)
Definition: polytest.cpp:61
Definition: bufpool.h:45
#define ConsoleInputUnicodeToAnsiChar(Console, dChar, sWChar)
Definition: coninput.c:35
#define LEFT_ALT_PRESSED
Definition: wincon.h:132
static BOOLEAN NTAPI ReadInputBufferThread(IN PLIST_ENTRY WaitList, IN PCSR_THREAD WaitThread, IN PCSR_API_MESSAGE WaitApiMessage, IN PVOID WaitContext, IN PVOID WaitArgument1, IN PVOID WaitArgument2, IN ULONG WaitFlags)
Definition: coninput.c:410
static ULONG PreprocessInput(PCONSRV_CONSOLE Console, PINPUT_RECORD InputEvent, ULONG NumEventsToWrite)
Definition: coninput.c:81
NTSTATUS NTAPI ConDrvReadConsole(IN PCONSOLE Console, IN PCONSOLE_INPUT_BUFFER InputBuffer, IN BOOLEAN Unicode, OUT PVOID Buffer, IN OUT PCONSOLE_READCONSOLE_CONTROL ReadControl, IN PVOID Parameter OPTIONAL, IN ULONG NumCharsToRead, OUT PULONG NumCharsRead OPTIONAL)
Definition: coninput.c:227
__wchar_t WCHAR
Definition: xmlstorage.h:180
static VOID PostprocessInput(PCONSRV_CONSOLE Console)
Definition: coninput.c:140
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define ConsoleInputAnsiToUnicodeChar(Console, dWChar, sChar)
Definition: coninput.c:39
#define ConsoleGetPerProcessData(Process)
Definition: consrv.h:37
ULONG InitialNumBytes
Definition: conmsg.h:266
KEY_EVENT_RECORD KeyEvent
Definition: wincon.h:263
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
PINPUT_RECORD RecordBufPtr
Definition: conmsg.h:567
#define ENABLE_LINE_INPUT
Definition: wincon.h:76
PINPUT_RECORD RecordBufPtr
Definition: conmsg.h:578
VOID NTAPI CsrDereferenceWait(IN PLIST_ENTRY WaitList)
Definition: wait.c:266
INPUT_RECORD RecordStaticBuffer[5]
Definition: conmsg.h:577
BOOLEAN AppendToEnd
Definition: conmsg.h:581
#define LEFT_CTRL_PRESSED
Definition: wincon.h:134
static NTSTATUS ConioAddInputEvents(PCONSRV_CONSOLE Console, PINPUT_RECORD InputRecords, ULONG NumEventsToWrite, PULONG NumEventsWritten, BOOLEAN AppendToEnd)
Definition: coninput.c:161
unsigned char BYTE
Definition: mem.h:68
#define GENERIC_READ
Definition: compat.h:124
Definition: typedefs.h:117
#define VK_RWIN
Definition: winuser.h:2211
#define CONSOLE_READ_KEEPEVENT
Definition: wincon.h:116
struct _CONSOLE_READCONSOLE_CONTROL CONSOLE_READCONSOLE_CONTROL
Status
Definition: gdiplustypes.h:24
BOOLEAN Unicode
Definition: conmsg.h:580
BOOLEAN Unicode
Definition: conmsg.h:570
#define CONSOLE_READ_CONTINUE
Definition: wincon.h:117
HANDLE InputHandle
Definition: apc.c:9
#define VK_SCROLL
Definition: winuser.h:2255
#define VK_NUMLOCK
Definition: winuser.h:2254
#define ConSrvGetInputBufferAndHandleEntry(ProcessData, Handle, Ptr, Entry, Access, LockConsole)
Definition: coninput.c:22
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
#define VK_CAPITAL
Definition: winuser.h:2181
unsigned int * PULONG
Definition: retypes.h:1
CConsole Console
WORD EventType
Definition: wincon.h:261
#define ConsoleFreeHeap(HeapBase)
Definition: heap.h:15
VOID ConioPause(PCONSRV_CONSOLE Console, UINT Flags)
Definition: console.c:243
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#define VK_PAUSE
Definition: winuser.h:2180
#define OUT
Definition: typedefs.h:39
#define ConSrvGetInputBuffer(ProcessData, Handle, Ptr, Access, LockConsole)
Definition: coninput.c:19
unsigned int ULONG
Definition: retypes.h:1
BOOLEAN(NTAPI * CSR_WAIT_FUNCTION)(IN PLIST_ENTRY WaitList, IN PCSR_THREAD WaitThread, IN PCSR_API_MESSAGE WaitApiMessage, IN PVOID WaitContext, IN PVOID WaitArgument1, IN PVOID WaitArgument2, IN ULONG WaitFlags)
Definition: csrsrv.h:145
PCONSOLE_INPUT_BUFFER InputBuffer
Definition: coninput.c:48
#define RIGHT_CTRL_PRESSED
Definition: wincon.h:133
NTSTATUS NTAPI ConDrvGetConsoleNumberOfInputEvents(IN PCONSOLE Console, IN PCONSOLE_INPUT_BUFFER InputBuffer, OUT PULONG NumberOfEvents)
Definition: coninput.c:377
BOOLEAN NTAPI CsrCreateWait(IN PLIST_ENTRY WaitList, IN CSR_WAIT_FUNCTION WaitFunction, IN PCSR_THREAD CsrWaitThread, IN OUT PCSR_API_MESSAGE WaitApiMessage, IN PVOID WaitContext)
Definition: wait.c:209
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
return STATUS_SUCCESS
Definition: btrfs.c:2938
NTSTATUS NTAPI ConDrvWriteConsoleInput(IN PCONSOLE Console, IN PCONSOLE_INPUT_BUFFER InputBuffer, IN BOOLEAN AppendToEnd, IN PINPUT_RECORD InputRecord, IN ULONG NumEventsToWrite, OUT PULONG NumEventsWritten OPTIONAL)
Definition: coninput.c:325
NTSTATUS NTAPI ConDrvGetConsoleInput(IN PCONSOLE Console, IN PCONSOLE_INPUT_BUFFER InputBuffer, IN BOOLEAN KeepEvents, IN BOOLEAN WaitForMoreEvents, OUT PINPUT_RECORD InputRecord, IN ULONG NumEventsToRead, OUT PULONG NumEventsRead OPTIONAL)
Definition: coninput.c:260
#define RIGHT_ALT_PRESSED
Definition: wincon.h:131
static NTSTATUS ReadInputBuffer(IN PGET_INPUT_INFO InputInfo, IN PCSR_API_MESSAGE ApiMessage, IN BOOLEAN CreateWaitBlock OPTIONAL)
Definition: coninput.c:475
NTSTATUS ConioProcessInputEvent(PCONSRV_CONSOLE Console, PINPUT_RECORD InputEvent)
Definition: coninput.c:195
#define ConSrvReleaseInputBuffer(Buff, IsConsoleLocked)
Definition: coninput.c:25
struct _GET_INPUT_INFO * PGET_INPUT_INFO
static NTSTATUS ReadChars(IN PGET_INPUT_INFO InputInfo, IN PCSR_API_MESSAGE ApiMessage, IN BOOLEAN CreateWaitBlock OPTIONAL)
Definition: coninput.c:312
struct _INPUT_RECORD INPUT_RECORD
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68