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