2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Driver DLL
4 * FILE: win32ss/user/winsrv/consrv/condrv/text.c
5 * PURPOSE: Console Output Functions for text-mode screen-buffers
6 * PROGRAMMERS: Jeffrey Morlan
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
10 /* INCLUDES *******************************************************************/
17 /* GLOBALS ********************************************************************/
21 /* PRIVATE FUNCTIONS **********************************************************/
23 CONSOLE_IO_OBJECT_TYPE
24 TEXTMODE_BUFFER_GetType(PCONSOLE_SCREEN_BUFFER This
)
26 // return This->Header.Type;
27 return TEXTMODE_BUFFER
;
30 static CONSOLE_SCREEN_BUFFER_VTBL TextVtbl
=
32 TEXTMODE_BUFFER_GetType
,
37 ClearLineBuffer(PTEXTMODE_SCREEN_BUFFER Buff
);
41 CONSOLE_SCREEN_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER
* Buffer
,
42 IN OUT PCONSOLE Console
,
43 IN PCONSOLE_SCREEN_BUFFER_VTBL Vtbl
,
46 CONSOLE_SCREEN_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer
);
50 TEXTMODE_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER
* Buffer
,
51 IN OUT PCONSOLE Console
,
52 IN PTEXTMODE_BUFFER_INFO TextModeInfo
)
54 NTSTATUS Status
= STATUS_SUCCESS
;
55 PTEXTMODE_SCREEN_BUFFER NewBuffer
= NULL
;
57 if (Console
== NULL
|| Buffer
== NULL
|| TextModeInfo
== NULL
)
58 return STATUS_INVALID_PARAMETER
;
62 Status
= CONSOLE_SCREEN_BUFFER_Initialize((PCONSOLE_SCREEN_BUFFER
*)&NewBuffer
,
65 sizeof(TEXTMODE_SCREEN_BUFFER
));
66 if (!NT_SUCCESS(Status
)) return Status
;
67 NewBuffer
->Header
.Type
= TEXTMODE_BUFFER
;
69 NewBuffer
->Buffer
= ConsoleAllocHeap(HEAP_ZERO_MEMORY
,
70 TextModeInfo
->ScreenBufferSize
.X
*
71 TextModeInfo
->ScreenBufferSize
.Y
*
73 if (NewBuffer
->Buffer
== NULL
)
75 CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER
)NewBuffer
);
76 return STATUS_INSUFFICIENT_RESOURCES
;
79 NewBuffer
->ScreenBufferSize
= NewBuffer
->OldScreenBufferSize
80 = TextModeInfo
->ScreenBufferSize
;
81 NewBuffer
->ViewSize
= NewBuffer
->OldViewSize
82 = Console
->ConsoleSize
;
84 NewBuffer
->ViewOrigin
.X
= NewBuffer
->ViewOrigin
.Y
= 0;
85 NewBuffer
->VirtualY
= 0;
87 NewBuffer
->CursorBlinkOn
= NewBuffer
->ForceCursorOff
= FALSE
;
88 NewBuffer
->CursorInfo
.bVisible
= (TextModeInfo
->IsCursorVisible
&& (TextModeInfo
->CursorSize
!= 0));
89 NewBuffer
->CursorInfo
.dwSize
= min(max(TextModeInfo
->CursorSize
, 0), 100);
91 NewBuffer
->ScreenDefaultAttrib
= TextModeInfo
->ScreenAttrib
;
92 NewBuffer
->PopupDefaultAttrib
= TextModeInfo
->PopupAttrib
;
94 /* Initialize buffer to be empty with default attributes */
95 for (NewBuffer
->CursorPosition
.Y
= 0 ; NewBuffer
->CursorPosition
.Y
< NewBuffer
->ScreenBufferSize
.Y
; NewBuffer
->CursorPosition
.Y
++)
97 ClearLineBuffer(NewBuffer
);
99 NewBuffer
->CursorPosition
.X
= NewBuffer
->CursorPosition
.Y
= 0;
101 NewBuffer
->Mode
= ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
;
103 *Buffer
= (PCONSOLE_SCREEN_BUFFER
)NewBuffer
;
104 return STATUS_SUCCESS
;
108 TEXTMODE_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer
)
110 PTEXTMODE_SCREEN_BUFFER Buff
= (PTEXTMODE_SCREEN_BUFFER
)Buffer
;
113 * IMPORTANT !! Reinitialize the type so that we don't enter a recursive
114 * infinite loop when calling CONSOLE_SCREEN_BUFFER_Destroy.
116 Buffer
->Header
.Type
= SCREEN_BUFFER
;
118 ConsoleFreeHeap(Buff
->Buffer
);
120 CONSOLE_SCREEN_BUFFER_Destroy(Buffer
);
125 ConioCoordToPointer(PTEXTMODE_SCREEN_BUFFER Buff
, ULONG X
, ULONG Y
)
127 return &Buff
->Buffer
[((Y
+ Buff
->VirtualY
) % Buff
->ScreenBufferSize
.Y
) * Buff
->ScreenBufferSize
.X
+ X
];
131 ClearLineBuffer(PTEXTMODE_SCREEN_BUFFER Buff
)
133 PCHAR_INFO Ptr
= ConioCoordToPointer(Buff
, 0, Buff
->CursorPosition
.Y
);
136 for (Pos
= 0; Pos
< Buff
->ScreenBufferSize
.X
; Pos
++, Ptr
++)
139 Ptr
->Char
.UnicodeChar
= L
' ';
140 Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
;
145 ConioComputeUpdateRect(IN PTEXTMODE_SCREEN_BUFFER Buff
,
146 IN OUT PSMALL_RECT UpdateRect
,
150 if (Buff
->ScreenBufferSize
.X
<= Start
->X
+ Length
)
152 UpdateRect
->Left
= 0;
156 UpdateRect
->Left
= Start
->X
;
158 if (Buff
->ScreenBufferSize
.X
<= Start
->X
+ Length
)
160 UpdateRect
->Right
= Buff
->ScreenBufferSize
.X
- 1;
164 UpdateRect
->Right
= Start
->X
+ Length
- 1;
166 UpdateRect
->Top
= Start
->Y
;
167 UpdateRect
->Bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->ScreenBufferSize
.X
;
168 if (Buff
->ScreenBufferSize
.Y
<= UpdateRect
->Bottom
)
170 UpdateRect
->Bottom
= Buff
->ScreenBufferSize
.Y
- 1;
175 * Move from one rectangle to another. We must be careful about the order that
176 * this is done, to avoid overwriting parts of the source before they are moved.
179 ConioMoveRegion(PTEXTMODE_SCREEN_BUFFER ScreenBuffer
,
180 PSMALL_RECT SrcRegion
,
181 PSMALL_RECT DstRegion
,
182 PSMALL_RECT ClipRegion
,
185 int Width
= ConioRectWidth(SrcRegion
);
186 int Height
= ConioRectHeight(SrcRegion
);
197 /* Moving down: work from bottom up */
198 SY
= SrcRegion
->Bottom
;
199 DY
= DstRegion
->Bottom
;
202 for (i
= 0; i
< Height
; i
++)
204 PCHAR_INFO SRow
= ConioCoordToPointer(ScreenBuffer
, 0, SY
);
205 PCHAR_INFO DRow
= ConioCoordToPointer(ScreenBuffer
, 0, DY
);
207 SX
= SrcRegion
->Left
;
208 DX
= DstRegion
->Left
;
212 /* Moving right: work from right to left */
213 SX
= SrcRegion
->Right
;
214 DX
= DstRegion
->Right
;
217 for (j
= 0; j
< Width
; j
++)
219 CHAR_INFO Cell
= SRow
[SX
];
220 if (SX
>= ClipRegion
->Left
&& SX
<= ClipRegion
->Right
&&
221 SY
>= ClipRegion
->Top
&& SY
<= ClipRegion
->Bottom
)
225 if (DX
>= ClipRegion
->Left
&& DX
<= ClipRegion
->Right
&&
226 DY
>= ClipRegion
->Top
&& DY
<= ClipRegion
->Bottom
)
239 ConioResizeBuffer(PCONSOLE Console
,
240 PTEXTMODE_SCREEN_BUFFER ScreenBuffer
,
246 WORD CurrentAttribute
;
248 PCHAR_INFO OldBuffer
;
252 /* Buffer size is not allowed to be smaller than the view size */
253 if (Size
.X
< ScreenBuffer
->ViewSize
.X
|| Size
.Y
< ScreenBuffer
->ViewSize
.Y
)
254 return STATUS_INVALID_PARAMETER
;
256 if (Size
.X
== ScreenBuffer
->ScreenBufferSize
.X
&& Size
.Y
== ScreenBuffer
->ScreenBufferSize
.Y
)
258 // FIXME: Trigger a buffer resize event ??
259 return STATUS_SUCCESS
;
262 if (Console
->FixedSize
)
265 * The console is in fixed-size mode, so we cannot resize anything
266 * at the moment. However, keep those settings somewhere so that
267 * we can try to set them up when we will be allowed to do so.
269 ScreenBuffer
->OldScreenBufferSize
= Size
;
270 return STATUS_NOT_SUPPORTED
; // STATUS_SUCCESS
273 Buffer
= ConsoleAllocHeap(HEAP_ZERO_MEMORY
, Size
.X
* Size
.Y
* sizeof(CHAR_INFO
));
274 if (!Buffer
) return STATUS_NO_MEMORY
;
276 DPRINT1("Resizing (%d,%d) to (%d,%d)\n", ScreenBuffer
->ScreenBufferSize
.X
, ScreenBuffer
->ScreenBufferSize
.Y
, Size
.X
, Size
.Y
);
277 OldBuffer
= ScreenBuffer
->Buffer
;
279 for (CurrentY
= 0; CurrentY
< ScreenBuffer
->ScreenBufferSize
.Y
&& CurrentY
< Size
.Y
; CurrentY
++)
281 ptr
= ConioCoordToPointer(ScreenBuffer
, 0, CurrentY
);
282 if (Size
.X
<= ScreenBuffer
->ScreenBufferSize
.X
)
285 RtlCopyMemory(Buffer
+ Offset
, ptr
, Size
.X
* sizeof(CHAR_INFO
));
291 RtlCopyMemory(Buffer
+ Offset
, ptr
, ScreenBuffer
->ScreenBufferSize
.X
* sizeof(CHAR_INFO
));
292 Offset
+= ScreenBuffer
->ScreenBufferSize
.X
;
294 /* The attribute to be used is the one of the last cell of the current line */
295 CurrentAttribute
= ConioCoordToPointer(ScreenBuffer
,
296 ScreenBuffer
->ScreenBufferSize
.X
- 1,
297 CurrentY
)->Attributes
;
299 diff
= Size
.X
- ScreenBuffer
->ScreenBufferSize
.X
;
301 /* Zero-out the new part of the buffer */
302 for (i
= 0; i
< diff
; i
++)
304 ptr
= Buffer
+ Offset
;
305 ptr
->Char
.UnicodeChar
= L
' ';
306 ptr
->Attributes
= CurrentAttribute
;
312 if (Size
.Y
> ScreenBuffer
->ScreenBufferSize
.Y
)
314 diff
= Size
.X
* (Size
.Y
- ScreenBuffer
->ScreenBufferSize
.Y
);
316 /* Zero-out the new part of the buffer */
317 for (i
= 0; i
< diff
; i
++)
319 ptr
= Buffer
+ Offset
;
320 ptr
->Char
.UnicodeChar
= L
' ';
321 ptr
->Attributes
= ScreenBuffer
->ScreenDefaultAttrib
;
326 (void)InterlockedExchangePointer((PVOID
volatile*)&ScreenBuffer
->Buffer
, Buffer
);
327 ConsoleFreeHeap(OldBuffer
);
328 ScreenBuffer
->ScreenBufferSize
= ScreenBuffer
->OldScreenBufferSize
= Size
;
329 ScreenBuffer
->VirtualY
= 0;
331 /* Ensure cursor and window are within buffer */
332 if (ScreenBuffer
->CursorPosition
.X
>= Size
.X
)
333 ScreenBuffer
->CursorPosition
.X
= Size
.X
- 1;
334 if (ScreenBuffer
->CursorPosition
.Y
>= Size
.Y
)
335 ScreenBuffer
->CursorPosition
.Y
= Size
.Y
- 1;
336 if (ScreenBuffer
->ViewOrigin
.X
> Size
.X
- ScreenBuffer
->ViewSize
.X
)
337 ScreenBuffer
->ViewOrigin
.X
= Size
.X
- ScreenBuffer
->ViewSize
.X
;
338 if (ScreenBuffer
->ViewOrigin
.Y
> Size
.Y
- ScreenBuffer
->ViewSize
.Y
)
339 ScreenBuffer
->ViewOrigin
.Y
= Size
.Y
- ScreenBuffer
->ViewSize
.Y
;
342 * Trigger a buffer resize event
344 if (Console
->InputBuffer
.Mode
& ENABLE_WINDOW_INPUT
)
348 er
.EventType
= WINDOW_BUFFER_SIZE_EVENT
;
349 er
.Event
.WindowBufferSizeEvent
.dwSize
= ScreenBuffer
->ScreenBufferSize
;
351 ConioProcessInputEvent(Console
, &er
);
354 return STATUS_SUCCESS
;
358 ConioNextLine(PTEXTMODE_SCREEN_BUFFER Buff
, PSMALL_RECT UpdateRect
, PUINT ScrolledLines
)
360 /* If we hit bottom, slide the viewable screen */
361 if (++Buff
->CursorPosition
.Y
== Buff
->ScreenBufferSize
.Y
)
363 Buff
->CursorPosition
.Y
--;
364 if (++Buff
->VirtualY
== Buff
->ScreenBufferSize
.Y
)
369 ClearLineBuffer(Buff
);
370 if (UpdateRect
->Top
!= 0)
375 UpdateRect
->Left
= 0;
376 UpdateRect
->Right
= Buff
->ScreenBufferSize
.X
- 1;
377 UpdateRect
->Bottom
= Buff
->CursorPosition
.Y
;
381 ConioWriteConsole(PCONSOLE Console
,
382 PTEXTMODE_SCREEN_BUFFER Buff
,
389 SMALL_RECT UpdateRect
;
390 SHORT CursorStartX
, CursorStartY
;
393 CursorStartX
= Buff
->CursorPosition
.X
;
394 CursorStartY
= Buff
->CursorPosition
.Y
;
395 UpdateRect
.Left
= Buff
->ScreenBufferSize
.X
;
396 UpdateRect
.Top
= Buff
->CursorPosition
.Y
;
397 UpdateRect
.Right
= -1;
398 UpdateRect
.Bottom
= Buff
->CursorPosition
.Y
;
401 for (i
= 0; i
< Length
; i
++)
404 * If we are in processed mode, interpret special characters and
405 * display them correctly. Otherwise, just put them into the buffer.
407 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
410 if (Buffer
[i
] == L
'\r')
412 Buff
->CursorPosition
.X
= 0;
413 UpdateRect
.Left
= min(UpdateRect
.Left
, Buff
->CursorPosition
.X
);
414 UpdateRect
.Right
= max(UpdateRect
.Right
, Buff
->CursorPosition
.X
);
418 else if (Buffer
[i
] == L
'\n')
420 Buff
->CursorPosition
.X
= 0;
421 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
425 else if (Buffer
[i
] == L
'\b')
427 /* Only handle BS if we're not on the first pos of the first line */
428 if (0 != Buff
->CursorPosition
.X
|| 0 != Buff
->CursorPosition
.Y
)
430 if (0 == Buff
->CursorPosition
.X
)
432 /* slide virtual position up */
433 Buff
->CursorPosition
.X
= Buff
->ScreenBufferSize
.X
- 1;
434 Buff
->CursorPosition
.Y
--;
435 UpdateRect
.Top
= min(UpdateRect
.Top
, Buff
->CursorPosition
.Y
);
439 Buff
->CursorPosition
.X
--;
441 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
442 Ptr
->Char
.UnicodeChar
= L
' ';
443 Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
;
444 UpdateRect
.Left
= min(UpdateRect
.Left
, Buff
->CursorPosition
.X
);
445 UpdateRect
.Right
= max(UpdateRect
.Right
, Buff
->CursorPosition
.X
);
450 else if (Buffer
[i
] == L
'\t')
454 UpdateRect
.Left
= min(UpdateRect
.Left
, Buff
->CursorPosition
.X
);
455 EndX
= (Buff
->CursorPosition
.X
+ TAB_WIDTH
) & ~(TAB_WIDTH
- 1);
456 EndX
= min(EndX
, (UINT
)Buff
->ScreenBufferSize
.X
);
457 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
458 while (Buff
->CursorPosition
.X
< EndX
)
460 Ptr
->Char
.UnicodeChar
= L
' ';
461 Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
;
463 Buff
->CursorPosition
.X
++;
465 UpdateRect
.Right
= max(UpdateRect
.Right
, Buff
->CursorPosition
.X
- 1);
466 if (Buff
->CursorPosition
.X
== Buff
->ScreenBufferSize
.X
)
468 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
470 Buff
->CursorPosition
.X
= 0;
471 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
475 Buff
->CursorPosition
.X
--;
481 // else if (Buffer[i] == L'\a')
483 // // FIXME: This MUST BE moved to the terminal emulator frontend!!
484 // DPRINT1("Bell\n");
485 // // SendNotifyMessage(Console->hWindow, PM_CONSOLE_BEEP, 0, 0);
489 UpdateRect
.Left
= min(UpdateRect
.Left
, Buff
->CursorPosition
.X
);
490 UpdateRect
.Right
= max(UpdateRect
.Right
, Buff
->CursorPosition
.X
);
492 Ptr
= ConioCoordToPointer(Buff
, Buff
->CursorPosition
.X
, Buff
->CursorPosition
.Y
);
493 Ptr
->Char
.UnicodeChar
= Buffer
[i
];
494 if (Attrib
) Ptr
->Attributes
= Buff
->ScreenDefaultAttrib
;
496 Buff
->CursorPosition
.X
++;
497 if (Buff
->CursorPosition
.X
== Buff
->ScreenBufferSize
.X
)
499 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
501 Buff
->CursorPosition
.X
= 0;
502 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
506 Buff
->CursorPosition
.X
= CursorStartX
;
511 if (!ConioIsRectEmpty(&UpdateRect
) && (PCONSOLE_SCREEN_BUFFER
)Buff
== Console
->ActiveBuffer
)
513 TermWriteStream(Console
, &UpdateRect
, CursorStartX
, CursorStartY
,
514 ScrolledLines
, Buffer
, Length
);
517 return STATUS_SUCCESS
;
521 ConDrvChangeScreenBufferAttributes(IN PCONSOLE Console
,
522 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
523 IN USHORT NewScreenAttrib
,
524 IN USHORT NewPopupAttrib
)
530 ULONG NumCodesToWrite
;
531 USHORT OldScreenAttrib
;
533 if (Console
== NULL
|| Buffer
== NULL
)
535 return STATUS_INVALID_PARAMETER
;
539 ASSERT(Console
== Buffer
->Header
.Console
);
541 NumCodesToWrite
= Buffer
->ScreenBufferSize
.X
* Buffer
->ScreenBufferSize
.Y
;
542 OldScreenAttrib
= Buffer
->ScreenDefaultAttrib
;
545 Y
= (TopLeft
.Y
+ Buffer
->VirtualY
) % Buffer
->ScreenBufferSize
.Y
;
546 Length
= NumCodesToWrite
;
548 // Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work
549 // Ptr = &Buffer->Buffer[X + Y * Buffer->ScreenBufferSize.X]; // May work
553 // Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work either
554 Ptr
= &Buffer
->Buffer
[X
+ Y
* Buffer
->ScreenBufferSize
.X
];
557 * Change the current colors only if they are the old ones.
560 /* Foreground color */
561 if ((Ptr
->Attributes
& 0x0F) == (OldScreenAttrib
& 0x0F))
562 Ptr
->Attributes
= (Ptr
->Attributes
& 0xFFF0) | (NewScreenAttrib
& 0x0F);
564 /* Background color */
565 if ((Ptr
->Attributes
& 0xF0) == (OldScreenAttrib
& 0xF0))
566 Ptr
->Attributes
= (Ptr
->Attributes
& 0xFF0F) | (NewScreenAttrib
& 0xF0);
570 if (++X
== Buffer
->ScreenBufferSize
.X
)
574 if (++Y
== Buffer
->ScreenBufferSize
.Y
)
581 /* Save foreground and background colors for both screen and popup */
582 Buffer
->ScreenDefaultAttrib
= (NewScreenAttrib
& 0x00FF);
583 Buffer
->PopupDefaultAttrib
= (NewPopupAttrib
& 0x00FF);
585 /* Refresh the display if needed */
586 if ((PCONSOLE_SCREEN_BUFFER
)Buffer
== Console
->ActiveBuffer
)
588 SMALL_RECT UpdateRect
;
589 ConioComputeUpdateRect(Buffer
, &UpdateRect
, &TopLeft
, NumCodesToWrite
);
590 TermDrawRegion(Console
, &UpdateRect
);
593 return STATUS_SUCCESS
;
597 /* PUBLIC DRIVER APIS *********************************************************/
600 ConDrvReadConsoleOutput(IN PCONSOLE Console
,
601 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
603 OUT PCHAR_INFO CharInfo
/*Buffer*/,
604 IN OUT PSMALL_RECT ReadRegion
)
607 SMALL_RECT ScreenBuffer
;
608 PCHAR_INFO CurCharInfo
;
609 SMALL_RECT CapturedReadRegion
;
612 if (Console
== NULL
|| Buffer
== NULL
|| CharInfo
== NULL
|| ReadRegion
== NULL
)
614 return STATUS_INVALID_PARAMETER
;
618 ASSERT(Console
== Buffer
->Header
.Console
);
620 CapturedReadRegion
= *ReadRegion
;
622 /* Make sure ReadRegion is inside the screen buffer */
623 ConioInitRect(&ScreenBuffer
, 0, 0,
624 Buffer
->ScreenBufferSize
.Y
- 1, Buffer
->ScreenBufferSize
.X
- 1);
625 if (!ConioGetIntersection(&CapturedReadRegion
, &ScreenBuffer
, &CapturedReadRegion
))
628 * It is okay to have a ReadRegion completely outside
629 * the screen buffer. No data is read then.
631 return STATUS_SUCCESS
;
634 CurCharInfo
= CharInfo
;
636 for (Y
= CapturedReadRegion
.Top
; Y
<= CapturedReadRegion
.Bottom
; ++Y
)
638 Ptr
= ConioCoordToPointer(Buffer
, CapturedReadRegion
.Left
, Y
);
639 for (X
= CapturedReadRegion
.Left
; X
<= CapturedReadRegion
.Right
; ++X
)
643 CurCharInfo
->Char
.UnicodeChar
= Ptr
->Char
.UnicodeChar
;
647 // ConsoleUnicodeCharToAnsiChar(Console, &CurCharInfo->Char.AsciiChar, &Ptr->Char.UnicodeChar);
648 WideCharToMultiByte(Console
->OutputCodePage
, 0, &Ptr
->Char
.UnicodeChar
, 1,
649 &CurCharInfo
->Char
.AsciiChar
, 1, NULL
, NULL
);
651 CurCharInfo
->Attributes
= Ptr
->Attributes
;
657 *ReadRegion
= CapturedReadRegion
;
659 return STATUS_SUCCESS
;
663 ConDrvWriteConsoleOutput(IN PCONSOLE Console
,
664 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
666 IN PCHAR_INFO CharInfo
/*Buffer*/,
667 IN OUT PSMALL_RECT WriteRegion
)
670 SMALL_RECT ScreenBuffer
;
671 PCHAR_INFO CurCharInfo
;
672 SMALL_RECT CapturedWriteRegion
;
675 if (Console
== NULL
|| Buffer
== NULL
|| CharInfo
== NULL
|| WriteRegion
== NULL
)
677 return STATUS_INVALID_PARAMETER
;
681 ASSERT(Console
== Buffer
->Header
.Console
);
683 CapturedWriteRegion
= *WriteRegion
;
685 /* Make sure WriteRegion is inside the screen buffer */
686 ConioInitRect(&ScreenBuffer
, 0, 0,
687 Buffer
->ScreenBufferSize
.Y
- 1, Buffer
->ScreenBufferSize
.X
- 1);
688 if (!ConioGetIntersection(&CapturedWriteRegion
, &ScreenBuffer
, &CapturedWriteRegion
))
691 * It is okay to have a WriteRegion completely outside
692 * the screen buffer. No data is written then.
694 return STATUS_SUCCESS
;
697 CurCharInfo
= CharInfo
;
699 for (Y
= CapturedWriteRegion
.Top
; Y
<= CapturedWriteRegion
.Bottom
; ++Y
)
701 Ptr
= ConioCoordToPointer(Buffer
, CapturedWriteRegion
.Left
, Y
);
702 for (X
= CapturedWriteRegion
.Left
; X
<= CapturedWriteRegion
.Right
; ++X
)
706 Ptr
->Char
.UnicodeChar
= CurCharInfo
->Char
.UnicodeChar
;
710 ConsoleAnsiCharToUnicodeChar(Console
, &Ptr
->Char
.UnicodeChar
, &CurCharInfo
->Char
.AsciiChar
);
712 Ptr
->Attributes
= CurCharInfo
->Attributes
;
718 TermDrawRegion(Console
, &CapturedWriteRegion
);
720 *WriteRegion
= CapturedWriteRegion
;
722 return STATUS_SUCCESS
;
726 * NOTE: This function is strongly inspired by ConDrvWriteConsoleOutput...
729 ConDrvWriteConsoleOutputVDM(IN PCONSOLE Console
,
730 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
731 IN PCHAR_CELL CharInfo
/*Buffer*/,
732 IN COORD CharInfoSize
,
733 IN OUT PSMALL_RECT WriteRegion
,
734 IN BOOLEAN DrawRegion
)
737 SMALL_RECT ScreenBuffer
;
738 PCHAR_CELL CurCharInfo
;
739 SMALL_RECT CapturedWriteRegion
;
742 if (Console
== NULL
|| Buffer
== NULL
|| CharInfo
== NULL
|| WriteRegion
== NULL
)
744 return STATUS_INVALID_PARAMETER
;
748 ASSERT(Console
== Buffer
->Header
.Console
);
750 CapturedWriteRegion
= *WriteRegion
;
752 /* Make sure WriteRegion is inside the screen buffer */
753 ConioInitRect(&ScreenBuffer
, 0, 0,
754 Buffer
->ScreenBufferSize
.Y
- 1, Buffer
->ScreenBufferSize
.X
- 1);
755 if (!ConioGetIntersection(&CapturedWriteRegion
, &ScreenBuffer
, &CapturedWriteRegion
))
758 * It is okay to have a WriteRegion completely outside
759 * the screen buffer. No data is written then.
761 return STATUS_SUCCESS
;
764 // CurCharInfo = CharInfo;
766 for (Y
= CapturedWriteRegion
.Top
; Y
<= CapturedWriteRegion
.Bottom
; ++Y
)
768 /**/CurCharInfo
= CharInfo
+ Y
* CharInfoSize
.X
+ CapturedWriteRegion
.Left
;/**/
770 Ptr
= ConioCoordToPointer(Buffer
, CapturedWriteRegion
.Left
, Y
);
771 for (X
= CapturedWriteRegion
.Left
; X
<= CapturedWriteRegion
.Right
; ++X
)
773 ConsoleAnsiCharToUnicodeChar(Console
, &Ptr
->Char
.UnicodeChar
, &CurCharInfo
->Char
);
774 Ptr
->Attributes
= CurCharInfo
->Attributes
;
780 if (DrawRegion
) TermDrawRegion(Console
, &CapturedWriteRegion
);
782 *WriteRegion
= CapturedWriteRegion
;
784 return STATUS_SUCCESS
;
788 ConDrvWriteConsole(IN PCONSOLE Console
,
789 IN PTEXTMODE_SCREEN_BUFFER ScreenBuffer
,
791 IN PVOID StringBuffer
,
792 IN ULONG NumCharsToWrite
,
793 OUT PULONG NumCharsWritten OPTIONAL
)
795 NTSTATUS Status
= STATUS_SUCCESS
;
796 PWCHAR Buffer
= NULL
;
800 if (Console
== NULL
|| ScreenBuffer
== NULL
/* || StringBuffer == NULL */)
801 return STATUS_INVALID_PARAMETER
;
803 /* Validity checks */
804 ASSERT(Console
== ScreenBuffer
->Header
.Console
);
805 ASSERT((StringBuffer
!= NULL
) || (StringBuffer
== NULL
&& NumCharsToWrite
== 0));
807 /* Stop here if the console is paused */
808 if (Console
->UnpauseEvent
!= NULL
) return STATUS_PENDING
;
812 Buffer
= StringBuffer
;
816 Length
= MultiByteToWideChar(Console
->OutputCodePage
, 0,
820 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, Length
* sizeof(WCHAR
));
823 MultiByteToWideChar(Console
->OutputCodePage
, 0,
826 (PWCHAR
)Buffer
, Length
);
830 Status
= STATUS_NO_MEMORY
;
836 if (NT_SUCCESS(Status
))
838 Status
= ConioWriteConsole(Console
,
843 if (NT_SUCCESS(Status
))
845 Written
= NumCharsToWrite
;
849 if (!Unicode
) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer
);
852 if (NumCharsWritten
) *NumCharsWritten
= Written
;
858 ConDrvReadConsoleOutputString(IN PCONSOLE Console
,
859 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
860 IN CODE_TYPE CodeType
,
861 OUT PVOID StringBuffer
,
862 IN ULONG NumCodesToRead
,
864 // OUT PCOORD EndCoord,
865 OUT PULONG NumCodesRead OPTIONAL
)
873 if (Console
== NULL
|| Buffer
== NULL
|| ReadCoord
== NULL
/* || EndCoord == NULL */)
875 return STATUS_INVALID_PARAMETER
;
878 /* Validity checks */
879 ASSERT(Console
== Buffer
->Header
.Console
);
880 ASSERT((StringBuffer
!= NULL
) || (StringBuffer
== NULL
&& NumCodesToRead
== 0));
882 if (NumCodesRead
) *NumCodesRead
= 0;
887 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, AsciiChar
);
891 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, UnicodeChar
);
895 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, Attribute
);
899 return STATUS_INVALID_PARAMETER
;
902 ReadBuffer
= StringBuffer
;
904 Ypos
= (ReadCoord
->Y
+ Buffer
->VirtualY
) % Buffer
->ScreenBufferSize
.Y
;
907 * MSDN (ReadConsoleOutputAttribute and ReadConsoleOutputCharacter) :
909 * If the number of attributes (resp. characters) to be read from extends
910 * beyond the end of the specified screen buffer row, attributes (resp.
911 * characters) are read from the next row. If the number of attributes
912 * (resp. characters) to be read from extends beyond the end of the console
913 * screen buffer, attributes (resp. characters) up to the end of the console
914 * screen buffer are read.
916 * TODO: Do NOT loop up to NumCodesToRead, but stop before
917 * if we are going to overflow...
919 // Ptr = ConioCoordToPointer(Buffer, Xpos, Ypos); // Doesn't work
920 for (i
= 0; i
< min(NumCodesToRead
, Buffer
->ScreenBufferSize
.X
* Buffer
->ScreenBufferSize
.Y
); ++i
)
922 // Ptr = ConioCoordToPointer(Buffer, Xpos, Ypos); // Doesn't work either
923 Ptr
= &Buffer
->Buffer
[Xpos
+ Ypos
* Buffer
->ScreenBufferSize
.X
];
928 ConsoleUnicodeCharToAnsiChar(Console
, (PCHAR
)ReadBuffer
, &Ptr
->Char
.UnicodeChar
);
932 *(PWCHAR
)ReadBuffer
= Ptr
->Char
.UnicodeChar
;
936 *(PWORD
)ReadBuffer
= Ptr
->Attributes
;
939 ReadBuffer
= (PVOID
)((ULONG_PTR
)ReadBuffer
+ CodeSize
);
944 if (Xpos
== Buffer
->ScreenBufferSize
.X
)
949 if (Ypos
== Buffer
->ScreenBufferSize
.Y
)
956 // EndCoord->X = Xpos;
957 // EndCoord->Y = (Ypos - Buffer->VirtualY + Buffer->ScreenBufferSize.Y) % Buffer->ScreenBufferSize.Y;
960 *NumCodesRead
= (ULONG
)((ULONG_PTR
)ReadBuffer
- (ULONG_PTR
)StringBuffer
) / CodeSize
;
963 return STATUS_SUCCESS
;
967 ConDrvWriteConsoleOutputString(IN PCONSOLE Console
,
968 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
969 IN CODE_TYPE CodeType
,
970 IN PVOID StringBuffer
,
971 IN ULONG NumCodesToWrite
,
972 IN PCOORD WriteCoord
,
973 // OUT PCOORD EndCoord,
974 OUT PULONG NumCodesWritten OPTIONAL
)
976 NTSTATUS Status
= STATUS_SUCCESS
;
977 PVOID WriteBuffer
= NULL
;
978 PWCHAR tmpString
= NULL
;
979 DWORD X
, Y
, Length
; // , Written = 0;
983 if (Console
== NULL
|| Buffer
== NULL
|| WriteCoord
== NULL
/* || EndCoord == NULL */)
985 return STATUS_INVALID_PARAMETER
;
988 /* Validity checks */
989 ASSERT(Console
== Buffer
->Header
.Console
);
990 ASSERT((StringBuffer
!= NULL
) || (StringBuffer
== NULL
&& NumCodesToWrite
== 0));
992 if (NumCodesWritten
) *NumCodesWritten
= 0;
997 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, AsciiChar
);
1001 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, UnicodeChar
);
1004 case CODE_ATTRIBUTE
:
1005 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, Attribute
);
1009 return STATUS_INVALID_PARAMETER
;
1012 if (CodeType
== CODE_ASCII
)
1014 /* Convert the ASCII string into Unicode before writing it to the console */
1015 Length
= MultiByteToWideChar(Console
->OutputCodePage
, 0,
1016 (PCHAR
)StringBuffer
,
1019 tmpString
= WriteBuffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, Length
* sizeof(WCHAR
));
1022 MultiByteToWideChar(Console
->OutputCodePage
, 0,
1023 (PCHAR
)StringBuffer
,
1025 (PWCHAR
)WriteBuffer
, Length
);
1029 Status
= STATUS_NO_MEMORY
;
1032 // FIXME: Quick fix: fix the CodeType and CodeSize since the
1033 // ASCII string was converted into UNICODE.
1034 // A proper fix needs to be written.
1035 CodeType
= CODE_UNICODE
;
1036 CodeSize
= RTL_FIELD_SIZE(CODE_ELEMENT
, UnicodeChar
);
1040 /* For CODE_UNICODE or CODE_ATTRIBUTE, we are already OK */
1041 WriteBuffer
= StringBuffer
;
1044 if (WriteBuffer
== NULL
|| !NT_SUCCESS(Status
)) goto Cleanup
;
1047 Y
= (WriteCoord
->Y
+ Buffer
->VirtualY
) % Buffer
->ScreenBufferSize
.Y
;
1048 Length
= NumCodesToWrite
;
1049 // Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work
1050 // Ptr = &Buffer->Buffer[X + Y * Buffer->ScreenBufferSize.X]; // May work
1054 // Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work either
1055 Ptr
= &Buffer
->Buffer
[X
+ Y
* Buffer
->ScreenBufferSize
.X
];
1061 Ptr
->Char
.UnicodeChar
= *(PWCHAR
)WriteBuffer
;
1064 case CODE_ATTRIBUTE
:
1065 Ptr
->Attributes
= *(PWORD
)WriteBuffer
;
1068 WriteBuffer
= (PVOID
)((ULONG_PTR
)WriteBuffer
+ CodeSize
);
1072 if (++X
== Buffer
->ScreenBufferSize
.X
)
1076 if (++Y
== Buffer
->ScreenBufferSize
.Y
)
1083 if ((PCONSOLE_SCREEN_BUFFER
)Buffer
== Console
->ActiveBuffer
)
1085 SMALL_RECT UpdateRect
;
1086 ConioComputeUpdateRect(Buffer
, &UpdateRect
, WriteCoord
, NumCodesToWrite
);
1087 TermDrawRegion(Console
, &UpdateRect
);
1091 // EndCoord->Y = (Y + Buffer->ScreenBufferSize.Y - Buffer->VirtualY) % Buffer->ScreenBufferSize.Y;
1094 if (tmpString
) RtlFreeHeap(RtlGetProcessHeap(), 0, tmpString
);
1096 if (NumCodesWritten
) *NumCodesWritten
= NumCodesToWrite
; // Written;
1101 ConDrvFillConsoleOutput(IN PCONSOLE Console
,
1102 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
1103 IN CODE_TYPE CodeType
,
1104 IN CODE_ELEMENT Code
,
1105 IN ULONG NumCodesToWrite
,
1106 IN PCOORD WriteCoord
,
1107 OUT PULONG NumCodesWritten OPTIONAL
)
1109 DWORD X
, Y
, Length
; // , Written = 0;
1112 if (Console
== NULL
|| Buffer
== NULL
|| WriteCoord
== NULL
)
1114 return STATUS_INVALID_PARAMETER
;
1117 /* Validity check */
1118 ASSERT(Console
== Buffer
->Header
.Console
);
1120 if (NumCodesWritten
) *NumCodesWritten
= 0;
1122 if (CodeType
== CODE_ASCII
)
1124 /* Conversion from the ASCII char to the UNICODE char */
1126 ConsoleAnsiCharToUnicodeChar(Console
, &tmp
.UnicodeChar
, &Code
.AsciiChar
);
1131 Y
= (WriteCoord
->Y
+ Buffer
->VirtualY
) % Buffer
->ScreenBufferSize
.Y
;
1132 Length
= NumCodesToWrite
;
1133 // Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work
1134 // Ptr = &Buffer->Buffer[X + Y * Buffer->ScreenBufferSize.X]; // May work
1138 // Ptr = ConioCoordToPointer(Buffer, X, Y); // Doesn't work either
1139 Ptr
= &Buffer
->Buffer
[X
+ Y
* Buffer
->ScreenBufferSize
.X
];
1145 Ptr
->Char
.UnicodeChar
= Code
.UnicodeChar
;
1148 case CODE_ATTRIBUTE
:
1149 Ptr
->Attributes
= Code
.Attribute
;
1155 if (++X
== Buffer
->ScreenBufferSize
.X
)
1159 if (++Y
== Buffer
->ScreenBufferSize
.Y
)
1166 if ((PCONSOLE_SCREEN_BUFFER
)Buffer
== Console
->ActiveBuffer
)
1168 SMALL_RECT UpdateRect
;
1169 ConioComputeUpdateRect(Buffer
, &UpdateRect
, WriteCoord
, NumCodesToWrite
);
1170 TermDrawRegion(Console
, &UpdateRect
);
1173 if (NumCodesWritten
) *NumCodesWritten
= NumCodesToWrite
; // Written;
1174 return STATUS_SUCCESS
;
1178 ConDrvGetConsoleScreenBufferInfo(IN PCONSOLE Console
,
1179 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
1180 OUT PCOORD ScreenBufferSize
,
1181 OUT PCOORD CursorPosition
,
1182 OUT PCOORD ViewOrigin
,
1183 OUT PCOORD ViewSize
,
1184 OUT PCOORD MaximumViewSize
,
1185 OUT PWORD Attributes
)
1187 if (Console
== NULL
|| Buffer
== NULL
|| ScreenBufferSize
== NULL
||
1188 CursorPosition
== NULL
|| ViewOrigin
== NULL
|| ViewSize
== NULL
||
1189 MaximumViewSize
== NULL
|| Attributes
== NULL
)
1191 return STATUS_INVALID_PARAMETER
;
1194 /* Validity check */
1195 ASSERT(Console
== Buffer
->Header
.Console
);
1197 *ScreenBufferSize
= Buffer
->ScreenBufferSize
;
1198 *CursorPosition
= Buffer
->CursorPosition
;
1199 *ViewOrigin
= Buffer
->ViewOrigin
;
1200 *ViewSize
= Buffer
->ViewSize
;
1201 *Attributes
= Buffer
->ScreenDefaultAttrib
;
1203 // FIXME: Refine the computation
1204 *MaximumViewSize
= Buffer
->ScreenBufferSize
;
1206 return STATUS_SUCCESS
;
1210 ConDrvSetConsoleTextAttribute(IN PCONSOLE Console
,
1211 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
1214 if (Console
== NULL
|| Buffer
== NULL
)
1215 return STATUS_INVALID_PARAMETER
;
1217 /* Validity check */
1218 ASSERT(Console
== Buffer
->Header
.Console
);
1220 Buffer
->ScreenDefaultAttrib
= Attributes
;
1221 return STATUS_SUCCESS
;
1225 ConDrvSetConsoleScreenBufferSize(IN PCONSOLE Console
,
1226 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
1231 if (Console
== NULL
|| Buffer
== NULL
|| Size
== NULL
)
1232 return STATUS_INVALID_PARAMETER
;
1234 /* Validity check */
1235 ASSERT(Console
== Buffer
->Header
.Console
);
1237 Status
= ConioResizeBuffer(Console
, Buffer
, *Size
);
1238 if (NT_SUCCESS(Status
)) TermResizeTerminal(Console
);
1244 ConDrvScrollConsoleScreenBuffer(IN PCONSOLE Console
,
1245 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
1247 IN PSMALL_RECT ScrollRectangle
,
1248 IN BOOLEAN UseClipRectangle
,
1249 IN PSMALL_RECT ClipRectangle OPTIONAL
,
1250 IN PCOORD DestinationOrigin
,
1251 IN CHAR_INFO FillChar
)
1253 COORD CapturedDestinationOrigin
;
1254 SMALL_RECT ScreenBuffer
;
1255 SMALL_RECT SrcRegion
;
1256 SMALL_RECT DstRegion
;
1257 SMALL_RECT UpdateRegion
;
1258 SMALL_RECT CapturedClipRectangle
;
1260 if (Console
== NULL
|| Buffer
== NULL
|| ScrollRectangle
== NULL
||
1261 (UseClipRectangle
? ClipRectangle
== NULL
: FALSE
) || DestinationOrigin
== NULL
)
1263 return STATUS_INVALID_PARAMETER
;
1266 /* Validity check */
1267 ASSERT(Console
== Buffer
->Header
.Console
);
1269 CapturedDestinationOrigin
= *DestinationOrigin
;
1271 /* Make sure the source rectangle is inside the screen buffer */
1272 ConioInitRect(&ScreenBuffer
, 0, 0,
1273 Buffer
->ScreenBufferSize
.Y
- 1, Buffer
->ScreenBufferSize
.X
- 1);
1274 if (!ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, ScrollRectangle
))
1276 return STATUS_SUCCESS
;
1279 /* If the source was clipped on the left or top, adjust the destination accordingly */
1280 if (ScrollRectangle
->Left
< 0)
1282 CapturedDestinationOrigin
.X
-= ScrollRectangle
->Left
;
1284 if (ScrollRectangle
->Top
< 0)
1286 CapturedDestinationOrigin
.Y
-= ScrollRectangle
->Top
;
1289 if (UseClipRectangle
)
1291 CapturedClipRectangle
= *ClipRectangle
;
1292 if (!ConioGetIntersection(&CapturedClipRectangle
, &CapturedClipRectangle
, &ScreenBuffer
))
1294 return STATUS_SUCCESS
;
1299 CapturedClipRectangle
= ScreenBuffer
;
1302 ConioInitRect(&DstRegion
,
1303 CapturedDestinationOrigin
.Y
,
1304 CapturedDestinationOrigin
.X
,
1305 CapturedDestinationOrigin
.Y
+ ConioRectHeight(&SrcRegion
) - 1,
1306 CapturedDestinationOrigin
.X
+ ConioRectWidth(&SrcRegion
) - 1);
1311 ConsoleAnsiCharToUnicodeChar(Console
, &tmp
, &FillChar
.Char
.AsciiChar
);
1312 FillChar
.Char
.UnicodeChar
= tmp
;
1315 ConioMoveRegion(Buffer
, &SrcRegion
, &DstRegion
, &CapturedClipRectangle
, FillChar
);
1317 if ((PCONSOLE_SCREEN_BUFFER
)Buffer
== Console
->ActiveBuffer
)
1319 ConioGetUnion(&UpdateRegion
, &SrcRegion
, &DstRegion
);
1320 if (ConioGetIntersection(&UpdateRegion
, &UpdateRegion
, &CapturedClipRectangle
))
1322 /* Draw update region */
1323 TermDrawRegion(Console
, &UpdateRegion
);
1327 return STATUS_SUCCESS
;
1331 ConDrvSetConsoleWindowInfo(IN PCONSOLE Console
,
1332 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
1333 IN BOOLEAN Absolute
,
1334 IN PSMALL_RECT WindowRect
)
1336 SMALL_RECT CapturedWindowRect
;
1338 if (Console
== NULL
|| Buffer
== NULL
|| WindowRect
== NULL
)
1339 return STATUS_INVALID_PARAMETER
;
1341 /* Validity check */
1342 ASSERT(Console
== Buffer
->Header
.Console
);
1344 CapturedWindowRect
= *WindowRect
;
1346 if (Absolute
== FALSE
)
1348 /* Relative positions given. Transform them to absolute ones */
1349 CapturedWindowRect
.Left
+= Buffer
->ViewOrigin
.X
;
1350 CapturedWindowRect
.Top
+= Buffer
->ViewOrigin
.Y
;
1351 CapturedWindowRect
.Right
+= Buffer
->ViewOrigin
.X
+ Buffer
->ViewSize
.X
- 1;
1352 CapturedWindowRect
.Bottom
+= Buffer
->ViewOrigin
.Y
+ Buffer
->ViewSize
.Y
- 1;
1355 /* See MSDN documentation on SetConsoleWindowInfo about the performed checks */
1356 if ( (CapturedWindowRect
.Left
< 0) || (CapturedWindowRect
.Top
< 0) ||
1357 (CapturedWindowRect
.Right
>= Buffer
->ScreenBufferSize
.X
) ||
1358 (CapturedWindowRect
.Bottom
>= Buffer
->ScreenBufferSize
.Y
) ||
1359 (CapturedWindowRect
.Right
<= CapturedWindowRect
.Left
) ||
1360 (CapturedWindowRect
.Bottom
<= CapturedWindowRect
.Top
) )
1362 return STATUS_INVALID_PARAMETER
;
1365 Buffer
->ViewOrigin
.X
= CapturedWindowRect
.Left
;
1366 Buffer
->ViewOrigin
.Y
= CapturedWindowRect
.Top
;
1368 Buffer
->ViewSize
.X
= CapturedWindowRect
.Right
- CapturedWindowRect
.Left
+ 1;
1369 Buffer
->ViewSize
.Y
= CapturedWindowRect
.Bottom
- CapturedWindowRect
.Top
+ 1;
1371 // TermResizeTerminal(Console);
1373 return STATUS_SUCCESS
;