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 IntReadConsole(IN HANDLE hConsoleInput
,
38 IN DWORD nNumberOfCharsToRead
,
39 OUT LPDWORD lpNumberOfCharsRead
,
40 IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL
,
44 CONSOLE_API_MESSAGE ApiMessage
;
45 PCONSOLE_READCONSOLE ReadConsoleRequest
= &ApiMessage
.Data
.ReadConsoleRequest
;
46 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
47 ULONG CharSize
, SizeBytes
;
49 DPRINT("IntReadConsole\n");
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
;
57 * Retrieve the (current) Input EXE name string and length,
58 * not NULL-terminated (always in UNICODE format).
60 ReadConsoleRequest
->ExeLength
=
61 GetCurrentExeName((PWCHAR
)ReadConsoleRequest
->StaticBuffer
,
62 sizeof(ReadConsoleRequest
->StaticBuffer
));
64 /*** For DEBUGGING purposes ***/
66 UNICODE_STRING ExeName
;
67 ExeName
.Length
= ExeName
.MaximumLength
= ReadConsoleRequest
->ExeLength
;
68 ExeName
.Buffer
= (PWCHAR
)ReadConsoleRequest
->StaticBuffer
;
69 DPRINT1("IntReadConsole(ExeName = %wZ)\n", &ExeName
);
71 /******************************/
73 /* Determine the needed size */
74 CharSize
= (bUnicode
? sizeof(WCHAR
) : sizeof(CHAR
));
75 SizeBytes
= nNumberOfCharsToRead
* CharSize
;
77 ReadConsoleRequest
->CaptureBufferSize
=
78 ReadConsoleRequest
->NumBytes
= SizeBytes
;
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.
86 if (SizeBytes
<= sizeof(ReadConsoleRequest
->StaticBuffer
))
88 ReadConsoleRequest
->Buffer
= ReadConsoleRequest
->StaticBuffer
;
89 // CaptureBuffer = NULL;
93 /* Allocate a Capture Buffer */
94 CaptureBuffer
= CsrAllocateCaptureBuffer(1, SizeBytes
);
95 if (CaptureBuffer
== NULL
)
97 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
98 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
102 /* Allocate space in the Buffer */
103 CsrAllocateMessagePointer(CaptureBuffer
,
105 (PVOID
*)&ReadConsoleRequest
->Buffer
);
108 ReadConsoleRequest
->InitialNumBytes
= 0;
109 ReadConsoleRequest
->CtrlWakeupMask
= 0;
110 ReadConsoleRequest
->ControlKeyState
= 0;
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."
120 if (bUnicode
&& pInputControl
&&
121 pInputControl
->nLength
== sizeof(CONSOLE_READCONSOLE_CONTROL
))
124 if (pInputControl
->nInitialChars
<= nNumberOfCharsToRead
)
126 ReadConsoleRequest
->InitialNumBytes
=
127 pInputControl
->nInitialChars
* sizeof(WCHAR
); // CharSize
129 if (pInputControl
->nInitialChars
!= 0)
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.
139 RtlCopyMemory(ReadConsoleRequest
->Buffer
,
141 ReadConsoleRequest
->InitialNumBytes
);
144 ReadConsoleRequest
->CtrlWakeupMask
= pInputControl
->dwCtrlWakeupMask
;
148 // Status = STATUS_INVALID_PARAMETER;
153 /* We are in a situation where pInputControl has no meaning */
154 pInputControl
= NULL
;
157 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
160 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
161 SetLastError(ERROR_INVALID_ACCESS
);
162 _SEH2_YIELD(return FALSE
);
166 /* FIXME: Check for sanity */
168 if (!NT_SUCCESS(Status) && pInputControl)
170 // Free CaptureBuffer if needed
171 // Set last error to last status
176 /* Call the server */
177 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
179 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepReadConsole
),
180 sizeof(*ReadConsoleRequest
));
182 /* Check for success */
183 Success
= NT_SUCCESS(ApiMessage
.Status
);
185 /* Retrieve the results */
190 *lpNumberOfCharsRead
= ReadConsoleRequest
->NumBytes
/ CharSize
;
192 if (bUnicode
&& pInputControl
)
193 pInputControl
->dwControlKeyState
= ReadConsoleRequest
->ControlKeyState
;
195 RtlCopyMemory(lpBuffer
,
196 ReadConsoleRequest
->Buffer
,
197 ReadConsoleRequest
->NumBytes
);
199 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
201 SetLastError(ERROR_INVALID_ACCESS
);
208 BaseSetLastNTError(ApiMessage
.Status
);
211 /* Release the capture buffer if needed */
212 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
216 /* Yield execution to another thread if Ctrl-C or Ctrl-Break happened */
217 if (ApiMessage
.Status
== STATUS_ALERTED
/* || ApiMessage.Status == STATUS_CANCELLED */)
220 SetLastError(ERROR_OPERATION_ABORTED
); // STATUS_CANCELLED
224 /* Return success status */
231 IntGetConsoleInput(IN HANDLE hConsoleInput
,
232 OUT PINPUT_RECORD lpBuffer
,
234 OUT LPDWORD lpNumberOfEventsRead
,
239 CONSOLE_API_MESSAGE ApiMessage
;
240 PCONSOLE_GETINPUT GetInputRequest
= &ApiMessage
.Data
.GetInputRequest
;
241 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
243 if (!IsConsoleHandle(hConsoleInput
))
247 *lpNumberOfEventsRead
= 0;
248 SetLastError(ERROR_INVALID_HANDLE
);
250 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
252 SetLastError(ERROR_INVALID_ACCESS
);
259 DPRINT("IntGetConsoleInput: %lx %p\n", nLength
, lpNumberOfEventsRead
);
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
;
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.
274 if (nLength
<= sizeof(GetInputRequest
->RecordStaticBuffer
)/sizeof(INPUT_RECORD
))
276 GetInputRequest
->RecordBufPtr
= GetInputRequest
->RecordStaticBuffer
;
277 // CaptureBuffer = NULL;
281 ULONG Size
= nLength
* sizeof(INPUT_RECORD
);
283 /* Allocate a Capture Buffer */
284 CaptureBuffer
= CsrAllocateCaptureBuffer(1, Size
);
285 if (CaptureBuffer
== NULL
)
287 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
288 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
292 /* Allocate space in the Buffer */
293 CsrAllocateMessagePointer(CaptureBuffer
,
295 (PVOID
*)&GetInputRequest
->RecordBufPtr
);
298 /* Call the server */
299 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
301 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepGetConsoleInput
),
302 sizeof(*GetInputRequest
));
304 /* Check for success */
305 Success
= NT_SUCCESS(ApiMessage
.Status
);
307 /* Retrieve the results */
310 DPRINT("Events read: %lx\n", GetInputRequest
->NumRecords
);
311 *lpNumberOfEventsRead
= GetInputRequest
->NumRecords
;
315 RtlCopyMemory(lpBuffer
,
316 GetInputRequest
->RecordBufPtr
,
317 GetInputRequest
->NumRecords
* sizeof(INPUT_RECORD
));
321 BaseSetLastNTError(ApiMessage
.Status
);
324 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
326 SetLastError(ERROR_INVALID_ACCESS
);
331 /* Release the capture buffer if needed */
332 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
334 /* Return success status */
341 IntReadConsoleOutput(IN HANDLE hConsoleOutput
,
342 OUT PCHAR_INFO lpBuffer
,
343 IN COORD dwBufferSize
,
344 IN COORD dwBufferCoord
,
345 IN OUT PSMALL_RECT lpReadRegion
,
349 CONSOLE_API_MESSAGE ApiMessage
;
350 PCONSOLE_READOUTPUT ReadOutputRequest
= &ApiMessage
.Data
.ReadOutputRequest
;
351 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
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
;
361 /* Update lpReadRegion */
364 SizeX
= min(dwBufferSize
.X
- dwBufferCoord
.X
, ConioRectWidth(lpReadRegion
));
365 SizeY
= min(dwBufferSize
.Y
- dwBufferCoord
.Y
, ConioRectHeight(lpReadRegion
));
366 if (SizeX
<= 0 || SizeY
<= 0)
368 SetLastError(ERROR_INVALID_PARAMETER
);
369 _SEH2_YIELD(return FALSE
);
371 lpReadRegion
->Right
= lpReadRegion
->Left
+ SizeX
- 1;
372 lpReadRegion
->Bottom
= lpReadRegion
->Top
+ SizeY
- 1;
374 ReadOutputRequest
->ReadRegion
= *lpReadRegion
;
376 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
378 SetLastError(ERROR_INVALID_ACCESS
);
379 _SEH2_YIELD(return FALSE
);
383 NumCells
= SizeX
* SizeY
;
384 DPRINT("IntReadConsoleOutput: (%d x %d)\n", SizeX
, SizeY
);
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.
394 ReadOutputRequest
->CharInfo
= &ReadOutputRequest
->StaticBuffer
;
395 // CaptureBuffer = NULL;
399 ULONG Size
= NumCells
* sizeof(CHAR_INFO
);
401 /* Allocate a Capture Buffer */
402 CaptureBuffer
= CsrAllocateCaptureBuffer(1, Size
);
403 if (CaptureBuffer
== NULL
)
405 DPRINT1("CsrAllocateCaptureBuffer failed with size %ld!\n", Size
);
406 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
410 /* Allocate space in the Buffer */
411 CsrAllocateMessagePointer(CaptureBuffer
,
413 (PVOID
*)&ReadOutputRequest
->CharInfo
);
416 /* Call the server */
417 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
419 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepReadConsoleOutput
),
420 sizeof(*ReadOutputRequest
));
422 /* Check for success */
423 Success
= NT_SUCCESS(ApiMessage
.Status
);
425 /* Retrieve the results */
428 *lpReadRegion
= ReadOutputRequest
->ReadRegion
;
437 /* Copy into the buffer */
439 SizeX
= ReadOutputRequest
->ReadRegion
.Right
-
440 ReadOutputRequest
->ReadRegion
.Left
+ 1;
442 for (y
= 0, Y
= ReadOutputRequest
->ReadRegion
.Top
; Y
<= ReadOutputRequest
->ReadRegion
.Bottom
; ++y
, ++Y
)
444 RtlCopyMemory(lpBuffer
+ (y
+ dwBufferCoord
.Y
) * dwBufferSize
.X
+ dwBufferCoord
.X
,
445 ReadOutputRequest
->CharInfo
+ y
* SizeX
,
446 SizeX
* sizeof(CHAR_INFO
));
448 for (x
= 0, X
= ReadOutputRequest
->ReadRegion
.Left
; X
<= ReadOutputRequest
->ReadRegion
.Right
; ++x
, ++X
)
450 *(lpBuffer
+ (y
+ dwBufferCoord
.Y
) * dwBufferSize
.X
+ (x
+ dwBufferCoord
.X
)) =
451 *(ReadOutputRequest
->CharInfo
+ y
* SizeX
+ x
);
458 BaseSetLastNTError(ApiMessage
.Status
);
461 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
463 SetLastError(ERROR_INVALID_ACCESS
);
468 /* Release the capture buffer if needed */
469 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
471 /* Return success status */
478 IntReadConsoleOutputCode(IN HANDLE hConsoleOutput
,
479 IN CODE_TYPE CodeType
,
482 IN COORD dwReadCoord
,
483 OUT LPDWORD lpNumberOfCodesRead
)
486 CONSOLE_API_MESSAGE ApiMessage
;
487 PCONSOLE_READOUTPUTCODE ReadOutputCodeRequest
= &ApiMessage
.Data
.ReadOutputCodeRequest
;
488 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
489 ULONG CodeSize
, SizeBytes
;
491 DPRINT("IntReadConsoleOutputCode\n");
493 if ( (CodeType
!= CODE_ASCII
) &&
494 (CodeType
!= CODE_UNICODE
) &&
495 (CodeType
!= CODE_ATTRIBUTE
) )
497 SetLastError(ERROR_INVALID_PARAMETER
);
501 /* Set up the data to send to the Console Server */
502 ReadOutputCodeRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
503 ReadOutputCodeRequest
->OutputHandle
= hConsoleOutput
;
504 ReadOutputCodeRequest
->Coord
= dwReadCoord
;
505 ReadOutputCodeRequest
->NumCodes
= nLength
;
507 /* Determine the needed size */
508 ReadOutputCodeRequest
->CodeType
= CodeType
;
512 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, AsciiChar
);
516 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, UnicodeChar
);
520 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, Attribute
);
523 SizeBytes
= nLength
* CodeSize
;
526 * For optimization purposes, Windows (and hence ReactOS, too, for
527 * compatibility reasons) uses a static buffer if no more than eighty
528 * bytes are read. Otherwise a new buffer is allocated.
529 * This behaviour is also expected in the server-side.
531 if (SizeBytes
<= sizeof(ReadOutputCodeRequest
->CodeStaticBuffer
))
533 ReadOutputCodeRequest
->pCode
= ReadOutputCodeRequest
->CodeStaticBuffer
;
534 // CaptureBuffer = NULL;
538 /* Allocate a Capture Buffer */
539 CaptureBuffer
= CsrAllocateCaptureBuffer(1, SizeBytes
);
540 if (CaptureBuffer
== NULL
)
542 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
543 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
547 /* Allocate space in the Buffer */
548 CsrAllocateMessagePointer(CaptureBuffer
,
550 (PVOID
*)&ReadOutputCodeRequest
->pCode
);
553 /* Call the server */
554 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
556 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepReadConsoleOutputString
),
557 sizeof(*ReadOutputCodeRequest
));
559 /* Check for success */
560 Success
= NT_SUCCESS(ApiMessage
.Status
);
562 /* Retrieve the results */
565 *lpNumberOfCodesRead
= ReadOutputCodeRequest
->NumCodes
;
570 ReadOutputCodeRequest
->pCode
,
571 ReadOutputCodeRequest
->NumCodes
* CodeSize
);
575 BaseSetLastNTError(ApiMessage
.Status
);
578 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
580 SetLastError(ERROR_INVALID_ACCESS
);
585 /* Release the capture buffer if needed */
586 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
588 /* Return success status */
599 IntWriteConsole(IN HANDLE hConsoleOutput
,
601 IN DWORD nNumberOfCharsToWrite
,
602 OUT LPDWORD lpNumberOfCharsWritten
,
607 CONSOLE_API_MESSAGE ApiMessage
;
608 PCONSOLE_WRITECONSOLE WriteConsoleRequest
= &ApiMessage
.Data
.WriteConsoleRequest
;
609 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
610 ULONG CharSize
, SizeBytes
;
612 DPRINT("IntWriteConsole\n");
614 /* Set up the data to send to the Console Server */
615 WriteConsoleRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
616 WriteConsoleRequest
->OutputHandle
= hConsoleOutput
;
617 WriteConsoleRequest
->Unicode
= bUnicode
;
619 /* Those members are unused by the client, on Windows */
620 WriteConsoleRequest
->Reserved1
= 0;
621 // WriteConsoleRequest->Reserved2 = {0};
623 /* Determine the needed size */
624 CharSize
= (bUnicode
? sizeof(WCHAR
) : sizeof(CHAR
));
625 SizeBytes
= nNumberOfCharsToWrite
* CharSize
;
627 WriteConsoleRequest
->NumBytes
= SizeBytes
;
630 * For optimization purposes, Windows (and hence ReactOS, too, for
631 * compatibility reasons) uses a static buffer if no more than eighty
632 * bytes are written. Otherwise a new buffer is allocated.
633 * This behaviour is also expected in the server-side.
635 if (SizeBytes
<= sizeof(WriteConsoleRequest
->StaticBuffer
))
637 WriteConsoleRequest
->Buffer
= WriteConsoleRequest
->StaticBuffer
;
638 // CaptureBuffer = NULL;
639 WriteConsoleRequest
->UsingStaticBuffer
= TRUE
;
643 RtlCopyMemory(WriteConsoleRequest
->Buffer
,
647 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
649 SetLastError(ERROR_INVALID_ACCESS
);
650 _SEH2_YIELD(return FALSE
);
656 /* Allocate a Capture Buffer */
657 CaptureBuffer
= CsrAllocateCaptureBuffer(1, SizeBytes
);
658 if (CaptureBuffer
== NULL
)
660 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
661 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
665 /* Capture the buffer to write */
666 CsrCaptureMessageBuffer(CaptureBuffer
,
669 (PVOID
*)&WriteConsoleRequest
->Buffer
);
670 WriteConsoleRequest
->UsingStaticBuffer
= FALSE
;
673 /* Call the server */
674 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
676 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepWriteConsole
),
677 sizeof(*WriteConsoleRequest
));
679 /* Check for success */
680 Success
= NT_SUCCESS(ApiMessage
.Status
);
682 /* Release the capture buffer if needed */
683 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
685 /* Retrieve the results */
690 *lpNumberOfCharsWritten
= WriteConsoleRequest
->NumBytes
/ CharSize
;
692 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
694 SetLastError(ERROR_INVALID_ACCESS
);
701 BaseSetLastNTError(ApiMessage
.Status
);
704 /* Return success status */
711 IntWriteConsoleInput(IN HANDLE hConsoleInput
,
712 IN PINPUT_RECORD lpBuffer
,
714 OUT LPDWORD lpNumberOfEventsWritten
,
716 IN BOOLEAN bAppendToEnd
)
719 CONSOLE_API_MESSAGE ApiMessage
;
720 PCONSOLE_WRITEINPUT WriteInputRequest
= &ApiMessage
.Data
.WriteInputRequest
;
721 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
723 DPRINT("IntWriteConsoleInput: %lx %p\n", nLength
, lpNumberOfEventsWritten
);
725 /* Set up the data to send to the Console Server */
726 WriteInputRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
727 WriteInputRequest
->InputHandle
= hConsoleInput
;
728 WriteInputRequest
->NumRecords
= nLength
;
729 WriteInputRequest
->Unicode
= bUnicode
;
730 WriteInputRequest
->AppendToEnd
= bAppendToEnd
;
733 * For optimization purposes, Windows (and hence ReactOS, too, for
734 * compatibility reasons) uses a static buffer if no more than five
735 * input records are written. Otherwise a new buffer is allocated.
736 * This behaviour is also expected in the server-side.
738 if (nLength
<= sizeof(WriteInputRequest
->RecordStaticBuffer
)/sizeof(INPUT_RECORD
))
740 WriteInputRequest
->RecordBufPtr
= WriteInputRequest
->RecordStaticBuffer
;
741 // CaptureBuffer = NULL;
745 RtlCopyMemory(WriteInputRequest
->RecordBufPtr
,
747 nLength
* sizeof(INPUT_RECORD
));
749 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
751 SetLastError(ERROR_INVALID_ACCESS
);
752 _SEH2_YIELD(return FALSE
);
758 ULONG Size
= nLength
* sizeof(INPUT_RECORD
);
760 /* Allocate a Capture Buffer */
761 CaptureBuffer
= CsrAllocateCaptureBuffer(1, Size
);
762 if (CaptureBuffer
== NULL
)
764 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
765 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
769 /* Capture the user buffer */
770 CsrCaptureMessageBuffer(CaptureBuffer
,
773 (PVOID
*)&WriteInputRequest
->RecordBufPtr
);
776 /* Call the server */
777 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
779 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepWriteConsoleInput
),
780 sizeof(*WriteInputRequest
));
782 /* Check for success */
783 Success
= NT_SUCCESS(ApiMessage
.Status
);
785 /* Release the capture buffer if needed */
786 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
788 /* Retrieve the results */
791 DPRINT("Events written: %lx\n", WriteInputRequest
->NumRecords
);
792 *lpNumberOfEventsWritten
= WriteInputRequest
->NumRecords
;
795 BaseSetLastNTError(ApiMessage
.Status
);
797 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
799 SetLastError(ERROR_INVALID_ACCESS
);
804 /* Return success status */
811 IntWriteConsoleOutput(IN HANDLE hConsoleOutput
,
812 IN CONST CHAR_INFO
*lpBuffer
,
813 IN COORD dwBufferSize
,
814 IN COORD dwBufferCoord
,
815 IN OUT PSMALL_RECT lpWriteRegion
,
819 CONSOLE_API_MESSAGE ApiMessage
;
820 PCONSOLE_WRITEOUTPUT WriteOutputRequest
= &ApiMessage
.Data
.WriteOutputRequest
;
821 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
826 /* Set up the data to send to the Console Server */
827 WriteOutputRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
828 WriteOutputRequest
->OutputHandle
= hConsoleOutput
;
829 WriteOutputRequest
->Unicode
= bUnicode
;
831 /* Update lpWriteRegion */
834 SizeX
= min(dwBufferSize
.X
- dwBufferCoord
.X
, ConioRectWidth(lpWriteRegion
));
835 SizeY
= min(dwBufferSize
.Y
- dwBufferCoord
.Y
, ConioRectHeight(lpWriteRegion
));
836 if (SizeX
<= 0 || SizeY
<= 0)
838 SetLastError(ERROR_INVALID_PARAMETER
);
839 _SEH2_YIELD(return FALSE
);
841 lpWriteRegion
->Right
= lpWriteRegion
->Left
+ SizeX
- 1;
842 lpWriteRegion
->Bottom
= lpWriteRegion
->Top
+ SizeY
- 1;
844 WriteOutputRequest
->WriteRegion
= *lpWriteRegion
;
846 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
848 SetLastError(ERROR_INVALID_ACCESS
);
849 _SEH2_YIELD(return FALSE
);
853 NumCells
= SizeX
* SizeY
;
854 DPRINT("IntWriteConsoleOutput: (%d x %d)\n", SizeX
, SizeY
);
857 * For optimization purposes, Windows (and hence ReactOS, too, for
858 * compatibility reasons) uses a static buffer if no more than one
859 * cell is written. Otherwise a new buffer is allocated.
860 * This behaviour is also expected in the server-side.
864 WriteOutputRequest
->CharInfo
= &WriteOutputRequest
->StaticBuffer
;
865 // CaptureBuffer = NULL;
866 WriteOutputRequest
->UseVirtualMemory
= FALSE
;
870 ULONG Size
= NumCells
* sizeof(CHAR_INFO
);
872 /* Allocate a Capture Buffer */
873 CaptureBuffer
= CsrAllocateCaptureBuffer(1, Size
);
876 /* Allocate space in the Buffer */
877 CsrAllocateMessagePointer(CaptureBuffer
,
879 (PVOID
*)&WriteOutputRequest
->CharInfo
);
880 WriteOutputRequest
->UseVirtualMemory
= FALSE
;
885 * CsrAllocateCaptureBuffer failed because we tried to allocate
886 * a too large (>= 64 kB, size of the CSR heap) data buffer.
887 * To circumvent this, Windows uses a trick (that we reproduce for
888 * compatibility reasons): we allocate a heap buffer in the process'
889 * memory, and CSR will read it via NtReadVirtualMemory.
891 DPRINT1("CsrAllocateCaptureBuffer failed with size %ld, let's use local heap buffer...\n", Size
);
893 WriteOutputRequest
->CharInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, Size
);
894 WriteOutputRequest
->UseVirtualMemory
= TRUE
;
896 /* Bail out if we still cannot allocate memory */
897 if (WriteOutputRequest
->CharInfo
== NULL
)
899 DPRINT1("Failed to allocate heap buffer with size %ld!\n", Size
);
900 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
906 /* Capture the user buffer contents */
914 /* Copy into the buffer */
916 SizeX
= WriteOutputRequest
->WriteRegion
.Right
-
917 WriteOutputRequest
->WriteRegion
.Left
+ 1;
919 for (y
= 0, Y
= WriteOutputRequest
->WriteRegion
.Top
; Y
<= WriteOutputRequest
->WriteRegion
.Bottom
; ++y
, ++Y
)
921 RtlCopyMemory(WriteOutputRequest
->CharInfo
+ y
* SizeX
,
922 lpBuffer
+ (y
+ dwBufferCoord
.Y
) * dwBufferSize
.X
+ dwBufferCoord
.X
,
923 SizeX
* sizeof(CHAR_INFO
));
925 for (x
= 0, X
= WriteOutputRequest
->WriteRegion
.Left
; X
<= WriteOutputRequest
->WriteRegion
.Right
; ++x
, ++X
)
927 *(WriteOutputRequest
->CharInfo
+ y
* SizeX
+ x
) =
928 *(lpBuffer
+ (y
+ dwBufferCoord
.Y
) * dwBufferSize
.X
+ (x
+ dwBufferCoord
.X
));
933 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
935 SetLastError(ERROR_INVALID_ACCESS
);
936 _SEH2_YIELD(return FALSE
);
940 /* Call the server */
941 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
943 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepWriteConsoleOutput
),
944 sizeof(*WriteOutputRequest
));
946 /* Check for success */
947 Success
= NT_SUCCESS(ApiMessage
.Status
);
949 /* Release the capture buffer if needed */
952 CsrFreeCaptureBuffer(CaptureBuffer
);
956 /* If we used a heap buffer, free it */
957 if (WriteOutputRequest
->UseVirtualMemory
)
958 RtlFreeHeap(RtlGetProcessHeap(), 0, WriteOutputRequest
->CharInfo
);
961 /* Retrieve the results */
964 *lpWriteRegion
= WriteOutputRequest
->WriteRegion
;
967 BaseSetLastNTError(ApiMessage
.Status
);
969 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
971 SetLastError(ERROR_INVALID_ACCESS
);
976 /* Return success status */
983 IntWriteConsoleOutputCode(IN HANDLE hConsoleOutput
,
984 IN CODE_TYPE CodeType
,
985 IN CONST VOID
*pCode
,
987 IN COORD dwWriteCoord
,
988 OUT LPDWORD lpNumberOfCodesWritten
)
991 CONSOLE_API_MESSAGE ApiMessage
;
992 PCONSOLE_WRITEOUTPUTCODE WriteOutputCodeRequest
= &ApiMessage
.Data
.WriteOutputCodeRequest
;
993 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
994 ULONG CodeSize
, SizeBytes
;
996 if ( (CodeType
!= CODE_ASCII
) &&
997 (CodeType
!= CODE_UNICODE
) &&
998 (CodeType
!= CODE_ATTRIBUTE
) )
1000 SetLastError(ERROR_INVALID_PARAMETER
);
1004 DPRINT("IntWriteConsoleOutputCode\n");
1006 /* Set up the data to send to the Console Server */
1007 WriteOutputCodeRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
1008 WriteOutputCodeRequest
->OutputHandle
= hConsoleOutput
;
1009 WriteOutputCodeRequest
->Coord
= dwWriteCoord
;
1010 WriteOutputCodeRequest
->NumCodes
= nLength
;
1012 /* Determine the needed size */
1013 WriteOutputCodeRequest
->CodeType
= CodeType
;
1017 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, AsciiChar
);
1021 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, UnicodeChar
);
1024 case CODE_ATTRIBUTE
:
1025 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, Attribute
);
1028 SizeBytes
= nLength
* CodeSize
;
1031 * For optimization purposes, Windows (and hence ReactOS, too, for
1032 * compatibility reasons) uses a static buffer if no more than eighty
1033 * bytes are written. Otherwise a new buffer is allocated.
1034 * This behaviour is also expected in the server-side.
1036 if (SizeBytes
<= sizeof(WriteOutputCodeRequest
->CodeStaticBuffer
))
1038 WriteOutputCodeRequest
->pCode
= WriteOutputCodeRequest
->CodeStaticBuffer
;
1039 // CaptureBuffer = NULL;
1043 RtlCopyMemory(WriteOutputCodeRequest
->pCode
,
1047 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1049 SetLastError(ERROR_INVALID_ACCESS
);
1050 _SEH2_YIELD(return FALSE
);
1056 /* Allocate a Capture Buffer */
1057 CaptureBuffer
= CsrAllocateCaptureBuffer(1, SizeBytes
);
1058 if (CaptureBuffer
== NULL
)
1060 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
1061 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1065 /* Capture the buffer to write */
1066 CsrCaptureMessageBuffer(CaptureBuffer
,
1069 (PVOID
*)&WriteOutputCodeRequest
->pCode
);
1072 /* Call the server */
1073 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
1075 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepWriteConsoleOutputString
),
1076 sizeof(*WriteOutputCodeRequest
));
1078 /* Check for success */
1079 Success
= NT_SUCCESS(ApiMessage
.Status
);
1081 /* Release the capture buffer if needed */
1082 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
1084 /* Retrieve the results */
1087 *lpNumberOfCodesWritten
= WriteOutputCodeRequest
->NumCodes
;
1090 BaseSetLastNTError(ApiMessage
.Status
);
1092 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1094 SetLastError(ERROR_INVALID_ACCESS
);
1099 /* Return success status */
1106 IntFillConsoleOutputCode(IN HANDLE hConsoleOutput
,
1107 IN CODE_TYPE CodeType
,
1108 IN CODE_ELEMENT Code
,
1110 IN COORD dwWriteCoord
,
1111 OUT LPDWORD lpNumberOfCodesWritten
)
1114 CONSOLE_API_MESSAGE ApiMessage
;
1115 PCONSOLE_FILLOUTPUTCODE FillOutputRequest
= &ApiMessage
.Data
.FillOutputRequest
;
1117 DPRINT("IntFillConsoleOutputCode\n");
1119 if ( (CodeType
!= CODE_ASCII
) &&
1120 (CodeType
!= CODE_UNICODE
) &&
1121 (CodeType
!= CODE_ATTRIBUTE
) )
1123 SetLastError(ERROR_INVALID_PARAMETER
);
1127 /* Set up the data to send to the Console Server */
1128 FillOutputRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
1129 FillOutputRequest
->OutputHandle
= hConsoleOutput
;
1130 FillOutputRequest
->WriteCoord
= dwWriteCoord
;
1131 FillOutputRequest
->CodeType
= CodeType
;
1132 FillOutputRequest
->Code
= Code
;
1133 FillOutputRequest
->NumCodes
= nLength
;
1135 /* Call the server */
1136 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
1138 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepFillConsoleOutput
),
1139 sizeof(*FillOutputRequest
));
1141 /* Check for success */
1142 Success
= NT_SUCCESS(ApiMessage
.Status
);
1144 /* Retrieve the results */
1147 *lpNumberOfCodesWritten
= FillOutputRequest
->NumCodes
;
1150 BaseSetLastNTError(ApiMessage
.Status
);
1152 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1154 SetLastError(ERROR_INVALID_ACCESS
);
1159 /* Return success status */
1164 /* FUNCTIONS ******************************************************************/
1176 ReadConsoleW(IN HANDLE hConsoleInput
,
1177 OUT LPVOID lpBuffer
,
1178 IN DWORD nNumberOfCharsToRead
,
1179 OUT LPDWORD lpNumberOfCharsRead
,
1180 IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL
)
1182 return IntReadConsole(hConsoleInput
,
1184 nNumberOfCharsToRead
,
1185 lpNumberOfCharsRead
,
1197 ReadConsoleA(IN HANDLE hConsoleInput
,
1198 OUT LPVOID lpBuffer
,
1199 IN DWORD nNumberOfCharsToRead
,
1200 OUT LPDWORD lpNumberOfCharsRead
,
1201 IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL
)
1203 return IntReadConsole(hConsoleInput
,
1205 nNumberOfCharsToRead
,
1206 lpNumberOfCharsRead
,
1218 PeekConsoleInputW(IN HANDLE hConsoleInput
,
1219 OUT PINPUT_RECORD lpBuffer
,
1221 OUT LPDWORD lpNumberOfEventsRead
)
1223 return IntGetConsoleInput(hConsoleInput
,
1226 lpNumberOfEventsRead
,
1227 CONSOLE_READ_KEEPEVENT
| CONSOLE_READ_CONTINUE
,
1238 PeekConsoleInputA(IN HANDLE hConsoleInput
,
1239 OUT PINPUT_RECORD lpBuffer
,
1241 OUT LPDWORD lpNumberOfEventsRead
)
1243 return IntGetConsoleInput(hConsoleInput
,
1246 lpNumberOfEventsRead
,
1247 CONSOLE_READ_KEEPEVENT
| CONSOLE_READ_CONTINUE
,
1258 ReadConsoleInputW(IN HANDLE hConsoleInput
,
1259 OUT PINPUT_RECORD lpBuffer
,
1261 OUT LPDWORD lpNumberOfEventsRead
)
1263 return IntGetConsoleInput(hConsoleInput
,
1266 lpNumberOfEventsRead
,
1278 ReadConsoleInputA(IN HANDLE hConsoleInput
,
1279 OUT PINPUT_RECORD lpBuffer
,
1281 OUT LPDWORD lpNumberOfEventsRead
)
1283 return IntGetConsoleInput(hConsoleInput
,
1286 lpNumberOfEventsRead
,
1298 ReadConsoleInputExW(IN HANDLE hConsoleInput
,
1299 OUT PINPUT_RECORD lpBuffer
,
1301 OUT LPDWORD lpNumberOfEventsRead
,
1304 return IntGetConsoleInput(hConsoleInput
,
1307 lpNumberOfEventsRead
,
1319 ReadConsoleInputExA(IN HANDLE hConsoleInput
,
1320 OUT PINPUT_RECORD lpBuffer
,
1322 OUT LPDWORD lpNumberOfEventsRead
,
1325 return IntGetConsoleInput(hConsoleInput
,
1328 lpNumberOfEventsRead
,
1340 ReadConsoleOutputW(IN HANDLE hConsoleOutput
,
1341 OUT PCHAR_INFO lpBuffer
,
1342 IN COORD dwBufferSize
,
1343 IN COORD dwBufferCoord
,
1344 IN OUT PSMALL_RECT lpReadRegion
)
1346 return IntReadConsoleOutput(hConsoleOutput
,
1361 ReadConsoleOutputA(IN HANDLE hConsoleOutput
,
1362 OUT PCHAR_INFO lpBuffer
,
1363 IN COORD dwBufferSize
,
1364 IN COORD dwBufferCoord
,
1365 IN OUT PSMALL_RECT lpReadRegion
)
1367 return IntReadConsoleOutput(hConsoleOutput
,
1382 ReadConsoleOutputCharacterW(IN HANDLE hConsoleOutput
,
1383 OUT LPWSTR lpCharacter
,
1385 IN COORD dwReadCoord
,
1386 OUT LPDWORD lpNumberOfCharsRead
)
1388 return IntReadConsoleOutputCode(hConsoleOutput
,
1393 lpNumberOfCharsRead
);
1403 ReadConsoleOutputCharacterA(IN HANDLE hConsoleOutput
,
1404 OUT LPSTR lpCharacter
,
1406 IN COORD dwReadCoord
,
1407 OUT LPDWORD lpNumberOfCharsRead
)
1409 return IntReadConsoleOutputCode(hConsoleOutput
,
1414 lpNumberOfCharsRead
);
1424 ReadConsoleOutputAttribute(IN HANDLE hConsoleOutput
,
1425 OUT LPWORD lpAttribute
,
1427 IN COORD dwReadCoord
,
1428 OUT LPDWORD lpNumberOfAttrsRead
)
1430 return IntReadConsoleOutputCode(hConsoleOutput
,
1435 lpNumberOfAttrsRead
);
1439 /*******************
1441 *******************/
1449 WriteConsoleW(IN HANDLE hConsoleOutput
,
1450 IN CONST VOID
*lpBuffer
,
1451 IN DWORD nNumberOfCharsToWrite
,
1452 OUT LPDWORD lpNumberOfCharsWritten
,
1455 return IntWriteConsole(hConsoleOutput
,
1457 nNumberOfCharsToWrite
,
1458 lpNumberOfCharsWritten
,
1470 WriteConsoleA(IN HANDLE hConsoleOutput
,
1471 IN CONST VOID
*lpBuffer
,
1472 IN DWORD nNumberOfCharsToWrite
,
1473 OUT LPDWORD lpNumberOfCharsWritten
,
1476 return IntWriteConsole(hConsoleOutput
,
1478 nNumberOfCharsToWrite
,
1479 lpNumberOfCharsWritten
,
1491 WriteConsoleInputW(IN HANDLE hConsoleInput
,
1492 IN CONST INPUT_RECORD
*lpBuffer
,
1494 OUT LPDWORD lpNumberOfEventsWritten
)
1496 return IntWriteConsoleInput(hConsoleInput
,
1497 (PINPUT_RECORD
)lpBuffer
,
1499 lpNumberOfEventsWritten
,
1511 WriteConsoleInputA(IN HANDLE hConsoleInput
,
1512 IN CONST INPUT_RECORD
*lpBuffer
,
1514 OUT LPDWORD lpNumberOfEventsWritten
)
1516 return IntWriteConsoleInput(hConsoleInput
,
1517 (PINPUT_RECORD
)lpBuffer
,
1519 lpNumberOfEventsWritten
,
1531 WriteConsoleInputVDMW(IN HANDLE hConsoleInput
,
1532 IN CONST INPUT_RECORD
*lpBuffer
,
1534 OUT LPDWORD lpNumberOfEventsWritten
)
1536 return IntWriteConsoleInput(hConsoleInput
,
1537 (PINPUT_RECORD
)lpBuffer
,
1539 lpNumberOfEventsWritten
,
1551 WriteConsoleInputVDMA(IN HANDLE hConsoleInput
,
1552 IN CONST INPUT_RECORD
*lpBuffer
,
1554 OUT LPDWORD lpNumberOfEventsWritten
)
1556 return IntWriteConsoleInput(hConsoleInput
,
1557 (PINPUT_RECORD
)lpBuffer
,
1559 lpNumberOfEventsWritten
,
1571 WriteConsoleOutputW(IN HANDLE hConsoleOutput
,
1572 IN CONST CHAR_INFO
*lpBuffer
,
1573 IN COORD dwBufferSize
,
1574 IN COORD dwBufferCoord
,
1575 IN OUT PSMALL_RECT lpWriteRegion
)
1577 return IntWriteConsoleOutput(hConsoleOutput
,
1592 WriteConsoleOutputA(IN HANDLE hConsoleOutput
,
1593 IN CONST CHAR_INFO
*lpBuffer
,
1594 IN COORD dwBufferSize
,
1595 IN COORD dwBufferCoord
,
1596 IN OUT PSMALL_RECT lpWriteRegion
)
1598 return IntWriteConsoleOutput(hConsoleOutput
,
1613 WriteConsoleOutputCharacterW(IN HANDLE hConsoleOutput
,
1614 IN LPCWSTR lpCharacter
,
1616 IN COORD dwWriteCoord
,
1617 OUT LPDWORD lpNumberOfCharsWritten
)
1619 return IntWriteConsoleOutputCode(hConsoleOutput
,
1624 lpNumberOfCharsWritten
);
1634 WriteConsoleOutputCharacterA(IN HANDLE hConsoleOutput
,
1635 IN LPCSTR lpCharacter
,
1637 IN COORD dwWriteCoord
,
1638 OUT LPDWORD lpNumberOfCharsWritten
)
1640 return IntWriteConsoleOutputCode(hConsoleOutput
,
1645 lpNumberOfCharsWritten
);
1655 WriteConsoleOutputAttribute(IN HANDLE hConsoleOutput
,
1656 IN CONST WORD
*lpAttribute
,
1658 IN COORD dwWriteCoord
,
1659 OUT LPDWORD lpNumberOfAttrsWritten
)
1661 return IntWriteConsoleOutputCode(hConsoleOutput
,
1666 lpNumberOfAttrsWritten
);
1676 FillConsoleOutputCharacterW(IN HANDLE hConsoleOutput
,
1677 IN WCHAR cCharacter
,
1679 IN COORD dwWriteCoord
,
1680 OUT LPDWORD lpNumberOfCharsWritten
)
1683 Code
.UnicodeChar
= cCharacter
;
1684 return IntFillConsoleOutputCode(hConsoleOutput
,
1689 lpNumberOfCharsWritten
);
1699 FillConsoleOutputCharacterA(IN HANDLE hConsoleOutput
,
1702 IN COORD dwWriteCoord
,
1703 LPDWORD lpNumberOfCharsWritten
)
1706 Code
.AsciiChar
= cCharacter
;
1707 return IntFillConsoleOutputCode(hConsoleOutput
,
1712 lpNumberOfCharsWritten
);
1722 FillConsoleOutputAttribute(IN HANDLE hConsoleOutput
,
1725 IN COORD dwWriteCoord
,
1726 OUT LPDWORD lpNumberOfAttrsWritten
)
1729 Code
.Attribute
= wAttribute
;
1730 return IntFillConsoleOutputCode(hConsoleOutput
,
1735 lpNumberOfAttrsWritten
);