2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/winsrv/consrv/conoutput.c
5 * PURPOSE: General Console Output Functions
6 * PROGRAMMERS: Jeffrey Morlan
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
10 /* INCLUDES *******************************************************************/
17 /* PUBLIC SERVER APIS *********************************************************/
20 * FIXME: This function MUST be moved from condrv/conoutput.c because only
21 * consrv knows how to manipulate VDM screenbuffers.
24 ConDrvWriteConsoleOutputVDM(IN PCONSOLE Console
,
25 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
26 IN PCHAR_CELL CharInfo
/*Buffer*/,
27 IN COORD CharInfoSize
,
28 IN PSMALL_RECT WriteRegion
);
30 ConDrvInvalidateBitMapRect(IN PCONSOLE Console
,
31 IN PCONSOLE_SCREEN_BUFFER Buffer
,
32 IN PSMALL_RECT Region
);
33 /* API_NUMBER: ConsolepInvalidateBitMapRect */
34 CON_API(SrvInvalidateBitMapRect
,
35 CONSOLE_INVALIDATEDIBITS
, InvalidateDIBitsRequest
)
38 PCONSOLE_SCREEN_BUFFER Buffer
;
40 Status
= ConSrvGetScreenBuffer(ProcessData
,
41 InvalidateDIBitsRequest
->OutputHandle
,
42 &Buffer
, GENERIC_READ
, TRUE
);
43 if (!NT_SUCCESS(Status
))
46 ASSERT((PCONSOLE
)Console
== Buffer
->Header
.Console
);
48 /* In text-mode only, draw the VDM buffer if present */
49 if (GetType(Buffer
) == TEXTMODE_BUFFER
&& Console
->VDMBuffer
)
51 PTEXTMODE_SCREEN_BUFFER TextBuffer
= (PTEXTMODE_SCREEN_BUFFER
)Buffer
;
53 /*Status =*/ ConDrvWriteConsoleOutputVDM((PCONSOLE
)Console
,
56 Console
->VDMBufferSize
,
57 &InvalidateDIBitsRequest
->Region
);
60 Status
= ConDrvInvalidateBitMapRect((PCONSOLE
)Console
,
62 &InvalidateDIBitsRequest
->Region
);
64 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
69 ConDrvSetConsolePalette(IN PCONSOLE Console
,
70 // IN PGRAPHICS_SCREEN_BUFFER Buffer,
71 IN PCONSOLE_SCREEN_BUFFER Buffer
,
72 IN HPALETTE PaletteHandle
,
73 IN UINT PaletteUsage
);
74 /* API_NUMBER: ConsolepSetPalette */
75 CON_API(SrvSetConsolePalette
,
76 CONSOLE_SETPALETTE
, SetPaletteRequest
)
79 // PGRAPHICS_SCREEN_BUFFER Buffer;
80 PCONSOLE_SCREEN_BUFFER Buffer
;
82 // NOTE: Tests show that this function is used only for graphics screen buffers
83 // and otherwise it returns FALSE + sets last error to invalid handle.
84 // I think it's ridiculous, because if you are in text mode, simulating
85 // a change of VGA palette via DAC registers (done by a call to SetConsolePalette)
86 // cannot be done... So I allow it in ReactOS !
88 Status = ConSrvGetGraphicsBuffer(ProcessData,
89 SetPaletteRequest->OutputHandle,
90 &Buffer, GENERIC_WRITE, TRUE);
92 Status
= ConSrvGetScreenBuffer(ProcessData
,
93 SetPaletteRequest
->OutputHandle
,
94 &Buffer
, GENERIC_WRITE
, TRUE
);
95 if (!NT_SUCCESS(Status
))
98 ASSERT((PCONSOLE
)Console
== Buffer
->Header
.Console
);
101 * Make the palette handle public, so that it can be
102 * used by other threads calling GDI functions on it.
103 * Indeed, the palette handle comes from a console app
104 * calling ourselves, running in CSRSS.
106 NtUserConsoleControl(ConsoleMakePalettePublic
,
107 &SetPaletteRequest
->PaletteHandle
,
108 sizeof(SetPaletteRequest
->PaletteHandle
));
110 Status
= ConDrvSetConsolePalette((PCONSOLE
)Console
,
112 SetPaletteRequest
->PaletteHandle
,
113 SetPaletteRequest
->Usage
);
115 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
120 ConDrvGetConsoleCursorInfo(IN PCONSOLE Console
,
121 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
122 OUT PCONSOLE_CURSOR_INFO CursorInfo
);
123 /* API_NUMBER: ConsolepGetCursorInfo */
124 CON_API(SrvGetConsoleCursorInfo
,
125 CONSOLE_GETSETCURSORINFO
, CursorInfoRequest
)
128 PTEXTMODE_SCREEN_BUFFER Buffer
;
130 Status
= ConSrvGetTextModeBuffer(ProcessData
,
131 CursorInfoRequest
->OutputHandle
,
132 &Buffer
, GENERIC_READ
, TRUE
);
133 if (!NT_SUCCESS(Status
))
136 ASSERT((PCONSOLE
)Console
== Buffer
->Header
.Console
);
138 Status
= ConDrvGetConsoleCursorInfo((PCONSOLE
)Console
,
140 &CursorInfoRequest
->Info
);
142 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
147 ConDrvSetConsoleCursorInfo(IN PCONSOLE Console
,
148 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
149 IN PCONSOLE_CURSOR_INFO CursorInfo
);
150 /* API_NUMBER: ConsolepSetCursorInfo */
151 CON_API(SrvSetConsoleCursorInfo
,
152 CONSOLE_GETSETCURSORINFO
, CursorInfoRequest
)
155 PTEXTMODE_SCREEN_BUFFER Buffer
;
157 Status
= ConSrvGetTextModeBuffer(ProcessData
,
158 CursorInfoRequest
->OutputHandle
,
159 &Buffer
, GENERIC_WRITE
, TRUE
);
160 if (!NT_SUCCESS(Status
))
163 ASSERT((PCONSOLE
)Console
== Buffer
->Header
.Console
);
165 Status
= ConDrvSetConsoleCursorInfo((PCONSOLE
)Console
,
167 &CursorInfoRequest
->Info
);
169 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
174 ConDrvSetConsoleCursorPosition(IN PCONSOLE Console
,
175 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
177 /* API_NUMBER: ConsolepSetCursorPosition */
178 CON_API(SrvSetConsoleCursorPosition
,
179 CONSOLE_SETCURSORPOSITION
, SetCursorPositionRequest
)
182 PTEXTMODE_SCREEN_BUFFER Buffer
;
184 Status
= ConSrvGetTextModeBuffer(ProcessData
,
185 SetCursorPositionRequest
->OutputHandle
,
186 &Buffer
, GENERIC_WRITE
, TRUE
);
187 if (!NT_SUCCESS(Status
))
190 ASSERT((PCONSOLE
)Console
== Buffer
->Header
.Console
);
192 Status
= ConDrvSetConsoleCursorPosition((PCONSOLE
)Console
,
194 &SetCursorPositionRequest
->Position
);
196 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
200 /* API_NUMBER: ConsolepCreateScreenBuffer */
201 CON_API(SrvCreateConsoleScreenBuffer
,
202 CONSOLE_CREATESCREENBUFFER
, CreateScreenBufferRequest
)
205 PCSR_PROCESS Process
= CsrGetClientThread()->Process
;
206 // PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(Process);
207 PCONSOLE_SCREEN_BUFFER Buff
;
209 PVOID ScreenBufferInfo
= NULL
;
210 TEXTMODE_BUFFER_INFO TextModeInfo
= {{80, 25},
212 DEFAULT_SCREEN_ATTRIB
,
213 DEFAULT_POPUP_ATTRIB
,
215 CSR_DEFAULT_CURSOR_SIZE
};
216 GRAPHICS_BUFFER_INFO GraphicsInfo
;
217 GraphicsInfo
.Info
= CreateScreenBufferRequest
->GraphicsBufferInfo
; // HACK for MSVC
219 if (CreateScreenBufferRequest
->ScreenBufferType
== CONSOLE_TEXTMODE_BUFFER
)
221 ScreenBufferInfo
= &TextModeInfo
;
224 * This is Windows behaviour, as described by MSDN and verified manually:
226 * The newly created screen buffer will copy some properties from the
227 * active screen buffer at the time that this function is called.
228 * The behavior is as follows:
229 * Font - copied from active screen buffer.
230 * Display Window Size - copied from active screen buffer.
231 * Buffer Size - matched to Display Window Size (NOT copied).
232 * Default Attributes (colors) - copied from active screen buffer.
233 * Default Popup Attributes (colors) - copied from active screen buffer.
236 /* If we have an active screen buffer, use its attributes as the new ones */
237 if (Console
->ActiveBuffer
&& GetType(Console
->ActiveBuffer
) == TEXTMODE_BUFFER
)
239 PTEXTMODE_SCREEN_BUFFER Buffer
= (PTEXTMODE_SCREEN_BUFFER
)Console
->ActiveBuffer
;
241 TextModeInfo
.ScreenAttrib
= Buffer
->ScreenDefaultAttrib
;
242 TextModeInfo
.PopupAttrib
= Buffer
->PopupDefaultAttrib
;
244 TextModeInfo
.CursorSize
= Buffer
->CursorInfo
.dwSize
;
245 TextModeInfo
.IsCursorVisible
= Buffer
->CursorInfo
.bVisible
;
247 /* Use the current view size */
248 TextModeInfo
.ScreenBufferSize
= Buffer
->ViewSize
;
249 TextModeInfo
.ViewSize
= Buffer
->ViewSize
;
253 /* Use the current console size */
254 TextModeInfo
.ScreenBufferSize
= Console
->ConsoleSize
;
255 TextModeInfo
.ViewSize
= Console
->ConsoleSize
;
258 /* Normalize the screen buffer size if needed */
259 if (TextModeInfo
.ScreenBufferSize
.X
== 0) TextModeInfo
.ScreenBufferSize
.X
= 1;
260 if (TextModeInfo
.ScreenBufferSize
.Y
== 0) TextModeInfo
.ScreenBufferSize
.Y
= 1;
262 else if (CreateScreenBufferRequest
->ScreenBufferType
== CONSOLE_GRAPHICS_BUFFER
)
264 /* Get information from the graphics buffer information structure */
265 if (!CsrValidateMessageBuffer(ApiMessage
,
266 (PVOID
*)&CreateScreenBufferRequest
->GraphicsBufferInfo
.lpBitMapInfo
,
267 CreateScreenBufferRequest
->GraphicsBufferInfo
.dwBitMapInfoLength
,
270 return STATUS_INVALID_PARAMETER
;
273 ScreenBufferInfo
= &GraphicsInfo
;
275 /* Initialize shared variables */
276 // CreateScreenBufferRequest->GraphicsBufferInfo.hMutex
277 CreateScreenBufferRequest
->hMutex
= GraphicsInfo
.Info
.hMutex
= INVALID_HANDLE_VALUE
;
278 // CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap
279 CreateScreenBufferRequest
->lpBitMap
= GraphicsInfo
.Info
.lpBitMap
= NULL
;
281 /* A graphics screen buffer is never inheritable */
282 CreateScreenBufferRequest
->InheritHandle
= FALSE
;
286 DPRINT1("Invalid ScreenBuffer type %lu\n", CreateScreenBufferRequest
->ScreenBufferType
);
287 return STATUS_INVALID_PARAMETER
;
290 Status
= ConDrvCreateScreenBuffer(&Buff
,
292 Process
->ProcessHandle
,
293 CreateScreenBufferRequest
->ScreenBufferType
,
295 if (!NT_SUCCESS(Status
))
298 /* Insert the new handle inside the process handles table */
299 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
301 Status
= ConSrvInsertObject(ProcessData
,
302 &CreateScreenBufferRequest
->OutputHandle
,
304 CreateScreenBufferRequest
->DesiredAccess
,
305 CreateScreenBufferRequest
->InheritHandle
,
306 CreateScreenBufferRequest
->ShareMode
);
308 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
310 if (!NT_SUCCESS(Status
))
312 ConDrvDeleteScreenBuffer(Buff
);
316 if (CreateScreenBufferRequest
->ScreenBufferType
== CONSOLE_GRAPHICS_BUFFER
)
318 PGRAPHICS_SCREEN_BUFFER Buffer
= (PGRAPHICS_SCREEN_BUFFER
)Buff
;
320 * Initialize the graphics buffer information structure
321 * and give it back to the client.
323 // CreateScreenBufferRequest->GraphicsBufferInfo.hMutex
324 CreateScreenBufferRequest
->hMutex
= Buffer
->ClientMutex
;
325 // CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap
326 CreateScreenBufferRequest
->lpBitMap
= Buffer
->ClientBitMap
;
333 ConDrvSetConsoleActiveScreenBuffer(IN PCONSOLE Console
,
334 IN PCONSOLE_SCREEN_BUFFER Buffer
);
335 /* API_NUMBER: ConsolepSetActiveScreenBuffer */
336 CON_API(SrvSetConsoleActiveScreenBuffer
,
337 CONSOLE_SETACTIVESCREENBUFFER
, SetScreenBufferRequest
)
340 PCONSOLE_SCREEN_BUFFER Buffer
;
342 Status
= ConSrvGetScreenBuffer(ProcessData
,
343 SetScreenBufferRequest
->OutputHandle
,
344 &Buffer
, GENERIC_WRITE
, TRUE
);
345 if (!NT_SUCCESS(Status
))
348 ASSERT((PCONSOLE
)Console
== Buffer
->Header
.Console
);
350 Status
= ConDrvSetConsoleActiveScreenBuffer((PCONSOLE
)Console
, Buffer
);
352 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
357 /* CSR THREADS FOR WriteConsole ***********************************************/
360 DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage
,
361 IN PCSR_THREAD ClientThread
,
362 IN BOOLEAN CreateWaitBlock OPTIONAL
);
364 // Wait function CSR_WAIT_FUNCTION
367 WriteConsoleThread(IN PLIST_ENTRY WaitList
,
368 IN PCSR_THREAD WaitThread
,
369 IN PCSR_API_MESSAGE WaitApiMessage
,
370 IN PVOID WaitContext
,
371 IN PVOID WaitArgument1
,
372 IN PVOID WaitArgument2
,
377 DPRINT("WriteConsoleThread - WaitContext = 0x%p, WaitArgument1 = 0x%p, WaitArgument2 = 0x%p, WaitFlags = %lu\n", WaitContext
, WaitArgument1
, WaitArgument2
, WaitFlags
);
380 * If we are notified of the process termination via a call
381 * to CsrNotifyWaitBlock triggered by CsrDestroyProcess or
382 * CsrDestroyThread, just return.
384 if (WaitFlags
& CsrProcessTerminating
)
386 Status
= STATUS_THREAD_IS_TERMINATING
;
390 Status
= DoWriteConsole(WaitApiMessage
, WaitThread
, FALSE
);
393 if (Status
!= STATUS_PENDING
)
395 WaitApiMessage
->Status
= Status
;
398 return (Status
== STATUS_PENDING
? FALSE
: TRUE
);
402 ConDrvWriteConsole(IN PCONSOLE Console
,
403 IN PTEXTMODE_SCREEN_BUFFER ScreenBuffer
,
405 IN PVOID StringBuffer
,
406 IN ULONG NumCharsToWrite
,
407 OUT PULONG NumCharsWritten OPTIONAL
);
409 DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage
,
410 IN PCSR_THREAD ClientThread
,
411 IN BOOLEAN CreateWaitBlock OPTIONAL
)
414 PCONSOLE_WRITECONSOLE WriteConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteConsoleRequest
;
415 PTEXTMODE_SCREEN_BUFFER ScreenBuffer
;
418 ULONG NrCharactersWritten
= 0;
419 ULONG CharSize
= (WriteConsoleRequest
->Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
421 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(ClientThread
->Process
),
422 WriteConsoleRequest
->OutputHandle
,
423 &ScreenBuffer
, GENERIC_WRITE
, FALSE
);
424 if (!NT_SUCCESS(Status
)) return Status
;
427 * For optimization purposes, Windows (and hence ReactOS, too, for
428 * compatibility reasons) uses a static buffer if no more than eighty
429 * bytes are written. Otherwise a new buffer is used.
430 * The client-side expects that we know this behaviour.
432 if (WriteConsoleRequest
->UsingStaticBuffer
&&
433 WriteConsoleRequest
->NumBytes
<= sizeof(WriteConsoleRequest
->StaticBuffer
))
436 * Adjust the internal pointer, because its old value points to
437 * the static buffer in the original ApiMessage structure.
439 // WriteConsoleRequest->Buffer = WriteConsoleRequest->StaticBuffer;
440 Buffer
= WriteConsoleRequest
->StaticBuffer
;
444 Buffer
= WriteConsoleRequest
->Buffer
;
447 DPRINT("Calling ConDrvWriteConsole\n");
448 Status
= ConDrvWriteConsole(ScreenBuffer
->Header
.Console
,
450 WriteConsoleRequest
->Unicode
,
452 WriteConsoleRequest
->NumBytes
/ CharSize
, // NrCharactersToWrite
453 &NrCharactersWritten
);
454 DPRINT("ConDrvWriteConsole returned (%d ; Status = 0x%08x)\n",
455 NrCharactersWritten
, Status
);
457 if (Status
== STATUS_PENDING
)
461 PCONSRV_CONSOLE Console
= (PCONSRV_CONSOLE
)ScreenBuffer
->Header
.Console
;
463 if (!CsrCreateWait(&Console
->WriteWaitQueue
,
470 Status
= STATUS_NO_MEMORY
;
475 /* Wait until we un-pause the console */
476 // Status = STATUS_PENDING;
480 /* We read all what we wanted. Set the number of bytes written. */
481 WriteConsoleRequest
->NumBytes
= NrCharactersWritten
* CharSize
;
485 ConSrvReleaseScreenBuffer(ScreenBuffer
, FALSE
);
490 /* TEXT OUTPUT APIS ***********************************************************/
493 ConDrvReadConsoleOutput(IN PCONSOLE Console
,
494 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
496 OUT PCHAR_INFO CharInfo
/*Buffer*/,
497 IN OUT PSMALL_RECT ReadRegion
);
498 /* API_NUMBER: ConsolepReadConsoleOutput */
499 CON_API(SrvReadConsoleOutput
,
500 CONSOLE_READOUTPUT
, ReadOutputRequest
)
503 PTEXTMODE_SCREEN_BUFFER Buffer
;
507 NumCells
= ConioRectWidth(&ReadOutputRequest
->ReadRegion
) *
508 ConioRectHeight(&ReadOutputRequest
->ReadRegion
);
511 * For optimization purposes, Windows (and hence ReactOS, too, for
512 * compatibility reasons) uses a static buffer if no more than one
513 * cell is read. Otherwise a new buffer is used.
514 * The client-side expects that we know this behaviour.
519 * Adjust the internal pointer, because its old value points to
520 * the static buffer in the original ApiMessage structure.
522 // ReadOutputRequest->CharInfo = &ReadOutputRequest->StaticBuffer;
523 CharInfo
= &ReadOutputRequest
->StaticBuffer
;
527 if (!CsrValidateMessageBuffer(ApiMessage
,
528 (PVOID
*)&ReadOutputRequest
->CharInfo
,
532 return STATUS_INVALID_PARAMETER
;
535 CharInfo
= ReadOutputRequest
->CharInfo
;
538 Status
= ConSrvGetTextModeBuffer(ProcessData
,
539 ReadOutputRequest
->OutputHandle
,
540 &Buffer
, GENERIC_READ
, TRUE
);
541 if (!NT_SUCCESS(Status
))
544 ASSERT((PCONSOLE
)Console
== Buffer
->Header
.Console
);
546 Status
= ConDrvReadConsoleOutput((PCONSOLE
)Console
,
548 ReadOutputRequest
->Unicode
,
550 &ReadOutputRequest
->ReadRegion
);
552 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
557 ConDrvWriteConsoleOutput(IN PCONSOLE Console
,
558 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
560 IN PCHAR_INFO CharInfo
/*Buffer*/,
561 IN OUT PSMALL_RECT WriteRegion
);
562 /* API_NUMBER: ConsolepWriteConsoleOutput */
563 CON_API(SrvWriteConsoleOutput
,
564 CONSOLE_WRITEOUTPUT
, WriteOutputRequest
)
567 PCSR_PROCESS Process
= CsrGetClientThread()->Process
;
568 // PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(Process);
569 PTEXTMODE_SCREEN_BUFFER Buffer
;
573 NumCells
= ConioRectWidth(&WriteOutputRequest
->WriteRegion
) *
574 ConioRectHeight(&WriteOutputRequest
->WriteRegion
);
576 Status
= ConSrvGetTextModeBuffer(ProcessData
,
577 WriteOutputRequest
->OutputHandle
,
578 &Buffer
, GENERIC_WRITE
, TRUE
);
579 if (!NT_SUCCESS(Status
))
582 ASSERT((PCONSOLE
)Console
== Buffer
->Header
.Console
);
585 * Validate the message buffer if we do not use a process' heap buffer
586 * (CsrAllocateCaptureBuffer succeeded because we haven't allocated
587 * a too large (>= 64 kB, size of the CSR heap) data buffer).
589 if (!WriteOutputRequest
->UseVirtualMemory
)
592 * For optimization purposes, Windows (and hence ReactOS, too, for
593 * compatibility reasons) uses a static buffer if no more than one
594 * cell is written. Otherwise a new buffer is used.
595 * The client-side expects that we know this behaviour.
600 * Adjust the internal pointer, because its old value points to
601 * the static buffer in the original ApiMessage structure.
603 // WriteOutputRequest->CharInfo = &WriteOutputRequest->StaticBuffer;
604 CharInfo
= &WriteOutputRequest
->StaticBuffer
;
608 if (!CsrValidateMessageBuffer(ApiMessage
,
609 (PVOID
*)&WriteOutputRequest
->CharInfo
,
613 Status
= STATUS_INVALID_PARAMETER
;
617 CharInfo
= WriteOutputRequest
->CharInfo
;
623 * This was not the case: we use a heap buffer. Retrieve its contents.
625 ULONG Size
= NumCells
* sizeof(CHAR_INFO
);
627 CharInfo
= ConsoleAllocHeap(HEAP_ZERO_MEMORY
, Size
);
628 if (CharInfo
== NULL
)
630 Status
= STATUS_NO_MEMORY
;
634 Status
= NtReadVirtualMemory(Process
->ProcessHandle
,
635 WriteOutputRequest
->CharInfo
,
639 if (!NT_SUCCESS(Status
))
641 ConsoleFreeHeap(CharInfo
);
642 // Status = STATUS_NO_MEMORY;
647 Status
= ConDrvWriteConsoleOutput((PCONSOLE
)Console
,
649 WriteOutputRequest
->Unicode
,
651 &WriteOutputRequest
->WriteRegion
);
653 /* Free the temporary buffer if we used the process' heap buffer */
654 if (WriteOutputRequest
->UseVirtualMemory
&& CharInfo
)
655 ConsoleFreeHeap(CharInfo
);
658 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
662 /* API_NUMBER: ConsolepWriteConsole */
663 CON_API(SrvWriteConsole
,
664 CONSOLE_WRITECONSOLE
, WriteConsoleRequest
)
668 DPRINT("SrvWriteConsole\n");
671 * For optimization purposes, Windows (and hence ReactOS, too, for
672 * compatibility reasons) uses a static buffer if no more than eighty
673 * bytes are written. Otherwise a new buffer is used.
674 * The client-side expects that we know this behaviour.
676 if (WriteConsoleRequest
->UsingStaticBuffer
&&
677 WriteConsoleRequest
->NumBytes
<= sizeof(WriteConsoleRequest
->StaticBuffer
))
680 * Adjust the internal pointer, because its old value points to
681 * the static buffer in the original ApiMessage structure.
683 // WriteConsoleRequest->Buffer = WriteConsoleRequest->StaticBuffer;
687 if (!CsrValidateMessageBuffer(ApiMessage
,
688 (PVOID
)&WriteConsoleRequest
->Buffer
,
689 WriteConsoleRequest
->NumBytes
,
692 return STATUS_INVALID_PARAMETER
;
696 Status
= DoWriteConsole(ApiMessage
, CsrGetClientThread(), TRUE
);
698 if (Status
== STATUS_PENDING
) *ReplyCode
= CsrReplyPending
;
704 ConDrvReadConsoleOutputString(IN PCONSOLE Console
,
705 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
706 IN CODE_TYPE CodeType
,
707 OUT PVOID StringBuffer
,
708 IN ULONG NumCodesToRead
,
710 // OUT PCOORD EndCoord,
711 OUT PULONG NumCodesRead OPTIONAL
);
712 /* API_NUMBER: ConsolepReadConsoleOutputString */
713 CON_API(SrvReadConsoleOutputString
,
714 CONSOLE_READOUTPUTCODE
, ReadOutputCodeRequest
)
717 PTEXTMODE_SCREEN_BUFFER Buffer
;
721 switch (ReadOutputCodeRequest
->CodeType
)
724 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, AsciiChar
);
728 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, UnicodeChar
);
732 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, Attribute
);
736 return STATUS_INVALID_PARAMETER
;
740 * For optimization purposes, Windows (and hence ReactOS, too, for
741 * compatibility reasons) uses a static buffer if no more than eighty
742 * bytes are read. Otherwise a new buffer is used.
743 * The client-side expects that we know this behaviour.
745 if (ReadOutputCodeRequest
->NumCodes
* CodeSize
<= sizeof(ReadOutputCodeRequest
->CodeStaticBuffer
))
748 * Adjust the internal pointer, because its old value points to
749 * the static buffer in the original ApiMessage structure.
751 // ReadOutputCodeRequest->pCode = ReadOutputCodeRequest->CodeStaticBuffer;
752 pCode
= ReadOutputCodeRequest
->CodeStaticBuffer
;
756 if (!CsrValidateMessageBuffer(ApiMessage
,
757 (PVOID
*)&ReadOutputCodeRequest
->pCode
,
758 ReadOutputCodeRequest
->NumCodes
,
761 return STATUS_INVALID_PARAMETER
;
764 pCode
= ReadOutputCodeRequest
->pCode
;
767 Status
= ConSrvGetTextModeBuffer(ProcessData
,
768 ReadOutputCodeRequest
->OutputHandle
,
769 &Buffer
, GENERIC_READ
, TRUE
);
770 if (!NT_SUCCESS(Status
))
772 ReadOutputCodeRequest
->NumCodes
= 0;
776 ASSERT((PCONSOLE
)Console
== Buffer
->Header
.Console
);
778 Status
= ConDrvReadConsoleOutputString((PCONSOLE
)Console
,
780 ReadOutputCodeRequest
->CodeType
,
782 ReadOutputCodeRequest
->NumCodes
,
783 &ReadOutputCodeRequest
->Coord
,
784 // &ReadOutputCodeRequest->EndCoord,
785 &ReadOutputCodeRequest
->NumCodes
);
787 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
792 ConDrvWriteConsoleOutputString(IN PCONSOLE Console
,
793 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
794 IN CODE_TYPE CodeType
,
795 IN PVOID StringBuffer
,
796 IN ULONG NumCodesToWrite
,
797 IN PCOORD WriteCoord
,
798 // OUT PCOORD EndCoord,
799 OUT PULONG NumCodesWritten OPTIONAL
);
800 /* API_NUMBER: ConsolepWriteConsoleOutputString */
801 CON_API(SrvWriteConsoleOutputString
,
802 CONSOLE_WRITEOUTPUTCODE
, WriteOutputCodeRequest
)
805 PTEXTMODE_SCREEN_BUFFER Buffer
;
809 switch (WriteOutputCodeRequest
->CodeType
)
812 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, AsciiChar
);
816 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, UnicodeChar
);
820 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, Attribute
);
824 return STATUS_INVALID_PARAMETER
;
828 * For optimization purposes, Windows (and hence ReactOS, too, for
829 * compatibility reasons) uses a static buffer if no more than eighty
830 * bytes are written. Otherwise a new buffer is used.
831 * The client-side expects that we know this behaviour.
833 if (WriteOutputCodeRequest
->NumCodes
* CodeSize
<= sizeof(WriteOutputCodeRequest
->CodeStaticBuffer
))
836 * Adjust the internal pointer, because its old value points to
837 * the static buffer in the original ApiMessage structure.
839 // WriteOutputCodeRequest->pCode = WriteOutputCodeRequest->CodeStaticBuffer;
840 pCode
= WriteOutputCodeRequest
->CodeStaticBuffer
;
844 if (!CsrValidateMessageBuffer(ApiMessage
,
845 (PVOID
*)&WriteOutputCodeRequest
->pCode
,
846 WriteOutputCodeRequest
->NumCodes
,
849 return STATUS_INVALID_PARAMETER
;
852 pCode
= WriteOutputCodeRequest
->pCode
;
855 Status
= ConSrvGetTextModeBuffer(ProcessData
,
856 WriteOutputCodeRequest
->OutputHandle
,
857 &Buffer
, GENERIC_WRITE
, TRUE
);
858 if (!NT_SUCCESS(Status
))
860 WriteOutputCodeRequest
->NumCodes
= 0;
864 ASSERT((PCONSOLE
)Console
== Buffer
->Header
.Console
);
866 Status
= ConDrvWriteConsoleOutputString((PCONSOLE
)Console
,
868 WriteOutputCodeRequest
->CodeType
,
870 WriteOutputCodeRequest
->NumCodes
,
871 &WriteOutputCodeRequest
->Coord
,
872 // &WriteOutputCodeRequest->EndCoord,
873 &WriteOutputCodeRequest
->NumCodes
);
875 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
880 ConDrvFillConsoleOutput(IN PCONSOLE Console
,
881 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
882 IN CODE_TYPE CodeType
,
883 IN CODE_ELEMENT Code
,
884 IN ULONG NumCodesToWrite
,
885 IN PCOORD WriteCoord
,
886 OUT PULONG NumCodesWritten OPTIONAL
);
887 /* API_NUMBER: ConsolepFillConsoleOutput */
888 CON_API(SrvFillConsoleOutput
,
889 CONSOLE_FILLOUTPUTCODE
, FillOutputRequest
)
892 PTEXTMODE_SCREEN_BUFFER Buffer
;
893 CODE_TYPE CodeType
= FillOutputRequest
->CodeType
;
895 if ( (CodeType
!= CODE_ASCII
) &&
896 (CodeType
!= CODE_UNICODE
) &&
897 (CodeType
!= CODE_ATTRIBUTE
) )
899 return STATUS_INVALID_PARAMETER
;
902 Status
= ConSrvGetTextModeBuffer(ProcessData
,
903 FillOutputRequest
->OutputHandle
,
904 &Buffer
, GENERIC_WRITE
, TRUE
);
905 if (!NT_SUCCESS(Status
))
907 FillOutputRequest
->NumCodes
= 0;
911 ASSERT((PCONSOLE
)Console
== Buffer
->Header
.Console
);
913 Status
= ConDrvFillConsoleOutput((PCONSOLE
)Console
,
916 FillOutputRequest
->Code
,
917 FillOutputRequest
->NumCodes
,
918 &FillOutputRequest
->WriteCoord
,
919 &FillOutputRequest
->NumCodes
);
921 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
926 ConDrvGetConsoleScreenBufferInfo(IN PCONSOLE Console
,
927 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
928 OUT PCOORD ScreenBufferSize
,
929 OUT PCOORD CursorPosition
,
930 OUT PCOORD ViewOrigin
,
932 OUT PCOORD MaximumViewSize
,
933 OUT PWORD Attributes
);
934 /* API_NUMBER: ConsolepGetScreenBufferInfo */
935 CON_API(SrvGetConsoleScreenBufferInfo
,
936 CONSOLE_GETSCREENBUFFERINFO
, ScreenBufferInfoRequest
)
939 PTEXTMODE_SCREEN_BUFFER Buffer
;
941 Status
= ConSrvGetTextModeBuffer(ProcessData
,
942 ScreenBufferInfoRequest
->OutputHandle
,
943 &Buffer
, GENERIC_READ
, TRUE
);
944 if (!NT_SUCCESS(Status
))
947 ASSERT((PCONSOLE
)Console
== Buffer
->Header
.Console
);
949 Status
= ConDrvGetConsoleScreenBufferInfo((PCONSOLE
)Console
,
951 &ScreenBufferInfoRequest
->ScreenBufferSize
,
952 &ScreenBufferInfoRequest
->CursorPosition
,
953 &ScreenBufferInfoRequest
->ViewOrigin
,
954 &ScreenBufferInfoRequest
->ViewSize
,
955 &ScreenBufferInfoRequest
->MaximumViewSize
,
956 &ScreenBufferInfoRequest
->Attributes
);
958 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
963 ConDrvSetConsoleTextAttribute(IN PCONSOLE Console
,
964 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
966 /* API_NUMBER: ConsolepSetTextAttribute */
967 CON_API(SrvSetConsoleTextAttribute
,
968 CONSOLE_SETTEXTATTRIB
, SetTextAttribRequest
)
971 PTEXTMODE_SCREEN_BUFFER Buffer
;
973 Status
= ConSrvGetTextModeBuffer(ProcessData
,
974 SetTextAttribRequest
->OutputHandle
,
975 &Buffer
, GENERIC_WRITE
, TRUE
);
976 if (!NT_SUCCESS(Status
))
979 ASSERT((PCONSOLE
)Console
== Buffer
->Header
.Console
);
981 Status
= ConDrvSetConsoleTextAttribute((PCONSOLE
)Console
,
983 SetTextAttribRequest
->Attributes
);
985 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
990 ConDrvSetConsoleScreenBufferSize(IN PCONSOLE Console
,
991 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
993 /* API_NUMBER: ConsolepSetScreenBufferSize */
994 CON_API(SrvSetConsoleScreenBufferSize
,
995 CONSOLE_SETSCREENBUFFERSIZE
, SetScreenBufferSizeRequest
)
998 PTEXTMODE_SCREEN_BUFFER Buffer
;
1000 Status
= ConSrvGetTextModeBuffer(ProcessData
,
1001 SetScreenBufferSizeRequest
->OutputHandle
,
1002 &Buffer
, GENERIC_WRITE
, TRUE
);
1003 if (!NT_SUCCESS(Status
))
1006 ASSERT((PCONSOLE
)Console
== Buffer
->Header
.Console
);
1008 Status
= ConDrvSetConsoleScreenBufferSize((PCONSOLE
)Console
,
1010 &SetScreenBufferSizeRequest
->Size
);
1012 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
1017 ConDrvScrollConsoleScreenBuffer(IN PCONSOLE Console
,
1018 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
1020 IN PSMALL_RECT ScrollRectangle
,
1021 IN BOOLEAN UseClipRectangle
,
1022 IN PSMALL_RECT ClipRectangle OPTIONAL
,
1023 IN PCOORD DestinationOrigin
,
1024 IN CHAR_INFO FillChar
);
1025 /* API_NUMBER: ConsolepScrollScreenBuffer */
1026 CON_API(SrvScrollConsoleScreenBuffer
,
1027 CONSOLE_SCROLLSCREENBUFFER
, ScrollScreenBufferRequest
)
1030 PTEXTMODE_SCREEN_BUFFER Buffer
;
1032 Status
= ConSrvGetTextModeBuffer(ProcessData
,
1033 ScrollScreenBufferRequest
->OutputHandle
,
1034 &Buffer
, GENERIC_WRITE
, TRUE
);
1035 if (!NT_SUCCESS(Status
))
1038 ASSERT((PCONSOLE
)Console
== Buffer
->Header
.Console
);
1040 Status
= ConDrvScrollConsoleScreenBuffer((PCONSOLE
)Console
,
1042 ScrollScreenBufferRequest
->Unicode
,
1043 &ScrollScreenBufferRequest
->ScrollRectangle
,
1044 ScrollScreenBufferRequest
->UseClipRectangle
,
1045 &ScrollScreenBufferRequest
->ClipRectangle
,
1046 &ScrollScreenBufferRequest
->DestinationOrigin
,
1047 ScrollScreenBufferRequest
->Fill
);
1049 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
1054 ConDrvSetConsoleWindowInfo(IN PCONSOLE Console
,
1055 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
1056 IN BOOLEAN Absolute
,
1057 IN PSMALL_RECT WindowRect
);
1058 /* API_NUMBER: ConsolepSetWindowInfo */
1059 CON_API(SrvSetConsoleWindowInfo
,
1060 CONSOLE_SETWINDOWINFO
, SetWindowInfoRequest
)
1063 // PCONSOLE_SCREEN_BUFFER Buffer;
1064 PTEXTMODE_SCREEN_BUFFER Buffer
;
1066 DPRINT("SrvSetConsoleWindowInfo(0x%08x, %d, {L%d, T%d, R%d, B%d}) called\n",
1067 SetWindowInfoRequest
->OutputHandle
, SetWindowInfoRequest
->Absolute
,
1068 SetWindowInfoRequest
->WindowRect
.Left
,
1069 SetWindowInfoRequest
->WindowRect
.Top
,
1070 SetWindowInfoRequest
->WindowRect
.Right
,
1071 SetWindowInfoRequest
->WindowRect
.Bottom
);
1073 // ConSrvGetScreenBuffer
1074 Status
= ConSrvGetTextModeBuffer(ProcessData
,
1075 SetWindowInfoRequest
->OutputHandle
,
1076 &Buffer
, GENERIC_READ
, TRUE
);
1077 if (!NT_SUCCESS(Status
))
1080 ASSERT((PCONSOLE
)Console
== Buffer
->Header
.Console
);
1082 Status
= ConDrvSetConsoleWindowInfo((PCONSOLE
)Console
,
1084 SetWindowInfoRequest
->Absolute
,
1085 &SetWindowInfoRequest
->WindowRect
);
1087 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);