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 PCSR_PROCESS Process
= CsrGetClientThread()->Process
;
173 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(Process
);
174 PCONSRV_CONSOLE Console
;
175 PCONSOLE_SCREEN_BUFFER Buff
;
177 PVOID ScreenBufferInfo
= NULL
;
178 TEXTMODE_BUFFER_INFO TextModeInfo
= {{80, 25},
179 DEFAULT_SCREEN_ATTRIB
,
180 DEFAULT_POPUP_ATTRIB
,
182 CSR_DEFAULT_CURSOR_SIZE
};
183 GRAPHICS_BUFFER_INFO GraphicsInfo
;
184 GraphicsInfo
.Info
= CreateScreenBufferRequest
->GraphicsBufferInfo
; // HACK for MSVC
186 DPRINT("SrvCreateConsoleScreenBuffer\n");
188 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
189 if (!NT_SUCCESS(Status
)) return Status
;
191 if (CreateScreenBufferRequest
->ScreenBufferType
== CONSOLE_TEXTMODE_BUFFER
)
193 ScreenBufferInfo
= &TextModeInfo
;
196 if (Console->ActiveBuffer)
198 TextModeInfo.ScreenBufferSize = Console->ActiveBuffer->ScreenBufferSize;
199 if (TextModeInfo.ScreenBufferSize.X == 0) TextModeInfo.ScreenBufferSize.X = 80;
200 if (TextModeInfo.ScreenBufferSize.Y == 0) TextModeInfo.ScreenBufferSize.Y = 25;
202 TextModeInfo.ScreenAttrib = Console->ActiveBuffer->ScreenBuffer.TextBuffer.ScreenDefaultAttrib;
203 TextModeInfo.PopupAttrib = Console->ActiveBuffer->ScreenBuffer.TextBuffer.PopupDefaultAttrib;
205 TextModeInfo.IsCursorVisible = Console->ActiveBuffer->CursorInfo.bVisible;
206 TextModeInfo.CursorSize = Console->ActiveBuffer->CursorInfo.dwSize;
211 * This is Windows' behaviour
214 /* Use the current console size. Regularize it if needed. */
215 TextModeInfo
.ScreenBufferSize
= Console
->ConsoleSize
;
216 if (TextModeInfo
.ScreenBufferSize
.X
== 0) TextModeInfo
.ScreenBufferSize
.X
= 1;
217 if (TextModeInfo
.ScreenBufferSize
.Y
== 0) TextModeInfo
.ScreenBufferSize
.Y
= 1;
219 /* If we have an active screen buffer, use its attributes as the new ones */
220 if (Console
->ActiveBuffer
&& GetType(Console
->ActiveBuffer
) == TEXTMODE_BUFFER
)
222 PTEXTMODE_SCREEN_BUFFER Buffer
= (PTEXTMODE_SCREEN_BUFFER
)Console
->ActiveBuffer
;
224 TextModeInfo
.ScreenAttrib
= Buffer
->ScreenDefaultAttrib
;
225 TextModeInfo
.PopupAttrib
= Buffer
->PopupDefaultAttrib
;
227 TextModeInfo
.IsCursorVisible
= Buffer
->CursorInfo
.bVisible
;
228 TextModeInfo
.CursorSize
= Buffer
->CursorInfo
.dwSize
;
231 else if (CreateScreenBufferRequest
->ScreenBufferType
== CONSOLE_GRAPHICS_BUFFER
)
233 /* Get infos from the graphics buffer information structure */
234 if (!CsrValidateMessageBuffer(ApiMessage
,
235 (PVOID
*)&CreateScreenBufferRequest
->GraphicsBufferInfo
.lpBitMapInfo
,
236 CreateScreenBufferRequest
->GraphicsBufferInfo
.dwBitMapInfoLength
,
239 Status
= STATUS_INVALID_PARAMETER
;
243 ScreenBufferInfo
= &GraphicsInfo
;
245 /* Initialize shared variables */
246 // CreateScreenBufferRequest->GraphicsBufferInfo.hMutex
247 CreateScreenBufferRequest
->hMutex
= GraphicsInfo
.Info
.hMutex
= INVALID_HANDLE_VALUE
;
248 // CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap
249 CreateScreenBufferRequest
->lpBitMap
= GraphicsInfo
.Info
.lpBitMap
= NULL
;
251 /* A graphics screen buffer is never inheritable */
252 CreateScreenBufferRequest
->InheritHandle
= FALSE
;
255 Status
= ConDrvCreateScreenBuffer(&Buff
,
257 Process
->ProcessHandle
,
258 CreateScreenBufferRequest
->ScreenBufferType
,
260 if (!NT_SUCCESS(Status
)) goto Quit
;
262 /* Insert the new handle inside the process handles table */
263 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
265 Status
= ConSrvInsertObject(ProcessData
,
266 &CreateScreenBufferRequest
->OutputHandle
,
268 CreateScreenBufferRequest
->DesiredAccess
,
269 CreateScreenBufferRequest
->InheritHandle
,
270 CreateScreenBufferRequest
->ShareMode
);
272 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
274 if (!NT_SUCCESS(Status
)) goto Quit
;
276 if (CreateScreenBufferRequest
->ScreenBufferType
== CONSOLE_GRAPHICS_BUFFER
)
278 PGRAPHICS_SCREEN_BUFFER Buffer
= (PGRAPHICS_SCREEN_BUFFER
)Buff
;
280 * Initialize the graphics buffer information structure
281 * and give it back to the client.
283 // CreateScreenBufferRequest->GraphicsBufferInfo.hMutex
284 CreateScreenBufferRequest
->hMutex
= Buffer
->ClientMutex
;
285 // CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap
286 CreateScreenBufferRequest
->lpBitMap
= Buffer
->ClientBitMap
;
290 ConSrvReleaseConsole(Console
, TRUE
);
295 ConDrvSetConsoleActiveScreenBuffer(IN PCONSOLE Console
,
296 IN PCONSOLE_SCREEN_BUFFER Buffer
);
297 CSR_API(SrvSetConsoleActiveScreenBuffer
)
300 PCONSOLE_SETACTIVESCREENBUFFER SetScreenBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetScreenBufferRequest
;
301 PCONSOLE_SCREEN_BUFFER Buffer
;
303 DPRINT("SrvSetConsoleActiveScreenBuffer\n");
305 Status
= ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
306 SetScreenBufferRequest
->OutputHandle
,
307 &Buffer
, GENERIC_WRITE
, TRUE
);
308 if (!NT_SUCCESS(Status
)) return Status
;
310 Status
= ConDrvSetConsoleActiveScreenBuffer(Buffer
->Header
.Console
,
313 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
318 /* CSR THREADS FOR WriteConsole ***********************************************/
321 DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage
,
322 IN PCSR_THREAD ClientThread
,
323 IN BOOLEAN CreateWaitBlock OPTIONAL
);
325 // Wait function CSR_WAIT_FUNCTION
328 WriteConsoleThread(IN PLIST_ENTRY WaitList
,
329 IN PCSR_THREAD WaitThread
,
330 IN PCSR_API_MESSAGE WaitApiMessage
,
331 IN PVOID WaitContext
,
332 IN PVOID WaitArgument1
,
333 IN PVOID WaitArgument2
,
338 DPRINT("WriteConsoleThread - WaitContext = 0x%p, WaitArgument1 = 0x%p, WaitArgument2 = 0x%p, WaitFlags = %lu\n", WaitContext
, WaitArgument1
, WaitArgument2
, WaitFlags
);
341 * If we are notified of the process termination via a call
342 * to CsrNotifyWaitBlock triggered by CsrDestroyProcess or
343 * CsrDestroyThread, just return.
345 if (WaitFlags
& CsrProcessTerminating
)
347 Status
= STATUS_THREAD_IS_TERMINATING
;
351 Status
= DoWriteConsole(WaitApiMessage
, WaitThread
, FALSE
);
354 if (Status
!= STATUS_PENDING
)
356 WaitApiMessage
->Status
= Status
;
359 return (Status
== STATUS_PENDING
? FALSE
: TRUE
);
363 ConDrvWriteConsole(IN PCONSOLE Console
,
364 IN PTEXTMODE_SCREEN_BUFFER ScreenBuffer
,
366 IN PVOID StringBuffer
,
367 IN ULONG NumCharsToWrite
,
368 OUT PULONG NumCharsWritten OPTIONAL
);
370 DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage
,
371 IN PCSR_THREAD ClientThread
,
372 IN BOOLEAN CreateWaitBlock OPTIONAL
)
375 PCONSOLE_WRITECONSOLE WriteConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteConsoleRequest
;
376 PTEXTMODE_SCREEN_BUFFER ScreenBuffer
;
379 ULONG NrCharactersWritten
= 0;
380 ULONG CharSize
= (WriteConsoleRequest
->Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
382 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(ClientThread
->Process
),
383 WriteConsoleRequest
->OutputHandle
,
384 &ScreenBuffer
, GENERIC_WRITE
, FALSE
);
385 if (!NT_SUCCESS(Status
)) return Status
;
388 * For optimization purposes, Windows (and hence ReactOS, too, for
389 * compatibility reasons) uses a static buffer if no more than eighty
390 * bytes are written. Otherwise a new buffer is used.
391 * The client-side expects that we know this behaviour.
393 if (WriteConsoleRequest
->UsingStaticBuffer
&&
394 WriteConsoleRequest
->NumBytes
<= sizeof(WriteConsoleRequest
->StaticBuffer
))
397 * Adjust the internal pointer, because its old value points to
398 * the static buffer in the original ApiMessage structure.
400 // WriteConsoleRequest->Buffer = WriteConsoleRequest->StaticBuffer;
401 Buffer
= WriteConsoleRequest
->StaticBuffer
;
405 Buffer
= WriteConsoleRequest
->Buffer
;
408 DPRINT("Calling ConDrvWriteConsole\n");
409 Status
= ConDrvWriteConsole(ScreenBuffer
->Header
.Console
,
411 WriteConsoleRequest
->Unicode
,
413 WriteConsoleRequest
->NumBytes
/ CharSize
, // NrCharactersToWrite
414 &NrCharactersWritten
);
415 DPRINT("ConDrvWriteConsole returned (%d ; Status = 0x%08x)\n",
416 NrCharactersWritten
, Status
);
418 if (Status
== STATUS_PENDING
)
422 PCONSRV_CONSOLE Console
= (PCONSRV_CONSOLE
)ScreenBuffer
->Header
.Console
;
424 if (!CsrCreateWait(&Console
->WriteWaitQueue
,
431 Status
= STATUS_NO_MEMORY
;
436 /* Wait until we un-pause the console */
437 // Status = STATUS_PENDING;
441 /* We read all what we wanted. Set the number of bytes written. */
442 WriteConsoleRequest
->NumBytes
= NrCharactersWritten
* CharSize
;
446 ConSrvReleaseScreenBuffer(ScreenBuffer
, FALSE
);
451 /* TEXT OUTPUT APIS ***********************************************************/
454 ConDrvReadConsoleOutput(IN PCONSOLE Console
,
455 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
457 OUT PCHAR_INFO CharInfo
/*Buffer*/,
458 IN OUT PSMALL_RECT ReadRegion
);
459 CSR_API(SrvReadConsoleOutput
)
462 PCONSOLE_READOUTPUT ReadOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ReadOutputRequest
;
463 PTEXTMODE_SCREEN_BUFFER Buffer
;
468 DPRINT("SrvReadConsoleOutput\n");
470 NumCells
= (ReadOutputRequest
->ReadRegion
.Right
- ReadOutputRequest
->ReadRegion
.Left
+ 1) *
471 (ReadOutputRequest
->ReadRegion
.Bottom
- ReadOutputRequest
->ReadRegion
.Top
+ 1);
474 * For optimization purposes, Windows (and hence ReactOS, too, for
475 * compatibility reasons) uses a static buffer if no more than one
476 * cell is read. Otherwise a new buffer is used.
477 * The client-side expects that we know this behaviour.
482 * Adjust the internal pointer, because its old value points to
483 * the static buffer in the original ApiMessage structure.
485 // ReadOutputRequest->CharInfo = &ReadOutputRequest->StaticBuffer;
486 CharInfo
= &ReadOutputRequest
->StaticBuffer
;
490 if (!CsrValidateMessageBuffer(ApiMessage
,
491 (PVOID
*)&ReadOutputRequest
->CharInfo
,
495 return STATUS_INVALID_PARAMETER
;
498 CharInfo
= ReadOutputRequest
->CharInfo
;
501 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
502 ReadOutputRequest
->OutputHandle
,
503 &Buffer
, GENERIC_READ
, TRUE
);
504 if (!NT_SUCCESS(Status
)) return Status
;
506 Status
= ConDrvReadConsoleOutput(Buffer
->Header
.Console
,
508 ReadOutputRequest
->Unicode
,
510 &ReadOutputRequest
->ReadRegion
);
512 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
517 ConDrvWriteConsoleOutput(IN PCONSOLE Console
,
518 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
520 IN PCHAR_INFO CharInfo
/*Buffer*/,
521 IN OUT PSMALL_RECT WriteRegion
);
522 CSR_API(SrvWriteConsoleOutput
)
525 PCONSOLE_WRITEOUTPUT WriteOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteOutputRequest
;
526 PTEXTMODE_SCREEN_BUFFER Buffer
;
527 PCSR_PROCESS Process
= CsrGetClientThread()->Process
;
532 DPRINT("SrvWriteConsoleOutput\n");
534 NumCells
= (WriteOutputRequest
->WriteRegion
.Right
- WriteOutputRequest
->WriteRegion
.Left
+ 1) *
535 (WriteOutputRequest
->WriteRegion
.Bottom
- WriteOutputRequest
->WriteRegion
.Top
+ 1);
537 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(Process
),
538 WriteOutputRequest
->OutputHandle
,
539 &Buffer
, GENERIC_WRITE
, TRUE
);
540 if (!NT_SUCCESS(Status
)) return Status
;
543 * Validate the message buffer if we do not use a process' heap buffer
544 * (CsrAllocateCaptureBuffer succeeded because we haven't allocated
545 * a too large (>= 64 kB, size of the CSR heap) data buffer).
547 if (!WriteOutputRequest
->UseVirtualMemory
)
550 * For optimization purposes, Windows (and hence ReactOS, too, for
551 * compatibility reasons) uses a static buffer if no more than one
552 * cell is written. Otherwise a new buffer is used.
553 * The client-side expects that we know this behaviour.
558 * Adjust the internal pointer, because its old value points to
559 * the static buffer in the original ApiMessage structure.
561 // WriteOutputRequest->CharInfo = &WriteOutputRequest->StaticBuffer;
562 CharInfo
= &WriteOutputRequest
->StaticBuffer
;
566 if (!CsrValidateMessageBuffer(ApiMessage
,
567 (PVOID
*)&WriteOutputRequest
->CharInfo
,
571 Status
= STATUS_INVALID_PARAMETER
;
575 CharInfo
= WriteOutputRequest
->CharInfo
;
581 * This was not the case: we use a heap buffer. Retrieve its contents.
583 ULONG Size
= NumCells
* sizeof(CHAR_INFO
);
585 CharInfo
= ConsoleAllocHeap(HEAP_ZERO_MEMORY
, Size
);
586 if (CharInfo
== NULL
)
588 Status
= STATUS_NO_MEMORY
;
592 Status
= NtReadVirtualMemory(Process
->ProcessHandle
,
593 WriteOutputRequest
->CharInfo
,
597 if (!NT_SUCCESS(Status
))
599 ConsoleFreeHeap(CharInfo
);
600 // Status = STATUS_NO_MEMORY;
605 Status
= ConDrvWriteConsoleOutput(Buffer
->Header
.Console
,
607 WriteOutputRequest
->Unicode
,
609 &WriteOutputRequest
->WriteRegion
);
611 /* Free the temporary buffer if we used the process' heap buffer */
612 if (WriteOutputRequest
->UseVirtualMemory
&& CharInfo
)
613 ConsoleFreeHeap(CharInfo
);
616 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
620 CSR_API(SrvWriteConsole
)
623 PCONSOLE_WRITECONSOLE WriteConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteConsoleRequest
;
625 DPRINT("SrvWriteConsole\n");
628 * For optimization purposes, Windows (and hence ReactOS, too, for
629 * compatibility reasons) uses a static buffer if no more than eighty
630 * bytes are written. Otherwise a new buffer is used.
631 * The client-side expects that we know this behaviour.
633 if (WriteConsoleRequest
->UsingStaticBuffer
&&
634 WriteConsoleRequest
->NumBytes
<= sizeof(WriteConsoleRequest
->StaticBuffer
))
637 * Adjust the internal pointer, because its old value points to
638 * the static buffer in the original ApiMessage structure.
640 // WriteConsoleRequest->Buffer = WriteConsoleRequest->StaticBuffer;
644 if (!CsrValidateMessageBuffer(ApiMessage
,
645 (PVOID
)&WriteConsoleRequest
->Buffer
,
646 WriteConsoleRequest
->NumBytes
,
649 return STATUS_INVALID_PARAMETER
;
653 Status
= DoWriteConsole(ApiMessage
, CsrGetClientThread(), TRUE
);
655 if (Status
== STATUS_PENDING
) *ReplyCode
= CsrReplyPending
;
661 ConDrvReadConsoleOutputString(IN PCONSOLE Console
,
662 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
663 IN CODE_TYPE CodeType
,
664 OUT PVOID StringBuffer
,
665 IN ULONG NumCodesToRead
,
667 // OUT PCOORD EndCoord,
668 OUT PULONG NumCodesRead OPTIONAL
);
669 CSR_API(SrvReadConsoleOutputString
)
672 PCONSOLE_READOUTPUTCODE ReadOutputCodeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ReadOutputCodeRequest
;
673 PTEXTMODE_SCREEN_BUFFER Buffer
;
678 DPRINT("SrvReadConsoleOutputString\n");
680 switch (ReadOutputCodeRequest
->CodeType
)
683 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, AsciiChar
);
687 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, UnicodeChar
);
691 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, Attribute
);
695 return STATUS_INVALID_PARAMETER
;
699 * For optimization purposes, Windows (and hence ReactOS, too, for
700 * compatibility reasons) uses a static buffer if no more than eighty
701 * bytes are read. Otherwise a new buffer is used.
702 * The client-side expects that we know this behaviour.
704 if (ReadOutputCodeRequest
->NumCodes
* CodeSize
<= sizeof(ReadOutputCodeRequest
->CodeStaticBuffer
))
707 * Adjust the internal pointer, because its old value points to
708 * the static buffer in the original ApiMessage structure.
710 // ReadOutputCodeRequest->pCode = ReadOutputCodeRequest->CodeStaticBuffer;
711 pCode
= ReadOutputCodeRequest
->CodeStaticBuffer
;
715 if (!CsrValidateMessageBuffer(ApiMessage
,
716 (PVOID
*)&ReadOutputCodeRequest
->pCode
,
717 ReadOutputCodeRequest
->NumCodes
,
720 return STATUS_INVALID_PARAMETER
;
723 pCode
= ReadOutputCodeRequest
->pCode
;
726 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
727 ReadOutputCodeRequest
->OutputHandle
,
728 &Buffer
, GENERIC_READ
, TRUE
);
729 if (!NT_SUCCESS(Status
))
731 ReadOutputCodeRequest
->NumCodes
= 0;
735 Status
= ConDrvReadConsoleOutputString(Buffer
->Header
.Console
,
737 ReadOutputCodeRequest
->CodeType
,
739 ReadOutputCodeRequest
->NumCodes
,
740 &ReadOutputCodeRequest
->Coord
,
741 // &ReadOutputCodeRequest->EndCoord,
742 &ReadOutputCodeRequest
->NumCodes
);
744 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
749 ConDrvWriteConsoleOutputString(IN PCONSOLE Console
,
750 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
751 IN CODE_TYPE CodeType
,
752 IN PVOID StringBuffer
,
753 IN ULONG NumCodesToWrite
,
754 IN PCOORD WriteCoord
,
755 // OUT PCOORD EndCoord,
756 OUT PULONG NumCodesWritten OPTIONAL
);
757 CSR_API(SrvWriteConsoleOutputString
)
760 PCONSOLE_WRITEOUTPUTCODE WriteOutputCodeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteOutputCodeRequest
;
761 PTEXTMODE_SCREEN_BUFFER Buffer
;
766 DPRINT("SrvWriteConsoleOutputString\n");
768 switch (WriteOutputCodeRequest
->CodeType
)
771 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, AsciiChar
);
775 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, UnicodeChar
);
779 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, Attribute
);
783 return STATUS_INVALID_PARAMETER
;
787 * For optimization purposes, Windows (and hence ReactOS, too, for
788 * compatibility reasons) uses a static buffer if no more than eighty
789 * bytes are written. Otherwise a new buffer is used.
790 * The client-side expects that we know this behaviour.
792 if (WriteOutputCodeRequest
->NumCodes
* CodeSize
<= sizeof(WriteOutputCodeRequest
->CodeStaticBuffer
))
795 * Adjust the internal pointer, because its old value points to
796 * the static buffer in the original ApiMessage structure.
798 // WriteOutputCodeRequest->pCode = WriteOutputCodeRequest->CodeStaticBuffer;
799 pCode
= WriteOutputCodeRequest
->CodeStaticBuffer
;
803 if (!CsrValidateMessageBuffer(ApiMessage
,
804 (PVOID
*)&WriteOutputCodeRequest
->pCode
,
805 WriteOutputCodeRequest
->NumCodes
,
808 return STATUS_INVALID_PARAMETER
;
811 pCode
= WriteOutputCodeRequest
->pCode
;
814 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
815 WriteOutputCodeRequest
->OutputHandle
,
816 &Buffer
, GENERIC_WRITE
, TRUE
);
817 if (!NT_SUCCESS(Status
))
819 WriteOutputCodeRequest
->NumCodes
= 0;
823 Status
= ConDrvWriteConsoleOutputString(Buffer
->Header
.Console
,
825 WriteOutputCodeRequest
->CodeType
,
827 WriteOutputCodeRequest
->NumCodes
,
828 &WriteOutputCodeRequest
->Coord
,
829 // &WriteOutputCodeRequest->EndCoord,
830 &WriteOutputCodeRequest
->NumCodes
);
832 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
837 ConDrvFillConsoleOutput(IN PCONSOLE Console
,
838 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
839 IN CODE_TYPE CodeType
,
840 IN CODE_ELEMENT Code
,
841 IN ULONG NumCodesToWrite
,
842 IN PCOORD WriteCoord
,
843 OUT PULONG NumCodesWritten OPTIONAL
);
844 CSR_API(SrvFillConsoleOutput
)
847 PCONSOLE_FILLOUTPUTCODE FillOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.FillOutputRequest
;
848 PTEXTMODE_SCREEN_BUFFER Buffer
;
849 CODE_TYPE CodeType
= FillOutputRequest
->CodeType
;
851 DPRINT("SrvFillConsoleOutput\n");
853 if ( (CodeType
!= CODE_ASCII
) &&
854 (CodeType
!= CODE_UNICODE
) &&
855 (CodeType
!= CODE_ATTRIBUTE
) )
857 return STATUS_INVALID_PARAMETER
;
860 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
861 FillOutputRequest
->OutputHandle
,
862 &Buffer
, GENERIC_WRITE
, TRUE
);
863 if (!NT_SUCCESS(Status
))
865 FillOutputRequest
->NumCodes
= 0;
869 Status
= ConDrvFillConsoleOutput(Buffer
->Header
.Console
,
872 FillOutputRequest
->Code
,
873 FillOutputRequest
->NumCodes
,
874 &FillOutputRequest
->WriteCoord
,
875 &FillOutputRequest
->NumCodes
);
877 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
882 ConDrvGetConsoleScreenBufferInfo(IN PCONSOLE Console
,
883 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
884 OUT PCOORD ScreenBufferSize
,
885 OUT PCOORD CursorPosition
,
886 OUT PCOORD ViewOrigin
,
888 OUT PCOORD MaximumViewSize
,
889 OUT PWORD Attributes
);
890 CSR_API(SrvGetConsoleScreenBufferInfo
)
893 PCONSOLE_GETSCREENBUFFERINFO ScreenBufferInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ScreenBufferInfoRequest
;
894 PTEXTMODE_SCREEN_BUFFER Buffer
;
896 DPRINT("SrvGetConsoleScreenBufferInfo\n");
898 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
899 ScreenBufferInfoRequest
->OutputHandle
,
900 &Buffer
, GENERIC_READ
, TRUE
);
901 if (!NT_SUCCESS(Status
)) return Status
;
903 Status
= ConDrvGetConsoleScreenBufferInfo(Buffer
->Header
.Console
,
905 &ScreenBufferInfoRequest
->ScreenBufferSize
,
906 &ScreenBufferInfoRequest
->CursorPosition
,
907 &ScreenBufferInfoRequest
->ViewOrigin
,
908 &ScreenBufferInfoRequest
->ViewSize
,
909 &ScreenBufferInfoRequest
->MaximumViewSize
,
910 &ScreenBufferInfoRequest
->Attributes
);
912 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
917 ConDrvSetConsoleTextAttribute(IN PCONSOLE Console
,
918 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
920 CSR_API(SrvSetConsoleTextAttribute
)
923 PCONSOLE_SETTEXTATTRIB SetTextAttribRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetTextAttribRequest
;
924 PTEXTMODE_SCREEN_BUFFER Buffer
;
926 DPRINT("SrvSetConsoleTextAttribute\n");
928 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
929 SetTextAttribRequest
->OutputHandle
,
930 &Buffer
, GENERIC_WRITE
, TRUE
);
931 if (!NT_SUCCESS(Status
)) return Status
;
933 Status
= ConDrvSetConsoleTextAttribute(Buffer
->Header
.Console
,
935 SetTextAttribRequest
->Attributes
);
937 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
942 ConDrvSetConsoleScreenBufferSize(IN PCONSOLE Console
,
943 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
945 CSR_API(SrvSetConsoleScreenBufferSize
)
948 PCONSOLE_SETSCREENBUFFERSIZE SetScreenBufferSizeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetScreenBufferSizeRequest
;
949 PTEXTMODE_SCREEN_BUFFER Buffer
;
951 DPRINT("SrvSetConsoleScreenBufferSize\n");
953 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
954 SetScreenBufferSizeRequest
->OutputHandle
,
955 &Buffer
, GENERIC_WRITE
, TRUE
);
956 if (!NT_SUCCESS(Status
)) return Status
;
958 Status
= ConDrvSetConsoleScreenBufferSize(Buffer
->Header
.Console
,
960 &SetScreenBufferSizeRequest
->Size
);
962 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
967 ConDrvScrollConsoleScreenBuffer(IN PCONSOLE Console
,
968 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
970 IN PSMALL_RECT ScrollRectangle
,
971 IN BOOLEAN UseClipRectangle
,
972 IN PSMALL_RECT ClipRectangle OPTIONAL
,
973 IN PCOORD DestinationOrigin
,
974 IN CHAR_INFO FillChar
);
975 CSR_API(SrvScrollConsoleScreenBuffer
)
978 PCONSOLE_SCROLLSCREENBUFFER ScrollScreenBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ScrollScreenBufferRequest
;
979 PTEXTMODE_SCREEN_BUFFER Buffer
;
981 DPRINT("SrvScrollConsoleScreenBuffer\n");
983 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
984 ScrollScreenBufferRequest
->OutputHandle
,
985 &Buffer
, GENERIC_WRITE
, TRUE
);
986 if (!NT_SUCCESS(Status
)) return Status
;
988 Status
= ConDrvScrollConsoleScreenBuffer(Buffer
->Header
.Console
,
990 ScrollScreenBufferRequest
->Unicode
,
991 &ScrollScreenBufferRequest
->ScrollRectangle
,
992 ScrollScreenBufferRequest
->UseClipRectangle
,
993 &ScrollScreenBufferRequest
->ClipRectangle
,
994 &ScrollScreenBufferRequest
->DestinationOrigin
,
995 ScrollScreenBufferRequest
->Fill
);
997 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
1002 ConDrvSetConsoleWindowInfo(IN PCONSOLE Console
,
1003 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
1004 IN BOOLEAN Absolute
,
1005 IN PSMALL_RECT WindowRect
);
1006 CSR_API(SrvSetConsoleWindowInfo
)
1009 PCONSOLE_SETWINDOWINFO SetWindowInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetWindowInfoRequest
;
1010 // PCONSOLE_SCREEN_BUFFER Buffer;
1011 PTEXTMODE_SCREEN_BUFFER Buffer
;
1013 DPRINT1("SrvSetConsoleWindowInfo(0x%08x, %d, {L%d, T%d, R%d, B%d}) called\n",
1014 SetWindowInfoRequest
->OutputHandle
, SetWindowInfoRequest
->Absolute
,
1015 SetWindowInfoRequest
->WindowRect
.Left
,
1016 SetWindowInfoRequest
->WindowRect
.Top
,
1017 SetWindowInfoRequest
->WindowRect
.Right
,
1018 SetWindowInfoRequest
->WindowRect
.Bottom
);
1020 // ConSrvGetScreenBuffer
1021 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
1022 SetWindowInfoRequest
->OutputHandle
,
1023 &Buffer
, GENERIC_READ
, TRUE
);
1024 if (!NT_SUCCESS(Status
)) return Status
;
1026 Status
= ConDrvSetConsoleWindowInfo(Buffer
->Header
.Console
,
1028 SetWindowInfoRequest
->Absolute
,
1029 &SetWindowInfoRequest
->WindowRect
);
1031 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);