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 fro 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 CSR_API(SrvInvalidateBitMapRect
)
36 PCONSOLE_INVALIDATEDIBITS InvalidateDIBitsRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.InvalidateDIBitsRequest
;
37 PCONSOLE_SCREEN_BUFFER Buffer
;
39 DPRINT("SrvInvalidateBitMapRect\n");
41 Status
= ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
42 InvalidateDIBitsRequest
->OutputHandle
,
43 &Buffer
, GENERIC_READ
, TRUE
);
44 if (!NT_SUCCESS(Status
)) return Status
;
46 /* In text-mode only, draw the VDM buffer if present */
47 if (GetType(Buffer
) == TEXTMODE_BUFFER
)
49 PTEXTMODE_SCREEN_BUFFER TextBuffer
= (PTEXTMODE_SCREEN_BUFFER
)Buffer
;
51 /*Status =*/ ConDrvWriteConsoleOutputVDM(Buffer
->Header
.Console
,
53 Buffer
->Header
.Console
->VDMBuffer
,
54 Buffer
->Header
.Console
->VDMBufferSize
,
55 &InvalidateDIBitsRequest
->Region
);
58 Status
= ConDrvInvalidateBitMapRect(Buffer
->Header
.Console
,
60 &InvalidateDIBitsRequest
->Region
);
62 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
67 ConDrvSetConsolePalette(IN PCONSOLE Console
,
68 // IN PGRAPHICS_SCREEN_BUFFER Buffer,
69 IN PCONSOLE_SCREEN_BUFFER Buffer
,
70 IN HPALETTE PaletteHandle
,
71 IN UINT PaletteUsage
);
72 CSR_API(SrvSetConsolePalette
)
75 PCONSOLE_SETPALETTE SetPaletteRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetPaletteRequest
;
76 // PGRAPHICS_SCREEN_BUFFER Buffer;
77 PCONSOLE_SCREEN_BUFFER Buffer
;
79 DPRINT("SrvSetConsolePalette\n");
81 // NOTE: Tests show that this function is used only for graphics screen buffers
82 // and otherwise it returns FALSE + sets last error to invalid handle.
83 // I think it's ridiculous, because if you are in text mode, simulating
84 // a change of VGA palette via DAC registers (done by a call to SetConsolePalette)
85 // cannot be done... So I allow it in ReactOS !
87 Status = ConSrvGetGraphicsBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
88 SetPaletteRequest->OutputHandle,
89 &Buffer, GENERIC_WRITE, TRUE);
91 Status
= ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
92 SetPaletteRequest
->OutputHandle
,
93 &Buffer
, GENERIC_WRITE
, TRUE
);
94 if (!NT_SUCCESS(Status
)) return Status
;
97 * Make the palette handle public, so that it can be
98 * used by other threads calling GDI functions on it.
99 * Indeed, the palette handle comes from a console app
100 * calling ourselves, running in CSRSS.
102 NtUserConsoleControl(ConsoleMakePalettePublic
,
103 &SetPaletteRequest
->PaletteHandle
,
104 sizeof(SetPaletteRequest
->PaletteHandle
));
106 Status
= ConDrvSetConsolePalette(Buffer
->Header
.Console
,
108 SetPaletteRequest
->PaletteHandle
,
109 SetPaletteRequest
->Usage
);
111 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
116 ConDrvGetConsoleCursorInfo(IN PCONSOLE Console
,
117 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
118 OUT PCONSOLE_CURSOR_INFO CursorInfo
);
119 CSR_API(SrvGetConsoleCursorInfo
)
122 PCONSOLE_GETSETCURSORINFO CursorInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CursorInfoRequest
;
123 PTEXTMODE_SCREEN_BUFFER Buffer
;
125 DPRINT("SrvGetConsoleCursorInfo\n");
127 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
128 CursorInfoRequest
->OutputHandle
,
129 &Buffer
, GENERIC_READ
, TRUE
);
130 if (!NT_SUCCESS(Status
)) return Status
;
132 Status
= ConDrvGetConsoleCursorInfo(Buffer
->Header
.Console
,
134 &CursorInfoRequest
->Info
);
136 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
141 ConDrvSetConsoleCursorInfo(IN PCONSOLE Console
,
142 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
143 IN PCONSOLE_CURSOR_INFO CursorInfo
);
144 CSR_API(SrvSetConsoleCursorInfo
)
147 PCONSOLE_GETSETCURSORINFO CursorInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CursorInfoRequest
;
148 PTEXTMODE_SCREEN_BUFFER Buffer
;
150 DPRINT("SrvSetConsoleCursorInfo\n");
152 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
153 CursorInfoRequest
->OutputHandle
,
154 &Buffer
, GENERIC_WRITE
, TRUE
);
155 if (!NT_SUCCESS(Status
)) return Status
;
157 Status
= ConDrvSetConsoleCursorInfo(Buffer
->Header
.Console
,
159 &CursorInfoRequest
->Info
);
161 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
166 ConDrvSetConsoleCursorPosition(IN PCONSOLE Console
,
167 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
169 CSR_API(SrvSetConsoleCursorPosition
)
172 PCONSOLE_SETCURSORPOSITION SetCursorPositionRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetCursorPositionRequest
;
173 PTEXTMODE_SCREEN_BUFFER Buffer
;
175 DPRINT("SrvSetConsoleCursorPosition\n");
177 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
178 SetCursorPositionRequest
->OutputHandle
,
179 &Buffer
, GENERIC_WRITE
, TRUE
);
180 if (!NT_SUCCESS(Status
)) return Status
;
182 Status
= ConDrvSetConsoleCursorPosition(Buffer
->Header
.Console
,
184 &SetCursorPositionRequest
->Position
);
186 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
190 CSR_API(SrvCreateConsoleScreenBuffer
)
192 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
193 PCONSOLE_CREATESCREENBUFFER CreateScreenBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CreateScreenBufferRequest
;
194 PCSR_PROCESS Process
= CsrGetClientThread()->Process
;
195 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(Process
);
196 PCONSRV_CONSOLE Console
;
197 PCONSOLE_SCREEN_BUFFER Buff
;
199 PVOID ScreenBufferInfo
= NULL
;
200 TEXTMODE_BUFFER_INFO TextModeInfo
= {{80, 25},
201 DEFAULT_SCREEN_ATTRIB
,
202 DEFAULT_POPUP_ATTRIB
,
204 CSR_DEFAULT_CURSOR_SIZE
};
205 GRAPHICS_BUFFER_INFO GraphicsInfo
;
206 GraphicsInfo
.Info
= CreateScreenBufferRequest
->GraphicsBufferInfo
; // HACK for MSVC
208 DPRINT("SrvCreateConsoleScreenBuffer\n");
210 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
211 if (!NT_SUCCESS(Status
)) return Status
;
213 if (CreateScreenBufferRequest
->ScreenBufferType
== CONSOLE_TEXTMODE_BUFFER
)
215 ScreenBufferInfo
= &TextModeInfo
;
218 if (Console->ActiveBuffer)
220 TextModeInfo.ScreenBufferSize = Console->ActiveBuffer->ScreenBufferSize;
221 if (TextModeInfo.ScreenBufferSize.X == 0) TextModeInfo.ScreenBufferSize.X = 80;
222 if (TextModeInfo.ScreenBufferSize.Y == 0) TextModeInfo.ScreenBufferSize.Y = 25;
224 TextModeInfo.ScreenAttrib = Console->ActiveBuffer->ScreenBuffer.TextBuffer.ScreenDefaultAttrib;
225 TextModeInfo.PopupAttrib = Console->ActiveBuffer->ScreenBuffer.TextBuffer.PopupDefaultAttrib;
227 TextModeInfo.IsCursorVisible = Console->ActiveBuffer->CursorInfo.bVisible;
228 TextModeInfo.CursorSize = Console->ActiveBuffer->CursorInfo.dwSize;
233 * This is Windows' behaviour
236 /* Use the current console size. Regularize it if needed. */
237 TextModeInfo
.ScreenBufferSize
= Console
->ConsoleSize
;
238 if (TextModeInfo
.ScreenBufferSize
.X
== 0) TextModeInfo
.ScreenBufferSize
.X
= 1;
239 if (TextModeInfo
.ScreenBufferSize
.Y
== 0) TextModeInfo
.ScreenBufferSize
.Y
= 1;
241 /* If we have an active screen buffer, use its attributes as the new ones */
242 if (Console
->ActiveBuffer
&& GetType(Console
->ActiveBuffer
) == TEXTMODE_BUFFER
)
244 PTEXTMODE_SCREEN_BUFFER Buffer
= (PTEXTMODE_SCREEN_BUFFER
)Console
->ActiveBuffer
;
246 TextModeInfo
.ScreenAttrib
= Buffer
->ScreenDefaultAttrib
;
247 TextModeInfo
.PopupAttrib
= Buffer
->PopupDefaultAttrib
;
249 TextModeInfo
.IsCursorVisible
= Buffer
->CursorInfo
.bVisible
;
250 TextModeInfo
.CursorSize
= Buffer
->CursorInfo
.dwSize
;
253 else if (CreateScreenBufferRequest
->ScreenBufferType
== CONSOLE_GRAPHICS_BUFFER
)
255 /* Get infos from the graphics buffer information structure */
256 if (!CsrValidateMessageBuffer(ApiMessage
,
257 (PVOID
*)&CreateScreenBufferRequest
->GraphicsBufferInfo
.lpBitMapInfo
,
258 CreateScreenBufferRequest
->GraphicsBufferInfo
.dwBitMapInfoLength
,
261 Status
= STATUS_INVALID_PARAMETER
;
265 ScreenBufferInfo
= &GraphicsInfo
;
267 /* Initialize shared variables */
268 // CreateScreenBufferRequest->GraphicsBufferInfo.hMutex
269 CreateScreenBufferRequest
->hMutex
= GraphicsInfo
.Info
.hMutex
= INVALID_HANDLE_VALUE
;
270 // CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap
271 CreateScreenBufferRequest
->lpBitMap
= GraphicsInfo
.Info
.lpBitMap
= NULL
;
273 /* A graphics screen buffer is never inheritable */
274 CreateScreenBufferRequest
->InheritHandle
= FALSE
;
277 Status
= ConDrvCreateScreenBuffer(&Buff
,
279 Process
->ProcessHandle
,
280 CreateScreenBufferRequest
->ScreenBufferType
,
282 if (!NT_SUCCESS(Status
)) goto Quit
;
284 /* Insert the new handle inside the process handles table */
285 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
287 Status
= ConSrvInsertObject(ProcessData
,
288 &CreateScreenBufferRequest
->OutputHandle
,
290 CreateScreenBufferRequest
->DesiredAccess
,
291 CreateScreenBufferRequest
->InheritHandle
,
292 CreateScreenBufferRequest
->ShareMode
);
294 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
296 if (!NT_SUCCESS(Status
)) goto Quit
;
298 if (CreateScreenBufferRequest
->ScreenBufferType
== CONSOLE_GRAPHICS_BUFFER
)
300 PGRAPHICS_SCREEN_BUFFER Buffer
= (PGRAPHICS_SCREEN_BUFFER
)Buff
;
302 * Initialize the graphics buffer information structure
303 * and give it back to the client.
305 // CreateScreenBufferRequest->GraphicsBufferInfo.hMutex
306 CreateScreenBufferRequest
->hMutex
= Buffer
->ClientMutex
;
307 // CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap
308 CreateScreenBufferRequest
->lpBitMap
= Buffer
->ClientBitMap
;
312 ConSrvReleaseConsole(Console
, TRUE
);
317 ConDrvSetConsoleActiveScreenBuffer(IN PCONSOLE Console
,
318 IN PCONSOLE_SCREEN_BUFFER Buffer
);
319 CSR_API(SrvSetConsoleActiveScreenBuffer
)
322 PCONSOLE_SETACTIVESCREENBUFFER SetScreenBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetScreenBufferRequest
;
323 PCONSOLE_SCREEN_BUFFER Buffer
;
325 DPRINT("SrvSetConsoleActiveScreenBuffer\n");
327 Status
= ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
328 SetScreenBufferRequest
->OutputHandle
,
329 &Buffer
, GENERIC_WRITE
, TRUE
);
330 if (!NT_SUCCESS(Status
)) return Status
;
332 Status
= ConDrvSetConsoleActiveScreenBuffer(Buffer
->Header
.Console
,
335 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
340 /* CSR THREADS FOR WriteConsole ***********************************************/
343 DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage
,
344 IN PCSR_THREAD ClientThread
,
345 IN BOOLEAN CreateWaitBlock OPTIONAL
);
347 // Wait function CSR_WAIT_FUNCTION
350 WriteConsoleThread(IN PLIST_ENTRY WaitList
,
351 IN PCSR_THREAD WaitThread
,
352 IN PCSR_API_MESSAGE WaitApiMessage
,
353 IN PVOID WaitContext
,
354 IN PVOID WaitArgument1
,
355 IN PVOID WaitArgument2
,
360 DPRINT("WriteConsoleThread - WaitContext = 0x%p, WaitArgument1 = 0x%p, WaitArgument2 = 0x%p, WaitFlags = %lu\n", WaitContext
, WaitArgument1
, WaitArgument2
, WaitFlags
);
363 * If we are notified of the process termination via a call
364 * to CsrNotifyWaitBlock triggered by CsrDestroyProcess or
365 * CsrDestroyThread, just return.
367 if (WaitFlags
& CsrProcessTerminating
)
369 Status
= STATUS_THREAD_IS_TERMINATING
;
373 Status
= DoWriteConsole(WaitApiMessage
, WaitThread
, FALSE
);
376 if (Status
!= STATUS_PENDING
)
378 WaitApiMessage
->Status
= Status
;
381 return (Status
== STATUS_PENDING
? FALSE
: TRUE
);
385 ConDrvWriteConsole(IN PCONSOLE Console
,
386 IN PTEXTMODE_SCREEN_BUFFER ScreenBuffer
,
388 IN PVOID StringBuffer
,
389 IN ULONG NumCharsToWrite
,
390 OUT PULONG NumCharsWritten OPTIONAL
);
392 DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage
,
393 IN PCSR_THREAD ClientThread
,
394 IN BOOLEAN CreateWaitBlock OPTIONAL
)
397 PCONSOLE_WRITECONSOLE WriteConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteConsoleRequest
;
398 PTEXTMODE_SCREEN_BUFFER ScreenBuffer
;
401 ULONG NrCharactersWritten
= 0;
402 ULONG CharSize
= (WriteConsoleRequest
->Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
404 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(ClientThread
->Process
),
405 WriteConsoleRequest
->OutputHandle
,
406 &ScreenBuffer
, GENERIC_WRITE
, FALSE
);
407 if (!NT_SUCCESS(Status
)) return Status
;
410 * For optimization purposes, Windows (and hence ReactOS, too, for
411 * compatibility reasons) uses a static buffer if no more than eighty
412 * bytes are written. Otherwise a new buffer is used.
413 * The client-side expects that we know this behaviour.
415 if (WriteConsoleRequest
->UsingStaticBuffer
&&
416 WriteConsoleRequest
->NumBytes
<= sizeof(WriteConsoleRequest
->StaticBuffer
))
419 * Adjust the internal pointer, because its old value points to
420 * the static buffer in the original ApiMessage structure.
422 // WriteConsoleRequest->Buffer = WriteConsoleRequest->StaticBuffer;
423 Buffer
= WriteConsoleRequest
->StaticBuffer
;
427 Buffer
= WriteConsoleRequest
->Buffer
;
430 DPRINT("Calling ConDrvWriteConsole\n");
431 Status
= ConDrvWriteConsole(ScreenBuffer
->Header
.Console
,
433 WriteConsoleRequest
->Unicode
,
435 WriteConsoleRequest
->NumBytes
/ CharSize
, // NrCharactersToWrite
436 &NrCharactersWritten
);
437 DPRINT("ConDrvWriteConsole returned (%d ; Status = 0x%08x)\n",
438 NrCharactersWritten
, Status
);
440 if (Status
== STATUS_PENDING
)
444 PCONSRV_CONSOLE Console
= (PCONSRV_CONSOLE
)ScreenBuffer
->Header
.Console
;
446 if (!CsrCreateWait(&Console
->WriteWaitQueue
,
453 Status
= STATUS_NO_MEMORY
;
458 /* Wait until we un-pause the console */
459 // Status = STATUS_PENDING;
463 /* We read all what we wanted. Set the number of bytes written. */
464 WriteConsoleRequest
->NumBytes
= NrCharactersWritten
* CharSize
;
468 ConSrvReleaseScreenBuffer(ScreenBuffer
, FALSE
);
473 /* TEXT OUTPUT APIS ***********************************************************/
476 ConDrvReadConsoleOutput(IN PCONSOLE Console
,
477 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
479 OUT PCHAR_INFO CharInfo
/*Buffer*/,
480 IN OUT PSMALL_RECT ReadRegion
);
481 CSR_API(SrvReadConsoleOutput
)
484 PCONSOLE_READOUTPUT ReadOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ReadOutputRequest
;
485 PTEXTMODE_SCREEN_BUFFER Buffer
;
490 DPRINT("SrvReadConsoleOutput\n");
492 NumCells
= (ReadOutputRequest
->ReadRegion
.Right
- ReadOutputRequest
->ReadRegion
.Left
+ 1) *
493 (ReadOutputRequest
->ReadRegion
.Bottom
- ReadOutputRequest
->ReadRegion
.Top
+ 1);
496 * For optimization purposes, Windows (and hence ReactOS, too, for
497 * compatibility reasons) uses a static buffer if no more than one
498 * cell is read. Otherwise a new buffer is used.
499 * The client-side expects that we know this behaviour.
504 * Adjust the internal pointer, because its old value points to
505 * the static buffer in the original ApiMessage structure.
507 // ReadOutputRequest->CharInfo = &ReadOutputRequest->StaticBuffer;
508 CharInfo
= &ReadOutputRequest
->StaticBuffer
;
512 if (!CsrValidateMessageBuffer(ApiMessage
,
513 (PVOID
*)&ReadOutputRequest
->CharInfo
,
517 return STATUS_INVALID_PARAMETER
;
520 CharInfo
= ReadOutputRequest
->CharInfo
;
523 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
524 ReadOutputRequest
->OutputHandle
,
525 &Buffer
, GENERIC_READ
, TRUE
);
526 if (!NT_SUCCESS(Status
)) return Status
;
528 Status
= ConDrvReadConsoleOutput(Buffer
->Header
.Console
,
530 ReadOutputRequest
->Unicode
,
532 &ReadOutputRequest
->ReadRegion
);
534 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
539 ConDrvWriteConsoleOutput(IN PCONSOLE Console
,
540 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
542 IN PCHAR_INFO CharInfo
/*Buffer*/,
543 IN OUT PSMALL_RECT WriteRegion
);
544 CSR_API(SrvWriteConsoleOutput
)
547 PCONSOLE_WRITEOUTPUT WriteOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteOutputRequest
;
548 PTEXTMODE_SCREEN_BUFFER Buffer
;
549 PCSR_PROCESS Process
= CsrGetClientThread()->Process
;
554 DPRINT("SrvWriteConsoleOutput\n");
556 NumCells
= (WriteOutputRequest
->WriteRegion
.Right
- WriteOutputRequest
->WriteRegion
.Left
+ 1) *
557 (WriteOutputRequest
->WriteRegion
.Bottom
- WriteOutputRequest
->WriteRegion
.Top
+ 1);
559 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(Process
),
560 WriteOutputRequest
->OutputHandle
,
561 &Buffer
, GENERIC_WRITE
, TRUE
);
562 if (!NT_SUCCESS(Status
)) return Status
;
565 * Validate the message buffer if we do not use a process' heap buffer
566 * (CsrAllocateCaptureBuffer succeeded because we haven't allocated
567 * a too large (>= 64 kB, size of the CSR heap) data buffer).
569 if (!WriteOutputRequest
->UseVirtualMemory
)
572 * For optimization purposes, Windows (and hence ReactOS, too, for
573 * compatibility reasons) uses a static buffer if no more than one
574 * cell is written. Otherwise a new buffer is used.
575 * The client-side expects that we know this behaviour.
580 * Adjust the internal pointer, because its old value points to
581 * the static buffer in the original ApiMessage structure.
583 // WriteOutputRequest->CharInfo = &WriteOutputRequest->StaticBuffer;
584 CharInfo
= &WriteOutputRequest
->StaticBuffer
;
588 if (!CsrValidateMessageBuffer(ApiMessage
,
589 (PVOID
*)&WriteOutputRequest
->CharInfo
,
593 Status
= STATUS_INVALID_PARAMETER
;
597 CharInfo
= WriteOutputRequest
->CharInfo
;
603 * This was not the case: we use a heap buffer. Retrieve its contents.
605 ULONG Size
= NumCells
* sizeof(CHAR_INFO
);
607 CharInfo
= ConsoleAllocHeap(HEAP_ZERO_MEMORY
, Size
);
608 if (CharInfo
== NULL
)
610 Status
= STATUS_NO_MEMORY
;
614 Status
= NtReadVirtualMemory(Process
->ProcessHandle
,
615 WriteOutputRequest
->CharInfo
,
619 if (!NT_SUCCESS(Status
))
621 ConsoleFreeHeap(CharInfo
);
622 // Status = STATUS_NO_MEMORY;
627 Status
= ConDrvWriteConsoleOutput(Buffer
->Header
.Console
,
629 WriteOutputRequest
->Unicode
,
631 &WriteOutputRequest
->WriteRegion
);
633 /* Free the temporary buffer if we used the process' heap buffer */
634 if (WriteOutputRequest
->UseVirtualMemory
&& CharInfo
)
635 ConsoleFreeHeap(CharInfo
);
638 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
642 CSR_API(SrvWriteConsole
)
645 PCONSOLE_WRITECONSOLE WriteConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteConsoleRequest
;
647 DPRINT("SrvWriteConsole\n");
650 * For optimization purposes, Windows (and hence ReactOS, too, for
651 * compatibility reasons) uses a static buffer if no more than eighty
652 * bytes are written. Otherwise a new buffer is used.
653 * The client-side expects that we know this behaviour.
655 if (WriteConsoleRequest
->UsingStaticBuffer
&&
656 WriteConsoleRequest
->NumBytes
<= sizeof(WriteConsoleRequest
->StaticBuffer
))
659 * Adjust the internal pointer, because its old value points to
660 * the static buffer in the original ApiMessage structure.
662 // WriteConsoleRequest->Buffer = WriteConsoleRequest->StaticBuffer;
666 if (!CsrValidateMessageBuffer(ApiMessage
,
667 (PVOID
)&WriteConsoleRequest
->Buffer
,
668 WriteConsoleRequest
->NumBytes
,
671 return STATUS_INVALID_PARAMETER
;
675 Status
= DoWriteConsole(ApiMessage
, CsrGetClientThread(), TRUE
);
677 if (Status
== STATUS_PENDING
) *ReplyCode
= CsrReplyPending
;
683 ConDrvReadConsoleOutputString(IN PCONSOLE Console
,
684 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
685 IN CODE_TYPE CodeType
,
686 OUT PVOID StringBuffer
,
687 IN ULONG NumCodesToRead
,
689 // OUT PCOORD EndCoord,
690 OUT PULONG NumCodesRead OPTIONAL
);
691 CSR_API(SrvReadConsoleOutputString
)
694 PCONSOLE_READOUTPUTCODE ReadOutputCodeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ReadOutputCodeRequest
;
695 PTEXTMODE_SCREEN_BUFFER Buffer
;
700 DPRINT("SrvReadConsoleOutputString\n");
702 switch (ReadOutputCodeRequest
->CodeType
)
705 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, AsciiChar
);
709 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, UnicodeChar
);
713 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, Attribute
);
717 return STATUS_INVALID_PARAMETER
;
721 * For optimization purposes, Windows (and hence ReactOS, too, for
722 * compatibility reasons) uses a static buffer if no more than eighty
723 * bytes are read. Otherwise a new buffer is used.
724 * The client-side expects that we know this behaviour.
726 if (ReadOutputCodeRequest
->NumCodes
* CodeSize
<= sizeof(ReadOutputCodeRequest
->CodeStaticBuffer
))
729 * Adjust the internal pointer, because its old value points to
730 * the static buffer in the original ApiMessage structure.
732 // ReadOutputCodeRequest->pCode = ReadOutputCodeRequest->CodeStaticBuffer;
733 pCode
= ReadOutputCodeRequest
->CodeStaticBuffer
;
737 if (!CsrValidateMessageBuffer(ApiMessage
,
738 (PVOID
*)&ReadOutputCodeRequest
->pCode
,
739 ReadOutputCodeRequest
->NumCodes
,
742 return STATUS_INVALID_PARAMETER
;
745 pCode
= ReadOutputCodeRequest
->pCode
;
748 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
749 ReadOutputCodeRequest
->OutputHandle
,
750 &Buffer
, GENERIC_READ
, TRUE
);
751 if (!NT_SUCCESS(Status
))
753 ReadOutputCodeRequest
->NumCodes
= 0;
757 Status
= ConDrvReadConsoleOutputString(Buffer
->Header
.Console
,
759 ReadOutputCodeRequest
->CodeType
,
761 ReadOutputCodeRequest
->NumCodes
,
762 &ReadOutputCodeRequest
->Coord
,
763 // &ReadOutputCodeRequest->EndCoord,
764 &ReadOutputCodeRequest
->NumCodes
);
766 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
771 ConDrvWriteConsoleOutputString(IN PCONSOLE Console
,
772 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
773 IN CODE_TYPE CodeType
,
774 IN PVOID StringBuffer
,
775 IN ULONG NumCodesToWrite
,
776 IN PCOORD WriteCoord
,
777 // OUT PCOORD EndCoord,
778 OUT PULONG NumCodesWritten OPTIONAL
);
779 CSR_API(SrvWriteConsoleOutputString
)
782 PCONSOLE_WRITEOUTPUTCODE WriteOutputCodeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteOutputCodeRequest
;
783 PTEXTMODE_SCREEN_BUFFER Buffer
;
788 DPRINT("SrvWriteConsoleOutputString\n");
790 switch (WriteOutputCodeRequest
->CodeType
)
793 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, AsciiChar
);
797 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, UnicodeChar
);
801 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, Attribute
);
805 return STATUS_INVALID_PARAMETER
;
809 * For optimization purposes, Windows (and hence ReactOS, too, for
810 * compatibility reasons) uses a static buffer if no more than eighty
811 * bytes are written. Otherwise a new buffer is used.
812 * The client-side expects that we know this behaviour.
814 if (WriteOutputCodeRequest
->NumCodes
* CodeSize
<= sizeof(WriteOutputCodeRequest
->CodeStaticBuffer
))
817 * Adjust the internal pointer, because its old value points to
818 * the static buffer in the original ApiMessage structure.
820 // WriteOutputCodeRequest->pCode = WriteOutputCodeRequest->CodeStaticBuffer;
821 pCode
= WriteOutputCodeRequest
->CodeStaticBuffer
;
825 if (!CsrValidateMessageBuffer(ApiMessage
,
826 (PVOID
*)&WriteOutputCodeRequest
->pCode
,
827 WriteOutputCodeRequest
->NumCodes
,
830 return STATUS_INVALID_PARAMETER
;
833 pCode
= WriteOutputCodeRequest
->pCode
;
836 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
837 WriteOutputCodeRequest
->OutputHandle
,
838 &Buffer
, GENERIC_WRITE
, TRUE
);
839 if (!NT_SUCCESS(Status
))
841 WriteOutputCodeRequest
->NumCodes
= 0;
845 Status
= ConDrvWriteConsoleOutputString(Buffer
->Header
.Console
,
847 WriteOutputCodeRequest
->CodeType
,
849 WriteOutputCodeRequest
->NumCodes
,
850 &WriteOutputCodeRequest
->Coord
,
851 // &WriteOutputCodeRequest->EndCoord,
852 &WriteOutputCodeRequest
->NumCodes
);
854 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
859 ConDrvFillConsoleOutput(IN PCONSOLE Console
,
860 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
861 IN CODE_TYPE CodeType
,
862 IN CODE_ELEMENT Code
,
863 IN ULONG NumCodesToWrite
,
864 IN PCOORD WriteCoord
,
865 OUT PULONG NumCodesWritten OPTIONAL
);
866 CSR_API(SrvFillConsoleOutput
)
869 PCONSOLE_FILLOUTPUTCODE FillOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.FillOutputRequest
;
870 PTEXTMODE_SCREEN_BUFFER Buffer
;
871 CODE_TYPE CodeType
= FillOutputRequest
->CodeType
;
873 DPRINT("SrvFillConsoleOutput\n");
875 if ( (CodeType
!= CODE_ASCII
) &&
876 (CodeType
!= CODE_UNICODE
) &&
877 (CodeType
!= CODE_ATTRIBUTE
) )
879 return STATUS_INVALID_PARAMETER
;
882 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
883 FillOutputRequest
->OutputHandle
,
884 &Buffer
, GENERIC_WRITE
, TRUE
);
885 if (!NT_SUCCESS(Status
))
887 FillOutputRequest
->NumCodes
= 0;
891 Status
= ConDrvFillConsoleOutput(Buffer
->Header
.Console
,
894 FillOutputRequest
->Code
,
895 FillOutputRequest
->NumCodes
,
896 &FillOutputRequest
->WriteCoord
,
897 &FillOutputRequest
->NumCodes
);
899 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
904 ConDrvGetConsoleScreenBufferInfo(IN PCONSOLE Console
,
905 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
906 OUT PCOORD ScreenBufferSize
,
907 OUT PCOORD CursorPosition
,
908 OUT PCOORD ViewOrigin
,
910 OUT PCOORD MaximumViewSize
,
911 OUT PWORD Attributes
);
912 CSR_API(SrvGetConsoleScreenBufferInfo
)
915 PCONSOLE_GETSCREENBUFFERINFO ScreenBufferInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ScreenBufferInfoRequest
;
916 PTEXTMODE_SCREEN_BUFFER Buffer
;
918 DPRINT("SrvGetConsoleScreenBufferInfo\n");
920 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
921 ScreenBufferInfoRequest
->OutputHandle
,
922 &Buffer
, GENERIC_READ
, TRUE
);
923 if (!NT_SUCCESS(Status
)) return Status
;
925 Status
= ConDrvGetConsoleScreenBufferInfo(Buffer
->Header
.Console
,
927 &ScreenBufferInfoRequest
->ScreenBufferSize
,
928 &ScreenBufferInfoRequest
->CursorPosition
,
929 &ScreenBufferInfoRequest
->ViewOrigin
,
930 &ScreenBufferInfoRequest
->ViewSize
,
931 &ScreenBufferInfoRequest
->MaximumViewSize
,
932 &ScreenBufferInfoRequest
->Attributes
);
934 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
939 ConDrvSetConsoleTextAttribute(IN PCONSOLE Console
,
940 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
942 CSR_API(SrvSetConsoleTextAttribute
)
945 PCONSOLE_SETTEXTATTRIB SetTextAttribRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetTextAttribRequest
;
946 PTEXTMODE_SCREEN_BUFFER Buffer
;
948 DPRINT("SrvSetConsoleTextAttribute\n");
950 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
951 SetTextAttribRequest
->OutputHandle
,
952 &Buffer
, GENERIC_WRITE
, TRUE
);
953 if (!NT_SUCCESS(Status
)) return Status
;
955 Status
= ConDrvSetConsoleTextAttribute(Buffer
->Header
.Console
,
957 SetTextAttribRequest
->Attributes
);
959 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
964 ConDrvSetConsoleScreenBufferSize(IN PCONSOLE Console
,
965 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
967 CSR_API(SrvSetConsoleScreenBufferSize
)
970 PCONSOLE_SETSCREENBUFFERSIZE SetScreenBufferSizeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetScreenBufferSizeRequest
;
971 PTEXTMODE_SCREEN_BUFFER Buffer
;
973 DPRINT("SrvSetConsoleScreenBufferSize\n");
975 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
976 SetScreenBufferSizeRequest
->OutputHandle
,
977 &Buffer
, GENERIC_WRITE
, TRUE
);
978 if (!NT_SUCCESS(Status
)) return Status
;
980 Status
= ConDrvSetConsoleScreenBufferSize(Buffer
->Header
.Console
,
982 &SetScreenBufferSizeRequest
->Size
);
984 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
989 ConDrvScrollConsoleScreenBuffer(IN PCONSOLE Console
,
990 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
992 IN PSMALL_RECT ScrollRectangle
,
993 IN BOOLEAN UseClipRectangle
,
994 IN PSMALL_RECT ClipRectangle OPTIONAL
,
995 IN PCOORD DestinationOrigin
,
996 IN CHAR_INFO FillChar
);
997 CSR_API(SrvScrollConsoleScreenBuffer
)
1000 PCONSOLE_SCROLLSCREENBUFFER ScrollScreenBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ScrollScreenBufferRequest
;
1001 PTEXTMODE_SCREEN_BUFFER Buffer
;
1003 DPRINT("SrvScrollConsoleScreenBuffer\n");
1005 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
1006 ScrollScreenBufferRequest
->OutputHandle
,
1007 &Buffer
, GENERIC_WRITE
, TRUE
);
1008 if (!NT_SUCCESS(Status
)) return Status
;
1010 Status
= ConDrvScrollConsoleScreenBuffer(Buffer
->Header
.Console
,
1012 ScrollScreenBufferRequest
->Unicode
,
1013 &ScrollScreenBufferRequest
->ScrollRectangle
,
1014 ScrollScreenBufferRequest
->UseClipRectangle
,
1015 &ScrollScreenBufferRequest
->ClipRectangle
,
1016 &ScrollScreenBufferRequest
->DestinationOrigin
,
1017 ScrollScreenBufferRequest
->Fill
);
1019 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
1024 ConDrvSetConsoleWindowInfo(IN PCONSOLE Console
,
1025 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
1026 IN BOOLEAN Absolute
,
1027 IN PSMALL_RECT WindowRect
);
1028 CSR_API(SrvSetConsoleWindowInfo
)
1031 PCONSOLE_SETWINDOWINFO SetWindowInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetWindowInfoRequest
;
1032 // PCONSOLE_SCREEN_BUFFER Buffer;
1033 PTEXTMODE_SCREEN_BUFFER Buffer
;
1035 DPRINT1("SrvSetConsoleWindowInfo(0x%08x, %d, {L%d, T%d, R%d, B%d}) called\n",
1036 SetWindowInfoRequest
->OutputHandle
, SetWindowInfoRequest
->Absolute
,
1037 SetWindowInfoRequest
->WindowRect
.Left
,
1038 SetWindowInfoRequest
->WindowRect
.Top
,
1039 SetWindowInfoRequest
->WindowRect
.Right
,
1040 SetWindowInfoRequest
->WindowRect
.Bottom
);
1042 // ConSrvGetScreenBuffer
1043 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
1044 SetWindowInfoRequest
->OutputHandle
,
1045 &Buffer
, GENERIC_READ
, TRUE
);
1046 if (!NT_SUCCESS(Status
)) return Status
;
1048 Status
= ConDrvSetConsoleWindowInfo(Buffer
->Header
.Console
,
1050 SetWindowInfoRequest
->Absolute
,
1051 &SetWindowInfoRequest
->WindowRect
);
1053 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);