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 CSR_API(SrvInvalidateBitMapRect
)
37 PCONSOLE_INVALIDATEDIBITS InvalidateDIBitsRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.InvalidateDIBitsRequest
;
38 PCONSOLE_SCREEN_BUFFER Buffer
;
40 DPRINT("SrvInvalidateBitMapRect\n");
42 Status
= ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
43 InvalidateDIBitsRequest
->OutputHandle
,
44 &Buffer
, GENERIC_READ
, TRUE
);
45 if (!NT_SUCCESS(Status
)) return Status
;
47 /* In text-mode only, draw the VDM buffer if present */
48 if (GetType(Buffer
) == TEXTMODE_BUFFER
&& Buffer
->Header
.Console
->VDMBuffer
)
50 PTEXTMODE_SCREEN_BUFFER TextBuffer
= (PTEXTMODE_SCREEN_BUFFER
)Buffer
;
52 /*Status =*/ ConDrvWriteConsoleOutputVDM(Buffer
->Header
.Console
,
54 Buffer
->Header
.Console
->VDMBuffer
,
55 Buffer
->Header
.Console
->VDMBufferSize
,
56 &InvalidateDIBitsRequest
->Region
);
59 Status
= ConDrvInvalidateBitMapRect(Buffer
->Header
.Console
,
61 &InvalidateDIBitsRequest
->Region
);
63 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
68 ConDrvSetConsolePalette(IN PCONSOLE Console
,
69 // IN PGRAPHICS_SCREEN_BUFFER Buffer,
70 IN PCONSOLE_SCREEN_BUFFER Buffer
,
71 IN HPALETTE PaletteHandle
,
72 IN UINT PaletteUsage
);
73 /* API_NUMBER: ConsolepSetPalette */
74 CSR_API(SrvSetConsolePalette
)
77 PCONSOLE_SETPALETTE SetPaletteRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetPaletteRequest
;
78 // PGRAPHICS_SCREEN_BUFFER Buffer;
79 PCONSOLE_SCREEN_BUFFER Buffer
;
81 DPRINT("SrvSetConsolePalette\n");
83 // NOTE: Tests show that this function is used only for graphics screen buffers
84 // and otherwise it returns FALSE + sets last error to invalid handle.
85 // I think it's ridiculous, because if you are in text mode, simulating
86 // a change of VGA palette via DAC registers (done by a call to SetConsolePalette)
87 // cannot be done... So I allow it in ReactOS !
89 Status = ConSrvGetGraphicsBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
90 SetPaletteRequest->OutputHandle,
91 &Buffer, GENERIC_WRITE, TRUE);
93 Status
= ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
94 SetPaletteRequest
->OutputHandle
,
95 &Buffer
, GENERIC_WRITE
, TRUE
);
96 if (!NT_SUCCESS(Status
)) return Status
;
99 * Make the palette handle public, so that it can be
100 * used by other threads calling GDI functions on it.
101 * Indeed, the palette handle comes from a console app
102 * calling ourselves, running in CSRSS.
104 NtUserConsoleControl(ConsoleMakePalettePublic
,
105 &SetPaletteRequest
->PaletteHandle
,
106 sizeof(SetPaletteRequest
->PaletteHandle
));
108 Status
= ConDrvSetConsolePalette(Buffer
->Header
.Console
,
110 SetPaletteRequest
->PaletteHandle
,
111 SetPaletteRequest
->Usage
);
113 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
118 ConDrvGetConsoleCursorInfo(IN PCONSOLE Console
,
119 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
120 OUT PCONSOLE_CURSOR_INFO CursorInfo
);
121 /* API_NUMBER: ConsolepGetCursorInfo */
122 CSR_API(SrvGetConsoleCursorInfo
)
125 PCONSOLE_GETSETCURSORINFO CursorInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CursorInfoRequest
;
126 PTEXTMODE_SCREEN_BUFFER Buffer
;
128 DPRINT("SrvGetConsoleCursorInfo\n");
130 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
131 CursorInfoRequest
->OutputHandle
,
132 &Buffer
, GENERIC_READ
, TRUE
);
133 if (!NT_SUCCESS(Status
)) return Status
;
135 Status
= ConDrvGetConsoleCursorInfo(Buffer
->Header
.Console
,
137 &CursorInfoRequest
->Info
);
139 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
144 ConDrvSetConsoleCursorInfo(IN PCONSOLE Console
,
145 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
146 IN PCONSOLE_CURSOR_INFO CursorInfo
);
147 /* API_NUMBER: ConsolepSetCursorInfo */
148 CSR_API(SrvSetConsoleCursorInfo
)
151 PCONSOLE_GETSETCURSORINFO CursorInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CursorInfoRequest
;
152 PTEXTMODE_SCREEN_BUFFER Buffer
;
154 DPRINT("SrvSetConsoleCursorInfo\n");
156 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
157 CursorInfoRequest
->OutputHandle
,
158 &Buffer
, GENERIC_WRITE
, TRUE
);
159 if (!NT_SUCCESS(Status
)) return Status
;
161 Status
= ConDrvSetConsoleCursorInfo(Buffer
->Header
.Console
,
163 &CursorInfoRequest
->Info
);
165 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
170 ConDrvSetConsoleCursorPosition(IN PCONSOLE Console
,
171 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
173 /* API_NUMBER: ConsolepSetCursorPosition */
174 CSR_API(SrvSetConsoleCursorPosition
)
177 PCONSOLE_SETCURSORPOSITION SetCursorPositionRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetCursorPositionRequest
;
178 PTEXTMODE_SCREEN_BUFFER Buffer
;
180 DPRINT("SrvSetConsoleCursorPosition\n");
182 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
183 SetCursorPositionRequest
->OutputHandle
,
184 &Buffer
, GENERIC_WRITE
, TRUE
);
185 if (!NT_SUCCESS(Status
)) return Status
;
187 Status
= ConDrvSetConsoleCursorPosition(Buffer
->Header
.Console
,
189 &SetCursorPositionRequest
->Position
);
191 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
195 /* API_NUMBER: ConsolepCreateScreenBuffer */
196 CSR_API(SrvCreateConsoleScreenBuffer
)
198 NTSTATUS Status
= STATUS_INVALID_PARAMETER
;
199 PCONSOLE_CREATESCREENBUFFER CreateScreenBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CreateScreenBufferRequest
;
200 PCSR_PROCESS Process
= CsrGetClientThread()->Process
;
201 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(Process
);
202 PCONSRV_CONSOLE Console
;
203 PCONSOLE_SCREEN_BUFFER Buff
;
205 PVOID ScreenBufferInfo
= NULL
;
206 TEXTMODE_BUFFER_INFO TextModeInfo
= {{80, 25},
207 DEFAULT_SCREEN_ATTRIB
,
208 DEFAULT_POPUP_ATTRIB
,
210 CSR_DEFAULT_CURSOR_SIZE
};
211 GRAPHICS_BUFFER_INFO GraphicsInfo
;
212 GraphicsInfo
.Info
= CreateScreenBufferRequest
->GraphicsBufferInfo
; // HACK for MSVC
214 DPRINT("SrvCreateConsoleScreenBuffer\n");
216 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
217 if (!NT_SUCCESS(Status
)) return Status
;
219 if (CreateScreenBufferRequest
->ScreenBufferType
== CONSOLE_TEXTMODE_BUFFER
)
221 ScreenBufferInfo
= &TextModeInfo
;
224 if (Console->ActiveBuffer)
226 TextModeInfo.ScreenBufferSize = Console->ActiveBuffer->ScreenBufferSize;
227 if (TextModeInfo.ScreenBufferSize.X == 0) TextModeInfo.ScreenBufferSize.X = 80;
228 if (TextModeInfo.ScreenBufferSize.Y == 0) TextModeInfo.ScreenBufferSize.Y = 25;
230 TextModeInfo.ScreenAttrib = Console->ActiveBuffer->ScreenBuffer.TextBuffer.ScreenDefaultAttrib;
231 TextModeInfo.PopupAttrib = Console->ActiveBuffer->ScreenBuffer.TextBuffer.PopupDefaultAttrib;
233 TextModeInfo.IsCursorVisible = Console->ActiveBuffer->CursorInfo.bVisible;
234 TextModeInfo.CursorSize = Console->ActiveBuffer->CursorInfo.dwSize;
239 * This is Windows behaviour.
242 /* Use the current console size. Normalize it if needed */
243 TextModeInfo
.ScreenBufferSize
= Console
->ConsoleSize
;
244 if (TextModeInfo
.ScreenBufferSize
.X
== 0) TextModeInfo
.ScreenBufferSize
.X
= 1;
245 if (TextModeInfo
.ScreenBufferSize
.Y
== 0) TextModeInfo
.ScreenBufferSize
.Y
= 1;
247 /* If we have an active screen buffer, use its attributes as the new ones */
248 if (Console
->ActiveBuffer
&& GetType(Console
->ActiveBuffer
) == TEXTMODE_BUFFER
)
250 PTEXTMODE_SCREEN_BUFFER Buffer
= (PTEXTMODE_SCREEN_BUFFER
)Console
->ActiveBuffer
;
252 TextModeInfo
.ScreenAttrib
= Buffer
->ScreenDefaultAttrib
;
253 TextModeInfo
.PopupAttrib
= Buffer
->PopupDefaultAttrib
;
255 TextModeInfo
.IsCursorVisible
= Buffer
->CursorInfo
.bVisible
;
256 TextModeInfo
.CursorSize
= Buffer
->CursorInfo
.dwSize
;
259 else if (CreateScreenBufferRequest
->ScreenBufferType
== CONSOLE_GRAPHICS_BUFFER
)
261 /* Get information from the graphics buffer information structure */
262 if (!CsrValidateMessageBuffer(ApiMessage
,
263 (PVOID
*)&CreateScreenBufferRequest
->GraphicsBufferInfo
.lpBitMapInfo
,
264 CreateScreenBufferRequest
->GraphicsBufferInfo
.dwBitMapInfoLength
,
267 Status
= STATUS_INVALID_PARAMETER
;
271 ScreenBufferInfo
= &GraphicsInfo
;
273 /* Initialize shared variables */
274 // CreateScreenBufferRequest->GraphicsBufferInfo.hMutex
275 CreateScreenBufferRequest
->hMutex
= GraphicsInfo
.Info
.hMutex
= INVALID_HANDLE_VALUE
;
276 // CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap
277 CreateScreenBufferRequest
->lpBitMap
= GraphicsInfo
.Info
.lpBitMap
= NULL
;
279 /* A graphics screen buffer is never inheritable */
280 CreateScreenBufferRequest
->InheritHandle
= FALSE
;
283 Status
= ConDrvCreateScreenBuffer(&Buff
,
285 Process
->ProcessHandle
,
286 CreateScreenBufferRequest
->ScreenBufferType
,
288 if (!NT_SUCCESS(Status
)) goto Quit
;
290 /* Insert the new handle inside the process handles table */
291 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
293 Status
= ConSrvInsertObject(ProcessData
,
294 &CreateScreenBufferRequest
->OutputHandle
,
296 CreateScreenBufferRequest
->DesiredAccess
,
297 CreateScreenBufferRequest
->InheritHandle
,
298 CreateScreenBufferRequest
->ShareMode
);
300 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
302 if (!NT_SUCCESS(Status
)) goto Quit
;
304 if (CreateScreenBufferRequest
->ScreenBufferType
== CONSOLE_GRAPHICS_BUFFER
)
306 PGRAPHICS_SCREEN_BUFFER Buffer
= (PGRAPHICS_SCREEN_BUFFER
)Buff
;
308 * Initialize the graphics buffer information structure
309 * and give it back to the client.
311 // CreateScreenBufferRequest->GraphicsBufferInfo.hMutex
312 CreateScreenBufferRequest
->hMutex
= Buffer
->ClientMutex
;
313 // CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap
314 CreateScreenBufferRequest
->lpBitMap
= Buffer
->ClientBitMap
;
318 ConSrvReleaseConsole(Console
, TRUE
);
323 ConDrvSetConsoleActiveScreenBuffer(IN PCONSOLE Console
,
324 IN PCONSOLE_SCREEN_BUFFER Buffer
);
325 /* API_NUMBER: ConsolepSetActiveScreenBuffer */
326 CSR_API(SrvSetConsoleActiveScreenBuffer
)
329 PCONSOLE_SETACTIVESCREENBUFFER SetScreenBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetScreenBufferRequest
;
330 PCONSOLE_SCREEN_BUFFER Buffer
;
332 DPRINT("SrvSetConsoleActiveScreenBuffer\n");
334 Status
= ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
335 SetScreenBufferRequest
->OutputHandle
,
336 &Buffer
, GENERIC_WRITE
, TRUE
);
337 if (!NT_SUCCESS(Status
)) return Status
;
339 Status
= ConDrvSetConsoleActiveScreenBuffer(Buffer
->Header
.Console
,
342 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
347 /* CSR THREADS FOR WriteConsole ***********************************************/
350 DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage
,
351 IN PCSR_THREAD ClientThread
,
352 IN BOOLEAN CreateWaitBlock OPTIONAL
);
354 // Wait function CSR_WAIT_FUNCTION
357 WriteConsoleThread(IN PLIST_ENTRY WaitList
,
358 IN PCSR_THREAD WaitThread
,
359 IN PCSR_API_MESSAGE WaitApiMessage
,
360 IN PVOID WaitContext
,
361 IN PVOID WaitArgument1
,
362 IN PVOID WaitArgument2
,
367 DPRINT("WriteConsoleThread - WaitContext = 0x%p, WaitArgument1 = 0x%p, WaitArgument2 = 0x%p, WaitFlags = %lu\n", WaitContext
, WaitArgument1
, WaitArgument2
, WaitFlags
);
370 * If we are notified of the process termination via a call
371 * to CsrNotifyWaitBlock triggered by CsrDestroyProcess or
372 * CsrDestroyThread, just return.
374 if (WaitFlags
& CsrProcessTerminating
)
376 Status
= STATUS_THREAD_IS_TERMINATING
;
380 Status
= DoWriteConsole(WaitApiMessage
, WaitThread
, FALSE
);
383 if (Status
!= STATUS_PENDING
)
385 WaitApiMessage
->Status
= Status
;
388 return (Status
== STATUS_PENDING
? FALSE
: TRUE
);
392 ConDrvWriteConsole(IN PCONSOLE Console
,
393 IN PTEXTMODE_SCREEN_BUFFER ScreenBuffer
,
395 IN PVOID StringBuffer
,
396 IN ULONG NumCharsToWrite
,
397 OUT PULONG NumCharsWritten OPTIONAL
);
399 DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage
,
400 IN PCSR_THREAD ClientThread
,
401 IN BOOLEAN CreateWaitBlock OPTIONAL
)
404 PCONSOLE_WRITECONSOLE WriteConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteConsoleRequest
;
405 PTEXTMODE_SCREEN_BUFFER ScreenBuffer
;
408 ULONG NrCharactersWritten
= 0;
409 ULONG CharSize
= (WriteConsoleRequest
->Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
411 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(ClientThread
->Process
),
412 WriteConsoleRequest
->OutputHandle
,
413 &ScreenBuffer
, GENERIC_WRITE
, FALSE
);
414 if (!NT_SUCCESS(Status
)) return Status
;
417 * For optimization purposes, Windows (and hence ReactOS, too, for
418 * compatibility reasons) uses a static buffer if no more than eighty
419 * bytes are written. Otherwise a new buffer is used.
420 * The client-side expects that we know this behaviour.
422 if (WriteConsoleRequest
->UsingStaticBuffer
&&
423 WriteConsoleRequest
->NumBytes
<= sizeof(WriteConsoleRequest
->StaticBuffer
))
426 * Adjust the internal pointer, because its old value points to
427 * the static buffer in the original ApiMessage structure.
429 // WriteConsoleRequest->Buffer = WriteConsoleRequest->StaticBuffer;
430 Buffer
= WriteConsoleRequest
->StaticBuffer
;
434 Buffer
= WriteConsoleRequest
->Buffer
;
437 DPRINT("Calling ConDrvWriteConsole\n");
438 Status
= ConDrvWriteConsole(ScreenBuffer
->Header
.Console
,
440 WriteConsoleRequest
->Unicode
,
442 WriteConsoleRequest
->NumBytes
/ CharSize
, // NrCharactersToWrite
443 &NrCharactersWritten
);
444 DPRINT("ConDrvWriteConsole returned (%d ; Status = 0x%08x)\n",
445 NrCharactersWritten
, Status
);
447 if (Status
== STATUS_PENDING
)
451 PCONSRV_CONSOLE Console
= (PCONSRV_CONSOLE
)ScreenBuffer
->Header
.Console
;
453 if (!CsrCreateWait(&Console
->WriteWaitQueue
,
460 Status
= STATUS_NO_MEMORY
;
465 /* Wait until we un-pause the console */
466 // Status = STATUS_PENDING;
470 /* We read all what we wanted. Set the number of bytes written. */
471 WriteConsoleRequest
->NumBytes
= NrCharactersWritten
* CharSize
;
475 ConSrvReleaseScreenBuffer(ScreenBuffer
, FALSE
);
480 /* TEXT OUTPUT APIS ***********************************************************/
483 ConDrvReadConsoleOutput(IN PCONSOLE Console
,
484 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
486 OUT PCHAR_INFO CharInfo
/*Buffer*/,
487 IN OUT PSMALL_RECT ReadRegion
);
488 /* API_NUMBER: ConsolepReadConsoleOutput */
489 CSR_API(SrvReadConsoleOutput
)
492 PCONSOLE_READOUTPUT ReadOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ReadOutputRequest
;
493 PTEXTMODE_SCREEN_BUFFER Buffer
;
498 DPRINT("SrvReadConsoleOutput\n");
500 NumCells
= (ReadOutputRequest
->ReadRegion
.Right
- ReadOutputRequest
->ReadRegion
.Left
+ 1) *
501 (ReadOutputRequest
->ReadRegion
.Bottom
- ReadOutputRequest
->ReadRegion
.Top
+ 1);
504 * For optimization purposes, Windows (and hence ReactOS, too, for
505 * compatibility reasons) uses a static buffer if no more than one
506 * cell is read. Otherwise a new buffer is used.
507 * The client-side expects that we know this behaviour.
512 * Adjust the internal pointer, because its old value points to
513 * the static buffer in the original ApiMessage structure.
515 // ReadOutputRequest->CharInfo = &ReadOutputRequest->StaticBuffer;
516 CharInfo
= &ReadOutputRequest
->StaticBuffer
;
520 if (!CsrValidateMessageBuffer(ApiMessage
,
521 (PVOID
*)&ReadOutputRequest
->CharInfo
,
525 return STATUS_INVALID_PARAMETER
;
528 CharInfo
= ReadOutputRequest
->CharInfo
;
531 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
532 ReadOutputRequest
->OutputHandle
,
533 &Buffer
, GENERIC_READ
, TRUE
);
534 if (!NT_SUCCESS(Status
)) return Status
;
536 Status
= ConDrvReadConsoleOutput(Buffer
->Header
.Console
,
538 ReadOutputRequest
->Unicode
,
540 &ReadOutputRequest
->ReadRegion
);
542 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
547 ConDrvWriteConsoleOutput(IN PCONSOLE Console
,
548 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
550 IN PCHAR_INFO CharInfo
/*Buffer*/,
551 IN OUT PSMALL_RECT WriteRegion
);
552 /* API_NUMBER: ConsolepWriteConsoleOutput */
553 CSR_API(SrvWriteConsoleOutput
)
556 PCONSOLE_WRITEOUTPUT WriteOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteOutputRequest
;
557 PTEXTMODE_SCREEN_BUFFER Buffer
;
558 PCSR_PROCESS Process
= CsrGetClientThread()->Process
;
563 DPRINT("SrvWriteConsoleOutput\n");
565 NumCells
= (WriteOutputRequest
->WriteRegion
.Right
- WriteOutputRequest
->WriteRegion
.Left
+ 1) *
566 (WriteOutputRequest
->WriteRegion
.Bottom
- WriteOutputRequest
->WriteRegion
.Top
+ 1);
568 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(Process
),
569 WriteOutputRequest
->OutputHandle
,
570 &Buffer
, GENERIC_WRITE
, TRUE
);
571 if (!NT_SUCCESS(Status
)) return Status
;
574 * Validate the message buffer if we do not use a process' heap buffer
575 * (CsrAllocateCaptureBuffer succeeded because we haven't allocated
576 * a too large (>= 64 kB, size of the CSR heap) data buffer).
578 if (!WriteOutputRequest
->UseVirtualMemory
)
581 * For optimization purposes, Windows (and hence ReactOS, too, for
582 * compatibility reasons) uses a static buffer if no more than one
583 * cell is written. Otherwise a new buffer is used.
584 * The client-side expects that we know this behaviour.
589 * Adjust the internal pointer, because its old value points to
590 * the static buffer in the original ApiMessage structure.
592 // WriteOutputRequest->CharInfo = &WriteOutputRequest->StaticBuffer;
593 CharInfo
= &WriteOutputRequest
->StaticBuffer
;
597 if (!CsrValidateMessageBuffer(ApiMessage
,
598 (PVOID
*)&WriteOutputRequest
->CharInfo
,
602 Status
= STATUS_INVALID_PARAMETER
;
606 CharInfo
= WriteOutputRequest
->CharInfo
;
612 * This was not the case: we use a heap buffer. Retrieve its contents.
614 ULONG Size
= NumCells
* sizeof(CHAR_INFO
);
616 CharInfo
= ConsoleAllocHeap(HEAP_ZERO_MEMORY
, Size
);
617 if (CharInfo
== NULL
)
619 Status
= STATUS_NO_MEMORY
;
623 Status
= NtReadVirtualMemory(Process
->ProcessHandle
,
624 WriteOutputRequest
->CharInfo
,
628 if (!NT_SUCCESS(Status
))
630 ConsoleFreeHeap(CharInfo
);
631 // Status = STATUS_NO_MEMORY;
636 Status
= ConDrvWriteConsoleOutput(Buffer
->Header
.Console
,
638 WriteOutputRequest
->Unicode
,
640 &WriteOutputRequest
->WriteRegion
);
642 /* Free the temporary buffer if we used the process' heap buffer */
643 if (WriteOutputRequest
->UseVirtualMemory
&& CharInfo
)
644 ConsoleFreeHeap(CharInfo
);
647 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
651 /* API_NUMBER: ConsolepWriteConsole */
652 CSR_API(SrvWriteConsole
)
655 PCONSOLE_WRITECONSOLE WriteConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteConsoleRequest
;
657 DPRINT("SrvWriteConsole\n");
660 * For optimization purposes, Windows (and hence ReactOS, too, for
661 * compatibility reasons) uses a static buffer if no more than eighty
662 * bytes are written. Otherwise a new buffer is used.
663 * The client-side expects that we know this behaviour.
665 if (WriteConsoleRequest
->UsingStaticBuffer
&&
666 WriteConsoleRequest
->NumBytes
<= sizeof(WriteConsoleRequest
->StaticBuffer
))
669 * Adjust the internal pointer, because its old value points to
670 * the static buffer in the original ApiMessage structure.
672 // WriteConsoleRequest->Buffer = WriteConsoleRequest->StaticBuffer;
676 if (!CsrValidateMessageBuffer(ApiMessage
,
677 (PVOID
)&WriteConsoleRequest
->Buffer
,
678 WriteConsoleRequest
->NumBytes
,
681 return STATUS_INVALID_PARAMETER
;
685 Status
= DoWriteConsole(ApiMessage
, CsrGetClientThread(), TRUE
);
687 if (Status
== STATUS_PENDING
) *ReplyCode
= CsrReplyPending
;
693 ConDrvReadConsoleOutputString(IN PCONSOLE Console
,
694 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
695 IN CODE_TYPE CodeType
,
696 OUT PVOID StringBuffer
,
697 IN ULONG NumCodesToRead
,
699 // OUT PCOORD EndCoord,
700 OUT PULONG NumCodesRead OPTIONAL
);
701 /* API_NUMBER: ConsolepReadConsoleOutputString */
702 CSR_API(SrvReadConsoleOutputString
)
705 PCONSOLE_READOUTPUTCODE ReadOutputCodeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ReadOutputCodeRequest
;
706 PTEXTMODE_SCREEN_BUFFER Buffer
;
711 DPRINT("SrvReadConsoleOutputString\n");
713 switch (ReadOutputCodeRequest
->CodeType
)
716 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, AsciiChar
);
720 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, UnicodeChar
);
724 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, Attribute
);
728 return STATUS_INVALID_PARAMETER
;
732 * For optimization purposes, Windows (and hence ReactOS, too, for
733 * compatibility reasons) uses a static buffer if no more than eighty
734 * bytes are read. Otherwise a new buffer is used.
735 * The client-side expects that we know this behaviour.
737 if (ReadOutputCodeRequest
->NumCodes
* CodeSize
<= sizeof(ReadOutputCodeRequest
->CodeStaticBuffer
))
740 * Adjust the internal pointer, because its old value points to
741 * the static buffer in the original ApiMessage structure.
743 // ReadOutputCodeRequest->pCode = ReadOutputCodeRequest->CodeStaticBuffer;
744 pCode
= ReadOutputCodeRequest
->CodeStaticBuffer
;
748 if (!CsrValidateMessageBuffer(ApiMessage
,
749 (PVOID
*)&ReadOutputCodeRequest
->pCode
,
750 ReadOutputCodeRequest
->NumCodes
,
753 return STATUS_INVALID_PARAMETER
;
756 pCode
= ReadOutputCodeRequest
->pCode
;
759 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
760 ReadOutputCodeRequest
->OutputHandle
,
761 &Buffer
, GENERIC_READ
, TRUE
);
762 if (!NT_SUCCESS(Status
))
764 ReadOutputCodeRequest
->NumCodes
= 0;
768 Status
= ConDrvReadConsoleOutputString(Buffer
->Header
.Console
,
770 ReadOutputCodeRequest
->CodeType
,
772 ReadOutputCodeRequest
->NumCodes
,
773 &ReadOutputCodeRequest
->Coord
,
774 // &ReadOutputCodeRequest->EndCoord,
775 &ReadOutputCodeRequest
->NumCodes
);
777 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
782 ConDrvWriteConsoleOutputString(IN PCONSOLE Console
,
783 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
784 IN CODE_TYPE CodeType
,
785 IN PVOID StringBuffer
,
786 IN ULONG NumCodesToWrite
,
787 IN PCOORD WriteCoord
,
788 // OUT PCOORD EndCoord,
789 OUT PULONG NumCodesWritten OPTIONAL
);
790 /* API_NUMBER: ConsolepWriteConsoleOutputString */
791 CSR_API(SrvWriteConsoleOutputString
)
794 PCONSOLE_WRITEOUTPUTCODE WriteOutputCodeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteOutputCodeRequest
;
795 PTEXTMODE_SCREEN_BUFFER Buffer
;
800 DPRINT("SrvWriteConsoleOutputString\n");
802 switch (WriteOutputCodeRequest
->CodeType
)
805 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, AsciiChar
);
809 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, UnicodeChar
);
813 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, Attribute
);
817 return STATUS_INVALID_PARAMETER
;
821 * For optimization purposes, Windows (and hence ReactOS, too, for
822 * compatibility reasons) uses a static buffer if no more than eighty
823 * bytes are written. Otherwise a new buffer is used.
824 * The client-side expects that we know this behaviour.
826 if (WriteOutputCodeRequest
->NumCodes
* CodeSize
<= sizeof(WriteOutputCodeRequest
->CodeStaticBuffer
))
829 * Adjust the internal pointer, because its old value points to
830 * the static buffer in the original ApiMessage structure.
832 // WriteOutputCodeRequest->pCode = WriteOutputCodeRequest->CodeStaticBuffer;
833 pCode
= WriteOutputCodeRequest
->CodeStaticBuffer
;
837 if (!CsrValidateMessageBuffer(ApiMessage
,
838 (PVOID
*)&WriteOutputCodeRequest
->pCode
,
839 WriteOutputCodeRequest
->NumCodes
,
842 return STATUS_INVALID_PARAMETER
;
845 pCode
= WriteOutputCodeRequest
->pCode
;
848 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
849 WriteOutputCodeRequest
->OutputHandle
,
850 &Buffer
, GENERIC_WRITE
, TRUE
);
851 if (!NT_SUCCESS(Status
))
853 WriteOutputCodeRequest
->NumCodes
= 0;
857 Status
= ConDrvWriteConsoleOutputString(Buffer
->Header
.Console
,
859 WriteOutputCodeRequest
->CodeType
,
861 WriteOutputCodeRequest
->NumCodes
,
862 &WriteOutputCodeRequest
->Coord
,
863 // &WriteOutputCodeRequest->EndCoord,
864 &WriteOutputCodeRequest
->NumCodes
);
866 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
871 ConDrvFillConsoleOutput(IN PCONSOLE Console
,
872 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
873 IN CODE_TYPE CodeType
,
874 IN CODE_ELEMENT Code
,
875 IN ULONG NumCodesToWrite
,
876 IN PCOORD WriteCoord
,
877 OUT PULONG NumCodesWritten OPTIONAL
);
878 /* API_NUMBER: ConsolepFillConsoleOutput */
879 CSR_API(SrvFillConsoleOutput
)
882 PCONSOLE_FILLOUTPUTCODE FillOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.FillOutputRequest
;
883 PTEXTMODE_SCREEN_BUFFER Buffer
;
884 CODE_TYPE CodeType
= FillOutputRequest
->CodeType
;
886 DPRINT("SrvFillConsoleOutput\n");
888 if ( (CodeType
!= CODE_ASCII
) &&
889 (CodeType
!= CODE_UNICODE
) &&
890 (CodeType
!= CODE_ATTRIBUTE
) )
892 return STATUS_INVALID_PARAMETER
;
895 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
896 FillOutputRequest
->OutputHandle
,
897 &Buffer
, GENERIC_WRITE
, TRUE
);
898 if (!NT_SUCCESS(Status
))
900 FillOutputRequest
->NumCodes
= 0;
904 Status
= ConDrvFillConsoleOutput(Buffer
->Header
.Console
,
907 FillOutputRequest
->Code
,
908 FillOutputRequest
->NumCodes
,
909 &FillOutputRequest
->WriteCoord
,
910 &FillOutputRequest
->NumCodes
);
912 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
917 ConDrvGetConsoleScreenBufferInfo(IN PCONSOLE Console
,
918 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
919 OUT PCOORD ScreenBufferSize
,
920 OUT PCOORD CursorPosition
,
921 OUT PCOORD ViewOrigin
,
923 OUT PCOORD MaximumViewSize
,
924 OUT PWORD Attributes
);
925 /* API_NUMBER: ConsolepGetScreenBufferInfo */
926 CSR_API(SrvGetConsoleScreenBufferInfo
)
929 PCONSOLE_GETSCREENBUFFERINFO ScreenBufferInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ScreenBufferInfoRequest
;
930 PTEXTMODE_SCREEN_BUFFER Buffer
;
932 DPRINT("SrvGetConsoleScreenBufferInfo\n");
934 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
935 ScreenBufferInfoRequest
->OutputHandle
,
936 &Buffer
, GENERIC_READ
, TRUE
);
937 if (!NT_SUCCESS(Status
)) return Status
;
939 Status
= ConDrvGetConsoleScreenBufferInfo(Buffer
->Header
.Console
,
941 &ScreenBufferInfoRequest
->ScreenBufferSize
,
942 &ScreenBufferInfoRequest
->CursorPosition
,
943 &ScreenBufferInfoRequest
->ViewOrigin
,
944 &ScreenBufferInfoRequest
->ViewSize
,
945 &ScreenBufferInfoRequest
->MaximumViewSize
,
946 &ScreenBufferInfoRequest
->Attributes
);
948 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
953 ConDrvSetConsoleTextAttribute(IN PCONSOLE Console
,
954 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
956 /* API_NUMBER: ConsolepSetTextAttribute */
957 CSR_API(SrvSetConsoleTextAttribute
)
960 PCONSOLE_SETTEXTATTRIB SetTextAttribRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetTextAttribRequest
;
961 PTEXTMODE_SCREEN_BUFFER Buffer
;
963 DPRINT("SrvSetConsoleTextAttribute\n");
965 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
966 SetTextAttribRequest
->OutputHandle
,
967 &Buffer
, GENERIC_WRITE
, TRUE
);
968 if (!NT_SUCCESS(Status
)) return Status
;
970 Status
= ConDrvSetConsoleTextAttribute(Buffer
->Header
.Console
,
972 SetTextAttribRequest
->Attributes
);
974 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
979 ConDrvSetConsoleScreenBufferSize(IN PCONSOLE Console
,
980 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
982 /* API_NUMBER: ConsolepSetScreenBufferSize */
983 CSR_API(SrvSetConsoleScreenBufferSize
)
986 PCONSOLE_SETSCREENBUFFERSIZE SetScreenBufferSizeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetScreenBufferSizeRequest
;
987 PTEXTMODE_SCREEN_BUFFER Buffer
;
989 DPRINT("SrvSetConsoleScreenBufferSize\n");
991 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
992 SetScreenBufferSizeRequest
->OutputHandle
,
993 &Buffer
, GENERIC_WRITE
, TRUE
);
994 if (!NT_SUCCESS(Status
)) return Status
;
996 Status
= ConDrvSetConsoleScreenBufferSize(Buffer
->Header
.Console
,
998 &SetScreenBufferSizeRequest
->Size
);
1000 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
1005 ConDrvScrollConsoleScreenBuffer(IN PCONSOLE Console
,
1006 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
1008 IN PSMALL_RECT ScrollRectangle
,
1009 IN BOOLEAN UseClipRectangle
,
1010 IN PSMALL_RECT ClipRectangle OPTIONAL
,
1011 IN PCOORD DestinationOrigin
,
1012 IN CHAR_INFO FillChar
);
1013 /* API_NUMBER: ConsolepScrollScreenBuffer */
1014 CSR_API(SrvScrollConsoleScreenBuffer
)
1017 PCONSOLE_SCROLLSCREENBUFFER ScrollScreenBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ScrollScreenBufferRequest
;
1018 PTEXTMODE_SCREEN_BUFFER Buffer
;
1020 DPRINT("SrvScrollConsoleScreenBuffer\n");
1022 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
1023 ScrollScreenBufferRequest
->OutputHandle
,
1024 &Buffer
, GENERIC_WRITE
, TRUE
);
1025 if (!NT_SUCCESS(Status
)) return Status
;
1027 Status
= ConDrvScrollConsoleScreenBuffer(Buffer
->Header
.Console
,
1029 ScrollScreenBufferRequest
->Unicode
,
1030 &ScrollScreenBufferRequest
->ScrollRectangle
,
1031 ScrollScreenBufferRequest
->UseClipRectangle
,
1032 &ScrollScreenBufferRequest
->ClipRectangle
,
1033 &ScrollScreenBufferRequest
->DestinationOrigin
,
1034 ScrollScreenBufferRequest
->Fill
);
1036 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);
1041 ConDrvSetConsoleWindowInfo(IN PCONSOLE Console
,
1042 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
1043 IN BOOLEAN Absolute
,
1044 IN PSMALL_RECT WindowRect
);
1045 /* API_NUMBER: ConsolepSetWindowInfo */
1046 CSR_API(SrvSetConsoleWindowInfo
)
1049 PCONSOLE_SETWINDOWINFO SetWindowInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetWindowInfoRequest
;
1050 // PCONSOLE_SCREEN_BUFFER Buffer;
1051 PTEXTMODE_SCREEN_BUFFER Buffer
;
1053 DPRINT("SrvSetConsoleWindowInfo(0x%08x, %d, {L%d, T%d, R%d, B%d}) called\n",
1054 SetWindowInfoRequest
->OutputHandle
, SetWindowInfoRequest
->Absolute
,
1055 SetWindowInfoRequest
->WindowRect
.Left
,
1056 SetWindowInfoRequest
->WindowRect
.Top
,
1057 SetWindowInfoRequest
->WindowRect
.Right
,
1058 SetWindowInfoRequest
->WindowRect
.Bottom
);
1060 // ConSrvGetScreenBuffer
1061 Status
= ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
1062 SetWindowInfoRequest
->OutputHandle
,
1063 &Buffer
, GENERIC_READ
, TRUE
);
1064 if (!NT_SUCCESS(Status
)) return Status
;
1066 Status
= ConDrvSetConsoleWindowInfo(Buffer
->Header
.Console
,
1068 SetWindowInfoRequest
->Absolute
,
1069 &SetWindowInfoRequest
->WindowRect
);
1071 ConSrvReleaseScreenBuffer(Buffer
, TRUE
);