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 /* PRIVATE FUNCTIONS **********************************************************/
29 GetConsoleInputExeNameW(DWORD nBufferLength
, LPWSTR lpBuffer
);
33 IntReadConsole(IN HANDLE hConsoleInput
,
35 IN DWORD nNumberOfCharsToRead
,
36 OUT LPDWORD lpNumberOfCharsRead
,
37 IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL
,
41 CONSOLE_API_MESSAGE ApiMessage
;
42 PCONSOLE_READCONSOLE ReadConsoleRequest
= &ApiMessage
.Data
.ReadConsoleRequest
;
43 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
44 ULONG CharSize
, SizeBytes
;
46 DPRINT("IntReadConsole\n");
48 /* Set up the data to send to the Console Server */
49 ReadConsoleRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
50 ReadConsoleRequest
->InputHandle
= hConsoleInput
;
51 ReadConsoleRequest
->Unicode
= bUnicode
;
54 * Retrieve the current console executable name string and length (always
56 * FIXME: Do not use GetConsoleInputExeNameW but use something else...
58 // 1- Get the exe name length in characters, including NULL character.
59 ReadConsoleRequest
->ExeLength
=
60 GetConsoleInputExeNameW(0, (PWCHAR
)ReadConsoleRequest
->StaticBuffer
);
61 // 2- Get the exe name (GetConsoleInputExeNameW returns 1 in case of success).
62 if (GetConsoleInputExeNameW(ReadConsoleRequest
->ExeLength
,
63 (PWCHAR
)ReadConsoleRequest
->StaticBuffer
) != 1)
66 ReadConsoleRequest
->ExeLength
= 0;
70 // Remove the NULL character, and convert in number of bytes.
71 ReadConsoleRequest
->ExeLength
--;
72 ReadConsoleRequest
->ExeLength
*= sizeof(WCHAR
);
75 /*** For DEBUGGING purposes ***/
77 UNICODE_STRING ExeName
;
78 ExeName
.Length
= ExeName
.MaximumLength
= ReadConsoleRequest
->ExeLength
;
79 ExeName
.Buffer
= (PWCHAR
)ReadConsoleRequest
->StaticBuffer
;
80 DPRINT1("IntReadConsole(ExeName = %wZ)\n", &ExeName
);
82 /******************************/
84 /* Determine the needed size */
85 CharSize
= (bUnicode
? sizeof(WCHAR
) : sizeof(CHAR
));
86 SizeBytes
= nNumberOfCharsToRead
* CharSize
;
88 ReadConsoleRequest
->CaptureBufferSize
=
89 ReadConsoleRequest
->NumBytes
= SizeBytes
;
92 * For optimization purposes, Windows (and hence ReactOS, too, for
93 * compatibility reasons) uses a static buffer if no more than eighty
94 * bytes are read. Otherwise a new buffer is allocated.
95 * This behaviour is also expected in the server-side.
97 if (SizeBytes
<= sizeof(ReadConsoleRequest
->StaticBuffer
))
99 ReadConsoleRequest
->Buffer
= ReadConsoleRequest
->StaticBuffer
;
100 // CaptureBuffer = NULL;
104 /* Allocate a Capture Buffer */
105 CaptureBuffer
= CsrAllocateCaptureBuffer(1, SizeBytes
);
106 if (CaptureBuffer
== NULL
)
108 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
109 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
113 /* Allocate space in the Buffer */
114 CsrAllocateMessagePointer(CaptureBuffer
,
116 (PVOID
*)&ReadConsoleRequest
->Buffer
);
119 ReadConsoleRequest
->InitialNumBytes
= 0;
120 ReadConsoleRequest
->CtrlWakeupMask
= 0;
121 ReadConsoleRequest
->ControlKeyState
= 0;
124 * From MSDN (ReadConsole function), the description
125 * for pInputControl says:
126 * "This parameter requires Unicode input by default.
127 * For ANSI mode, set this parameter to NULL."
129 if (bUnicode
&& pInputControl
&&
130 pInputControl
->nLength
== sizeof(CONSOLE_READCONSOLE_CONTROL
))
133 if (pInputControl
->nInitialChars
<= nNumberOfCharsToRead
)
135 ReadConsoleRequest
->InitialNumBytes
=
136 pInputControl
->nInitialChars
* sizeof(WCHAR
); // CharSize
138 if (pInputControl
->nInitialChars
!= 0)
141 * It is possible here to overwrite the static buffer, in case
142 * the number of bytes to read was smaller than the static buffer.
143 * In this case, this means we are continuing a pending read,
144 * and we do not need in fact the executable name that was
145 * stored in the static buffer because it was first grabbed when
146 * we started the first read.
148 RtlCopyMemory(ReadConsoleRequest
->Buffer
,
150 ReadConsoleRequest
->InitialNumBytes
);
153 ReadConsoleRequest
->CtrlWakeupMask
= pInputControl
->dwCtrlWakeupMask
;
157 // Status = STATUS_INVALID_PARAMETER;
162 /* We are in a situation where pInputControl has no meaning */
163 pInputControl
= NULL
;
166 /* 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
,
348 CONSOLE_API_MESSAGE ApiMessage
;
349 PCONSOLE_READOUTPUT ReadOutputRequest
= &ApiMessage
.Data
.ReadOutputRequest
;
350 PCSR_CAPTURE_BUFFER CaptureBuffer
;
351 DWORD Size
, SizeX
, SizeY
;
353 if (lpBuffer
== NULL
)
355 SetLastError(ERROR_INVALID_ACCESS
);
359 Size
= dwBufferSize
.X
* dwBufferSize
.Y
* sizeof(CHAR_INFO
);
361 DPRINT("IntReadConsoleOutput: %lx %p\n", Size
, lpReadRegion
);
363 /* Allocate a Capture Buffer */
364 CaptureBuffer
= CsrAllocateCaptureBuffer(1, Size
);
365 if (CaptureBuffer
== NULL
)
367 DPRINT1("CsrAllocateCaptureBuffer failed with size 0x%x!\n", Size
);
368 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
372 /* Allocate space in the Buffer */
373 CsrAllocateMessagePointer(CaptureBuffer
,
375 (PVOID
*)&ReadOutputRequest
->CharInfo
);
377 /* Set up the data to send to the Console Server */
378 ReadOutputRequest
->OutputHandle
= hConsoleOutput
;
379 ReadOutputRequest
->Unicode
= bUnicode
;
380 ReadOutputRequest
->BufferSize
= dwBufferSize
;
381 ReadOutputRequest
->BufferCoord
= dwBufferCoord
;
382 ReadOutputRequest
->ReadRegion
= *lpReadRegion
;
384 /* Call the server */
385 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
387 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepReadConsoleOutput
),
388 sizeof(*ReadOutputRequest
));
390 /* Check for success */
391 if (NT_SUCCESS(ApiMessage
.Status
))
393 /* Copy into the buffer */
394 DPRINT("Copying to buffer\n");
395 SizeX
= ReadOutputRequest
->ReadRegion
.Right
-
396 ReadOutputRequest
->ReadRegion
.Left
+ 1;
397 SizeY
= ReadOutputRequest
->ReadRegion
.Bottom
-
398 ReadOutputRequest
->ReadRegion
.Top
+ 1;
399 RtlCopyMemory(lpBuffer
,
400 ReadOutputRequest
->CharInfo
,
401 sizeof(CHAR_INFO
) * SizeX
* SizeY
);
405 BaseSetLastNTError(ApiMessage
.Status
);
408 /* Return the read region */
409 DPRINT("read region: %p\n", ReadOutputRequest
->ReadRegion
);
410 *lpReadRegion
= ReadOutputRequest
->ReadRegion
;
412 /* Release the capture buffer */
413 CsrFreeCaptureBuffer(CaptureBuffer
);
415 /* Return TRUE or FALSE */
416 return NT_SUCCESS(ApiMessage
.Status
);
422 IntReadConsoleOutputCode(IN HANDLE hConsoleOutput
,
423 IN CODE_TYPE CodeType
,
426 IN COORD dwReadCoord
,
427 OUT LPDWORD lpNumberOfCodesRead
)
430 CONSOLE_API_MESSAGE ApiMessage
;
431 PCONSOLE_READOUTPUTCODE ReadOutputCodeRequest
= &ApiMessage
.Data
.ReadOutputCodeRequest
;
432 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
433 ULONG CodeSize
, SizeBytes
;
435 DPRINT("IntReadConsoleOutputCode\n");
437 if ( (CodeType
!= CODE_ASCII
) &&
438 (CodeType
!= CODE_UNICODE
) &&
439 (CodeType
!= CODE_ATTRIBUTE
) )
441 SetLastError(ERROR_INVALID_PARAMETER
);
445 /* Set up the data to send to the Console Server */
446 ReadOutputCodeRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
447 ReadOutputCodeRequest
->OutputHandle
= hConsoleOutput
;
448 ReadOutputCodeRequest
->Coord
= dwReadCoord
;
449 ReadOutputCodeRequest
->NumCodes
= nLength
;
451 /* Determine the needed size */
452 ReadOutputCodeRequest
->CodeType
= CodeType
;
456 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, AsciiChar
);
460 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, UnicodeChar
);
464 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, Attribute
);
467 SizeBytes
= nLength
* CodeSize
;
470 * For optimization purposes, Windows (and hence ReactOS, too, for
471 * compatibility reasons) uses a static buffer if no more than eighty
472 * bytes are read. Otherwise a new buffer is allocated.
473 * This behaviour is also expected in the server-side.
475 if (SizeBytes
<= sizeof(ReadOutputCodeRequest
->CodeStaticBuffer
))
477 ReadOutputCodeRequest
->pCode
= ReadOutputCodeRequest
->CodeStaticBuffer
;
478 // CaptureBuffer = NULL;
482 /* Allocate a Capture Buffer */
483 CaptureBuffer
= CsrAllocateCaptureBuffer(1, SizeBytes
);
484 if (CaptureBuffer
== NULL
)
486 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
487 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
491 /* Allocate space in the Buffer */
492 CsrAllocateMessagePointer(CaptureBuffer
,
494 (PVOID
*)&ReadOutputCodeRequest
->pCode
);
497 /* Call the server */
498 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
500 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepReadConsoleOutputString
),
501 sizeof(*ReadOutputCodeRequest
));
503 /* Check for success */
504 Success
= NT_SUCCESS(ApiMessage
.Status
);
506 /* Retrieve the results */
509 *lpNumberOfCodesRead
= ReadOutputCodeRequest
->NumCodes
;
514 ReadOutputCodeRequest
->pCode
,
515 ReadOutputCodeRequest
->NumCodes
* CodeSize
);
519 BaseSetLastNTError(ApiMessage
.Status
);
522 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
524 SetLastError(ERROR_INVALID_ACCESS
);
529 /* Release the capture buffer if needed */
530 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
532 /* Return success status */
543 IntWriteConsole(IN HANDLE hConsoleOutput
,
545 IN DWORD nNumberOfCharsToWrite
,
546 OUT LPDWORD lpNumberOfCharsWritten
,
551 CONSOLE_API_MESSAGE ApiMessage
;
552 PCONSOLE_WRITECONSOLE WriteConsoleRequest
= &ApiMessage
.Data
.WriteConsoleRequest
;
553 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
554 ULONG CharSize
, SizeBytes
;
556 DPRINT("IntWriteConsole\n");
558 /* Set up the data to send to the Console Server */
559 WriteConsoleRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
560 WriteConsoleRequest
->OutputHandle
= hConsoleOutput
;
561 WriteConsoleRequest
->Unicode
= bUnicode
;
563 /* Those members are unused by the client, on Windows */
564 WriteConsoleRequest
->Reserved1
= 0;
565 // WriteConsoleRequest->Reserved2 = {0};
567 /* Determine the needed size */
568 CharSize
= (bUnicode
? sizeof(WCHAR
) : sizeof(CHAR
));
569 SizeBytes
= nNumberOfCharsToWrite
* CharSize
;
571 WriteConsoleRequest
->NumBytes
= SizeBytes
;
574 * For optimization purposes, Windows (and hence ReactOS, too, for
575 * compatibility reasons) uses a static buffer if no more than eighty
576 * bytes are written. Otherwise a new buffer is allocated.
577 * This behaviour is also expected in the server-side.
579 if (SizeBytes
<= sizeof(WriteConsoleRequest
->StaticBuffer
))
581 WriteConsoleRequest
->Buffer
= WriteConsoleRequest
->StaticBuffer
;
582 // CaptureBuffer = NULL;
583 WriteConsoleRequest
->UsingStaticBuffer
= TRUE
;
587 RtlCopyMemory(WriteConsoleRequest
->Buffer
,
591 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
593 SetLastError(ERROR_INVALID_ACCESS
);
600 /* Allocate a Capture Buffer */
601 CaptureBuffer
= CsrAllocateCaptureBuffer(1, SizeBytes
);
602 if (CaptureBuffer
== NULL
)
604 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
605 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
609 /* Capture the buffer to write */
610 CsrCaptureMessageBuffer(CaptureBuffer
,
613 (PVOID
*)&WriteConsoleRequest
->Buffer
);
614 WriteConsoleRequest
->UsingStaticBuffer
= FALSE
;
617 /* Call the server */
618 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
620 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepWriteConsole
),
621 sizeof(*WriteConsoleRequest
));
623 /* Check for success */
624 Success
= NT_SUCCESS(ApiMessage
.Status
);
626 /* Release the capture buffer if needed */
627 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
629 /* Retrieve the results */
634 *lpNumberOfCharsWritten
= WriteConsoleRequest
->NumBytes
/ CharSize
;
636 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
638 SetLastError(ERROR_INVALID_ACCESS
);
645 BaseSetLastNTError(ApiMessage
.Status
);
648 /* Return success status */
655 IntWriteConsoleInput(IN HANDLE hConsoleInput
,
656 IN PINPUT_RECORD lpBuffer
,
658 OUT LPDWORD lpNumberOfEventsWritten
,
660 IN BOOLEAN bAppendToEnd
)
663 CONSOLE_API_MESSAGE ApiMessage
;
664 PCONSOLE_WRITEINPUT WriteInputRequest
= &ApiMessage
.Data
.WriteInputRequest
;
665 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
667 DPRINT("IntWriteConsoleInput: %lx %p\n", nLength
, lpNumberOfEventsWritten
);
669 /* Set up the data to send to the Console Server */
670 WriteInputRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
671 WriteInputRequest
->InputHandle
= hConsoleInput
;
672 WriteInputRequest
->NumRecords
= nLength
;
673 WriteInputRequest
->Unicode
= bUnicode
;
674 WriteInputRequest
->AppendToEnd
= bAppendToEnd
;
677 * For optimization purposes, Windows (and hence ReactOS, too, for
678 * compatibility reasons) uses a static buffer if no more than five
679 * input records are written. Otherwise a new buffer is allocated.
680 * This behaviour is also expected in the server-side.
682 if (nLength
<= sizeof(WriteInputRequest
->RecordStaticBuffer
)/sizeof(INPUT_RECORD
))
684 WriteInputRequest
->RecordBufPtr
= WriteInputRequest
->RecordStaticBuffer
;
685 // CaptureBuffer = NULL;
689 RtlCopyMemory(WriteInputRequest
->RecordBufPtr
,
691 nLength
* sizeof(INPUT_RECORD
));
693 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
695 SetLastError(ERROR_INVALID_ACCESS
);
702 ULONG Size
= nLength
* sizeof(INPUT_RECORD
);
704 /* Allocate a Capture Buffer */
705 CaptureBuffer
= CsrAllocateCaptureBuffer(1, Size
);
706 if (CaptureBuffer
== NULL
)
708 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
709 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
713 /* Capture the user buffer */
714 CsrCaptureMessageBuffer(CaptureBuffer
,
717 (PVOID
*)&WriteInputRequest
->RecordBufPtr
);
720 /* Call the server */
721 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
723 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepWriteConsoleInput
),
724 sizeof(*WriteInputRequest
));
726 /* Check for success */
727 Success
= NT_SUCCESS(ApiMessage
.Status
);
729 /* Release the capture buffer if needed */
730 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
732 /* Retrieve the results */
735 DPRINT("Events written: %lx\n", WriteInputRequest
->NumRecords
);
736 *lpNumberOfEventsWritten
= WriteInputRequest
->NumRecords
;
739 BaseSetLastNTError(ApiMessage
.Status
);
741 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
743 SetLastError(ERROR_INVALID_ACCESS
);
748 /* Return success status */
755 IntWriteConsoleOutput(IN HANDLE hConsoleOutput
,
756 IN CONST CHAR_INFO
*lpBuffer
,
757 IN COORD dwBufferSize
,
758 IN COORD dwBufferCoord
,
759 IN OUT PSMALL_RECT lpWriteRegion
,
762 CONSOLE_API_MESSAGE ApiMessage
;
763 PCONSOLE_WRITEOUTPUT WriteOutputRequest
= &ApiMessage
.Data
.WriteOutputRequest
;
764 PCSR_CAPTURE_BUFFER CaptureBuffer
;
767 if ((lpBuffer
== NULL
) || (lpWriteRegion
== NULL
))
769 SetLastError(ERROR_INVALID_ACCESS
);
773 if (lpWriteRegion == NULL)
775 SetLastError(ERROR_INVALID_PARAMETER);
780 Size
= dwBufferSize
.Y
* dwBufferSize
.X
* sizeof(CHAR_INFO
);
782 DPRINT("IntWriteConsoleOutput: %lx %p\n", Size
, lpWriteRegion
);
784 /* Allocate a Capture Buffer */
785 CaptureBuffer
= CsrAllocateCaptureBuffer(1, Size
);
786 if (CaptureBuffer
== NULL
)
788 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
789 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
793 /* Capture the user buffer */
794 CsrCaptureMessageBuffer(CaptureBuffer
,
797 (PVOID
*)&WriteOutputRequest
->CharInfo
);
799 /* Set up the data to send to the Console Server */
800 WriteOutputRequest
->OutputHandle
= hConsoleOutput
;
801 WriteOutputRequest
->Unicode
= bUnicode
;
802 WriteOutputRequest
->BufferSize
= dwBufferSize
;
803 WriteOutputRequest
->BufferCoord
= dwBufferCoord
;
804 WriteOutputRequest
->WriteRegion
= *lpWriteRegion
;
806 /* Call the server */
807 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
809 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepWriteConsoleOutput
),
810 sizeof(*WriteOutputRequest
));
812 /* Check for success */
813 if (!NT_SUCCESS(ApiMessage
.Status
))
815 BaseSetLastNTError(ApiMessage
.Status
);
818 /* Return the read region */
819 DPRINT("read region: %p\n", WriteOutputRequest
->WriteRegion
);
820 *lpWriteRegion
= WriteOutputRequest
->WriteRegion
;
822 /* Release the capture buffer */
823 CsrFreeCaptureBuffer(CaptureBuffer
);
825 /* Return TRUE or FALSE */
826 return NT_SUCCESS(ApiMessage
.Status
);
832 IntWriteConsoleOutputCode(IN HANDLE hConsoleOutput
,
833 IN CODE_TYPE CodeType
,
834 IN CONST VOID
*pCode
,
836 IN COORD dwWriteCoord
,
837 OUT LPDWORD lpNumberOfCodesWritten
)
840 CONSOLE_API_MESSAGE ApiMessage
;
841 PCONSOLE_WRITEOUTPUTCODE WriteOutputCodeRequest
= &ApiMessage
.Data
.WriteOutputCodeRequest
;
842 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
843 ULONG CodeSize
, SizeBytes
;
845 if ( (CodeType
!= CODE_ASCII
) &&
846 (CodeType
!= CODE_UNICODE
) &&
847 (CodeType
!= CODE_ATTRIBUTE
) )
849 SetLastError(ERROR_INVALID_PARAMETER
);
853 DPRINT("IntWriteConsoleOutputCode\n");
855 /* Set up the data to send to the Console Server */
856 WriteOutputCodeRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
857 WriteOutputCodeRequest
->OutputHandle
= hConsoleOutput
;
858 WriteOutputCodeRequest
->Coord
= dwWriteCoord
;
859 WriteOutputCodeRequest
->NumCodes
= nLength
;
861 /* Determine the needed size */
862 WriteOutputCodeRequest
->CodeType
= CodeType
;
866 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, AsciiChar
);
870 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, UnicodeChar
);
874 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, Attribute
);
877 SizeBytes
= nLength
* CodeSize
;
880 * For optimization purposes, Windows (and hence ReactOS, too, for
881 * compatibility reasons) uses a static buffer if no more than eighty
882 * bytes are written. Otherwise a new buffer is allocated.
883 * This behaviour is also expected in the server-side.
885 if (SizeBytes
<= sizeof(WriteOutputCodeRequest
->CodeStaticBuffer
))
887 WriteOutputCodeRequest
->pCode
= WriteOutputCodeRequest
->CodeStaticBuffer
;
888 // CaptureBuffer = NULL;
892 RtlCopyMemory(WriteOutputCodeRequest
->pCode
,
896 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
898 SetLastError(ERROR_INVALID_ACCESS
);
905 /* Allocate a Capture Buffer */
906 CaptureBuffer
= CsrAllocateCaptureBuffer(1, SizeBytes
);
907 if (CaptureBuffer
== NULL
)
909 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
910 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
914 /* Capture the buffer to write */
915 CsrCaptureMessageBuffer(CaptureBuffer
,
918 (PVOID
*)&WriteOutputCodeRequest
->pCode
);
921 /* Call the server */
922 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
924 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepWriteConsoleOutputString
),
925 sizeof(*WriteOutputCodeRequest
));
927 /* Check for success */
928 Success
= NT_SUCCESS(ApiMessage
.Status
);
930 /* Release the capture buffer if needed */
931 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
933 /* Retrieve the results */
936 *lpNumberOfCodesWritten
= WriteOutputCodeRequest
->NumCodes
;
939 BaseSetLastNTError(ApiMessage
.Status
);
941 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
943 SetLastError(ERROR_INVALID_ACCESS
);
948 /* Return success status */
955 IntFillConsoleOutputCode(IN HANDLE hConsoleOutput
,
956 IN CODE_TYPE CodeType
,
957 IN CODE_ELEMENT Code
,
959 IN COORD dwWriteCoord
,
960 OUT LPDWORD lpNumberOfCodesWritten
)
963 CONSOLE_API_MESSAGE ApiMessage
;
964 PCONSOLE_FILLOUTPUTCODE FillOutputRequest
= &ApiMessage
.Data
.FillOutputRequest
;
966 DPRINT("IntFillConsoleOutputCode\n");
968 if ( (CodeType
!= CODE_ASCII
) &&
969 (CodeType
!= CODE_UNICODE
) &&
970 (CodeType
!= CODE_ATTRIBUTE
) )
972 SetLastError(ERROR_INVALID_PARAMETER
);
976 /* Set up the data to send to the Console Server */
977 FillOutputRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
978 FillOutputRequest
->OutputHandle
= hConsoleOutput
;
979 FillOutputRequest
->WriteCoord
= dwWriteCoord
;
980 FillOutputRequest
->CodeType
= CodeType
;
981 FillOutputRequest
->Code
= Code
;
982 FillOutputRequest
->NumCodes
= nLength
;
984 /* Call the server */
985 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
987 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepFillConsoleOutput
),
988 sizeof(*FillOutputRequest
));
990 /* Check for success */
991 Success
= NT_SUCCESS(ApiMessage
.Status
);
993 /* Retrieve the results */
996 *lpNumberOfCodesWritten
= FillOutputRequest
->NumCodes
;
999 BaseSetLastNTError(ApiMessage
.Status
);
1001 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1003 SetLastError(ERROR_INVALID_ACCESS
);
1008 /* Return success status */
1013 /* FUNCTIONS ******************************************************************/
1019 /*--------------------------------------------------------------
1026 ReadConsoleW(IN HANDLE hConsoleInput
,
1027 OUT LPVOID lpBuffer
,
1028 IN DWORD nNumberOfCharsToRead
,
1029 OUT LPDWORD lpNumberOfCharsRead
,
1030 IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL
)
1032 return IntReadConsole(hConsoleInput
,
1034 nNumberOfCharsToRead
,
1035 lpNumberOfCharsRead
,
1041 /*--------------------------------------------------------------
1048 ReadConsoleA(IN HANDLE hConsoleInput
,
1049 OUT LPVOID lpBuffer
,
1050 IN DWORD nNumberOfCharsToRead
,
1051 OUT LPDWORD lpNumberOfCharsRead
,
1052 IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL
)
1054 return IntReadConsole(hConsoleInput
,
1056 nNumberOfCharsToRead
,
1057 lpNumberOfCharsRead
,
1063 /*--------------------------------------------------------------
1070 PeekConsoleInputW(IN HANDLE hConsoleInput
,
1071 OUT PINPUT_RECORD lpBuffer
,
1073 OUT LPDWORD lpNumberOfEventsRead
)
1075 return IntGetConsoleInput(hConsoleInput
,
1078 lpNumberOfEventsRead
,
1079 CONSOLE_READ_KEEPEVENT
| CONSOLE_READ_CONTINUE
,
1084 /*--------------------------------------------------------------
1091 PeekConsoleInputA(IN HANDLE hConsoleInput
,
1092 OUT PINPUT_RECORD lpBuffer
,
1094 OUT LPDWORD lpNumberOfEventsRead
)
1096 return IntGetConsoleInput(hConsoleInput
,
1099 lpNumberOfEventsRead
,
1100 CONSOLE_READ_KEEPEVENT
| CONSOLE_READ_CONTINUE
,
1105 /*--------------------------------------------------------------
1112 ReadConsoleInputW(IN HANDLE hConsoleInput
,
1113 OUT PINPUT_RECORD lpBuffer
,
1115 OUT LPDWORD lpNumberOfEventsRead
)
1117 return IntGetConsoleInput(hConsoleInput
,
1120 lpNumberOfEventsRead
,
1126 /*--------------------------------------------------------------
1133 ReadConsoleInputA(IN HANDLE hConsoleInput
,
1134 OUT PINPUT_RECORD lpBuffer
,
1136 OUT LPDWORD lpNumberOfEventsRead
)
1138 return IntGetConsoleInput(hConsoleInput
,
1141 lpNumberOfEventsRead
,
1147 /*--------------------------------------------------------------
1148 * ReadConsoleInputExW
1154 ReadConsoleInputExW(IN HANDLE hConsoleInput
,
1155 OUT PINPUT_RECORD lpBuffer
,
1157 OUT LPDWORD lpNumberOfEventsRead
,
1160 return IntGetConsoleInput(hConsoleInput
,
1163 lpNumberOfEventsRead
,
1169 /*--------------------------------------------------------------
1170 * ReadConsoleInputExA
1176 ReadConsoleInputExA(IN HANDLE hConsoleInput
,
1177 OUT PINPUT_RECORD lpBuffer
,
1179 OUT LPDWORD lpNumberOfEventsRead
,
1182 return IntGetConsoleInput(hConsoleInput
,
1185 lpNumberOfEventsRead
,
1191 /*--------------------------------------------------------------
1192 * ReadConsoleOutputW
1198 ReadConsoleOutputW(IN HANDLE hConsoleOutput
,
1199 OUT PCHAR_INFO lpBuffer
,
1200 IN COORD dwBufferSize
,
1201 IN COORD dwBufferCoord
,
1202 IN OUT PSMALL_RECT lpReadRegion
)
1204 return IntReadConsoleOutput(hConsoleOutput
,
1213 /*--------------------------------------------------------------
1214 * ReadConsoleOutputA
1220 ReadConsoleOutputA(IN HANDLE hConsoleOutput
,
1221 OUT PCHAR_INFO lpBuffer
,
1222 IN COORD dwBufferSize
,
1223 IN COORD dwBufferCoord
,
1224 IN OUT PSMALL_RECT lpReadRegion
)
1226 return IntReadConsoleOutput(hConsoleOutput
,
1235 /*--------------------------------------------------------------
1236 * ReadConsoleOutputCharacterW
1242 ReadConsoleOutputCharacterW(IN HANDLE hConsoleOutput
,
1243 OUT LPWSTR lpCharacter
,
1245 IN COORD dwReadCoord
,
1246 OUT LPDWORD lpNumberOfCharsRead
)
1248 return IntReadConsoleOutputCode(hConsoleOutput
,
1253 lpNumberOfCharsRead
);
1257 /*--------------------------------------------------------------
1258 * ReadConsoleOutputCharacterA
1264 ReadConsoleOutputCharacterA(IN HANDLE hConsoleOutput
,
1265 OUT LPSTR lpCharacter
,
1267 IN COORD dwReadCoord
,
1268 OUT LPDWORD lpNumberOfCharsRead
)
1270 return IntReadConsoleOutputCode(hConsoleOutput
,
1275 lpNumberOfCharsRead
);
1279 /*--------------------------------------------------------------
1280 * ReadConsoleOutputAttribute
1286 ReadConsoleOutputAttribute(IN HANDLE hConsoleOutput
,
1287 OUT LPWORD lpAttribute
,
1289 IN COORD dwReadCoord
,
1290 OUT LPDWORD lpNumberOfAttrsRead
)
1292 return IntReadConsoleOutputCode(hConsoleOutput
,
1297 lpNumberOfAttrsRead
);
1301 /*******************
1303 *******************/
1305 /*--------------------------------------------------------------
1312 WriteConsoleW(IN HANDLE hConsoleOutput
,
1313 IN CONST VOID
*lpBuffer
,
1314 IN DWORD nNumberOfCharsToWrite
,
1315 OUT LPDWORD lpNumberOfCharsWritten
,
1318 return IntWriteConsole(hConsoleOutput
,
1320 nNumberOfCharsToWrite
,
1321 lpNumberOfCharsWritten
,
1327 /*--------------------------------------------------------------
1334 WriteConsoleA(IN HANDLE hConsoleOutput
,
1335 IN CONST VOID
*lpBuffer
,
1336 IN DWORD nNumberOfCharsToWrite
,
1337 OUT LPDWORD lpNumberOfCharsWritten
,
1340 return IntWriteConsole(hConsoleOutput
,
1342 nNumberOfCharsToWrite
,
1343 lpNumberOfCharsWritten
,
1349 /*--------------------------------------------------------------
1350 * WriteConsoleInputW
1356 WriteConsoleInputW(IN HANDLE hConsoleInput
,
1357 IN CONST INPUT_RECORD
*lpBuffer
,
1359 OUT LPDWORD lpNumberOfEventsWritten
)
1361 return IntWriteConsoleInput(hConsoleInput
,
1362 (PINPUT_RECORD
)lpBuffer
,
1364 lpNumberOfEventsWritten
,
1370 /*--------------------------------------------------------------
1371 * WriteConsoleInputA
1377 WriteConsoleInputA(IN HANDLE hConsoleInput
,
1378 IN CONST INPUT_RECORD
*lpBuffer
,
1380 OUT LPDWORD lpNumberOfEventsWritten
)
1382 return IntWriteConsoleInput(hConsoleInput
,
1383 (PINPUT_RECORD
)lpBuffer
,
1385 lpNumberOfEventsWritten
,
1391 /*--------------------------------------------------------------
1392 * WriteConsoleInputVDMW
1398 WriteConsoleInputVDMW(IN HANDLE hConsoleInput
,
1399 IN CONST INPUT_RECORD
*lpBuffer
,
1401 OUT LPDWORD lpNumberOfEventsWritten
)
1403 return IntWriteConsoleInput(hConsoleInput
,
1404 (PINPUT_RECORD
)lpBuffer
,
1406 lpNumberOfEventsWritten
,
1412 /*--------------------------------------------------------------
1413 * WriteConsoleInputVDMA
1419 WriteConsoleInputVDMA(IN HANDLE hConsoleInput
,
1420 IN CONST INPUT_RECORD
*lpBuffer
,
1422 OUT LPDWORD lpNumberOfEventsWritten
)
1424 return IntWriteConsoleInput(hConsoleInput
,
1425 (PINPUT_RECORD
)lpBuffer
,
1427 lpNumberOfEventsWritten
,
1433 /*--------------------------------------------------------------
1434 * WriteConsoleOutputW
1440 WriteConsoleOutputW(IN HANDLE hConsoleOutput
,
1441 IN CONST CHAR_INFO
*lpBuffer
,
1442 IN COORD dwBufferSize
,
1443 IN COORD dwBufferCoord
,
1444 IN OUT PSMALL_RECT lpWriteRegion
)
1446 return IntWriteConsoleOutput(hConsoleOutput
,
1455 /*--------------------------------------------------------------
1456 * WriteConsoleOutputA
1462 WriteConsoleOutputA(IN HANDLE hConsoleOutput
,
1463 IN CONST CHAR_INFO
*lpBuffer
,
1464 IN COORD dwBufferSize
,
1465 IN COORD dwBufferCoord
,
1466 IN OUT PSMALL_RECT lpWriteRegion
)
1468 return IntWriteConsoleOutput(hConsoleOutput
,
1477 /*--------------------------------------------------------------
1478 * WriteConsoleOutputCharacterW
1484 WriteConsoleOutputCharacterW(IN HANDLE hConsoleOutput
,
1485 IN LPCWSTR lpCharacter
,
1487 IN COORD dwWriteCoord
,
1488 OUT LPDWORD lpNumberOfCharsWritten
)
1490 return IntWriteConsoleOutputCode(hConsoleOutput
,
1495 lpNumberOfCharsWritten
);
1499 /*--------------------------------------------------------------
1500 * WriteConsoleOutputCharacterA
1506 WriteConsoleOutputCharacterA(IN HANDLE hConsoleOutput
,
1507 IN LPCSTR lpCharacter
,
1509 IN COORD dwWriteCoord
,
1510 OUT LPDWORD lpNumberOfCharsWritten
)
1512 return IntWriteConsoleOutputCode(hConsoleOutput
,
1517 lpNumberOfCharsWritten
);
1521 /*--------------------------------------------------------------
1522 * WriteConsoleOutputAttribute
1528 WriteConsoleOutputAttribute(IN HANDLE hConsoleOutput
,
1529 IN CONST WORD
*lpAttribute
,
1531 IN COORD dwWriteCoord
,
1532 OUT LPDWORD lpNumberOfAttrsWritten
)
1534 return IntWriteConsoleOutputCode(hConsoleOutput
,
1539 lpNumberOfAttrsWritten
);
1543 /*--------------------------------------------------------------
1544 * FillConsoleOutputCharacterW
1550 FillConsoleOutputCharacterW(IN HANDLE hConsoleOutput
,
1551 IN WCHAR cCharacter
,
1553 IN COORD dwWriteCoord
,
1554 OUT LPDWORD lpNumberOfCharsWritten
)
1557 Code
.UnicodeChar
= cCharacter
;
1558 return IntFillConsoleOutputCode(hConsoleOutput
,
1563 lpNumberOfCharsWritten
);
1567 /*--------------------------------------------------------------
1568 * FillConsoleOutputCharacterA
1574 FillConsoleOutputCharacterA(IN HANDLE hConsoleOutput
,
1577 IN COORD dwWriteCoord
,
1578 LPDWORD lpNumberOfCharsWritten
)
1581 Code
.AsciiChar
= cCharacter
;
1582 return IntFillConsoleOutputCode(hConsoleOutput
,
1587 lpNumberOfCharsWritten
);
1591 /*--------------------------------------------------------------
1592 * FillConsoleOutputAttribute
1598 FillConsoleOutputAttribute(IN HANDLE hConsoleOutput
,
1601 IN COORD dwWriteCoord
,
1602 OUT LPDWORD lpNumberOfAttrsWritten
)
1605 Code
.Attribute
= wAttribute
;
1606 return IntFillConsoleOutputCode(hConsoleOutput
,
1611 lpNumberOfAttrsWritten
);