1 /* $Id: conio.c,v 1.19 2004/12/25 11:22:37 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 #define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
50 WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
52 #define ConsoleAnsiCharToUnicodeChar(Console, sWChar, dChar) \
53 MultiByteToWideChar((Console)->CodePage, 0, (dChar), 1, (sWChar), 1)
55 #define ConsoleUnicodeToAnsiN(Console, dChar, sWChar, nChars) \
56 WideCharToMultiByte((Console)->CodePage, 0, (sWChar), (nChars), (dChar), (nChars) * sizeof(WCHAR), NULL, NULL)
58 /* FUNCTIONS *****************************************************************/
60 STATIC NTSTATUS FASTCALL
61 ConioConsoleFromProcessData(PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_CONSOLE
*Console
)
63 if (NULL
== ProcessData
->Console
)
66 return STATUS_SUCCESS
;
69 EnterCriticalSection(&(ProcessData
->Console
->Header
.Lock
));
70 *Console
= ProcessData
->Console
;
72 return STATUS_SUCCESS
;
76 ConioConsoleCtrlEvent(DWORD Event
, PCSRSS_PROCESS_DATA ProcessData
)
78 HANDLE Process
, Thread
;
80 DPRINT("ConioConsoleCtrlEvent Parent ProcessId = %x\n", ProcessData
->ProcessId
);
82 if (ProcessData
->CtrlDispatcher
)
84 Process
= OpenProcess(PROCESS_DUP_HANDLE
, FALSE
, ProcessData
->ProcessId
);
87 DPRINT1("Failed for handle duplication\n");
91 DPRINT("ConioConsoleCtrlEvent Process Handle = %x\n", Process
);
93 Thread
= CreateRemoteThread(Process
, NULL
, 0,
94 (LPTHREAD_START_ROUTINE
) ProcessData
->CtrlDispatcher
,
95 (PVOID
) Event
, 0, NULL
);
98 DPRINT1("Failed thread creation\n");
103 CloseHandle(Process
);
107 #define GET_CELL_BUFFER(b,o)\
110 #define SET_CELL_BUFFER(b,o,c,a)\
111 (b)->Buffer[(o)++]=(c),\
112 (b)->Buffer[(o)++]=(a)
115 ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff
)
117 DWORD Offset
= 2 * (Buff
->CurrentY
* Buff
->MaxX
);
120 for (Pos
= 0; Pos
< Buff
->MaxX
; Pos
++)
122 /* Fill the cell: Offset is incremented by the macro */
123 SET_CELL_BUFFER(Buff
, Offset
, ' ', Buff
->DefaultAttrib
);
127 STATIC NTSTATUS FASTCALL
128 CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console
,
129 PCSRSS_SCREEN_BUFFER Buffer
)
131 Buffer
->Header
.Type
= CONIO_SCREEN_BUFFER_MAGIC
;
132 Buffer
->Header
.ReferenceCount
= 0;
133 Buffer
->MaxX
= Console
->Size
.X
;
134 Buffer
->MaxY
= Console
->Size
.Y
;
137 Buffer
->Buffer
= HeapAlloc(Win32CsrApiHeap
, 0, Buffer
->MaxX
* Buffer
->MaxY
* 2);
138 if (NULL
== Buffer
->Buffer
)
140 return STATUS_INSUFFICIENT_RESOURCES
;
142 RtlInitializeCriticalSection(&Buffer
->Header
.Lock
);
143 ConioInitScreenBuffer(Console
, Buffer
);
144 /* initialize buffer to be empty with default attributes */
145 for (Buffer
->CurrentY
= 0 ; Buffer
->CurrentY
< Buffer
->MaxY
; Buffer
->CurrentY
++)
147 ClearLineBuffer(Buffer
);
149 Buffer
->CursorInfo
.bVisible
= TRUE
;
150 Buffer
->CursorInfo
.dwSize
= 5;
151 Buffer
->Mode
= ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
;
152 Buffer
->CurrentX
= 0;
153 Buffer
->CurrentY
= 0;
155 return STATUS_SUCCESS
;
158 STATIC NTSTATUS STDCALL
159 CsrInitConsole(PCSRSS_CONSOLE Console
)
162 SECURITY_ATTRIBUTES SecurityAttributes
;
163 PCSRSS_SCREEN_BUFFER NewBuffer
;
166 Console
->Title
.MaximumLength
= Console
->Title
.Length
= 0;
167 Console
->Title
.Buffer
= NULL
;
169 RtlCreateUnicodeString(&Console
->Title
, L
"Command Prompt");
171 Console
->Header
.ReferenceCount
= 0;
172 Console
->WaitingChars
= 0;
173 Console
->WaitingLines
= 0;
174 Console
->EchoCount
= 0;
175 Console
->Header
.Type
= CONIO_CONSOLE_MAGIC
;
176 Console
->Mode
= ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_PROCESSED_INPUT
| ENABLE_MOUSE_INPUT
;
177 Console
->EarlyReturn
= FALSE
;
178 Console
->ActiveBuffer
= NULL
;
179 InitializeListHead(&Console
->InputEvents
);
180 InitializeListHead(&Console
->ProcessList
);
182 Console
->CodePage
= GetOEMCP();
183 Console
->OutputCodePage
= GetOEMCP();
185 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
186 SecurityAttributes
.lpSecurityDescriptor
= NULL
;
187 SecurityAttributes
.bInheritHandle
= TRUE
;
189 Console
->ActiveEvent
= CreateEventW(&SecurityAttributes
, TRUE
, FALSE
, NULL
);
190 if (NULL
== Console
->ActiveEvent
)
192 RtlFreeUnicodeString(&Console
->Title
);
193 return STATUS_UNSUCCESSFUL
;
195 Console
->PrivateData
= NULL
;
196 RtlInitializeCriticalSection(&Console
->Header
.Lock
);
197 GuiMode
= DtbgIsDesktopVisible();
200 Status
= TuiInitConsole(Console
);
201 if (! NT_SUCCESS(Status
))
203 DPRINT1("Failed to open text-mode console, switching to gui-mode\n");
209 Status
= GuiInitConsole(Console
);
210 if (! NT_SUCCESS(Status
))
212 RtlFreeUnicodeString(&Console
->Title
);
213 RtlDeleteCriticalSection(&Console
->Header
.Lock
);
214 CloseHandle(Console
->ActiveEvent
);
219 NewBuffer
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(CSRSS_SCREEN_BUFFER
));
220 if (NULL
== NewBuffer
)
222 ConioCleanupConsole(Console
);
223 RtlFreeUnicodeString(&Console
->Title
);
224 RtlDeleteCriticalSection(&Console
->Header
.Lock
);
225 CloseHandle(Console
->ActiveEvent
);
226 return STATUS_INSUFFICIENT_RESOURCES
;
228 Status
= CsrInitConsoleScreenBuffer(Console
, NewBuffer
);
229 if (! NT_SUCCESS(Status
))
231 ConioCleanupConsole(Console
);
232 RtlFreeUnicodeString(&Console
->Title
);
233 RtlDeleteCriticalSection(&Console
->Header
.Lock
);
234 CloseHandle(Console
->ActiveEvent
);
235 HeapFree(Win32CsrApiHeap
, 0, NewBuffer
);
238 Console
->ActiveBuffer
= NewBuffer
;
239 /* add a reference count because the buffer is tied to the console */
240 Console
->ActiveBuffer
->Header
.ReferenceCount
++;
241 /* make console active, and insert into console list */
242 /* copy buffer contents to screen */
243 ConioDrawConsole(Console
);
245 return STATUS_SUCCESS
;
249 CSR_API(CsrAllocConsole
)
251 PCSRSS_CONSOLE Console
;
255 DPRINT("CsrAllocConsole\n");
257 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
258 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
260 if (ProcessData
== NULL
)
262 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
265 if (ProcessData
->Console
)
267 Reply
->Status
= STATUS_INVALID_PARAMETER
;
268 return STATUS_INVALID_PARAMETER
;
271 Reply
->Status
= STATUS_SUCCESS
;
272 Console
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(CSRSS_CONSOLE
));
275 Reply
->Status
= STATUS_NO_MEMORY
;
276 return STATUS_NO_MEMORY
;
278 Reply
->Status
= CsrInitConsole(Console
);
279 if (! NT_SUCCESS(Reply
->Status
))
281 HeapFree(Win32CsrApiHeap
, 0, Console
);
282 return Reply
->Status
;
284 ProcessData
->Console
= Console
;
285 Reply
->Data
.AllocConsoleReply
.Console
= Console
;
287 /* add a reference count because the process is tied to the console */
288 Console
->Header
.ReferenceCount
++;
289 Status
= Win32CsrInsertObject(ProcessData
, &Reply
->Data
.AllocConsoleReply
.InputHandle
, &Console
->Header
);
290 if (! NT_SUCCESS(Status
))
292 ConioDeleteConsole((Object_t
*) Console
);
293 ProcessData
->Console
= 0;
294 return Reply
->Status
= Status
;
296 Status
= Win32CsrInsertObject(ProcessData
, &Reply
->Data
.AllocConsoleReply
.OutputHandle
, &Console
->ActiveBuffer
->Header
);
297 if (!NT_SUCCESS(Status
))
299 Console
->Header
.ReferenceCount
--;
300 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.InputHandle
);
301 ProcessData
->Console
= 0;
302 return Reply
->Status
= Status
;
305 Process
= OpenProcess(PROCESS_DUP_HANDLE
, FALSE
, ProcessData
->ProcessId
);
308 DPRINT1("OpenProcess() failed for handle duplication\n");
309 Console
->Header
.ReferenceCount
--;
310 ProcessData
->Console
= 0;
311 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.OutputHandle
);
312 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.InputHandle
);
313 Reply
->Status
= Status
;
316 if (! DuplicateHandle(GetCurrentProcess(), ProcessData
->Console
->ActiveEvent
,
317 Process
, &ProcessData
->ConsoleEvent
, EVENT_ALL_ACCESS
, FALSE
, 0))
319 DPRINT1("DuplicateHandle() failed: %d\n", GetLastError
);
320 CloseHandle(Process
);
321 Console
->Header
.ReferenceCount
--;
322 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.OutputHandle
);
323 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.InputHandle
);
324 ProcessData
->Console
= 0;
325 Reply
->Status
= Status
;
328 CloseHandle(Process
);
329 ProcessData
->CtrlDispatcher
= Request
->Data
.AllocConsoleRequest
.CtrlDispatcher
;
330 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
331 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ProcessEntry
);
333 return STATUS_SUCCESS
;
336 CSR_API(CsrFreeConsole
)
338 PCSRSS_CONSOLE Console
;
340 DPRINT("CsrFreeConsole\n");
342 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
343 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
345 if (ProcessData
== NULL
|| ProcessData
->Console
== NULL
)
347 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
350 Console
= ProcessData
->Console
;
351 Console
->Header
.ReferenceCount
--;
352 ProcessData
->Console
= NULL
;
353 if (0 == Console
->Header
.ReferenceCount
)
355 ConioDeleteConsole((Object_t
*) Console
);
358 return STATUS_SUCCESS
;
362 ConioNextLine(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, UINT
*ScrolledLines
)
364 /* slide the viewable screen */
365 if (((Buff
->CurrentY
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
) == Buff
->MaxY
- 1)
367 if (++Buff
->ShowY
== Buff
->MaxY
)
373 if (++Buff
->CurrentY
== Buff
->MaxY
)
377 ClearLineBuffer(Buff
);
378 UpdateRect
->left
= 0;
379 UpdateRect
->right
= Buff
->MaxX
- 1;
380 if (UpdateRect
->top
== Buff
->CurrentY
)
382 if (++UpdateRect
->top
== Buff
->MaxY
)
387 UpdateRect
->bottom
= Buff
->CurrentY
;
390 STATIC NTSTATUS FASTCALL
391 ConioWriteConsole(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
,
392 CHAR
*Buffer
, DWORD Length
, BOOL Attrib
)
397 LONG CursorStartX
, CursorStartY
;
400 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &CursorStartX
, &CursorStartY
);
401 UpdateRect
.left
= Buff
->MaxX
;
402 UpdateRect
.top
= Buff
->CurrentY
;
403 UpdateRect
.right
= -1;
404 UpdateRect
.bottom
= Buff
->CurrentY
;
407 for (i
= 0; i
< Length
; i
++)
409 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
412 if (Buffer
[i
] == '\n')
415 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
419 else if (Buffer
[i
] == '\b')
421 /* Only handle BS if we're not on the first pos of the first line */
422 if (0 != Buff
->CurrentX
|| Buff
->ShowY
!= Buff
->CurrentY
)
424 if (0 == Buff
->CurrentX
)
426 /* slide virtual position up */
427 Buff
->CurrentX
= Buff
->MaxX
- 1;
428 if (0 == Buff
->CurrentY
)
430 Buff
->CurrentY
= Buff
->MaxY
;
436 if ((0 == UpdateRect
.top
&& UpdateRect
.bottom
< Buff
->CurrentY
)
437 || (0 != UpdateRect
.top
&& Buff
->CurrentY
< UpdateRect
.top
))
439 UpdateRect
.top
= Buff
->CurrentY
;
446 Offset
= 2 * ((Buff
->CurrentY
* Buff
->MaxX
) + Buff
->CurrentX
);
447 SET_CELL_BUFFER(Buff
, Offset
, ' ', Buff
->DefaultAttrib
);
448 UpdateRect
.left
= RtlRosMin(UpdateRect
.left
, Buff
->CurrentX
);
449 UpdateRect
.right
= RtlRosMax(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
454 else if (Buffer
[i
] == '\r')
457 UpdateRect
.left
= RtlRosMin(UpdateRect
.left
, Buff
->CurrentX
);
458 UpdateRect
.right
= RtlRosMax(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
462 else if (Buffer
[i
] == '\t')
466 UpdateRect
.left
= RtlRosMin(UpdateRect
.left
, Buff
->CurrentX
);
467 EndX
= (Buff
->CurrentX
+ 8) & ~7;
468 if (EndX
> Buff
->MaxX
)
472 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
473 while (Buff
->CurrentX
< EndX
)
475 Buff
->Buffer
[Offset
] = ' ';
479 UpdateRect
.right
= RtlRosMax(UpdateRect
.right
, (LONG
) Buff
->CurrentX
- 1);
480 if (Buff
->CurrentX
== Buff
->MaxX
)
482 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
485 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
495 UpdateRect
.left
= RtlRosMin(UpdateRect
.left
, Buff
->CurrentX
);
496 UpdateRect
.right
= RtlRosMax(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
497 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
498 Buff
->Buffer
[Offset
++] = Buffer
[i
];
501 Buff
->Buffer
[Offset
] = Buff
->DefaultAttrib
;
504 if (Buff
->CurrentX
== Buff
->MaxX
)
506 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
509 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
513 Buff
->CurrentX
= CursorStartX
;
518 ConioPhysicalToLogical(Buff
, UpdateRect
.left
, UpdateRect
.top
, &(UpdateRect
.left
),
520 ConioPhysicalToLogical(Buff
, UpdateRect
.right
, UpdateRect
.bottom
, &(UpdateRect
.right
),
521 &(UpdateRect
.bottom
));
522 if (! ConioIsRectEmpty(&UpdateRect
) && NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
524 ConioWriteStream(Console
, &UpdateRect
, CursorStartX
, CursorStartY
, ScrolledLines
,
528 return STATUS_SUCCESS
;
531 CSR_API(CsrReadConsole
)
533 PLIST_ENTRY CurrentEntry
;
536 PWCHAR UnicodeBuffer
;
538 ULONG nNumberOfCharsToRead
, CharSize
;
539 PCSRSS_CONSOLE Console
;
542 DPRINT("CsrReadConsole\n");
544 CharSize
= (Request
->Data
.ReadConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
546 /* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */
547 nNumberOfCharsToRead
= min(Request
->Data
.ReadConsoleRequest
.NrCharactersToRead
, CSRSS_MAX_READ_CONSOLE_REQUEST
/ CharSize
);
548 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
549 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
551 Buffer
= Reply
->Data
.ReadConsoleReply
.Buffer
;
552 UnicodeBuffer
= (PWCHAR
)Buffer
;
553 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadConsoleRequest
.ConsoleHandle
,
555 if (! NT_SUCCESS(Status
))
557 return Reply
->Status
= Status
;
559 Reply
->Data
.ReadConsoleReply
.EventHandle
= ProcessData
->ConsoleEvent
;
560 for (i
= 0; i
< nNumberOfCharsToRead
&& Console
->InputEvents
.Flink
!= &Console
->InputEvents
; i
++)
562 /* remove input event from queue */
563 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
564 if (IsListEmpty(&Console
->InputEvents
))
567 ResetEvent(Console
->ActiveEvent
);
569 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
571 /* only pay attention to valid ascii chars, on key down */
572 if (KEY_EVENT
== Input
->InputEvent
.EventType
573 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
574 && Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
!= '\0')
576 /* backspace handling */
577 if ('\b' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
579 /* echo if it has not already been done, and either we or the client has chars to be deleted */
581 && (0 != i
|| Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
))
583 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
584 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
588 i
-= 2; /* if we already have something to return, just back it up by 2 */
591 { /* otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer */
592 Console
->WaitingChars
--;
593 ConioUnlockConsole(Console
);
594 HeapFree(Win32CsrApiHeap
, 0, Input
);
595 Reply
->Data
.ReadConsoleReply
.NrCharactersRead
= 0;
596 Reply
->Status
= STATUS_NOTIFY_CLEANUP
;
597 return STATUS_NOTIFY_CLEANUP
;
599 Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
--;
600 Input
->Echoed
= TRUE
; /* mark as echoed so we don't echo it below */
602 /* do not copy backspace to buffer */
605 if(Request
->Data
.ReadConsoleRequest
.Unicode
)
606 UnicodeBuffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
; /* FIXME */
608 Buffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
;
610 /* echo to screen if enabled and we did not already echo the char */
611 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
)
613 && '\r' != Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
615 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
616 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
623 Console
->WaitingChars
--;
624 HeapFree(Win32CsrApiHeap
, 0, Input
);
626 Reply
->Data
.ReadConsoleReply
.NrCharactersRead
= i
;
629 Reply
->Status
= STATUS_PENDING
; /* we didn't read anything */
631 else if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
))
633 if (0 == Console
->WaitingLines
||
634 (Request
->Data
.ReadConsoleRequest
.Unicode
? (L
'\n' != UnicodeBuffer
[i
- 1]) : ('\n' != Buffer
[i
- 1])))
636 Reply
->Status
= STATUS_PENDING
; /* line buffered, didn't get a complete line */
640 Console
->WaitingLines
--;
641 Reply
->Status
= STATUS_SUCCESS
; /* line buffered, did get a complete line */
646 Reply
->Status
= STATUS_SUCCESS
; /* not line buffered, did read something */
649 if (Reply
->Status
== STATUS_PENDING
)
651 Console
->EchoCount
= nNumberOfCharsToRead
- i
;
655 Console
->EchoCount
= 0; /* if the client is no longer waiting on input, do not echo */
657 Reply
->Header
.MessageSize
+= i
* CharSize
;
659 ConioUnlockConsole(Console
);
660 return Reply
->Status
;
664 ConioPhysicalToLogical(PCSRSS_SCREEN_BUFFER Buff
,
670 *LogicalX
= PhysicalX
;
671 if (PhysicalY
< Buff
->ShowY
)
673 *LogicalY
= Buff
->MaxY
- Buff
->ShowY
+ PhysicalY
;
677 *LogicalY
= PhysicalY
- Buff
->ShowY
;
681 inline BOOLEAN
ConioIsEqualRect(
685 return ((Rect1
->left
== Rect2
->left
) && (Rect1
->right
== Rect2
->right
) &&
686 (Rect1
->top
== Rect2
->top
) && (Rect1
->bottom
== Rect2
->bottom
));
689 inline BOOLEAN
ConioGetIntersection(
694 if (ConioIsRectEmpty(Rect1
) ||
695 (ConioIsRectEmpty(Rect2
)) ||
696 (Rect1
->top
> Rect2
->bottom
) ||
697 (Rect1
->left
> Rect2
->right
) ||
698 (Rect1
->bottom
< Rect2
->top
) ||
699 (Rect1
->right
< Rect2
->left
))
701 /* The rectangles do not intersect */
702 ConioInitRect(Intersection
, 0, -1, 0, -1);
706 ConioInitRect(Intersection
,
707 RtlRosMax(Rect1
->top
, Rect2
->top
),
708 RtlRosMax(Rect1
->left
, Rect2
->left
),
709 RtlRosMin(Rect1
->bottom
, Rect2
->bottom
),
710 RtlRosMin(Rect1
->right
, Rect2
->right
));
715 inline BOOLEAN
ConioGetUnion(
720 if (ConioIsRectEmpty(Rect1
))
722 if (ConioIsRectEmpty(Rect2
))
724 ConioInitRect(Union
, 0, -1, 0, -1);
732 else if (ConioIsRectEmpty(Rect2
))
739 RtlRosMin(Rect1
->top
, Rect2
->top
),
740 RtlRosMin(Rect1
->left
, Rect2
->left
),
741 RtlRosMax(Rect1
->bottom
, Rect2
->bottom
),
742 RtlRosMax(Rect1
->right
, Rect2
->right
));
748 inline BOOLEAN
ConioSubtractRect(
755 if (ConioIsRectEmpty(Rect1
))
757 ConioInitRect(Subtraction
, 0, -1, 0, -1);
760 *Subtraction
= *Rect1
;
761 if (ConioGetIntersection(&tmp
, Rect1
, Rect2
))
763 if (ConioIsEqualRect(&tmp
, Subtraction
))
765 ConioInitRect(Subtraction
, 0, -1, 0, -1);
768 if ((tmp
.top
== Subtraction
->top
) && (tmp
.bottom
== Subtraction
->bottom
))
770 if (tmp
.left
== Subtraction
->left
)
772 Subtraction
->left
= tmp
.right
;
774 else if (tmp
.right
== Subtraction
->right
)
776 Subtraction
->right
= tmp
.left
;
779 else if ((tmp
.left
== Subtraction
->left
) && (tmp
.right
== Subtraction
->right
))
781 if (tmp
.top
== Subtraction
->top
)
783 Subtraction
->top
= tmp
.bottom
;
785 else if (tmp
.bottom
== Subtraction
->bottom
)
787 Subtraction
->bottom
= tmp
.top
;
796 ConioCopyRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer
,
806 DstY
= DstRegion
->top
;
807 BytesPerLine
= ConioRectWidth(DstRegion
) * 2;
809 SrcY
= (SrcRegion
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
810 DstY
= (DstRegion
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
811 SrcOffset
= (SrcY
* ScreenBuffer
->MaxX
+ SrcRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
812 DstOffset
= (DstY
* ScreenBuffer
->MaxX
+ DstRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
814 for (i
= SrcRegion
->top
; i
<= SrcRegion
->bottom
; i
++)
817 &ScreenBuffer
->Buffer
[DstOffset
],
818 &ScreenBuffer
->Buffer
[SrcOffset
],
821 if (++DstY
== ScreenBuffer
->MaxY
)
824 DstOffset
= (DstRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
828 DstOffset
+= ScreenBuffer
->MaxX
* 2;
831 if (++SrcY
== ScreenBuffer
->MaxY
)
834 SrcOffset
= (SrcRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
838 SrcOffset
+= ScreenBuffer
->MaxX
* 2;
844 ConioFillRegion(PCSRSS_CONSOLE Console
,
845 PCSRSS_SCREEN_BUFFER ScreenBuffer
,
857 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &CharInfo
->Char
.UnicodeChar
);
859 Char
= CharInfo
->Char
.AsciiChar
;
861 Y
= (Region
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
862 Offset
= (Y
* ScreenBuffer
->MaxX
+ Region
->left
+ ScreenBuffer
->ShowX
) * 2;
863 Delta
= (ScreenBuffer
->MaxX
- ConioRectWidth(Region
)) * 2;
865 for (i
= Region
->top
; i
<= Region
->bottom
; i
++)
867 for (X
= Region
->left
; X
<= Region
->right
; X
++)
869 SET_CELL_BUFFER(ScreenBuffer
, Offset
, Char
, CharInfo
->Attributes
);
871 if (++Y
== ScreenBuffer
->MaxY
)
874 Offset
= (Region
->left
+ ScreenBuffer
->ShowX
) * 2;
884 ConioInputEventToAnsi(PCSRSS_CONSOLE Console
, PINPUT_RECORD InputEvent
)
886 if (InputEvent
->EventType
== KEY_EVENT
)
888 ConsoleUnicodeCharToAnsiChar(Console
,
889 &InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
,
890 &InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
);
894 CSR_API(CsrWriteConsole
)
897 PCHAR Buffer
= (PCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
;
898 PCSRSS_SCREEN_BUFFER Buff
;
899 PCSRSS_CONSOLE Console
;
900 ULONG CharSize
= (Request
->Data
.WriteConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
902 DPRINT("CsrWriteConsole\n");
904 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
905 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
907 if (Request
->Header
.DataSize
908 < sizeof(CSRSS_WRITE_CONSOLE_REQUEST
) - 1
909 + (Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
* CharSize
))
911 DPRINT1("Invalid request size\n");
912 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
914 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
915 if (! NT_SUCCESS(Status
))
917 return Reply
->Status
= Status
;
920 if(Request
->Data
.WriteConsoleRequest
.Unicode
)
922 ConsoleUnicodeToAnsiN(Console
, Buffer
, (PWCHAR
)Buffer
, Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
);
925 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.WriteConsoleRequest
.ConsoleHandle
, &Buff
);
926 if (! NT_SUCCESS(Status
))
930 ConioUnlockConsole(Console
);
932 return Reply
->Status
= Status
;
935 Reply
->Status
= ConioWriteConsole(Console
, Buff
, Buffer
,
936 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
, TRUE
);
937 ConioUnlockScreenBuffer(Buff
);
940 ConioUnlockConsole(Console
);
943 if(NT_SUCCESS(Reply
->Status
))
945 Reply
->Data
.WriteConsoleReply
.NrCharactersWritten
= Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
;
949 Reply
->Data
.WriteConsoleReply
.NrCharactersWritten
= 0; /* FIXME - return the actual number of characters written! */
952 return Reply
->Status
= STATUS_SUCCESS
;
956 ConioDeleteScreenBuffer(Object_t
*Object
)
958 PCSRSS_SCREEN_BUFFER Buffer
= (PCSRSS_SCREEN_BUFFER
) Object
;
959 RtlDeleteCriticalSection(&Buffer
->Header
.Lock
);
960 HeapFree(Win32CsrApiHeap
, 0, Buffer
->Buffer
);
961 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
965 ConioDrawConsole(PCSRSS_CONSOLE Console
)
969 ConioInitRect(&Region
, 0, 0, Console
->Size
.Y
- 1, Console
->Size
.X
- 1);
971 ConioDrawRegion(Console
, &Region
);
976 ConioDeleteConsole(Object_t
*Object
)
978 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Object
;
981 DPRINT("ConioDeleteConsole\n");
983 /* Drain input event queue */
984 while (Console
->InputEvents
.Flink
!= &Console
->InputEvents
)
986 Event
= (ConsoleInput
*) Console
->InputEvents
.Flink
;
987 Console
->InputEvents
.Flink
= Console
->InputEvents
.Flink
->Flink
;
988 Console
->InputEvents
.Flink
->Flink
->Blink
= &Console
->InputEvents
;
989 HeapFree(Win32CsrApiHeap
, 0, Event
);
992 if (0 == --Console
->ActiveBuffer
->Header
.ReferenceCount
)
994 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
997 Console
->ActiveBuffer
= NULL
;
998 ConioCleanupConsole(Console
);
1000 CloseHandle(Console
->ActiveEvent
);
1001 RtlDeleteCriticalSection(&Console
->Header
.Lock
);
1002 RtlFreeUnicodeString(&Console
->Title
);
1003 HeapFree(Win32CsrApiHeap
, 0, Console
);
1007 CsrInitConsoleSupport(VOID
)
1009 DPRINT("CSR: CsrInitConsoleSupport()\n");
1011 /* Should call LoadKeyboardLayout */
1014 STATIC VOID FASTCALL
1015 ConioProcessChar(PCSRSS_CONSOLE Console
,
1016 ConsoleInput
*KeyEventRecord
)
1019 BOOL bClientWake
= FALSE
;
1020 ConsoleInput
*TempInput
;
1022 /* process Ctrl-C and Ctrl-Break */
1023 if (Console
->Mode
& ENABLE_PROCESSED_INPUT
&&
1024 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
&&
1025 ((KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== VK_PAUSE
) ||
1026 (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== 'C')) &&
1027 (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
)))
1029 PCSRSS_PROCESS_DATA current
;
1030 PLIST_ENTRY current_entry
;
1031 DPRINT1("Console_Api Ctrl-C\n");
1032 current_entry
= Console
->ProcessList
.Flink
;
1033 while (current_entry
!= &Console
->ProcessList
)
1035 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
1036 current_entry
= current_entry
->Flink
;
1037 ConioConsoleCtrlEvent((DWORD
)CTRL_C_EVENT
, current
);
1039 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1043 if (0 != (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
1044 & (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1045 && (VK_UP
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
1046 || VK_DOWN
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
))
1048 if (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1050 /* scroll up or down */
1051 if (NULL
== Console
)
1053 DPRINT1("No Active Console!\n");
1054 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1057 if (VK_UP
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
)
1059 /* only scroll up if there is room to scroll up into */
1060 if (Console
->ActiveBuffer
->ShowY
!= ((Console
->ActiveBuffer
->CurrentY
+ 1) %
1061 Console
->ActiveBuffer
->MaxY
))
1063 Console
->ActiveBuffer
->ShowY
= (Console
->ActiveBuffer
->ShowY
+
1064 Console
->ActiveBuffer
->MaxY
- 1) %
1065 Console
->ActiveBuffer
->MaxY
;
1068 else if (Console
->ActiveBuffer
->ShowY
!= Console
->ActiveBuffer
->CurrentY
)
1069 /* only scroll down if there is room to scroll down into */
1071 if (Console
->ActiveBuffer
->ShowY
% Console
->ActiveBuffer
->MaxY
!=
1072 Console
->ActiveBuffer
->CurrentY
)
1074 if (((Console
->ActiveBuffer
->CurrentY
+ 1) % Console
->ActiveBuffer
->MaxY
) !=
1075 (Console
->ActiveBuffer
->ShowY
+ Console
->ActiveBuffer
->MaxY
) %
1076 Console
->ActiveBuffer
->MaxY
)
1078 Console
->ActiveBuffer
->ShowY
= (Console
->ActiveBuffer
->ShowY
+ 1) %
1079 Console
->ActiveBuffer
->MaxY
;
1083 ConioDrawConsole(Console
);
1085 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1088 if (NULL
== Console
)
1090 DPRINT1("No Active Console!\n");
1091 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1095 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
)))
1097 switch(KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1100 /* first add the \r */
1101 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1102 updown
= KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
;
1103 KeyEventRecord
->Echoed
= FALSE
;
1104 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= VK_RETURN
;
1105 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\r';
1106 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1107 Console
->WaitingChars
++;
1108 KeyEventRecord
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1109 if (NULL
== KeyEventRecord
)
1111 DPRINT1("Failed to allocate KeyEventRecord\n");
1114 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1115 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
= updown
;
1116 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= 0;
1117 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualScanCode
= 0;
1118 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\n';
1119 KeyEventRecord
->Fake
= TRUE
;
1123 /* add event to the queue */
1124 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1125 Console
->WaitingChars
++;
1126 /* if line input mode is enabled, only wake the client on enter key down */
1127 if (0 == (Console
->Mode
& ENABLE_LINE_INPUT
)
1128 || Console
->EarlyReturn
1129 || ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1130 && ! KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
))
1132 if ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1134 Console
->WaitingLines
++;
1137 SetEvent(Console
->ActiveEvent
);
1139 KeyEventRecord
->Echoed
= FALSE
;
1140 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
))
1141 && '\b' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1142 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1144 /* walk the input queue looking for a char to backspace */
1145 for (TempInput
= (ConsoleInput
*) Console
->InputEvents
.Blink
;
1146 TempInput
!= (ConsoleInput
*) &Console
->InputEvents
1147 && (KEY_EVENT
== TempInput
->InputEvent
.EventType
1148 || ! TempInput
->InputEvent
.Event
.KeyEvent
.bKeyDown
1149 || '\b' == TempInput
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
);
1150 TempInput
= (ConsoleInput
*) TempInput
->ListEntry
.Blink
)
1154 /* if we found one, delete it, otherwise, wake the client */
1155 if (TempInput
!= (ConsoleInput
*) &Console
->InputEvents
)
1157 /* delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue */
1158 RemoveEntryList(&TempInput
->ListEntry
);
1159 if (TempInput
->Echoed
)
1161 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1162 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1165 HeapFree(Win32CsrApiHeap
, 0, TempInput
);
1166 RemoveEntryList(&KeyEventRecord
->ListEntry
);
1167 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1168 Console
->WaitingChars
-= 2;
1172 SetEvent(Console
->ActiveEvent
);
1177 /* echo chars if we are supposed to and client is waiting for some */
1178 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
) && Console
->EchoCount
1179 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1180 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
1181 && '\r' != KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1183 /* mark the char as already echoed */
1184 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1185 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1187 Console
->EchoCount
--;
1188 KeyEventRecord
->Echoed
= TRUE
;
1192 /* Console->WaitingChars++; */
1193 if (bClientWake
|| 0 == (Console
->Mode
& ENABLE_LINE_INPUT
))
1195 SetEvent(Console
->ActiveEvent
);
1199 STATIC DWORD FASTCALL
1200 ConioGetShiftState(PBYTE KeyState
)
1204 if (KeyState
[VK_CAPITAL
] & 1)
1205 ssOut
|= CAPSLOCK_ON
;
1207 if (KeyState
[VK_NUMLOCK
] & 1)
1208 ssOut
|= NUMLOCK_ON
;
1210 if (KeyState
[VK_SCROLL
] & 1)
1211 ssOut
|= SCROLLLOCK_ON
;
1213 if (KeyState
[VK_SHIFT
] & 0x80)
1214 ssOut
|= SHIFT_PRESSED
;
1216 if (KeyState
[VK_LCONTROL
] & 0x80)
1217 ssOut
|= LEFT_CTRL_PRESSED
;
1218 if (KeyState
[VK_RCONTROL
] & 0x80)
1219 ssOut
|= RIGHT_CTRL_PRESSED
;
1221 if (KeyState
[VK_LMENU
] & 0x80)
1222 ssOut
|= LEFT_ALT_PRESSED
;
1223 if (KeyState
[VK_RMENU
] & 0x80)
1224 ssOut
|= RIGHT_ALT_PRESSED
;
1230 ConioProcessKey(MSG
*msg
, PCSRSS_CONSOLE Console
, BOOL TextMode
)
1232 static BYTE KeyState
[256] = { 0 };
1233 /* MSDN mentions that you should use the last virtual key code received
1234 * when putting a virtual key identity to a WM_CHAR message since multiple
1235 * or translated keys may be involved. */
1236 static UINT LastVirtualKey
= 0;
1238 ConsoleInput
*ConInRec
;
1242 UINT VirtualKeyCode
;
1243 UINT VirtualScanCode
;
1246 ULONG ResultSize
= 0;
1249 VirtualScanCode
= (msg
->lParam
>> 16) & 0xff;
1250 Down
= msg
->message
== WM_KEYDOWN
|| msg
->message
== WM_CHAR
||
1251 msg
->message
== WM_SYSKEYDOWN
|| msg
->message
== WM_SYSCHAR
;
1253 GetKeyboardState(KeyState
);
1254 ShiftState
= ConioGetShiftState(KeyState
);
1256 if (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
)
1258 VirtualKeyCode
= LastVirtualKey
;
1259 UnicodeChar
= msg
->wParam
;
1266 VirtualKeyCode
= msg
->wParam
;
1267 RetChars
= ToUnicodeEx(VirtualKeyCode
,
1274 UnicodeChar
= (1 == RetChars
? Chars
[0] : 0);
1277 if (0 == ResultSize
)
1282 er
.EventType
= KEY_EVENT
;
1283 er
.Event
.KeyEvent
.bKeyDown
= Down
;
1284 er
.Event
.KeyEvent
.wRepeatCount
= RepeatCount
;
1285 er
.Event
.KeyEvent
.uChar
.UnicodeChar
= UnicodeChar
;
1286 er
.Event
.KeyEvent
.dwControlKeyState
= ShiftState
;
1287 er
.Event
.KeyEvent
.wVirtualKeyCode
= VirtualKeyCode
;
1288 er
.Event
.KeyEvent
.wVirtualScanCode
= VirtualScanCode
;
1292 if (0 != (ShiftState
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1293 && VK_TAB
== VirtualKeyCode
)
1297 TuiSwapConsole(ShiftState
& SHIFT_PRESSED
? -1 : 1);
1302 else if (VK_MENU
== VirtualKeyCode
&& ! Down
)
1304 if (TuiSwapConsole(0))
1311 if (NULL
== Console
)
1316 ConInRec
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1318 if (NULL
== ConInRec
)
1323 ConInRec
->InputEvent
= er
;
1324 ConInRec
->Fake
= UnicodeChar
&&
1325 (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
&&
1326 msg
->message
!= WM_KEYUP
&& msg
->message
!= WM_SYSKEYUP
);
1327 ConInRec
->NotChar
= (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
);
1328 ConInRec
->Echoed
= FALSE
;
1329 if (ConInRec
->NotChar
)
1330 LastVirtualKey
= msg
->wParam
;
1332 DPRINT ("csrss: %s %s %s %s %02x %02x '%c' %04x\n",
1333 Down
? "down" : "up ",
1334 (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
) ?
1336 ConInRec
->Fake
? "fake" : "real",
1337 ConInRec
->NotChar
? "notc" : "char",
1340 (AsciiChar
>= ' ') ? AsciiChar
: '.',
1343 if (! ConInRec
->Fake
|| ! ConInRec
->NotChar
)
1345 /* FIXME - convert to ascii */
1346 ConioProcessChar(Console
, ConInRec
);
1350 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1355 Console_Api(DWORD RefreshEvent
)
1357 /* keep reading events from the keyboard and stuffing them into the current
1358 console's input queue */
1361 /* This call establishes our message queue */
1362 PeekMessageW(&msg
, 0, 0, 0, PM_NOREMOVE
);
1363 /* This call registers our message queue */
1364 PrivateCsrssRegisterPrimitive();
1365 /* This call turns on the input system in win32k */
1366 PrivateCsrssAcquireOrReleaseInputOwnership(FALSE
);
1370 GetMessageW(&msg
, 0, 0, 0);
1371 TranslateMessage(&msg
);
1373 if (msg
.message
== WM_CHAR
|| msg
.message
== WM_SYSCHAR
||
1374 msg
.message
== WM_KEYDOWN
|| msg
.message
== WM_KEYUP
||
1375 msg
.message
== WM_SYSKEYDOWN
|| msg
.message
== WM_SYSKEYUP
)
1377 ConioProcessKey(&msg
, TuiGetFocusConsole(), TRUE
);
1381 PrivateCsrssAcquireOrReleaseInputOwnership(TRUE
);
1384 CSR_API(CsrGetScreenBufferInfo
)
1387 PCSRSS_SCREEN_BUFFER Buff
;
1388 PCONSOLE_SCREEN_BUFFER_INFO pInfo
;
1390 DPRINT("CsrGetScreenBufferInfo\n");
1392 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1393 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1395 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ScreenBufferInfoRequest
.ConsoleHandle
, &Buff
);
1396 if (! NT_SUCCESS(Status
))
1398 return Reply
->Status
= Status
;
1400 pInfo
= &Reply
->Data
.ScreenBufferInfoReply
.Info
;
1401 pInfo
->dwSize
.X
= Buff
->MaxX
;
1402 pInfo
->dwSize
.Y
= Buff
->MaxY
;
1403 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1404 pInfo
->dwCursorPosition
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1405 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
1406 pInfo
->srWindow
.Left
= 0;
1407 pInfo
->srWindow
.Right
= Buff
->MaxX
- 1;
1408 pInfo
->srWindow
.Top
= 0;
1409 pInfo
->srWindow
.Bottom
= Buff
->MaxY
- 1;
1410 pInfo
->dwMaximumWindowSize
.X
= Buff
->MaxX
;
1411 pInfo
->dwMaximumWindowSize
.Y
= Buff
->MaxY
;
1412 ConioUnlockScreenBuffer(Buff
);
1414 Reply
->Status
= STATUS_SUCCESS
;
1416 return Reply
->Status
;
1419 CSR_API(CsrSetCursor
)
1422 PCSRSS_CONSOLE Console
;
1423 PCSRSS_SCREEN_BUFFER Buff
;
1424 LONG OldCursorX
, OldCursorY
;
1425 LONG NewCursorX
, NewCursorY
;
1427 DPRINT("CsrSetCursor\n");
1429 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1430 if (! NT_SUCCESS(Status
))
1432 return Reply
->Status
= Status
;
1435 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1436 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1438 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
);
1439 if (! NT_SUCCESS(Status
))
1441 if (NULL
!= Console
)
1443 ConioUnlockConsole(Console
);
1445 return Reply
->Status
= Status
;
1448 NewCursorX
= Request
->Data
.SetCursorRequest
.Position
.X
;
1449 NewCursorY
= Request
->Data
.SetCursorRequest
.Position
.Y
;
1450 if (NewCursorX
< 0 || NewCursorX
>= Buff
->MaxX
||
1451 NewCursorY
< 0 || NewCursorY
>= Buff
->MaxY
)
1453 ConioUnlockScreenBuffer(Buff
);
1454 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
1456 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &OldCursorX
, &OldCursorY
);
1457 Buff
->CurrentX
= NewCursorX
+ Buff
->ShowX
;
1458 Buff
->CurrentY
= (NewCursorY
+ Buff
->ShowY
) % Buff
->MaxY
;
1459 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1461 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
1463 ConioUnlockScreenBuffer(Buff
);
1464 return Reply
->Status
= STATUS_UNSUCCESSFUL
;
1468 ConioUnlockScreenBuffer(Buff
);
1469 if (NULL
!= Console
)
1471 ConioUnlockConsole(Console
);
1474 return Reply
->Status
= STATUS_SUCCESS
;
1477 STATIC FASTCALL VOID
1478 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, COORD
*Start
, UINT Length
)
1480 if (Buff
->MaxX
<= Start
->X
+ Length
)
1482 UpdateRect
->left
= 0;
1486 UpdateRect
->left
= Start
->X
;
1488 if (Buff
->MaxX
<= Start
->X
+ Length
)
1490 UpdateRect
->right
= Buff
->MaxX
- 1;
1494 UpdateRect
->right
= Start
->X
+ Length
- 1;
1496 UpdateRect
->top
= Start
->Y
;
1497 UpdateRect
->bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->MaxX
;
1498 if (Buff
->MaxY
<= UpdateRect
->bottom
)
1500 UpdateRect
->bottom
= Buff
->MaxY
- 1;
1504 CSR_API(CsrWriteConsoleOutputChar
)
1507 PCHAR String
= (PCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
;
1509 PCSRSS_CONSOLE Console
;
1510 PCSRSS_SCREEN_BUFFER Buff
;
1511 DWORD X
, Y
, Length
, CharSize
, Written
= 0;
1514 DPRINT("CsrWriteConsoleOutputChar\n");
1516 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1517 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1519 CharSize
= (Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
1521 if (Request
->Header
.DataSize
1522 < sizeof(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR_REQUEST
) - 1
1523 + (Request
->Data
.WriteConsoleOutputCharRequest
.Length
* CharSize
))
1525 DPRINT1("Invalid request size\n");
1526 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
1529 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1530 if (! NT_SUCCESS(Status
))
1532 return Reply
->Status
= Status
;
1535 if(Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
)
1537 ConsoleUnicodeToAnsiN(Console
, String
, (PWCHAR
)String
, Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
1540 Status
= ConioLockScreenBuffer(ProcessData
,
1541 Request
->Data
.WriteConsoleOutputCharRequest
.ConsoleHandle
,
1543 if (! NT_SUCCESS(Status
))
1545 if (NULL
!= Console
)
1547 ConioUnlockConsole(Console
);
1549 return Reply
->Status
= Status
;
1552 X
= Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.X
+ Buff
->ShowX
;
1553 Y
= (Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1554 Length
= Request
->Data
.WriteConsoleOutputCharRequest
.Length
;
1555 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1558 *Buffer
= *String
++;
1561 if (++X
== Buff
->MaxX
)
1563 if (++Y
== Buff
->MaxY
)
1566 Buffer
= Buff
->Buffer
;
1572 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1574 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputCharRequest
.Coord
,
1575 Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
1576 ConioDrawRegion(Console
, &UpdateRect
);
1579 Reply
->Data
.WriteConsoleOutputCharReply
.EndCoord
.X
= X
- Buff
->ShowX
;
1580 Reply
->Data
.WriteConsoleOutputCharReply
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1582 ConioUnlockScreenBuffer(Buff
);
1583 if (NULL
!= Console
)
1585 ConioUnlockConsole(Console
);
1588 Reply
->Data
.WriteConsoleOutputCharReply
.NrCharactersWritten
= Written
;
1589 return Reply
->Status
= STATUS_SUCCESS
;
1592 CSR_API(CsrFillOutputChar
)
1595 PCSRSS_CONSOLE Console
;
1596 PCSRSS_SCREEN_BUFFER Buff
;
1597 DWORD X
, Y
, Length
, Written
= 0;
1602 DPRINT("CsrFillOutputChar\n");
1604 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1605 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1607 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1608 if (! NT_SUCCESS(Status
))
1610 return Reply
->Status
= Status
;
1613 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputRequest
.ConsoleHandle
, &Buff
);
1614 if (! NT_SUCCESS(Status
))
1616 if (NULL
!= Console
)
1618 ConioUnlockConsole(Console
);
1620 return Reply
->Status
= Status
;
1623 X
= Request
->Data
.FillOutputRequest
.Position
.X
+ Buff
->ShowX
;
1624 Y
= (Request
->Data
.FillOutputRequest
.Position
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1625 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1626 if(Request
->Data
.FillOutputRequest
.Unicode
)
1627 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &Request
->Data
.FillOutputRequest
.Char
.UnicodeChar
);
1629 Char
= Request
->Data
.FillOutputRequest
.Char
.AsciiChar
;
1630 Length
= Request
->Data
.FillOutputRequest
.Length
;
1636 if (++X
== Buff
->MaxX
)
1638 if (++Y
== Buff
->MaxY
)
1641 Buffer
= Buff
->Buffer
;
1647 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1649 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputRequest
.Position
,
1650 Request
->Data
.FillOutputRequest
.Length
);
1651 ConioDrawRegion(Console
, &UpdateRect
);
1654 ConioUnlockScreenBuffer(Buff
);
1655 if (NULL
!= Console
)
1657 ConioUnlockConsole(Console
);
1660 return Reply
->Status
;
1663 CSR_API(CsrReadInputEvent
)
1665 PLIST_ENTRY CurrentEntry
;
1666 PCSRSS_CONSOLE Console
;
1668 BOOLEAN Done
= FALSE
;
1669 ConsoleInput
*Input
;
1671 DPRINT("CsrReadInputEvent\n");
1673 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1674 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1675 Reply
->Data
.ReadInputReply
.Event
= ProcessData
->ConsoleEvent
;
1677 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadInputRequest
.ConsoleHandle
, &Console
);
1678 if (! NT_SUCCESS(Status
))
1680 return Reply
->Status
= Status
;
1683 /* only get input if there is any */
1684 CurrentEntry
= Console
->InputEvents
.Flink
;
1685 while (CurrentEntry
!= &Console
->InputEvents
)
1687 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
1688 CurrentEntry
= CurrentEntry
->Flink
;
1690 if (Done
&& !Input
->Fake
)
1692 Reply
->Data
.ReadInputReply
.MoreEvents
= TRUE
;
1696 RemoveEntryList(&Input
->ListEntry
);
1698 if (!Done
&& !Input
->Fake
)
1700 Reply
->Data
.ReadInputReply
.Input
= Input
->InputEvent
;
1701 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
1703 ConioInputEventToAnsi(Console
, &Reply
->Data
.ReadInputReply
.Input
);
1708 if (Input
->InputEvent
.EventType
== KEY_EVENT
)
1710 if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
)
1711 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
1712 && '\r' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1714 Console
->WaitingLines
--;
1716 Console
->WaitingChars
--;
1718 HeapFree(Win32CsrApiHeap
, 0, Input
);
1723 Status
= STATUS_SUCCESS
;
1724 Console
->EarlyReturn
= FALSE
;
1728 Status
= STATUS_PENDING
;
1729 Console
->EarlyReturn
= TRUE
; /* mark for early return */
1732 if (IsListEmpty(&Console
->InputEvents
))
1734 ResetEvent(Console
->ActiveEvent
);
1737 ConioUnlockConsole(Console
);
1739 return Reply
->Status
= Status
;
1742 CSR_API(CsrWriteConsoleOutputAttrib
)
1744 PCSRSS_CONSOLE Console
;
1745 PCSRSS_SCREEN_BUFFER Buff
;
1746 PUCHAR Buffer
, Attribute
;
1751 DPRINT("CsrWriteConsoleOutputAttrib\n");
1753 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1754 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1756 if (Request
->Header
.DataSize
1757 < sizeof(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB_REQUEST
) - 1
1758 + Request
->Data
.WriteConsoleOutputAttribRequest
.Length
)
1760 DPRINT1("Invalid request size\n");
1761 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
1764 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1765 if (! NT_SUCCESS(Status
))
1767 return Reply
->Status
= Status
;
1770 Status
= ConioLockScreenBuffer(ProcessData
,
1771 Request
->Data
.WriteConsoleOutputAttribRequest
.ConsoleHandle
,
1773 if (! NT_SUCCESS(Status
))
1775 if (NULL
!= Console
)
1777 ConioUnlockConsole(Console
);
1779 return Reply
->Status
= Status
;
1782 X
= Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1783 Y
= (Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1784 Length
= Request
->Data
.WriteConsoleOutputAttribRequest
.Length
;
1785 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + 1];
1786 Attribute
= (PUCHAR
)Request
->Data
.WriteConsoleOutputAttribRequest
.String
;
1789 *Buffer
= *Attribute
++;
1791 if (++X
== Buff
->MaxX
)
1793 if (++Y
== Buff
->MaxY
)
1796 Buffer
= Buff
->Buffer
+ 1;
1802 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1804 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
,
1805 Request
->Data
.WriteConsoleOutputAttribRequest
.Length
);
1806 ConioDrawRegion(Console
, &UpdateRect
);
1809 if (NULL
!= Console
)
1811 ConioUnlockConsole(Console
);
1814 Reply
->Data
.WriteConsoleOutputAttribReply
.EndCoord
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1815 Reply
->Data
.WriteConsoleOutputAttribReply
.EndCoord
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1817 ConioUnlockScreenBuffer(Buff
);
1819 return Reply
->Status
= STATUS_SUCCESS
;
1822 CSR_API(CsrFillOutputAttrib
)
1824 PCSRSS_SCREEN_BUFFER Buff
;
1830 PCSRSS_CONSOLE Console
;
1832 DPRINT("CsrFillOutputAttrib\n");
1834 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1835 if (! NT_SUCCESS(Status
))
1837 return Reply
->Status
= Status
;
1840 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1841 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1842 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputAttribRequest
.ConsoleHandle
, &Buff
);
1843 if (! NT_SUCCESS(Status
))
1845 if (NULL
!= Console
)
1847 ConioUnlockConsole(Console
);
1849 return Reply
->Status
= Status
;
1852 X
= Request
->Data
.FillOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1853 Y
= (Request
->Data
.FillOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1854 Length
= Request
->Data
.FillOutputAttribRequest
.Length
;
1855 Attr
= Request
->Data
.FillOutputAttribRequest
.Attribute
;
1856 Buffer
= &Buff
->Buffer
[(Y
* Buff
->MaxX
* 2) + (X
* 2) + 1];
1861 if (++X
== Buff
->MaxX
)
1863 if (++Y
== Buff
->MaxY
)
1866 Buffer
= Buff
->Buffer
+ 1;
1872 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1874 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputAttribRequest
.Coord
,
1875 Request
->Data
.FillOutputAttribRequest
.Length
);
1876 ConioDrawRegion(Console
, &UpdateRect
);
1879 ConioUnlockScreenBuffer(Buff
);
1880 if (NULL
!= Console
)
1882 ConioUnlockConsole(Console
);
1885 return Reply
->Status
= STATUS_SUCCESS
;
1889 CSR_API(CsrGetCursorInfo
)
1891 PCSRSS_SCREEN_BUFFER Buff
;
1894 DPRINT("CsrGetCursorInfo\n");
1896 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1897 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1899 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.GetCursorInfoRequest
.ConsoleHandle
, &Buff
);
1900 if (! NT_SUCCESS(Status
))
1902 return Reply
->Status
= Status
;
1904 Reply
->Data
.GetCursorInfoReply
.Info
= Buff
->CursorInfo
;
1905 ConioUnlockScreenBuffer(Buff
);
1907 return Reply
->Status
= STATUS_SUCCESS
;
1910 CSR_API(CsrSetCursorInfo
)
1912 PCSRSS_CONSOLE Console
;
1913 PCSRSS_SCREEN_BUFFER Buff
;
1918 DPRINT("CsrSetCursorInfo\n");
1920 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1921 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1923 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1924 if (! NT_SUCCESS(Status
))
1926 return Reply
->Status
= Status
;
1929 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorInfoRequest
.ConsoleHandle
, &Buff
);
1930 if (! NT_SUCCESS(Status
))
1932 if (NULL
!= Console
)
1934 ConioUnlockConsole(Console
);
1936 return Reply
->Status
= Status
;
1939 Size
= Request
->Data
.SetCursorInfoRequest
.Info
.dwSize
;
1940 Visible
= Request
->Data
.SetCursorInfoRequest
.Info
.bVisible
;
1950 if (Size
!= Buff
->CursorInfo
.dwSize
1951 || (Visible
&& ! Buff
->CursorInfo
.bVisible
) || (! Visible
&& Buff
->CursorInfo
.bVisible
))
1953 Buff
->CursorInfo
.dwSize
= Size
;
1954 Buff
->CursorInfo
.bVisible
= Visible
;
1956 if (NULL
!= Console
&& ! ConioSetCursorInfo(Console
, Buff
))
1958 ConioUnlockScreenBuffer(Buff
);
1959 ConioUnlockConsole(Console
);
1960 return Reply
->Status
= STATUS_UNSUCCESSFUL
;
1964 ConioUnlockScreenBuffer(Buff
);
1965 if (NULL
!= Console
)
1967 ConioUnlockConsole(Console
);
1970 return Reply
->Status
= STATUS_SUCCESS
;
1973 CSR_API(CsrSetTextAttrib
)
1976 PCSRSS_CONSOLE Console
;
1977 PCSRSS_SCREEN_BUFFER Buff
;
1978 LONG OldCursorX
, OldCursorY
;
1980 DPRINT("CsrSetTextAttrib\n");
1982 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1983 if (! NT_SUCCESS(Status
))
1985 return Reply
->Status
= Status
;
1988 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
);
1989 if (! NT_SUCCESS(Status
))
1991 if (NULL
!= Console
)
1993 ConioUnlockConsole(Console
);
1995 return Reply
->Status
= Status
;
1998 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &OldCursorX
, &OldCursorY
);
2000 Buff
->DefaultAttrib
= Request
->Data
.SetAttribRequest
.Attrib
;
2001 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
2003 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
2005 ConioUnlockScreenBuffer(Buff
);
2006 ConioUnlockConsole(Console
);
2007 return Reply
->Status
= STATUS_UNSUCCESSFUL
;
2011 ConioUnlockScreenBuffer(Buff
);
2012 if (NULL
!= Console
)
2014 ConioUnlockConsole(Console
);
2017 return Reply
->Status
= STATUS_SUCCESS
;
2020 CSR_API(CsrSetConsoleMode
)
2023 PCSRSS_CONSOLE Console
;
2024 PCSRSS_SCREEN_BUFFER Buff
;
2026 DPRINT("CsrSetConsoleMode\n");
2028 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2029 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2030 Status
= Win32CsrGetObject(ProcessData
,
2031 Request
->Data
.SetConsoleModeRequest
.ConsoleHandle
,
2032 (Object_t
**) &Console
);
2033 if (! NT_SUCCESS(Status
))
2035 return Reply
->Status
= Status
;
2038 Buff
= (PCSRSS_SCREEN_BUFFER
)Console
;
2039 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
2041 Console
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_INPUT_MODE_VALID
;
2043 else if (CONIO_SCREEN_BUFFER_MAGIC
== Console
->Header
.Type
)
2045 Buff
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_OUTPUT_MODE_VALID
;
2049 return Reply
->Status
= STATUS_INVALID_HANDLE
;
2052 Reply
->Status
= STATUS_SUCCESS
;
2054 return Reply
->Status
;
2057 CSR_API(CsrGetConsoleMode
)
2060 PCSRSS_CONSOLE Console
;
2061 PCSRSS_SCREEN_BUFFER Buff
; /* gee, I really wish I could use an anonymous union here */
2063 DPRINT("CsrGetConsoleMode\n");
2065 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2066 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2067 Status
= Win32CsrGetObject(ProcessData
, Request
->Data
.GetConsoleModeRequest
.ConsoleHandle
,
2068 (Object_t
**) &Console
);
2069 if (! NT_SUCCESS(Status
))
2071 return Reply
->Status
= Status
;
2073 Reply
->Status
= STATUS_SUCCESS
;
2074 Buff
= (PCSRSS_SCREEN_BUFFER
) Console
;
2075 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
2077 Reply
->Data
.GetConsoleModeReply
.ConsoleMode
= Console
->Mode
;
2079 else if (CONIO_SCREEN_BUFFER_MAGIC
== Buff
->Header
.Type
)
2081 Reply
->Data
.GetConsoleModeReply
.ConsoleMode
= Buff
->Mode
;
2085 Reply
->Status
= STATUS_INVALID_HANDLE
;
2088 return Reply
->Status
;
2091 CSR_API(CsrCreateScreenBuffer
)
2093 PCSRSS_CONSOLE Console
;
2094 PCSRSS_SCREEN_BUFFER Buff
;
2097 DPRINT("CsrCreateScreenBuffer\n");
2099 if (ProcessData
== NULL
)
2101 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
2104 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2105 if (! NT_SUCCESS(Status
))
2107 return Reply
->Status
= Status
;
2109 if (NULL
== Console
)
2111 return Reply
->Status
= STATUS_INVALID_HANDLE
;
2114 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2115 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2117 Buff
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(CSRSS_SCREEN_BUFFER
));
2120 Reply
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2123 Status
= CsrInitConsoleScreenBuffer(Console
, Buff
);
2124 if(! NT_SUCCESS(Status
))
2126 Reply
->Status
= Status
;
2130 Reply
->Status
= Win32CsrInsertObject(ProcessData
, &Reply
->Data
.CreateScreenBufferReply
.OutputHandle
, &Buff
->Header
);
2133 ConioUnlockConsole(Console
);
2135 return Reply
->Status
;
2138 CSR_API(CsrSetScreenBuffer
)
2141 PCSRSS_CONSOLE Console
;
2142 PCSRSS_SCREEN_BUFFER Buff
;
2144 DPRINT("CsrSetScreenBuffer\n");
2146 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2147 if (! NT_SUCCESS(Status
))
2149 return Reply
->Status
= Status
;
2151 if (NULL
== Console
)
2153 DPRINT1("Trying to set screen buffer for app without console\n");
2154 return Reply
->Status
= STATUS_INVALID_HANDLE
;
2157 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2158 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2160 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetScreenBufferRequest
.OutputHandle
, &Buff
);
2161 if (! NT_SUCCESS(Status
))
2163 ConioUnlockConsole(Console
);
2164 return Reply
->Status
;
2167 if (Buff
== Console
->ActiveBuffer
)
2169 ConioUnlockScreenBuffer(Buff
);
2170 ConioUnlockConsole(Console
);
2171 return STATUS_SUCCESS
;
2174 /* drop reference to old buffer, maybe delete */
2175 if (! InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
2177 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
2179 /* tie console to new buffer */
2180 Console
->ActiveBuffer
= Buff
;
2181 /* inc ref count on new buffer */
2182 InterlockedIncrement(&Buff
->Header
.ReferenceCount
);
2183 /* Redraw the console */
2184 ConioDrawConsole(Console
);
2186 ConioUnlockScreenBuffer(Buff
);
2187 ConioUnlockConsole(Console
);
2189 return Reply
->Status
= STATUS_SUCCESS
;
2192 CSR_API(CsrSetTitle
)
2195 PCSRSS_CONSOLE Console
;
2197 DPRINT("CsrSetTitle\n");
2199 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2200 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2202 if (Request
->Header
.DataSize
2203 < sizeof(CSRSS_SET_TITLE_REQUEST
) - 1
2204 + Request
->Data
.SetTitleRequest
.Length
)
2206 DPRINT1("Invalid request size\n");
2207 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
2210 Status
= ConioLockConsole(ProcessData
, Request
->Data
.SetTitleRequest
.Console
, &Console
);
2211 if(! NT_SUCCESS(Status
))
2213 Reply
->Status
= Status
;
2217 /* copy title to console */
2218 RtlFreeUnicodeString(&Console
->Title
);
2219 RtlCreateUnicodeString(&Console
->Title
, Request
->Data
.SetTitleRequest
.Title
);
2220 if (! ConioChangeTitle(Console
))
2222 Reply
->Status
= STATUS_UNSUCCESSFUL
;
2226 Reply
->Status
= STATUS_SUCCESS
;
2229 ConioUnlockConsole(Console
);
2231 return Reply
->Status
;
2234 CSR_API(CsrGetTitle
)
2237 PCSRSS_CONSOLE Console
;
2239 DPRINT("CsrGetTitle\n");
2241 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2242 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2243 Status
= ConioLockConsole(ProcessData
,
2244 Request
->Data
.GetTitleRequest
.ConsoleHandle
,
2246 if (! NT_SUCCESS(Status
))
2248 DPRINT1("Can't get console\n");
2249 return Reply
->Status
= Status
;
2252 /* Copy title of the console to the user title buffer */
2253 RtlZeroMemory(&Reply
->Data
.GetTitleReply
, sizeof(CSRSS_GET_TITLE_REPLY
));
2254 Reply
->Data
.GetTitleReply
.ConsoleHandle
= Request
->Data
.GetTitleRequest
.ConsoleHandle
;
2255 Reply
->Data
.GetTitleReply
.Length
= Console
->Title
.Length
;
2256 wcscpy (Reply
->Data
.GetTitleReply
.Title
, Console
->Title
.Buffer
);
2257 Reply
->Header
.MessageSize
+= Console
->Title
.Length
;
2258 Reply
->Header
.DataSize
+= Console
->Title
.Length
;
2259 Reply
->Status
= STATUS_SUCCESS
;
2261 ConioUnlockConsole(Console
);
2263 return Reply
->Status
;
2266 CSR_API(CsrWriteConsoleOutput
)
2268 SHORT i
, X
, Y
, SizeX
, SizeY
;
2269 PCSRSS_CONSOLE Console
;
2270 PCSRSS_SCREEN_BUFFER Buff
;
2272 CHAR_INFO
* CurCharInfo
;
2274 CHAR_INFO
* CharInfo
;
2281 DPRINT("CsrWriteConsoleOutput\n");
2283 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2284 if (! NT_SUCCESS(Status
))
2286 return Reply
->Status
= Status
;
2289 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2290 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2291 Status
= ConioLockScreenBuffer(ProcessData
,
2292 Request
->Data
.WriteConsoleOutputRequest
.ConsoleHandle
,
2294 if (! NT_SUCCESS(Status
))
2296 if (NULL
!= Console
)
2298 ConioUnlockConsole(Console
);
2300 return Reply
->Status
= Status
;
2303 BufferSize
= Request
->Data
.WriteConsoleOutputRequest
.BufferSize
;
2304 PSize
= BufferSize
.X
* BufferSize
.Y
* sizeof(CHAR_INFO
);
2305 BufferCoord
= Request
->Data
.WriteConsoleOutputRequest
.BufferCoord
;
2306 CharInfo
= Request
->Data
.WriteConsoleOutputRequest
.CharInfo
;
2307 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
) ||
2308 (((PVOID
)CharInfo
+ PSize
) >
2309 (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2311 ConioUnlockScreenBuffer(Buff
);
2312 ConioUnlockConsole(Console
);
2313 return Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2315 WriteRegion
.left
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
;
2316 WriteRegion
.top
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
;
2317 WriteRegion
.right
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
;
2318 WriteRegion
.bottom
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
;
2320 SizeY
= RtlRosMin(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&WriteRegion
));
2321 SizeX
= RtlRosMin(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&WriteRegion
));
2322 WriteRegion
.bottom
= WriteRegion
.top
+ SizeY
- 1;
2323 WriteRegion
.right
= WriteRegion
.left
+ SizeX
- 1;
2325 /* Make sure WriteRegion is inside the screen buffer */
2326 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2327 if (! ConioGetIntersection(&WriteRegion
, &ScreenBuffer
, &WriteRegion
))
2329 ConioUnlockScreenBuffer(Buff
);
2330 ConioUnlockConsole(Console
);
2332 /* It is okay to have a WriteRegion completely outside the screen buffer.
2333 No data is written then. */
2334 return Reply
->Status
= STATUS_SUCCESS
;
2337 for (i
= 0, Y
= WriteRegion
.top
; Y
<= WriteRegion
.bottom
; i
++, Y
++)
2339 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
2340 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ WriteRegion
.left
) * 2;
2341 for (X
= WriteRegion
.left
; X
<= WriteRegion
.right
; X
++)
2343 if (Request
->Data
.WriteConsoleOutputRequest
.Unicode
)
2346 ConsoleUnicodeCharToAnsiChar(Console
, &AsciiChar
, &CurCharInfo
->Char
.UnicodeChar
);
2347 SET_CELL_BUFFER(Buff
, Offset
, AsciiChar
, CurCharInfo
->Attributes
);
2351 SET_CELL_BUFFER(Buff
, Offset
, CurCharInfo
->Char
.AsciiChar
, CurCharInfo
->Attributes
);
2357 if (NULL
!= Console
)
2359 ConioDrawRegion(Console
, &WriteRegion
);
2362 ConioUnlockScreenBuffer(Buff
);
2363 ConioUnlockConsole(Console
);
2365 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Right
= WriteRegion
.left
+ SizeX
- 1;
2366 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Bottom
= WriteRegion
.top
+ SizeY
- 1;
2367 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Left
= WriteRegion
.left
;
2368 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Top
= WriteRegion
.top
;
2370 return Reply
->Status
= STATUS_SUCCESS
;
2373 CSR_API(CsrFlushInputBuffer
)
2375 PLIST_ENTRY CurrentEntry
;
2376 PCSRSS_CONSOLE Console
;
2377 ConsoleInput
* Input
;
2380 DPRINT("CsrFlushInputBuffer\n");
2382 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2383 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2384 Status
= ConioLockConsole(ProcessData
,
2385 Request
->Data
.FlushInputBufferRequest
.ConsoleInput
,
2387 if(! NT_SUCCESS(Status
))
2389 return Reply
->Status
= Status
;
2392 /* Discard all entries in the input event queue */
2393 while (!IsListEmpty(&Console
->InputEvents
))
2395 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
2396 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
2397 /* Destroy the event */
2398 HeapFree(Win32CsrApiHeap
, 0, Input
);
2400 ResetEvent(Console
->ActiveEvent
);
2401 Console
->WaitingChars
=0;
2403 ConioUnlockConsole(Console
);
2405 return Reply
->Status
= STATUS_SUCCESS
;
2408 CSR_API(CsrScrollConsoleScreenBuffer
)
2410 PCSRSS_CONSOLE Console
;
2411 PCSRSS_SCREEN_BUFFER Buff
;
2416 RECT ScrollRectangle
;
2421 DPRINT("CsrScrollConsoleScreenBuffer\n");
2423 ALIAS(ConsoleHandle
,Request
->Data
.ScrollConsoleScreenBufferRequest
.ConsoleHandle
);
2424 ALIAS(UseClipRectangle
,Request
->Data
.ScrollConsoleScreenBufferRequest
.UseClipRectangle
);
2425 ALIAS(DestinationOrigin
,Request
->Data
.ScrollConsoleScreenBufferRequest
.DestinationOrigin
);
2426 ALIAS(Fill
,Request
->Data
.ScrollConsoleScreenBufferRequest
.Fill
);
2428 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2429 if (! NT_SUCCESS(Status
))
2431 return Reply
->Status
= Status
;
2434 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2435 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2436 Status
= ConioLockScreenBuffer(ProcessData
, ConsoleHandle
, &Buff
);
2437 if (! NT_SUCCESS(Status
))
2439 if (NULL
!= Console
)
2441 ConioUnlockConsole(Console
);
2443 return Reply
->Status
= Status
;
2446 ScrollRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Left
;
2447 ScrollRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Top
;
2448 ScrollRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Right
;
2449 ScrollRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Bottom
;
2450 ClipRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Left
;
2451 ClipRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Top
;
2452 ClipRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Right
;
2453 ClipRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Bottom
;
2455 /* Make sure source rectangle is inside the screen buffer */
2456 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2457 if (! ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, &ScrollRectangle
))
2459 ConioUnlockScreenBuffer(Buff
);
2460 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
2463 if (UseClipRectangle
&& ! ConioGetIntersection(&SrcRegion
, &SrcRegion
, &ClipRectangle
))
2465 ConioUnlockScreenBuffer(Buff
);
2466 return Reply
->Status
= STATUS_SUCCESS
;
2470 ConioInitRect(&DstRegion
,
2471 DestinationOrigin
.Y
,
2472 DestinationOrigin
.X
,
2473 DestinationOrigin
.Y
+ ConioRectHeight(&ScrollRectangle
) - 1,
2474 DestinationOrigin
.X
+ ConioRectWidth(&ScrollRectangle
) - 1);
2476 /* Make sure destination rectangle is inside the screen buffer */
2477 if (! ConioGetIntersection(&DstRegion
, &DstRegion
, &ScreenBuffer
))
2479 ConioUnlockScreenBuffer(Buff
);
2480 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
2483 ConioCopyRegion(Buff
, &SrcRegion
, &DstRegion
);
2485 /* Get the region that should be filled with the specified character and attributes */
2489 ConioGetUnion(&FillRegion
, &SrcRegion
, &DstRegion
);
2491 if (ConioSubtractRect(&FillRegion
, &FillRegion
, &DstRegion
))
2493 /* FIXME: The subtracted rectangle is off by one line */
2494 FillRegion
.top
+= 1;
2496 ConioFillRegion(Console
, Buff
, &FillRegion
, &Fill
, Request
->Data
.ScrollConsoleScreenBufferRequest
.Unicode
);
2500 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
2502 /* Draw destination region */
2503 ConioDrawRegion(Console
, &DstRegion
);
2507 /* Draw filled region */
2508 ConioDrawRegion(Console
, &FillRegion
);
2512 ConioUnlockScreenBuffer(Buff
);
2513 if (NULL
!= Console
)
2515 ConioUnlockConsole(Console
);
2518 return Reply
->Status
= STATUS_SUCCESS
;
2521 CSR_API(CsrReadConsoleOutputChar
)
2524 PCSRSS_CONSOLE Console
;
2525 PCSRSS_SCREEN_BUFFER Buff
;
2532 DPRINT("CsrReadConsoleOutputChar\n");
2534 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2535 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
2536 ReadBuffer
= Reply
->Data
.ReadConsoleOutputCharReply
.String
;
2538 CharSize
= (Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
2540 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2541 if (! NT_SUCCESS(Status
))
2543 return Reply
->Status
= Status
;
2546 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputCharRequest
.ConsoleHandle
, &Buff
);
2547 if (! NT_SUCCESS(Status
))
2549 return Reply
->Status
= Status
;
2552 Xpos
= Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.X
+ Buff
->ShowX
;
2553 Ypos
= (Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
2555 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
; ++i
)
2557 Char
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
)];
2559 if(Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
)
2561 ConsoleAnsiCharToUnicodeChar(Console
, (WCHAR
*)ReadBuffer
, &Char
);
2562 ReadBuffer
+= sizeof(WCHAR
);
2565 *(ReadBuffer
++) = Char
;
2569 if (Xpos
== Buff
->MaxX
)
2574 if (Ypos
== Buff
->MaxY
)
2582 Reply
->Status
= STATUS_SUCCESS
;
2583 Reply
->Data
.ReadConsoleOutputCharReply
.EndCoord
.X
= Xpos
- Buff
->ShowX
;
2584 Reply
->Data
.ReadConsoleOutputCharReply
.EndCoord
.Y
= (Ypos
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
;
2585 Reply
->Header
.MessageSize
+= Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
;
2586 Reply
->Header
.DataSize
+= Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
;
2588 ConioUnlockScreenBuffer(Buff
);
2589 if (NULL
!= Console
)
2591 ConioUnlockConsole(Console
);
2594 Reply
->Data
.ReadConsoleOutputCharReply
.CharsRead
= (DWORD
)((ULONG_PTR
)ReadBuffer
- (ULONG_PTR
)Reply
->Data
.ReadConsoleOutputCharReply
.String
) / CharSize
;
2596 return Reply
->Status
;
2600 CSR_API(CsrReadConsoleOutputAttrib
)
2603 PCSRSS_SCREEN_BUFFER Buff
;
2608 DPRINT("CsrReadConsoleOutputAttrib\n");
2610 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2611 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
2612 ReadBuffer
= Reply
->Data
.ReadConsoleOutputAttribReply
.String
;
2614 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputAttribRequest
.ConsoleHandle
, &Buff
);
2615 if (! NT_SUCCESS(Status
))
2617 return Reply
->Status
= Status
;
2620 Xpos
= Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.X
+ Buff
->ShowX
;
2621 Ypos
= (Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
2623 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
; ++i
)
2625 *ReadBuffer
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
) + 1];
2630 if (Xpos
== Buff
->MaxX
)
2635 if (Ypos
== Buff
->MaxY
)
2644 Reply
->Status
= STATUS_SUCCESS
;
2645 Reply
->Data
.ReadConsoleOutputAttribReply
.EndCoord
.X
= Xpos
- Buff
->ShowX
;
2646 Reply
->Data
.ReadConsoleOutputAttribReply
.EndCoord
.Y
= (Ypos
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
;
2647 Reply
->Header
.MessageSize
+= Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
;
2648 Reply
->Header
.DataSize
+= Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
;
2650 ConioUnlockScreenBuffer(Buff
);
2652 return Reply
->Status
;
2656 CSR_API(CsrGetNumberOfConsoleInputEvents
)
2659 PCSRSS_CONSOLE Console
;
2660 PLIST_ENTRY CurrentItem
;
2662 ConsoleInput
*Input
;
2664 DPRINT("CsrGetNumberOfConsoleInputEvents\n");
2666 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2667 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
2669 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
);
2670 if (! NT_SUCCESS(Status
))
2672 return Reply
->Status
= Status
;
2675 CurrentItem
= Console
->InputEvents
.Flink
;
2678 /* If there are any events ... */
2679 while (CurrentItem
!= &Console
->InputEvents
)
2681 Input
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2682 CurrentItem
= CurrentItem
->Flink
;
2689 ConioUnlockConsole(Console
);
2691 Reply
->Status
= STATUS_SUCCESS
;
2692 Reply
->Data
.GetNumInputEventsReply
.NumInputEvents
= NumEvents
;
2694 return Reply
->Status
;
2698 CSR_API(CsrPeekConsoleInput
)
2701 PCSRSS_CONSOLE Console
;
2704 PLIST_ENTRY CurrentItem
;
2705 PINPUT_RECORD InputRecord
;
2709 DPRINT("CsrPeekConsoleInput\n");
2711 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2712 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2714 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
);
2715 if(! NT_SUCCESS(Status
))
2717 return Reply
->Status
= Status
;
2720 InputRecord
= Request
->Data
.PeekConsoleInputRequest
.InputRecord
;
2721 Length
= Request
->Data
.PeekConsoleInputRequest
.Length
;
2722 Size
= Length
* sizeof(INPUT_RECORD
);
2724 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2725 || (((PVOID
)InputRecord
+ Size
) > (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2727 ConioUnlockConsole(Console
);
2728 Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2729 return Reply
->Status
;
2734 if (! IsListEmpty(&Console
->InputEvents
))
2736 CurrentItem
= Console
->InputEvents
.Flink
;
2738 while (CurrentItem
!= &Console
->InputEvents
&& NumItems
< Length
)
2740 Item
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2744 CurrentItem
= CurrentItem
->Flink
;
2749 *InputRecord
= Item
->InputEvent
;
2751 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
2753 ConioInputEventToAnsi(Console
, InputRecord
);
2757 CurrentItem
= CurrentItem
->Flink
;
2761 ConioUnlockConsole(Console
);
2763 Reply
->Status
= STATUS_SUCCESS
;
2764 Reply
->Data
.PeekConsoleInputReply
.Length
= NumItems
;
2766 return Reply
->Status
;
2770 CSR_API(CsrReadConsoleOutput
)
2772 PCHAR_INFO CharInfo
;
2773 PCHAR_INFO CurCharInfo
;
2774 PCSRSS_SCREEN_BUFFER Buff
;
2783 DWORD i
, Y
, X
, Offset
;
2786 DPRINT("CsrReadConsoleOutput\n");
2788 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2789 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2791 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputRequest
.ConsoleHandle
, &Buff
);
2792 if (! NT_SUCCESS(Status
))
2794 return Reply
->Status
= Status
;
2797 CharInfo
= Request
->Data
.ReadConsoleOutputRequest
.CharInfo
;
2798 ReadRegion
.left
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
;
2799 ReadRegion
.top
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
;
2800 ReadRegion
.right
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
;
2801 ReadRegion
.bottom
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
;
2802 BufferSize
= Request
->Data
.ReadConsoleOutputRequest
.BufferSize
;
2803 BufferCoord
= Request
->Data
.ReadConsoleOutputRequest
.BufferCoord
;
2804 Length
= BufferSize
.X
* BufferSize
.Y
;
2805 Size
= Length
* sizeof(CHAR_INFO
);
2807 /* FIXME: Is this correct? */
2808 CodePage
= ProcessData
->Console
->OutputCodePage
;
2810 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
)
2811 || (((PVOID
)CharInfo
+ Size
) > (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2813 ConioUnlockScreenBuffer(Buff
);
2814 Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2815 return Reply
->Status
;
2818 SizeY
= RtlRosMin(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&ReadRegion
));
2819 SizeX
= RtlRosMin(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&ReadRegion
));
2820 ReadRegion
.bottom
= ReadRegion
.top
+ SizeY
;
2821 ReadRegion
.right
= ReadRegion
.left
+ SizeX
;
2823 ConioInitRect(&ScreenRect
, 0, 0, Buff
->MaxY
, Buff
->MaxX
);
2824 if (! ConioGetIntersection(&ReadRegion
, &ScreenRect
, &ReadRegion
))
2826 ConioUnlockScreenBuffer(Buff
);
2827 Reply
->Status
= STATUS_SUCCESS
;
2828 return Reply
->Status
;
2831 for (i
= 0, Y
= ReadRegion
.top
; Y
< ReadRegion
.bottom
; ++i
, ++Y
)
2833 CurCharInfo
= CharInfo
+ (i
* BufferSize
.X
);
2835 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ ReadRegion
.left
) * 2;
2836 for (X
= ReadRegion
.left
; X
< ReadRegion
.right
; ++X
)
2838 if (Request
->Data
.ReadConsoleOutputRequest
.Unicode
)
2840 MultiByteToWideChar(CodePage
, 0,
2841 (PCHAR
)&GET_CELL_BUFFER(Buff
, Offset
), 1,
2842 &CurCharInfo
->Char
.UnicodeChar
, 1);
2846 CurCharInfo
->Char
.AsciiChar
= GET_CELL_BUFFER(Buff
, Offset
);
2848 CurCharInfo
->Attributes
= GET_CELL_BUFFER(Buff
, Offset
);
2853 ConioUnlockScreenBuffer(Buff
);
2855 Reply
->Status
= STATUS_SUCCESS
;
2856 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Right
= ReadRegion
.left
+ SizeX
- 1;
2857 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Bottom
= ReadRegion
.top
+ SizeY
- 1;
2858 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Left
= ReadRegion
.left
;
2859 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Top
= ReadRegion
.top
;
2861 return Reply
->Status
;
2865 CSR_API(CsrWriteConsoleInput
)
2867 PINPUT_RECORD InputRecord
;
2868 PCSRSS_CONSOLE Console
;
2873 ConsoleInput
* Record
;
2875 DPRINT("CsrWriteConsoleInput\n");
2877 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2878 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2880 Status
= ConioLockConsole(ProcessData
, Request
->Data
.WriteConsoleInputRequest
.ConsoleHandle
, &Console
);
2881 if (! NT_SUCCESS(Status
))
2883 return Reply
->Status
= Status
;
2886 InputRecord
= Request
->Data
.WriteConsoleInputRequest
.InputRecord
;
2887 Length
= Request
->Data
.WriteConsoleInputRequest
.Length
;
2888 Size
= Length
* sizeof(INPUT_RECORD
);
2890 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2891 || (((PVOID
)InputRecord
+ Size
) > (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2893 ConioUnlockConsole(Console
);
2894 Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2895 return Reply
->Status
;
2898 for (i
= 0; i
< Length
; i
++)
2900 Record
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
2903 ConioUnlockConsole(Console
);
2904 Reply
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2905 return Reply
->Status
;
2908 Record
->Echoed
= FALSE
;
2909 Record
->Fake
= FALSE
;
2910 Record
->InputEvent
= *InputRecord
++;
2911 if (KEY_EVENT
== Record
->InputEvent
.EventType
)
2913 /* FIXME - convert from unicode to ascii!! */
2914 ConioProcessChar(Console
, Record
);
2918 ConioUnlockConsole(Console
);
2920 Reply
->Status
= STATUS_SUCCESS
;
2921 Reply
->Data
.WriteConsoleInputReply
.Length
= i
;
2923 return Reply
->Status
;
2926 /**********************************************************************
2927 * HardwareStateProperty
2930 * Set/Get the value of the HardwareState and switch
2931 * between direct video buffer ouput and GDI windowed
2934 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
2935 * object. We use the same object to reply.
2937 * ConsoleHwState has the correct size to be compatible
2938 * with NT's, but values are not.
2940 STATIC NTSTATUS FASTCALL
2941 SetConsoleHardwareState (PCSRSS_CONSOLE Console
, DWORD ConsoleHwState
)
2943 DPRINT1("Console Hardware State: %d\n", ConsoleHwState
);
2945 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED
== ConsoleHwState
)
2946 ||(CONSOLE_HARDWARE_STATE_DIRECT
== ConsoleHwState
))
2948 if (Console
->HardwareState
!= ConsoleHwState
)
2950 /* TODO: implement switching from full screen to windowed mode */
2951 /* TODO: or back; now simply store the hardware state */
2952 Console
->HardwareState
= ConsoleHwState
;
2955 return STATUS_SUCCESS
;
2958 return STATUS_INVALID_PARAMETER_3
; /* Client: (handle, set_get, [mode]) */
2961 CSR_API(CsrHardwareStateProperty
)
2963 PCSRSS_CONSOLE Console
;
2966 DPRINT("CsrHardwareStateProperty\n");
2968 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2969 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2971 Status
= ConioLockConsole(ProcessData
,
2972 Request
->Data
.ConsoleHardwareStateRequest
.ConsoleHandle
,
2974 if (! NT_SUCCESS(Status
))
2976 DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
2977 return Reply
->Status
= Status
;
2980 switch (Request
->Data
.ConsoleHardwareStateRequest
.SetGet
)
2982 case CONSOLE_HARDWARE_STATE_GET
:
2983 Reply
->Data
.ConsoleHardwareStateReply
.State
= Console
->HardwareState
;
2986 case CONSOLE_HARDWARE_STATE_SET
:
2987 DPRINT("Setting console hardware state.\n");
2988 Reply
->Status
= SetConsoleHardwareState(Console
, Request
->Data
.ConsoleHardwareStateRequest
.State
);
2992 Reply
->Status
= STATUS_INVALID_PARAMETER_2
; /* Client: (handle, [set_get], mode) */
2996 ConioUnlockConsole(Console
);
2998 return Reply
->Status
;
3001 CSR_API(CsrGetConsoleWindow
)
3003 PCSRSS_CONSOLE Console
;
3006 DPRINT("CsrGetConsoleWindow\n");
3008 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3009 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3011 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3012 if (! NT_SUCCESS(Status
))
3014 return Reply
->Status
= Status
;
3017 Reply
->Data
.GetConsoleWindowReply
.WindowHandle
= Console
->hWindow
;
3018 ConioUnlockConsole(Console
);
3020 return Reply
->Status
= STATUS_SUCCESS
;
3023 CSR_API(CsrSetConsoleIcon
)
3025 PCSRSS_CONSOLE Console
;
3028 DPRINT("CsrSetConsoleIcon\n");
3030 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3031 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3033 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3034 if (! NT_SUCCESS(Status
))
3036 return Reply
->Status
= Status
;
3039 Console
->hWindowIcon
= Request
->Data
.SetConsoleIconRequest
.WindowIcon
;
3040 Reply
->Status
= (ConioChangeIcon(Console
) ? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
3041 ConioUnlockConsole(Console
);
3043 return Reply
->Status
;
3046 CSR_API(CsrGetConsoleCodePage
)
3048 PCSRSS_CONSOLE Console
;
3051 DPRINT("CsrGetConsoleCodePage\n");
3053 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3054 if (! NT_SUCCESS(Status
))
3056 return Reply
->Status
= Status
;
3059 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3060 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3061 Reply
->Data
.GetConsoleCodePage
.CodePage
= Console
->CodePage
;
3062 ConioUnlockConsole(Console
);
3063 return Reply
->Status
= STATUS_SUCCESS
;
3066 CSR_API(CsrSetConsoleCodePage
)
3068 PCSRSS_CONSOLE Console
;
3071 DPRINT("CsrSetConsoleCodePage\n");
3073 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3074 if (! NT_SUCCESS(Status
))
3076 return Reply
->Status
= Status
;
3079 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3080 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3081 if (IsValidCodePage(Request
->Data
.SetConsoleCodePage
.CodePage
))
3083 Console
->CodePage
= Request
->Data
.SetConsoleCodePage
.CodePage
;
3084 ConioUnlockConsole(Console
);
3085 return Reply
->Status
= STATUS_SUCCESS
;
3087 ConioUnlockConsole(Console
);
3088 return Reply
->Status
= STATUS_UNSUCCESSFUL
;
3091 CSR_API(CsrGetConsoleOutputCodePage
)
3093 PCSRSS_CONSOLE Console
;
3096 DPRINT("CsrGetConsoleOutputCodePage\n");
3098 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3099 if (! NT_SUCCESS(Status
))
3101 return Reply
->Status
= Status
;
3104 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3105 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3106 Reply
->Data
.GetConsoleOutputCodePage
.CodePage
= Console
->OutputCodePage
;
3107 ConioUnlockConsole(Console
);
3108 return Reply
->Status
= STATUS_SUCCESS
;
3111 CSR_API(CsrSetConsoleOutputCodePage
)
3113 PCSRSS_CONSOLE Console
;
3116 DPRINT("CsrSetConsoleOutputCodePage\n");
3118 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3119 if (! NT_SUCCESS(Status
))
3121 return Reply
->Status
= Status
;
3124 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3125 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3126 if (IsValidCodePage(Request
->Data
.SetConsoleOutputCodePage
.CodePage
))
3128 Console
->OutputCodePage
= Request
->Data
.SetConsoleOutputCodePage
.CodePage
;
3129 ConioUnlockConsole(Console
);
3130 return Reply
->Status
= STATUS_SUCCESS
;
3132 ConioUnlockConsole(Console
);
3133 return Reply
->Status
= STATUS_UNSUCCESSFUL
;