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(PCONSOLE_SCREEN_BUFFER Buff
, ULONG X
, ULONG Y
)
43 return &Buff
->Buffer
[2 * (((Y
+ Buff
->VirtualY
) % Buff
->MaxY
) * Buff
->MaxX
+ X
)];
47 ClearLineBuffer(PCONSOLE_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(PCONSOLE Console
,
62 PCONSOLE_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(PCONSOLE_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(PCONSOLE Console
, PCONSOLE_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(PCONSOLE_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(PCONSOLE_SCREEN_BUFFER Buffer
)
368 PCONSOLE 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
, CONSOLE_SCREEN_BUFFER
, ListEntry
);
378 ConioDrawConsole(Console
);
382 HeapFree(ConSrvHeap
, 0, Buffer
->Buffer
);
383 HeapFree(ConSrvHeap
, 0, Buffer
);
387 ConioDrawConsole(PCONSOLE Console
)
391 ConioInitRect(&Region
, 0, 0, Console
->Size
.Y
- 1, Console
->Size
.X
- 1);
393 ConioDrawRegion(Console
, &Region
);
397 ConioComputeUpdateRect(PCONSOLE_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(PCONSOLE 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 PCONSOLE_WRITECONSOLE WriteConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteConsoleRequest
;
470 PCONSOLE_SCREEN_BUFFER Buff
;
475 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(ClientThread
->Process
), WriteConsoleRequest
->OutputHandle
, &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
,
493 ConioUnlockScreenBuffer(Buff
);
494 return STATUS_NO_MEMORY
;
498 /* Wait until we un-pause the console */
499 Status
= STATUS_PENDING
;
503 if(WriteConsoleRequest
->Unicode
)
505 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
506 (PWCHAR
)WriteConsoleRequest
->Buffer
,
507 WriteConsoleRequest
->NrCharactersToWrite
,
508 NULL
, 0, NULL
, NULL
);
509 Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
512 WideCharToMultiByte(Console
->OutputCodePage
, 0,
513 (PWCHAR
)WriteConsoleRequest
->Buffer
,
514 WriteConsoleRequest
->NrCharactersToWrite
,
515 Buffer
, Length
, NULL
, NULL
);
519 Status
= STATUS_NO_MEMORY
;
524 Buffer
= (PCHAR
)WriteConsoleRequest
->Buffer
;
529 if (NT_SUCCESS(Status
))
531 Status
= ConioWriteConsole(Console
, Buff
, Buffer
,
532 WriteConsoleRequest
->NrCharactersToWrite
, TRUE
);
533 if (NT_SUCCESS(Status
))
535 Written
= WriteConsoleRequest
->NrCharactersToWrite
;
538 if (WriteConsoleRequest
->Unicode
)
540 RtlFreeHeap(GetProcessHeap(), 0, Buffer
);
544 WriteConsoleRequest
->NrCharactersWritten
= Written
;
547 ConioUnlockScreenBuffer(Buff
);
552 /* PUBLIC APIS ****************************************************************/
554 CSR_API(SrvReadConsoleOutput
)
556 PCONSOLE_READOUTPUT ReadOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ReadOutputRequest
;
557 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
559 PCHAR_INFO CurCharInfo
;
560 PCONSOLE_SCREEN_BUFFER Buff
;
565 SMALL_RECT ReadRegion
;
566 SMALL_RECT ScreenRect
;
572 DPRINT("SrvReadConsoleOutput\n");
574 CharInfo
= ReadOutputRequest
->CharInfo
;
575 ReadRegion
= ReadOutputRequest
->ReadRegion
;
576 BufferSize
= ReadOutputRequest
->BufferSize
;
577 BufferCoord
= ReadOutputRequest
->BufferCoord
;
579 if (!CsrValidateMessageBuffer(ApiMessage
,
580 (PVOID
*)&ReadOutputRequest
->CharInfo
,
581 BufferSize
.X
* BufferSize
.Y
,
584 return STATUS_INVALID_PARAMETER
;
587 Status
= ConioLockScreenBuffer(ProcessData
, ReadOutputRequest
->OutputHandle
, &Buff
, GENERIC_READ
);
588 if (!NT_SUCCESS(Status
)) return Status
;
590 /* FIXME: Is this correct? */
591 CodePage
= ProcessData
->Console
->OutputCodePage
;
593 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&ReadRegion
));
594 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&ReadRegion
));
595 ReadRegion
.Bottom
= ReadRegion
.Top
+ SizeY
;
596 ReadRegion
.Right
= ReadRegion
.Left
+ SizeX
;
598 ConioInitRect(&ScreenRect
, 0, 0, Buff
->MaxY
, Buff
->MaxX
);
599 if (!ConioGetIntersection(&ReadRegion
, &ScreenRect
, &ReadRegion
))
601 ConioUnlockScreenBuffer(Buff
);
602 return STATUS_SUCCESS
;
605 for (i
= 0, Y
= ReadRegion
.Top
; Y
< ReadRegion
.Bottom
; ++i
, ++Y
)
607 CurCharInfo
= CharInfo
+ (i
* BufferSize
.X
);
609 Ptr
= ConioCoordToPointer(Buff
, ReadRegion
.Left
, Y
);
610 for (X
= ReadRegion
.Left
; X
< ReadRegion
.Right
; ++X
)
612 if (ReadOutputRequest
->Unicode
)
614 // ConsoleAnsiCharToUnicodeChar(ProcessData->Console, (PCHAR)Ptr++, &CurCharInfo->Char.UnicodeChar);
615 MultiByteToWideChar(CodePage
, 0,
617 &CurCharInfo
->Char
.UnicodeChar
, 1);
621 CurCharInfo
->Char
.AsciiChar
= *Ptr
++;
623 CurCharInfo
->Attributes
= *Ptr
++;
628 ConioUnlockScreenBuffer(Buff
);
630 ReadOutputRequest
->ReadRegion
.Right
= ReadRegion
.Left
+ SizeX
- 1;
631 ReadOutputRequest
->ReadRegion
.Bottom
= ReadRegion
.Top
+ SizeY
- 1;
632 ReadOutputRequest
->ReadRegion
.Left
= ReadRegion
.Left
;
633 ReadOutputRequest
->ReadRegion
.Top
= ReadRegion
.Top
;
635 return STATUS_SUCCESS
;
638 CSR_API(SrvWriteConsole
)
641 PCONSOLE_WRITECONSOLE WriteConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteConsoleRequest
;
643 DPRINT("SrvWriteConsole\n");
645 if (!CsrValidateMessageBuffer(ApiMessage
,
646 (PVOID
)&WriteConsoleRequest
->Buffer
,
647 WriteConsoleRequest
->BufferSize
,
650 return STATUS_INVALID_PARAMETER
;
653 Status
= DoWriteConsole(ApiMessage
,
654 CsrGetClientThread(),
657 if (Status
== STATUS_PENDING
)
658 *ReplyCode
= CsrReplyPending
;
663 CSR_API(SrvWriteConsoleOutput
)
665 PCONSOLE_WRITEOUTPUT WriteOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteOutputRequest
;
666 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
667 SHORT i
, X
, Y
, SizeX
, SizeY
;
669 PCONSOLE_SCREEN_BUFFER Buff
;
670 SMALL_RECT ScreenBuffer
;
671 CHAR_INFO
* CurCharInfo
;
672 SMALL_RECT WriteRegion
;
679 DPRINT("SrvWriteConsoleOutput\n");
681 BufferSize
= WriteOutputRequest
->BufferSize
;
682 BufferCoord
= WriteOutputRequest
->BufferCoord
;
683 CharInfo
= WriteOutputRequest
->CharInfo
;
685 if (!CsrValidateMessageBuffer(ApiMessage
,
686 (PVOID
*)&WriteOutputRequest
->CharInfo
,
687 BufferSize
.X
* BufferSize
.Y
,
690 return STATUS_INVALID_PARAMETER
;
693 Status
= ConioLockScreenBuffer(ProcessData
,
694 WriteOutputRequest
->OutputHandle
,
697 if (!NT_SUCCESS(Status
)) return Status
;
699 Console
= Buff
->Header
.Console
;
701 WriteRegion
= WriteOutputRequest
->WriteRegion
;
703 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&WriteRegion
));
704 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&WriteRegion
));
705 WriteRegion
.Bottom
= WriteRegion
.Top
+ SizeY
- 1;
706 WriteRegion
.Right
= WriteRegion
.Left
+ SizeX
- 1;
708 /* Make sure WriteRegion is inside the screen buffer */
709 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
710 if (!ConioGetIntersection(&WriteRegion
, &ScreenBuffer
, &WriteRegion
))
712 ConioUnlockScreenBuffer(Buff
);
714 /* It is okay to have a WriteRegion completely outside the screen buffer.
715 No data is written then. */
716 return STATUS_SUCCESS
;
719 for (i
= 0, Y
= WriteRegion
.Top
; Y
<= WriteRegion
.Bottom
; i
++, Y
++)
721 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
722 Ptr
= ConioCoordToPointer(Buff
, WriteRegion
.Left
, Y
);
723 for (X
= WriteRegion
.Left
; X
<= WriteRegion
.Right
; X
++)
726 if (WriteOutputRequest
->Unicode
)
728 ConsoleUnicodeCharToAnsiChar(Console
, &AsciiChar
, &CurCharInfo
->Char
.UnicodeChar
);
732 AsciiChar
= CurCharInfo
->Char
.AsciiChar
;
735 *Ptr
++ = CurCharInfo
->Attributes
;
740 ConioDrawRegion(Console
, &WriteRegion
);
742 ConioUnlockScreenBuffer(Buff
);
744 WriteOutputRequest
->WriteRegion
.Right
= WriteRegion
.Left
+ SizeX
- 1;
745 WriteOutputRequest
->WriteRegion
.Bottom
= WriteRegion
.Top
+ SizeY
- 1;
746 WriteOutputRequest
->WriteRegion
.Left
= WriteRegion
.Left
;
747 WriteOutputRequest
->WriteRegion
.Top
= WriteRegion
.Top
;
749 return STATUS_SUCCESS
;
752 CSR_API(SrvReadConsoleOutputString
)
755 PCONSOLE_READOUTPUTCODE ReadOutputCodeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ReadOutputCodeRequest
;
757 PCONSOLE_SCREEN_BUFFER Buff
;
765 DPRINT("SrvReadConsoleOutputString\n");
767 CodeType
= ReadOutputCodeRequest
->CodeType
;
771 CodeSize
= sizeof(CHAR
);
775 CodeSize
= sizeof(WCHAR
);
779 CodeSize
= sizeof(WORD
);
783 return STATUS_INVALID_PARAMETER
;
786 if (!CsrValidateMessageBuffer(ApiMessage
,
787 (PVOID
*)&ReadOutputCodeRequest
->pCode
.pCode
,
788 ReadOutputCodeRequest
->NumCodesToRead
,
791 return STATUS_INVALID_PARAMETER
;
794 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), ReadOutputCodeRequest
->OutputHandle
, &Buff
, GENERIC_READ
);
795 if (!NT_SUCCESS(Status
)) return Status
;
797 Console
= Buff
->Header
.Console
;
799 ReadBuffer
= ReadOutputCodeRequest
->pCode
.pCode
;
800 Xpos
= ReadOutputCodeRequest
->ReadCoord
.X
;
801 Ypos
= (ReadOutputCodeRequest
->ReadCoord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
804 * MSDN (ReadConsoleOutputAttribute and ReadConsoleOutputCharacter) :
806 * If the number of attributes (resp. characters) to be read from extends
807 * beyond the end of the specified screen buffer row, attributes (resp.
808 * characters) are read from the next row. If the number of attributes
809 * (resp. characters) to be read from extends beyond the end of the console
810 * screen buffer, attributes (resp. characters) up to the end of the console
811 * screen buffer are read.
813 * TODO: Do NOT loop up to NumCodesToRead, but stop before
814 * if we are going to overflow...
816 for (i
= 0; i
< ReadOutputCodeRequest
->NumCodesToRead
; ++i
)
818 Code
= Buff
->Buffer
[2 * (Xpos
+ Ypos
* Buff
->MaxX
) + (CodeType
== CODE_ATTRIBUTE
? 1 : 0)];
823 ConsoleAnsiCharToUnicodeChar(Console
, (PWCHAR
)ReadBuffer
, (PCHAR
)&Code
);
827 *(PCHAR
)ReadBuffer
= (CHAR
)Code
;
831 *(PWORD
)ReadBuffer
= (WORD
)Code
;
834 ReadBuffer
= (PVOID
)((ULONG_PTR
)ReadBuffer
+ CodeSize
);
838 if (Xpos
== Buff
->MaxX
)
843 if (Ypos
== Buff
->MaxY
)
853 *(PWCHAR
)ReadBuffer
= 0;
857 *(PCHAR
)ReadBuffer
= 0;
861 *(PWORD
)ReadBuffer
= 0;
865 ReadOutputCodeRequest
->EndCoord
.X
= Xpos
;
866 ReadOutputCodeRequest
->EndCoord
.Y
= (Ypos
- Buff
->VirtualY
+ Buff
->MaxY
) % Buff
->MaxY
;
868 ConioUnlockScreenBuffer(Buff
);
870 ReadOutputCodeRequest
->CodesRead
= (DWORD
)((ULONG_PTR
)ReadBuffer
- (ULONG_PTR
)ReadOutputCodeRequest
->pCode
.pCode
) / CodeSize
;
871 // <= ReadOutputCodeRequest->NumCodesToRead
873 return STATUS_SUCCESS
;
876 CSR_API(SrvWriteConsoleOutputString
)
879 PCONSOLE_WRITEOUTPUTCODE WriteOutputCodeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteOutputCodeRequest
;
881 PCONSOLE_SCREEN_BUFFER Buff
;
883 PBYTE Buffer
; // PUCHAR
884 PCHAR String
, tmpString
= NULL
;
885 DWORD X
, Y
, Length
; // , Written = 0;
887 SMALL_RECT UpdateRect
;
889 DPRINT("SrvWriteConsoleOutputString\n");
891 CodeType
= WriteOutputCodeRequest
->CodeType
;
895 CodeSize
= sizeof(CHAR
);
899 CodeSize
= sizeof(WCHAR
);
903 CodeSize
= sizeof(WORD
);
907 return STATUS_INVALID_PARAMETER
;
910 if (!CsrValidateMessageBuffer(ApiMessage
,
911 (PVOID
*)&WriteOutputCodeRequest
->pCode
.pCode
,
912 WriteOutputCodeRequest
->Length
,
915 return STATUS_INVALID_PARAMETER
;
918 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
919 WriteOutputCodeRequest
->OutputHandle
,
922 if (!NT_SUCCESS(Status
)) return Status
;
924 Console
= Buff
->Header
.Console
;
930 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
931 (PWCHAR
)WriteOutputCodeRequest
->pCode
.UnicodeChar
,
932 WriteOutputCodeRequest
->Length
,
933 NULL
, 0, NULL
, NULL
);
934 tmpString
= String
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
937 WideCharToMultiByte(Console
->OutputCodePage
, 0,
938 (PWCHAR
)WriteOutputCodeRequest
->pCode
.UnicodeChar
,
939 WriteOutputCodeRequest
->Length
,
940 String
, Length
, NULL
, NULL
);
944 Status
= STATUS_NO_MEMORY
;
951 String
= (PCHAR
)WriteOutputCodeRequest
->pCode
.AsciiChar
;
956 // *(ReadBuffer++) = Code;
957 String
= (PCHAR
)WriteOutputCodeRequest
->pCode
.Attribute
;
961 if (String
&& NT_SUCCESS(Status
))
963 X
= WriteOutputCodeRequest
->Coord
.X
;
964 Y
= (WriteOutputCodeRequest
->Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
965 Length
= WriteOutputCodeRequest
->Length
;
966 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + (CodeType
== CODE_ATTRIBUTE
? 1 : 0)];
971 // ReadBuffer = (PVOID)((ULONG_PTR)ReadBuffer + CodeSize);
972 String
= (PCHAR
)((ULONG_PTR
)String
+ CodeSize
);
975 if (++X
== Buff
->MaxX
)
977 if (++Y
== Buff
->MaxY
)
980 Buffer
= Buff
->Buffer
+ (CodeType
== CODE_ATTRIBUTE
? 1 : 0);
986 if (Buff
== Console
->ActiveBuffer
)
988 ConioComputeUpdateRect(Buff
, &UpdateRect
, &WriteOutputCodeRequest
->Coord
,
989 WriteOutputCodeRequest
->Length
);
990 ConioDrawRegion(Console
, &UpdateRect
);
993 WriteOutputCodeRequest
->EndCoord
.X
= X
;
994 WriteOutputCodeRequest
->EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->VirtualY
) % Buff
->MaxY
;
999 RtlFreeHeap(GetProcessHeap(), 0, tmpString
);
1002 ConioUnlockScreenBuffer(Buff
);
1004 // WriteOutputCodeRequest->NrCharactersWritten = Written;
1008 CSR_API(SrvFillConsoleOutput
)
1011 PCONSOLE_FILLOUTPUTCODE FillOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.FillOutputRequest
;
1013 PCONSOLE_SCREEN_BUFFER Buff
;
1014 DWORD X
, Y
, Length
; // , Written = 0;
1018 SMALL_RECT UpdateRect
;
1020 DPRINT("SrvFillConsoleOutput\n");
1022 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), FillOutputRequest
->OutputHandle
, &Buff
, GENERIC_WRITE
);
1023 if (!NT_SUCCESS(Status
)) return Status
;
1025 Console
= Buff
->Header
.Console
;
1027 CodeType
= FillOutputRequest
->CodeType
;
1029 X
= FillOutputRequest
->Coord
.X
;
1030 Y
= (FillOutputRequest
->Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1031 Length
= FillOutputRequest
->Length
;
1032 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + (CodeType
== CODE_ATTRIBUTE
? 1 : 0)];
1037 Code
= (BYTE
)FillOutputRequest
->Code
.AsciiChar
;
1041 ConsoleUnicodeCharToAnsiChar(Console
, (PCHAR
)&Code
, &FillOutputRequest
->Code
.UnicodeChar
);
1044 case CODE_ATTRIBUTE
:
1045 Code
= (BYTE
)FillOutputRequest
->Code
.Attribute
;
1049 ConioUnlockScreenBuffer(Buff
);
1050 return STATUS_INVALID_PARAMETER
;
1058 if (++X
== Buff
->MaxX
)
1060 if (++Y
== Buff
->MaxY
)
1063 Buffer
= Buff
->Buffer
+ (CodeType
== CODE_ATTRIBUTE
? 1 : 0);
1069 if (Buff
== Console
->ActiveBuffer
)
1071 ConioComputeUpdateRect(Buff
, &UpdateRect
, &FillOutputRequest
->Coord
,
1072 FillOutputRequest
->Length
);
1073 ConioDrawRegion(Console
, &UpdateRect
);
1076 ConioUnlockScreenBuffer(Buff
);
1078 Length = FillOutputRequest->Length;
1079 FillOutputRequest->NrCharactersWritten = Length;
1081 return STATUS_SUCCESS
;
1084 CSR_API(SrvGetConsoleCursorInfo
)
1087 PCONSOLE_GETSETCURSORINFO CursorInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CursorInfoRequest
;
1088 PCONSOLE_SCREEN_BUFFER Buff
;
1090 DPRINT("SrvGetConsoleCursorInfo\n");
1092 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), CursorInfoRequest
->OutputHandle
, &Buff
, GENERIC_READ
);
1093 if (!NT_SUCCESS(Status
)) return Status
;
1095 CursorInfoRequest
->Info
.bVisible
= Buff
->CursorInfo
.bVisible
;
1096 CursorInfoRequest
->Info
.dwSize
= Buff
->CursorInfo
.dwSize
;
1097 ConioUnlockScreenBuffer(Buff
);
1099 return STATUS_SUCCESS
;
1102 CSR_API(SrvSetConsoleCursorInfo
)
1105 PCONSOLE_GETSETCURSORINFO CursorInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CursorInfoRequest
;
1107 PCONSOLE_SCREEN_BUFFER Buff
;
1111 DPRINT("SrvSetConsoleCursorInfo\n");
1113 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), CursorInfoRequest
->OutputHandle
, &Buff
, GENERIC_WRITE
);
1114 if (!NT_SUCCESS(Status
)) return Status
;
1116 Console
= Buff
->Header
.Console
;
1118 Size
= CursorInfoRequest
->Info
.dwSize
;
1119 Visible
= CursorInfoRequest
->Info
.bVisible
;
1129 if ( (Size
!= Buff
->CursorInfo
.dwSize
) ||
1130 (Visible
&& ! Buff
->CursorInfo
.bVisible
) ||
1131 (! Visible
&& Buff
->CursorInfo
.bVisible
) )
1133 Buff
->CursorInfo
.dwSize
= Size
;
1134 Buff
->CursorInfo
.bVisible
= Visible
;
1136 if (!ConioSetCursorInfo(Console
, Buff
))
1138 ConioUnlockScreenBuffer(Buff
);
1139 return STATUS_UNSUCCESSFUL
;
1143 ConioUnlockScreenBuffer(Buff
);
1145 return STATUS_SUCCESS
;
1148 CSR_API(SrvSetConsoleCursorPosition
)
1151 PCONSOLE_SETCURSORPOSITION SetCursorPositionRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetCursorPositionRequest
;
1153 PCONSOLE_SCREEN_BUFFER Buff
;
1154 LONG OldCursorX
, OldCursorY
;
1155 LONG NewCursorX
, NewCursorY
;
1157 DPRINT("SrvSetConsoleCursorPosition\n");
1159 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), SetCursorPositionRequest
->OutputHandle
, &Buff
, GENERIC_WRITE
);
1160 if (!NT_SUCCESS(Status
)) return Status
;
1162 Console
= Buff
->Header
.Console
;
1164 NewCursorX
= SetCursorPositionRequest
->Position
.X
;
1165 NewCursorY
= SetCursorPositionRequest
->Position
.Y
;
1166 if ( NewCursorX
< 0 || NewCursorX
>= Buff
->MaxX
||
1167 NewCursorY
< 0 || NewCursorY
>= Buff
->MaxY
)
1169 ConioUnlockScreenBuffer(Buff
);
1170 return STATUS_INVALID_PARAMETER
;
1172 OldCursorX
= Buff
->CurrentX
;
1173 OldCursorY
= Buff
->CurrentY
;
1174 Buff
->CurrentX
= NewCursorX
;
1175 Buff
->CurrentY
= NewCursorY
;
1176 if (Buff
== Console
->ActiveBuffer
)
1178 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
1180 ConioUnlockScreenBuffer(Buff
);
1181 return STATUS_UNSUCCESSFUL
;
1185 ConioUnlockScreenBuffer(Buff
);
1187 return STATUS_SUCCESS
;
1190 CSR_API(SrvSetConsoleTextAttribute
)
1193 PCONSOLE_SETTEXTATTRIB SetTextAttribRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetTextAttribRequest
;
1195 PCONSOLE_SCREEN_BUFFER Buff
;
1197 DPRINT("SrvSetConsoleTextAttribute\n");
1199 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), SetTextAttribRequest
->OutputHandle
, &Buff
, GENERIC_WRITE
);
1200 if (!NT_SUCCESS(Status
)) return Status
;
1202 Console
= Buff
->Header
.Console
;
1204 Buff
->DefaultAttrib
= SetTextAttribRequest
->Attrib
;
1205 if (Buff
== Console
->ActiveBuffer
)
1207 if (!ConioUpdateScreenInfo(Console
, Buff
))
1209 ConioUnlockScreenBuffer(Buff
);
1210 return STATUS_UNSUCCESSFUL
;
1214 ConioUnlockScreenBuffer(Buff
);
1216 return STATUS_SUCCESS
;
1219 CSR_API(SrvCreateConsoleScreenBuffer
)
1222 PCONSOLE_CREATESCREENBUFFER CreateScreenBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CreateScreenBufferRequest
;
1223 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
1225 PCONSOLE_SCREEN_BUFFER Buff
;
1227 DPRINT("SrvCreateConsoleScreenBuffer\n");
1229 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
1231 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1232 if (!NT_SUCCESS(Status
))
1234 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
1238 Buff
= HeapAlloc(ConSrvHeap
, HEAP_ZERO_MEMORY
, sizeof(CONSOLE_SCREEN_BUFFER
));
1241 if (Console
->ActiveBuffer
)
1243 Buff
->MaxX
= Console
->ActiveBuffer
->MaxX
;
1244 Buff
->MaxY
= Console
->ActiveBuffer
->MaxY
;
1245 Buff
->CursorInfo
.bVisible
= Console
->ActiveBuffer
->CursorInfo
.bVisible
;
1246 Buff
->CursorInfo
.dwSize
= Console
->ActiveBuffer
->CursorInfo
.dwSize
;
1250 Buff
->CursorInfo
.bVisible
= TRUE
;
1251 Buff
->CursorInfo
.dwSize
= CSR_DEFAULT_CURSOR_SIZE
;
1254 if (Buff
->MaxX
== 0)
1259 if (Buff
->MaxY
== 0)
1264 Status
= CsrInitConsoleScreenBuffer(Console
, Buff
);
1265 if (NT_SUCCESS(Status
))
1267 Status
= Win32CsrInsertObject(ProcessData
,
1268 &CreateScreenBufferRequest
->OutputHandle
,
1270 CreateScreenBufferRequest
->Access
,
1271 CreateScreenBufferRequest
->Inheritable
,
1272 CreateScreenBufferRequest
->ShareMode
);
1277 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1280 ConioUnlockConsole(Console
);
1282 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
1287 CSR_API(SrvGetConsoleScreenBufferInfo
)
1290 PCONSOLE_GETSCREENBUFFERINFO ScreenBufferInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ScreenBufferInfoRequest
;
1292 PCONSOLE_SCREEN_BUFFER Buff
;
1293 PCONSOLE_SCREEN_BUFFER_INFO pInfo
= &ScreenBufferInfoRequest
->Info
;
1295 DPRINT("SrvGetConsoleScreenBufferInfo\n");
1297 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), ScreenBufferInfoRequest
->OutputHandle
, &Buff
, GENERIC_READ
);
1298 if (!NT_SUCCESS(Status
)) return Status
;
1300 Console
= Buff
->Header
.Console
;
1302 pInfo
->dwSize
.X
= Buff
->MaxX
;
1303 pInfo
->dwSize
.Y
= Buff
->MaxY
;
1304 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
;
1305 pInfo
->dwCursorPosition
.Y
= Buff
->CurrentY
;
1306 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
1307 pInfo
->srWindow
.Left
= Buff
->ShowX
;
1308 pInfo
->srWindow
.Right
= Buff
->ShowX
+ Console
->Size
.X
- 1;
1309 pInfo
->srWindow
.Top
= Buff
->ShowY
;
1310 pInfo
->srWindow
.Bottom
= Buff
->ShowY
+ Console
->Size
.Y
- 1;
1311 pInfo
->dwMaximumWindowSize
.X
= Buff
->MaxX
;
1312 pInfo
->dwMaximumWindowSize
.Y
= Buff
->MaxY
;
1314 ConioUnlockScreenBuffer(Buff
);
1316 return STATUS_SUCCESS
;
1319 CSR_API(SrvSetConsoleActiveScreenBuffer
)
1322 PCONSOLE_SETACTIVESCREENBUFFER SetScreenBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetScreenBufferRequest
;
1324 PCONSOLE_SCREEN_BUFFER Buff
;
1326 DPRINT("SrvSetConsoleActiveScreenBuffer\n");
1328 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), SetScreenBufferRequest
->OutputHandle
, &Buff
, GENERIC_WRITE
);
1329 if (!NT_SUCCESS(Status
)) return Status
;
1331 Console
= Buff
->Header
.Console
;
1333 if (Buff
== Console
->ActiveBuffer
)
1335 ConioUnlockScreenBuffer(Buff
);
1336 return STATUS_SUCCESS
;
1339 /* If old buffer has no handles, it's now unreferenced */
1340 if (Console
->ActiveBuffer
->Header
.HandleCount
== 0)
1342 ConioDeleteScreenBuffer(Console
->ActiveBuffer
);
1345 /* Tie console to new buffer */
1346 Console
->ActiveBuffer
= Buff
;
1348 /* Redraw the console */
1349 ConioDrawConsole(Console
);
1351 ConioUnlockScreenBuffer(Buff
);
1353 return STATUS_SUCCESS
;
1356 CSR_API(SrvScrollConsoleScreenBuffer
)
1358 PCONSOLE_SCROLLSCREENBUFFER ScrollScreenBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ScrollScreenBufferRequest
;
1360 PCONSOLE_SCREEN_BUFFER Buff
;
1361 SMALL_RECT ScreenBuffer
;
1362 SMALL_RECT SrcRegion
;
1363 SMALL_RECT DstRegion
;
1364 SMALL_RECT UpdateRegion
;
1365 SMALL_RECT ScrollRectangle
;
1366 SMALL_RECT ClipRectangle
;
1368 HANDLE OutputHandle
;
1369 BOOLEAN UseClipRectangle
;
1370 COORD DestinationOrigin
;
1374 DPRINT("SrvScrollConsoleScreenBuffer\n");
1376 OutputHandle
= ScrollScreenBufferRequest
->OutputHandle
;
1377 UseClipRectangle
= ScrollScreenBufferRequest
->UseClipRectangle
;
1378 DestinationOrigin
= ScrollScreenBufferRequest
->DestinationOrigin
;
1379 Fill
= ScrollScreenBufferRequest
->Fill
;
1381 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), OutputHandle
, &Buff
, GENERIC_WRITE
);
1382 if (!NT_SUCCESS(Status
)) return Status
;
1384 Console
= Buff
->Header
.Console
;
1386 ScrollRectangle
= ScrollScreenBufferRequest
->ScrollRectangle
;
1388 /* Make sure source rectangle is inside the screen buffer */
1389 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
1390 if (! ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, &ScrollRectangle
))
1392 ConioUnlockScreenBuffer(Buff
);
1393 return STATUS_SUCCESS
;
1396 /* If the source was clipped on the left or top, adjust the destination accordingly */
1397 if (ScrollRectangle
.Left
< 0)
1399 DestinationOrigin
.X
-= ScrollRectangle
.Left
;
1401 if (ScrollRectangle
.Top
< 0)
1403 DestinationOrigin
.Y
-= ScrollRectangle
.Top
;
1406 if (UseClipRectangle
)
1408 ClipRectangle
= ScrollScreenBufferRequest
->ClipRectangle
;
1409 if (!ConioGetIntersection(&ClipRectangle
, &ClipRectangle
, &ScreenBuffer
))
1411 ConioUnlockScreenBuffer(Buff
);
1412 return STATUS_SUCCESS
;
1417 ClipRectangle
= ScreenBuffer
;
1420 ConioInitRect(&DstRegion
,
1421 DestinationOrigin
.Y
,
1422 DestinationOrigin
.X
,
1423 DestinationOrigin
.Y
+ ConioRectHeight(&SrcRegion
) - 1,
1424 DestinationOrigin
.X
+ ConioRectWidth(&SrcRegion
) - 1);
1426 if (ScrollScreenBufferRequest
->Unicode
)
1427 ConsoleUnicodeCharToAnsiChar(Console
, &FillChar
, &Fill
.Char
.UnicodeChar
);
1429 FillChar
= Fill
.Char
.AsciiChar
;
1431 ConioMoveRegion(Buff
, &SrcRegion
, &DstRegion
, &ClipRectangle
, Fill
.Attributes
<< 8 | (BYTE
)FillChar
);
1433 if (Buff
== Console
->ActiveBuffer
)
1435 ConioGetUnion(&UpdateRegion
, &SrcRegion
, &DstRegion
);
1436 if (ConioGetIntersection(&UpdateRegion
, &UpdateRegion
, &ClipRectangle
))
1438 /* Draw update region */
1439 ConioDrawRegion(Console
, &UpdateRegion
);
1443 ConioUnlockScreenBuffer(Buff
);
1445 return STATUS_SUCCESS
;
1448 CSR_API(SrvSetConsoleScreenBufferSize
)
1451 PCONSOLE_SETSCREENBUFFERSIZE SetScreenBufferSizeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetScreenBufferSizeRequest
;
1452 PCONSOLE_SCREEN_BUFFER Buff
;
1454 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), SetScreenBufferSizeRequest
->OutputHandle
, &Buff
, GENERIC_WRITE
);
1455 if (!NT_SUCCESS(Status
)) return Status
;
1457 Status
= ConioResizeBuffer(Buff
->Header
.Console
, Buff
, SetScreenBufferSizeRequest
->Size
);
1458 ConioUnlockScreenBuffer(Buff
);