2 * reactos/subsys/csrss/win32csr/conio.c
4 * Console I/O functions
6 * ReactOS Operating System
9 /* INCLUDES ******************************************************************/
16 /* FIXME: Is there a way to create real aliasses with gcc? [CSH] */
17 #define ALIAS(Name, Target) typeof(Target) Name = Target
19 /* Private user32 routines for CSRSS, not defined in any header file */
20 extern VOID STDCALL
PrivateCsrssRegisterPrimitive(VOID
);
21 extern VOID STDCALL
PrivateCsrssAcquireOrReleaseInputOwnership(BOOL Release
);
23 /* GLOBALS *******************************************************************/
25 #define ConioInitRect(Rect, Top, Left, Bottom, Right) \
26 ((Rect)->top) = Top; \
27 ((Rect)->left) = Left; \
28 ((Rect)->bottom) = Bottom; \
29 ((Rect)->right) = Right
31 #define ConioIsRectEmpty(Rect) \
32 (((Rect)->left > (Rect)->right) || ((Rect)->top > (Rect)->bottom))
34 #define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
35 WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
37 #define ConsoleAnsiCharToUnicodeChar(Console, sWChar, dChar) \
38 MultiByteToWideChar((Console)->CodePage, 0, (dChar), 1, (sWChar), 1)
40 #define ConsoleUnicodeToAnsiN(Console, dChar, sWChar, nChars) \
41 WideCharToMultiByte((Console)->CodePage, 0, (sWChar), (nChars), (dChar), (nChars) * sizeof(WCHAR), NULL, NULL)
43 /* FUNCTIONS *****************************************************************/
45 STATIC NTSTATUS FASTCALL
46 ConioConsoleFromProcessData(PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_CONSOLE
*Console
)
48 if (NULL
== ProcessData
->Console
)
51 return STATUS_SUCCESS
;
54 EnterCriticalSection(&(ProcessData
->Console
->Header
.Lock
));
55 *Console
= ProcessData
->Console
;
57 return STATUS_SUCCESS
;
61 ConioConsoleCtrlEvent(DWORD Event
, PCSRSS_PROCESS_DATA ProcessData
)
65 DPRINT("ConioConsoleCtrlEvent Parent ProcessId = %x\n", ProcessData
->ProcessId
);
67 if (ProcessData
->CtrlDispatcher
)
70 Thread
= CreateRemoteThread(ProcessData
->Process
, NULL
, 0,
71 (LPTHREAD_START_ROUTINE
) ProcessData
->CtrlDispatcher
,
72 (PVOID
) Event
, 0, NULL
);
75 DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
82 #define GET_CELL_BUFFER(b,o)\
85 #define SET_CELL_BUFFER(b,o,c,a)\
86 (b)->Buffer[(o)++]=(c),\
87 (b)->Buffer[(o)++]=(a)
90 ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff
)
92 DWORD Offset
= 2 * (Buff
->CurrentY
* Buff
->MaxX
);
95 for (Pos
= 0; Pos
< Buff
->MaxX
; Pos
++)
97 /* Fill the cell: Offset is incremented by the macro */
98 SET_CELL_BUFFER(Buff
, Offset
, ' ', Buff
->DefaultAttrib
);
102 STATIC NTSTATUS FASTCALL
103 CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console
,
104 PCSRSS_SCREEN_BUFFER Buffer
)
106 Buffer
->Header
.Type
= CONIO_SCREEN_BUFFER_MAGIC
;
107 Buffer
->Header
.ReferenceCount
= 0;
108 Buffer
->MaxX
= Console
->Size
.X
;
109 Buffer
->MaxY
= Console
->Size
.Y
;
112 Buffer
->Buffer
= HeapAlloc(Win32CsrApiHeap
, 0, Buffer
->MaxX
* Buffer
->MaxY
* 2);
113 if (NULL
== Buffer
->Buffer
)
115 return STATUS_INSUFFICIENT_RESOURCES
;
117 InitializeCriticalSection(&Buffer
->Header
.Lock
);
118 ConioInitScreenBuffer(Console
, Buffer
);
119 /* initialize buffer to be empty with default attributes */
120 for (Buffer
->CurrentY
= 0 ; Buffer
->CurrentY
< Buffer
->MaxY
; Buffer
->CurrentY
++)
122 ClearLineBuffer(Buffer
);
124 Buffer
->CursorInfo
.bVisible
= TRUE
;
125 Buffer
->CursorInfo
.dwSize
= 5;
126 Buffer
->Mode
= ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
;
127 Buffer
->CurrentX
= 0;
128 Buffer
->CurrentY
= 0;
130 return STATUS_SUCCESS
;
133 STATIC NTSTATUS STDCALL
134 CsrInitConsole(PCSRSS_CONSOLE Console
)
137 SECURITY_ATTRIBUTES SecurityAttributes
;
138 PCSRSS_SCREEN_BUFFER NewBuffer
;
141 Console
->Title
.MaximumLength
= Console
->Title
.Length
= 0;
142 Console
->Title
.Buffer
= NULL
;
144 RtlCreateUnicodeString(&Console
->Title
, L
"Command Prompt");
146 Console
->Header
.ReferenceCount
= 0;
147 Console
->WaitingChars
= 0;
148 Console
->WaitingLines
= 0;
149 Console
->EchoCount
= 0;
150 Console
->Header
.Type
= CONIO_CONSOLE_MAGIC
;
151 Console
->Mode
= ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_PROCESSED_INPUT
| ENABLE_MOUSE_INPUT
;
152 Console
->EarlyReturn
= FALSE
;
153 Console
->ActiveBuffer
= NULL
;
154 InitializeListHead(&Console
->InputEvents
);
155 InitializeListHead(&Console
->ProcessList
);
157 Console
->CodePage
= GetOEMCP();
158 Console
->OutputCodePage
= GetOEMCP();
160 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
161 SecurityAttributes
.lpSecurityDescriptor
= NULL
;
162 SecurityAttributes
.bInheritHandle
= TRUE
;
164 Console
->ActiveEvent
= CreateEventW(&SecurityAttributes
, TRUE
, FALSE
, NULL
);
165 if (NULL
== Console
->ActiveEvent
)
167 RtlFreeUnicodeString(&Console
->Title
);
168 return STATUS_UNSUCCESSFUL
;
170 Console
->PrivateData
= NULL
;
171 InitializeCriticalSection(&Console
->Header
.Lock
);
172 GuiMode
= DtbgIsDesktopVisible();
175 Status
= TuiInitConsole(Console
);
176 if (! NT_SUCCESS(Status
))
178 DPRINT1("Failed to open text-mode console, switching to gui-mode\n");
184 Status
= GuiInitConsole(Console
);
185 if (! NT_SUCCESS(Status
))
187 RtlFreeUnicodeString(&Console
->Title
);
188 DeleteCriticalSection(&Console
->Header
.Lock
);
189 CloseHandle(Console
->ActiveEvent
);
194 NewBuffer
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(CSRSS_SCREEN_BUFFER
));
195 if (NULL
== NewBuffer
)
197 ConioCleanupConsole(Console
);
198 RtlFreeUnicodeString(&Console
->Title
);
199 DeleteCriticalSection(&Console
->Header
.Lock
);
200 CloseHandle(Console
->ActiveEvent
);
201 return STATUS_INSUFFICIENT_RESOURCES
;
203 Status
= CsrInitConsoleScreenBuffer(Console
, NewBuffer
);
204 if (! NT_SUCCESS(Status
))
206 ConioCleanupConsole(Console
);
207 RtlFreeUnicodeString(&Console
->Title
);
208 DeleteCriticalSection(&Console
->Header
.Lock
);
209 CloseHandle(Console
->ActiveEvent
);
210 HeapFree(Win32CsrApiHeap
, 0, NewBuffer
);
213 Console
->ActiveBuffer
= NewBuffer
;
214 /* add a reference count because the buffer is tied to the console */
215 InterlockedIncrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
);
216 /* make console active, and insert into console list */
217 /* copy buffer contents to screen */
218 ConioDrawConsole(Console
);
220 return STATUS_SUCCESS
;
224 CSR_API(CsrAllocConsole
)
226 PCSRSS_CONSOLE Console
;
227 NTSTATUS Status
= STATUS_SUCCESS
;
228 BOOLEAN NewConsole
= FALSE
;
230 DPRINT("CsrAllocConsole\n");
232 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
233 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
235 if (ProcessData
== NULL
)
237 DPRINT1("No process data\n");
238 return Request
->Status
= STATUS_INVALID_PARAMETER
;
241 if (ProcessData
->Console
)
243 DPRINT1("Process already has a console\n");
244 Request
->Status
= STATUS_INVALID_PARAMETER
;
245 return STATUS_INVALID_PARAMETER
;
249 Request
->Status
= STATUS_SUCCESS
;
251 /* If we don't need a console, then get out of here */
252 if (!Request
->Data
.AllocConsoleRequest
.ConsoleNeeded
)
254 DPRINT("No console needed\n");
255 return STATUS_SUCCESS
;
258 /* If we already have one, then don't create a new one... */
259 if (!Request
->Data
.AllocConsoleRequest
.Console
||
260 Request
->Data
.AllocConsoleRequest
.Console
!= ProcessData
->ParentConsole
)
262 /* Allocate a console structure */
264 Console
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(CSRSS_CONSOLE
));
267 DPRINT1("Not enough memory for console\n");
268 Request
->Status
= STATUS_NO_MEMORY
;
269 return STATUS_NO_MEMORY
;
272 /* Initialize the Console */
273 Request
->Status
= CsrInitConsole(Console
);
274 if (!NT_SUCCESS(Request
->Status
))
276 DPRINT1("Console init failed\n");
277 HeapFree(Win32CsrApiHeap
, 0, Console
);
278 return Request
->Status
;
283 /* Reuse our current console */
284 Console
= Request
->Data
.AllocConsoleRequest
.Console
;
287 /* Set the Process Console */
288 ProcessData
->Console
= Console
;
290 /* Return it to the caller */
291 Request
->Data
.AllocConsoleRequest
.Console
= Console
;
293 /* Add a reference count because the process is tied to the console */
294 Console
->Header
.ReferenceCount
++;
296 if (NewConsole
|| !ProcessData
->bInheritHandles
)
298 /* Insert the Objects */
299 Status
= Win32CsrInsertObject(ProcessData
,
300 &Request
->Data
.AllocConsoleRequest
.InputHandle
,
302 if (! NT_SUCCESS(Status
))
304 DPRINT1("Failed to insert object\n");
305 ConioDeleteConsole((Object_t
*) Console
);
306 ProcessData
->Console
= 0;
307 return Request
->Status
= Status
;
310 Status
= Win32CsrInsertObject(ProcessData
,
311 &Request
->Data
.AllocConsoleRequest
.OutputHandle
,
312 &Console
->ActiveBuffer
->Header
);
313 if (!NT_SUCCESS(Status
))
315 DPRINT1("Failed to insert object\n");
316 ConioDeleteConsole((Object_t
*) Console
);
317 Win32CsrReleaseObject(ProcessData
,
318 Request
->Data
.AllocConsoleRequest
.InputHandle
);
319 ProcessData
->Console
= 0;
320 return Request
->Status
= Status
;
324 /* Duplicate the Event */
325 if (!DuplicateHandle(GetCurrentProcess(),
326 ProcessData
->Console
->ActiveEvent
,
327 ProcessData
->Process
,
328 &ProcessData
->ConsoleEvent
,
333 DPRINT1("DuplicateHandle() failed: %d\n", GetLastError
);
334 ConioDeleteConsole((Object_t
*) Console
);
335 if (NewConsole
|| !ProcessData
->bInheritHandles
)
337 Win32CsrReleaseObject(ProcessData
,
338 Request
->Data
.AllocConsoleRequest
.OutputHandle
);
339 Win32CsrReleaseObject(ProcessData
,
340 Request
->Data
.AllocConsoleRequest
.InputHandle
);
342 ProcessData
->Console
= 0;
343 return Request
->Status
= Status
;
346 /* Set the Ctrl Dispatcher */
347 ProcessData
->CtrlDispatcher
= Request
->Data
.AllocConsoleRequest
.CtrlDispatcher
;
348 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
350 /* Insert into the list */
351 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ProcessEntry
);
352 return STATUS_SUCCESS
;
355 CSR_API(CsrFreeConsole
)
357 PCSRSS_CONSOLE Console
;
359 DPRINT("CsrFreeConsole\n");
361 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
362 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
364 if (ProcessData
== NULL
|| ProcessData
->Console
== NULL
)
366 return Request
->Status
= STATUS_INVALID_PARAMETER
;
369 Console
= ProcessData
->Console
;
370 ProcessData
->Console
= NULL
;
371 if (0 == InterlockedDecrement(&Console
->Header
.ReferenceCount
))
373 ConioDeleteConsole((Object_t
*) Console
);
376 return STATUS_SUCCESS
;
380 ConioNextLine(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, UINT
*ScrolledLines
)
382 /* slide the viewable screen */
383 if (((Buff
->CurrentY
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
) == (ULONG
)Buff
->MaxY
- 1)
385 if (++Buff
->ShowY
== Buff
->MaxY
)
391 if (++Buff
->CurrentY
== Buff
->MaxY
)
395 ClearLineBuffer(Buff
);
396 UpdateRect
->left
= 0;
397 UpdateRect
->right
= Buff
->MaxX
- 1;
398 if (UpdateRect
->top
== (LONG
)Buff
->CurrentY
)
400 if (++UpdateRect
->top
== Buff
->MaxY
)
405 UpdateRect
->bottom
= Buff
->CurrentY
;
408 STATIC NTSTATUS FASTCALL
409 ConioWriteConsole(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
,
410 CHAR
*Buffer
, DWORD Length
, BOOL Attrib
)
415 LONG CursorStartX
, CursorStartY
;
418 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &CursorStartX
, &CursorStartY
);
419 UpdateRect
.left
= Buff
->MaxX
;
420 UpdateRect
.top
= Buff
->CurrentY
;
421 UpdateRect
.right
= -1;
422 UpdateRect
.bottom
= Buff
->CurrentY
;
425 for (i
= 0; i
< Length
; i
++)
427 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
430 if (Buffer
[i
] == '\n')
433 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
437 else if (Buffer
[i
] == '\b')
439 /* Only handle BS if we're not on the first pos of the first line */
440 if (0 != Buff
->CurrentX
|| Buff
->ShowY
!= Buff
->CurrentY
)
442 if (0 == Buff
->CurrentX
)
444 /* slide virtual position up */
445 Buff
->CurrentX
= Buff
->MaxX
- 1;
446 if (0 == Buff
->CurrentY
)
448 Buff
->CurrentY
= Buff
->MaxY
;
454 if ((0 == UpdateRect
.top
&& UpdateRect
.bottom
< (LONG
)Buff
->CurrentY
)
455 || (0 != UpdateRect
.top
&& (LONG
)Buff
->CurrentY
< UpdateRect
.top
))
457 UpdateRect
.top
= Buff
->CurrentY
;
464 Offset
= 2 * ((Buff
->CurrentY
* Buff
->MaxX
) + Buff
->CurrentX
);
465 SET_CELL_BUFFER(Buff
, Offset
, ' ', Buff
->DefaultAttrib
);
466 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
) Buff
->CurrentX
);
467 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
472 else if (Buffer
[i
] == '\r')
475 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
) Buff
->CurrentX
);
476 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
480 else if (Buffer
[i
] == '\t')
484 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
)Buff
->CurrentX
);
485 EndX
= (Buff
->CurrentX
+ 8) & ~7;
486 if (EndX
> Buff
->MaxX
)
490 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
491 while (Buff
->CurrentX
< EndX
)
493 Buff
->Buffer
[Offset
] = ' ';
497 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
- 1);
498 if (Buff
->CurrentX
== Buff
->MaxX
)
500 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
503 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
513 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
)Buff
->CurrentX
);
514 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
515 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
516 Buff
->Buffer
[Offset
++] = Buffer
[i
];
519 Buff
->Buffer
[Offset
] = Buff
->DefaultAttrib
;
522 if (Buff
->CurrentX
== Buff
->MaxX
)
524 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
527 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
531 Buff
->CurrentX
= CursorStartX
;
536 ConioPhysicalToLogical(Buff
, UpdateRect
.left
, UpdateRect
.top
, &(UpdateRect
.left
),
538 ConioPhysicalToLogical(Buff
, UpdateRect
.right
, UpdateRect
.bottom
, &(UpdateRect
.right
),
539 &(UpdateRect
.bottom
));
540 if (! ConioIsRectEmpty(&UpdateRect
) && NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
542 ConioWriteStream(Console
, &UpdateRect
, CursorStartX
, CursorStartY
, ScrolledLines
,
546 return STATUS_SUCCESS
;
549 CSR_API(CsrReadConsole
)
551 PLIST_ENTRY CurrentEntry
;
554 PWCHAR UnicodeBuffer
;
556 ULONG nNumberOfCharsToRead
, CharSize
;
557 PCSRSS_CONSOLE Console
;
560 DPRINT("CsrReadConsole\n");
562 CharSize
= (Request
->Data
.ReadConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
564 /* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */
565 nNumberOfCharsToRead
= min(Request
->Data
.ReadConsoleRequest
.NrCharactersToRead
, CSRSS_MAX_READ_CONSOLE
/ CharSize
);
566 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
567 Request
->Header
.DataSize
= Request
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
569 Buffer
= Request
->Data
.ReadConsoleRequest
.Buffer
;
570 UnicodeBuffer
= (PWCHAR
)Buffer
;
571 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadConsoleRequest
.ConsoleHandle
,
573 if (! NT_SUCCESS(Status
))
575 return Request
->Status
= Status
;
577 Request
->Data
.ReadConsoleRequest
.EventHandle
= ProcessData
->ConsoleEvent
;
578 for (i
= 0; i
< nNumberOfCharsToRead
&& Console
->InputEvents
.Flink
!= &Console
->InputEvents
; i
++)
580 /* remove input event from queue */
581 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
582 if (IsListEmpty(&Console
->InputEvents
))
585 ResetEvent(Console
->ActiveEvent
);
587 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
589 /* only pay attention to valid ascii chars, on key down */
590 if (KEY_EVENT
== Input
->InputEvent
.EventType
591 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
592 && Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
!= '\0')
594 /* backspace handling */
595 if ('\b' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
597 /* echo if it has not already been done, and either we or the client has chars to be deleted */
599 && (0 != i
|| Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
))
601 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
602 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
606 i
-= 2; /* if we already have something to return, just back it up by 2 */
609 { /* otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer */
610 Console
->WaitingChars
--;
611 ConioUnlockConsole(Console
);
612 HeapFree(Win32CsrApiHeap
, 0, Input
);
613 Request
->Data
.ReadConsoleRequest
.NrCharactersRead
= 0;
614 Request
->Status
= STATUS_NOTIFY_CLEANUP
;
615 return STATUS_NOTIFY_CLEANUP
;
617 Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
--;
618 Input
->Echoed
= TRUE
; /* mark as echoed so we don't echo it below */
620 /* do not copy backspace to buffer */
623 if(Request
->Data
.ReadConsoleRequest
.Unicode
)
624 UnicodeBuffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
; /* FIXME */
626 Buffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
;
628 /* echo to screen if enabled and we did not already echo the char */
629 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
)
631 && '\r' != Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
633 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
634 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
641 Console
->WaitingChars
--;
642 HeapFree(Win32CsrApiHeap
, 0, Input
);
644 Request
->Data
.ReadConsoleRequest
.NrCharactersRead
= i
;
647 Request
->Status
= STATUS_PENDING
; /* we didn't read anything */
649 else if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
))
651 if (0 == Console
->WaitingLines
||
652 (Request
->Data
.ReadConsoleRequest
.Unicode
? (L
'\n' != UnicodeBuffer
[i
- 1]) : ('\n' != Buffer
[i
- 1])))
654 Request
->Status
= STATUS_PENDING
; /* line buffered, didn't get a complete line */
658 Console
->WaitingLines
--;
659 Request
->Status
= STATUS_SUCCESS
; /* line buffered, did get a complete line */
664 Request
->Status
= STATUS_SUCCESS
; /* not line buffered, did read something */
667 if (Request
->Status
== STATUS_PENDING
)
669 Console
->EchoCount
= nNumberOfCharsToRead
- i
;
673 Console
->EchoCount
= 0; /* if the client is no longer waiting on input, do not echo */
675 Request
->Header
.MessageSize
+= i
* CharSize
;
677 ConioUnlockConsole(Console
);
678 return Request
->Status
;
682 ConioPhysicalToLogical(PCSRSS_SCREEN_BUFFER Buff
,
688 *LogicalX
= PhysicalX
;
689 if (PhysicalY
< Buff
->ShowY
)
691 *LogicalY
= Buff
->MaxY
- Buff
->ShowY
+ PhysicalY
;
695 *LogicalY
= PhysicalY
- Buff
->ShowY
;
699 inline BOOLEAN
ConioIsEqualRect(
703 return ((Rect1
->left
== Rect2
->left
) && (Rect1
->right
== Rect2
->right
) &&
704 (Rect1
->top
== Rect2
->top
) && (Rect1
->bottom
== Rect2
->bottom
));
707 inline BOOLEAN
ConioGetIntersection(
712 if (ConioIsRectEmpty(Rect1
) ||
713 (ConioIsRectEmpty(Rect2
)) ||
714 (Rect1
->top
> Rect2
->bottom
) ||
715 (Rect1
->left
> Rect2
->right
) ||
716 (Rect1
->bottom
< Rect2
->top
) ||
717 (Rect1
->right
< Rect2
->left
))
719 /* The rectangles do not intersect */
720 ConioInitRect(Intersection
, 0, -1, 0, -1);
724 ConioInitRect(Intersection
,
725 max(Rect1
->top
, Rect2
->top
),
726 max(Rect1
->left
, Rect2
->left
),
727 min(Rect1
->bottom
, Rect2
->bottom
),
728 min(Rect1
->right
, Rect2
->right
));
733 inline BOOLEAN
ConioGetUnion(
738 if (ConioIsRectEmpty(Rect1
))
740 if (ConioIsRectEmpty(Rect2
))
742 ConioInitRect(Union
, 0, -1, 0, -1);
750 else if (ConioIsRectEmpty(Rect2
))
757 min(Rect1
->top
, Rect2
->top
),
758 min(Rect1
->left
, Rect2
->left
),
759 max(Rect1
->bottom
, Rect2
->bottom
),
760 max(Rect1
->right
, Rect2
->right
));
766 inline BOOLEAN
ConioSubtractRect(
773 if (ConioIsRectEmpty(Rect1
))
775 ConioInitRect(Subtraction
, 0, -1, 0, -1);
778 *Subtraction
= *Rect1
;
779 if (ConioGetIntersection(&tmp
, Rect1
, Rect2
))
781 if (ConioIsEqualRect(&tmp
, Subtraction
))
783 ConioInitRect(Subtraction
, 0, -1, 0, -1);
786 if ((tmp
.top
== Subtraction
->top
) && (tmp
.bottom
== Subtraction
->bottom
))
788 if (tmp
.left
== Subtraction
->left
)
790 Subtraction
->left
= tmp
.right
;
792 else if (tmp
.right
== Subtraction
->right
)
794 Subtraction
->right
= tmp
.left
;
797 else if ((tmp
.left
== Subtraction
->left
) && (tmp
.right
== Subtraction
->right
))
799 if (tmp
.top
== Subtraction
->top
)
801 Subtraction
->top
= tmp
.bottom
;
803 else if (tmp
.bottom
== Subtraction
->bottom
)
805 Subtraction
->bottom
= tmp
.top
;
814 ConioCopyRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer
,
824 DstY
= DstRegion
->top
;
825 BytesPerLine
= ConioRectWidth(DstRegion
) * 2;
827 SrcY
= (SrcRegion
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
828 DstY
= (DstRegion
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
829 SrcOffset
= (SrcY
* ScreenBuffer
->MaxX
+ SrcRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
830 DstOffset
= (DstY
* ScreenBuffer
->MaxX
+ DstRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
832 for (i
= SrcRegion
->top
; i
<= SrcRegion
->bottom
; i
++)
835 &ScreenBuffer
->Buffer
[DstOffset
],
836 &ScreenBuffer
->Buffer
[SrcOffset
],
839 if (++DstY
== ScreenBuffer
->MaxY
)
842 DstOffset
= (DstRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
846 DstOffset
+= ScreenBuffer
->MaxX
* 2;
849 if (++SrcY
== ScreenBuffer
->MaxY
)
852 SrcOffset
= (SrcRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
856 SrcOffset
+= ScreenBuffer
->MaxX
* 2;
862 ConioFillRegion(PCSRSS_CONSOLE Console
,
863 PCSRSS_SCREEN_BUFFER ScreenBuffer
,
875 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &CharInfo
->Char
.UnicodeChar
);
877 Char
= CharInfo
->Char
.AsciiChar
;
879 Y
= (Region
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
880 Offset
= (Y
* ScreenBuffer
->MaxX
+ Region
->left
+ ScreenBuffer
->ShowX
) * 2;
881 Delta
= (ScreenBuffer
->MaxX
- ConioRectWidth(Region
)) * 2;
883 for (i
= Region
->top
; i
<= Region
->bottom
; i
++)
885 for (X
= Region
->left
; X
<= Region
->right
; X
++)
887 SET_CELL_BUFFER(ScreenBuffer
, Offset
, Char
, CharInfo
->Attributes
);
889 if (++Y
== ScreenBuffer
->MaxY
)
892 Offset
= (Region
->left
+ ScreenBuffer
->ShowX
) * 2;
902 ConioInputEventToAnsi(PCSRSS_CONSOLE Console
, PINPUT_RECORD InputEvent
)
904 if (InputEvent
->EventType
== KEY_EVENT
)
906 ConsoleUnicodeCharToAnsiChar(Console
,
907 &InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
,
908 &InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
);
912 CSR_API(CsrWriteConsole
)
915 PCHAR Buffer
= (PCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
;
916 PCSRSS_SCREEN_BUFFER Buff
;
917 PCSRSS_CONSOLE Console
;
918 ULONG CharSize
= (Request
->Data
.WriteConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
920 DPRINT("CsrWriteConsole\n");
922 if (Request
->Header
.DataSize
923 < sizeof(CSRSS_WRITE_CONSOLE
) - 1
924 + (Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
* CharSize
))
926 DPRINT1("Invalid request size\n");
927 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
928 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
929 return Request
->Status
= STATUS_INVALID_PARAMETER
;
931 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
933 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
934 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
936 if (! NT_SUCCESS(Status
))
938 return Request
->Status
= Status
;
941 if(Request
->Data
.WriteConsoleRequest
.Unicode
)
943 ConsoleUnicodeToAnsiN(Console
, Buffer
, (PWCHAR
)Buffer
, Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
);
946 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.WriteConsoleRequest
.ConsoleHandle
, &Buff
);
947 if (! NT_SUCCESS(Status
))
951 ConioUnlockConsole(Console
);
953 return Request
->Status
= Status
;
956 Request
->Status
= ConioWriteConsole(Console
, Buff
, Buffer
,
957 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
, TRUE
);
958 ConioUnlockScreenBuffer(Buff
);
961 ConioUnlockConsole(Console
);
964 if(NT_SUCCESS(Request
->Status
))
966 Request
->Data
.WriteConsoleRequest
.NrCharactersWritten
= Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
;
970 Request
->Data
.WriteConsoleRequest
.NrCharactersWritten
= 0; /* FIXME - return the actual number of characters written! */
973 return Request
->Status
= STATUS_SUCCESS
;
977 ConioDeleteScreenBuffer(Object_t
*Object
)
979 PCSRSS_SCREEN_BUFFER Buffer
= (PCSRSS_SCREEN_BUFFER
) Object
;
980 DeleteCriticalSection(&Buffer
->Header
.Lock
);
981 HeapFree(Win32CsrApiHeap
, 0, Buffer
->Buffer
);
982 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
986 ConioDrawConsole(PCSRSS_CONSOLE Console
)
990 ConioInitRect(&Region
, 0, 0, Console
->Size
.Y
- 1, Console
->Size
.X
- 1);
992 ConioDrawRegion(Console
, &Region
);
997 ConioDeleteConsole(Object_t
*Object
)
999 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Object
;
1000 ConsoleInput
*Event
;
1002 DPRINT("ConioDeleteConsole\n");
1004 /* Drain input event queue */
1005 while (Console
->InputEvents
.Flink
!= &Console
->InputEvents
)
1007 Event
= (ConsoleInput
*) Console
->InputEvents
.Flink
;
1008 Console
->InputEvents
.Flink
= Console
->InputEvents
.Flink
->Flink
;
1009 Console
->InputEvents
.Flink
->Flink
->Blink
= &Console
->InputEvents
;
1010 HeapFree(Win32CsrApiHeap
, 0, Event
);
1013 if (0 == InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
1015 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
1018 Console
->ActiveBuffer
= NULL
;
1019 ConioCleanupConsole(Console
);
1021 CloseHandle(Console
->ActiveEvent
);
1022 DeleteCriticalSection(&Console
->Header
.Lock
);
1023 RtlFreeUnicodeString(&Console
->Title
);
1024 HeapFree(Win32CsrApiHeap
, 0, Console
);
1028 CsrInitConsoleSupport(VOID
)
1030 DPRINT("CSR: CsrInitConsoleSupport()\n");
1032 /* Should call LoadKeyboardLayout */
1035 STATIC VOID FASTCALL
1036 ConioProcessChar(PCSRSS_CONSOLE Console
,
1037 ConsoleInput
*KeyEventRecord
)
1040 BOOL bClientWake
= FALSE
;
1041 ConsoleInput
*TempInput
;
1043 /* process Ctrl-C and Ctrl-Break */
1044 if (Console
->Mode
& ENABLE_PROCESSED_INPUT
&&
1045 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
&&
1046 ((KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== VK_PAUSE
) ||
1047 (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== 'C')) &&
1048 (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
)))
1050 PCSRSS_PROCESS_DATA current
;
1051 PLIST_ENTRY current_entry
;
1052 DPRINT1("Console_Api Ctrl-C\n");
1053 current_entry
= Console
->ProcessList
.Flink
;
1054 while (current_entry
!= &Console
->ProcessList
)
1056 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
1057 current_entry
= current_entry
->Flink
;
1058 ConioConsoleCtrlEvent((DWORD
)CTRL_C_EVENT
, current
);
1060 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1064 if (0 != (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
1065 & (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1066 && (VK_UP
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
1067 || VK_DOWN
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
))
1069 if (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1071 /* scroll up or down */
1072 if (NULL
== Console
)
1074 DPRINT1("No Active Console!\n");
1075 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1078 if (VK_UP
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
)
1080 /* only scroll up if there is room to scroll up into */
1081 if (Console
->ActiveBuffer
->ShowY
!= ((Console
->ActiveBuffer
->CurrentY
+ 1) %
1082 Console
->ActiveBuffer
->MaxY
))
1084 Console
->ActiveBuffer
->ShowY
= (Console
->ActiveBuffer
->ShowY
+
1085 Console
->ActiveBuffer
->MaxY
- 1) %
1086 Console
->ActiveBuffer
->MaxY
;
1089 else if (Console
->ActiveBuffer
->ShowY
!= Console
->ActiveBuffer
->CurrentY
)
1090 /* only scroll down if there is room to scroll down into */
1092 if (Console
->ActiveBuffer
->ShowY
% Console
->ActiveBuffer
->MaxY
!=
1093 Console
->ActiveBuffer
->CurrentY
)
1095 if (((Console
->ActiveBuffer
->CurrentY
+ 1) % Console
->ActiveBuffer
->MaxY
) !=
1096 (Console
->ActiveBuffer
->ShowY
+ Console
->ActiveBuffer
->MaxY
) %
1097 Console
->ActiveBuffer
->MaxY
)
1099 Console
->ActiveBuffer
->ShowY
= (Console
->ActiveBuffer
->ShowY
+ 1) %
1100 Console
->ActiveBuffer
->MaxY
;
1104 ConioDrawConsole(Console
);
1106 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1109 if (NULL
== Console
)
1111 DPRINT1("No Active Console!\n");
1112 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1116 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
)))
1118 switch(KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1121 /* first add the \r */
1122 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1123 updown
= KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
;
1124 KeyEventRecord
->Echoed
= FALSE
;
1125 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= VK_RETURN
;
1126 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\r';
1127 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1128 Console
->WaitingChars
++;
1129 KeyEventRecord
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1130 if (NULL
== KeyEventRecord
)
1132 DPRINT1("Failed to allocate KeyEventRecord\n");
1135 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1136 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
= updown
;
1137 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= 0;
1138 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualScanCode
= 0;
1139 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\n';
1140 KeyEventRecord
->Fake
= TRUE
;
1144 /* add event to the queue */
1145 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1146 Console
->WaitingChars
++;
1147 /* if line input mode is enabled, only wake the client on enter key down */
1148 if (0 == (Console
->Mode
& ENABLE_LINE_INPUT
)
1149 || Console
->EarlyReturn
1150 || ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1151 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
))
1153 if ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1155 Console
->WaitingLines
++;
1158 SetEvent(Console
->ActiveEvent
);
1160 KeyEventRecord
->Echoed
= FALSE
;
1161 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
))
1162 && '\b' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1163 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1165 /* walk the input queue looking for a char to backspace */
1166 for (TempInput
= (ConsoleInput
*) Console
->InputEvents
.Blink
;
1167 TempInput
!= (ConsoleInput
*) &Console
->InputEvents
1168 && (KEY_EVENT
== TempInput
->InputEvent
.EventType
1169 || ! TempInput
->InputEvent
.Event
.KeyEvent
.bKeyDown
1170 || '\b' == TempInput
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
);
1171 TempInput
= (ConsoleInput
*) TempInput
->ListEntry
.Blink
)
1175 /* if we found one, delete it, otherwise, wake the client */
1176 if (TempInput
!= (ConsoleInput
*) &Console
->InputEvents
)
1178 /* delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue */
1179 RemoveEntryList(&TempInput
->ListEntry
);
1180 if (TempInput
->Echoed
)
1182 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1183 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1186 HeapFree(Win32CsrApiHeap
, 0, TempInput
);
1187 RemoveEntryList(&KeyEventRecord
->ListEntry
);
1188 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1189 Console
->WaitingChars
-= 2;
1193 SetEvent(Console
->ActiveEvent
);
1198 /* echo chars if we are supposed to and client is waiting for some */
1199 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
) && Console
->EchoCount
1200 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1201 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
1202 && '\r' != KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1204 /* mark the char as already echoed */
1205 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1206 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1208 Console
->EchoCount
--;
1209 KeyEventRecord
->Echoed
= TRUE
;
1213 /* Console->WaitingChars++; */
1214 if (bClientWake
|| 0 == (Console
->Mode
& ENABLE_LINE_INPUT
))
1216 SetEvent(Console
->ActiveEvent
);
1220 STATIC DWORD FASTCALL
1221 ConioGetShiftState(PBYTE KeyState
)
1225 if (KeyState
[VK_CAPITAL
] & 1)
1226 ssOut
|= CAPSLOCK_ON
;
1228 if (KeyState
[VK_NUMLOCK
] & 1)
1229 ssOut
|= NUMLOCK_ON
;
1231 if (KeyState
[VK_SCROLL
] & 1)
1232 ssOut
|= SCROLLLOCK_ON
;
1234 if (KeyState
[VK_SHIFT
] & 0x80)
1235 ssOut
|= SHIFT_PRESSED
;
1237 if (KeyState
[VK_LCONTROL
] & 0x80)
1238 ssOut
|= LEFT_CTRL_PRESSED
;
1239 if (KeyState
[VK_RCONTROL
] & 0x80)
1240 ssOut
|= RIGHT_CTRL_PRESSED
;
1242 if (KeyState
[VK_LMENU
] & 0x80)
1243 ssOut
|= LEFT_ALT_PRESSED
;
1244 if (KeyState
[VK_RMENU
] & 0x80)
1245 ssOut
|= RIGHT_ALT_PRESSED
;
1251 ConioProcessKey(MSG
*msg
, PCSRSS_CONSOLE Console
, BOOL TextMode
)
1253 static BYTE KeyState
[256] = { 0 };
1254 /* MSDN mentions that you should use the last virtual key code received
1255 * when putting a virtual key identity to a WM_CHAR message since multiple
1256 * or translated keys may be involved. */
1257 static UINT LastVirtualKey
= 0;
1259 ConsoleInput
*ConInRec
;
1263 UINT VirtualKeyCode
;
1264 UINT VirtualScanCode
;
1267 ULONG ResultSize
= 0;
1270 VirtualScanCode
= (msg
->lParam
>> 16) & 0xff;
1271 Down
= msg
->message
== WM_KEYDOWN
|| msg
->message
== WM_CHAR
||
1272 msg
->message
== WM_SYSKEYDOWN
|| msg
->message
== WM_SYSCHAR
;
1274 GetKeyboardState(KeyState
);
1275 ShiftState
= ConioGetShiftState(KeyState
);
1277 if (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
)
1279 VirtualKeyCode
= LastVirtualKey
;
1280 UnicodeChar
= msg
->wParam
;
1287 VirtualKeyCode
= msg
->wParam
;
1288 RetChars
= ToUnicodeEx(VirtualKeyCode
,
1295 UnicodeChar
= (1 == RetChars
? Chars
[0] : 0);
1298 if (0 == ResultSize
)
1303 er
.EventType
= KEY_EVENT
;
1304 er
.Event
.KeyEvent
.bKeyDown
= Down
;
1305 er
.Event
.KeyEvent
.wRepeatCount
= RepeatCount
;
1306 er
.Event
.KeyEvent
.uChar
.UnicodeChar
= UnicodeChar
;
1307 er
.Event
.KeyEvent
.dwControlKeyState
= ShiftState
;
1308 er
.Event
.KeyEvent
.wVirtualKeyCode
= VirtualKeyCode
;
1309 er
.Event
.KeyEvent
.wVirtualScanCode
= VirtualScanCode
;
1313 if (0 != (ShiftState
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1314 && VK_TAB
== VirtualKeyCode
)
1318 TuiSwapConsole(ShiftState
& SHIFT_PRESSED
? -1 : 1);
1323 else if (VK_MENU
== VirtualKeyCode
&& ! Down
)
1325 if (TuiSwapConsole(0))
1332 if (NULL
== Console
)
1337 ConInRec
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1339 if (NULL
== ConInRec
)
1344 ConInRec
->InputEvent
= er
;
1345 ConInRec
->Fake
= UnicodeChar
&&
1346 (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
&&
1347 msg
->message
!= WM_KEYUP
&& msg
->message
!= WM_SYSKEYUP
);
1348 ConInRec
->NotChar
= (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
);
1349 ConInRec
->Echoed
= FALSE
;
1350 if (ConInRec
->NotChar
)
1351 LastVirtualKey
= msg
->wParam
;
1353 DPRINT ("csrss: %s %s %s %s %02x %02x '%c' %04x\n",
1354 Down
? "down" : "up ",
1355 (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
) ?
1357 ConInRec
->Fake
? "fake" : "real",
1358 ConInRec
->NotChar
? "notc" : "char",
1361 (AsciiChar
>= ' ') ? AsciiChar
: '.',
1364 if (! ConInRec
->Fake
|| ! ConInRec
->NotChar
)
1366 /* FIXME - convert to ascii */
1367 ConioProcessChar(Console
, ConInRec
);
1371 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1376 Console_Api (PVOID unused
)
1378 /* keep reading events from the keyboard and stuffing them into the current
1379 console's input queue */
1382 /* This call establishes our message queue */
1383 PeekMessageW(&msg
, 0, 0, 0, PM_NOREMOVE
);
1384 /* This call registers our message queue */
1385 PrivateCsrssRegisterPrimitive();
1386 /* This call turns on the input system in win32k */
1387 PrivateCsrssAcquireOrReleaseInputOwnership(FALSE
);
1391 GetMessageW(&msg
, 0, 0, 0);
1392 TranslateMessage(&msg
);
1394 if (msg
.message
== WM_CHAR
|| msg
.message
== WM_SYSCHAR
||
1395 msg
.message
== WM_KEYDOWN
|| msg
.message
== WM_KEYUP
||
1396 msg
.message
== WM_SYSKEYDOWN
|| msg
.message
== WM_SYSKEYUP
)
1398 ConioProcessKey(&msg
, TuiGetFocusConsole(), TRUE
);
1402 PrivateCsrssAcquireOrReleaseInputOwnership(TRUE
);
1406 CSR_API(CsrGetScreenBufferInfo
)
1409 PCSRSS_SCREEN_BUFFER Buff
;
1410 PCONSOLE_SCREEN_BUFFER_INFO pInfo
;
1412 DPRINT("CsrGetScreenBufferInfo\n");
1414 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1415 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1417 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ScreenBufferInfoRequest
.ConsoleHandle
, &Buff
);
1418 if (! NT_SUCCESS(Status
))
1420 return Request
->Status
= Status
;
1422 pInfo
= &Request
->Data
.ScreenBufferInfoRequest
.Info
;
1423 pInfo
->dwSize
.X
= Buff
->MaxX
;
1424 pInfo
->dwSize
.Y
= Buff
->MaxY
;
1425 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1426 pInfo
->dwCursorPosition
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1427 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
1428 pInfo
->srWindow
.Left
= 0;
1429 pInfo
->srWindow
.Right
= Buff
->MaxX
- 1;
1430 pInfo
->srWindow
.Top
= 0;
1431 pInfo
->srWindow
.Bottom
= Buff
->MaxY
- 1;
1432 pInfo
->dwMaximumWindowSize
.X
= Buff
->MaxX
;
1433 pInfo
->dwMaximumWindowSize
.Y
= Buff
->MaxY
;
1434 ConioUnlockScreenBuffer(Buff
);
1436 Request
->Status
= STATUS_SUCCESS
;
1438 return Request
->Status
;
1441 CSR_API(CsrSetCursor
)
1444 PCSRSS_CONSOLE Console
;
1445 PCSRSS_SCREEN_BUFFER Buff
;
1446 LONG OldCursorX
, OldCursorY
;
1447 LONG NewCursorX
, NewCursorY
;
1449 DPRINT("CsrSetCursor\n");
1451 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1452 if (! NT_SUCCESS(Status
))
1454 return Request
->Status
= Status
;
1457 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1458 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1460 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
);
1461 if (! NT_SUCCESS(Status
))
1463 if (NULL
!= Console
)
1465 ConioUnlockConsole(Console
);
1467 return Request
->Status
= Status
;
1470 NewCursorX
= Request
->Data
.SetCursorRequest
.Position
.X
;
1471 NewCursorY
= Request
->Data
.SetCursorRequest
.Position
.Y
;
1472 if (NewCursorX
< 0 || NewCursorX
>= Buff
->MaxX
||
1473 NewCursorY
< 0 || NewCursorY
>= Buff
->MaxY
)
1475 ConioUnlockScreenBuffer(Buff
);
1476 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1478 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &OldCursorX
, &OldCursorY
);
1479 Buff
->CurrentX
= NewCursorX
+ Buff
->ShowX
;
1480 Buff
->CurrentY
= (NewCursorY
+ Buff
->ShowY
) % Buff
->MaxY
;
1481 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1483 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
1485 ConioUnlockScreenBuffer(Buff
);
1486 return Request
->Status
= STATUS_UNSUCCESSFUL
;
1490 ConioUnlockScreenBuffer(Buff
);
1491 if (NULL
!= Console
)
1493 ConioUnlockConsole(Console
);
1496 return Request
->Status
= STATUS_SUCCESS
;
1499 STATIC FASTCALL VOID
1500 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, COORD
*Start
, UINT Length
)
1502 if (Buff
->MaxX
<= Start
->X
+ Length
)
1504 UpdateRect
->left
= 0;
1508 UpdateRect
->left
= Start
->X
;
1510 if (Buff
->MaxX
<= Start
->X
+ Length
)
1512 UpdateRect
->right
= Buff
->MaxX
- 1;
1516 UpdateRect
->right
= Start
->X
+ Length
- 1;
1518 UpdateRect
->top
= Start
->Y
;
1519 UpdateRect
->bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->MaxX
;
1520 if (Buff
->MaxY
<= UpdateRect
->bottom
)
1522 UpdateRect
->bottom
= Buff
->MaxY
- 1;
1526 CSR_API(CsrWriteConsoleOutputChar
)
1529 PCHAR String
= (PCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
;
1531 PCSRSS_CONSOLE Console
;
1532 PCSRSS_SCREEN_BUFFER Buff
;
1533 DWORD X
, Y
, Length
, CharSize
, Written
= 0;
1536 DPRINT("CsrWriteConsoleOutputChar\n");
1538 CharSize
= (Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
1540 if (Request
->Header
.DataSize
1541 < sizeof(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR
) - 1
1542 + (Request
->Data
.WriteConsoleOutputCharRequest
.Length
* CharSize
))
1544 DPRINT1("Invalid request size\n");
1545 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1546 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1547 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1550 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1551 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1552 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1553 if (! NT_SUCCESS(Status
))
1555 return Request
->Status
= Status
;
1558 if(Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
)
1560 ConsoleUnicodeToAnsiN(Console
, String
, (PWCHAR
)String
, Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
1563 Status
= ConioLockScreenBuffer(ProcessData
,
1564 Request
->Data
.WriteConsoleOutputCharRequest
.ConsoleHandle
,
1566 if (! NT_SUCCESS(Status
))
1568 if (NULL
!= Console
)
1570 ConioUnlockConsole(Console
);
1572 return Request
->Status
= Status
;
1575 X
= Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.X
+ Buff
->ShowX
;
1576 Y
= (Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1577 Length
= Request
->Data
.WriteConsoleOutputCharRequest
.Length
;
1578 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1581 *Buffer
= *String
++;
1584 if (++X
== Buff
->MaxX
)
1586 if (++Y
== Buff
->MaxY
)
1589 Buffer
= Buff
->Buffer
;
1595 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1597 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputCharRequest
.Coord
,
1598 Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
1599 ConioDrawRegion(Console
, &UpdateRect
);
1602 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.X
= X
- Buff
->ShowX
;
1603 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1605 ConioUnlockScreenBuffer(Buff
);
1606 if (NULL
!= Console
)
1608 ConioUnlockConsole(Console
);
1611 Request
->Data
.WriteConsoleOutputCharRequest
.NrCharactersWritten
= Written
;
1612 return Request
->Status
= STATUS_SUCCESS
;
1615 CSR_API(CsrFillOutputChar
)
1618 PCSRSS_CONSOLE Console
;
1619 PCSRSS_SCREEN_BUFFER Buff
;
1620 DWORD X
, Y
, Length
, Written
= 0;
1625 DPRINT("CsrFillOutputChar\n");
1627 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1628 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1630 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1631 if (! NT_SUCCESS(Status
))
1633 return Request
->Status
= Status
;
1636 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputRequest
.ConsoleHandle
, &Buff
);
1637 if (! NT_SUCCESS(Status
))
1639 if (NULL
!= Console
)
1641 ConioUnlockConsole(Console
);
1643 return Request
->Status
= Status
;
1646 X
= Request
->Data
.FillOutputRequest
.Position
.X
+ Buff
->ShowX
;
1647 Y
= (Request
->Data
.FillOutputRequest
.Position
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1648 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1649 if(Request
->Data
.FillOutputRequest
.Unicode
)
1650 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &Request
->Data
.FillOutputRequest
.Char
.UnicodeChar
);
1652 Char
= Request
->Data
.FillOutputRequest
.Char
.AsciiChar
;
1653 Length
= Request
->Data
.FillOutputRequest
.Length
;
1659 if (++X
== Buff
->MaxX
)
1661 if (++Y
== Buff
->MaxY
)
1664 Buffer
= Buff
->Buffer
;
1670 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1672 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputRequest
.Position
,
1673 Request
->Data
.FillOutputRequest
.Length
);
1674 ConioDrawRegion(Console
, &UpdateRect
);
1677 ConioUnlockScreenBuffer(Buff
);
1678 if (NULL
!= Console
)
1680 ConioUnlockConsole(Console
);
1683 return Request
->Status
;
1686 CSR_API(CsrReadInputEvent
)
1688 PLIST_ENTRY CurrentEntry
;
1689 PCSRSS_CONSOLE Console
;
1691 BOOLEAN Done
= FALSE
;
1692 ConsoleInput
*Input
;
1694 DPRINT("CsrReadInputEvent\n");
1696 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1697 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1698 Request
->Data
.ReadInputRequest
.Event
= ProcessData
->ConsoleEvent
;
1700 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadInputRequest
.ConsoleHandle
, &Console
);
1701 if (! NT_SUCCESS(Status
))
1703 return Request
->Status
= Status
;
1706 /* only get input if there is any */
1707 CurrentEntry
= Console
->InputEvents
.Flink
;
1708 while (CurrentEntry
!= &Console
->InputEvents
)
1710 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
1711 CurrentEntry
= CurrentEntry
->Flink
;
1713 if (Done
&& !Input
->Fake
)
1715 Request
->Data
.ReadInputRequest
.MoreEvents
= TRUE
;
1719 RemoveEntryList(&Input
->ListEntry
);
1721 if (!Done
&& !Input
->Fake
)
1723 Request
->Data
.ReadInputRequest
.Input
= Input
->InputEvent
;
1724 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
1726 ConioInputEventToAnsi(Console
, &Request
->Data
.ReadInputRequest
.Input
);
1731 if (Input
->InputEvent
.EventType
== KEY_EVENT
)
1733 if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
)
1734 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
1735 && '\r' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1737 Console
->WaitingLines
--;
1739 Console
->WaitingChars
--;
1741 HeapFree(Win32CsrApiHeap
, 0, Input
);
1746 Status
= STATUS_SUCCESS
;
1747 Console
->EarlyReturn
= FALSE
;
1751 Status
= STATUS_PENDING
;
1752 Console
->EarlyReturn
= TRUE
; /* mark for early return */
1755 if (IsListEmpty(&Console
->InputEvents
))
1757 ResetEvent(Console
->ActiveEvent
);
1760 ConioUnlockConsole(Console
);
1762 return Request
->Status
= Status
;
1765 CSR_API(CsrWriteConsoleOutputAttrib
)
1767 PCSRSS_CONSOLE Console
;
1768 PCSRSS_SCREEN_BUFFER Buff
;
1769 PUCHAR Buffer
, Attribute
;
1774 DPRINT("CsrWriteConsoleOutputAttrib\n");
1776 if (Request
->Header
.DataSize
1777 < sizeof(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB
) - 1
1778 + Request
->Data
.WriteConsoleOutputAttribRequest
.Length
)
1780 DPRINT1("Invalid request size\n");
1781 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1782 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1783 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1786 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1787 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1788 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1789 if (! NT_SUCCESS(Status
))
1791 return Request
->Status
= Status
;
1794 Status
= ConioLockScreenBuffer(ProcessData
,
1795 Request
->Data
.WriteConsoleOutputAttribRequest
.ConsoleHandle
,
1797 if (! NT_SUCCESS(Status
))
1799 if (NULL
!= Console
)
1801 ConioUnlockConsole(Console
);
1803 return Request
->Status
= Status
;
1806 X
= Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1807 Y
= (Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1808 Length
= Request
->Data
.WriteConsoleOutputAttribRequest
.Length
;
1809 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + 1];
1810 Attribute
= (PUCHAR
)Request
->Data
.WriteConsoleOutputAttribRequest
.String
;
1813 *Buffer
= *Attribute
++;
1815 if (++X
== Buff
->MaxX
)
1817 if (++Y
== Buff
->MaxY
)
1820 Buffer
= Buff
->Buffer
+ 1;
1826 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1828 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
,
1829 Request
->Data
.WriteConsoleOutputAttribRequest
.Length
);
1830 ConioDrawRegion(Console
, &UpdateRect
);
1833 if (NULL
!= Console
)
1835 ConioUnlockConsole(Console
);
1838 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1839 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1841 ConioUnlockScreenBuffer(Buff
);
1843 return Request
->Status
= STATUS_SUCCESS
;
1846 CSR_API(CsrFillOutputAttrib
)
1848 PCSRSS_SCREEN_BUFFER Buff
;
1854 PCSRSS_CONSOLE Console
;
1856 DPRINT("CsrFillOutputAttrib\n");
1858 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1859 if (! NT_SUCCESS(Status
))
1861 return Request
->Status
= Status
;
1864 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1865 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1866 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputAttribRequest
.ConsoleHandle
, &Buff
);
1867 if (! NT_SUCCESS(Status
))
1869 if (NULL
!= Console
)
1871 ConioUnlockConsole(Console
);
1873 return Request
->Status
= Status
;
1876 X
= Request
->Data
.FillOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1877 Y
= (Request
->Data
.FillOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1878 Length
= Request
->Data
.FillOutputAttribRequest
.Length
;
1879 Attr
= Request
->Data
.FillOutputAttribRequest
.Attribute
;
1880 Buffer
= &Buff
->Buffer
[(Y
* Buff
->MaxX
* 2) + (X
* 2) + 1];
1885 if (++X
== Buff
->MaxX
)
1887 if (++Y
== Buff
->MaxY
)
1890 Buffer
= Buff
->Buffer
+ 1;
1896 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1898 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputAttribRequest
.Coord
,
1899 Request
->Data
.FillOutputAttribRequest
.Length
);
1900 ConioDrawRegion(Console
, &UpdateRect
);
1903 ConioUnlockScreenBuffer(Buff
);
1904 if (NULL
!= Console
)
1906 ConioUnlockConsole(Console
);
1909 return Request
->Status
= STATUS_SUCCESS
;
1913 CSR_API(CsrGetCursorInfo
)
1915 PCSRSS_SCREEN_BUFFER Buff
;
1918 DPRINT("CsrGetCursorInfo\n");
1920 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1921 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1923 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.GetCursorInfoRequest
.ConsoleHandle
, &Buff
);
1924 if (! NT_SUCCESS(Status
))
1926 return Request
->Status
= Status
;
1928 Request
->Data
.GetCursorInfoRequest
.Info
= Buff
->CursorInfo
;
1929 ConioUnlockScreenBuffer(Buff
);
1931 return Request
->Status
= STATUS_SUCCESS
;
1934 CSR_API(CsrSetCursorInfo
)
1936 PCSRSS_CONSOLE Console
;
1937 PCSRSS_SCREEN_BUFFER Buff
;
1942 DPRINT("CsrSetCursorInfo\n");
1944 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1945 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1947 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1948 if (! NT_SUCCESS(Status
))
1950 return Request
->Status
= Status
;
1953 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorInfoRequest
.ConsoleHandle
, &Buff
);
1954 if (! NT_SUCCESS(Status
))
1956 if (NULL
!= Console
)
1958 ConioUnlockConsole(Console
);
1960 return Request
->Status
= Status
;
1963 Size
= Request
->Data
.SetCursorInfoRequest
.Info
.dwSize
;
1964 Visible
= Request
->Data
.SetCursorInfoRequest
.Info
.bVisible
;
1974 if (Size
!= Buff
->CursorInfo
.dwSize
1975 || (Visible
&& ! Buff
->CursorInfo
.bVisible
) || (! Visible
&& Buff
->CursorInfo
.bVisible
))
1977 Buff
->CursorInfo
.dwSize
= Size
;
1978 Buff
->CursorInfo
.bVisible
= Visible
;
1980 if (NULL
!= Console
&& ! ConioSetCursorInfo(Console
, Buff
))
1982 ConioUnlockScreenBuffer(Buff
);
1983 ConioUnlockConsole(Console
);
1984 return Request
->Status
= STATUS_UNSUCCESSFUL
;
1988 ConioUnlockScreenBuffer(Buff
);
1989 if (NULL
!= Console
)
1991 ConioUnlockConsole(Console
);
1994 return Request
->Status
= STATUS_SUCCESS
;
1997 CSR_API(CsrSetTextAttrib
)
2000 PCSRSS_CONSOLE Console
;
2001 PCSRSS_SCREEN_BUFFER Buff
;
2002 LONG OldCursorX
, OldCursorY
;
2004 DPRINT("CsrSetTextAttrib\n");
2006 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2007 if (! NT_SUCCESS(Status
))
2009 return Request
->Status
= Status
;
2012 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
);
2013 if (! NT_SUCCESS(Status
))
2015 if (NULL
!= Console
)
2017 ConioUnlockConsole(Console
);
2019 return Request
->Status
= Status
;
2022 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &OldCursorX
, &OldCursorY
);
2024 Buff
->DefaultAttrib
= Request
->Data
.SetAttribRequest
.Attrib
;
2025 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
2027 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
2029 ConioUnlockScreenBuffer(Buff
);
2030 ConioUnlockConsole(Console
);
2031 return Request
->Status
= STATUS_UNSUCCESSFUL
;
2035 ConioUnlockScreenBuffer(Buff
);
2036 if (NULL
!= Console
)
2038 ConioUnlockConsole(Console
);
2041 return Request
->Status
= STATUS_SUCCESS
;
2044 CSR_API(CsrSetConsoleMode
)
2047 PCSRSS_CONSOLE Console
;
2048 PCSRSS_SCREEN_BUFFER Buff
;
2050 DPRINT("CsrSetConsoleMode\n");
2052 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2053 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2054 Status
= Win32CsrGetObject(ProcessData
,
2055 Request
->Data
.SetConsoleModeRequest
.ConsoleHandle
,
2056 (Object_t
**) &Console
);
2057 if (! NT_SUCCESS(Status
))
2059 return Request
->Status
= Status
;
2062 Buff
= (PCSRSS_SCREEN_BUFFER
)Console
;
2063 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
2065 Console
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_INPUT_MODE_VALID
;
2067 else if (CONIO_SCREEN_BUFFER_MAGIC
== Console
->Header
.Type
)
2069 Buff
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_OUTPUT_MODE_VALID
;
2073 return Request
->Status
= STATUS_INVALID_HANDLE
;
2076 Request
->Status
= STATUS_SUCCESS
;
2078 return Request
->Status
;
2081 CSR_API(CsrGetConsoleMode
)
2084 PCSRSS_CONSOLE Console
;
2085 PCSRSS_SCREEN_BUFFER Buff
; /* gee, I really wish I could use an anonymous union here */
2087 DPRINT("CsrGetConsoleMode\n");
2089 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2090 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2091 Status
= Win32CsrGetObject(ProcessData
, Request
->Data
.GetConsoleModeRequest
.ConsoleHandle
,
2092 (Object_t
**) &Console
);
2093 if (! NT_SUCCESS(Status
))
2095 return Request
->Status
= Status
;
2097 Request
->Status
= STATUS_SUCCESS
;
2098 Buff
= (PCSRSS_SCREEN_BUFFER
) Console
;
2099 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
2101 Request
->Data
.GetConsoleModeRequest
.ConsoleMode
= Console
->Mode
;
2103 else if (CONIO_SCREEN_BUFFER_MAGIC
== Buff
->Header
.Type
)
2105 Request
->Data
.GetConsoleModeRequest
.ConsoleMode
= Buff
->Mode
;
2109 Request
->Status
= STATUS_INVALID_HANDLE
;
2112 return Request
->Status
;
2115 CSR_API(CsrCreateScreenBuffer
)
2117 PCSRSS_CONSOLE Console
;
2118 PCSRSS_SCREEN_BUFFER Buff
;
2121 DPRINT("CsrCreateScreenBuffer\n");
2123 if (ProcessData
== NULL
)
2125 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2128 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2129 if (! NT_SUCCESS(Status
))
2131 return Request
->Status
= Status
;
2133 if (NULL
== Console
)
2135 return Request
->Status
= STATUS_INVALID_HANDLE
;
2138 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2139 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2141 Buff
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(CSRSS_SCREEN_BUFFER
));
2144 Request
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2147 Status
= CsrInitConsoleScreenBuffer(Console
, Buff
);
2148 if(! NT_SUCCESS(Status
))
2150 Request
->Status
= Status
;
2154 Request
->Status
= Win32CsrInsertObject(ProcessData
, &Request
->Data
.CreateScreenBufferRequest
.OutputHandle
, &Buff
->Header
);
2157 ConioUnlockConsole(Console
);
2159 return Request
->Status
;
2162 CSR_API(CsrSetScreenBuffer
)
2165 PCSRSS_CONSOLE Console
;
2166 PCSRSS_SCREEN_BUFFER Buff
;
2168 DPRINT("CsrSetScreenBuffer\n");
2170 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2171 if (! NT_SUCCESS(Status
))
2173 return Request
->Status
= Status
;
2175 if (NULL
== Console
)
2177 DPRINT1("Trying to set screen buffer for app without console\n");
2178 return Request
->Status
= STATUS_INVALID_HANDLE
;
2181 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2182 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2184 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetScreenBufferRequest
.OutputHandle
, &Buff
);
2185 if (! NT_SUCCESS(Status
))
2187 ConioUnlockConsole(Console
);
2188 return Request
->Status
;
2191 if (Buff
== Console
->ActiveBuffer
)
2193 ConioUnlockScreenBuffer(Buff
);
2194 ConioUnlockConsole(Console
);
2195 return STATUS_SUCCESS
;
2198 /* drop reference to old buffer, maybe delete */
2199 if (! InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
2201 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
2203 /* tie console to new buffer */
2204 Console
->ActiveBuffer
= Buff
;
2205 /* inc ref count on new buffer */
2206 InterlockedIncrement(&Buff
->Header
.ReferenceCount
);
2207 /* Redraw the console */
2208 ConioDrawConsole(Console
);
2210 ConioUnlockScreenBuffer(Buff
);
2211 ConioUnlockConsole(Console
);
2213 return Request
->Status
= STATUS_SUCCESS
;
2216 CSR_API(CsrSetTitle
)
2219 PCSRSS_CONSOLE Console
;
2221 DPRINT("CsrSetTitle\n");
2223 if (Request
->Header
.DataSize
2224 < sizeof(CSRSS_SET_TITLE
) - 1
2225 + Request
->Data
.SetTitleRequest
.Length
)
2227 DPRINT1("Invalid request size\n");
2228 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2229 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2230 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2233 Status
= ConioLockConsole(ProcessData
, Request
->Data
.SetTitleRequest
.Console
, &Console
);
2234 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2235 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2236 if(! NT_SUCCESS(Status
))
2238 Request
->Status
= Status
;
2242 /* copy title to console */
2243 RtlFreeUnicodeString(&Console
->Title
);
2244 RtlCreateUnicodeString(&Console
->Title
, Request
->Data
.SetTitleRequest
.Title
);
2245 if (! ConioChangeTitle(Console
))
2247 Request
->Status
= STATUS_UNSUCCESSFUL
;
2251 Request
->Status
= STATUS_SUCCESS
;
2254 ConioUnlockConsole(Console
);
2256 return Request
->Status
;
2259 CSR_API(CsrGetTitle
)
2262 PCSRSS_CONSOLE Console
;
2264 DPRINT("CsrGetTitle\n");
2266 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2267 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2268 Status
= ConioLockConsole(ProcessData
,
2269 Request
->Data
.GetTitleRequest
.ConsoleHandle
,
2271 if (! NT_SUCCESS(Status
))
2273 DPRINT1("Can't get console\n");
2274 return Request
->Status
= Status
;
2277 /* Copy title of the console to the user title buffer */
2278 RtlZeroMemory(&Request
->Data
.GetTitleRequest
, sizeof(CSRSS_GET_TITLE
));
2279 Request
->Data
.GetTitleRequest
.ConsoleHandle
= Request
->Data
.GetTitleRequest
.ConsoleHandle
;
2280 Request
->Data
.GetTitleRequest
.Length
= Console
->Title
.Length
;
2281 wcscpy (Request
->Data
.GetTitleRequest
.Title
, Console
->Title
.Buffer
);
2282 Request
->Header
.MessageSize
+= Console
->Title
.Length
;
2283 Request
->Header
.DataSize
+= Console
->Title
.Length
;
2284 Request
->Status
= STATUS_SUCCESS
;
2286 ConioUnlockConsole(Console
);
2288 return Request
->Status
;
2291 CSR_API(CsrWriteConsoleOutput
)
2293 SHORT i
, X
, Y
, SizeX
, SizeY
;
2294 PCSRSS_CONSOLE Console
;
2295 PCSRSS_SCREEN_BUFFER Buff
;
2297 CHAR_INFO
* CurCharInfo
;
2299 CHAR_INFO
* CharInfo
;
2306 DPRINT("CsrWriteConsoleOutput\n");
2308 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2309 if (! NT_SUCCESS(Status
))
2311 return Request
->Status
= Status
;
2314 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2315 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2316 Status
= ConioLockScreenBuffer(ProcessData
,
2317 Request
->Data
.WriteConsoleOutputRequest
.ConsoleHandle
,
2319 if (! NT_SUCCESS(Status
))
2321 if (NULL
!= Console
)
2323 ConioUnlockConsole(Console
);
2325 return Request
->Status
= Status
;
2328 BufferSize
= Request
->Data
.WriteConsoleOutputRequest
.BufferSize
;
2329 PSize
= BufferSize
.X
* BufferSize
.Y
* sizeof(CHAR_INFO
);
2330 BufferCoord
= Request
->Data
.WriteConsoleOutputRequest
.BufferCoord
;
2331 CharInfo
= Request
->Data
.WriteConsoleOutputRequest
.CharInfo
;
2332 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
) ||
2333 (((ULONG_PTR
)CharInfo
+ PSize
) >
2334 ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2336 ConioUnlockScreenBuffer(Buff
);
2337 ConioUnlockConsole(Console
);
2338 return Request
->Status
= STATUS_ACCESS_VIOLATION
;
2340 WriteRegion
.left
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
;
2341 WriteRegion
.top
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
;
2342 WriteRegion
.right
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
;
2343 WriteRegion
.bottom
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
;
2345 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&WriteRegion
));
2346 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&WriteRegion
));
2347 WriteRegion
.bottom
= WriteRegion
.top
+ SizeY
- 1;
2348 WriteRegion
.right
= WriteRegion
.left
+ SizeX
- 1;
2350 /* Make sure WriteRegion is inside the screen buffer */
2351 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2352 if (! ConioGetIntersection(&WriteRegion
, &ScreenBuffer
, &WriteRegion
))
2354 ConioUnlockScreenBuffer(Buff
);
2355 ConioUnlockConsole(Console
);
2357 /* It is okay to have a WriteRegion completely outside the screen buffer.
2358 No data is written then. */
2359 return Request
->Status
= STATUS_SUCCESS
;
2362 for (i
= 0, Y
= WriteRegion
.top
; Y
<= WriteRegion
.bottom
; i
++, Y
++)
2364 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
2365 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ WriteRegion
.left
) * 2;
2366 for (X
= WriteRegion
.left
; X
<= WriteRegion
.right
; X
++)
2368 if (Request
->Data
.WriteConsoleOutputRequest
.Unicode
)
2371 ConsoleUnicodeCharToAnsiChar(Console
, &AsciiChar
, &CurCharInfo
->Char
.UnicodeChar
);
2372 SET_CELL_BUFFER(Buff
, Offset
, AsciiChar
, CurCharInfo
->Attributes
);
2376 SET_CELL_BUFFER(Buff
, Offset
, CurCharInfo
->Char
.AsciiChar
, CurCharInfo
->Attributes
);
2382 if (NULL
!= Console
)
2384 ConioDrawRegion(Console
, &WriteRegion
);
2387 ConioUnlockScreenBuffer(Buff
);
2388 ConioUnlockConsole(Console
);
2390 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
= WriteRegion
.left
+ SizeX
- 1;
2391 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
= WriteRegion
.top
+ SizeY
- 1;
2392 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
= WriteRegion
.left
;
2393 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
= WriteRegion
.top
;
2395 return Request
->Status
= STATUS_SUCCESS
;
2398 CSR_API(CsrFlushInputBuffer
)
2400 PLIST_ENTRY CurrentEntry
;
2401 PCSRSS_CONSOLE Console
;
2402 ConsoleInput
* Input
;
2405 DPRINT("CsrFlushInputBuffer\n");
2407 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2408 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2409 Status
= ConioLockConsole(ProcessData
,
2410 Request
->Data
.FlushInputBufferRequest
.ConsoleInput
,
2412 if(! NT_SUCCESS(Status
))
2414 return Request
->Status
= Status
;
2417 /* Discard all entries in the input event queue */
2418 while (!IsListEmpty(&Console
->InputEvents
))
2420 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
2421 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
2422 /* Destroy the event */
2423 HeapFree(Win32CsrApiHeap
, 0, Input
);
2425 ResetEvent(Console
->ActiveEvent
);
2426 Console
->WaitingChars
=0;
2428 ConioUnlockConsole(Console
);
2430 return Request
->Status
= STATUS_SUCCESS
;
2433 CSR_API(CsrScrollConsoleScreenBuffer
)
2435 PCSRSS_CONSOLE Console
;
2436 PCSRSS_SCREEN_BUFFER Buff
;
2441 RECT ScrollRectangle
;
2446 DPRINT("CsrScrollConsoleScreenBuffer\n");
2448 ALIAS(ConsoleHandle
,Request
->Data
.ScrollConsoleScreenBufferRequest
.ConsoleHandle
);
2449 ALIAS(UseClipRectangle
,Request
->Data
.ScrollConsoleScreenBufferRequest
.UseClipRectangle
);
2450 ALIAS(DestinationOrigin
,Request
->Data
.ScrollConsoleScreenBufferRequest
.DestinationOrigin
);
2451 ALIAS(Fill
,Request
->Data
.ScrollConsoleScreenBufferRequest
.Fill
);
2453 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2454 if (! NT_SUCCESS(Status
))
2456 return Request
->Status
= Status
;
2459 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2460 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2461 Status
= ConioLockScreenBuffer(ProcessData
, ConsoleHandle
, &Buff
);
2462 if (! NT_SUCCESS(Status
))
2464 if (NULL
!= Console
)
2466 ConioUnlockConsole(Console
);
2468 return Request
->Status
= Status
;
2471 ScrollRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Left
;
2472 ScrollRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Top
;
2473 ScrollRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Right
;
2474 ScrollRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Bottom
;
2475 ClipRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Left
;
2476 ClipRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Top
;
2477 ClipRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Right
;
2478 ClipRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Bottom
;
2480 /* Make sure source rectangle is inside the screen buffer */
2481 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2482 if (! ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, &ScrollRectangle
))
2484 ConioUnlockScreenBuffer(Buff
);
2485 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2488 if (UseClipRectangle
&& ! ConioGetIntersection(&SrcRegion
, &SrcRegion
, &ClipRectangle
))
2490 ConioUnlockScreenBuffer(Buff
);
2491 return Request
->Status
= STATUS_SUCCESS
;
2495 ConioInitRect(&DstRegion
,
2496 DestinationOrigin
.Y
,
2497 DestinationOrigin
.X
,
2498 DestinationOrigin
.Y
+ ConioRectHeight(&ScrollRectangle
) - 1,
2499 DestinationOrigin
.X
+ ConioRectWidth(&ScrollRectangle
) - 1);
2501 /* Make sure destination rectangle is inside the screen buffer */
2502 if (! ConioGetIntersection(&DstRegion
, &DstRegion
, &ScreenBuffer
))
2504 ConioUnlockScreenBuffer(Buff
);
2505 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2508 ConioCopyRegion(Buff
, &SrcRegion
, &DstRegion
);
2510 /* Get the region that should be filled with the specified character and attributes */
2514 ConioGetUnion(&FillRegion
, &SrcRegion
, &DstRegion
);
2516 if (ConioSubtractRect(&FillRegion
, &FillRegion
, &DstRegion
))
2518 /* FIXME: The subtracted rectangle is off by one line */
2519 FillRegion
.top
+= 1;
2521 ConioFillRegion(Console
, Buff
, &FillRegion
, &Fill
, Request
->Data
.ScrollConsoleScreenBufferRequest
.Unicode
);
2525 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
2527 /* Draw destination region */
2528 ConioDrawRegion(Console
, &DstRegion
);
2532 /* Draw filled region */
2533 ConioDrawRegion(Console
, &FillRegion
);
2537 ConioUnlockScreenBuffer(Buff
);
2538 if (NULL
!= Console
)
2540 ConioUnlockConsole(Console
);
2543 return Request
->Status
= STATUS_SUCCESS
;
2546 CSR_API(CsrReadConsoleOutputChar
)
2549 PCSRSS_CONSOLE Console
;
2550 PCSRSS_SCREEN_BUFFER Buff
;
2557 DPRINT("CsrReadConsoleOutputChar\n");
2559 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2560 Request
->Header
.DataSize
= Request
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
2561 ReadBuffer
= Request
->Data
.ReadConsoleOutputCharRequest
.String
;
2563 CharSize
= (Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
2565 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2566 if (! NT_SUCCESS(Status
))
2568 return Request
->Status
= Status
;
2571 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputCharRequest
.ConsoleHandle
, &Buff
);
2572 if (! NT_SUCCESS(Status
))
2574 return Request
->Status
= Status
;
2577 Xpos
= Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.X
+ Buff
->ShowX
;
2578 Ypos
= (Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
2580 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
; ++i
)
2582 Char
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
)];
2584 if(Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
)
2586 ConsoleAnsiCharToUnicodeChar(Console
, (WCHAR
*)ReadBuffer
, &Char
);
2587 ReadBuffer
+= sizeof(WCHAR
);
2590 *(ReadBuffer
++) = Char
;
2594 if (Xpos
== Buff
->MaxX
)
2599 if (Ypos
== Buff
->MaxY
)
2607 Request
->Status
= STATUS_SUCCESS
;
2608 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.X
= Xpos
- Buff
->ShowX
;
2609 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.Y
= (Ypos
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
;
2610 Request
->Header
.MessageSize
+= Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
;
2611 Request
->Header
.DataSize
+= Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
;
2613 ConioUnlockScreenBuffer(Buff
);
2614 if (NULL
!= Console
)
2616 ConioUnlockConsole(Console
);
2619 Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
= (DWORD
)((ULONG_PTR
)ReadBuffer
- (ULONG_PTR
)Request
->Data
.ReadConsoleOutputCharRequest
.String
) / CharSize
;
2621 return Request
->Status
;
2625 CSR_API(CsrReadConsoleOutputAttrib
)
2628 PCSRSS_SCREEN_BUFFER Buff
;
2633 DPRINT("CsrReadConsoleOutputAttrib\n");
2635 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2636 Request
->Header
.DataSize
= Request
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
2637 ReadBuffer
= Request
->Data
.ReadConsoleOutputAttribRequest
.String
;
2639 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputAttribRequest
.ConsoleHandle
, &Buff
);
2640 if (! NT_SUCCESS(Status
))
2642 return Request
->Status
= Status
;
2645 Xpos
= Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.X
+ Buff
->ShowX
;
2646 Ypos
= (Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
2648 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
; ++i
)
2650 *ReadBuffer
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
) + 1];
2655 if (Xpos
== Buff
->MaxX
)
2660 if (Ypos
== Buff
->MaxY
)
2669 Request
->Status
= STATUS_SUCCESS
;
2670 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.X
= Xpos
- Buff
->ShowX
;
2671 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.Y
= (Ypos
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
;
2672 Request
->Header
.MessageSize
+= Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
;
2673 Request
->Header
.DataSize
+= Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
;
2675 ConioUnlockScreenBuffer(Buff
);
2677 return Request
->Status
;
2681 CSR_API(CsrGetNumberOfConsoleInputEvents
)
2684 PCSRSS_CONSOLE Console
;
2685 PLIST_ENTRY CurrentItem
;
2687 ConsoleInput
*Input
;
2689 DPRINT("CsrGetNumberOfConsoleInputEvents\n");
2691 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2692 Request
->Header
.DataSize
= Request
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
2694 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
);
2695 if (! NT_SUCCESS(Status
))
2697 return Request
->Status
= Status
;
2700 CurrentItem
= Console
->InputEvents
.Flink
;
2703 /* If there are any events ... */
2704 while (CurrentItem
!= &Console
->InputEvents
)
2706 Input
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2707 CurrentItem
= CurrentItem
->Flink
;
2714 ConioUnlockConsole(Console
);
2716 Request
->Status
= STATUS_SUCCESS
;
2717 Request
->Data
.GetNumInputEventsRequest
.NumInputEvents
= NumEvents
;
2719 return Request
->Status
;
2723 CSR_API(CsrPeekConsoleInput
)
2726 PCSRSS_CONSOLE Console
;
2729 PLIST_ENTRY CurrentItem
;
2730 PINPUT_RECORD InputRecord
;
2734 DPRINT("CsrPeekConsoleInput\n");
2736 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2737 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2739 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
);
2740 if(! NT_SUCCESS(Status
))
2742 return Request
->Status
= Status
;
2745 InputRecord
= Request
->Data
.PeekConsoleInputRequest
.InputRecord
;
2746 Length
= Request
->Data
.PeekConsoleInputRequest
.Length
;
2747 Size
= Length
* sizeof(INPUT_RECORD
);
2749 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2750 || (((ULONG_PTR
)InputRecord
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2752 ConioUnlockConsole(Console
);
2753 Request
->Status
= STATUS_ACCESS_VIOLATION
;
2754 return Request
->Status
;
2759 if (! IsListEmpty(&Console
->InputEvents
))
2761 CurrentItem
= Console
->InputEvents
.Flink
;
2763 while (CurrentItem
!= &Console
->InputEvents
&& NumItems
< Length
)
2765 Item
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2769 CurrentItem
= CurrentItem
->Flink
;
2774 *InputRecord
= Item
->InputEvent
;
2776 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
2778 ConioInputEventToAnsi(Console
, InputRecord
);
2782 CurrentItem
= CurrentItem
->Flink
;
2786 ConioUnlockConsole(Console
);
2788 Request
->Status
= STATUS_SUCCESS
;
2789 Request
->Data
.PeekConsoleInputRequest
.Length
= NumItems
;
2791 return Request
->Status
;
2795 CSR_API(CsrReadConsoleOutput
)
2797 PCHAR_INFO CharInfo
;
2798 PCHAR_INFO CurCharInfo
;
2799 PCSRSS_SCREEN_BUFFER Buff
;
2812 DPRINT("CsrReadConsoleOutput\n");
2814 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2815 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2817 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputRequest
.ConsoleHandle
, &Buff
);
2818 if (! NT_SUCCESS(Status
))
2820 return Request
->Status
= Status
;
2823 CharInfo
= Request
->Data
.ReadConsoleOutputRequest
.CharInfo
;
2824 ReadRegion
.left
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
;
2825 ReadRegion
.top
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
;
2826 ReadRegion
.right
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
;
2827 ReadRegion
.bottom
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
;
2828 BufferSize
= Request
->Data
.ReadConsoleOutputRequest
.BufferSize
;
2829 BufferCoord
= Request
->Data
.ReadConsoleOutputRequest
.BufferCoord
;
2830 Length
= BufferSize
.X
* BufferSize
.Y
;
2831 Size
= Length
* sizeof(CHAR_INFO
);
2833 /* FIXME: Is this correct? */
2834 CodePage
= ProcessData
->Console
->OutputCodePage
;
2836 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
)
2837 || (((ULONG_PTR
)CharInfo
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2839 ConioUnlockScreenBuffer(Buff
);
2840 Request
->Status
= STATUS_ACCESS_VIOLATION
;
2841 return Request
->Status
;
2844 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&ReadRegion
));
2845 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&ReadRegion
));
2846 ReadRegion
.bottom
= ReadRegion
.top
+ SizeY
;
2847 ReadRegion
.right
= ReadRegion
.left
+ SizeX
;
2849 ConioInitRect(&ScreenRect
, 0, 0, Buff
->MaxY
, Buff
->MaxX
);
2850 if (! ConioGetIntersection(&ReadRegion
, &ScreenRect
, &ReadRegion
))
2852 ConioUnlockScreenBuffer(Buff
);
2853 Request
->Status
= STATUS_SUCCESS
;
2854 return Request
->Status
;
2857 for (i
= 0, Y
= ReadRegion
.top
; Y
< ReadRegion
.bottom
; ++i
, ++Y
)
2859 CurCharInfo
= CharInfo
+ (i
* BufferSize
.X
);
2861 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ ReadRegion
.left
) * 2;
2862 for (X
= ReadRegion
.left
; X
< ReadRegion
.right
; ++X
)
2864 if (Request
->Data
.ReadConsoleOutputRequest
.Unicode
)
2866 MultiByteToWideChar(CodePage
, 0,
2867 (PCHAR
)&GET_CELL_BUFFER(Buff
, Offset
), 1,
2868 &CurCharInfo
->Char
.UnicodeChar
, 1);
2872 CurCharInfo
->Char
.AsciiChar
= GET_CELL_BUFFER(Buff
, Offset
);
2874 CurCharInfo
->Attributes
= GET_CELL_BUFFER(Buff
, Offset
);
2879 ConioUnlockScreenBuffer(Buff
);
2881 Request
->Status
= STATUS_SUCCESS
;
2882 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
= ReadRegion
.left
+ SizeX
- 1;
2883 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
= ReadRegion
.top
+ SizeY
- 1;
2884 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
= ReadRegion
.left
;
2885 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
= ReadRegion
.top
;
2887 return Request
->Status
;
2891 CSR_API(CsrWriteConsoleInput
)
2893 PINPUT_RECORD InputRecord
;
2894 PCSRSS_CONSOLE Console
;
2899 ConsoleInput
* Record
;
2901 DPRINT("CsrWriteConsoleInput\n");
2903 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2904 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2906 Status
= ConioLockConsole(ProcessData
, Request
->Data
.WriteConsoleInputRequest
.ConsoleHandle
, &Console
);
2907 if (! NT_SUCCESS(Status
))
2909 return Request
->Status
= Status
;
2912 InputRecord
= Request
->Data
.WriteConsoleInputRequest
.InputRecord
;
2913 Length
= Request
->Data
.WriteConsoleInputRequest
.Length
;
2914 Size
= Length
* sizeof(INPUT_RECORD
);
2916 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2917 || (((ULONG_PTR
)InputRecord
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2919 ConioUnlockConsole(Console
);
2920 Request
->Status
= STATUS_ACCESS_VIOLATION
;
2921 return Request
->Status
;
2924 for (i
= 0; i
< Length
; i
++)
2926 Record
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
2929 ConioUnlockConsole(Console
);
2930 Request
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2931 return Request
->Status
;
2934 Record
->Echoed
= FALSE
;
2935 Record
->Fake
= FALSE
;
2936 Record
->InputEvent
= *InputRecord
++;
2937 if (KEY_EVENT
== Record
->InputEvent
.EventType
)
2939 /* FIXME - convert from unicode to ascii!! */
2940 ConioProcessChar(Console
, Record
);
2944 ConioUnlockConsole(Console
);
2946 Request
->Status
= STATUS_SUCCESS
;
2947 Request
->Data
.WriteConsoleInputRequest
.Length
= i
;
2949 return Request
->Status
;
2952 /**********************************************************************
2953 * HardwareStateProperty
2956 * Set/Get the value of the HardwareState and switch
2957 * between direct video buffer ouput and GDI windowed
2960 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
2961 * object. We use the same object to Request.
2963 * ConsoleHwState has the correct size to be compatible
2964 * with NT's, but values are not.
2966 STATIC NTSTATUS FASTCALL
2967 SetConsoleHardwareState (PCSRSS_CONSOLE Console
, DWORD ConsoleHwState
)
2969 DPRINT1("Console Hardware State: %d\n", ConsoleHwState
);
2971 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED
== ConsoleHwState
)
2972 ||(CONSOLE_HARDWARE_STATE_DIRECT
== ConsoleHwState
))
2974 if (Console
->HardwareState
!= ConsoleHwState
)
2976 /* TODO: implement switching from full screen to windowed mode */
2977 /* TODO: or back; now simply store the hardware state */
2978 Console
->HardwareState
= ConsoleHwState
;
2981 return STATUS_SUCCESS
;
2984 return STATUS_INVALID_PARAMETER_3
; /* Client: (handle, set_get, [mode]) */
2987 CSR_API(CsrHardwareStateProperty
)
2989 PCSRSS_CONSOLE Console
;
2992 DPRINT("CsrHardwareStateProperty\n");
2994 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2995 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2997 Status
= ConioLockConsole(ProcessData
,
2998 Request
->Data
.ConsoleHardwareStateRequest
.ConsoleHandle
,
3000 if (! NT_SUCCESS(Status
))
3002 DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
3003 return Request
->Status
= Status
;
3006 switch (Request
->Data
.ConsoleHardwareStateRequest
.SetGet
)
3008 case CONSOLE_HARDWARE_STATE_GET
:
3009 Request
->Data
.ConsoleHardwareStateRequest
.State
= Console
->HardwareState
;
3012 case CONSOLE_HARDWARE_STATE_SET
:
3013 DPRINT("Setting console hardware state.\n");
3014 Request
->Status
= SetConsoleHardwareState(Console
, Request
->Data
.ConsoleHardwareStateRequest
.State
);
3018 Request
->Status
= STATUS_INVALID_PARAMETER_2
; /* Client: (handle, [set_get], mode) */
3022 ConioUnlockConsole(Console
);
3024 return Request
->Status
;
3027 CSR_API(CsrGetConsoleWindow
)
3029 PCSRSS_CONSOLE Console
;
3032 DPRINT("CsrGetConsoleWindow\n");
3034 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
3035 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
3037 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3038 if (! NT_SUCCESS(Status
))
3040 return Request
->Status
= Status
;
3043 Request
->Data
.GetConsoleWindowRequest
.WindowHandle
= Console
->hWindow
;
3044 ConioUnlockConsole(Console
);
3046 return Request
->Status
= STATUS_SUCCESS
;
3049 CSR_API(CsrSetConsoleIcon
)
3051 PCSRSS_CONSOLE Console
;
3054 DPRINT("CsrSetConsoleIcon\n");
3056 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
3057 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
3059 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3060 if (! NT_SUCCESS(Status
))
3062 return Request
->Status
= Status
;
3065 Console
->hWindowIcon
= Request
->Data
.SetConsoleIconRequest
.WindowIcon
;
3066 Request
->Status
= (ConioChangeIcon(Console
) ? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
3067 ConioUnlockConsole(Console
);
3069 return Request
->Status
;
3072 CSR_API(CsrGetConsoleCodePage
)
3074 PCSRSS_CONSOLE Console
;
3077 DPRINT("CsrGetConsoleCodePage\n");
3079 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3080 if (! NT_SUCCESS(Status
))
3082 return Request
->Status
= Status
;
3085 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
3086 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
3087 Request
->Data
.GetConsoleCodePage
.CodePage
= Console
->CodePage
;
3088 ConioUnlockConsole(Console
);
3089 return Request
->Status
= STATUS_SUCCESS
;
3092 CSR_API(CsrSetConsoleCodePage
)
3094 PCSRSS_CONSOLE Console
;
3097 DPRINT("CsrSetConsoleCodePage\n");
3099 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3100 if (! NT_SUCCESS(Status
))
3102 return Request
->Status
= Status
;
3105 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
3106 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
3107 if (IsValidCodePage(Request
->Data
.SetConsoleCodePage
.CodePage
))
3109 Console
->CodePage
= Request
->Data
.SetConsoleCodePage
.CodePage
;
3110 ConioUnlockConsole(Console
);
3111 return Request
->Status
= STATUS_SUCCESS
;
3113 ConioUnlockConsole(Console
);
3114 return Request
->Status
= STATUS_UNSUCCESSFUL
;
3117 CSR_API(CsrGetConsoleOutputCodePage
)
3119 PCSRSS_CONSOLE Console
;
3122 DPRINT("CsrGetConsoleOutputCodePage\n");
3124 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3125 if (! NT_SUCCESS(Status
))
3127 return Request
->Status
= Status
;
3130 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
3131 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
3132 Request
->Data
.GetConsoleOutputCodePage
.CodePage
= Console
->OutputCodePage
;
3133 ConioUnlockConsole(Console
);
3134 return Request
->Status
= STATUS_SUCCESS
;
3137 CSR_API(CsrSetConsoleOutputCodePage
)
3139 PCSRSS_CONSOLE Console
;
3142 DPRINT("CsrSetConsoleOutputCodePage\n");
3144 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3145 if (! NT_SUCCESS(Status
))
3147 return Request
->Status
= Status
;
3150 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
3151 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
3152 if (IsValidCodePage(Request
->Data
.SetConsoleOutputCodePage
.CodePage
))
3154 Console
->OutputCodePage
= Request
->Data
.SetConsoleOutputCodePage
.CodePage
;
3155 ConioUnlockConsole(Console
);
3156 return Request
->Status
= STATUS_SUCCESS
;
3158 ConioUnlockConsole(Console
);
3159 return Request
->Status
= STATUS_UNSUCCESSFUL
;
3162 CSR_API(CsrGetProcessList
)
3165 PCSRSS_CONSOLE Console
;
3166 PCSRSS_PROCESS_DATA current
;
3167 PLIST_ENTRY current_entry
;
3168 ULONG nItems
, nCopied
;
3171 DPRINT("CsrGetProcessList\n");
3173 Buffer
= Request
->Data
.GetProcessListRequest
.ProcessId
;
3174 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
3175 Request
->Header
.DataSize
= Request
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
3177 nItems
= nCopied
= 0;
3178 Request
->Data
.GetProcessListRequest
.nProcessIdsCopied
= 0;
3179 Request
->Data
.GetProcessListRequest
.nProcessIdsTotal
= 0;
3181 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3182 if (! NT_SUCCESS(Status
))
3184 return Request
->Status
= Status
;
3187 DPRINT1("Console_Api Ctrl-C\n");
3189 for(current_entry
= Console
->ProcessList
.Flink
;
3190 current_entry
!= &Console
->ProcessList
;
3191 current_entry
= current_entry
->Flink
)
3193 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
3194 if(nItems
++ < Request
->Data
.GetProcessListRequest
.nMaxIds
)
3196 *(Buffer
++) = current
->ProcessId
;
3201 ConioUnlockConsole(Console
);
3203 Request
->Data
.GetProcessListRequest
.nProcessIdsCopied
= nCopied
;
3204 Request
->Data
.GetProcessListRequest
.nProcessIdsTotal
= nItems
;
3206 return Request
->Status
= STATUS_SUCCESS
;