2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/consrv/conoutput.c
5 * PURPOSE: Console I/O functions
9 /* INCLUDES *******************************************************************/
18 /* GLOBALS ********************************************************************/
20 #define ConioInitRect(Rect, top, left, bottom, right) \
22 ((Rect)->Top) = top; \
23 ((Rect)->Left) = left; \
24 ((Rect)->Bottom) = bottom; \
25 ((Rect)->Right) = right; \
28 #define ConioIsRectEmpty(Rect) \
29 (((Rect)->Left > (Rect)->Right) || ((Rect)->Top > (Rect)->Bottom))
31 #define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
32 WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
34 #define ConsoleAnsiCharToUnicodeChar(Console, dWChar, sChar) \
35 MultiByteToWideChar((Console)->OutputCodePage, 0, (sChar), 1, (dWChar), 1)
38 /* PRIVATE FUNCTIONS **********************************************************/
41 ConioCoordToPointer(PCSRSS_SCREEN_BUFFER Buff
, ULONG X
, ULONG Y
)
43 return &Buff
->Buffer
[2 * (((Y
+ Buff
->VirtualY
) % Buff
->MaxY
) * Buff
->MaxX
+ X
)];
47 ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff
)
49 PBYTE Ptr
= ConioCoordToPointer(Buff
, 0, Buff
->CurrentY
);
52 for (Pos
= 0; Pos
< Buff
->MaxX
; Pos
++)
56 *Ptr
++ = Buff
->DefaultAttrib
;
61 CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console
,
62 PCSRSS_SCREEN_BUFFER Buffer
)
64 DPRINT("CsrInitConsoleScreenBuffer Size X %d Size Y %d\n", Buffer
->MaxX
, Buffer
->MaxY
);
66 Buffer
->Header
.Type
= CONIO_SCREEN_BUFFER_MAGIC
;
67 Buffer
->Header
.Console
= Console
;
68 Buffer
->Header
.HandleCount
= 0;
72 Buffer
->Buffer
= HeapAlloc(ConSrvHeap
, HEAP_ZERO_MEMORY
, Buffer
->MaxX
* Buffer
->MaxY
* 2);
73 if (NULL
== Buffer
->Buffer
)
75 return STATUS_INSUFFICIENT_RESOURCES
;
77 ConioInitScreenBuffer(Console
, Buffer
);
78 /* initialize buffer to be empty with default attributes */
79 for (Buffer
->CurrentY
= 0 ; Buffer
->CurrentY
< Buffer
->MaxY
; Buffer
->CurrentY
++)
81 ClearLineBuffer(Buffer
);
83 Buffer
->Mode
= ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
;
87 InsertHeadList(&Console
->BufferList
, &Buffer
->ListEntry
);
88 return STATUS_SUCCESS
;
92 ConioNextLine(PCSRSS_SCREEN_BUFFER Buff
, SMALL_RECT
*UpdateRect
, UINT
*ScrolledLines
)
94 /* If we hit bottom, slide the viewable screen */
95 if (++Buff
->CurrentY
== Buff
->MaxY
)
98 if (++Buff
->VirtualY
== Buff
->MaxY
)
103 ClearLineBuffer(Buff
);
104 if (UpdateRect
->Top
!= 0)
109 UpdateRect
->Left
= 0;
110 UpdateRect
->Right
= Buff
->MaxX
- 1;
111 UpdateRect
->Bottom
= Buff
->CurrentY
;
115 ConioWriteConsole(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
,
116 CHAR
*Buffer
, DWORD Length
, BOOL Attrib
)
120 SMALL_RECT UpdateRect
;
121 LONG CursorStartX
, CursorStartY
;
124 CursorStartX
= Buff
->CurrentX
;
125 CursorStartY
= Buff
->CurrentY
;
126 UpdateRect
.Left
= Buff
->MaxX
;
127 UpdateRect
.Top
= Buff
->CurrentY
;
128 UpdateRect
.Right
= -1;
129 UpdateRect
.Bottom
= Buff
->CurrentY
;
132 for (i
= 0; i
< Length
; i
++)
134 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
137 if (Buffer
[i
] == '\n')
140 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
144 else if (Buffer
[i
] == '\b')
146 /* Only handle BS if we're not on the first pos of the first line */
147 if (0 != Buff
->CurrentX
|| 0 != Buff
->CurrentY
)
149 if (0 == Buff
->CurrentX
)
151 /* slide virtual position up */
152 Buff
->CurrentX
= Buff
->MaxX
- 1;
154 UpdateRect
.Top
= min(UpdateRect
.Top
, (LONG
)Buff
->CurrentY
);
160 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
162 Ptr
[1] = Buff
->DefaultAttrib
;
163 UpdateRect
.Left
= min(UpdateRect
.Left
, (LONG
) Buff
->CurrentX
);
164 UpdateRect
.Right
= max(UpdateRect
.Right
, (LONG
) Buff
->CurrentX
);
169 else if (Buffer
[i
] == '\r')
172 UpdateRect
.Left
= min(UpdateRect
.Left
, (LONG
) Buff
->CurrentX
);
173 UpdateRect
.Right
= max(UpdateRect
.Right
, (LONG
) Buff
->CurrentX
);
177 else if (Buffer
[i
] == '\t')
181 UpdateRect
.Left
= min(UpdateRect
.Left
, (LONG
)Buff
->CurrentX
);
182 EndX
= (Buff
->CurrentX
+ 8) & ~7;
183 if (EndX
> Buff
->MaxX
)
187 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
188 while (Buff
->CurrentX
< EndX
)
191 *Ptr
++ = Buff
->DefaultAttrib
;
194 UpdateRect
.Right
= max(UpdateRect
.Right
, (LONG
) Buff
->CurrentX
- 1);
195 if (Buff
->CurrentX
== Buff
->MaxX
)
197 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
200 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
210 UpdateRect
.Left
= min(UpdateRect
.Left
, (LONG
)Buff
->CurrentX
);
211 UpdateRect
.Right
= max(UpdateRect
.Right
, (LONG
) Buff
->CurrentX
);
212 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
216 Ptr
[1] = Buff
->DefaultAttrib
;
219 if (Buff
->CurrentX
== Buff
->MaxX
)
221 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
224 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
228 Buff
->CurrentX
= CursorStartX
;
233 if (! ConioIsRectEmpty(&UpdateRect
) && Buff
== Console
->ActiveBuffer
)
235 ConioWriteStream(Console
, &UpdateRect
, CursorStartX
, CursorStartY
, ScrolledLines
,
239 return STATUS_SUCCESS
;
242 __inline BOOLEAN
ConioGetIntersection(
243 SMALL_RECT
*Intersection
,
247 if (ConioIsRectEmpty(Rect1
) ||
248 (ConioIsRectEmpty(Rect2
)) ||
249 (Rect1
->Top
> Rect2
->Bottom
) ||
250 (Rect1
->Left
> Rect2
->Right
) ||
251 (Rect1
->Bottom
< Rect2
->Top
) ||
252 (Rect1
->Right
< Rect2
->Left
))
254 /* The rectangles do not intersect */
255 ConioInitRect(Intersection
, 0, -1, 0, -1);
259 ConioInitRect(Intersection
,
260 max(Rect1
->Top
, Rect2
->Top
),
261 max(Rect1
->Left
, Rect2
->Left
),
262 min(Rect1
->Bottom
, Rect2
->Bottom
),
263 min(Rect1
->Right
, Rect2
->Right
));
268 __inline BOOLEAN
ConioGetUnion(
273 if (ConioIsRectEmpty(Rect1
))
275 if (ConioIsRectEmpty(Rect2
))
277 ConioInitRect(Union
, 0, -1, 0, -1);
285 else if (ConioIsRectEmpty(Rect2
))
292 min(Rect1
->Top
, Rect2
->Top
),
293 min(Rect1
->Left
, Rect2
->Left
),
294 max(Rect1
->Bottom
, Rect2
->Bottom
),
295 max(Rect1
->Right
, Rect2
->Right
));
302 * Move from one rectangle to another. We must be careful about the order that
303 * this is done, to avoid overwriting parts of the source before they are moved.
306 ConioMoveRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer
,
307 SMALL_RECT
*SrcRegion
,
308 SMALL_RECT
*DstRegion
,
309 SMALL_RECT
*ClipRegion
,
312 int Width
= ConioRectWidth(SrcRegion
);
313 int Height
= ConioRectHeight(SrcRegion
);
324 /* Moving down: work from bottom up */
325 SY
= SrcRegion
->Bottom
;
326 DY
= DstRegion
->Bottom
;
329 for (i
= 0; i
< Height
; i
++)
331 PWORD SRow
= (PWORD
)ConioCoordToPointer(ScreenBuffer
, 0, SY
);
332 PWORD DRow
= (PWORD
)ConioCoordToPointer(ScreenBuffer
, 0, DY
);
334 SX
= SrcRegion
->Left
;
335 DX
= DstRegion
->Left
;
339 /* Moving right: work from right to left */
340 SX
= SrcRegion
->Right
;
341 DX
= DstRegion
->Right
;
344 for (j
= 0; j
< Width
; j
++)
346 WORD Cell
= SRow
[SX
];
347 if (SX
>= ClipRegion
->Left
&& SX
<= ClipRegion
->Right
348 && SY
>= ClipRegion
->Top
&& SY
<= ClipRegion
->Bottom
)
352 if (DX
>= ClipRegion
->Left
&& DX
<= ClipRegion
->Right
353 && DY
>= ClipRegion
->Top
&& DY
<= ClipRegion
->Bottom
)
366 ConioDeleteScreenBuffer(PCSRSS_SCREEN_BUFFER Buffer
)
368 PCSRSS_CONSOLE Console
= Buffer
->Header
.Console
;
370 RemoveEntryList(&Buffer
->ListEntry
);
371 if (Buffer
== Console
->ActiveBuffer
)
373 /* Deleted active buffer; switch to most recently created */
374 Console
->ActiveBuffer
= NULL
;
375 if (!IsListEmpty(&Console
->BufferList
))
377 Console
->ActiveBuffer
= CONTAINING_RECORD(Console
->BufferList
.Flink
, CSRSS_SCREEN_BUFFER
, ListEntry
);
378 ConioDrawConsole(Console
);
382 HeapFree(ConSrvHeap
, 0, Buffer
->Buffer
);
383 HeapFree(ConSrvHeap
, 0, Buffer
);
387 ConioDrawConsole(PCSRSS_CONSOLE Console
)
391 ConioInitRect(&Region
, 0, 0, Console
->Size
.Y
- 1, Console
->Size
.X
- 1);
393 ConioDrawRegion(Console
, &Region
);
397 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff
, SMALL_RECT
*UpdateRect
, COORD
*Start
, UINT Length
)
399 if (Buff
->MaxX
<= Start
->X
+ Length
)
401 UpdateRect
->Left
= 0;
405 UpdateRect
->Left
= Start
->X
;
407 if (Buff
->MaxX
<= Start
->X
+ Length
)
409 UpdateRect
->Right
= Buff
->MaxX
- 1;
413 UpdateRect
->Right
= Start
->X
+ Length
- 1;
415 UpdateRect
->Top
= Start
->Y
;
416 UpdateRect
->Bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->MaxX
;
417 if (Buff
->MaxY
<= UpdateRect
->Bottom
)
419 UpdateRect
->Bottom
= Buff
->MaxY
- 1;
424 ConioEffectiveCursorSize(PCSRSS_CONSOLE Console
, DWORD Scale
)
426 DWORD Size
= (Console
->ActiveBuffer
->CursorInfo
.dwSize
* Scale
+ 99) / 100;
427 /* If line input in progress, perhaps adjust for insert toggle */
428 if (Console
->LineBuffer
&& !Console
->LineComplete
&& Console
->LineInsertToggle
)
429 return (Size
* 2 <= Scale
) ? (Size
* 2) : (Size
/ 2);
434 /* PUBLIC APIS ****************************************************************/
436 CSR_API(SrvReadConsoleOutput
)
438 PCSRSS_READ_CONSOLE_OUTPUT ReadConsoleOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ReadConsoleOutputRequest
;
439 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
441 PCHAR_INFO CurCharInfo
;
442 PCSRSS_SCREEN_BUFFER Buff
;
447 SMALL_RECT ReadRegion
;
448 SMALL_RECT ScreenRect
;
454 DPRINT("SrvReadConsoleOutput\n");
456 CharInfo
= ReadConsoleOutputRequest
->CharInfo
;
457 ReadRegion
= ReadConsoleOutputRequest
->ReadRegion
;
458 BufferSize
= ReadConsoleOutputRequest
->BufferSize
;
459 BufferCoord
= ReadConsoleOutputRequest
->BufferCoord
;
461 if (!CsrValidateMessageBuffer(ApiMessage
,
462 (PVOID
*)&ReadConsoleOutputRequest
->CharInfo
,
463 BufferSize
.X
* BufferSize
.Y
,
466 return STATUS_INVALID_PARAMETER
;
469 if (!Win32CsrValidateBuffer(ProcessData->Process, CharInfo,
470 BufferSize.X * BufferSize.Y, sizeof(CHAR_INFO)))
472 ConioUnlockScreenBuffer(Buff);
473 return STATUS_ACCESS_VIOLATION;
477 Status
= ConioLockScreenBuffer(ProcessData
, ReadConsoleOutputRequest
->ConsoleHandle
, &Buff
, GENERIC_READ
);
478 if (!NT_SUCCESS(Status
)) return Status
;
480 /* FIXME: Is this correct? */
481 CodePage
= ProcessData
->Console
->OutputCodePage
;
483 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&ReadRegion
));
484 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&ReadRegion
));
485 ReadRegion
.Bottom
= ReadRegion
.Top
+ SizeY
;
486 ReadRegion
.Right
= ReadRegion
.Left
+ SizeX
;
488 ConioInitRect(&ScreenRect
, 0, 0, Buff
->MaxY
, Buff
->MaxX
);
489 if (!ConioGetIntersection(&ReadRegion
, &ScreenRect
, &ReadRegion
))
491 ConioUnlockScreenBuffer(Buff
);
492 return STATUS_SUCCESS
;
495 for (i
= 0, Y
= ReadRegion
.Top
; Y
< ReadRegion
.Bottom
; ++i
, ++Y
)
497 CurCharInfo
= CharInfo
+ (i
* BufferSize
.X
);
499 Ptr
= ConioCoordToPointer(Buff
, ReadRegion
.Left
, Y
);
500 for (X
= ReadRegion
.Left
; X
< ReadRegion
.Right
; ++X
)
502 if (ReadConsoleOutputRequest
->Unicode
)
504 // ConsoleAnsiCharToUnicodeChar(ProcessData->Console, (PCHAR)Ptr++, &CurCharInfo->Char.UnicodeChar);
505 MultiByteToWideChar(CodePage
, 0,
507 &CurCharInfo
->Char
.UnicodeChar
, 1);
511 CurCharInfo
->Char
.AsciiChar
= *Ptr
++;
513 CurCharInfo
->Attributes
= *Ptr
++;
518 ConioUnlockScreenBuffer(Buff
);
520 ReadConsoleOutputRequest
->ReadRegion
.Right
= ReadRegion
.Left
+ SizeX
- 1;
521 ReadConsoleOutputRequest
->ReadRegion
.Bottom
= ReadRegion
.Top
+ SizeY
- 1;
522 ReadConsoleOutputRequest
->ReadRegion
.Left
= ReadRegion
.Left
;
523 ReadConsoleOutputRequest
->ReadRegion
.Top
= ReadRegion
.Top
;
525 return STATUS_SUCCESS
;
528 CSR_API(SrvWriteConsole
)
531 PCSRSS_WRITE_CONSOLE WriteConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteConsoleRequest
;
533 PCSRSS_SCREEN_BUFFER Buff
;
534 PCSR_PROCESS ProcessData
= CsrGetClientThread()->Process
;
535 PCSRSS_CONSOLE Console
;
538 ULONG CharSize
= (WriteConsoleRequest
->Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
540 DPRINT("SrvWriteConsole\n");
542 if (ApiMessage
->Header
.u1
.s1
.TotalLength
543 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE
)
544 + (WriteConsoleRequest
->NrCharactersToWrite
* CharSize
))
546 DPRINT1("Invalid ApiMessage size\n");
547 return STATUS_INVALID_PARAMETER
;
550 Status
= ConioLockScreenBuffer(ProcessData
, WriteConsoleRequest
->ConsoleHandle
, &Buff
, GENERIC_WRITE
);
551 if (! NT_SUCCESS(Status
))
555 Console
= Buff
->Header
.Console
;
557 if (Console
->UnpauseEvent
)
559 Status
= NtDuplicateObject(NtCurrentProcess(), Console
->UnpauseEvent
,
560 ProcessData
->ProcessHandle
, &WriteConsoleRequest
->UnpauseEvent
,
562 ConioUnlockScreenBuffer(Buff
);
563 return NT_SUCCESS(Status
) ? STATUS_PENDING
: Status
;
566 if(WriteConsoleRequest
->Unicode
)
568 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
569 (PWCHAR
)WriteConsoleRequest
->Buffer
,
570 WriteConsoleRequest
->NrCharactersToWrite
,
571 NULL
, 0, NULL
, NULL
);
572 Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
575 WideCharToMultiByte(Console
->OutputCodePage
, 0,
576 (PWCHAR
)WriteConsoleRequest
->Buffer
,
577 WriteConsoleRequest
->NrCharactersToWrite
,
578 Buffer
, Length
, NULL
, NULL
);
582 Status
= STATUS_NO_MEMORY
;
587 Buffer
= (PCHAR
)WriteConsoleRequest
->Buffer
;
592 if (NT_SUCCESS(Status
))
594 Status
= ConioWriteConsole(Console
, Buff
, Buffer
,
595 WriteConsoleRequest
->NrCharactersToWrite
, TRUE
);
596 if (NT_SUCCESS(Status
))
598 Written
= WriteConsoleRequest
->NrCharactersToWrite
;
601 if (WriteConsoleRequest
->Unicode
)
603 RtlFreeHeap(GetProcessHeap(), 0, Buffer
);
606 ConioUnlockScreenBuffer(Buff
);
608 WriteConsoleRequest
->NrCharactersWritten
= Written
;
613 CSR_API(SrvWriteConsoleOutput
)
615 PCSRSS_WRITE_CONSOLE_OUTPUT WriteConsoleOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteConsoleOutputRequest
;
616 SHORT i
, X
, Y
, SizeX
, SizeY
;
617 PCSR_PROCESS ProcessData
= CsrGetClientThread()->Process
;
618 PCSRSS_CONSOLE Console
;
619 PCSRSS_SCREEN_BUFFER Buff
;
620 SMALL_RECT ScreenBuffer
;
621 CHAR_INFO
* CurCharInfo
;
622 SMALL_RECT WriteRegion
;
629 DPRINT("SrvWriteConsoleOutput\n");
631 Status
= ConioLockScreenBuffer(ProcessData
,
632 WriteConsoleOutputRequest
->ConsoleHandle
,
635 if (! NT_SUCCESS(Status
))
639 Console
= Buff
->Header
.Console
;
641 BufferSize
= WriteConsoleOutputRequest
->BufferSize
;
642 BufferCoord
= WriteConsoleOutputRequest
->BufferCoord
;
643 CharInfo
= WriteConsoleOutputRequest
->CharInfo
;
644 if (!Win32CsrValidateBuffer(ProcessData
, CharInfo
,
645 BufferSize
.X
* BufferSize
.Y
, sizeof(CHAR_INFO
)))
647 ConioUnlockScreenBuffer(Buff
);
648 return STATUS_ACCESS_VIOLATION
;
650 WriteRegion
= WriteConsoleOutputRequest
->WriteRegion
;
652 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&WriteRegion
));
653 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&WriteRegion
));
654 WriteRegion
.Bottom
= WriteRegion
.Top
+ SizeY
- 1;
655 WriteRegion
.Right
= WriteRegion
.Left
+ SizeX
- 1;
657 /* Make sure WriteRegion is inside the screen buffer */
658 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
659 if (! ConioGetIntersection(&WriteRegion
, &ScreenBuffer
, &WriteRegion
))
661 ConioUnlockScreenBuffer(Buff
);
663 /* It is okay to have a WriteRegion completely outside the screen buffer.
664 No data is written then. */
665 return STATUS_SUCCESS
;
668 for (i
= 0, Y
= WriteRegion
.Top
; Y
<= WriteRegion
.Bottom
; i
++, Y
++)
670 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
671 Ptr
= ConioCoordToPointer(Buff
, WriteRegion
.Left
, Y
);
672 for (X
= WriteRegion
.Left
; X
<= WriteRegion
.Right
; X
++)
675 if (WriteConsoleOutputRequest
->Unicode
)
677 ConsoleUnicodeCharToAnsiChar(Console
, &AsciiChar
, &CurCharInfo
->Char
.UnicodeChar
);
681 AsciiChar
= CurCharInfo
->Char
.AsciiChar
;
684 *Ptr
++ = CurCharInfo
->Attributes
;
689 ConioDrawRegion(Console
, &WriteRegion
);
691 ConioUnlockScreenBuffer(Buff
);
693 WriteConsoleOutputRequest
->WriteRegion
.Right
= WriteRegion
.Left
+ SizeX
- 1;
694 WriteConsoleOutputRequest
->WriteRegion
.Bottom
= WriteRegion
.Top
+ SizeY
- 1;
695 WriteConsoleOutputRequest
->WriteRegion
.Left
= WriteRegion
.Left
;
696 WriteConsoleOutputRequest
->WriteRegion
.Top
= WriteRegion
.Top
;
698 return STATUS_SUCCESS
;
701 CSR_API(SrvReadConsoleOutputString
)
704 PCSRSS_READ_CONSOLE_OUTPUT_CODE ReadConsoleOutputCodeRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ReadConsoleOutputCodeRequest
;
705 PCSRSS_CONSOLE Console
;
706 PCSRSS_SCREEN_BUFFER Buff
;
714 DPRINT("SrvReadConsoleOutputString\n");
716 ReadBuffer
= ReadConsoleOutputCodeRequest
->pCode
.pCode
;
718 CodeType
= ReadConsoleOutputCodeRequest
->CodeType
;
722 CodeSize
= sizeof(CHAR
);
726 CodeSize
= sizeof(WCHAR
);
730 CodeSize
= sizeof(WORD
);
734 return STATUS_INVALID_PARAMETER
;
737 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), ReadConsoleOutputCodeRequest
->ConsoleHandle
, &Buff
, GENERIC_READ
);
738 if (!NT_SUCCESS(Status
)) return Status
;
740 Console
= Buff
->Header
.Console
;
742 Xpos
= ReadConsoleOutputCodeRequest
->ReadCoord
.X
;
743 Ypos
= (ReadConsoleOutputCodeRequest
->ReadCoord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
746 * MSDN (ReadConsoleOutputAttribute and ReadConsoleOutputCharacter) :
748 * If the number of attributes (resp. characters) to be read from extends
749 * beyond the end of the specified screen buffer row, attributes (resp.
750 * characters) are read from the next row. If the number of attributes
751 * (resp. characters) to be read from extends beyond the end of the console
752 * screen buffer, attributes (resp. characters) up to the end of the console
753 * screen buffer are read.
755 * TODO: Do NOT loop up to NumCodesToRead, but stop before
756 * if we are going to overflow...
758 for (i
= 0; i
< ReadConsoleOutputCodeRequest
->NumCodesToRead
; ++i
)
760 Code
= Buff
->Buffer
[2 * (Xpos
+ Ypos
* Buff
->MaxX
) + (CodeType
== CODE_ATTRIBUTE
? 1 : 0)];
765 ConsoleAnsiCharToUnicodeChar(Console
, (PWCHAR
)ReadBuffer
, (PCHAR
)&Code
);
769 *(PCHAR
)ReadBuffer
= (CHAR
)Code
;
773 *(PWORD
)ReadBuffer
= (WORD
)Code
;
776 ReadBuffer
= (PVOID
)((ULONG_PTR
)ReadBuffer
+ CodeSize
);
780 if (Xpos
== Buff
->MaxX
)
785 if (Ypos
== Buff
->MaxY
)
795 *(PWCHAR
)ReadBuffer
= 0;
799 *(PCHAR
)ReadBuffer
= 0;
803 *(PWORD
)ReadBuffer
= 0;
807 ReadConsoleOutputCodeRequest
->EndCoord
.X
= Xpos
;
808 ReadConsoleOutputCodeRequest
->EndCoord
.Y
= (Ypos
- Buff
->VirtualY
+ Buff
->MaxY
) % Buff
->MaxY
;
810 ConioUnlockScreenBuffer(Buff
);
812 ReadConsoleOutputCodeRequest
->CodesRead
= (DWORD
)((ULONG_PTR
)ReadBuffer
- (ULONG_PTR
)ReadConsoleOutputCodeRequest
->pCode
.pCode
) / CodeSize
;
813 // <= ReadConsoleOutputCodeRequest->NumCodesToRead
815 return STATUS_SUCCESS
;
818 CSR_API(CsrWriteConsoleOutputChar
)
821 PCSRSS_WRITE_CONSOLE_OUTPUT_CHAR WriteConsoleOutputCharRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteConsoleOutputCharRequest
;
822 PCHAR String
, tmpString
= NULL
;
824 PCSRSS_CONSOLE Console
;
825 PCSRSS_SCREEN_BUFFER Buff
;
826 DWORD X
, Y
, Length
, CharSize
, Written
= 0;
827 SMALL_RECT UpdateRect
;
829 DPRINT("CsrWriteConsoleOutputChar\n");
831 CharSize
= (WriteConsoleOutputCharRequest
->Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
833 if (ApiMessage
->Header
.u1
.s1
.TotalLength
834 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR
)
835 + (WriteConsoleOutputCharRequest
->Length
* CharSize
))
837 DPRINT1("Invalid ApiMessage size\n");
838 return STATUS_INVALID_PARAMETER
;
841 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
,
842 WriteConsoleOutputCharRequest
->ConsoleHandle
,
845 if (NT_SUCCESS(Status
))
847 Console
= Buff
->Header
.Console
;
848 if(WriteConsoleOutputCharRequest
->Unicode
)
850 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
851 (PWCHAR
)WriteConsoleOutputCharRequest
->String
,
852 WriteConsoleOutputCharRequest
->Length
,
853 NULL
, 0, NULL
, NULL
);
854 tmpString
= String
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
857 WideCharToMultiByte(Console
->OutputCodePage
, 0,
858 (PWCHAR
)WriteConsoleOutputCharRequest
->String
,
859 WriteConsoleOutputCharRequest
->Length
,
860 String
, Length
, NULL
, NULL
);
864 Status
= STATUS_NO_MEMORY
;
869 String
= (PCHAR
)WriteConsoleOutputCharRequest
->String
;
874 if (NT_SUCCESS(Status
))
876 X
= WriteConsoleOutputCharRequest
->Coord
.X
;
877 Y
= (WriteConsoleOutputCharRequest
->Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
878 Length
= WriteConsoleOutputCharRequest
->Length
;
879 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
885 if (++X
== Buff
->MaxX
)
887 if (++Y
== Buff
->MaxY
)
890 Buffer
= Buff
->Buffer
;
895 if (Buff
== Console
->ActiveBuffer
)
897 ConioComputeUpdateRect(Buff
, &UpdateRect
, &WriteConsoleOutputCharRequest
->Coord
,
898 WriteConsoleOutputCharRequest
->Length
);
899 ConioDrawRegion(Console
, &UpdateRect
);
902 WriteConsoleOutputCharRequest
->EndCoord
.X
= X
;
903 WriteConsoleOutputCharRequest
->EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->VirtualY
) % Buff
->MaxY
;
906 if (WriteConsoleOutputCharRequest
->Unicode
)
908 RtlFreeHeap(GetProcessHeap(), 0, tmpString
);
911 ConioUnlockScreenBuffer(Buff
);
913 WriteConsoleOutputCharRequest
->NrCharactersWritten
= Written
;
917 CSR_API(CsrWriteConsoleOutputAttrib
)
919 PCSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB WriteConsoleOutputAttribRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteConsoleOutputAttribRequest
;
920 PCSRSS_CONSOLE Console
;
921 PCSRSS_SCREEN_BUFFER Buff
;
926 SMALL_RECT UpdateRect
;
928 DPRINT("CsrWriteConsoleOutputAttrib\n");
930 if (ApiMessage
->Header
.u1
.s1
.TotalLength
931 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB
)
932 + WriteConsoleOutputAttribRequest
->Length
* sizeof(WORD
))
934 DPRINT1("Invalid ApiMessage size\n");
935 return STATUS_INVALID_PARAMETER
;
938 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
,
939 WriteConsoleOutputAttribRequest
->ConsoleHandle
,
942 if (! NT_SUCCESS(Status
))
946 Console
= Buff
->Header
.Console
;
948 X
= WriteConsoleOutputAttribRequest
->Coord
.X
;
949 Y
= (WriteConsoleOutputAttribRequest
->Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
950 Length
= WriteConsoleOutputAttribRequest
->Length
;
951 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + 1];
952 Attribute
= WriteConsoleOutputAttribRequest
->Attribute
;
955 *Buffer
= (UCHAR
)(*Attribute
++);
957 if (++X
== Buff
->MaxX
)
959 if (++Y
== Buff
->MaxY
)
962 Buffer
= Buff
->Buffer
+ 1;
968 if (Buff
== Console
->ActiveBuffer
)
970 ConioComputeUpdateRect(Buff
, &UpdateRect
, &WriteConsoleOutputAttribRequest
->Coord
,
971 WriteConsoleOutputAttribRequest
->Length
);
972 ConioDrawRegion(Console
, &UpdateRect
);
975 WriteConsoleOutputAttribRequest
->EndCoord
.X
= X
;
976 WriteConsoleOutputAttribRequest
->EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->VirtualY
) % Buff
->MaxY
;
978 ConioUnlockScreenBuffer(Buff
);
980 return STATUS_SUCCESS
;
983 CSR_API(CsrFillOutputChar
)
986 PCSRSS_FILL_OUTPUT FillOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.FillOutputRequest
;
987 PCSRSS_CONSOLE Console
;
988 PCSRSS_SCREEN_BUFFER Buff
;
989 DWORD X
, Y
, Length
, Written
= 0;
992 SMALL_RECT UpdateRect
;
994 DPRINT("CsrFillOutputChar\n");
996 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, FillOutputRequest
->ConsoleHandle
, &Buff
, GENERIC_WRITE
);
997 if (! NT_SUCCESS(Status
))
1001 Console
= Buff
->Header
.Console
;
1003 X
= FillOutputRequest
->Position
.X
;
1004 Y
= (FillOutputRequest
->Position
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1005 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1006 if(FillOutputRequest
->Unicode
)
1007 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &FillOutputRequest
->Char
.UnicodeChar
);
1009 Char
= FillOutputRequest
->Char
.AsciiChar
;
1010 Length
= FillOutputRequest
->Length
;
1016 if (++X
== Buff
->MaxX
)
1018 if (++Y
== Buff
->MaxY
)
1021 Buffer
= Buff
->Buffer
;
1027 if (Buff
== Console
->ActiveBuffer
)
1029 ConioComputeUpdateRect(Buff
, &UpdateRect
, &FillOutputRequest
->Position
,
1030 FillOutputRequest
->Length
);
1031 ConioDrawRegion(Console
, &UpdateRect
);
1034 ConioUnlockScreenBuffer(Buff
);
1035 Length
= FillOutputRequest
->Length
;
1036 FillOutputRequest
->NrCharactersWritten
= Length
;
1037 return STATUS_SUCCESS
;
1040 CSR_API(CsrFillOutputAttrib
)
1042 PCSRSS_FILL_OUTPUT_ATTRIB FillOutputAttribRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.FillOutputAttribRequest
;
1043 PCSRSS_SCREEN_BUFFER Buff
;
1048 SMALL_RECT UpdateRect
;
1049 PCSRSS_CONSOLE Console
;
1051 DPRINT("CsrFillOutputAttrib\n");
1053 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, FillOutputAttribRequest
->ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1054 if (! NT_SUCCESS(Status
))
1058 Console
= Buff
->Header
.Console
;
1060 X
= FillOutputAttribRequest
->Coord
.X
;
1061 Y
= (FillOutputAttribRequest
->Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1062 Length
= FillOutputAttribRequest
->Length
;
1063 Attr
= FillOutputAttribRequest
->Attribute
;
1064 Buffer
= &Buff
->Buffer
[(Y
* Buff
->MaxX
* 2) + (X
* 2) + 1];
1069 if (++X
== Buff
->MaxX
)
1071 if (++Y
== Buff
->MaxY
)
1074 Buffer
= Buff
->Buffer
+ 1;
1080 if (Buff
== Console
->ActiveBuffer
)
1082 ConioComputeUpdateRect(Buff
, &UpdateRect
, &FillOutputAttribRequest
->Coord
,
1083 FillOutputAttribRequest
->Length
);
1084 ConioDrawRegion(Console
, &UpdateRect
);
1087 ConioUnlockScreenBuffer(Buff
);
1089 return STATUS_SUCCESS
;
1092 CSR_API(SrvGetConsoleCursorInfo
)
1095 PCSRSS_CURSOR_INFO CursorInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CursorInfoRequest
;
1096 PCSRSS_SCREEN_BUFFER Buff
;
1098 DPRINT("SrvGetConsoleCursorInfo\n");
1100 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), CursorInfoRequest
->ConsoleHandle
, &Buff
, GENERIC_READ
);
1101 if (!NT_SUCCESS(Status
)) return Status
;
1103 CursorInfoRequest
->Info
.bVisible
= Buff
->CursorInfo
.bVisible
;
1104 CursorInfoRequest
->Info
.dwSize
= Buff
->CursorInfo
.dwSize
;
1105 ConioUnlockScreenBuffer(Buff
);
1107 return STATUS_SUCCESS
;
1110 CSR_API(SrvSetConsoleCursorInfo
)
1113 PCSRSS_CURSOR_INFO CursorInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CursorInfoRequest
;
1114 PCSRSS_CONSOLE Console
;
1115 PCSRSS_SCREEN_BUFFER Buff
;
1119 DPRINT("SrvSetConsoleCursorInfo\n");
1121 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), CursorInfoRequest
->ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1122 if (!NT_SUCCESS(Status
)) return Status
;
1124 Console
= Buff
->Header
.Console
;
1126 Size
= CursorInfoRequest
->Info
.dwSize
;
1127 Visible
= CursorInfoRequest
->Info
.bVisible
;
1137 if ( (Size
!= Buff
->CursorInfo
.dwSize
) ||
1138 (Visible
&& ! Buff
->CursorInfo
.bVisible
) ||
1139 (! Visible
&& Buff
->CursorInfo
.bVisible
) )
1141 Buff
->CursorInfo
.dwSize
= Size
;
1142 Buff
->CursorInfo
.bVisible
= Visible
;
1144 if (!ConioSetCursorInfo(Console
, Buff
))
1146 ConioUnlockScreenBuffer(Buff
);
1147 return STATUS_UNSUCCESSFUL
;
1151 ConioUnlockScreenBuffer(Buff
);
1153 return STATUS_SUCCESS
;
1156 CSR_API(SrvSetConsoleCursorPosition
)
1159 PCSRSS_SET_CURSOR_POSITION SetCursorPositionRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetCursorPositionRequest
;
1160 PCSRSS_CONSOLE Console
;
1161 PCSRSS_SCREEN_BUFFER Buff
;
1162 LONG OldCursorX
, OldCursorY
;
1163 LONG NewCursorX
, NewCursorY
;
1165 DPRINT("SrvSetConsoleCursorPosition\n");
1167 Status
= ConioLockScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process
), SetCursorPositionRequest
->ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1168 if (!NT_SUCCESS(Status
)) return Status
;
1170 Console
= Buff
->Header
.Console
;
1172 NewCursorX
= SetCursorPositionRequest
->Position
.X
;
1173 NewCursorY
= SetCursorPositionRequest
->Position
.Y
;
1174 if ( NewCursorX
< 0 || NewCursorX
>= Buff
->MaxX
||
1175 NewCursorY
< 0 || NewCursorY
>= Buff
->MaxY
)
1177 ConioUnlockScreenBuffer(Buff
);
1178 return STATUS_INVALID_PARAMETER
;
1180 OldCursorX
= Buff
->CurrentX
;
1181 OldCursorY
= Buff
->CurrentY
;
1182 Buff
->CurrentX
= NewCursorX
;
1183 Buff
->CurrentY
= NewCursorY
;
1184 if (Buff
== Console
->ActiveBuffer
)
1186 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
1188 ConioUnlockScreenBuffer(Buff
);
1189 return STATUS_UNSUCCESSFUL
;
1193 ConioUnlockScreenBuffer(Buff
);
1195 return STATUS_SUCCESS
;
1198 CSR_API(CsrSetTextAttrib
)
1201 PCSRSS_SET_ATTRIB SetAttribRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetAttribRequest
;
1202 PCSRSS_CONSOLE Console
;
1203 PCSRSS_SCREEN_BUFFER Buff
;
1205 DPRINT("CsrSetTextAttrib\n");
1207 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, SetAttribRequest
->ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1208 if (! NT_SUCCESS(Status
))
1212 Console
= Buff
->Header
.Console
;
1214 Buff
->DefaultAttrib
= SetAttribRequest
->Attrib
;
1215 if (Buff
== Console
->ActiveBuffer
)
1217 if (! ConioUpdateScreenInfo(Console
, Buff
))
1219 ConioUnlockScreenBuffer(Buff
);
1220 return STATUS_UNSUCCESSFUL
;
1224 ConioUnlockScreenBuffer(Buff
);
1226 return STATUS_SUCCESS
;
1229 CSR_API(SrvCreateConsoleScreenBuffer
)
1231 PCSRSS_CREATE_SCREEN_BUFFER CreateScreenBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CreateScreenBufferRequest
;
1232 PCSR_PROCESS ProcessData
= CsrGetClientThread()->Process
;
1233 PCSRSS_CONSOLE Console
;
1234 PCSRSS_SCREEN_BUFFER Buff
;
1237 DPRINT("SrvCreateConsoleScreenBuffer\n");
1239 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
1240 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1241 if (! NT_SUCCESS(Status
))
1246 Buff
= HeapAlloc(ConSrvHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
1250 if (Console
->ActiveBuffer
)
1252 Buff
->MaxX
= Console
->ActiveBuffer
->MaxX
;
1253 Buff
->MaxY
= Console
->ActiveBuffer
->MaxY
;
1254 Buff
->CursorInfo
.bVisible
= Console
->ActiveBuffer
->CursorInfo
.bVisible
;
1255 Buff
->CursorInfo
.dwSize
= Console
->ActiveBuffer
->CursorInfo
.dwSize
;
1259 Buff
->CursorInfo
.bVisible
= TRUE
;
1260 Buff
->CursorInfo
.dwSize
= CSR_DEFAULT_CURSOR_SIZE
;
1263 if (Buff
->MaxX
== 0)
1268 if (Buff
->MaxY
== 0)
1273 Status
= CsrInitConsoleScreenBuffer(Console
, Buff
);
1274 if (NT_SUCCESS(Status
))
1276 Status
= Win32CsrInsertObject(ProcessData
,
1277 &CreateScreenBufferRequest
->OutputHandle
,
1279 CreateScreenBufferRequest
->Access
,
1280 CreateScreenBufferRequest
->Inheritable
,
1281 CreateScreenBufferRequest
->ShareMode
);
1286 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1289 ConioUnlockConsole(Console
);
1290 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
1294 CSR_API(SrvGetConsoleScreenBufferInfo
) // CsrGetScreenBufferInfo
1297 PCSRSS_SCREEN_BUFFER_INFO ScreenBufferInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ScreenBufferInfoRequest
;
1298 PCSRSS_CONSOLE Console
;
1299 PCSRSS_SCREEN_BUFFER Buff
;
1300 PCONSOLE_SCREEN_BUFFER_INFO pInfo
;
1302 DPRINT("SrvGetConsoleScreenBufferInfo\n");
1304 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, ScreenBufferInfoRequest
->ConsoleHandle
, &Buff
, GENERIC_READ
);
1305 if (! NT_SUCCESS(Status
))
1309 Console
= Buff
->Header
.Console
;
1310 pInfo
= &ScreenBufferInfoRequest
->Info
;
1311 pInfo
->dwSize
.X
= Buff
->MaxX
;
1312 pInfo
->dwSize
.Y
= Buff
->MaxY
;
1313 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
;
1314 pInfo
->dwCursorPosition
.Y
= Buff
->CurrentY
;
1315 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
1316 pInfo
->srWindow
.Left
= Buff
->ShowX
;
1317 pInfo
->srWindow
.Right
= Buff
->ShowX
+ Console
->Size
.X
- 1;
1318 pInfo
->srWindow
.Top
= Buff
->ShowY
;
1319 pInfo
->srWindow
.Bottom
= Buff
->ShowY
+ Console
->Size
.Y
- 1;
1320 pInfo
->dwMaximumWindowSize
.X
= Buff
->MaxX
;
1321 pInfo
->dwMaximumWindowSize
.Y
= Buff
->MaxY
;
1322 ConioUnlockScreenBuffer(Buff
);
1324 return STATUS_SUCCESS
;
1327 CSR_API(SrvSetConsoleActiveScreenBuffer
)
1330 PCSRSS_SET_SCREEN_BUFFER SetScreenBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetScreenBufferRequest
;
1331 PCSRSS_CONSOLE Console
;
1332 PCSRSS_SCREEN_BUFFER Buff
;
1334 DPRINT("SrvSetConsoleActiveScreenBuffer\n");
1336 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, SetScreenBufferRequest
->OutputHandle
, &Buff
, GENERIC_WRITE
);
1337 if (! NT_SUCCESS(Status
))
1341 Console
= Buff
->Header
.Console
;
1343 if (Buff
== Console
->ActiveBuffer
)
1345 ConioUnlockScreenBuffer(Buff
);
1346 return STATUS_SUCCESS
;
1349 /* If old buffer has no handles, it's now unreferenced */
1350 if (Console
->ActiveBuffer
->Header
.HandleCount
== 0)
1352 ConioDeleteScreenBuffer(Console
->ActiveBuffer
);
1354 /* tie console to new buffer */
1355 Console
->ActiveBuffer
= Buff
;
1356 /* Redraw the console */
1357 ConioDrawConsole(Console
);
1359 ConioUnlockScreenBuffer(Buff
);
1361 return STATUS_SUCCESS
;
1364 CSR_API(SrvScrollConsoleScreenBuffer
)
1366 PCSRSS_SCROLL_CONSOLE_SCREEN_BUFFER ScrollConsoleScreenBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ScrollConsoleScreenBufferRequest
;
1367 PCSRSS_CONSOLE Console
;
1368 PCSRSS_SCREEN_BUFFER Buff
;
1369 SMALL_RECT ScreenBuffer
;
1370 SMALL_RECT SrcRegion
;
1371 SMALL_RECT DstRegion
;
1372 SMALL_RECT UpdateRegion
;
1373 SMALL_RECT ScrollRectangle
;
1374 SMALL_RECT ClipRectangle
;
1376 HANDLE ConsoleHandle
;
1377 BOOLEAN UseClipRectangle
;
1378 COORD DestinationOrigin
;
1382 DPRINT("SrvScrollConsoleScreenBuffer\n");
1384 ConsoleHandle
= ScrollConsoleScreenBufferRequest
->ConsoleHandle
;
1385 UseClipRectangle
= ScrollConsoleScreenBufferRequest
->UseClipRectangle
;
1386 DestinationOrigin
= ScrollConsoleScreenBufferRequest
->DestinationOrigin
;
1387 Fill
= ScrollConsoleScreenBufferRequest
->Fill
;
1389 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1390 if (! NT_SUCCESS(Status
))
1394 Console
= Buff
->Header
.Console
;
1396 ScrollRectangle
= ScrollConsoleScreenBufferRequest
->ScrollRectangle
;
1398 /* Make sure source rectangle is inside the screen buffer */
1399 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
1400 if (! ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, &ScrollRectangle
))
1402 ConioUnlockScreenBuffer(Buff
);
1403 return STATUS_SUCCESS
;
1406 /* If the source was clipped on the left or top, adjust the destination accordingly */
1407 if (ScrollRectangle
.Left
< 0)
1409 DestinationOrigin
.X
-= ScrollRectangle
.Left
;
1411 if (ScrollRectangle
.Top
< 0)
1413 DestinationOrigin
.Y
-= ScrollRectangle
.Top
;
1416 if (UseClipRectangle
)
1418 ClipRectangle
= ScrollConsoleScreenBufferRequest
->ClipRectangle
;
1419 if (!ConioGetIntersection(&ClipRectangle
, &ClipRectangle
, &ScreenBuffer
))
1421 ConioUnlockScreenBuffer(Buff
);
1422 return STATUS_SUCCESS
;
1427 ClipRectangle
= ScreenBuffer
;
1430 ConioInitRect(&DstRegion
,
1431 DestinationOrigin
.Y
,
1432 DestinationOrigin
.X
,
1433 DestinationOrigin
.Y
+ ConioRectHeight(&SrcRegion
) - 1,
1434 DestinationOrigin
.X
+ ConioRectWidth(&SrcRegion
) - 1);
1436 if (ScrollConsoleScreenBufferRequest
->Unicode
)
1437 ConsoleUnicodeCharToAnsiChar(Console
, &FillChar
, &Fill
.Char
.UnicodeChar
);
1439 FillChar
= Fill
.Char
.AsciiChar
;
1441 ConioMoveRegion(Buff
, &SrcRegion
, &DstRegion
, &ClipRectangle
, Fill
.Attributes
<< 8 | (BYTE
)FillChar
);
1443 if (Buff
== Console
->ActiveBuffer
)
1445 ConioGetUnion(&UpdateRegion
, &SrcRegion
, &DstRegion
);
1446 if (ConioGetIntersection(&UpdateRegion
, &UpdateRegion
, &ClipRectangle
))
1448 /* Draw update region */
1449 ConioDrawRegion(Console
, &UpdateRegion
);
1453 ConioUnlockScreenBuffer(Buff
);
1455 return STATUS_SUCCESS
;
1458 CSR_API(SrvSetConsoleScreenBufferSize
)
1461 PCSRSS_SET_SCREEN_BUFFER_SIZE SetScreenBufferSize
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetScreenBufferSize
;
1462 PCSRSS_CONSOLE Console
;
1463 PCSRSS_SCREEN_BUFFER Buff
;
1465 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, SetScreenBufferSize
->OutputHandle
, &Buff
, GENERIC_WRITE
);
1466 if (!NT_SUCCESS(Status
))
1470 Console
= Buff
->Header
.Console
;
1472 Status
= ConioResizeBuffer(Console
, Buff
, SetScreenBufferSize
->Size
);
1473 ConioUnlockScreenBuffer(Buff
);