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."
131 if (bUnicode
&& pInputControl
&&
132 pInputControl
->nLength
== sizeof(CONSOLE_READCONSOLE_CONTROL
))
135 if (pInputControl
->nInitialChars
<= nNumberOfCharsToRead
)
137 ReadConsoleRequest
->InitialNumBytes
=
138 pInputControl
->nInitialChars
* sizeof(WCHAR
); // CharSize
140 if (pInputControl
->nInitialChars
!= 0)
143 * It is possible here to overwrite the static buffer, in case
144 * the number of bytes to read was smaller than the static buffer.
145 * In this case, this means we are continuing a pending read,
146 * and we do not need in fact the executable name that was
147 * stored in the static buffer because it was first grabbed when
148 * we started the first read.
150 RtlCopyMemory(ReadConsoleRequest
->Buffer
,
152 ReadConsoleRequest
->InitialNumBytes
);
155 ReadConsoleRequest
->CtrlWakeupMask
= pInputControl
->dwCtrlWakeupMask
;
159 // Status = STATUS_INVALID_PARAMETER;
164 /* We are in a situation where pInputControl has no meaning */
165 pInputControl
= NULL
;
168 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
171 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
172 SetLastError(ERROR_INVALID_ACCESS
);
177 /* Check for sanity */
179 if (!NT_SUCCESS(Status) && pInputControl)
181 // Free CaptureBuffer if needed
182 // Set last error to last status
187 /* Call the server */
188 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
190 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepReadConsole
),
191 sizeof(*ReadConsoleRequest
));
193 /* Check for success */
194 Success
= NT_SUCCESS(ApiMessage
.Status
);
196 /* Retrieve the results */
201 *lpNumberOfCharsRead
= ReadConsoleRequest
->NumBytes
/ CharSize
;
203 if (bUnicode
&& pInputControl
)
204 pInputControl
->dwControlKeyState
= ReadConsoleRequest
->ControlKeyState
;
206 RtlCopyMemory(lpBuffer
,
207 ReadConsoleRequest
->Buffer
,
208 ReadConsoleRequest
->NumBytes
);
210 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
212 SetLastError(ERROR_INVALID_ACCESS
);
219 BaseSetLastNTError(ApiMessage
.Status
);
222 /* Release the capture buffer if needed */
223 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
227 /* Yield execution to another thread if Ctrl-C or Ctrl-Break happened */
228 if (ApiMessage
.Status
== STATUS_ALERTED
/* || ApiMessage.Status == STATUS_CANCELLED */)
231 SetLastError(ERROR_OPERATION_ABORTED
); // STATUS_CANCELLED
235 /* Return success status */
242 IntGetConsoleInput(IN HANDLE hConsoleInput
,
243 OUT PINPUT_RECORD lpBuffer
,
245 OUT LPDWORD lpNumberOfEventsRead
,
250 CONSOLE_API_MESSAGE ApiMessage
;
251 PCONSOLE_GETINPUT GetInputRequest
= &ApiMessage
.Data
.GetInputRequest
;
252 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
254 if (!IsConsoleHandle(hConsoleInput
))
258 *lpNumberOfEventsRead
= 0;
259 SetLastError(ERROR_INVALID_HANDLE
);
261 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
263 SetLastError(ERROR_INVALID_ACCESS
);
270 DPRINT("IntGetConsoleInput: %lx %p\n", nLength
, lpNumberOfEventsRead
);
272 /* Set up the data to send to the Console Server */
273 GetInputRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
274 GetInputRequest
->InputHandle
= hConsoleInput
;
275 GetInputRequest
->NumRecords
= nLength
;
276 GetInputRequest
->Flags
= wFlags
;
277 GetInputRequest
->Unicode
= bUnicode
;
280 * For optimization purposes, Windows (and hence ReactOS, too, for
281 * compatibility reasons) uses a static buffer if no more than five
282 * input records are read. Otherwise a new buffer is allocated.
283 * This behaviour is also expected in the server-side.
285 if (nLength
<= sizeof(GetInputRequest
->RecordStaticBuffer
)/sizeof(INPUT_RECORD
))
287 GetInputRequest
->RecordBufPtr
= GetInputRequest
->RecordStaticBuffer
;
288 // CaptureBuffer = NULL;
292 ULONG Size
= nLength
* sizeof(INPUT_RECORD
);
294 /* Allocate a Capture Buffer */
295 CaptureBuffer
= CsrAllocateCaptureBuffer(1, Size
);
296 if (CaptureBuffer
== NULL
)
298 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
299 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
303 /* Allocate space in the Buffer */
304 CsrAllocateMessagePointer(CaptureBuffer
,
306 (PVOID
*)&GetInputRequest
->RecordBufPtr
);
309 /* Call the server */
310 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
312 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepGetConsoleInput
),
313 sizeof(*GetInputRequest
));
315 /* Check for success */
316 Success
= NT_SUCCESS(ApiMessage
.Status
);
318 /* Retrieve the results */
321 DPRINT("Events read: %lx\n", GetInputRequest
->NumRecords
);
322 *lpNumberOfEventsRead
= GetInputRequest
->NumRecords
;
326 RtlCopyMemory(lpBuffer
,
327 GetInputRequest
->RecordBufPtr
,
328 GetInputRequest
->NumRecords
* sizeof(INPUT_RECORD
));
332 BaseSetLastNTError(ApiMessage
.Status
);
335 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
337 SetLastError(ERROR_INVALID_ACCESS
);
342 /* Release the capture buffer if needed */
343 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
345 /* Return success status */
352 IntReadConsoleOutput(IN HANDLE hConsoleOutput
,
353 OUT PCHAR_INFO lpBuffer
,
354 IN COORD dwBufferSize
,
355 IN COORD dwBufferCoord
,
356 IN OUT PSMALL_RECT lpReadRegion
,
359 CONSOLE_API_MESSAGE ApiMessage
;
360 PCONSOLE_READOUTPUT ReadOutputRequest
= &ApiMessage
.Data
.ReadOutputRequest
;
361 PCSR_CAPTURE_BUFFER CaptureBuffer
;
362 DWORD Size
, SizeX
, SizeY
;
364 if (lpBuffer
== NULL
)
366 SetLastError(ERROR_INVALID_ACCESS
);
370 Size
= dwBufferSize
.X
* dwBufferSize
.Y
* sizeof(CHAR_INFO
);
372 DPRINT("IntReadConsoleOutput: %lx %p\n", Size
, lpReadRegion
);
374 /* Allocate a Capture Buffer */
375 CaptureBuffer
= CsrAllocateCaptureBuffer(1, Size
);
376 if (CaptureBuffer
== NULL
)
378 DPRINT1("CsrAllocateCaptureBuffer failed with size 0x%x!\n", Size
);
379 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
383 /* Allocate space in the Buffer */
384 CsrAllocateMessagePointer(CaptureBuffer
,
386 (PVOID
*)&ReadOutputRequest
->CharInfo
);
388 /* Set up the data to send to the Console Server */
389 ReadOutputRequest
->OutputHandle
= hConsoleOutput
;
390 ReadOutputRequest
->Unicode
= bUnicode
;
391 ReadOutputRequest
->BufferSize
= dwBufferSize
;
392 ReadOutputRequest
->BufferCoord
= dwBufferCoord
;
393 ReadOutputRequest
->ReadRegion
= *lpReadRegion
;
395 /* Call the server */
396 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
398 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepReadConsoleOutput
),
399 sizeof(*ReadOutputRequest
));
401 /* Check for success */
402 if (NT_SUCCESS(ApiMessage
.Status
))
404 /* Copy into the buffer */
405 DPRINT("Copying to buffer\n");
406 SizeX
= ReadOutputRequest
->ReadRegion
.Right
-
407 ReadOutputRequest
->ReadRegion
.Left
+ 1;
408 SizeY
= ReadOutputRequest
->ReadRegion
.Bottom
-
409 ReadOutputRequest
->ReadRegion
.Top
+ 1;
410 RtlCopyMemory(lpBuffer
,
411 ReadOutputRequest
->CharInfo
,
412 sizeof(CHAR_INFO
) * SizeX
* SizeY
);
416 BaseSetLastNTError(ApiMessage
.Status
);
419 /* Return the read region */
420 DPRINT("read region: %p\n", ReadOutputRequest
->ReadRegion
);
421 *lpReadRegion
= ReadOutputRequest
->ReadRegion
;
423 /* Release the capture buffer */
424 CsrFreeCaptureBuffer(CaptureBuffer
);
426 /* Return TRUE or FALSE */
427 return NT_SUCCESS(ApiMessage
.Status
);
433 IntReadConsoleOutputCode(IN HANDLE hConsoleOutput
,
434 IN CODE_TYPE CodeType
,
437 IN COORD dwReadCoord
,
438 OUT LPDWORD lpNumberOfCodesRead
)
441 CONSOLE_API_MESSAGE ApiMessage
;
442 PCONSOLE_READOUTPUTCODE ReadOutputCodeRequest
= &ApiMessage
.Data
.ReadOutputCodeRequest
;
443 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
444 ULONG CodeSize
, SizeBytes
;
446 DPRINT("IntReadConsoleOutputCode\n");
448 if ( (CodeType
!= CODE_ASCII
) &&
449 (CodeType
!= CODE_UNICODE
) &&
450 (CodeType
!= CODE_ATTRIBUTE
) )
452 SetLastError(ERROR_INVALID_PARAMETER
);
456 /* Set up the data to send to the Console Server */
457 ReadOutputCodeRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
458 ReadOutputCodeRequest
->OutputHandle
= hConsoleOutput
;
459 ReadOutputCodeRequest
->Coord
= dwReadCoord
;
460 ReadOutputCodeRequest
->NumCodes
= nLength
;
462 /* Determine the needed size */
463 ReadOutputCodeRequest
->CodeType
= CodeType
;
467 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, AsciiChar
);
471 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, UnicodeChar
);
475 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, Attribute
);
478 SizeBytes
= nLength
* CodeSize
;
481 * For optimization purposes, Windows (and hence ReactOS, too, for
482 * compatibility reasons) uses a static buffer if no more than eighty
483 * bytes are read. Otherwise a new buffer is allocated.
484 * This behaviour is also expected in the server-side.
486 if (SizeBytes
<= sizeof(ReadOutputCodeRequest
->CodeStaticBuffer
))
488 ReadOutputCodeRequest
->pCode
= ReadOutputCodeRequest
->CodeStaticBuffer
;
489 // CaptureBuffer = NULL;
493 /* Allocate a Capture Buffer */
494 CaptureBuffer
= CsrAllocateCaptureBuffer(1, SizeBytes
);
495 if (CaptureBuffer
== NULL
)
497 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
498 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
502 /* Allocate space in the Buffer */
503 CsrAllocateMessagePointer(CaptureBuffer
,
505 (PVOID
*)&ReadOutputCodeRequest
->pCode
);
508 /* Call the server */
509 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
511 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepReadConsoleOutputString
),
512 sizeof(*ReadOutputCodeRequest
));
514 /* Check for success */
515 Success
= NT_SUCCESS(ApiMessage
.Status
);
517 /* Retrieve the results */
520 *lpNumberOfCodesRead
= ReadOutputCodeRequest
->NumCodes
;
525 ReadOutputCodeRequest
->pCode
,
526 ReadOutputCodeRequest
->NumCodes
* CodeSize
);
530 BaseSetLastNTError(ApiMessage
.Status
);
533 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
535 SetLastError(ERROR_INVALID_ACCESS
);
540 /* Release the capture buffer if needed */
541 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
543 /* Return success status */
554 IntWriteConsole(IN HANDLE hConsoleOutput
,
556 IN DWORD nNumberOfCharsToWrite
,
557 OUT LPDWORD lpNumberOfCharsWritten
,
562 CONSOLE_API_MESSAGE ApiMessage
;
563 PCONSOLE_WRITECONSOLE WriteConsoleRequest
= &ApiMessage
.Data
.WriteConsoleRequest
;
564 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
565 ULONG CharSize
, SizeBytes
;
567 DPRINT("IntWriteConsole\n");
569 /* Set up the data to send to the Console Server */
570 WriteConsoleRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
571 WriteConsoleRequest
->OutputHandle
= hConsoleOutput
;
572 WriteConsoleRequest
->Unicode
= bUnicode
;
574 /* Those members are unused by the client, on Windows */
575 WriteConsoleRequest
->Reserved1
= 0;
576 // WriteConsoleRequest->Reserved2 = {0};
578 /* Determine the needed size */
579 CharSize
= (bUnicode
? sizeof(WCHAR
) : sizeof(CHAR
));
580 SizeBytes
= nNumberOfCharsToWrite
* CharSize
;
582 WriteConsoleRequest
->NumBytes
= SizeBytes
;
585 * For optimization purposes, Windows (and hence ReactOS, too, for
586 * compatibility reasons) uses a static buffer if no more than eighty
587 * bytes are written. Otherwise a new buffer is allocated.
588 * This behaviour is also expected in the server-side.
590 if (SizeBytes
<= sizeof(WriteConsoleRequest
->StaticBuffer
))
592 WriteConsoleRequest
->Buffer
= WriteConsoleRequest
->StaticBuffer
;
593 // CaptureBuffer = NULL;
594 WriteConsoleRequest
->UsingStaticBuffer
= TRUE
;
598 RtlCopyMemory(WriteConsoleRequest
->Buffer
,
602 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
604 SetLastError(ERROR_INVALID_ACCESS
);
611 /* Allocate a Capture Buffer */
612 CaptureBuffer
= CsrAllocateCaptureBuffer(1, SizeBytes
);
613 if (CaptureBuffer
== NULL
)
615 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
616 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
620 /* Capture the buffer to write */
621 CsrCaptureMessageBuffer(CaptureBuffer
,
624 (PVOID
*)&WriteConsoleRequest
->Buffer
);
625 WriteConsoleRequest
->UsingStaticBuffer
= FALSE
;
628 /* Call the server */
629 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
631 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepWriteConsole
),
632 sizeof(*WriteConsoleRequest
));
634 /* Check for success */
635 Success
= NT_SUCCESS(ApiMessage
.Status
);
637 /* Release the capture buffer if needed */
638 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
640 /* Retrieve the results */
645 *lpNumberOfCharsWritten
= WriteConsoleRequest
->NumBytes
/ CharSize
;
647 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
649 SetLastError(ERROR_INVALID_ACCESS
);
656 BaseSetLastNTError(ApiMessage
.Status
);
659 /* Return success status */
666 IntWriteConsoleInput(IN HANDLE hConsoleInput
,
667 IN PINPUT_RECORD lpBuffer
,
669 OUT LPDWORD lpNumberOfEventsWritten
,
671 IN BOOLEAN bAppendToEnd
)
674 CONSOLE_API_MESSAGE ApiMessage
;
675 PCONSOLE_WRITEINPUT WriteInputRequest
= &ApiMessage
.Data
.WriteInputRequest
;
676 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
678 DPRINT("IntWriteConsoleInput: %lx %p\n", nLength
, lpNumberOfEventsWritten
);
680 /* Set up the data to send to the Console Server */
681 WriteInputRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
682 WriteInputRequest
->InputHandle
= hConsoleInput
;
683 WriteInputRequest
->NumRecords
= nLength
;
684 WriteInputRequest
->Unicode
= bUnicode
;
685 WriteInputRequest
->AppendToEnd
= bAppendToEnd
;
688 * For optimization purposes, Windows (and hence ReactOS, too, for
689 * compatibility reasons) uses a static buffer if no more than five
690 * input records are written. Otherwise a new buffer is allocated.
691 * This behaviour is also expected in the server-side.
693 if (nLength
<= sizeof(WriteInputRequest
->RecordStaticBuffer
)/sizeof(INPUT_RECORD
))
695 WriteInputRequest
->RecordBufPtr
= WriteInputRequest
->RecordStaticBuffer
;
696 // CaptureBuffer = NULL;
700 RtlCopyMemory(WriteInputRequest
->RecordBufPtr
,
702 nLength
* sizeof(INPUT_RECORD
));
704 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
706 SetLastError(ERROR_INVALID_ACCESS
);
713 ULONG Size
= nLength
* sizeof(INPUT_RECORD
);
715 /* Allocate a Capture Buffer */
716 CaptureBuffer
= CsrAllocateCaptureBuffer(1, Size
);
717 if (CaptureBuffer
== NULL
)
719 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
720 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
724 /* Capture the user buffer */
725 CsrCaptureMessageBuffer(CaptureBuffer
,
728 (PVOID
*)&WriteInputRequest
->RecordBufPtr
);
731 /* Call the server */
732 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
734 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepWriteConsoleInput
),
735 sizeof(*WriteInputRequest
));
737 /* Check for success */
738 Success
= NT_SUCCESS(ApiMessage
.Status
);
740 /* Release the capture buffer if needed */
741 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
743 /* Retrieve the results */
746 DPRINT("Events written: %lx\n", WriteInputRequest
->NumRecords
);
747 *lpNumberOfEventsWritten
= WriteInputRequest
->NumRecords
;
750 BaseSetLastNTError(ApiMessage
.Status
);
752 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
754 SetLastError(ERROR_INVALID_ACCESS
);
759 /* Return success status */
766 IntWriteConsoleOutput(IN HANDLE hConsoleOutput
,
767 IN CONST CHAR_INFO
*lpBuffer
,
768 IN COORD dwBufferSize
,
769 IN COORD dwBufferCoord
,
770 IN OUT PSMALL_RECT lpWriteRegion
,
773 CONSOLE_API_MESSAGE ApiMessage
;
774 PCONSOLE_WRITEOUTPUT WriteOutputRequest
= &ApiMessage
.Data
.WriteOutputRequest
;
775 PCSR_CAPTURE_BUFFER CaptureBuffer
;
778 if ((lpBuffer
== NULL
) || (lpWriteRegion
== NULL
))
780 SetLastError(ERROR_INVALID_ACCESS
);
784 if (lpWriteRegion == NULL)
786 SetLastError(ERROR_INVALID_PARAMETER);
791 Size
= dwBufferSize
.Y
* dwBufferSize
.X
* sizeof(CHAR_INFO
);
793 DPRINT("IntWriteConsoleOutput: %lx %p\n", Size
, lpWriteRegion
);
795 /* Allocate a Capture Buffer */
796 CaptureBuffer
= CsrAllocateCaptureBuffer(1, Size
);
797 if (CaptureBuffer
== NULL
)
799 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
800 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
804 /* Capture the user buffer */
805 CsrCaptureMessageBuffer(CaptureBuffer
,
808 (PVOID
*)&WriteOutputRequest
->CharInfo
);
810 /* Set up the data to send to the Console Server */
811 WriteOutputRequest
->OutputHandle
= hConsoleOutput
;
812 WriteOutputRequest
->Unicode
= bUnicode
;
813 WriteOutputRequest
->BufferSize
= dwBufferSize
;
814 WriteOutputRequest
->BufferCoord
= dwBufferCoord
;
815 WriteOutputRequest
->WriteRegion
= *lpWriteRegion
;
817 /* Call the server */
818 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
820 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepWriteConsoleOutput
),
821 sizeof(*WriteOutputRequest
));
823 /* Check for success */
824 if (!NT_SUCCESS(ApiMessage
.Status
))
826 BaseSetLastNTError(ApiMessage
.Status
);
829 /* Return the read region */
830 DPRINT("read region: %p\n", WriteOutputRequest
->WriteRegion
);
831 *lpWriteRegion
= WriteOutputRequest
->WriteRegion
;
833 /* Release the capture buffer */
834 CsrFreeCaptureBuffer(CaptureBuffer
);
836 /* Return TRUE or FALSE */
837 return NT_SUCCESS(ApiMessage
.Status
);
843 IntWriteConsoleOutputCode(IN HANDLE hConsoleOutput
,
844 IN CODE_TYPE CodeType
,
845 IN CONST VOID
*pCode
,
847 IN COORD dwWriteCoord
,
848 OUT LPDWORD lpNumberOfCodesWritten
)
851 CONSOLE_API_MESSAGE ApiMessage
;
852 PCONSOLE_WRITEOUTPUTCODE WriteOutputCodeRequest
= &ApiMessage
.Data
.WriteOutputCodeRequest
;
853 PCSR_CAPTURE_BUFFER CaptureBuffer
= NULL
;
854 ULONG CodeSize
, SizeBytes
;
856 if ( (CodeType
!= CODE_ASCII
) &&
857 (CodeType
!= CODE_UNICODE
) &&
858 (CodeType
!= CODE_ATTRIBUTE
) )
860 SetLastError(ERROR_INVALID_PARAMETER
);
864 DPRINT("IntWriteConsoleOutputCode\n");
866 /* Set up the data to send to the Console Server */
867 WriteOutputCodeRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
868 WriteOutputCodeRequest
->OutputHandle
= hConsoleOutput
;
869 WriteOutputCodeRequest
->Coord
= dwWriteCoord
;
870 WriteOutputCodeRequest
->NumCodes
= nLength
;
872 /* Determine the needed size */
873 WriteOutputCodeRequest
->CodeType
= CodeType
;
877 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, AsciiChar
);
881 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, UnicodeChar
);
885 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, Attribute
);
888 SizeBytes
= nLength
* CodeSize
;
891 * For optimization purposes, Windows (and hence ReactOS, too, for
892 * compatibility reasons) uses a static buffer if no more than eighty
893 * bytes are written. Otherwise a new buffer is allocated.
894 * This behaviour is also expected in the server-side.
896 if (SizeBytes
<= sizeof(WriteOutputCodeRequest
->CodeStaticBuffer
))
898 WriteOutputCodeRequest
->pCode
= WriteOutputCodeRequest
->CodeStaticBuffer
;
899 // CaptureBuffer = NULL;
903 RtlCopyMemory(WriteOutputCodeRequest
->pCode
,
907 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
909 SetLastError(ERROR_INVALID_ACCESS
);
916 /* Allocate a Capture Buffer */
917 CaptureBuffer
= CsrAllocateCaptureBuffer(1, SizeBytes
);
918 if (CaptureBuffer
== NULL
)
920 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
921 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
925 /* Capture the buffer to write */
926 CsrCaptureMessageBuffer(CaptureBuffer
,
929 (PVOID
*)&WriteOutputCodeRequest
->pCode
);
932 /* Call the server */
933 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
935 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepWriteConsoleOutputString
),
936 sizeof(*WriteOutputCodeRequest
));
938 /* Check for success */
939 Success
= NT_SUCCESS(ApiMessage
.Status
);
941 /* Release the capture buffer if needed */
942 if (CaptureBuffer
) CsrFreeCaptureBuffer(CaptureBuffer
);
944 /* Retrieve the results */
947 *lpNumberOfCodesWritten
= WriteOutputCodeRequest
->NumCodes
;
950 BaseSetLastNTError(ApiMessage
.Status
);
952 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
954 SetLastError(ERROR_INVALID_ACCESS
);
959 /* Return success status */
966 IntFillConsoleOutputCode(IN HANDLE hConsoleOutput
,
967 IN CODE_TYPE CodeType
,
968 IN CODE_ELEMENT Code
,
970 IN COORD dwWriteCoord
,
971 OUT LPDWORD lpNumberOfCodesWritten
)
974 CONSOLE_API_MESSAGE ApiMessage
;
975 PCONSOLE_FILLOUTPUTCODE FillOutputRequest
= &ApiMessage
.Data
.FillOutputRequest
;
977 DPRINT("IntFillConsoleOutputCode\n");
979 if ( (CodeType
!= CODE_ASCII
) &&
980 (CodeType
!= CODE_UNICODE
) &&
981 (CodeType
!= CODE_ATTRIBUTE
) )
983 SetLastError(ERROR_INVALID_PARAMETER
);
987 /* Set up the data to send to the Console Server */
988 FillOutputRequest
->ConsoleHandle
= NtCurrentPeb()->ProcessParameters
->ConsoleHandle
;
989 FillOutputRequest
->OutputHandle
= hConsoleOutput
;
990 FillOutputRequest
->WriteCoord
= dwWriteCoord
;
991 FillOutputRequest
->CodeType
= CodeType
;
992 FillOutputRequest
->Code
= Code
;
993 FillOutputRequest
->NumCodes
= nLength
;
995 /* Call the server */
996 CsrClientCallServer((PCSR_API_MESSAGE
)&ApiMessage
,
998 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX
, ConsolepFillConsoleOutput
),
999 sizeof(*FillOutputRequest
));
1001 /* Check for success */
1002 Success
= NT_SUCCESS(ApiMessage
.Status
);
1004 /* Retrieve the results */
1007 *lpNumberOfCodesWritten
= FillOutputRequest
->NumCodes
;
1010 BaseSetLastNTError(ApiMessage
.Status
);
1012 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1014 SetLastError(ERROR_INVALID_ACCESS
);
1019 /* Return success status */
1024 /* FUNCTIONS ******************************************************************/
1030 /*--------------------------------------------------------------
1037 ReadConsoleW(IN HANDLE hConsoleInput
,
1038 OUT LPVOID lpBuffer
,
1039 IN DWORD nNumberOfCharsToRead
,
1040 OUT LPDWORD lpNumberOfCharsRead
,
1041 IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL
)
1043 return IntReadConsole(hConsoleInput
,
1045 nNumberOfCharsToRead
,
1046 lpNumberOfCharsRead
,
1052 /*--------------------------------------------------------------
1059 ReadConsoleA(IN HANDLE hConsoleInput
,
1060 OUT LPVOID lpBuffer
,
1061 IN DWORD nNumberOfCharsToRead
,
1062 OUT LPDWORD lpNumberOfCharsRead
,
1063 IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL
)
1065 return IntReadConsole(hConsoleInput
,
1067 nNumberOfCharsToRead
,
1068 lpNumberOfCharsRead
,
1074 /*--------------------------------------------------------------
1081 PeekConsoleInputW(IN HANDLE hConsoleInput
,
1082 OUT PINPUT_RECORD lpBuffer
,
1084 OUT LPDWORD lpNumberOfEventsRead
)
1086 return IntGetConsoleInput(hConsoleInput
,
1089 lpNumberOfEventsRead
,
1090 CONSOLE_READ_KEEPEVENT
| CONSOLE_READ_CONTINUE
,
1095 /*--------------------------------------------------------------
1102 PeekConsoleInputA(IN HANDLE hConsoleInput
,
1103 OUT PINPUT_RECORD lpBuffer
,
1105 OUT LPDWORD lpNumberOfEventsRead
)
1107 return IntGetConsoleInput(hConsoleInput
,
1110 lpNumberOfEventsRead
,
1111 CONSOLE_READ_KEEPEVENT
| CONSOLE_READ_CONTINUE
,
1116 /*--------------------------------------------------------------
1123 ReadConsoleInputW(IN HANDLE hConsoleInput
,
1124 OUT PINPUT_RECORD lpBuffer
,
1126 OUT LPDWORD lpNumberOfEventsRead
)
1128 return IntGetConsoleInput(hConsoleInput
,
1131 lpNumberOfEventsRead
,
1137 /*--------------------------------------------------------------
1144 ReadConsoleInputA(IN HANDLE hConsoleInput
,
1145 OUT PINPUT_RECORD lpBuffer
,
1147 OUT LPDWORD lpNumberOfEventsRead
)
1149 return IntGetConsoleInput(hConsoleInput
,
1152 lpNumberOfEventsRead
,
1158 /*--------------------------------------------------------------
1159 * ReadConsoleInputExW
1165 ReadConsoleInputExW(IN HANDLE hConsoleInput
,
1166 OUT PINPUT_RECORD lpBuffer
,
1168 OUT LPDWORD lpNumberOfEventsRead
,
1171 return IntGetConsoleInput(hConsoleInput
,
1174 lpNumberOfEventsRead
,
1180 /*--------------------------------------------------------------
1181 * ReadConsoleInputExA
1187 ReadConsoleInputExA(IN HANDLE hConsoleInput
,
1188 OUT PINPUT_RECORD lpBuffer
,
1190 OUT LPDWORD lpNumberOfEventsRead
,
1193 return IntGetConsoleInput(hConsoleInput
,
1196 lpNumberOfEventsRead
,
1202 /*--------------------------------------------------------------
1203 * ReadConsoleOutputW
1209 ReadConsoleOutputW(IN HANDLE hConsoleOutput
,
1210 OUT PCHAR_INFO lpBuffer
,
1211 IN COORD dwBufferSize
,
1212 IN COORD dwBufferCoord
,
1213 IN OUT PSMALL_RECT lpReadRegion
)
1215 return IntReadConsoleOutput(hConsoleOutput
,
1224 /*--------------------------------------------------------------
1225 * ReadConsoleOutputA
1231 ReadConsoleOutputA(IN HANDLE hConsoleOutput
,
1232 OUT PCHAR_INFO lpBuffer
,
1233 IN COORD dwBufferSize
,
1234 IN COORD dwBufferCoord
,
1235 IN OUT PSMALL_RECT lpReadRegion
)
1237 return IntReadConsoleOutput(hConsoleOutput
,
1246 /*--------------------------------------------------------------
1247 * ReadConsoleOutputCharacterW
1253 ReadConsoleOutputCharacterW(IN HANDLE hConsoleOutput
,
1254 OUT LPWSTR lpCharacter
,
1256 IN COORD dwReadCoord
,
1257 OUT LPDWORD lpNumberOfCharsRead
)
1259 return IntReadConsoleOutputCode(hConsoleOutput
,
1264 lpNumberOfCharsRead
);
1268 /*--------------------------------------------------------------
1269 * ReadConsoleOutputCharacterA
1275 ReadConsoleOutputCharacterA(IN HANDLE hConsoleOutput
,
1276 OUT LPSTR lpCharacter
,
1278 IN COORD dwReadCoord
,
1279 OUT LPDWORD lpNumberOfCharsRead
)
1281 return IntReadConsoleOutputCode(hConsoleOutput
,
1286 lpNumberOfCharsRead
);
1290 /*--------------------------------------------------------------
1291 * ReadConsoleOutputAttribute
1297 ReadConsoleOutputAttribute(IN HANDLE hConsoleOutput
,
1298 OUT LPWORD lpAttribute
,
1300 IN COORD dwReadCoord
,
1301 OUT LPDWORD lpNumberOfAttrsRead
)
1303 return IntReadConsoleOutputCode(hConsoleOutput
,
1308 lpNumberOfAttrsRead
);
1312 /*******************
1314 *******************/
1316 /*--------------------------------------------------------------
1323 WriteConsoleW(IN HANDLE hConsoleOutput
,
1324 IN CONST VOID
*lpBuffer
,
1325 IN DWORD nNumberOfCharsToWrite
,
1326 OUT LPDWORD lpNumberOfCharsWritten
,
1329 return IntWriteConsole(hConsoleOutput
,
1331 nNumberOfCharsToWrite
,
1332 lpNumberOfCharsWritten
,
1338 /*--------------------------------------------------------------
1345 WriteConsoleA(IN HANDLE hConsoleOutput
,
1346 IN CONST VOID
*lpBuffer
,
1347 IN DWORD nNumberOfCharsToWrite
,
1348 OUT LPDWORD lpNumberOfCharsWritten
,
1351 return IntWriteConsole(hConsoleOutput
,
1353 nNumberOfCharsToWrite
,
1354 lpNumberOfCharsWritten
,
1360 /*--------------------------------------------------------------
1361 * WriteConsoleInputW
1367 WriteConsoleInputW(IN HANDLE hConsoleInput
,
1368 IN CONST INPUT_RECORD
*lpBuffer
,
1370 OUT LPDWORD lpNumberOfEventsWritten
)
1372 return IntWriteConsoleInput(hConsoleInput
,
1373 (PINPUT_RECORD
)lpBuffer
,
1375 lpNumberOfEventsWritten
,
1381 /*--------------------------------------------------------------
1382 * WriteConsoleInputA
1388 WriteConsoleInputA(IN HANDLE hConsoleInput
,
1389 IN CONST INPUT_RECORD
*lpBuffer
,
1391 OUT LPDWORD lpNumberOfEventsWritten
)
1393 return IntWriteConsoleInput(hConsoleInput
,
1394 (PINPUT_RECORD
)lpBuffer
,
1396 lpNumberOfEventsWritten
,
1402 /*--------------------------------------------------------------
1403 * WriteConsoleInputVDMW
1409 WriteConsoleInputVDMW(IN HANDLE hConsoleInput
,
1410 IN CONST INPUT_RECORD
*lpBuffer
,
1412 OUT LPDWORD lpNumberOfEventsWritten
)
1414 return IntWriteConsoleInput(hConsoleInput
,
1415 (PINPUT_RECORD
)lpBuffer
,
1417 lpNumberOfEventsWritten
,
1423 /*--------------------------------------------------------------
1424 * WriteConsoleInputVDMA
1430 WriteConsoleInputVDMA(IN HANDLE hConsoleInput
,
1431 IN CONST INPUT_RECORD
*lpBuffer
,
1433 OUT LPDWORD lpNumberOfEventsWritten
)
1435 return IntWriteConsoleInput(hConsoleInput
,
1436 (PINPUT_RECORD
)lpBuffer
,
1438 lpNumberOfEventsWritten
,
1444 /*--------------------------------------------------------------
1445 * WriteConsoleOutputW
1451 WriteConsoleOutputW(IN HANDLE hConsoleOutput
,
1452 IN CONST CHAR_INFO
*lpBuffer
,
1453 IN COORD dwBufferSize
,
1454 IN COORD dwBufferCoord
,
1455 IN OUT PSMALL_RECT lpWriteRegion
)
1457 return IntWriteConsoleOutput(hConsoleOutput
,
1466 /*--------------------------------------------------------------
1467 * WriteConsoleOutputA
1473 WriteConsoleOutputA(IN HANDLE hConsoleOutput
,
1474 IN CONST CHAR_INFO
*lpBuffer
,
1475 IN COORD dwBufferSize
,
1476 IN COORD dwBufferCoord
,
1477 IN OUT PSMALL_RECT lpWriteRegion
)
1479 return IntWriteConsoleOutput(hConsoleOutput
,
1488 /*--------------------------------------------------------------
1489 * WriteConsoleOutputCharacterW
1495 WriteConsoleOutputCharacterW(IN HANDLE hConsoleOutput
,
1496 IN LPCWSTR lpCharacter
,
1498 IN COORD dwWriteCoord
,
1499 OUT LPDWORD lpNumberOfCharsWritten
)
1501 return IntWriteConsoleOutputCode(hConsoleOutput
,
1506 lpNumberOfCharsWritten
);
1510 /*--------------------------------------------------------------
1511 * WriteConsoleOutputCharacterA
1517 WriteConsoleOutputCharacterA(IN HANDLE hConsoleOutput
,
1518 IN LPCSTR lpCharacter
,
1520 IN COORD dwWriteCoord
,
1521 OUT LPDWORD lpNumberOfCharsWritten
)
1523 return IntWriteConsoleOutputCode(hConsoleOutput
,
1528 lpNumberOfCharsWritten
);
1532 /*--------------------------------------------------------------
1533 * WriteConsoleOutputAttribute
1539 WriteConsoleOutputAttribute(IN HANDLE hConsoleOutput
,
1540 IN CONST WORD
*lpAttribute
,
1542 IN COORD dwWriteCoord
,
1543 OUT LPDWORD lpNumberOfAttrsWritten
)
1545 return IntWriteConsoleOutputCode(hConsoleOutput
,
1550 lpNumberOfAttrsWritten
);
1554 /*--------------------------------------------------------------
1555 * FillConsoleOutputCharacterW
1561 FillConsoleOutputCharacterW(IN HANDLE hConsoleOutput
,
1562 IN WCHAR cCharacter
,
1564 IN COORD dwWriteCoord
,
1565 OUT LPDWORD lpNumberOfCharsWritten
)
1568 Code
.UnicodeChar
= cCharacter
;
1569 return IntFillConsoleOutputCode(hConsoleOutput
,
1574 lpNumberOfCharsWritten
);
1578 /*--------------------------------------------------------------
1579 * FillConsoleOutputCharacterA
1585 FillConsoleOutputCharacterA(IN HANDLE hConsoleOutput
,
1588 IN COORD dwWriteCoord
,
1589 LPDWORD lpNumberOfCharsWritten
)
1592 Code
.AsciiChar
= cCharacter
;
1593 return IntFillConsoleOutputCode(hConsoleOutput
,
1598 lpNumberOfCharsWritten
);
1602 /*--------------------------------------------------------------
1603 * FillConsoleOutputAttribute
1609 FillConsoleOutputAttribute(IN HANDLE hConsoleOutput
,
1612 IN COORD dwWriteCoord
,
1613 OUT LPDWORD lpNumberOfAttrsWritten
)
1616 Code
.Attribute
= wAttribute
;
1617 return IntFillConsoleOutputCode(hConsoleOutput
,
1622 lpNumberOfAttrsWritten
);