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
IntReadConsole(IN HANDLE hConsoleInput,OUT PVOID lpBuffer,IN DWORD nNumberOfCharsToRead,OUT LPDWORD lpNumberOfCharsRead,IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL,IN BOOLEAN bUnicode)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
IntGetConsoleInput(IN HANDLE hConsoleInput,OUT PINPUT_RECORD lpBuffer,IN DWORD nLength,OUT LPDWORD lpNumberOfEventsRead,IN WORD wFlags,IN BOOLEAN bUnicode)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
IntReadConsoleOutput(IN HANDLE hConsoleOutput,OUT PCHAR_INFO lpBuffer,IN COORD dwBufferSize,IN COORD dwBufferCoord,IN OUT PSMALL_RECT lpReadRegion,IN BOOLEAN bUnicode)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
IntReadConsoleOutputCode(IN HANDLE hConsoleOutput,IN CODE_TYPE CodeType,OUT PVOID pCode,IN DWORD nLength,IN COORD dwReadCoord,OUT LPDWORD lpNumberOfCodesRead)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
IntWriteConsole(IN HANDLE hConsoleOutput,IN PVOID lpBuffer,IN DWORD nNumberOfCharsToWrite,OUT LPDWORD lpNumberOfCharsWritten,LPVOID lpReserved,IN BOOLEAN bUnicode)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
IntWriteConsoleInput(IN HANDLE hConsoleInput,IN PINPUT_RECORD lpBuffer,IN DWORD nLength,OUT LPDWORD lpNumberOfEventsWritten,IN BOOLEAN bUnicode,IN BOOLEAN bAppendToEnd)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
IntWriteConsoleOutput(IN HANDLE hConsoleOutput,IN CONST CHAR_INFO * lpBuffer,IN COORD dwBufferSize,IN COORD dwBufferCoord,IN OUT PSMALL_RECT lpWriteRegion,IN BOOLEAN bUnicode)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
IntWriteConsoleOutputCode(IN HANDLE hConsoleOutput,IN CODE_TYPE CodeType,IN CONST VOID * pCode,IN DWORD nLength,IN COORD dwWriteCoord,OUT LPDWORD lpNumberOfCodesWritten)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
IntFillConsoleOutputCode(IN HANDLE hConsoleOutput,IN CODE_TYPE CodeType,IN CODE_ELEMENT Code,IN DWORD nLength,IN COORD dwWriteCoord,OUT LPDWORD lpNumberOfCodesWritten)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
ReadConsoleW(IN HANDLE hConsoleInput,OUT LPVOID lpBuffer,IN DWORD nNumberOfCharsToRead,OUT LPDWORD lpNumberOfCharsRead,IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL)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
ReadConsoleA(IN HANDLE hConsoleInput,OUT LPVOID lpBuffer,IN DWORD nNumberOfCharsToRead,OUT LPDWORD lpNumberOfCharsRead,IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL)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
PeekConsoleInputW(IN HANDLE hConsoleInput,OUT PINPUT_RECORD lpBuffer,IN DWORD nLength,OUT LPDWORD lpNumberOfEventsRead)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_NOREMOVE | CONSOLE_READ_NOWAIT,
1226                               TRUE);
1227 }
1228 
1229 
1230 /*
1231  * @implemented
1232  */
1233 BOOL
1234 WINAPI
1235 DECLSPEC_HOTPATCH
PeekConsoleInputA(IN HANDLE hConsoleInput,OUT PINPUT_RECORD lpBuffer,IN DWORD nLength,OUT LPDWORD lpNumberOfEventsRead)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_NOREMOVE | CONSOLE_READ_NOWAIT,
1246                               FALSE);
1247 }
1248 
1249 
1250 /*
1251  * @implemented
1252  */
1253 BOOL
1254 WINAPI
1255 DECLSPEC_HOTPATCH
ReadConsoleInputW(IN HANDLE hConsoleInput,OUT PINPUT_RECORD lpBuffer,IN DWORD nLength,OUT LPDWORD lpNumberOfEventsRead)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
ReadConsoleInputA(IN HANDLE hConsoleInput,OUT PINPUT_RECORD lpBuffer,IN DWORD nLength,OUT LPDWORD lpNumberOfEventsRead)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
ReadConsoleInputExW(IN HANDLE hConsoleInput,OUT PINPUT_RECORD lpBuffer,IN DWORD nLength,OUT LPDWORD lpNumberOfEventsRead,IN WORD wFlags)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
ReadConsoleInputExA(IN HANDLE hConsoleInput,OUT PINPUT_RECORD lpBuffer,IN DWORD nLength,OUT LPDWORD lpNumberOfEventsRead,IN WORD wFlags)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
ReadConsoleOutputW(IN HANDLE hConsoleOutput,OUT PCHAR_INFO lpBuffer,IN COORD dwBufferSize,IN COORD dwBufferCoord,IN OUT PSMALL_RECT lpReadRegion)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
ReadConsoleOutputA(IN HANDLE hConsoleOutput,OUT PCHAR_INFO lpBuffer,IN COORD dwBufferSize,IN COORD dwBufferCoord,IN OUT PSMALL_RECT lpReadRegion)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
ReadConsoleOutputCharacterW(IN HANDLE hConsoleOutput,OUT LPWSTR lpCharacter,IN DWORD nLength,IN COORD dwReadCoord,OUT LPDWORD lpNumberOfCharsRead)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
ReadConsoleOutputCharacterA(IN HANDLE hConsoleOutput,OUT LPSTR lpCharacter,IN DWORD nLength,IN COORD dwReadCoord,OUT LPDWORD lpNumberOfCharsRead)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
ReadConsoleOutputAttribute(IN HANDLE hConsoleOutput,OUT LPWORD lpAttribute,IN DWORD nLength,IN COORD dwReadCoord,OUT LPDWORD lpNumberOfAttrsRead)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
WriteConsoleW(IN HANDLE hConsoleOutput,IN CONST VOID * lpBuffer,IN DWORD nNumberOfCharsToWrite,OUT LPDWORD lpNumberOfCharsWritten,LPVOID lpReserved)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
WriteConsoleA(IN HANDLE hConsoleOutput,IN CONST VOID * lpBuffer,IN DWORD nNumberOfCharsToWrite,OUT LPDWORD lpNumberOfCharsWritten,LPVOID lpReserved)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
WriteConsoleInputW(IN HANDLE hConsoleInput,IN CONST INPUT_RECORD * lpBuffer,IN DWORD nLength,OUT LPDWORD lpNumberOfEventsWritten)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
WriteConsoleInputA(IN HANDLE hConsoleInput,IN CONST INPUT_RECORD * lpBuffer,IN DWORD nLength,OUT LPDWORD lpNumberOfEventsWritten)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
WriteConsoleInputVDMW(IN HANDLE hConsoleInput,IN CONST INPUT_RECORD * lpBuffer,IN DWORD nLength,OUT LPDWORD lpNumberOfEventsWritten)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
WriteConsoleInputVDMA(IN HANDLE hConsoleInput,IN CONST INPUT_RECORD * lpBuffer,IN DWORD nLength,OUT LPDWORD lpNumberOfEventsWritten)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
WriteConsoleOutputW(IN HANDLE hConsoleOutput,IN CONST CHAR_INFO * lpBuffer,IN COORD dwBufferSize,IN COORD dwBufferCoord,IN OUT PSMALL_RECT lpWriteRegion)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
WriteConsoleOutputA(IN HANDLE hConsoleOutput,IN CONST CHAR_INFO * lpBuffer,IN COORD dwBufferSize,IN COORD dwBufferCoord,IN OUT PSMALL_RECT lpWriteRegion)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
WriteConsoleOutputCharacterW(IN HANDLE hConsoleOutput,IN LPCWSTR lpCharacter,IN DWORD nLength,IN COORD dwWriteCoord,OUT LPDWORD lpNumberOfCharsWritten)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
WriteConsoleOutputCharacterA(IN HANDLE hConsoleOutput,IN LPCSTR lpCharacter,IN DWORD nLength,IN COORD dwWriteCoord,OUT LPDWORD lpNumberOfCharsWritten)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
WriteConsoleOutputAttribute(IN HANDLE hConsoleOutput,IN CONST WORD * lpAttribute,IN DWORD nLength,IN COORD dwWriteCoord,OUT LPDWORD lpNumberOfAttrsWritten)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
FillConsoleOutputCharacterW(IN HANDLE hConsoleOutput,IN WCHAR cCharacter,IN DWORD nLength,IN COORD dwWriteCoord,OUT LPDWORD lpNumberOfCharsWritten)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
FillConsoleOutputCharacterA(IN HANDLE hConsoleOutput,IN CHAR cCharacter,IN DWORD nLength,IN COORD dwWriteCoord,LPDWORD lpNumberOfCharsWritten)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
FillConsoleOutputAttribute(IN HANDLE hConsoleOutput,IN WORD wAttribute,IN DWORD nLength,IN COORD dwWriteCoord,OUT LPDWORD lpNumberOfAttrsWritten)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