1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS system libraries
4  * FILE:            dll/win32/kernel32/client/console/readwrite.c
5  * PURPOSE:         Win32 Console Client read-write functions
6  * PROGRAMMERS:     Emanuele Aliberti
7  *                  Marty Dill
8  *                  Filip Navara (xnavara@volny.cz)
9  *                  Thomas Weidenmueller (w3seek@reactos.org)
10  *                  Jeffrey Morlan
11  */
12 
13 /* INCLUDES *******************************************************************/
14 
15 #include <k32.h>
16 
17 #define NDEBUG
18 #include <debug.h>
19 
20 
21 /* See consrv/include/rect.h */
22 #define ConioRectHeight(Rect) \
23     (((Rect)->Top > (Rect)->Bottom) ? 0 : ((Rect)->Bottom - (Rect)->Top + 1))
24 #define ConioRectWidth(Rect) \
25     (((Rect)->Left > (Rect)->Right) ? 0 : ((Rect)->Right - (Rect)->Left + 1))
26 
27 
28 /* PRIVATE FUNCTIONS **********************************************************/
29 
30 /******************
31  * Read functions *
32  ******************/
33 
34 static
35 BOOL
36 IntReadConsole(IN HANDLE hConsoleInput,
37                OUT PVOID lpBuffer,
38                IN DWORD nNumberOfCharsToRead,
39                OUT LPDWORD lpNumberOfCharsRead,
40                IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL,
41                IN BOOLEAN bUnicode)
42 {
43     BOOL Success;
44     CONSOLE_API_MESSAGE ApiMessage;
45     PCONSOLE_READCONSOLE ReadConsoleRequest = &ApiMessage.Data.ReadConsoleRequest;
46     PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
47     ULONG CharSize, SizeBytes;
48 
49     DPRINT("IntReadConsole\n");
50 
51     /* Set up the data to send to the Console Server */
52     ReadConsoleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
53     ReadConsoleRequest->InputHandle   = hConsoleInput;
54     ReadConsoleRequest->Unicode       = bUnicode;
55 
56     /*
57      * Retrieve the (current) Input EXE name string and length,
58      * not NULL-terminated (always in UNICODE format).
59      */
60     ReadConsoleRequest->ExeLength =
61         GetCurrentExeName((PWCHAR)ReadConsoleRequest->StaticBuffer,
62                           sizeof(ReadConsoleRequest->StaticBuffer));
63 
64     /*** For DEBUGGING purposes ***/
65     {
66         UNICODE_STRING ExeName;
67         ExeName.Length = ExeName.MaximumLength = ReadConsoleRequest->ExeLength;
68         ExeName.Buffer = (PWCHAR)ReadConsoleRequest->StaticBuffer;
69         DPRINT("IntReadConsole(ExeName = %wZ)\n", &ExeName);
70     }
71     /******************************/
72 
73     /* Determine the needed size */
74     CharSize  = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
75     SizeBytes = nNumberOfCharsToRead * CharSize;
76 
77     ReadConsoleRequest->CaptureBufferSize =
78     ReadConsoleRequest->NumBytes          = SizeBytes;
79 
80     /*
81      * For optimization purposes, Windows (and hence ReactOS, too, for
82      * compatibility reasons) uses a static buffer if no more than eighty
83      * bytes are read. Otherwise a new buffer is allocated.
84      * This behaviour is also expected in the server-side.
85      */
86     if (SizeBytes <= sizeof(ReadConsoleRequest->StaticBuffer))
87     {
88         ReadConsoleRequest->Buffer = ReadConsoleRequest->StaticBuffer;
89         // CaptureBuffer = NULL;
90     }
91     else
92     {
93         /* Allocate a Capture Buffer */
94         CaptureBuffer = CsrAllocateCaptureBuffer(1, SizeBytes);
95         if (CaptureBuffer == NULL)
96         {
97             DPRINT1("CsrAllocateCaptureBuffer failed!\n");
98             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
99             return FALSE;
100         }
101 
102         /* Allocate space in the Buffer */
103         CsrAllocateMessagePointer(CaptureBuffer,
104                                   SizeBytes,
105                                   (PVOID*)&ReadConsoleRequest->Buffer);
106     }
107 
108     ReadConsoleRequest->InitialNumBytes = 0;
109     ReadConsoleRequest->CtrlWakeupMask  = 0;
110     ReadConsoleRequest->ControlKeyState = 0;
111 
112     /*
113      * From MSDN (ReadConsole function), the description
114      * for pInputControl says:
115      * "This parameter requires Unicode input by default.
116      * For ANSI mode, set this parameter to NULL."
117      */
118     _SEH2_TRY
119     {
120         if (bUnicode && pInputControl &&
121             pInputControl->nLength == sizeof(CONSOLE_READCONSOLE_CONTROL))
122         {
123             /* Sanity check */
124             if (pInputControl->nInitialChars <= nNumberOfCharsToRead)
125             {
126                 ReadConsoleRequest->InitialNumBytes =
127                     pInputControl->nInitialChars * sizeof(WCHAR); // CharSize
128 
129                 if (pInputControl->nInitialChars != 0)
130                 {
131                     /*
132                      * It is possible here to overwrite the static buffer, in case
133                      * the number of bytes to read was smaller than the static buffer.
134                      * In this case, this means we are continuing a pending read,
135                      * and we do not need in fact the executable name that was
136                      * stored in the static buffer because it was first grabbed when
137                      * we started the first read.
138                      */
139                     RtlCopyMemory(ReadConsoleRequest->Buffer,
140                                   lpBuffer,
141                                   ReadConsoleRequest->InitialNumBytes);
142                 }
143 
144                 ReadConsoleRequest->CtrlWakeupMask = pInputControl->dwCtrlWakeupMask;
145             }
146             else
147             {
148                 // Status = STATUS_INVALID_PARAMETER;
149             }
150         }
151         else
152         {
153             /* We are in a situation where pInputControl has no meaning */
154             pInputControl = NULL;
155         }
156     }
157     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
158     {
159         // HACK
160         if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
161         SetLastError(ERROR_INVALID_ACCESS);
162         _SEH2_YIELD(return FALSE);
163     }
164     _SEH2_END;
165 
166     /* FIXME: Check for sanity */
167 /*
168     if (!NT_SUCCESS(Status) && pInputControl)
169     {
170         // Free CaptureBuffer if needed
171         // Set last error to last status
172         // Return FALSE
173     }
174 */
175 
176     /* Call the server */
177     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
178                         CaptureBuffer,
179                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepReadConsole),
180                         sizeof(*ReadConsoleRequest));
181 
182     /* Check for success */
183     Success = NT_SUCCESS(ApiMessage.Status);
184 
185     /* Retrieve the results */
186     if (Success)
187     {
188         _SEH2_TRY
189         {
190             *lpNumberOfCharsRead = ReadConsoleRequest->NumBytes / CharSize;
191 
192             if (bUnicode && pInputControl)
193                 pInputControl->dwControlKeyState = ReadConsoleRequest->ControlKeyState;
194 
195             RtlCopyMemory(lpBuffer,
196                           ReadConsoleRequest->Buffer,
197                           ReadConsoleRequest->NumBytes);
198         }
199         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
200         {
201             SetLastError(ERROR_INVALID_ACCESS);
202             Success = FALSE;
203         }
204         _SEH2_END;
205     }
206     else
207     {
208         BaseSetLastNTError(ApiMessage.Status);
209     }
210 
211     /* Release the capture buffer if needed */
212     if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
213 
214     if (Success)
215     {
216         /* Yield execution to another thread if Ctrl-C or Ctrl-Break happened */
217         if (ApiMessage.Status == STATUS_ALERTED /* || ApiMessage.Status == STATUS_CANCELLED */)
218         {
219             NtYieldExecution();
220             SetLastError(ERROR_OPERATION_ABORTED); // STATUS_CANCELLED
221         }
222     }
223 
224     /* Return success status */
225     return Success;
226 }
227 
228 
229 static
230 BOOL
231 IntGetConsoleInput(IN HANDLE hConsoleInput,
232                    OUT PINPUT_RECORD lpBuffer,
233                    IN DWORD nLength,
234                    OUT LPDWORD lpNumberOfEventsRead,
235                    IN WORD wFlags,
236                    IN BOOLEAN bUnicode)
237 {
238     BOOL Success;
239     CONSOLE_API_MESSAGE ApiMessage;
240     PCONSOLE_GETINPUT GetInputRequest = &ApiMessage.Data.GetInputRequest;
241     PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
242 
243     if (!IsConsoleHandle(hConsoleInput))
244     {
245         _SEH2_TRY
246         {
247             *lpNumberOfEventsRead = 0;
248             SetLastError(ERROR_INVALID_HANDLE);
249         }
250         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
251         {
252             SetLastError(ERROR_INVALID_ACCESS);
253         }
254         _SEH2_END;
255 
256         return FALSE;
257     }
258 
259     DPRINT("IntGetConsoleInput: %lx %p\n", nLength, lpNumberOfEventsRead);
260 
261     /* Set up the data to send to the Console Server */
262     GetInputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
263     GetInputRequest->InputHandle   = hConsoleInput;
264     GetInputRequest->NumRecords    = nLength;
265     GetInputRequest->Flags         = wFlags;
266     GetInputRequest->Unicode       = bUnicode;
267 
268     /*
269      * For optimization purposes, Windows (and hence ReactOS, too, for
270      * compatibility reasons) uses a static buffer if no more than five
271      * input records are read. Otherwise a new buffer is allocated.
272      * This behaviour is also expected in the server-side.
273      */
274     if (nLength <= sizeof(GetInputRequest->RecordStaticBuffer)/sizeof(INPUT_RECORD))
275     {
276         GetInputRequest->RecordBufPtr = GetInputRequest->RecordStaticBuffer;
277         // CaptureBuffer = NULL;
278     }
279     else
280     {
281         ULONG Size = nLength * sizeof(INPUT_RECORD);
282 
283         /* Allocate a Capture Buffer */
284         CaptureBuffer = CsrAllocateCaptureBuffer(1, Size);
285         if (CaptureBuffer == NULL)
286         {
287             DPRINT1("CsrAllocateCaptureBuffer failed!\n");
288             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
289             return FALSE;
290         }
291 
292         /* Allocate space in the Buffer */
293         CsrAllocateMessagePointer(CaptureBuffer,
294                                   Size,
295                                   (PVOID*)&GetInputRequest->RecordBufPtr);
296     }
297 
298     /* Call the server */
299     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
300                         CaptureBuffer,
301                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetConsoleInput),
302                         sizeof(*GetInputRequest));
303 
304     /* Check for success */
305     Success = NT_SUCCESS(ApiMessage.Status);
306 
307     /* Retrieve the results */
308     _SEH2_TRY
309     {
310         DPRINT("Events read: %lx\n", GetInputRequest->NumRecords);
311         *lpNumberOfEventsRead = GetInputRequest->NumRecords;
312 
313         if (Success)
314         {
315             RtlCopyMemory(lpBuffer,
316                           GetInputRequest->RecordBufPtr,
317                           GetInputRequest->NumRecords * sizeof(INPUT_RECORD));
318         }
319         else
320         {
321             BaseSetLastNTError(ApiMessage.Status);
322         }
323     }
324     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
325     {
326         SetLastError(ERROR_INVALID_ACCESS);
327         Success = FALSE;
328     }
329     _SEH2_END;
330 
331     /* Release the capture buffer if needed */
332     if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
333 
334     /* Return success status */
335     return Success;
336 }
337 
338 
339 static
340 BOOL
341 IntReadConsoleOutput(IN HANDLE hConsoleOutput,
342                      OUT PCHAR_INFO lpBuffer,
343                      IN COORD dwBufferSize,
344                      IN COORD dwBufferCoord,
345                      IN OUT PSMALL_RECT lpReadRegion,
346                      IN BOOLEAN bUnicode)
347 {
348     BOOL Success;
349     CONSOLE_API_MESSAGE ApiMessage;
350     PCONSOLE_READOUTPUT ReadOutputRequest = &ApiMessage.Data.ReadOutputRequest;
351     PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
352 
353     SHORT SizeX, SizeY;
354     ULONG NumCells;
355 
356     /* Set up the data to send to the Console Server */
357     ReadOutputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
358     ReadOutputRequest->OutputHandle  = hConsoleOutput;
359     ReadOutputRequest->Unicode       = bUnicode;
360 
361     /* Update lpReadRegion */
362     _SEH2_TRY
363     {
364         SizeX = min(dwBufferSize.X - dwBufferCoord.X, ConioRectWidth(lpReadRegion));
365         SizeY = min(dwBufferSize.Y - dwBufferCoord.Y, ConioRectHeight(lpReadRegion));
366         if (SizeX <= 0 || SizeY <= 0)
367         {
368             SetLastError(ERROR_INVALID_PARAMETER);
369             _SEH2_YIELD(return FALSE);
370         }
371         lpReadRegion->Right  = lpReadRegion->Left + SizeX - 1;
372         lpReadRegion->Bottom = lpReadRegion->Top  + SizeY - 1;
373 
374         ReadOutputRequest->ReadRegion = *lpReadRegion;
375     }
376     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
377     {
378         SetLastError(ERROR_INVALID_ACCESS);
379         _SEH2_YIELD(return FALSE);
380     }
381     _SEH2_END;
382 
383     NumCells = SizeX * SizeY;
384     DPRINT("IntReadConsoleOutput: (%d x %d)\n", SizeX, SizeY);
385 
386     /*
387      * For optimization purposes, Windows (and hence ReactOS, too, for
388      * compatibility reasons) uses a static buffer if no more than one
389      * cell is read. Otherwise a new buffer is allocated.
390      * This behaviour is also expected in the server-side.
391      */
392     if (NumCells <= 1)
393     {
394         ReadOutputRequest->CharInfo = &ReadOutputRequest->StaticBuffer;
395         // CaptureBuffer = NULL;
396     }
397     else
398     {
399         ULONG Size = NumCells * sizeof(CHAR_INFO);
400 
401         /* Allocate a Capture Buffer */
402         CaptureBuffer = CsrAllocateCaptureBuffer(1, Size);
403         if (CaptureBuffer == NULL)
404         {
405             DPRINT1("CsrAllocateCaptureBuffer failed with size %ld!\n", Size);
406             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
407             return FALSE;
408         }
409 
410         /* Allocate space in the Buffer */
411         CsrAllocateMessagePointer(CaptureBuffer,
412                                   Size,
413                                   (PVOID*)&ReadOutputRequest->CharInfo);
414     }
415 
416     /* Call the server */
417     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
418                         CaptureBuffer,
419                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepReadConsoleOutput),
420                         sizeof(*ReadOutputRequest));
421 
422     /* Check for success */
423     Success = NT_SUCCESS(ApiMessage.Status);
424 
425     /* Retrieve the results */
426     _SEH2_TRY
427     {
428         *lpReadRegion = ReadOutputRequest->ReadRegion;
429 
430         if (Success)
431         {
432 #if 0
433             SHORT x, X;
434 #endif
435             SHORT y, Y;
436 
437             /* Copy into the buffer */
438 
439             SizeX = ConioRectWidth(&ReadOutputRequest->ReadRegion);
440 
441             for (y = 0, Y = ReadOutputRequest->ReadRegion.Top; Y <= ReadOutputRequest->ReadRegion.Bottom; ++y, ++Y)
442             {
443                 RtlCopyMemory(lpBuffer + (y + dwBufferCoord.Y) * dwBufferSize.X + dwBufferCoord.X,
444                               ReadOutputRequest->CharInfo + y * SizeX,
445                               SizeX * sizeof(CHAR_INFO));
446 #if 0
447                 for (x = 0, X = ReadOutputRequest->ReadRegion.Left; X <= ReadOutputRequest->ReadRegion.Right; ++x, ++X)
448                 {
449                     *(lpBuffer + (y + dwBufferCoord.Y) * dwBufferSize.X + (x + dwBufferCoord.X)) =
450                     *(ReadOutputRequest->CharInfo + y * SizeX + x);
451                 }
452 #endif
453             }
454         }
455         else
456         {
457             BaseSetLastNTError(ApiMessage.Status);
458         }
459     }
460     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
461     {
462         SetLastError(ERROR_INVALID_ACCESS);
463         Success = FALSE;
464     }
465     _SEH2_END;
466 
467     /* Release the capture buffer if needed */
468     if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
469 
470     /* Return success status */
471     return Success;
472 }
473 
474 
475 static
476 BOOL
477 IntReadConsoleOutputCode(IN HANDLE hConsoleOutput,
478                          IN CODE_TYPE CodeType,
479                          OUT PVOID pCode,
480                          IN DWORD nLength,
481                          IN COORD dwReadCoord,
482                          OUT LPDWORD lpNumberOfCodesRead)
483 {
484     BOOL Success;
485     CONSOLE_API_MESSAGE ApiMessage;
486     PCONSOLE_READOUTPUTCODE ReadOutputCodeRequest = &ApiMessage.Data.ReadOutputCodeRequest;
487     PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
488     ULONG CodeSize, SizeBytes;
489 
490     DPRINT("IntReadConsoleOutputCode\n");
491 
492     if ( (CodeType != CODE_ASCII    ) &&
493          (CodeType != CODE_UNICODE  ) &&
494          (CodeType != CODE_ATTRIBUTE) )
495     {
496         SetLastError(ERROR_INVALID_PARAMETER);
497         return FALSE;
498     }
499 
500     /* Set up the data to send to the Console Server */
501     ReadOutputCodeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
502     ReadOutputCodeRequest->OutputHandle  = hConsoleOutput;
503     ReadOutputCodeRequest->Coord         = dwReadCoord;
504     ReadOutputCodeRequest->NumCodes      = nLength;
505 
506     /* Determine the needed size */
507     ReadOutputCodeRequest->CodeType = CodeType;
508     switch (CodeType)
509     {
510         case CODE_ASCII:
511             CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar);
512             break;
513 
514         case CODE_UNICODE:
515             CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar);
516             break;
517 
518         case CODE_ATTRIBUTE:
519             CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute);
520             break;
521     }
522     SizeBytes = nLength * CodeSize;
523 
524     /*
525      * For optimization purposes, Windows (and hence ReactOS, too, for
526      * compatibility reasons) uses a static buffer if no more than eighty
527      * bytes are read. Otherwise a new buffer is allocated.
528      * This behaviour is also expected in the server-side.
529      */
530     if (SizeBytes <= sizeof(ReadOutputCodeRequest->CodeStaticBuffer))
531     {
532         ReadOutputCodeRequest->pCode = ReadOutputCodeRequest->CodeStaticBuffer;
533         // CaptureBuffer = NULL;
534     }
535     else
536     {
537         /* Allocate a Capture Buffer */
538         CaptureBuffer = CsrAllocateCaptureBuffer(1, SizeBytes);
539         if (CaptureBuffer == NULL)
540         {
541             DPRINT1("CsrAllocateCaptureBuffer failed!\n");
542             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
543             return FALSE;
544         }
545 
546         /* Allocate space in the Buffer */
547         CsrAllocateMessagePointer(CaptureBuffer,
548                                   SizeBytes,
549                                   (PVOID*)&ReadOutputCodeRequest->pCode);
550     }
551 
552     /* Call the server */
553     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
554                         CaptureBuffer,
555                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepReadConsoleOutputString),
556                         sizeof(*ReadOutputCodeRequest));
557 
558     /* Check for success */
559     Success = NT_SUCCESS(ApiMessage.Status);
560 
561     /* Retrieve the results */
562     _SEH2_TRY
563     {
564         *lpNumberOfCodesRead = ReadOutputCodeRequest->NumCodes;
565 
566         if (Success)
567         {
568             RtlCopyMemory(pCode,
569                           ReadOutputCodeRequest->pCode,
570                           ReadOutputCodeRequest->NumCodes * CodeSize);
571         }
572         else
573         {
574             BaseSetLastNTError(ApiMessage.Status);
575         }
576     }
577     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
578     {
579         SetLastError(ERROR_INVALID_ACCESS);
580         Success = FALSE;
581     }
582     _SEH2_END;
583 
584     /* Release the capture buffer if needed */
585     if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
586 
587     /* Return success status */
588     return Success;
589 }
590 
591 
592 /*******************
593  * Write functions *
594  *******************/
595 
596 static
597 BOOL
598 IntWriteConsole(IN HANDLE hConsoleOutput,
599                 IN PVOID lpBuffer,
600                 IN DWORD nNumberOfCharsToWrite,
601                 OUT LPDWORD lpNumberOfCharsWritten,
602                 LPVOID lpReserved,
603                 IN BOOLEAN bUnicode)
604 {
605     BOOL Success;
606     CONSOLE_API_MESSAGE ApiMessage;
607     PCONSOLE_WRITECONSOLE WriteConsoleRequest = &ApiMessage.Data.WriteConsoleRequest;
608     PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
609     ULONG CharSize, SizeBytes;
610 
611     DPRINT("IntWriteConsole\n");
612 
613     /* Set up the data to send to the Console Server */
614     WriteConsoleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
615     WriteConsoleRequest->OutputHandle  = hConsoleOutput;
616     WriteConsoleRequest->Unicode       = bUnicode;
617 
618     /* Those members are unused by the client, on Windows */
619     WriteConsoleRequest->Reserved1 = 0;
620     // WriteConsoleRequest->Reserved2 = {0};
621 
622     /* Determine the needed size */
623     CharSize  = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
624     SizeBytes = nNumberOfCharsToWrite * CharSize;
625 
626     WriteConsoleRequest->NumBytes = SizeBytes;
627 
628     /*
629      * For optimization purposes, Windows (and hence ReactOS, too, for
630      * compatibility reasons) uses a static buffer if no more than eighty
631      * bytes are written. Otherwise a new buffer is allocated.
632      * This behaviour is also expected in the server-side.
633      */
634     if (SizeBytes <= sizeof(WriteConsoleRequest->StaticBuffer))
635     {
636         WriteConsoleRequest->Buffer = WriteConsoleRequest->StaticBuffer;
637         // CaptureBuffer = NULL;
638         WriteConsoleRequest->UsingStaticBuffer = TRUE;
639 
640         _SEH2_TRY
641         {
642             RtlCopyMemory(WriteConsoleRequest->Buffer,
643                           lpBuffer,
644                           SizeBytes);
645         }
646         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
647         {
648             SetLastError(ERROR_INVALID_ACCESS);
649             _SEH2_YIELD(return FALSE);
650         }
651         _SEH2_END;
652     }
653     else
654     {
655         /* Allocate a Capture Buffer */
656         CaptureBuffer = CsrAllocateCaptureBuffer(1, SizeBytes);
657         if (CaptureBuffer == NULL)
658         {
659             DPRINT1("CsrAllocateCaptureBuffer failed!\n");
660             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
661             return FALSE;
662         }
663 
664         /* Capture the buffer to write */
665         CsrCaptureMessageBuffer(CaptureBuffer,
666                                 (PVOID)lpBuffer,
667                                 SizeBytes,
668                                 (PVOID*)&WriteConsoleRequest->Buffer);
669         WriteConsoleRequest->UsingStaticBuffer = FALSE;
670     }
671 
672     /* Call the server */
673     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
674                         CaptureBuffer,
675                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsole),
676                         sizeof(*WriteConsoleRequest));
677 
678     /* Check for success */
679     Success = NT_SUCCESS(ApiMessage.Status);
680 
681     /* Release the capture buffer if needed */
682     if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
683 
684     /* Retrieve the results. NOTE: lpNumberOfCharsWritten optional since Vista+ */
685     if (Success && lpNumberOfCharsWritten)
686     {
687         _SEH2_TRY
688         {
689             *lpNumberOfCharsWritten = WriteConsoleRequest->NumBytes / CharSize;
690         }
691         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
692         {
693             SetLastError(ERROR_INVALID_ACCESS);
694             Success = FALSE;
695         }
696         _SEH2_END;
697     }
698     else if (!Success)
699     {
700         BaseSetLastNTError(ApiMessage.Status);
701     }
702 
703     /* Return success status */
704     return Success;
705 }
706 
707 
708 static
709 BOOL
710 IntWriteConsoleInput(IN HANDLE hConsoleInput,
711                      IN PINPUT_RECORD lpBuffer,
712                      IN DWORD nLength,
713                      OUT LPDWORD lpNumberOfEventsWritten,
714                      IN BOOLEAN bUnicode,
715                      IN BOOLEAN bAppendToEnd)
716 {
717     BOOL Success;
718     CONSOLE_API_MESSAGE ApiMessage;
719     PCONSOLE_WRITEINPUT WriteInputRequest = &ApiMessage.Data.WriteInputRequest;
720     PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
721 
722     DPRINT("IntWriteConsoleInput: %lx %p\n", nLength, lpNumberOfEventsWritten);
723 
724     /* Set up the data to send to the Console Server */
725     WriteInputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
726     WriteInputRequest->InputHandle   = hConsoleInput;
727     WriteInputRequest->NumRecords    = nLength;
728     WriteInputRequest->Unicode       = bUnicode;
729     WriteInputRequest->AppendToEnd   = bAppendToEnd;
730 
731     /*
732      * For optimization purposes, Windows (and hence ReactOS, too, for
733      * compatibility reasons) uses a static buffer if no more than five
734      * input records are written. Otherwise a new buffer is allocated.
735      * This behaviour is also expected in the server-side.
736      */
737     if (nLength <= sizeof(WriteInputRequest->RecordStaticBuffer)/sizeof(INPUT_RECORD))
738     {
739         WriteInputRequest->RecordBufPtr = WriteInputRequest->RecordStaticBuffer;
740         // CaptureBuffer = NULL;
741 
742         _SEH2_TRY
743         {
744             RtlCopyMemory(WriteInputRequest->RecordBufPtr,
745                           lpBuffer,
746                           nLength * sizeof(INPUT_RECORD));
747         }
748         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
749         {
750             SetLastError(ERROR_INVALID_ACCESS);
751             _SEH2_YIELD(return FALSE);
752         }
753         _SEH2_END;
754     }
755     else
756     {
757         ULONG Size = nLength * sizeof(INPUT_RECORD);
758 
759         /* Allocate a Capture Buffer */
760         CaptureBuffer = CsrAllocateCaptureBuffer(1, Size);
761         if (CaptureBuffer == NULL)
762         {
763             DPRINT1("CsrAllocateCaptureBuffer failed!\n");
764             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
765             return FALSE;
766         }
767 
768         /* Capture the user buffer */
769         CsrCaptureMessageBuffer(CaptureBuffer,
770                                 lpBuffer,
771                                 Size,
772                                 (PVOID*)&WriteInputRequest->RecordBufPtr);
773     }
774 
775     /* Call the server */
776     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
777                         CaptureBuffer,
778                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsoleInput),
779                         sizeof(*WriteInputRequest));
780 
781     /* Check for success */
782     Success = NT_SUCCESS(ApiMessage.Status);
783 
784     /* Release the capture buffer if needed */
785     if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
786 
787     /* Retrieve the results */
788     _SEH2_TRY
789     {
790         DPRINT("Events written: %lx\n", WriteInputRequest->NumRecords);
791         *lpNumberOfEventsWritten = WriteInputRequest->NumRecords;
792 
793         if (!Success)
794             BaseSetLastNTError(ApiMessage.Status);
795     }
796     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
797     {
798         SetLastError(ERROR_INVALID_ACCESS);
799         Success = FALSE;
800     }
801     _SEH2_END;
802 
803     /* Return success status */
804     return Success;
805 }
806 
807 
808 static
809 BOOL
810 IntWriteConsoleOutput(IN HANDLE hConsoleOutput,
811                       IN CONST CHAR_INFO *lpBuffer,
812                       IN COORD dwBufferSize,
813                       IN COORD dwBufferCoord,
814                       IN OUT PSMALL_RECT lpWriteRegion,
815                       IN BOOLEAN bUnicode)
816 {
817     BOOL Success;
818     CONSOLE_API_MESSAGE ApiMessage;
819     PCONSOLE_WRITEOUTPUT WriteOutputRequest = &ApiMessage.Data.WriteOutputRequest;
820     PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
821 
822     SHORT SizeX, SizeY;
823     ULONG NumCells;
824 
825     /* Set up the data to send to the Console Server */
826     WriteOutputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
827     WriteOutputRequest->OutputHandle  = hConsoleOutput;
828     WriteOutputRequest->Unicode       = bUnicode;
829 
830     /* Update lpWriteRegion */
831     _SEH2_TRY
832     {
833         SizeX = min(dwBufferSize.X - dwBufferCoord.X, ConioRectWidth(lpWriteRegion));
834         SizeY = min(dwBufferSize.Y - dwBufferCoord.Y, ConioRectHeight(lpWriteRegion));
835         if (SizeX <= 0 || SizeY <= 0)
836         {
837             SetLastError(ERROR_INVALID_PARAMETER);
838             _SEH2_YIELD(return FALSE);
839         }
840         lpWriteRegion->Right  = lpWriteRegion->Left + SizeX - 1;
841         lpWriteRegion->Bottom = lpWriteRegion->Top  + SizeY - 1;
842 
843         WriteOutputRequest->WriteRegion = *lpWriteRegion;
844     }
845     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
846     {
847         SetLastError(ERROR_INVALID_ACCESS);
848         _SEH2_YIELD(return FALSE);
849     }
850     _SEH2_END;
851 
852     NumCells = SizeX * SizeY;
853     DPRINT("IntWriteConsoleOutput: (%d x %d)\n", SizeX, SizeY);
854 
855     /*
856      * For optimization purposes, Windows (and hence ReactOS, too, for
857      * compatibility reasons) uses a static buffer if no more than one
858      * cell is written. Otherwise a new buffer is allocated.
859      * This behaviour is also expected in the server-side.
860      */
861     if (NumCells <= 1)
862     {
863         WriteOutputRequest->CharInfo = &WriteOutputRequest->StaticBuffer;
864         // CaptureBuffer = NULL;
865         WriteOutputRequest->UseVirtualMemory = FALSE;
866     }
867     else
868     {
869         ULONG Size = NumCells * sizeof(CHAR_INFO);
870 
871         /* Allocate a Capture Buffer */
872         CaptureBuffer = CsrAllocateCaptureBuffer(1, Size);
873         if (CaptureBuffer)
874         {
875             /* Allocate space in the Buffer */
876             CsrAllocateMessagePointer(CaptureBuffer,
877                                       Size,
878                                       (PVOID*)&WriteOutputRequest->CharInfo);
879             WriteOutputRequest->UseVirtualMemory = FALSE;
880         }
881         else
882         {
883             /*
884              * CsrAllocateCaptureBuffer failed because we tried to allocate
885              * a too large (>= 64 kB, size of the CSR heap) data buffer.
886              * To circumvent this, Windows uses a trick (that we reproduce for
887              * compatibility reasons): we allocate a heap buffer in the process'
888              * memory, and CSR will read it via NtReadVirtualMemory.
889              */
890             DPRINT1("CsrAllocateCaptureBuffer failed with size %ld, let's use local heap buffer...\n", Size);
891 
892             WriteOutputRequest->CharInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, Size);
893             WriteOutputRequest->UseVirtualMemory = TRUE;
894 
895             /* Bail out if we still cannot allocate memory */
896             if (WriteOutputRequest->CharInfo == NULL)
897             {
898                 DPRINT1("Failed to allocate heap buffer with size %ld!\n", Size);
899                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
900                 return FALSE;
901             }
902         }
903     }
904 
905     /* Capture the user buffer contents */
906     _SEH2_TRY
907     {
908 #if 0
909         SHORT x, X;
910 #endif
911         SHORT y, Y;
912 
913         /* Copy into the buffer */
914 
915         SizeX = ConioRectWidth(&WriteOutputRequest->WriteRegion);
916 
917         for (y = 0, Y = WriteOutputRequest->WriteRegion.Top; Y <= WriteOutputRequest->WriteRegion.Bottom; ++y, ++Y)
918         {
919             RtlCopyMemory(WriteOutputRequest->CharInfo + y * SizeX,
920                           lpBuffer + (y + dwBufferCoord.Y) * dwBufferSize.X + dwBufferCoord.X,
921                           SizeX * sizeof(CHAR_INFO));
922 #if 0
923             for (x = 0, X = WriteOutputRequest->WriteRegion.Left; X <= WriteOutputRequest->WriteRegion.Right; ++x, ++X)
924             {
925                 *(WriteOutputRequest->CharInfo + y * SizeX + x) =
926                 *(lpBuffer + (y + dwBufferCoord.Y) * dwBufferSize.X + (x + dwBufferCoord.X));
927             }
928 #endif
929         }
930     }
931     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
932     {
933         SetLastError(ERROR_INVALID_ACCESS);
934         _SEH2_YIELD(return FALSE);
935     }
936     _SEH2_END;
937 
938     /* Call the server */
939     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
940                         CaptureBuffer,
941                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsoleOutput),
942                         sizeof(*WriteOutputRequest));
943 
944     /* Check for success */
945     Success = NT_SUCCESS(ApiMessage.Status);
946 
947     /* Release the capture buffer if needed */
948     if (CaptureBuffer)
949     {
950         CsrFreeCaptureBuffer(CaptureBuffer);
951     }
952     else
953     {
954         /* If we used a heap buffer, free it */
955         if (WriteOutputRequest->UseVirtualMemory)
956             RtlFreeHeap(RtlGetProcessHeap(), 0, WriteOutputRequest->CharInfo);
957     }
958 
959     /* Retrieve the results */
960     _SEH2_TRY
961     {
962         *lpWriteRegion = WriteOutputRequest->WriteRegion;
963 
964         if (!Success)
965             BaseSetLastNTError(ApiMessage.Status);
966     }
967     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
968     {
969         SetLastError(ERROR_INVALID_ACCESS);
970         Success = FALSE;
971     }
972     _SEH2_END;
973 
974     /* Return success status */
975     return Success;
976 }
977 
978 
979 static
980 BOOL
981 IntWriteConsoleOutputCode(IN HANDLE hConsoleOutput,
982                           IN CODE_TYPE CodeType,
983                           IN CONST VOID *pCode,
984                           IN DWORD nLength,
985                           IN COORD dwWriteCoord,
986                           OUT LPDWORD lpNumberOfCodesWritten)
987 {
988     BOOL Success;
989     CONSOLE_API_MESSAGE ApiMessage;
990     PCONSOLE_WRITEOUTPUTCODE WriteOutputCodeRequest = &ApiMessage.Data.WriteOutputCodeRequest;
991     PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
992     ULONG CodeSize, SizeBytes;
993 
994     if ( (CodeType != CODE_ASCII    ) &&
995          (CodeType != CODE_UNICODE  ) &&
996          (CodeType != CODE_ATTRIBUTE) )
997     {
998         SetLastError(ERROR_INVALID_PARAMETER);
999         return FALSE;
1000     }
1001 
1002     DPRINT("IntWriteConsoleOutputCode\n");
1003 
1004     /* Set up the data to send to the Console Server */
1005     WriteOutputCodeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1006     WriteOutputCodeRequest->OutputHandle  = hConsoleOutput;
1007     WriteOutputCodeRequest->Coord         = dwWriteCoord;
1008     WriteOutputCodeRequest->NumCodes      = nLength;
1009 
1010     /* Determine the needed size */
1011     WriteOutputCodeRequest->CodeType = CodeType;
1012     switch (CodeType)
1013     {
1014         case CODE_ASCII:
1015             CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar);
1016             break;
1017 
1018         case CODE_UNICODE:
1019             CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar);
1020             break;
1021 
1022         case CODE_ATTRIBUTE:
1023             CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute);
1024             break;
1025     }
1026     SizeBytes = nLength * CodeSize;
1027 
1028     /*
1029      * For optimization purposes, Windows (and hence ReactOS, too, for
1030      * compatibility reasons) uses a static buffer if no more than eighty
1031      * bytes are written. Otherwise a new buffer is allocated.
1032      * This behaviour is also expected in the server-side.
1033      */
1034     if (SizeBytes <= sizeof(WriteOutputCodeRequest->CodeStaticBuffer))
1035     {
1036         WriteOutputCodeRequest->pCode = WriteOutputCodeRequest->CodeStaticBuffer;
1037         // CaptureBuffer = NULL;
1038 
1039         _SEH2_TRY
1040         {
1041             RtlCopyMemory(WriteOutputCodeRequest->pCode,
1042                           pCode,
1043                           SizeBytes);
1044         }
1045         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1046         {
1047             SetLastError(ERROR_INVALID_ACCESS);
1048             _SEH2_YIELD(return FALSE);
1049         }
1050         _SEH2_END;
1051     }
1052     else
1053     {
1054         /* Allocate a Capture Buffer */
1055         CaptureBuffer = CsrAllocateCaptureBuffer(1, SizeBytes);
1056         if (CaptureBuffer == NULL)
1057         {
1058             DPRINT1("CsrAllocateCaptureBuffer failed!\n");
1059             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1060             return FALSE;
1061         }
1062 
1063         /* Capture the buffer to write */
1064         CsrCaptureMessageBuffer(CaptureBuffer,
1065                                 (PVOID)pCode,
1066                                 SizeBytes,
1067                                 (PVOID*)&WriteOutputCodeRequest->pCode);
1068     }
1069 
1070     /* Call the server */
1071     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1072                         CaptureBuffer,
1073                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsoleOutputString),
1074                         sizeof(*WriteOutputCodeRequest));
1075 
1076     /* Check for success */
1077     Success = NT_SUCCESS(ApiMessage.Status);
1078 
1079     /* Release the capture buffer if needed */
1080     if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
1081 
1082     /* Retrieve the results */
1083     _SEH2_TRY
1084     {
1085         *lpNumberOfCodesWritten = WriteOutputCodeRequest->NumCodes;
1086 
1087         if (!Success)
1088             BaseSetLastNTError(ApiMessage.Status);
1089     }
1090     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1091     {
1092         SetLastError(ERROR_INVALID_ACCESS);
1093         Success = FALSE;
1094     }
1095     _SEH2_END;
1096 
1097     /* Return success status */
1098     return Success;
1099 }
1100 
1101 
1102 static
1103 BOOL
1104 IntFillConsoleOutputCode(IN HANDLE hConsoleOutput,
1105                          IN CODE_TYPE CodeType,
1106                          IN CODE_ELEMENT Code,
1107                          IN DWORD nLength,
1108                          IN COORD dwWriteCoord,
1109                          OUT LPDWORD lpNumberOfCodesWritten)
1110 {
1111     BOOL Success;
1112     CONSOLE_API_MESSAGE ApiMessage;
1113     PCONSOLE_FILLOUTPUTCODE FillOutputRequest = &ApiMessage.Data.FillOutputRequest;
1114 
1115     DPRINT("IntFillConsoleOutputCode\n");
1116 
1117     if ( (CodeType != CODE_ASCII    ) &&
1118          (CodeType != CODE_UNICODE  ) &&
1119          (CodeType != CODE_ATTRIBUTE) )
1120     {
1121         SetLastError(ERROR_INVALID_PARAMETER);
1122         return FALSE;
1123     }
1124 
1125     /* Set up the data to send to the Console Server */
1126     FillOutputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1127     FillOutputRequest->OutputHandle  = hConsoleOutput;
1128     FillOutputRequest->WriteCoord    = dwWriteCoord;
1129     FillOutputRequest->CodeType = CodeType;
1130     FillOutputRequest->Code     = Code;
1131     FillOutputRequest->NumCodes = nLength;
1132 
1133     /* Call the server */
1134     CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1135                         NULL,
1136                         CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepFillConsoleOutput),
1137                         sizeof(*FillOutputRequest));
1138 
1139     /* Check for success */
1140     Success = NT_SUCCESS(ApiMessage.Status);
1141 
1142     /* Retrieve the results */
1143     _SEH2_TRY
1144     {
1145         *lpNumberOfCodesWritten = FillOutputRequest->NumCodes;
1146 
1147         if (!Success)
1148             BaseSetLastNTError(ApiMessage.Status);
1149     }
1150     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1151     {
1152         SetLastError(ERROR_INVALID_ACCESS);
1153         Success = FALSE;
1154     }
1155     _SEH2_END;
1156 
1157     /* Return success status */
1158     return Success;
1159 }
1160 
1161 
1162 /* FUNCTIONS ******************************************************************/
1163 
1164 /******************
1165  * Read functions *
1166  ******************/
1167 
1168 /*
1169  * @implemented
1170  */
1171 BOOL
1172 WINAPI
1173 DECLSPEC_HOTPATCH
1174 ReadConsoleW(IN HANDLE hConsoleInput,
1175              OUT LPVOID lpBuffer,
1176              IN DWORD nNumberOfCharsToRead,
1177              OUT LPDWORD lpNumberOfCharsRead,
1178              IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL)
1179 {
1180     return IntReadConsole(hConsoleInput,
1181                           lpBuffer,
1182                           nNumberOfCharsToRead,
1183                           lpNumberOfCharsRead,
1184                           pInputControl,
1185                           TRUE);
1186 }
1187 
1188 
1189 /*
1190  * @implemented
1191  */
1192 BOOL
1193 WINAPI
1194 DECLSPEC_HOTPATCH
1195 ReadConsoleA(IN HANDLE hConsoleInput,
1196              OUT LPVOID lpBuffer,
1197              IN DWORD nNumberOfCharsToRead,
1198              OUT LPDWORD lpNumberOfCharsRead,
1199              IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL)
1200 {
1201     return IntReadConsole(hConsoleInput,
1202                           lpBuffer,
1203                           nNumberOfCharsToRead,
1204                           lpNumberOfCharsRead,
1205                           NULL,
1206                           FALSE);
1207 }
1208 
1209 
1210 /*
1211  * @implemented
1212  */
1213 BOOL
1214 WINAPI
1215 DECLSPEC_HOTPATCH
1216 PeekConsoleInputW(IN HANDLE hConsoleInput,
1217                   OUT PINPUT_RECORD lpBuffer,
1218                   IN DWORD nLength,
1219                   OUT LPDWORD lpNumberOfEventsRead)
1220 {
1221     return IntGetConsoleInput(hConsoleInput,
1222                               lpBuffer,
1223                               nLength,
1224                               lpNumberOfEventsRead,
1225                               CONSOLE_READ_KEEPEVENT | CONSOLE_READ_CONTINUE,
1226                               TRUE);
1227 }
1228 
1229 
1230 /*
1231  * @implemented
1232  */
1233 BOOL
1234 WINAPI
1235 DECLSPEC_HOTPATCH
1236 PeekConsoleInputA(IN HANDLE hConsoleInput,
1237                   OUT PINPUT_RECORD lpBuffer,
1238                   IN DWORD nLength,
1239                   OUT LPDWORD lpNumberOfEventsRead)
1240 {
1241     return IntGetConsoleInput(hConsoleInput,
1242                               lpBuffer,
1243                               nLength,
1244                               lpNumberOfEventsRead,
1245                               CONSOLE_READ_KEEPEVENT | CONSOLE_READ_CONTINUE,
1246                               FALSE);
1247 }
1248 
1249 
1250 /*
1251  * @implemented
1252  */
1253 BOOL
1254 WINAPI
1255 DECLSPEC_HOTPATCH
1256 ReadConsoleInputW(IN HANDLE hConsoleInput,
1257                   OUT PINPUT_RECORD lpBuffer,
1258                   IN DWORD nLength,
1259                   OUT LPDWORD lpNumberOfEventsRead)
1260 {
1261     return IntGetConsoleInput(hConsoleInput,
1262                               lpBuffer,
1263                               nLength,
1264                               lpNumberOfEventsRead,
1265                               0,
1266                               TRUE);
1267 }
1268 
1269 
1270 /*
1271  * @implemented
1272  */
1273 BOOL
1274 WINAPI
1275 DECLSPEC_HOTPATCH
1276 ReadConsoleInputA(IN HANDLE hConsoleInput,
1277                   OUT PINPUT_RECORD lpBuffer,
1278                   IN DWORD nLength,
1279                   OUT LPDWORD lpNumberOfEventsRead)
1280 {
1281     return IntGetConsoleInput(hConsoleInput,
1282                               lpBuffer,
1283                               nLength,
1284                               lpNumberOfEventsRead,
1285                               0,
1286                               FALSE);
1287 }
1288 
1289 
1290 /*
1291  * @implemented
1292  */
1293 BOOL
1294 WINAPI
1295 DECLSPEC_HOTPATCH
1296 ReadConsoleInputExW(IN HANDLE hConsoleInput,
1297                     OUT PINPUT_RECORD lpBuffer,
1298                     IN DWORD nLength,
1299                     OUT LPDWORD lpNumberOfEventsRead,
1300                     IN WORD wFlags)
1301 {
1302     return IntGetConsoleInput(hConsoleInput,
1303                               lpBuffer,
1304                               nLength,
1305                               lpNumberOfEventsRead,
1306                               wFlags,
1307                               TRUE);
1308 }
1309 
1310 
1311 /*
1312  * @implemented
1313  */
1314 BOOL
1315 WINAPI
1316 DECLSPEC_HOTPATCH
1317 ReadConsoleInputExA(IN HANDLE hConsoleInput,
1318                     OUT PINPUT_RECORD lpBuffer,
1319                     IN DWORD nLength,
1320                     OUT LPDWORD lpNumberOfEventsRead,
1321                     IN WORD wFlags)
1322 {
1323     return IntGetConsoleInput(hConsoleInput,
1324                               lpBuffer,
1325                               nLength,
1326                               lpNumberOfEventsRead,
1327                               wFlags,
1328                               FALSE);
1329 }
1330 
1331 
1332 /*
1333  * @implemented
1334  */
1335 BOOL
1336 WINAPI
1337 DECLSPEC_HOTPATCH
1338 ReadConsoleOutputW(IN HANDLE hConsoleOutput,
1339                    OUT PCHAR_INFO lpBuffer,
1340                    IN COORD dwBufferSize,
1341                    IN COORD dwBufferCoord,
1342                    IN OUT PSMALL_RECT lpReadRegion)
1343 {
1344     return IntReadConsoleOutput(hConsoleOutput,
1345                                 lpBuffer,
1346                                 dwBufferSize,
1347                                 dwBufferCoord,
1348                                 lpReadRegion,
1349                                 TRUE);
1350 }
1351 
1352 
1353 /*
1354  * @implemented
1355  */
1356 BOOL
1357 WINAPI
1358 DECLSPEC_HOTPATCH
1359 ReadConsoleOutputA(IN HANDLE hConsoleOutput,
1360                    OUT PCHAR_INFO lpBuffer,
1361                    IN COORD dwBufferSize,
1362                    IN COORD dwBufferCoord,
1363                    IN OUT PSMALL_RECT lpReadRegion)
1364 {
1365     return IntReadConsoleOutput(hConsoleOutput,
1366                                 lpBuffer,
1367                                 dwBufferSize,
1368                                 dwBufferCoord,
1369                                 lpReadRegion,
1370                                 FALSE);
1371 }
1372 
1373 
1374 /*
1375  * @implemented
1376  */
1377 BOOL
1378 WINAPI
1379 DECLSPEC_HOTPATCH
1380 ReadConsoleOutputCharacterW(IN HANDLE hConsoleOutput,
1381                             OUT LPWSTR lpCharacter,
1382                             IN DWORD nLength,
1383                             IN COORD dwReadCoord,
1384                             OUT LPDWORD lpNumberOfCharsRead)
1385 {
1386     return IntReadConsoleOutputCode(hConsoleOutput,
1387                                     CODE_UNICODE,
1388                                     lpCharacter,
1389                                     nLength,
1390                                     dwReadCoord,
1391                                     lpNumberOfCharsRead);
1392 }
1393 
1394 
1395 /*
1396  * @implemented
1397  */
1398 BOOL
1399 WINAPI
1400 DECLSPEC_HOTPATCH
1401 ReadConsoleOutputCharacterA(IN HANDLE hConsoleOutput,
1402                             OUT LPSTR lpCharacter,
1403                             IN DWORD nLength,
1404                             IN COORD dwReadCoord,
1405                             OUT LPDWORD lpNumberOfCharsRead)
1406 {
1407     return IntReadConsoleOutputCode(hConsoleOutput,
1408                                     CODE_ASCII,
1409                                     lpCharacter,
1410                                     nLength,
1411                                     dwReadCoord,
1412                                     lpNumberOfCharsRead);
1413 }
1414 
1415 
1416 /*
1417  * @implemented
1418  */
1419 BOOL
1420 WINAPI
1421 DECLSPEC_HOTPATCH
1422 ReadConsoleOutputAttribute(IN HANDLE hConsoleOutput,
1423                            OUT LPWORD lpAttribute,
1424                            IN DWORD nLength,
1425                            IN COORD dwReadCoord,
1426                            OUT LPDWORD lpNumberOfAttrsRead)
1427 {
1428     return IntReadConsoleOutputCode(hConsoleOutput,
1429                                     CODE_ATTRIBUTE,
1430                                     lpAttribute,
1431                                     nLength,
1432                                     dwReadCoord,
1433                                     lpNumberOfAttrsRead);
1434 }
1435 
1436 
1437 /*******************
1438  * Write functions *
1439  *******************/
1440 
1441 /*
1442  * @implemented
1443  */
1444 BOOL
1445 WINAPI
1446 DECLSPEC_HOTPATCH
1447 WriteConsoleW(IN HANDLE hConsoleOutput,
1448               IN CONST VOID *lpBuffer,
1449               IN DWORD nNumberOfCharsToWrite,
1450               OUT LPDWORD lpNumberOfCharsWritten,
1451               LPVOID lpReserved)
1452 {
1453     return IntWriteConsole(hConsoleOutput,
1454                            (PVOID)lpBuffer,
1455                            nNumberOfCharsToWrite,
1456                            lpNumberOfCharsWritten,
1457                            lpReserved,
1458                            TRUE);
1459 }
1460 
1461 
1462 /*
1463  * @implemented
1464  */
1465 BOOL
1466 WINAPI
1467 DECLSPEC_HOTPATCH
1468 WriteConsoleA(IN HANDLE hConsoleOutput,
1469               IN CONST VOID *lpBuffer,
1470               IN DWORD nNumberOfCharsToWrite,
1471               OUT LPDWORD lpNumberOfCharsWritten,
1472               LPVOID lpReserved)
1473 {
1474     return IntWriteConsole(hConsoleOutput,
1475                            (PVOID)lpBuffer,
1476                            nNumberOfCharsToWrite,
1477                            lpNumberOfCharsWritten,
1478                            lpReserved,
1479                            FALSE);
1480 }
1481 
1482 
1483 /*
1484  * @implemented
1485  */
1486 BOOL
1487 WINAPI
1488 DECLSPEC_HOTPATCH
1489 WriteConsoleInputW(IN HANDLE hConsoleInput,
1490                    IN CONST INPUT_RECORD *lpBuffer,
1491                    IN DWORD nLength,
1492                    OUT LPDWORD lpNumberOfEventsWritten)
1493 {
1494     return IntWriteConsoleInput(hConsoleInput,
1495                                 (PINPUT_RECORD)lpBuffer,
1496                                 nLength,
1497                                 lpNumberOfEventsWritten,
1498                                 TRUE,
1499                                 TRUE);
1500 }
1501 
1502 
1503 /*
1504  * @implemented
1505  */
1506 BOOL
1507 WINAPI
1508 DECLSPEC_HOTPATCH
1509 WriteConsoleInputA(IN HANDLE hConsoleInput,
1510                    IN CONST INPUT_RECORD *lpBuffer,
1511                    IN DWORD nLength,
1512                    OUT LPDWORD lpNumberOfEventsWritten)
1513 {
1514     return IntWriteConsoleInput(hConsoleInput,
1515                                 (PINPUT_RECORD)lpBuffer,
1516                                 nLength,
1517                                 lpNumberOfEventsWritten,
1518                                 FALSE,
1519                                 TRUE);
1520 }
1521 
1522 
1523 /*
1524  * @implemented
1525  */
1526 BOOL
1527 WINAPI
1528 DECLSPEC_HOTPATCH
1529 WriteConsoleInputVDMW(IN HANDLE hConsoleInput,
1530                       IN CONST INPUT_RECORD *lpBuffer,
1531                       IN DWORD nLength,
1532                       OUT LPDWORD lpNumberOfEventsWritten)
1533 {
1534     return IntWriteConsoleInput(hConsoleInput,
1535                                 (PINPUT_RECORD)lpBuffer,
1536                                 nLength,
1537                                 lpNumberOfEventsWritten,
1538                                 TRUE,
1539                                 FALSE);
1540 }
1541 
1542 
1543 /*
1544  * @implemented
1545  */
1546 BOOL
1547 WINAPI
1548 DECLSPEC_HOTPATCH
1549 WriteConsoleInputVDMA(IN HANDLE hConsoleInput,
1550                       IN CONST INPUT_RECORD *lpBuffer,
1551                       IN DWORD nLength,
1552                       OUT LPDWORD lpNumberOfEventsWritten)
1553 {
1554     return IntWriteConsoleInput(hConsoleInput,
1555                                 (PINPUT_RECORD)lpBuffer,
1556                                 nLength,
1557                                 lpNumberOfEventsWritten,
1558                                 FALSE,
1559                                 FALSE);
1560 }
1561 
1562 
1563 /*
1564  * @implemented
1565  */
1566 BOOL
1567 WINAPI
1568 DECLSPEC_HOTPATCH
1569 WriteConsoleOutputW(IN HANDLE hConsoleOutput,
1570                     IN CONST CHAR_INFO *lpBuffer,
1571                     IN COORD dwBufferSize,
1572                     IN COORD dwBufferCoord,
1573                     IN OUT PSMALL_RECT lpWriteRegion)
1574 {
1575     return IntWriteConsoleOutput(hConsoleOutput,
1576                                  lpBuffer,
1577                                  dwBufferSize,
1578                                  dwBufferCoord,
1579                                  lpWriteRegion,
1580                                  TRUE);
1581 }
1582 
1583 
1584 /*
1585  * @implemented
1586  */
1587 BOOL
1588 WINAPI
1589 DECLSPEC_HOTPATCH
1590 WriteConsoleOutputA(IN HANDLE hConsoleOutput,
1591                     IN CONST CHAR_INFO *lpBuffer,
1592                     IN COORD dwBufferSize,
1593                     IN COORD dwBufferCoord,
1594                     IN OUT PSMALL_RECT lpWriteRegion)
1595 {
1596     return IntWriteConsoleOutput(hConsoleOutput,
1597                                  lpBuffer,
1598                                  dwBufferSize,
1599                                  dwBufferCoord,
1600                                  lpWriteRegion,
1601                                  FALSE);
1602 }
1603 
1604 
1605 /*
1606  * @implemented
1607  */
1608 BOOL
1609 WINAPI
1610 DECLSPEC_HOTPATCH
1611 WriteConsoleOutputCharacterW(IN HANDLE hConsoleOutput,
1612                              IN LPCWSTR lpCharacter,
1613                              IN DWORD nLength,
1614                              IN COORD dwWriteCoord,
1615                              OUT LPDWORD lpNumberOfCharsWritten)
1616 {
1617     return IntWriteConsoleOutputCode(hConsoleOutput,
1618                                      CODE_UNICODE,
1619                                      lpCharacter,
1620                                      nLength,
1621                                      dwWriteCoord,
1622                                      lpNumberOfCharsWritten);
1623 }
1624 
1625 
1626 /*
1627  * @implemented
1628  */
1629 BOOL
1630 WINAPI
1631 DECLSPEC_HOTPATCH
1632 WriteConsoleOutputCharacterA(IN HANDLE hConsoleOutput,
1633                              IN LPCSTR lpCharacter,
1634                              IN DWORD nLength,
1635                              IN COORD dwWriteCoord,
1636                              OUT LPDWORD lpNumberOfCharsWritten)
1637 {
1638     return IntWriteConsoleOutputCode(hConsoleOutput,
1639                                      CODE_ASCII,
1640                                      lpCharacter,
1641                                      nLength,
1642                                      dwWriteCoord,
1643                                      lpNumberOfCharsWritten);
1644 }
1645 
1646 
1647 /*
1648  * @implemented
1649  */
1650 BOOL
1651 WINAPI
1652 DECLSPEC_HOTPATCH
1653 WriteConsoleOutputAttribute(IN HANDLE hConsoleOutput,
1654                             IN CONST WORD *lpAttribute,
1655                             IN DWORD nLength,
1656                             IN COORD dwWriteCoord,
1657                             OUT LPDWORD lpNumberOfAttrsWritten)
1658 {
1659     return IntWriteConsoleOutputCode(hConsoleOutput,
1660                                      CODE_ATTRIBUTE,
1661                                      lpAttribute,
1662                                      nLength,
1663                                      dwWriteCoord,
1664                                      lpNumberOfAttrsWritten);
1665 }
1666 
1667 
1668 /*
1669  * @implemented
1670  */
1671 BOOL
1672 WINAPI
1673 DECLSPEC_HOTPATCH
1674 FillConsoleOutputCharacterW(IN HANDLE hConsoleOutput,
1675                             IN WCHAR cCharacter,
1676                             IN DWORD nLength,
1677                             IN COORD dwWriteCoord,
1678                             OUT LPDWORD lpNumberOfCharsWritten)
1679 {
1680     CODE_ELEMENT Code;
1681     Code.UnicodeChar = cCharacter;
1682     return IntFillConsoleOutputCode(hConsoleOutput,
1683                                     CODE_UNICODE,
1684                                     Code,
1685                                     nLength,
1686                                     dwWriteCoord,
1687                                     lpNumberOfCharsWritten);
1688 }
1689 
1690 
1691 /*
1692  * @implemented
1693  */
1694 BOOL
1695 WINAPI
1696 DECLSPEC_HOTPATCH
1697 FillConsoleOutputCharacterA(IN HANDLE hConsoleOutput,
1698                             IN CHAR cCharacter,
1699                             IN DWORD nLength,
1700                             IN COORD dwWriteCoord,
1701                             LPDWORD lpNumberOfCharsWritten)
1702 {
1703     CODE_ELEMENT Code;
1704     Code.AsciiChar = cCharacter;
1705     return IntFillConsoleOutputCode(hConsoleOutput,
1706                                     CODE_ASCII,
1707                                     Code,
1708                                     nLength,
1709                                     dwWriteCoord,
1710                                     lpNumberOfCharsWritten);
1711 }
1712 
1713 
1714 /*
1715  * @implemented
1716  */
1717 BOOL
1718 WINAPI
1719 DECLSPEC_HOTPATCH
1720 FillConsoleOutputAttribute(IN HANDLE hConsoleOutput,
1721                            IN WORD wAttribute,
1722                            IN DWORD nLength,
1723                            IN COORD dwWriteCoord,
1724                            OUT LPDWORD lpNumberOfAttrsWritten)
1725 {
1726     CODE_ELEMENT Code;
1727     Code.Attribute = wAttribute;
1728     return IntFillConsoleOutputCode(hConsoleOutput,
1729                                     CODE_ATTRIBUTE,
1730                                     Code,
1731                                     nLength,
1732                                     dwWriteCoord,
1733                                     lpNumberOfAttrsWritten);
1734 }
1735 
1736 /* EOF */
1737