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 ******************************************************************/
17 /* GLOBALS *******************************************************************/
19 #define ConioInitRect(Rect, top, left, bottom, right) \
20 ((Rect)->Top) = top; \
21 ((Rect)->Left) = left; \
22 ((Rect)->Bottom) = bottom; \
23 ((Rect)->Right) = right
25 #define ConioIsRectEmpty(Rect) \
26 (((Rect)->Left > (Rect)->Right) || ((Rect)->Top > (Rect)->Bottom))
28 #define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
29 WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
31 #define ConsoleAnsiCharToUnicodeChar(Console, dWChar, sChar) \
32 MultiByteToWideChar((Console)->OutputCodePage, 0, (sChar), 1, (dWChar), 1)
34 /* FUNCTIONS *****************************************************************/
37 ConioCoordToPointer(PCSRSS_SCREEN_BUFFER Buff
, ULONG X
, ULONG Y
)
39 return &Buff
->Buffer
[2 * (((Y
+ Buff
->VirtualY
) % Buff
->MaxY
) * Buff
->MaxX
+ X
)];
43 ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff
)
45 PBYTE Ptr
= ConioCoordToPointer(Buff
, 0, Buff
->CurrentY
);
48 for (Pos
= 0; Pos
< Buff
->MaxX
; Pos
++)
52 *Ptr
++ = Buff
->DefaultAttrib
;
57 CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console
,
58 PCSRSS_SCREEN_BUFFER Buffer
)
60 DPRINT("CsrInitConsoleScreenBuffer Size X %d Size Y %d\n", Buffer
->MaxX
, Buffer
->MaxY
);
62 Buffer
->Header
.Type
= CONIO_SCREEN_BUFFER_MAGIC
;
63 Buffer
->Header
.Console
= Console
;
64 Buffer
->Header
.HandleCount
= 0;
68 Buffer
->Buffer
= HeapAlloc(ConSrvHeap
, HEAP_ZERO_MEMORY
, Buffer
->MaxX
* Buffer
->MaxY
* 2);
69 if (NULL
== Buffer
->Buffer
)
71 return STATUS_INSUFFICIENT_RESOURCES
;
73 ConioInitScreenBuffer(Console
, Buffer
);
74 /* initialize buffer to be empty with default attributes */
75 for (Buffer
->CurrentY
= 0 ; Buffer
->CurrentY
< Buffer
->MaxY
; Buffer
->CurrentY
++)
77 ClearLineBuffer(Buffer
);
79 Buffer
->Mode
= ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
;
83 InsertHeadList(&Console
->BufferList
, &Buffer
->ListEntry
);
84 return STATUS_SUCCESS
;
88 ConioNextLine(PCSRSS_SCREEN_BUFFER Buff
, SMALL_RECT
*UpdateRect
, UINT
*ScrolledLines
)
90 /* If we hit bottom, slide the viewable screen */
91 if (++Buff
->CurrentY
== Buff
->MaxY
)
94 if (++Buff
->VirtualY
== Buff
->MaxY
)
99 ClearLineBuffer(Buff
);
100 if (UpdateRect
->Top
!= 0)
105 UpdateRect
->Left
= 0;
106 UpdateRect
->Right
= Buff
->MaxX
- 1;
107 UpdateRect
->Bottom
= Buff
->CurrentY
;
111 ConioWriteConsole(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
,
112 CHAR
*Buffer
, DWORD Length
, BOOL Attrib
)
116 SMALL_RECT UpdateRect
;
117 LONG CursorStartX
, CursorStartY
;
120 CursorStartX
= Buff
->CurrentX
;
121 CursorStartY
= Buff
->CurrentY
;
122 UpdateRect
.Left
= Buff
->MaxX
;
123 UpdateRect
.Top
= Buff
->CurrentY
;
124 UpdateRect
.Right
= -1;
125 UpdateRect
.Bottom
= Buff
->CurrentY
;
128 for (i
= 0; i
< Length
; i
++)
130 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
133 if (Buffer
[i
] == '\n')
136 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
140 else if (Buffer
[i
] == '\b')
142 /* Only handle BS if we're not on the first pos of the first line */
143 if (0 != Buff
->CurrentX
|| 0 != Buff
->CurrentY
)
145 if (0 == Buff
->CurrentX
)
147 /* slide virtual position up */
148 Buff
->CurrentX
= Buff
->MaxX
- 1;
150 UpdateRect
.Top
= min(UpdateRect
.Top
, (LONG
)Buff
->CurrentY
);
156 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
158 Ptr
[1] = Buff
->DefaultAttrib
;
159 UpdateRect
.Left
= min(UpdateRect
.Left
, (LONG
) Buff
->CurrentX
);
160 UpdateRect
.Right
= max(UpdateRect
.Right
, (LONG
) Buff
->CurrentX
);
165 else if (Buffer
[i
] == '\r')
168 UpdateRect
.Left
= min(UpdateRect
.Left
, (LONG
) Buff
->CurrentX
);
169 UpdateRect
.Right
= max(UpdateRect
.Right
, (LONG
) Buff
->CurrentX
);
173 else if (Buffer
[i
] == '\t')
177 UpdateRect
.Left
= min(UpdateRect
.Left
, (LONG
)Buff
->CurrentX
);
178 EndX
= (Buff
->CurrentX
+ 8) & ~7;
179 if (EndX
> Buff
->MaxX
)
183 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
184 while (Buff
->CurrentX
< EndX
)
187 *Ptr
++ = Buff
->DefaultAttrib
;
190 UpdateRect
.Right
= max(UpdateRect
.Right
, (LONG
) Buff
->CurrentX
- 1);
191 if (Buff
->CurrentX
== Buff
->MaxX
)
193 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
196 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
206 UpdateRect
.Left
= min(UpdateRect
.Left
, (LONG
)Buff
->CurrentX
);
207 UpdateRect
.Right
= max(UpdateRect
.Right
, (LONG
) Buff
->CurrentX
);
208 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
212 Ptr
[1] = Buff
->DefaultAttrib
;
215 if (Buff
->CurrentX
== Buff
->MaxX
)
217 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
220 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
224 Buff
->CurrentX
= CursorStartX
;
229 if (! ConioIsRectEmpty(&UpdateRect
) && Buff
== Console
->ActiveBuffer
)
231 ConioWriteStream(Console
, &UpdateRect
, CursorStartX
, CursorStartY
, ScrolledLines
,
235 return STATUS_SUCCESS
;
238 __inline BOOLEAN
ConioGetIntersection(
239 SMALL_RECT
*Intersection
,
243 if (ConioIsRectEmpty(Rect1
) ||
244 (ConioIsRectEmpty(Rect2
)) ||
245 (Rect1
->Top
> Rect2
->Bottom
) ||
246 (Rect1
->Left
> Rect2
->Right
) ||
247 (Rect1
->Bottom
< Rect2
->Top
) ||
248 (Rect1
->Right
< Rect2
->Left
))
250 /* The rectangles do not intersect */
251 ConioInitRect(Intersection
, 0, -1, 0, -1);
255 ConioInitRect(Intersection
,
256 max(Rect1
->Top
, Rect2
->Top
),
257 max(Rect1
->Left
, Rect2
->Left
),
258 min(Rect1
->Bottom
, Rect2
->Bottom
),
259 min(Rect1
->Right
, Rect2
->Right
));
264 __inline BOOLEAN
ConioGetUnion(
269 if (ConioIsRectEmpty(Rect1
))
271 if (ConioIsRectEmpty(Rect2
))
273 ConioInitRect(Union
, 0, -1, 0, -1);
281 else if (ConioIsRectEmpty(Rect2
))
288 min(Rect1
->Top
, Rect2
->Top
),
289 min(Rect1
->Left
, Rect2
->Left
),
290 max(Rect1
->Bottom
, Rect2
->Bottom
),
291 max(Rect1
->Right
, Rect2
->Right
));
297 /* Move from one rectangle to another. We must be careful about the order that
298 * this is done, to avoid overwriting parts of the source before they are moved. */
300 ConioMoveRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer
,
301 SMALL_RECT
*SrcRegion
,
302 SMALL_RECT
*DstRegion
,
303 SMALL_RECT
*ClipRegion
,
306 int Width
= ConioRectWidth(SrcRegion
);
307 int Height
= ConioRectHeight(SrcRegion
);
318 /* Moving down: work from bottom up */
319 SY
= SrcRegion
->Bottom
;
320 DY
= DstRegion
->Bottom
;
323 for (i
= 0; i
< Height
; i
++)
325 PWORD SRow
= (PWORD
)ConioCoordToPointer(ScreenBuffer
, 0, SY
);
326 PWORD DRow
= (PWORD
)ConioCoordToPointer(ScreenBuffer
, 0, DY
);
328 SX
= SrcRegion
->Left
;
329 DX
= DstRegion
->Left
;
333 /* Moving right: work from right to left */
334 SX
= SrcRegion
->Right
;
335 DX
= DstRegion
->Right
;
338 for (j
= 0; j
< Width
; j
++)
340 WORD Cell
= SRow
[SX
];
341 if (SX
>= ClipRegion
->Left
&& SX
<= ClipRegion
->Right
342 && SY
>= ClipRegion
->Top
&& SY
<= ClipRegion
->Bottom
)
346 if (DX
>= ClipRegion
->Left
&& DX
<= ClipRegion
->Right
347 && DY
>= ClipRegion
->Top
&& DY
<= ClipRegion
->Bottom
)
359 CSR_API(SrvWriteConsole
)
362 PCSRSS_WRITE_CONSOLE WriteConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteConsoleRequest
;
364 PCSRSS_SCREEN_BUFFER Buff
;
365 PCSR_PROCESS ProcessData
= CsrGetClientThread()->Process
;
366 PCSRSS_CONSOLE Console
;
369 ULONG CharSize
= (WriteConsoleRequest
->Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
371 DPRINT("SrvWriteConsole\n");
373 if (ApiMessage
->Header
.u1
.s1
.TotalLength
374 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE
)
375 + (WriteConsoleRequest
->NrCharactersToWrite
* CharSize
))
377 DPRINT1("Invalid ApiMessage size\n");
378 return STATUS_INVALID_PARAMETER
;
381 Status
= ConioLockScreenBuffer(ProcessData
, WriteConsoleRequest
->ConsoleHandle
, &Buff
, GENERIC_WRITE
);
382 if (! NT_SUCCESS(Status
))
386 Console
= Buff
->Header
.Console
;
388 if (Console
->UnpauseEvent
)
390 Status
= NtDuplicateObject(GetCurrentProcess(), Console
->UnpauseEvent
,
391 ProcessData
->ProcessHandle
, &WriteConsoleRequest
->UnpauseEvent
,
393 ConioUnlockScreenBuffer(Buff
);
394 return NT_SUCCESS(Status
) ? STATUS_PENDING
: Status
;
397 if(WriteConsoleRequest
->Unicode
)
399 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
400 (PWCHAR
)WriteConsoleRequest
->Buffer
,
401 WriteConsoleRequest
->NrCharactersToWrite
,
402 NULL
, 0, NULL
, NULL
);
403 Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
406 WideCharToMultiByte(Console
->OutputCodePage
, 0,
407 (PWCHAR
)WriteConsoleRequest
->Buffer
,
408 WriteConsoleRequest
->NrCharactersToWrite
,
409 Buffer
, Length
, NULL
, NULL
);
413 Status
= STATUS_NO_MEMORY
;
418 Buffer
= (PCHAR
)WriteConsoleRequest
->Buffer
;
423 if (NT_SUCCESS(Status
))
425 Status
= ConioWriteConsole(Console
, Buff
, Buffer
,
426 WriteConsoleRequest
->NrCharactersToWrite
, TRUE
);
427 if (NT_SUCCESS(Status
))
429 Written
= WriteConsoleRequest
->NrCharactersToWrite
;
432 if (WriteConsoleRequest
->Unicode
)
434 RtlFreeHeap(GetProcessHeap(), 0, Buffer
);
437 ConioUnlockScreenBuffer(Buff
);
439 WriteConsoleRequest
->NrCharactersWritten
= Written
;
445 ConioDeleteScreenBuffer(PCSRSS_SCREEN_BUFFER Buffer
)
447 PCSRSS_CONSOLE Console
= Buffer
->Header
.Console
;
449 RemoveEntryList(&Buffer
->ListEntry
);
450 if (Buffer
== Console
->ActiveBuffer
)
452 /* Deleted active buffer; switch to most recently created */
453 Console
->ActiveBuffer
= NULL
;
454 if (!IsListEmpty(&Console
->BufferList
))
456 Console
->ActiveBuffer
= CONTAINING_RECORD(Console
->BufferList
.Flink
, CSRSS_SCREEN_BUFFER
, ListEntry
);
457 ConioDrawConsole(Console
);
461 HeapFree(ConSrvHeap
, 0, Buffer
->Buffer
);
462 HeapFree(ConSrvHeap
, 0, Buffer
);
466 ConioDrawConsole(PCSRSS_CONSOLE Console
)
470 ConioInitRect(&Region
, 0, 0, Console
->Size
.Y
- 1, Console
->Size
.X
- 1);
472 ConioDrawRegion(Console
, &Region
);
475 CSR_API(SrvGetConsoleScreenBufferInfo
) // CsrGetScreenBufferInfo
478 PCSRSS_SCREEN_BUFFER_INFO ScreenBufferInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ScreenBufferInfoRequest
;
479 PCSRSS_CONSOLE Console
;
480 PCSRSS_SCREEN_BUFFER Buff
;
481 PCONSOLE_SCREEN_BUFFER_INFO pInfo
;
483 DPRINT("SrvGetConsoleScreenBufferInfo\n");
485 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, ScreenBufferInfoRequest
->ConsoleHandle
, &Buff
, GENERIC_READ
);
486 if (! NT_SUCCESS(Status
))
490 Console
= Buff
->Header
.Console
;
491 pInfo
= &ScreenBufferInfoRequest
->Info
;
492 pInfo
->dwSize
.X
= Buff
->MaxX
;
493 pInfo
->dwSize
.Y
= Buff
->MaxY
;
494 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
;
495 pInfo
->dwCursorPosition
.Y
= Buff
->CurrentY
;
496 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
497 pInfo
->srWindow
.Left
= Buff
->ShowX
;
498 pInfo
->srWindow
.Right
= Buff
->ShowX
+ Console
->Size
.X
- 1;
499 pInfo
->srWindow
.Top
= Buff
->ShowY
;
500 pInfo
->srWindow
.Bottom
= Buff
->ShowY
+ Console
->Size
.Y
- 1;
501 pInfo
->dwMaximumWindowSize
.X
= Buff
->MaxX
;
502 pInfo
->dwMaximumWindowSize
.Y
= Buff
->MaxY
;
503 ConioUnlockScreenBuffer(Buff
);
505 return STATUS_SUCCESS
;
508 CSR_API(SrvSetConsoleCursor
)
511 PCSRSS_SET_CURSOR SetCursorRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetCursorRequest
;
512 PCSRSS_CONSOLE Console
;
513 PCSRSS_SCREEN_BUFFER Buff
;
514 LONG OldCursorX
, OldCursorY
;
515 LONG NewCursorX
, NewCursorY
;
517 DPRINT("SrvSetConsoleCursor\n");
519 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, SetCursorRequest
->ConsoleHandle
, &Buff
, GENERIC_WRITE
);
520 if (! NT_SUCCESS(Status
))
524 Console
= Buff
->Header
.Console
;
526 NewCursorX
= SetCursorRequest
->Position
.X
;
527 NewCursorY
= SetCursorRequest
->Position
.Y
;
528 if (NewCursorX
< 0 || NewCursorX
>= Buff
->MaxX
||
529 NewCursorY
< 0 || NewCursorY
>= Buff
->MaxY
)
531 ConioUnlockScreenBuffer(Buff
);
532 return STATUS_INVALID_PARAMETER
;
534 OldCursorX
= Buff
->CurrentX
;
535 OldCursorY
= Buff
->CurrentY
;
536 Buff
->CurrentX
= NewCursorX
;
537 Buff
->CurrentY
= NewCursorY
;
538 if (Buff
== Console
->ActiveBuffer
)
540 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
542 ConioUnlockScreenBuffer(Buff
);
543 return STATUS_UNSUCCESSFUL
;
547 ConioUnlockScreenBuffer(Buff
);
549 return STATUS_SUCCESS
;
553 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff
, SMALL_RECT
*UpdateRect
, COORD
*Start
, UINT Length
)
555 if (Buff
->MaxX
<= Start
->X
+ Length
)
557 UpdateRect
->Left
= 0;
561 UpdateRect
->Left
= Start
->X
;
563 if (Buff
->MaxX
<= Start
->X
+ Length
)
565 UpdateRect
->Right
= Buff
->MaxX
- 1;
569 UpdateRect
->Right
= Start
->X
+ Length
- 1;
571 UpdateRect
->Top
= Start
->Y
;
572 UpdateRect
->Bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->MaxX
;
573 if (Buff
->MaxY
<= UpdateRect
->Bottom
)
575 UpdateRect
->Bottom
= Buff
->MaxY
- 1;
579 CSR_API(CsrWriteConsoleOutputChar
)
582 PCSRSS_WRITE_CONSOLE_OUTPUT_CHAR WriteConsoleOutputCharRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteConsoleOutputCharRequest
;
583 PCHAR String
, tmpString
= NULL
;
585 PCSRSS_CONSOLE Console
;
586 PCSRSS_SCREEN_BUFFER Buff
;
587 DWORD X
, Y
, Length
, CharSize
, Written
= 0;
588 SMALL_RECT UpdateRect
;
590 DPRINT("CsrWriteConsoleOutputChar\n");
592 CharSize
= (WriteConsoleOutputCharRequest
->Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
594 if (ApiMessage
->Header
.u1
.s1
.TotalLength
595 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR
)
596 + (WriteConsoleOutputCharRequest
->Length
* CharSize
))
598 DPRINT1("Invalid ApiMessage size\n");
599 return STATUS_INVALID_PARAMETER
;
602 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
,
603 WriteConsoleOutputCharRequest
->ConsoleHandle
,
606 if (NT_SUCCESS(Status
))
608 Console
= Buff
->Header
.Console
;
609 if(WriteConsoleOutputCharRequest
->Unicode
)
611 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
612 (PWCHAR
)WriteConsoleOutputCharRequest
->String
,
613 WriteConsoleOutputCharRequest
->Length
,
614 NULL
, 0, NULL
, NULL
);
615 tmpString
= String
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
618 WideCharToMultiByte(Console
->OutputCodePage
, 0,
619 (PWCHAR
)WriteConsoleOutputCharRequest
->String
,
620 WriteConsoleOutputCharRequest
->Length
,
621 String
, Length
, NULL
, NULL
);
625 Status
= STATUS_NO_MEMORY
;
630 String
= (PCHAR
)WriteConsoleOutputCharRequest
->String
;
635 if (NT_SUCCESS(Status
))
637 X
= WriteConsoleOutputCharRequest
->Coord
.X
;
638 Y
= (WriteConsoleOutputCharRequest
->Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
639 Length
= WriteConsoleOutputCharRequest
->Length
;
640 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
646 if (++X
== Buff
->MaxX
)
648 if (++Y
== Buff
->MaxY
)
651 Buffer
= Buff
->Buffer
;
656 if (Buff
== Console
->ActiveBuffer
)
658 ConioComputeUpdateRect(Buff
, &UpdateRect
, &WriteConsoleOutputCharRequest
->Coord
,
659 WriteConsoleOutputCharRequest
->Length
);
660 ConioDrawRegion(Console
, &UpdateRect
);
663 WriteConsoleOutputCharRequest
->EndCoord
.X
= X
;
664 WriteConsoleOutputCharRequest
->EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->VirtualY
) % Buff
->MaxY
;
667 if (WriteConsoleOutputCharRequest
->Unicode
)
669 RtlFreeHeap(GetProcessHeap(), 0, tmpString
);
672 ConioUnlockScreenBuffer(Buff
);
674 WriteConsoleOutputCharRequest
->NrCharactersWritten
= Written
;
678 CSR_API(CsrFillOutputChar
)
681 PCSRSS_FILL_OUTPUT FillOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.FillOutputRequest
;
682 PCSRSS_CONSOLE Console
;
683 PCSRSS_SCREEN_BUFFER Buff
;
684 DWORD X
, Y
, Length
, Written
= 0;
687 SMALL_RECT UpdateRect
;
689 DPRINT("CsrFillOutputChar\n");
691 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, FillOutputRequest
->ConsoleHandle
, &Buff
, GENERIC_WRITE
);
692 if (! NT_SUCCESS(Status
))
696 Console
= Buff
->Header
.Console
;
698 X
= FillOutputRequest
->Position
.X
;
699 Y
= (FillOutputRequest
->Position
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
700 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
701 if(FillOutputRequest
->Unicode
)
702 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &FillOutputRequest
->Char
.UnicodeChar
);
704 Char
= FillOutputRequest
->Char
.AsciiChar
;
705 Length
= FillOutputRequest
->Length
;
711 if (++X
== Buff
->MaxX
)
713 if (++Y
== Buff
->MaxY
)
716 Buffer
= Buff
->Buffer
;
722 if (Buff
== Console
->ActiveBuffer
)
724 ConioComputeUpdateRect(Buff
, &UpdateRect
, &FillOutputRequest
->Position
,
725 FillOutputRequest
->Length
);
726 ConioDrawRegion(Console
, &UpdateRect
);
729 ConioUnlockScreenBuffer(Buff
);
730 Length
= FillOutputRequest
->Length
;
731 FillOutputRequest
->NrCharactersWritten
= Length
;
732 return STATUS_SUCCESS
;
735 CSR_API(CsrWriteConsoleOutputAttrib
)
737 PCSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB WriteConsoleOutputAttribRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteConsoleOutputAttribRequest
;
738 PCSRSS_CONSOLE Console
;
739 PCSRSS_SCREEN_BUFFER Buff
;
744 SMALL_RECT UpdateRect
;
746 DPRINT("CsrWriteConsoleOutputAttrib\n");
748 if (ApiMessage
->Header
.u1
.s1
.TotalLength
749 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB
)
750 + WriteConsoleOutputAttribRequest
->Length
* sizeof(WORD
))
752 DPRINT1("Invalid ApiMessage size\n");
753 return STATUS_INVALID_PARAMETER
;
756 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
,
757 WriteConsoleOutputAttribRequest
->ConsoleHandle
,
760 if (! NT_SUCCESS(Status
))
764 Console
= Buff
->Header
.Console
;
766 X
= WriteConsoleOutputAttribRequest
->Coord
.X
;
767 Y
= (WriteConsoleOutputAttribRequest
->Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
768 Length
= WriteConsoleOutputAttribRequest
->Length
;
769 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + 1];
770 Attribute
= WriteConsoleOutputAttribRequest
->Attribute
;
773 *Buffer
= (UCHAR
)(*Attribute
++);
775 if (++X
== Buff
->MaxX
)
777 if (++Y
== Buff
->MaxY
)
780 Buffer
= Buff
->Buffer
+ 1;
786 if (Buff
== Console
->ActiveBuffer
)
788 ConioComputeUpdateRect(Buff
, &UpdateRect
, &WriteConsoleOutputAttribRequest
->Coord
,
789 WriteConsoleOutputAttribRequest
->Length
);
790 ConioDrawRegion(Console
, &UpdateRect
);
793 WriteConsoleOutputAttribRequest
->EndCoord
.X
= X
;
794 WriteConsoleOutputAttribRequest
->EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->VirtualY
) % Buff
->MaxY
;
796 ConioUnlockScreenBuffer(Buff
);
798 return STATUS_SUCCESS
;
801 CSR_API(CsrFillOutputAttrib
)
803 PCSRSS_FILL_OUTPUT_ATTRIB FillOutputAttribRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.FillOutputAttribRequest
;
804 PCSRSS_SCREEN_BUFFER Buff
;
809 SMALL_RECT UpdateRect
;
810 PCSRSS_CONSOLE Console
;
812 DPRINT("CsrFillOutputAttrib\n");
814 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, FillOutputAttribRequest
->ConsoleHandle
, &Buff
, GENERIC_WRITE
);
815 if (! NT_SUCCESS(Status
))
819 Console
= Buff
->Header
.Console
;
821 X
= FillOutputAttribRequest
->Coord
.X
;
822 Y
= (FillOutputAttribRequest
->Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
823 Length
= FillOutputAttribRequest
->Length
;
824 Attr
= FillOutputAttribRequest
->Attribute
;
825 Buffer
= &Buff
->Buffer
[(Y
* Buff
->MaxX
* 2) + (X
* 2) + 1];
830 if (++X
== Buff
->MaxX
)
832 if (++Y
== Buff
->MaxY
)
835 Buffer
= Buff
->Buffer
+ 1;
841 if (Buff
== Console
->ActiveBuffer
)
843 ConioComputeUpdateRect(Buff
, &UpdateRect
, &FillOutputAttribRequest
->Coord
,
844 FillOutputAttribRequest
->Length
);
845 ConioDrawRegion(Console
, &UpdateRect
);
848 ConioUnlockScreenBuffer(Buff
);
850 return STATUS_SUCCESS
;
854 ConioEffectiveCursorSize(PCSRSS_CONSOLE Console
, DWORD Scale
)
856 DWORD Size
= (Console
->ActiveBuffer
->CursorInfo
.dwSize
* Scale
+ 99) / 100;
857 /* If line input in progress, perhaps adjust for insert toggle */
858 if (Console
->LineBuffer
&& !Console
->LineComplete
&& Console
->LineInsertToggle
)
859 return (Size
* 2 <= Scale
) ? (Size
* 2) : (Size
/ 2);
863 CSR_API(SrvGetConsoleCursorInfo
)
866 PCSRSS_GET_CURSOR_INFO GetCursorInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetCursorInfoRequest
;
867 PCSRSS_SCREEN_BUFFER Buff
;
869 DPRINT("SrvGetConsoleCursorInfo\n");
871 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, GetCursorInfoRequest
->ConsoleHandle
, &Buff
, GENERIC_READ
);
872 if (! NT_SUCCESS(Status
))
876 GetCursorInfoRequest
->Info
.bVisible
= Buff
->CursorInfo
.bVisible
;
877 GetCursorInfoRequest
->Info
.dwSize
= Buff
->CursorInfo
.dwSize
;
878 ConioUnlockScreenBuffer(Buff
);
880 return STATUS_SUCCESS
;
883 CSR_API(SrvSetConsoleCursorInfo
)
885 PCSRSS_SET_CURSOR_INFO SetCursorInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetCursorInfoRequest
;
886 PCSRSS_CONSOLE Console
;
887 PCSRSS_SCREEN_BUFFER Buff
;
892 DPRINT("SrvSetConsoleCursorInfo\n");
894 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, SetCursorInfoRequest
->ConsoleHandle
, &Buff
, GENERIC_WRITE
);
895 if (! NT_SUCCESS(Status
))
899 Console
= Buff
->Header
.Console
;
901 Size
= SetCursorInfoRequest
->Info
.dwSize
;
902 Visible
= SetCursorInfoRequest
->Info
.bVisible
;
912 if (Size
!= Buff
->CursorInfo
.dwSize
913 || (Visible
&& ! Buff
->CursorInfo
.bVisible
) || (! Visible
&& Buff
->CursorInfo
.bVisible
))
915 Buff
->CursorInfo
.dwSize
= Size
;
916 Buff
->CursorInfo
.bVisible
= Visible
;
918 if (! ConioSetCursorInfo(Console
, Buff
))
920 ConioUnlockScreenBuffer(Buff
);
921 return STATUS_UNSUCCESSFUL
;
925 ConioUnlockScreenBuffer(Buff
);
927 return STATUS_SUCCESS
;
930 CSR_API(CsrSetTextAttrib
)
933 PCSRSS_SET_ATTRIB SetAttribRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetAttribRequest
;
934 PCSRSS_CONSOLE Console
;
935 PCSRSS_SCREEN_BUFFER Buff
;
937 DPRINT("CsrSetTextAttrib\n");
939 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, SetAttribRequest
->ConsoleHandle
, &Buff
, GENERIC_WRITE
);
940 if (! NT_SUCCESS(Status
))
944 Console
= Buff
->Header
.Console
;
946 Buff
->DefaultAttrib
= SetAttribRequest
->Attrib
;
947 if (Buff
== Console
->ActiveBuffer
)
949 if (! ConioUpdateScreenInfo(Console
, Buff
))
951 ConioUnlockScreenBuffer(Buff
);
952 return STATUS_UNSUCCESSFUL
;
956 ConioUnlockScreenBuffer(Buff
);
958 return STATUS_SUCCESS
;
961 CSR_API(SrvCreateConsoleScreenBuffer
)
963 PCSRSS_CREATE_SCREEN_BUFFER CreateScreenBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CreateScreenBufferRequest
;
964 PCSR_PROCESS ProcessData
= CsrGetClientThread()->Process
;
965 PCSRSS_CONSOLE Console
;
966 PCSRSS_SCREEN_BUFFER Buff
;
969 DPRINT("SrvCreateConsoleScreenBuffer\n");
971 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
972 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
973 if (! NT_SUCCESS(Status
))
978 Buff
= HeapAlloc(ConSrvHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
982 if (Console
->ActiveBuffer
)
984 Buff
->MaxX
= Console
->ActiveBuffer
->MaxX
;
985 Buff
->MaxY
= Console
->ActiveBuffer
->MaxY
;
986 Buff
->CursorInfo
.bVisible
= Console
->ActiveBuffer
->CursorInfo
.bVisible
;
987 Buff
->CursorInfo
.dwSize
= Console
->ActiveBuffer
->CursorInfo
.dwSize
;
991 Buff
->CursorInfo
.bVisible
= TRUE
;
992 Buff
->CursorInfo
.dwSize
= CSR_DEFAULT_CURSOR_SIZE
;
1000 if (Buff
->MaxY
== 0)
1005 Status
= CsrInitConsoleScreenBuffer(Console
, Buff
);
1006 if (NT_SUCCESS(Status
))
1008 Status
= Win32CsrInsertObject(ProcessData
,
1009 &CreateScreenBufferRequest
->OutputHandle
,
1011 CreateScreenBufferRequest
->Access
,
1012 CreateScreenBufferRequest
->Inheritable
,
1013 CreateScreenBufferRequest
->ShareMode
);
1018 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1021 ConioUnlockConsole(Console
);
1022 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
1026 CSR_API(SrvSetConsoleActiveScreenBuffer
)
1029 PCSRSS_SET_SCREEN_BUFFER SetScreenBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetScreenBufferRequest
;
1030 PCSRSS_CONSOLE Console
;
1031 PCSRSS_SCREEN_BUFFER Buff
;
1033 DPRINT("SrvSetConsoleActiveScreenBuffer\n");
1035 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, SetScreenBufferRequest
->OutputHandle
, &Buff
, GENERIC_WRITE
);
1036 if (! NT_SUCCESS(Status
))
1040 Console
= Buff
->Header
.Console
;
1042 if (Buff
== Console
->ActiveBuffer
)
1044 ConioUnlockScreenBuffer(Buff
);
1045 return STATUS_SUCCESS
;
1048 /* If old buffer has no handles, it's now unreferenced */
1049 if (Console
->ActiveBuffer
->Header
.HandleCount
== 0)
1051 ConioDeleteScreenBuffer(Console
->ActiveBuffer
);
1053 /* tie console to new buffer */
1054 Console
->ActiveBuffer
= Buff
;
1055 /* Redraw the console */
1056 ConioDrawConsole(Console
);
1058 ConioUnlockScreenBuffer(Buff
);
1060 return STATUS_SUCCESS
;
1063 CSR_API(SrvWriteConsoleOutput
)
1065 PCSRSS_WRITE_CONSOLE_OUTPUT WriteConsoleOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.WriteConsoleOutputRequest
;
1066 SHORT i
, X
, Y
, SizeX
, SizeY
;
1067 PCSR_PROCESS ProcessData
= CsrGetClientThread()->Process
;
1068 PCSRSS_CONSOLE Console
;
1069 PCSRSS_SCREEN_BUFFER Buff
;
1070 SMALL_RECT ScreenBuffer
;
1071 CHAR_INFO
* CurCharInfo
;
1072 SMALL_RECT WriteRegion
;
1073 CHAR_INFO
* CharInfo
;
1079 DPRINT("SrvWriteConsoleOutput\n");
1081 Status
= ConioLockScreenBuffer(ProcessData
,
1082 WriteConsoleOutputRequest
->ConsoleHandle
,
1085 if (! NT_SUCCESS(Status
))
1089 Console
= Buff
->Header
.Console
;
1091 BufferSize
= WriteConsoleOutputRequest
->BufferSize
;
1092 BufferCoord
= WriteConsoleOutputRequest
->BufferCoord
;
1093 CharInfo
= WriteConsoleOutputRequest
->CharInfo
;
1094 if (!Win32CsrValidateBuffer(ProcessData
, CharInfo
,
1095 BufferSize
.X
* BufferSize
.Y
, sizeof(CHAR_INFO
)))
1097 ConioUnlockScreenBuffer(Buff
);
1098 return STATUS_ACCESS_VIOLATION
;
1100 WriteRegion
= WriteConsoleOutputRequest
->WriteRegion
;
1102 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&WriteRegion
));
1103 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&WriteRegion
));
1104 WriteRegion
.Bottom
= WriteRegion
.Top
+ SizeY
- 1;
1105 WriteRegion
.Right
= WriteRegion
.Left
+ SizeX
- 1;
1107 /* Make sure WriteRegion is inside the screen buffer */
1108 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
1109 if (! ConioGetIntersection(&WriteRegion
, &ScreenBuffer
, &WriteRegion
))
1111 ConioUnlockScreenBuffer(Buff
);
1113 /* It is okay to have a WriteRegion completely outside the screen buffer.
1114 No data is written then. */
1115 return STATUS_SUCCESS
;
1118 for (i
= 0, Y
= WriteRegion
.Top
; Y
<= WriteRegion
.Bottom
; i
++, Y
++)
1120 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
1121 Ptr
= ConioCoordToPointer(Buff
, WriteRegion
.Left
, Y
);
1122 for (X
= WriteRegion
.Left
; X
<= WriteRegion
.Right
; X
++)
1125 if (WriteConsoleOutputRequest
->Unicode
)
1127 ConsoleUnicodeCharToAnsiChar(Console
, &AsciiChar
, &CurCharInfo
->Char
.UnicodeChar
);
1131 AsciiChar
= CurCharInfo
->Char
.AsciiChar
;
1134 *Ptr
++ = CurCharInfo
->Attributes
;
1139 ConioDrawRegion(Console
, &WriteRegion
);
1141 ConioUnlockScreenBuffer(Buff
);
1143 WriteConsoleOutputRequest
->WriteRegion
.Right
= WriteRegion
.Left
+ SizeX
- 1;
1144 WriteConsoleOutputRequest
->WriteRegion
.Bottom
= WriteRegion
.Top
+ SizeY
- 1;
1145 WriteConsoleOutputRequest
->WriteRegion
.Left
= WriteRegion
.Left
;
1146 WriteConsoleOutputRequest
->WriteRegion
.Top
= WriteRegion
.Top
;
1148 return STATUS_SUCCESS
;
1151 CSR_API(SrvScrollConsoleScreenBuffer
)
1153 PCSRSS_SCROLL_CONSOLE_SCREEN_BUFFER ScrollConsoleScreenBufferRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ScrollConsoleScreenBufferRequest
;
1154 PCSRSS_CONSOLE Console
;
1155 PCSRSS_SCREEN_BUFFER Buff
;
1156 SMALL_RECT ScreenBuffer
;
1157 SMALL_RECT SrcRegion
;
1158 SMALL_RECT DstRegion
;
1159 SMALL_RECT UpdateRegion
;
1160 SMALL_RECT ScrollRectangle
;
1161 SMALL_RECT ClipRectangle
;
1163 HANDLE ConsoleHandle
;
1164 BOOLEAN UseClipRectangle
;
1165 COORD DestinationOrigin
;
1169 DPRINT("SrvScrollConsoleScreenBuffer\n");
1171 ConsoleHandle
= ScrollConsoleScreenBufferRequest
->ConsoleHandle
;
1172 UseClipRectangle
= ScrollConsoleScreenBufferRequest
->UseClipRectangle
;
1173 DestinationOrigin
= ScrollConsoleScreenBufferRequest
->DestinationOrigin
;
1174 Fill
= ScrollConsoleScreenBufferRequest
->Fill
;
1176 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1177 if (! NT_SUCCESS(Status
))
1181 Console
= Buff
->Header
.Console
;
1183 ScrollRectangle
= ScrollConsoleScreenBufferRequest
->ScrollRectangle
;
1185 /* Make sure source rectangle is inside the screen buffer */
1186 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
1187 if (! ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, &ScrollRectangle
))
1189 ConioUnlockScreenBuffer(Buff
);
1190 return STATUS_SUCCESS
;
1193 /* If the source was clipped on the left or top, adjust the destination accordingly */
1194 if (ScrollRectangle
.Left
< 0)
1196 DestinationOrigin
.X
-= ScrollRectangle
.Left
;
1198 if (ScrollRectangle
.Top
< 0)
1200 DestinationOrigin
.Y
-= ScrollRectangle
.Top
;
1203 if (UseClipRectangle
)
1205 ClipRectangle
= ScrollConsoleScreenBufferRequest
->ClipRectangle
;
1206 if (!ConioGetIntersection(&ClipRectangle
, &ClipRectangle
, &ScreenBuffer
))
1208 ConioUnlockScreenBuffer(Buff
);
1209 return STATUS_SUCCESS
;
1214 ClipRectangle
= ScreenBuffer
;
1217 ConioInitRect(&DstRegion
,
1218 DestinationOrigin
.Y
,
1219 DestinationOrigin
.X
,
1220 DestinationOrigin
.Y
+ ConioRectHeight(&SrcRegion
) - 1,
1221 DestinationOrigin
.X
+ ConioRectWidth(&SrcRegion
) - 1);
1223 if (ScrollConsoleScreenBufferRequest
->Unicode
)
1224 ConsoleUnicodeCharToAnsiChar(Console
, &FillChar
, &Fill
.Char
.UnicodeChar
);
1226 FillChar
= Fill
.Char
.AsciiChar
;
1228 ConioMoveRegion(Buff
, &SrcRegion
, &DstRegion
, &ClipRectangle
, Fill
.Attributes
<< 8 | (BYTE
)FillChar
);
1230 if (Buff
== Console
->ActiveBuffer
)
1232 ConioGetUnion(&UpdateRegion
, &SrcRegion
, &DstRegion
);
1233 if (ConioGetIntersection(&UpdateRegion
, &UpdateRegion
, &ClipRectangle
))
1235 /* Draw update region */
1236 ConioDrawRegion(Console
, &UpdateRegion
);
1240 ConioUnlockScreenBuffer(Buff
);
1242 return STATUS_SUCCESS
;
1245 CSR_API(CsrReadConsoleOutputChar
)
1248 PCSRSS_READ_CONSOLE_OUTPUT_CHAR ReadConsoleOutputCharRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ReadConsoleOutputCharRequest
;
1249 PCSRSS_CONSOLE Console
;
1250 PCSRSS_SCREEN_BUFFER Buff
;
1257 DPRINT("CsrReadConsoleOutputChar\n");
1259 ReadBuffer
= ReadConsoleOutputCharRequest
->String
;
1261 CharSize
= (ReadConsoleOutputCharRequest
->Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
1263 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, ReadConsoleOutputCharRequest
->ConsoleHandle
, &Buff
, GENERIC_READ
);
1264 if (! NT_SUCCESS(Status
))
1268 Console
= Buff
->Header
.Console
;
1270 Xpos
= ReadConsoleOutputCharRequest
->ReadCoord
.X
;
1271 Ypos
= (ReadConsoleOutputCharRequest
->ReadCoord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1273 for (i
= 0; i
< ReadConsoleOutputCharRequest
->NumCharsToRead
; ++i
)
1275 Char
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
)];
1277 if(ReadConsoleOutputCharRequest
->Unicode
)
1279 ConsoleAnsiCharToUnicodeChar(Console
, (WCHAR
*)ReadBuffer
, &Char
);
1280 ReadBuffer
+= sizeof(WCHAR
);
1283 *(ReadBuffer
++) = Char
;
1287 if (Xpos
== Buff
->MaxX
)
1292 if (Ypos
== Buff
->MaxY
)
1300 ReadConsoleOutputCharRequest
->EndCoord
.X
= Xpos
;
1301 ReadConsoleOutputCharRequest
->EndCoord
.Y
= (Ypos
- Buff
->VirtualY
+ Buff
->MaxY
) % Buff
->MaxY
;
1303 ConioUnlockScreenBuffer(Buff
);
1305 ReadConsoleOutputCharRequest
->CharsRead
= (DWORD
)((ULONG_PTR
)ReadBuffer
- (ULONG_PTR
)ReadConsoleOutputCharRequest
->String
) / CharSize
;
1306 if (ReadConsoleOutputCharRequest
->CharsRead
* CharSize
+ CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR
) > sizeof(CSR_API_MESSAGE
))
1308 DPRINT1("Length won't fit in message\n");
1309 return STATUS_BUFFER_TOO_SMALL
;
1312 return STATUS_SUCCESS
;
1315 CSR_API(CsrReadConsoleOutputAttrib
)
1318 PCSRSS_READ_CONSOLE_OUTPUT_ATTRIB ReadConsoleOutputAttribRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ReadConsoleOutputAttribRequest
;
1319 PCSRSS_SCREEN_BUFFER Buff
;
1323 DWORD CurrentLength
;
1325 DPRINT("CsrReadConsoleOutputAttrib\n");
1327 ReadBuffer
= ReadConsoleOutputAttribRequest
->Attribute
;
1329 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, ReadConsoleOutputAttribRequest
->ConsoleHandle
, &Buff
, GENERIC_READ
);
1330 if (! NT_SUCCESS(Status
))
1335 Xpos
= ReadConsoleOutputAttribRequest
->ReadCoord
.X
;
1336 Ypos
= (ReadConsoleOutputAttribRequest
->ReadCoord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1338 for (i
= 0; i
< ReadConsoleOutputAttribRequest
->NumAttrsToRead
; ++i
)
1340 *ReadBuffer
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
) + 1];
1345 if (Xpos
== Buff
->MaxX
)
1350 if (Ypos
== Buff
->MaxY
)
1359 ReadConsoleOutputAttribRequest
->EndCoord
.X
= Xpos
;
1360 ReadConsoleOutputAttribRequest
->EndCoord
.Y
= (Ypos
- Buff
->VirtualY
+ Buff
->MaxY
) % Buff
->MaxY
;
1362 ConioUnlockScreenBuffer(Buff
);
1364 CurrentLength
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_ATTRIB
)
1365 + ReadConsoleOutputAttribRequest
->NumAttrsToRead
* sizeof(WORD
);
1366 if (CurrentLength
> sizeof(CSR_API_MESSAGE
))
1368 DPRINT1("Length won't fit in message\n");
1369 return STATUS_BUFFER_TOO_SMALL
;
1372 return STATUS_SUCCESS
;
1375 CSR_API(SrvReadConsoleOutput
)
1377 PCSRSS_READ_CONSOLE_OUTPUT ReadConsoleOutputRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.ReadConsoleOutputRequest
;
1378 PCSR_PROCESS ProcessData
= CsrGetClientThread()->Process
;
1379 PCHAR_INFO CharInfo
;
1380 PCHAR_INFO CurCharInfo
;
1381 PCSRSS_SCREEN_BUFFER Buff
;
1386 SMALL_RECT ReadRegion
;
1387 SMALL_RECT ScreenRect
;
1393 DPRINT("SrvReadConsoleOutput\n");
1395 Status
= ConioLockScreenBuffer(ProcessData
, ReadConsoleOutputRequest
->ConsoleHandle
, &Buff
, GENERIC_READ
);
1396 if (! NT_SUCCESS(Status
))
1401 CharInfo
= ReadConsoleOutputRequest
->CharInfo
;
1402 ReadRegion
= ReadConsoleOutputRequest
->ReadRegion
;
1403 BufferSize
= ReadConsoleOutputRequest
->BufferSize
;
1404 BufferCoord
= ReadConsoleOutputRequest
->BufferCoord
;
1406 /* FIXME: Is this correct? */
1407 CodePage
= ProcessData
->Console
->OutputCodePage
;
1409 if (!Win32CsrValidateBuffer(ProcessData
, CharInfo
,
1410 BufferSize
.X
* BufferSize
.Y
, sizeof(CHAR_INFO
)))
1412 ConioUnlockScreenBuffer(Buff
);
1413 return STATUS_ACCESS_VIOLATION
;
1416 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&ReadRegion
));
1417 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&ReadRegion
));
1418 ReadRegion
.Bottom
= ReadRegion
.Top
+ SizeY
;
1419 ReadRegion
.Right
= ReadRegion
.Left
+ SizeX
;
1421 ConioInitRect(&ScreenRect
, 0, 0, Buff
->MaxY
, Buff
->MaxX
);
1422 if (! ConioGetIntersection(&ReadRegion
, &ScreenRect
, &ReadRegion
))
1424 ConioUnlockScreenBuffer(Buff
);
1425 return STATUS_SUCCESS
;
1428 for (i
= 0, Y
= ReadRegion
.Top
; Y
< ReadRegion
.Bottom
; ++i
, ++Y
)
1430 CurCharInfo
= CharInfo
+ (i
* BufferSize
.X
);
1432 Ptr
= ConioCoordToPointer(Buff
, ReadRegion
.Left
, Y
);
1433 for (X
= ReadRegion
.Left
; X
< ReadRegion
.Right
; ++X
)
1435 if (ReadConsoleOutputRequest
->Unicode
)
1437 MultiByteToWideChar(CodePage
, 0,
1439 &CurCharInfo
->Char
.UnicodeChar
, 1);
1443 CurCharInfo
->Char
.AsciiChar
= *Ptr
++;
1445 CurCharInfo
->Attributes
= *Ptr
++;
1450 ConioUnlockScreenBuffer(Buff
);
1452 ReadConsoleOutputRequest
->ReadRegion
.Right
= ReadRegion
.Left
+ SizeX
- 1;
1453 ReadConsoleOutputRequest
->ReadRegion
.Bottom
= ReadRegion
.Top
+ SizeY
- 1;
1454 ReadConsoleOutputRequest
->ReadRegion
.Left
= ReadRegion
.Left
;
1455 ReadConsoleOutputRequest
->ReadRegion
.Top
= ReadRegion
.Top
;
1457 return STATUS_SUCCESS
;
1460 CSR_API(SrvSetConsoleScreenBufferSize
)
1463 PCSRSS_SET_SCREEN_BUFFER_SIZE SetScreenBufferSize
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetScreenBufferSize
;
1464 PCSRSS_CONSOLE Console
;
1465 PCSRSS_SCREEN_BUFFER Buff
;
1467 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, SetScreenBufferSize
->OutputHandle
, &Buff
, GENERIC_WRITE
);
1468 if (!NT_SUCCESS(Status
))
1472 Console
= Buff
->Header
.Console
;
1474 Status
= ConioResizeBuffer(Console
, Buff
, SetScreenBufferSize
->Size
);
1475 ConioUnlockScreenBuffer(Buff
);