2 * reactos/subsys/csrss/win32csr/conio.c
4 * Console I/O functions
6 * ReactOS Operating System
9 /* INCLUDES ******************************************************************/
14 #include <csrss/csrss.h>
15 #include <ntdll/rtl.h>
16 #include <ntdll/ldr.h>
17 #include <ddk/ntddblue.h>
18 #include <rosrtl/string.h>
19 #include <rosrtl/minmax.h>
22 #include "desktopbg.h"
23 #include "guiconsole.h"
24 #include "tuiconsole.h"
30 /* FIXME: Is there a way to create real aliasses with gcc? [CSH] */
31 #define ALIAS(Name, Target) typeof(Target) Name = Target
33 /* Private user32 routines for CSRSS, not defined in any header file */
34 extern VOID STDCALL
PrivateCsrssRegisterPrimitive(VOID
);
35 extern VOID STDCALL
PrivateCsrssAcquireOrReleaseInputOwnership(BOOL Release
);
37 /* GLOBALS *******************************************************************/
39 #define ConioInitRect(Rect, Top, Left, Bottom, Right) \
40 ((Rect)->top) = Top; \
41 ((Rect)->left) = Left; \
42 ((Rect)->bottom) = Bottom; \
43 ((Rect)->right) = Right
45 #define ConioIsRectEmpty(Rect) \
46 (((Rect)->left > (Rect)->right) || ((Rect)->top > (Rect)->bottom))
48 #define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
49 WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
51 #define ConsoleAnsiCharToUnicodeChar(Console, sWChar, dChar) \
52 MultiByteToWideChar((Console)->CodePage, 0, (dChar), 1, (sWChar), 1)
54 #define ConsoleUnicodeToAnsiN(Console, dChar, sWChar, nChars) \
55 WideCharToMultiByte((Console)->CodePage, 0, (sWChar), (nChars), (dChar), (nChars) * sizeof(WCHAR), NULL, NULL)
57 /* FUNCTIONS *****************************************************************/
59 STATIC NTSTATUS FASTCALL
60 ConioConsoleFromProcessData(PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_CONSOLE
*Console
)
62 if (NULL
== ProcessData
->Console
)
65 return STATUS_SUCCESS
;
68 EnterCriticalSection(&(ProcessData
->Console
->Header
.Lock
));
69 *Console
= ProcessData
->Console
;
71 return STATUS_SUCCESS
;
75 ConioConsoleCtrlEvent(DWORD Event
, PCSRSS_PROCESS_DATA ProcessData
)
77 HANDLE Process
, Thread
;
79 DPRINT("ConioConsoleCtrlEvent Parent ProcessId = %x\n", ProcessData
->ProcessId
);
81 if (ProcessData
->CtrlDispatcher
)
83 Process
= OpenProcess(PROCESS_DUP_HANDLE
, FALSE
, ProcessData
->ProcessId
);
86 DPRINT1("Failed for handle duplication\n");
90 DPRINT("ConioConsoleCtrlEvent Process Handle = %x\n", Process
);
92 Thread
= CreateRemoteThread(Process
, NULL
, 0,
93 (LPTHREAD_START_ROUTINE
) ProcessData
->CtrlDispatcher
,
94 (PVOID
) Event
, 0, NULL
);
97 DPRINT1("Failed thread creation\n");
102 CloseHandle(Process
);
106 #define GET_CELL_BUFFER(b,o)\
109 #define SET_CELL_BUFFER(b,o,c,a)\
110 (b)->Buffer[(o)++]=(c),\
111 (b)->Buffer[(o)++]=(a)
114 ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff
)
116 DWORD Offset
= 2 * (Buff
->CurrentY
* Buff
->MaxX
);
119 for (Pos
= 0; Pos
< Buff
->MaxX
; Pos
++)
121 /* Fill the cell: Offset is incremented by the macro */
122 SET_CELL_BUFFER(Buff
, Offset
, ' ', Buff
->DefaultAttrib
);
126 STATIC NTSTATUS FASTCALL
127 CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console
,
128 PCSRSS_SCREEN_BUFFER Buffer
)
130 Buffer
->Header
.Type
= CONIO_SCREEN_BUFFER_MAGIC
;
131 Buffer
->Header
.ReferenceCount
= 0;
132 Buffer
->MaxX
= Console
->Size
.X
;
133 Buffer
->MaxY
= Console
->Size
.Y
;
136 Buffer
->Buffer
= HeapAlloc(Win32CsrApiHeap
, 0, Buffer
->MaxX
* Buffer
->MaxY
* 2);
137 if (NULL
== Buffer
->Buffer
)
139 return STATUS_INSUFFICIENT_RESOURCES
;
141 InitializeCriticalSection(&Buffer
->Header
.Lock
);
142 ConioInitScreenBuffer(Console
, Buffer
);
143 /* initialize buffer to be empty with default attributes */
144 for (Buffer
->CurrentY
= 0 ; Buffer
->CurrentY
< Buffer
->MaxY
; Buffer
->CurrentY
++)
146 ClearLineBuffer(Buffer
);
148 Buffer
->CursorInfo
.bVisible
= TRUE
;
149 Buffer
->CursorInfo
.dwSize
= 5;
150 Buffer
->Mode
= ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
;
151 Buffer
->CurrentX
= 0;
152 Buffer
->CurrentY
= 0;
154 return STATUS_SUCCESS
;
157 STATIC NTSTATUS STDCALL
158 CsrInitConsole(PCSRSS_CONSOLE Console
)
161 SECURITY_ATTRIBUTES SecurityAttributes
;
162 PCSRSS_SCREEN_BUFFER NewBuffer
;
165 Console
->Title
.MaximumLength
= Console
->Title
.Length
= 0;
166 Console
->Title
.Buffer
= NULL
;
168 RtlCreateUnicodeString(&Console
->Title
, L
"Command Prompt");
170 Console
->Header
.ReferenceCount
= 0;
171 Console
->WaitingChars
= 0;
172 Console
->WaitingLines
= 0;
173 Console
->EchoCount
= 0;
174 Console
->Header
.Type
= CONIO_CONSOLE_MAGIC
;
175 Console
->Mode
= ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_PROCESSED_INPUT
| ENABLE_MOUSE_INPUT
;
176 Console
->EarlyReturn
= FALSE
;
177 Console
->ActiveBuffer
= NULL
;
178 InitializeListHead(&Console
->InputEvents
);
179 InitializeListHead(&Console
->ProcessList
);
181 Console
->CodePage
= GetOEMCP();
182 Console
->OutputCodePage
= GetOEMCP();
184 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
185 SecurityAttributes
.lpSecurityDescriptor
= NULL
;
186 SecurityAttributes
.bInheritHandle
= TRUE
;
188 Console
->ActiveEvent
= CreateEventW(&SecurityAttributes
, TRUE
, FALSE
, NULL
);
189 if (NULL
== Console
->ActiveEvent
)
191 RtlFreeUnicodeString(&Console
->Title
);
192 return STATUS_UNSUCCESSFUL
;
194 Console
->PrivateData
= NULL
;
195 InitializeCriticalSection(&Console
->Header
.Lock
);
196 GuiMode
= DtbgIsDesktopVisible();
199 Status
= TuiInitConsole(Console
);
200 if (! NT_SUCCESS(Status
))
202 DPRINT1("Failed to open text-mode console, switching to gui-mode\n");
208 Status
= GuiInitConsole(Console
);
209 if (! NT_SUCCESS(Status
))
211 RtlFreeUnicodeString(&Console
->Title
);
212 DeleteCriticalSection(&Console
->Header
.Lock
);
213 CloseHandle(Console
->ActiveEvent
);
218 NewBuffer
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(CSRSS_SCREEN_BUFFER
));
219 if (NULL
== NewBuffer
)
221 ConioCleanupConsole(Console
);
222 RtlFreeUnicodeString(&Console
->Title
);
223 DeleteCriticalSection(&Console
->Header
.Lock
);
224 CloseHandle(Console
->ActiveEvent
);
225 return STATUS_INSUFFICIENT_RESOURCES
;
227 Status
= CsrInitConsoleScreenBuffer(Console
, NewBuffer
);
228 if (! NT_SUCCESS(Status
))
230 ConioCleanupConsole(Console
);
231 RtlFreeUnicodeString(&Console
->Title
);
232 DeleteCriticalSection(&Console
->Header
.Lock
);
233 CloseHandle(Console
->ActiveEvent
);
234 HeapFree(Win32CsrApiHeap
, 0, NewBuffer
);
237 Console
->ActiveBuffer
= NewBuffer
;
238 /* add a reference count because the buffer is tied to the console */
239 Console
->ActiveBuffer
->Header
.ReferenceCount
++;
240 /* make console active, and insert into console list */
241 /* copy buffer contents to screen */
242 ConioDrawConsole(Console
);
244 return STATUS_SUCCESS
;
248 CSR_API(CsrAllocConsole
)
250 PCSRSS_CONSOLE Console
;
254 DPRINT("CsrAllocConsole\n");
256 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
257 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
259 if (ProcessData
== NULL
)
261 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
264 if (ProcessData
->Console
)
266 Reply
->Status
= STATUS_INVALID_PARAMETER
;
267 return STATUS_INVALID_PARAMETER
;
270 Reply
->Status
= STATUS_SUCCESS
;
271 Console
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(CSRSS_CONSOLE
));
274 Reply
->Status
= STATUS_NO_MEMORY
;
275 return STATUS_NO_MEMORY
;
277 Reply
->Status
= CsrInitConsole(Console
);
278 if (! NT_SUCCESS(Reply
->Status
))
280 HeapFree(Win32CsrApiHeap
, 0, Console
);
281 return Reply
->Status
;
283 ProcessData
->Console
= Console
;
284 Reply
->Data
.AllocConsoleReply
.Console
= Console
;
286 /* add a reference count because the process is tied to the console */
287 Console
->Header
.ReferenceCount
++;
288 Status
= Win32CsrInsertObject(ProcessData
, &Reply
->Data
.AllocConsoleReply
.InputHandle
, &Console
->Header
);
289 if (! NT_SUCCESS(Status
))
291 ConioDeleteConsole((Object_t
*) Console
);
292 ProcessData
->Console
= 0;
293 return Reply
->Status
= Status
;
295 Status
= Win32CsrInsertObject(ProcessData
, &Reply
->Data
.AllocConsoleReply
.OutputHandle
, &Console
->ActiveBuffer
->Header
);
296 if (!NT_SUCCESS(Status
))
298 Console
->Header
.ReferenceCount
--;
299 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.InputHandle
);
300 ProcessData
->Console
= 0;
301 return Reply
->Status
= Status
;
304 Process
= OpenProcess(PROCESS_DUP_HANDLE
, FALSE
, ProcessData
->ProcessId
);
307 DPRINT1("OpenProcess() failed for handle duplication\n");
308 Console
->Header
.ReferenceCount
--;
309 ProcessData
->Console
= 0;
310 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.OutputHandle
);
311 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.InputHandle
);
312 Reply
->Status
= Status
;
315 if (! DuplicateHandle(GetCurrentProcess(), ProcessData
->Console
->ActiveEvent
,
316 Process
, &ProcessData
->ConsoleEvent
, EVENT_ALL_ACCESS
, FALSE
, 0))
318 DPRINT1("DuplicateHandle() failed: %d\n", GetLastError
);
319 CloseHandle(Process
);
320 Console
->Header
.ReferenceCount
--;
321 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.OutputHandle
);
322 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.InputHandle
);
323 ProcessData
->Console
= 0;
324 Reply
->Status
= Status
;
327 CloseHandle(Process
);
328 ProcessData
->CtrlDispatcher
= Request
->Data
.AllocConsoleRequest
.CtrlDispatcher
;
329 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
330 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ProcessEntry
);
332 return STATUS_SUCCESS
;
335 CSR_API(CsrFreeConsole
)
337 PCSRSS_CONSOLE Console
;
339 DPRINT("CsrFreeConsole\n");
341 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
342 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
344 if (ProcessData
== NULL
|| ProcessData
->Console
== NULL
)
346 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
349 Console
= ProcessData
->Console
;
350 Console
->Header
.ReferenceCount
--;
351 ProcessData
->Console
= NULL
;
352 if (0 == Console
->Header
.ReferenceCount
)
354 ConioDeleteConsole((Object_t
*) Console
);
357 return STATUS_SUCCESS
;
361 ConioNextLine(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, UINT
*ScrolledLines
)
363 /* slide the viewable screen */
364 if (((Buff
->CurrentY
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
) == Buff
->MaxY
- 1)
366 if (++Buff
->ShowY
== Buff
->MaxY
)
372 if (++Buff
->CurrentY
== Buff
->MaxY
)
376 ClearLineBuffer(Buff
);
377 UpdateRect
->left
= 0;
378 UpdateRect
->right
= Buff
->MaxX
- 1;
379 if (UpdateRect
->top
== Buff
->CurrentY
)
381 if (++UpdateRect
->top
== Buff
->MaxY
)
386 UpdateRect
->bottom
= Buff
->CurrentY
;
389 STATIC NTSTATUS FASTCALL
390 ConioWriteConsole(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
,
391 CHAR
*Buffer
, DWORD Length
, BOOL Attrib
)
396 LONG CursorStartX
, CursorStartY
;
399 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &CursorStartX
, &CursorStartY
);
400 UpdateRect
.left
= Buff
->MaxX
;
401 UpdateRect
.top
= Buff
->CurrentY
;
402 UpdateRect
.right
= -1;
403 UpdateRect
.bottom
= Buff
->CurrentY
;
406 for (i
= 0; i
< Length
; i
++)
408 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
411 if (Buffer
[i
] == '\n')
414 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
418 else if (Buffer
[i
] == '\b')
420 /* Only handle BS if we're not on the first pos of the first line */
421 if (0 != Buff
->CurrentX
|| Buff
->ShowY
!= Buff
->CurrentY
)
423 if (0 == Buff
->CurrentX
)
425 /* slide virtual position up */
426 Buff
->CurrentX
= Buff
->MaxX
- 1;
427 if (0 == Buff
->CurrentY
)
429 Buff
->CurrentY
= Buff
->MaxY
;
435 if ((0 == UpdateRect
.top
&& UpdateRect
.bottom
< Buff
->CurrentY
)
436 || (0 != UpdateRect
.top
&& Buff
->CurrentY
< UpdateRect
.top
))
438 UpdateRect
.top
= Buff
->CurrentY
;
445 Offset
= 2 * ((Buff
->CurrentY
* Buff
->MaxX
) + Buff
->CurrentX
);
446 SET_CELL_BUFFER(Buff
, Offset
, ' ', Buff
->DefaultAttrib
);
447 UpdateRect
.left
= RtlRosMin(UpdateRect
.left
, Buff
->CurrentX
);
448 UpdateRect
.right
= RtlRosMax(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
453 else if (Buffer
[i
] == '\r')
456 UpdateRect
.left
= RtlRosMin(UpdateRect
.left
, Buff
->CurrentX
);
457 UpdateRect
.right
= RtlRosMax(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
461 else if (Buffer
[i
] == '\t')
465 UpdateRect
.left
= RtlRosMin(UpdateRect
.left
, Buff
->CurrentX
);
466 EndX
= (Buff
->CurrentX
+ 8) & ~7;
467 if (EndX
> Buff
->MaxX
)
471 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
472 while (Buff
->CurrentX
< EndX
)
474 Buff
->Buffer
[Offset
] = ' ';
478 UpdateRect
.right
= RtlRosMax(UpdateRect
.right
, (LONG
) Buff
->CurrentX
- 1);
479 if (Buff
->CurrentX
== Buff
->MaxX
)
481 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
484 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
494 UpdateRect
.left
= RtlRosMin(UpdateRect
.left
, Buff
->CurrentX
);
495 UpdateRect
.right
= RtlRosMax(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
496 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
497 Buff
->Buffer
[Offset
++] = Buffer
[i
];
500 Buff
->Buffer
[Offset
] = Buff
->DefaultAttrib
;
503 if (Buff
->CurrentX
== Buff
->MaxX
)
505 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
508 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
512 Buff
->CurrentX
= CursorStartX
;
517 ConioPhysicalToLogical(Buff
, UpdateRect
.left
, UpdateRect
.top
, &(UpdateRect
.left
),
519 ConioPhysicalToLogical(Buff
, UpdateRect
.right
, UpdateRect
.bottom
, &(UpdateRect
.right
),
520 &(UpdateRect
.bottom
));
521 if (! ConioIsRectEmpty(&UpdateRect
) && NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
523 ConioWriteStream(Console
, &UpdateRect
, CursorStartX
, CursorStartY
, ScrolledLines
,
527 return STATUS_SUCCESS
;
530 CSR_API(CsrReadConsole
)
532 PLIST_ENTRY CurrentEntry
;
535 PWCHAR UnicodeBuffer
;
537 ULONG nNumberOfCharsToRead
, CharSize
;
538 PCSRSS_CONSOLE Console
;
541 DPRINT("CsrReadConsole\n");
543 CharSize
= (Request
->Data
.ReadConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
545 /* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */
546 nNumberOfCharsToRead
= min(Request
->Data
.ReadConsoleRequest
.NrCharactersToRead
, CSRSS_MAX_READ_CONSOLE_REQUEST
/ CharSize
);
547 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
548 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
550 Buffer
= Reply
->Data
.ReadConsoleReply
.Buffer
;
551 UnicodeBuffer
= (PWCHAR
)Buffer
;
552 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadConsoleRequest
.ConsoleHandle
,
554 if (! NT_SUCCESS(Status
))
556 return Reply
->Status
= Status
;
558 Reply
->Data
.ReadConsoleReply
.EventHandle
= ProcessData
->ConsoleEvent
;
559 for (i
= 0; i
< nNumberOfCharsToRead
&& Console
->InputEvents
.Flink
!= &Console
->InputEvents
; i
++)
561 /* remove input event from queue */
562 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
563 if (IsListEmpty(&Console
->InputEvents
))
566 ResetEvent(Console
->ActiveEvent
);
568 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
570 /* only pay attention to valid ascii chars, on key down */
571 if (KEY_EVENT
== Input
->InputEvent
.EventType
572 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
573 && Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
!= '\0')
575 /* backspace handling */
576 if ('\b' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
578 /* echo if it has not already been done, and either we or the client has chars to be deleted */
580 && (0 != i
|| Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
))
582 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
583 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
587 i
-= 2; /* if we already have something to return, just back it up by 2 */
590 { /* otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer */
591 Console
->WaitingChars
--;
592 ConioUnlockConsole(Console
);
593 HeapFree(Win32CsrApiHeap
, 0, Input
);
594 Reply
->Data
.ReadConsoleReply
.NrCharactersRead
= 0;
595 Reply
->Status
= STATUS_NOTIFY_CLEANUP
;
596 return STATUS_NOTIFY_CLEANUP
;
598 Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
--;
599 Input
->Echoed
= TRUE
; /* mark as echoed so we don't echo it below */
601 /* do not copy backspace to buffer */
604 if(Request
->Data
.ReadConsoleRequest
.Unicode
)
605 UnicodeBuffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
; /* FIXME */
607 Buffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
;
609 /* echo to screen if enabled and we did not already echo the char */
610 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
)
612 && '\r' != Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
614 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
615 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
622 Console
->WaitingChars
--;
623 HeapFree(Win32CsrApiHeap
, 0, Input
);
625 Reply
->Data
.ReadConsoleReply
.NrCharactersRead
= i
;
628 Reply
->Status
= STATUS_PENDING
; /* we didn't read anything */
630 else if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
))
632 if (0 == Console
->WaitingLines
||
633 (Request
->Data
.ReadConsoleRequest
.Unicode
? (L
'\n' != UnicodeBuffer
[i
- 1]) : ('\n' != Buffer
[i
- 1])))
635 Reply
->Status
= STATUS_PENDING
; /* line buffered, didn't get a complete line */
639 Console
->WaitingLines
--;
640 Reply
->Status
= STATUS_SUCCESS
; /* line buffered, did get a complete line */
645 Reply
->Status
= STATUS_SUCCESS
; /* not line buffered, did read something */
648 if (Reply
->Status
== STATUS_PENDING
)
650 Console
->EchoCount
= nNumberOfCharsToRead
- i
;
654 Console
->EchoCount
= 0; /* if the client is no longer waiting on input, do not echo */
656 Reply
->Header
.MessageSize
+= i
* CharSize
;
658 ConioUnlockConsole(Console
);
659 return Reply
->Status
;
663 ConioPhysicalToLogical(PCSRSS_SCREEN_BUFFER Buff
,
669 *LogicalX
= PhysicalX
;
670 if (PhysicalY
< Buff
->ShowY
)
672 *LogicalY
= Buff
->MaxY
- Buff
->ShowY
+ PhysicalY
;
676 *LogicalY
= PhysicalY
- Buff
->ShowY
;
680 inline BOOLEAN
ConioIsEqualRect(
684 return ((Rect1
->left
== Rect2
->left
) && (Rect1
->right
== Rect2
->right
) &&
685 (Rect1
->top
== Rect2
->top
) && (Rect1
->bottom
== Rect2
->bottom
));
688 inline BOOLEAN
ConioGetIntersection(
693 if (ConioIsRectEmpty(Rect1
) ||
694 (ConioIsRectEmpty(Rect2
)) ||
695 (Rect1
->top
> Rect2
->bottom
) ||
696 (Rect1
->left
> Rect2
->right
) ||
697 (Rect1
->bottom
< Rect2
->top
) ||
698 (Rect1
->right
< Rect2
->left
))
700 /* The rectangles do not intersect */
701 ConioInitRect(Intersection
, 0, -1, 0, -1);
705 ConioInitRect(Intersection
,
706 RtlRosMax(Rect1
->top
, Rect2
->top
),
707 RtlRosMax(Rect1
->left
, Rect2
->left
),
708 RtlRosMin(Rect1
->bottom
, Rect2
->bottom
),
709 RtlRosMin(Rect1
->right
, Rect2
->right
));
714 inline BOOLEAN
ConioGetUnion(
719 if (ConioIsRectEmpty(Rect1
))
721 if (ConioIsRectEmpty(Rect2
))
723 ConioInitRect(Union
, 0, -1, 0, -1);
731 else if (ConioIsRectEmpty(Rect2
))
738 RtlRosMin(Rect1
->top
, Rect2
->top
),
739 RtlRosMin(Rect1
->left
, Rect2
->left
),
740 RtlRosMax(Rect1
->bottom
, Rect2
->bottom
),
741 RtlRosMax(Rect1
->right
, Rect2
->right
));
747 inline BOOLEAN
ConioSubtractRect(
754 if (ConioIsRectEmpty(Rect1
))
756 ConioInitRect(Subtraction
, 0, -1, 0, -1);
759 *Subtraction
= *Rect1
;
760 if (ConioGetIntersection(&tmp
, Rect1
, Rect2
))
762 if (ConioIsEqualRect(&tmp
, Subtraction
))
764 ConioInitRect(Subtraction
, 0, -1, 0, -1);
767 if ((tmp
.top
== Subtraction
->top
) && (tmp
.bottom
== Subtraction
->bottom
))
769 if (tmp
.left
== Subtraction
->left
)
771 Subtraction
->left
= tmp
.right
;
773 else if (tmp
.right
== Subtraction
->right
)
775 Subtraction
->right
= tmp
.left
;
778 else if ((tmp
.left
== Subtraction
->left
) && (tmp
.right
== Subtraction
->right
))
780 if (tmp
.top
== Subtraction
->top
)
782 Subtraction
->top
= tmp
.bottom
;
784 else if (tmp
.bottom
== Subtraction
->bottom
)
786 Subtraction
->bottom
= tmp
.top
;
795 ConioCopyRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer
,
805 DstY
= DstRegion
->top
;
806 BytesPerLine
= ConioRectWidth(DstRegion
) * 2;
808 SrcY
= (SrcRegion
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
809 DstY
= (DstRegion
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
810 SrcOffset
= (SrcY
* ScreenBuffer
->MaxX
+ SrcRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
811 DstOffset
= (DstY
* ScreenBuffer
->MaxX
+ DstRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
813 for (i
= SrcRegion
->top
; i
<= SrcRegion
->bottom
; i
++)
816 &ScreenBuffer
->Buffer
[DstOffset
],
817 &ScreenBuffer
->Buffer
[SrcOffset
],
820 if (++DstY
== ScreenBuffer
->MaxY
)
823 DstOffset
= (DstRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
827 DstOffset
+= ScreenBuffer
->MaxX
* 2;
830 if (++SrcY
== ScreenBuffer
->MaxY
)
833 SrcOffset
= (SrcRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
837 SrcOffset
+= ScreenBuffer
->MaxX
* 2;
843 ConioFillRegion(PCSRSS_CONSOLE Console
,
844 PCSRSS_SCREEN_BUFFER ScreenBuffer
,
856 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &CharInfo
->Char
.UnicodeChar
);
858 Char
= CharInfo
->Char
.AsciiChar
;
860 Y
= (Region
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
861 Offset
= (Y
* ScreenBuffer
->MaxX
+ Region
->left
+ ScreenBuffer
->ShowX
) * 2;
862 Delta
= (ScreenBuffer
->MaxX
- ConioRectWidth(Region
)) * 2;
864 for (i
= Region
->top
; i
<= Region
->bottom
; i
++)
866 for (X
= Region
->left
; X
<= Region
->right
; X
++)
868 SET_CELL_BUFFER(ScreenBuffer
, Offset
, Char
, CharInfo
->Attributes
);
870 if (++Y
== ScreenBuffer
->MaxY
)
873 Offset
= (Region
->left
+ ScreenBuffer
->ShowX
) * 2;
883 ConioInputEventToAnsi(PCSRSS_CONSOLE Console
, PINPUT_RECORD InputEvent
)
885 if (InputEvent
->EventType
== KEY_EVENT
)
887 ConsoleUnicodeCharToAnsiChar(Console
,
888 &InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
,
889 &InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
);
893 CSR_API(CsrWriteConsole
)
896 PCHAR Buffer
= (PCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
;
897 PCSRSS_SCREEN_BUFFER Buff
;
898 PCSRSS_CONSOLE Console
;
899 ULONG CharSize
= (Request
->Data
.WriteConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
901 DPRINT("CsrWriteConsole\n");
903 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
904 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
906 if (Request
->Header
.DataSize
907 < sizeof(CSRSS_WRITE_CONSOLE_REQUEST
) - 1
908 + (Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
* CharSize
))
910 DPRINT1("Invalid request size\n");
911 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
913 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
914 if (! NT_SUCCESS(Status
))
916 return Reply
->Status
= Status
;
919 if(Request
->Data
.WriteConsoleRequest
.Unicode
)
921 ConsoleUnicodeToAnsiN(Console
, Buffer
, (PWCHAR
)Buffer
, Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
);
924 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.WriteConsoleRequest
.ConsoleHandle
, &Buff
);
925 if (! NT_SUCCESS(Status
))
929 ConioUnlockConsole(Console
);
931 return Reply
->Status
= Status
;
934 Reply
->Status
= ConioWriteConsole(Console
, Buff
, Buffer
,
935 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
, TRUE
);
936 ConioUnlockScreenBuffer(Buff
);
939 ConioUnlockConsole(Console
);
942 if(NT_SUCCESS(Reply
->Status
))
944 Reply
->Data
.WriteConsoleReply
.NrCharactersWritten
= Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
;
948 Reply
->Data
.WriteConsoleReply
.NrCharactersWritten
= 0; /* FIXME - return the actual number of characters written! */
951 return Reply
->Status
= STATUS_SUCCESS
;
955 ConioDeleteScreenBuffer(Object_t
*Object
)
957 PCSRSS_SCREEN_BUFFER Buffer
= (PCSRSS_SCREEN_BUFFER
) Object
;
958 DeleteCriticalSection(&Buffer
->Header
.Lock
);
959 HeapFree(Win32CsrApiHeap
, 0, Buffer
->Buffer
);
960 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
964 ConioDrawConsole(PCSRSS_CONSOLE Console
)
968 ConioInitRect(&Region
, 0, 0, Console
->Size
.Y
- 1, Console
->Size
.X
- 1);
970 ConioDrawRegion(Console
, &Region
);
975 ConioDeleteConsole(Object_t
*Object
)
977 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Object
;
980 DPRINT("ConioDeleteConsole\n");
982 /* Drain input event queue */
983 while (Console
->InputEvents
.Flink
!= &Console
->InputEvents
)
985 Event
= (ConsoleInput
*) Console
->InputEvents
.Flink
;
986 Console
->InputEvents
.Flink
= Console
->InputEvents
.Flink
->Flink
;
987 Console
->InputEvents
.Flink
->Flink
->Blink
= &Console
->InputEvents
;
988 HeapFree(Win32CsrApiHeap
, 0, Event
);
991 if (0 == --Console
->ActiveBuffer
->Header
.ReferenceCount
)
993 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
996 Console
->ActiveBuffer
= NULL
;
997 ConioCleanupConsole(Console
);
999 CloseHandle(Console
->ActiveEvent
);
1000 DeleteCriticalSection(&Console
->Header
.Lock
);
1001 RtlFreeUnicodeString(&Console
->Title
);
1002 HeapFree(Win32CsrApiHeap
, 0, Console
);
1006 CsrInitConsoleSupport(VOID
)
1008 DPRINT("CSR: CsrInitConsoleSupport()\n");
1010 /* Should call LoadKeyboardLayout */
1013 STATIC VOID FASTCALL
1014 ConioProcessChar(PCSRSS_CONSOLE Console
,
1015 ConsoleInput
*KeyEventRecord
)
1018 BOOL bClientWake
= FALSE
;
1019 ConsoleInput
*TempInput
;
1021 /* process Ctrl-C and Ctrl-Break */
1022 if (Console
->Mode
& ENABLE_PROCESSED_INPUT
&&
1023 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
&&
1024 ((KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== VK_PAUSE
) ||
1025 (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== 'C')) &&
1026 (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
)))
1028 PCSRSS_PROCESS_DATA current
;
1029 PLIST_ENTRY current_entry
;
1030 DPRINT1("Console_Api Ctrl-C\n");
1031 current_entry
= Console
->ProcessList
.Flink
;
1032 while (current_entry
!= &Console
->ProcessList
)
1034 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
1035 current_entry
= current_entry
->Flink
;
1036 ConioConsoleCtrlEvent((DWORD
)CTRL_C_EVENT
, current
);
1038 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1042 if (0 != (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
1043 & (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1044 && (VK_UP
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
1045 || VK_DOWN
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
))
1047 if (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1049 /* scroll up or down */
1050 if (NULL
== Console
)
1052 DPRINT1("No Active Console!\n");
1053 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1056 if (VK_UP
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
)
1058 /* only scroll up if there is room to scroll up into */
1059 if (Console
->ActiveBuffer
->ShowY
!= ((Console
->ActiveBuffer
->CurrentY
+ 1) %
1060 Console
->ActiveBuffer
->MaxY
))
1062 Console
->ActiveBuffer
->ShowY
= (Console
->ActiveBuffer
->ShowY
+
1063 Console
->ActiveBuffer
->MaxY
- 1) %
1064 Console
->ActiveBuffer
->MaxY
;
1067 else if (Console
->ActiveBuffer
->ShowY
!= Console
->ActiveBuffer
->CurrentY
)
1068 /* only scroll down if there is room to scroll down into */
1070 if (Console
->ActiveBuffer
->ShowY
% Console
->ActiveBuffer
->MaxY
!=
1071 Console
->ActiveBuffer
->CurrentY
)
1073 if (((Console
->ActiveBuffer
->CurrentY
+ 1) % Console
->ActiveBuffer
->MaxY
) !=
1074 (Console
->ActiveBuffer
->ShowY
+ Console
->ActiveBuffer
->MaxY
) %
1075 Console
->ActiveBuffer
->MaxY
)
1077 Console
->ActiveBuffer
->ShowY
= (Console
->ActiveBuffer
->ShowY
+ 1) %
1078 Console
->ActiveBuffer
->MaxY
;
1082 ConioDrawConsole(Console
);
1084 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1087 if (NULL
== Console
)
1089 DPRINT1("No Active Console!\n");
1090 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1094 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
)))
1096 switch(KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1099 /* first add the \r */
1100 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1101 updown
= KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
;
1102 KeyEventRecord
->Echoed
= FALSE
;
1103 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= VK_RETURN
;
1104 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\r';
1105 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1106 Console
->WaitingChars
++;
1107 KeyEventRecord
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1108 if (NULL
== KeyEventRecord
)
1110 DPRINT1("Failed to allocate KeyEventRecord\n");
1113 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1114 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
= updown
;
1115 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= 0;
1116 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualScanCode
= 0;
1117 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\n';
1118 KeyEventRecord
->Fake
= TRUE
;
1122 /* add event to the queue */
1123 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1124 Console
->WaitingChars
++;
1125 /* if line input mode is enabled, only wake the client on enter key down */
1126 if (0 == (Console
->Mode
& ENABLE_LINE_INPUT
)
1127 || Console
->EarlyReturn
1128 || ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1129 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
))
1131 if ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1133 Console
->WaitingLines
++;
1136 SetEvent(Console
->ActiveEvent
);
1138 KeyEventRecord
->Echoed
= FALSE
;
1139 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
))
1140 && '\b' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1141 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1143 /* walk the input queue looking for a char to backspace */
1144 for (TempInput
= (ConsoleInput
*) Console
->InputEvents
.Blink
;
1145 TempInput
!= (ConsoleInput
*) &Console
->InputEvents
1146 && (KEY_EVENT
== TempInput
->InputEvent
.EventType
1147 || ! TempInput
->InputEvent
.Event
.KeyEvent
.bKeyDown
1148 || '\b' == TempInput
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
);
1149 TempInput
= (ConsoleInput
*) TempInput
->ListEntry
.Blink
)
1153 /* if we found one, delete it, otherwise, wake the client */
1154 if (TempInput
!= (ConsoleInput
*) &Console
->InputEvents
)
1156 /* delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue */
1157 RemoveEntryList(&TempInput
->ListEntry
);
1158 if (TempInput
->Echoed
)
1160 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1161 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1164 HeapFree(Win32CsrApiHeap
, 0, TempInput
);
1165 RemoveEntryList(&KeyEventRecord
->ListEntry
);
1166 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1167 Console
->WaitingChars
-= 2;
1171 SetEvent(Console
->ActiveEvent
);
1176 /* echo chars if we are supposed to and client is waiting for some */
1177 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
) && Console
->EchoCount
1178 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1179 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
1180 && '\r' != KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1182 /* mark the char as already echoed */
1183 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1184 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1186 Console
->EchoCount
--;
1187 KeyEventRecord
->Echoed
= TRUE
;
1191 /* Console->WaitingChars++; */
1192 if (bClientWake
|| 0 == (Console
->Mode
& ENABLE_LINE_INPUT
))
1194 SetEvent(Console
->ActiveEvent
);
1198 STATIC DWORD FASTCALL
1199 ConioGetShiftState(PBYTE KeyState
)
1203 if (KeyState
[VK_CAPITAL
] & 1)
1204 ssOut
|= CAPSLOCK_ON
;
1206 if (KeyState
[VK_NUMLOCK
] & 1)
1207 ssOut
|= NUMLOCK_ON
;
1209 if (KeyState
[VK_SCROLL
] & 1)
1210 ssOut
|= SCROLLLOCK_ON
;
1212 if (KeyState
[VK_SHIFT
] & 0x80)
1213 ssOut
|= SHIFT_PRESSED
;
1215 if (KeyState
[VK_LCONTROL
] & 0x80)
1216 ssOut
|= LEFT_CTRL_PRESSED
;
1217 if (KeyState
[VK_RCONTROL
] & 0x80)
1218 ssOut
|= RIGHT_CTRL_PRESSED
;
1220 if (KeyState
[VK_LMENU
] & 0x80)
1221 ssOut
|= LEFT_ALT_PRESSED
;
1222 if (KeyState
[VK_RMENU
] & 0x80)
1223 ssOut
|= RIGHT_ALT_PRESSED
;
1229 ConioProcessKey(MSG
*msg
, PCSRSS_CONSOLE Console
, BOOL TextMode
)
1231 static BYTE KeyState
[256] = { 0 };
1232 /* MSDN mentions that you should use the last virtual key code received
1233 * when putting a virtual key identity to a WM_CHAR message since multiple
1234 * or translated keys may be involved. */
1235 static UINT LastVirtualKey
= 0;
1237 ConsoleInput
*ConInRec
;
1241 UINT VirtualKeyCode
;
1242 UINT VirtualScanCode
;
1245 ULONG ResultSize
= 0;
1248 VirtualScanCode
= (msg
->lParam
>> 16) & 0xff;
1249 Down
= msg
->message
== WM_KEYDOWN
|| msg
->message
== WM_CHAR
||
1250 msg
->message
== WM_SYSKEYDOWN
|| msg
->message
== WM_SYSCHAR
;
1252 GetKeyboardState(KeyState
);
1253 ShiftState
= ConioGetShiftState(KeyState
);
1255 if (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
)
1257 VirtualKeyCode
= LastVirtualKey
;
1258 UnicodeChar
= msg
->wParam
;
1265 VirtualKeyCode
= msg
->wParam
;
1266 RetChars
= ToUnicodeEx(VirtualKeyCode
,
1273 UnicodeChar
= (1 == RetChars
? Chars
[0] : 0);
1276 if (0 == ResultSize
)
1281 er
.EventType
= KEY_EVENT
;
1282 er
.Event
.KeyEvent
.bKeyDown
= Down
;
1283 er
.Event
.KeyEvent
.wRepeatCount
= RepeatCount
;
1284 er
.Event
.KeyEvent
.uChar
.UnicodeChar
= UnicodeChar
;
1285 er
.Event
.KeyEvent
.dwControlKeyState
= ShiftState
;
1286 er
.Event
.KeyEvent
.wVirtualKeyCode
= VirtualKeyCode
;
1287 er
.Event
.KeyEvent
.wVirtualScanCode
= VirtualScanCode
;
1291 if (0 != (ShiftState
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1292 && VK_TAB
== VirtualKeyCode
)
1296 TuiSwapConsole(ShiftState
& SHIFT_PRESSED
? -1 : 1);
1301 else if (VK_MENU
== VirtualKeyCode
&& ! Down
)
1303 if (TuiSwapConsole(0))
1310 if (NULL
== Console
)
1315 ConInRec
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1317 if (NULL
== ConInRec
)
1322 ConInRec
->InputEvent
= er
;
1323 ConInRec
->Fake
= UnicodeChar
&&
1324 (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
&&
1325 msg
->message
!= WM_KEYUP
&& msg
->message
!= WM_SYSKEYUP
);
1326 ConInRec
->NotChar
= (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
);
1327 ConInRec
->Echoed
= FALSE
;
1328 if (ConInRec
->NotChar
)
1329 LastVirtualKey
= msg
->wParam
;
1331 DPRINT ("csrss: %s %s %s %s %02x %02x '%c' %04x\n",
1332 Down
? "down" : "up ",
1333 (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
) ?
1335 ConInRec
->Fake
? "fake" : "real",
1336 ConInRec
->NotChar
? "notc" : "char",
1339 (AsciiChar
>= ' ') ? AsciiChar
: '.',
1342 if (! ConInRec
->Fake
|| ! ConInRec
->NotChar
)
1344 /* FIXME - convert to ascii */
1345 ConioProcessChar(Console
, ConInRec
);
1349 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1354 Console_Api(DWORD RefreshEvent
)
1356 /* keep reading events from the keyboard and stuffing them into the current
1357 console's input queue */
1360 /* This call establishes our message queue */
1361 PeekMessageW(&msg
, 0, 0, 0, PM_NOREMOVE
);
1362 /* This call registers our message queue */
1363 PrivateCsrssRegisterPrimitive();
1364 /* This call turns on the input system in win32k */
1365 PrivateCsrssAcquireOrReleaseInputOwnership(FALSE
);
1369 GetMessageW(&msg
, 0, 0, 0);
1370 TranslateMessage(&msg
);
1372 if (msg
.message
== WM_CHAR
|| msg
.message
== WM_SYSCHAR
||
1373 msg
.message
== WM_KEYDOWN
|| msg
.message
== WM_KEYUP
||
1374 msg
.message
== WM_SYSKEYDOWN
|| msg
.message
== WM_SYSKEYUP
)
1376 ConioProcessKey(&msg
, TuiGetFocusConsole(), TRUE
);
1380 PrivateCsrssAcquireOrReleaseInputOwnership(TRUE
);
1383 CSR_API(CsrGetScreenBufferInfo
)
1386 PCSRSS_SCREEN_BUFFER Buff
;
1387 PCONSOLE_SCREEN_BUFFER_INFO pInfo
;
1389 DPRINT("CsrGetScreenBufferInfo\n");
1391 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1392 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1394 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ScreenBufferInfoRequest
.ConsoleHandle
, &Buff
);
1395 if (! NT_SUCCESS(Status
))
1397 return Reply
->Status
= Status
;
1399 pInfo
= &Reply
->Data
.ScreenBufferInfoReply
.Info
;
1400 pInfo
->dwSize
.X
= Buff
->MaxX
;
1401 pInfo
->dwSize
.Y
= Buff
->MaxY
;
1402 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1403 pInfo
->dwCursorPosition
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1404 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
1405 pInfo
->srWindow
.Left
= 0;
1406 pInfo
->srWindow
.Right
= Buff
->MaxX
- 1;
1407 pInfo
->srWindow
.Top
= 0;
1408 pInfo
->srWindow
.Bottom
= Buff
->MaxY
- 1;
1409 pInfo
->dwMaximumWindowSize
.X
= Buff
->MaxX
;
1410 pInfo
->dwMaximumWindowSize
.Y
= Buff
->MaxY
;
1411 ConioUnlockScreenBuffer(Buff
);
1413 Reply
->Status
= STATUS_SUCCESS
;
1415 return Reply
->Status
;
1418 CSR_API(CsrSetCursor
)
1421 PCSRSS_CONSOLE Console
;
1422 PCSRSS_SCREEN_BUFFER Buff
;
1423 LONG OldCursorX
, OldCursorY
;
1424 LONG NewCursorX
, NewCursorY
;
1426 DPRINT("CsrSetCursor\n");
1428 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1429 if (! NT_SUCCESS(Status
))
1431 return Reply
->Status
= Status
;
1434 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1435 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1437 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
);
1438 if (! NT_SUCCESS(Status
))
1440 if (NULL
!= Console
)
1442 ConioUnlockConsole(Console
);
1444 return Reply
->Status
= Status
;
1447 NewCursorX
= Request
->Data
.SetCursorRequest
.Position
.X
;
1448 NewCursorY
= Request
->Data
.SetCursorRequest
.Position
.Y
;
1449 if (NewCursorX
< 0 || NewCursorX
>= Buff
->MaxX
||
1450 NewCursorY
< 0 || NewCursorY
>= Buff
->MaxY
)
1452 ConioUnlockScreenBuffer(Buff
);
1453 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
1455 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &OldCursorX
, &OldCursorY
);
1456 Buff
->CurrentX
= NewCursorX
+ Buff
->ShowX
;
1457 Buff
->CurrentY
= (NewCursorY
+ Buff
->ShowY
) % Buff
->MaxY
;
1458 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1460 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
1462 ConioUnlockScreenBuffer(Buff
);
1463 return Reply
->Status
= STATUS_UNSUCCESSFUL
;
1467 ConioUnlockScreenBuffer(Buff
);
1468 if (NULL
!= Console
)
1470 ConioUnlockConsole(Console
);
1473 return Reply
->Status
= STATUS_SUCCESS
;
1476 STATIC FASTCALL VOID
1477 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, COORD
*Start
, UINT Length
)
1479 if (Buff
->MaxX
<= Start
->X
+ Length
)
1481 UpdateRect
->left
= 0;
1485 UpdateRect
->left
= Start
->X
;
1487 if (Buff
->MaxX
<= Start
->X
+ Length
)
1489 UpdateRect
->right
= Buff
->MaxX
- 1;
1493 UpdateRect
->right
= Start
->X
+ Length
- 1;
1495 UpdateRect
->top
= Start
->Y
;
1496 UpdateRect
->bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->MaxX
;
1497 if (Buff
->MaxY
<= UpdateRect
->bottom
)
1499 UpdateRect
->bottom
= Buff
->MaxY
- 1;
1503 CSR_API(CsrWriteConsoleOutputChar
)
1506 PCHAR String
= (PCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
;
1508 PCSRSS_CONSOLE Console
;
1509 PCSRSS_SCREEN_BUFFER Buff
;
1510 DWORD X
, Y
, Length
, CharSize
, Written
= 0;
1513 DPRINT("CsrWriteConsoleOutputChar\n");
1515 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1516 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1518 CharSize
= (Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
1520 if (Request
->Header
.DataSize
1521 < sizeof(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR_REQUEST
) - 1
1522 + (Request
->Data
.WriteConsoleOutputCharRequest
.Length
* CharSize
))
1524 DPRINT1("Invalid request size\n");
1525 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
1528 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1529 if (! NT_SUCCESS(Status
))
1531 return Reply
->Status
= Status
;
1534 if(Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
)
1536 ConsoleUnicodeToAnsiN(Console
, String
, (PWCHAR
)String
, Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
1539 Status
= ConioLockScreenBuffer(ProcessData
,
1540 Request
->Data
.WriteConsoleOutputCharRequest
.ConsoleHandle
,
1542 if (! NT_SUCCESS(Status
))
1544 if (NULL
!= Console
)
1546 ConioUnlockConsole(Console
);
1548 return Reply
->Status
= Status
;
1551 X
= Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.X
+ Buff
->ShowX
;
1552 Y
= (Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1553 Length
= Request
->Data
.WriteConsoleOutputCharRequest
.Length
;
1554 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1557 *Buffer
= *String
++;
1560 if (++X
== Buff
->MaxX
)
1562 if (++Y
== Buff
->MaxY
)
1565 Buffer
= Buff
->Buffer
;
1571 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1573 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputCharRequest
.Coord
,
1574 Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
1575 ConioDrawRegion(Console
, &UpdateRect
);
1578 Reply
->Data
.WriteConsoleOutputCharReply
.EndCoord
.X
= X
- Buff
->ShowX
;
1579 Reply
->Data
.WriteConsoleOutputCharReply
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1581 ConioUnlockScreenBuffer(Buff
);
1582 if (NULL
!= Console
)
1584 ConioUnlockConsole(Console
);
1587 Reply
->Data
.WriteConsoleOutputCharReply
.NrCharactersWritten
= Written
;
1588 return Reply
->Status
= STATUS_SUCCESS
;
1591 CSR_API(CsrFillOutputChar
)
1594 PCSRSS_CONSOLE Console
;
1595 PCSRSS_SCREEN_BUFFER Buff
;
1596 DWORD X
, Y
, Length
, Written
= 0;
1601 DPRINT("CsrFillOutputChar\n");
1603 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1604 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1606 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1607 if (! NT_SUCCESS(Status
))
1609 return Reply
->Status
= Status
;
1612 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputRequest
.ConsoleHandle
, &Buff
);
1613 if (! NT_SUCCESS(Status
))
1615 if (NULL
!= Console
)
1617 ConioUnlockConsole(Console
);
1619 return Reply
->Status
= Status
;
1622 X
= Request
->Data
.FillOutputRequest
.Position
.X
+ Buff
->ShowX
;
1623 Y
= (Request
->Data
.FillOutputRequest
.Position
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1624 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1625 if(Request
->Data
.FillOutputRequest
.Unicode
)
1626 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &Request
->Data
.FillOutputRequest
.Char
.UnicodeChar
);
1628 Char
= Request
->Data
.FillOutputRequest
.Char
.AsciiChar
;
1629 Length
= Request
->Data
.FillOutputRequest
.Length
;
1635 if (++X
== Buff
->MaxX
)
1637 if (++Y
== Buff
->MaxY
)
1640 Buffer
= Buff
->Buffer
;
1646 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1648 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputRequest
.Position
,
1649 Request
->Data
.FillOutputRequest
.Length
);
1650 ConioDrawRegion(Console
, &UpdateRect
);
1653 ConioUnlockScreenBuffer(Buff
);
1654 if (NULL
!= Console
)
1656 ConioUnlockConsole(Console
);
1659 return Reply
->Status
;
1662 CSR_API(CsrReadInputEvent
)
1664 PLIST_ENTRY CurrentEntry
;
1665 PCSRSS_CONSOLE Console
;
1667 BOOLEAN Done
= FALSE
;
1668 ConsoleInput
*Input
;
1670 DPRINT("CsrReadInputEvent\n");
1672 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1673 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1674 Reply
->Data
.ReadInputReply
.Event
= ProcessData
->ConsoleEvent
;
1676 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadInputRequest
.ConsoleHandle
, &Console
);
1677 if (! NT_SUCCESS(Status
))
1679 return Reply
->Status
= Status
;
1682 /* only get input if there is any */
1683 CurrentEntry
= Console
->InputEvents
.Flink
;
1684 while (CurrentEntry
!= &Console
->InputEvents
)
1686 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
1687 CurrentEntry
= CurrentEntry
->Flink
;
1689 if (Done
&& !Input
->Fake
)
1691 Reply
->Data
.ReadInputReply
.MoreEvents
= TRUE
;
1695 RemoveEntryList(&Input
->ListEntry
);
1697 if (!Done
&& !Input
->Fake
)
1699 Reply
->Data
.ReadInputReply
.Input
= Input
->InputEvent
;
1700 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
1702 ConioInputEventToAnsi(Console
, &Reply
->Data
.ReadInputReply
.Input
);
1707 if (Input
->InputEvent
.EventType
== KEY_EVENT
)
1709 if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
)
1710 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
1711 && '\r' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1713 Console
->WaitingLines
--;
1715 Console
->WaitingChars
--;
1717 HeapFree(Win32CsrApiHeap
, 0, Input
);
1722 Status
= STATUS_SUCCESS
;
1723 Console
->EarlyReturn
= FALSE
;
1727 Status
= STATUS_PENDING
;
1728 Console
->EarlyReturn
= TRUE
; /* mark for early return */
1731 if (IsListEmpty(&Console
->InputEvents
))
1733 ResetEvent(Console
->ActiveEvent
);
1736 ConioUnlockConsole(Console
);
1738 return Reply
->Status
= Status
;
1741 CSR_API(CsrWriteConsoleOutputAttrib
)
1743 PCSRSS_CONSOLE Console
;
1744 PCSRSS_SCREEN_BUFFER Buff
;
1745 PUCHAR Buffer
, Attribute
;
1750 DPRINT("CsrWriteConsoleOutputAttrib\n");
1752 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1753 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1755 if (Request
->Header
.DataSize
1756 < sizeof(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB_REQUEST
) - 1
1757 + Request
->Data
.WriteConsoleOutputAttribRequest
.Length
)
1759 DPRINT1("Invalid request size\n");
1760 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
1763 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1764 if (! NT_SUCCESS(Status
))
1766 return Reply
->Status
= Status
;
1769 Status
= ConioLockScreenBuffer(ProcessData
,
1770 Request
->Data
.WriteConsoleOutputAttribRequest
.ConsoleHandle
,
1772 if (! NT_SUCCESS(Status
))
1774 if (NULL
!= Console
)
1776 ConioUnlockConsole(Console
);
1778 return Reply
->Status
= Status
;
1781 X
= Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1782 Y
= (Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1783 Length
= Request
->Data
.WriteConsoleOutputAttribRequest
.Length
;
1784 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + 1];
1785 Attribute
= (PUCHAR
)Request
->Data
.WriteConsoleOutputAttribRequest
.String
;
1788 *Buffer
= *Attribute
++;
1790 if (++X
== Buff
->MaxX
)
1792 if (++Y
== Buff
->MaxY
)
1795 Buffer
= Buff
->Buffer
+ 1;
1801 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1803 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
,
1804 Request
->Data
.WriteConsoleOutputAttribRequest
.Length
);
1805 ConioDrawRegion(Console
, &UpdateRect
);
1808 if (NULL
!= Console
)
1810 ConioUnlockConsole(Console
);
1813 Reply
->Data
.WriteConsoleOutputAttribReply
.EndCoord
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1814 Reply
->Data
.WriteConsoleOutputAttribReply
.EndCoord
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1816 ConioUnlockScreenBuffer(Buff
);
1818 return Reply
->Status
= STATUS_SUCCESS
;
1821 CSR_API(CsrFillOutputAttrib
)
1823 PCSRSS_SCREEN_BUFFER Buff
;
1829 PCSRSS_CONSOLE Console
;
1831 DPRINT("CsrFillOutputAttrib\n");
1833 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1834 if (! NT_SUCCESS(Status
))
1836 return Reply
->Status
= Status
;
1839 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1840 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1841 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputAttribRequest
.ConsoleHandle
, &Buff
);
1842 if (! NT_SUCCESS(Status
))
1844 if (NULL
!= Console
)
1846 ConioUnlockConsole(Console
);
1848 return Reply
->Status
= Status
;
1851 X
= Request
->Data
.FillOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1852 Y
= (Request
->Data
.FillOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1853 Length
= Request
->Data
.FillOutputAttribRequest
.Length
;
1854 Attr
= Request
->Data
.FillOutputAttribRequest
.Attribute
;
1855 Buffer
= &Buff
->Buffer
[(Y
* Buff
->MaxX
* 2) + (X
* 2) + 1];
1860 if (++X
== Buff
->MaxX
)
1862 if (++Y
== Buff
->MaxY
)
1865 Buffer
= Buff
->Buffer
+ 1;
1871 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1873 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputAttribRequest
.Coord
,
1874 Request
->Data
.FillOutputAttribRequest
.Length
);
1875 ConioDrawRegion(Console
, &UpdateRect
);
1878 ConioUnlockScreenBuffer(Buff
);
1879 if (NULL
!= Console
)
1881 ConioUnlockConsole(Console
);
1884 return Reply
->Status
= STATUS_SUCCESS
;
1888 CSR_API(CsrGetCursorInfo
)
1890 PCSRSS_SCREEN_BUFFER Buff
;
1893 DPRINT("CsrGetCursorInfo\n");
1895 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1896 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1898 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.GetCursorInfoRequest
.ConsoleHandle
, &Buff
);
1899 if (! NT_SUCCESS(Status
))
1901 return Reply
->Status
= Status
;
1903 Reply
->Data
.GetCursorInfoReply
.Info
= Buff
->CursorInfo
;
1904 ConioUnlockScreenBuffer(Buff
);
1906 return Reply
->Status
= STATUS_SUCCESS
;
1909 CSR_API(CsrSetCursorInfo
)
1911 PCSRSS_CONSOLE Console
;
1912 PCSRSS_SCREEN_BUFFER Buff
;
1917 DPRINT("CsrSetCursorInfo\n");
1919 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1920 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1922 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1923 if (! NT_SUCCESS(Status
))
1925 return Reply
->Status
= Status
;
1928 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorInfoRequest
.ConsoleHandle
, &Buff
);
1929 if (! NT_SUCCESS(Status
))
1931 if (NULL
!= Console
)
1933 ConioUnlockConsole(Console
);
1935 return Reply
->Status
= Status
;
1938 Size
= Request
->Data
.SetCursorInfoRequest
.Info
.dwSize
;
1939 Visible
= Request
->Data
.SetCursorInfoRequest
.Info
.bVisible
;
1949 if (Size
!= Buff
->CursorInfo
.dwSize
1950 || (Visible
&& ! Buff
->CursorInfo
.bVisible
) || (! Visible
&& Buff
->CursorInfo
.bVisible
))
1952 Buff
->CursorInfo
.dwSize
= Size
;
1953 Buff
->CursorInfo
.bVisible
= Visible
;
1955 if (NULL
!= Console
&& ! ConioSetCursorInfo(Console
, Buff
))
1957 ConioUnlockScreenBuffer(Buff
);
1958 ConioUnlockConsole(Console
);
1959 return Reply
->Status
= STATUS_UNSUCCESSFUL
;
1963 ConioUnlockScreenBuffer(Buff
);
1964 if (NULL
!= Console
)
1966 ConioUnlockConsole(Console
);
1969 return Reply
->Status
= STATUS_SUCCESS
;
1972 CSR_API(CsrSetTextAttrib
)
1975 PCSRSS_CONSOLE Console
;
1976 PCSRSS_SCREEN_BUFFER Buff
;
1977 LONG OldCursorX
, OldCursorY
;
1979 DPRINT("CsrSetTextAttrib\n");
1981 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1982 if (! NT_SUCCESS(Status
))
1984 return Reply
->Status
= Status
;
1987 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
);
1988 if (! NT_SUCCESS(Status
))
1990 if (NULL
!= Console
)
1992 ConioUnlockConsole(Console
);
1994 return Reply
->Status
= Status
;
1997 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &OldCursorX
, &OldCursorY
);
1999 Buff
->DefaultAttrib
= Request
->Data
.SetAttribRequest
.Attrib
;
2000 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
2002 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
2004 ConioUnlockScreenBuffer(Buff
);
2005 ConioUnlockConsole(Console
);
2006 return Reply
->Status
= STATUS_UNSUCCESSFUL
;
2010 ConioUnlockScreenBuffer(Buff
);
2011 if (NULL
!= Console
)
2013 ConioUnlockConsole(Console
);
2016 return Reply
->Status
= STATUS_SUCCESS
;
2019 CSR_API(CsrSetConsoleMode
)
2022 PCSRSS_CONSOLE Console
;
2023 PCSRSS_SCREEN_BUFFER Buff
;
2025 DPRINT("CsrSetConsoleMode\n");
2027 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2028 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2029 Status
= Win32CsrGetObject(ProcessData
,
2030 Request
->Data
.SetConsoleModeRequest
.ConsoleHandle
,
2031 (Object_t
**) &Console
);
2032 if (! NT_SUCCESS(Status
))
2034 return Reply
->Status
= Status
;
2037 Buff
= (PCSRSS_SCREEN_BUFFER
)Console
;
2038 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
2040 Console
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_INPUT_MODE_VALID
;
2042 else if (CONIO_SCREEN_BUFFER_MAGIC
== Console
->Header
.Type
)
2044 Buff
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_OUTPUT_MODE_VALID
;
2048 return Reply
->Status
= STATUS_INVALID_HANDLE
;
2051 Reply
->Status
= STATUS_SUCCESS
;
2053 return Reply
->Status
;
2056 CSR_API(CsrGetConsoleMode
)
2059 PCSRSS_CONSOLE Console
;
2060 PCSRSS_SCREEN_BUFFER Buff
; /* gee, I really wish I could use an anonymous union here */
2062 DPRINT("CsrGetConsoleMode\n");
2064 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2065 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2066 Status
= Win32CsrGetObject(ProcessData
, Request
->Data
.GetConsoleModeRequest
.ConsoleHandle
,
2067 (Object_t
**) &Console
);
2068 if (! NT_SUCCESS(Status
))
2070 return Reply
->Status
= Status
;
2072 Reply
->Status
= STATUS_SUCCESS
;
2073 Buff
= (PCSRSS_SCREEN_BUFFER
) Console
;
2074 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
2076 Reply
->Data
.GetConsoleModeReply
.ConsoleMode
= Console
->Mode
;
2078 else if (CONIO_SCREEN_BUFFER_MAGIC
== Buff
->Header
.Type
)
2080 Reply
->Data
.GetConsoleModeReply
.ConsoleMode
= Buff
->Mode
;
2084 Reply
->Status
= STATUS_INVALID_HANDLE
;
2087 return Reply
->Status
;
2090 CSR_API(CsrCreateScreenBuffer
)
2092 PCSRSS_CONSOLE Console
;
2093 PCSRSS_SCREEN_BUFFER Buff
;
2096 DPRINT("CsrCreateScreenBuffer\n");
2098 if (ProcessData
== NULL
)
2100 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
2103 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2104 if (! NT_SUCCESS(Status
))
2106 return Reply
->Status
= Status
;
2108 if (NULL
== Console
)
2110 return Reply
->Status
= STATUS_INVALID_HANDLE
;
2113 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2114 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2116 Buff
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(CSRSS_SCREEN_BUFFER
));
2119 Reply
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2122 Status
= CsrInitConsoleScreenBuffer(Console
, Buff
);
2123 if(! NT_SUCCESS(Status
))
2125 Reply
->Status
= Status
;
2129 Reply
->Status
= Win32CsrInsertObject(ProcessData
, &Reply
->Data
.CreateScreenBufferReply
.OutputHandle
, &Buff
->Header
);
2132 ConioUnlockConsole(Console
);
2134 return Reply
->Status
;
2137 CSR_API(CsrSetScreenBuffer
)
2140 PCSRSS_CONSOLE Console
;
2141 PCSRSS_SCREEN_BUFFER Buff
;
2143 DPRINT("CsrSetScreenBuffer\n");
2145 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2146 if (! NT_SUCCESS(Status
))
2148 return Reply
->Status
= Status
;
2150 if (NULL
== Console
)
2152 DPRINT1("Trying to set screen buffer for app without console\n");
2153 return Reply
->Status
= STATUS_INVALID_HANDLE
;
2156 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2157 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2159 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetScreenBufferRequest
.OutputHandle
, &Buff
);
2160 if (! NT_SUCCESS(Status
))
2162 ConioUnlockConsole(Console
);
2163 return Reply
->Status
;
2166 if (Buff
== Console
->ActiveBuffer
)
2168 ConioUnlockScreenBuffer(Buff
);
2169 ConioUnlockConsole(Console
);
2170 return STATUS_SUCCESS
;
2173 /* drop reference to old buffer, maybe delete */
2174 if (! InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
2176 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
2178 /* tie console to new buffer */
2179 Console
->ActiveBuffer
= Buff
;
2180 /* inc ref count on new buffer */
2181 InterlockedIncrement(&Buff
->Header
.ReferenceCount
);
2182 /* Redraw the console */
2183 ConioDrawConsole(Console
);
2185 ConioUnlockScreenBuffer(Buff
);
2186 ConioUnlockConsole(Console
);
2188 return Reply
->Status
= STATUS_SUCCESS
;
2191 CSR_API(CsrSetTitle
)
2194 PCSRSS_CONSOLE Console
;
2196 DPRINT("CsrSetTitle\n");
2198 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2199 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2201 if (Request
->Header
.DataSize
2202 < sizeof(CSRSS_SET_TITLE_REQUEST
) - 1
2203 + Request
->Data
.SetTitleRequest
.Length
)
2205 DPRINT1("Invalid request size\n");
2206 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
2209 Status
= ConioLockConsole(ProcessData
, Request
->Data
.SetTitleRequest
.Console
, &Console
);
2210 if(! NT_SUCCESS(Status
))
2212 Reply
->Status
= Status
;
2216 /* copy title to console */
2217 RtlFreeUnicodeString(&Console
->Title
);
2218 RtlCreateUnicodeString(&Console
->Title
, Request
->Data
.SetTitleRequest
.Title
);
2219 if (! ConioChangeTitle(Console
))
2221 Reply
->Status
= STATUS_UNSUCCESSFUL
;
2225 Reply
->Status
= STATUS_SUCCESS
;
2228 ConioUnlockConsole(Console
);
2230 return Reply
->Status
;
2233 CSR_API(CsrGetTitle
)
2236 PCSRSS_CONSOLE Console
;
2238 DPRINT("CsrGetTitle\n");
2240 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2241 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2242 Status
= ConioLockConsole(ProcessData
,
2243 Request
->Data
.GetTitleRequest
.ConsoleHandle
,
2245 if (! NT_SUCCESS(Status
))
2247 DPRINT1("Can't get console\n");
2248 return Reply
->Status
= Status
;
2251 /* Copy title of the console to the user title buffer */
2252 RtlZeroMemory(&Reply
->Data
.GetTitleReply
, sizeof(CSRSS_GET_TITLE_REPLY
));
2253 Reply
->Data
.GetTitleReply
.ConsoleHandle
= Request
->Data
.GetTitleRequest
.ConsoleHandle
;
2254 Reply
->Data
.GetTitleReply
.Length
= Console
->Title
.Length
;
2255 wcscpy (Reply
->Data
.GetTitleReply
.Title
, Console
->Title
.Buffer
);
2256 Reply
->Header
.MessageSize
+= Console
->Title
.Length
;
2257 Reply
->Header
.DataSize
+= Console
->Title
.Length
;
2258 Reply
->Status
= STATUS_SUCCESS
;
2260 ConioUnlockConsole(Console
);
2262 return Reply
->Status
;
2265 CSR_API(CsrWriteConsoleOutput
)
2267 SHORT i
, X
, Y
, SizeX
, SizeY
;
2268 PCSRSS_CONSOLE Console
;
2269 PCSRSS_SCREEN_BUFFER Buff
;
2271 CHAR_INFO
* CurCharInfo
;
2273 CHAR_INFO
* CharInfo
;
2280 DPRINT("CsrWriteConsoleOutput\n");
2282 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2283 if (! NT_SUCCESS(Status
))
2285 return Reply
->Status
= Status
;
2288 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2289 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2290 Status
= ConioLockScreenBuffer(ProcessData
,
2291 Request
->Data
.WriteConsoleOutputRequest
.ConsoleHandle
,
2293 if (! NT_SUCCESS(Status
))
2295 if (NULL
!= Console
)
2297 ConioUnlockConsole(Console
);
2299 return Reply
->Status
= Status
;
2302 BufferSize
= Request
->Data
.WriteConsoleOutputRequest
.BufferSize
;
2303 PSize
= BufferSize
.X
* BufferSize
.Y
* sizeof(CHAR_INFO
);
2304 BufferCoord
= Request
->Data
.WriteConsoleOutputRequest
.BufferCoord
;
2305 CharInfo
= Request
->Data
.WriteConsoleOutputRequest
.CharInfo
;
2306 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
) ||
2307 (((PVOID
)CharInfo
+ PSize
) >
2308 (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2310 ConioUnlockScreenBuffer(Buff
);
2311 ConioUnlockConsole(Console
);
2312 return Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2314 WriteRegion
.left
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
;
2315 WriteRegion
.top
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
;
2316 WriteRegion
.right
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
;
2317 WriteRegion
.bottom
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
;
2319 SizeY
= RtlRosMin(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&WriteRegion
));
2320 SizeX
= RtlRosMin(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&WriteRegion
));
2321 WriteRegion
.bottom
= WriteRegion
.top
+ SizeY
- 1;
2322 WriteRegion
.right
= WriteRegion
.left
+ SizeX
- 1;
2324 /* Make sure WriteRegion is inside the screen buffer */
2325 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2326 if (! ConioGetIntersection(&WriteRegion
, &ScreenBuffer
, &WriteRegion
))
2328 ConioUnlockScreenBuffer(Buff
);
2329 ConioUnlockConsole(Console
);
2331 /* It is okay to have a WriteRegion completely outside the screen buffer.
2332 No data is written then. */
2333 return Reply
->Status
= STATUS_SUCCESS
;
2336 for (i
= 0, Y
= WriteRegion
.top
; Y
<= WriteRegion
.bottom
; i
++, Y
++)
2338 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
2339 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ WriteRegion
.left
) * 2;
2340 for (X
= WriteRegion
.left
; X
<= WriteRegion
.right
; X
++)
2342 if (Request
->Data
.WriteConsoleOutputRequest
.Unicode
)
2345 ConsoleUnicodeCharToAnsiChar(Console
, &AsciiChar
, &CurCharInfo
->Char
.UnicodeChar
);
2346 SET_CELL_BUFFER(Buff
, Offset
, AsciiChar
, CurCharInfo
->Attributes
);
2350 SET_CELL_BUFFER(Buff
, Offset
, CurCharInfo
->Char
.AsciiChar
, CurCharInfo
->Attributes
);
2356 if (NULL
!= Console
)
2358 ConioDrawRegion(Console
, &WriteRegion
);
2361 ConioUnlockScreenBuffer(Buff
);
2362 ConioUnlockConsole(Console
);
2364 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Right
= WriteRegion
.left
+ SizeX
- 1;
2365 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Bottom
= WriteRegion
.top
+ SizeY
- 1;
2366 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Left
= WriteRegion
.left
;
2367 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Top
= WriteRegion
.top
;
2369 return Reply
->Status
= STATUS_SUCCESS
;
2372 CSR_API(CsrFlushInputBuffer
)
2374 PLIST_ENTRY CurrentEntry
;
2375 PCSRSS_CONSOLE Console
;
2376 ConsoleInput
* Input
;
2379 DPRINT("CsrFlushInputBuffer\n");
2381 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2382 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2383 Status
= ConioLockConsole(ProcessData
,
2384 Request
->Data
.FlushInputBufferRequest
.ConsoleInput
,
2386 if(! NT_SUCCESS(Status
))
2388 return Reply
->Status
= Status
;
2391 /* Discard all entries in the input event queue */
2392 while (!IsListEmpty(&Console
->InputEvents
))
2394 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
2395 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
2396 /* Destroy the event */
2397 HeapFree(Win32CsrApiHeap
, 0, Input
);
2399 ResetEvent(Console
->ActiveEvent
);
2400 Console
->WaitingChars
=0;
2402 ConioUnlockConsole(Console
);
2404 return Reply
->Status
= STATUS_SUCCESS
;
2407 CSR_API(CsrScrollConsoleScreenBuffer
)
2409 PCSRSS_CONSOLE Console
;
2410 PCSRSS_SCREEN_BUFFER Buff
;
2415 RECT ScrollRectangle
;
2420 DPRINT("CsrScrollConsoleScreenBuffer\n");
2422 ALIAS(ConsoleHandle
,Request
->Data
.ScrollConsoleScreenBufferRequest
.ConsoleHandle
);
2423 ALIAS(UseClipRectangle
,Request
->Data
.ScrollConsoleScreenBufferRequest
.UseClipRectangle
);
2424 ALIAS(DestinationOrigin
,Request
->Data
.ScrollConsoleScreenBufferRequest
.DestinationOrigin
);
2425 ALIAS(Fill
,Request
->Data
.ScrollConsoleScreenBufferRequest
.Fill
);
2427 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2428 if (! NT_SUCCESS(Status
))
2430 return Reply
->Status
= Status
;
2433 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2434 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2435 Status
= ConioLockScreenBuffer(ProcessData
, ConsoleHandle
, &Buff
);
2436 if (! NT_SUCCESS(Status
))
2438 if (NULL
!= Console
)
2440 ConioUnlockConsole(Console
);
2442 return Reply
->Status
= Status
;
2445 ScrollRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Left
;
2446 ScrollRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Top
;
2447 ScrollRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Right
;
2448 ScrollRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Bottom
;
2449 ClipRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Left
;
2450 ClipRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Top
;
2451 ClipRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Right
;
2452 ClipRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Bottom
;
2454 /* Make sure source rectangle is inside the screen buffer */
2455 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2456 if (! ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, &ScrollRectangle
))
2458 ConioUnlockScreenBuffer(Buff
);
2459 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
2462 if (UseClipRectangle
&& ! ConioGetIntersection(&SrcRegion
, &SrcRegion
, &ClipRectangle
))
2464 ConioUnlockScreenBuffer(Buff
);
2465 return Reply
->Status
= STATUS_SUCCESS
;
2469 ConioInitRect(&DstRegion
,
2470 DestinationOrigin
.Y
,
2471 DestinationOrigin
.X
,
2472 DestinationOrigin
.Y
+ ConioRectHeight(&ScrollRectangle
) - 1,
2473 DestinationOrigin
.X
+ ConioRectWidth(&ScrollRectangle
) - 1);
2475 /* Make sure destination rectangle is inside the screen buffer */
2476 if (! ConioGetIntersection(&DstRegion
, &DstRegion
, &ScreenBuffer
))
2478 ConioUnlockScreenBuffer(Buff
);
2479 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
2482 ConioCopyRegion(Buff
, &SrcRegion
, &DstRegion
);
2484 /* Get the region that should be filled with the specified character and attributes */
2488 ConioGetUnion(&FillRegion
, &SrcRegion
, &DstRegion
);
2490 if (ConioSubtractRect(&FillRegion
, &FillRegion
, &DstRegion
))
2492 /* FIXME: The subtracted rectangle is off by one line */
2493 FillRegion
.top
+= 1;
2495 ConioFillRegion(Console
, Buff
, &FillRegion
, &Fill
, Request
->Data
.ScrollConsoleScreenBufferRequest
.Unicode
);
2499 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
2501 /* Draw destination region */
2502 ConioDrawRegion(Console
, &DstRegion
);
2506 /* Draw filled region */
2507 ConioDrawRegion(Console
, &FillRegion
);
2511 ConioUnlockScreenBuffer(Buff
);
2512 if (NULL
!= Console
)
2514 ConioUnlockConsole(Console
);
2517 return Reply
->Status
= STATUS_SUCCESS
;
2520 CSR_API(CsrReadConsoleOutputChar
)
2523 PCSRSS_CONSOLE Console
;
2524 PCSRSS_SCREEN_BUFFER Buff
;
2531 DPRINT("CsrReadConsoleOutputChar\n");
2533 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2534 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
2535 ReadBuffer
= Reply
->Data
.ReadConsoleOutputCharReply
.String
;
2537 CharSize
= (Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
2539 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2540 if (! NT_SUCCESS(Status
))
2542 return Reply
->Status
= Status
;
2545 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputCharRequest
.ConsoleHandle
, &Buff
);
2546 if (! NT_SUCCESS(Status
))
2548 return Reply
->Status
= Status
;
2551 Xpos
= Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.X
+ Buff
->ShowX
;
2552 Ypos
= (Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
2554 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
; ++i
)
2556 Char
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
)];
2558 if(Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
)
2560 ConsoleAnsiCharToUnicodeChar(Console
, (WCHAR
*)ReadBuffer
, &Char
);
2561 ReadBuffer
+= sizeof(WCHAR
);
2564 *(ReadBuffer
++) = Char
;
2568 if (Xpos
== Buff
->MaxX
)
2573 if (Ypos
== Buff
->MaxY
)
2581 Reply
->Status
= STATUS_SUCCESS
;
2582 Reply
->Data
.ReadConsoleOutputCharReply
.EndCoord
.X
= Xpos
- Buff
->ShowX
;
2583 Reply
->Data
.ReadConsoleOutputCharReply
.EndCoord
.Y
= (Ypos
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
;
2584 Reply
->Header
.MessageSize
+= Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
;
2585 Reply
->Header
.DataSize
+= Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
;
2587 ConioUnlockScreenBuffer(Buff
);
2588 if (NULL
!= Console
)
2590 ConioUnlockConsole(Console
);
2593 Reply
->Data
.ReadConsoleOutputCharReply
.CharsRead
= (DWORD
)((ULONG_PTR
)ReadBuffer
- (ULONG_PTR
)Reply
->Data
.ReadConsoleOutputCharReply
.String
) / CharSize
;
2595 return Reply
->Status
;
2599 CSR_API(CsrReadConsoleOutputAttrib
)
2602 PCSRSS_SCREEN_BUFFER Buff
;
2607 DPRINT("CsrReadConsoleOutputAttrib\n");
2609 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2610 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
2611 ReadBuffer
= Reply
->Data
.ReadConsoleOutputAttribReply
.String
;
2613 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputAttribRequest
.ConsoleHandle
, &Buff
);
2614 if (! NT_SUCCESS(Status
))
2616 return Reply
->Status
= Status
;
2619 Xpos
= Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.X
+ Buff
->ShowX
;
2620 Ypos
= (Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
2622 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
; ++i
)
2624 *ReadBuffer
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
) + 1];
2629 if (Xpos
== Buff
->MaxX
)
2634 if (Ypos
== Buff
->MaxY
)
2643 Reply
->Status
= STATUS_SUCCESS
;
2644 Reply
->Data
.ReadConsoleOutputAttribReply
.EndCoord
.X
= Xpos
- Buff
->ShowX
;
2645 Reply
->Data
.ReadConsoleOutputAttribReply
.EndCoord
.Y
= (Ypos
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
;
2646 Reply
->Header
.MessageSize
+= Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
;
2647 Reply
->Header
.DataSize
+= Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
;
2649 ConioUnlockScreenBuffer(Buff
);
2651 return Reply
->Status
;
2655 CSR_API(CsrGetNumberOfConsoleInputEvents
)
2658 PCSRSS_CONSOLE Console
;
2659 PLIST_ENTRY CurrentItem
;
2661 ConsoleInput
*Input
;
2663 DPRINT("CsrGetNumberOfConsoleInputEvents\n");
2665 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2666 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
2668 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
);
2669 if (! NT_SUCCESS(Status
))
2671 return Reply
->Status
= Status
;
2674 CurrentItem
= Console
->InputEvents
.Flink
;
2677 /* If there are any events ... */
2678 while (CurrentItem
!= &Console
->InputEvents
)
2680 Input
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2681 CurrentItem
= CurrentItem
->Flink
;
2688 ConioUnlockConsole(Console
);
2690 Reply
->Status
= STATUS_SUCCESS
;
2691 Reply
->Data
.GetNumInputEventsReply
.NumInputEvents
= NumEvents
;
2693 return Reply
->Status
;
2697 CSR_API(CsrPeekConsoleInput
)
2700 PCSRSS_CONSOLE Console
;
2703 PLIST_ENTRY CurrentItem
;
2704 PINPUT_RECORD InputRecord
;
2708 DPRINT("CsrPeekConsoleInput\n");
2710 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2711 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2713 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
);
2714 if(! NT_SUCCESS(Status
))
2716 return Reply
->Status
= Status
;
2719 InputRecord
= Request
->Data
.PeekConsoleInputRequest
.InputRecord
;
2720 Length
= Request
->Data
.PeekConsoleInputRequest
.Length
;
2721 Size
= Length
* sizeof(INPUT_RECORD
);
2723 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2724 || (((PVOID
)InputRecord
+ Size
) > (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2726 ConioUnlockConsole(Console
);
2727 Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2728 return Reply
->Status
;
2733 if (! IsListEmpty(&Console
->InputEvents
))
2735 CurrentItem
= Console
->InputEvents
.Flink
;
2737 while (CurrentItem
!= &Console
->InputEvents
&& NumItems
< Length
)
2739 Item
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2743 CurrentItem
= CurrentItem
->Flink
;
2748 *InputRecord
= Item
->InputEvent
;
2750 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
2752 ConioInputEventToAnsi(Console
, InputRecord
);
2756 CurrentItem
= CurrentItem
->Flink
;
2760 ConioUnlockConsole(Console
);
2762 Reply
->Status
= STATUS_SUCCESS
;
2763 Reply
->Data
.PeekConsoleInputReply
.Length
= NumItems
;
2765 return Reply
->Status
;
2769 CSR_API(CsrReadConsoleOutput
)
2771 PCHAR_INFO CharInfo
;
2772 PCHAR_INFO CurCharInfo
;
2773 PCSRSS_SCREEN_BUFFER Buff
;
2782 DWORD i
, Y
, X
, Offset
;
2785 DPRINT("CsrReadConsoleOutput\n");
2787 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2788 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2790 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputRequest
.ConsoleHandle
, &Buff
);
2791 if (! NT_SUCCESS(Status
))
2793 return Reply
->Status
= Status
;
2796 CharInfo
= Request
->Data
.ReadConsoleOutputRequest
.CharInfo
;
2797 ReadRegion
.left
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
;
2798 ReadRegion
.top
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
;
2799 ReadRegion
.right
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
;
2800 ReadRegion
.bottom
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
;
2801 BufferSize
= Request
->Data
.ReadConsoleOutputRequest
.BufferSize
;
2802 BufferCoord
= Request
->Data
.ReadConsoleOutputRequest
.BufferCoord
;
2803 Length
= BufferSize
.X
* BufferSize
.Y
;
2804 Size
= Length
* sizeof(CHAR_INFO
);
2806 /* FIXME: Is this correct? */
2807 CodePage
= ProcessData
->Console
->OutputCodePage
;
2809 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
)
2810 || (((PVOID
)CharInfo
+ Size
) > (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2812 ConioUnlockScreenBuffer(Buff
);
2813 Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2814 return Reply
->Status
;
2817 SizeY
= RtlRosMin(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&ReadRegion
));
2818 SizeX
= RtlRosMin(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&ReadRegion
));
2819 ReadRegion
.bottom
= ReadRegion
.top
+ SizeY
;
2820 ReadRegion
.right
= ReadRegion
.left
+ SizeX
;
2822 ConioInitRect(&ScreenRect
, 0, 0, Buff
->MaxY
, Buff
->MaxX
);
2823 if (! ConioGetIntersection(&ReadRegion
, &ScreenRect
, &ReadRegion
))
2825 ConioUnlockScreenBuffer(Buff
);
2826 Reply
->Status
= STATUS_SUCCESS
;
2827 return Reply
->Status
;
2830 for (i
= 0, Y
= ReadRegion
.top
; Y
< ReadRegion
.bottom
; ++i
, ++Y
)
2832 CurCharInfo
= CharInfo
+ (i
* BufferSize
.X
);
2834 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ ReadRegion
.left
) * 2;
2835 for (X
= ReadRegion
.left
; X
< ReadRegion
.right
; ++X
)
2837 if (Request
->Data
.ReadConsoleOutputRequest
.Unicode
)
2839 MultiByteToWideChar(CodePage
, 0,
2840 (PCHAR
)&GET_CELL_BUFFER(Buff
, Offset
), 1,
2841 &CurCharInfo
->Char
.UnicodeChar
, 1);
2845 CurCharInfo
->Char
.AsciiChar
= GET_CELL_BUFFER(Buff
, Offset
);
2847 CurCharInfo
->Attributes
= GET_CELL_BUFFER(Buff
, Offset
);
2852 ConioUnlockScreenBuffer(Buff
);
2854 Reply
->Status
= STATUS_SUCCESS
;
2855 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Right
= ReadRegion
.left
+ SizeX
- 1;
2856 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Bottom
= ReadRegion
.top
+ SizeY
- 1;
2857 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Left
= ReadRegion
.left
;
2858 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Top
= ReadRegion
.top
;
2860 return Reply
->Status
;
2864 CSR_API(CsrWriteConsoleInput
)
2866 PINPUT_RECORD InputRecord
;
2867 PCSRSS_CONSOLE Console
;
2872 ConsoleInput
* Record
;
2874 DPRINT("CsrWriteConsoleInput\n");
2876 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2877 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2879 Status
= ConioLockConsole(ProcessData
, Request
->Data
.WriteConsoleInputRequest
.ConsoleHandle
, &Console
);
2880 if (! NT_SUCCESS(Status
))
2882 return Reply
->Status
= Status
;
2885 InputRecord
= Request
->Data
.WriteConsoleInputRequest
.InputRecord
;
2886 Length
= Request
->Data
.WriteConsoleInputRequest
.Length
;
2887 Size
= Length
* sizeof(INPUT_RECORD
);
2889 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2890 || (((PVOID
)InputRecord
+ Size
) > (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2892 ConioUnlockConsole(Console
);
2893 Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2894 return Reply
->Status
;
2897 for (i
= 0; i
< Length
; i
++)
2899 Record
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
2902 ConioUnlockConsole(Console
);
2903 Reply
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2904 return Reply
->Status
;
2907 Record
->Echoed
= FALSE
;
2908 Record
->Fake
= FALSE
;
2909 Record
->InputEvent
= *InputRecord
++;
2910 if (KEY_EVENT
== Record
->InputEvent
.EventType
)
2912 /* FIXME - convert from unicode to ascii!! */
2913 ConioProcessChar(Console
, Record
);
2917 ConioUnlockConsole(Console
);
2919 Reply
->Status
= STATUS_SUCCESS
;
2920 Reply
->Data
.WriteConsoleInputReply
.Length
= i
;
2922 return Reply
->Status
;
2925 /**********************************************************************
2926 * HardwareStateProperty
2929 * Set/Get the value of the HardwareState and switch
2930 * between direct video buffer ouput and GDI windowed
2933 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
2934 * object. We use the same object to reply.
2936 * ConsoleHwState has the correct size to be compatible
2937 * with NT's, but values are not.
2939 STATIC NTSTATUS FASTCALL
2940 SetConsoleHardwareState (PCSRSS_CONSOLE Console
, DWORD ConsoleHwState
)
2942 DPRINT1("Console Hardware State: %d\n", ConsoleHwState
);
2944 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED
== ConsoleHwState
)
2945 ||(CONSOLE_HARDWARE_STATE_DIRECT
== ConsoleHwState
))
2947 if (Console
->HardwareState
!= ConsoleHwState
)
2949 /* TODO: implement switching from full screen to windowed mode */
2950 /* TODO: or back; now simply store the hardware state */
2951 Console
->HardwareState
= ConsoleHwState
;
2954 return STATUS_SUCCESS
;
2957 return STATUS_INVALID_PARAMETER_3
; /* Client: (handle, set_get, [mode]) */
2960 CSR_API(CsrHardwareStateProperty
)
2962 PCSRSS_CONSOLE Console
;
2965 DPRINT("CsrHardwareStateProperty\n");
2967 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2968 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2970 Status
= ConioLockConsole(ProcessData
,
2971 Request
->Data
.ConsoleHardwareStateRequest
.ConsoleHandle
,
2973 if (! NT_SUCCESS(Status
))
2975 DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
2976 return Reply
->Status
= Status
;
2979 switch (Request
->Data
.ConsoleHardwareStateRequest
.SetGet
)
2981 case CONSOLE_HARDWARE_STATE_GET
:
2982 Reply
->Data
.ConsoleHardwareStateReply
.State
= Console
->HardwareState
;
2985 case CONSOLE_HARDWARE_STATE_SET
:
2986 DPRINT("Setting console hardware state.\n");
2987 Reply
->Status
= SetConsoleHardwareState(Console
, Request
->Data
.ConsoleHardwareStateRequest
.State
);
2991 Reply
->Status
= STATUS_INVALID_PARAMETER_2
; /* Client: (handle, [set_get], mode) */
2995 ConioUnlockConsole(Console
);
2997 return Reply
->Status
;
3000 CSR_API(CsrGetConsoleWindow
)
3002 PCSRSS_CONSOLE Console
;
3005 DPRINT("CsrGetConsoleWindow\n");
3007 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3008 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3010 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3011 if (! NT_SUCCESS(Status
))
3013 return Reply
->Status
= Status
;
3016 Reply
->Data
.GetConsoleWindowReply
.WindowHandle
= Console
->hWindow
;
3017 ConioUnlockConsole(Console
);
3019 return Reply
->Status
= STATUS_SUCCESS
;
3022 CSR_API(CsrSetConsoleIcon
)
3024 PCSRSS_CONSOLE Console
;
3027 DPRINT("CsrSetConsoleIcon\n");
3029 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3030 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3032 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3033 if (! NT_SUCCESS(Status
))
3035 return Reply
->Status
= Status
;
3038 Console
->hWindowIcon
= Request
->Data
.SetConsoleIconRequest
.WindowIcon
;
3039 Reply
->Status
= (ConioChangeIcon(Console
) ? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
3040 ConioUnlockConsole(Console
);
3042 return Reply
->Status
;
3045 CSR_API(CsrGetConsoleCodePage
)
3047 PCSRSS_CONSOLE Console
;
3050 DPRINT("CsrGetConsoleCodePage\n");
3052 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3053 if (! NT_SUCCESS(Status
))
3055 return Reply
->Status
= Status
;
3058 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3059 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3060 Reply
->Data
.GetConsoleCodePage
.CodePage
= Console
->CodePage
;
3061 ConioUnlockConsole(Console
);
3062 return Reply
->Status
= STATUS_SUCCESS
;
3065 CSR_API(CsrSetConsoleCodePage
)
3067 PCSRSS_CONSOLE Console
;
3070 DPRINT("CsrSetConsoleCodePage\n");
3072 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3073 if (! NT_SUCCESS(Status
))
3075 return Reply
->Status
= Status
;
3078 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3079 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3080 if (IsValidCodePage(Request
->Data
.SetConsoleCodePage
.CodePage
))
3082 Console
->CodePage
= Request
->Data
.SetConsoleCodePage
.CodePage
;
3083 ConioUnlockConsole(Console
);
3084 return Reply
->Status
= STATUS_SUCCESS
;
3086 ConioUnlockConsole(Console
);
3087 return Reply
->Status
= STATUS_UNSUCCESSFUL
;
3090 CSR_API(CsrGetConsoleOutputCodePage
)
3092 PCSRSS_CONSOLE Console
;
3095 DPRINT("CsrGetConsoleOutputCodePage\n");
3097 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3098 if (! NT_SUCCESS(Status
))
3100 return Reply
->Status
= Status
;
3103 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3104 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3105 Reply
->Data
.GetConsoleOutputCodePage
.CodePage
= Console
->OutputCodePage
;
3106 ConioUnlockConsole(Console
);
3107 return Reply
->Status
= STATUS_SUCCESS
;
3110 CSR_API(CsrSetConsoleOutputCodePage
)
3112 PCSRSS_CONSOLE Console
;
3115 DPRINT("CsrSetConsoleOutputCodePage\n");
3117 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3118 if (! NT_SUCCESS(Status
))
3120 return Reply
->Status
= Status
;
3123 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3124 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3125 if (IsValidCodePage(Request
->Data
.SetConsoleOutputCodePage
.CodePage
))
3127 Console
->OutputCodePage
= Request
->Data
.SetConsoleOutputCodePage
.CodePage
;
3128 ConioUnlockConsole(Console
);
3129 return Reply
->Status
= STATUS_SUCCESS
;
3131 ConioUnlockConsole(Console
);
3132 return Reply
->Status
= STATUS_UNSUCCESSFUL
;