1 /* $Id: conio.c,v 1.7 2004/02/27 17:35:42 hbirr Exp $
3 * reactos/subsys/csrss/win32csr/conio.c
5 * Console I/O functions
7 * ReactOS Operating System
10 /* INCLUDES ******************************************************************/
15 #include <csrss/csrss.h>
16 #include <ntdll/rtl.h>
17 #include <ntdll/ldr.h>
18 #include <ddk/ntddblue.h>
19 #include <rosrtl/string.h>
20 #include <rosrtl/minmax.h>
23 #include "desktopbg.h"
24 #include "guiconsole.h"
25 #include "tuiconsole.h"
31 /* FIXME: Is there a way to create real aliasses with gcc? [CSH] */
32 #define ALIAS(Name, Target) typeof(Target) Name = Target
34 /* Private user32 routines for CSRSS, not defined in any header file */
35 extern VOID STDCALL
PrivateCsrssRegisterPrimitive(VOID
);
36 extern VOID STDCALL
PrivateCsrssAcquireOrReleaseInputOwnership(BOOL Release
);
38 /* GLOBALS *******************************************************************/
40 #define ConioInitRect(Rect, Top, Left, Bottom, Right) \
41 ((Rect)->top) = Top; \
42 ((Rect)->left) = Left; \
43 ((Rect)->bottom) = Bottom; \
44 ((Rect)->right) = Right
46 #define ConioIsRectEmpty(Rect) \
47 (((Rect)->left > (Rect)->right) || ((Rect)->top > (Rect)->bottom))
49 /* FUNCTIONS *****************************************************************/
51 STATIC NTSTATUS FASTCALL
52 ConioConsoleFromProcessData(PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_CONSOLE
*Console
)
54 if (NULL
== ProcessData
->Console
)
57 return STATUS_SUCCESS
;
60 EnterCriticalSection(&(ProcessData
->Console
->Header
.Lock
));
61 *Console
= ProcessData
->Console
;
63 return STATUS_SUCCESS
;
67 CsrConsoleCtrlEvent(DWORD Event
, PCSRSS_PROCESS_DATA ProcessData
)
69 HANDLE Process
, Thread
;
71 DPRINT("CsrConsoleCtrlEvent Parent ProcessId = %x\n", ClientId
.UniqueProcess
);
73 if (ProcessData
->CtrlDispatcher
)
75 Process
= OpenProcess(PROCESS_DUP_HANDLE
, FALSE
, ProcessData
->ProcessId
);
78 DPRINT1("Failed for handle duplication\n");
82 DPRINT("CsrConsoleCtrlEvent Process Handle = %x\n", Process
);
84 Thread
= CreateRemoteThread(Process
, NULL
, 0,
85 (LPTHREAD_START_ROUTINE
) ProcessData
->CtrlDispatcher
,
86 (PVOID
) Event
, 0, NULL
);
89 DPRINT1("Failed thread creation\n");
98 #define GET_CELL_BUFFER(b,o)\
101 #define SET_CELL_BUFFER(b,o,c,a)\
102 (b)->Buffer[(o)++]=(c);\
103 (b)->Buffer[(o)++]=(a);
106 ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff
)
108 DWORD Offset
= 2 * (Buff
->CurrentY
* Buff
->MaxX
);
111 for (Pos
= 0; Pos
< Buff
->MaxX
; Pos
++)
113 /* Fill the cell: Offset is incremented by the macro */
114 SET_CELL_BUFFER(Buff
, Offset
, ' ', Buff
->DefaultAttrib
)
118 STATIC NTSTATUS FASTCALL
119 CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console
,
120 PCSRSS_SCREEN_BUFFER Buffer
)
122 Buffer
->Header
.Type
= CONIO_SCREEN_BUFFER_MAGIC
;
123 Buffer
->Header
.ReferenceCount
= 0;
124 Buffer
->MaxX
= Console
->Size
.X
;
125 Buffer
->MaxY
= Console
->Size
.Y
;
128 Buffer
->Buffer
= HeapAlloc(Win32CsrApiHeap
, 0, Buffer
->MaxX
* Buffer
->MaxY
* 2);
129 if (NULL
== Buffer
->Buffer
)
131 return STATUS_INSUFFICIENT_RESOURCES
;
133 RtlInitializeCriticalSection(&Buffer
->Header
.Lock
);
134 ConioInitScreenBuffer(Console
, Buffer
);
135 /* initialize buffer to be empty with default attributes */
136 for (Buffer
->CurrentY
= 0 ; Buffer
->CurrentY
< Buffer
->MaxY
; Buffer
->CurrentY
++)
138 ClearLineBuffer(Buffer
);
140 Buffer
->CursorInfo
.bVisible
= TRUE
;
141 Buffer
->CursorInfo
.dwSize
= 5;
142 Buffer
->Mode
= ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
;
143 Buffer
->CurrentX
= 0;
144 Buffer
->CurrentY
= 0;
146 return STATUS_SUCCESS
;
149 STATIC NTSTATUS STDCALL
150 CsrInitConsole(PCSRSS_CONSOLE Console
)
153 SECURITY_ATTRIBUTES SecurityAttributes
;
154 PCSRSS_SCREEN_BUFFER NewBuffer
;
157 Console
->Title
.MaximumLength
= Console
->Title
.Length
= 0;
158 Console
->Title
.Buffer
= NULL
;
160 RtlCreateUnicodeString(&Console
->Title
, L
"Command Prompt");
162 Console
->Header
.ReferenceCount
= 0;
163 Console
->WaitingChars
= 0;
164 Console
->WaitingLines
= 0;
165 Console
->EchoCount
= 0;
166 Console
->Header
.Type
= CONIO_CONSOLE_MAGIC
;
167 Console
->Mode
= ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_PROCESSED_INPUT
| ENABLE_MOUSE_INPUT
;
168 Console
->EarlyReturn
= FALSE
;
169 Console
->ActiveBuffer
= NULL
;
170 InitializeListHead(&Console
->InputEvents
);
171 InitializeListHead(&Console
->ProcessList
);
173 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
174 SecurityAttributes
.lpSecurityDescriptor
= NULL
;
175 SecurityAttributes
.bInheritHandle
= TRUE
;
177 Console
->ActiveEvent
= CreateEventW(&SecurityAttributes
, FALSE
, FALSE
, NULL
);
178 if (NULL
== Console
->ActiveEvent
)
180 RtlFreeUnicodeString(&Console
->Title
);
181 return STATUS_UNSUCCESSFUL
;
183 Console
->PrivateData
= NULL
;
184 RtlInitializeCriticalSection(&Console
->Header
.Lock
);
185 GuiMode
= DtbgIsDesktopVisible();
188 Status
= TuiInitConsole(Console
);
189 if (! NT_SUCCESS(Status
))
191 DPRINT1("Failed to open text-mode console, switching to gui-mode\n");
197 Status
= GuiInitConsole(Console
);
198 if (! NT_SUCCESS(Status
))
200 RtlFreeUnicodeString(&Console
->Title
);
201 RtlDeleteCriticalSection(&Console
->Header
.Lock
);
202 CloseHandle(Console
->ActiveEvent
);
207 NewBuffer
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(CSRSS_SCREEN_BUFFER
));
208 if (NULL
== NewBuffer
)
210 RtlFreeUnicodeString(&Console
->Title
);
211 RtlDeleteCriticalSection(&Console
->Header
.Lock
);
212 CloseHandle(Console
->ActiveEvent
);
213 return STATUS_INSUFFICIENT_RESOURCES
;
215 Status
= CsrInitConsoleScreenBuffer(Console
, NewBuffer
);
216 if (! NT_SUCCESS(Status
))
218 RtlFreeUnicodeString(&Console
->Title
);
219 RtlDeleteCriticalSection(&Console
->Header
.Lock
);
220 CloseHandle(Console
->ActiveEvent
);
221 HeapFree(Win32CsrApiHeap
, 0, NewBuffer
);
224 Console
->ActiveBuffer
= NewBuffer
;
225 /* add a reference count because the buffer is tied to the console */
226 Console
->ActiveBuffer
->Header
.ReferenceCount
++;
227 /* make console active, and insert into console list */
228 /* copy buffer contents to screen */
229 ConioDrawConsole(Console
);
231 return STATUS_SUCCESS
;
235 CSR_API(CsrAllocConsole
)
237 PCSRSS_CONSOLE Console
;
241 DPRINT("CsrAllocConsole\n");
243 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
244 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
246 if (ProcessData
== NULL
)
248 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
251 if (ProcessData
->Console
)
253 Reply
->Status
= STATUS_INVALID_PARAMETER
;
254 return STATUS_INVALID_PARAMETER
;
257 Reply
->Status
= STATUS_SUCCESS
;
258 Console
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(CSRSS_CONSOLE
));
261 Reply
->Status
= STATUS_NO_MEMORY
;
262 return STATUS_NO_MEMORY
;
264 Reply
->Status
= CsrInitConsole(Console
);
265 if (! NT_SUCCESS(Reply
->Status
))
267 HeapFree(Win32CsrApiHeap
, 0, Console
);
268 return Reply
->Status
;
270 ProcessData
->Console
= Console
;
271 Reply
->Data
.AllocConsoleReply
.Console
= Console
;
273 /* add a reference count because the process is tied to the console */
274 Console
->Header
.ReferenceCount
++;
275 Status
= Win32CsrInsertObject(ProcessData
, &Reply
->Data
.AllocConsoleReply
.InputHandle
, &Console
->Header
);
276 if (! NT_SUCCESS(Status
))
278 ConioDeleteConsole((Object_t
*) Console
);
279 ProcessData
->Console
= 0;
280 return Reply
->Status
= Status
;
282 Status
= Win32CsrInsertObject(ProcessData
, &Reply
->Data
.AllocConsoleReply
.OutputHandle
, &Console
->ActiveBuffer
->Header
);
283 if (!NT_SUCCESS(Status
))
285 Console
->Header
.ReferenceCount
--;
286 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.InputHandle
);
287 ProcessData
->Console
= 0;
288 return Reply
->Status
= Status
;
291 Process
= OpenProcess(PROCESS_DUP_HANDLE
, FALSE
, ProcessData
->ProcessId
);
294 DPRINT1("OpenProcess() failed for handle duplication\n");
295 Console
->Header
.ReferenceCount
--;
296 ProcessData
->Console
= 0;
297 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.OutputHandle
);
298 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.InputHandle
);
299 Reply
->Status
= Status
;
302 if (! DuplicateHandle(GetCurrentProcess(), ProcessData
->Console
->ActiveEvent
,
303 Process
, &ProcessData
->ConsoleEvent
, EVENT_ALL_ACCESS
, FALSE
, 0))
305 DPRINT1("DuplicateHandle() failed: %d\n", GetLastError
);
306 CloseHandle(Process
);
307 Console
->Header
.ReferenceCount
--;
308 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.OutputHandle
);
309 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.InputHandle
);
310 ProcessData
->Console
= 0;
311 Reply
->Status
= Status
;
314 CloseHandle(Process
);
315 ProcessData
->CtrlDispatcher
= Request
->Data
.AllocConsoleRequest
.CtrlDispatcher
;
316 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
317 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ProcessEntry
);
319 return STATUS_SUCCESS
;
322 CSR_API(CsrFreeConsole
)
324 PCSRSS_CONSOLE Console
;
326 DPRINT("CsrFreeConsole\n");
328 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
329 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
331 if (ProcessData
== NULL
|| ProcessData
->Console
== NULL
)
333 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
336 Console
= ProcessData
->Console
;
337 Console
->Header
.ReferenceCount
--;
338 ProcessData
->Console
= NULL
;
339 if (0 == Console
->Header
.ReferenceCount
)
341 ConioDeleteConsole((Object_t
*) Console
);
344 return STATUS_SUCCESS
;
348 ConioNextLine(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, UINT
*ScrolledLines
)
350 /* slide the viewable screen */
351 if (((Buff
->CurrentY
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
) == Buff
->MaxY
- 1)
353 if (++Buff
->ShowY
== Buff
->MaxY
)
359 if (++Buff
->CurrentY
== Buff
->MaxY
)
363 ClearLineBuffer(Buff
);
364 UpdateRect
->left
= 0;
365 UpdateRect
->right
= Buff
->MaxX
- 1;
366 if (UpdateRect
->top
== Buff
->CurrentY
)
368 if (++UpdateRect
->top
== Buff
->MaxY
)
373 UpdateRect
->bottom
= Buff
->CurrentY
;
376 STATIC NTSTATUS FASTCALL
377 ConioWriteConsole(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
,
378 CHAR
*Buffer
, DWORD Length
, BOOL Attrib
)
383 LONG CursorStartX
, CursorStartY
;
386 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &CursorStartX
, &CursorStartY
);
387 UpdateRect
.left
= Buff
->MaxX
;
388 UpdateRect
.top
= Buff
->CurrentY
;
389 UpdateRect
.right
= -1;
390 UpdateRect
.bottom
= Buff
->CurrentY
;
393 for (i
= 0; i
< Length
; i
++)
400 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
405 /* Only handle BS if we're not on the first pos of the first line */
406 if (0 != Buff
->CurrentX
|| Buff
->ShowY
!= Buff
->CurrentY
)
408 if (0 == Buff
->CurrentX
)
410 /* slide virtual position up */
411 Buff
->CurrentX
= Buff
->MaxX
- 1;
412 if (0 == Buff
->CurrentY
)
414 Buff
->CurrentY
= Buff
->MaxY
;
420 if ((0 == UpdateRect
.top
&& UpdateRect
.bottom
< Buff
->CurrentY
)
421 || (0 != UpdateRect
.top
&& Buff
->CurrentY
< UpdateRect
.top
))
423 UpdateRect
.top
= Buff
->CurrentY
;
430 Offset
= 2 * ((Buff
->CurrentY
* Buff
->MaxX
) + Buff
->CurrentX
);
431 SET_CELL_BUFFER(Buff
, Offset
, ' ', Buff
->DefaultAttrib
);
432 UpdateRect
.left
= RtlRosMin(UpdateRect
.left
, Buff
->CurrentX
);
433 UpdateRect
.right
= RtlRosMax(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
440 UpdateRect
.left
= RtlRosMin(UpdateRect
.left
, Buff
->CurrentX
);
441 UpdateRect
.right
= RtlRosMax(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
449 UpdateRect
.left
= RtlRosMin(UpdateRect
.left
, Buff
->CurrentX
);
450 EndX
= 8 * ((Buff
->CurrentX
+ 8) / 8);
451 if (Buff
->MaxX
< EndX
)
455 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
456 while (Buff
->CurrentX
< EndX
)
458 Buff
->Buffer
[Offset
] = ' ';
462 UpdateRect
.right
= RtlRosMax(UpdateRect
.right
, (LONG
) Buff
->CurrentX
- 1);
463 if (Buff
->CurrentX
== Buff
->MaxX
)
466 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
473 UpdateRect
.left
= RtlRosMin(UpdateRect
.left
, Buff
->CurrentX
);
474 UpdateRect
.right
= RtlRosMax(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
475 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
476 Buff
->Buffer
[Offset
++] = Buffer
[i
];
479 Buff
->Buffer
[Offset
] = Buff
->DefaultAttrib
;
482 if (Buff
->CurrentX
== Buff
->MaxX
)
485 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
491 ConioPhysicalToLogical(Buff
, UpdateRect
.left
, UpdateRect
.top
, &(UpdateRect
.left
),
493 ConioPhysicalToLogical(Buff
, UpdateRect
.right
, UpdateRect
.bottom
, &(UpdateRect
.right
),
494 &(UpdateRect
.bottom
));
495 if (! ConioIsRectEmpty(&UpdateRect
) && NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
497 ConioWriteStream(Console
, &UpdateRect
, CursorStartX
, CursorStartY
, ScrolledLines
,
501 return STATUS_SUCCESS
;
504 CSR_API(CsrReadConsole
)
506 PLIST_ENTRY CurrentEntry
;
510 ULONG nNumberOfCharsToRead
;
511 PCSRSS_CONSOLE Console
;
514 DPRINT("CsrReadConsole\n");
516 /* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */
517 nNumberOfCharsToRead
= Request
->Data
.ReadConsoleRequest
.NrCharactersToRead
> CSRSS_MAX_READ_CONSOLE_REQUEST
? CSRSS_MAX_READ_CONSOLE_REQUEST
: Request
->Data
.ReadConsoleRequest
.NrCharactersToRead
;
518 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
519 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- sizeof(LPC_MESSAGE
);
521 Buffer
= Reply
->Data
.ReadConsoleReply
.Buffer
;
522 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadConsoleRequest
.ConsoleHandle
,
524 if (! NT_SUCCESS(Status
))
526 return Reply
->Status
= Status
;
528 Reply
->Data
.ReadConsoleReply
.EventHandle
= ProcessData
->ConsoleEvent
;
529 for (i
= 0; i
< nNumberOfCharsToRead
&& Console
->InputEvents
.Flink
!= &Console
->InputEvents
; i
++)
531 /* remove input event from queue */
532 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
533 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
535 /* only pay attention to valid ascii chars, on key down */
536 if (KEY_EVENT
== Input
->InputEvent
.EventType
537 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
538 && Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
540 /* backspace handling */
541 if ('\b' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
543 /* echo if it has not already been done, and either we or the client has chars to be deleted */
545 && (0 != i
|| Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
))
547 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
548 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
552 i
-= 2; /* if we already have something to return, just back it up by 2 */
555 { /* otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer */
556 Reply
->Data
.ReadConsoleReply
.NrCharactersRead
= 0;
557 Reply
->Status
= STATUS_NOTIFY_CLEANUP
;
558 Console
->WaitingChars
--;
559 HeapFree(Win32CsrApiHeap
, 0, Input
);
560 ConioUnlockConsole(Console
);
561 return STATUS_NOTIFY_CLEANUP
;
563 Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
--;
564 Input
->Echoed
= TRUE
; /* mark as echoed so we don't echo it below */
566 /* do not copy backspace to buffer */
569 Buffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
;
571 /* echo to screen if enabled and we did not already echo the char */
572 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
)
574 && '\r' != Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
576 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
577 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
584 Console
->WaitingChars
--;
585 HeapFree(Win32CsrApiHeap
, 0, Input
);
587 Reply
->Data
.ReadConsoleReply
.NrCharactersRead
= i
;
590 Reply
->Status
= STATUS_PENDING
; /* we didn't read anything */
592 else if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
))
594 if (0 == Console
->WaitingLines
|| '\n' != Buffer
[i
- 1])
596 Reply
->Status
= STATUS_PENDING
; /* line buffered, didn't get a complete line */
600 Console
->WaitingLines
--;
601 Reply
->Status
= STATUS_SUCCESS
; /* line buffered, did get a complete line */
606 Reply
->Status
= STATUS_SUCCESS
; /* not line buffered, did read something */
609 if (Reply
->Status
== STATUS_PENDING
)
611 Console
->EchoCount
= nNumberOfCharsToRead
- i
;
615 Console
->EchoCount
= 0; /* if the client is no longer waiting on input, do not echo */
617 Reply
->Header
.MessageSize
+= i
;
619 ConioUnlockConsole(Console
);
620 return Reply
->Status
;
624 ConioPhysicalToLogical(PCSRSS_SCREEN_BUFFER Buff
,
630 *LogicalX
= PhysicalX
;
631 if (PhysicalY
< Buff
->ShowY
)
633 *LogicalY
= Buff
->MaxY
- Buff
->ShowY
+ PhysicalY
;
637 *LogicalY
= PhysicalY
- Buff
->ShowY
;
641 inline BOOLEAN
ConioIsEqualRect(
645 return ((Rect1
->left
== Rect2
->left
) && (Rect1
->right
== Rect2
->right
) &&
646 (Rect1
->top
== Rect2
->top
) && (Rect1
->bottom
== Rect2
->bottom
));
649 inline BOOLEAN
ConioGetIntersection(
654 if (ConioIsRectEmpty(Rect1
) ||
655 (ConioIsRectEmpty(Rect2
)) ||
656 (Rect1
->top
> Rect2
->bottom
) ||
657 (Rect1
->left
> Rect2
->right
) ||
658 (Rect1
->bottom
< Rect2
->top
) ||
659 (Rect1
->right
< Rect2
->left
))
661 /* The rectangles do not intersect */
662 ConioInitRect(Intersection
, 0, -1, 0, -1);
666 ConioInitRect(Intersection
,
667 RtlRosMax(Rect1
->top
, Rect2
->top
),
668 RtlRosMax(Rect1
->left
, Rect2
->left
),
669 RtlRosMin(Rect1
->bottom
, Rect2
->bottom
),
670 RtlRosMin(Rect1
->right
, Rect2
->right
));
675 inline BOOLEAN
ConioGetUnion(
680 if (ConioIsRectEmpty(Rect1
))
682 if (ConioIsRectEmpty(Rect2
))
684 ConioInitRect(Union
, 0, -1, 0, -1);
692 else if (ConioIsRectEmpty(Rect2
))
699 RtlRosMin(Rect1
->top
, Rect2
->top
),
700 RtlRosMin(Rect1
->left
, Rect2
->left
),
701 RtlRosMax(Rect1
->bottom
, Rect2
->bottom
),
702 RtlRosMax(Rect1
->right
, Rect2
->right
));
708 inline BOOLEAN
ConioSubtractRect(
715 if (ConioIsRectEmpty(Rect1
))
717 ConioInitRect(Subtraction
, 0, -1, 0, -1);
720 *Subtraction
= *Rect1
;
721 if (ConioGetIntersection(&tmp
, Rect1
, Rect2
))
723 if (ConioIsEqualRect(&tmp
, Subtraction
))
725 ConioInitRect(Subtraction
, 0, -1, 0, -1);
728 if ((tmp
.top
== Subtraction
->top
) && (tmp
.bottom
== Subtraction
->bottom
))
730 if (tmp
.left
== Subtraction
->left
)
732 Subtraction
->left
= tmp
.right
;
734 else if (tmp
.right
== Subtraction
->right
)
736 Subtraction
->right
= tmp
.left
;
739 else if ((tmp
.left
== Subtraction
->left
) && (tmp
.right
== Subtraction
->right
))
741 if (tmp
.top
== Subtraction
->top
)
743 Subtraction
->top
= tmp
.bottom
;
745 else if (tmp
.bottom
== Subtraction
->bottom
)
747 Subtraction
->bottom
= tmp
.top
;
756 ConioCopyRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer
,
766 DstY
= DstRegion
->top
;
767 BytesPerLine
= ConioRectWidth(DstRegion
) * 2;
769 SrcY
= (SrcRegion
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
770 DstY
= (DstRegion
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
771 SrcOffset
= (SrcY
* ScreenBuffer
->MaxX
+ SrcRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
772 DstOffset
= (DstY
* ScreenBuffer
->MaxX
+ DstRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
774 for (i
= SrcRegion
->top
; i
<= SrcRegion
->bottom
; i
++)
777 &ScreenBuffer
->Buffer
[DstOffset
],
778 &ScreenBuffer
->Buffer
[SrcOffset
],
781 if (++DstY
== ScreenBuffer
->MaxY
)
784 DstOffset
= (DstRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
788 DstOffset
+= ScreenBuffer
->MaxX
* 2;
791 if (++SrcY
== ScreenBuffer
->MaxY
)
794 SrcOffset
= (SrcRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
798 SrcOffset
+= ScreenBuffer
->MaxX
* 2;
804 ConioFillRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer
,
813 Y
= (Region
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
814 Offset
= (Y
* ScreenBuffer
->MaxX
+ Region
->left
+ ScreenBuffer
->ShowX
) * 2;
815 Delta
= (ScreenBuffer
->MaxX
- ConioRectWidth(Region
)) * 2;
817 for (i
= Region
->top
; i
<= Region
->bottom
; i
++)
819 for (X
= Region
->left
; X
<= Region
->right
; X
++)
821 SET_CELL_BUFFER(ScreenBuffer
, Offset
, CharInfo
.Char
.AsciiChar
, CharInfo
.Attributes
);
823 if (++Y
== ScreenBuffer
->MaxY
)
826 Offset
= (Region
->left
+ ScreenBuffer
->ShowX
) * 2;
835 CSR_API(CsrWriteConsole
)
838 BYTE
*Buffer
= Request
->Data
.WriteConsoleRequest
.Buffer
;
839 PCSRSS_SCREEN_BUFFER Buff
;
840 PCSRSS_CONSOLE Console
;
842 DPRINT("CsrWriteConsole\n");
844 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
845 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
848 if (Request
->Header
.DataSize
849 < sizeof(CSRSS_WRITE_CONSOLE_REQUEST
) - 1
850 + Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
)
852 DPRINT1("Invalid request size\n");
853 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
855 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
856 if (! NT_SUCCESS(Status
))
858 return Reply
->Status
= Status
;
861 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.WriteConsoleRequest
.ConsoleHandle
, &Buff
);
862 if (! NT_SUCCESS(Status
))
866 ConioUnlockConsole(Console
);
868 return Reply
->Status
= Status
;
871 ConioWriteConsole(Console
, Buff
, Buffer
,
872 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
, TRUE
);
873 ConioUnlockScreenBuffer(Buff
);
876 ConioUnlockConsole(Console
);
879 return Reply
->Status
= STATUS_SUCCESS
;
883 ConioDeleteScreenBuffer(Object_t
*Object
)
885 PCSRSS_SCREEN_BUFFER Buffer
= (PCSRSS_SCREEN_BUFFER
) Object
;
886 RtlDeleteCriticalSection(&Buffer
->Header
.Lock
);
887 HeapFree(Win32CsrApiHeap
, 0, Buffer
->Buffer
);
888 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
892 ConioDrawConsole(PCSRSS_CONSOLE Console
)
896 ConioInitRect(&Region
, 0, 0, Console
->Size
.Y
- 1, Console
->Size
.X
- 1);
898 ConioDrawRegion(Console
, &Region
);
903 ConioDeleteConsole(Object_t
*Object
)
905 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Object
;
908 DPRINT("ConioDeleteConsole\n");
910 /* Drain input event queue */
911 while (Console
->InputEvents
.Flink
!= &Console
->InputEvents
)
913 Event
= (ConsoleInput
*) Console
->InputEvents
.Flink
;
914 Console
->InputEvents
.Flink
= Console
->InputEvents
.Flink
->Flink
;
915 Console
->InputEvents
.Flink
->Flink
->Blink
= &Console
->InputEvents
;
916 HeapFree(Win32CsrApiHeap
, 0, Event
);
919 if (0 == --Console
->ActiveBuffer
->Header
.ReferenceCount
)
921 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
924 Console
->ActiveBuffer
= NULL
;
925 ConioCleanupConsole(Console
);
927 CloseHandle(Console
->ActiveEvent
);
928 RtlDeleteCriticalSection(&Console
->Header
.Lock
);
929 RtlFreeUnicodeString(&Console
->Title
);
930 HeapFree(Win32CsrApiHeap
, 0, Console
);
934 CsrInitConsoleSupport(VOID
)
936 DPRINT("CSR: CsrInitConsoleSupport()\n");
938 /* Should call LoadKeyboardLayout */
942 ConioProcessChar(PCSRSS_CONSOLE Console
,
943 ConsoleInput
*KeyEventRecord
)
946 BOOL bClientWake
= FALSE
;
947 ConsoleInput
*TempInput
;
949 /* process Ctrl-C and Ctrl-Break */
950 if (Console
->Mode
& ENABLE_PROCESSED_INPUT
&&
951 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
&&
952 ((KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== VK_PAUSE
) ||
953 (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== 'C')) &&
954 (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
)))
956 PCSRSS_PROCESS_DATA current
;
957 PLIST_ENTRY current_entry
;
958 DPRINT1("Console_Api Ctrl-C\n");
959 current_entry
= Console
->ProcessList
.Flink
;
960 while (current_entry
!= &Console
->ProcessList
)
962 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
963 current_entry
= current_entry
->Flink
;
964 CsrConsoleCtrlEvent((DWORD
)CTRL_C_EVENT
, current
);
966 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
970 if (0 != (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
971 & (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
972 && (VK_UP
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
973 || VK_DOWN
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
))
975 if (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
977 /* scroll up or down */
980 DPRINT1("No Active Console!\n");
981 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
984 if (VK_UP
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
)
986 /* only scroll up if there is room to scroll up into */
987 if (Console
->ActiveBuffer
->ShowY
!= ((Console
->ActiveBuffer
->CurrentY
+ 1) %
988 Console
->ActiveBuffer
->MaxY
))
990 Console
->ActiveBuffer
->ShowY
= (Console
->ActiveBuffer
->ShowY
+
991 Console
->ActiveBuffer
->MaxY
- 1) %
992 Console
->ActiveBuffer
->MaxY
;
995 else if (Console
->ActiveBuffer
->ShowY
!= Console
->ActiveBuffer
->CurrentY
)
996 /* only scroll down if there is room to scroll down into */
998 if (Console
->ActiveBuffer
->ShowY
% Console
->ActiveBuffer
->MaxY
!=
999 Console
->ActiveBuffer
->CurrentY
)
1001 if (((Console
->ActiveBuffer
->CurrentY
+ 1) % Console
->ActiveBuffer
->MaxY
) !=
1002 (Console
->ActiveBuffer
->ShowY
+ Console
->ActiveBuffer
->MaxY
) %
1003 Console
->ActiveBuffer
->MaxY
)
1005 Console
->ActiveBuffer
->ShowY
= (Console
->ActiveBuffer
->ShowY
+ 1) %
1006 Console
->ActiveBuffer
->MaxY
;
1010 ConioDrawConsole(Console
);
1012 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1015 if (NULL
== Console
)
1017 DPRINT1("No Active Console!\n");
1018 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1022 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
)))
1024 switch(KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1027 /* first add the \r */
1028 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1029 updown
= KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
;
1030 KeyEventRecord
->Echoed
= FALSE
;
1031 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= VK_RETURN
;
1032 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\r';
1033 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1034 Console
->WaitingChars
++;
1035 KeyEventRecord
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1036 if (NULL
== KeyEventRecord
)
1038 DPRINT1("Failed to allocate KeyEventRecord\n");
1041 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1042 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
= updown
;
1043 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= 0;
1044 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualScanCode
= 0;
1045 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\n';
1046 KeyEventRecord
->Fake
= TRUE
;
1050 /* add event to the queue */
1051 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1052 Console
->WaitingChars
++;
1053 /* if line input mode is enabled, only wake the client on enter key down */
1054 if (0 == (Console
->Mode
& ENABLE_LINE_INPUT
)
1055 || Console
->EarlyReturn
1056 || ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1057 && ! KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
))
1059 if ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1061 Console
->WaitingLines
++;
1064 SetEvent(Console
->ActiveEvent
);
1066 KeyEventRecord
->Echoed
= FALSE
;
1067 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
))
1068 && '\b' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1069 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1071 /* walk the input queue looking for a char to backspace */
1072 for (TempInput
= (ConsoleInput
*) Console
->InputEvents
.Blink
;
1073 TempInput
!= (ConsoleInput
*) &Console
->InputEvents
1074 && (KEY_EVENT
== TempInput
->InputEvent
.EventType
1075 || ! TempInput
->InputEvent
.Event
.KeyEvent
.bKeyDown
1076 || '\b' == TempInput
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
);
1077 TempInput
= (ConsoleInput
*) TempInput
->ListEntry
.Blink
)
1081 /* if we found one, delete it, otherwise, wake the client */
1082 if (TempInput
!= (ConsoleInput
*) &Console
->InputEvents
)
1084 /* delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue */
1085 RemoveEntryList(&TempInput
->ListEntry
);
1086 if (TempInput
->Echoed
)
1088 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1089 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1092 HeapFree(Win32CsrApiHeap
, 0, TempInput
);
1093 RemoveEntryList(&KeyEventRecord
->ListEntry
);
1094 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1095 Console
->WaitingChars
-= 2;
1099 SetEvent(Console
->ActiveEvent
);
1104 /* echo chars if we are supposed to and client is waiting for some */
1105 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
) && Console
->EchoCount
1106 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1107 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
1108 && '\r' != KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1110 /* mark the char as already echoed */
1111 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1112 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1114 Console
->EchoCount
--;
1115 KeyEventRecord
->Echoed
= TRUE
;
1119 /* Console->WaitingChars++; */
1120 if (bClientWake
|| 0 == (Console
->Mode
& ENABLE_LINE_INPUT
))
1122 SetEvent(Console
->ActiveEvent
);
1126 STATIC DWORD FASTCALL
1127 ConioGetShiftState(PBYTE KeyState
)
1132 for (i
= 0; i
< 0x100; i
++)
1134 if (0 != (KeyState
[i
] & 0x80))
1136 UINT vk
= MapVirtualKeyExW(i
, 3, 0) & 0xff;
1140 ssOut
|= CAPSLOCK_ON
;
1144 ssOut
|= NUMLOCK_ON
;
1148 ssOut
|= SCROLLLOCK_ON
;
1154 if (KeyState
[VK_LSHIFT
] & 0x80 || KeyState
[VK_RSHIFT
] & 0x80)
1155 ssOut
|= SHIFT_PRESSED
;
1157 if (KeyState
[VK_LCONTROL
] & 0x80)
1158 ssOut
|= RIGHT_CTRL_PRESSED
;
1159 else if (KeyState
[VK_RCONTROL
] & 0x80)
1160 ssOut
|= LEFT_CTRL_PRESSED
;
1162 if (KeyState
[VK_LMENU
] & 0x80)
1163 ssOut
|= RIGHT_ALT_PRESSED
;
1164 else if (KeyState
[VK_RMENU
] & 0x80)
1165 ssOut
|= LEFT_ALT_PRESSED
;
1171 ConioProcessKey(MSG
*msg
, PCSRSS_CONSOLE Console
, BOOL TextMode
)
1173 static BYTE KeyState
[256] = { 0 };
1174 /* MSDN mentions that you should use the last virtual key code received
1175 * when putting a virtual key identity to a WM_CHAR message since multiple
1176 * or translated keys may be involved. */
1177 static UINT LastVirtualKey
= 0;
1179 ConsoleInput
*ConInRec
;
1183 UINT VirtualKeyCode
;
1184 UINT VirtualScanCode
;
1187 ULONG ResultSize
= 0;
1190 VirtualScanCode
= (msg
->lParam
>> 16) & 0xff;
1191 Down
= msg
->message
== WM_KEYDOWN
|| msg
->message
== WM_CHAR
||
1192 msg
->message
== WM_SYSKEYDOWN
|| msg
->message
== WM_SYSCHAR
;
1194 GetKeyboardState(KeyState
);
1195 ShiftState
= ConioGetShiftState(KeyState
);
1197 if (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
)
1199 VirtualKeyCode
= LastVirtualKey
;
1200 UnicodeChar
= msg
->wParam
;
1207 VirtualKeyCode
= msg
->wParam
;
1208 RetChars
= ToUnicodeEx(VirtualKeyCode
,
1215 UnicodeChar
= (1 == RetChars
? Chars
[0] : 0);
1220 RtlUnicodeToOemN(&AsciiChar
,
1226 if (0 == ResultSize
)
1231 er
.EventType
= KEY_EVENT
;
1232 er
.Event
.KeyEvent
.bKeyDown
= Down
;
1233 er
.Event
.KeyEvent
.wRepeatCount
= RepeatCount
;
1234 er
.Event
.KeyEvent
.uChar
.UnicodeChar
= AsciiChar
& 0xff;
1235 er
.Event
.KeyEvent
.dwControlKeyState
= ShiftState
;
1236 er
.Event
.KeyEvent
.wVirtualKeyCode
= VirtualKeyCode
;
1237 er
.Event
.KeyEvent
.wVirtualScanCode
= VirtualScanCode
;
1241 if (0 != (ShiftState
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1242 && VK_TAB
== VirtualKeyCode
)
1246 TuiSwapConsole(ShiftState
& SHIFT_PRESSED
? -1 : 1);
1251 else if (VK_MENU
== VirtualKeyCode
&& ! Down
)
1253 if (TuiSwapConsole(0))
1260 if (NULL
== Console
)
1265 ConInRec
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1267 if (NULL
== ConInRec
)
1272 ConInRec
->InputEvent
= er
;
1273 ConInRec
->Fake
= AsciiChar
&&
1274 (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
&&
1275 msg
->message
!= WM_KEYUP
&& msg
->message
!= WM_SYSKEYUP
);
1276 ConInRec
->NotChar
= (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
);
1277 ConInRec
->Echoed
= FALSE
;
1278 if (ConInRec
->NotChar
)
1279 LastVirtualKey
= msg
->wParam
;
1281 DPRINT ("csrss: %s %s %s %s %02x %02x '%c' %04x\n",
1282 Down
? "down" : "up ",
1283 (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
) ?
1285 ConInRec
->Fake
? "fake" : "real",
1286 ConInRec
->NotChar
? "notc" : "char",
1289 (AsciiChar
>= ' ') ? AsciiChar
: '.',
1292 if (! ConInRec
->Fake
|| ! ConInRec
->NotChar
)
1294 ConioProcessChar(Console
, ConInRec
);
1298 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1303 Console_Api(DWORD RefreshEvent
)
1305 /* keep reading events from the keyboard and stuffing them into the current
1306 console's input queue */
1309 /* This call establishes our message queue */
1310 PeekMessageW(&msg
, 0, 0, 0, PM_NOREMOVE
);
1311 /* This call registers our message queue */
1312 PrivateCsrssRegisterPrimitive();
1313 /* This call turns on the input system in win32k */
1314 PrivateCsrssAcquireOrReleaseInputOwnership(FALSE
);
1318 GetMessageW(&msg
, 0, 0, 0);
1319 TranslateMessage(&msg
);
1321 if (msg
.message
== WM_CHAR
|| msg
.message
== WM_SYSCHAR
||
1322 msg
.message
== WM_KEYDOWN
|| msg
.message
== WM_KEYUP
||
1323 msg
.message
== WM_SYSKEYDOWN
|| msg
.message
== WM_SYSKEYUP
)
1325 ConioProcessKey(&msg
, TuiGetFocusConsole(), TRUE
);
1329 PrivateCsrssAcquireOrReleaseInputOwnership(TRUE
);
1332 CSR_API(CsrGetScreenBufferInfo
)
1335 PCSRSS_SCREEN_BUFFER Buff
;
1336 PCONSOLE_SCREEN_BUFFER_INFO pInfo
;
1338 DPRINT("CsrGetScreenBufferInfo\n");
1340 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1341 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
1343 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ScreenBufferInfoRequest
.ConsoleHandle
, &Buff
);
1344 if (! NT_SUCCESS(Status
))
1346 return Reply
->Status
= Status
;
1348 pInfo
= &Reply
->Data
.ScreenBufferInfoReply
.Info
;
1349 pInfo
->dwSize
.X
= Buff
->MaxX
;
1350 pInfo
->dwSize
.Y
= Buff
->MaxY
;
1351 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1352 pInfo
->dwCursorPosition
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1353 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
1354 pInfo
->srWindow
.Left
= 0;
1355 pInfo
->srWindow
.Right
= Buff
->MaxX
- 1;
1356 pInfo
->srWindow
.Top
= 0;
1357 pInfo
->srWindow
.Bottom
= Buff
->MaxY
- 1;
1358 pInfo
->dwMaximumWindowSize
.X
= Buff
->MaxX
;
1359 pInfo
->dwMaximumWindowSize
.Y
= Buff
->MaxY
;
1360 ConioUnlockScreenBuffer(Buff
);
1362 Reply
->Status
= STATUS_SUCCESS
;
1364 return Reply
->Status
;
1367 CSR_API(CsrSetCursor
)
1370 PCSRSS_CONSOLE Console
;
1371 PCSRSS_SCREEN_BUFFER Buff
;
1372 LONG OldCursorX
, OldCursorY
;
1374 DPRINT("CsrSetCursor\n");
1376 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1377 if (! NT_SUCCESS(Status
))
1379 return Reply
->Status
= Status
;
1382 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1383 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
1385 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
);
1386 if (! NT_SUCCESS(Status
))
1388 if (NULL
!= Console
)
1390 ConioUnlockConsole(Console
);
1392 return Reply
->Status
= Status
;
1395 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &OldCursorX
, &OldCursorY
);
1396 Buff
->CurrentX
= Request
->Data
.SetCursorRequest
.Position
.X
+ Buff
->ShowX
;
1397 Buff
->CurrentY
= (Request
->Data
.SetCursorRequest
.Position
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1398 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1400 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
1402 ConioUnlockScreenBuffer(Buff
);
1403 return Reply
->Status
= STATUS_UNSUCCESSFUL
;
1407 ConioUnlockScreenBuffer(Buff
);
1408 if (NULL
!= Console
)
1410 ConioUnlockConsole(Console
);
1413 return Reply
->Status
= STATUS_SUCCESS
;
1416 STATIC FASTCALL VOID
1417 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, COORD
*Start
, UINT Length
)
1419 if (Buff
->MaxX
<= Start
->X
+ Length
)
1421 UpdateRect
->left
= 0;
1425 UpdateRect
->left
= Start
->X
;
1427 if (Buff
->MaxX
<= Start
->X
+ Length
)
1429 UpdateRect
->right
= Buff
->MaxX
- 1;
1433 UpdateRect
->right
= Start
->X
+ Length
- 1;
1435 UpdateRect
->top
= Start
->Y
;
1436 UpdateRect
->bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->MaxX
;
1437 if (Buff
->MaxY
<= UpdateRect
->bottom
)
1439 UpdateRect
->bottom
= Buff
->MaxY
- 1;
1443 CSR_API(CsrWriteConsoleOutputChar
)
1446 PBYTE String
= Request
->Data
.WriteConsoleOutputCharRequest
.String
;
1448 PCSRSS_CONSOLE Console
;
1449 PCSRSS_SCREEN_BUFFER Buff
;
1453 DPRINT("CsrWriteConsoleOutputChar\n");
1455 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1456 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
1457 sizeof(LPC_MESSAGE
);
1459 if (Request
->Header
.DataSize
1460 < sizeof(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR_REQUEST
) - 1
1461 + Request
->Data
.WriteConsoleOutputCharRequest
.Length
)
1463 DPRINT1("Invalid request size\n");
1464 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
1467 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1468 if (! NT_SUCCESS(Status
))
1470 return Reply
->Status
= Status
;
1473 Status
= ConioLockScreenBuffer(ProcessData
,
1474 Request
->Data
.WriteConsoleOutputCharRequest
.ConsoleHandle
,
1476 if (! NT_SUCCESS(Status
))
1478 if (NULL
!= Console
)
1480 ConioUnlockConsole(Console
);
1482 return Reply
->Status
= Status
;
1485 X
= Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.X
+ Buff
->ShowX
;
1486 Y
= (Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1487 Length
= Request
->Data
.WriteConsoleOutputCharRequest
.Length
;
1488 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1491 *Buffer
= *String
++;
1493 if (++X
== Buff
->MaxX
)
1495 if (++Y
== Buff
->MaxY
)
1498 Buffer
= Buff
->Buffer
;
1504 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1506 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputCharRequest
.Coord
,
1507 Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
1508 ConioDrawRegion(Console
, &UpdateRect
);
1511 Reply
->Data
.WriteConsoleOutputCharReply
.EndCoord
.X
= X
- Buff
->ShowX
;
1512 Reply
->Data
.WriteConsoleOutputCharReply
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1514 ConioUnlockScreenBuffer(Buff
);
1515 if (NULL
!= Console
)
1517 ConioUnlockConsole(Console
);
1520 return Reply
->Status
= STATUS_SUCCESS
;
1523 CSR_API(CsrFillOutputChar
)
1526 PCSRSS_CONSOLE Console
;
1527 PCSRSS_SCREEN_BUFFER Buff
;
1533 DPRINT("CsrFillOutputChar\n");
1535 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1536 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
1538 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1539 if (! NT_SUCCESS(Status
))
1541 return Reply
->Status
= Status
;
1544 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputRequest
.ConsoleHandle
, &Buff
);
1545 if (! NT_SUCCESS(Status
))
1547 if (NULL
!= Console
)
1549 ConioUnlockConsole(Console
);
1551 return Reply
->Status
= Status
;
1554 X
= Request
->Data
.FillOutputRequest
.Position
.X
+ Buff
->ShowX
;
1555 Y
= (Request
->Data
.FillOutputRequest
.Position
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1556 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1557 Char
= Request
->Data
.FillOutputRequest
.Char
;
1558 Length
= Request
->Data
.FillOutputRequest
.Length
;
1563 if (++X
== Buff
->MaxX
)
1565 if (++Y
== Buff
->MaxY
)
1568 Buffer
= Buff
->Buffer
;
1574 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1576 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputRequest
.Position
,
1577 Request
->Data
.FillOutputRequest
.Length
);
1578 ConioDrawRegion(Console
, &UpdateRect
);
1581 ConioUnlockScreenBuffer(Buff
);
1582 if (NULL
!= Console
)
1584 ConioUnlockConsole(Console
);
1587 return Reply
->Status
;
1590 CSR_API(CsrReadInputEvent
)
1592 PLIST_ENTRY CurrentEntry
;
1593 PCSRSS_CONSOLE Console
;
1595 BOOLEAN Done
= FALSE
;
1596 ConsoleInput
*Input
;
1598 DPRINT("CsrReadInputEvent\n");
1600 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1601 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
1602 Reply
->Data
.ReadInputReply
.Event
= ProcessData
->ConsoleEvent
;
1604 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadInputRequest
.ConsoleHandle
, &Console
);
1605 if (! NT_SUCCESS(Status
))
1607 return Reply
->Status
= Status
;
1610 /* only get input if there is any */
1611 while (Console
->InputEvents
.Flink
!= &Console
->InputEvents
&& ! Done
)
1613 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
1614 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
1615 Done
= !Input
->Fake
;
1616 Reply
->Data
.ReadInputReply
.Input
= Input
->InputEvent
;
1618 if (Input
->InputEvent
.EventType
== KEY_EVENT
)
1620 if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
)
1621 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
1622 && '\r' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1624 Console
->WaitingLines
--;
1626 Console
->WaitingChars
--;
1628 HeapFree(Win32CsrApiHeap
, 0, Input
);
1630 Reply
->Data
.ReadInputReply
.MoreEvents
= (Console
->InputEvents
.Flink
!= &Console
->InputEvents
);
1631 Status
= STATUS_SUCCESS
;
1632 Console
->EarlyReturn
= FALSE
; /* clear early return */
1637 Status
= STATUS_PENDING
;
1638 Console
->EarlyReturn
= TRUE
; /* mark for early return */
1641 ConioUnlockConsole(Console
);
1643 return Reply
->Status
= Status
;
1646 CSR_API(CsrWriteConsoleOutputAttrib
)
1648 PCSRSS_CONSOLE Console
;
1649 PCSRSS_SCREEN_BUFFER Buff
;
1650 PUCHAR Buffer
, Attribute
;
1655 DPRINT("CsrWriteConsoleOutputAttrib\n");
1657 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1658 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
1659 sizeof(LPC_MESSAGE
);
1661 if (Request
->Header
.DataSize
1662 < sizeof(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB_REQUEST
) - 1
1663 + Request
->Data
.WriteConsoleOutputAttribRequest
.Length
)
1665 DPRINT1("Invalid request size\n");
1666 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
1669 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1670 if (! NT_SUCCESS(Status
))
1672 return Reply
->Status
= Status
;
1675 Status
= ConioLockScreenBuffer(ProcessData
,
1676 Request
->Data
.WriteConsoleOutputAttribRequest
.ConsoleHandle
,
1678 if (! NT_SUCCESS(Status
))
1680 if (NULL
!= Console
)
1682 ConioUnlockConsole(Console
);
1684 return Reply
->Status
= Status
;
1687 X
= Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1688 Y
= (Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1689 Length
= Request
->Data
.WriteConsoleOutputAttribRequest
.Length
;
1690 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + 1];
1691 Attribute
= Request
->Data
.WriteConsoleOutputAttribRequest
.String
;
1694 *Buffer
= *Attribute
++;
1696 if (++X
== Buff
->MaxX
)
1698 if (++Y
== Buff
->MaxY
)
1701 Buffer
= Buff
->Buffer
+ 1;
1707 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1709 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
,
1710 Request
->Data
.WriteConsoleOutputAttribRequest
.Length
);
1711 ConioDrawRegion(Console
, &UpdateRect
);
1714 if (NULL
!= Console
)
1716 ConioUnlockConsole(Console
);
1719 Reply
->Data
.WriteConsoleOutputAttribReply
.EndCoord
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1720 Reply
->Data
.WriteConsoleOutputAttribReply
.EndCoord
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1722 ConioUnlockScreenBuffer(Buff
);
1724 return Reply
->Status
= STATUS_SUCCESS
;
1727 CSR_API(CsrFillOutputAttrib
)
1729 PCSRSS_SCREEN_BUFFER Buff
;
1735 PCSRSS_CONSOLE Console
;
1737 DPRINT("CsrFillOutputAttrib\n");
1739 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1740 if (! NT_SUCCESS(Status
))
1742 return Reply
->Status
= Status
;
1745 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1746 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
1747 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputAttribRequest
.ConsoleHandle
, &Buff
);
1748 if (! NT_SUCCESS(Status
))
1750 if (NULL
!= Console
)
1752 ConioUnlockConsole(Console
);
1754 return Reply
->Status
= Status
;
1757 X
= Request
->Data
.FillOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1758 Y
= (Request
->Data
.FillOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1759 Length
= Request
->Data
.FillOutputAttribRequest
.Length
;
1760 Attr
= Request
->Data
.FillOutputAttribRequest
.Attribute
;
1761 Buffer
= &Buff
->Buffer
[(Y
* Buff
->MaxX
* 2) + (X
* 2) + 1];
1766 if (++X
== Buff
->MaxX
)
1768 if (++Y
== Buff
->MaxY
)
1771 Buffer
= Buff
->Buffer
+ 1;
1777 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1779 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputAttribRequest
.Coord
,
1780 Request
->Data
.FillOutputAttribRequest
.Length
);
1781 ConioDrawRegion(Console
, &UpdateRect
);
1784 ConioUnlockScreenBuffer(Buff
);
1785 if (NULL
!= Console
)
1787 ConioUnlockConsole(Console
);
1790 return Reply
->Status
= STATUS_SUCCESS
;
1794 CSR_API(CsrGetCursorInfo
)
1796 PCSRSS_SCREEN_BUFFER Buff
;
1799 DPRINT("CsrGetCursorInfo\n");
1801 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1802 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
1804 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.GetCursorInfoRequest
.ConsoleHandle
, &Buff
);
1805 if (! NT_SUCCESS(Status
))
1807 return Reply
->Status
= Status
;
1809 Reply
->Data
.GetCursorInfoReply
.Info
= Buff
->CursorInfo
;
1810 ConioUnlockScreenBuffer(Buff
);
1812 return Reply
->Status
= STATUS_SUCCESS
;
1815 CSR_API(CsrSetCursorInfo
)
1817 PCSRSS_CONSOLE Console
;
1818 PCSRSS_SCREEN_BUFFER Buff
;
1823 DPRINT("CsrSetCursorInfo\n");
1825 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1826 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
1828 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1829 if (! NT_SUCCESS(Status
))
1831 return Reply
->Status
= Status
;
1834 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorInfoRequest
.ConsoleHandle
, &Buff
);
1835 if (! NT_SUCCESS(Status
))
1837 if (NULL
!= Console
)
1839 ConioUnlockConsole(Console
);
1841 return Reply
->Status
= Status
;
1844 Size
= Request
->Data
.SetCursorInfoRequest
.Info
.dwSize
;
1845 Visible
= Request
->Data
.SetCursorInfoRequest
.Info
.bVisible
;
1855 if (Size
!= Buff
->CursorInfo
.dwSize
1856 || (Visible
&& ! Buff
->CursorInfo
.bVisible
) || (! Visible
&& Buff
->CursorInfo
.bVisible
))
1858 Buff
->CursorInfo
.dwSize
= Size
;
1859 Buff
->CursorInfo
.bVisible
= Visible
;
1861 if (NULL
!= Console
&& ! ConioSetCursorInfo(Console
, Buff
))
1863 ConioUnlockScreenBuffer(Buff
);
1864 ConioUnlockConsole(Console
);
1865 return Reply
->Status
= STATUS_UNSUCCESSFUL
;
1869 ConioUnlockScreenBuffer(Buff
);
1870 if (NULL
!= Console
)
1872 ConioUnlockConsole(Console
);
1875 return Reply
->Status
= STATUS_SUCCESS
;
1878 CSR_API(CsrSetTextAttrib
)
1881 PCSRSS_CONSOLE Console
;
1882 PCSRSS_SCREEN_BUFFER Buff
;
1883 LONG OldCursorX
, OldCursorY
;
1885 DPRINT("CsrSetTextAttrib\n");
1887 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1888 if (! NT_SUCCESS(Status
))
1890 return Reply
->Status
= Status
;
1893 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
);
1894 if (! NT_SUCCESS(Status
))
1896 if (NULL
!= Console
)
1898 ConioUnlockConsole(Console
);
1900 return Reply
->Status
= Status
;
1903 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &OldCursorX
, &OldCursorY
);
1905 Buff
->DefaultAttrib
= Request
->Data
.SetAttribRequest
.Attrib
;
1906 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1908 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
1910 ConioUnlockScreenBuffer(Buff
);
1911 ConioUnlockConsole(Console
);
1912 return Reply
->Status
= STATUS_UNSUCCESSFUL
;
1916 ConioUnlockScreenBuffer(Buff
);
1917 if (NULL
!= Console
)
1919 ConioUnlockConsole(Console
);
1922 return Reply
->Status
= STATUS_SUCCESS
;
1925 CSR_API(CsrSetConsoleMode
)
1928 PCSRSS_CONSOLE Console
;
1929 PCSRSS_SCREEN_BUFFER Buff
;
1931 DPRINT("CsrSetConsoleMode\n");
1933 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1934 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
1935 Status
= Win32CsrGetObject(ProcessData
,
1936 Request
->Data
.SetConsoleModeRequest
.ConsoleHandle
,
1937 (Object_t
**) &Console
);
1938 if (! NT_SUCCESS(Status
))
1940 return Reply
->Status
= Status
;
1943 Buff
= (PCSRSS_SCREEN_BUFFER
)Console
;
1944 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
1946 Console
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_INPUT_MODE_VALID
;
1948 else if (CONIO_SCREEN_BUFFER_MAGIC
== Console
->Header
.Type
)
1950 Buff
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_OUTPUT_MODE_VALID
;
1954 return Reply
->Status
= STATUS_INVALID_HANDLE
;
1957 Reply
->Status
= STATUS_SUCCESS
;
1959 return Reply
->Status
;
1962 CSR_API(CsrGetConsoleMode
)
1965 PCSRSS_CONSOLE Console
;
1966 PCSRSS_SCREEN_BUFFER Buff
; /* gee, I really wish I could use an anonymous union here */
1968 DPRINT("CsrGetConsoleMode\n");
1970 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1971 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
1972 Status
= Win32CsrGetObject(ProcessData
, Request
->Data
.GetConsoleModeRequest
.ConsoleHandle
,
1973 (Object_t
**) &Console
);
1974 if (! NT_SUCCESS(Status
))
1976 return Reply
->Status
= Status
;
1978 Reply
->Status
= STATUS_SUCCESS
;
1979 Buff
= (PCSRSS_SCREEN_BUFFER
) Console
;
1980 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
1982 Reply
->Data
.GetConsoleModeReply
.ConsoleMode
= Console
->Mode
;
1984 else if (CONIO_SCREEN_BUFFER_MAGIC
== Buff
->Header
.Type
)
1986 Reply
->Data
.GetConsoleModeReply
.ConsoleMode
= Buff
->Mode
;
1990 Reply
->Status
= STATUS_INVALID_HANDLE
;
1993 return Reply
->Status
;
1996 CSR_API(CsrCreateScreenBuffer
)
1998 PCSRSS_CONSOLE Console
;
1999 PCSRSS_SCREEN_BUFFER Buff
;
2002 DPRINT("CsrCreateScreenBuffer\n");
2004 if (ProcessData
== NULL
)
2006 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
2009 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2010 if (! NT_SUCCESS(Status
))
2012 return Reply
->Status
= Status
;
2014 if (NULL
== Console
)
2016 return Reply
->Status
= STATUS_INVALID_HANDLE
;
2019 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2020 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
2022 Buff
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(CSRSS_SCREEN_BUFFER
));
2025 Reply
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2028 Status
= CsrInitConsoleScreenBuffer(Console
, Buff
);
2029 if(! NT_SUCCESS(Status
))
2031 Reply
->Status
= Status
;
2035 Reply
->Status
= Win32CsrInsertObject(ProcessData
, &Reply
->Data
.CreateScreenBufferReply
.OutputHandle
, &Buff
->Header
);
2038 ConioUnlockConsole(Console
);
2040 return Reply
->Status
;
2043 CSR_API(CsrSetScreenBuffer
)
2046 PCSRSS_CONSOLE Console
;
2047 PCSRSS_SCREEN_BUFFER Buff
;
2049 DPRINT("CsrSetScreenBuffer\n");
2051 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2052 if (! NT_SUCCESS(Status
))
2054 return Reply
->Status
= Status
;
2056 if (NULL
== Console
)
2058 DPRINT1("Trying to set screen buffer for app without console\n");
2059 return Reply
->Status
= STATUS_INVALID_HANDLE
;
2062 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2063 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
2065 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetScreenBufferRequest
.OutputHandle
, &Buff
);
2066 if (! NT_SUCCESS(Status
))
2068 ConioUnlockConsole(Console
);
2069 return Reply
->Status
;
2072 if (Buff
== Console
->ActiveBuffer
)
2074 ConioUnlockScreenBuffer(Buff
);
2075 ConioUnlockConsole(Console
);
2076 return STATUS_SUCCESS
;
2079 /* drop reference to old buffer, maybe delete */
2080 if (! InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
2082 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
2084 /* tie console to new buffer */
2085 Console
->ActiveBuffer
= Buff
;
2086 /* inc ref count on new buffer */
2087 InterlockedIncrement(&Buff
->Header
.ReferenceCount
);
2088 /* Redraw the console */
2089 ConioDrawConsole(Console
);
2091 ConioUnlockScreenBuffer(Buff
);
2092 ConioUnlockConsole(Console
);
2094 return Reply
->Status
= STATUS_SUCCESS
;
2097 CSR_API(CsrSetTitle
)
2100 PCSRSS_CONSOLE Console
;
2102 DPRINT("CsrSetTitle\n");
2104 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2105 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
2107 if (Request
->Header
.DataSize
2108 < sizeof(CSRSS_SET_TITLE_REQUEST
) - 1
2109 + Request
->Data
.SetTitleRequest
.Length
)
2111 DPRINT1("Invalid request size\n");
2112 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
2115 Status
= ConioLockConsole(ProcessData
, Request
->Data
.SetTitleRequest
.Console
, &Console
);
2116 if(! NT_SUCCESS(Status
))
2118 Reply
->Status
= Status
;
2122 /* copy title to console */
2123 RtlFreeUnicodeString(&Console
->Title
);
2124 RtlCreateUnicodeString(&Console
->Title
, Request
->Data
.SetTitleRequest
.Title
);
2125 if (! ConioChangeTitle(Console
))
2127 Reply
->Status
= STATUS_UNSUCCESSFUL
;
2131 Reply
->Status
= STATUS_SUCCESS
;
2134 ConioUnlockConsole(Console
);
2136 return Reply
->Status
;
2139 CSR_API(CsrGetTitle
)
2142 PCSRSS_CONSOLE Console
;
2144 DPRINT("CsrGetTitle\n");
2146 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2147 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
2148 Status
= ConioLockConsole(ProcessData
,
2149 Request
->Data
.GetTitleRequest
.ConsoleHandle
,
2151 if (! NT_SUCCESS(Status
))
2153 DPRINT1("Can't get console\n");
2154 return Reply
->Status
= Status
;
2157 /* Copy title of the console to the user title buffer */
2158 RtlZeroMemory(&Reply
->Data
.GetTitleReply
, sizeof(CSRSS_GET_TITLE_REPLY
));
2159 Reply
->Data
.GetTitleReply
.ConsoleHandle
= Request
->Data
.GetTitleRequest
.ConsoleHandle
;
2160 Reply
->Data
.GetTitleReply
.Length
= Console
->Title
.Length
;
2161 wcscpy (Reply
->Data
.GetTitleReply
.Title
, Console
->Title
.Buffer
);
2162 Reply
->Header
.MessageSize
+= Console
->Title
.Length
;
2163 Reply
->Header
.DataSize
+= Console
->Title
.Length
;
2164 Reply
->Status
= STATUS_SUCCESS
;
2166 ConioUnlockConsole(Console
);
2168 return Reply
->Status
;
2171 CSR_API(CsrWriteConsoleOutput
)
2173 SHORT i
, X
, Y
, SizeX
, SizeY
;
2174 PCSRSS_CONSOLE Console
;
2175 PCSRSS_SCREEN_BUFFER Buff
;
2177 CHAR_INFO
* CurCharInfo
;
2179 CHAR_INFO
* CharInfo
;
2186 DPRINT("CsrWriteConsoleOutput\n");
2188 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2189 if (! NT_SUCCESS(Status
))
2191 return Reply
->Status
= Status
;
2194 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2195 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
2196 Status
= ConioLockScreenBuffer(ProcessData
,
2197 Request
->Data
.WriteConsoleOutputRequest
.ConsoleHandle
,
2199 if (! NT_SUCCESS(Status
))
2201 if (NULL
!= Console
)
2203 ConioUnlockConsole(Console
);
2205 return Reply
->Status
= Status
;
2208 BufferSize
= Request
->Data
.WriteConsoleOutputRequest
.BufferSize
;
2209 PSize
= BufferSize
.X
* BufferSize
.Y
* sizeof(CHAR_INFO
);
2210 BufferCoord
= Request
->Data
.WriteConsoleOutputRequest
.BufferCoord
;
2211 CharInfo
= Request
->Data
.WriteConsoleOutputRequest
.CharInfo
;
2212 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
) ||
2213 (((PVOID
)CharInfo
+ PSize
) >
2214 (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2216 ConioUnlockScreenBuffer(Buff
);
2217 ConioUnlockConsole(Console
);
2218 return Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2220 WriteRegion
.left
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
;
2221 WriteRegion
.top
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
;
2222 WriteRegion
.right
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
;
2223 WriteRegion
.bottom
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
;
2225 SizeY
= RtlRosMin(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&WriteRegion
));
2226 SizeX
= RtlRosMin(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&WriteRegion
));
2227 WriteRegion
.bottom
= WriteRegion
.top
+ SizeY
- 1;
2228 WriteRegion
.right
= WriteRegion
.left
+ SizeX
- 1;
2230 /* Make sure WriteRegion is inside the screen buffer */
2231 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2232 if (! ConioGetIntersection(&WriteRegion
, &ScreenBuffer
, &WriteRegion
))
2234 ConioUnlockScreenBuffer(Buff
);
2235 ConioUnlockConsole(Console
);
2237 /* It is okay to have a WriteRegion completely outside the screen buffer.
2238 No data is written then. */
2239 return Reply
->Status
= STATUS_SUCCESS
;
2242 for (i
= 0, Y
= WriteRegion
.top
; Y
<= WriteRegion
.bottom
; i
++, Y
++)
2244 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
2245 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ WriteRegion
.left
) * 2;
2246 for (X
= WriteRegion
.left
; X
<= WriteRegion
.right
; X
++)
2248 SET_CELL_BUFFER(Buff
, Offset
, CurCharInfo
->Char
.AsciiChar
, CurCharInfo
->Attributes
);
2253 if (NULL
!= Console
)
2255 ConioDrawRegion(Console
, &WriteRegion
);
2258 ConioUnlockScreenBuffer(Buff
);
2259 ConioUnlockConsole(Console
);
2261 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Right
= WriteRegion
.left
+ SizeX
- 1;
2262 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Bottom
= WriteRegion
.top
+ SizeY
- 1;
2263 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Left
= WriteRegion
.left
;
2264 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Top
= WriteRegion
.top
;
2266 return Reply
->Status
= STATUS_SUCCESS
;
2269 CSR_API(CsrFlushInputBuffer
)
2271 PLIST_ENTRY CurrentEntry
;
2272 PCSRSS_CONSOLE Console
;
2273 ConsoleInput
* Input
;
2276 DPRINT("CsrFlushInputBuffer\n");
2278 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2279 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
2280 Status
= ConioLockConsole(ProcessData
,
2281 Request
->Data
.FlushInputBufferRequest
.ConsoleInput
,
2283 if(! NT_SUCCESS(Status
))
2285 return Reply
->Status
= Status
;
2288 /* Discard all entries in the input event queue */
2289 while (!IsListEmpty(&Console
->InputEvents
))
2291 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
2292 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
2293 /* Destroy the event */
2294 HeapFree(Win32CsrApiHeap
, 0, Input
);
2296 Console
->WaitingChars
=0;
2298 ConioUnlockConsole(Console
);
2300 return Reply
->Status
= STATUS_SUCCESS
;
2303 CSR_API(CsrScrollConsoleScreenBuffer
)
2305 PCSRSS_CONSOLE Console
;
2306 PCSRSS_SCREEN_BUFFER Buff
;
2311 RECT ScrollRectangle
;
2316 DPRINT("CsrScrollConsoleScreenBuffer\n");
2318 ALIAS(ConsoleHandle
,Request
->Data
.ScrollConsoleScreenBufferRequest
.ConsoleHandle
);
2319 ALIAS(UseClipRectangle
,Request
->Data
.ScrollConsoleScreenBufferRequest
.UseClipRectangle
);
2320 ALIAS(DestinationOrigin
,Request
->Data
.ScrollConsoleScreenBufferRequest
.DestinationOrigin
);
2321 ALIAS(Fill
,Request
->Data
.ScrollConsoleScreenBufferRequest
.Fill
);
2323 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2324 if (! NT_SUCCESS(Status
))
2326 return Reply
->Status
= Status
;
2329 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2330 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
2331 Status
= ConioLockScreenBuffer(ProcessData
, ConsoleHandle
, &Buff
);
2332 if (! NT_SUCCESS(Status
))
2334 if (NULL
!= Console
)
2336 ConioUnlockConsole(Console
);
2338 return Reply
->Status
= Status
;
2341 ScrollRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Left
;
2342 ScrollRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Top
;
2343 ScrollRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Right
;
2344 ScrollRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Bottom
;
2345 ClipRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Left
;
2346 ClipRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Top
;
2347 ClipRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Right
;
2348 ClipRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Bottom
;
2350 /* Make sure source rectangle is inside the screen buffer */
2351 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2352 if (! ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, &ScrollRectangle
))
2354 ConioUnlockScreenBuffer(Buff
);
2355 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
2358 if (UseClipRectangle
&& ! ConioGetIntersection(&SrcRegion
, &SrcRegion
, &ClipRectangle
))
2360 ConioUnlockScreenBuffer(Buff
);
2361 return Reply
->Status
= STATUS_SUCCESS
;
2365 ConioInitRect(&DstRegion
,
2366 DestinationOrigin
.Y
,
2367 DestinationOrigin
.X
,
2368 DestinationOrigin
.Y
+ ConioRectHeight(&ScrollRectangle
) - 1,
2369 DestinationOrigin
.X
+ ConioRectWidth(&ScrollRectangle
) - 1);
2371 /* Make sure destination rectangle is inside the screen buffer */
2372 if (! ConioGetIntersection(&DstRegion
, &DstRegion
, &ScreenBuffer
))
2374 ConioUnlockScreenBuffer(Buff
);
2375 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
2378 ConioCopyRegion(Buff
, &SrcRegion
, &DstRegion
);
2380 /* Get the region that should be filled with the specified character and attributes */
2384 ConioGetUnion(&FillRegion
, &SrcRegion
, &DstRegion
);
2386 if (ConioSubtractRect(&FillRegion
, &FillRegion
, &DstRegion
))
2388 /* FIXME: The subtracted rectangle is off by one line */
2389 FillRegion
.top
+= 1;
2391 ConioFillRegion(Buff
, &FillRegion
, Fill
);
2395 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
2397 /* Draw destination region */
2398 ConioDrawRegion(Console
, &DstRegion
);
2402 /* Draw filled region */
2403 ConioDrawRegion(Console
, &FillRegion
);
2407 ConioUnlockScreenBuffer(Buff
);
2408 if (NULL
!= Console
)
2410 ConioUnlockConsole(Console
);
2413 return Reply
->Status
= STATUS_SUCCESS
;
2416 CSR_API(CsrReadConsoleOutputChar
)
2419 PCSRSS_SCREEN_BUFFER Buff
;
2424 DPRINT("CsrReadConsoleOutputChar\n");
2426 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2427 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- sizeof(LPC_MESSAGE
);
2428 ReadBuffer
= Reply
->Data
.ReadConsoleOutputCharReply
.String
;
2430 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputCharRequest
.ConsoleHandle
, Buff
);
2431 if (! NT_SUCCESS(Status
))
2433 return Reply
->Status
= Status
;
2436 Xpos
= Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.X
+ Buff
->ShowX
;
2437 Ypos
= (Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
2439 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
; ++i
)
2441 *ReadBuffer
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
)];
2446 if (Xpos
== Buff
->MaxX
)
2451 if (Ypos
== Buff
->MaxY
)
2459 Reply
->Status
= STATUS_SUCCESS
;
2460 Reply
->Data
.ReadConsoleOutputCharReply
.EndCoord
.X
= Xpos
- Buff
->ShowX
;
2461 Reply
->Data
.ReadConsoleOutputCharReply
.EndCoord
.Y
= (Ypos
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
;
2462 Reply
->Header
.MessageSize
+= Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
;
2463 Reply
->Header
.DataSize
+= Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
;
2465 ConioUnlockScreenBuffer(Buff
);
2467 return Reply
->Status
;
2471 CSR_API(CsrReadConsoleOutputAttrib
)
2474 PCSRSS_SCREEN_BUFFER Buff
;
2479 DPRINT("CsrReadConsoleOutputAttrib\n");
2481 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2482 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- sizeof(LPC_MESSAGE
);
2483 ReadBuffer
= Reply
->Data
.ReadConsoleOutputAttribReply
.String
;
2485 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputAttribRequest
.ConsoleHandle
, &Buff
);
2486 if (! NT_SUCCESS(Status
))
2488 return Reply
->Status
= Status
;
2491 Xpos
= Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.X
+ Buff
->ShowX
;
2492 Ypos
= (Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
2494 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
; ++i
)
2496 *ReadBuffer
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
) + 1];
2501 if (Xpos
== Buff
->MaxX
)
2506 if (Ypos
== Buff
->MaxY
)
2515 Reply
->Status
= STATUS_SUCCESS
;
2516 Reply
->Data
.ReadConsoleOutputAttribReply
.EndCoord
.X
= Xpos
- Buff
->ShowX
;
2517 Reply
->Data
.ReadConsoleOutputAttribReply
.EndCoord
.Y
= (Ypos
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
;
2518 Reply
->Header
.MessageSize
+= Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
;
2519 Reply
->Header
.DataSize
+= Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
;
2521 ConioUnlockScreenBuffer(Buff
);
2523 return Reply
->Status
;
2527 CSR_API(CsrGetNumberOfConsoleInputEvents
)
2530 PCSRSS_CONSOLE Console
;
2531 PLIST_ENTRY CurrentItem
;
2533 ConsoleInput
*Input
;
2535 DPRINT("CsrGetNumberOfConsoleInputEvents\n");
2537 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2538 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- sizeof(LPC_MESSAGE
);
2540 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
);
2541 if (! NT_SUCCESS(Status
))
2543 return Reply
->Status
= Status
;
2546 CurrentItem
= Console
->InputEvents
.Flink
;
2549 /* If there are any events ... */
2550 while (CurrentItem
!= &Console
->InputEvents
)
2552 Input
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2553 CurrentItem
= CurrentItem
->Flink
;
2560 ConioUnlockConsole(Console
);
2562 Reply
->Status
= STATUS_SUCCESS
;
2563 Reply
->Data
.GetNumInputEventsReply
.NumInputEvents
= NumEvents
;
2565 return Reply
->Status
;
2569 CSR_API(CsrPeekConsoleInput
)
2572 PCSRSS_CONSOLE Console
;
2575 PLIST_ENTRY CurrentItem
;
2576 PINPUT_RECORD InputRecord
;
2580 DPRINT("CsrPeekConsoleInput\n");
2582 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2583 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
2585 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
);
2586 if(! NT_SUCCESS(Status
))
2588 return Reply
->Status
= Status
;
2591 InputRecord
= Request
->Data
.PeekConsoleInputRequest
.InputRecord
;
2592 Length
= Request
->Data
.PeekConsoleInputRequest
.Length
;
2593 Size
= Length
* sizeof(INPUT_RECORD
);
2595 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2596 || (((PVOID
)InputRecord
+ Size
) > (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2598 ConioUnlockConsole(Console
);
2599 Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2600 return Reply
->Status
;
2605 if (! IsListEmpty(&Console
->InputEvents
))
2607 CurrentItem
= &Console
->InputEvents
;
2609 while (NumItems
< Length
)
2612 Item
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2613 *InputRecord
++ = Item
->InputEvent
;
2615 if (CurrentItem
->Flink
== &Console
->InputEvents
)
2621 CurrentItem
= CurrentItem
->Flink
;
2626 ConioUnlockConsole(Console
);
2628 Reply
->Status
= STATUS_SUCCESS
;
2629 Reply
->Data
.PeekConsoleInputReply
.Length
= NumItems
;
2631 return Reply
->Status
;
2635 CSR_API(CsrReadConsoleOutput
)
2637 PCHAR_INFO CharInfo
;
2638 PCHAR_INFO CurCharInfo
;
2639 PCSRSS_SCREEN_BUFFER Buff
;
2648 DWORD i
, Y
, X
, Offset
;
2650 DPRINT("CsrReadConsoleOutput\n");
2652 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2653 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
2655 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputRequest
.ConsoleHandle
, &Buff
);
2656 if (! NT_SUCCESS(Status
))
2658 return Reply
->Status
= Status
;
2661 CharInfo
= Request
->Data
.ReadConsoleOutputRequest
.CharInfo
;
2662 ReadRegion
.left
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
;
2663 ReadRegion
.top
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
;
2664 ReadRegion
.right
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
;
2665 ReadRegion
.bottom
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
;
2666 BufferSize
= Request
->Data
.ReadConsoleOutputRequest
.BufferSize
;
2667 BufferCoord
= Request
->Data
.ReadConsoleOutputRequest
.BufferCoord
;
2668 Length
= BufferSize
.X
* BufferSize
.Y
;
2669 Size
= Length
* sizeof(CHAR_INFO
);
2671 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
)
2672 || (((PVOID
)CharInfo
+ Size
) > (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2674 ConioUnlockScreenBuffer(Buff
);
2675 Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2676 return Reply
->Status
;
2679 SizeY
= RtlRosMin(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&ReadRegion
));
2680 SizeX
= RtlRosMin(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&ReadRegion
));
2681 ReadRegion
.bottom
= ReadRegion
.top
+ SizeY
;
2682 ReadRegion
.right
= ReadRegion
.left
+ SizeX
;
2684 ConioInitRect(&ScreenRect
, 0, 0, Buff
->MaxY
, Buff
->MaxX
);
2685 if (! ConioGetIntersection(&ReadRegion
, &ScreenRect
, &ReadRegion
))
2687 ConioUnlockScreenBuffer(Buff
);
2688 Reply
->Status
= STATUS_SUCCESS
;
2689 return Reply
->Status
;
2692 for (i
= 0, Y
= ReadRegion
.top
; Y
< ReadRegion
.bottom
; ++i
, ++Y
)
2694 CurCharInfo
= CharInfo
+ (i
* BufferSize
.X
);
2696 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ ReadRegion
.left
) * 2;
2697 for (X
= ReadRegion
.left
; X
< ReadRegion
.right
; ++X
)
2699 CurCharInfo
->Char
.AsciiChar
= GET_CELL_BUFFER(Buff
, Offset
);
2700 CurCharInfo
->Attributes
= GET_CELL_BUFFER(Buff
, Offset
);
2705 ConioUnlockScreenBuffer(Buff
);
2707 Reply
->Status
= STATUS_SUCCESS
;
2708 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Right
= ReadRegion
.left
+ SizeX
- 1;
2709 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Bottom
= ReadRegion
.top
+ SizeY
- 1;
2710 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Left
= ReadRegion
.left
;
2711 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Top
= ReadRegion
.top
;
2713 return Reply
->Status
;
2717 CSR_API(CsrWriteConsoleInput
)
2719 PINPUT_RECORD InputRecord
;
2720 PCSRSS_CONSOLE Console
;
2725 ConsoleInput
* Record
;
2727 DPRINT("CsrWriteConsoleInput\n");
2729 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2730 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
2732 Status
= ConioLockConsole(ProcessData
, Request
->Data
.WriteConsoleInputRequest
.ConsoleHandle
, &Console
);
2733 if (! NT_SUCCESS(Status
))
2735 return Reply
->Status
= Status
;
2738 InputRecord
= Request
->Data
.WriteConsoleInputRequest
.InputRecord
;
2739 Length
= Request
->Data
.WriteConsoleInputRequest
.Length
;
2740 Size
= Length
* sizeof(INPUT_RECORD
);
2742 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2743 || (((PVOID
)InputRecord
+ Size
) > (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2745 ConioUnlockConsole(Console
);
2746 Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2747 return Reply
->Status
;
2750 for (i
= 0; i
< Length
; i
++)
2752 Record
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
2755 ConioUnlockConsole(Console
);
2756 Reply
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2757 return Reply
->Status
;
2760 Record
->Echoed
= FALSE
;
2761 Record
->Fake
= FALSE
;
2762 Record
->InputEvent
= *InputRecord
++;
2763 if (KEY_EVENT
== Record
->InputEvent
.EventType
)
2765 ConioProcessChar(Console
, Record
);
2769 ConioUnlockConsole(Console
);
2771 Reply
->Status
= STATUS_SUCCESS
;
2772 Reply
->Data
.WriteConsoleInputReply
.Length
= i
;
2774 return Reply
->Status
;
2777 /**********************************************************************
2778 * HardwareStateProperty
2781 * Set/Get the value of the HardwareState and switch
2782 * between direct video buffer ouput and GDI windowed
2785 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
2786 * object. We use the same object to reply.
2788 * ConsoleHwState has the correct size to be compatible
2789 * with NT's, but values are not.
2791 STATIC NTSTATUS FASTCALL
2792 SetConsoleHardwareState (PCSRSS_CONSOLE Console
, DWORD ConsoleHwState
)
2794 DPRINT1("Console Hardware State: %d\n", ConsoleHwState
);
2796 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED
== ConsoleHwState
)
2797 ||(CONSOLE_HARDWARE_STATE_DIRECT
== ConsoleHwState
))
2799 if (Console
->HardwareState
!= ConsoleHwState
)
2801 /* TODO: implement switching from full screen to windowed mode */
2802 /* TODO: or back; now simply store the hardware state */
2803 Console
->HardwareState
= ConsoleHwState
;
2806 return STATUS_SUCCESS
;
2809 return STATUS_INVALID_PARAMETER_3
; /* Client: (handle, set_get, [mode]) */
2812 CSR_API(CsrHardwareStateProperty
)
2814 PCSRSS_CONSOLE Console
;
2817 DPRINT("CsrHardwareStateProperty\n");
2819 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2820 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
2822 Status
= ConioLockConsole(ProcessData
,
2823 Request
->Data
.ConsoleHardwareStateRequest
.ConsoleHandle
,
2825 if (! NT_SUCCESS(Status
))
2827 DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
2828 return Reply
->Status
= Status
;
2831 switch (Request
->Data
.ConsoleHardwareStateRequest
.SetGet
)
2833 case CONSOLE_HARDWARE_STATE_GET
:
2834 Reply
->Data
.ConsoleHardwareStateReply
.State
= Console
->HardwareState
;
2837 case CONSOLE_HARDWARE_STATE_SET
:
2838 DPRINT("Setting console hardware state.\n");
2839 Reply
->Status
= SetConsoleHardwareState(Console
, Request
->Data
.ConsoleHardwareStateRequest
.State
);
2843 Reply
->Status
= STATUS_INVALID_PARAMETER_2
; /* Client: (handle, [set_get], mode) */
2847 ConioUnlockConsole(Console
);
2849 return Reply
->Status
;
2852 CSR_API(CsrGetConsoleWindow
)
2854 PCSRSS_CONSOLE Console
;
2857 DPRINT("CsrGetConsoleWindow\n");
2859 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2860 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE
);
2862 Status
= ConioLockConsole(ProcessData
,
2863 Request
->Data
.ConsoleWindowRequest
.ConsoleHandle
,
2865 if (! NT_SUCCESS(Status
))
2867 return Reply
->Status
= Status
;
2870 Reply
->Data
.ConsoleWindowReply
.WindowHandle
= Console
->hWindow
;
2871 ConioUnlockConsole(Console
);
2873 return Reply
->Status
= STATUS_SUCCESS
;