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;
887 ULONG Size
= NumCells
* sizeof(CHAR_INFO
);
889 /* Allocate a Capture Buffer */
890 CaptureBuffer
= CsrAllocateCaptureBuffer(1, Size
);
891 if (CaptureBuffer
== NULL
)
893 DPRINT1("CsrAllocateCaptureBuffer failed with size %ld!\n", Size
);
894 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
898 /* Allocate space in the Buffer */
899 CsrAllocateMessagePointer(CaptureBuffer
,
901 (PVOID
*)&WriteOutputRequest
->CharInfo
);
904 /* Capture the user buffer contents */
912 /* Copy into the buffer */
914 SizeX
= WriteOutputRequest
->WriteRegion
.Right
-
915 WriteOutputRequest
->WriteRegion
.Left
+ 1;
917 for (y
= 0, Y
= WriteOutputRequest
->WriteRegion
.Top
; Y
<= WriteOutputRequest
->WriteRegion
.Bottom
; ++y
, ++Y
)
919 RtlCopyMemory(WriteOutputRequest
->CharInfo
+ y
* SizeX
,
920 lpBuffer
+ (y
+ dwBufferCoord
.Y
) * dwBufferSize
.X
+ dwBufferCoord
.X
,
921 SizeX
* sizeof(CHAR_INFO
));
923 for (x
= 0, X
= WriteOutputRequest
->WriteRegion
.Left
; X
<= WriteOutputRequest
->WriteRegion
.Right
; ++x
, ++X
)
925 *(WriteOutputRequest
->CharInfo
+ y
* SizeX
+ x
) =
926 *(lpBuffer
+ (y
+ dwBufferCoord
.Y
) * dwBufferSize
.X
+ (x
+ dwBufferCoord
.X
));
931 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
933 SetLastError(ERROR_INVALID_ACCESS
);
934 _SEH2_YIELD(return FALSE
);
938 /* Call the server */
939 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
941 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepWriteConsoleOutput
),
942 sizeof(*WriteOutputRequest
));
944 /* Check for success */
945 Success
= NT_SUCCESS(ApiMessage
.Status
);
947 /* Release the capture buffer if needed */
948 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
950 /* Retrieve the results */
953 *lpWriteRegion
= WriteOutputRequest
->WriteRegion
;
956 BaseSetLastNTError(ApiMessage
.Status
);
958 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
960 SetLastError(ERROR_INVALID_ACCESS
);
965 /* Return success status */
972 IntWriteConsoleOutputCode(IN HANDLE hConsoleOutput
,
973 IN CODE_TYPE CodeType
,
974 IN CONST VOID
*pCode
,
976 IN COORD dwWriteCoord
,
977 OUT LPDWORD lpNumberOfCodesWritten
)
980 CONSOLE_API_MESSAGE ApiMessage
;
981 PCONSOLE_WRITEOUTPUTCODE WriteOutputCodeRequest
= &ApiMessage
.Data
.WriteOutputCodeRequest
;
982 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
983 ULONG CodeSize
, SizeBytes
;
985 if ( (CodeType
!= CODE_ASCII
) &&
986 (CodeType
!= CODE_UNICODE
) &&
987 (CodeType
!= CODE_ATTRIBUTE
) )
989 SetLastError(ERROR_INVALID_PARAMETER
);
993 DPRINT("IntWriteConsoleOutputCode\n");
995 /* Set up the data to send to the Console Server */
996 WriteOutputCodeRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
997 WriteOutputCodeRequest
->OutputHandle
= hConsoleOutput
;
998 WriteOutputCodeRequest
->Coord
= dwWriteCoord
;
999 WriteOutputCodeRequest
->NumCodes
= nLength
;
1001 /* Determine the needed size */
1002 WriteOutputCodeRequest
->CodeType
= CodeType
;
1006 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, AsciiChar
);
1010 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, UnicodeChar
);
1013 case CODE_ATTRIBUTE
:
1014 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, Attribute
);
1017 SizeBytes
= nLength
* CodeSize
;
1020 * For optimization purposes, Windows (and hence ReactOS, too, for
1021 * compatibility reasons) uses a static buffer if no more than eighty
1022 * bytes are written. Otherwise a new buffer is allocated.
1023 * This behaviour is also expected in the server-side.
1025 if (SizeBytes
<= sizeof(WriteOutputCodeRequest
->CodeStaticBuffer
))
1027 WriteOutputCodeRequest
->pCode
= WriteOutputCodeRequest
->CodeStaticBuffer
;
1028 // CaptureBuffer = NULL;
1032 RtlCopyMemory(WriteOutputCodeRequest
->pCode
,
1036 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1038 SetLastError(ERROR_INVALID_ACCESS
);
1039 _SEH2_YIELD(return FALSE
);
1045 /* Allocate a Capture Buffer */
1046 CaptureBuffer
= CsrAllocateCaptureBuffer(1, SizeBytes
);
1047 if (CaptureBuffer
== NULL
)
1049 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
1050 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1054 /* Capture the buffer to write */
1055 CsrCaptureMessageBuffer(CaptureBuffer
,
1058 (PVOID
*)&WriteOutputCodeRequest
->pCode
);
1061 /* Call the server */
1062 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
1064 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepWriteConsoleOutputString
),
1065 sizeof(*WriteOutputCodeRequest
));
1067 /* Check for success */
1068 Success
= NT_SUCCESS(ApiMessage
.Status
);
1070 /* Release the capture buffer if needed */
1071 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
1073 /* Retrieve the results */
1076 *lpNumberOfCodesWritten
= WriteOutputCodeRequest
->NumCodes
;
1079 BaseSetLastNTError(ApiMessage
.Status
);
1081 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1083 SetLastError(ERROR_INVALID_ACCESS
);
1088 /* Return success status */
1095 IntFillConsoleOutputCode(IN HANDLE hConsoleOutput
,
1096 IN CODE_TYPE CodeType
,
1097 IN CODE_ELEMENT Code
,
1099 IN COORD dwWriteCoord
,
1100 OUT LPDWORD lpNumberOfCodesWritten
)
1103 CONSOLE_API_MESSAGE ApiMessage
;
1104 PCONSOLE_FILLOUTPUTCODE FillOutputRequest
= &ApiMessage
.Data
.FillOutputRequest
;
1106 DPRINT("IntFillConsoleOutputCode\n");
1108 if ( (CodeType
!= CODE_ASCII
) &&
1109 (CodeType
!= CODE_UNICODE
) &&
1110 (CodeType
!= CODE_ATTRIBUTE
) )
1112 SetLastError(ERROR_INVALID_PARAMETER
);
1116 /* Set up the data to send to the Console Server */
1117 FillOutputRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
1118 FillOutputRequest
->OutputHandle
= hConsoleOutput
;
1119 FillOutputRequest
->WriteCoord
= dwWriteCoord
;
1120 FillOutputRequest
->CodeType
= CodeType
;
1121 FillOutputRequest
->Code
= Code
;
1122 FillOutputRequest
->NumCodes
= nLength
;
1124 /* Call the server */
1125 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
1127 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepFillConsoleOutput
),
1128 sizeof(*FillOutputRequest
));
1130 /* Check for success */
1131 Success
= NT_SUCCESS(ApiMessage
.Status
);
1133 /* Retrieve the results */
1136 *lpNumberOfCodesWritten
= FillOutputRequest
->NumCodes
;
1139 BaseSetLastNTError(ApiMessage
.Status
);
1141 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1143 SetLastError(ERROR_INVALID_ACCESS
);
1148 /* Return success status */
1153 /* FUNCTIONS ******************************************************************/
1159 /*--------------------------------------------------------------
1166 ReadConsoleW(IN HANDLE hConsoleInput
,
1167 OUT LPVOID lpBuffer
,
1168 IN DWORD nNumberOfCharsToRead
,
1169 OUT LPDWORD lpNumberOfCharsRead
,
1170 IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL
)
1172 return IntReadConsole(hConsoleInput
,
1174 nNumberOfCharsToRead
,
1175 lpNumberOfCharsRead
,
1181 /*--------------------------------------------------------------
1188 ReadConsoleA(IN HANDLE hConsoleInput
,
1189 OUT LPVOID lpBuffer
,
1190 IN DWORD nNumberOfCharsToRead
,
1191 OUT LPDWORD lpNumberOfCharsRead
,
1192 IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL
)
1194 return IntReadConsole(hConsoleInput
,
1196 nNumberOfCharsToRead
,
1197 lpNumberOfCharsRead
,
1203 /*--------------------------------------------------------------
1210 PeekConsoleInputW(IN HANDLE hConsoleInput
,
1211 OUT PINPUT_RECORD lpBuffer
,
1213 OUT LPDWORD lpNumberOfEventsRead
)
1215 return IntGetConsoleInput(hConsoleInput
,
1218 lpNumberOfEventsRead
,
1219 CONSOLE_READ_KEEPEVENT
| CONSOLE_READ_CONTINUE
,
1224 /*--------------------------------------------------------------
1231 PeekConsoleInputA(IN HANDLE hConsoleInput
,
1232 OUT PINPUT_RECORD lpBuffer
,
1234 OUT LPDWORD lpNumberOfEventsRead
)
1236 return IntGetConsoleInput(hConsoleInput
,
1239 lpNumberOfEventsRead
,
1240 CONSOLE_READ_KEEPEVENT
| CONSOLE_READ_CONTINUE
,
1245 /*--------------------------------------------------------------
1252 ReadConsoleInputW(IN HANDLE hConsoleInput
,
1253 OUT PINPUT_RECORD lpBuffer
,
1255 OUT LPDWORD lpNumberOfEventsRead
)
1257 return IntGetConsoleInput(hConsoleInput
,
1260 lpNumberOfEventsRead
,
1266 /*--------------------------------------------------------------
1273 ReadConsoleInputA(IN HANDLE hConsoleInput
,
1274 OUT PINPUT_RECORD lpBuffer
,
1276 OUT LPDWORD lpNumberOfEventsRead
)
1278 return IntGetConsoleInput(hConsoleInput
,
1281 lpNumberOfEventsRead
,
1287 /*--------------------------------------------------------------
1288 * ReadConsoleInputExW
1294 ReadConsoleInputExW(IN HANDLE hConsoleInput
,
1295 OUT PINPUT_RECORD lpBuffer
,
1297 OUT LPDWORD lpNumberOfEventsRead
,
1300 return IntGetConsoleInput(hConsoleInput
,
1303 lpNumberOfEventsRead
,
1309 /*--------------------------------------------------------------
1310 * ReadConsoleInputExA
1316 ReadConsoleInputExA(IN HANDLE hConsoleInput
,
1317 OUT PINPUT_RECORD lpBuffer
,
1319 OUT LPDWORD lpNumberOfEventsRead
,
1322 return IntGetConsoleInput(hConsoleInput
,
1325 lpNumberOfEventsRead
,
1331 /*--------------------------------------------------------------
1332 * ReadConsoleOutputW
1338 ReadConsoleOutputW(IN HANDLE hConsoleOutput
,
1339 OUT PCHAR_INFO lpBuffer
,
1340 IN COORD dwBufferSize
,
1341 IN COORD dwBufferCoord
,
1342 IN OUT PSMALL_RECT lpReadRegion
)
1344 return IntReadConsoleOutput(hConsoleOutput
,
1353 /*--------------------------------------------------------------
1354 * ReadConsoleOutputA
1360 ReadConsoleOutputA(IN HANDLE hConsoleOutput
,
1361 OUT PCHAR_INFO lpBuffer
,
1362 IN COORD dwBufferSize
,
1363 IN COORD dwBufferCoord
,
1364 IN OUT PSMALL_RECT lpReadRegion
)
1366 return IntReadConsoleOutput(hConsoleOutput
,
1375 /*--------------------------------------------------------------
1376 * ReadConsoleOutputCharacterW
1382 ReadConsoleOutputCharacterW(IN HANDLE hConsoleOutput
,
1383 OUT LPWSTR lpCharacter
,
1385 IN COORD dwReadCoord
,
1386 OUT LPDWORD lpNumberOfCharsRead
)
1388 return IntReadConsoleOutputCode(hConsoleOutput
,
1393 lpNumberOfCharsRead
);
1397 /*--------------------------------------------------------------
1398 * ReadConsoleOutputCharacterA
1404 ReadConsoleOutputCharacterA(IN HANDLE hConsoleOutput
,
1405 OUT LPSTR lpCharacter
,
1407 IN COORD dwReadCoord
,
1408 OUT LPDWORD lpNumberOfCharsRead
)
1410 return IntReadConsoleOutputCode(hConsoleOutput
,
1415 lpNumberOfCharsRead
);
1419 /*--------------------------------------------------------------
1420 * ReadConsoleOutputAttribute
1426 ReadConsoleOutputAttribute(IN HANDLE hConsoleOutput
,
1427 OUT LPWORD lpAttribute
,
1429 IN COORD dwReadCoord
,
1430 OUT LPDWORD lpNumberOfAttrsRead
)
1432 return IntReadConsoleOutputCode(hConsoleOutput
,
1437 lpNumberOfAttrsRead
);
1441 /*******************
1443 *******************/
1445 /*--------------------------------------------------------------
1452 WriteConsoleW(IN HANDLE hConsoleOutput
,
1453 IN CONST VOID
*lpBuffer
,
1454 IN DWORD nNumberOfCharsToWrite
,
1455 OUT LPDWORD lpNumberOfCharsWritten
,
1458 return IntWriteConsole(hConsoleOutput
,
1460 nNumberOfCharsToWrite
,
1461 lpNumberOfCharsWritten
,
1467 /*--------------------------------------------------------------
1474 WriteConsoleA(IN HANDLE hConsoleOutput
,
1475 IN CONST VOID
*lpBuffer
,
1476 IN DWORD nNumberOfCharsToWrite
,
1477 OUT LPDWORD lpNumberOfCharsWritten
,
1480 return IntWriteConsole(hConsoleOutput
,
1482 nNumberOfCharsToWrite
,
1483 lpNumberOfCharsWritten
,
1489 /*--------------------------------------------------------------
1490 * WriteConsoleInputW
1496 WriteConsoleInputW(IN HANDLE hConsoleInput
,
1497 IN CONST INPUT_RECORD
*lpBuffer
,
1499 OUT LPDWORD lpNumberOfEventsWritten
)
1501 return IntWriteConsoleInput(hConsoleInput
,
1502 (PINPUT_RECORD
)lpBuffer
,
1504 lpNumberOfEventsWritten
,
1510 /*--------------------------------------------------------------
1511 * WriteConsoleInputA
1517 WriteConsoleInputA(IN HANDLE hConsoleInput
,
1518 IN CONST INPUT_RECORD
*lpBuffer
,
1520 OUT LPDWORD lpNumberOfEventsWritten
)
1522 return IntWriteConsoleInput(hConsoleInput
,
1523 (PINPUT_RECORD
)lpBuffer
,
1525 lpNumberOfEventsWritten
,
1531 /*--------------------------------------------------------------
1532 * WriteConsoleInputVDMW
1538 WriteConsoleInputVDMW(IN HANDLE hConsoleInput
,
1539 IN CONST INPUT_RECORD
*lpBuffer
,
1541 OUT LPDWORD lpNumberOfEventsWritten
)
1543 return IntWriteConsoleInput(hConsoleInput
,
1544 (PINPUT_RECORD
)lpBuffer
,
1546 lpNumberOfEventsWritten
,
1552 /*--------------------------------------------------------------
1553 * WriteConsoleInputVDMA
1559 WriteConsoleInputVDMA(IN HANDLE hConsoleInput
,
1560 IN CONST INPUT_RECORD
*lpBuffer
,
1562 OUT LPDWORD lpNumberOfEventsWritten
)
1564 return IntWriteConsoleInput(hConsoleInput
,
1565 (PINPUT_RECORD
)lpBuffer
,
1567 lpNumberOfEventsWritten
,
1573 /*--------------------------------------------------------------
1574 * WriteConsoleOutputW
1580 WriteConsoleOutputW(IN HANDLE hConsoleOutput
,
1581 IN CONST CHAR_INFO
*lpBuffer
,
1582 IN COORD dwBufferSize
,
1583 IN COORD dwBufferCoord
,
1584 IN OUT PSMALL_RECT lpWriteRegion
)
1586 return IntWriteConsoleOutput(hConsoleOutput
,
1595 /*--------------------------------------------------------------
1596 * WriteConsoleOutputA
1602 WriteConsoleOutputA(IN HANDLE hConsoleOutput
,
1603 IN CONST CHAR_INFO
*lpBuffer
,
1604 IN COORD dwBufferSize
,
1605 IN COORD dwBufferCoord
,
1606 IN OUT PSMALL_RECT lpWriteRegion
)
1608 return IntWriteConsoleOutput(hConsoleOutput
,
1617 /*--------------------------------------------------------------
1618 * WriteConsoleOutputCharacterW
1624 WriteConsoleOutputCharacterW(IN HANDLE hConsoleOutput
,
1625 IN LPCWSTR lpCharacter
,
1627 IN COORD dwWriteCoord
,
1628 OUT LPDWORD lpNumberOfCharsWritten
)
1630 return IntWriteConsoleOutputCode(hConsoleOutput
,
1635 lpNumberOfCharsWritten
);
1639 /*--------------------------------------------------------------
1640 * WriteConsoleOutputCharacterA
1646 WriteConsoleOutputCharacterA(IN HANDLE hConsoleOutput
,
1647 IN LPCSTR lpCharacter
,
1649 IN COORD dwWriteCoord
,
1650 OUT LPDWORD lpNumberOfCharsWritten
)
1652 return IntWriteConsoleOutputCode(hConsoleOutput
,
1657 lpNumberOfCharsWritten
);
1661 /*--------------------------------------------------------------
1662 * WriteConsoleOutputAttribute
1668 WriteConsoleOutputAttribute(IN HANDLE hConsoleOutput
,
1669 IN CONST WORD
*lpAttribute
,
1671 IN COORD dwWriteCoord
,
1672 OUT LPDWORD lpNumberOfAttrsWritten
)
1674 return IntWriteConsoleOutputCode(hConsoleOutput
,
1679 lpNumberOfAttrsWritten
);
1683 /*--------------------------------------------------------------
1684 * FillConsoleOutputCharacterW
1690 FillConsoleOutputCharacterW(IN HANDLE hConsoleOutput
,
1691 IN WCHAR cCharacter
,
1693 IN COORD dwWriteCoord
,
1694 OUT LPDWORD lpNumberOfCharsWritten
)
1697 Code
.UnicodeChar
= cCharacter
;
1698 return IntFillConsoleOutputCode(hConsoleOutput
,
1703 lpNumberOfCharsWritten
);
1707 /*--------------------------------------------------------------
1708 * FillConsoleOutputCharacterA
1714 FillConsoleOutputCharacterA(IN HANDLE hConsoleOutput
,
1717 IN COORD dwWriteCoord
,
1718 LPDWORD lpNumberOfCharsWritten
)
1721 Code
.AsciiChar
= cCharacter
;
1722 return IntFillConsoleOutputCode(hConsoleOutput
,
1727 lpNumberOfCharsWritten
);
1731 /*--------------------------------------------------------------
1732 * FillConsoleOutputAttribute
1738 FillConsoleOutputAttribute(IN HANDLE hConsoleOutput
,
1741 IN COORD dwWriteCoord
,
1742 OUT LPDWORD lpNumberOfAttrsWritten
)
1745 Code
.Attribute
= wAttribute
;
1746 return IntFillConsoleOutputCode(hConsoleOutput
,
1751 lpNumberOfAttrsWritten
);