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
,
97 PROCESS_DUP_HANDLE
| PROCESS_VM_OPERATION
|
98 PROCESS_VM_WRITE
| PROCESS_CREATE_THREAD
,
101 if (!NT_SUCCESS(Status
))
103 DPRINT1("Failed for handle duplication, Status: 0x%x\n", Status
);
107 DPRINT("ConioConsoleCtrlEvent Process Handle = %x\n", Process
);
109 Thread
= CreateRemoteThread(Process
, NULL
, 0,
110 (LPTHREAD_START_ROUTINE
) ProcessData
->CtrlDispatcher
,
111 (PVOID
) Event
, 0, NULL
);
114 DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
115 CloseHandle(Process
);
119 CloseHandle(Process
);
123 #define GET_CELL_BUFFER(b,o)\
126 #define SET_CELL_BUFFER(b,o,c,a)\
127 (b)->Buffer[(o)++]=(c),\
128 (b)->Buffer[(o)++]=(a)
131 ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff
)
133 DWORD Offset
= 2 * (Buff
->CurrentY
* Buff
->MaxX
);
136 for (Pos
= 0; Pos
< Buff
->MaxX
; Pos
++)
138 /* Fill the cell: Offset is incremented by the macro */
139 SET_CELL_BUFFER(Buff
, Offset
, ' ', Buff
->DefaultAttrib
);
143 STATIC NTSTATUS FASTCALL
144 CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console
,
145 PCSRSS_SCREEN_BUFFER Buffer
)
147 Buffer
->Header
.Type
= CONIO_SCREEN_BUFFER_MAGIC
;
148 Buffer
->Header
.ReferenceCount
= 0;
149 Buffer
->MaxX
= Console
->Size
.X
;
150 Buffer
->MaxY
= Console
->Size
.Y
;
153 Buffer
->Buffer
= HeapAlloc(Win32CsrApiHeap
, 0, Buffer
->MaxX
* Buffer
->MaxY
* 2);
154 if (NULL
== Buffer
->Buffer
)
156 return STATUS_INSUFFICIENT_RESOURCES
;
158 InitializeCriticalSection(&Buffer
->Header
.Lock
);
159 ConioInitScreenBuffer(Console
, Buffer
);
160 /* initialize buffer to be empty with default attributes */
161 for (Buffer
->CurrentY
= 0 ; Buffer
->CurrentY
< Buffer
->MaxY
; Buffer
->CurrentY
++)
163 ClearLineBuffer(Buffer
);
165 Buffer
->CursorInfo
.bVisible
= TRUE
;
166 Buffer
->CursorInfo
.dwSize
= 5;
167 Buffer
->Mode
= ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
;
168 Buffer
->CurrentX
= 0;
169 Buffer
->CurrentY
= 0;
171 return STATUS_SUCCESS
;
174 STATIC NTSTATUS STDCALL
175 CsrInitConsole(PCSRSS_CONSOLE Console
)
178 SECURITY_ATTRIBUTES SecurityAttributes
;
179 PCSRSS_SCREEN_BUFFER NewBuffer
;
182 Console
->Title
.MaximumLength
= Console
->Title
.Length
= 0;
183 Console
->Title
.Buffer
= NULL
;
185 RtlCreateUnicodeString(&Console
->Title
, L
"Command Prompt");
187 Console
->Header
.ReferenceCount
= 0;
188 Console
->WaitingChars
= 0;
189 Console
->WaitingLines
= 0;
190 Console
->EchoCount
= 0;
191 Console
->Header
.Type
= CONIO_CONSOLE_MAGIC
;
192 Console
->Mode
= ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_PROCESSED_INPUT
| ENABLE_MOUSE_INPUT
;
193 Console
->EarlyReturn
= FALSE
;
194 Console
->ActiveBuffer
= NULL
;
195 InitializeListHead(&Console
->InputEvents
);
196 InitializeListHead(&Console
->ProcessList
);
198 Console
->CodePage
= GetOEMCP();
199 Console
->OutputCodePage
= GetOEMCP();
201 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
202 SecurityAttributes
.lpSecurityDescriptor
= NULL
;
203 SecurityAttributes
.bInheritHandle
= TRUE
;
205 Console
->ActiveEvent
= CreateEventW(&SecurityAttributes
, TRUE
, FALSE
, NULL
);
206 if (NULL
== Console
->ActiveEvent
)
208 RtlFreeUnicodeString(&Console
->Title
);
209 return STATUS_UNSUCCESSFUL
;
211 Console
->PrivateData
= NULL
;
212 InitializeCriticalSection(&Console
->Header
.Lock
);
213 GuiMode
= DtbgIsDesktopVisible();
216 Status
= TuiInitConsole(Console
);
217 if (! NT_SUCCESS(Status
))
219 DPRINT1("Failed to open text-mode console, switching to gui-mode\n");
225 Status
= GuiInitConsole(Console
);
226 if (! NT_SUCCESS(Status
))
228 RtlFreeUnicodeString(&Console
->Title
);
229 DeleteCriticalSection(&Console
->Header
.Lock
);
230 CloseHandle(Console
->ActiveEvent
);
235 NewBuffer
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(CSRSS_SCREEN_BUFFER
));
236 if (NULL
== NewBuffer
)
238 ConioCleanupConsole(Console
);
239 RtlFreeUnicodeString(&Console
->Title
);
240 DeleteCriticalSection(&Console
->Header
.Lock
);
241 CloseHandle(Console
->ActiveEvent
);
242 return STATUS_INSUFFICIENT_RESOURCES
;
244 Status
= CsrInitConsoleScreenBuffer(Console
, NewBuffer
);
245 if (! NT_SUCCESS(Status
))
247 ConioCleanupConsole(Console
);
248 RtlFreeUnicodeString(&Console
->Title
);
249 DeleteCriticalSection(&Console
->Header
.Lock
);
250 CloseHandle(Console
->ActiveEvent
);
251 HeapFree(Win32CsrApiHeap
, 0, NewBuffer
);
254 Console
->ActiveBuffer
= NewBuffer
;
255 /* add a reference count because the buffer is tied to the console */
256 Console
->ActiveBuffer
->Header
.ReferenceCount
++;
257 /* make console active, and insert into console list */
258 /* copy buffer contents to screen */
259 ConioDrawConsole(Console
);
261 return STATUS_SUCCESS
;
265 CSR_API(CsrAllocConsole
)
267 PCSRSS_CONSOLE Console
;
268 OBJECT_ATTRIBUTES ObjectAttributes
;
273 DPRINT("CsrAllocConsole\n");
275 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
276 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
278 if (ProcessData
== NULL
)
280 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
283 if (ProcessData
->Console
)
285 Reply
->Status
= STATUS_INVALID_PARAMETER
;
286 return STATUS_INVALID_PARAMETER
;
289 Reply
->Status
= STATUS_SUCCESS
;
290 Console
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(CSRSS_CONSOLE
));
293 Reply
->Status
= STATUS_NO_MEMORY
;
294 return STATUS_NO_MEMORY
;
296 Reply
->Status
= CsrInitConsole(Console
);
297 if (! NT_SUCCESS(Reply
->Status
))
299 HeapFree(Win32CsrApiHeap
, 0, Console
);
300 return Reply
->Status
;
302 ProcessData
->Console
= Console
;
303 Reply
->Data
.AllocConsoleReply
.Console
= Console
;
305 /* add a reference count because the process is tied to the console */
306 Console
->Header
.ReferenceCount
++;
307 Status
= Win32CsrInsertObject(ProcessData
, &Reply
->Data
.AllocConsoleReply
.InputHandle
, &Console
->Header
);
308 if (! NT_SUCCESS(Status
))
310 ConioDeleteConsole((Object_t
*) Console
);
311 ProcessData
->Console
= 0;
312 return Reply
->Status
= Status
;
314 Status
= Win32CsrInsertObject(ProcessData
, &Reply
->Data
.AllocConsoleReply
.OutputHandle
, &Console
->ActiveBuffer
->Header
);
315 if (!NT_SUCCESS(Status
))
317 Console
->Header
.ReferenceCount
--;
318 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.InputHandle
);
319 ProcessData
->Console
= 0;
320 return Reply
->Status
= Status
;
323 ClientId
.UniqueThread
= NULL
;
324 ClientId
.UniqueProcess
= ProcessData
->ProcessId
;
325 InitializeObjectAttributes(&ObjectAttributes
,
331 /* using OpenProcess is not optimal due to HANDLE vs. DWORD PIDs... */
332 Status
= NtOpenProcess(&Process
,
336 if (!NT_SUCCESS(Status
))
338 DPRINT1("NtOpenProcess() failed for handle duplication, Status: 0x%x\n", Status
);
339 Console
->Header
.ReferenceCount
--;
340 ProcessData
->Console
= 0;
341 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.OutputHandle
);
342 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.InputHandle
);
343 Reply
->Status
= Status
;
347 if (! DuplicateHandle(GetCurrentProcess(), ProcessData
->Console
->ActiveEvent
,
348 Process
, &ProcessData
->ConsoleEvent
, EVENT_ALL_ACCESS
, FALSE
, 0))
350 DPRINT1("DuplicateHandle() failed: %d\n", GetLastError
);
351 CloseHandle(Process
);
352 Console
->Header
.ReferenceCount
--;
353 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.OutputHandle
);
354 Win32CsrReleaseObject(ProcessData
, Reply
->Data
.AllocConsoleReply
.InputHandle
);
355 ProcessData
->Console
= 0;
356 Reply
->Status
= Status
;
359 CloseHandle(Process
);
360 ProcessData
->CtrlDispatcher
= Request
->Data
.AllocConsoleRequest
.CtrlDispatcher
;
361 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
362 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ProcessEntry
);
364 return STATUS_SUCCESS
;
367 CSR_API(CsrFreeConsole
)
369 PCSRSS_CONSOLE Console
;
371 DPRINT("CsrFreeConsole\n");
373 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
374 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
376 if (ProcessData
== NULL
|| ProcessData
->Console
== NULL
)
378 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
381 Console
= ProcessData
->Console
;
382 Console
->Header
.ReferenceCount
--;
383 ProcessData
->Console
= NULL
;
384 if (0 == Console
->Header
.ReferenceCount
)
386 ConioDeleteConsole((Object_t
*) Console
);
389 return STATUS_SUCCESS
;
393 ConioNextLine(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, UINT
*ScrolledLines
)
395 /* slide the viewable screen */
396 if (((Buff
->CurrentY
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
) == Buff
->MaxY
- 1)
398 if (++Buff
->ShowY
== Buff
->MaxY
)
404 if (++Buff
->CurrentY
== Buff
->MaxY
)
408 ClearLineBuffer(Buff
);
409 UpdateRect
->left
= 0;
410 UpdateRect
->right
= Buff
->MaxX
- 1;
411 if (UpdateRect
->top
== Buff
->CurrentY
)
413 if (++UpdateRect
->top
== Buff
->MaxY
)
418 UpdateRect
->bottom
= Buff
->CurrentY
;
421 STATIC NTSTATUS FASTCALL
422 ConioWriteConsole(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
,
423 CHAR
*Buffer
, DWORD Length
, BOOL Attrib
)
428 LONG CursorStartX
, CursorStartY
;
431 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &CursorStartX
, &CursorStartY
);
432 UpdateRect
.left
= Buff
->MaxX
;
433 UpdateRect
.top
= Buff
->CurrentY
;
434 UpdateRect
.right
= -1;
435 UpdateRect
.bottom
= Buff
->CurrentY
;
438 for (i
= 0; i
< Length
; i
++)
440 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
443 if (Buffer
[i
] == '\n')
446 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
450 else if (Buffer
[i
] == '\b')
452 /* Only handle BS if we're not on the first pos of the first line */
453 if (0 != Buff
->CurrentX
|| Buff
->ShowY
!= Buff
->CurrentY
)
455 if (0 == Buff
->CurrentX
)
457 /* slide virtual position up */
458 Buff
->CurrentX
= Buff
->MaxX
- 1;
459 if (0 == Buff
->CurrentY
)
461 Buff
->CurrentY
= Buff
->MaxY
;
467 if ((0 == UpdateRect
.top
&& UpdateRect
.bottom
< Buff
->CurrentY
)
468 || (0 != UpdateRect
.top
&& Buff
->CurrentY
< UpdateRect
.top
))
470 UpdateRect
.top
= Buff
->CurrentY
;
477 Offset
= 2 * ((Buff
->CurrentY
* Buff
->MaxX
) + Buff
->CurrentX
);
478 SET_CELL_BUFFER(Buff
, Offset
, ' ', Buff
->DefaultAttrib
);
479 UpdateRect
.left
= RtlRosMin(UpdateRect
.left
, Buff
->CurrentX
);
480 UpdateRect
.right
= RtlRosMax(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
485 else if (Buffer
[i
] == '\r')
488 UpdateRect
.left
= RtlRosMin(UpdateRect
.left
, Buff
->CurrentX
);
489 UpdateRect
.right
= RtlRosMax(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
493 else if (Buffer
[i
] == '\t')
497 UpdateRect
.left
= RtlRosMin(UpdateRect
.left
, Buff
->CurrentX
);
498 EndX
= (Buff
->CurrentX
+ 8) & ~7;
499 if (EndX
> Buff
->MaxX
)
503 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
504 while (Buff
->CurrentX
< EndX
)
506 Buff
->Buffer
[Offset
] = ' ';
510 UpdateRect
.right
= RtlRosMax(UpdateRect
.right
, (LONG
) Buff
->CurrentX
- 1);
511 if (Buff
->CurrentX
== Buff
->MaxX
)
513 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
516 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
526 UpdateRect
.left
= RtlRosMin(UpdateRect
.left
, Buff
->CurrentX
);
527 UpdateRect
.right
= RtlRosMax(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
528 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
529 Buff
->Buffer
[Offset
++] = Buffer
[i
];
532 Buff
->Buffer
[Offset
] = Buff
->DefaultAttrib
;
535 if (Buff
->CurrentX
== Buff
->MaxX
)
537 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
540 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
544 Buff
->CurrentX
= CursorStartX
;
549 ConioPhysicalToLogical(Buff
, UpdateRect
.left
, UpdateRect
.top
, &(UpdateRect
.left
),
551 ConioPhysicalToLogical(Buff
, UpdateRect
.right
, UpdateRect
.bottom
, &(UpdateRect
.right
),
552 &(UpdateRect
.bottom
));
553 if (! ConioIsRectEmpty(&UpdateRect
) && NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
555 ConioWriteStream(Console
, &UpdateRect
, CursorStartX
, CursorStartY
, ScrolledLines
,
559 return STATUS_SUCCESS
;
562 CSR_API(CsrReadConsole
)
564 PLIST_ENTRY CurrentEntry
;
567 PWCHAR UnicodeBuffer
;
569 ULONG nNumberOfCharsToRead
, CharSize
;
570 PCSRSS_CONSOLE Console
;
573 DPRINT("CsrReadConsole\n");
575 CharSize
= (Request
->Data
.ReadConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
577 /* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */
578 nNumberOfCharsToRead
= min(Request
->Data
.ReadConsoleRequest
.NrCharactersToRead
, CSRSS_MAX_READ_CONSOLE_REQUEST
/ CharSize
);
579 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
580 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
582 Buffer
= Reply
->Data
.ReadConsoleReply
.Buffer
;
583 UnicodeBuffer
= (PWCHAR
)Buffer
;
584 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadConsoleRequest
.ConsoleHandle
,
586 if (! NT_SUCCESS(Status
))
588 return Reply
->Status
= Status
;
590 Reply
->Data
.ReadConsoleReply
.EventHandle
= ProcessData
->ConsoleEvent
;
591 for (i
= 0; i
< nNumberOfCharsToRead
&& Console
->InputEvents
.Flink
!= &Console
->InputEvents
; i
++)
593 /* remove input event from queue */
594 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
595 if (IsListEmpty(&Console
->InputEvents
))
598 ResetEvent(Console
->ActiveEvent
);
600 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
602 /* only pay attention to valid ascii chars, on key down */
603 if (KEY_EVENT
== Input
->InputEvent
.EventType
604 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
605 && Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
!= '\0')
607 /* backspace handling */
608 if ('\b' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
610 /* echo if it has not already been done, and either we or the client has chars to be deleted */
612 && (0 != i
|| Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
))
614 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
615 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
619 i
-= 2; /* if we already have something to return, just back it up by 2 */
622 { /* otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer */
623 Console
->WaitingChars
--;
624 ConioUnlockConsole(Console
);
625 HeapFree(Win32CsrApiHeap
, 0, Input
);
626 Reply
->Data
.ReadConsoleReply
.NrCharactersRead
= 0;
627 Reply
->Status
= STATUS_NOTIFY_CLEANUP
;
628 return STATUS_NOTIFY_CLEANUP
;
630 Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
--;
631 Input
->Echoed
= TRUE
; /* mark as echoed so we don't echo it below */
633 /* do not copy backspace to buffer */
636 if(Request
->Data
.ReadConsoleRequest
.Unicode
)
637 UnicodeBuffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
; /* FIXME */
639 Buffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
;
641 /* echo to screen if enabled and we did not already echo the char */
642 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
)
644 && '\r' != Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
646 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
647 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
654 Console
->WaitingChars
--;
655 HeapFree(Win32CsrApiHeap
, 0, Input
);
657 Reply
->Data
.ReadConsoleReply
.NrCharactersRead
= i
;
660 Reply
->Status
= STATUS_PENDING
; /* we didn't read anything */
662 else if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
))
664 if (0 == Console
->WaitingLines
||
665 (Request
->Data
.ReadConsoleRequest
.Unicode
? (L
'\n' != UnicodeBuffer
[i
- 1]) : ('\n' != Buffer
[i
- 1])))
667 Reply
->Status
= STATUS_PENDING
; /* line buffered, didn't get a complete line */
671 Console
->WaitingLines
--;
672 Reply
->Status
= STATUS_SUCCESS
; /* line buffered, did get a complete line */
677 Reply
->Status
= STATUS_SUCCESS
; /* not line buffered, did read something */
680 if (Reply
->Status
== STATUS_PENDING
)
682 Console
->EchoCount
= nNumberOfCharsToRead
- i
;
686 Console
->EchoCount
= 0; /* if the client is no longer waiting on input, do not echo */
688 Reply
->Header
.MessageSize
+= i
* CharSize
;
690 ConioUnlockConsole(Console
);
691 return Reply
->Status
;
695 ConioPhysicalToLogical(PCSRSS_SCREEN_BUFFER Buff
,
701 *LogicalX
= PhysicalX
;
702 if (PhysicalY
< Buff
->ShowY
)
704 *LogicalY
= Buff
->MaxY
- Buff
->ShowY
+ PhysicalY
;
708 *LogicalY
= PhysicalY
- Buff
->ShowY
;
712 inline BOOLEAN
ConioIsEqualRect(
716 return ((Rect1
->left
== Rect2
->left
) && (Rect1
->right
== Rect2
->right
) &&
717 (Rect1
->top
== Rect2
->top
) && (Rect1
->bottom
== Rect2
->bottom
));
720 inline BOOLEAN
ConioGetIntersection(
725 if (ConioIsRectEmpty(Rect1
) ||
726 (ConioIsRectEmpty(Rect2
)) ||
727 (Rect1
->top
> Rect2
->bottom
) ||
728 (Rect1
->left
> Rect2
->right
) ||
729 (Rect1
->bottom
< Rect2
->top
) ||
730 (Rect1
->right
< Rect2
->left
))
732 /* The rectangles do not intersect */
733 ConioInitRect(Intersection
, 0, -1, 0, -1);
737 ConioInitRect(Intersection
,
738 RtlRosMax(Rect1
->top
, Rect2
->top
),
739 RtlRosMax(Rect1
->left
, Rect2
->left
),
740 RtlRosMin(Rect1
->bottom
, Rect2
->bottom
),
741 RtlRosMin(Rect1
->right
, Rect2
->right
));
746 inline BOOLEAN
ConioGetUnion(
751 if (ConioIsRectEmpty(Rect1
))
753 if (ConioIsRectEmpty(Rect2
))
755 ConioInitRect(Union
, 0, -1, 0, -1);
763 else if (ConioIsRectEmpty(Rect2
))
770 RtlRosMin(Rect1
->top
, Rect2
->top
),
771 RtlRosMin(Rect1
->left
, Rect2
->left
),
772 RtlRosMax(Rect1
->bottom
, Rect2
->bottom
),
773 RtlRosMax(Rect1
->right
, Rect2
->right
));
779 inline BOOLEAN
ConioSubtractRect(
786 if (ConioIsRectEmpty(Rect1
))
788 ConioInitRect(Subtraction
, 0, -1, 0, -1);
791 *Subtraction
= *Rect1
;
792 if (ConioGetIntersection(&tmp
, Rect1
, Rect2
))
794 if (ConioIsEqualRect(&tmp
, Subtraction
))
796 ConioInitRect(Subtraction
, 0, -1, 0, -1);
799 if ((tmp
.top
== Subtraction
->top
) && (tmp
.bottom
== Subtraction
->bottom
))
801 if (tmp
.left
== Subtraction
->left
)
803 Subtraction
->left
= tmp
.right
;
805 else if (tmp
.right
== Subtraction
->right
)
807 Subtraction
->right
= tmp
.left
;
810 else if ((tmp
.left
== Subtraction
->left
) && (tmp
.right
== Subtraction
->right
))
812 if (tmp
.top
== Subtraction
->top
)
814 Subtraction
->top
= tmp
.bottom
;
816 else if (tmp
.bottom
== Subtraction
->bottom
)
818 Subtraction
->bottom
= tmp
.top
;
827 ConioCopyRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer
,
837 DstY
= DstRegion
->top
;
838 BytesPerLine
= ConioRectWidth(DstRegion
) * 2;
840 SrcY
= (SrcRegion
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
841 DstY
= (DstRegion
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
842 SrcOffset
= (SrcY
* ScreenBuffer
->MaxX
+ SrcRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
843 DstOffset
= (DstY
* ScreenBuffer
->MaxX
+ DstRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
845 for (i
= SrcRegion
->top
; i
<= SrcRegion
->bottom
; i
++)
848 &ScreenBuffer
->Buffer
[DstOffset
],
849 &ScreenBuffer
->Buffer
[SrcOffset
],
852 if (++DstY
== ScreenBuffer
->MaxY
)
855 DstOffset
= (DstRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
859 DstOffset
+= ScreenBuffer
->MaxX
* 2;
862 if (++SrcY
== ScreenBuffer
->MaxY
)
865 SrcOffset
= (SrcRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
869 SrcOffset
+= ScreenBuffer
->MaxX
* 2;
875 ConioFillRegion(PCSRSS_CONSOLE Console
,
876 PCSRSS_SCREEN_BUFFER ScreenBuffer
,
888 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &CharInfo
->Char
.UnicodeChar
);
890 Char
= CharInfo
->Char
.AsciiChar
;
892 Y
= (Region
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
893 Offset
= (Y
* ScreenBuffer
->MaxX
+ Region
->left
+ ScreenBuffer
->ShowX
) * 2;
894 Delta
= (ScreenBuffer
->MaxX
- ConioRectWidth(Region
)) * 2;
896 for (i
= Region
->top
; i
<= Region
->bottom
; i
++)
898 for (X
= Region
->left
; X
<= Region
->right
; X
++)
900 SET_CELL_BUFFER(ScreenBuffer
, Offset
, Char
, CharInfo
->Attributes
);
902 if (++Y
== ScreenBuffer
->MaxY
)
905 Offset
= (Region
->left
+ ScreenBuffer
->ShowX
) * 2;
915 ConioInputEventToAnsi(PCSRSS_CONSOLE Console
, PINPUT_RECORD InputEvent
)
917 if (InputEvent
->EventType
== KEY_EVENT
)
919 ConsoleUnicodeCharToAnsiChar(Console
,
920 &InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
,
921 &InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
);
925 CSR_API(CsrWriteConsole
)
928 PCHAR Buffer
= (PCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
;
929 PCSRSS_SCREEN_BUFFER Buff
;
930 PCSRSS_CONSOLE Console
;
931 ULONG CharSize
= (Request
->Data
.WriteConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
933 DPRINT("CsrWriteConsole\n");
935 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
936 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
938 if (Request
->Header
.DataSize
939 < sizeof(CSRSS_WRITE_CONSOLE_REQUEST
) - 1
940 + (Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
* CharSize
))
942 DPRINT1("Invalid request size\n");
943 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
945 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
946 if (! NT_SUCCESS(Status
))
948 return Reply
->Status
= Status
;
951 if(Request
->Data
.WriteConsoleRequest
.Unicode
)
953 ConsoleUnicodeToAnsiN(Console
, Buffer
, (PWCHAR
)Buffer
, Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
);
956 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.WriteConsoleRequest
.ConsoleHandle
, &Buff
);
957 if (! NT_SUCCESS(Status
))
961 ConioUnlockConsole(Console
);
963 return Reply
->Status
= Status
;
966 Reply
->Status
= ConioWriteConsole(Console
, Buff
, Buffer
,
967 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
, TRUE
);
968 ConioUnlockScreenBuffer(Buff
);
971 ConioUnlockConsole(Console
);
974 if(NT_SUCCESS(Reply
->Status
))
976 Reply
->Data
.WriteConsoleReply
.NrCharactersWritten
= Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
;
980 Reply
->Data
.WriteConsoleReply
.NrCharactersWritten
= 0; /* FIXME - return the actual number of characters written! */
983 return Reply
->Status
= STATUS_SUCCESS
;
987 ConioDeleteScreenBuffer(Object_t
*Object
)
989 PCSRSS_SCREEN_BUFFER Buffer
= (PCSRSS_SCREEN_BUFFER
) Object
;
990 DeleteCriticalSection(&Buffer
->Header
.Lock
);
991 HeapFree(Win32CsrApiHeap
, 0, Buffer
->Buffer
);
992 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
996 ConioDrawConsole(PCSRSS_CONSOLE Console
)
1000 ConioInitRect(&Region
, 0, 0, Console
->Size
.Y
- 1, Console
->Size
.X
- 1);
1002 ConioDrawRegion(Console
, &Region
);
1007 ConioDeleteConsole(Object_t
*Object
)
1009 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Object
;
1010 ConsoleInput
*Event
;
1012 DPRINT("ConioDeleteConsole\n");
1014 /* Drain input event queue */
1015 while (Console
->InputEvents
.Flink
!= &Console
->InputEvents
)
1017 Event
= (ConsoleInput
*) Console
->InputEvents
.Flink
;
1018 Console
->InputEvents
.Flink
= Console
->InputEvents
.Flink
->Flink
;
1019 Console
->InputEvents
.Flink
->Flink
->Blink
= &Console
->InputEvents
;
1020 HeapFree(Win32CsrApiHeap
, 0, Event
);
1023 if (0 == --Console
->ActiveBuffer
->Header
.ReferenceCount
)
1025 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
1028 Console
->ActiveBuffer
= NULL
;
1029 ConioCleanupConsole(Console
);
1031 CloseHandle(Console
->ActiveEvent
);
1032 DeleteCriticalSection(&Console
->Header
.Lock
);
1033 RtlFreeUnicodeString(&Console
->Title
);
1034 HeapFree(Win32CsrApiHeap
, 0, Console
);
1038 CsrInitConsoleSupport(VOID
)
1040 DPRINT("CSR: CsrInitConsoleSupport()\n");
1042 /* Should call LoadKeyboardLayout */
1045 STATIC VOID FASTCALL
1046 ConioProcessChar(PCSRSS_CONSOLE Console
,
1047 ConsoleInput
*KeyEventRecord
)
1050 BOOL bClientWake
= FALSE
;
1051 ConsoleInput
*TempInput
;
1053 /* process Ctrl-C and Ctrl-Break */
1054 if (Console
->Mode
& ENABLE_PROCESSED_INPUT
&&
1055 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
&&
1056 ((KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== VK_PAUSE
) ||
1057 (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== 'C')) &&
1058 (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
)))
1060 PCSRSS_PROCESS_DATA current
;
1061 PLIST_ENTRY current_entry
;
1062 DPRINT1("Console_Api Ctrl-C\n");
1063 current_entry
= Console
->ProcessList
.Flink
;
1064 while (current_entry
!= &Console
->ProcessList
)
1066 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
1067 current_entry
= current_entry
->Flink
;
1068 ConioConsoleCtrlEvent((DWORD
)CTRL_C_EVENT
, current
);
1070 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1074 if (0 != (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
1075 & (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1076 && (VK_UP
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
1077 || VK_DOWN
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
))
1079 if (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1081 /* scroll up or down */
1082 if (NULL
== Console
)
1084 DPRINT1("No Active Console!\n");
1085 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1088 if (VK_UP
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
)
1090 /* only scroll up if there is room to scroll up into */
1091 if (Console
->ActiveBuffer
->ShowY
!= ((Console
->ActiveBuffer
->CurrentY
+ 1) %
1092 Console
->ActiveBuffer
->MaxY
))
1094 Console
->ActiveBuffer
->ShowY
= (Console
->ActiveBuffer
->ShowY
+
1095 Console
->ActiveBuffer
->MaxY
- 1) %
1096 Console
->ActiveBuffer
->MaxY
;
1099 else if (Console
->ActiveBuffer
->ShowY
!= Console
->ActiveBuffer
->CurrentY
)
1100 /* only scroll down if there is room to scroll down into */
1102 if (Console
->ActiveBuffer
->ShowY
% Console
->ActiveBuffer
->MaxY
!=
1103 Console
->ActiveBuffer
->CurrentY
)
1105 if (((Console
->ActiveBuffer
->CurrentY
+ 1) % Console
->ActiveBuffer
->MaxY
) !=
1106 (Console
->ActiveBuffer
->ShowY
+ Console
->ActiveBuffer
->MaxY
) %
1107 Console
->ActiveBuffer
->MaxY
)
1109 Console
->ActiveBuffer
->ShowY
= (Console
->ActiveBuffer
->ShowY
+ 1) %
1110 Console
->ActiveBuffer
->MaxY
;
1114 ConioDrawConsole(Console
);
1116 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1119 if (NULL
== Console
)
1121 DPRINT1("No Active Console!\n");
1122 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1126 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
)))
1128 switch(KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1131 /* first add the \r */
1132 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1133 updown
= KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
;
1134 KeyEventRecord
->Echoed
= FALSE
;
1135 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= VK_RETURN
;
1136 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\r';
1137 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1138 Console
->WaitingChars
++;
1139 KeyEventRecord
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1140 if (NULL
== KeyEventRecord
)
1142 DPRINT1("Failed to allocate KeyEventRecord\n");
1145 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1146 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
= updown
;
1147 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= 0;
1148 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualScanCode
= 0;
1149 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\n';
1150 KeyEventRecord
->Fake
= TRUE
;
1154 /* add event to the queue */
1155 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1156 Console
->WaitingChars
++;
1157 /* if line input mode is enabled, only wake the client on enter key down */
1158 if (0 == (Console
->Mode
& ENABLE_LINE_INPUT
)
1159 || Console
->EarlyReturn
1160 || ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1161 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
))
1163 if ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1165 Console
->WaitingLines
++;
1168 SetEvent(Console
->ActiveEvent
);
1170 KeyEventRecord
->Echoed
= FALSE
;
1171 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
))
1172 && '\b' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1173 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1175 /* walk the input queue looking for a char to backspace */
1176 for (TempInput
= (ConsoleInput
*) Console
->InputEvents
.Blink
;
1177 TempInput
!= (ConsoleInput
*) &Console
->InputEvents
1178 && (KEY_EVENT
== TempInput
->InputEvent
.EventType
1179 || ! TempInput
->InputEvent
.Event
.KeyEvent
.bKeyDown
1180 || '\b' == TempInput
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
);
1181 TempInput
= (ConsoleInput
*) TempInput
->ListEntry
.Blink
)
1185 /* if we found one, delete it, otherwise, wake the client */
1186 if (TempInput
!= (ConsoleInput
*) &Console
->InputEvents
)
1188 /* delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue */
1189 RemoveEntryList(&TempInput
->ListEntry
);
1190 if (TempInput
->Echoed
)
1192 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1193 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1196 HeapFree(Win32CsrApiHeap
, 0, TempInput
);
1197 RemoveEntryList(&KeyEventRecord
->ListEntry
);
1198 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1199 Console
->WaitingChars
-= 2;
1203 SetEvent(Console
->ActiveEvent
);
1208 /* echo chars if we are supposed to and client is waiting for some */
1209 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
) && Console
->EchoCount
1210 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1211 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
1212 && '\r' != KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1214 /* mark the char as already echoed */
1215 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1216 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1218 Console
->EchoCount
--;
1219 KeyEventRecord
->Echoed
= TRUE
;
1223 /* Console->WaitingChars++; */
1224 if (bClientWake
|| 0 == (Console
->Mode
& ENABLE_LINE_INPUT
))
1226 SetEvent(Console
->ActiveEvent
);
1230 STATIC DWORD FASTCALL
1231 ConioGetShiftState(PBYTE KeyState
)
1235 if (KeyState
[VK_CAPITAL
] & 1)
1236 ssOut
|= CAPSLOCK_ON
;
1238 if (KeyState
[VK_NUMLOCK
] & 1)
1239 ssOut
|= NUMLOCK_ON
;
1241 if (KeyState
[VK_SCROLL
] & 1)
1242 ssOut
|= SCROLLLOCK_ON
;
1244 if (KeyState
[VK_SHIFT
] & 0x80)
1245 ssOut
|= SHIFT_PRESSED
;
1247 if (KeyState
[VK_LCONTROL
] & 0x80)
1248 ssOut
|= LEFT_CTRL_PRESSED
;
1249 if (KeyState
[VK_RCONTROL
] & 0x80)
1250 ssOut
|= RIGHT_CTRL_PRESSED
;
1252 if (KeyState
[VK_LMENU
] & 0x80)
1253 ssOut
|= LEFT_ALT_PRESSED
;
1254 if (KeyState
[VK_RMENU
] & 0x80)
1255 ssOut
|= RIGHT_ALT_PRESSED
;
1261 ConioProcessKey(MSG
*msg
, PCSRSS_CONSOLE Console
, BOOL TextMode
)
1263 static BYTE KeyState
[256] = { 0 };
1264 /* MSDN mentions that you should use the last virtual key code received
1265 * when putting a virtual key identity to a WM_CHAR message since multiple
1266 * or translated keys may be involved. */
1267 static UINT LastVirtualKey
= 0;
1269 ConsoleInput
*ConInRec
;
1273 UINT VirtualKeyCode
;
1274 UINT VirtualScanCode
;
1277 ULONG ResultSize
= 0;
1280 VirtualScanCode
= (msg
->lParam
>> 16) & 0xff;
1281 Down
= msg
->message
== WM_KEYDOWN
|| msg
->message
== WM_CHAR
||
1282 msg
->message
== WM_SYSKEYDOWN
|| msg
->message
== WM_SYSCHAR
;
1284 GetKeyboardState(KeyState
);
1285 ShiftState
= ConioGetShiftState(KeyState
);
1287 if (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
)
1289 VirtualKeyCode
= LastVirtualKey
;
1290 UnicodeChar
= msg
->wParam
;
1297 VirtualKeyCode
= msg
->wParam
;
1298 RetChars
= ToUnicodeEx(VirtualKeyCode
,
1305 UnicodeChar
= (1 == RetChars
? Chars
[0] : 0);
1308 if (0 == ResultSize
)
1313 er
.EventType
= KEY_EVENT
;
1314 er
.Event
.KeyEvent
.bKeyDown
= Down
;
1315 er
.Event
.KeyEvent
.wRepeatCount
= RepeatCount
;
1316 er
.Event
.KeyEvent
.uChar
.UnicodeChar
= UnicodeChar
;
1317 er
.Event
.KeyEvent
.dwControlKeyState
= ShiftState
;
1318 er
.Event
.KeyEvent
.wVirtualKeyCode
= VirtualKeyCode
;
1319 er
.Event
.KeyEvent
.wVirtualScanCode
= VirtualScanCode
;
1323 if (0 != (ShiftState
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1324 && VK_TAB
== VirtualKeyCode
)
1328 TuiSwapConsole(ShiftState
& SHIFT_PRESSED
? -1 : 1);
1333 else if (VK_MENU
== VirtualKeyCode
&& ! Down
)
1335 if (TuiSwapConsole(0))
1342 if (NULL
== Console
)
1347 ConInRec
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1349 if (NULL
== ConInRec
)
1354 ConInRec
->InputEvent
= er
;
1355 ConInRec
->Fake
= UnicodeChar
&&
1356 (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
&&
1357 msg
->message
!= WM_KEYUP
&& msg
->message
!= WM_SYSKEYUP
);
1358 ConInRec
->NotChar
= (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
);
1359 ConInRec
->Echoed
= FALSE
;
1360 if (ConInRec
->NotChar
)
1361 LastVirtualKey
= msg
->wParam
;
1363 DPRINT ("csrss: %s %s %s %s %02x %02x '%c' %04x\n",
1364 Down
? "down" : "up ",
1365 (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
) ?
1367 ConInRec
->Fake
? "fake" : "real",
1368 ConInRec
->NotChar
? "notc" : "char",
1371 (AsciiChar
>= ' ') ? AsciiChar
: '.',
1374 if (! ConInRec
->Fake
|| ! ConInRec
->NotChar
)
1376 /* FIXME - convert to ascii */
1377 ConioProcessChar(Console
, ConInRec
);
1381 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1386 Console_Api (PVOID unused
)
1388 /* keep reading events from the keyboard and stuffing them into the current
1389 console's input queue */
1392 /* This call establishes our message queue */
1393 PeekMessageW(&msg
, 0, 0, 0, PM_NOREMOVE
);
1394 /* This call registers our message queue */
1395 PrivateCsrssRegisterPrimitive();
1396 /* This call turns on the input system in win32k */
1397 PrivateCsrssAcquireOrReleaseInputOwnership(FALSE
);
1401 GetMessageW(&msg
, 0, 0, 0);
1402 TranslateMessage(&msg
);
1404 if (msg
.message
== WM_CHAR
|| msg
.message
== WM_SYSCHAR
||
1405 msg
.message
== WM_KEYDOWN
|| msg
.message
== WM_KEYUP
||
1406 msg
.message
== WM_SYSKEYDOWN
|| msg
.message
== WM_SYSKEYUP
)
1408 ConioProcessKey(&msg
, TuiGetFocusConsole(), TRUE
);
1412 PrivateCsrssAcquireOrReleaseInputOwnership(TRUE
);
1416 CSR_API(CsrGetScreenBufferInfo
)
1419 PCSRSS_SCREEN_BUFFER Buff
;
1420 PCONSOLE_SCREEN_BUFFER_INFO pInfo
;
1422 DPRINT("CsrGetScreenBufferInfo\n");
1424 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1425 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1427 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ScreenBufferInfoRequest
.ConsoleHandle
, &Buff
);
1428 if (! NT_SUCCESS(Status
))
1430 return Reply
->Status
= Status
;
1432 pInfo
= &Reply
->Data
.ScreenBufferInfoReply
.Info
;
1433 pInfo
->dwSize
.X
= Buff
->MaxX
;
1434 pInfo
->dwSize
.Y
= Buff
->MaxY
;
1435 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1436 pInfo
->dwCursorPosition
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1437 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
1438 pInfo
->srWindow
.Left
= 0;
1439 pInfo
->srWindow
.Right
= Buff
->MaxX
- 1;
1440 pInfo
->srWindow
.Top
= 0;
1441 pInfo
->srWindow
.Bottom
= Buff
->MaxY
- 1;
1442 pInfo
->dwMaximumWindowSize
.X
= Buff
->MaxX
;
1443 pInfo
->dwMaximumWindowSize
.Y
= Buff
->MaxY
;
1444 ConioUnlockScreenBuffer(Buff
);
1446 Reply
->Status
= STATUS_SUCCESS
;
1448 return Reply
->Status
;
1451 CSR_API(CsrSetCursor
)
1454 PCSRSS_CONSOLE Console
;
1455 PCSRSS_SCREEN_BUFFER Buff
;
1456 LONG OldCursorX
, OldCursorY
;
1457 LONG NewCursorX
, NewCursorY
;
1459 DPRINT("CsrSetCursor\n");
1461 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1462 if (! NT_SUCCESS(Status
))
1464 return Reply
->Status
= Status
;
1467 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1468 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1470 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
);
1471 if (! NT_SUCCESS(Status
))
1473 if (NULL
!= Console
)
1475 ConioUnlockConsole(Console
);
1477 return Reply
->Status
= Status
;
1480 NewCursorX
= Request
->Data
.SetCursorRequest
.Position
.X
;
1481 NewCursorY
= Request
->Data
.SetCursorRequest
.Position
.Y
;
1482 if (NewCursorX
< 0 || NewCursorX
>= Buff
->MaxX
||
1483 NewCursorY
< 0 || NewCursorY
>= Buff
->MaxY
)
1485 ConioUnlockScreenBuffer(Buff
);
1486 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
1488 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &OldCursorX
, &OldCursorY
);
1489 Buff
->CurrentX
= NewCursorX
+ Buff
->ShowX
;
1490 Buff
->CurrentY
= (NewCursorY
+ Buff
->ShowY
) % Buff
->MaxY
;
1491 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1493 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
1495 ConioUnlockScreenBuffer(Buff
);
1496 return Reply
->Status
= STATUS_UNSUCCESSFUL
;
1500 ConioUnlockScreenBuffer(Buff
);
1501 if (NULL
!= Console
)
1503 ConioUnlockConsole(Console
);
1506 return Reply
->Status
= STATUS_SUCCESS
;
1509 STATIC FASTCALL VOID
1510 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, COORD
*Start
, UINT Length
)
1512 if (Buff
->MaxX
<= Start
->X
+ Length
)
1514 UpdateRect
->left
= 0;
1518 UpdateRect
->left
= Start
->X
;
1520 if (Buff
->MaxX
<= Start
->X
+ Length
)
1522 UpdateRect
->right
= Buff
->MaxX
- 1;
1526 UpdateRect
->right
= Start
->X
+ Length
- 1;
1528 UpdateRect
->top
= Start
->Y
;
1529 UpdateRect
->bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->MaxX
;
1530 if (Buff
->MaxY
<= UpdateRect
->bottom
)
1532 UpdateRect
->bottom
= Buff
->MaxY
- 1;
1536 CSR_API(CsrWriteConsoleOutputChar
)
1539 PCHAR String
= (PCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
;
1541 PCSRSS_CONSOLE Console
;
1542 PCSRSS_SCREEN_BUFFER Buff
;
1543 DWORD X
, Y
, Length
, CharSize
, Written
= 0;
1546 DPRINT("CsrWriteConsoleOutputChar\n");
1548 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1549 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1551 CharSize
= (Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
1553 if (Request
->Header
.DataSize
1554 < sizeof(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR_REQUEST
) - 1
1555 + (Request
->Data
.WriteConsoleOutputCharRequest
.Length
* CharSize
))
1557 DPRINT1("Invalid request size\n");
1558 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
1561 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1562 if (! NT_SUCCESS(Status
))
1564 return Reply
->Status
= Status
;
1567 if(Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
)
1569 ConsoleUnicodeToAnsiN(Console
, String
, (PWCHAR
)String
, Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
1572 Status
= ConioLockScreenBuffer(ProcessData
,
1573 Request
->Data
.WriteConsoleOutputCharRequest
.ConsoleHandle
,
1575 if (! NT_SUCCESS(Status
))
1577 if (NULL
!= Console
)
1579 ConioUnlockConsole(Console
);
1581 return Reply
->Status
= Status
;
1584 X
= Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.X
+ Buff
->ShowX
;
1585 Y
= (Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1586 Length
= Request
->Data
.WriteConsoleOutputCharRequest
.Length
;
1587 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1590 *Buffer
= *String
++;
1593 if (++X
== Buff
->MaxX
)
1595 if (++Y
== Buff
->MaxY
)
1598 Buffer
= Buff
->Buffer
;
1604 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1606 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputCharRequest
.Coord
,
1607 Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
1608 ConioDrawRegion(Console
, &UpdateRect
);
1611 Reply
->Data
.WriteConsoleOutputCharReply
.EndCoord
.X
= X
- Buff
->ShowX
;
1612 Reply
->Data
.WriteConsoleOutputCharReply
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1614 ConioUnlockScreenBuffer(Buff
);
1615 if (NULL
!= Console
)
1617 ConioUnlockConsole(Console
);
1620 Reply
->Data
.WriteConsoleOutputCharReply
.NrCharactersWritten
= Written
;
1621 return Reply
->Status
= STATUS_SUCCESS
;
1624 CSR_API(CsrFillOutputChar
)
1627 PCSRSS_CONSOLE Console
;
1628 PCSRSS_SCREEN_BUFFER Buff
;
1629 DWORD X
, Y
, Length
, Written
= 0;
1634 DPRINT("CsrFillOutputChar\n");
1636 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1637 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1639 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1640 if (! NT_SUCCESS(Status
))
1642 return Reply
->Status
= Status
;
1645 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputRequest
.ConsoleHandle
, &Buff
);
1646 if (! NT_SUCCESS(Status
))
1648 if (NULL
!= Console
)
1650 ConioUnlockConsole(Console
);
1652 return Reply
->Status
= Status
;
1655 X
= Request
->Data
.FillOutputRequest
.Position
.X
+ Buff
->ShowX
;
1656 Y
= (Request
->Data
.FillOutputRequest
.Position
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1657 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1658 if(Request
->Data
.FillOutputRequest
.Unicode
)
1659 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &Request
->Data
.FillOutputRequest
.Char
.UnicodeChar
);
1661 Char
= Request
->Data
.FillOutputRequest
.Char
.AsciiChar
;
1662 Length
= Request
->Data
.FillOutputRequest
.Length
;
1668 if (++X
== Buff
->MaxX
)
1670 if (++Y
== Buff
->MaxY
)
1673 Buffer
= Buff
->Buffer
;
1679 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1681 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputRequest
.Position
,
1682 Request
->Data
.FillOutputRequest
.Length
);
1683 ConioDrawRegion(Console
, &UpdateRect
);
1686 ConioUnlockScreenBuffer(Buff
);
1687 if (NULL
!= Console
)
1689 ConioUnlockConsole(Console
);
1692 return Reply
->Status
;
1695 CSR_API(CsrReadInputEvent
)
1697 PLIST_ENTRY CurrentEntry
;
1698 PCSRSS_CONSOLE Console
;
1700 BOOLEAN Done
= FALSE
;
1701 ConsoleInput
*Input
;
1703 DPRINT("CsrReadInputEvent\n");
1705 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1706 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1707 Reply
->Data
.ReadInputReply
.Event
= ProcessData
->ConsoleEvent
;
1709 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadInputRequest
.ConsoleHandle
, &Console
);
1710 if (! NT_SUCCESS(Status
))
1712 return Reply
->Status
= Status
;
1715 /* only get input if there is any */
1716 CurrentEntry
= Console
->InputEvents
.Flink
;
1717 while (CurrentEntry
!= &Console
->InputEvents
)
1719 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
1720 CurrentEntry
= CurrentEntry
->Flink
;
1722 if (Done
&& !Input
->Fake
)
1724 Reply
->Data
.ReadInputReply
.MoreEvents
= TRUE
;
1728 RemoveEntryList(&Input
->ListEntry
);
1730 if (!Done
&& !Input
->Fake
)
1732 Reply
->Data
.ReadInputReply
.Input
= Input
->InputEvent
;
1733 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
1735 ConioInputEventToAnsi(Console
, &Reply
->Data
.ReadInputReply
.Input
);
1740 if (Input
->InputEvent
.EventType
== KEY_EVENT
)
1742 if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
)
1743 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
1744 && '\r' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1746 Console
->WaitingLines
--;
1748 Console
->WaitingChars
--;
1750 HeapFree(Win32CsrApiHeap
, 0, Input
);
1755 Status
= STATUS_SUCCESS
;
1756 Console
->EarlyReturn
= FALSE
;
1760 Status
= STATUS_PENDING
;
1761 Console
->EarlyReturn
= TRUE
; /* mark for early return */
1764 if (IsListEmpty(&Console
->InputEvents
))
1766 ResetEvent(Console
->ActiveEvent
);
1769 ConioUnlockConsole(Console
);
1771 return Reply
->Status
= Status
;
1774 CSR_API(CsrWriteConsoleOutputAttrib
)
1776 PCSRSS_CONSOLE Console
;
1777 PCSRSS_SCREEN_BUFFER Buff
;
1778 PUCHAR Buffer
, Attribute
;
1783 DPRINT("CsrWriteConsoleOutputAttrib\n");
1785 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1786 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1788 if (Request
->Header
.DataSize
1789 < sizeof(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB_REQUEST
) - 1
1790 + Request
->Data
.WriteConsoleOutputAttribRequest
.Length
)
1792 DPRINT1("Invalid request size\n");
1793 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
1796 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1797 if (! NT_SUCCESS(Status
))
1799 return Reply
->Status
= Status
;
1802 Status
= ConioLockScreenBuffer(ProcessData
,
1803 Request
->Data
.WriteConsoleOutputAttribRequest
.ConsoleHandle
,
1805 if (! NT_SUCCESS(Status
))
1807 if (NULL
!= Console
)
1809 ConioUnlockConsole(Console
);
1811 return Reply
->Status
= Status
;
1814 X
= Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1815 Y
= (Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1816 Length
= Request
->Data
.WriteConsoleOutputAttribRequest
.Length
;
1817 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + 1];
1818 Attribute
= (PUCHAR
)Request
->Data
.WriteConsoleOutputAttribRequest
.String
;
1821 *Buffer
= *Attribute
++;
1823 if (++X
== Buff
->MaxX
)
1825 if (++Y
== Buff
->MaxY
)
1828 Buffer
= Buff
->Buffer
+ 1;
1834 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1836 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
,
1837 Request
->Data
.WriteConsoleOutputAttribRequest
.Length
);
1838 ConioDrawRegion(Console
, &UpdateRect
);
1841 if (NULL
!= Console
)
1843 ConioUnlockConsole(Console
);
1846 Reply
->Data
.WriteConsoleOutputAttribReply
.EndCoord
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1847 Reply
->Data
.WriteConsoleOutputAttribReply
.EndCoord
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1849 ConioUnlockScreenBuffer(Buff
);
1851 return Reply
->Status
= STATUS_SUCCESS
;
1854 CSR_API(CsrFillOutputAttrib
)
1856 PCSRSS_SCREEN_BUFFER Buff
;
1862 PCSRSS_CONSOLE Console
;
1864 DPRINT("CsrFillOutputAttrib\n");
1866 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1867 if (! NT_SUCCESS(Status
))
1869 return Reply
->Status
= Status
;
1872 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1873 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1874 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputAttribRequest
.ConsoleHandle
, &Buff
);
1875 if (! NT_SUCCESS(Status
))
1877 if (NULL
!= Console
)
1879 ConioUnlockConsole(Console
);
1881 return Reply
->Status
= Status
;
1884 X
= Request
->Data
.FillOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1885 Y
= (Request
->Data
.FillOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1886 Length
= Request
->Data
.FillOutputAttribRequest
.Length
;
1887 Attr
= Request
->Data
.FillOutputAttribRequest
.Attribute
;
1888 Buffer
= &Buff
->Buffer
[(Y
* Buff
->MaxX
* 2) + (X
* 2) + 1];
1893 if (++X
== Buff
->MaxX
)
1895 if (++Y
== Buff
->MaxY
)
1898 Buffer
= Buff
->Buffer
+ 1;
1904 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1906 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputAttribRequest
.Coord
,
1907 Request
->Data
.FillOutputAttribRequest
.Length
);
1908 ConioDrawRegion(Console
, &UpdateRect
);
1911 ConioUnlockScreenBuffer(Buff
);
1912 if (NULL
!= Console
)
1914 ConioUnlockConsole(Console
);
1917 return Reply
->Status
= STATUS_SUCCESS
;
1921 CSR_API(CsrGetCursorInfo
)
1923 PCSRSS_SCREEN_BUFFER Buff
;
1926 DPRINT("CsrGetCursorInfo\n");
1928 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1929 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1931 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.GetCursorInfoRequest
.ConsoleHandle
, &Buff
);
1932 if (! NT_SUCCESS(Status
))
1934 return Reply
->Status
= Status
;
1936 Reply
->Data
.GetCursorInfoReply
.Info
= Buff
->CursorInfo
;
1937 ConioUnlockScreenBuffer(Buff
);
1939 return Reply
->Status
= STATUS_SUCCESS
;
1942 CSR_API(CsrSetCursorInfo
)
1944 PCSRSS_CONSOLE Console
;
1945 PCSRSS_SCREEN_BUFFER Buff
;
1950 DPRINT("CsrSetCursorInfo\n");
1952 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1953 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
1955 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1956 if (! NT_SUCCESS(Status
))
1958 return Reply
->Status
= Status
;
1961 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorInfoRequest
.ConsoleHandle
, &Buff
);
1962 if (! NT_SUCCESS(Status
))
1964 if (NULL
!= Console
)
1966 ConioUnlockConsole(Console
);
1968 return Reply
->Status
= Status
;
1971 Size
= Request
->Data
.SetCursorInfoRequest
.Info
.dwSize
;
1972 Visible
= Request
->Data
.SetCursorInfoRequest
.Info
.bVisible
;
1982 if (Size
!= Buff
->CursorInfo
.dwSize
1983 || (Visible
&& ! Buff
->CursorInfo
.bVisible
) || (! Visible
&& Buff
->CursorInfo
.bVisible
))
1985 Buff
->CursorInfo
.dwSize
= Size
;
1986 Buff
->CursorInfo
.bVisible
= Visible
;
1988 if (NULL
!= Console
&& ! ConioSetCursorInfo(Console
, Buff
))
1990 ConioUnlockScreenBuffer(Buff
);
1991 ConioUnlockConsole(Console
);
1992 return Reply
->Status
= STATUS_UNSUCCESSFUL
;
1996 ConioUnlockScreenBuffer(Buff
);
1997 if (NULL
!= Console
)
1999 ConioUnlockConsole(Console
);
2002 return Reply
->Status
= STATUS_SUCCESS
;
2005 CSR_API(CsrSetTextAttrib
)
2008 PCSRSS_CONSOLE Console
;
2009 PCSRSS_SCREEN_BUFFER Buff
;
2010 LONG OldCursorX
, OldCursorY
;
2012 DPRINT("CsrSetTextAttrib\n");
2014 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2015 if (! NT_SUCCESS(Status
))
2017 return Reply
->Status
= Status
;
2020 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
);
2021 if (! NT_SUCCESS(Status
))
2023 if (NULL
!= Console
)
2025 ConioUnlockConsole(Console
);
2027 return Reply
->Status
= Status
;
2030 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &OldCursorX
, &OldCursorY
);
2032 Buff
->DefaultAttrib
= Request
->Data
.SetAttribRequest
.Attrib
;
2033 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
2035 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
2037 ConioUnlockScreenBuffer(Buff
);
2038 ConioUnlockConsole(Console
);
2039 return Reply
->Status
= STATUS_UNSUCCESSFUL
;
2043 ConioUnlockScreenBuffer(Buff
);
2044 if (NULL
!= Console
)
2046 ConioUnlockConsole(Console
);
2049 return Reply
->Status
= STATUS_SUCCESS
;
2052 CSR_API(CsrSetConsoleMode
)
2055 PCSRSS_CONSOLE Console
;
2056 PCSRSS_SCREEN_BUFFER Buff
;
2058 DPRINT("CsrSetConsoleMode\n");
2060 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2061 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2062 Status
= Win32CsrGetObject(ProcessData
,
2063 Request
->Data
.SetConsoleModeRequest
.ConsoleHandle
,
2064 (Object_t
**) &Console
);
2065 if (! NT_SUCCESS(Status
))
2067 return Reply
->Status
= Status
;
2070 Buff
= (PCSRSS_SCREEN_BUFFER
)Console
;
2071 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
2073 Console
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_INPUT_MODE_VALID
;
2075 else if (CONIO_SCREEN_BUFFER_MAGIC
== Console
->Header
.Type
)
2077 Buff
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_OUTPUT_MODE_VALID
;
2081 return Reply
->Status
= STATUS_INVALID_HANDLE
;
2084 Reply
->Status
= STATUS_SUCCESS
;
2086 return Reply
->Status
;
2089 CSR_API(CsrGetConsoleMode
)
2092 PCSRSS_CONSOLE Console
;
2093 PCSRSS_SCREEN_BUFFER Buff
; /* gee, I really wish I could use an anonymous union here */
2095 DPRINT("CsrGetConsoleMode\n");
2097 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2098 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2099 Status
= Win32CsrGetObject(ProcessData
, Request
->Data
.GetConsoleModeRequest
.ConsoleHandle
,
2100 (Object_t
**) &Console
);
2101 if (! NT_SUCCESS(Status
))
2103 return Reply
->Status
= Status
;
2105 Reply
->Status
= STATUS_SUCCESS
;
2106 Buff
= (PCSRSS_SCREEN_BUFFER
) Console
;
2107 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
2109 Reply
->Data
.GetConsoleModeReply
.ConsoleMode
= Console
->Mode
;
2111 else if (CONIO_SCREEN_BUFFER_MAGIC
== Buff
->Header
.Type
)
2113 Reply
->Data
.GetConsoleModeReply
.ConsoleMode
= Buff
->Mode
;
2117 Reply
->Status
= STATUS_INVALID_HANDLE
;
2120 return Reply
->Status
;
2123 CSR_API(CsrCreateScreenBuffer
)
2125 PCSRSS_CONSOLE Console
;
2126 PCSRSS_SCREEN_BUFFER Buff
;
2129 DPRINT("CsrCreateScreenBuffer\n");
2131 if (ProcessData
== NULL
)
2133 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
2136 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2137 if (! NT_SUCCESS(Status
))
2139 return Reply
->Status
= Status
;
2141 if (NULL
== Console
)
2143 return Reply
->Status
= STATUS_INVALID_HANDLE
;
2146 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2147 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2149 Buff
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(CSRSS_SCREEN_BUFFER
));
2152 Reply
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2155 Status
= CsrInitConsoleScreenBuffer(Console
, Buff
);
2156 if(! NT_SUCCESS(Status
))
2158 Reply
->Status
= Status
;
2162 Reply
->Status
= Win32CsrInsertObject(ProcessData
, &Reply
->Data
.CreateScreenBufferReply
.OutputHandle
, &Buff
->Header
);
2165 ConioUnlockConsole(Console
);
2167 return Reply
->Status
;
2170 CSR_API(CsrSetScreenBuffer
)
2173 PCSRSS_CONSOLE Console
;
2174 PCSRSS_SCREEN_BUFFER Buff
;
2176 DPRINT("CsrSetScreenBuffer\n");
2178 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2179 if (! NT_SUCCESS(Status
))
2181 return Reply
->Status
= Status
;
2183 if (NULL
== Console
)
2185 DPRINT1("Trying to set screen buffer for app without console\n");
2186 return Reply
->Status
= STATUS_INVALID_HANDLE
;
2189 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2190 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2192 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetScreenBufferRequest
.OutputHandle
, &Buff
);
2193 if (! NT_SUCCESS(Status
))
2195 ConioUnlockConsole(Console
);
2196 return Reply
->Status
;
2199 if (Buff
== Console
->ActiveBuffer
)
2201 ConioUnlockScreenBuffer(Buff
);
2202 ConioUnlockConsole(Console
);
2203 return STATUS_SUCCESS
;
2206 /* drop reference to old buffer, maybe delete */
2207 if (! InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
2209 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
2211 /* tie console to new buffer */
2212 Console
->ActiveBuffer
= Buff
;
2213 /* inc ref count on new buffer */
2214 InterlockedIncrement(&Buff
->Header
.ReferenceCount
);
2215 /* Redraw the console */
2216 ConioDrawConsole(Console
);
2218 ConioUnlockScreenBuffer(Buff
);
2219 ConioUnlockConsole(Console
);
2221 return Reply
->Status
= STATUS_SUCCESS
;
2224 CSR_API(CsrSetTitle
)
2227 PCSRSS_CONSOLE Console
;
2229 DPRINT("CsrSetTitle\n");
2231 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2232 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2234 if (Request
->Header
.DataSize
2235 < sizeof(CSRSS_SET_TITLE_REQUEST
) - 1
2236 + Request
->Data
.SetTitleRequest
.Length
)
2238 DPRINT1("Invalid request size\n");
2239 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
2242 Status
= ConioLockConsole(ProcessData
, Request
->Data
.SetTitleRequest
.Console
, &Console
);
2243 if(! NT_SUCCESS(Status
))
2245 Reply
->Status
= Status
;
2249 /* copy title to console */
2250 RtlFreeUnicodeString(&Console
->Title
);
2251 RtlCreateUnicodeString(&Console
->Title
, Request
->Data
.SetTitleRequest
.Title
);
2252 if (! ConioChangeTitle(Console
))
2254 Reply
->Status
= STATUS_UNSUCCESSFUL
;
2258 Reply
->Status
= STATUS_SUCCESS
;
2261 ConioUnlockConsole(Console
);
2263 return Reply
->Status
;
2266 CSR_API(CsrGetTitle
)
2269 PCSRSS_CONSOLE Console
;
2271 DPRINT("CsrGetTitle\n");
2273 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2274 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2275 Status
= ConioLockConsole(ProcessData
,
2276 Request
->Data
.GetTitleRequest
.ConsoleHandle
,
2278 if (! NT_SUCCESS(Status
))
2280 DPRINT1("Can't get console\n");
2281 return Reply
->Status
= Status
;
2284 /* Copy title of the console to the user title buffer */
2285 RtlZeroMemory(&Reply
->Data
.GetTitleReply
, sizeof(CSRSS_GET_TITLE_REPLY
));
2286 Reply
->Data
.GetTitleReply
.ConsoleHandle
= Request
->Data
.GetTitleRequest
.ConsoleHandle
;
2287 Reply
->Data
.GetTitleReply
.Length
= Console
->Title
.Length
;
2288 wcscpy (Reply
->Data
.GetTitleReply
.Title
, Console
->Title
.Buffer
);
2289 Reply
->Header
.MessageSize
+= Console
->Title
.Length
;
2290 Reply
->Header
.DataSize
+= Console
->Title
.Length
;
2291 Reply
->Status
= STATUS_SUCCESS
;
2293 ConioUnlockConsole(Console
);
2295 return Reply
->Status
;
2298 CSR_API(CsrWriteConsoleOutput
)
2300 SHORT i
, X
, Y
, SizeX
, SizeY
;
2301 PCSRSS_CONSOLE Console
;
2302 PCSRSS_SCREEN_BUFFER Buff
;
2304 CHAR_INFO
* CurCharInfo
;
2306 CHAR_INFO
* CharInfo
;
2313 DPRINT("CsrWriteConsoleOutput\n");
2315 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2316 if (! NT_SUCCESS(Status
))
2318 return Reply
->Status
= Status
;
2321 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2322 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2323 Status
= ConioLockScreenBuffer(ProcessData
,
2324 Request
->Data
.WriteConsoleOutputRequest
.ConsoleHandle
,
2326 if (! NT_SUCCESS(Status
))
2328 if (NULL
!= Console
)
2330 ConioUnlockConsole(Console
);
2332 return Reply
->Status
= Status
;
2335 BufferSize
= Request
->Data
.WriteConsoleOutputRequest
.BufferSize
;
2336 PSize
= BufferSize
.X
* BufferSize
.Y
* sizeof(CHAR_INFO
);
2337 BufferCoord
= Request
->Data
.WriteConsoleOutputRequest
.BufferCoord
;
2338 CharInfo
= Request
->Data
.WriteConsoleOutputRequest
.CharInfo
;
2339 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
) ||
2340 (((PVOID
)CharInfo
+ PSize
) >
2341 (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2343 ConioUnlockScreenBuffer(Buff
);
2344 ConioUnlockConsole(Console
);
2345 return Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2347 WriteRegion
.left
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
;
2348 WriteRegion
.top
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
;
2349 WriteRegion
.right
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
;
2350 WriteRegion
.bottom
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
;
2352 SizeY
= RtlRosMin(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&WriteRegion
));
2353 SizeX
= RtlRosMin(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&WriteRegion
));
2354 WriteRegion
.bottom
= WriteRegion
.top
+ SizeY
- 1;
2355 WriteRegion
.right
= WriteRegion
.left
+ SizeX
- 1;
2357 /* Make sure WriteRegion is inside the screen buffer */
2358 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2359 if (! ConioGetIntersection(&WriteRegion
, &ScreenBuffer
, &WriteRegion
))
2361 ConioUnlockScreenBuffer(Buff
);
2362 ConioUnlockConsole(Console
);
2364 /* It is okay to have a WriteRegion completely outside the screen buffer.
2365 No data is written then. */
2366 return Reply
->Status
= STATUS_SUCCESS
;
2369 for (i
= 0, Y
= WriteRegion
.top
; Y
<= WriteRegion
.bottom
; i
++, Y
++)
2371 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
2372 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ WriteRegion
.left
) * 2;
2373 for (X
= WriteRegion
.left
; X
<= WriteRegion
.right
; X
++)
2375 if (Request
->Data
.WriteConsoleOutputRequest
.Unicode
)
2378 ConsoleUnicodeCharToAnsiChar(Console
, &AsciiChar
, &CurCharInfo
->Char
.UnicodeChar
);
2379 SET_CELL_BUFFER(Buff
, Offset
, AsciiChar
, CurCharInfo
->Attributes
);
2383 SET_CELL_BUFFER(Buff
, Offset
, CurCharInfo
->Char
.AsciiChar
, CurCharInfo
->Attributes
);
2389 if (NULL
!= Console
)
2391 ConioDrawRegion(Console
, &WriteRegion
);
2394 ConioUnlockScreenBuffer(Buff
);
2395 ConioUnlockConsole(Console
);
2397 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Right
= WriteRegion
.left
+ SizeX
- 1;
2398 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Bottom
= WriteRegion
.top
+ SizeY
- 1;
2399 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Left
= WriteRegion
.left
;
2400 Reply
->Data
.WriteConsoleOutputReply
.WriteRegion
.Top
= WriteRegion
.top
;
2402 return Reply
->Status
= STATUS_SUCCESS
;
2405 CSR_API(CsrFlushInputBuffer
)
2407 PLIST_ENTRY CurrentEntry
;
2408 PCSRSS_CONSOLE Console
;
2409 ConsoleInput
* Input
;
2412 DPRINT("CsrFlushInputBuffer\n");
2414 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2415 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2416 Status
= ConioLockConsole(ProcessData
,
2417 Request
->Data
.FlushInputBufferRequest
.ConsoleInput
,
2419 if(! NT_SUCCESS(Status
))
2421 return Reply
->Status
= Status
;
2424 /* Discard all entries in the input event queue */
2425 while (!IsListEmpty(&Console
->InputEvents
))
2427 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
2428 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
2429 /* Destroy the event */
2430 HeapFree(Win32CsrApiHeap
, 0, Input
);
2432 ResetEvent(Console
->ActiveEvent
);
2433 Console
->WaitingChars
=0;
2435 ConioUnlockConsole(Console
);
2437 return Reply
->Status
= STATUS_SUCCESS
;
2440 CSR_API(CsrScrollConsoleScreenBuffer
)
2442 PCSRSS_CONSOLE Console
;
2443 PCSRSS_SCREEN_BUFFER Buff
;
2448 RECT ScrollRectangle
;
2453 DPRINT("CsrScrollConsoleScreenBuffer\n");
2455 ALIAS(ConsoleHandle
,Request
->Data
.ScrollConsoleScreenBufferRequest
.ConsoleHandle
);
2456 ALIAS(UseClipRectangle
,Request
->Data
.ScrollConsoleScreenBufferRequest
.UseClipRectangle
);
2457 ALIAS(DestinationOrigin
,Request
->Data
.ScrollConsoleScreenBufferRequest
.DestinationOrigin
);
2458 ALIAS(Fill
,Request
->Data
.ScrollConsoleScreenBufferRequest
.Fill
);
2460 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2461 if (! NT_SUCCESS(Status
))
2463 return Reply
->Status
= Status
;
2466 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2467 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2468 Status
= ConioLockScreenBuffer(ProcessData
, ConsoleHandle
, &Buff
);
2469 if (! NT_SUCCESS(Status
))
2471 if (NULL
!= Console
)
2473 ConioUnlockConsole(Console
);
2475 return Reply
->Status
= Status
;
2478 ScrollRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Left
;
2479 ScrollRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Top
;
2480 ScrollRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Right
;
2481 ScrollRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Bottom
;
2482 ClipRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Left
;
2483 ClipRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Top
;
2484 ClipRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Right
;
2485 ClipRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Bottom
;
2487 /* Make sure source rectangle is inside the screen buffer */
2488 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2489 if (! ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, &ScrollRectangle
))
2491 ConioUnlockScreenBuffer(Buff
);
2492 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
2495 if (UseClipRectangle
&& ! ConioGetIntersection(&SrcRegion
, &SrcRegion
, &ClipRectangle
))
2497 ConioUnlockScreenBuffer(Buff
);
2498 return Reply
->Status
= STATUS_SUCCESS
;
2502 ConioInitRect(&DstRegion
,
2503 DestinationOrigin
.Y
,
2504 DestinationOrigin
.X
,
2505 DestinationOrigin
.Y
+ ConioRectHeight(&ScrollRectangle
) - 1,
2506 DestinationOrigin
.X
+ ConioRectWidth(&ScrollRectangle
) - 1);
2508 /* Make sure destination rectangle is inside the screen buffer */
2509 if (! ConioGetIntersection(&DstRegion
, &DstRegion
, &ScreenBuffer
))
2511 ConioUnlockScreenBuffer(Buff
);
2512 return Reply
->Status
= STATUS_INVALID_PARAMETER
;
2515 ConioCopyRegion(Buff
, &SrcRegion
, &DstRegion
);
2517 /* Get the region that should be filled with the specified character and attributes */
2521 ConioGetUnion(&FillRegion
, &SrcRegion
, &DstRegion
);
2523 if (ConioSubtractRect(&FillRegion
, &FillRegion
, &DstRegion
))
2525 /* FIXME: The subtracted rectangle is off by one line */
2526 FillRegion
.top
+= 1;
2528 ConioFillRegion(Console
, Buff
, &FillRegion
, &Fill
, Request
->Data
.ScrollConsoleScreenBufferRequest
.Unicode
);
2532 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
2534 /* Draw destination region */
2535 ConioDrawRegion(Console
, &DstRegion
);
2539 /* Draw filled region */
2540 ConioDrawRegion(Console
, &FillRegion
);
2544 ConioUnlockScreenBuffer(Buff
);
2545 if (NULL
!= Console
)
2547 ConioUnlockConsole(Console
);
2550 return Reply
->Status
= STATUS_SUCCESS
;
2553 CSR_API(CsrReadConsoleOutputChar
)
2556 PCSRSS_CONSOLE Console
;
2557 PCSRSS_SCREEN_BUFFER Buff
;
2564 DPRINT("CsrReadConsoleOutputChar\n");
2566 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2567 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
2568 ReadBuffer
= Reply
->Data
.ReadConsoleOutputCharReply
.String
;
2570 CharSize
= (Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
2572 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2573 if (! NT_SUCCESS(Status
))
2575 return Reply
->Status
= Status
;
2578 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputCharRequest
.ConsoleHandle
, &Buff
);
2579 if (! NT_SUCCESS(Status
))
2581 return Reply
->Status
= Status
;
2584 Xpos
= Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.X
+ Buff
->ShowX
;
2585 Ypos
= (Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
2587 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
; ++i
)
2589 Char
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
)];
2591 if(Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
)
2593 ConsoleAnsiCharToUnicodeChar(Console
, (WCHAR
*)ReadBuffer
, &Char
);
2594 ReadBuffer
+= sizeof(WCHAR
);
2597 *(ReadBuffer
++) = Char
;
2601 if (Xpos
== Buff
->MaxX
)
2606 if (Ypos
== Buff
->MaxY
)
2614 Reply
->Status
= STATUS_SUCCESS
;
2615 Reply
->Data
.ReadConsoleOutputCharReply
.EndCoord
.X
= Xpos
- Buff
->ShowX
;
2616 Reply
->Data
.ReadConsoleOutputCharReply
.EndCoord
.Y
= (Ypos
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
;
2617 Reply
->Header
.MessageSize
+= Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
;
2618 Reply
->Header
.DataSize
+= Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
;
2620 ConioUnlockScreenBuffer(Buff
);
2621 if (NULL
!= Console
)
2623 ConioUnlockConsole(Console
);
2626 Reply
->Data
.ReadConsoleOutputCharReply
.CharsRead
= (DWORD
)((ULONG_PTR
)ReadBuffer
- (ULONG_PTR
)Reply
->Data
.ReadConsoleOutputCharReply
.String
) / CharSize
;
2628 return Reply
->Status
;
2632 CSR_API(CsrReadConsoleOutputAttrib
)
2635 PCSRSS_SCREEN_BUFFER Buff
;
2640 DPRINT("CsrReadConsoleOutputAttrib\n");
2642 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2643 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
2644 ReadBuffer
= Reply
->Data
.ReadConsoleOutputAttribReply
.String
;
2646 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputAttribRequest
.ConsoleHandle
, &Buff
);
2647 if (! NT_SUCCESS(Status
))
2649 return Reply
->Status
= Status
;
2652 Xpos
= Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.X
+ Buff
->ShowX
;
2653 Ypos
= (Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
2655 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
; ++i
)
2657 *ReadBuffer
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
) + 1];
2662 if (Xpos
== Buff
->MaxX
)
2667 if (Ypos
== Buff
->MaxY
)
2676 Reply
->Status
= STATUS_SUCCESS
;
2677 Reply
->Data
.ReadConsoleOutputAttribReply
.EndCoord
.X
= Xpos
- Buff
->ShowX
;
2678 Reply
->Data
.ReadConsoleOutputAttribReply
.EndCoord
.Y
= (Ypos
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
;
2679 Reply
->Header
.MessageSize
+= Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
;
2680 Reply
->Header
.DataSize
+= Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
;
2682 ConioUnlockScreenBuffer(Buff
);
2684 return Reply
->Status
;
2688 CSR_API(CsrGetNumberOfConsoleInputEvents
)
2691 PCSRSS_CONSOLE Console
;
2692 PLIST_ENTRY CurrentItem
;
2694 ConsoleInput
*Input
;
2696 DPRINT("CsrGetNumberOfConsoleInputEvents\n");
2698 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2699 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
2701 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
);
2702 if (! NT_SUCCESS(Status
))
2704 return Reply
->Status
= Status
;
2707 CurrentItem
= Console
->InputEvents
.Flink
;
2710 /* If there are any events ... */
2711 while (CurrentItem
!= &Console
->InputEvents
)
2713 Input
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2714 CurrentItem
= CurrentItem
->Flink
;
2721 ConioUnlockConsole(Console
);
2723 Reply
->Status
= STATUS_SUCCESS
;
2724 Reply
->Data
.GetNumInputEventsReply
.NumInputEvents
= NumEvents
;
2726 return Reply
->Status
;
2730 CSR_API(CsrPeekConsoleInput
)
2733 PCSRSS_CONSOLE Console
;
2736 PLIST_ENTRY CurrentItem
;
2737 PINPUT_RECORD InputRecord
;
2741 DPRINT("CsrPeekConsoleInput\n");
2743 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2744 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2746 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
);
2747 if(! NT_SUCCESS(Status
))
2749 return Reply
->Status
= Status
;
2752 InputRecord
= Request
->Data
.PeekConsoleInputRequest
.InputRecord
;
2753 Length
= Request
->Data
.PeekConsoleInputRequest
.Length
;
2754 Size
= Length
* sizeof(INPUT_RECORD
);
2756 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2757 || (((PVOID
)InputRecord
+ Size
) > (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2759 ConioUnlockConsole(Console
);
2760 Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2761 return Reply
->Status
;
2766 if (! IsListEmpty(&Console
->InputEvents
))
2768 CurrentItem
= Console
->InputEvents
.Flink
;
2770 while (CurrentItem
!= &Console
->InputEvents
&& NumItems
< Length
)
2772 Item
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2776 CurrentItem
= CurrentItem
->Flink
;
2781 *InputRecord
= Item
->InputEvent
;
2783 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
2785 ConioInputEventToAnsi(Console
, InputRecord
);
2789 CurrentItem
= CurrentItem
->Flink
;
2793 ConioUnlockConsole(Console
);
2795 Reply
->Status
= STATUS_SUCCESS
;
2796 Reply
->Data
.PeekConsoleInputReply
.Length
= NumItems
;
2798 return Reply
->Status
;
2802 CSR_API(CsrReadConsoleOutput
)
2804 PCHAR_INFO CharInfo
;
2805 PCHAR_INFO CurCharInfo
;
2806 PCSRSS_SCREEN_BUFFER Buff
;
2815 DWORD i
, Y
, X
, Offset
;
2818 DPRINT("CsrReadConsoleOutput\n");
2820 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2821 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2823 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputRequest
.ConsoleHandle
, &Buff
);
2824 if (! NT_SUCCESS(Status
))
2826 return Reply
->Status
= Status
;
2829 CharInfo
= Request
->Data
.ReadConsoleOutputRequest
.CharInfo
;
2830 ReadRegion
.left
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
;
2831 ReadRegion
.top
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
;
2832 ReadRegion
.right
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
;
2833 ReadRegion
.bottom
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
;
2834 BufferSize
= Request
->Data
.ReadConsoleOutputRequest
.BufferSize
;
2835 BufferCoord
= Request
->Data
.ReadConsoleOutputRequest
.BufferCoord
;
2836 Length
= BufferSize
.X
* BufferSize
.Y
;
2837 Size
= Length
* sizeof(CHAR_INFO
);
2839 /* FIXME: Is this correct? */
2840 CodePage
= ProcessData
->Console
->OutputCodePage
;
2842 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
)
2843 || (((PVOID
)CharInfo
+ Size
) > (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2845 ConioUnlockScreenBuffer(Buff
);
2846 Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2847 return Reply
->Status
;
2850 SizeY
= RtlRosMin(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&ReadRegion
));
2851 SizeX
= RtlRosMin(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&ReadRegion
));
2852 ReadRegion
.bottom
= ReadRegion
.top
+ SizeY
;
2853 ReadRegion
.right
= ReadRegion
.left
+ SizeX
;
2855 ConioInitRect(&ScreenRect
, 0, 0, Buff
->MaxY
, Buff
->MaxX
);
2856 if (! ConioGetIntersection(&ReadRegion
, &ScreenRect
, &ReadRegion
))
2858 ConioUnlockScreenBuffer(Buff
);
2859 Reply
->Status
= STATUS_SUCCESS
;
2860 return Reply
->Status
;
2863 for (i
= 0, Y
= ReadRegion
.top
; Y
< ReadRegion
.bottom
; ++i
, ++Y
)
2865 CurCharInfo
= CharInfo
+ (i
* BufferSize
.X
);
2867 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ ReadRegion
.left
) * 2;
2868 for (X
= ReadRegion
.left
; X
< ReadRegion
.right
; ++X
)
2870 if (Request
->Data
.ReadConsoleOutputRequest
.Unicode
)
2872 MultiByteToWideChar(CodePage
, 0,
2873 (PCHAR
)&GET_CELL_BUFFER(Buff
, Offset
), 1,
2874 &CurCharInfo
->Char
.UnicodeChar
, 1);
2878 CurCharInfo
->Char
.AsciiChar
= GET_CELL_BUFFER(Buff
, Offset
);
2880 CurCharInfo
->Attributes
= GET_CELL_BUFFER(Buff
, Offset
);
2885 ConioUnlockScreenBuffer(Buff
);
2887 Reply
->Status
= STATUS_SUCCESS
;
2888 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Right
= ReadRegion
.left
+ SizeX
- 1;
2889 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Bottom
= ReadRegion
.top
+ SizeY
- 1;
2890 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Left
= ReadRegion
.left
;
2891 Reply
->Data
.ReadConsoleOutputReply
.ReadRegion
.Top
= ReadRegion
.top
;
2893 return Reply
->Status
;
2897 CSR_API(CsrWriteConsoleInput
)
2899 PINPUT_RECORD InputRecord
;
2900 PCSRSS_CONSOLE Console
;
2905 ConsoleInput
* Record
;
2907 DPRINT("CsrWriteConsoleInput\n");
2909 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
2910 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
2912 Status
= ConioLockConsole(ProcessData
, Request
->Data
.WriteConsoleInputRequest
.ConsoleHandle
, &Console
);
2913 if (! NT_SUCCESS(Status
))
2915 return Reply
->Status
= Status
;
2918 InputRecord
= Request
->Data
.WriteConsoleInputRequest
.InputRecord
;
2919 Length
= Request
->Data
.WriteConsoleInputRequest
.Length
;
2920 Size
= Length
* sizeof(INPUT_RECORD
);
2922 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2923 || (((PVOID
)InputRecord
+ Size
) > (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2925 ConioUnlockConsole(Console
);
2926 Reply
->Status
= STATUS_ACCESS_VIOLATION
;
2927 return Reply
->Status
;
2930 for (i
= 0; i
< Length
; i
++)
2932 Record
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
2935 ConioUnlockConsole(Console
);
2936 Reply
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2937 return Reply
->Status
;
2940 Record
->Echoed
= FALSE
;
2941 Record
->Fake
= FALSE
;
2942 Record
->InputEvent
= *InputRecord
++;
2943 if (KEY_EVENT
== Record
->InputEvent
.EventType
)
2945 /* FIXME - convert from unicode to ascii!! */
2946 ConioProcessChar(Console
, Record
);
2950 ConioUnlockConsole(Console
);
2952 Reply
->Status
= STATUS_SUCCESS
;
2953 Reply
->Data
.WriteConsoleInputReply
.Length
= i
;
2955 return Reply
->Status
;
2958 /**********************************************************************
2959 * HardwareStateProperty
2962 * Set/Get the value of the HardwareState and switch
2963 * between direct video buffer ouput and GDI windowed
2966 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
2967 * object. We use the same object to reply.
2969 * ConsoleHwState has the correct size to be compatible
2970 * with NT's, but values are not.
2972 STATIC NTSTATUS FASTCALL
2973 SetConsoleHardwareState (PCSRSS_CONSOLE Console
, DWORD ConsoleHwState
)
2975 DPRINT1("Console Hardware State: %d\n", ConsoleHwState
);
2977 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED
== ConsoleHwState
)
2978 ||(CONSOLE_HARDWARE_STATE_DIRECT
== ConsoleHwState
))
2980 if (Console
->HardwareState
!= ConsoleHwState
)
2982 /* TODO: implement switching from full screen to windowed mode */
2983 /* TODO: or back; now simply store the hardware state */
2984 Console
->HardwareState
= ConsoleHwState
;
2987 return STATUS_SUCCESS
;
2990 return STATUS_INVALID_PARAMETER_3
; /* Client: (handle, set_get, [mode]) */
2993 CSR_API(CsrHardwareStateProperty
)
2995 PCSRSS_CONSOLE Console
;
2998 DPRINT("CsrHardwareStateProperty\n");
3000 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3001 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3003 Status
= ConioLockConsole(ProcessData
,
3004 Request
->Data
.ConsoleHardwareStateRequest
.ConsoleHandle
,
3006 if (! NT_SUCCESS(Status
))
3008 DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
3009 return Reply
->Status
= Status
;
3012 switch (Request
->Data
.ConsoleHardwareStateRequest
.SetGet
)
3014 case CONSOLE_HARDWARE_STATE_GET
:
3015 Reply
->Data
.ConsoleHardwareStateReply
.State
= Console
->HardwareState
;
3018 case CONSOLE_HARDWARE_STATE_SET
:
3019 DPRINT("Setting console hardware state.\n");
3020 Reply
->Status
= SetConsoleHardwareState(Console
, Request
->Data
.ConsoleHardwareStateRequest
.State
);
3024 Reply
->Status
= STATUS_INVALID_PARAMETER_2
; /* Client: (handle, [set_get], mode) */
3028 ConioUnlockConsole(Console
);
3030 return Reply
->Status
;
3033 CSR_API(CsrGetConsoleWindow
)
3035 PCSRSS_CONSOLE Console
;
3038 DPRINT("CsrGetConsoleWindow\n");
3040 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3041 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3043 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3044 if (! NT_SUCCESS(Status
))
3046 return Reply
->Status
= Status
;
3049 Reply
->Data
.GetConsoleWindowReply
.WindowHandle
= Console
->hWindow
;
3050 ConioUnlockConsole(Console
);
3052 return Reply
->Status
= STATUS_SUCCESS
;
3055 CSR_API(CsrSetConsoleIcon
)
3057 PCSRSS_CONSOLE Console
;
3060 DPRINT("CsrSetConsoleIcon\n");
3062 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3063 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3065 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3066 if (! NT_SUCCESS(Status
))
3068 return Reply
->Status
= Status
;
3071 Console
->hWindowIcon
= Request
->Data
.SetConsoleIconRequest
.WindowIcon
;
3072 Reply
->Status
= (ConioChangeIcon(Console
) ? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
3073 ConioUnlockConsole(Console
);
3075 return Reply
->Status
;
3078 CSR_API(CsrGetConsoleCodePage
)
3080 PCSRSS_CONSOLE Console
;
3083 DPRINT("CsrGetConsoleCodePage\n");
3085 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3086 if (! NT_SUCCESS(Status
))
3088 return Reply
->Status
= Status
;
3091 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3092 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3093 Reply
->Data
.GetConsoleCodePage
.CodePage
= Console
->CodePage
;
3094 ConioUnlockConsole(Console
);
3095 return Reply
->Status
= STATUS_SUCCESS
;
3098 CSR_API(CsrSetConsoleCodePage
)
3100 PCSRSS_CONSOLE Console
;
3103 DPRINT("CsrSetConsoleCodePage\n");
3105 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3106 if (! NT_SUCCESS(Status
))
3108 return Reply
->Status
= Status
;
3111 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3112 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3113 if (IsValidCodePage(Request
->Data
.SetConsoleCodePage
.CodePage
))
3115 Console
->CodePage
= Request
->Data
.SetConsoleCodePage
.CodePage
;
3116 ConioUnlockConsole(Console
);
3117 return Reply
->Status
= STATUS_SUCCESS
;
3119 ConioUnlockConsole(Console
);
3120 return Reply
->Status
= STATUS_UNSUCCESSFUL
;
3123 CSR_API(CsrGetConsoleOutputCodePage
)
3125 PCSRSS_CONSOLE Console
;
3128 DPRINT("CsrGetConsoleOutputCodePage\n");
3130 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3131 if (! NT_SUCCESS(Status
))
3133 return Reply
->Status
= Status
;
3136 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3137 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3138 Reply
->Data
.GetConsoleOutputCodePage
.CodePage
= Console
->OutputCodePage
;
3139 ConioUnlockConsole(Console
);
3140 return Reply
->Status
= STATUS_SUCCESS
;
3143 CSR_API(CsrSetConsoleOutputCodePage
)
3145 PCSRSS_CONSOLE Console
;
3148 DPRINT("CsrSetConsoleOutputCodePage\n");
3150 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3151 if (! NT_SUCCESS(Status
))
3153 return Reply
->Status
= Status
;
3156 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3157 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - LPC_MESSAGE_BASE_SIZE
;
3158 if (IsValidCodePage(Request
->Data
.SetConsoleOutputCodePage
.CodePage
))
3160 Console
->OutputCodePage
= Request
->Data
.SetConsoleOutputCodePage
.CodePage
;
3161 ConioUnlockConsole(Console
);
3162 return Reply
->Status
= STATUS_SUCCESS
;
3164 ConioUnlockConsole(Console
);
3165 return Reply
->Status
= STATUS_UNSUCCESSFUL
;
3168 CSR_API(CsrGetProcessList
)
3171 PCSRSS_CONSOLE Console
;
3172 PCSRSS_PROCESS_DATA current
;
3173 PLIST_ENTRY current_entry
;
3174 ULONG nItems
, nCopied
;
3177 DPRINT("CsrGetProcessList\n");
3179 Buffer
= Reply
->Data
.GetProcessListReply
.ProcessId
;
3180 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
3181 Reply
->Header
.DataSize
= Reply
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
3183 nItems
= nCopied
= 0;
3184 Reply
->Data
.GetProcessListReply
.nProcessIdsCopied
= 0;
3185 Reply
->Data
.GetProcessListReply
.nProcessIdsTotal
= 0;
3187 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3188 if (! NT_SUCCESS(Status
))
3190 return Reply
->Status
= Status
;
3193 DPRINT1("Console_Api Ctrl-C\n");
3195 for(current_entry
= Console
->ProcessList
.Flink
;
3196 current_entry
!= &Console
->ProcessList
;
3197 current_entry
= current_entry
->Flink
)
3199 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
3200 if(nItems
++ < Request
->Data
.GetProcessListRequest
.nMaxIds
)
3202 *(Buffer
++) = current
->ProcessId
;
3207 ConioUnlockConsole(Console
);
3209 Reply
->Data
.GetProcessListReply
.nProcessIdsCopied
= nCopied
;
3210 Reply
->Data
.GetProcessListReply
.nProcessIdsTotal
= nItems
;
3212 return Reply
->Status
= STATUS_SUCCESS
;