1 /* $Id: conio.c,v 1.12 2004/08/22 20:52:28 navaraf 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", ProcessData
->ProcessId
);
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 Console
->CodePage
= CP_OEMCP
;
174 Console
->OutputCodePage
= CP_OEMCP
;
176 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
177 SecurityAttributes
.lpSecurityDescriptor
= NULL
;
178 SecurityAttributes
.bInheritHandle
= TRUE
;
180 Console
->ActiveEvent
= CreateEventW(&SecurityAttributes
, FALSE
, FALSE
, NULL
);
181 if (NULL
== Console
->ActiveEvent
)
183 RtlFreeUnicodeString(&Console
->Title
);
184 return STATUS_UNSUCCESSFUL
;
186 Console
->PrivateData
= NULL
;
187 RtlInitializeCriticalSection(&Console
->Header
.Lock
);
188 GuiMode
= DtbgIsDesktopVisible();
191 Status
= TuiInitConsole(Console
);
192 if (! NT_SUCCESS(Status
))
194 DPRINT1("Failed to open text-mode console, switching to gui-mode\n");
200 Status
= GuiInitConsole(Console
);
201 if (! NT_SUCCESS(Status
))
203 RtlFreeUnicodeString(&Console
->Title
);
204 RtlDeleteCriticalSection(&Console
->Header
.Lock
);
205 CloseHandle(Console
->ActiveEvent
);
210 NewBuffer
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(CSRSS_SCREEN_BUFFER
));
211 if (NULL
== NewBuffer
)
213 RtlFreeUnicodeString(&Console
->Title
);
214 RtlDeleteCriticalSection(&Console
->Header
.Lock
);
215 CloseHandle(Console
->ActiveEvent
);
216 return STATUS_INSUFFICIENT_RESOURCES
;
218 Status
= CsrInitConsoleScreenBuffer(Console
, NewBuffer
);
219 if (! NT_SUCCESS(Status
))
221 RtlFreeUnicodeString(&Console
->Title
);
222 RtlDeleteCriticalSection(&Console
->Header
.Lock
);
223 CloseHandle(Console
->ActiveEvent
);
224 HeapFree(Win32CsrApiHeap
, 0, NewBuffer
);
227 Console
->ActiveBuffer
= NewBuffer
;
228 /* add a reference count because the buffer is tied to the console */
229 Console
->ActiveBuffer
->Header
.ReferenceCount
++;
230 /* make console active, and insert into console list */
231 /* copy buffer contents to screen */
232 ConioDrawConsole(Console
);
234 return STATUS_SUCCESS
;
238 CSR_API(CsrAllocConsole
)
240 PCSRSS_CONSOLE Console
;
244 DPRINT("CsrAllocConsole\n");
246 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
247 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
249 if (ProcessData
== NULL
)
251 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
254 if (ProcessData
->Console
)
256 Reply
->Status
= STATUS_INVALID_PARAMETER
;
257 return STATUS_INVALID_PARAMETER
;
260 Reply
->Status
= STATUS_SUCCESS
;
261 Console
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(CSRSS_CONSOLE
));
264 Reply
->Status
= STATUS_NO_MEMORY
;
265 return STATUS_NO_MEMORY
;
267 Reply
->Status
= CsrInitConsole(Console
);
268 if (! NT_SUCCESS(Reply
->Status
))
270 HeapFree(Win32CsrApiHeap
, 0, Console
);
271 return Reply
->Status
;
273 ProcessData
->Console
= Console
;
274 Reply
->Data
.AllocConsoleReply
.Console
= Console
;
276 /* add a reference count because the process is tied to the console */
277 Console
->Header
.ReferenceCount
++;
278 Status
= Win32CsrInsertObject(ProcessData
, &Reply
->Data
.AllocConsoleReply
.InputHandle
, &Console
->Header
);
279 if (! NT_SUCCESS(Status
))
281 ConioDeleteConsole((Object_t
*) Console
);
282 ProcessData
->Console
= 0;
283 return Reply
->Status
= Status
;
285 Status
= Win32CsrInsertObject(ProcessData
, &Reply
->Data
.AllocConsoleReply
.OutputHandle
, &Console
->ActiveBuffer
->Header
);
286 if (!NT_SUCCESS(Status
))
288 Console
->Header
.ReferenceCount
--;
289 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.InputHandle
);
290 ProcessData
->Console
= 0;
291 return Reply
->Status
= Status
;
294 Process
= OpenProcess(PROCESS_DUP_HANDLE
, FALSE
, ProcessData
->ProcessId
);
297 DPRINT1("OpenProcess() failed for handle duplication\n");
298 Console
->Header
.ReferenceCount
--;
299 ProcessData
->Console
= 0;
300 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.OutputHandle
);
301 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.InputHandle
);
302 Reply
->Status
= Status
;
305 if (! DuplicateHandle(GetCurrentProcess(), ProcessData
->Console
->ActiveEvent
,
306 Process
, &ProcessData
->ConsoleEvent
, EVENT_ALL_ACCESS
, FALSE
, 0))
308 DPRINT1("DuplicateHandle() failed: %d\n", GetLastError
);
309 CloseHandle(Process
);
310 Console
->Header
.ReferenceCount
--;
311 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.OutputHandle
);
312 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.InputHandle
);
313 ProcessData
->Console
= 0;
314 Reply
->Status
= Status
;
317 CloseHandle(Process
);
318 ProcessData
->CtrlDispatcher
= Request
->Data
.AllocConsoleRequest
.CtrlDispatcher
;
319 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
320 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ProcessEntry
);
322 return STATUS_SUCCESS
;
325 CSR_API(CsrFreeConsole
)
327 PCSRSS_CONSOLE Console
;
329 DPRINT("CsrFreeConsole\n");
331 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
332 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
334 if (ProcessData
== NULL
|| ProcessData
->Console
== NULL
)
336 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
339 Console
= ProcessData
->Console
;
340 Console
->Header
.ReferenceCount
--;
341 ProcessData
->Console
= NULL
;
342 if (0 == Console
->Header
.ReferenceCount
)
344 ConioDeleteConsole((Object_t
*) Console
);
347 return STATUS_SUCCESS
;
351 ConioNextLine(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, UINT
*ScrolledLines
)
353 /* slide the viewable screen */
354 if (((Buff
->CurrentY
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
) == Buff
->MaxY
- 1)
356 if (++Buff
->ShowY
== Buff
->MaxY
)
362 if (++Buff
->CurrentY
== Buff
->MaxY
)
366 ClearLineBuffer(Buff
);
367 UpdateRect
->left
= 0;
368 UpdateRect
->right
= Buff
->MaxX
- 1;
369 if (UpdateRect
->top
== Buff
->CurrentY
)
371 if (++UpdateRect
->top
== Buff
->MaxY
)
376 UpdateRect
->bottom
= Buff
->CurrentY
;
379 STATIC NTSTATUS FASTCALL
380 ConioWriteConsole(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
,
381 CHAR
*Buffer
, DWORD Length
, BOOL Attrib
)
386 LONG CursorStartX
, CursorStartY
;
389 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &CursorStartX
, &CursorStartY
);
390 UpdateRect
.left
= Buff
->MaxX
;
391 UpdateRect
.top
= Buff
->CurrentY
;
392 UpdateRect
.right
= -1;
393 UpdateRect
.bottom
= Buff
->CurrentY
;
396 for (i
= 0; i
< Length
; i
++)
403 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
408 /* Only handle BS if we're not on the first pos of the first line */
409 if (0 != Buff
->CurrentX
|| Buff
->ShowY
!= Buff
->CurrentY
)
411 if (0 == Buff
->CurrentX
)
413 /* slide virtual position up */
414 Buff
->CurrentX
= Buff
->MaxX
- 1;
415 if (0 == Buff
->CurrentY
)
417 Buff
->CurrentY
= Buff
->MaxY
;
423 if ((0 == UpdateRect
.top
&& UpdateRect
.bottom
< Buff
->CurrentY
)
424 || (0 != UpdateRect
.top
&& Buff
->CurrentY
< UpdateRect
.top
))
426 UpdateRect
.top
= Buff
->CurrentY
;
433 Offset
= 2 * ((Buff
->CurrentY
* Buff
->MaxX
) + Buff
->CurrentX
);
434 SET_CELL_BUFFER(Buff
, Offset
, ' ', Buff
->DefaultAttrib
);
435 UpdateRect
.left
= RtlRosMin(UpdateRect
.left
, Buff
->CurrentX
);
436 UpdateRect
.right
= RtlRosMax(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
443 UpdateRect
.left
= RtlRosMin(UpdateRect
.left
, Buff
->CurrentX
);
444 UpdateRect
.right
= RtlRosMax(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
452 UpdateRect
.left
= RtlRosMin(UpdateRect
.left
, Buff
->CurrentX
);
453 EndX
= 8 * ((Buff
->CurrentX
+ 8) / 8);
454 if (Buff
->MaxX
< EndX
)
458 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
459 while (Buff
->CurrentX
< EndX
)
461 Buff
->Buffer
[Offset
] = ' ';
465 UpdateRect
.right
= RtlRosMax(UpdateRect
.right
, (LONG
) Buff
->CurrentX
- 1);
466 if (Buff
->CurrentX
== Buff
->MaxX
)
469 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
476 UpdateRect
.left
= RtlRosMin(UpdateRect
.left
, Buff
->CurrentX
);
477 UpdateRect
.right
= RtlRosMax(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
478 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
479 Buff
->Buffer
[Offset
++] = Buffer
[i
];
482 Buff
->Buffer
[Offset
] = Buff
->DefaultAttrib
;
485 if (Buff
->CurrentX
== Buff
->MaxX
)
488 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
494 ConioPhysicalToLogical(Buff
, UpdateRect
.left
, UpdateRect
.top
, &(UpdateRect
.left
),
496 ConioPhysicalToLogical(Buff
, UpdateRect
.right
, UpdateRect
.bottom
, &(UpdateRect
.right
),
497 &(UpdateRect
.bottom
));
498 if (! ConioIsRectEmpty(&UpdateRect
) && NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
500 ConioWriteStream(Console
, &UpdateRect
, CursorStartX
, CursorStartY
, ScrolledLines
,
504 return STATUS_SUCCESS
;
507 CSR_API(CsrReadConsole
)
509 PLIST_ENTRY CurrentEntry
;
513 ULONG nNumberOfCharsToRead
;
514 PCSRSS_CONSOLE Console
;
517 DPRINT("CsrReadConsole\n");
519 /* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */
520 nNumberOfCharsToRead
= Request
->Data
.ReadConsoleRequest
.NrCharactersToRead
> CSRSS_MAX_READ_CONSOLE_REQUEST
? CSRSS_MAX_READ_CONSOLE_REQUEST
: Request
->Data
.ReadConsoleRequest
.NrCharactersToRead
;
521 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
522 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
524 Buffer
= Reply
->Data
.ReadConsoleReply
.Buffer
;
525 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadConsoleRequest
.ConsoleHandle
,
527 if (! NT_SUCCESS(Status
))
529 return Reply
->Status
= Status
;
531 Reply
->Data
.ReadConsoleReply
.EventHandle
= ProcessData
->ConsoleEvent
;
532 for (i
= 0; i
< nNumberOfCharsToRead
&& Console
->InputEvents
.Flink
!= &Console
->InputEvents
; i
++)
534 /* remove input event from queue */
535 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
536 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
538 /* only pay attention to valid ascii chars, on key down */
539 if (KEY_EVENT
== Input
->InputEvent
.EventType
540 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
541 && Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
543 /* backspace handling */
544 if ('\b' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
546 /* echo if it has not already been done, and either we or the client has chars to be deleted */
548 && (0 != i
|| Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
))
550 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
551 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
555 i
-= 2; /* if we already have something to return, just back it up by 2 */
558 { /* otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer */
559 Reply
->Data
.ReadConsoleReply
.NrCharactersRead
= 0;
560 Reply
->Status
= STATUS_NOTIFY_CLEANUP
;
561 Console
->WaitingChars
--;
562 HeapFree(Win32CsrApiHeap
, 0, Input
);
563 ConioUnlockConsole(Console
);
564 return STATUS_NOTIFY_CLEANUP
;
566 Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
--;
567 Input
->Echoed
= TRUE
; /* mark as echoed so we don't echo it below */
569 /* do not copy backspace to buffer */
572 Buffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
;
574 /* echo to screen if enabled and we did not already echo the char */
575 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
)
577 && '\r' != Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
579 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
580 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
587 Console
->WaitingChars
--;
588 HeapFree(Win32CsrApiHeap
, 0, Input
);
590 Reply
->Data
.ReadConsoleReply
.NrCharactersRead
= i
;
593 Reply
->Status
= STATUS_PENDING
; /* we didn't read anything */
595 else if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
))
597 if (0 == Console
->WaitingLines
|| '\n' != Buffer
[i
- 1])
599 Reply
->Status
= STATUS_PENDING
; /* line buffered, didn't get a complete line */
603 Console
->WaitingLines
--;
604 Reply
->Status
= STATUS_SUCCESS
; /* line buffered, did get a complete line */
609 Reply
->Status
= STATUS_SUCCESS
; /* not line buffered, did read something */
612 if (Reply
->Status
== STATUS_PENDING
)
614 Console
->EchoCount
= nNumberOfCharsToRead
- i
;
618 Console
->EchoCount
= 0; /* if the client is no longer waiting on input, do not echo */
620 Reply
->Header
.MessageSize
+= i
;
622 ConioUnlockConsole(Console
);
623 return Reply
->Status
;
627 ConioPhysicalToLogical(PCSRSS_SCREEN_BUFFER Buff
,
633 *LogicalX
= PhysicalX
;
634 if (PhysicalY
< Buff
->ShowY
)
636 *LogicalY
= Buff
->MaxY
- Buff
->ShowY
+ PhysicalY
;
640 *LogicalY
= PhysicalY
- Buff
->ShowY
;
644 inline BOOLEAN
ConioIsEqualRect(
648 return ((Rect1
->left
== Rect2
->left
) && (Rect1
->right
== Rect2
->right
) &&
649 (Rect1
->top
== Rect2
->top
) && (Rect1
->bottom
== Rect2
->bottom
));
652 inline BOOLEAN
ConioGetIntersection(
657 if (ConioIsRectEmpty(Rect1
) ||
658 (ConioIsRectEmpty(Rect2
)) ||
659 (Rect1
->top
> Rect2
->bottom
) ||
660 (Rect1
->left
> Rect2
->right
) ||
661 (Rect1
->bottom
< Rect2
->top
) ||
662 (Rect1
->right
< Rect2
->left
))
664 /* The rectangles do not intersect */
665 ConioInitRect(Intersection
, 0, -1, 0, -1);
669 ConioInitRect(Intersection
,
670 RtlRosMax(Rect1
->top
, Rect2
->top
),
671 RtlRosMax(Rect1
->left
, Rect2
->left
),
672 RtlRosMin(Rect1
->bottom
, Rect2
->bottom
),
673 RtlRosMin(Rect1
->right
, Rect2
->right
));
678 inline BOOLEAN
ConioGetUnion(
683 if (ConioIsRectEmpty(Rect1
))
685 if (ConioIsRectEmpty(Rect2
))
687 ConioInitRect(Union
, 0, -1, 0, -1);
695 else if (ConioIsRectEmpty(Rect2
))
702 RtlRosMin(Rect1
->top
, Rect2
->top
),
703 RtlRosMin(Rect1
->left
, Rect2
->left
),
704 RtlRosMax(Rect1
->bottom
, Rect2
->bottom
),
705 RtlRosMax(Rect1
->right
, Rect2
->right
));
711 inline BOOLEAN
ConioSubtractRect(
718 if (ConioIsRectEmpty(Rect1
))
720 ConioInitRect(Subtraction
, 0, -1, 0, -1);
723 *Subtraction
= *Rect1
;
724 if (ConioGetIntersection(&tmp
, Rect1
, Rect2
))
726 if (ConioIsEqualRect(&tmp
, Subtraction
))
728 ConioInitRect(Subtraction
, 0, -1, 0, -1);
731 if ((tmp
.top
== Subtraction
->top
) && (tmp
.bottom
== Subtraction
->bottom
))
733 if (tmp
.left
== Subtraction
->left
)
735 Subtraction
->left
= tmp
.right
;
737 else if (tmp
.right
== Subtraction
->right
)
739 Subtraction
->right
= tmp
.left
;
742 else if ((tmp
.left
== Subtraction
->left
) && (tmp
.right
== Subtraction
->right
))
744 if (tmp
.top
== Subtraction
->top
)
746 Subtraction
->top
= tmp
.bottom
;
748 else if (tmp
.bottom
== Subtraction
->bottom
)
750 Subtraction
->bottom
= tmp
.top
;
759 ConioCopyRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer
,
769 DstY
= DstRegion
->top
;
770 BytesPerLine
= ConioRectWidth(DstRegion
) * 2;
772 SrcY
= (SrcRegion
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
773 DstY
= (DstRegion
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
774 SrcOffset
= (SrcY
* ScreenBuffer
->MaxX
+ SrcRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
775 DstOffset
= (DstY
* ScreenBuffer
->MaxX
+ DstRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
777 for (i
= SrcRegion
->top
; i
<= SrcRegion
->bottom
; i
++)
780 &ScreenBuffer
->Buffer
[DstOffset
],
781 &ScreenBuffer
->Buffer
[SrcOffset
],
784 if (++DstY
== ScreenBuffer
->MaxY
)
787 DstOffset
= (DstRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
791 DstOffset
+= ScreenBuffer
->MaxX
* 2;
794 if (++SrcY
== ScreenBuffer
->MaxY
)
797 SrcOffset
= (SrcRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
801 SrcOffset
+= ScreenBuffer
->MaxX
* 2;
807 ConioFillRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer
,
816 Y
= (Region
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
817 Offset
= (Y
* ScreenBuffer
->MaxX
+ Region
->left
+ ScreenBuffer
->ShowX
) * 2;
818 Delta
= (ScreenBuffer
->MaxX
- ConioRectWidth(Region
)) * 2;
820 for (i
= Region
->top
; i
<= Region
->bottom
; i
++)
822 for (X
= Region
->left
; X
<= Region
->right
; X
++)
824 SET_CELL_BUFFER(ScreenBuffer
, Offset
, CharInfo
.Char
.AsciiChar
, CharInfo
.Attributes
);
826 if (++Y
== ScreenBuffer
->MaxY
)
829 Offset
= (Region
->left
+ ScreenBuffer
->ShowX
) * 2;
839 ConioInputEventToAnsi(PCSRSS_CONSOLE Console
, PINPUT_RECORD InputEvent
)
841 if (InputEvent
->EventType
== KEY_EVENT
)
843 WideCharToMultiByte(Console
->CodePage
, 0,
844 &InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
, 1,
845 &InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
, 1,
850 CSR_API(CsrWriteConsole
)
853 BYTE
*Buffer
= Request
->Data
.WriteConsoleRequest
.Buffer
;
854 PCSRSS_SCREEN_BUFFER Buff
;
855 PCSRSS_CONSOLE Console
;
857 DPRINT("CsrWriteConsole\n");
859 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
860 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
862 if (Request
->Header
.DataSize
863 < sizeof(CSRSS_WRITE_CONSOLE_REQUEST
) - 1
864 + Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
)
866 DPRINT1("Invalid request size\n");
867 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
869 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
870 if (! NT_SUCCESS(Status
))
872 return Reply
->Status
= Status
;
875 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.WriteConsoleRequest
.ConsoleHandle
, &Buff
);
876 if (! NT_SUCCESS(Status
))
880 ConioUnlockConsole(Console
);
882 return Reply
->Status
= Status
;
885 ConioWriteConsole(Console
, Buff
, Buffer
,
886 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
, TRUE
);
887 ConioUnlockScreenBuffer(Buff
);
890 ConioUnlockConsole(Console
);
893 return Reply
->Status
= STATUS_SUCCESS
;
897 ConioDeleteScreenBuffer(Object_t
*Object
)
899 PCSRSS_SCREEN_BUFFER Buffer
= (PCSRSS_SCREEN_BUFFER
) Object
;
900 RtlDeleteCriticalSection(&Buffer
->Header
.Lock
);
901 HeapFree(Win32CsrApiHeap
, 0, Buffer
->Buffer
);
902 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
906 ConioDrawConsole(PCSRSS_CONSOLE Console
)
910 ConioInitRect(&Region
, 0, 0, Console
->Size
.Y
- 1, Console
->Size
.X
- 1);
912 ConioDrawRegion(Console
, &Region
);
917 ConioDeleteConsole(Object_t
*Object
)
919 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Object
;
922 DPRINT("ConioDeleteConsole\n");
924 /* Drain input event queue */
925 while (Console
->InputEvents
.Flink
!= &Console
->InputEvents
)
927 Event
= (ConsoleInput
*) Console
->InputEvents
.Flink
;
928 Console
->InputEvents
.Flink
= Console
->InputEvents
.Flink
->Flink
;
929 Console
->InputEvents
.Flink
->Flink
->Blink
= &Console
->InputEvents
;
930 HeapFree(Win32CsrApiHeap
, 0, Event
);
933 if (0 == --Console
->ActiveBuffer
->Header
.ReferenceCount
)
935 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
938 Console
->ActiveBuffer
= NULL
;
939 ConioCleanupConsole(Console
);
941 CloseHandle(Console
->ActiveEvent
);
942 RtlDeleteCriticalSection(&Console
->Header
.Lock
);
943 RtlFreeUnicodeString(&Console
->Title
);
944 HeapFree(Win32CsrApiHeap
, 0, Console
);
948 CsrInitConsoleSupport(VOID
)
950 DPRINT("CSR: CsrInitConsoleSupport()\n");
952 /* Should call LoadKeyboardLayout */
956 ConioProcessChar(PCSRSS_CONSOLE Console
,
957 ConsoleInput
*KeyEventRecord
)
960 BOOL bClientWake
= FALSE
;
961 ConsoleInput
*TempInput
;
963 /* process Ctrl-C and Ctrl-Break */
964 if (Console
->Mode
& ENABLE_PROCESSED_INPUT
&&
965 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
&&
966 ((KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== VK_PAUSE
) ||
967 (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== 'C')) &&
968 (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
)))
970 PCSRSS_PROCESS_DATA current
;
971 PLIST_ENTRY current_entry
;
972 DPRINT1("Console_Api Ctrl-C\n");
973 current_entry
= Console
->ProcessList
.Flink
;
974 while (current_entry
!= &Console
->ProcessList
)
976 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
977 current_entry
= current_entry
->Flink
;
978 CsrConsoleCtrlEvent((DWORD
)CTRL_C_EVENT
, current
);
980 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
984 if (0 != (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
985 & (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
986 && (VK_UP
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
987 || VK_DOWN
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
))
989 if (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
991 /* scroll up or down */
994 DPRINT1("No Active Console!\n");
995 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
998 if (VK_UP
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
)
1000 /* only scroll up if there is room to scroll up into */
1001 if (Console
->ActiveBuffer
->ShowY
!= ((Console
->ActiveBuffer
->CurrentY
+ 1) %
1002 Console
->ActiveBuffer
->MaxY
))
1004 Console
->ActiveBuffer
->ShowY
= (Console
->ActiveBuffer
->ShowY
+
1005 Console
->ActiveBuffer
->MaxY
- 1) %
1006 Console
->ActiveBuffer
->MaxY
;
1009 else if (Console
->ActiveBuffer
->ShowY
!= Console
->ActiveBuffer
->CurrentY
)
1010 /* only scroll down if there is room to scroll down into */
1012 if (Console
->ActiveBuffer
->ShowY
% Console
->ActiveBuffer
->MaxY
!=
1013 Console
->ActiveBuffer
->CurrentY
)
1015 if (((Console
->ActiveBuffer
->CurrentY
+ 1) % Console
->ActiveBuffer
->MaxY
) !=
1016 (Console
->ActiveBuffer
->ShowY
+ Console
->ActiveBuffer
->MaxY
) %
1017 Console
->ActiveBuffer
->MaxY
)
1019 Console
->ActiveBuffer
->ShowY
= (Console
->ActiveBuffer
->ShowY
+ 1) %
1020 Console
->ActiveBuffer
->MaxY
;
1024 ConioDrawConsole(Console
);
1026 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1029 if (NULL
== Console
)
1031 DPRINT1("No Active Console!\n");
1032 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1036 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
)))
1038 switch(KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1041 /* first add the \r */
1042 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1043 updown
= KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
;
1044 KeyEventRecord
->Echoed
= FALSE
;
1045 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= VK_RETURN
;
1046 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\r';
1047 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1048 Console
->WaitingChars
++;
1049 KeyEventRecord
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1050 if (NULL
== KeyEventRecord
)
1052 DPRINT1("Failed to allocate KeyEventRecord\n");
1055 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1056 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
= updown
;
1057 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= 0;
1058 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualScanCode
= 0;
1059 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\n';
1060 KeyEventRecord
->Fake
= TRUE
;
1064 /* add event to the queue */
1065 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1066 Console
->WaitingChars
++;
1067 /* if line input mode is enabled, only wake the client on enter key down */
1068 if (0 == (Console
->Mode
& ENABLE_LINE_INPUT
)
1069 || Console
->EarlyReturn
1070 || ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1071 && ! KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
))
1073 if ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1075 Console
->WaitingLines
++;
1078 SetEvent(Console
->ActiveEvent
);
1080 KeyEventRecord
->Echoed
= FALSE
;
1081 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
))
1082 && '\b' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1083 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1085 /* walk the input queue looking for a char to backspace */
1086 for (TempInput
= (ConsoleInput
*) Console
->InputEvents
.Blink
;
1087 TempInput
!= (ConsoleInput
*) &Console
->InputEvents
1088 && (KEY_EVENT
== TempInput
->InputEvent
.EventType
1089 || ! TempInput
->InputEvent
.Event
.KeyEvent
.bKeyDown
1090 || '\b' == TempInput
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
);
1091 TempInput
= (ConsoleInput
*) TempInput
->ListEntry
.Blink
)
1095 /* if we found one, delete it, otherwise, wake the client */
1096 if (TempInput
!= (ConsoleInput
*) &Console
->InputEvents
)
1098 /* delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue */
1099 RemoveEntryList(&TempInput
->ListEntry
);
1100 if (TempInput
->Echoed
)
1102 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1103 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1106 HeapFree(Win32CsrApiHeap
, 0, TempInput
);
1107 RemoveEntryList(&KeyEventRecord
->ListEntry
);
1108 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1109 Console
->WaitingChars
-= 2;
1113 SetEvent(Console
->ActiveEvent
);
1118 /* echo chars if we are supposed to and client is waiting for some */
1119 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
) && Console
->EchoCount
1120 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1121 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
1122 && '\r' != KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1124 /* mark the char as already echoed */
1125 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1126 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1128 Console
->EchoCount
--;
1129 KeyEventRecord
->Echoed
= TRUE
;
1133 /* Console->WaitingChars++; */
1134 if (bClientWake
|| 0 == (Console
->Mode
& ENABLE_LINE_INPUT
))
1136 SetEvent(Console
->ActiveEvent
);
1140 STATIC DWORD FASTCALL
1141 ConioGetShiftState(PBYTE KeyState
)
1145 if (KeyState
[VK_CAPITAL
] & 1)
1146 ssOut
|= CAPSLOCK_ON
;
1148 if (KeyState
[VK_NUMLOCK
] & 1)
1149 ssOut
|= NUMLOCK_ON
;
1151 if (KeyState
[VK_SCROLL
] & 1)
1152 ssOut
|= SCROLLLOCK_ON
;
1154 if (KeyState
[VK_SHIFT
] & 0x80)
1155 ssOut
|= SHIFT_PRESSED
;
1157 if (KeyState
[VK_LCONTROL
] & 0x80)
1158 ssOut
|= LEFT_CTRL_PRESSED
;
1159 if (KeyState
[VK_RCONTROL
] & 0x80)
1160 ssOut
|= RIGHT_CTRL_PRESSED
;
1162 if (KeyState
[VK_LMENU
] & 0x80)
1163 ssOut
|= LEFT_ALT_PRESSED
;
1164 if (KeyState
[VK_RMENU
] & 0x80)
1165 ssOut
|= RIGHT_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);
1218 if (0 == ResultSize
)
1223 er
.EventType
= KEY_EVENT
;
1224 er
.Event
.KeyEvent
.bKeyDown
= Down
;
1225 er
.Event
.KeyEvent
.wRepeatCount
= RepeatCount
;
1226 er
.Event
.KeyEvent
.uChar
.UnicodeChar
= UnicodeChar
;
1227 er
.Event
.KeyEvent
.dwControlKeyState
= ShiftState
;
1228 er
.Event
.KeyEvent
.wVirtualKeyCode
= VirtualKeyCode
;
1229 er
.Event
.KeyEvent
.wVirtualScanCode
= VirtualScanCode
;
1233 if (0 != (ShiftState
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1234 && VK_TAB
== VirtualKeyCode
)
1238 TuiSwapConsole(ShiftState
& SHIFT_PRESSED
? -1 : 1);
1243 else if (VK_MENU
== VirtualKeyCode
&& ! Down
)
1245 if (TuiSwapConsole(0))
1252 if (NULL
== Console
)
1257 ConInRec
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1259 if (NULL
== ConInRec
)
1264 ConInRec
->InputEvent
= er
;
1265 ConInRec
->Fake
= UnicodeChar
&&
1266 (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
&&
1267 msg
->message
!= WM_KEYUP
&& msg
->message
!= WM_SYSKEYUP
);
1268 ConInRec
->NotChar
= (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
);
1269 ConInRec
->Echoed
= FALSE
;
1270 if (ConInRec
->NotChar
)
1271 LastVirtualKey
= msg
->wParam
;
1273 DPRINT ("csrss: %s %s %s %s %02x %02x '%c' %04x\n",
1274 Down
? "down" : "up ",
1275 (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
) ?
1277 ConInRec
->Fake
? "fake" : "real",
1278 ConInRec
->NotChar
? "notc" : "char",
1281 (AsciiChar
>= ' ') ? AsciiChar
: '.',
1284 if (! ConInRec
->Fake
|| ! ConInRec
->NotChar
)
1286 ConioProcessChar(Console
, ConInRec
);
1290 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1295 Console_Api(DWORD RefreshEvent
)
1297 /* keep reading events from the keyboard and stuffing them into the current
1298 console's input queue */
1301 /* This call establishes our message queue */
1302 PeekMessageW(&msg
, 0, 0, 0, PM_NOREMOVE
);
1303 /* This call registers our message queue */
1304 PrivateCsrssRegisterPrimitive();
1305 /* This call turns on the input system in win32k */
1306 PrivateCsrssAcquireOrReleaseInputOwnership(FALSE
);
1310 GetMessageW(&msg
, 0, 0, 0);
1311 TranslateMessage(&msg
);
1313 if (msg
.message
== WM_CHAR
|| msg
.message
== WM_SYSCHAR
||
1314 msg
.message
== WM_KEYDOWN
|| msg
.message
== WM_KEYUP
||
1315 msg
.message
== WM_SYSKEYDOWN
|| msg
.message
== WM_SYSKEYUP
)
1317 ConioProcessKey(&msg
, TuiGetFocusConsole(), TRUE
);
1321 PrivateCsrssAcquireOrReleaseInputOwnership(TRUE
);
1324 CSR_API(CsrGetScreenBufferInfo
)
1327 PCSRSS_SCREEN_BUFFER Buff
;
1328 PCONSOLE_SCREEN_BUFFER_INFO pInfo
;
1330 DPRINT("CsrGetScreenBufferInfo\n");
1332 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1333 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1335 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ScreenBufferInfoRequest
.ConsoleHandle
, &Buff
);
1336 if (! NT_SUCCESS(Status
))
1338 return Reply
->Status
= Status
;
1340 pInfo
= &Reply
->Data
.ScreenBufferInfoReply
.Info
;
1341 pInfo
->dwSize
.X
= Buff
->MaxX
;
1342 pInfo
->dwSize
.Y
= Buff
->MaxY
;
1343 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1344 pInfo
->dwCursorPosition
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1345 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
1346 pInfo
->srWindow
.Left
= 0;
1347 pInfo
->srWindow
.Right
= Buff
->MaxX
- 1;
1348 pInfo
->srWindow
.Top
= 0;
1349 pInfo
->srWindow
.Bottom
= Buff
->MaxY
- 1;
1350 pInfo
->dwMaximumWindowSize
.X
= Buff
->MaxX
;
1351 pInfo
->dwMaximumWindowSize
.Y
= Buff
->MaxY
;
1352 ConioUnlockScreenBuffer(Buff
);
1354 Reply
->Status
= STATUS_SUCCESS
;
1356 return Reply
->Status
;
1359 CSR_API(CsrSetCursor
)
1362 PCSRSS_CONSOLE Console
;
1363 PCSRSS_SCREEN_BUFFER Buff
;
1364 LONG OldCursorX
, OldCursorY
;
1366 DPRINT("CsrSetCursor\n");
1368 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1369 if (! NT_SUCCESS(Status
))
1371 return Reply
->Status
= Status
;
1374 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1375 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1377 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
);
1378 if (! NT_SUCCESS(Status
))
1380 if (NULL
!= Console
)
1382 ConioUnlockConsole(Console
);
1384 return Reply
->Status
= Status
;
1387 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &OldCursorX
, &OldCursorY
);
1388 Buff
->CurrentX
= Request
->Data
.SetCursorRequest
.Position
.X
+ Buff
->ShowX
;
1389 Buff
->CurrentY
= (Request
->Data
.SetCursorRequest
.Position
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1390 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1392 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
1394 ConioUnlockScreenBuffer(Buff
);
1395 return Reply
->Status
= STATUS_UNSUCCESSFUL
;
1399 ConioUnlockScreenBuffer(Buff
);
1400 if (NULL
!= Console
)
1402 ConioUnlockConsole(Console
);
1405 return Reply
->Status
= STATUS_SUCCESS
;
1408 STATIC FASTCALL VOID
1409 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, COORD
*Start
, UINT Length
)
1411 if (Buff
->MaxX
<= Start
->X
+ Length
)
1413 UpdateRect
->left
= 0;
1417 UpdateRect
->left
= Start
->X
;
1419 if (Buff
->MaxX
<= Start
->X
+ Length
)
1421 UpdateRect
->right
= Buff
->MaxX
- 1;
1425 UpdateRect
->right
= Start
->X
+ Length
- 1;
1427 UpdateRect
->top
= Start
->Y
;
1428 UpdateRect
->bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->MaxX
;
1429 if (Buff
->MaxY
<= UpdateRect
->bottom
)
1431 UpdateRect
->bottom
= Buff
->MaxY
- 1;
1435 CSR_API(CsrWriteConsoleOutputChar
)
1438 PBYTE String
= Request
->Data
.WriteConsoleOutputCharRequest
.String
;
1440 PCSRSS_CONSOLE Console
;
1441 PCSRSS_SCREEN_BUFFER Buff
;
1445 DPRINT("CsrWriteConsoleOutputChar\n");
1447 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1448 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1450 if (Request
->Header
.DataSize
1451 < sizeof(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR_REQUEST
) - 1
1452 + Request
->Data
.WriteConsoleOutputCharRequest
.Length
)
1454 DPRINT1("Invalid request size\n");
1455 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
1458 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1459 if (! NT_SUCCESS(Status
))
1461 return Reply
->Status
= Status
;
1464 Status
= ConioLockScreenBuffer(ProcessData
,
1465 Request
->Data
.WriteConsoleOutputCharRequest
.ConsoleHandle
,
1467 if (! NT_SUCCESS(Status
))
1469 if (NULL
!= Console
)
1471 ConioUnlockConsole(Console
);
1473 return Reply
->Status
= Status
;
1476 X
= Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.X
+ Buff
->ShowX
;
1477 Y
= (Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1478 Length
= Request
->Data
.WriteConsoleOutputCharRequest
.Length
;
1479 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1482 *Buffer
= *String
++;
1484 if (++X
== Buff
->MaxX
)
1486 if (++Y
== Buff
->MaxY
)
1489 Buffer
= Buff
->Buffer
;
1495 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1497 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputCharRequest
.Coord
,
1498 Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
1499 ConioDrawRegion(Console
, &UpdateRect
);
1502 Reply
->Data
.WriteConsoleOutputCharReply
.EndCoord
.X
= X
- Buff
->ShowX
;
1503 Reply
->Data
.WriteConsoleOutputCharReply
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1505 ConioUnlockScreenBuffer(Buff
);
1506 if (NULL
!= Console
)
1508 ConioUnlockConsole(Console
);
1511 return Reply
->Status
= STATUS_SUCCESS
;
1514 CSR_API(CsrFillOutputChar
)
1517 PCSRSS_CONSOLE Console
;
1518 PCSRSS_SCREEN_BUFFER Buff
;
1524 DPRINT("CsrFillOutputChar\n");
1526 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1527 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1529 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1530 if (! NT_SUCCESS(Status
))
1532 return Reply
->Status
= Status
;
1535 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputRequest
.ConsoleHandle
, &Buff
);
1536 if (! NT_SUCCESS(Status
))
1538 if (NULL
!= Console
)
1540 ConioUnlockConsole(Console
);
1542 return Reply
->Status
= Status
;
1545 X
= Request
->Data
.FillOutputRequest
.Position
.X
+ Buff
->ShowX
;
1546 Y
= (Request
->Data
.FillOutputRequest
.Position
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1547 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1548 Char
= Request
->Data
.FillOutputRequest
.Char
;
1549 Length
= Request
->Data
.FillOutputRequest
.Length
;
1554 if (++X
== Buff
->MaxX
)
1556 if (++Y
== Buff
->MaxY
)
1559 Buffer
= Buff
->Buffer
;
1565 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1567 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputRequest
.Position
,
1568 Request
->Data
.FillOutputRequest
.Length
);
1569 ConioDrawRegion(Console
, &UpdateRect
);
1572 ConioUnlockScreenBuffer(Buff
);
1573 if (NULL
!= Console
)
1575 ConioUnlockConsole(Console
);
1578 return Reply
->Status
;
1581 CSR_API(CsrReadInputEvent
)
1583 PLIST_ENTRY CurrentEntry
;
1584 PCSRSS_CONSOLE Console
;
1586 BOOLEAN Done
= FALSE
;
1587 ConsoleInput
*Input
;
1589 DPRINT("CsrReadInputEvent\n");
1591 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1592 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1593 Reply
->Data
.ReadInputReply
.Event
= ProcessData
->ConsoleEvent
;
1595 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadInputRequest
.ConsoleHandle
, &Console
);
1596 if (! NT_SUCCESS(Status
))
1598 return Reply
->Status
= Status
;
1601 /* only get input if there is any */
1602 while (Console
->InputEvents
.Flink
!= &Console
->InputEvents
&& ! Done
)
1604 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
1605 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
1606 Done
= !Input
->Fake
;
1607 Reply
->Data
.ReadInputReply
.Input
= Input
->InputEvent
;
1609 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
1611 ConioInputEventToAnsi(Console
, &Reply
->Data
.ReadInputReply
.Input
);
1614 if (Input
->InputEvent
.EventType
== KEY_EVENT
)
1616 if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
)
1617 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
1618 && '\r' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1620 Console
->WaitingLines
--;
1622 Console
->WaitingChars
--;
1624 HeapFree(Win32CsrApiHeap
, 0, Input
);
1626 Reply
->Data
.ReadInputReply
.MoreEvents
= (Console
->InputEvents
.Flink
!= &Console
->InputEvents
);
1627 Status
= STATUS_SUCCESS
;
1628 Console
->EarlyReturn
= FALSE
; /* clear early return */
1633 Status
= STATUS_PENDING
;
1634 Console
->EarlyReturn
= TRUE
; /* mark for early return */
1637 ConioUnlockConsole(Console
);
1639 return Reply
->Status
= Status
;
1642 CSR_API(CsrWriteConsoleOutputAttrib
)
1644 PCSRSS_CONSOLE Console
;
1645 PCSRSS_SCREEN_BUFFER Buff
;
1646 PUCHAR Buffer
, Attribute
;
1651 DPRINT("CsrWriteConsoleOutputAttrib\n");
1653 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1654 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1656 if (Request
->Header
.DataSize
1657 < sizeof(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB_REQUEST
) - 1
1658 + Request
->Data
.WriteConsoleOutputAttribRequest
.Length
)
1660 DPRINT1("Invalid request size\n");
1661 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
1664 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1665 if (! NT_SUCCESS(Status
))
1667 return Reply
->Status
= Status
;
1670 Status
= ConioLockScreenBuffer(ProcessData
,
1671 Request
->Data
.WriteConsoleOutputAttribRequest
.ConsoleHandle
,
1673 if (! NT_SUCCESS(Status
))
1675 if (NULL
!= Console
)
1677 ConioUnlockConsole(Console
);
1679 return Reply
->Status
= Status
;
1682 X
= Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1683 Y
= (Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1684 Length
= Request
->Data
.WriteConsoleOutputAttribRequest
.Length
;
1685 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + 1];
1686 Attribute
= Request
->Data
.WriteConsoleOutputAttribRequest
.String
;
1689 *Buffer
= *Attribute
++;
1691 if (++X
== Buff
->MaxX
)
1693 if (++Y
== Buff
->MaxY
)
1696 Buffer
= Buff
->Buffer
+ 1;
1702 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1704 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
,
1705 Request
->Data
.WriteConsoleOutputAttribRequest
.Length
);
1706 ConioDrawRegion(Console
, &UpdateRect
);
1709 if (NULL
!= Console
)
1711 ConioUnlockConsole(Console
);
1714 Reply
->Data
.WriteConsoleOutputAttribReply
.EndCoord
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1715 Reply
->Data
.WriteConsoleOutputAttribReply
.EndCoord
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1717 ConioUnlockScreenBuffer(Buff
);
1719 return Reply
->Status
= STATUS_SUCCESS
;
1722 CSR_API(CsrFillOutputAttrib
)
1724 PCSRSS_SCREEN_BUFFER Buff
;
1730 PCSRSS_CONSOLE Console
;
1732 DPRINT("CsrFillOutputAttrib\n");
1734 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1735 if (! NT_SUCCESS(Status
))
1737 return Reply
->Status
= Status
;
1740 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1741 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1742 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputAttribRequest
.ConsoleHandle
, &Buff
);
1743 if (! NT_SUCCESS(Status
))
1745 if (NULL
!= Console
)
1747 ConioUnlockConsole(Console
);
1749 return Reply
->Status
= Status
;
1752 X
= Request
->Data
.FillOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1753 Y
= (Request
->Data
.FillOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1754 Length
= Request
->Data
.FillOutputAttribRequest
.Length
;
1755 Attr
= Request
->Data
.FillOutputAttribRequest
.Attribute
;
1756 Buffer
= &Buff
->Buffer
[(Y
* Buff
->MaxX
* 2) + (X
* 2) + 1];
1761 if (++X
== Buff
->MaxX
)
1763 if (++Y
== Buff
->MaxY
)
1766 Buffer
= Buff
->Buffer
+ 1;
1772 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1774 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputAttribRequest
.Coord
,
1775 Request
->Data
.FillOutputAttribRequest
.Length
);
1776 ConioDrawRegion(Console
, &UpdateRect
);
1779 ConioUnlockScreenBuffer(Buff
);
1780 if (NULL
!= Console
)
1782 ConioUnlockConsole(Console
);
1785 return Reply
->Status
= STATUS_SUCCESS
;
1789 CSR_API(CsrGetCursorInfo
)
1791 PCSRSS_SCREEN_BUFFER Buff
;
1794 DPRINT("CsrGetCursorInfo\n");
1796 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1797 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1799 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.GetCursorInfoRequest
.ConsoleHandle
, &Buff
);
1800 if (! NT_SUCCESS(Status
))
1802 return Reply
->Status
= Status
;
1804 Reply
->Data
.GetCursorInfoReply
.Info
= Buff
->CursorInfo
;
1805 ConioUnlockScreenBuffer(Buff
);
1807 return Reply
->Status
= STATUS_SUCCESS
;
1810 CSR_API(CsrSetCursorInfo
)
1812 PCSRSS_CONSOLE Console
;
1813 PCSRSS_SCREEN_BUFFER Buff
;
1818 DPRINT("CsrSetCursorInfo\n");
1820 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1821 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1823 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1824 if (! NT_SUCCESS(Status
))
1826 return Reply
->Status
= Status
;
1829 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorInfoRequest
.ConsoleHandle
, &Buff
);
1830 if (! NT_SUCCESS(Status
))
1832 if (NULL
!= Console
)
1834 ConioUnlockConsole(Console
);
1836 return Reply
->Status
= Status
;
1839 Size
= Request
->Data
.SetCursorInfoRequest
.Info
.dwSize
;
1840 Visible
= Request
->Data
.SetCursorInfoRequest
.Info
.bVisible
;
1850 if (Size
!= Buff
->CursorInfo
.dwSize
1851 || (Visible
&& ! Buff
->CursorInfo
.bVisible
) || (! Visible
&& Buff
->CursorInfo
.bVisible
))
1853 Buff
->CursorInfo
.dwSize
= Size
;
1854 Buff
->CursorInfo
.bVisible
= Visible
;
1856 if (NULL
!= Console
&& ! ConioSetCursorInfo(Console
, Buff
))
1858 ConioUnlockScreenBuffer(Buff
);
1859 ConioUnlockConsole(Console
);
1860 return Reply
->Status
= STATUS_UNSUCCESSFUL
;
1864 ConioUnlockScreenBuffer(Buff
);
1865 if (NULL
!= Console
)
1867 ConioUnlockConsole(Console
);
1870 return Reply
->Status
= STATUS_SUCCESS
;
1873 CSR_API(CsrSetTextAttrib
)
1876 PCSRSS_CONSOLE Console
;
1877 PCSRSS_SCREEN_BUFFER Buff
;
1878 LONG OldCursorX
, OldCursorY
;
1880 DPRINT("CsrSetTextAttrib\n");
1882 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1883 if (! NT_SUCCESS(Status
))
1885 return Reply
->Status
= Status
;
1888 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
);
1889 if (! NT_SUCCESS(Status
))
1891 if (NULL
!= Console
)
1893 ConioUnlockConsole(Console
);
1895 return Reply
->Status
= Status
;
1898 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &OldCursorX
, &OldCursorY
);
1900 Buff
->DefaultAttrib
= Request
->Data
.SetAttribRequest
.Attrib
;
1901 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1903 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
1905 ConioUnlockScreenBuffer(Buff
);
1906 ConioUnlockConsole(Console
);
1907 return Reply
->Status
= STATUS_UNSUCCESSFUL
;
1911 ConioUnlockScreenBuffer(Buff
);
1912 if (NULL
!= Console
)
1914 ConioUnlockConsole(Console
);
1917 return Reply
->Status
= STATUS_SUCCESS
;
1920 CSR_API(CsrSetConsoleMode
)
1923 PCSRSS_CONSOLE Console
;
1924 PCSRSS_SCREEN_BUFFER Buff
;
1926 DPRINT("CsrSetConsoleMode\n");
1928 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1929 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1930 Status
= Win32CsrGetObject(ProcessData
,
1931 Request
->Data
.SetConsoleModeRequest
.ConsoleHandle
,
1932 (Object_t
**) &Console
);
1933 if (! NT_SUCCESS(Status
))
1935 return Reply
->Status
= Status
;
1938 Buff
= (PCSRSS_SCREEN_BUFFER
)Console
;
1939 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
1941 Console
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_INPUT_MODE_VALID
;
1943 else if (CONIO_SCREEN_BUFFER_MAGIC
== Console
->Header
.Type
)
1945 Buff
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_OUTPUT_MODE_VALID
;
1949 return Reply
->Status
= STATUS_INVALID_HANDLE
;
1952 Reply
->Status
= STATUS_SUCCESS
;
1954 return Reply
->Status
;
1957 CSR_API(CsrGetConsoleMode
)
1960 PCSRSS_CONSOLE Console
;
1961 PCSRSS_SCREEN_BUFFER Buff
; /* gee, I really wish I could use an anonymous union here */
1963 DPRINT("CsrGetConsoleMode\n");
1965 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1966 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1967 Status
= Win32CsrGetObject(ProcessData
, Request
->Data
.GetConsoleModeRequest
.ConsoleHandle
,
1968 (Object_t
**) &Console
);
1969 if (! NT_SUCCESS(Status
))
1971 return Reply
->Status
= Status
;
1973 Reply
->Status
= STATUS_SUCCESS
;
1974 Buff
= (PCSRSS_SCREEN_BUFFER
) Console
;
1975 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
1977 Reply
->Data
.GetConsoleModeReply
.ConsoleMode
= Console
->Mode
;
1979 else if (CONIO_SCREEN_BUFFER_MAGIC
== Buff
->Header
.Type
)
1981 Reply
->Data
.GetConsoleModeReply
.ConsoleMode
= Buff
->Mode
;
1985 Reply
->Status
= STATUS_INVALID_HANDLE
;
1988 return Reply
->Status
;
1991 CSR_API(CsrCreateScreenBuffer
)
1993 PCSRSS_CONSOLE Console
;
1994 PCSRSS_SCREEN_BUFFER Buff
;
1997 DPRINT("CsrCreateScreenBuffer\n");
1999 if (ProcessData
== NULL
)
2001 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
2004 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2005 if (! NT_SUCCESS(Status
))
2007 return Reply
->Status
= Status
;
2009 if (NULL
== Console
)
2011 return Reply
->Status
= STATUS_INVALID_HANDLE
;
2014 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2015 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2017 Buff
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(CSRSS_SCREEN_BUFFER
));
2020 Reply
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2023 Status
= CsrInitConsoleScreenBuffer(Console
, Buff
);
2024 if(! NT_SUCCESS(Status
))
2026 Reply
->Status
= Status
;
2030 Reply
->Status
= Win32CsrInsertObject(ProcessData
, &Reply
->Data
.CreateScreenBufferReply
.OutputHandle
, &Buff
->Header
);
2033 ConioUnlockConsole(Console
);
2035 return Reply
->Status
;
2038 CSR_API(CsrSetScreenBuffer
)
2041 PCSRSS_CONSOLE Console
;
2042 PCSRSS_SCREEN_BUFFER Buff
;
2044 DPRINT("CsrSetScreenBuffer\n");
2046 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2047 if (! NT_SUCCESS(Status
))
2049 return Reply
->Status
= Status
;
2051 if (NULL
== Console
)
2053 DPRINT1("Trying to set screen buffer for app without console\n");
2054 return Reply
->Status
= STATUS_INVALID_HANDLE
;
2057 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2058 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2060 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetScreenBufferRequest
.OutputHandle
, &Buff
);
2061 if (! NT_SUCCESS(Status
))
2063 ConioUnlockConsole(Console
);
2064 return Reply
->Status
;
2067 if (Buff
== Console
->ActiveBuffer
)
2069 ConioUnlockScreenBuffer(Buff
);
2070 ConioUnlockConsole(Console
);
2071 return STATUS_SUCCESS
;
2074 /* drop reference to old buffer, maybe delete */
2075 if (! InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
2077 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
2079 /* tie console to new buffer */
2080 Console
->ActiveBuffer
= Buff
;
2081 /* inc ref count on new buffer */
2082 InterlockedIncrement(&Buff
->Header
.ReferenceCount
);
2083 /* Redraw the console */
2084 ConioDrawConsole(Console
);
2086 ConioUnlockScreenBuffer(Buff
);
2087 ConioUnlockConsole(Console
);
2089 return Reply
->Status
= STATUS_SUCCESS
;
2092 CSR_API(CsrSetTitle
)
2095 PCSRSS_CONSOLE Console
;
2097 DPRINT("CsrSetTitle\n");
2099 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2100 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2102 if (Request
->Header
.DataSize
2103 < sizeof(CSRSS_SET_TITLE_REQUEST
) - 1
2104 + Request
->Data
.SetTitleRequest
.Length
)
2106 DPRINT1("Invalid request size\n");
2107 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
2110 Status
= ConioLockConsole(ProcessData
, Request
->Data
.SetTitleRequest
.Console
, &Console
);
2111 if(! NT_SUCCESS(Status
))
2113 Reply
->Status
= Status
;
2117 /* copy title to console */
2118 RtlFreeUnicodeString(&Console
->Title
);
2119 RtlCreateUnicodeString(&Console
->Title
, Request
->Data
.SetTitleRequest
.Title
);
2120 if (! ConioChangeTitle(Console
))
2122 Reply
->Status
= STATUS_UNSUCCESSFUL
;
2126 Reply
->Status
= STATUS_SUCCESS
;
2129 ConioUnlockConsole(Console
);
2131 return Reply
->Status
;
2134 CSR_API(CsrGetTitle
)
2137 PCSRSS_CONSOLE Console
;
2139 DPRINT("CsrGetTitle\n");
2141 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2142 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2143 Status
= ConioLockConsole(ProcessData
,
2144 Request
->Data
.GetTitleRequest
.ConsoleHandle
,
2146 if (! NT_SUCCESS(Status
))
2148 DPRINT1("Can't get console\n");
2149 return Reply
->Status
= Status
;
2152 /* Copy title of the console to the user title buffer */
2153 RtlZeroMemory(&Reply
->Data
.GetTitleReply
, sizeof(CSRSS_GET_TITLE_REPLY
));
2154 Reply
->Data
.GetTitleReply
.ConsoleHandle
= Request
->Data
.GetTitleRequest
.ConsoleHandle
;
2155 Reply
->Data
.GetTitleReply
.Length
= Console
->Title
.Length
;
2156 wcscpy (Reply
->Data
.GetTitleReply
.Title
, Console
->Title
.Buffer
);
2157 Reply
->Header
.MessageSize
+= Console
->Title
.Length
;
2158 Reply
->Header
.DataSize
+= Console
->Title
.Length
;
2159 Reply
->Status
= STATUS_SUCCESS
;
2161 ConioUnlockConsole(Console
);
2163 return Reply
->Status
;
2166 CSR_API(CsrWriteConsoleOutput
)
2168 SHORT i
, X
, Y
, SizeX
, SizeY
;
2169 PCSRSS_CONSOLE Console
;
2170 PCSRSS_SCREEN_BUFFER Buff
;
2172 CHAR_INFO
* CurCharInfo
;
2174 CHAR_INFO
* CharInfo
;
2181 DPRINT("CsrWriteConsoleOutput\n");
2183 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2184 if (! NT_SUCCESS(Status
))
2186 return Reply
->Status
= Status
;
2189 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2190 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2191 Status
= ConioLockScreenBuffer(ProcessData
,
2192 Request
->Data
.WriteConsoleOutputRequest
.ConsoleHandle
,
2194 if (! NT_SUCCESS(Status
))
2196 if (NULL
!= Console
)
2198 ConioUnlockConsole(Console
);
2200 return Reply
->Status
= Status
;
2203 BufferSize
= Request
->Data
.WriteConsoleOutputRequest
.BufferSize
;
2204 PSize
= BufferSize
.X
* BufferSize
.Y
* sizeof(CHAR_INFO
);
2205 BufferCoord
= Request
->Data
.WriteConsoleOutputRequest
.BufferCoord
;
2206 CharInfo
= Request
->Data
.WriteConsoleOutputRequest
.CharInfo
;
2207 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
) ||
2208 (((PVOID
)CharInfo
+ PSize
) >
2209 (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2211 ConioUnlockScreenBuffer(Buff
);
2212 ConioUnlockConsole(Console
);
2213 return Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2215 WriteRegion
.left
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
;
2216 WriteRegion
.top
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
;
2217 WriteRegion
.right
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
;
2218 WriteRegion
.bottom
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
;
2220 SizeY
= RtlRosMin(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&WriteRegion
));
2221 SizeX
= RtlRosMin(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&WriteRegion
));
2222 WriteRegion
.bottom
= WriteRegion
.top
+ SizeY
- 1;
2223 WriteRegion
.right
= WriteRegion
.left
+ SizeX
- 1;
2225 /* Make sure WriteRegion is inside the screen buffer */
2226 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2227 if (! ConioGetIntersection(&WriteRegion
, &ScreenBuffer
, &WriteRegion
))
2229 ConioUnlockScreenBuffer(Buff
);
2230 ConioUnlockConsole(Console
);
2232 /* It is okay to have a WriteRegion completely outside the screen buffer.
2233 No data is written then. */
2234 return Reply
->Status
= STATUS_SUCCESS
;
2237 for (i
= 0, Y
= WriteRegion
.top
; Y
<= WriteRegion
.bottom
; i
++, Y
++)
2239 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
2240 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ WriteRegion
.left
) * 2;
2241 for (X
= WriteRegion
.left
; X
<= WriteRegion
.right
; X
++)
2243 if (Request
->Data
.WriteConsoleOutputRequest
.Unicode
)
2246 WideCharToMultiByte(Console
->OutputCodePage
, 0,
2247 &CurCharInfo
->Char
.UnicodeChar
, 1,
2248 &AsciiChar
, 1, NULL
, NULL
);
2249 SET_CELL_BUFFER(Buff
, Offset
, AsciiChar
, CurCharInfo
->Attributes
);
2253 SET_CELL_BUFFER(Buff
, Offset
, CurCharInfo
->Char
.AsciiChar
, CurCharInfo
->Attributes
);
2259 if (NULL
!= Console
)
2261 ConioDrawRegion(Console
, &WriteRegion
);
2264 ConioUnlockScreenBuffer(Buff
);
2265 ConioUnlockConsole(Console
);
2267 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Right
= WriteRegion
.left
+ SizeX
- 1;
2268 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Bottom
= WriteRegion
.top
+ SizeY
- 1;
2269 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Left
= WriteRegion
.left
;
2270 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Top
= WriteRegion
.top
;
2272 return Reply
->Status
= STATUS_SUCCESS
;
2275 CSR_API(CsrFlushInputBuffer
)
2277 PLIST_ENTRY CurrentEntry
;
2278 PCSRSS_CONSOLE Console
;
2279 ConsoleInput
* Input
;
2282 DPRINT("CsrFlushInputBuffer\n");
2284 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2285 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2286 Status
= ConioLockConsole(ProcessData
,
2287 Request
->Data
.FlushInputBufferRequest
.ConsoleInput
,
2289 if(! NT_SUCCESS(Status
))
2291 return Reply
->Status
= Status
;
2294 /* Discard all entries in the input event queue */
2295 while (!IsListEmpty(&Console
->InputEvents
))
2297 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
2298 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
2299 /* Destroy the event */
2300 HeapFree(Win32CsrApiHeap
, 0, Input
);
2302 Console
->WaitingChars
=0;
2304 ConioUnlockConsole(Console
);
2306 return Reply
->Status
= STATUS_SUCCESS
;
2309 CSR_API(CsrScrollConsoleScreenBuffer
)
2311 PCSRSS_CONSOLE Console
;
2312 PCSRSS_SCREEN_BUFFER Buff
;
2317 RECT ScrollRectangle
;
2322 DPRINT("CsrScrollConsoleScreenBuffer\n");
2324 ALIAS(ConsoleHandle
,Request
->Data
.ScrollConsoleScreenBufferRequest
.ConsoleHandle
);
2325 ALIAS(UseClipRectangle
,Request
->Data
.ScrollConsoleScreenBufferRequest
.UseClipRectangle
);
2326 ALIAS(DestinationOrigin
,Request
->Data
.ScrollConsoleScreenBufferRequest
.DestinationOrigin
);
2327 ALIAS(Fill
,Request
->Data
.ScrollConsoleScreenBufferRequest
.Fill
);
2329 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2330 if (! NT_SUCCESS(Status
))
2332 return Reply
->Status
= Status
;
2335 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2336 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2337 Status
= ConioLockScreenBuffer(ProcessData
, ConsoleHandle
, &Buff
);
2338 if (! NT_SUCCESS(Status
))
2340 if (NULL
!= Console
)
2342 ConioUnlockConsole(Console
);
2344 return Reply
->Status
= Status
;
2347 ScrollRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Left
;
2348 ScrollRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Top
;
2349 ScrollRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Right
;
2350 ScrollRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Bottom
;
2351 ClipRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Left
;
2352 ClipRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Top
;
2353 ClipRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Right
;
2354 ClipRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Bottom
;
2356 /* Make sure source rectangle is inside the screen buffer */
2357 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2358 if (! ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, &ScrollRectangle
))
2360 ConioUnlockScreenBuffer(Buff
);
2361 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
2364 if (UseClipRectangle
&& ! ConioGetIntersection(&SrcRegion
, &SrcRegion
, &ClipRectangle
))
2366 ConioUnlockScreenBuffer(Buff
);
2367 return Reply
->Status
= STATUS_SUCCESS
;
2371 ConioInitRect(&DstRegion
,
2372 DestinationOrigin
.Y
,
2373 DestinationOrigin
.X
,
2374 DestinationOrigin
.Y
+ ConioRectHeight(&ScrollRectangle
) - 1,
2375 DestinationOrigin
.X
+ ConioRectWidth(&ScrollRectangle
) - 1);
2377 /* Make sure destination rectangle is inside the screen buffer */
2378 if (! ConioGetIntersection(&DstRegion
, &DstRegion
, &ScreenBuffer
))
2380 ConioUnlockScreenBuffer(Buff
);
2381 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
2384 ConioCopyRegion(Buff
, &SrcRegion
, &DstRegion
);
2386 /* Get the region that should be filled with the specified character and attributes */
2390 ConioGetUnion(&FillRegion
, &SrcRegion
, &DstRegion
);
2392 if (ConioSubtractRect(&FillRegion
, &FillRegion
, &DstRegion
))
2394 /* FIXME: The subtracted rectangle is off by one line */
2395 FillRegion
.top
+= 1;
2397 ConioFillRegion(Buff
, &FillRegion
, Fill
);
2401 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
2403 /* Draw destination region */
2404 ConioDrawRegion(Console
, &DstRegion
);
2408 /* Draw filled region */
2409 ConioDrawRegion(Console
, &FillRegion
);
2413 ConioUnlockScreenBuffer(Buff
);
2414 if (NULL
!= Console
)
2416 ConioUnlockConsole(Console
);
2419 return Reply
->Status
= STATUS_SUCCESS
;
2422 CSR_API(CsrReadConsoleOutputChar
)
2425 PCSRSS_SCREEN_BUFFER Buff
;
2430 DPRINT("CsrReadConsoleOutputChar\n");
2432 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2433 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
2434 ReadBuffer
= Reply
->Data
.ReadConsoleOutputCharReply
.String
;
2436 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputCharRequest
.ConsoleHandle
, &Buff
);
2437 if (! NT_SUCCESS(Status
))
2439 return Reply
->Status
= Status
;
2442 Xpos
= Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.X
+ Buff
->ShowX
;
2443 Ypos
= (Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
2445 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
; ++i
)
2447 *ReadBuffer
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
)];
2452 if (Xpos
== Buff
->MaxX
)
2457 if (Ypos
== Buff
->MaxY
)
2465 Reply
->Status
= STATUS_SUCCESS
;
2466 Reply
->Data
.ReadConsoleOutputCharReply
.EndCoord
.X
= Xpos
- Buff
->ShowX
;
2467 Reply
->Data
.ReadConsoleOutputCharReply
.EndCoord
.Y
= (Ypos
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
;
2468 Reply
->Header
.MessageSize
+= Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
;
2469 Reply
->Header
.DataSize
+= Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
;
2471 ConioUnlockScreenBuffer(Buff
);
2473 return Reply
->Status
;
2477 CSR_API(CsrReadConsoleOutputAttrib
)
2480 PCSRSS_SCREEN_BUFFER Buff
;
2485 DPRINT("CsrReadConsoleOutputAttrib\n");
2487 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2488 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
2489 ReadBuffer
= Reply
->Data
.ReadConsoleOutputAttribReply
.String
;
2491 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputAttribRequest
.ConsoleHandle
, &Buff
);
2492 if (! NT_SUCCESS(Status
))
2494 return Reply
->Status
= Status
;
2497 Xpos
= Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.X
+ Buff
->ShowX
;
2498 Ypos
= (Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
2500 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
; ++i
)
2502 *ReadBuffer
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
) + 1];
2507 if (Xpos
== Buff
->MaxX
)
2512 if (Ypos
== Buff
->MaxY
)
2521 Reply
->Status
= STATUS_SUCCESS
;
2522 Reply
->Data
.ReadConsoleOutputAttribReply
.EndCoord
.X
= Xpos
- Buff
->ShowX
;
2523 Reply
->Data
.ReadConsoleOutputAttribReply
.EndCoord
.Y
= (Ypos
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
;
2524 Reply
->Header
.MessageSize
+= Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
;
2525 Reply
->Header
.DataSize
+= Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
;
2527 ConioUnlockScreenBuffer(Buff
);
2529 return Reply
->Status
;
2533 CSR_API(CsrGetNumberOfConsoleInputEvents
)
2536 PCSRSS_CONSOLE Console
;
2537 PLIST_ENTRY CurrentItem
;
2539 ConsoleInput
*Input
;
2541 DPRINT("CsrGetNumberOfConsoleInputEvents\n");
2543 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2544 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
2546 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
);
2547 if (! NT_SUCCESS(Status
))
2549 return Reply
->Status
= Status
;
2552 CurrentItem
= Console
->InputEvents
.Flink
;
2555 /* If there are any events ... */
2556 while (CurrentItem
!= &Console
->InputEvents
)
2558 Input
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2559 CurrentItem
= CurrentItem
->Flink
;
2566 ConioUnlockConsole(Console
);
2568 Reply
->Status
= STATUS_SUCCESS
;
2569 Reply
->Data
.GetNumInputEventsReply
.NumInputEvents
= NumEvents
;
2571 return Reply
->Status
;
2575 CSR_API(CsrPeekConsoleInput
)
2578 PCSRSS_CONSOLE Console
;
2581 PLIST_ENTRY CurrentItem
;
2582 PINPUT_RECORD InputRecord
;
2586 DPRINT("CsrPeekConsoleInput\n");
2588 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2589 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2591 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
);
2592 if(! NT_SUCCESS(Status
))
2594 return Reply
->Status
= Status
;
2597 InputRecord
= Request
->Data
.PeekConsoleInputRequest
.InputRecord
;
2598 Length
= Request
->Data
.PeekConsoleInputRequest
.Length
;
2599 Size
= Length
* sizeof(INPUT_RECORD
);
2601 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2602 || (((PVOID
)InputRecord
+ Size
) > (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2604 ConioUnlockConsole(Console
);
2605 Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2606 return Reply
->Status
;
2611 if (! IsListEmpty(&Console
->InputEvents
))
2613 CurrentItem
= Console
->InputEvents
.Flink
;
2615 while (CurrentItem
!= &Console
->InputEvents
&& NumItems
< Length
)
2617 Item
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2621 CurrentItem
= CurrentItem
->Flink
;
2626 *InputRecord
= Item
->InputEvent
;
2628 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
2630 ConioInputEventToAnsi(Console
, InputRecord
);
2634 CurrentItem
= CurrentItem
->Flink
;
2638 ConioUnlockConsole(Console
);
2640 Reply
->Status
= STATUS_SUCCESS
;
2641 Reply
->Data
.PeekConsoleInputReply
.Length
= NumItems
;
2643 return Reply
->Status
;
2647 CSR_API(CsrReadConsoleOutput
)
2649 PCHAR_INFO CharInfo
;
2650 PCHAR_INFO CurCharInfo
;
2651 PCSRSS_SCREEN_BUFFER Buff
;
2660 DWORD i
, Y
, X
, Offset
;
2663 DPRINT("CsrReadConsoleOutput\n");
2665 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2666 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2668 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputRequest
.ConsoleHandle
, &Buff
);
2669 if (! NT_SUCCESS(Status
))
2671 return Reply
->Status
= Status
;
2674 CharInfo
= Request
->Data
.ReadConsoleOutputRequest
.CharInfo
;
2675 ReadRegion
.left
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
;
2676 ReadRegion
.top
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
;
2677 ReadRegion
.right
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
;
2678 ReadRegion
.bottom
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
;
2679 BufferSize
= Request
->Data
.ReadConsoleOutputRequest
.BufferSize
;
2680 BufferCoord
= Request
->Data
.ReadConsoleOutputRequest
.BufferCoord
;
2681 Length
= BufferSize
.X
* BufferSize
.Y
;
2682 Size
= Length
* sizeof(CHAR_INFO
);
2684 /* FIXME: Is this correct? */
2685 CodePage
= ProcessData
->Console
->OutputCodePage
;
2687 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
)
2688 || (((PVOID
)CharInfo
+ Size
) > (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2690 ConioUnlockScreenBuffer(Buff
);
2691 Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2692 return Reply
->Status
;
2695 SizeY
= RtlRosMin(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&ReadRegion
));
2696 SizeX
= RtlRosMin(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&ReadRegion
));
2697 ReadRegion
.bottom
= ReadRegion
.top
+ SizeY
;
2698 ReadRegion
.right
= ReadRegion
.left
+ SizeX
;
2700 ConioInitRect(&ScreenRect
, 0, 0, Buff
->MaxY
, Buff
->MaxX
);
2701 if (! ConioGetIntersection(&ReadRegion
, &ScreenRect
, &ReadRegion
))
2703 ConioUnlockScreenBuffer(Buff
);
2704 Reply
->Status
= STATUS_SUCCESS
;
2705 return Reply
->Status
;
2708 for (i
= 0, Y
= ReadRegion
.top
; Y
< ReadRegion
.bottom
; ++i
, ++Y
)
2710 CurCharInfo
= CharInfo
+ (i
* BufferSize
.X
);
2712 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ ReadRegion
.left
) * 2;
2713 for (X
= ReadRegion
.left
; X
< ReadRegion
.right
; ++X
)
2715 if (Request
->Data
.ReadConsoleOutputRequest
.Unicode
)
2717 MultiByteToWideChar(CodePage
, 0,
2718 &GET_CELL_BUFFER(Buff
, Offset
), 1,
2719 &CurCharInfo
->Char
.UnicodeChar
, 1);
2723 CurCharInfo
->Char
.AsciiChar
= GET_CELL_BUFFER(Buff
, Offset
);
2725 CurCharInfo
->Attributes
= GET_CELL_BUFFER(Buff
, Offset
);
2730 ConioUnlockScreenBuffer(Buff
);
2732 Reply
->Status
= STATUS_SUCCESS
;
2733 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Right
= ReadRegion
.left
+ SizeX
- 1;
2734 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Bottom
= ReadRegion
.top
+ SizeY
- 1;
2735 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Left
= ReadRegion
.left
;
2736 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Top
= ReadRegion
.top
;
2738 return Reply
->Status
;
2742 CSR_API(CsrWriteConsoleInput
)
2744 PINPUT_RECORD InputRecord
;
2745 PCSRSS_CONSOLE Console
;
2750 ConsoleInput
* Record
;
2752 DPRINT("CsrWriteConsoleInput\n");
2754 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2755 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2757 Status
= ConioLockConsole(ProcessData
, Request
->Data
.WriteConsoleInputRequest
.ConsoleHandle
, &Console
);
2758 if (! NT_SUCCESS(Status
))
2760 return Reply
->Status
= Status
;
2763 InputRecord
= Request
->Data
.WriteConsoleInputRequest
.InputRecord
;
2764 Length
= Request
->Data
.WriteConsoleInputRequest
.Length
;
2765 Size
= Length
* sizeof(INPUT_RECORD
);
2767 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2768 || (((PVOID
)InputRecord
+ Size
) > (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2770 ConioUnlockConsole(Console
);
2771 Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2772 return Reply
->Status
;
2775 for (i
= 0; i
< Length
; i
++)
2777 Record
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
2780 ConioUnlockConsole(Console
);
2781 Reply
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2782 return Reply
->Status
;
2785 Record
->Echoed
= FALSE
;
2786 Record
->Fake
= FALSE
;
2787 Record
->InputEvent
= *InputRecord
++;
2788 if (KEY_EVENT
== Record
->InputEvent
.EventType
)
2790 ConioProcessChar(Console
, Record
);
2794 ConioUnlockConsole(Console
);
2796 Reply
->Status
= STATUS_SUCCESS
;
2797 Reply
->Data
.WriteConsoleInputReply
.Length
= i
;
2799 return Reply
->Status
;
2802 /**********************************************************************
2803 * HardwareStateProperty
2806 * Set/Get the value of the HardwareState and switch
2807 * between direct video buffer ouput and GDI windowed
2810 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
2811 * object. We use the same object to reply.
2813 * ConsoleHwState has the correct size to be compatible
2814 * with NT's, but values are not.
2816 STATIC NTSTATUS FASTCALL
2817 SetConsoleHardwareState (PCSRSS_CONSOLE Console
, DWORD ConsoleHwState
)
2819 DPRINT1("Console Hardware State: %d\n", ConsoleHwState
);
2821 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED
== ConsoleHwState
)
2822 ||(CONSOLE_HARDWARE_STATE_DIRECT
== ConsoleHwState
))
2824 if (Console
->HardwareState
!= ConsoleHwState
)
2826 /* TODO: implement switching from full screen to windowed mode */
2827 /* TODO: or back; now simply store the hardware state */
2828 Console
->HardwareState
= ConsoleHwState
;
2831 return STATUS_SUCCESS
;
2834 return STATUS_INVALID_PARAMETER_3
; /* Client: (handle, set_get, [mode]) */
2837 CSR_API(CsrHardwareStateProperty
)
2839 PCSRSS_CONSOLE Console
;
2842 DPRINT("CsrHardwareStateProperty\n");
2844 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2845 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2847 Status
= ConioLockConsole(ProcessData
,
2848 Request
->Data
.ConsoleHardwareStateRequest
.ConsoleHandle
,
2850 if (! NT_SUCCESS(Status
))
2852 DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
2853 return Reply
->Status
= Status
;
2856 switch (Request
->Data
.ConsoleHardwareStateRequest
.SetGet
)
2858 case CONSOLE_HARDWARE_STATE_GET
:
2859 Reply
->Data
.ConsoleHardwareStateReply
.State
= Console
->HardwareState
;
2862 case CONSOLE_HARDWARE_STATE_SET
:
2863 DPRINT("Setting console hardware state.\n");
2864 Reply
->Status
= SetConsoleHardwareState(Console
, Request
->Data
.ConsoleHardwareStateRequest
.State
);
2868 Reply
->Status
= STATUS_INVALID_PARAMETER_2
; /* Client: (handle, [set_get], mode) */
2872 ConioUnlockConsole(Console
);
2874 return Reply
->Status
;
2877 CSR_API(CsrGetConsoleWindow
)
2879 PCSRSS_CONSOLE Console
;
2882 DPRINT("CsrGetConsoleWindow\n");
2884 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2885 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2887 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2888 if (! NT_SUCCESS(Status
))
2890 return Reply
->Status
= Status
;
2893 Reply
->Data
.GetConsoleWindowReply
.WindowHandle
= Console
->hWindow
;
2894 ConioUnlockConsole(Console
);
2896 return Reply
->Status
= STATUS_SUCCESS
;
2899 CSR_API(CsrSetConsoleIcon
)
2901 PCSRSS_CONSOLE Console
;
2904 DPRINT("CsrSetConsoleIcon\n");
2906 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2907 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2909 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2910 if (! NT_SUCCESS(Status
))
2912 return Reply
->Status
= Status
;
2915 Console
->hWindowIcon
= Request
->Data
.SetConsoleIconRequest
.WindowIcon
;
2916 Reply
->Status
= (ConioChangeIcon(Console
) ? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
2917 ConioUnlockConsole(Console
);
2919 return Reply
->Status
;
2922 CSR_API(CsrGetConsoleCodePage
)
2924 PCSRSS_CONSOLE Console
;
2927 DPRINT("CsrGetConsoleCodePage\n");
2929 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2930 if (! NT_SUCCESS(Status
))
2932 return Reply
->Status
= Status
;
2935 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2936 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2937 Reply
->Data
.GetConsoleCodePage
.CodePage
= Console
->CodePage
;
2938 ConioUnlockConsole(Console
);
2939 return Reply
->Status
= STATUS_SUCCESS
;
2942 CSR_API(CsrSetConsoleCodePage
)
2944 PCSRSS_CONSOLE Console
;
2947 DPRINT("CsrSetConsoleCodePage\n");
2949 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2950 if (! NT_SUCCESS(Status
))
2952 return Reply
->Status
= Status
;
2955 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2956 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2957 if (IsValidCodePage(Request
->Data
.SetConsoleCodePage
.CodePage
))
2959 Console
->CodePage
= Request
->Data
.SetConsoleCodePage
.CodePage
;
2960 ConioUnlockConsole(Console
);
2961 return Reply
->Status
= STATUS_SUCCESS
;
2963 ConioUnlockConsole(Console
);
2964 return Reply
->Status
= STATUS_UNSUCCESSFUL
;
2967 CSR_API(CsrGetConsoleOutputCodePage
)
2969 PCSRSS_CONSOLE Console
;
2972 DPRINT("CsrGetConsoleOutputCodePage\n");
2974 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2975 if (! NT_SUCCESS(Status
))
2977 return Reply
->Status
= Status
;
2980 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2981 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2982 Reply
->Data
.GetConsoleOutputCodePage
.CodePage
= Console
->OutputCodePage
;
2983 ConioUnlockConsole(Console
);
2984 return Reply
->Status
= STATUS_SUCCESS
;
2987 CSR_API(CsrSetConsoleOutputCodePage
)
2989 PCSRSS_CONSOLE Console
;
2992 DPRINT("CsrSetConsoleOutputCodePage\n");
2994 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2995 if (! NT_SUCCESS(Status
))
2997 return Reply
->Status
= Status
;
3000 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3001 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3002 if (IsValidCodePage(Request
->Data
.SetConsoleOutputCodePage
.CodePage
))
3004 Console
->OutputCodePage
= Request
->Data
.SetConsoleOutputCodePage
.CodePage
;
3005 ConioUnlockConsole(Console
);
3006 return Reply
->Status
= STATUS_SUCCESS
;
3008 ConioUnlockConsole(Console
);
3009 return Reply
->Status
= STATUS_UNSUCCESSFUL
;