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 ConDrvInvalidateBitMapRect(IN PCONSOLE Console
,
21 IN PCONSOLE_SCREEN_BUFFER Buffer
,
22 IN PSMALL_RECT Region
);
23 CSR_API(SrvInvalidateBitMapRect
)
26 PCONSOLE_INVALIDATEDIBITS InvalidateDIBitsRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.InvalidateDIBitsRequest
;
27 PCONSOLE_SCREEN_BUFFER Buffer
;
29 DPRINT("SrvInvalidateBitMapRect\n");
31 Status
= ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
32 InvalidateDIBitsRequest
->OutputHandle
,
33 &Buffer
, GENERIC_READ
, TRUE
);
34 if (!NT_SUCCESS(Status
)) return Status
;
36 Status
= ConDrvInvalidateBitMapRect(Buffer
->Header
.Console
,
38 &InvalidateDIBitsRequest
->Region
);
40 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
45 ConDrvSetConsolePalette(IN PCONSOLE Console
,
46 // IN PGRAPHICS_SCREEN_BUFFER Buffer,
47 IN PCONSOLE_SCREEN_BUFFER Buffer
,
48 IN HPALETTE PaletteHandle
,
49 IN UINT PaletteUsage
);
50 CSR_API(SrvSetConsolePalette
)
53 PCONSOLE_SETPALETTE SetPaletteRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetPaletteRequest
;
54 // PGRAPHICS_SCREEN_BUFFER Buffer;
55 PCONSOLE_SCREEN_BUFFER Buffer
;
57 DPRINT("SrvSetConsolePalette\n");
59 // NOTE: Tests show that this function is used only for graphics screen buffers
60 // and otherwise it returns FALSE + sets last error to invalid handle.
61 // I think it's ridiculous, because if you are in text mode, simulating
62 // a change of VGA palette via DAC registers (done by a call to SetConsolePalette)
63 // cannot be done... So I allow it in ReactOS !
65 Status = ConSrvGetGraphicsBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
66 SetPaletteRequest->OutputHandle,
67 &Buffer, GENERIC_WRITE, TRUE);
69 Status
= ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
70 SetPaletteRequest
->OutputHandle
,
71 &Buffer
, GENERIC_WRITE
, TRUE
);
72 if (!NT_SUCCESS(Status
)) return Status
;
75 * Make the palette handle public, so that it can be
76 * used by other threads calling GDI functions on it.
77 * Indeed, the palette handle comes from a console app
78 * calling ourselves, running in CSRSS.
80 NtUserConsoleControl(ConsoleMakePalettePublic
,
81 &SetPaletteRequest
->PaletteHandle
,
82 sizeof(SetPaletteRequest
->PaletteHandle
));
84 Status
= ConDrvSetConsolePalette(Buffer
->Header
.Console
,
86 SetPaletteRequest
->PaletteHandle
,
87 SetPaletteRequest
->Usage
);
89 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
94 ConDrvGetConsoleCursorInfo(IN PCONSOLE Console
,
95 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
96 OUT PCONSOLE_CURSOR_INFO CursorInfo
);
97 CSR_API(SrvGetConsoleCursorInfo
)
100 PCONSOLE_GETSETCURSORINFO CursorInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CursorInfoRequest
;
101 PTEXTMODE_SCREEN_BUFFER Buffer
;
103 DPRINT("SrvGetConsoleCursorInfo\n");
105 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
106 CursorInfoRequest
->OutputHandle
,
107 &Buffer
, GENERIC_READ
, TRUE
);
108 if (!NT_SUCCESS(Status
)) return Status
;
110 Status
= ConDrvGetConsoleCursorInfo(Buffer
->Header
.Console
,
112 &CursorInfoRequest
->Info
);
114 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
119 ConDrvSetConsoleCursorInfo(IN PCONSOLE Console
,
120 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
121 IN PCONSOLE_CURSOR_INFO CursorInfo
);
122 CSR_API(SrvSetConsoleCursorInfo
)
125 PCONSOLE_GETSETCURSORINFO CursorInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CursorInfoRequest
;
126 PTEXTMODE_SCREEN_BUFFER Buffer
;
128 DPRINT("SrvSetConsoleCursorInfo\n");
130 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
131 CursorInfoRequest
->OutputHandle
,
132 &Buffer
, GENERIC_WRITE
, TRUE
);
133 if (!NT_SUCCESS(Status
)) return Status
;
135 Status
= ConDrvSetConsoleCursorInfo(Buffer
->Header
.Console
,
137 &CursorInfoRequest
->Info
);
139 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
144 ConDrvSetConsoleCursorPosition(IN PCONSOLE Console
,
145 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
147 CSR_API(SrvSetConsoleCursorPosition
)
150 PCONSOLE_SETCURSORPOSITION SetCursorPositionRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetCursorPositionRequest
;
151 PTEXTMODE_SCREEN_BUFFER Buffer
;
153 DPRINT("SrvSetConsoleCursorPosition\n");
155 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
156 SetCursorPositionRequest
->OutputHandle
,
157 &Buffer
, GENERIC_WRITE
, TRUE
);
158 if (!NT_SUCCESS(Status
)) return Status
;
160 Status
= ConDrvSetConsoleCursorPosition(Buffer
->Header
.Console
,
162 &SetCursorPositionRequest
->Position
);
164 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
168 CSR_API(SrvCreateConsoleScreenBuffer
)
170 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
171 PCONSOLE_CREATESCREENBUFFER CreateScreenBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CreateScreenBufferRequest
;
172 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
173 PCONSRV_CONSOLE Console
;
174 PCONSOLE_SCREEN_BUFFER Buff
;
176 PVOID ScreenBufferInfo
= NULL
;
177 TEXTMODE_BUFFER_INFO TextModeInfo
= {{80, 25},
178 DEFAULT_SCREEN_ATTRIB
,
179 DEFAULT_POPUP_ATTRIB
,
181 CSR_DEFAULT_CURSOR_SIZE
};
182 GRAPHICS_BUFFER_INFO GraphicsInfo
;
183 GraphicsInfo
.Info
= CreateScreenBufferRequest
->GraphicsBufferInfo
; // HACK for MSVC
185 DPRINT("SrvCreateConsoleScreenBuffer\n");
187 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
188 if (!NT_SUCCESS(Status
)) return Status
;
190 if (CreateScreenBufferRequest
->ScreenBufferType
== CONSOLE_TEXTMODE_BUFFER
)
192 ScreenBufferInfo
= &TextModeInfo
;
195 if (Console->ActiveBuffer)
197 TextModeInfo.ScreenBufferSize = Console->ActiveBuffer->ScreenBufferSize;
198 if (TextModeInfo.ScreenBufferSize.X == 0) TextModeInfo.ScreenBufferSize.X = 80;
199 if (TextModeInfo.ScreenBufferSize.Y == 0) TextModeInfo.ScreenBufferSize.Y = 25;
201 TextModeInfo.ScreenAttrib = Console->ActiveBuffer->ScreenBuffer.TextBuffer.ScreenDefaultAttrib;
202 TextModeInfo.PopupAttrib = Console->ActiveBuffer->ScreenBuffer.TextBuffer.PopupDefaultAttrib;
204 TextModeInfo.IsCursorVisible = Console->ActiveBuffer->CursorInfo.bVisible;
205 TextModeInfo.CursorSize = Console->ActiveBuffer->CursorInfo.dwSize;
210 * This is Windows' behaviour
213 /* Use the current console size. Regularize it if needed. */
214 TextModeInfo
.ScreenBufferSize
= Console
->ConsoleSize
;
215 if (TextModeInfo
.ScreenBufferSize
.X
== 0) TextModeInfo
.ScreenBufferSize
.X
= 1;
216 if (TextModeInfo
.ScreenBufferSize
.Y
== 0) TextModeInfo
.ScreenBufferSize
.Y
= 1;
218 /* If we have an active screen buffer, use its attributes as the new ones */
219 if (Console
->ActiveBuffer
&& GetType(Console
->ActiveBuffer
) == TEXTMODE_BUFFER
)
221 PTEXTMODE_SCREEN_BUFFER Buffer
= (PTEXTMODE_SCREEN_BUFFER
)Console
->ActiveBuffer
;
223 TextModeInfo
.ScreenAttrib
= Buffer
->ScreenDefaultAttrib
;
224 TextModeInfo
.PopupAttrib
= Buffer
->PopupDefaultAttrib
;
226 TextModeInfo
.IsCursorVisible
= Buffer
->CursorInfo
.bVisible
;
227 TextModeInfo
.CursorSize
= Buffer
->CursorInfo
.dwSize
;
230 else if (CreateScreenBufferRequest
->ScreenBufferType
== CONSOLE_GRAPHICS_BUFFER
)
232 /* Get infos from the graphics buffer information structure */
233 if (!CsrValidateMessageBuffer(ApiMessage
,
234 (PVOID
*)&CreateScreenBufferRequest
->GraphicsBufferInfo
.lpBitMapInfo
,
235 CreateScreenBufferRequest
->GraphicsBufferInfo
.dwBitMapInfoLength
,
238 Status
= STATUS_INVALID_PARAMETER
;
242 ScreenBufferInfo
= &GraphicsInfo
;
244 /* Initialize shared variables */
245 // CreateScreenBufferRequest->GraphicsBufferInfo.hMutex
246 CreateScreenBufferRequest
->hMutex
= GraphicsInfo
.Info
.hMutex
= INVALID_HANDLE_VALUE
;
247 // CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap
248 CreateScreenBufferRequest
->lpBitMap
= GraphicsInfo
.Info
.lpBitMap
= NULL
;
250 /* A graphics screen buffer is never inheritable */
251 CreateScreenBufferRequest
->InheritHandle
= FALSE
;
254 Status
= ConDrvCreateScreenBuffer(&Buff
,
256 CreateScreenBufferRequest
->ScreenBufferType
,
258 if (!NT_SUCCESS(Status
)) goto Quit
;
260 /* Insert the new handle inside the process handles table */
261 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
263 Status
= ConSrvInsertObject(ProcessData
,
264 &CreateScreenBufferRequest
->OutputHandle
,
266 CreateScreenBufferRequest
->DesiredAccess
,
267 CreateScreenBufferRequest
->InheritHandle
,
268 CreateScreenBufferRequest
->ShareMode
);
270 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
272 if (!NT_SUCCESS(Status
)) goto Quit
;
274 if (CreateScreenBufferRequest
->ScreenBufferType
== CONSOLE_GRAPHICS_BUFFER
)
276 PGRAPHICS_SCREEN_BUFFER Buffer
= (PGRAPHICS_SCREEN_BUFFER
)Buff
;
278 * Initialize the graphics buffer information structure
279 * and give it back to the client.
281 // CreateScreenBufferRequest->GraphicsBufferInfo.hMutex
282 CreateScreenBufferRequest
->hMutex
= Buffer
->ClientMutex
;
283 // CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap
284 CreateScreenBufferRequest
->lpBitMap
= Buffer
->ClientBitMap
;
288 ConSrvReleaseConsole(Console
, TRUE
);
293 ConDrvSetConsoleActiveScreenBuffer(IN PCONSOLE Console
,
294 IN PCONSOLE_SCREEN_BUFFER Buffer
);
295 CSR_API(SrvSetConsoleActiveScreenBuffer
)
298 PCONSOLE_SETACTIVESCREENBUFFER SetScreenBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetScreenBufferRequest
;
299 PCONSOLE_SCREEN_BUFFER Buffer
;
301 DPRINT("SrvSetConsoleActiveScreenBuffer\n");
303 Status
= ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
304 SetScreenBufferRequest
->OutputHandle
,
305 &Buffer
, GENERIC_WRITE
, TRUE
);
306 if (!NT_SUCCESS(Status
)) return Status
;
308 Status
= ConDrvSetConsoleActiveScreenBuffer(Buffer
->Header
.Console
,
311 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
316 /* CSR THREADS FOR WriteConsole ***********************************************/
319 DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage
,
320 IN PCSR_THREAD ClientThread
,
321 IN BOOLEAN CreateWaitBlock OPTIONAL
);
323 // Wait function CSR_WAIT_FUNCTION
326 WriteConsoleThread(IN PLIST_ENTRY WaitList
,
327 IN PCSR_THREAD WaitThread
,
328 IN PCSR_API_MESSAGE WaitApiMessage
,
329 IN PVOID WaitContext
,
330 IN PVOID WaitArgument1
,
331 IN PVOID WaitArgument2
,
336 DPRINT("WriteConsoleThread - WaitContext = 0x%p, WaitArgument1 = 0x%p, WaitArgument2 = 0x%p, WaitFlags = %lu\n", WaitContext
, WaitArgument1
, WaitArgument2
, WaitFlags
);
339 * If we are notified of the process termination via a call
340 * to CsrNotifyWaitBlock triggered by CsrDestroyProcess or
341 * CsrDestroyThread, just return.
343 if (WaitFlags
& CsrProcessTerminating
)
345 Status
= STATUS_THREAD_IS_TERMINATING
;
349 Status
= DoWriteConsole(WaitApiMessage
, WaitThread
, FALSE
);
352 if (Status
!= STATUS_PENDING
)
354 WaitApiMessage
->Status
= Status
;
357 return (Status
== STATUS_PENDING
? FALSE
: TRUE
);
361 ConDrvWriteConsole(IN PCONSOLE Console
,
362 IN PTEXTMODE_SCREEN_BUFFER ScreenBuffer
,
364 IN PVOID StringBuffer
,
365 IN ULONG NumCharsToWrite
,
366 OUT PULONG NumCharsWritten OPTIONAL
);
368 DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage
,
369 IN PCSR_THREAD ClientThread
,
370 IN BOOLEAN CreateWaitBlock OPTIONAL
)
373 PCONSOLE_WRITECONSOLE WriteConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteConsoleRequest
;
374 PTEXTMODE_SCREEN_BUFFER ScreenBuffer
;
377 ULONG NrCharactersWritten
= 0;
378 ULONG CharSize
= (WriteConsoleRequest
->Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
380 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(ClientThread
->Process
),
381 WriteConsoleRequest
->OutputHandle
,
382 &ScreenBuffer
, GENERIC_WRITE
, FALSE
);
383 if (!NT_SUCCESS(Status
)) return Status
;
386 * For optimization purposes, Windows (and hence ReactOS, too, for
387 * compatibility reasons) uses a static buffer if no more than eighty
388 * bytes are written. Otherwise a new buffer is used.
389 * The client-side expects that we know this behaviour.
391 if (WriteConsoleRequest
->UsingStaticBuffer
&&
392 WriteConsoleRequest
->NumBytes
<= sizeof(WriteConsoleRequest
->StaticBuffer
))
395 * Adjust the internal pointer, because its old value points to
396 * the static buffer in the original ApiMessage structure.
398 // WriteConsoleRequest->Buffer = WriteConsoleRequest->StaticBuffer;
399 Buffer
= WriteConsoleRequest
->StaticBuffer
;
403 Buffer
= WriteConsoleRequest
->Buffer
;
406 DPRINT("Calling ConDrvWriteConsole\n");
407 Status
= ConDrvWriteConsole(ScreenBuffer
->Header
.Console
,
409 WriteConsoleRequest
->Unicode
,
411 WriteConsoleRequest
->NumBytes
/ CharSize
, // NrCharactersToWrite
412 &NrCharactersWritten
);
413 DPRINT("ConDrvWriteConsole returned (%d ; Status = 0x%08x)\n",
414 NrCharactersWritten
, Status
);
416 if (Status
== STATUS_PENDING
)
420 PCONSRV_CONSOLE Console
= (PCONSRV_CONSOLE
)ScreenBuffer
->Header
.Console
;
422 if (!CsrCreateWait(&Console
->WriteWaitQueue
,
429 Status
= STATUS_NO_MEMORY
;
434 /* Wait until we un-pause the console */
435 // Status = STATUS_PENDING;
439 /* We read all what we wanted. Set the number of bytes written. */
440 WriteConsoleRequest
->NumBytes
= NrCharactersWritten
* CharSize
;
444 ConSrvReleaseScreenBuffer(ScreenBuffer
, FALSE
);
449 /* TEXT OUTPUT APIS ***********************************************************/
452 ConDrvReadConsoleOutput(IN PCONSOLE Console
,
453 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
455 OUT PCHAR_INFO CharInfo
/*Buffer*/,
456 IN OUT PSMALL_RECT ReadRegion
);
457 CSR_API(SrvReadConsoleOutput
)
460 PCONSOLE_READOUTPUT ReadOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ReadOutputRequest
;
461 PTEXTMODE_SCREEN_BUFFER Buffer
;
466 DPRINT("SrvReadConsoleOutput\n");
468 NumCells
= (ReadOutputRequest
->ReadRegion
.Right
- ReadOutputRequest
->ReadRegion
.Left
+ 1) *
469 (ReadOutputRequest
->ReadRegion
.Bottom
- ReadOutputRequest
->ReadRegion
.Top
+ 1);
472 * For optimization purposes, Windows (and hence ReactOS, too, for
473 * compatibility reasons) uses a static buffer if no more than one
474 * cell is read. Otherwise a new buffer is used.
475 * The client-side expects that we know this behaviour.
480 * Adjust the internal pointer, because its old value points to
481 * the static buffer in the original ApiMessage structure.
483 // ReadOutputRequest->CharInfo = &ReadOutputRequest->StaticBuffer;
484 CharInfo
= &ReadOutputRequest
->StaticBuffer
;
488 if (!CsrValidateMessageBuffer(ApiMessage
,
489 (PVOID
*)&ReadOutputRequest
->CharInfo
,
493 return STATUS_INVALID_PARAMETER
;
496 CharInfo
= ReadOutputRequest
->CharInfo
;
499 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
500 ReadOutputRequest
->OutputHandle
,
501 &Buffer
, GENERIC_READ
, TRUE
);
502 if (!NT_SUCCESS(Status
)) return Status
;
504 Status
= ConDrvReadConsoleOutput(Buffer
->Header
.Console
,
506 ReadOutputRequest
->Unicode
,
508 &ReadOutputRequest
->ReadRegion
);
510 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
515 ConDrvWriteConsoleOutput(IN PCONSOLE Console
,
516 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
518 IN PCHAR_INFO CharInfo
/*Buffer*/,
519 IN OUT PSMALL_RECT WriteRegion
);
520 CSR_API(SrvWriteConsoleOutput
)
523 PCONSOLE_WRITEOUTPUT WriteOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteOutputRequest
;
524 PTEXTMODE_SCREEN_BUFFER Buffer
;
525 PCSR_PROCESS Process
= CsrGetClientThread()->Process
;
530 DPRINT("SrvWriteConsoleOutput\n");
532 NumCells
= (WriteOutputRequest
->WriteRegion
.Right
- WriteOutputRequest
->WriteRegion
.Left
+ 1) *
533 (WriteOutputRequest
->WriteRegion
.Bottom
- WriteOutputRequest
->WriteRegion
.Top
+ 1);
535 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(Process
),
536 WriteOutputRequest
->OutputHandle
,
537 &Buffer
, GENERIC_WRITE
, TRUE
);
538 if (!NT_SUCCESS(Status
)) return Status
;
541 * Validate the message buffer if we do not use a process' heap buffer
542 * (CsrAllocateCaptureBuffer succeeded because we haven't allocated
543 * a too large (>= 64 kB, size of the CSR heap) data buffer).
545 if (!WriteOutputRequest
->UseVirtualMemory
)
548 * For optimization purposes, Windows (and hence ReactOS, too, for
549 * compatibility reasons) uses a static buffer if no more than one
550 * cell is written. Otherwise a new buffer is used.
551 * The client-side expects that we know this behaviour.
556 * Adjust the internal pointer, because its old value points to
557 * the static buffer in the original ApiMessage structure.
559 // WriteOutputRequest->CharInfo = &WriteOutputRequest->StaticBuffer;
560 CharInfo
= &WriteOutputRequest
->StaticBuffer
;
564 if (!CsrValidateMessageBuffer(ApiMessage
,
565 (PVOID
*)&WriteOutputRequest
->CharInfo
,
569 Status
= STATUS_INVALID_PARAMETER
;
573 CharInfo
= WriteOutputRequest
->CharInfo
;
579 * This was not the case: we use a heap buffer. Retrieve its contents.
581 ULONG Size
= NumCells
* sizeof(CHAR_INFO
);
583 CharInfo
= ConsoleAllocHeap(HEAP_ZERO_MEMORY
, Size
);
584 if (CharInfo
== NULL
)
586 Status
= STATUS_NO_MEMORY
;
590 Status
= NtReadVirtualMemory(Process
->ProcessHandle
,
591 WriteOutputRequest
->CharInfo
,
595 if (!NT_SUCCESS(Status
))
597 ConsoleFreeHeap(CharInfo
);
598 // Status = STATUS_NO_MEMORY;
603 Status
= ConDrvWriteConsoleOutput(Buffer
->Header
.Console
,
605 WriteOutputRequest
->Unicode
,
607 &WriteOutputRequest
->WriteRegion
);
609 /* Free the temporary buffer if we used the process' heap buffer */
610 if (WriteOutputRequest
->UseVirtualMemory
&& CharInfo
)
611 ConsoleFreeHeap(CharInfo
);
614 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
618 CSR_API(SrvWriteConsole
)
621 PCONSOLE_WRITECONSOLE WriteConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteConsoleRequest
;
623 DPRINT("SrvWriteConsole\n");
626 * For optimization purposes, Windows (and hence ReactOS, too, for
627 * compatibility reasons) uses a static buffer if no more than eighty
628 * bytes are written. Otherwise a new buffer is used.
629 * The client-side expects that we know this behaviour.
631 if (WriteConsoleRequest
->UsingStaticBuffer
&&
632 WriteConsoleRequest
->NumBytes
<= sizeof(WriteConsoleRequest
->StaticBuffer
))
635 * Adjust the internal pointer, because its old value points to
636 * the static buffer in the original ApiMessage structure.
638 // WriteConsoleRequest->Buffer = WriteConsoleRequest->StaticBuffer;
642 if (!CsrValidateMessageBuffer(ApiMessage
,
643 (PVOID
)&WriteConsoleRequest
->Buffer
,
644 WriteConsoleRequest
->NumBytes
,
647 return STATUS_INVALID_PARAMETER
;
651 Status
= DoWriteConsole(ApiMessage
, CsrGetClientThread(), TRUE
);
653 if (Status
== STATUS_PENDING
) *ReplyCode
= CsrReplyPending
;
659 ConDrvReadConsoleOutputString(IN PCONSOLE Console
,
660 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
661 IN CODE_TYPE CodeType
,
662 OUT PVOID StringBuffer
,
663 IN ULONG NumCodesToRead
,
665 // OUT PCOORD EndCoord,
666 OUT PULONG NumCodesRead OPTIONAL
);
667 CSR_API(SrvReadConsoleOutputString
)
670 PCONSOLE_READOUTPUTCODE ReadOutputCodeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ReadOutputCodeRequest
;
671 PTEXTMODE_SCREEN_BUFFER Buffer
;
676 DPRINT("SrvReadConsoleOutputString\n");
678 switch (ReadOutputCodeRequest
->CodeType
)
681 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, AsciiChar
);
685 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, UnicodeChar
);
689 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, Attribute
);
693 return STATUS_INVALID_PARAMETER
;
697 * For optimization purposes, Windows (and hence ReactOS, too, for
698 * compatibility reasons) uses a static buffer if no more than eighty
699 * bytes are read. Otherwise a new buffer is used.
700 * The client-side expects that we know this behaviour.
702 if (ReadOutputCodeRequest
->NumCodes
* CodeSize
<= sizeof(ReadOutputCodeRequest
->CodeStaticBuffer
))
705 * Adjust the internal pointer, because its old value points to
706 * the static buffer in the original ApiMessage structure.
708 // ReadOutputCodeRequest->pCode = ReadOutputCodeRequest->CodeStaticBuffer;
709 pCode
= ReadOutputCodeRequest
->CodeStaticBuffer
;
713 if (!CsrValidateMessageBuffer(ApiMessage
,
714 (PVOID
*)&ReadOutputCodeRequest
->pCode
,
715 ReadOutputCodeRequest
->NumCodes
,
718 return STATUS_INVALID_PARAMETER
;
721 pCode
= ReadOutputCodeRequest
->pCode
;
724 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
725 ReadOutputCodeRequest
->OutputHandle
,
726 &Buffer
, GENERIC_READ
, TRUE
);
727 if (!NT_SUCCESS(Status
))
729 ReadOutputCodeRequest
->NumCodes
= 0;
733 Status
= ConDrvReadConsoleOutputString(Buffer
->Header
.Console
,
735 ReadOutputCodeRequest
->CodeType
,
737 ReadOutputCodeRequest
->NumCodes
,
738 &ReadOutputCodeRequest
->Coord
,
739 // &ReadOutputCodeRequest->EndCoord,
740 &ReadOutputCodeRequest
->NumCodes
);
742 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
747 ConDrvWriteConsoleOutputString(IN PCONSOLE Console
,
748 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
749 IN CODE_TYPE CodeType
,
750 IN PVOID StringBuffer
,
751 IN ULONG NumCodesToWrite
,
752 IN PCOORD WriteCoord
,
753 // OUT PCOORD EndCoord,
754 OUT PULONG NumCodesWritten OPTIONAL
);
755 CSR_API(SrvWriteConsoleOutputString
)
758 PCONSOLE_WRITEOUTPUTCODE WriteOutputCodeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteOutputCodeRequest
;
759 PTEXTMODE_SCREEN_BUFFER Buffer
;
764 DPRINT("SrvWriteConsoleOutputString\n");
766 switch (WriteOutputCodeRequest
->CodeType
)
769 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, AsciiChar
);
773 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, UnicodeChar
);
777 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, Attribute
);
781 return STATUS_INVALID_PARAMETER
;
785 * For optimization purposes, Windows (and hence ReactOS, too, for
786 * compatibility reasons) uses a static buffer if no more than eighty
787 * bytes are written. Otherwise a new buffer is used.
788 * The client-side expects that we know this behaviour.
790 if (WriteOutputCodeRequest
->NumCodes
* CodeSize
<= sizeof(WriteOutputCodeRequest
->CodeStaticBuffer
))
793 * Adjust the internal pointer, because its old value points to
794 * the static buffer in the original ApiMessage structure.
796 // WriteOutputCodeRequest->pCode = WriteOutputCodeRequest->CodeStaticBuffer;
797 pCode
= WriteOutputCodeRequest
->CodeStaticBuffer
;
801 if (!CsrValidateMessageBuffer(ApiMessage
,
802 (PVOID
*)&WriteOutputCodeRequest
->pCode
,
803 WriteOutputCodeRequest
->NumCodes
,
806 return STATUS_INVALID_PARAMETER
;
809 pCode
= WriteOutputCodeRequest
->pCode
;
812 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
813 WriteOutputCodeRequest
->OutputHandle
,
814 &Buffer
, GENERIC_WRITE
, TRUE
);
815 if (!NT_SUCCESS(Status
))
817 WriteOutputCodeRequest
->NumCodes
= 0;
821 Status
= ConDrvWriteConsoleOutputString(Buffer
->Header
.Console
,
823 WriteOutputCodeRequest
->CodeType
,
825 WriteOutputCodeRequest
->NumCodes
,
826 &WriteOutputCodeRequest
->Coord
,
827 // &WriteOutputCodeRequest->EndCoord,
828 &WriteOutputCodeRequest
->NumCodes
);
830 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
835 ConDrvFillConsoleOutput(IN PCONSOLE Console
,
836 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
837 IN CODE_TYPE CodeType
,
838 IN CODE_ELEMENT Code
,
839 IN ULONG NumCodesToWrite
,
840 IN PCOORD WriteCoord
,
841 OUT PULONG NumCodesWritten OPTIONAL
);
842 CSR_API(SrvFillConsoleOutput
)
845 PCONSOLE_FILLOUTPUTCODE FillOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.FillOutputRequest
;
846 PTEXTMODE_SCREEN_BUFFER Buffer
;
847 CODE_TYPE CodeType
= FillOutputRequest
->CodeType
;
849 DPRINT("SrvFillConsoleOutput\n");
851 if ( (CodeType
!= CODE_ASCII
) &&
852 (CodeType
!= CODE_UNICODE
) &&
853 (CodeType
!= CODE_ATTRIBUTE
) )
855 return STATUS_INVALID_PARAMETER
;
858 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
859 FillOutputRequest
->OutputHandle
,
860 &Buffer
, GENERIC_WRITE
, TRUE
);
861 if (!NT_SUCCESS(Status
))
863 FillOutputRequest
->NumCodes
= 0;
867 Status
= ConDrvFillConsoleOutput(Buffer
->Header
.Console
,
870 FillOutputRequest
->Code
,
871 FillOutputRequest
->NumCodes
,
872 &FillOutputRequest
->WriteCoord
,
873 &FillOutputRequest
->NumCodes
);
875 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
880 ConDrvGetConsoleScreenBufferInfo(IN PCONSOLE Console
,
881 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
882 OUT PCOORD ScreenBufferSize
,
883 OUT PCOORD CursorPosition
,
884 OUT PCOORD ViewOrigin
,
886 OUT PCOORD MaximumViewSize
,
887 OUT PWORD Attributes
);
888 CSR_API(SrvGetConsoleScreenBufferInfo
)
891 PCONSOLE_GETSCREENBUFFERINFO ScreenBufferInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ScreenBufferInfoRequest
;
892 PTEXTMODE_SCREEN_BUFFER Buffer
;
894 DPRINT("SrvGetConsoleScreenBufferInfo\n");
896 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
897 ScreenBufferInfoRequest
->OutputHandle
,
898 &Buffer
, GENERIC_READ
, TRUE
);
899 if (!NT_SUCCESS(Status
)) return Status
;
901 Status
= ConDrvGetConsoleScreenBufferInfo(Buffer
->Header
.Console
,
903 &ScreenBufferInfoRequest
->ScreenBufferSize
,
904 &ScreenBufferInfoRequest
->CursorPosition
,
905 &ScreenBufferInfoRequest
->ViewOrigin
,
906 &ScreenBufferInfoRequest
->ViewSize
,
907 &ScreenBufferInfoRequest
->MaximumViewSize
,
908 &ScreenBufferInfoRequest
->Attributes
);
910 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
915 ConDrvSetConsoleTextAttribute(IN PCONSOLE Console
,
916 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
918 CSR_API(SrvSetConsoleTextAttribute
)
921 PCONSOLE_SETTEXTATTRIB SetTextAttribRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetTextAttribRequest
;
922 PTEXTMODE_SCREEN_BUFFER Buffer
;
924 DPRINT("SrvSetConsoleTextAttribute\n");
926 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
927 SetTextAttribRequest
->OutputHandle
,
928 &Buffer
, GENERIC_WRITE
, TRUE
);
929 if (!NT_SUCCESS(Status
)) return Status
;
931 Status
= ConDrvSetConsoleTextAttribute(Buffer
->Header
.Console
,
933 SetTextAttribRequest
->Attributes
);
935 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
940 ConDrvSetConsoleScreenBufferSize(IN PCONSOLE Console
,
941 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
943 CSR_API(SrvSetConsoleScreenBufferSize
)
946 PCONSOLE_SETSCREENBUFFERSIZE SetScreenBufferSizeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetScreenBufferSizeRequest
;
947 PTEXTMODE_SCREEN_BUFFER Buffer
;
949 DPRINT("SrvSetConsoleScreenBufferSize\n");
951 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
952 SetScreenBufferSizeRequest
->OutputHandle
,
953 &Buffer
, GENERIC_WRITE
, TRUE
);
954 if (!NT_SUCCESS(Status
)) return Status
;
956 Status
= ConDrvSetConsoleScreenBufferSize(Buffer
->Header
.Console
,
958 &SetScreenBufferSizeRequest
->Size
);
960 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
965 ConDrvScrollConsoleScreenBuffer(IN PCONSOLE Console
,
966 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
968 IN PSMALL_RECT ScrollRectangle
,
969 IN BOOLEAN UseClipRectangle
,
970 IN PSMALL_RECT ClipRectangle OPTIONAL
,
971 IN PCOORD DestinationOrigin
,
972 IN CHAR_INFO FillChar
);
973 CSR_API(SrvScrollConsoleScreenBuffer
)
976 PCONSOLE_SCROLLSCREENBUFFER ScrollScreenBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ScrollScreenBufferRequest
;
977 PTEXTMODE_SCREEN_BUFFER Buffer
;
979 DPRINT("SrvScrollConsoleScreenBuffer\n");
981 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
982 ScrollScreenBufferRequest
->OutputHandle
,
983 &Buffer
, GENERIC_WRITE
, TRUE
);
984 if (!NT_SUCCESS(Status
)) return Status
;
986 Status
= ConDrvScrollConsoleScreenBuffer(Buffer
->Header
.Console
,
988 ScrollScreenBufferRequest
->Unicode
,
989 &ScrollScreenBufferRequest
->ScrollRectangle
,
990 ScrollScreenBufferRequest
->UseClipRectangle
,
991 &ScrollScreenBufferRequest
->ClipRectangle
,
992 &ScrollScreenBufferRequest
->DestinationOrigin
,
993 ScrollScreenBufferRequest
->Fill
);
995 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
1000 ConDrvSetConsoleWindowInfo(IN PCONSOLE Console
,
1001 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
1002 IN BOOLEAN Absolute
,
1003 IN PSMALL_RECT WindowRect
);
1004 CSR_API(SrvSetConsoleWindowInfo
)
1007 PCONSOLE_SETWINDOWINFO SetWindowInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetWindowInfoRequest
;
1008 // PCONSOLE_SCREEN_BUFFER Buffer;
1009 PTEXTMODE_SCREEN_BUFFER Buffer
;
1011 DPRINT1("SrvSetConsoleWindowInfo(0x%08x, %d, {L%d, T%d, R%d, B%d}) called\n",
1012 SetWindowInfoRequest
->OutputHandle
, SetWindowInfoRequest
->Absolute
,
1013 SetWindowInfoRequest
->WindowRect
.Left
,
1014 SetWindowInfoRequest
->WindowRect
.Top
,
1015 SetWindowInfoRequest
->WindowRect
.Right
,
1016 SetWindowInfoRequest
->WindowRect
.Bottom
);
1018 // ConSrvGetScreenBuffer
1019 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
1020 SetWindowInfoRequest
->OutputHandle
,
1021 &Buffer
, GENERIC_READ
, TRUE
);
1022 if (!NT_SUCCESS(Status
)) return Status
;
1024 Status
= ConDrvSetConsoleWindowInfo(Buffer
->Header
.Console
,
1026 SetWindowInfoRequest
->Absolute
,
1027 &SetWindowInfoRequest
->WindowRect
);
1029 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);