2 * reactos/subsys/csrss/win32csr/conio.c
4 * Console I/O functions
6 * ReactOS Operating System
9 /* INCLUDES ******************************************************************/
15 /* GLOBALS *******************************************************************/
17 #define ConioInitRect(Rect, top, left, bottom, right) \
18 ((Rect)->Top) = top; \
19 ((Rect)->Left) = left; \
20 ((Rect)->Bottom) = bottom; \
21 ((Rect)->Right) = right
23 #define ConioIsRectEmpty(Rect) \
24 (((Rect)->Left > (Rect)->Right) || ((Rect)->Top > (Rect)->Bottom))
26 #define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
27 WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
29 #define ConsoleAnsiCharToUnicodeChar(Console, dWChar, sChar) \
30 MultiByteToWideChar((Console)->OutputCodePage, 0, (sChar), 1, (dWChar), 1)
32 /* FUNCTIONS *****************************************************************/
35 ConioCoordToPointer(PCSRSS_SCREEN_BUFFER Buff
, ULONG X
, ULONG Y
)
37 return &Buff
->Buffer
[2 * (((Y
+ Buff
->VirtualY
) % Buff
->MaxY
) * Buff
->MaxX
+ X
)];
41 ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff
)
43 PBYTE Ptr
= ConioCoordToPointer(Buff
, 0, Buff
->CurrentY
);
46 for (Pos
= 0; Pos
< Buff
->MaxX
; Pos
++)
50 *Ptr
++ = Buff
->DefaultAttrib
;
55 CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console
,
56 PCSRSS_SCREEN_BUFFER Buffer
)
58 DPRINT("CsrInitConsoleScreenBuffer Size X %d Size Y %d\n", Buffer
->MaxX
, Buffer
->MaxY
);
60 Buffer
->Header
.Type
= CONIO_SCREEN_BUFFER_MAGIC
;
61 Buffer
->Header
.Console
= Console
;
62 Buffer
->Header
.HandleCount
= 0;
66 Buffer
->Buffer
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, Buffer
->MaxX
* Buffer
->MaxY
* 2);
67 if (NULL
== Buffer
->Buffer
)
69 return STATUS_INSUFFICIENT_RESOURCES
;
71 ConioInitScreenBuffer(Console
, Buffer
);
72 /* initialize buffer to be empty with default attributes */
73 for (Buffer
->CurrentY
= 0 ; Buffer
->CurrentY
< Buffer
->MaxY
; Buffer
->CurrentY
++)
75 ClearLineBuffer(Buffer
);
77 Buffer
->Mode
= ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
;
81 InsertHeadList(&Console
->BufferList
, &Buffer
->ListEntry
);
82 return STATUS_SUCCESS
;
86 ConioNextLine(PCSRSS_SCREEN_BUFFER Buff
, SMALL_RECT
*UpdateRect
, UINT
*ScrolledLines
)
88 /* If we hit bottom, slide the viewable screen */
89 if (++Buff
->CurrentY
== Buff
->MaxY
)
92 if (++Buff
->VirtualY
== Buff
->MaxY
)
97 ClearLineBuffer(Buff
);
98 if (UpdateRect
->Top
!= 0)
103 UpdateRect
->Left
= 0;
104 UpdateRect
->Right
= Buff
->MaxX
- 1;
105 UpdateRect
->Bottom
= Buff
->CurrentY
;
109 ConioWriteConsole(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
,
110 CHAR
*Buffer
, DWORD Length
, BOOL Attrib
)
114 SMALL_RECT UpdateRect
;
115 LONG CursorStartX
, CursorStartY
;
118 CursorStartX
= Buff
->CurrentX
;
119 CursorStartY
= Buff
->CurrentY
;
120 UpdateRect
.Left
= Buff
->MaxX
;
121 UpdateRect
.Top
= Buff
->CurrentY
;
122 UpdateRect
.Right
= -1;
123 UpdateRect
.Bottom
= Buff
->CurrentY
;
126 for (i
= 0; i
< Length
; i
++)
128 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
131 if (Buffer
[i
] == '\n')
134 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
138 else if (Buffer
[i
] == '\b')
140 /* Only handle BS if we're not on the first pos of the first line */
141 if (0 != Buff
->CurrentX
|| 0 != Buff
->CurrentY
)
143 if (0 == Buff
->CurrentX
)
145 /* slide virtual position up */
146 Buff
->CurrentX
= Buff
->MaxX
- 1;
148 UpdateRect
.Top
= min(UpdateRect
.Top
, (LONG
)Buff
->CurrentY
);
154 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
156 Ptr
[1] = Buff
->DefaultAttrib
;
157 UpdateRect
.Left
= min(UpdateRect
.Left
, (LONG
) Buff
->CurrentX
);
158 UpdateRect
.Right
= max(UpdateRect
.Right
, (LONG
) Buff
->CurrentX
);
163 else if (Buffer
[i
] == '\r')
166 UpdateRect
.Left
= min(UpdateRect
.Left
, (LONG
) Buff
->CurrentX
);
167 UpdateRect
.Right
= max(UpdateRect
.Right
, (LONG
) Buff
->CurrentX
);
171 else if (Buffer
[i
] == '\t')
175 UpdateRect
.Left
= min(UpdateRect
.Left
, (LONG
)Buff
->CurrentX
);
176 EndX
= (Buff
->CurrentX
+ 8) & ~7;
177 if (EndX
> Buff
->MaxX
)
181 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
182 while (Buff
->CurrentX
< EndX
)
185 *Ptr
++ = Buff
->DefaultAttrib
;
188 UpdateRect
.Right
= max(UpdateRect
.Right
, (LONG
) Buff
->CurrentX
- 1);
189 if (Buff
->CurrentX
== Buff
->MaxX
)
191 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
194 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
204 UpdateRect
.Left
= min(UpdateRect
.Left
, (LONG
)Buff
->CurrentX
);
205 UpdateRect
.Right
= max(UpdateRect
.Right
, (LONG
) Buff
->CurrentX
);
206 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
210 Ptr
[1] = Buff
->DefaultAttrib
;
213 if (Buff
->CurrentX
== Buff
->MaxX
)
215 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
218 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
222 Buff
->CurrentX
= CursorStartX
;
227 if (! ConioIsRectEmpty(&UpdateRect
) && Buff
== Console
->ActiveBuffer
)
229 ConioWriteStream(Console
, &UpdateRect
, CursorStartX
, CursorStartY
, ScrolledLines
,
233 return STATUS_SUCCESS
;
236 __inline BOOLEAN
ConioGetIntersection(
237 SMALL_RECT
*Intersection
,
241 if (ConioIsRectEmpty(Rect1
) ||
242 (ConioIsRectEmpty(Rect2
)) ||
243 (Rect1
->Top
> Rect2
->Bottom
) ||
244 (Rect1
->Left
> Rect2
->Right
) ||
245 (Rect1
->Bottom
< Rect2
->Top
) ||
246 (Rect1
->Right
< Rect2
->Left
))
248 /* The rectangles do not intersect */
249 ConioInitRect(Intersection
, 0, -1, 0, -1);
253 ConioInitRect(Intersection
,
254 max(Rect1
->Top
, Rect2
->Top
),
255 max(Rect1
->Left
, Rect2
->Left
),
256 min(Rect1
->Bottom
, Rect2
->Bottom
),
257 min(Rect1
->Right
, Rect2
->Right
));
262 __inline BOOLEAN
ConioGetUnion(
267 if (ConioIsRectEmpty(Rect1
))
269 if (ConioIsRectEmpty(Rect2
))
271 ConioInitRect(Union
, 0, -1, 0, -1);
279 else if (ConioIsRectEmpty(Rect2
))
286 min(Rect1
->Top
, Rect2
->Top
),
287 min(Rect1
->Left
, Rect2
->Left
),
288 max(Rect1
->Bottom
, Rect2
->Bottom
),
289 max(Rect1
->Right
, Rect2
->Right
));
295 /* Move from one rectangle to another. We must be careful about the order that
296 * this is done, to avoid overwriting parts of the source before they are moved. */
298 ConioMoveRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer
,
299 SMALL_RECT
*SrcRegion
,
300 SMALL_RECT
*DstRegion
,
301 SMALL_RECT
*ClipRegion
,
304 int Width
= ConioRectWidth(SrcRegion
);
305 int Height
= ConioRectHeight(SrcRegion
);
316 /* Moving down: work from bottom up */
317 SY
= SrcRegion
->Bottom
;
318 DY
= DstRegion
->Bottom
;
321 for (i
= 0; i
< Height
; i
++)
323 PWORD SRow
= (PWORD
)ConioCoordToPointer(ScreenBuffer
, 0, SY
);
324 PWORD DRow
= (PWORD
)ConioCoordToPointer(ScreenBuffer
, 0, DY
);
326 SX
= SrcRegion
->Left
;
327 DX
= DstRegion
->Left
;
331 /* Moving right: work from right to left */
332 SX
= SrcRegion
->Right
;
333 DX
= DstRegion
->Right
;
336 for (j
= 0; j
< Width
; j
++)
338 WORD Cell
= SRow
[SX
];
339 if (SX
>= ClipRegion
->Left
&& SX
<= ClipRegion
->Right
340 && SY
>= ClipRegion
->Top
&& SY
<= ClipRegion
->Bottom
)
344 if (DX
>= ClipRegion
->Left
&& DX
<= ClipRegion
->Right
345 && DY
>= ClipRegion
->Top
&& DY
<= ClipRegion
->Bottom
)
357 CSR_API(CsrWriteConsole
)
361 PCSRSS_SCREEN_BUFFER Buff
;
362 PCSR_PROCESS ProcessData
= CsrGetClientThread()->Process
;
363 PCSRSS_CONSOLE Console
;
366 ULONG CharSize
= (ApiMessage
->Data
.WriteConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
368 DPRINT("CsrWriteConsole\n");
370 if (ApiMessage
->Header
.u1
.s1
.TotalLength
371 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE
)
372 + (ApiMessage
->Data
.WriteConsoleRequest
.NrCharactersToWrite
* CharSize
))
374 DPRINT1("Invalid ApiMessage size\n");
375 return STATUS_INVALID_PARAMETER
;
378 Status
= ConioLockScreenBuffer(ProcessData
, ApiMessage
->Data
.WriteConsoleRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
379 if (! NT_SUCCESS(Status
))
383 Console
= Buff
->Header
.Console
;
385 if (Console
->UnpauseEvent
)
387 Status
= NtDuplicateObject(GetCurrentProcess(), Console
->UnpauseEvent
,
388 ProcessData
->ProcessHandle
, &ApiMessage
->Data
.WriteConsoleRequest
.UnpauseEvent
,
390 ConioUnlockScreenBuffer(Buff
);
391 return NT_SUCCESS(Status
) ? STATUS_PENDING
: Status
;
394 if(ApiMessage
->Data
.WriteConsoleRequest
.Unicode
)
396 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
397 (PWCHAR
)ApiMessage
->Data
.WriteConsoleRequest
.Buffer
,
398 ApiMessage
->Data
.WriteConsoleRequest
.NrCharactersToWrite
,
399 NULL
, 0, NULL
, NULL
);
400 Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
403 WideCharToMultiByte(Console
->OutputCodePage
, 0,
404 (PWCHAR
)ApiMessage
->Data
.WriteConsoleRequest
.Buffer
,
405 ApiMessage
->Data
.WriteConsoleRequest
.NrCharactersToWrite
,
406 Buffer
, Length
, NULL
, NULL
);
410 Status
= STATUS_NO_MEMORY
;
415 Buffer
= (PCHAR
)ApiMessage
->Data
.WriteConsoleRequest
.Buffer
;
420 if (NT_SUCCESS(Status
))
422 Status
= ConioWriteConsole(Console
, Buff
, Buffer
,
423 ApiMessage
->Data
.WriteConsoleRequest
.NrCharactersToWrite
, TRUE
);
424 if (NT_SUCCESS(Status
))
426 Written
= ApiMessage
->Data
.WriteConsoleRequest
.NrCharactersToWrite
;
429 if (ApiMessage
->Data
.WriteConsoleRequest
.Unicode
)
431 RtlFreeHeap(GetProcessHeap(), 0, Buffer
);
434 ConioUnlockScreenBuffer(Buff
);
436 ApiMessage
->Data
.WriteConsoleRequest
.NrCharactersWritten
= Written
;
442 ConioDeleteScreenBuffer(PCSRSS_SCREEN_BUFFER Buffer
)
444 PCSRSS_CONSOLE Console
= Buffer
->Header
.Console
;
446 RemoveEntryList(&Buffer
->ListEntry
);
447 if (Buffer
== Console
->ActiveBuffer
)
449 /* Deleted active buffer; switch to most recently created */
450 Console
->ActiveBuffer
= NULL
;
451 if (!IsListEmpty(&Console
->BufferList
))
453 Console
->ActiveBuffer
= CONTAINING_RECORD(Console
->BufferList
.Flink
, CSRSS_SCREEN_BUFFER
, ListEntry
);
454 ConioDrawConsole(Console
);
458 HeapFree(Win32CsrApiHeap
, 0, Buffer
->Buffer
);
459 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
463 ConioDrawConsole(PCSRSS_CONSOLE Console
)
467 ConioInitRect(&Region
, 0, 0, Console
->Size
.Y
- 1, Console
->Size
.X
- 1);
469 ConioDrawRegion(Console
, &Region
);
472 CSR_API(CsrGetScreenBufferInfo
)
475 PCSRSS_CONSOLE Console
;
476 PCSRSS_SCREEN_BUFFER Buff
;
477 PCONSOLE_SCREEN_BUFFER_INFO pInfo
;
479 DPRINT("CsrGetScreenBufferInfo\n");
481 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, ApiMessage
->Data
.ScreenBufferInfoRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
482 if (! NT_SUCCESS(Status
))
486 Console
= Buff
->Header
.Console
;
487 pInfo
= &ApiMessage
->Data
.ScreenBufferInfoRequest
.Info
;
488 pInfo
->dwSize
.X
= Buff
->MaxX
;
489 pInfo
->dwSize
.Y
= Buff
->MaxY
;
490 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
;
491 pInfo
->dwCursorPosition
.Y
= Buff
->CurrentY
;
492 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
493 pInfo
->srWindow
.Left
= Buff
->ShowX
;
494 pInfo
->srWindow
.Right
= Buff
->ShowX
+ Console
->Size
.X
- 1;
495 pInfo
->srWindow
.Top
= Buff
->ShowY
;
496 pInfo
->srWindow
.Bottom
= Buff
->ShowY
+ Console
->Size
.Y
- 1;
497 pInfo
->dwMaximumWindowSize
.X
= Buff
->MaxX
;
498 pInfo
->dwMaximumWindowSize
.Y
= Buff
->MaxY
;
499 ConioUnlockScreenBuffer(Buff
);
501 return STATUS_SUCCESS
;
504 CSR_API(CsrSetCursor
)
507 PCSRSS_CONSOLE Console
;
508 PCSRSS_SCREEN_BUFFER Buff
;
509 LONG OldCursorX
, OldCursorY
;
510 LONG NewCursorX
, NewCursorY
;
512 DPRINT("CsrSetCursor\n");
514 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, ApiMessage
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
515 if (! NT_SUCCESS(Status
))
519 Console
= Buff
->Header
.Console
;
521 NewCursorX
= ApiMessage
->Data
.SetCursorRequest
.Position
.X
;
522 NewCursorY
= ApiMessage
->Data
.SetCursorRequest
.Position
.Y
;
523 if (NewCursorX
< 0 || NewCursorX
>= Buff
->MaxX
||
524 NewCursorY
< 0 || NewCursorY
>= Buff
->MaxY
)
526 ConioUnlockScreenBuffer(Buff
);
527 return STATUS_INVALID_PARAMETER
;
529 OldCursorX
= Buff
->CurrentX
;
530 OldCursorY
= Buff
->CurrentY
;
531 Buff
->CurrentX
= NewCursorX
;
532 Buff
->CurrentY
= NewCursorY
;
533 if (Buff
== Console
->ActiveBuffer
)
535 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
537 ConioUnlockScreenBuffer(Buff
);
538 return STATUS_UNSUCCESSFUL
;
542 ConioUnlockScreenBuffer(Buff
);
544 return STATUS_SUCCESS
;
548 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff
, SMALL_RECT
*UpdateRect
, COORD
*Start
, UINT Length
)
550 if (Buff
->MaxX
<= Start
->X
+ Length
)
552 UpdateRect
->Left
= 0;
556 UpdateRect
->Left
= Start
->X
;
558 if (Buff
->MaxX
<= Start
->X
+ Length
)
560 UpdateRect
->Right
= Buff
->MaxX
- 1;
564 UpdateRect
->Right
= Start
->X
+ Length
- 1;
566 UpdateRect
->Top
= Start
->Y
;
567 UpdateRect
->Bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->MaxX
;
568 if (Buff
->MaxY
<= UpdateRect
->Bottom
)
570 UpdateRect
->Bottom
= Buff
->MaxY
- 1;
574 CSR_API(CsrWriteConsoleOutputChar
)
577 PCHAR String
, tmpString
= NULL
;
579 PCSRSS_CONSOLE Console
;
580 PCSRSS_SCREEN_BUFFER Buff
;
581 DWORD X
, Y
, Length
, CharSize
, Written
= 0;
582 SMALL_RECT UpdateRect
;
584 DPRINT("CsrWriteConsoleOutputChar\n");
586 CharSize
= (ApiMessage
->Data
.WriteConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
588 if (ApiMessage
->Header
.u1
.s1
.TotalLength
589 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR
)
590 + (ApiMessage
->Data
.WriteConsoleOutputCharRequest
.Length
* CharSize
))
592 DPRINT1("Invalid ApiMessage size\n");
593 return STATUS_INVALID_PARAMETER
;
596 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
,
597 ApiMessage
->Data
.WriteConsoleOutputCharRequest
.ConsoleHandle
,
600 if (NT_SUCCESS(Status
))
602 Console
= Buff
->Header
.Console
;
603 if(ApiMessage
->Data
.WriteConsoleOutputCharRequest
.Unicode
)
605 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
606 (PWCHAR
)ApiMessage
->Data
.WriteConsoleOutputCharRequest
.String
,
607 ApiMessage
->Data
.WriteConsoleOutputCharRequest
.Length
,
608 NULL
, 0, NULL
, NULL
);
609 tmpString
= String
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
612 WideCharToMultiByte(Console
->OutputCodePage
, 0,
613 (PWCHAR
)ApiMessage
->Data
.WriteConsoleOutputCharRequest
.String
,
614 ApiMessage
->Data
.WriteConsoleOutputCharRequest
.Length
,
615 String
, Length
, NULL
, NULL
);
619 Status
= STATUS_NO_MEMORY
;
624 String
= (PCHAR
)ApiMessage
->Data
.WriteConsoleOutputCharRequest
.String
;
629 if (NT_SUCCESS(Status
))
631 X
= ApiMessage
->Data
.WriteConsoleOutputCharRequest
.Coord
.X
;
632 Y
= (ApiMessage
->Data
.WriteConsoleOutputCharRequest
.Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
633 Length
= ApiMessage
->Data
.WriteConsoleOutputCharRequest
.Length
;
634 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
640 if (++X
== Buff
->MaxX
)
642 if (++Y
== Buff
->MaxY
)
645 Buffer
= Buff
->Buffer
;
650 if (Buff
== Console
->ActiveBuffer
)
652 ConioComputeUpdateRect(Buff
, &UpdateRect
, &ApiMessage
->Data
.WriteConsoleOutputCharRequest
.Coord
,
653 ApiMessage
->Data
.WriteConsoleOutputCharRequest
.Length
);
654 ConioDrawRegion(Console
, &UpdateRect
);
657 ApiMessage
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.X
= X
;
658 ApiMessage
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->VirtualY
) % Buff
->MaxY
;
661 if (ApiMessage
->Data
.WriteConsoleRequest
.Unicode
)
663 RtlFreeHeap(GetProcessHeap(), 0, tmpString
);
666 ConioUnlockScreenBuffer(Buff
);
668 ApiMessage
->Data
.WriteConsoleOutputCharRequest
.NrCharactersWritten
= Written
;
672 CSR_API(CsrFillOutputChar
)
675 PCSRSS_CONSOLE Console
;
676 PCSRSS_SCREEN_BUFFER Buff
;
677 DWORD X
, Y
, Length
, Written
= 0;
680 SMALL_RECT UpdateRect
;
682 DPRINT("CsrFillOutputChar\n");
684 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, ApiMessage
->Data
.FillOutputRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
685 if (! NT_SUCCESS(Status
))
689 Console
= Buff
->Header
.Console
;
691 X
= ApiMessage
->Data
.FillOutputRequest
.Position
.X
;
692 Y
= (ApiMessage
->Data
.FillOutputRequest
.Position
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
693 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
694 if(ApiMessage
->Data
.FillOutputRequest
.Unicode
)
695 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &ApiMessage
->Data
.FillOutputRequest
.Char
.UnicodeChar
);
697 Char
= ApiMessage
->Data
.FillOutputRequest
.Char
.AsciiChar
;
698 Length
= ApiMessage
->Data
.FillOutputRequest
.Length
;
704 if (++X
== Buff
->MaxX
)
706 if (++Y
== Buff
->MaxY
)
709 Buffer
= Buff
->Buffer
;
715 if (Buff
== Console
->ActiveBuffer
)
717 ConioComputeUpdateRect(Buff
, &UpdateRect
, &ApiMessage
->Data
.FillOutputRequest
.Position
,
718 ApiMessage
->Data
.FillOutputRequest
.Length
);
719 ConioDrawRegion(Console
, &UpdateRect
);
722 ConioUnlockScreenBuffer(Buff
);
723 Length
= ApiMessage
->Data
.FillOutputRequest
.Length
;
724 ApiMessage
->Data
.FillOutputRequest
.NrCharactersWritten
= Length
;
725 return STATUS_SUCCESS
;
728 CSR_API(CsrWriteConsoleOutputAttrib
)
730 PCSRSS_CONSOLE Console
;
731 PCSRSS_SCREEN_BUFFER Buff
;
736 SMALL_RECT UpdateRect
;
738 DPRINT("CsrWriteConsoleOutputAttrib\n");
740 if (ApiMessage
->Header
.u1
.s1
.TotalLength
741 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB
)
742 + ApiMessage
->Data
.WriteConsoleOutputAttribRequest
.Length
* sizeof(WORD
))
744 DPRINT1("Invalid ApiMessage size\n");
745 return STATUS_INVALID_PARAMETER
;
748 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
,
749 ApiMessage
->Data
.WriteConsoleOutputAttribRequest
.ConsoleHandle
,
752 if (! NT_SUCCESS(Status
))
756 Console
= Buff
->Header
.Console
;
758 X
= ApiMessage
->Data
.WriteConsoleOutputAttribRequest
.Coord
.X
;
759 Y
= (ApiMessage
->Data
.WriteConsoleOutputAttribRequest
.Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
760 Length
= ApiMessage
->Data
.WriteConsoleOutputAttribRequest
.Length
;
761 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + 1];
762 Attribute
= ApiMessage
->Data
.WriteConsoleOutputAttribRequest
.Attribute
;
765 *Buffer
= (UCHAR
)(*Attribute
++);
767 if (++X
== Buff
->MaxX
)
769 if (++Y
== Buff
->MaxY
)
772 Buffer
= Buff
->Buffer
+ 1;
778 if (Buff
== Console
->ActiveBuffer
)
780 ConioComputeUpdateRect(Buff
, &UpdateRect
, &ApiMessage
->Data
.WriteConsoleOutputAttribRequest
.Coord
,
781 ApiMessage
->Data
.WriteConsoleOutputAttribRequest
.Length
);
782 ConioDrawRegion(Console
, &UpdateRect
);
785 ApiMessage
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.X
= X
;
786 ApiMessage
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->VirtualY
) % Buff
->MaxY
;
788 ConioUnlockScreenBuffer(Buff
);
790 return STATUS_SUCCESS
;
793 CSR_API(CsrFillOutputAttrib
)
795 PCSRSS_SCREEN_BUFFER Buff
;
800 SMALL_RECT UpdateRect
;
801 PCSRSS_CONSOLE Console
;
803 DPRINT("CsrFillOutputAttrib\n");
805 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, ApiMessage
->Data
.FillOutputAttribRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
806 if (! NT_SUCCESS(Status
))
810 Console
= Buff
->Header
.Console
;
812 X
= ApiMessage
->Data
.FillOutputAttribRequest
.Coord
.X
;
813 Y
= (ApiMessage
->Data
.FillOutputAttribRequest
.Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
814 Length
= ApiMessage
->Data
.FillOutputAttribRequest
.Length
;
815 Attr
= ApiMessage
->Data
.FillOutputAttribRequest
.Attribute
;
816 Buffer
= &Buff
->Buffer
[(Y
* Buff
->MaxX
* 2) + (X
* 2) + 1];
821 if (++X
== Buff
->MaxX
)
823 if (++Y
== Buff
->MaxY
)
826 Buffer
= Buff
->Buffer
+ 1;
832 if (Buff
== Console
->ActiveBuffer
)
834 ConioComputeUpdateRect(Buff
, &UpdateRect
, &ApiMessage
->Data
.FillOutputAttribRequest
.Coord
,
835 ApiMessage
->Data
.FillOutputAttribRequest
.Length
);
836 ConioDrawRegion(Console
, &UpdateRect
);
839 ConioUnlockScreenBuffer(Buff
);
841 return STATUS_SUCCESS
;
845 ConioEffectiveCursorSize(PCSRSS_CONSOLE Console
, DWORD Scale
)
847 DWORD Size
= (Console
->ActiveBuffer
->CursorInfo
.dwSize
* Scale
+ 99) / 100;
848 /* If line input in progress, perhaps adjust for insert toggle */
849 if (Console
->LineBuffer
&& !Console
->LineComplete
&& Console
->LineInsertToggle
)
850 return (Size
* 2 <= Scale
) ? (Size
* 2) : (Size
/ 2);
854 CSR_API(CsrGetCursorInfo
)
856 PCSRSS_SCREEN_BUFFER Buff
;
859 DPRINT("CsrGetCursorInfo\n");
861 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, ApiMessage
->Data
.GetCursorInfoRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
862 if (! NT_SUCCESS(Status
))
866 ApiMessage
->Data
.GetCursorInfoRequest
.Info
.bVisible
= Buff
->CursorInfo
.bVisible
;
867 ApiMessage
->Data
.GetCursorInfoRequest
.Info
.dwSize
= Buff
->CursorInfo
.dwSize
;
868 ConioUnlockScreenBuffer(Buff
);
870 return STATUS_SUCCESS
;
873 CSR_API(CsrSetCursorInfo
)
875 PCSRSS_CONSOLE Console
;
876 PCSRSS_SCREEN_BUFFER Buff
;
881 DPRINT("CsrSetCursorInfo\n");
883 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, ApiMessage
->Data
.SetCursorInfoRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
884 if (! NT_SUCCESS(Status
))
888 Console
= Buff
->Header
.Console
;
890 Size
= ApiMessage
->Data
.SetCursorInfoRequest
.Info
.dwSize
;
891 Visible
= ApiMessage
->Data
.SetCursorInfoRequest
.Info
.bVisible
;
901 if (Size
!= Buff
->CursorInfo
.dwSize
902 || (Visible
&& ! Buff
->CursorInfo
.bVisible
) || (! Visible
&& Buff
->CursorInfo
.bVisible
))
904 Buff
->CursorInfo
.dwSize
= Size
;
905 Buff
->CursorInfo
.bVisible
= Visible
;
907 if (! ConioSetCursorInfo(Console
, Buff
))
909 ConioUnlockScreenBuffer(Buff
);
910 return STATUS_UNSUCCESSFUL
;
914 ConioUnlockScreenBuffer(Buff
);
916 return STATUS_SUCCESS
;
919 CSR_API(CsrSetTextAttrib
)
922 PCSRSS_CONSOLE Console
;
923 PCSRSS_SCREEN_BUFFER Buff
;
925 DPRINT("CsrSetTextAttrib\n");
927 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, ApiMessage
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
928 if (! NT_SUCCESS(Status
))
932 Console
= Buff
->Header
.Console
;
934 Buff
->DefaultAttrib
= ApiMessage
->Data
.SetAttribRequest
.Attrib
;
935 if (Buff
== Console
->ActiveBuffer
)
937 if (! ConioUpdateScreenInfo(Console
, Buff
))
939 ConioUnlockScreenBuffer(Buff
);
940 return STATUS_UNSUCCESSFUL
;
944 ConioUnlockScreenBuffer(Buff
);
946 return STATUS_SUCCESS
;
949 CSR_API(CsrCreateScreenBuffer
)
951 PCSR_PROCESS ProcessData
= CsrGetClientThread()->Process
;
952 PCSRSS_CONSOLE Console
;
953 PCSRSS_SCREEN_BUFFER Buff
;
956 DPRINT("CsrCreateScreenBuffer\n");
958 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
959 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
960 if (! NT_SUCCESS(Status
))
965 Buff
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
969 if (Console
->ActiveBuffer
)
971 Buff
->MaxX
= Console
->ActiveBuffer
->MaxX
;
972 Buff
->MaxY
= Console
->ActiveBuffer
->MaxY
;
973 Buff
->CursorInfo
.bVisible
= Console
->ActiveBuffer
->CursorInfo
.bVisible
;
974 Buff
->CursorInfo
.dwSize
= Console
->ActiveBuffer
->CursorInfo
.dwSize
;
978 Buff
->CursorInfo
.bVisible
= TRUE
;
979 Buff
->CursorInfo
.dwSize
= CSR_DEFAULT_CURSOR_SIZE
;
992 Status
= CsrInitConsoleScreenBuffer(Console
, Buff
);
993 if (NT_SUCCESS(Status
))
995 Status
= Win32CsrInsertObject(ProcessData
,
996 &ApiMessage
->Data
.CreateScreenBufferRequest
.OutputHandle
,
998 ApiMessage
->Data
.CreateScreenBufferRequest
.Access
,
999 ApiMessage
->Data
.CreateScreenBufferRequest
.Inheritable
,
1000 ApiMessage
->Data
.CreateScreenBufferRequest
.ShareMode
);
1005 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1008 ConioUnlockConsole(Console
);
1009 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
1013 CSR_API(CsrSetScreenBuffer
)
1016 PCSRSS_CONSOLE Console
;
1017 PCSRSS_SCREEN_BUFFER Buff
;
1019 DPRINT("CsrSetScreenBuffer\n");
1021 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, ApiMessage
->Data
.SetScreenBufferRequest
.OutputHandle
, &Buff
, GENERIC_WRITE
);
1022 if (! NT_SUCCESS(Status
))
1026 Console
= Buff
->Header
.Console
;
1028 if (Buff
== Console
->ActiveBuffer
)
1030 ConioUnlockScreenBuffer(Buff
);
1031 return STATUS_SUCCESS
;
1034 /* If old buffer has no handles, it's now unreferenced */
1035 if (Console
->ActiveBuffer
->Header
.HandleCount
== 0)
1037 ConioDeleteScreenBuffer(Console
->ActiveBuffer
);
1039 /* tie console to new buffer */
1040 Console
->ActiveBuffer
= Buff
;
1041 /* Redraw the console */
1042 ConioDrawConsole(Console
);
1044 ConioUnlockScreenBuffer(Buff
);
1046 return STATUS_SUCCESS
;
1049 CSR_API(CsrWriteConsoleOutput
)
1051 SHORT i
, X
, Y
, SizeX
, SizeY
;
1052 PCSR_PROCESS ProcessData
= CsrGetClientThread()->Process
;
1053 PCSRSS_CONSOLE Console
;
1054 PCSRSS_SCREEN_BUFFER Buff
;
1055 SMALL_RECT ScreenBuffer
;
1056 CHAR_INFO
* CurCharInfo
;
1057 SMALL_RECT WriteRegion
;
1058 CHAR_INFO
* CharInfo
;
1064 DPRINT("CsrWriteConsoleOutput\n");
1066 Status
= ConioLockScreenBuffer(ProcessData
,
1067 ApiMessage
->Data
.WriteConsoleOutputRequest
.ConsoleHandle
,
1070 if (! NT_SUCCESS(Status
))
1074 Console
= Buff
->Header
.Console
;
1076 BufferSize
= ApiMessage
->Data
.WriteConsoleOutputRequest
.BufferSize
;
1077 BufferCoord
= ApiMessage
->Data
.WriteConsoleOutputRequest
.BufferCoord
;
1078 CharInfo
= ApiMessage
->Data
.WriteConsoleOutputRequest
.CharInfo
;
1079 if (!Win32CsrValidateBuffer(ProcessData
, CharInfo
,
1080 BufferSize
.X
* BufferSize
.Y
, sizeof(CHAR_INFO
)))
1082 ConioUnlockScreenBuffer(Buff
);
1083 return STATUS_ACCESS_VIOLATION
;
1085 WriteRegion
= ApiMessage
->Data
.WriteConsoleOutputRequest
.WriteRegion
;
1087 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&WriteRegion
));
1088 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&WriteRegion
));
1089 WriteRegion
.Bottom
= WriteRegion
.Top
+ SizeY
- 1;
1090 WriteRegion
.Right
= WriteRegion
.Left
+ SizeX
- 1;
1092 /* Make sure WriteRegion is inside the screen buffer */
1093 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
1094 if (! ConioGetIntersection(&WriteRegion
, &ScreenBuffer
, &WriteRegion
))
1096 ConioUnlockScreenBuffer(Buff
);
1098 /* It is okay to have a WriteRegion completely outside the screen buffer.
1099 No data is written then. */
1100 return STATUS_SUCCESS
;
1103 for (i
= 0, Y
= WriteRegion
.Top
; Y
<= WriteRegion
.Bottom
; i
++, Y
++)
1105 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
1106 Ptr
= ConioCoordToPointer(Buff
, WriteRegion
.Left
, Y
);
1107 for (X
= WriteRegion
.Left
; X
<= WriteRegion
.Right
; X
++)
1110 if (ApiMessage
->Data
.WriteConsoleOutputRequest
.Unicode
)
1112 ConsoleUnicodeCharToAnsiChar(Console
, &AsciiChar
, &CurCharInfo
->Char
.UnicodeChar
);
1116 AsciiChar
= CurCharInfo
->Char
.AsciiChar
;
1119 *Ptr
++ = CurCharInfo
->Attributes
;
1124 ConioDrawRegion(Console
, &WriteRegion
);
1126 ConioUnlockScreenBuffer(Buff
);
1128 ApiMessage
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
= WriteRegion
.Left
+ SizeX
- 1;
1129 ApiMessage
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
= WriteRegion
.Top
+ SizeY
- 1;
1130 ApiMessage
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
= WriteRegion
.Left
;
1131 ApiMessage
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
= WriteRegion
.Top
;
1133 return STATUS_SUCCESS
;
1136 CSR_API(CsrScrollConsoleScreenBuffer
)
1138 PCSRSS_CONSOLE Console
;
1139 PCSRSS_SCREEN_BUFFER Buff
;
1140 SMALL_RECT ScreenBuffer
;
1141 SMALL_RECT SrcRegion
;
1142 SMALL_RECT DstRegion
;
1143 SMALL_RECT UpdateRegion
;
1144 SMALL_RECT ScrollRectangle
;
1145 SMALL_RECT ClipRectangle
;
1147 HANDLE ConsoleHandle
;
1148 BOOLEAN UseClipRectangle
;
1149 COORD DestinationOrigin
;
1153 DPRINT("CsrScrollConsoleScreenBuffer\n");
1155 ConsoleHandle
= ApiMessage
->Data
.ScrollConsoleScreenBufferRequest
.ConsoleHandle
;
1156 UseClipRectangle
= ApiMessage
->Data
.ScrollConsoleScreenBufferRequest
.UseClipRectangle
;
1157 DestinationOrigin
= ApiMessage
->Data
.ScrollConsoleScreenBufferRequest
.DestinationOrigin
;
1158 Fill
= ApiMessage
->Data
.ScrollConsoleScreenBufferRequest
.Fill
;
1160 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1161 if (! NT_SUCCESS(Status
))
1165 Console
= Buff
->Header
.Console
;
1167 ScrollRectangle
= ApiMessage
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
;
1169 /* Make sure source rectangle is inside the screen buffer */
1170 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
1171 if (! ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, &ScrollRectangle
))
1173 ConioUnlockScreenBuffer(Buff
);
1174 return STATUS_SUCCESS
;
1177 /* If the source was clipped on the left or top, adjust the destination accordingly */
1178 if (ScrollRectangle
.Left
< 0)
1180 DestinationOrigin
.X
-= ScrollRectangle
.Left
;
1182 if (ScrollRectangle
.Top
< 0)
1184 DestinationOrigin
.Y
-= ScrollRectangle
.Top
;
1187 if (UseClipRectangle
)
1189 ClipRectangle
= ApiMessage
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
;
1190 if (!ConioGetIntersection(&ClipRectangle
, &ClipRectangle
, &ScreenBuffer
))
1192 ConioUnlockScreenBuffer(Buff
);
1193 return STATUS_SUCCESS
;
1198 ClipRectangle
= ScreenBuffer
;
1201 ConioInitRect(&DstRegion
,
1202 DestinationOrigin
.Y
,
1203 DestinationOrigin
.X
,
1204 DestinationOrigin
.Y
+ ConioRectHeight(&SrcRegion
) - 1,
1205 DestinationOrigin
.X
+ ConioRectWidth(&SrcRegion
) - 1);
1207 if (ApiMessage
->Data
.ScrollConsoleScreenBufferRequest
.Unicode
)
1208 ConsoleUnicodeCharToAnsiChar(Console
, &FillChar
, &Fill
.Char
.UnicodeChar
);
1210 FillChar
= Fill
.Char
.AsciiChar
;
1212 ConioMoveRegion(Buff
, &SrcRegion
, &DstRegion
, &ClipRectangle
, Fill
.Attributes
<< 8 | (BYTE
)FillChar
);
1214 if (Buff
== Console
->ActiveBuffer
)
1216 ConioGetUnion(&UpdateRegion
, &SrcRegion
, &DstRegion
);
1217 if (ConioGetIntersection(&UpdateRegion
, &UpdateRegion
, &ClipRectangle
))
1219 /* Draw update region */
1220 ConioDrawRegion(Console
, &UpdateRegion
);
1224 ConioUnlockScreenBuffer(Buff
);
1226 return STATUS_SUCCESS
;
1229 CSR_API(CsrReadConsoleOutputChar
)
1232 PCSRSS_CONSOLE Console
;
1233 PCSRSS_SCREEN_BUFFER Buff
;
1240 DPRINT("CsrReadConsoleOutputChar\n");
1242 ReadBuffer
= ApiMessage
->Data
.ReadConsoleOutputCharRequest
.String
;
1244 CharSize
= (ApiMessage
->Data
.ReadConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
1246 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, ApiMessage
->Data
.ReadConsoleOutputCharRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
1247 if (! NT_SUCCESS(Status
))
1251 Console
= Buff
->Header
.Console
;
1253 Xpos
= ApiMessage
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.X
;
1254 Ypos
= (ApiMessage
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1256 for (i
= 0; i
< ApiMessage
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
; ++i
)
1258 Char
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
)];
1260 if(ApiMessage
->Data
.ReadConsoleOutputCharRequest
.Unicode
)
1262 ConsoleAnsiCharToUnicodeChar(Console
, (WCHAR
*)ReadBuffer
, &Char
);
1263 ReadBuffer
+= sizeof(WCHAR
);
1266 *(ReadBuffer
++) = Char
;
1270 if (Xpos
== Buff
->MaxX
)
1275 if (Ypos
== Buff
->MaxY
)
1283 ApiMessage
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.X
= Xpos
;
1284 ApiMessage
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.Y
= (Ypos
- Buff
->VirtualY
+ Buff
->MaxY
) % Buff
->MaxY
;
1286 ConioUnlockScreenBuffer(Buff
);
1288 ApiMessage
->Data
.ReadConsoleOutputCharRequest
.CharsRead
= (DWORD
)((ULONG_PTR
)ReadBuffer
- (ULONG_PTR
)ApiMessage
->Data
.ReadConsoleOutputCharRequest
.String
) / CharSize
;
1289 if (ApiMessage
->Data
.ReadConsoleOutputCharRequest
.CharsRead
* CharSize
+ CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR
) > sizeof(CSR_API_MESSAGE
))
1291 DPRINT1("Length won't fit in message\n");
1292 return STATUS_BUFFER_TOO_SMALL
;
1295 return STATUS_SUCCESS
;
1299 CSR_API(CsrReadConsoleOutputAttrib
)
1302 PCSRSS_SCREEN_BUFFER Buff
;
1306 DWORD CurrentLength
;
1308 DPRINT("CsrReadConsoleOutputAttrib\n");
1310 ReadBuffer
= ApiMessage
->Data
.ReadConsoleOutputAttribRequest
.Attribute
;
1312 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, ApiMessage
->Data
.ReadConsoleOutputAttribRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
1313 if (! NT_SUCCESS(Status
))
1318 Xpos
= ApiMessage
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.X
;
1319 Ypos
= (ApiMessage
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1321 for (i
= 0; i
< ApiMessage
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
; ++i
)
1323 *ReadBuffer
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
) + 1];
1328 if (Xpos
== Buff
->MaxX
)
1333 if (Ypos
== Buff
->MaxY
)
1342 ApiMessage
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.X
= Xpos
;
1343 ApiMessage
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.Y
= (Ypos
- Buff
->VirtualY
+ Buff
->MaxY
) % Buff
->MaxY
;
1345 ConioUnlockScreenBuffer(Buff
);
1347 CurrentLength
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_ATTRIB
)
1348 + ApiMessage
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
* sizeof(WORD
);
1349 if (CurrentLength
> sizeof(CSR_API_MESSAGE
))
1351 DPRINT1("Length won't fit in message\n");
1352 return STATUS_BUFFER_TOO_SMALL
;
1355 return STATUS_SUCCESS
;
1358 CSR_API(CsrReadConsoleOutput
)
1360 PCSR_PROCESS ProcessData
= CsrGetClientThread()->Process
;
1361 PCHAR_INFO CharInfo
;
1362 PCHAR_INFO CurCharInfo
;
1363 PCSRSS_SCREEN_BUFFER Buff
;
1368 SMALL_RECT ReadRegion
;
1369 SMALL_RECT ScreenRect
;
1375 DPRINT("CsrReadConsoleOutput\n");
1377 Status
= ConioLockScreenBuffer(ProcessData
, ApiMessage
->Data
.ReadConsoleOutputRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
1378 if (! NT_SUCCESS(Status
))
1383 CharInfo
= ApiMessage
->Data
.ReadConsoleOutputRequest
.CharInfo
;
1384 ReadRegion
= ApiMessage
->Data
.ReadConsoleOutputRequest
.ReadRegion
;
1385 BufferSize
= ApiMessage
->Data
.ReadConsoleOutputRequest
.BufferSize
;
1386 BufferCoord
= ApiMessage
->Data
.ReadConsoleOutputRequest
.BufferCoord
;
1388 /* FIXME: Is this correct? */
1389 CodePage
= ProcessData
->Console
->OutputCodePage
;
1391 if (!Win32CsrValidateBuffer(ProcessData
, CharInfo
,
1392 BufferSize
.X
* BufferSize
.Y
, sizeof(CHAR_INFO
)))
1394 ConioUnlockScreenBuffer(Buff
);
1395 return STATUS_ACCESS_VIOLATION
;
1398 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&ReadRegion
));
1399 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&ReadRegion
));
1400 ReadRegion
.Bottom
= ReadRegion
.Top
+ SizeY
;
1401 ReadRegion
.Right
= ReadRegion
.Left
+ SizeX
;
1403 ConioInitRect(&ScreenRect
, 0, 0, Buff
->MaxY
, Buff
->MaxX
);
1404 if (! ConioGetIntersection(&ReadRegion
, &ScreenRect
, &ReadRegion
))
1406 ConioUnlockScreenBuffer(Buff
);
1407 return STATUS_SUCCESS
;
1410 for (i
= 0, Y
= ReadRegion
.Top
; Y
< ReadRegion
.Bottom
; ++i
, ++Y
)
1412 CurCharInfo
= CharInfo
+ (i
* BufferSize
.X
);
1414 Ptr
= ConioCoordToPointer(Buff
, ReadRegion
.Left
, Y
);
1415 for (X
= ReadRegion
.Left
; X
< ReadRegion
.Right
; ++X
)
1417 if (ApiMessage
->Data
.ReadConsoleOutputRequest
.Unicode
)
1419 MultiByteToWideChar(CodePage
, 0,
1421 &CurCharInfo
->Char
.UnicodeChar
, 1);
1425 CurCharInfo
->Char
.AsciiChar
= *Ptr
++;
1427 CurCharInfo
->Attributes
= *Ptr
++;
1432 ConioUnlockScreenBuffer(Buff
);
1434 ApiMessage
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
= ReadRegion
.Left
+ SizeX
- 1;
1435 ApiMessage
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
= ReadRegion
.Top
+ SizeY
- 1;
1436 ApiMessage
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
= ReadRegion
.Left
;
1437 ApiMessage
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
= ReadRegion
.Top
;
1439 return STATUS_SUCCESS
;
1442 CSR_API(CsrSetScreenBufferSize
)
1445 PCSRSS_CONSOLE Console
;
1446 PCSRSS_SCREEN_BUFFER Buff
;
1448 Status
= ConioLockScreenBuffer(CsrGetClientThread()->Process
, ApiMessage
->Data
.SetScreenBufferSize
.OutputHandle
, &Buff
, GENERIC_WRITE
);
1449 if (!NT_SUCCESS(Status
))
1453 Console
= Buff
->Header
.Console
;
1455 Status
= ConioResizeBuffer(Console
, Buff
, ApiMessage
->Data
.SetScreenBufferSize
.Size
);
1456 ConioUnlockScreenBuffer(Buff
);