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 OBJECT_ATTRIBUTES ObjectAttributes
;
87 ClientId
.UniqueThread
= NULL
;
88 ClientId
.UniqueProcess
= ProcessData
->ProcessId
;
89 InitializeObjectAttributes(&ObjectAttributes
,
95 /* using OpenProcess is not optimal due to HANDLE vs. DWORD PIDs... */
96 Status
= NtOpenProcess(&Process
,
100 if (!NT_SUCCESS(Status
))
102 DPRINT1("Failed for handle duplication, Status: 0x%x\n", Status
);
106 DPRINT("ConioConsoleCtrlEvent Process Handle = %x\n", Process
);
108 Thread
= CreateRemoteThread(Process
, NULL
, 0,
109 (LPTHREAD_START_ROUTINE
) ProcessData
->CtrlDispatcher
,
110 (PVOID
) Event
, 0, NULL
);
113 DPRINT1("Failed thread creation\n");
114 CloseHandle(Process
);
118 CloseHandle(Process
);
122 #define GET_CELL_BUFFER(b,o)\
125 #define SET_CELL_BUFFER(b,o,c,a)\
126 (b)->Buffer[(o)++]=(c),\
127 (b)->Buffer[(o)++]=(a)
130 ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff
)
132 DWORD Offset
= 2 * (Buff
->CurrentY
* Buff
->MaxX
);
135 for (Pos
= 0; Pos
< Buff
->MaxX
; Pos
++)
137 /* Fill the cell: Offset is incremented by the macro */
138 SET_CELL_BUFFER(Buff
, Offset
, ' ', Buff
->DefaultAttrib
);
142 STATIC NTSTATUS FASTCALL
143 CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console
,
144 PCSRSS_SCREEN_BUFFER Buffer
)
146 Buffer
->Header
.Type
= CONIO_SCREEN_BUFFER_MAGIC
;
147 Buffer
->Header
.ReferenceCount
= 0;
148 Buffer
->MaxX
= Console
->Size
.X
;
149 Buffer
->MaxY
= Console
->Size
.Y
;
152 Buffer
->Buffer
= HeapAlloc(Win32CsrApiHeap
, 0, Buffer
->MaxX
* Buffer
->MaxY
* 2);
153 if (NULL
== Buffer
->Buffer
)
155 return STATUS_INSUFFICIENT_RESOURCES
;
157 InitializeCriticalSection(&Buffer
->Header
.Lock
);
158 ConioInitScreenBuffer(Console
, Buffer
);
159 /* initialize buffer to be empty with default attributes */
160 for (Buffer
->CurrentY
= 0 ; Buffer
->CurrentY
< Buffer
->MaxY
; Buffer
->CurrentY
++)
162 ClearLineBuffer(Buffer
);
164 Buffer
->CursorInfo
.bVisible
= TRUE
;
165 Buffer
->CursorInfo
.dwSize
= 5;
166 Buffer
->Mode
= ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
;
167 Buffer
->CurrentX
= 0;
168 Buffer
->CurrentY
= 0;
170 return STATUS_SUCCESS
;
173 STATIC NTSTATUS STDCALL
174 CsrInitConsole(PCSRSS_CONSOLE Console
)
177 SECURITY_ATTRIBUTES SecurityAttributes
;
178 PCSRSS_SCREEN_BUFFER NewBuffer
;
181 Console
->Title
.MaximumLength
= Console
->Title
.Length
= 0;
182 Console
->Title
.Buffer
= NULL
;
184 RtlCreateUnicodeString(&Console
->Title
, L
"Command Prompt");
186 Console
->Header
.ReferenceCount
= 0;
187 Console
->WaitingChars
= 0;
188 Console
->WaitingLines
= 0;
189 Console
->EchoCount
= 0;
190 Console
->Header
.Type
= CONIO_CONSOLE_MAGIC
;
191 Console
->Mode
= ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_PROCESSED_INPUT
| ENABLE_MOUSE_INPUT
;
192 Console
->EarlyReturn
= FALSE
;
193 Console
->ActiveBuffer
= NULL
;
194 InitializeListHead(&Console
->InputEvents
);
195 InitializeListHead(&Console
->ProcessList
);
197 Console
->CodePage
= GetOEMCP();
198 Console
->OutputCodePage
= GetOEMCP();
200 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
201 SecurityAttributes
.lpSecurityDescriptor
= NULL
;
202 SecurityAttributes
.bInheritHandle
= TRUE
;
204 Console
->ActiveEvent
= CreateEventW(&SecurityAttributes
, TRUE
, FALSE
, NULL
);
205 if (NULL
== Console
->ActiveEvent
)
207 RtlFreeUnicodeString(&Console
->Title
);
208 return STATUS_UNSUCCESSFUL
;
210 Console
->PrivateData
= NULL
;
211 InitializeCriticalSection(&Console
->Header
.Lock
);
212 GuiMode
= DtbgIsDesktopVisible();
215 Status
= TuiInitConsole(Console
);
216 if (! NT_SUCCESS(Status
))
218 DPRINT1("Failed to open text-mode console, switching to gui-mode\n");
224 Status
= GuiInitConsole(Console
);
225 if (! NT_SUCCESS(Status
))
227 RtlFreeUnicodeString(&Console
->Title
);
228 DeleteCriticalSection(&Console
->Header
.Lock
);
229 CloseHandle(Console
->ActiveEvent
);
234 NewBuffer
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(CSRSS_SCREEN_BUFFER
));
235 if (NULL
== NewBuffer
)
237 ConioCleanupConsole(Console
);
238 RtlFreeUnicodeString(&Console
->Title
);
239 DeleteCriticalSection(&Console
->Header
.Lock
);
240 CloseHandle(Console
->ActiveEvent
);
241 return STATUS_INSUFFICIENT_RESOURCES
;
243 Status
= CsrInitConsoleScreenBuffer(Console
, NewBuffer
);
244 if (! NT_SUCCESS(Status
))
246 ConioCleanupConsole(Console
);
247 RtlFreeUnicodeString(&Console
->Title
);
248 DeleteCriticalSection(&Console
->Header
.Lock
);
249 CloseHandle(Console
->ActiveEvent
);
250 HeapFree(Win32CsrApiHeap
, 0, NewBuffer
);
253 Console
->ActiveBuffer
= NewBuffer
;
254 /* add a reference count because the buffer is tied to the console */
255 Console
->ActiveBuffer
->Header
.ReferenceCount
++;
256 /* make console active, and insert into console list */
257 /* copy buffer contents to screen */
258 ConioDrawConsole(Console
);
260 return STATUS_SUCCESS
;
264 CSR_API(CsrAllocConsole
)
266 PCSRSS_CONSOLE Console
;
267 OBJECT_ATTRIBUTES ObjectAttributes
;
272 DPRINT("CsrAllocConsole\n");
274 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
275 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
277 if (ProcessData
== NULL
)
279 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
282 if (ProcessData
->Console
)
284 Reply
->Status
= STATUS_INVALID_PARAMETER
;
285 return STATUS_INVALID_PARAMETER
;
288 Reply
->Status
= STATUS_SUCCESS
;
289 Console
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(CSRSS_CONSOLE
));
292 Reply
->Status
= STATUS_NO_MEMORY
;
293 return STATUS_NO_MEMORY
;
295 Reply
->Status
= CsrInitConsole(Console
);
296 if (! NT_SUCCESS(Reply
->Status
))
298 HeapFree(Win32CsrApiHeap
, 0, Console
);
299 return Reply
->Status
;
301 ProcessData
->Console
= Console
;
302 Reply
->Data
.AllocConsoleReply
.Console
= Console
;
304 /* add a reference count because the process is tied to the console */
305 Console
->Header
.ReferenceCount
++;
306 Status
= Win32CsrInsertObject(ProcessData
, &Reply
->Data
.AllocConsoleReply
.InputHandle
, &Console
->Header
);
307 if (! NT_SUCCESS(Status
))
309 ConioDeleteConsole((Object_t
*) Console
);
310 ProcessData
->Console
= 0;
311 return Reply
->Status
= Status
;
313 Status
= Win32CsrInsertObject(ProcessData
, &Reply
->Data
.AllocConsoleReply
.OutputHandle
, &Console
->ActiveBuffer
->Header
);
314 if (!NT_SUCCESS(Status
))
316 Console
->Header
.ReferenceCount
--;
317 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.InputHandle
);
318 ProcessData
->Console
= 0;
319 return Reply
->Status
= Status
;
322 ClientId
.UniqueThread
= NULL
;
323 ClientId
.UniqueProcess
= ProcessData
->ProcessId
;
324 InitializeObjectAttributes(&ObjectAttributes
,
330 /* using OpenProcess is not optimal due to HANDLE vs. DWORD PIDs... */
331 Status
= NtOpenProcess(&Process
,
335 if (!NT_SUCCESS(Status
))
337 DPRINT1("NtOpenProcess() failed for handle duplication, Status: 0x%x\n", Status
);
338 Console
->Header
.ReferenceCount
--;
339 ProcessData
->Console
= 0;
340 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.OutputHandle
);
341 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.InputHandle
);
342 Reply
->Status
= Status
;
346 if (! DuplicateHandle(GetCurrentProcess(), ProcessData
->Console
->ActiveEvent
,
347 Process
, &ProcessData
->ConsoleEvent
, EVENT_ALL_ACCESS
, FALSE
, 0))
349 DPRINT1("DuplicateHandle() failed: %d\n", GetLastError
);
350 CloseHandle(Process
);
351 Console
->Header
.ReferenceCount
--;
352 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.OutputHandle
);
353 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.InputHandle
);
354 ProcessData
->Console
= 0;
355 Reply
->Status
= Status
;
358 CloseHandle(Process
);
359 ProcessData
->CtrlDispatcher
= Request
->Data
.AllocConsoleRequest
.CtrlDispatcher
;
360 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
361 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ProcessEntry
);
363 return STATUS_SUCCESS
;
366 CSR_API(CsrFreeConsole
)
368 PCSRSS_CONSOLE Console
;
370 DPRINT("CsrFreeConsole\n");
372 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
373 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
375 if (ProcessData
== NULL
|| ProcessData
->Console
== NULL
)
377 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
380 Console
= ProcessData
->Console
;
381 Console
->Header
.ReferenceCount
--;
382 ProcessData
->Console
= NULL
;
383 if (0 == Console
->Header
.ReferenceCount
)
385 ConioDeleteConsole((Object_t
*) Console
);
388 return STATUS_SUCCESS
;
392 ConioNextLine(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, UINT
*ScrolledLines
)
394 /* slide the viewable screen */
395 if (((Buff
->CurrentY
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
) == Buff
->MaxY
- 1)
397 if (++Buff
->ShowY
== Buff
->MaxY
)
403 if (++Buff
->CurrentY
== Buff
->MaxY
)
407 ClearLineBuffer(Buff
);
408 UpdateRect
->left
= 0;
409 UpdateRect
->right
= Buff
->MaxX
- 1;
410 if (UpdateRect
->top
== Buff
->CurrentY
)
412 if (++UpdateRect
->top
== Buff
->MaxY
)
417 UpdateRect
->bottom
= Buff
->CurrentY
;
420 STATIC NTSTATUS FASTCALL
421 ConioWriteConsole(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
,
422 CHAR
*Buffer
, DWORD Length
, BOOL Attrib
)
427 LONG CursorStartX
, CursorStartY
;
430 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &CursorStartX
, &CursorStartY
);
431 UpdateRect
.left
= Buff
->MaxX
;
432 UpdateRect
.top
= Buff
->CurrentY
;
433 UpdateRect
.right
= -1;
434 UpdateRect
.bottom
= Buff
->CurrentY
;
437 for (i
= 0; i
< Length
; i
++)
439 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
442 if (Buffer
[i
] == '\n')
445 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
449 else if (Buffer
[i
] == '\b')
451 /* Only handle BS if we're not on the first pos of the first line */
452 if (0 != Buff
->CurrentX
|| Buff
->ShowY
!= Buff
->CurrentY
)
454 if (0 == Buff
->CurrentX
)
456 /* slide virtual position up */
457 Buff
->CurrentX
= Buff
->MaxX
- 1;
458 if (0 == Buff
->CurrentY
)
460 Buff
->CurrentY
= Buff
->MaxY
;
466 if ((0 == UpdateRect
.top
&& UpdateRect
.bottom
< Buff
->CurrentY
)
467 || (0 != UpdateRect
.top
&& Buff
->CurrentY
< UpdateRect
.top
))
469 UpdateRect
.top
= Buff
->CurrentY
;
476 Offset
= 2 * ((Buff
->CurrentY
* Buff
->MaxX
) + Buff
->CurrentX
);
477 SET_CELL_BUFFER(Buff
, Offset
, ' ', Buff
->DefaultAttrib
);
478 UpdateRect
.left
= RtlRosMin(UpdateRect
.left
, Buff
->CurrentX
);
479 UpdateRect
.right
= RtlRosMax(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
484 else if (Buffer
[i
] == '\r')
487 UpdateRect
.left
= RtlRosMin(UpdateRect
.left
, Buff
->CurrentX
);
488 UpdateRect
.right
= RtlRosMax(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
492 else if (Buffer
[i
] == '\t')
496 UpdateRect
.left
= RtlRosMin(UpdateRect
.left
, Buff
->CurrentX
);
497 EndX
= (Buff
->CurrentX
+ 8) & ~7;
498 if (EndX
> Buff
->MaxX
)
502 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
503 while (Buff
->CurrentX
< EndX
)
505 Buff
->Buffer
[Offset
] = ' ';
509 UpdateRect
.right
= RtlRosMax(UpdateRect
.right
, (LONG
) Buff
->CurrentX
- 1);
510 if (Buff
->CurrentX
== Buff
->MaxX
)
512 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
515 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
525 UpdateRect
.left
= RtlRosMin(UpdateRect
.left
, Buff
->CurrentX
);
526 UpdateRect
.right
= RtlRosMax(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
527 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
528 Buff
->Buffer
[Offset
++] = Buffer
[i
];
531 Buff
->Buffer
[Offset
] = Buff
->DefaultAttrib
;
534 if (Buff
->CurrentX
== Buff
->MaxX
)
536 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
539 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
543 Buff
->CurrentX
= CursorStartX
;
548 ConioPhysicalToLogical(Buff
, UpdateRect
.left
, UpdateRect
.top
, &(UpdateRect
.left
),
550 ConioPhysicalToLogical(Buff
, UpdateRect
.right
, UpdateRect
.bottom
, &(UpdateRect
.right
),
551 &(UpdateRect
.bottom
));
552 if (! ConioIsRectEmpty(&UpdateRect
) && NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
554 ConioWriteStream(Console
, &UpdateRect
, CursorStartX
, CursorStartY
, ScrolledLines
,
558 return STATUS_SUCCESS
;
561 CSR_API(CsrReadConsole
)
563 PLIST_ENTRY CurrentEntry
;
566 PWCHAR UnicodeBuffer
;
568 ULONG nNumberOfCharsToRead
, CharSize
;
569 PCSRSS_CONSOLE Console
;
572 DPRINT("CsrReadConsole\n");
574 CharSize
= (Request
->Data
.ReadConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
576 /* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */
577 nNumberOfCharsToRead
= min(Request
->Data
.ReadConsoleRequest
.NrCharactersToRead
, CSRSS_MAX_READ_CONSOLE_REQUEST
/ CharSize
);
578 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
579 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
581 Buffer
= Reply
->Data
.ReadConsoleReply
.Buffer
;
582 UnicodeBuffer
= (PWCHAR
)Buffer
;
583 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadConsoleRequest
.ConsoleHandle
,
585 if (! NT_SUCCESS(Status
))
587 return Reply
->Status
= Status
;
589 Reply
->Data
.ReadConsoleReply
.EventHandle
= ProcessData
->ConsoleEvent
;
590 for (i
= 0; i
< nNumberOfCharsToRead
&& Console
->InputEvents
.Flink
!= &Console
->InputEvents
; i
++)
592 /* remove input event from queue */
593 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
594 if (IsListEmpty(&Console
->InputEvents
))
597 ResetEvent(Console
->ActiveEvent
);
599 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
601 /* only pay attention to valid ascii chars, on key down */
602 if (KEY_EVENT
== Input
->InputEvent
.EventType
603 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
604 && Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
!= '\0')
606 /* backspace handling */
607 if ('\b' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
609 /* echo if it has not already been done, and either we or the client has chars to be deleted */
611 && (0 != i
|| Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
))
613 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
614 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
618 i
-= 2; /* if we already have something to return, just back it up by 2 */
621 { /* otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer */
622 Console
->WaitingChars
--;
623 ConioUnlockConsole(Console
);
624 HeapFree(Win32CsrApiHeap
, 0, Input
);
625 Reply
->Data
.ReadConsoleReply
.NrCharactersRead
= 0;
626 Reply
->Status
= STATUS_NOTIFY_CLEANUP
;
627 return STATUS_NOTIFY_CLEANUP
;
629 Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
--;
630 Input
->Echoed
= TRUE
; /* mark as echoed so we don't echo it below */
632 /* do not copy backspace to buffer */
635 if(Request
->Data
.ReadConsoleRequest
.Unicode
)
636 UnicodeBuffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
; /* FIXME */
638 Buffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
;
640 /* echo to screen if enabled and we did not already echo the char */
641 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
)
643 && '\r' != Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
645 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
646 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
653 Console
->WaitingChars
--;
654 HeapFree(Win32CsrApiHeap
, 0, Input
);
656 Reply
->Data
.ReadConsoleReply
.NrCharactersRead
= i
;
659 Reply
->Status
= STATUS_PENDING
; /* we didn't read anything */
661 else if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
))
663 if (0 == Console
->WaitingLines
||
664 (Request
->Data
.ReadConsoleRequest
.Unicode
? (L
'\n' != UnicodeBuffer
[i
- 1]) : ('\n' != Buffer
[i
- 1])))
666 Reply
->Status
= STATUS_PENDING
; /* line buffered, didn't get a complete line */
670 Console
->WaitingLines
--;
671 Reply
->Status
= STATUS_SUCCESS
; /* line buffered, did get a complete line */
676 Reply
->Status
= STATUS_SUCCESS
; /* not line buffered, did read something */
679 if (Reply
->Status
== STATUS_PENDING
)
681 Console
->EchoCount
= nNumberOfCharsToRead
- i
;
685 Console
->EchoCount
= 0; /* if the client is no longer waiting on input, do not echo */
687 Reply
->Header
.MessageSize
+= i
* CharSize
;
689 ConioUnlockConsole(Console
);
690 return Reply
->Status
;
694 ConioPhysicalToLogical(PCSRSS_SCREEN_BUFFER Buff
,
700 *LogicalX
= PhysicalX
;
701 if (PhysicalY
< Buff
->ShowY
)
703 *LogicalY
= Buff
->MaxY
- Buff
->ShowY
+ PhysicalY
;
707 *LogicalY
= PhysicalY
- Buff
->ShowY
;
711 inline BOOLEAN
ConioIsEqualRect(
715 return ((Rect1
->left
== Rect2
->left
) && (Rect1
->right
== Rect2
->right
) &&
716 (Rect1
->top
== Rect2
->top
) && (Rect1
->bottom
== Rect2
->bottom
));
719 inline BOOLEAN
ConioGetIntersection(
724 if (ConioIsRectEmpty(Rect1
) ||
725 (ConioIsRectEmpty(Rect2
)) ||
726 (Rect1
->top
> Rect2
->bottom
) ||
727 (Rect1
->left
> Rect2
->right
) ||
728 (Rect1
->bottom
< Rect2
->top
) ||
729 (Rect1
->right
< Rect2
->left
))
731 /* The rectangles do not intersect */
732 ConioInitRect(Intersection
, 0, -1, 0, -1);
736 ConioInitRect(Intersection
,
737 RtlRosMax(Rect1
->top
, Rect2
->top
),
738 RtlRosMax(Rect1
->left
, Rect2
->left
),
739 RtlRosMin(Rect1
->bottom
, Rect2
->bottom
),
740 RtlRosMin(Rect1
->right
, Rect2
->right
));
745 inline BOOLEAN
ConioGetUnion(
750 if (ConioIsRectEmpty(Rect1
))
752 if (ConioIsRectEmpty(Rect2
))
754 ConioInitRect(Union
, 0, -1, 0, -1);
762 else if (ConioIsRectEmpty(Rect2
))
769 RtlRosMin(Rect1
->top
, Rect2
->top
),
770 RtlRosMin(Rect1
->left
, Rect2
->left
),
771 RtlRosMax(Rect1
->bottom
, Rect2
->bottom
),
772 RtlRosMax(Rect1
->right
, Rect2
->right
));
778 inline BOOLEAN
ConioSubtractRect(
785 if (ConioIsRectEmpty(Rect1
))
787 ConioInitRect(Subtraction
, 0, -1, 0, -1);
790 *Subtraction
= *Rect1
;
791 if (ConioGetIntersection(&tmp
, Rect1
, Rect2
))
793 if (ConioIsEqualRect(&tmp
, Subtraction
))
795 ConioInitRect(Subtraction
, 0, -1, 0, -1);
798 if ((tmp
.top
== Subtraction
->top
) && (tmp
.bottom
== Subtraction
->bottom
))
800 if (tmp
.left
== Subtraction
->left
)
802 Subtraction
->left
= tmp
.right
;
804 else if (tmp
.right
== Subtraction
->right
)
806 Subtraction
->right
= tmp
.left
;
809 else if ((tmp
.left
== Subtraction
->left
) && (tmp
.right
== Subtraction
->right
))
811 if (tmp
.top
== Subtraction
->top
)
813 Subtraction
->top
= tmp
.bottom
;
815 else if (tmp
.bottom
== Subtraction
->bottom
)
817 Subtraction
->bottom
= tmp
.top
;
826 ConioCopyRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer
,
836 DstY
= DstRegion
->top
;
837 BytesPerLine
= ConioRectWidth(DstRegion
) * 2;
839 SrcY
= (SrcRegion
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
840 DstY
= (DstRegion
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
841 SrcOffset
= (SrcY
* ScreenBuffer
->MaxX
+ SrcRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
842 DstOffset
= (DstY
* ScreenBuffer
->MaxX
+ DstRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
844 for (i
= SrcRegion
->top
; i
<= SrcRegion
->bottom
; i
++)
847 &ScreenBuffer
->Buffer
[DstOffset
],
848 &ScreenBuffer
->Buffer
[SrcOffset
],
851 if (++DstY
== ScreenBuffer
->MaxY
)
854 DstOffset
= (DstRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
858 DstOffset
+= ScreenBuffer
->MaxX
* 2;
861 if (++SrcY
== ScreenBuffer
->MaxY
)
864 SrcOffset
= (SrcRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
868 SrcOffset
+= ScreenBuffer
->MaxX
* 2;
874 ConioFillRegion(PCSRSS_CONSOLE Console
,
875 PCSRSS_SCREEN_BUFFER ScreenBuffer
,
887 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &CharInfo
->Char
.UnicodeChar
);
889 Char
= CharInfo
->Char
.AsciiChar
;
891 Y
= (Region
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
892 Offset
= (Y
* ScreenBuffer
->MaxX
+ Region
->left
+ ScreenBuffer
->ShowX
) * 2;
893 Delta
= (ScreenBuffer
->MaxX
- ConioRectWidth(Region
)) * 2;
895 for (i
= Region
->top
; i
<= Region
->bottom
; i
++)
897 for (X
= Region
->left
; X
<= Region
->right
; X
++)
899 SET_CELL_BUFFER(ScreenBuffer
, Offset
, Char
, CharInfo
->Attributes
);
901 if (++Y
== ScreenBuffer
->MaxY
)
904 Offset
= (Region
->left
+ ScreenBuffer
->ShowX
) * 2;
914 ConioInputEventToAnsi(PCSRSS_CONSOLE Console
, PINPUT_RECORD InputEvent
)
916 if (InputEvent
->EventType
== KEY_EVENT
)
918 ConsoleUnicodeCharToAnsiChar(Console
,
919 &InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
,
920 &InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
);
924 CSR_API(CsrWriteConsole
)
927 PCHAR Buffer
= (PCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
;
928 PCSRSS_SCREEN_BUFFER Buff
;
929 PCSRSS_CONSOLE Console
;
930 ULONG CharSize
= (Request
->Data
.WriteConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
932 DPRINT("CsrWriteConsole\n");
934 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
935 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
937 if (Request
->Header
.DataSize
938 < sizeof(CSRSS_WRITE_CONSOLE_REQUEST
) - 1
939 + (Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
* CharSize
))
941 DPRINT1("Invalid request size\n");
942 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
944 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
945 if (! NT_SUCCESS(Status
))
947 return Reply
->Status
= Status
;
950 if(Request
->Data
.WriteConsoleRequest
.Unicode
)
952 ConsoleUnicodeToAnsiN(Console
, Buffer
, (PWCHAR
)Buffer
, Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
);
955 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.WriteConsoleRequest
.ConsoleHandle
, &Buff
);
956 if (! NT_SUCCESS(Status
))
960 ConioUnlockConsole(Console
);
962 return Reply
->Status
= Status
;
965 Reply
->Status
= ConioWriteConsole(Console
, Buff
, Buffer
,
966 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
, TRUE
);
967 ConioUnlockScreenBuffer(Buff
);
970 ConioUnlockConsole(Console
);
973 if(NT_SUCCESS(Reply
->Status
))
975 Reply
->Data
.WriteConsoleReply
.NrCharactersWritten
= Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
;
979 Reply
->Data
.WriteConsoleReply
.NrCharactersWritten
= 0; /* FIXME - return the actual number of characters written! */
982 return Reply
->Status
= STATUS_SUCCESS
;
986 ConioDeleteScreenBuffer(Object_t
*Object
)
988 PCSRSS_SCREEN_BUFFER Buffer
= (PCSRSS_SCREEN_BUFFER
) Object
;
989 DeleteCriticalSection(&Buffer
->Header
.Lock
);
990 HeapFree(Win32CsrApiHeap
, 0, Buffer
->Buffer
);
991 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
995 ConioDrawConsole(PCSRSS_CONSOLE Console
)
999 ConioInitRect(&Region
, 0, 0, Console
->Size
.Y
- 1, Console
->Size
.X
- 1);
1001 ConioDrawRegion(Console
, &Region
);
1006 ConioDeleteConsole(Object_t
*Object
)
1008 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Object
;
1009 ConsoleInput
*Event
;
1011 DPRINT("ConioDeleteConsole\n");
1013 /* Drain input event queue */
1014 while (Console
->InputEvents
.Flink
!= &Console
->InputEvents
)
1016 Event
= (ConsoleInput
*) Console
->InputEvents
.Flink
;
1017 Console
->InputEvents
.Flink
= Console
->InputEvents
.Flink
->Flink
;
1018 Console
->InputEvents
.Flink
->Flink
->Blink
= &Console
->InputEvents
;
1019 HeapFree(Win32CsrApiHeap
, 0, Event
);
1022 if (0 == --Console
->ActiveBuffer
->Header
.ReferenceCount
)
1024 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
1027 Console
->ActiveBuffer
= NULL
;
1028 ConioCleanupConsole(Console
);
1030 CloseHandle(Console
->ActiveEvent
);
1031 DeleteCriticalSection(&Console
->Header
.Lock
);
1032 RtlFreeUnicodeString(&Console
->Title
);
1033 HeapFree(Win32CsrApiHeap
, 0, Console
);
1037 CsrInitConsoleSupport(VOID
)
1039 DPRINT("CSR: CsrInitConsoleSupport()\n");
1041 /* Should call LoadKeyboardLayout */
1044 STATIC VOID FASTCALL
1045 ConioProcessChar(PCSRSS_CONSOLE Console
,
1046 ConsoleInput
*KeyEventRecord
)
1049 BOOL bClientWake
= FALSE
;
1050 ConsoleInput
*TempInput
;
1052 /* process Ctrl-C and Ctrl-Break */
1053 if (Console
->Mode
& ENABLE_PROCESSED_INPUT
&&
1054 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
&&
1055 ((KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== VK_PAUSE
) ||
1056 (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== 'C')) &&
1057 (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
)))
1059 PCSRSS_PROCESS_DATA current
;
1060 PLIST_ENTRY current_entry
;
1061 DPRINT1("Console_Api Ctrl-C\n");
1062 current_entry
= Console
->ProcessList
.Flink
;
1063 while (current_entry
!= &Console
->ProcessList
)
1065 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
1066 current_entry
= current_entry
->Flink
;
1067 ConioConsoleCtrlEvent((DWORD
)CTRL_C_EVENT
, current
);
1069 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1073 if (0 != (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
1074 & (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1075 && (VK_UP
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
1076 || VK_DOWN
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
))
1078 if (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1080 /* scroll up or down */
1081 if (NULL
== Console
)
1083 DPRINT1("No Active Console!\n");
1084 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1087 if (VK_UP
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
)
1089 /* only scroll up if there is room to scroll up into */
1090 if (Console
->ActiveBuffer
->ShowY
!= ((Console
->ActiveBuffer
->CurrentY
+ 1) %
1091 Console
->ActiveBuffer
->MaxY
))
1093 Console
->ActiveBuffer
->ShowY
= (Console
->ActiveBuffer
->ShowY
+
1094 Console
->ActiveBuffer
->MaxY
- 1) %
1095 Console
->ActiveBuffer
->MaxY
;
1098 else if (Console
->ActiveBuffer
->ShowY
!= Console
->ActiveBuffer
->CurrentY
)
1099 /* only scroll down if there is room to scroll down into */
1101 if (Console
->ActiveBuffer
->ShowY
% Console
->ActiveBuffer
->MaxY
!=
1102 Console
->ActiveBuffer
->CurrentY
)
1104 if (((Console
->ActiveBuffer
->CurrentY
+ 1) % Console
->ActiveBuffer
->MaxY
) !=
1105 (Console
->ActiveBuffer
->ShowY
+ Console
->ActiveBuffer
->MaxY
) %
1106 Console
->ActiveBuffer
->MaxY
)
1108 Console
->ActiveBuffer
->ShowY
= (Console
->ActiveBuffer
->ShowY
+ 1) %
1109 Console
->ActiveBuffer
->MaxY
;
1113 ConioDrawConsole(Console
);
1115 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1118 if (NULL
== Console
)
1120 DPRINT1("No Active Console!\n");
1121 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1125 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
)))
1127 switch(KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1130 /* first add the \r */
1131 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1132 updown
= KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
;
1133 KeyEventRecord
->Echoed
= FALSE
;
1134 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= VK_RETURN
;
1135 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\r';
1136 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1137 Console
->WaitingChars
++;
1138 KeyEventRecord
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1139 if (NULL
== KeyEventRecord
)
1141 DPRINT1("Failed to allocate KeyEventRecord\n");
1144 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1145 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
= updown
;
1146 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= 0;
1147 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualScanCode
= 0;
1148 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\n';
1149 KeyEventRecord
->Fake
= TRUE
;
1153 /* add event to the queue */
1154 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1155 Console
->WaitingChars
++;
1156 /* if line input mode is enabled, only wake the client on enter key down */
1157 if (0 == (Console
->Mode
& ENABLE_LINE_INPUT
)
1158 || Console
->EarlyReturn
1159 || ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1160 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
))
1162 if ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1164 Console
->WaitingLines
++;
1167 SetEvent(Console
->ActiveEvent
);
1169 KeyEventRecord
->Echoed
= FALSE
;
1170 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
))
1171 && '\b' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1172 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1174 /* walk the input queue looking for a char to backspace */
1175 for (TempInput
= (ConsoleInput
*) Console
->InputEvents
.Blink
;
1176 TempInput
!= (ConsoleInput
*) &Console
->InputEvents
1177 && (KEY_EVENT
== TempInput
->InputEvent
.EventType
1178 || ! TempInput
->InputEvent
.Event
.KeyEvent
.bKeyDown
1179 || '\b' == TempInput
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
);
1180 TempInput
= (ConsoleInput
*) TempInput
->ListEntry
.Blink
)
1184 /* if we found one, delete it, otherwise, wake the client */
1185 if (TempInput
!= (ConsoleInput
*) &Console
->InputEvents
)
1187 /* delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue */
1188 RemoveEntryList(&TempInput
->ListEntry
);
1189 if (TempInput
->Echoed
)
1191 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1192 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1195 HeapFree(Win32CsrApiHeap
, 0, TempInput
);
1196 RemoveEntryList(&KeyEventRecord
->ListEntry
);
1197 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1198 Console
->WaitingChars
-= 2;
1202 SetEvent(Console
->ActiveEvent
);
1207 /* echo chars if we are supposed to and client is waiting for some */
1208 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
) && Console
->EchoCount
1209 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1210 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
1211 && '\r' != KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1213 /* mark the char as already echoed */
1214 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1215 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1217 Console
->EchoCount
--;
1218 KeyEventRecord
->Echoed
= TRUE
;
1222 /* Console->WaitingChars++; */
1223 if (bClientWake
|| 0 == (Console
->Mode
& ENABLE_LINE_INPUT
))
1225 SetEvent(Console
->ActiveEvent
);
1229 STATIC DWORD FASTCALL
1230 ConioGetShiftState(PBYTE KeyState
)
1234 if (KeyState
[VK_CAPITAL
] & 1)
1235 ssOut
|= CAPSLOCK_ON
;
1237 if (KeyState
[VK_NUMLOCK
] & 1)
1238 ssOut
|= NUMLOCK_ON
;
1240 if (KeyState
[VK_SCROLL
] & 1)
1241 ssOut
|= SCROLLLOCK_ON
;
1243 if (KeyState
[VK_SHIFT
] & 0x80)
1244 ssOut
|= SHIFT_PRESSED
;
1246 if (KeyState
[VK_LCONTROL
] & 0x80)
1247 ssOut
|= LEFT_CTRL_PRESSED
;
1248 if (KeyState
[VK_RCONTROL
] & 0x80)
1249 ssOut
|= RIGHT_CTRL_PRESSED
;
1251 if (KeyState
[VK_LMENU
] & 0x80)
1252 ssOut
|= LEFT_ALT_PRESSED
;
1253 if (KeyState
[VK_RMENU
] & 0x80)
1254 ssOut
|= RIGHT_ALT_PRESSED
;
1260 ConioProcessKey(MSG
*msg
, PCSRSS_CONSOLE Console
, BOOL TextMode
)
1262 static BYTE KeyState
[256] = { 0 };
1263 /* MSDN mentions that you should use the last virtual key code received
1264 * when putting a virtual key identity to a WM_CHAR message since multiple
1265 * or translated keys may be involved. */
1266 static UINT LastVirtualKey
= 0;
1268 ConsoleInput
*ConInRec
;
1272 UINT VirtualKeyCode
;
1273 UINT VirtualScanCode
;
1276 ULONG ResultSize
= 0;
1279 VirtualScanCode
= (msg
->lParam
>> 16) & 0xff;
1280 Down
= msg
->message
== WM_KEYDOWN
|| msg
->message
== WM_CHAR
||
1281 msg
->message
== WM_SYSKEYDOWN
|| msg
->message
== WM_SYSCHAR
;
1283 GetKeyboardState(KeyState
);
1284 ShiftState
= ConioGetShiftState(KeyState
);
1286 if (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
)
1288 VirtualKeyCode
= LastVirtualKey
;
1289 UnicodeChar
= msg
->wParam
;
1296 VirtualKeyCode
= msg
->wParam
;
1297 RetChars
= ToUnicodeEx(VirtualKeyCode
,
1304 UnicodeChar
= (1 == RetChars
? Chars
[0] : 0);
1307 if (0 == ResultSize
)
1312 er
.EventType
= KEY_EVENT
;
1313 er
.Event
.KeyEvent
.bKeyDown
= Down
;
1314 er
.Event
.KeyEvent
.wRepeatCount
= RepeatCount
;
1315 er
.Event
.KeyEvent
.uChar
.UnicodeChar
= UnicodeChar
;
1316 er
.Event
.KeyEvent
.dwControlKeyState
= ShiftState
;
1317 er
.Event
.KeyEvent
.wVirtualKeyCode
= VirtualKeyCode
;
1318 er
.Event
.KeyEvent
.wVirtualScanCode
= VirtualScanCode
;
1322 if (0 != (ShiftState
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1323 && VK_TAB
== VirtualKeyCode
)
1327 TuiSwapConsole(ShiftState
& SHIFT_PRESSED
? -1 : 1);
1332 else if (VK_MENU
== VirtualKeyCode
&& ! Down
)
1334 if (TuiSwapConsole(0))
1341 if (NULL
== Console
)
1346 ConInRec
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1348 if (NULL
== ConInRec
)
1353 ConInRec
->InputEvent
= er
;
1354 ConInRec
->Fake
= UnicodeChar
&&
1355 (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
&&
1356 msg
->message
!= WM_KEYUP
&& msg
->message
!= WM_SYSKEYUP
);
1357 ConInRec
->NotChar
= (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
);
1358 ConInRec
->Echoed
= FALSE
;
1359 if (ConInRec
->NotChar
)
1360 LastVirtualKey
= msg
->wParam
;
1362 DPRINT ("csrss: %s %s %s %s %02x %02x '%c' %04x\n",
1363 Down
? "down" : "up ",
1364 (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
) ?
1366 ConInRec
->Fake
? "fake" : "real",
1367 ConInRec
->NotChar
? "notc" : "char",
1370 (AsciiChar
>= ' ') ? AsciiChar
: '.',
1373 if (! ConInRec
->Fake
|| ! ConInRec
->NotChar
)
1375 /* FIXME - convert to ascii */
1376 ConioProcessChar(Console
, ConInRec
);
1380 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1385 Console_Api(DWORD RefreshEvent
)
1387 /* keep reading events from the keyboard and stuffing them into the current
1388 console's input queue */
1391 /* This call establishes our message queue */
1392 PeekMessageW(&msg
, 0, 0, 0, PM_NOREMOVE
);
1393 /* This call registers our message queue */
1394 PrivateCsrssRegisterPrimitive();
1395 /* This call turns on the input system in win32k */
1396 PrivateCsrssAcquireOrReleaseInputOwnership(FALSE
);
1400 GetMessageW(&msg
, 0, 0, 0);
1401 TranslateMessage(&msg
);
1403 if (msg
.message
== WM_CHAR
|| msg
.message
== WM_SYSCHAR
||
1404 msg
.message
== WM_KEYDOWN
|| msg
.message
== WM_KEYUP
||
1405 msg
.message
== WM_SYSKEYDOWN
|| msg
.message
== WM_SYSKEYUP
)
1407 ConioProcessKey(&msg
, TuiGetFocusConsole(), TRUE
);
1411 PrivateCsrssAcquireOrReleaseInputOwnership(TRUE
);
1414 CSR_API(CsrGetScreenBufferInfo
)
1417 PCSRSS_SCREEN_BUFFER Buff
;
1418 PCONSOLE_SCREEN_BUFFER_INFO pInfo
;
1420 DPRINT("CsrGetScreenBufferInfo\n");
1422 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1423 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1425 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ScreenBufferInfoRequest
.ConsoleHandle
, &Buff
);
1426 if (! NT_SUCCESS(Status
))
1428 return Reply
->Status
= Status
;
1430 pInfo
= &Reply
->Data
.ScreenBufferInfoReply
.Info
;
1431 pInfo
->dwSize
.X
= Buff
->MaxX
;
1432 pInfo
->dwSize
.Y
= Buff
->MaxY
;
1433 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1434 pInfo
->dwCursorPosition
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1435 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
1436 pInfo
->srWindow
.Left
= 0;
1437 pInfo
->srWindow
.Right
= Buff
->MaxX
- 1;
1438 pInfo
->srWindow
.Top
= 0;
1439 pInfo
->srWindow
.Bottom
= Buff
->MaxY
- 1;
1440 pInfo
->dwMaximumWindowSize
.X
= Buff
->MaxX
;
1441 pInfo
->dwMaximumWindowSize
.Y
= Buff
->MaxY
;
1442 ConioUnlockScreenBuffer(Buff
);
1444 Reply
->Status
= STATUS_SUCCESS
;
1446 return Reply
->Status
;
1449 CSR_API(CsrSetCursor
)
1452 PCSRSS_CONSOLE Console
;
1453 PCSRSS_SCREEN_BUFFER Buff
;
1454 LONG OldCursorX
, OldCursorY
;
1455 LONG NewCursorX
, NewCursorY
;
1457 DPRINT("CsrSetCursor\n");
1459 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1460 if (! NT_SUCCESS(Status
))
1462 return Reply
->Status
= Status
;
1465 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1466 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1468 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
);
1469 if (! NT_SUCCESS(Status
))
1471 if (NULL
!= Console
)
1473 ConioUnlockConsole(Console
);
1475 return Reply
->Status
= Status
;
1478 NewCursorX
= Request
->Data
.SetCursorRequest
.Position
.X
;
1479 NewCursorY
= Request
->Data
.SetCursorRequest
.Position
.Y
;
1480 if (NewCursorX
< 0 || NewCursorX
>= Buff
->MaxX
||
1481 NewCursorY
< 0 || NewCursorY
>= Buff
->MaxY
)
1483 ConioUnlockScreenBuffer(Buff
);
1484 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
1486 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &OldCursorX
, &OldCursorY
);
1487 Buff
->CurrentX
= NewCursorX
+ Buff
->ShowX
;
1488 Buff
->CurrentY
= (NewCursorY
+ Buff
->ShowY
) % Buff
->MaxY
;
1489 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1491 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
1493 ConioUnlockScreenBuffer(Buff
);
1494 return Reply
->Status
= STATUS_UNSUCCESSFUL
;
1498 ConioUnlockScreenBuffer(Buff
);
1499 if (NULL
!= Console
)
1501 ConioUnlockConsole(Console
);
1504 return Reply
->Status
= STATUS_SUCCESS
;
1507 STATIC FASTCALL VOID
1508 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, COORD
*Start
, UINT Length
)
1510 if (Buff
->MaxX
<= Start
->X
+ Length
)
1512 UpdateRect
->left
= 0;
1516 UpdateRect
->left
= Start
->X
;
1518 if (Buff
->MaxX
<= Start
->X
+ Length
)
1520 UpdateRect
->right
= Buff
->MaxX
- 1;
1524 UpdateRect
->right
= Start
->X
+ Length
- 1;
1526 UpdateRect
->top
= Start
->Y
;
1527 UpdateRect
->bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->MaxX
;
1528 if (Buff
->MaxY
<= UpdateRect
->bottom
)
1530 UpdateRect
->bottom
= Buff
->MaxY
- 1;
1534 CSR_API(CsrWriteConsoleOutputChar
)
1537 PCHAR String
= (PCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
;
1539 PCSRSS_CONSOLE Console
;
1540 PCSRSS_SCREEN_BUFFER Buff
;
1541 DWORD X
, Y
, Length
, CharSize
, Written
= 0;
1544 DPRINT("CsrWriteConsoleOutputChar\n");
1546 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1547 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1549 CharSize
= (Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
1551 if (Request
->Header
.DataSize
1552 < sizeof(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR_REQUEST
) - 1
1553 + (Request
->Data
.WriteConsoleOutputCharRequest
.Length
* CharSize
))
1555 DPRINT1("Invalid request size\n");
1556 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
1559 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1560 if (! NT_SUCCESS(Status
))
1562 return Reply
->Status
= Status
;
1565 if(Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
)
1567 ConsoleUnicodeToAnsiN(Console
, String
, (PWCHAR
)String
, Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
1570 Status
= ConioLockScreenBuffer(ProcessData
,
1571 Request
->Data
.WriteConsoleOutputCharRequest
.ConsoleHandle
,
1573 if (! NT_SUCCESS(Status
))
1575 if (NULL
!= Console
)
1577 ConioUnlockConsole(Console
);
1579 return Reply
->Status
= Status
;
1582 X
= Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.X
+ Buff
->ShowX
;
1583 Y
= (Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1584 Length
= Request
->Data
.WriteConsoleOutputCharRequest
.Length
;
1585 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1588 *Buffer
= *String
++;
1591 if (++X
== Buff
->MaxX
)
1593 if (++Y
== Buff
->MaxY
)
1596 Buffer
= Buff
->Buffer
;
1602 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1604 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputCharRequest
.Coord
,
1605 Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
1606 ConioDrawRegion(Console
, &UpdateRect
);
1609 Reply
->Data
.WriteConsoleOutputCharReply
.EndCoord
.X
= X
- Buff
->ShowX
;
1610 Reply
->Data
.WriteConsoleOutputCharReply
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1612 ConioUnlockScreenBuffer(Buff
);
1613 if (NULL
!= Console
)
1615 ConioUnlockConsole(Console
);
1618 Reply
->Data
.WriteConsoleOutputCharReply
.NrCharactersWritten
= Written
;
1619 return Reply
->Status
= STATUS_SUCCESS
;
1622 CSR_API(CsrFillOutputChar
)
1625 PCSRSS_CONSOLE Console
;
1626 PCSRSS_SCREEN_BUFFER Buff
;
1627 DWORD X
, Y
, Length
, Written
= 0;
1632 DPRINT("CsrFillOutputChar\n");
1634 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1635 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1637 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1638 if (! NT_SUCCESS(Status
))
1640 return Reply
->Status
= Status
;
1643 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputRequest
.ConsoleHandle
, &Buff
);
1644 if (! NT_SUCCESS(Status
))
1646 if (NULL
!= Console
)
1648 ConioUnlockConsole(Console
);
1650 return Reply
->Status
= Status
;
1653 X
= Request
->Data
.FillOutputRequest
.Position
.X
+ Buff
->ShowX
;
1654 Y
= (Request
->Data
.FillOutputRequest
.Position
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1655 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1656 if(Request
->Data
.FillOutputRequest
.Unicode
)
1657 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &Request
->Data
.FillOutputRequest
.Char
.UnicodeChar
);
1659 Char
= Request
->Data
.FillOutputRequest
.Char
.AsciiChar
;
1660 Length
= Request
->Data
.FillOutputRequest
.Length
;
1666 if (++X
== Buff
->MaxX
)
1668 if (++Y
== Buff
->MaxY
)
1671 Buffer
= Buff
->Buffer
;
1677 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1679 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputRequest
.Position
,
1680 Request
->Data
.FillOutputRequest
.Length
);
1681 ConioDrawRegion(Console
, &UpdateRect
);
1684 ConioUnlockScreenBuffer(Buff
);
1685 if (NULL
!= Console
)
1687 ConioUnlockConsole(Console
);
1690 return Reply
->Status
;
1693 CSR_API(CsrReadInputEvent
)
1695 PLIST_ENTRY CurrentEntry
;
1696 PCSRSS_CONSOLE Console
;
1698 BOOLEAN Done
= FALSE
;
1699 ConsoleInput
*Input
;
1701 DPRINT("CsrReadInputEvent\n");
1703 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1704 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1705 Reply
->Data
.ReadInputReply
.Event
= ProcessData
->ConsoleEvent
;
1707 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadInputRequest
.ConsoleHandle
, &Console
);
1708 if (! NT_SUCCESS(Status
))
1710 return Reply
->Status
= Status
;
1713 /* only get input if there is any */
1714 CurrentEntry
= Console
->InputEvents
.Flink
;
1715 while (CurrentEntry
!= &Console
->InputEvents
)
1717 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
1718 CurrentEntry
= CurrentEntry
->Flink
;
1720 if (Done
&& !Input
->Fake
)
1722 Reply
->Data
.ReadInputReply
.MoreEvents
= TRUE
;
1726 RemoveEntryList(&Input
->ListEntry
);
1728 if (!Done
&& !Input
->Fake
)
1730 Reply
->Data
.ReadInputReply
.Input
= Input
->InputEvent
;
1731 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
1733 ConioInputEventToAnsi(Console
, &Reply
->Data
.ReadInputReply
.Input
);
1738 if (Input
->InputEvent
.EventType
== KEY_EVENT
)
1740 if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
)
1741 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
1742 && '\r' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1744 Console
->WaitingLines
--;
1746 Console
->WaitingChars
--;
1748 HeapFree(Win32CsrApiHeap
, 0, Input
);
1753 Status
= STATUS_SUCCESS
;
1754 Console
->EarlyReturn
= FALSE
;
1758 Status
= STATUS_PENDING
;
1759 Console
->EarlyReturn
= TRUE
; /* mark for early return */
1762 if (IsListEmpty(&Console
->InputEvents
))
1764 ResetEvent(Console
->ActiveEvent
);
1767 ConioUnlockConsole(Console
);
1769 return Reply
->Status
= Status
;
1772 CSR_API(CsrWriteConsoleOutputAttrib
)
1774 PCSRSS_CONSOLE Console
;
1775 PCSRSS_SCREEN_BUFFER Buff
;
1776 PUCHAR Buffer
, Attribute
;
1781 DPRINT("CsrWriteConsoleOutputAttrib\n");
1783 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1784 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1786 if (Request
->Header
.DataSize
1787 < sizeof(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB_REQUEST
) - 1
1788 + Request
->Data
.WriteConsoleOutputAttribRequest
.Length
)
1790 DPRINT1("Invalid request size\n");
1791 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
1794 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1795 if (! NT_SUCCESS(Status
))
1797 return Reply
->Status
= Status
;
1800 Status
= ConioLockScreenBuffer(ProcessData
,
1801 Request
->Data
.WriteConsoleOutputAttribRequest
.ConsoleHandle
,
1803 if (! NT_SUCCESS(Status
))
1805 if (NULL
!= Console
)
1807 ConioUnlockConsole(Console
);
1809 return Reply
->Status
= Status
;
1812 X
= Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1813 Y
= (Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1814 Length
= Request
->Data
.WriteConsoleOutputAttribRequest
.Length
;
1815 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + 1];
1816 Attribute
= (PUCHAR
)Request
->Data
.WriteConsoleOutputAttribRequest
.String
;
1819 *Buffer
= *Attribute
++;
1821 if (++X
== Buff
->MaxX
)
1823 if (++Y
== Buff
->MaxY
)
1826 Buffer
= Buff
->Buffer
+ 1;
1832 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1834 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
,
1835 Request
->Data
.WriteConsoleOutputAttribRequest
.Length
);
1836 ConioDrawRegion(Console
, &UpdateRect
);
1839 if (NULL
!= Console
)
1841 ConioUnlockConsole(Console
);
1844 Reply
->Data
.WriteConsoleOutputAttribReply
.EndCoord
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1845 Reply
->Data
.WriteConsoleOutputAttribReply
.EndCoord
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1847 ConioUnlockScreenBuffer(Buff
);
1849 return Reply
->Status
= STATUS_SUCCESS
;
1852 CSR_API(CsrFillOutputAttrib
)
1854 PCSRSS_SCREEN_BUFFER Buff
;
1860 PCSRSS_CONSOLE Console
;
1862 DPRINT("CsrFillOutputAttrib\n");
1864 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1865 if (! NT_SUCCESS(Status
))
1867 return Reply
->Status
= Status
;
1870 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1871 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1872 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputAttribRequest
.ConsoleHandle
, &Buff
);
1873 if (! NT_SUCCESS(Status
))
1875 if (NULL
!= Console
)
1877 ConioUnlockConsole(Console
);
1879 return Reply
->Status
= Status
;
1882 X
= Request
->Data
.FillOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1883 Y
= (Request
->Data
.FillOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1884 Length
= Request
->Data
.FillOutputAttribRequest
.Length
;
1885 Attr
= Request
->Data
.FillOutputAttribRequest
.Attribute
;
1886 Buffer
= &Buff
->Buffer
[(Y
* Buff
->MaxX
* 2) + (X
* 2) + 1];
1891 if (++X
== Buff
->MaxX
)
1893 if (++Y
== Buff
->MaxY
)
1896 Buffer
= Buff
->Buffer
+ 1;
1902 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1904 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputAttribRequest
.Coord
,
1905 Request
->Data
.FillOutputAttribRequest
.Length
);
1906 ConioDrawRegion(Console
, &UpdateRect
);
1909 ConioUnlockScreenBuffer(Buff
);
1910 if (NULL
!= Console
)
1912 ConioUnlockConsole(Console
);
1915 return Reply
->Status
= STATUS_SUCCESS
;
1919 CSR_API(CsrGetCursorInfo
)
1921 PCSRSS_SCREEN_BUFFER Buff
;
1924 DPRINT("CsrGetCursorInfo\n");
1926 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1927 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1929 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.GetCursorInfoRequest
.ConsoleHandle
, &Buff
);
1930 if (! NT_SUCCESS(Status
))
1932 return Reply
->Status
= Status
;
1934 Reply
->Data
.GetCursorInfoReply
.Info
= Buff
->CursorInfo
;
1935 ConioUnlockScreenBuffer(Buff
);
1937 return Reply
->Status
= STATUS_SUCCESS
;
1940 CSR_API(CsrSetCursorInfo
)
1942 PCSRSS_CONSOLE Console
;
1943 PCSRSS_SCREEN_BUFFER Buff
;
1948 DPRINT("CsrSetCursorInfo\n");
1950 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1951 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1953 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1954 if (! NT_SUCCESS(Status
))
1956 return Reply
->Status
= Status
;
1959 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorInfoRequest
.ConsoleHandle
, &Buff
);
1960 if (! NT_SUCCESS(Status
))
1962 if (NULL
!= Console
)
1964 ConioUnlockConsole(Console
);
1966 return Reply
->Status
= Status
;
1969 Size
= Request
->Data
.SetCursorInfoRequest
.Info
.dwSize
;
1970 Visible
= Request
->Data
.SetCursorInfoRequest
.Info
.bVisible
;
1980 if (Size
!= Buff
->CursorInfo
.dwSize
1981 || (Visible
&& ! Buff
->CursorInfo
.bVisible
) || (! Visible
&& Buff
->CursorInfo
.bVisible
))
1983 Buff
->CursorInfo
.dwSize
= Size
;
1984 Buff
->CursorInfo
.bVisible
= Visible
;
1986 if (NULL
!= Console
&& ! ConioSetCursorInfo(Console
, Buff
))
1988 ConioUnlockScreenBuffer(Buff
);
1989 ConioUnlockConsole(Console
);
1990 return Reply
->Status
= STATUS_UNSUCCESSFUL
;
1994 ConioUnlockScreenBuffer(Buff
);
1995 if (NULL
!= Console
)
1997 ConioUnlockConsole(Console
);
2000 return Reply
->Status
= STATUS_SUCCESS
;
2003 CSR_API(CsrSetTextAttrib
)
2006 PCSRSS_CONSOLE Console
;
2007 PCSRSS_SCREEN_BUFFER Buff
;
2008 LONG OldCursorX
, OldCursorY
;
2010 DPRINT("CsrSetTextAttrib\n");
2012 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2013 if (! NT_SUCCESS(Status
))
2015 return Reply
->Status
= Status
;
2018 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
);
2019 if (! NT_SUCCESS(Status
))
2021 if (NULL
!= Console
)
2023 ConioUnlockConsole(Console
);
2025 return Reply
->Status
= Status
;
2028 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &OldCursorX
, &OldCursorY
);
2030 Buff
->DefaultAttrib
= Request
->Data
.SetAttribRequest
.Attrib
;
2031 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
2033 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
2035 ConioUnlockScreenBuffer(Buff
);
2036 ConioUnlockConsole(Console
);
2037 return Reply
->Status
= STATUS_UNSUCCESSFUL
;
2041 ConioUnlockScreenBuffer(Buff
);
2042 if (NULL
!= Console
)
2044 ConioUnlockConsole(Console
);
2047 return Reply
->Status
= STATUS_SUCCESS
;
2050 CSR_API(CsrSetConsoleMode
)
2053 PCSRSS_CONSOLE Console
;
2054 PCSRSS_SCREEN_BUFFER Buff
;
2056 DPRINT("CsrSetConsoleMode\n");
2058 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2059 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2060 Status
= Win32CsrGetObject(ProcessData
,
2061 Request
->Data
.SetConsoleModeRequest
.ConsoleHandle
,
2062 (Object_t
**) &Console
);
2063 if (! NT_SUCCESS(Status
))
2065 return Reply
->Status
= Status
;
2068 Buff
= (PCSRSS_SCREEN_BUFFER
)Console
;
2069 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
2071 Console
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_INPUT_MODE_VALID
;
2073 else if (CONIO_SCREEN_BUFFER_MAGIC
== Console
->Header
.Type
)
2075 Buff
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_OUTPUT_MODE_VALID
;
2079 return Reply
->Status
= STATUS_INVALID_HANDLE
;
2082 Reply
->Status
= STATUS_SUCCESS
;
2084 return Reply
->Status
;
2087 CSR_API(CsrGetConsoleMode
)
2090 PCSRSS_CONSOLE Console
;
2091 PCSRSS_SCREEN_BUFFER Buff
; /* gee, I really wish I could use an anonymous union here */
2093 DPRINT("CsrGetConsoleMode\n");
2095 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2096 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2097 Status
= Win32CsrGetObject(ProcessData
, Request
->Data
.GetConsoleModeRequest
.ConsoleHandle
,
2098 (Object_t
**) &Console
);
2099 if (! NT_SUCCESS(Status
))
2101 return Reply
->Status
= Status
;
2103 Reply
->Status
= STATUS_SUCCESS
;
2104 Buff
= (PCSRSS_SCREEN_BUFFER
) Console
;
2105 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
2107 Reply
->Data
.GetConsoleModeReply
.ConsoleMode
= Console
->Mode
;
2109 else if (CONIO_SCREEN_BUFFER_MAGIC
== Buff
->Header
.Type
)
2111 Reply
->Data
.GetConsoleModeReply
.ConsoleMode
= Buff
->Mode
;
2115 Reply
->Status
= STATUS_INVALID_HANDLE
;
2118 return Reply
->Status
;
2121 CSR_API(CsrCreateScreenBuffer
)
2123 PCSRSS_CONSOLE Console
;
2124 PCSRSS_SCREEN_BUFFER Buff
;
2127 DPRINT("CsrCreateScreenBuffer\n");
2129 if (ProcessData
== NULL
)
2131 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
2134 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2135 if (! NT_SUCCESS(Status
))
2137 return Reply
->Status
= Status
;
2139 if (NULL
== Console
)
2141 return Reply
->Status
= STATUS_INVALID_HANDLE
;
2144 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2145 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2147 Buff
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(CSRSS_SCREEN_BUFFER
));
2150 Reply
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2153 Status
= CsrInitConsoleScreenBuffer(Console
, Buff
);
2154 if(! NT_SUCCESS(Status
))
2156 Reply
->Status
= Status
;
2160 Reply
->Status
= Win32CsrInsertObject(ProcessData
, &Reply
->Data
.CreateScreenBufferReply
.OutputHandle
, &Buff
->Header
);
2163 ConioUnlockConsole(Console
);
2165 return Reply
->Status
;
2168 CSR_API(CsrSetScreenBuffer
)
2171 PCSRSS_CONSOLE Console
;
2172 PCSRSS_SCREEN_BUFFER Buff
;
2174 DPRINT("CsrSetScreenBuffer\n");
2176 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2177 if (! NT_SUCCESS(Status
))
2179 return Reply
->Status
= Status
;
2181 if (NULL
== Console
)
2183 DPRINT1("Trying to set screen buffer for app without console\n");
2184 return Reply
->Status
= STATUS_INVALID_HANDLE
;
2187 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2188 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2190 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetScreenBufferRequest
.OutputHandle
, &Buff
);
2191 if (! NT_SUCCESS(Status
))
2193 ConioUnlockConsole(Console
);
2194 return Reply
->Status
;
2197 if (Buff
== Console
->ActiveBuffer
)
2199 ConioUnlockScreenBuffer(Buff
);
2200 ConioUnlockConsole(Console
);
2201 return STATUS_SUCCESS
;
2204 /* drop reference to old buffer, maybe delete */
2205 if (! InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
2207 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
2209 /* tie console to new buffer */
2210 Console
->ActiveBuffer
= Buff
;
2211 /* inc ref count on new buffer */
2212 InterlockedIncrement(&Buff
->Header
.ReferenceCount
);
2213 /* Redraw the console */
2214 ConioDrawConsole(Console
);
2216 ConioUnlockScreenBuffer(Buff
);
2217 ConioUnlockConsole(Console
);
2219 return Reply
->Status
= STATUS_SUCCESS
;
2222 CSR_API(CsrSetTitle
)
2225 PCSRSS_CONSOLE Console
;
2227 DPRINT("CsrSetTitle\n");
2229 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2230 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2232 if (Request
->Header
.DataSize
2233 < sizeof(CSRSS_SET_TITLE_REQUEST
) - 1
2234 + Request
->Data
.SetTitleRequest
.Length
)
2236 DPRINT1("Invalid request size\n");
2237 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
2240 Status
= ConioLockConsole(ProcessData
, Request
->Data
.SetTitleRequest
.Console
, &Console
);
2241 if(! NT_SUCCESS(Status
))
2243 Reply
->Status
= Status
;
2247 /* copy title to console */
2248 RtlFreeUnicodeString(&Console
->Title
);
2249 RtlCreateUnicodeString(&Console
->Title
, Request
->Data
.SetTitleRequest
.Title
);
2250 if (! ConioChangeTitle(Console
))
2252 Reply
->Status
= STATUS_UNSUCCESSFUL
;
2256 Reply
->Status
= STATUS_SUCCESS
;
2259 ConioUnlockConsole(Console
);
2261 return Reply
->Status
;
2264 CSR_API(CsrGetTitle
)
2267 PCSRSS_CONSOLE Console
;
2269 DPRINT("CsrGetTitle\n");
2271 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2272 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2273 Status
= ConioLockConsole(ProcessData
,
2274 Request
->Data
.GetTitleRequest
.ConsoleHandle
,
2276 if (! NT_SUCCESS(Status
))
2278 DPRINT1("Can't get console\n");
2279 return Reply
->Status
= Status
;
2282 /* Copy title of the console to the user title buffer */
2283 RtlZeroMemory(&Reply
->Data
.GetTitleReply
, sizeof(CSRSS_GET_TITLE_REPLY
));
2284 Reply
->Data
.GetTitleReply
.ConsoleHandle
= Request
->Data
.GetTitleRequest
.ConsoleHandle
;
2285 Reply
->Data
.GetTitleReply
.Length
= Console
->Title
.Length
;
2286 wcscpy (Reply
->Data
.GetTitleReply
.Title
, Console
->Title
.Buffer
);
2287 Reply
->Header
.MessageSize
+= Console
->Title
.Length
;
2288 Reply
->Header
.DataSize
+= Console
->Title
.Length
;
2289 Reply
->Status
= STATUS_SUCCESS
;
2291 ConioUnlockConsole(Console
);
2293 return Reply
->Status
;
2296 CSR_API(CsrWriteConsoleOutput
)
2298 SHORT i
, X
, Y
, SizeX
, SizeY
;
2299 PCSRSS_CONSOLE Console
;
2300 PCSRSS_SCREEN_BUFFER Buff
;
2302 CHAR_INFO
* CurCharInfo
;
2304 CHAR_INFO
* CharInfo
;
2311 DPRINT("CsrWriteConsoleOutput\n");
2313 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2314 if (! NT_SUCCESS(Status
))
2316 return Reply
->Status
= Status
;
2319 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2320 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2321 Status
= ConioLockScreenBuffer(ProcessData
,
2322 Request
->Data
.WriteConsoleOutputRequest
.ConsoleHandle
,
2324 if (! NT_SUCCESS(Status
))
2326 if (NULL
!= Console
)
2328 ConioUnlockConsole(Console
);
2330 return Reply
->Status
= Status
;
2333 BufferSize
= Request
->Data
.WriteConsoleOutputRequest
.BufferSize
;
2334 PSize
= BufferSize
.X
* BufferSize
.Y
* sizeof(CHAR_INFO
);
2335 BufferCoord
= Request
->Data
.WriteConsoleOutputRequest
.BufferCoord
;
2336 CharInfo
= Request
->Data
.WriteConsoleOutputRequest
.CharInfo
;
2337 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
) ||
2338 (((PVOID
)CharInfo
+ PSize
) >
2339 (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2341 ConioUnlockScreenBuffer(Buff
);
2342 ConioUnlockConsole(Console
);
2343 return Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2345 WriteRegion
.left
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
;
2346 WriteRegion
.top
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
;
2347 WriteRegion
.right
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
;
2348 WriteRegion
.bottom
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
;
2350 SizeY
= RtlRosMin(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&WriteRegion
));
2351 SizeX
= RtlRosMin(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&WriteRegion
));
2352 WriteRegion
.bottom
= WriteRegion
.top
+ SizeY
- 1;
2353 WriteRegion
.right
= WriteRegion
.left
+ SizeX
- 1;
2355 /* Make sure WriteRegion is inside the screen buffer */
2356 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2357 if (! ConioGetIntersection(&WriteRegion
, &ScreenBuffer
, &WriteRegion
))
2359 ConioUnlockScreenBuffer(Buff
);
2360 ConioUnlockConsole(Console
);
2362 /* It is okay to have a WriteRegion completely outside the screen buffer.
2363 No data is written then. */
2364 return Reply
->Status
= STATUS_SUCCESS
;
2367 for (i
= 0, Y
= WriteRegion
.top
; Y
<= WriteRegion
.bottom
; i
++, Y
++)
2369 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
2370 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ WriteRegion
.left
) * 2;
2371 for (X
= WriteRegion
.left
; X
<= WriteRegion
.right
; X
++)
2373 if (Request
->Data
.WriteConsoleOutputRequest
.Unicode
)
2376 ConsoleUnicodeCharToAnsiChar(Console
, &AsciiChar
, &CurCharInfo
->Char
.UnicodeChar
);
2377 SET_CELL_BUFFER(Buff
, Offset
, AsciiChar
, CurCharInfo
->Attributes
);
2381 SET_CELL_BUFFER(Buff
, Offset
, CurCharInfo
->Char
.AsciiChar
, CurCharInfo
->Attributes
);
2387 if (NULL
!= Console
)
2389 ConioDrawRegion(Console
, &WriteRegion
);
2392 ConioUnlockScreenBuffer(Buff
);
2393 ConioUnlockConsole(Console
);
2395 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Right
= WriteRegion
.left
+ SizeX
- 1;
2396 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Bottom
= WriteRegion
.top
+ SizeY
- 1;
2397 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Left
= WriteRegion
.left
;
2398 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Top
= WriteRegion
.top
;
2400 return Reply
->Status
= STATUS_SUCCESS
;
2403 CSR_API(CsrFlushInputBuffer
)
2405 PLIST_ENTRY CurrentEntry
;
2406 PCSRSS_CONSOLE Console
;
2407 ConsoleInput
* Input
;
2410 DPRINT("CsrFlushInputBuffer\n");
2412 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2413 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2414 Status
= ConioLockConsole(ProcessData
,
2415 Request
->Data
.FlushInputBufferRequest
.ConsoleInput
,
2417 if(! NT_SUCCESS(Status
))
2419 return Reply
->Status
= Status
;
2422 /* Discard all entries in the input event queue */
2423 while (!IsListEmpty(&Console
->InputEvents
))
2425 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
2426 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
2427 /* Destroy the event */
2428 HeapFree(Win32CsrApiHeap
, 0, Input
);
2430 ResetEvent(Console
->ActiveEvent
);
2431 Console
->WaitingChars
=0;
2433 ConioUnlockConsole(Console
);
2435 return Reply
->Status
= STATUS_SUCCESS
;
2438 CSR_API(CsrScrollConsoleScreenBuffer
)
2440 PCSRSS_CONSOLE Console
;
2441 PCSRSS_SCREEN_BUFFER Buff
;
2446 RECT ScrollRectangle
;
2451 DPRINT("CsrScrollConsoleScreenBuffer\n");
2453 ALIAS(ConsoleHandle
,Request
->Data
.ScrollConsoleScreenBufferRequest
.ConsoleHandle
);
2454 ALIAS(UseClipRectangle
,Request
->Data
.ScrollConsoleScreenBufferRequest
.UseClipRectangle
);
2455 ALIAS(DestinationOrigin
,Request
->Data
.ScrollConsoleScreenBufferRequest
.DestinationOrigin
);
2456 ALIAS(Fill
,Request
->Data
.ScrollConsoleScreenBufferRequest
.Fill
);
2458 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2459 if (! NT_SUCCESS(Status
))
2461 return Reply
->Status
= Status
;
2464 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2465 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2466 Status
= ConioLockScreenBuffer(ProcessData
, ConsoleHandle
, &Buff
);
2467 if (! NT_SUCCESS(Status
))
2469 if (NULL
!= Console
)
2471 ConioUnlockConsole(Console
);
2473 return Reply
->Status
= Status
;
2476 ScrollRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Left
;
2477 ScrollRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Top
;
2478 ScrollRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Right
;
2479 ScrollRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Bottom
;
2480 ClipRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Left
;
2481 ClipRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Top
;
2482 ClipRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Right
;
2483 ClipRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Bottom
;
2485 /* Make sure source rectangle is inside the screen buffer */
2486 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2487 if (! ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, &ScrollRectangle
))
2489 ConioUnlockScreenBuffer(Buff
);
2490 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
2493 if (UseClipRectangle
&& ! ConioGetIntersection(&SrcRegion
, &SrcRegion
, &ClipRectangle
))
2495 ConioUnlockScreenBuffer(Buff
);
2496 return Reply
->Status
= STATUS_SUCCESS
;
2500 ConioInitRect(&DstRegion
,
2501 DestinationOrigin
.Y
,
2502 DestinationOrigin
.X
,
2503 DestinationOrigin
.Y
+ ConioRectHeight(&ScrollRectangle
) - 1,
2504 DestinationOrigin
.X
+ ConioRectWidth(&ScrollRectangle
) - 1);
2506 /* Make sure destination rectangle is inside the screen buffer */
2507 if (! ConioGetIntersection(&DstRegion
, &DstRegion
, &ScreenBuffer
))
2509 ConioUnlockScreenBuffer(Buff
);
2510 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
2513 ConioCopyRegion(Buff
, &SrcRegion
, &DstRegion
);
2515 /* Get the region that should be filled with the specified character and attributes */
2519 ConioGetUnion(&FillRegion
, &SrcRegion
, &DstRegion
);
2521 if (ConioSubtractRect(&FillRegion
, &FillRegion
, &DstRegion
))
2523 /* FIXME: The subtracted rectangle is off by one line */
2524 FillRegion
.top
+= 1;
2526 ConioFillRegion(Console
, Buff
, &FillRegion
, &Fill
, Request
->Data
.ScrollConsoleScreenBufferRequest
.Unicode
);
2530 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
2532 /* Draw destination region */
2533 ConioDrawRegion(Console
, &DstRegion
);
2537 /* Draw filled region */
2538 ConioDrawRegion(Console
, &FillRegion
);
2542 ConioUnlockScreenBuffer(Buff
);
2543 if (NULL
!= Console
)
2545 ConioUnlockConsole(Console
);
2548 return Reply
->Status
= STATUS_SUCCESS
;
2551 CSR_API(CsrReadConsoleOutputChar
)
2554 PCSRSS_CONSOLE Console
;
2555 PCSRSS_SCREEN_BUFFER Buff
;
2562 DPRINT("CsrReadConsoleOutputChar\n");
2564 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2565 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
2566 ReadBuffer
= Reply
->Data
.ReadConsoleOutputCharReply
.String
;
2568 CharSize
= (Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
2570 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2571 if (! NT_SUCCESS(Status
))
2573 return Reply
->Status
= Status
;
2576 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputCharRequest
.ConsoleHandle
, &Buff
);
2577 if (! NT_SUCCESS(Status
))
2579 return Reply
->Status
= Status
;
2582 Xpos
= Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.X
+ Buff
->ShowX
;
2583 Ypos
= (Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
2585 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
; ++i
)
2587 Char
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
)];
2589 if(Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
)
2591 ConsoleAnsiCharToUnicodeChar(Console
, (WCHAR
*)ReadBuffer
, &Char
);
2592 ReadBuffer
+= sizeof(WCHAR
);
2595 *(ReadBuffer
++) = Char
;
2599 if (Xpos
== Buff
->MaxX
)
2604 if (Ypos
== Buff
->MaxY
)
2612 Reply
->Status
= STATUS_SUCCESS
;
2613 Reply
->Data
.ReadConsoleOutputCharReply
.EndCoord
.X
= Xpos
- Buff
->ShowX
;
2614 Reply
->Data
.ReadConsoleOutputCharReply
.EndCoord
.Y
= (Ypos
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
;
2615 Reply
->Header
.MessageSize
+= Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
;
2616 Reply
->Header
.DataSize
+= Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
;
2618 ConioUnlockScreenBuffer(Buff
);
2619 if (NULL
!= Console
)
2621 ConioUnlockConsole(Console
);
2624 Reply
->Data
.ReadConsoleOutputCharReply
.CharsRead
= (DWORD
)((ULONG_PTR
)ReadBuffer
- (ULONG_PTR
)Reply
->Data
.ReadConsoleOutputCharReply
.String
) / CharSize
;
2626 return Reply
->Status
;
2630 CSR_API(CsrReadConsoleOutputAttrib
)
2633 PCSRSS_SCREEN_BUFFER Buff
;
2638 DPRINT("CsrReadConsoleOutputAttrib\n");
2640 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2641 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
2642 ReadBuffer
= Reply
->Data
.ReadConsoleOutputAttribReply
.String
;
2644 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputAttribRequest
.ConsoleHandle
, &Buff
);
2645 if (! NT_SUCCESS(Status
))
2647 return Reply
->Status
= Status
;
2650 Xpos
= Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.X
+ Buff
->ShowX
;
2651 Ypos
= (Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
2653 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
; ++i
)
2655 *ReadBuffer
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
) + 1];
2660 if (Xpos
== Buff
->MaxX
)
2665 if (Ypos
== Buff
->MaxY
)
2674 Reply
->Status
= STATUS_SUCCESS
;
2675 Reply
->Data
.ReadConsoleOutputAttribReply
.EndCoord
.X
= Xpos
- Buff
->ShowX
;
2676 Reply
->Data
.ReadConsoleOutputAttribReply
.EndCoord
.Y
= (Ypos
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
;
2677 Reply
->Header
.MessageSize
+= Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
;
2678 Reply
->Header
.DataSize
+= Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
;
2680 ConioUnlockScreenBuffer(Buff
);
2682 return Reply
->Status
;
2686 CSR_API(CsrGetNumberOfConsoleInputEvents
)
2689 PCSRSS_CONSOLE Console
;
2690 PLIST_ENTRY CurrentItem
;
2692 ConsoleInput
*Input
;
2694 DPRINT("CsrGetNumberOfConsoleInputEvents\n");
2696 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2697 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
2699 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
);
2700 if (! NT_SUCCESS(Status
))
2702 return Reply
->Status
= Status
;
2705 CurrentItem
= Console
->InputEvents
.Flink
;
2708 /* If there are any events ... */
2709 while (CurrentItem
!= &Console
->InputEvents
)
2711 Input
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2712 CurrentItem
= CurrentItem
->Flink
;
2719 ConioUnlockConsole(Console
);
2721 Reply
->Status
= STATUS_SUCCESS
;
2722 Reply
->Data
.GetNumInputEventsReply
.NumInputEvents
= NumEvents
;
2724 return Reply
->Status
;
2728 CSR_API(CsrPeekConsoleInput
)
2731 PCSRSS_CONSOLE Console
;
2734 PLIST_ENTRY CurrentItem
;
2735 PINPUT_RECORD InputRecord
;
2739 DPRINT("CsrPeekConsoleInput\n");
2741 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2742 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2744 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
);
2745 if(! NT_SUCCESS(Status
))
2747 return Reply
->Status
= Status
;
2750 InputRecord
= Request
->Data
.PeekConsoleInputRequest
.InputRecord
;
2751 Length
= Request
->Data
.PeekConsoleInputRequest
.Length
;
2752 Size
= Length
* sizeof(INPUT_RECORD
);
2754 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2755 || (((PVOID
)InputRecord
+ Size
) > (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2757 ConioUnlockConsole(Console
);
2758 Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2759 return Reply
->Status
;
2764 if (! IsListEmpty(&Console
->InputEvents
))
2766 CurrentItem
= Console
->InputEvents
.Flink
;
2768 while (CurrentItem
!= &Console
->InputEvents
&& NumItems
< Length
)
2770 Item
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2774 CurrentItem
= CurrentItem
->Flink
;
2779 *InputRecord
= Item
->InputEvent
;
2781 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
2783 ConioInputEventToAnsi(Console
, InputRecord
);
2787 CurrentItem
= CurrentItem
->Flink
;
2791 ConioUnlockConsole(Console
);
2793 Reply
->Status
= STATUS_SUCCESS
;
2794 Reply
->Data
.PeekConsoleInputReply
.Length
= NumItems
;
2796 return Reply
->Status
;
2800 CSR_API(CsrReadConsoleOutput
)
2802 PCHAR_INFO CharInfo
;
2803 PCHAR_INFO CurCharInfo
;
2804 PCSRSS_SCREEN_BUFFER Buff
;
2813 DWORD i
, Y
, X
, Offset
;
2816 DPRINT("CsrReadConsoleOutput\n");
2818 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2819 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2821 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputRequest
.ConsoleHandle
, &Buff
);
2822 if (! NT_SUCCESS(Status
))
2824 return Reply
->Status
= Status
;
2827 CharInfo
= Request
->Data
.ReadConsoleOutputRequest
.CharInfo
;
2828 ReadRegion
.left
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
;
2829 ReadRegion
.top
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
;
2830 ReadRegion
.right
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
;
2831 ReadRegion
.bottom
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
;
2832 BufferSize
= Request
->Data
.ReadConsoleOutputRequest
.BufferSize
;
2833 BufferCoord
= Request
->Data
.ReadConsoleOutputRequest
.BufferCoord
;
2834 Length
= BufferSize
.X
* BufferSize
.Y
;
2835 Size
= Length
* sizeof(CHAR_INFO
);
2837 /* FIXME: Is this correct? */
2838 CodePage
= ProcessData
->Console
->OutputCodePage
;
2840 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
)
2841 || (((PVOID
)CharInfo
+ Size
) > (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2843 ConioUnlockScreenBuffer(Buff
);
2844 Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2845 return Reply
->Status
;
2848 SizeY
= RtlRosMin(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&ReadRegion
));
2849 SizeX
= RtlRosMin(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&ReadRegion
));
2850 ReadRegion
.bottom
= ReadRegion
.top
+ SizeY
;
2851 ReadRegion
.right
= ReadRegion
.left
+ SizeX
;
2853 ConioInitRect(&ScreenRect
, 0, 0, Buff
->MaxY
, Buff
->MaxX
);
2854 if (! ConioGetIntersection(&ReadRegion
, &ScreenRect
, &ReadRegion
))
2856 ConioUnlockScreenBuffer(Buff
);
2857 Reply
->Status
= STATUS_SUCCESS
;
2858 return Reply
->Status
;
2861 for (i
= 0, Y
= ReadRegion
.top
; Y
< ReadRegion
.bottom
; ++i
, ++Y
)
2863 CurCharInfo
= CharInfo
+ (i
* BufferSize
.X
);
2865 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ ReadRegion
.left
) * 2;
2866 for (X
= ReadRegion
.left
; X
< ReadRegion
.right
; ++X
)
2868 if (Request
->Data
.ReadConsoleOutputRequest
.Unicode
)
2870 MultiByteToWideChar(CodePage
, 0,
2871 (PCHAR
)&GET_CELL_BUFFER(Buff
, Offset
), 1,
2872 &CurCharInfo
->Char
.UnicodeChar
, 1);
2876 CurCharInfo
->Char
.AsciiChar
= GET_CELL_BUFFER(Buff
, Offset
);
2878 CurCharInfo
->Attributes
= GET_CELL_BUFFER(Buff
, Offset
);
2883 ConioUnlockScreenBuffer(Buff
);
2885 Reply
->Status
= STATUS_SUCCESS
;
2886 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Right
= ReadRegion
.left
+ SizeX
- 1;
2887 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Bottom
= ReadRegion
.top
+ SizeY
- 1;
2888 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Left
= ReadRegion
.left
;
2889 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Top
= ReadRegion
.top
;
2891 return Reply
->Status
;
2895 CSR_API(CsrWriteConsoleInput
)
2897 PINPUT_RECORD InputRecord
;
2898 PCSRSS_CONSOLE Console
;
2903 ConsoleInput
* Record
;
2905 DPRINT("CsrWriteConsoleInput\n");
2907 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2908 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2910 Status
= ConioLockConsole(ProcessData
, Request
->Data
.WriteConsoleInputRequest
.ConsoleHandle
, &Console
);
2911 if (! NT_SUCCESS(Status
))
2913 return Reply
->Status
= Status
;
2916 InputRecord
= Request
->Data
.WriteConsoleInputRequest
.InputRecord
;
2917 Length
= Request
->Data
.WriteConsoleInputRequest
.Length
;
2918 Size
= Length
* sizeof(INPUT_RECORD
);
2920 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2921 || (((PVOID
)InputRecord
+ Size
) > (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2923 ConioUnlockConsole(Console
);
2924 Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2925 return Reply
->Status
;
2928 for (i
= 0; i
< Length
; i
++)
2930 Record
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
2933 ConioUnlockConsole(Console
);
2934 Reply
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2935 return Reply
->Status
;
2938 Record
->Echoed
= FALSE
;
2939 Record
->Fake
= FALSE
;
2940 Record
->InputEvent
= *InputRecord
++;
2941 if (KEY_EVENT
== Record
->InputEvent
.EventType
)
2943 /* FIXME - convert from unicode to ascii!! */
2944 ConioProcessChar(Console
, Record
);
2948 ConioUnlockConsole(Console
);
2950 Reply
->Status
= STATUS_SUCCESS
;
2951 Reply
->Data
.WriteConsoleInputReply
.Length
= i
;
2953 return Reply
->Status
;
2956 /**********************************************************************
2957 * HardwareStateProperty
2960 * Set/Get the value of the HardwareState and switch
2961 * between direct video buffer ouput and GDI windowed
2964 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
2965 * object. We use the same object to reply.
2967 * ConsoleHwState has the correct size to be compatible
2968 * with NT's, but values are not.
2970 STATIC NTSTATUS FASTCALL
2971 SetConsoleHardwareState (PCSRSS_CONSOLE Console
, DWORD ConsoleHwState
)
2973 DPRINT1("Console Hardware State: %d\n", ConsoleHwState
);
2975 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED
== ConsoleHwState
)
2976 ||(CONSOLE_HARDWARE_STATE_DIRECT
== ConsoleHwState
))
2978 if (Console
->HardwareState
!= ConsoleHwState
)
2980 /* TODO: implement switching from full screen to windowed mode */
2981 /* TODO: or back; now simply store the hardware state */
2982 Console
->HardwareState
= ConsoleHwState
;
2985 return STATUS_SUCCESS
;
2988 return STATUS_INVALID_PARAMETER_3
; /* Client: (handle, set_get, [mode]) */
2991 CSR_API(CsrHardwareStateProperty
)
2993 PCSRSS_CONSOLE Console
;
2996 DPRINT("CsrHardwareStateProperty\n");
2998 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2999 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3001 Status
= ConioLockConsole(ProcessData
,
3002 Request
->Data
.ConsoleHardwareStateRequest
.ConsoleHandle
,
3004 if (! NT_SUCCESS(Status
))
3006 DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
3007 return Reply
->Status
= Status
;
3010 switch (Request
->Data
.ConsoleHardwareStateRequest
.SetGet
)
3012 case CONSOLE_HARDWARE_STATE_GET
:
3013 Reply
->Data
.ConsoleHardwareStateReply
.State
= Console
->HardwareState
;
3016 case CONSOLE_HARDWARE_STATE_SET
:
3017 DPRINT("Setting console hardware state.\n");
3018 Reply
->Status
= SetConsoleHardwareState(Console
, Request
->Data
.ConsoleHardwareStateRequest
.State
);
3022 Reply
->Status
= STATUS_INVALID_PARAMETER_2
; /* Client: (handle, [set_get], mode) */
3026 ConioUnlockConsole(Console
);
3028 return Reply
->Status
;
3031 CSR_API(CsrGetConsoleWindow
)
3033 PCSRSS_CONSOLE Console
;
3036 DPRINT("CsrGetConsoleWindow\n");
3038 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3039 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3041 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3042 if (! NT_SUCCESS(Status
))
3044 return Reply
->Status
= Status
;
3047 Reply
->Data
.GetConsoleWindowReply
.WindowHandle
= Console
->hWindow
;
3048 ConioUnlockConsole(Console
);
3050 return Reply
->Status
= STATUS_SUCCESS
;
3053 CSR_API(CsrSetConsoleIcon
)
3055 PCSRSS_CONSOLE Console
;
3058 DPRINT("CsrSetConsoleIcon\n");
3060 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3061 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3063 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3064 if (! NT_SUCCESS(Status
))
3066 return Reply
->Status
= Status
;
3069 Console
->hWindowIcon
= Request
->Data
.SetConsoleIconRequest
.WindowIcon
;
3070 Reply
->Status
= (ConioChangeIcon(Console
) ? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
3071 ConioUnlockConsole(Console
);
3073 return Reply
->Status
;
3076 CSR_API(CsrGetConsoleCodePage
)
3078 PCSRSS_CONSOLE Console
;
3081 DPRINT("CsrGetConsoleCodePage\n");
3083 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3084 if (! NT_SUCCESS(Status
))
3086 return Reply
->Status
= Status
;
3089 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3090 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3091 Reply
->Data
.GetConsoleCodePage
.CodePage
= Console
->CodePage
;
3092 ConioUnlockConsole(Console
);
3093 return Reply
->Status
= STATUS_SUCCESS
;
3096 CSR_API(CsrSetConsoleCodePage
)
3098 PCSRSS_CONSOLE Console
;
3101 DPRINT("CsrSetConsoleCodePage\n");
3103 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3104 if (! NT_SUCCESS(Status
))
3106 return Reply
->Status
= Status
;
3109 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3110 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3111 if (IsValidCodePage(Request
->Data
.SetConsoleCodePage
.CodePage
))
3113 Console
->CodePage
= Request
->Data
.SetConsoleCodePage
.CodePage
;
3114 ConioUnlockConsole(Console
);
3115 return Reply
->Status
= STATUS_SUCCESS
;
3117 ConioUnlockConsole(Console
);
3118 return Reply
->Status
= STATUS_UNSUCCESSFUL
;
3121 CSR_API(CsrGetConsoleOutputCodePage
)
3123 PCSRSS_CONSOLE Console
;
3126 DPRINT("CsrGetConsoleOutputCodePage\n");
3128 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3129 if (! NT_SUCCESS(Status
))
3131 return Reply
->Status
= Status
;
3134 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3135 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3136 Reply
->Data
.GetConsoleOutputCodePage
.CodePage
= Console
->OutputCodePage
;
3137 ConioUnlockConsole(Console
);
3138 return Reply
->Status
= STATUS_SUCCESS
;
3141 CSR_API(CsrSetConsoleOutputCodePage
)
3143 PCSRSS_CONSOLE Console
;
3146 DPRINT("CsrSetConsoleOutputCodePage\n");
3148 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3149 if (! NT_SUCCESS(Status
))
3151 return Reply
->Status
= Status
;
3154 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3155 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3156 if (IsValidCodePage(Request
->Data
.SetConsoleOutputCodePage
.CodePage
))
3158 Console
->OutputCodePage
= Request
->Data
.SetConsoleOutputCodePage
.CodePage
;
3159 ConioUnlockConsole(Console
);
3160 return Reply
->Status
= STATUS_SUCCESS
;
3162 ConioUnlockConsole(Console
);
3163 return Reply
->Status
= STATUS_UNSUCCESSFUL
;
3166 CSR_API(CsrGetProcessList
)
3169 PCSRSS_CONSOLE Console
;
3170 PCSRSS_PROCESS_DATA current
;
3171 PLIST_ENTRY current_entry
;
3172 ULONG nItems
, nCopied
;
3175 DPRINT("CsrGetProcessList\n");
3177 Buffer
= Reply
->Data
.GetProcessListReply
.ProcessId
;
3178 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3179 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
3181 nItems
= nCopied
= 0;
3182 Reply
->Data
.GetProcessListReply
.nProcessIdsCopied
= 0;
3183 Reply
->Data
.GetProcessListReply
.nProcessIdsTotal
= 0;
3185 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3186 if (! NT_SUCCESS(Status
))
3188 return Reply
->Status
= Status
;
3191 DPRINT1("Console_Api Ctrl-C\n");
3193 for(current_entry
= Console
->ProcessList
.Flink
;
3194 current_entry
!= &Console
->ProcessList
;
3195 current_entry
= current_entry
->Flink
)
3197 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
3198 if(nItems
++ < Request
->Data
.GetProcessListRequest
.nMaxIds
)
3200 *(Buffer
++) = current
->ProcessId
;
3205 ConioUnlockConsole(Console
);
3207 Reply
->Data
.GetProcessListReply
.nProcessIdsCopied
= nCopied
;
3208 Reply
->Data
.GetProcessListReply
.nProcessIdsTotal
= nItems
;
3210 return Reply
->Status
= STATUS_SUCCESS
;