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
8 * Filip Navara (xnavara@volny.cz)
9 * Thomas Weidenmueller (w3seek@reactos.org)
13 /* INCLUDES *******************************************************************/
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)
28 /* PRIVATE FUNCTIONS **********************************************************/
36 GetConsoleInputExeNameW(DWORD nBufferLength
, LPWSTR lpBuffer
);
40 IntReadConsole(IN HANDLE hConsoleInput
,
42 IN DWORD nNumberOfCharsToRead
,
43 OUT LPDWORD lpNumberOfCharsRead
,
44 IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL
,
48 CONSOLE_API_MESSAGE ApiMessage
;
49 PCONSOLE_READCONSOLE ReadConsoleRequest
= &ApiMessage
.Data
.ReadConsoleRequest
;
50 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
51 ULONG CharSize
, SizeBytes
;
53 DPRINT("IntReadConsole\n");
55 /* Set up the data to send to the Console Server */
56 ReadConsoleRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
57 ReadConsoleRequest
->InputHandle
= hConsoleInput
;
58 ReadConsoleRequest
->Unicode
= bUnicode
;
61 * Retrieve the current console executable name string and length (always
63 * FIXME: Do not use GetConsoleInputExeNameW but use something else...
65 // 1- Get the exe name length in characters, including NULL character.
66 ReadConsoleRequest
->ExeLength
=
67 (USHORT
)GetConsoleInputExeNameW(0, (PWCHAR
)ReadConsoleRequest
->StaticBuffer
);
68 // 2- Get the exe name (GetConsoleInputExeNameW returns 1 in case of success).
69 if (GetConsoleInputExeNameW(ReadConsoleRequest
->ExeLength
,
70 (PWCHAR
)ReadConsoleRequest
->StaticBuffer
) != 1)
73 ReadConsoleRequest
->ExeLength
= 0;
77 // Remove the NULL character, and convert in number of bytes.
78 ReadConsoleRequest
->ExeLength
--;
79 ReadConsoleRequest
->ExeLength
*= sizeof(WCHAR
);
82 /*** For DEBUGGING purposes ***/
84 UNICODE_STRING ExeName
;
85 ExeName
.Length
= ExeName
.MaximumLength
= ReadConsoleRequest
->ExeLength
;
86 ExeName
.Buffer
= (PWCHAR
)ReadConsoleRequest
->StaticBuffer
;
87 DPRINT1("IntReadConsole(ExeName = %wZ)\n", &ExeName
);
89 /******************************/
91 /* Determine the needed size */
92 CharSize
= (bUnicode
? sizeof(WCHAR
) : sizeof(CHAR
));
93 SizeBytes
= nNumberOfCharsToRead
* CharSize
;
95 ReadConsoleRequest
->CaptureBufferSize
=
96 ReadConsoleRequest
->NumBytes
= SizeBytes
;
99 * For optimization purposes, Windows (and hence ReactOS, too, for
100 * compatibility reasons) uses a static buffer if no more than eighty
101 * bytes are read. Otherwise a new buffer is allocated.
102 * This behaviour is also expected in the server-side.
104 if (SizeBytes
<= sizeof(ReadConsoleRequest
->StaticBuffer
))
106 ReadConsoleRequest
->Buffer
= ReadConsoleRequest
->StaticBuffer
;
107 // CaptureBuffer = NULL;
111 /* Allocate a Capture Buffer */
112 CaptureBuffer
= CsrAllocateCaptureBuffer(1, SizeBytes
);
113 if (CaptureBuffer
== NULL
)
115 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
116 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
120 /* Allocate space in the Buffer */
121 CsrAllocateMessagePointer(CaptureBuffer
,
123 (PVOID
*)&ReadConsoleRequest
->Buffer
);
126 ReadConsoleRequest
->InitialNumBytes
= 0;
127 ReadConsoleRequest
->CtrlWakeupMask
= 0;
128 ReadConsoleRequest
->ControlKeyState
= 0;
131 * From MSDN (ReadConsole function), the description
132 * for pInputControl says:
133 * "This parameter requires Unicode input by default.
134 * For ANSI mode, set this parameter to NULL."
138 if (bUnicode
&& pInputControl
&&
139 pInputControl
->nLength
== sizeof(CONSOLE_READCONSOLE_CONTROL
))
142 if (pInputControl
->nInitialChars
<= nNumberOfCharsToRead
)
144 ReadConsoleRequest
->InitialNumBytes
=
145 pInputControl
->nInitialChars
* sizeof(WCHAR
); // CharSize
147 if (pInputControl
->nInitialChars
!= 0)
150 * It is possible here to overwrite the static buffer, in case
151 * the number of bytes to read was smaller than the static buffer.
152 * In this case, this means we are continuing a pending read,
153 * and we do not need in fact the executable name that was
154 * stored in the static buffer because it was first grabbed when
155 * we started the first read.
157 RtlCopyMemory(ReadConsoleRequest
->Buffer
,
159 ReadConsoleRequest
->InitialNumBytes
);
162 ReadConsoleRequest
->CtrlWakeupMask
= pInputControl
->dwCtrlWakeupMask
;
166 // Status = STATUS_INVALID_PARAMETER;
171 /* We are in a situation where pInputControl has no meaning */
172 pInputControl
= NULL
;
175 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
178 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
179 SetLastError(ERROR_INVALID_ACCESS
);
180 _SEH2_YIELD(return FALSE
);
184 /* Check for sanity */
186 if (!NT_SUCCESS(Status) && pInputControl)
188 // Free CaptureBuffer if needed
189 // Set last error to last status
194 /* Call the server */
195 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
197 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepReadConsole
),
198 sizeof(*ReadConsoleRequest
));
200 /* Check for success */
201 Success
= NT_SUCCESS(ApiMessage
.Status
);
203 /* Retrieve the results */
208 *lpNumberOfCharsRead
= ReadConsoleRequest
->NumBytes
/ CharSize
;
210 if (bUnicode
&& pInputControl
)
211 pInputControl
->dwControlKeyState
= ReadConsoleRequest
->ControlKeyState
;
213 RtlCopyMemory(lpBuffer
,
214 ReadConsoleRequest
->Buffer
,
215 ReadConsoleRequest
->NumBytes
);
217 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
219 SetLastError(ERROR_INVALID_ACCESS
);
226 BaseSetLastNTError(ApiMessage
.Status
);
229 /* Release the capture buffer if needed */
230 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
234 /* Yield execution to another thread if Ctrl-C or Ctrl-Break happened */
235 if (ApiMessage
.Status
== STATUS_ALERTED
/* || ApiMessage.Status == STATUS_CANCELLED */)
238 SetLastError(ERROR_OPERATION_ABORTED
); // STATUS_CANCELLED
242 /* Return success status */
249 IntGetConsoleInput(IN HANDLE hConsoleInput
,
250 OUT PINPUT_RECORD lpBuffer
,
252 OUT LPDWORD lpNumberOfEventsRead
,
257 CONSOLE_API_MESSAGE ApiMessage
;
258 PCONSOLE_GETINPUT GetInputRequest
= &ApiMessage
.Data
.GetInputRequest
;
259 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
261 if (!IsConsoleHandle(hConsoleInput
))
265 *lpNumberOfEventsRead
= 0;
266 SetLastError(ERROR_INVALID_HANDLE
);
268 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
270 SetLastError(ERROR_INVALID_ACCESS
);
277 DPRINT("IntGetConsoleInput: %lx %p\n", nLength
, lpNumberOfEventsRead
);
279 /* Set up the data to send to the Console Server */
280 GetInputRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
281 GetInputRequest
->InputHandle
= hConsoleInput
;
282 GetInputRequest
->NumRecords
= nLength
;
283 GetInputRequest
->Flags
= wFlags
;
284 GetInputRequest
->Unicode
= bUnicode
;
287 * For optimization purposes, Windows (and hence ReactOS, too, for
288 * compatibility reasons) uses a static buffer if no more than five
289 * input records are read. Otherwise a new buffer is allocated.
290 * This behaviour is also expected in the server-side.
292 if (nLength
<= sizeof(GetInputRequest
->RecordStaticBuffer
)/sizeof(INPUT_RECORD
))
294 GetInputRequest
->RecordBufPtr
= GetInputRequest
->RecordStaticBuffer
;
295 // CaptureBuffer = NULL;
299 ULONG Size
= nLength
* sizeof(INPUT_RECORD
);
301 /* Allocate a Capture Buffer */
302 CaptureBuffer
= CsrAllocateCaptureBuffer(1, Size
);
303 if (CaptureBuffer
== NULL
)
305 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
306 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
310 /* Allocate space in the Buffer */
311 CsrAllocateMessagePointer(CaptureBuffer
,
313 (PVOID
*)&GetInputRequest
->RecordBufPtr
);
316 /* Call the server */
317 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
319 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepGetConsoleInput
),
320 sizeof(*GetInputRequest
));
322 /* Check for success */
323 Success
= NT_SUCCESS(ApiMessage
.Status
);
325 /* Retrieve the results */
328 DPRINT("Events read: %lx\n", GetInputRequest
->NumRecords
);
329 *lpNumberOfEventsRead
= GetInputRequest
->NumRecords
;
333 RtlCopyMemory(lpBuffer
,
334 GetInputRequest
->RecordBufPtr
,
335 GetInputRequest
->NumRecords
* sizeof(INPUT_RECORD
));
339 BaseSetLastNTError(ApiMessage
.Status
);
342 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
344 SetLastError(ERROR_INVALID_ACCESS
);
349 /* Release the capture buffer if needed */
350 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
352 /* Return success status */
359 IntReadConsoleOutput(IN HANDLE hConsoleOutput
,
360 OUT PCHAR_INFO lpBuffer
,
361 IN COORD dwBufferSize
,
362 IN COORD dwBufferCoord
,
363 IN OUT PSMALL_RECT lpReadRegion
,
367 CONSOLE_API_MESSAGE ApiMessage
;
368 PCONSOLE_READOUTPUT ReadOutputRequest
= &ApiMessage
.Data
.ReadOutputRequest
;
369 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
374 /* Set up the data to send to the Console Server */
375 ReadOutputRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
376 ReadOutputRequest
->OutputHandle
= hConsoleOutput
;
377 ReadOutputRequest
->Unicode
= bUnicode
;
379 /* Update lpReadRegion */
382 SizeX
= min(dwBufferSize
.X
- dwBufferCoord
.X
, ConioRectWidth(lpReadRegion
));
383 SizeY
= min(dwBufferSize
.Y
- dwBufferCoord
.Y
, ConioRectHeight(lpReadRegion
));
384 if (SizeX
<= 0 || SizeY
<= 0)
386 SetLastError(ERROR_INVALID_PARAMETER
);
387 _SEH2_YIELD(return FALSE
);
389 lpReadRegion
->Right
= lpReadRegion
->Left
+ SizeX
- 1;
390 lpReadRegion
->Bottom
= lpReadRegion
->Top
+ SizeY
- 1;
392 ReadOutputRequest
->ReadRegion
= *lpReadRegion
;
394 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
396 SetLastError(ERROR_INVALID_ACCESS
);
397 _SEH2_YIELD(return FALSE
);
401 NumCells
= SizeX
* SizeY
;
402 DPRINT("IntReadConsoleOutput: (%d x %d)\n", SizeX
, SizeY
);
405 * For optimization purposes, Windows (and hence ReactOS, too, for
406 * compatibility reasons) uses a static buffer if no more than one
407 * cell is read. Otherwise a new buffer is allocated.
408 * This behaviour is also expected in the server-side.
412 ReadOutputRequest
->CharInfo
= &ReadOutputRequest
->StaticBuffer
;
413 // CaptureBuffer = NULL;
417 ULONG Size
= NumCells
* sizeof(CHAR_INFO
);
419 /* Allocate a Capture Buffer */
420 CaptureBuffer
= CsrAllocateCaptureBuffer(1, Size
);
421 if (CaptureBuffer
== NULL
)
423 DPRINT1("CsrAllocateCaptureBuffer failed with size %ld!\n", Size
);
424 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
428 /* Allocate space in the Buffer */
429 CsrAllocateMessagePointer(CaptureBuffer
,
431 (PVOID
*)&ReadOutputRequest
->CharInfo
);
434 /* Call the server */
435 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
437 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepReadConsoleOutput
),
438 sizeof(*ReadOutputRequest
));
440 /* Check for success */
441 Success
= NT_SUCCESS(ApiMessage
.Status
);
443 /* Retrieve the results */
446 *lpReadRegion
= ReadOutputRequest
->ReadRegion
;
455 /* Copy into the buffer */
457 SizeX
= ReadOutputRequest
->ReadRegion
.Right
-
458 ReadOutputRequest
->ReadRegion
.Left
+ 1;
460 for (y
= 0, Y
= ReadOutputRequest
->ReadRegion
.Top
; Y
<= ReadOutputRequest
->ReadRegion
.Bottom
; ++y
, ++Y
)
462 RtlCopyMemory(lpBuffer
+ (y
+ dwBufferCoord
.Y
) * dwBufferSize
.X
+ dwBufferCoord
.X
,
463 ReadOutputRequest
->CharInfo
+ y
* SizeX
,
464 SizeX
* sizeof(CHAR_INFO
));
466 for (x
= 0, X
= ReadOutputRequest
->ReadRegion
.Left
; X
<= ReadOutputRequest
->ReadRegion
.Right
; ++x
, ++X
)
468 *(lpBuffer
+ (y
+ dwBufferCoord
.Y
) * dwBufferSize
.X
+ (x
+ dwBufferCoord
.X
)) =
469 *(ReadOutputRequest
->CharInfo
+ y
* SizeX
+ x
);
476 BaseSetLastNTError(ApiMessage
.Status
);
479 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
481 SetLastError(ERROR_INVALID_ACCESS
);
486 /* Release the capture buffer if needed */
487 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
489 /* Return success status */
496 IntReadConsoleOutputCode(IN HANDLE hConsoleOutput
,
497 IN CODE_TYPE CodeType
,
500 IN COORD dwReadCoord
,
501 OUT LPDWORD lpNumberOfCodesRead
)
504 CONSOLE_API_MESSAGE ApiMessage
;
505 PCONSOLE_READOUTPUTCODE ReadOutputCodeRequest
= &ApiMessage
.Data
.ReadOutputCodeRequest
;
506 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
507 ULONG CodeSize
, SizeBytes
;
509 DPRINT("IntReadConsoleOutputCode\n");
511 if ( (CodeType
!= CODE_ASCII
) &&
512 (CodeType
!= CODE_UNICODE
) &&
513 (CodeType
!= CODE_ATTRIBUTE
) )
515 SetLastError(ERROR_INVALID_PARAMETER
);
519 /* Set up the data to send to the Console Server */
520 ReadOutputCodeRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
521 ReadOutputCodeRequest
->OutputHandle
= hConsoleOutput
;
522 ReadOutputCodeRequest
->Coord
= dwReadCoord
;
523 ReadOutputCodeRequest
->NumCodes
= nLength
;
525 /* Determine the needed size */
526 ReadOutputCodeRequest
->CodeType
= CodeType
;
530 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, AsciiChar
);
534 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, UnicodeChar
);
538 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, Attribute
);
541 SizeBytes
= nLength
* CodeSize
;
544 * For optimization purposes, Windows (and hence ReactOS, too, for
545 * compatibility reasons) uses a static buffer if no more than eighty
546 * bytes are read. Otherwise a new buffer is allocated.
547 * This behaviour is also expected in the server-side.
549 if (SizeBytes
<= sizeof(ReadOutputCodeRequest
->CodeStaticBuffer
))
551 ReadOutputCodeRequest
->pCode
= ReadOutputCodeRequest
->CodeStaticBuffer
;
552 // CaptureBuffer = NULL;
556 /* Allocate a Capture Buffer */
557 CaptureBuffer
= CsrAllocateCaptureBuffer(1, SizeBytes
);
558 if (CaptureBuffer
== NULL
)
560 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
561 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
565 /* Allocate space in the Buffer */
566 CsrAllocateMessagePointer(CaptureBuffer
,
568 (PVOID
*)&ReadOutputCodeRequest
->pCode
);
571 /* Call the server */
572 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
574 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepReadConsoleOutputString
),
575 sizeof(*ReadOutputCodeRequest
));
577 /* Check for success */
578 Success
= NT_SUCCESS(ApiMessage
.Status
);
580 /* Retrieve the results */
583 *lpNumberOfCodesRead
= ReadOutputCodeRequest
->NumCodes
;
588 ReadOutputCodeRequest
->pCode
,
589 ReadOutputCodeRequest
->NumCodes
* CodeSize
);
593 BaseSetLastNTError(ApiMessage
.Status
);
596 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
598 SetLastError(ERROR_INVALID_ACCESS
);
603 /* Release the capture buffer if needed */
604 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
606 /* Return success status */
617 IntWriteConsole(IN HANDLE hConsoleOutput
,
619 IN DWORD nNumberOfCharsToWrite
,
620 OUT LPDWORD lpNumberOfCharsWritten
,
625 CONSOLE_API_MESSAGE ApiMessage
;
626 PCONSOLE_WRITECONSOLE WriteConsoleRequest
= &ApiMessage
.Data
.WriteConsoleRequest
;
627 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
628 ULONG CharSize
, SizeBytes
;
630 DPRINT("IntWriteConsole\n");
632 /* Set up the data to send to the Console Server */
633 WriteConsoleRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
634 WriteConsoleRequest
->OutputHandle
= hConsoleOutput
;
635 WriteConsoleRequest
->Unicode
= bUnicode
;
637 /* Those members are unused by the client, on Windows */
638 WriteConsoleRequest
->Reserved1
= 0;
639 // WriteConsoleRequest->Reserved2 = {0};
641 /* Determine the needed size */
642 CharSize
= (bUnicode
? sizeof(WCHAR
) : sizeof(CHAR
));
643 SizeBytes
= nNumberOfCharsToWrite
* CharSize
;
645 WriteConsoleRequest
->NumBytes
= SizeBytes
;
648 * For optimization purposes, Windows (and hence ReactOS, too, for
649 * compatibility reasons) uses a static buffer if no more than eighty
650 * bytes are written. Otherwise a new buffer is allocated.
651 * This behaviour is also expected in the server-side.
653 if (SizeBytes
<= sizeof(WriteConsoleRequest
->StaticBuffer
))
655 WriteConsoleRequest
->Buffer
= WriteConsoleRequest
->StaticBuffer
;
656 // CaptureBuffer = NULL;
657 WriteConsoleRequest
->UsingStaticBuffer
= TRUE
;
661 RtlCopyMemory(WriteConsoleRequest
->Buffer
,
665 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
667 SetLastError(ERROR_INVALID_ACCESS
);
668 _SEH2_YIELD(return FALSE
);
674 /* Allocate a Capture Buffer */
675 CaptureBuffer
= CsrAllocateCaptureBuffer(1, SizeBytes
);
676 if (CaptureBuffer
== NULL
)
678 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
679 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
683 /* Capture the buffer to write */
684 CsrCaptureMessageBuffer(CaptureBuffer
,
687 (PVOID
*)&WriteConsoleRequest
->Buffer
);
688 WriteConsoleRequest
->UsingStaticBuffer
= FALSE
;
691 /* Call the server */
692 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
694 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepWriteConsole
),
695 sizeof(*WriteConsoleRequest
));
697 /* Check for success */
698 Success
= NT_SUCCESS(ApiMessage
.Status
);
700 /* Release the capture buffer if needed */
701 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
703 /* Retrieve the results */
708 *lpNumberOfCharsWritten
= WriteConsoleRequest
->NumBytes
/ CharSize
;
710 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
712 SetLastError(ERROR_INVALID_ACCESS
);
719 BaseSetLastNTError(ApiMessage
.Status
);
722 /* Return success status */
729 IntWriteConsoleInput(IN HANDLE hConsoleInput
,
730 IN PINPUT_RECORD lpBuffer
,
732 OUT LPDWORD lpNumberOfEventsWritten
,
734 IN BOOLEAN bAppendToEnd
)
737 CONSOLE_API_MESSAGE ApiMessage
;
738 PCONSOLE_WRITEINPUT WriteInputRequest
= &ApiMessage
.Data
.WriteInputRequest
;
739 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
741 DPRINT("IntWriteConsoleInput: %lx %p\n", nLength
, lpNumberOfEventsWritten
);
743 /* Set up the data to send to the Console Server */
744 WriteInputRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
745 WriteInputRequest
->InputHandle
= hConsoleInput
;
746 WriteInputRequest
->NumRecords
= nLength
;
747 WriteInputRequest
->Unicode
= bUnicode
;
748 WriteInputRequest
->AppendToEnd
= bAppendToEnd
;
751 * For optimization purposes, Windows (and hence ReactOS, too, for
752 * compatibility reasons) uses a static buffer if no more than five
753 * input records are written. Otherwise a new buffer is allocated.
754 * This behaviour is also expected in the server-side.
756 if (nLength
<= sizeof(WriteInputRequest
->RecordStaticBuffer
)/sizeof(INPUT_RECORD
))
758 WriteInputRequest
->RecordBufPtr
= WriteInputRequest
->RecordStaticBuffer
;
759 // CaptureBuffer = NULL;
763 RtlCopyMemory(WriteInputRequest
->RecordBufPtr
,
765 nLength
* sizeof(INPUT_RECORD
));
767 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
769 SetLastError(ERROR_INVALID_ACCESS
);
770 _SEH2_YIELD(return FALSE
);
776 ULONG Size
= nLength
* sizeof(INPUT_RECORD
);
778 /* Allocate a Capture Buffer */
779 CaptureBuffer
= CsrAllocateCaptureBuffer(1, Size
);
780 if (CaptureBuffer
== NULL
)
782 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
783 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
787 /* Capture the user buffer */
788 CsrCaptureMessageBuffer(CaptureBuffer
,
791 (PVOID
*)&WriteInputRequest
->RecordBufPtr
);
794 /* Call the server */
795 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
797 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepWriteConsoleInput
),
798 sizeof(*WriteInputRequest
));
800 /* Check for success */
801 Success
= NT_SUCCESS(ApiMessage
.Status
);
803 /* Release the capture buffer if needed */
804 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
806 /* Retrieve the results */
809 DPRINT("Events written: %lx\n", WriteInputRequest
->NumRecords
);
810 *lpNumberOfEventsWritten
= WriteInputRequest
->NumRecords
;
813 BaseSetLastNTError(ApiMessage
.Status
);
815 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
817 SetLastError(ERROR_INVALID_ACCESS
);
822 /* Return success status */
829 IntWriteConsoleOutput(IN HANDLE hConsoleOutput
,
830 IN CONST CHAR_INFO
*lpBuffer
,
831 IN COORD dwBufferSize
,
832 IN COORD dwBufferCoord
,
833 IN OUT PSMALL_RECT lpWriteRegion
,
837 CONSOLE_API_MESSAGE ApiMessage
;
838 PCONSOLE_WRITEOUTPUT WriteOutputRequest
= &ApiMessage
.Data
.WriteOutputRequest
;
839 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
844 /* Set up the data to send to the Console Server */
845 WriteOutputRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
846 WriteOutputRequest
->OutputHandle
= hConsoleOutput
;
847 WriteOutputRequest
->Unicode
= bUnicode
;
849 /* Update lpWriteRegion */
852 SizeX
= min(dwBufferSize
.X
- dwBufferCoord
.X
, ConioRectWidth(lpWriteRegion
));
853 SizeY
= min(dwBufferSize
.Y
- dwBufferCoord
.Y
, ConioRectHeight(lpWriteRegion
));
854 if (SizeX
<= 0 || SizeY
<= 0)
856 SetLastError(ERROR_INVALID_PARAMETER
);
857 _SEH2_YIELD(return FALSE
);
859 lpWriteRegion
->Right
= lpWriteRegion
->Left
+ SizeX
- 1;
860 lpWriteRegion
->Bottom
= lpWriteRegion
->Top
+ SizeY
- 1;
862 WriteOutputRequest
->WriteRegion
= *lpWriteRegion
;
864 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
866 SetLastError(ERROR_INVALID_ACCESS
);
867 _SEH2_YIELD(return FALSE
);
871 NumCells
= SizeX
* SizeY
;
872 DPRINT("IntWriteConsoleOutput: (%d x %d)\n", SizeX
, SizeY
);
875 * For optimization purposes, Windows (and hence ReactOS, too, for
876 * compatibility reasons) uses a static buffer if no more than one
877 * cell is written. Otherwise a new buffer is allocated.
878 * This behaviour is also expected in the server-side.
882 WriteOutputRequest
->CharInfo
= &WriteOutputRequest
->StaticBuffer
;
883 // CaptureBuffer = NULL;
884 WriteOutputRequest
->UseVirtualMemory
= FALSE
;
888 ULONG Size
= NumCells
* sizeof(CHAR_INFO
);
890 /* Allocate a Capture Buffer */
891 CaptureBuffer
= CsrAllocateCaptureBuffer(1, Size
);
894 /* Allocate space in the Buffer */
895 CsrAllocateMessagePointer(CaptureBuffer
,
897 (PVOID
*)&WriteOutputRequest
->CharInfo
);
898 WriteOutputRequest
->UseVirtualMemory
= FALSE
;
903 * CsrAllocateCaptureBuffer failed because we tried to allocate
904 * a too large (>= 64 kB, size of the CSR heap) data buffer.
905 * To circumvent this, Windows uses a trick (that we reproduce for
906 * compatibility reasons): we allocate a heap buffer in the process'
907 * memory, and CSR will read it via NtReadVirtualMemory.
909 DPRINT1("CsrAllocateCaptureBuffer failed with size %ld, let's use local heap buffer...\n", Size
);
911 WriteOutputRequest
->CharInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, Size
);
912 WriteOutputRequest
->UseVirtualMemory
= TRUE
;
914 /* Bail out if we still cannot allocate memory */
915 if (WriteOutputRequest
->CharInfo
== NULL
)
917 DPRINT1("Failed to allocate heap buffer with size %ld!\n", Size
);
918 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
924 /* Capture the user buffer contents */
932 /* Copy into the buffer */
934 SizeX
= WriteOutputRequest
->WriteRegion
.Right
-
935 WriteOutputRequest
->WriteRegion
.Left
+ 1;
937 for (y
= 0, Y
= WriteOutputRequest
->WriteRegion
.Top
; Y
<= WriteOutputRequest
->WriteRegion
.Bottom
; ++y
, ++Y
)
939 RtlCopyMemory(WriteOutputRequest
->CharInfo
+ y
* SizeX
,
940 lpBuffer
+ (y
+ dwBufferCoord
.Y
) * dwBufferSize
.X
+ dwBufferCoord
.X
,
941 SizeX
* sizeof(CHAR_INFO
));
943 for (x
= 0, X
= WriteOutputRequest
->WriteRegion
.Left
; X
<= WriteOutputRequest
->WriteRegion
.Right
; ++x
, ++X
)
945 *(WriteOutputRequest
->CharInfo
+ y
* SizeX
+ x
) =
946 *(lpBuffer
+ (y
+ dwBufferCoord
.Y
) * dwBufferSize
.X
+ (x
+ dwBufferCoord
.X
));
951 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
953 SetLastError(ERROR_INVALID_ACCESS
);
954 _SEH2_YIELD(return FALSE
);
958 /* Call the server */
959 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
961 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepWriteConsoleOutput
),
962 sizeof(*WriteOutputRequest
));
964 /* Check for success */
965 Success
= NT_SUCCESS(ApiMessage
.Status
);
967 /* Release the capture buffer if needed */
970 CsrFreeCaptureBuffer(CaptureBuffer
);
974 /* If we used a heap buffer, free it */
975 if (WriteOutputRequest
->UseVirtualMemory
)
976 RtlFreeHeap(RtlGetProcessHeap(), 0, WriteOutputRequest
->CharInfo
);
979 /* Retrieve the results */
982 *lpWriteRegion
= WriteOutputRequest
->WriteRegion
;
985 BaseSetLastNTError(ApiMessage
.Status
);
987 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
989 SetLastError(ERROR_INVALID_ACCESS
);
994 /* Return success status */
1001 IntWriteConsoleOutputCode(IN HANDLE hConsoleOutput
,
1002 IN CODE_TYPE CodeType
,
1003 IN CONST VOID
*pCode
,
1005 IN COORD dwWriteCoord
,
1006 OUT LPDWORD lpNumberOfCodesWritten
)
1009 CONSOLE_API_MESSAGE ApiMessage
;
1010 PCONSOLE_WRITEOUTPUTCODE WriteOutputCodeRequest
= &ApiMessage
.Data
.WriteOutputCodeRequest
;
1011 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
1012 ULONG CodeSize
, SizeBytes
;
1014 if ( (CodeType
!= CODE_ASCII
) &&
1015 (CodeType
!= CODE_UNICODE
) &&
1016 (CodeType
!= CODE_ATTRIBUTE
) )
1018 SetLastError(ERROR_INVALID_PARAMETER
);
1022 DPRINT("IntWriteConsoleOutputCode\n");
1024 /* Set up the data to send to the Console Server */
1025 WriteOutputCodeRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
1026 WriteOutputCodeRequest
->OutputHandle
= hConsoleOutput
;
1027 WriteOutputCodeRequest
->Coord
= dwWriteCoord
;
1028 WriteOutputCodeRequest
->NumCodes
= nLength
;
1030 /* Determine the needed size */
1031 WriteOutputCodeRequest
->CodeType
= CodeType
;
1035 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, AsciiChar
);
1039 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, UnicodeChar
);
1042 case CODE_ATTRIBUTE
:
1043 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, Attribute
);
1046 SizeBytes
= nLength
* CodeSize
;
1049 * For optimization purposes, Windows (and hence ReactOS, too, for
1050 * compatibility reasons) uses a static buffer if no more than eighty
1051 * bytes are written. Otherwise a new buffer is allocated.
1052 * This behaviour is also expected in the server-side.
1054 if (SizeBytes
<= sizeof(WriteOutputCodeRequest
->CodeStaticBuffer
))
1056 WriteOutputCodeRequest
->pCode
= WriteOutputCodeRequest
->CodeStaticBuffer
;
1057 // CaptureBuffer = NULL;
1061 RtlCopyMemory(WriteOutputCodeRequest
->pCode
,
1065 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1067 SetLastError(ERROR_INVALID_ACCESS
);
1068 _SEH2_YIELD(return FALSE
);
1074 /* Allocate a Capture Buffer */
1075 CaptureBuffer
= CsrAllocateCaptureBuffer(1, SizeBytes
);
1076 if (CaptureBuffer
== NULL
)
1078 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
1079 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1083 /* Capture the buffer to write */
1084 CsrCaptureMessageBuffer(CaptureBuffer
,
1087 (PVOID
*)&WriteOutputCodeRequest
->pCode
);
1090 /* Call the server */
1091 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
1093 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepWriteConsoleOutputString
),
1094 sizeof(*WriteOutputCodeRequest
));
1096 /* Check for success */
1097 Success
= NT_SUCCESS(ApiMessage
.Status
);
1099 /* Release the capture buffer if needed */
1100 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
1102 /* Retrieve the results */
1105 *lpNumberOfCodesWritten
= WriteOutputCodeRequest
->NumCodes
;
1108 BaseSetLastNTError(ApiMessage
.Status
);
1110 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1112 SetLastError(ERROR_INVALID_ACCESS
);
1117 /* Return success status */
1124 IntFillConsoleOutputCode(IN HANDLE hConsoleOutput
,
1125 IN CODE_TYPE CodeType
,
1126 IN CODE_ELEMENT Code
,
1128 IN COORD dwWriteCoord
,
1129 OUT LPDWORD lpNumberOfCodesWritten
)
1132 CONSOLE_API_MESSAGE ApiMessage
;
1133 PCONSOLE_FILLOUTPUTCODE FillOutputRequest
= &ApiMessage
.Data
.FillOutputRequest
;
1135 DPRINT("IntFillConsoleOutputCode\n");
1137 if ( (CodeType
!= CODE_ASCII
) &&
1138 (CodeType
!= CODE_UNICODE
) &&
1139 (CodeType
!= CODE_ATTRIBUTE
) )
1141 SetLastError(ERROR_INVALID_PARAMETER
);
1145 /* Set up the data to send to the Console Server */
1146 FillOutputRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
1147 FillOutputRequest
->OutputHandle
= hConsoleOutput
;
1148 FillOutputRequest
->WriteCoord
= dwWriteCoord
;
1149 FillOutputRequest
->CodeType
= CodeType
;
1150 FillOutputRequest
->Code
= Code
;
1151 FillOutputRequest
->NumCodes
= nLength
;
1153 /* Call the server */
1154 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
1156 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepFillConsoleOutput
),
1157 sizeof(*FillOutputRequest
));
1159 /* Check for success */
1160 Success
= NT_SUCCESS(ApiMessage
.Status
);
1162 /* Retrieve the results */
1165 *lpNumberOfCodesWritten
= FillOutputRequest
->NumCodes
;
1168 BaseSetLastNTError(ApiMessage
.Status
);
1170 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1172 SetLastError(ERROR_INVALID_ACCESS
);
1177 /* Return success status */
1182 /* FUNCTIONS ******************************************************************/
1188 /*--------------------------------------------------------------
1195 ReadConsoleW(IN HANDLE hConsoleInput
,
1196 OUT LPVOID lpBuffer
,
1197 IN DWORD nNumberOfCharsToRead
,
1198 OUT LPDWORD lpNumberOfCharsRead
,
1199 IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL
)
1201 return IntReadConsole(hConsoleInput
,
1203 nNumberOfCharsToRead
,
1204 lpNumberOfCharsRead
,
1210 /*--------------------------------------------------------------
1217 ReadConsoleA(IN HANDLE hConsoleInput
,
1218 OUT LPVOID lpBuffer
,
1219 IN DWORD nNumberOfCharsToRead
,
1220 OUT LPDWORD lpNumberOfCharsRead
,
1221 IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL
)
1223 return IntReadConsole(hConsoleInput
,
1225 nNumberOfCharsToRead
,
1226 lpNumberOfCharsRead
,
1232 /*--------------------------------------------------------------
1239 PeekConsoleInputW(IN HANDLE hConsoleInput
,
1240 OUT PINPUT_RECORD lpBuffer
,
1242 OUT LPDWORD lpNumberOfEventsRead
)
1244 return IntGetConsoleInput(hConsoleInput
,
1247 lpNumberOfEventsRead
,
1248 CONSOLE_READ_KEEPEVENT
| CONSOLE_READ_CONTINUE
,
1253 /*--------------------------------------------------------------
1260 PeekConsoleInputA(IN HANDLE hConsoleInput
,
1261 OUT PINPUT_RECORD lpBuffer
,
1263 OUT LPDWORD lpNumberOfEventsRead
)
1265 return IntGetConsoleInput(hConsoleInput
,
1268 lpNumberOfEventsRead
,
1269 CONSOLE_READ_KEEPEVENT
| CONSOLE_READ_CONTINUE
,
1274 /*--------------------------------------------------------------
1281 ReadConsoleInputW(IN HANDLE hConsoleInput
,
1282 OUT PINPUT_RECORD lpBuffer
,
1284 OUT LPDWORD lpNumberOfEventsRead
)
1286 return IntGetConsoleInput(hConsoleInput
,
1289 lpNumberOfEventsRead
,
1295 /*--------------------------------------------------------------
1302 ReadConsoleInputA(IN HANDLE hConsoleInput
,
1303 OUT PINPUT_RECORD lpBuffer
,
1305 OUT LPDWORD lpNumberOfEventsRead
)
1307 return IntGetConsoleInput(hConsoleInput
,
1310 lpNumberOfEventsRead
,
1316 /*--------------------------------------------------------------
1317 * ReadConsoleInputExW
1323 ReadConsoleInputExW(IN HANDLE hConsoleInput
,
1324 OUT PINPUT_RECORD lpBuffer
,
1326 OUT LPDWORD lpNumberOfEventsRead
,
1329 return IntGetConsoleInput(hConsoleInput
,
1332 lpNumberOfEventsRead
,
1338 /*--------------------------------------------------------------
1339 * ReadConsoleInputExA
1345 ReadConsoleInputExA(IN HANDLE hConsoleInput
,
1346 OUT PINPUT_RECORD lpBuffer
,
1348 OUT LPDWORD lpNumberOfEventsRead
,
1351 return IntGetConsoleInput(hConsoleInput
,
1354 lpNumberOfEventsRead
,
1360 /*--------------------------------------------------------------
1361 * ReadConsoleOutputW
1367 ReadConsoleOutputW(IN HANDLE hConsoleOutput
,
1368 OUT PCHAR_INFO lpBuffer
,
1369 IN COORD dwBufferSize
,
1370 IN COORD dwBufferCoord
,
1371 IN OUT PSMALL_RECT lpReadRegion
)
1373 return IntReadConsoleOutput(hConsoleOutput
,
1382 /*--------------------------------------------------------------
1383 * ReadConsoleOutputA
1389 ReadConsoleOutputA(IN HANDLE hConsoleOutput
,
1390 OUT PCHAR_INFO lpBuffer
,
1391 IN COORD dwBufferSize
,
1392 IN COORD dwBufferCoord
,
1393 IN OUT PSMALL_RECT lpReadRegion
)
1395 return IntReadConsoleOutput(hConsoleOutput
,
1404 /*--------------------------------------------------------------
1405 * ReadConsoleOutputCharacterW
1411 ReadConsoleOutputCharacterW(IN HANDLE hConsoleOutput
,
1412 OUT LPWSTR lpCharacter
,
1414 IN COORD dwReadCoord
,
1415 OUT LPDWORD lpNumberOfCharsRead
)
1417 return IntReadConsoleOutputCode(hConsoleOutput
,
1422 lpNumberOfCharsRead
);
1426 /*--------------------------------------------------------------
1427 * ReadConsoleOutputCharacterA
1433 ReadConsoleOutputCharacterA(IN HANDLE hConsoleOutput
,
1434 OUT LPSTR lpCharacter
,
1436 IN COORD dwReadCoord
,
1437 OUT LPDWORD lpNumberOfCharsRead
)
1439 return IntReadConsoleOutputCode(hConsoleOutput
,
1444 lpNumberOfCharsRead
);
1448 /*--------------------------------------------------------------
1449 * ReadConsoleOutputAttribute
1455 ReadConsoleOutputAttribute(IN HANDLE hConsoleOutput
,
1456 OUT LPWORD lpAttribute
,
1458 IN COORD dwReadCoord
,
1459 OUT LPDWORD lpNumberOfAttrsRead
)
1461 return IntReadConsoleOutputCode(hConsoleOutput
,
1466 lpNumberOfAttrsRead
);
1470 /*******************
1472 *******************/
1474 /*--------------------------------------------------------------
1481 WriteConsoleW(IN HANDLE hConsoleOutput
,
1482 IN CONST VOID
*lpBuffer
,
1483 IN DWORD nNumberOfCharsToWrite
,
1484 OUT LPDWORD lpNumberOfCharsWritten
,
1487 return IntWriteConsole(hConsoleOutput
,
1489 nNumberOfCharsToWrite
,
1490 lpNumberOfCharsWritten
,
1496 /*--------------------------------------------------------------
1503 WriteConsoleA(IN HANDLE hConsoleOutput
,
1504 IN CONST VOID
*lpBuffer
,
1505 IN DWORD nNumberOfCharsToWrite
,
1506 OUT LPDWORD lpNumberOfCharsWritten
,
1509 return IntWriteConsole(hConsoleOutput
,
1511 nNumberOfCharsToWrite
,
1512 lpNumberOfCharsWritten
,
1518 /*--------------------------------------------------------------
1519 * WriteConsoleInputW
1525 WriteConsoleInputW(IN HANDLE hConsoleInput
,
1526 IN CONST INPUT_RECORD
*lpBuffer
,
1528 OUT LPDWORD lpNumberOfEventsWritten
)
1530 return IntWriteConsoleInput(hConsoleInput
,
1531 (PINPUT_RECORD
)lpBuffer
,
1533 lpNumberOfEventsWritten
,
1539 /*--------------------------------------------------------------
1540 * WriteConsoleInputA
1546 WriteConsoleInputA(IN HANDLE hConsoleInput
,
1547 IN CONST INPUT_RECORD
*lpBuffer
,
1549 OUT LPDWORD lpNumberOfEventsWritten
)
1551 return IntWriteConsoleInput(hConsoleInput
,
1552 (PINPUT_RECORD
)lpBuffer
,
1554 lpNumberOfEventsWritten
,
1560 /*--------------------------------------------------------------
1561 * WriteConsoleInputVDMW
1567 WriteConsoleInputVDMW(IN HANDLE hConsoleInput
,
1568 IN CONST INPUT_RECORD
*lpBuffer
,
1570 OUT LPDWORD lpNumberOfEventsWritten
)
1572 return IntWriteConsoleInput(hConsoleInput
,
1573 (PINPUT_RECORD
)lpBuffer
,
1575 lpNumberOfEventsWritten
,
1581 /*--------------------------------------------------------------
1582 * WriteConsoleInputVDMA
1588 WriteConsoleInputVDMA(IN HANDLE hConsoleInput
,
1589 IN CONST INPUT_RECORD
*lpBuffer
,
1591 OUT LPDWORD lpNumberOfEventsWritten
)
1593 return IntWriteConsoleInput(hConsoleInput
,
1594 (PINPUT_RECORD
)lpBuffer
,
1596 lpNumberOfEventsWritten
,
1602 /*--------------------------------------------------------------
1603 * WriteConsoleOutputW
1609 WriteConsoleOutputW(IN HANDLE hConsoleOutput
,
1610 IN CONST CHAR_INFO
*lpBuffer
,
1611 IN COORD dwBufferSize
,
1612 IN COORD dwBufferCoord
,
1613 IN OUT PSMALL_RECT lpWriteRegion
)
1615 return IntWriteConsoleOutput(hConsoleOutput
,
1624 /*--------------------------------------------------------------
1625 * WriteConsoleOutputA
1631 WriteConsoleOutputA(IN HANDLE hConsoleOutput
,
1632 IN CONST CHAR_INFO
*lpBuffer
,
1633 IN COORD dwBufferSize
,
1634 IN COORD dwBufferCoord
,
1635 IN OUT PSMALL_RECT lpWriteRegion
)
1637 return IntWriteConsoleOutput(hConsoleOutput
,
1646 /*--------------------------------------------------------------
1647 * WriteConsoleOutputCharacterW
1653 WriteConsoleOutputCharacterW(IN HANDLE hConsoleOutput
,
1654 IN LPCWSTR lpCharacter
,
1656 IN COORD dwWriteCoord
,
1657 OUT LPDWORD lpNumberOfCharsWritten
)
1659 return IntWriteConsoleOutputCode(hConsoleOutput
,
1664 lpNumberOfCharsWritten
);
1668 /*--------------------------------------------------------------
1669 * WriteConsoleOutputCharacterA
1675 WriteConsoleOutputCharacterA(IN HANDLE hConsoleOutput
,
1676 IN LPCSTR lpCharacter
,
1678 IN COORD dwWriteCoord
,
1679 OUT LPDWORD lpNumberOfCharsWritten
)
1681 return IntWriteConsoleOutputCode(hConsoleOutput
,
1686 lpNumberOfCharsWritten
);
1690 /*--------------------------------------------------------------
1691 * WriteConsoleOutputAttribute
1697 WriteConsoleOutputAttribute(IN HANDLE hConsoleOutput
,
1698 IN CONST WORD
*lpAttribute
,
1700 IN COORD dwWriteCoord
,
1701 OUT LPDWORD lpNumberOfAttrsWritten
)
1703 return IntWriteConsoleOutputCode(hConsoleOutput
,
1708 lpNumberOfAttrsWritten
);
1712 /*--------------------------------------------------------------
1713 * FillConsoleOutputCharacterW
1719 FillConsoleOutputCharacterW(IN HANDLE hConsoleOutput
,
1720 IN WCHAR cCharacter
,
1722 IN COORD dwWriteCoord
,
1723 OUT LPDWORD lpNumberOfCharsWritten
)
1726 Code
.UnicodeChar
= cCharacter
;
1727 return IntFillConsoleOutputCode(hConsoleOutput
,
1732 lpNumberOfCharsWritten
);
1736 /*--------------------------------------------------------------
1737 * FillConsoleOutputCharacterA
1743 FillConsoleOutputCharacterA(IN HANDLE hConsoleOutput
,
1746 IN COORD dwWriteCoord
,
1747 LPDWORD lpNumberOfCharsWritten
)
1750 Code
.AsciiChar
= cCharacter
;
1751 return IntFillConsoleOutputCode(hConsoleOutput
,
1756 lpNumberOfCharsWritten
);
1760 /*--------------------------------------------------------------
1761 * FillConsoleOutputAttribute
1767 FillConsoleOutputAttribute(IN HANDLE hConsoleOutput
,
1770 IN COORD dwWriteCoord
,
1771 OUT LPDWORD lpNumberOfAttrsWritten
)
1774 Code
.Attribute
= wAttribute
;
1775 return IntFillConsoleOutputCode(hConsoleOutput
,
1780 lpNumberOfAttrsWritten
);