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 (Console
->UnpauseEvent
)
136 /** FIXME: Added in 47359 for pausing
137 Status = NtDuplicateObject(NtCurrentProcess(),
138 Console->UnpauseEvent,
139 Process->ProcessHandle,
140 &WriteConsoleRequest->UnpauseEvent,
142 ConioUnlockScreenBuffer(Buff);
143 return (NT_SUCCESS(Status) ? STATUS_PENDING : Status);
146 /* Wait on the console unpause event till it becomes signaled */
147 WaitForSingleObject(Console
->UnpauseEvent
, INFINITE
);
150 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
153 if (Buffer
[i
] == '\n')
156 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
160 else if (Buffer
[i
] == '\b')
162 /* Only handle BS if we're not on the first pos of the first line */
163 if (0 != Buff
->CurrentX
|| 0 != Buff
->CurrentY
)
165 if (0 == Buff
->CurrentX
)
167 /* slide virtual position up */
168 Buff
->CurrentX
= Buff
->MaxX
- 1;
170 UpdateRect
.Top
= min(UpdateRect
.Top
, (LONG
)Buff
->CurrentY
);
176 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
178 Ptr
[1] = Buff
->DefaultAttrib
;
179 UpdateRect
.Left
= min(UpdateRect
.Left
, (LONG
) Buff
->CurrentX
);
180 UpdateRect
.Right
= max(UpdateRect
.Right
, (LONG
) Buff
->CurrentX
);
185 else if (Buffer
[i
] == '\r')
188 UpdateRect
.Left
= min(UpdateRect
.Left
, (LONG
) Buff
->CurrentX
);
189 UpdateRect
.Right
= max(UpdateRect
.Right
, (LONG
) Buff
->CurrentX
);
193 else if (Buffer
[i
] == '\t')
197 UpdateRect
.Left
= min(UpdateRect
.Left
, (LONG
)Buff
->CurrentX
);
198 EndX
= (Buff
->CurrentX
+ 8) & ~7;
199 if (EndX
> Buff
->MaxX
)
203 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
204 while (Buff
->CurrentX
< EndX
)
207 *Ptr
++ = Buff
->DefaultAttrib
;
210 UpdateRect
.Right
= max(UpdateRect
.Right
, (LONG
) Buff
->CurrentX
- 1);
211 if (Buff
->CurrentX
== Buff
->MaxX
)
213 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
216 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
226 UpdateRect
.Left
= min(UpdateRect
.Left
, (LONG
)Buff
->CurrentX
);
227 UpdateRect
.Right
= max(UpdateRect
.Right
, (LONG
) Buff
->CurrentX
);
228 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
232 Ptr
[1] = Buff
->DefaultAttrib
;
235 if (Buff
->CurrentX
== Buff
->MaxX
)
237 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
240 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
244 Buff
->CurrentX
= CursorStartX
;
249 if (!ConioIsRectEmpty(&UpdateRect
) && Buff
== Console
->ActiveBuffer
)
251 ConioWriteStream(Console
, &UpdateRect
, CursorStartX
, CursorStartY
, ScrolledLines
,
255 return STATUS_SUCCESS
;
258 __inline BOOLEAN
ConioGetIntersection(
259 SMALL_RECT
*Intersection
,
263 if (ConioIsRectEmpty(Rect1
) ||
264 (ConioIsRectEmpty(Rect2
)) ||
265 (Rect1
->Top
> Rect2
->Bottom
) ||
266 (Rect1
->Left
> Rect2
->Right
) ||
267 (Rect1
->Bottom
< Rect2
->Top
) ||
268 (Rect1
->Right
< Rect2
->Left
))
270 /* The rectangles do not intersect */
271 ConioInitRect(Intersection
, 0, -1, 0, -1);
275 ConioInitRect(Intersection
,
276 max(Rect1
->Top
, Rect2
->Top
),
277 max(Rect1
->Left
, Rect2
->Left
),
278 min(Rect1
->Bottom
, Rect2
->Bottom
),
279 min(Rect1
->Right
, Rect2
->Right
));
284 __inline BOOLEAN
ConioGetUnion(
289 if (ConioIsRectEmpty(Rect1
))
291 if (ConioIsRectEmpty(Rect2
))
293 ConioInitRect(Union
, 0, -1, 0, -1);
301 else if (ConioIsRectEmpty(Rect2
))
308 min(Rect1
->Top
, Rect2
->Top
),
309 min(Rect1
->Left
, Rect2
->Left
),
310 max(Rect1
->Bottom
, Rect2
->Bottom
),
311 max(Rect1
->Right
, Rect2
->Right
));
318 * Move from one rectangle to another. We must be careful about the order that
319 * this is done, to avoid overwriting parts of the source before they are moved.
322 ConioMoveRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer
,
323 SMALL_RECT
*SrcRegion
,
324 SMALL_RECT
*DstRegion
,
325 SMALL_RECT
*ClipRegion
,
328 int Width
= ConioRectWidth(SrcRegion
);
329 int Height
= ConioRectHeight(SrcRegion
);
340 /* Moving down: work from bottom up */
341 SY
= SrcRegion
->Bottom
;
342 DY
= DstRegion
->Bottom
;
345 for (i
= 0; i
< Height
; i
++)
347 PWORD SRow
= (PWORD
)ConioCoordToPointer(ScreenBuffer
, 0, SY
);
348 PWORD DRow
= (PWORD
)ConioCoordToPointer(ScreenBuffer
, 0, DY
);
350 SX
= SrcRegion
->Left
;
351 DX
= DstRegion
->Left
;
355 /* Moving right: work from right to left */
356 SX
= SrcRegion
->Right
;
357 DX
= DstRegion
->Right
;
360 for (j
= 0; j
< Width
; j
++)
362 WORD Cell
= SRow
[SX
];
363 if (SX
>= ClipRegion
->Left
&& SX
<= ClipRegion
->Right
364 && SY
>= ClipRegion
->Top
&& SY
<= ClipRegion
->Bottom
)
368 if (DX
>= ClipRegion
->Left
&& DX
<= ClipRegion
->Right
369 && DY
>= ClipRegion
->Top
&& DY
<= ClipRegion
->Bottom
)
382 ConioDeleteScreenBuffer(PCSRSS_SCREEN_BUFFER Buffer
)
384 PCSRSS_CONSOLE Console
= Buffer
->Header
.Console
;
386 RemoveEntryList(&Buffer
->ListEntry
);
387 if (Buffer
== Console
->ActiveBuffer
)
389 /* Deleted active buffer; switch to most recently created */
390 Console
->ActiveBuffer
= NULL
;
391 if (!IsListEmpty(&Console
->BufferList
))
393 Console
->ActiveBuffer
= CONTAINING_RECORD(Console
->BufferList
.Flink
, CSRSS_SCREEN_BUFFER
, ListEntry
);
394 ConioDrawConsole(Console
);
398 HeapFree(ConSrvHeap
, 0, Buffer
->Buffer
);
399 HeapFree(ConSrvHeap
, 0, Buffer
);
403 ConioDrawConsole(PCSRSS_CONSOLE Console
)
407 ConioInitRect(&Region
, 0, 0, Console
->Size
.Y
- 1, Console
->Size
.X
- 1);
409 ConioDrawRegion(Console
, &Region
);
413 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff
, SMALL_RECT
*UpdateRect
, COORD
*Start
, UINT Length
)
415 if (Buff
->MaxX
<= Start
->X
+ Length
)
417 UpdateRect
->Left
= 0;
421 UpdateRect
->Left
= Start
->X
;
423 if (Buff
->MaxX
<= Start
->X
+ Length
)
425 UpdateRect
->Right
= Buff
->MaxX
- 1;
429 UpdateRect
->Right
= Start
->X
+ Length
- 1;
431 UpdateRect
->Top
= Start
->Y
;
432 UpdateRect
->Bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->MaxX
;
433 if (Buff
->MaxY
<= UpdateRect
->Bottom
)
435 UpdateRect
->Bottom
= Buff
->MaxY
- 1;
440 ConioEffectiveCursorSize(PCSRSS_CONSOLE Console
, DWORD Scale
)
442 DWORD Size
= (Console
->ActiveBuffer
->CursorInfo
.dwSize
* Scale
+ 99) / 100;
443 /* If line input in progress, perhaps adjust for insert toggle */
444 if (Console
->LineBuffer
&& !Console
->LineComplete
&& Console
->LineInsertToggle
)
445 return (Size
* 2 <= Scale
) ? (Size
* 2) : (Size
/ 2);
450 /* PUBLIC APIS ****************************************************************/
452 CSR_API(SrvReadConsoleOutput
)
454 PCSRSS_READ_CONSOLE_OUTPUT ReadConsoleOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ReadConsoleOutputRequest
;
455 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
457 PCHAR_INFO CurCharInfo
;
458 PCSRSS_SCREEN_BUFFER Buff
;
463 SMALL_RECT ReadRegion
;
464 SMALL_RECT ScreenRect
;
470 DPRINT("SrvReadConsoleOutput\n");
472 CharInfo
= ReadConsoleOutputRequest
->CharInfo
;
473 ReadRegion
= ReadConsoleOutputRequest
->ReadRegion
;
474 BufferSize
= ReadConsoleOutputRequest
->BufferSize
;
475 BufferCoord
= ReadConsoleOutputRequest
->BufferCoord
;
477 if (!CsrValidateMessageBuffer(ApiMessage
,
478 (PVOID
*)&ReadConsoleOutputRequest
->CharInfo
,
479 BufferSize
.X
* BufferSize
.Y
,
482 return STATUS_INVALID_PARAMETER
;
485 Status
= ConioLockScreenBuffer(ProcessData
, ReadConsoleOutputRequest
->ConsoleHandle
, &Buff
, GENERIC_READ
);
486 if (!NT_SUCCESS(Status
)) return Status
;
489 if (!Win32CsrValidateBuffer(ProcessData->Process, CharInfo,
490 BufferSize.X * BufferSize.Y, sizeof(CHAR_INFO)))
492 ConioUnlockScreenBuffer(Buff);
493 return STATUS_ACCESS_VIOLATION;
497 /* FIXME: Is this correct? */
498 CodePage
= ProcessData
->Console
->OutputCodePage
;
500 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&ReadRegion
));
501 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&ReadRegion
));
502 ReadRegion
.Bottom
= ReadRegion
.Top
+ SizeY
;
503 ReadRegion
.Right
= ReadRegion
.Left
+ SizeX
;
505 ConioInitRect(&ScreenRect
, 0, 0, Buff
->MaxY
, Buff
->MaxX
);
506 if (!ConioGetIntersection(&ReadRegion
, &ScreenRect
, &ReadRegion
))
508 ConioUnlockScreenBuffer(Buff
);
509 return STATUS_SUCCESS
;
512 for (i
= 0, Y
= ReadRegion
.Top
; Y
< ReadRegion
.Bottom
; ++i
, ++Y
)
514 CurCharInfo
= CharInfo
+ (i
* BufferSize
.X
);
516 Ptr
= ConioCoordToPointer(Buff
, ReadRegion
.Left
, Y
);
517 for (X
= ReadRegion
.Left
; X
< ReadRegion
.Right
; ++X
)
519 if (ReadConsoleOutputRequest
->Unicode
)
521 // ConsoleAnsiCharToUnicodeChar(ProcessData->Console, (PCHAR)Ptr++, &CurCharInfo->Char.UnicodeChar);
522 MultiByteToWideChar(CodePage
, 0,
524 &CurCharInfo
->Char
.UnicodeChar
, 1);
528 CurCharInfo
->Char
.AsciiChar
= *Ptr
++;
530 CurCharInfo
->Attributes
= *Ptr
++;
535 ConioUnlockScreenBuffer(Buff
);
537 ReadConsoleOutputRequest
->ReadRegion
.Right
= ReadRegion
.Left
+ SizeX
- 1;
538 ReadConsoleOutputRequest
->ReadRegion
.Bottom
= ReadRegion
.Top
+ SizeY
- 1;
539 ReadConsoleOutputRequest
->ReadRegion
.Left
= ReadRegion
.Left
;
540 ReadConsoleOutputRequest
->ReadRegion
.Top
= ReadRegion
.Top
;
542 return STATUS_SUCCESS
;
545 CSR_API(SrvWriteConsole
)
548 PCSRSS_WRITE_CONSOLE WriteConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteConsoleRequest
;
550 PCSRSS_SCREEN_BUFFER Buff
;
551 // PCSR_PROCESS Process = CsrGetClientThread()->Process;
552 PCSRSS_CONSOLE Console
;
555 // ULONG CharSize = (WriteConsoleRequest->Unicode ? sizeof(WCHAR) : sizeof(CHAR));
557 DPRINT("SrvWriteConsole\n");
559 if (!CsrValidateMessageBuffer(ApiMessage
,
560 (PVOID
)&WriteConsoleRequest
->Buffer
,
561 WriteConsoleRequest
->BufferSize
,
564 return STATUS_INVALID_PARAMETER
;
567 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), WriteConsoleRequest
->ConsoleHandle
, &Buff
, GENERIC_WRITE
);
568 if (!NT_SUCCESS(Status
)) return Status
;
570 Console
= Buff
->Header
.Console
;
572 /** FIXME: Added in 47359 for pausing
573 if (Console->UnpauseEvent)
575 Status = NtDuplicateObject(NtCurrentProcess(),
576 Console->UnpauseEvent,
577 Process->ProcessHandle,
578 &WriteConsoleRequest->UnpauseEvent,
580 ConioUnlockScreenBuffer(Buff);
581 return (NT_SUCCESS(Status) ? STATUS_PENDING : Status);
585 if(WriteConsoleRequest
->Unicode
)
587 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
588 (PWCHAR
)WriteConsoleRequest
->Buffer
,
589 WriteConsoleRequest
->NrCharactersToWrite
,
590 NULL
, 0, NULL
, NULL
);
591 Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
594 WideCharToMultiByte(Console
->OutputCodePage
, 0,
595 (PWCHAR
)WriteConsoleRequest
->Buffer
,
596 WriteConsoleRequest
->NrCharactersToWrite
,
597 Buffer
, Length
, NULL
, NULL
);
601 Status
= STATUS_NO_MEMORY
;
606 Buffer
= (PCHAR
)WriteConsoleRequest
->Buffer
;
611 if (NT_SUCCESS(Status
))
613 Status
= ConioWriteConsole(Console
, Buff
, Buffer
,
614 WriteConsoleRequest
->NrCharactersToWrite
, TRUE
);
615 if (NT_SUCCESS(Status
))
617 Written
= WriteConsoleRequest
->NrCharactersToWrite
;
620 if (WriteConsoleRequest
->Unicode
)
622 RtlFreeHeap(GetProcessHeap(), 0, Buffer
);
626 ConioUnlockScreenBuffer(Buff
);
628 WriteConsoleRequest
->NrCharactersWritten
= Written
;
633 CSR_API(SrvWriteConsoleOutput
)
635 PCSRSS_WRITE_CONSOLE_OUTPUT WriteConsoleOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteConsoleOutputRequest
;
636 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
637 SHORT i
, X
, Y
, SizeX
, SizeY
;
638 PCSRSS_CONSOLE Console
;
639 PCSRSS_SCREEN_BUFFER Buff
;
640 SMALL_RECT ScreenBuffer
;
641 CHAR_INFO
* CurCharInfo
;
642 SMALL_RECT WriteRegion
;
649 DPRINT("SrvWriteConsoleOutput\n");
651 BufferSize
= WriteConsoleOutputRequest
->BufferSize
;
652 BufferCoord
= WriteConsoleOutputRequest
->BufferCoord
;
653 CharInfo
= WriteConsoleOutputRequest
->CharInfo
;
655 if (!CsrValidateMessageBuffer(ApiMessage
,
656 (PVOID
*)&WriteConsoleOutputRequest
->CharInfo
,
657 BufferSize
.X
* BufferSize
.Y
,
660 return STATUS_INVALID_PARAMETER
;
663 Status
= ConioLockScreenBuffer(ProcessData
,
664 WriteConsoleOutputRequest
->ConsoleHandle
,
667 if (!NT_SUCCESS(Status
)) return Status
;
669 Console
= Buff
->Header
.Console
;
672 if (!Win32CsrValidateBuffer(ProcessData->Process, CharInfo,
673 BufferSize.X * BufferSize.Y, sizeof(CHAR_INFO)))
675 ConioUnlockScreenBuffer(Buff);
676 return STATUS_ACCESS_VIOLATION;
680 WriteRegion
= WriteConsoleOutputRequest
->WriteRegion
;
682 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&WriteRegion
));
683 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&WriteRegion
));
684 WriteRegion
.Bottom
= WriteRegion
.Top
+ SizeY
- 1;
685 WriteRegion
.Right
= WriteRegion
.Left
+ SizeX
- 1;
687 /* Make sure WriteRegion is inside the screen buffer */
688 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
689 if (!ConioGetIntersection(&WriteRegion
, &ScreenBuffer
, &WriteRegion
))
691 ConioUnlockScreenBuffer(Buff
);
693 /* It is okay to have a WriteRegion completely outside the screen buffer.
694 No data is written then. */
695 return STATUS_SUCCESS
;
698 for (i
= 0, Y
= WriteRegion
.Top
; Y
<= WriteRegion
.Bottom
; i
++, Y
++)
700 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
701 Ptr
= ConioCoordToPointer(Buff
, WriteRegion
.Left
, Y
);
702 for (X
= WriteRegion
.Left
; X
<= WriteRegion
.Right
; X
++)
705 if (WriteConsoleOutputRequest
->Unicode
)
707 ConsoleUnicodeCharToAnsiChar(Console
, &AsciiChar
, &CurCharInfo
->Char
.UnicodeChar
);
711 AsciiChar
= CurCharInfo
->Char
.AsciiChar
;
714 *Ptr
++ = CurCharInfo
->Attributes
;
719 ConioDrawRegion(Console
, &WriteRegion
);
721 ConioUnlockScreenBuffer(Buff
);
723 WriteConsoleOutputRequest
->WriteRegion
.Right
= WriteRegion
.Left
+ SizeX
- 1;
724 WriteConsoleOutputRequest
->WriteRegion
.Bottom
= WriteRegion
.Top
+ SizeY
- 1;
725 WriteConsoleOutputRequest
->WriteRegion
.Left
= WriteRegion
.Left
;
726 WriteConsoleOutputRequest
->WriteRegion
.Top
= WriteRegion
.Top
;
728 return STATUS_SUCCESS
;
731 CSR_API(SrvReadConsoleOutputString
)
734 PCSRSS_READ_CONSOLE_OUTPUT_CODE ReadConsoleOutputCodeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ReadConsoleOutputCodeRequest
;
735 PCSRSS_CONSOLE Console
;
736 PCSRSS_SCREEN_BUFFER Buff
;
744 DPRINT("SrvReadConsoleOutputString\n");
746 CodeType
= ReadConsoleOutputCodeRequest
->CodeType
;
750 CodeSize
= sizeof(CHAR
);
754 CodeSize
= sizeof(WCHAR
);
758 CodeSize
= sizeof(WORD
);
762 return STATUS_INVALID_PARAMETER
;
765 if (!CsrValidateMessageBuffer(ApiMessage
,
766 (PVOID
*)&ReadConsoleOutputCodeRequest
->pCode
.pCode
,
767 ReadConsoleOutputCodeRequest
->NumCodesToRead
,
770 return STATUS_INVALID_PARAMETER
;
773 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), ReadConsoleOutputCodeRequest
->ConsoleHandle
, &Buff
, GENERIC_READ
);
774 if (!NT_SUCCESS(Status
)) return Status
;
776 Console
= Buff
->Header
.Console
;
778 ReadBuffer
= ReadConsoleOutputCodeRequest
->pCode
.pCode
;
779 Xpos
= ReadConsoleOutputCodeRequest
->ReadCoord
.X
;
780 Ypos
= (ReadConsoleOutputCodeRequest
->ReadCoord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
783 * MSDN (ReadConsoleOutputAttribute and ReadConsoleOutputCharacter) :
785 * If the number of attributes (resp. characters) to be read from extends
786 * beyond the end of the specified screen buffer row, attributes (resp.
787 * characters) are read from the next row. If the number of attributes
788 * (resp. characters) to be read from extends beyond the end of the console
789 * screen buffer, attributes (resp. characters) up to the end of the console
790 * screen buffer are read.
792 * TODO: Do NOT loop up to NumCodesToRead, but stop before
793 * if we are going to overflow...
795 for (i
= 0; i
< ReadConsoleOutputCodeRequest
->NumCodesToRead
; ++i
)
797 Code
= Buff
->Buffer
[2 * (Xpos
+ Ypos
* Buff
->MaxX
) + (CodeType
== CODE_ATTRIBUTE
? 1 : 0)];
802 ConsoleAnsiCharToUnicodeChar(Console
, (PWCHAR
)ReadBuffer
, (PCHAR
)&Code
);
806 *(PCHAR
)ReadBuffer
= (CHAR
)Code
;
810 *(PWORD
)ReadBuffer
= (WORD
)Code
;
813 ReadBuffer
= (PVOID
)((ULONG_PTR
)ReadBuffer
+ CodeSize
);
817 if (Xpos
== Buff
->MaxX
)
822 if (Ypos
== Buff
->MaxY
)
832 *(PWCHAR
)ReadBuffer
= 0;
836 *(PCHAR
)ReadBuffer
= 0;
840 *(PWORD
)ReadBuffer
= 0;
844 ReadConsoleOutputCodeRequest
->EndCoord
.X
= Xpos
;
845 ReadConsoleOutputCodeRequest
->EndCoord
.Y
= (Ypos
- Buff
->VirtualY
+ Buff
->MaxY
) % Buff
->MaxY
;
847 ConioUnlockScreenBuffer(Buff
);
849 ReadConsoleOutputCodeRequest
->CodesRead
= (DWORD
)((ULONG_PTR
)ReadBuffer
- (ULONG_PTR
)ReadConsoleOutputCodeRequest
->pCode
.pCode
) / CodeSize
;
850 // <= ReadConsoleOutputCodeRequest->NumCodesToRead
852 return STATUS_SUCCESS
;
855 CSR_API(SrvWriteConsoleOutputString
)
858 PCSRSS_WRITE_CONSOLE_OUTPUT_CODE WriteConsoleOutputCodeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteConsoleOutputCodeRequest
;
859 PCSRSS_CONSOLE Console
;
860 PCSRSS_SCREEN_BUFFER Buff
;
862 PBYTE Buffer
; // PUCHAR
863 PCHAR String
, tmpString
= NULL
;
864 DWORD X
, Y
, Length
; // , Written = 0;
866 SMALL_RECT UpdateRect
;
868 DPRINT("SrvWriteConsoleOutputString\n");
870 CodeType
= WriteConsoleOutputCodeRequest
->CodeType
;
874 CodeSize
= sizeof(CHAR
);
878 CodeSize
= sizeof(WCHAR
);
882 CodeSize
= sizeof(WORD
);
886 return STATUS_INVALID_PARAMETER
;
889 if (!CsrValidateMessageBuffer(ApiMessage
,
890 (PVOID
*)&WriteConsoleOutputCodeRequest
->pCode
.pCode
,
891 WriteConsoleOutputCodeRequest
->Length
,
894 return STATUS_INVALID_PARAMETER
;
897 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
898 WriteConsoleOutputCodeRequest
->ConsoleHandle
,
901 if (!NT_SUCCESS(Status
)) return Status
;
903 Console
= Buff
->Header
.Console
;
909 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
910 (PWCHAR
)WriteConsoleOutputCodeRequest
->pCode
.UnicodeChar
,
911 WriteConsoleOutputCodeRequest
->Length
,
912 NULL
, 0, NULL
, NULL
);
913 tmpString
= String
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
916 WideCharToMultiByte(Console
->OutputCodePage
, 0,
917 (PWCHAR
)WriteConsoleOutputCodeRequest
->pCode
.UnicodeChar
,
918 WriteConsoleOutputCodeRequest
->Length
,
919 String
, Length
, NULL
, NULL
);
923 Status
= STATUS_NO_MEMORY
;
930 String
= (PCHAR
)WriteConsoleOutputCodeRequest
->pCode
.AsciiChar
;
935 // *(ReadBuffer++) = Code;
936 String
= (PCHAR
)WriteConsoleOutputCodeRequest
->pCode
.Attribute
;
940 if (String
&& NT_SUCCESS(Status
))
942 X
= WriteConsoleOutputCodeRequest
->Coord
.X
;
943 Y
= (WriteConsoleOutputCodeRequest
->Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
944 Length
= WriteConsoleOutputCodeRequest
->Length
;
945 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + (CodeType
== CODE_ATTRIBUTE
? 1 : 0)];
950 // ReadBuffer = (PVOID)((ULONG_PTR)ReadBuffer + CodeSize);
951 String
= (PCHAR
)((ULONG_PTR
)String
+ CodeSize
);
954 if (++X
== Buff
->MaxX
)
956 if (++Y
== Buff
->MaxY
)
959 Buffer
= Buff
->Buffer
+ (CodeType
== CODE_ATTRIBUTE
? 1 : 0);
965 if (Buff
== Console
->ActiveBuffer
)
967 ConioComputeUpdateRect(Buff
, &UpdateRect
, &WriteConsoleOutputCodeRequest
->Coord
,
968 WriteConsoleOutputCodeRequest
->Length
);
969 ConioDrawRegion(Console
, &UpdateRect
);
972 WriteConsoleOutputCodeRequest
->EndCoord
.X
= X
;
973 WriteConsoleOutputCodeRequest
->EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->VirtualY
) % Buff
->MaxY
;
978 RtlFreeHeap(GetProcessHeap(), 0, tmpString
);
981 ConioUnlockScreenBuffer(Buff
);
983 // WriteConsoleOutputCodeRequest->NrCharactersWritten = Written;
987 CSR_API(SrvFillConsoleOutput
)
990 PCSRSS_FILL_OUTPUT FillOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.FillOutputRequest
;
991 PCSRSS_CONSOLE Console
;
992 PCSRSS_SCREEN_BUFFER Buff
;
993 DWORD X
, Y
, Length
; // , Written = 0;
997 SMALL_RECT UpdateRect
;
999 DPRINT("SrvFillConsoleOutput\n");
1001 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), FillOutputRequest
->ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1002 if (!NT_SUCCESS(Status
)) return Status
;
1004 Console
= Buff
->Header
.Console
;
1006 CodeType
= FillOutputRequest
->CodeType
;
1008 X
= FillOutputRequest
->Coord
.X
;
1009 Y
= (FillOutputRequest
->Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1010 Length
= FillOutputRequest
->Length
;
1011 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + (CodeType
== CODE_ATTRIBUTE
? 1 : 0)];
1016 Code
= (BYTE
)FillOutputRequest
->Code
.AsciiChar
;
1020 ConsoleUnicodeCharToAnsiChar(Console
, (PCHAR
)&Code
, &FillOutputRequest
->Code
.UnicodeChar
);
1023 case CODE_ATTRIBUTE
:
1024 Code
= (BYTE
)FillOutputRequest
->Code
.Attribute
;
1028 ConioUnlockScreenBuffer(Buff
);
1029 return STATUS_INVALID_PARAMETER
;
1037 if (++X
== Buff
->MaxX
)
1039 if (++Y
== Buff
->MaxY
)
1042 Buffer
= Buff
->Buffer
+ (CodeType
== CODE_ATTRIBUTE
? 1 : 0);
1048 if (Buff
== Console
->ActiveBuffer
)
1050 ConioComputeUpdateRect(Buff
, &UpdateRect
, &FillOutputRequest
->Coord
,
1051 FillOutputRequest
->Length
);
1052 ConioDrawRegion(Console
, &UpdateRect
);
1055 ConioUnlockScreenBuffer(Buff
);
1057 Length = FillOutputRequest->Length;
1058 FillOutputRequest->NrCharactersWritten = Length;
1060 return STATUS_SUCCESS
;
1063 CSR_API(SrvGetConsoleCursorInfo
)
1066 PCSRSS_CURSOR_INFO CursorInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CursorInfoRequest
;
1067 PCSRSS_SCREEN_BUFFER Buff
;
1069 DPRINT("SrvGetConsoleCursorInfo\n");
1071 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), CursorInfoRequest
->ConsoleHandle
, &Buff
, GENERIC_READ
);
1072 if (!NT_SUCCESS(Status
)) return Status
;
1074 CursorInfoRequest
->Info
.bVisible
= Buff
->CursorInfo
.bVisible
;
1075 CursorInfoRequest
->Info
.dwSize
= Buff
->CursorInfo
.dwSize
;
1076 ConioUnlockScreenBuffer(Buff
);
1078 return STATUS_SUCCESS
;
1081 CSR_API(SrvSetConsoleCursorInfo
)
1084 PCSRSS_CURSOR_INFO CursorInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CursorInfoRequest
;
1085 PCSRSS_CONSOLE Console
;
1086 PCSRSS_SCREEN_BUFFER Buff
;
1090 DPRINT("SrvSetConsoleCursorInfo\n");
1092 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), CursorInfoRequest
->ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1093 if (!NT_SUCCESS(Status
)) return Status
;
1095 Console
= Buff
->Header
.Console
;
1097 Size
= CursorInfoRequest
->Info
.dwSize
;
1098 Visible
= CursorInfoRequest
->Info
.bVisible
;
1108 if ( (Size
!= Buff
->CursorInfo
.dwSize
) ||
1109 (Visible
&& ! Buff
->CursorInfo
.bVisible
) ||
1110 (! Visible
&& Buff
->CursorInfo
.bVisible
) )
1112 Buff
->CursorInfo
.dwSize
= Size
;
1113 Buff
->CursorInfo
.bVisible
= Visible
;
1115 if (!ConioSetCursorInfo(Console
, Buff
))
1117 ConioUnlockScreenBuffer(Buff
);
1118 return STATUS_UNSUCCESSFUL
;
1122 ConioUnlockScreenBuffer(Buff
);
1124 return STATUS_SUCCESS
;
1127 CSR_API(SrvSetConsoleCursorPosition
)
1130 PCSRSS_SET_CURSOR_POSITION SetCursorPositionRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetCursorPositionRequest
;
1131 PCSRSS_CONSOLE Console
;
1132 PCSRSS_SCREEN_BUFFER Buff
;
1133 LONG OldCursorX
, OldCursorY
;
1134 LONG NewCursorX
, NewCursorY
;
1136 DPRINT("SrvSetConsoleCursorPosition\n");
1138 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), SetCursorPositionRequest
->ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1139 if (!NT_SUCCESS(Status
)) return Status
;
1141 Console
= Buff
->Header
.Console
;
1143 NewCursorX
= SetCursorPositionRequest
->Position
.X
;
1144 NewCursorY
= SetCursorPositionRequest
->Position
.Y
;
1145 if ( NewCursorX
< 0 || NewCursorX
>= Buff
->MaxX
||
1146 NewCursorY
< 0 || NewCursorY
>= Buff
->MaxY
)
1148 ConioUnlockScreenBuffer(Buff
);
1149 return STATUS_INVALID_PARAMETER
;
1151 OldCursorX
= Buff
->CurrentX
;
1152 OldCursorY
= Buff
->CurrentY
;
1153 Buff
->CurrentX
= NewCursorX
;
1154 Buff
->CurrentY
= NewCursorY
;
1155 if (Buff
== Console
->ActiveBuffer
)
1157 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
1159 ConioUnlockScreenBuffer(Buff
);
1160 return STATUS_UNSUCCESSFUL
;
1164 ConioUnlockScreenBuffer(Buff
);
1166 return STATUS_SUCCESS
;
1169 CSR_API(SrvSetConsoleTextAttribute
)
1172 PCSRSS_SET_ATTRIB SetAttribRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetAttribRequest
;
1173 PCSRSS_CONSOLE Console
;
1174 PCSRSS_SCREEN_BUFFER Buff
;
1176 DPRINT("SrvSetConsoleTextAttribute\n");
1178 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), SetAttribRequest
->ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1179 if (!NT_SUCCESS(Status
)) return Status
;
1181 Console
= Buff
->Header
.Console
;
1183 Buff
->DefaultAttrib
= SetAttribRequest
->Attrib
;
1184 if (Buff
== Console
->ActiveBuffer
)
1186 if (!ConioUpdateScreenInfo(Console
, Buff
))
1188 ConioUnlockScreenBuffer(Buff
);
1189 return STATUS_UNSUCCESSFUL
;
1193 ConioUnlockScreenBuffer(Buff
);
1195 return STATUS_SUCCESS
;
1198 CSR_API(SrvCreateConsoleScreenBuffer
)
1201 PCSRSS_CREATE_SCREEN_BUFFER CreateScreenBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CreateScreenBufferRequest
;
1202 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
1203 PCSRSS_CONSOLE Console
;
1204 PCSRSS_SCREEN_BUFFER Buff
;
1206 DPRINT("SrvCreateConsoleScreenBuffer\n");
1208 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
1210 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1211 if (!NT_SUCCESS(Status
))
1213 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
1217 Buff
= HeapAlloc(ConSrvHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
1220 if (Console
->ActiveBuffer
)
1222 Buff
->MaxX
= Console
->ActiveBuffer
->MaxX
;
1223 Buff
->MaxY
= Console
->ActiveBuffer
->MaxY
;
1224 Buff
->CursorInfo
.bVisible
= Console
->ActiveBuffer
->CursorInfo
.bVisible
;
1225 Buff
->CursorInfo
.dwSize
= Console
->ActiveBuffer
->CursorInfo
.dwSize
;
1229 Buff
->CursorInfo
.bVisible
= TRUE
;
1230 Buff
->CursorInfo
.dwSize
= CSR_DEFAULT_CURSOR_SIZE
;
1233 if (Buff
->MaxX
== 0)
1238 if (Buff
->MaxY
== 0)
1243 Status
= CsrInitConsoleScreenBuffer(Console
, Buff
);
1244 if (NT_SUCCESS(Status
))
1246 Status
= Win32CsrInsertObject(ProcessData
,
1247 &CreateScreenBufferRequest
->OutputHandle
,
1249 CreateScreenBufferRequest
->Access
,
1250 CreateScreenBufferRequest
->Inheritable
,
1251 CreateScreenBufferRequest
->ShareMode
);
1256 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1259 ConioUnlockConsole(Console
);
1261 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
1266 CSR_API(SrvGetConsoleScreenBufferInfo
)
1269 PCSRSS_SCREEN_BUFFER_INFO ScreenBufferInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ScreenBufferInfoRequest
;
1270 PCSRSS_CONSOLE Console
;
1271 PCSRSS_SCREEN_BUFFER Buff
;
1272 PCONSOLE_SCREEN_BUFFER_INFO pInfo
= &ScreenBufferInfoRequest
->Info
;
1274 DPRINT("SrvGetConsoleScreenBufferInfo\n");
1276 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), ScreenBufferInfoRequest
->ConsoleHandle
, &Buff
, GENERIC_READ
);
1277 if (!NT_SUCCESS(Status
)) return Status
;
1279 Console
= Buff
->Header
.Console
;
1281 pInfo
->dwSize
.X
= Buff
->MaxX
;
1282 pInfo
->dwSize
.Y
= Buff
->MaxY
;
1283 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
;
1284 pInfo
->dwCursorPosition
.Y
= Buff
->CurrentY
;
1285 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
1286 pInfo
->srWindow
.Left
= Buff
->ShowX
;
1287 pInfo
->srWindow
.Right
= Buff
->ShowX
+ Console
->Size
.X
- 1;
1288 pInfo
->srWindow
.Top
= Buff
->ShowY
;
1289 pInfo
->srWindow
.Bottom
= Buff
->ShowY
+ Console
->Size
.Y
- 1;
1290 pInfo
->dwMaximumWindowSize
.X
= Buff
->MaxX
;
1291 pInfo
->dwMaximumWindowSize
.Y
= Buff
->MaxY
;
1293 ConioUnlockScreenBuffer(Buff
);
1295 return STATUS_SUCCESS
;
1298 CSR_API(SrvSetConsoleActiveScreenBuffer
)
1301 PCSRSS_SET_SCREEN_BUFFER SetScreenBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetScreenBufferRequest
;
1302 PCSRSS_CONSOLE Console
;
1303 PCSRSS_SCREEN_BUFFER Buff
;
1305 DPRINT("SrvSetConsoleActiveScreenBuffer\n");
1307 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), SetScreenBufferRequest
->OutputHandle
, &Buff
, GENERIC_WRITE
);
1308 if (!NT_SUCCESS(Status
)) return Status
;
1310 Console
= Buff
->Header
.Console
;
1312 if (Buff
== Console
->ActiveBuffer
)
1314 ConioUnlockScreenBuffer(Buff
);
1315 return STATUS_SUCCESS
;
1318 /* If old buffer has no handles, it's now unreferenced */
1319 if (Console
->ActiveBuffer
->Header
.HandleCount
== 0)
1321 ConioDeleteScreenBuffer(Console
->ActiveBuffer
);
1324 /* Tie console to new buffer */
1325 Console
->ActiveBuffer
= Buff
;
1327 /* Redraw the console */
1328 ConioDrawConsole(Console
);
1330 ConioUnlockScreenBuffer(Buff
);
1332 return STATUS_SUCCESS
;
1335 CSR_API(SrvScrollConsoleScreenBuffer
)
1337 PCSRSS_SCROLL_CONSOLE_SCREEN_BUFFER ScrollConsoleScreenBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ScrollConsoleScreenBufferRequest
;
1338 PCSRSS_CONSOLE Console
;
1339 PCSRSS_SCREEN_BUFFER Buff
;
1340 SMALL_RECT ScreenBuffer
;
1341 SMALL_RECT SrcRegion
;
1342 SMALL_RECT DstRegion
;
1343 SMALL_RECT UpdateRegion
;
1344 SMALL_RECT ScrollRectangle
;
1345 SMALL_RECT ClipRectangle
;
1347 HANDLE ConsoleHandle
;
1348 BOOLEAN UseClipRectangle
;
1349 COORD DestinationOrigin
;
1353 DPRINT("SrvScrollConsoleScreenBuffer\n");
1355 ConsoleHandle
= ScrollConsoleScreenBufferRequest
->ConsoleHandle
;
1356 UseClipRectangle
= ScrollConsoleScreenBufferRequest
->UseClipRectangle
;
1357 DestinationOrigin
= ScrollConsoleScreenBufferRequest
->DestinationOrigin
;
1358 Fill
= ScrollConsoleScreenBufferRequest
->Fill
;
1360 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1361 if (!NT_SUCCESS(Status
)) return Status
;
1363 Console
= Buff
->Header
.Console
;
1365 ScrollRectangle
= ScrollConsoleScreenBufferRequest
->ScrollRectangle
;
1367 /* Make sure source rectangle is inside the screen buffer */
1368 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
1369 if (! ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, &ScrollRectangle
))
1371 ConioUnlockScreenBuffer(Buff
);
1372 return STATUS_SUCCESS
;
1375 /* If the source was clipped on the left or top, adjust the destination accordingly */
1376 if (ScrollRectangle
.Left
< 0)
1378 DestinationOrigin
.X
-= ScrollRectangle
.Left
;
1380 if (ScrollRectangle
.Top
< 0)
1382 DestinationOrigin
.Y
-= ScrollRectangle
.Top
;
1385 if (UseClipRectangle
)
1387 ClipRectangle
= ScrollConsoleScreenBufferRequest
->ClipRectangle
;
1388 if (!ConioGetIntersection(&ClipRectangle
, &ClipRectangle
, &ScreenBuffer
))
1390 ConioUnlockScreenBuffer(Buff
);
1391 return STATUS_SUCCESS
;
1396 ClipRectangle
= ScreenBuffer
;
1399 ConioInitRect(&DstRegion
,
1400 DestinationOrigin
.Y
,
1401 DestinationOrigin
.X
,
1402 DestinationOrigin
.Y
+ ConioRectHeight(&SrcRegion
) - 1,
1403 DestinationOrigin
.X
+ ConioRectWidth(&SrcRegion
) - 1);
1405 if (ScrollConsoleScreenBufferRequest
->Unicode
)
1406 ConsoleUnicodeCharToAnsiChar(Console
, &FillChar
, &Fill
.Char
.UnicodeChar
);
1408 FillChar
= Fill
.Char
.AsciiChar
;
1410 ConioMoveRegion(Buff
, &SrcRegion
, &DstRegion
, &ClipRectangle
, Fill
.Attributes
<< 8 | (BYTE
)FillChar
);
1412 if (Buff
== Console
->ActiveBuffer
)
1414 ConioGetUnion(&UpdateRegion
, &SrcRegion
, &DstRegion
);
1415 if (ConioGetIntersection(&UpdateRegion
, &UpdateRegion
, &ClipRectangle
))
1417 /* Draw update region */
1418 ConioDrawRegion(Console
, &UpdateRegion
);
1422 ConioUnlockScreenBuffer(Buff
);
1424 return STATUS_SUCCESS
;
1427 CSR_API(SrvSetConsoleScreenBufferSize
)
1430 PCSRSS_SET_SCREEN_BUFFER_SIZE SetScreenBufferSize
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetScreenBufferSize
;
1431 PCSRSS_SCREEN_BUFFER Buff
;
1433 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), SetScreenBufferSize
->OutputHandle
, &Buff
, GENERIC_WRITE
);
1434 if (!NT_SUCCESS(Status
)) return Status
;
1436 Status
= ConioResizeBuffer(Buff
->Header
.Console
, Buff
, SetScreenBufferSize
->Size
);
1437 ConioUnlockScreenBuffer(Buff
);