2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/consrv/conoutput.c
5 * PURPOSE: Console I/O functions
9 /* INCLUDES *******************************************************************/
18 /* GLOBALS ********************************************************************/
20 #define ConioInitRect(Rect, top, left, bottom, right) \
22 ((Rect)->Top) = top; \
23 ((Rect)->Left) = left; \
24 ((Rect)->Bottom) = bottom; \
25 ((Rect)->Right) = right; \
28 #define ConioIsRectEmpty(Rect) \
29 (((Rect)->Left > (Rect)->Right) || ((Rect)->Top > (Rect)->Bottom))
31 #define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
32 WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
34 #define ConsoleAnsiCharToUnicodeChar(Console, dWChar, sChar) \
35 MultiByteToWideChar((Console)->OutputCodePage, 0, (sChar), 1, (dWChar), 1)
38 /* PRIVATE FUNCTIONS **********************************************************/
41 ConioCoordToPointer(PCSRSS_SCREEN_BUFFER Buff
, ULONG X
, ULONG Y
)
43 return &Buff
->Buffer
[2 * (((Y
+ Buff
->VirtualY
) % Buff
->MaxY
) * Buff
->MaxX
+ X
)];
47 ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff
)
49 PBYTE Ptr
= ConioCoordToPointer(Buff
, 0, Buff
->CurrentY
);
52 for (Pos
= 0; Pos
< Buff
->MaxX
; Pos
++)
56 *Ptr
++ = Buff
->DefaultAttrib
;
61 CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console
,
62 PCSRSS_SCREEN_BUFFER Buffer
)
64 DPRINT("CsrInitConsoleScreenBuffer Size X %d Size Y %d\n", Buffer
->MaxX
, Buffer
->MaxY
);
66 Buffer
->Header
.Type
= CONIO_SCREEN_BUFFER_MAGIC
;
67 Buffer
->Header
.Console
= Console
;
68 Buffer
->Header
.HandleCount
= 0;
72 Buffer
->Buffer
= HeapAlloc(ConSrvHeap
, HEAP_ZERO_MEMORY
, Buffer
->MaxX
* Buffer
->MaxY
* 2);
73 if (NULL
== Buffer
->Buffer
)
75 return STATUS_INSUFFICIENT_RESOURCES
;
77 ConioInitScreenBuffer(Console
, Buffer
);
78 /* initialize buffer to be empty with default attributes */
79 for (Buffer
->CurrentY
= 0 ; Buffer
->CurrentY
< Buffer
->MaxY
; Buffer
->CurrentY
++)
81 ClearLineBuffer(Buffer
);
83 Buffer
->Mode
= ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
;
87 InsertHeadList(&Console
->BufferList
, &Buffer
->ListEntry
);
88 return STATUS_SUCCESS
;
92 ConioNextLine(PCSRSS_SCREEN_BUFFER Buff
, SMALL_RECT
*UpdateRect
, UINT
*ScrolledLines
)
94 /* If we hit bottom, slide the viewable screen */
95 if (++Buff
->CurrentY
== Buff
->MaxY
)
98 if (++Buff
->VirtualY
== Buff
->MaxY
)
103 ClearLineBuffer(Buff
);
104 if (UpdateRect
->Top
!= 0)
109 UpdateRect
->Left
= 0;
110 UpdateRect
->Right
= Buff
->MaxX
- 1;
111 UpdateRect
->Bottom
= Buff
->CurrentY
;
115 ConioWriteConsole(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
,
116 CHAR
*Buffer
, DWORD Length
, BOOL Attrib
)
120 SMALL_RECT UpdateRect
;
121 LONG CursorStartX
, CursorStartY
;
124 CursorStartX
= Buff
->CurrentX
;
125 CursorStartY
= Buff
->CurrentY
;
126 UpdateRect
.Left
= Buff
->MaxX
;
127 UpdateRect
.Top
= Buff
->CurrentY
;
128 UpdateRect
.Right
= -1;
129 UpdateRect
.Bottom
= Buff
->CurrentY
;
132 for (i
= 0; i
< Length
; i
++)
134 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
137 if (Buffer
[i
] == '\n')
140 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
144 else if (Buffer
[i
] == '\b')
146 /* Only handle BS if we're not on the first pos of the first line */
147 if (0 != Buff
->CurrentX
|| 0 != Buff
->CurrentY
)
149 if (0 == Buff
->CurrentX
)
151 /* slide virtual position up */
152 Buff
->CurrentX
= Buff
->MaxX
- 1;
154 UpdateRect
.Top
= min(UpdateRect
.Top
, (LONG
)Buff
->CurrentY
);
160 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
162 Ptr
[1] = Buff
->DefaultAttrib
;
163 UpdateRect
.Left
= min(UpdateRect
.Left
, (LONG
) Buff
->CurrentX
);
164 UpdateRect
.Right
= max(UpdateRect
.Right
, (LONG
) Buff
->CurrentX
);
169 else if (Buffer
[i
] == '\r')
172 UpdateRect
.Left
= min(UpdateRect
.Left
, (LONG
) Buff
->CurrentX
);
173 UpdateRect
.Right
= max(UpdateRect
.Right
, (LONG
) Buff
->CurrentX
);
177 else if (Buffer
[i
] == '\t')
181 UpdateRect
.Left
= min(UpdateRect
.Left
, (LONG
)Buff
->CurrentX
);
182 EndX
= (Buff
->CurrentX
+ 8) & ~7;
183 if (EndX
> Buff
->MaxX
)
187 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
188 while (Buff
->CurrentX
< EndX
)
191 *Ptr
++ = Buff
->DefaultAttrib
;
194 UpdateRect
.Right
= max(UpdateRect
.Right
, (LONG
) Buff
->CurrentX
- 1);
195 if (Buff
->CurrentX
== Buff
->MaxX
)
197 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
200 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
210 UpdateRect
.Left
= min(UpdateRect
.Left
, (LONG
)Buff
->CurrentX
);
211 UpdateRect
.Right
= max(UpdateRect
.Right
, (LONG
) Buff
->CurrentX
);
212 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
216 Ptr
[1] = Buff
->DefaultAttrib
;
219 if (Buff
->CurrentX
== Buff
->MaxX
)
221 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
224 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
228 Buff
->CurrentX
= CursorStartX
;
233 if (!ConioIsRectEmpty(&UpdateRect
) && Buff
== Console
->ActiveBuffer
)
235 ConioWriteStream(Console
, &UpdateRect
, CursorStartX
, CursorStartY
, ScrolledLines
,
239 return STATUS_SUCCESS
;
242 __inline BOOLEAN
ConioGetIntersection(
243 SMALL_RECT
*Intersection
,
247 if (ConioIsRectEmpty(Rect1
) ||
248 (ConioIsRectEmpty(Rect2
)) ||
249 (Rect1
->Top
> Rect2
->Bottom
) ||
250 (Rect1
->Left
> Rect2
->Right
) ||
251 (Rect1
->Bottom
< Rect2
->Top
) ||
252 (Rect1
->Right
< Rect2
->Left
))
254 /* The rectangles do not intersect */
255 ConioInitRect(Intersection
, 0, -1, 0, -1);
259 ConioInitRect(Intersection
,
260 max(Rect1
->Top
, Rect2
->Top
),
261 max(Rect1
->Left
, Rect2
->Left
),
262 min(Rect1
->Bottom
, Rect2
->Bottom
),
263 min(Rect1
->Right
, Rect2
->Right
));
268 __inline BOOLEAN
ConioGetUnion(
273 if (ConioIsRectEmpty(Rect1
))
275 if (ConioIsRectEmpty(Rect2
))
277 ConioInitRect(Union
, 0, -1, 0, -1);
285 else if (ConioIsRectEmpty(Rect2
))
292 min(Rect1
->Top
, Rect2
->Top
),
293 min(Rect1
->Left
, Rect2
->Left
),
294 max(Rect1
->Bottom
, Rect2
->Bottom
),
295 max(Rect1
->Right
, Rect2
->Right
));
302 * Move from one rectangle to another. We must be careful about the order that
303 * this is done, to avoid overwriting parts of the source before they are moved.
306 ConioMoveRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer
,
307 SMALL_RECT
*SrcRegion
,
308 SMALL_RECT
*DstRegion
,
309 SMALL_RECT
*ClipRegion
,
312 int Width
= ConioRectWidth(SrcRegion
);
313 int Height
= ConioRectHeight(SrcRegion
);
324 /* Moving down: work from bottom up */
325 SY
= SrcRegion
->Bottom
;
326 DY
= DstRegion
->Bottom
;
329 for (i
= 0; i
< Height
; i
++)
331 PWORD SRow
= (PWORD
)ConioCoordToPointer(ScreenBuffer
, 0, SY
);
332 PWORD DRow
= (PWORD
)ConioCoordToPointer(ScreenBuffer
, 0, DY
);
334 SX
= SrcRegion
->Left
;
335 DX
= DstRegion
->Left
;
339 /* Moving right: work from right to left */
340 SX
= SrcRegion
->Right
;
341 DX
= DstRegion
->Right
;
344 for (j
= 0; j
< Width
; j
++)
346 WORD Cell
= SRow
[SX
];
347 if (SX
>= ClipRegion
->Left
&& SX
<= ClipRegion
->Right
348 && SY
>= ClipRegion
->Top
&& SY
<= ClipRegion
->Bottom
)
352 if (DX
>= ClipRegion
->Left
&& DX
<= ClipRegion
->Right
353 && DY
>= ClipRegion
->Top
&& DY
<= ClipRegion
->Bottom
)
366 ConioDeleteScreenBuffer(PCSRSS_SCREEN_BUFFER Buffer
)
368 PCSRSS_CONSOLE Console
= Buffer
->Header
.Console
;
370 RemoveEntryList(&Buffer
->ListEntry
);
371 if (Buffer
== Console
->ActiveBuffer
)
373 /* Deleted active buffer; switch to most recently created */
374 Console
->ActiveBuffer
= NULL
;
375 if (!IsListEmpty(&Console
->BufferList
))
377 Console
->ActiveBuffer
= CONTAINING_RECORD(Console
->BufferList
.Flink
, CSRSS_SCREEN_BUFFER
, ListEntry
);
378 ConioDrawConsole(Console
);
382 HeapFree(ConSrvHeap
, 0, Buffer
->Buffer
);
383 HeapFree(ConSrvHeap
, 0, Buffer
);
387 ConioDrawConsole(PCSRSS_CONSOLE Console
)
391 ConioInitRect(&Region
, 0, 0, Console
->Size
.Y
- 1, Console
->Size
.X
- 1);
393 ConioDrawRegion(Console
, &Region
);
397 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff
, SMALL_RECT
*UpdateRect
, COORD
*Start
, UINT Length
)
399 if (Buff
->MaxX
<= Start
->X
+ Length
)
401 UpdateRect
->Left
= 0;
405 UpdateRect
->Left
= Start
->X
;
407 if (Buff
->MaxX
<= Start
->X
+ Length
)
409 UpdateRect
->Right
= Buff
->MaxX
- 1;
413 UpdateRect
->Right
= Start
->X
+ Length
- 1;
415 UpdateRect
->Top
= Start
->Y
;
416 UpdateRect
->Bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->MaxX
;
417 if (Buff
->MaxY
<= UpdateRect
->Bottom
)
419 UpdateRect
->Bottom
= Buff
->MaxY
- 1;
424 ConioEffectiveCursorSize(PCSRSS_CONSOLE Console
, DWORD Scale
)
426 DWORD Size
= (Console
->ActiveBuffer
->CursorInfo
.dwSize
* Scale
+ 99) / 100;
427 /* If line input in progress, perhaps adjust for insert toggle */
428 if (Console
->LineBuffer
&& !Console
->LineComplete
&& Console
->LineInsertToggle
)
429 return (Size
* 2 <= Scale
) ? (Size
* 2) : (Size
/ 2);
434 DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage
,
435 IN PCSR_THREAD ClientThread
,
436 IN BOOL CreateWaitBlock OPTIONAL
);
438 // Wait function CSR_WAIT_FUNCTION
440 WriteConsoleThread(IN PLIST_ENTRY WaitList
,
441 IN PCSR_THREAD WaitThread
,
442 IN PCSR_API_MESSAGE WaitApiMessage
,
443 IN PVOID WaitContext
,
444 IN PVOID WaitArgument1
,
445 IN PVOID WaitArgument2
,
450 Status
= DoWriteConsole(WaitApiMessage
,
454 if (Status
!= STATUS_PENDING
)
456 WaitApiMessage
->Status
= Status
;
459 return (Status
== STATUS_PENDING
? FALSE
: TRUE
);
463 DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage
,
464 IN PCSR_THREAD ClientThread
,
465 IN BOOL CreateWaitBlock OPTIONAL
)
467 NTSTATUS Status
= STATUS_SUCCESS
;
468 PCSRSS_WRITE_CONSOLE WriteConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteConsoleRequest
;
469 PCSRSS_CONSOLE Console
;
470 PCSRSS_SCREEN_BUFFER Buff
;
475 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(ClientThread
->Process
), WriteConsoleRequest
->ConsoleHandle
, &Buff
, GENERIC_WRITE
);
476 if (!NT_SUCCESS(Status
)) return Status
;
478 Console
= Buff
->Header
.Console
;
480 // if (Console->PauseFlags & (PAUSED_FROM_KEYBOARD | PAUSED_FROM_SCROLLBAR | PAUSED_FROM_SELECTION))
481 if (Console
->PauseFlags
&& Console
->UnpauseEvent
!= NULL
)
485 if (!CsrCreateWait(&Console
->WriteWaitQueue
,
492 ConioUnlockScreenBuffer(Buff
);
493 return STATUS_NO_MEMORY
;
497 /* Wait until we un-pause the console */
498 ConioUnlockScreenBuffer(Buff
);
499 return STATUS_PENDING
;
502 if(WriteConsoleRequest
->Unicode
)
504 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
505 (PWCHAR
)WriteConsoleRequest
->Buffer
,
506 WriteConsoleRequest
->NrCharactersToWrite
,
507 NULL
, 0, NULL
, NULL
);
508 Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
511 WideCharToMultiByte(Console
->OutputCodePage
, 0,
512 (PWCHAR
)WriteConsoleRequest
->Buffer
,
513 WriteConsoleRequest
->NrCharactersToWrite
,
514 Buffer
, Length
, NULL
, NULL
);
518 Status
= STATUS_NO_MEMORY
;
523 Buffer
= (PCHAR
)WriteConsoleRequest
->Buffer
;
528 if (NT_SUCCESS(Status
))
530 Status
= ConioWriteConsole(Console
, Buff
, Buffer
,
531 WriteConsoleRequest
->NrCharactersToWrite
, TRUE
);
532 if (NT_SUCCESS(Status
))
534 Written
= WriteConsoleRequest
->NrCharactersToWrite
;
537 if (WriteConsoleRequest
->Unicode
)
539 RtlFreeHeap(GetProcessHeap(), 0, Buffer
);
543 WriteConsoleRequest
->NrCharactersWritten
= Written
;
545 ConioUnlockScreenBuffer(Buff
);
550 /* PUBLIC APIS ****************************************************************/
552 CSR_API(SrvReadConsoleOutput
)
554 PCSRSS_READ_CONSOLE_OUTPUT ReadConsoleOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ReadConsoleOutputRequest
;
555 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
557 PCHAR_INFO CurCharInfo
;
558 PCSRSS_SCREEN_BUFFER Buff
;
563 SMALL_RECT ReadRegion
;
564 SMALL_RECT ScreenRect
;
570 DPRINT("SrvReadConsoleOutput\n");
572 CharInfo
= ReadConsoleOutputRequest
->CharInfo
;
573 ReadRegion
= ReadConsoleOutputRequest
->ReadRegion
;
574 BufferSize
= ReadConsoleOutputRequest
->BufferSize
;
575 BufferCoord
= ReadConsoleOutputRequest
->BufferCoord
;
577 if (!CsrValidateMessageBuffer(ApiMessage
,
578 (PVOID
*)&ReadConsoleOutputRequest
->CharInfo
,
579 BufferSize
.X
* BufferSize
.Y
,
582 return STATUS_INVALID_PARAMETER
;
585 Status
= ConioLockScreenBuffer(ProcessData
, ReadConsoleOutputRequest
->ConsoleHandle
, &Buff
, GENERIC_READ
);
586 if (!NT_SUCCESS(Status
)) return Status
;
588 /* FIXME: Is this correct? */
589 CodePage
= ProcessData
->Console
->OutputCodePage
;
591 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&ReadRegion
));
592 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&ReadRegion
));
593 ReadRegion
.Bottom
= ReadRegion
.Top
+ SizeY
;
594 ReadRegion
.Right
= ReadRegion
.Left
+ SizeX
;
596 ConioInitRect(&ScreenRect
, 0, 0, Buff
->MaxY
, Buff
->MaxX
);
597 if (!ConioGetIntersection(&ReadRegion
, &ScreenRect
, &ReadRegion
))
599 ConioUnlockScreenBuffer(Buff
);
600 return STATUS_SUCCESS
;
603 for (i
= 0, Y
= ReadRegion
.Top
; Y
< ReadRegion
.Bottom
; ++i
, ++Y
)
605 CurCharInfo
= CharInfo
+ (i
* BufferSize
.X
);
607 Ptr
= ConioCoordToPointer(Buff
, ReadRegion
.Left
, Y
);
608 for (X
= ReadRegion
.Left
; X
< ReadRegion
.Right
; ++X
)
610 if (ReadConsoleOutputRequest
->Unicode
)
612 // ConsoleAnsiCharToUnicodeChar(ProcessData->Console, (PCHAR)Ptr++, &CurCharInfo->Char.UnicodeChar);
613 MultiByteToWideChar(CodePage
, 0,
615 &CurCharInfo
->Char
.UnicodeChar
, 1);
619 CurCharInfo
->Char
.AsciiChar
= *Ptr
++;
621 CurCharInfo
->Attributes
= *Ptr
++;
626 ConioUnlockScreenBuffer(Buff
);
628 ReadConsoleOutputRequest
->ReadRegion
.Right
= ReadRegion
.Left
+ SizeX
- 1;
629 ReadConsoleOutputRequest
->ReadRegion
.Bottom
= ReadRegion
.Top
+ SizeY
- 1;
630 ReadConsoleOutputRequest
->ReadRegion
.Left
= ReadRegion
.Left
;
631 ReadConsoleOutputRequest
->ReadRegion
.Top
= ReadRegion
.Top
;
633 return STATUS_SUCCESS
;
636 CSR_API(SrvWriteConsole
)
639 PCSRSS_WRITE_CONSOLE WriteConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteConsoleRequest
;
641 DPRINT("SrvWriteConsole\n");
643 if (!CsrValidateMessageBuffer(ApiMessage
,
644 (PVOID
)&WriteConsoleRequest
->Buffer
,
645 WriteConsoleRequest
->BufferSize
,
648 return STATUS_INVALID_PARAMETER
;
651 Status
= DoWriteConsole(ApiMessage
,
652 CsrGetClientThread(),
655 if (Status
== STATUS_PENDING
)
656 *ReplyCode
= CsrReplyPending
;
661 CSR_API(SrvWriteConsoleOutput
)
663 PCSRSS_WRITE_CONSOLE_OUTPUT WriteConsoleOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteConsoleOutputRequest
;
664 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
665 SHORT i
, X
, Y
, SizeX
, SizeY
;
666 PCSRSS_CONSOLE Console
;
667 PCSRSS_SCREEN_BUFFER Buff
;
668 SMALL_RECT ScreenBuffer
;
669 CHAR_INFO
* CurCharInfo
;
670 SMALL_RECT WriteRegion
;
677 DPRINT("SrvWriteConsoleOutput\n");
679 BufferSize
= WriteConsoleOutputRequest
->BufferSize
;
680 BufferCoord
= WriteConsoleOutputRequest
->BufferCoord
;
681 CharInfo
= WriteConsoleOutputRequest
->CharInfo
;
683 if (!CsrValidateMessageBuffer(ApiMessage
,
684 (PVOID
*)&WriteConsoleOutputRequest
->CharInfo
,
685 BufferSize
.X
* BufferSize
.Y
,
688 return STATUS_INVALID_PARAMETER
;
691 Status
= ConioLockScreenBuffer(ProcessData
,
692 WriteConsoleOutputRequest
->ConsoleHandle
,
695 if (!NT_SUCCESS(Status
)) return Status
;
697 Console
= Buff
->Header
.Console
;
699 WriteRegion
= WriteConsoleOutputRequest
->WriteRegion
;
701 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&WriteRegion
));
702 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&WriteRegion
));
703 WriteRegion
.Bottom
= WriteRegion
.Top
+ SizeY
- 1;
704 WriteRegion
.Right
= WriteRegion
.Left
+ SizeX
- 1;
706 /* Make sure WriteRegion is inside the screen buffer */
707 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
708 if (!ConioGetIntersection(&WriteRegion
, &ScreenBuffer
, &WriteRegion
))
710 ConioUnlockScreenBuffer(Buff
);
712 /* It is okay to have a WriteRegion completely outside the screen buffer.
713 No data is written then. */
714 return STATUS_SUCCESS
;
717 for (i
= 0, Y
= WriteRegion
.Top
; Y
<= WriteRegion
.Bottom
; i
++, Y
++)
719 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
720 Ptr
= ConioCoordToPointer(Buff
, WriteRegion
.Left
, Y
);
721 for (X
= WriteRegion
.Left
; X
<= WriteRegion
.Right
; X
++)
724 if (WriteConsoleOutputRequest
->Unicode
)
726 ConsoleUnicodeCharToAnsiChar(Console
, &AsciiChar
, &CurCharInfo
->Char
.UnicodeChar
);
730 AsciiChar
= CurCharInfo
->Char
.AsciiChar
;
733 *Ptr
++ = CurCharInfo
->Attributes
;
738 ConioDrawRegion(Console
, &WriteRegion
);
740 ConioUnlockScreenBuffer(Buff
);
742 WriteConsoleOutputRequest
->WriteRegion
.Right
= WriteRegion
.Left
+ SizeX
- 1;
743 WriteConsoleOutputRequest
->WriteRegion
.Bottom
= WriteRegion
.Top
+ SizeY
- 1;
744 WriteConsoleOutputRequest
->WriteRegion
.Left
= WriteRegion
.Left
;
745 WriteConsoleOutputRequest
->WriteRegion
.Top
= WriteRegion
.Top
;
747 return STATUS_SUCCESS
;
750 CSR_API(SrvReadConsoleOutputString
)
753 PCSRSS_READ_CONSOLE_OUTPUT_CODE ReadConsoleOutputCodeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ReadConsoleOutputCodeRequest
;
754 PCSRSS_CONSOLE Console
;
755 PCSRSS_SCREEN_BUFFER Buff
;
763 DPRINT("SrvReadConsoleOutputString\n");
765 CodeType
= ReadConsoleOutputCodeRequest
->CodeType
;
769 CodeSize
= sizeof(CHAR
);
773 CodeSize
= sizeof(WCHAR
);
777 CodeSize
= sizeof(WORD
);
781 return STATUS_INVALID_PARAMETER
;
784 if (!CsrValidateMessageBuffer(ApiMessage
,
785 (PVOID
*)&ReadConsoleOutputCodeRequest
->pCode
.pCode
,
786 ReadConsoleOutputCodeRequest
->NumCodesToRead
,
789 return STATUS_INVALID_PARAMETER
;
792 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), ReadConsoleOutputCodeRequest
->ConsoleHandle
, &Buff
, GENERIC_READ
);
793 if (!NT_SUCCESS(Status
)) return Status
;
795 Console
= Buff
->Header
.Console
;
797 ReadBuffer
= ReadConsoleOutputCodeRequest
->pCode
.pCode
;
798 Xpos
= ReadConsoleOutputCodeRequest
->ReadCoord
.X
;
799 Ypos
= (ReadConsoleOutputCodeRequest
->ReadCoord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
802 * MSDN (ReadConsoleOutputAttribute and ReadConsoleOutputCharacter) :
804 * If the number of attributes (resp. characters) to be read from extends
805 * beyond the end of the specified screen buffer row, attributes (resp.
806 * characters) are read from the next row. If the number of attributes
807 * (resp. characters) to be read from extends beyond the end of the console
808 * screen buffer, attributes (resp. characters) up to the end of the console
809 * screen buffer are read.
811 * TODO: Do NOT loop up to NumCodesToRead, but stop before
812 * if we are going to overflow...
814 for (i
= 0; i
< ReadConsoleOutputCodeRequest
->NumCodesToRead
; ++i
)
816 Code
= Buff
->Buffer
[2 * (Xpos
+ Ypos
* Buff
->MaxX
) + (CodeType
== CODE_ATTRIBUTE
? 1 : 0)];
821 ConsoleAnsiCharToUnicodeChar(Console
, (PWCHAR
)ReadBuffer
, (PCHAR
)&Code
);
825 *(PCHAR
)ReadBuffer
= (CHAR
)Code
;
829 *(PWORD
)ReadBuffer
= (WORD
)Code
;
832 ReadBuffer
= (PVOID
)((ULONG_PTR
)ReadBuffer
+ CodeSize
);
836 if (Xpos
== Buff
->MaxX
)
841 if (Ypos
== Buff
->MaxY
)
851 *(PWCHAR
)ReadBuffer
= 0;
855 *(PCHAR
)ReadBuffer
= 0;
859 *(PWORD
)ReadBuffer
= 0;
863 ReadConsoleOutputCodeRequest
->EndCoord
.X
= Xpos
;
864 ReadConsoleOutputCodeRequest
->EndCoord
.Y
= (Ypos
- Buff
->VirtualY
+ Buff
->MaxY
) % Buff
->MaxY
;
866 ConioUnlockScreenBuffer(Buff
);
868 ReadConsoleOutputCodeRequest
->CodesRead
= (DWORD
)((ULONG_PTR
)ReadBuffer
- (ULONG_PTR
)ReadConsoleOutputCodeRequest
->pCode
.pCode
) / CodeSize
;
869 // <= ReadConsoleOutputCodeRequest->NumCodesToRead
871 return STATUS_SUCCESS
;
874 CSR_API(SrvWriteConsoleOutputString
)
877 PCSRSS_WRITE_CONSOLE_OUTPUT_CODE WriteConsoleOutputCodeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteConsoleOutputCodeRequest
;
878 PCSRSS_CONSOLE Console
;
879 PCSRSS_SCREEN_BUFFER Buff
;
881 PBYTE Buffer
; // PUCHAR
882 PCHAR String
, tmpString
= NULL
;
883 DWORD X
, Y
, Length
; // , Written = 0;
885 SMALL_RECT UpdateRect
;
887 DPRINT("SrvWriteConsoleOutputString\n");
889 CodeType
= WriteConsoleOutputCodeRequest
->CodeType
;
893 CodeSize
= sizeof(CHAR
);
897 CodeSize
= sizeof(WCHAR
);
901 CodeSize
= sizeof(WORD
);
905 return STATUS_INVALID_PARAMETER
;
908 if (!CsrValidateMessageBuffer(ApiMessage
,
909 (PVOID
*)&WriteConsoleOutputCodeRequest
->pCode
.pCode
,
910 WriteConsoleOutputCodeRequest
->Length
,
913 return STATUS_INVALID_PARAMETER
;
916 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
917 WriteConsoleOutputCodeRequest
->ConsoleHandle
,
920 if (!NT_SUCCESS(Status
)) return Status
;
922 Console
= Buff
->Header
.Console
;
928 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
929 (PWCHAR
)WriteConsoleOutputCodeRequest
->pCode
.UnicodeChar
,
930 WriteConsoleOutputCodeRequest
->Length
,
931 NULL
, 0, NULL
, NULL
);
932 tmpString
= String
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
935 WideCharToMultiByte(Console
->OutputCodePage
, 0,
936 (PWCHAR
)WriteConsoleOutputCodeRequest
->pCode
.UnicodeChar
,
937 WriteConsoleOutputCodeRequest
->Length
,
938 String
, Length
, NULL
, NULL
);
942 Status
= STATUS_NO_MEMORY
;
949 String
= (PCHAR
)WriteConsoleOutputCodeRequest
->pCode
.AsciiChar
;
954 // *(ReadBuffer++) = Code;
955 String
= (PCHAR
)WriteConsoleOutputCodeRequest
->pCode
.Attribute
;
959 if (String
&& NT_SUCCESS(Status
))
961 X
= WriteConsoleOutputCodeRequest
->Coord
.X
;
962 Y
= (WriteConsoleOutputCodeRequest
->Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
963 Length
= WriteConsoleOutputCodeRequest
->Length
;
964 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + (CodeType
== CODE_ATTRIBUTE
? 1 : 0)];
969 // ReadBuffer = (PVOID)((ULONG_PTR)ReadBuffer + CodeSize);
970 String
= (PCHAR
)((ULONG_PTR
)String
+ CodeSize
);
973 if (++X
== Buff
->MaxX
)
975 if (++Y
== Buff
->MaxY
)
978 Buffer
= Buff
->Buffer
+ (CodeType
== CODE_ATTRIBUTE
? 1 : 0);
984 if (Buff
== Console
->ActiveBuffer
)
986 ConioComputeUpdateRect(Buff
, &UpdateRect
, &WriteConsoleOutputCodeRequest
->Coord
,
987 WriteConsoleOutputCodeRequest
->Length
);
988 ConioDrawRegion(Console
, &UpdateRect
);
991 WriteConsoleOutputCodeRequest
->EndCoord
.X
= X
;
992 WriteConsoleOutputCodeRequest
->EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->VirtualY
) % Buff
->MaxY
;
997 RtlFreeHeap(GetProcessHeap(), 0, tmpString
);
1000 ConioUnlockScreenBuffer(Buff
);
1002 // WriteConsoleOutputCodeRequest->NrCharactersWritten = Written;
1006 CSR_API(SrvFillConsoleOutput
)
1009 PCSRSS_FILL_OUTPUT FillOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.FillOutputRequest
;
1010 PCSRSS_CONSOLE Console
;
1011 PCSRSS_SCREEN_BUFFER Buff
;
1012 DWORD X
, Y
, Length
; // , Written = 0;
1016 SMALL_RECT UpdateRect
;
1018 DPRINT("SrvFillConsoleOutput\n");
1020 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), FillOutputRequest
->ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1021 if (!NT_SUCCESS(Status
)) return Status
;
1023 Console
= Buff
->Header
.Console
;
1025 CodeType
= FillOutputRequest
->CodeType
;
1027 X
= FillOutputRequest
->Coord
.X
;
1028 Y
= (FillOutputRequest
->Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1029 Length
= FillOutputRequest
->Length
;
1030 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + (CodeType
== CODE_ATTRIBUTE
? 1 : 0)];
1035 Code
= (BYTE
)FillOutputRequest
->Code
.AsciiChar
;
1039 ConsoleUnicodeCharToAnsiChar(Console
, (PCHAR
)&Code
, &FillOutputRequest
->Code
.UnicodeChar
);
1042 case CODE_ATTRIBUTE
:
1043 Code
= (BYTE
)FillOutputRequest
->Code
.Attribute
;
1047 ConioUnlockScreenBuffer(Buff
);
1048 return STATUS_INVALID_PARAMETER
;
1056 if (++X
== Buff
->MaxX
)
1058 if (++Y
== Buff
->MaxY
)
1061 Buffer
= Buff
->Buffer
+ (CodeType
== CODE_ATTRIBUTE
? 1 : 0);
1067 if (Buff
== Console
->ActiveBuffer
)
1069 ConioComputeUpdateRect(Buff
, &UpdateRect
, &FillOutputRequest
->Coord
,
1070 FillOutputRequest
->Length
);
1071 ConioDrawRegion(Console
, &UpdateRect
);
1074 ConioUnlockScreenBuffer(Buff
);
1076 Length = FillOutputRequest->Length;
1077 FillOutputRequest->NrCharactersWritten = Length;
1079 return STATUS_SUCCESS
;
1082 CSR_API(SrvGetConsoleCursorInfo
)
1085 PCSRSS_CURSOR_INFO CursorInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CursorInfoRequest
;
1086 PCSRSS_SCREEN_BUFFER Buff
;
1088 DPRINT("SrvGetConsoleCursorInfo\n");
1090 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), CursorInfoRequest
->ConsoleHandle
, &Buff
, GENERIC_READ
);
1091 if (!NT_SUCCESS(Status
)) return Status
;
1093 CursorInfoRequest
->Info
.bVisible
= Buff
->CursorInfo
.bVisible
;
1094 CursorInfoRequest
->Info
.dwSize
= Buff
->CursorInfo
.dwSize
;
1095 ConioUnlockScreenBuffer(Buff
);
1097 return STATUS_SUCCESS
;
1100 CSR_API(SrvSetConsoleCursorInfo
)
1103 PCSRSS_CURSOR_INFO CursorInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CursorInfoRequest
;
1104 PCSRSS_CONSOLE Console
;
1105 PCSRSS_SCREEN_BUFFER Buff
;
1109 DPRINT("SrvSetConsoleCursorInfo\n");
1111 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), CursorInfoRequest
->ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1112 if (!NT_SUCCESS(Status
)) return Status
;
1114 Console
= Buff
->Header
.Console
;
1116 Size
= CursorInfoRequest
->Info
.dwSize
;
1117 Visible
= CursorInfoRequest
->Info
.bVisible
;
1127 if ( (Size
!= Buff
->CursorInfo
.dwSize
) ||
1128 (Visible
&& ! Buff
->CursorInfo
.bVisible
) ||
1129 (! Visible
&& Buff
->CursorInfo
.bVisible
) )
1131 Buff
->CursorInfo
.dwSize
= Size
;
1132 Buff
->CursorInfo
.bVisible
= Visible
;
1134 if (!ConioSetCursorInfo(Console
, Buff
))
1136 ConioUnlockScreenBuffer(Buff
);
1137 return STATUS_UNSUCCESSFUL
;
1141 ConioUnlockScreenBuffer(Buff
);
1143 return STATUS_SUCCESS
;
1146 CSR_API(SrvSetConsoleCursorPosition
)
1149 PCSRSS_SET_CURSOR_POSITION SetCursorPositionRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetCursorPositionRequest
;
1150 PCSRSS_CONSOLE Console
;
1151 PCSRSS_SCREEN_BUFFER Buff
;
1152 LONG OldCursorX
, OldCursorY
;
1153 LONG NewCursorX
, NewCursorY
;
1155 DPRINT("SrvSetConsoleCursorPosition\n");
1157 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), SetCursorPositionRequest
->ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1158 if (!NT_SUCCESS(Status
)) return Status
;
1160 Console
= Buff
->Header
.Console
;
1162 NewCursorX
= SetCursorPositionRequest
->Position
.X
;
1163 NewCursorY
= SetCursorPositionRequest
->Position
.Y
;
1164 if ( NewCursorX
< 0 || NewCursorX
>= Buff
->MaxX
||
1165 NewCursorY
< 0 || NewCursorY
>= Buff
->MaxY
)
1167 ConioUnlockScreenBuffer(Buff
);
1168 return STATUS_INVALID_PARAMETER
;
1170 OldCursorX
= Buff
->CurrentX
;
1171 OldCursorY
= Buff
->CurrentY
;
1172 Buff
->CurrentX
= NewCursorX
;
1173 Buff
->CurrentY
= NewCursorY
;
1174 if (Buff
== Console
->ActiveBuffer
)
1176 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
1178 ConioUnlockScreenBuffer(Buff
);
1179 return STATUS_UNSUCCESSFUL
;
1183 ConioUnlockScreenBuffer(Buff
);
1185 return STATUS_SUCCESS
;
1188 CSR_API(SrvSetConsoleTextAttribute
)
1191 PCSRSS_SET_ATTRIB SetAttribRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetAttribRequest
;
1192 PCSRSS_CONSOLE Console
;
1193 PCSRSS_SCREEN_BUFFER Buff
;
1195 DPRINT("SrvSetConsoleTextAttribute\n");
1197 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), SetAttribRequest
->ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1198 if (!NT_SUCCESS(Status
)) return Status
;
1200 Console
= Buff
->Header
.Console
;
1202 Buff
->DefaultAttrib
= SetAttribRequest
->Attrib
;
1203 if (Buff
== Console
->ActiveBuffer
)
1205 if (!ConioUpdateScreenInfo(Console
, Buff
))
1207 ConioUnlockScreenBuffer(Buff
);
1208 return STATUS_UNSUCCESSFUL
;
1212 ConioUnlockScreenBuffer(Buff
);
1214 return STATUS_SUCCESS
;
1217 CSR_API(SrvCreateConsoleScreenBuffer
)
1220 PCSRSS_CREATE_SCREEN_BUFFER CreateScreenBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CreateScreenBufferRequest
;
1221 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
1222 PCSRSS_CONSOLE Console
;
1223 PCSRSS_SCREEN_BUFFER Buff
;
1225 DPRINT("SrvCreateConsoleScreenBuffer\n");
1227 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
1229 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1230 if (!NT_SUCCESS(Status
))
1232 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
1236 Buff
= HeapAlloc(ConSrvHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
1239 if (Console
->ActiveBuffer
)
1241 Buff
->MaxX
= Console
->ActiveBuffer
->MaxX
;
1242 Buff
->MaxY
= Console
->ActiveBuffer
->MaxY
;
1243 Buff
->CursorInfo
.bVisible
= Console
->ActiveBuffer
->CursorInfo
.bVisible
;
1244 Buff
->CursorInfo
.dwSize
= Console
->ActiveBuffer
->CursorInfo
.dwSize
;
1248 Buff
->CursorInfo
.bVisible
= TRUE
;
1249 Buff
->CursorInfo
.dwSize
= CSR_DEFAULT_CURSOR_SIZE
;
1252 if (Buff
->MaxX
== 0)
1257 if (Buff
->MaxY
== 0)
1262 Status
= CsrInitConsoleScreenBuffer(Console
, Buff
);
1263 if (NT_SUCCESS(Status
))
1265 Status
= Win32CsrInsertObject(ProcessData
,
1266 &CreateScreenBufferRequest
->OutputHandle
,
1268 CreateScreenBufferRequest
->Access
,
1269 CreateScreenBufferRequest
->Inheritable
,
1270 CreateScreenBufferRequest
->ShareMode
);
1275 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1278 ConioUnlockConsole(Console
);
1280 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
1285 CSR_API(SrvGetConsoleScreenBufferInfo
)
1288 PCSRSS_SCREEN_BUFFER_INFO ScreenBufferInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ScreenBufferInfoRequest
;
1289 PCSRSS_CONSOLE Console
;
1290 PCSRSS_SCREEN_BUFFER Buff
;
1291 PCONSOLE_SCREEN_BUFFER_INFO pInfo
= &ScreenBufferInfoRequest
->Info
;
1293 DPRINT("SrvGetConsoleScreenBufferInfo\n");
1295 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), ScreenBufferInfoRequest
->ConsoleHandle
, &Buff
, GENERIC_READ
);
1296 if (!NT_SUCCESS(Status
)) return Status
;
1298 Console
= Buff
->Header
.Console
;
1300 pInfo
->dwSize
.X
= Buff
->MaxX
;
1301 pInfo
->dwSize
.Y
= Buff
->MaxY
;
1302 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
;
1303 pInfo
->dwCursorPosition
.Y
= Buff
->CurrentY
;
1304 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
1305 pInfo
->srWindow
.Left
= Buff
->ShowX
;
1306 pInfo
->srWindow
.Right
= Buff
->ShowX
+ Console
->Size
.X
- 1;
1307 pInfo
->srWindow
.Top
= Buff
->ShowY
;
1308 pInfo
->srWindow
.Bottom
= Buff
->ShowY
+ Console
->Size
.Y
- 1;
1309 pInfo
->dwMaximumWindowSize
.X
= Buff
->MaxX
;
1310 pInfo
->dwMaximumWindowSize
.Y
= Buff
->MaxY
;
1312 ConioUnlockScreenBuffer(Buff
);
1314 return STATUS_SUCCESS
;
1317 CSR_API(SrvSetConsoleActiveScreenBuffer
)
1320 PCSRSS_SET_SCREEN_BUFFER SetScreenBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetScreenBufferRequest
;
1321 PCSRSS_CONSOLE Console
;
1322 PCSRSS_SCREEN_BUFFER Buff
;
1324 DPRINT("SrvSetConsoleActiveScreenBuffer\n");
1326 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), SetScreenBufferRequest
->OutputHandle
, &Buff
, GENERIC_WRITE
);
1327 if (!NT_SUCCESS(Status
)) return Status
;
1329 Console
= Buff
->Header
.Console
;
1331 if (Buff
== Console
->ActiveBuffer
)
1333 ConioUnlockScreenBuffer(Buff
);
1334 return STATUS_SUCCESS
;
1337 /* If old buffer has no handles, it's now unreferenced */
1338 if (Console
->ActiveBuffer
->Header
.HandleCount
== 0)
1340 ConioDeleteScreenBuffer(Console
->ActiveBuffer
);
1343 /* Tie console to new buffer */
1344 Console
->ActiveBuffer
= Buff
;
1346 /* Redraw the console */
1347 ConioDrawConsole(Console
);
1349 ConioUnlockScreenBuffer(Buff
);
1351 return STATUS_SUCCESS
;
1354 CSR_API(SrvScrollConsoleScreenBuffer
)
1356 PCSRSS_SCROLL_CONSOLE_SCREEN_BUFFER ScrollConsoleScreenBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ScrollConsoleScreenBufferRequest
;
1357 PCSRSS_CONSOLE Console
;
1358 PCSRSS_SCREEN_BUFFER Buff
;
1359 SMALL_RECT ScreenBuffer
;
1360 SMALL_RECT SrcRegion
;
1361 SMALL_RECT DstRegion
;
1362 SMALL_RECT UpdateRegion
;
1363 SMALL_RECT ScrollRectangle
;
1364 SMALL_RECT ClipRectangle
;
1366 HANDLE ConsoleHandle
;
1367 BOOLEAN UseClipRectangle
;
1368 COORD DestinationOrigin
;
1372 DPRINT("SrvScrollConsoleScreenBuffer\n");
1374 ConsoleHandle
= ScrollConsoleScreenBufferRequest
->ConsoleHandle
;
1375 UseClipRectangle
= ScrollConsoleScreenBufferRequest
->UseClipRectangle
;
1376 DestinationOrigin
= ScrollConsoleScreenBufferRequest
->DestinationOrigin
;
1377 Fill
= ScrollConsoleScreenBufferRequest
->Fill
;
1379 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1380 if (!NT_SUCCESS(Status
)) return Status
;
1382 Console
= Buff
->Header
.Console
;
1384 ScrollRectangle
= ScrollConsoleScreenBufferRequest
->ScrollRectangle
;
1386 /* Make sure source rectangle is inside the screen buffer */
1387 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
1388 if (! ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, &ScrollRectangle
))
1390 ConioUnlockScreenBuffer(Buff
);
1391 return STATUS_SUCCESS
;
1394 /* If the source was clipped on the left or top, adjust the destination accordingly */
1395 if (ScrollRectangle
.Left
< 0)
1397 DestinationOrigin
.X
-= ScrollRectangle
.Left
;
1399 if (ScrollRectangle
.Top
< 0)
1401 DestinationOrigin
.Y
-= ScrollRectangle
.Top
;
1404 if (UseClipRectangle
)
1406 ClipRectangle
= ScrollConsoleScreenBufferRequest
->ClipRectangle
;
1407 if (!ConioGetIntersection(&ClipRectangle
, &ClipRectangle
, &ScreenBuffer
))
1409 ConioUnlockScreenBuffer(Buff
);
1410 return STATUS_SUCCESS
;
1415 ClipRectangle
= ScreenBuffer
;
1418 ConioInitRect(&DstRegion
,
1419 DestinationOrigin
.Y
,
1420 DestinationOrigin
.X
,
1421 DestinationOrigin
.Y
+ ConioRectHeight(&SrcRegion
) - 1,
1422 DestinationOrigin
.X
+ ConioRectWidth(&SrcRegion
) - 1);
1424 if (ScrollConsoleScreenBufferRequest
->Unicode
)
1425 ConsoleUnicodeCharToAnsiChar(Console
, &FillChar
, &Fill
.Char
.UnicodeChar
);
1427 FillChar
= Fill
.Char
.AsciiChar
;
1429 ConioMoveRegion(Buff
, &SrcRegion
, &DstRegion
, &ClipRectangle
, Fill
.Attributes
<< 8 | (BYTE
)FillChar
);
1431 if (Buff
== Console
->ActiveBuffer
)
1433 ConioGetUnion(&UpdateRegion
, &SrcRegion
, &DstRegion
);
1434 if (ConioGetIntersection(&UpdateRegion
, &UpdateRegion
, &ClipRectangle
))
1436 /* Draw update region */
1437 ConioDrawRegion(Console
, &UpdateRegion
);
1441 ConioUnlockScreenBuffer(Buff
);
1443 return STATUS_SUCCESS
;
1446 CSR_API(SrvSetConsoleScreenBufferSize
)
1449 PCSRSS_SET_SCREEN_BUFFER_SIZE SetScreenBufferSize
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetScreenBufferSize
;
1450 PCSRSS_SCREEN_BUFFER Buff
;
1452 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), SetScreenBufferSize
->OutputHandle
, &Buff
, GENERIC_WRITE
);
1453 if (!NT_SUCCESS(Status
)) return Status
;
1455 Status
= ConioResizeBuffer(Buff
->Header
.Console
, Buff
, SetScreenBufferSize
->Size
);
1456 ConioUnlockScreenBuffer(Buff
);