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 PCSRSS_CONSOLE Console
;
365 ULONG CharSize
= (Request
->Data
.WriteConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
367 DPRINT("CsrWriteConsole\n");
369 if (Request
->Header
.u1
.s1
.TotalLength
370 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE
)
371 + (Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
* CharSize
))
373 DPRINT1("Invalid request size\n");
374 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
375 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
376 return STATUS_INVALID_PARAMETER
;
379 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
380 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
382 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.WriteConsoleRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
383 if (! NT_SUCCESS(Status
))
387 Console
= Buff
->Header
.Console
;
389 if (Console
->UnpauseEvent
)
391 Status
= NtDuplicateObject(GetCurrentProcess(), Console
->UnpauseEvent
,
392 ProcessData
->Process
, &Request
->Data
.WriteConsoleRequest
.UnpauseEvent
,
394 ConioUnlockScreenBuffer(Buff
);
395 return NT_SUCCESS(Status
) ? STATUS_PENDING
: Status
;
398 if(Request
->Data
.WriteConsoleRequest
.Unicode
)
400 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
401 (PWCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
,
402 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
,
403 NULL
, 0, NULL
, NULL
);
404 Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
407 WideCharToMultiByte(Console
->OutputCodePage
, 0,
408 (PWCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
,
409 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
,
410 Buffer
, Length
, NULL
, NULL
);
414 Status
= STATUS_NO_MEMORY
;
419 Buffer
= (PCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
;
424 if (NT_SUCCESS(Status
))
426 Status
= ConioWriteConsole(Console
, Buff
, Buffer
,
427 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
, TRUE
);
428 if (NT_SUCCESS(Status
))
430 Written
= Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
;
433 if (Request
->Data
.WriteConsoleRequest
.Unicode
)
435 RtlFreeHeap(GetProcessHeap(), 0, Buffer
);
438 ConioUnlockScreenBuffer(Buff
);
440 Request
->Data
.WriteConsoleRequest
.NrCharactersWritten
= Written
;
446 ConioDeleteScreenBuffer(PCSRSS_SCREEN_BUFFER Buffer
)
448 PCSRSS_CONSOLE Console
= Buffer
->Header
.Console
;
450 RemoveEntryList(&Buffer
->ListEntry
);
451 if (Buffer
== Console
->ActiveBuffer
)
453 /* Deleted active buffer; switch to most recently created */
454 Console
->ActiveBuffer
= NULL
;
455 if (!IsListEmpty(&Console
->BufferList
))
457 Console
->ActiveBuffer
= CONTAINING_RECORD(Console
->BufferList
.Flink
, CSRSS_SCREEN_BUFFER
, ListEntry
);
458 ConioDrawConsole(Console
);
462 HeapFree(Win32CsrApiHeap
, 0, Buffer
->Buffer
);
463 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
467 ConioDrawConsole(PCSRSS_CONSOLE Console
)
471 ConioInitRect(&Region
, 0, 0, Console
->Size
.Y
- 1, Console
->Size
.X
- 1);
473 ConioDrawRegion(Console
, &Region
);
476 CSR_API(CsrGetScreenBufferInfo
)
479 PCSRSS_CONSOLE Console
;
480 PCSRSS_SCREEN_BUFFER Buff
;
481 PCONSOLE_SCREEN_BUFFER_INFO pInfo
;
483 DPRINT("CsrGetScreenBufferInfo\n");
485 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
486 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
488 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ScreenBufferInfoRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
489 if (! NT_SUCCESS(Status
))
493 Console
= Buff
->Header
.Console
;
494 pInfo
= &Request
->Data
.ScreenBufferInfoRequest
.Info
;
495 pInfo
->dwSize
.X
= Buff
->MaxX
;
496 pInfo
->dwSize
.Y
= Buff
->MaxY
;
497 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
;
498 pInfo
->dwCursorPosition
.Y
= Buff
->CurrentY
;
499 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
500 pInfo
->srWindow
.Left
= Buff
->ShowX
;
501 pInfo
->srWindow
.Right
= Buff
->ShowX
+ Console
->Size
.X
- 1;
502 pInfo
->srWindow
.Top
= Buff
->ShowY
;
503 pInfo
->srWindow
.Bottom
= Buff
->ShowY
+ Console
->Size
.Y
- 1;
504 pInfo
->dwMaximumWindowSize
.X
= Buff
->MaxX
;
505 pInfo
->dwMaximumWindowSize
.Y
= Buff
->MaxY
;
506 ConioUnlockScreenBuffer(Buff
);
508 return STATUS_SUCCESS
;
511 CSR_API(CsrSetCursor
)
514 PCSRSS_CONSOLE Console
;
515 PCSRSS_SCREEN_BUFFER Buff
;
516 LONG OldCursorX
, OldCursorY
;
517 LONG NewCursorX
, NewCursorY
;
519 DPRINT("CsrSetCursor\n");
521 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
522 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
524 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
525 if (! NT_SUCCESS(Status
))
529 Console
= Buff
->Header
.Console
;
531 NewCursorX
= Request
->Data
.SetCursorRequest
.Position
.X
;
532 NewCursorY
= Request
->Data
.SetCursorRequest
.Position
.Y
;
533 if (NewCursorX
< 0 || NewCursorX
>= Buff
->MaxX
||
534 NewCursorY
< 0 || NewCursorY
>= Buff
->MaxY
)
536 ConioUnlockScreenBuffer(Buff
);
537 return STATUS_INVALID_PARAMETER
;
539 OldCursorX
= Buff
->CurrentX
;
540 OldCursorY
= Buff
->CurrentY
;
541 Buff
->CurrentX
= NewCursorX
;
542 Buff
->CurrentY
= NewCursorY
;
543 if (Buff
== Console
->ActiveBuffer
)
545 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
547 ConioUnlockScreenBuffer(Buff
);
548 return STATUS_UNSUCCESSFUL
;
552 ConioUnlockScreenBuffer(Buff
);
554 return STATUS_SUCCESS
;
558 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff
, SMALL_RECT
*UpdateRect
, COORD
*Start
, UINT Length
)
560 if (Buff
->MaxX
<= Start
->X
+ Length
)
562 UpdateRect
->Left
= 0;
566 UpdateRect
->Left
= Start
->X
;
568 if (Buff
->MaxX
<= Start
->X
+ Length
)
570 UpdateRect
->Right
= Buff
->MaxX
- 1;
574 UpdateRect
->Right
= Start
->X
+ Length
- 1;
576 UpdateRect
->Top
= Start
->Y
;
577 UpdateRect
->Bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->MaxX
;
578 if (Buff
->MaxY
<= UpdateRect
->Bottom
)
580 UpdateRect
->Bottom
= Buff
->MaxY
- 1;
584 CSR_API(CsrWriteConsoleOutputChar
)
587 PCHAR String
, tmpString
= NULL
;
589 PCSRSS_CONSOLE Console
;
590 PCSRSS_SCREEN_BUFFER Buff
;
591 DWORD X
, Y
, Length
, CharSize
, Written
= 0;
592 SMALL_RECT UpdateRect
;
594 DPRINT("CsrWriteConsoleOutputChar\n");
596 CharSize
= (Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
598 if (Request
->Header
.u1
.s1
.TotalLength
599 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR
)
600 + (Request
->Data
.WriteConsoleOutputCharRequest
.Length
* CharSize
))
602 DPRINT1("Invalid request size\n");
603 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
604 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
605 return STATUS_INVALID_PARAMETER
;
608 Status
= ConioLockScreenBuffer(ProcessData
,
609 Request
->Data
.WriteConsoleOutputCharRequest
.ConsoleHandle
,
612 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
613 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
614 if (NT_SUCCESS(Status
))
616 Console
= Buff
->Header
.Console
;
617 if(Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
)
619 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
620 (PWCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
,
621 Request
->Data
.WriteConsoleOutputCharRequest
.Length
,
622 NULL
, 0, NULL
, NULL
);
623 tmpString
= String
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
626 WideCharToMultiByte(Console
->OutputCodePage
, 0,
627 (PWCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
,
628 Request
->Data
.WriteConsoleOutputCharRequest
.Length
,
629 String
, Length
, NULL
, NULL
);
633 Status
= STATUS_NO_MEMORY
;
638 String
= (PCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
;
643 if (NT_SUCCESS(Status
))
645 X
= Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.X
;
646 Y
= (Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
647 Length
= Request
->Data
.WriteConsoleOutputCharRequest
.Length
;
648 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
654 if (++X
== Buff
->MaxX
)
656 if (++Y
== Buff
->MaxY
)
659 Buffer
= Buff
->Buffer
;
664 if (Buff
== Console
->ActiveBuffer
)
666 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputCharRequest
.Coord
,
667 Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
668 ConioDrawRegion(Console
, &UpdateRect
);
671 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.X
= X
;
672 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->VirtualY
) % Buff
->MaxY
;
675 if (Request
->Data
.WriteConsoleRequest
.Unicode
)
677 RtlFreeHeap(GetProcessHeap(), 0, tmpString
);
680 ConioUnlockScreenBuffer(Buff
);
682 Request
->Data
.WriteConsoleOutputCharRequest
.NrCharactersWritten
= Written
;
686 CSR_API(CsrFillOutputChar
)
689 PCSRSS_CONSOLE Console
;
690 PCSRSS_SCREEN_BUFFER Buff
;
691 DWORD X
, Y
, Length
, Written
= 0;
694 SMALL_RECT UpdateRect
;
696 DPRINT("CsrFillOutputChar\n");
698 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
699 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
701 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
702 if (! NT_SUCCESS(Status
))
706 Console
= Buff
->Header
.Console
;
708 X
= Request
->Data
.FillOutputRequest
.Position
.X
;
709 Y
= (Request
->Data
.FillOutputRequest
.Position
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
710 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
711 if(Request
->Data
.FillOutputRequest
.Unicode
)
712 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &Request
->Data
.FillOutputRequest
.Char
.UnicodeChar
);
714 Char
= Request
->Data
.FillOutputRequest
.Char
.AsciiChar
;
715 Length
= Request
->Data
.FillOutputRequest
.Length
;
721 if (++X
== Buff
->MaxX
)
723 if (++Y
== Buff
->MaxY
)
726 Buffer
= Buff
->Buffer
;
732 if (Buff
== Console
->ActiveBuffer
)
734 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputRequest
.Position
,
735 Request
->Data
.FillOutputRequest
.Length
);
736 ConioDrawRegion(Console
, &UpdateRect
);
739 ConioUnlockScreenBuffer(Buff
);
740 Length
= Request
->Data
.FillOutputRequest
.Length
;
741 Request
->Data
.FillOutputRequest
.NrCharactersWritten
= Length
;
742 return STATUS_SUCCESS
;
745 CSR_API(CsrWriteConsoleOutputAttrib
)
747 PCSRSS_CONSOLE Console
;
748 PCSRSS_SCREEN_BUFFER Buff
;
753 SMALL_RECT UpdateRect
;
755 DPRINT("CsrWriteConsoleOutputAttrib\n");
757 if (Request
->Header
.u1
.s1
.TotalLength
758 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB
)
759 + Request
->Data
.WriteConsoleOutputAttribRequest
.Length
* sizeof(WORD
))
761 DPRINT1("Invalid request size\n");
762 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
763 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
764 return STATUS_INVALID_PARAMETER
;
767 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
768 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
770 Status
= ConioLockScreenBuffer(ProcessData
,
771 Request
->Data
.WriteConsoleOutputAttribRequest
.ConsoleHandle
,
774 if (! NT_SUCCESS(Status
))
778 Console
= Buff
->Header
.Console
;
780 X
= Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.X
;
781 Y
= (Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
782 Length
= Request
->Data
.WriteConsoleOutputAttribRequest
.Length
;
783 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + 1];
784 Attribute
= Request
->Data
.WriteConsoleOutputAttribRequest
.Attribute
;
787 *Buffer
= (UCHAR
)(*Attribute
++);
789 if (++X
== Buff
->MaxX
)
791 if (++Y
== Buff
->MaxY
)
794 Buffer
= Buff
->Buffer
+ 1;
800 if (Buff
== Console
->ActiveBuffer
)
802 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
,
803 Request
->Data
.WriteConsoleOutputAttribRequest
.Length
);
804 ConioDrawRegion(Console
, &UpdateRect
);
807 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.X
= X
;
808 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->VirtualY
) % Buff
->MaxY
;
810 ConioUnlockScreenBuffer(Buff
);
812 return STATUS_SUCCESS
;
815 CSR_API(CsrFillOutputAttrib
)
817 PCSRSS_SCREEN_BUFFER Buff
;
822 SMALL_RECT UpdateRect
;
823 PCSRSS_CONSOLE Console
;
825 DPRINT("CsrFillOutputAttrib\n");
827 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
828 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
829 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputAttribRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
830 if (! NT_SUCCESS(Status
))
834 Console
= Buff
->Header
.Console
;
836 X
= Request
->Data
.FillOutputAttribRequest
.Coord
.X
;
837 Y
= (Request
->Data
.FillOutputAttribRequest
.Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
838 Length
= Request
->Data
.FillOutputAttribRequest
.Length
;
839 Attr
= Request
->Data
.FillOutputAttribRequest
.Attribute
;
840 Buffer
= &Buff
->Buffer
[(Y
* Buff
->MaxX
* 2) + (X
* 2) + 1];
845 if (++X
== Buff
->MaxX
)
847 if (++Y
== Buff
->MaxY
)
850 Buffer
= Buff
->Buffer
+ 1;
856 if (Buff
== Console
->ActiveBuffer
)
858 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputAttribRequest
.Coord
,
859 Request
->Data
.FillOutputAttribRequest
.Length
);
860 ConioDrawRegion(Console
, &UpdateRect
);
863 ConioUnlockScreenBuffer(Buff
);
865 return STATUS_SUCCESS
;
869 ConioEffectiveCursorSize(PCSRSS_CONSOLE Console
, DWORD Scale
)
871 DWORD Size
= (Console
->ActiveBuffer
->CursorInfo
.dwSize
* Scale
+ 99) / 100;
872 /* If line input in progress, perhaps adjust for insert toggle */
873 if (Console
->LineBuffer
&& !Console
->LineComplete
&& Console
->LineInsertToggle
)
874 return (Size
* 2 <= Scale
) ? (Size
* 2) : (Size
/ 2);
878 CSR_API(CsrGetCursorInfo
)
880 PCSRSS_SCREEN_BUFFER Buff
;
883 DPRINT("CsrGetCursorInfo\n");
885 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
886 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
888 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.GetCursorInfoRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
889 if (! NT_SUCCESS(Status
))
893 Request
->Data
.GetCursorInfoRequest
.Info
.bVisible
= Buff
->CursorInfo
.bVisible
;
894 Request
->Data
.GetCursorInfoRequest
.Info
.dwSize
= Buff
->CursorInfo
.dwSize
;
895 ConioUnlockScreenBuffer(Buff
);
897 return STATUS_SUCCESS
;
900 CSR_API(CsrSetCursorInfo
)
902 PCSRSS_CONSOLE Console
;
903 PCSRSS_SCREEN_BUFFER Buff
;
908 DPRINT("CsrSetCursorInfo\n");
910 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
911 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
913 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorInfoRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
914 if (! NT_SUCCESS(Status
))
918 Console
= Buff
->Header
.Console
;
920 Size
= Request
->Data
.SetCursorInfoRequest
.Info
.dwSize
;
921 Visible
= Request
->Data
.SetCursorInfoRequest
.Info
.bVisible
;
931 if (Size
!= Buff
->CursorInfo
.dwSize
932 || (Visible
&& ! Buff
->CursorInfo
.bVisible
) || (! Visible
&& Buff
->CursorInfo
.bVisible
))
934 Buff
->CursorInfo
.dwSize
= Size
;
935 Buff
->CursorInfo
.bVisible
= Visible
;
937 if (! ConioSetCursorInfo(Console
, Buff
))
939 ConioUnlockScreenBuffer(Buff
);
940 return STATUS_UNSUCCESSFUL
;
944 ConioUnlockScreenBuffer(Buff
);
946 return STATUS_SUCCESS
;
949 CSR_API(CsrSetTextAttrib
)
952 PCSRSS_CONSOLE Console
;
953 PCSRSS_SCREEN_BUFFER Buff
;
955 DPRINT("CsrSetTextAttrib\n");
957 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
958 if (! NT_SUCCESS(Status
))
962 Console
= Buff
->Header
.Console
;
964 Buff
->DefaultAttrib
= Request
->Data
.SetAttribRequest
.Attrib
;
965 if (Buff
== Console
->ActiveBuffer
)
967 if (! ConioUpdateScreenInfo(Console
, Buff
))
969 ConioUnlockScreenBuffer(Buff
);
970 return STATUS_UNSUCCESSFUL
;
974 ConioUnlockScreenBuffer(Buff
);
976 return STATUS_SUCCESS
;
979 CSR_API(CsrCreateScreenBuffer
)
981 PCSRSS_CONSOLE Console
;
982 PCSRSS_SCREEN_BUFFER Buff
;
985 DPRINT("CsrCreateScreenBuffer\n");
987 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
988 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
989 if (! NT_SUCCESS(Status
))
994 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
995 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
997 Buff
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
1001 if (Console
->ActiveBuffer
)
1003 Buff
->MaxX
= Console
->ActiveBuffer
->MaxX
;
1004 Buff
->MaxY
= Console
->ActiveBuffer
->MaxY
;
1005 Buff
->CursorInfo
.bVisible
= Console
->ActiveBuffer
->CursorInfo
.bVisible
;
1006 Buff
->CursorInfo
.dwSize
= Console
->ActiveBuffer
->CursorInfo
.dwSize
;
1010 Buff
->CursorInfo
.bVisible
= TRUE
;
1011 Buff
->CursorInfo
.dwSize
= CSR_DEFAULT_CURSOR_SIZE
;
1014 if (Buff
->MaxX
== 0)
1019 if (Buff
->MaxY
== 0)
1024 Status
= CsrInitConsoleScreenBuffer(Console
, Buff
);
1025 if (NT_SUCCESS(Status
))
1027 Status
= Win32CsrInsertObject(ProcessData
,
1028 &Request
->Data
.CreateScreenBufferRequest
.OutputHandle
,
1030 Request
->Data
.CreateScreenBufferRequest
.Access
,
1031 Request
->Data
.CreateScreenBufferRequest
.Inheritable
,
1032 Request
->Data
.CreateScreenBufferRequest
.ShareMode
);
1037 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1040 ConioUnlockConsole(Console
);
1041 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
1045 CSR_API(CsrSetScreenBuffer
)
1048 PCSRSS_CONSOLE Console
;
1049 PCSRSS_SCREEN_BUFFER Buff
;
1051 DPRINT("CsrSetScreenBuffer\n");
1053 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1054 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1056 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetScreenBufferRequest
.OutputHandle
, &Buff
, GENERIC_WRITE
);
1057 if (! NT_SUCCESS(Status
))
1061 Console
= Buff
->Header
.Console
;
1063 if (Buff
== Console
->ActiveBuffer
)
1065 ConioUnlockScreenBuffer(Buff
);
1066 return STATUS_SUCCESS
;
1069 /* If old buffer has no handles, it's now unreferenced */
1070 if (Console
->ActiveBuffer
->Header
.HandleCount
== 0)
1072 ConioDeleteScreenBuffer(Console
->ActiveBuffer
);
1074 /* tie console to new buffer */
1075 Console
->ActiveBuffer
= Buff
;
1076 /* Redraw the console */
1077 ConioDrawConsole(Console
);
1079 ConioUnlockScreenBuffer(Buff
);
1081 return STATUS_SUCCESS
;
1084 CSR_API(CsrWriteConsoleOutput
)
1086 SHORT i
, X
, Y
, SizeX
, SizeY
;
1087 PCSRSS_CONSOLE Console
;
1088 PCSRSS_SCREEN_BUFFER Buff
;
1089 SMALL_RECT ScreenBuffer
;
1090 CHAR_INFO
* CurCharInfo
;
1091 SMALL_RECT WriteRegion
;
1092 CHAR_INFO
* CharInfo
;
1098 DPRINT("CsrWriteConsoleOutput\n");
1100 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1101 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1102 Status
= ConioLockScreenBuffer(ProcessData
,
1103 Request
->Data
.WriteConsoleOutputRequest
.ConsoleHandle
,
1106 if (! NT_SUCCESS(Status
))
1110 Console
= Buff
->Header
.Console
;
1112 BufferSize
= Request
->Data
.WriteConsoleOutputRequest
.BufferSize
;
1113 BufferCoord
= Request
->Data
.WriteConsoleOutputRequest
.BufferCoord
;
1114 CharInfo
= Request
->Data
.WriteConsoleOutputRequest
.CharInfo
;
1115 if (!Win32CsrValidateBuffer(ProcessData
, CharInfo
,
1116 BufferSize
.X
* BufferSize
.Y
, sizeof(CHAR_INFO
)))
1118 ConioUnlockScreenBuffer(Buff
);
1119 return STATUS_ACCESS_VIOLATION
;
1121 WriteRegion
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
;
1123 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&WriteRegion
));
1124 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&WriteRegion
));
1125 WriteRegion
.Bottom
= WriteRegion
.Top
+ SizeY
- 1;
1126 WriteRegion
.Right
= WriteRegion
.Left
+ SizeX
- 1;
1128 /* Make sure WriteRegion is inside the screen buffer */
1129 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
1130 if (! ConioGetIntersection(&WriteRegion
, &ScreenBuffer
, &WriteRegion
))
1132 ConioUnlockScreenBuffer(Buff
);
1134 /* It is okay to have a WriteRegion completely outside the screen buffer.
1135 No data is written then. */
1136 return STATUS_SUCCESS
;
1139 for (i
= 0, Y
= WriteRegion
.Top
; Y
<= WriteRegion
.Bottom
; i
++, Y
++)
1141 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
1142 Ptr
= ConioCoordToPointer(Buff
, WriteRegion
.Left
, Y
);
1143 for (X
= WriteRegion
.Left
; X
<= WriteRegion
.Right
; X
++)
1146 if (Request
->Data
.WriteConsoleOutputRequest
.Unicode
)
1148 ConsoleUnicodeCharToAnsiChar(Console
, &AsciiChar
, &CurCharInfo
->Char
.UnicodeChar
);
1152 AsciiChar
= CurCharInfo
->Char
.AsciiChar
;
1155 *Ptr
++ = CurCharInfo
->Attributes
;
1160 ConioDrawRegion(Console
, &WriteRegion
);
1162 ConioUnlockScreenBuffer(Buff
);
1164 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
= WriteRegion
.Left
+ SizeX
- 1;
1165 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
= WriteRegion
.Top
+ SizeY
- 1;
1166 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
= WriteRegion
.Left
;
1167 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
= WriteRegion
.Top
;
1169 return STATUS_SUCCESS
;
1172 CSR_API(CsrScrollConsoleScreenBuffer
)
1174 PCSRSS_CONSOLE Console
;
1175 PCSRSS_SCREEN_BUFFER Buff
;
1176 SMALL_RECT ScreenBuffer
;
1177 SMALL_RECT SrcRegion
;
1178 SMALL_RECT DstRegion
;
1179 SMALL_RECT UpdateRegion
;
1180 SMALL_RECT ScrollRectangle
;
1181 SMALL_RECT ClipRectangle
;
1183 HANDLE ConsoleHandle
;
1184 BOOLEAN UseClipRectangle
;
1185 COORD DestinationOrigin
;
1189 DPRINT("CsrScrollConsoleScreenBuffer\n");
1191 ConsoleHandle
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ConsoleHandle
;
1192 UseClipRectangle
= Request
->Data
.ScrollConsoleScreenBufferRequest
.UseClipRectangle
;
1193 DestinationOrigin
= Request
->Data
.ScrollConsoleScreenBufferRequest
.DestinationOrigin
;
1194 Fill
= Request
->Data
.ScrollConsoleScreenBufferRequest
.Fill
;
1196 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1197 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1198 Status
= ConioLockScreenBuffer(ProcessData
, ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1199 if (! NT_SUCCESS(Status
))
1203 Console
= Buff
->Header
.Console
;
1205 ScrollRectangle
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
;
1207 /* Make sure source rectangle is inside the screen buffer */
1208 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
1209 if (! ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, &ScrollRectangle
))
1211 ConioUnlockScreenBuffer(Buff
);
1212 return STATUS_SUCCESS
;
1215 /* If the source was clipped on the left or top, adjust the destination accordingly */
1216 if (ScrollRectangle
.Left
< 0)
1218 DestinationOrigin
.X
-= ScrollRectangle
.Left
;
1220 if (ScrollRectangle
.Top
< 0)
1222 DestinationOrigin
.Y
-= ScrollRectangle
.Top
;
1225 if (UseClipRectangle
)
1227 ClipRectangle
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
;
1228 if (!ConioGetIntersection(&ClipRectangle
, &ClipRectangle
, &ScreenBuffer
))
1230 ConioUnlockScreenBuffer(Buff
);
1231 return STATUS_SUCCESS
;
1236 ClipRectangle
= ScreenBuffer
;
1239 ConioInitRect(&DstRegion
,
1240 DestinationOrigin
.Y
,
1241 DestinationOrigin
.X
,
1242 DestinationOrigin
.Y
+ ConioRectHeight(&SrcRegion
) - 1,
1243 DestinationOrigin
.X
+ ConioRectWidth(&SrcRegion
) - 1);
1245 if (Request
->Data
.ScrollConsoleScreenBufferRequest
.Unicode
)
1246 ConsoleUnicodeCharToAnsiChar(Console
, &FillChar
, &Fill
.Char
.UnicodeChar
);
1248 FillChar
= Fill
.Char
.AsciiChar
;
1250 ConioMoveRegion(Buff
, &SrcRegion
, &DstRegion
, &ClipRectangle
, Fill
.Attributes
<< 8 | (BYTE
)FillChar
);
1252 if (Buff
== Console
->ActiveBuffer
)
1254 ConioGetUnion(&UpdateRegion
, &SrcRegion
, &DstRegion
);
1255 if (ConioGetIntersection(&UpdateRegion
, &UpdateRegion
, &ClipRectangle
))
1257 /* Draw update region */
1258 ConioDrawRegion(Console
, &UpdateRegion
);
1262 ConioUnlockScreenBuffer(Buff
);
1264 return STATUS_SUCCESS
;
1267 CSR_API(CsrReadConsoleOutputChar
)
1270 PCSRSS_CONSOLE Console
;
1271 PCSRSS_SCREEN_BUFFER Buff
;
1278 DPRINT("CsrReadConsoleOutputChar\n");
1280 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1281 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
1282 ReadBuffer
= Request
->Data
.ReadConsoleOutputCharRequest
.String
;
1284 CharSize
= (Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
1286 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputCharRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
1287 if (! NT_SUCCESS(Status
))
1291 Console
= Buff
->Header
.Console
;
1293 Xpos
= Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.X
;
1294 Ypos
= (Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1296 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
; ++i
)
1298 Char
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
)];
1300 if(Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
)
1302 ConsoleAnsiCharToUnicodeChar(Console
, (WCHAR
*)ReadBuffer
, &Char
);
1303 ReadBuffer
+= sizeof(WCHAR
);
1306 *(ReadBuffer
++) = Char
;
1310 if (Xpos
== Buff
->MaxX
)
1315 if (Ypos
== Buff
->MaxY
)
1323 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.X
= Xpos
;
1324 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.Y
= (Ypos
- Buff
->VirtualY
+ Buff
->MaxY
) % Buff
->MaxY
;
1326 ConioUnlockScreenBuffer(Buff
);
1328 Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
= (DWORD
)((ULONG_PTR
)ReadBuffer
- (ULONG_PTR
)Request
->Data
.ReadConsoleOutputCharRequest
.String
) / CharSize
;
1329 if (Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
* CharSize
+ CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR
) > sizeof(CSR_API_MESSAGE
))
1331 Request
->Header
.u1
.s1
.TotalLength
= Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
* CharSize
+ CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR
);
1332 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
1335 return STATUS_SUCCESS
;
1339 CSR_API(CsrReadConsoleOutputAttrib
)
1342 PCSRSS_SCREEN_BUFFER Buff
;
1346 DWORD CurrentLength
;
1348 DPRINT("CsrReadConsoleOutputAttrib\n");
1350 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1351 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
1352 ReadBuffer
= Request
->Data
.ReadConsoleOutputAttribRequest
.Attribute
;
1354 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputAttribRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
1355 if (! NT_SUCCESS(Status
))
1360 Xpos
= Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.X
;
1361 Ypos
= (Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1363 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
; ++i
)
1365 *ReadBuffer
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
) + 1];
1370 if (Xpos
== Buff
->MaxX
)
1375 if (Ypos
== Buff
->MaxY
)
1384 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.X
= Xpos
;
1385 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.Y
= (Ypos
- Buff
->VirtualY
+ Buff
->MaxY
) % Buff
->MaxY
;
1387 ConioUnlockScreenBuffer(Buff
);
1389 CurrentLength
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_ATTRIB
)
1390 + Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
* sizeof(WORD
);
1391 if (CurrentLength
> sizeof(CSR_API_MESSAGE
))
1393 Request
->Header
.u1
.s1
.TotalLength
= CurrentLength
;
1394 Request
->Header
.u1
.s1
.DataLength
= CurrentLength
- sizeof(PORT_MESSAGE
);
1397 return STATUS_SUCCESS
;
1400 CSR_API(CsrReadConsoleOutput
)
1402 PCHAR_INFO CharInfo
;
1403 PCHAR_INFO CurCharInfo
;
1404 PCSRSS_SCREEN_BUFFER Buff
;
1409 SMALL_RECT ReadRegion
;
1410 SMALL_RECT ScreenRect
;
1416 DPRINT("CsrReadConsoleOutput\n");
1418 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1419 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1421 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
1422 if (! NT_SUCCESS(Status
))
1427 CharInfo
= Request
->Data
.ReadConsoleOutputRequest
.CharInfo
;
1428 ReadRegion
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
;
1429 BufferSize
= Request
->Data
.ReadConsoleOutputRequest
.BufferSize
;
1430 BufferCoord
= Request
->Data
.ReadConsoleOutputRequest
.BufferCoord
;
1432 /* FIXME: Is this correct? */
1433 CodePage
= ProcessData
->Console
->OutputCodePage
;
1435 if (!Win32CsrValidateBuffer(ProcessData
, CharInfo
,
1436 BufferSize
.X
* BufferSize
.Y
, sizeof(CHAR_INFO
)))
1438 ConioUnlockScreenBuffer(Buff
);
1439 return STATUS_ACCESS_VIOLATION
;
1442 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&ReadRegion
));
1443 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&ReadRegion
));
1444 ReadRegion
.Bottom
= ReadRegion
.Top
+ SizeY
;
1445 ReadRegion
.Right
= ReadRegion
.Left
+ SizeX
;
1447 ConioInitRect(&ScreenRect
, 0, 0, Buff
->MaxY
, Buff
->MaxX
);
1448 if (! ConioGetIntersection(&ReadRegion
, &ScreenRect
, &ReadRegion
))
1450 ConioUnlockScreenBuffer(Buff
);
1451 return STATUS_SUCCESS
;
1454 for (i
= 0, Y
= ReadRegion
.Top
; Y
< ReadRegion
.Bottom
; ++i
, ++Y
)
1456 CurCharInfo
= CharInfo
+ (i
* BufferSize
.X
);
1458 Ptr
= ConioCoordToPointer(Buff
, ReadRegion
.Left
, Y
);
1459 for (X
= ReadRegion
.Left
; X
< ReadRegion
.Right
; ++X
)
1461 if (Request
->Data
.ReadConsoleOutputRequest
.Unicode
)
1463 MultiByteToWideChar(CodePage
, 0,
1465 &CurCharInfo
->Char
.UnicodeChar
, 1);
1469 CurCharInfo
->Char
.AsciiChar
= *Ptr
++;
1471 CurCharInfo
->Attributes
= *Ptr
++;
1476 ConioUnlockScreenBuffer(Buff
);
1478 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
= ReadRegion
.Left
+ SizeX
- 1;
1479 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
= ReadRegion
.Top
+ SizeY
- 1;
1480 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
= ReadRegion
.Left
;
1481 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
= ReadRegion
.Top
;
1483 return STATUS_SUCCESS
;
1486 CSR_API(CsrSetScreenBufferSize
)
1489 PCSRSS_CONSOLE Console
;
1490 PCSRSS_SCREEN_BUFFER Buff
;
1492 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1493 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1495 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetScreenBufferSize
.OutputHandle
, &Buff
, GENERIC_WRITE
);
1496 if (!NT_SUCCESS(Status
))
1500 Console
= Buff
->Header
.Console
;
1502 Status
= ConioResizeBuffer(Console
, Buff
, Request
->Data
.SetScreenBufferSize
.Size
);
1503 ConioUnlockScreenBuffer(Buff
);