2 * reactos/subsys/csrss/win32csr/conio.c
4 * Console I/O functions
6 * ReactOS Operating System
9 /* INCLUDES ******************************************************************/
12 #define NTOS_MODE_USER
13 #include <ndk/ntndk.h>
14 #include <ddk/ntddblue.h>
15 #include <rosrtl/string.h>
21 #include "desktopbg.h"
22 #include "guiconsole.h"
23 #include "tuiconsole.h"
29 /* FIXME: Is there a way to create real aliasses with gcc? [CSH] */
30 #define ALIAS(Name, Target) typeof(Target) Name = Target
32 /* Private user32 routines for CSRSS, not defined in any header file */
33 extern VOID STDCALL
PrivateCsrssRegisterPrimitive(VOID
);
34 extern VOID STDCALL
PrivateCsrssAcquireOrReleaseInputOwnership(BOOL Release
);
36 /* GLOBALS *******************************************************************/
38 #define ConioInitRect(Rect, Top, Left, Bottom, Right) \
39 ((Rect)->top) = Top; \
40 ((Rect)->left) = Left; \
41 ((Rect)->bottom) = Bottom; \
42 ((Rect)->right) = Right
44 #define ConioIsRectEmpty(Rect) \
45 (((Rect)->left > (Rect)->right) || ((Rect)->top > (Rect)->bottom))
47 #define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
48 WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
50 #define ConsoleAnsiCharToUnicodeChar(Console, sWChar, dChar) \
51 MultiByteToWideChar((Console)->CodePage, 0, (dChar), 1, (sWChar), 1)
53 #define ConsoleUnicodeToAnsiN(Console, dChar, sWChar, nChars) \
54 WideCharToMultiByte((Console)->CodePage, 0, (sWChar), (nChars), (dChar), (nChars) * sizeof(WCHAR), NULL, NULL)
56 /* FUNCTIONS *****************************************************************/
58 STATIC NTSTATUS FASTCALL
59 ConioConsoleFromProcessData(PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_CONSOLE
*Console
)
61 if (NULL
== ProcessData
->Console
)
64 return STATUS_SUCCESS
;
67 EnterCriticalSection(&(ProcessData
->Console
->Header
.Lock
));
68 *Console
= ProcessData
->Console
;
70 return STATUS_SUCCESS
;
74 ConioConsoleCtrlEvent(DWORD Event
, PCSRSS_PROCESS_DATA ProcessData
)
78 DPRINT("ConioConsoleCtrlEvent Parent ProcessId = %x\n", ProcessData
->ProcessId
);
80 if (ProcessData
->CtrlDispatcher
)
83 Thread
= CreateRemoteThread(ProcessData
->Process
, NULL
, 0,
84 (LPTHREAD_START_ROUTINE
) ProcessData
->CtrlDispatcher
,
85 (PVOID
) Event
, 0, NULL
);
88 DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
95 #define GET_CELL_BUFFER(b,o)\
98 #define SET_CELL_BUFFER(b,o,c,a)\
99 (b)->Buffer[(o)++]=(c),\
100 (b)->Buffer[(o)++]=(a)
103 ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff
)
105 DWORD Offset
= 2 * (Buff
->CurrentY
* Buff
->MaxX
);
108 for (Pos
= 0; Pos
< Buff
->MaxX
; Pos
++)
110 /* Fill the cell: Offset is incremented by the macro */
111 SET_CELL_BUFFER(Buff
, Offset
, ' ', Buff
->DefaultAttrib
);
115 STATIC NTSTATUS FASTCALL
116 CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console
,
117 PCSRSS_SCREEN_BUFFER Buffer
)
119 Buffer
->Header
.Type
= CONIO_SCREEN_BUFFER_MAGIC
;
120 Buffer
->Header
.ReferenceCount
= 0;
121 Buffer
->MaxX
= Console
->Size
.X
;
122 Buffer
->MaxY
= Console
->Size
.Y
;
125 Buffer
->Buffer
= HeapAlloc(Win32CsrApiHeap
, 0, Buffer
->MaxX
* Buffer
->MaxY
* 2);
126 if (NULL
== Buffer
->Buffer
)
128 return STATUS_INSUFFICIENT_RESOURCES
;
130 InitializeCriticalSection(&Buffer
->Header
.Lock
);
131 ConioInitScreenBuffer(Console
, Buffer
);
132 /* initialize buffer to be empty with default attributes */
133 for (Buffer
->CurrentY
= 0 ; Buffer
->CurrentY
< Buffer
->MaxY
; Buffer
->CurrentY
++)
135 ClearLineBuffer(Buffer
);
137 Buffer
->CursorInfo
.bVisible
= TRUE
;
138 Buffer
->CursorInfo
.dwSize
= 5;
139 Buffer
->Mode
= ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
;
140 Buffer
->CurrentX
= 0;
141 Buffer
->CurrentY
= 0;
143 return STATUS_SUCCESS
;
146 STATIC NTSTATUS STDCALL
147 CsrInitConsole(PCSRSS_CONSOLE Console
)
150 SECURITY_ATTRIBUTES SecurityAttributes
;
151 PCSRSS_SCREEN_BUFFER NewBuffer
;
154 Console
->Title
.MaximumLength
= Console
->Title
.Length
= 0;
155 Console
->Title
.Buffer
= NULL
;
157 RtlCreateUnicodeString(&Console
->Title
, L
"Command Prompt");
159 Console
->Header
.ReferenceCount
= 0;
160 Console
->WaitingChars
= 0;
161 Console
->WaitingLines
= 0;
162 Console
->EchoCount
= 0;
163 Console
->Header
.Type
= CONIO_CONSOLE_MAGIC
;
164 Console
->Mode
= ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_PROCESSED_INPUT
| ENABLE_MOUSE_INPUT
;
165 Console
->EarlyReturn
= FALSE
;
166 Console
->ActiveBuffer
= NULL
;
167 InitializeListHead(&Console
->InputEvents
);
168 InitializeListHead(&Console
->ProcessList
);
170 Console
->CodePage
= GetOEMCP();
171 Console
->OutputCodePage
= GetOEMCP();
173 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
174 SecurityAttributes
.lpSecurityDescriptor
= NULL
;
175 SecurityAttributes
.bInheritHandle
= TRUE
;
177 Console
->ActiveEvent
= CreateEventW(&SecurityAttributes
, TRUE
, FALSE
, NULL
);
178 if (NULL
== Console
->ActiveEvent
)
180 RtlFreeUnicodeString(&Console
->Title
);
181 return STATUS_UNSUCCESSFUL
;
183 Console
->PrivateData
= NULL
;
184 InitializeCriticalSection(&Console
->Header
.Lock
);
185 GuiMode
= DtbgIsDesktopVisible();
188 Status
= TuiInitConsole(Console
);
189 if (! NT_SUCCESS(Status
))
191 DPRINT1("Failed to open text-mode console, switching to gui-mode\n");
197 Status
= GuiInitConsole(Console
);
198 if (! NT_SUCCESS(Status
))
200 RtlFreeUnicodeString(&Console
->Title
);
201 DeleteCriticalSection(&Console
->Header
.Lock
);
202 CloseHandle(Console
->ActiveEvent
);
207 NewBuffer
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(CSRSS_SCREEN_BUFFER
));
208 if (NULL
== NewBuffer
)
210 ConioCleanupConsole(Console
);
211 RtlFreeUnicodeString(&Console
->Title
);
212 DeleteCriticalSection(&Console
->Header
.Lock
);
213 CloseHandle(Console
->ActiveEvent
);
214 return STATUS_INSUFFICIENT_RESOURCES
;
216 Status
= CsrInitConsoleScreenBuffer(Console
, NewBuffer
);
217 if (! NT_SUCCESS(Status
))
219 ConioCleanupConsole(Console
);
220 RtlFreeUnicodeString(&Console
->Title
);
221 DeleteCriticalSection(&Console
->Header
.Lock
);
222 CloseHandle(Console
->ActiveEvent
);
223 HeapFree(Win32CsrApiHeap
, 0, NewBuffer
);
226 Console
->ActiveBuffer
= NewBuffer
;
227 /* add a reference count because the buffer is tied to the console */
228 Console
->ActiveBuffer
->Header
.ReferenceCount
++;
229 /* make console active, and insert into console list */
230 /* copy buffer contents to screen */
231 ConioDrawConsole(Console
);
233 return STATUS_SUCCESS
;
237 CSR_API(CsrAllocConsole
)
239 PCSRSS_CONSOLE Console
;
242 DPRINT("CsrAllocConsole\n");
244 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
245 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
247 if (ProcessData
== NULL
)
249 return Request
->Status
= STATUS_INVALID_PARAMETER
;
252 if (ProcessData
->Console
)
254 Request
->Status
= STATUS_INVALID_PARAMETER
;
255 return STATUS_INVALID_PARAMETER
;
258 Request
->Status
= STATUS_SUCCESS
;
259 Console
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(CSRSS_CONSOLE
));
262 Request
->Status
= STATUS_NO_MEMORY
;
263 return STATUS_NO_MEMORY
;
265 Request
->Status
= CsrInitConsole(Console
);
266 if (! NT_SUCCESS(Request
->Status
))
268 HeapFree(Win32CsrApiHeap
, 0, Console
);
269 return Request
->Status
;
271 ProcessData
->Console
= Console
;
272 Request
->Data
.AllocConsoleRequest
.Console
= Console
;
274 /* add a reference count because the process is tied to the console */
275 Console
->Header
.ReferenceCount
++;
276 Status
= Win32CsrInsertObject(ProcessData
, &Request
->Data
.AllocConsoleRequest
.InputHandle
, &Console
->Header
);
277 if (! NT_SUCCESS(Status
))
279 ConioDeleteConsole((Object_t
*) Console
);
280 ProcessData
->Console
= 0;
281 return Request
->Status
= Status
;
283 Status
= Win32CsrInsertObject(ProcessData
, &Request
->Data
.AllocConsoleRequest
.OutputHandle
, &Console
->ActiveBuffer
->Header
);
284 if (!NT_SUCCESS(Status
))
286 Console
->Header
.ReferenceCount
--;
287 Win32CsrReleaseObject(ProcessData
, Request
->Data
.AllocConsoleRequest
.InputHandle
);
288 ProcessData
->Console
= 0;
289 return Request
->Status
= Status
;
292 if (! DuplicateHandle(GetCurrentProcess(), ProcessData
->Console
->ActiveEvent
,
293 ProcessData
->Process
, &ProcessData
->ConsoleEvent
, EVENT_ALL_ACCESS
, FALSE
, 0))
295 DPRINT1("DuplicateHandle() failed: %d\n", GetLastError
);
296 Console
->Header
.ReferenceCount
--;
297 Win32CsrReleaseObject(ProcessData
, Request
->Data
.AllocConsoleRequest
.OutputHandle
);
298 Win32CsrReleaseObject(ProcessData
, Request
->Data
.AllocConsoleRequest
.InputHandle
);
299 ProcessData
->Console
= 0;
300 Request
->Status
= Status
;
303 ProcessData
->CtrlDispatcher
= Request
->Data
.AllocConsoleRequest
.CtrlDispatcher
;
304 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
305 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ProcessEntry
);
307 return STATUS_SUCCESS
;
310 CSR_API(CsrFreeConsole
)
312 PCSRSS_CONSOLE Console
;
314 DPRINT("CsrFreeConsole\n");
316 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
317 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
319 if (ProcessData
== NULL
|| ProcessData
->Console
== NULL
)
321 return Request
->Status
= STATUS_INVALID_PARAMETER
;
324 Console
= ProcessData
->Console
;
325 Console
->Header
.ReferenceCount
--;
326 ProcessData
->Console
= NULL
;
327 if (0 == Console
->Header
.ReferenceCount
)
329 ConioDeleteConsole((Object_t
*) Console
);
332 return STATUS_SUCCESS
;
336 ConioNextLine(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, UINT
*ScrolledLines
)
338 /* slide the viewable screen */
339 if (((Buff
->CurrentY
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
) == Buff
->MaxY
- 1)
341 if (++Buff
->ShowY
== Buff
->MaxY
)
347 if (++Buff
->CurrentY
== Buff
->MaxY
)
351 ClearLineBuffer(Buff
);
352 UpdateRect
->left
= 0;
353 UpdateRect
->right
= Buff
->MaxX
- 1;
354 if (UpdateRect
->top
== Buff
->CurrentY
)
356 if (++UpdateRect
->top
== Buff
->MaxY
)
361 UpdateRect
->bottom
= Buff
->CurrentY
;
364 STATIC NTSTATUS FASTCALL
365 ConioWriteConsole(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
,
366 CHAR
*Buffer
, DWORD Length
, BOOL Attrib
)
371 LONG CursorStartX
, CursorStartY
;
374 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &CursorStartX
, &CursorStartY
);
375 UpdateRect
.left
= Buff
->MaxX
;
376 UpdateRect
.top
= Buff
->CurrentY
;
377 UpdateRect
.right
= -1;
378 UpdateRect
.bottom
= Buff
->CurrentY
;
381 for (i
= 0; i
< Length
; i
++)
383 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
386 if (Buffer
[i
] == '\n')
389 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
393 else if (Buffer
[i
] == '\b')
395 /* Only handle BS if we're not on the first pos of the first line */
396 if (0 != Buff
->CurrentX
|| Buff
->ShowY
!= Buff
->CurrentY
)
398 if (0 == Buff
->CurrentX
)
400 /* slide virtual position up */
401 Buff
->CurrentX
= Buff
->MaxX
- 1;
402 if (0 == Buff
->CurrentY
)
404 Buff
->CurrentY
= Buff
->MaxY
;
410 if ((0 == UpdateRect
.top
&& UpdateRect
.bottom
< Buff
->CurrentY
)
411 || (0 != UpdateRect
.top
&& Buff
->CurrentY
< UpdateRect
.top
))
413 UpdateRect
.top
= Buff
->CurrentY
;
420 Offset
= 2 * ((Buff
->CurrentY
* Buff
->MaxX
) + Buff
->CurrentX
);
421 SET_CELL_BUFFER(Buff
, Offset
, ' ', Buff
->DefaultAttrib
);
422 UpdateRect
.left
= min(UpdateRect
.left
, Buff
->CurrentX
);
423 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
428 else if (Buffer
[i
] == '\r')
431 UpdateRect
.left
= min(UpdateRect
.left
, Buff
->CurrentX
);
432 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
436 else if (Buffer
[i
] == '\t')
440 UpdateRect
.left
= min(UpdateRect
.left
, Buff
->CurrentX
);
441 EndX
= (Buff
->CurrentX
+ 8) & ~7;
442 if (EndX
> Buff
->MaxX
)
446 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
447 while (Buff
->CurrentX
< EndX
)
449 Buff
->Buffer
[Offset
] = ' ';
453 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
- 1);
454 if (Buff
->CurrentX
== Buff
->MaxX
)
456 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
459 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
469 UpdateRect
.left
= min(UpdateRect
.left
, Buff
->CurrentX
);
470 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
471 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
472 Buff
->Buffer
[Offset
++] = Buffer
[i
];
475 Buff
->Buffer
[Offset
] = Buff
->DefaultAttrib
;
478 if (Buff
->CurrentX
== Buff
->MaxX
)
480 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
483 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
487 Buff
->CurrentX
= CursorStartX
;
492 ConioPhysicalToLogical(Buff
, UpdateRect
.left
, UpdateRect
.top
, &(UpdateRect
.left
),
494 ConioPhysicalToLogical(Buff
, UpdateRect
.right
, UpdateRect
.bottom
, &(UpdateRect
.right
),
495 &(UpdateRect
.bottom
));
496 if (! ConioIsRectEmpty(&UpdateRect
) && NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
498 ConioWriteStream(Console
, &UpdateRect
, CursorStartX
, CursorStartY
, ScrolledLines
,
502 return STATUS_SUCCESS
;
505 CSR_API(CsrReadConsole
)
507 PLIST_ENTRY CurrentEntry
;
510 PWCHAR UnicodeBuffer
;
512 ULONG nNumberOfCharsToRead
, CharSize
;
513 PCSRSS_CONSOLE Console
;
516 DPRINT("CsrReadConsole\n");
518 CharSize
= (Request
->Data
.ReadConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
520 /* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */
521 nNumberOfCharsToRead
= min(Request
->Data
.ReadConsoleRequest
.NrCharactersToRead
, CSRSS_MAX_READ_CONSOLE
/ CharSize
);
522 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
523 Request
->Header
.DataSize
= Request
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
525 Buffer
= Request
->Data
.ReadConsoleRequest
.Buffer
;
526 UnicodeBuffer
= (PWCHAR
)Buffer
;
527 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadConsoleRequest
.ConsoleHandle
,
529 if (! NT_SUCCESS(Status
))
531 return Request
->Status
= Status
;
533 Request
->Data
.ReadConsoleRequest
.EventHandle
= ProcessData
->ConsoleEvent
;
534 for (i
= 0; i
< nNumberOfCharsToRead
&& Console
->InputEvents
.Flink
!= &Console
->InputEvents
; i
++)
536 /* remove input event from queue */
537 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
538 if (IsListEmpty(&Console
->InputEvents
))
541 ResetEvent(Console
->ActiveEvent
);
543 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
545 /* only pay attention to valid ascii chars, on key down */
546 if (KEY_EVENT
== Input
->InputEvent
.EventType
547 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
548 && Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
!= '\0')
550 /* backspace handling */
551 if ('\b' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
553 /* echo if it has not already been done, and either we or the client has chars to be deleted */
555 && (0 != i
|| Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
))
557 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
558 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
562 i
-= 2; /* if we already have something to return, just back it up by 2 */
565 { /* otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer */
566 Console
->WaitingChars
--;
567 ConioUnlockConsole(Console
);
568 HeapFree(Win32CsrApiHeap
, 0, Input
);
569 Request
->Data
.ReadConsoleRequest
.NrCharactersRead
= 0;
570 Request
->Status
= STATUS_NOTIFY_CLEANUP
;
571 return STATUS_NOTIFY_CLEANUP
;
573 Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
--;
574 Input
->Echoed
= TRUE
; /* mark as echoed so we don't echo it below */
576 /* do not copy backspace to buffer */
579 if(Request
->Data
.ReadConsoleRequest
.Unicode
)
580 UnicodeBuffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
; /* FIXME */
582 Buffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
;
584 /* echo to screen if enabled and we did not already echo the char */
585 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
)
587 && '\r' != Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
589 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
590 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
597 Console
->WaitingChars
--;
598 HeapFree(Win32CsrApiHeap
, 0, Input
);
600 Request
->Data
.ReadConsoleRequest
.NrCharactersRead
= i
;
603 Request
->Status
= STATUS_PENDING
; /* we didn't read anything */
605 else if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
))
607 if (0 == Console
->WaitingLines
||
608 (Request
->Data
.ReadConsoleRequest
.Unicode
? (L
'\n' != UnicodeBuffer
[i
- 1]) : ('\n' != Buffer
[i
- 1])))
610 Request
->Status
= STATUS_PENDING
; /* line buffered, didn't get a complete line */
614 Console
->WaitingLines
--;
615 Request
->Status
= STATUS_SUCCESS
; /* line buffered, did get a complete line */
620 Request
->Status
= STATUS_SUCCESS
; /* not line buffered, did read something */
623 if (Request
->Status
== STATUS_PENDING
)
625 Console
->EchoCount
= nNumberOfCharsToRead
- i
;
629 Console
->EchoCount
= 0; /* if the client is no longer waiting on input, do not echo */
631 Request
->Header
.MessageSize
+= i
* CharSize
;
633 ConioUnlockConsole(Console
);
634 return Request
->Status
;
638 ConioPhysicalToLogical(PCSRSS_SCREEN_BUFFER Buff
,
644 *LogicalX
= PhysicalX
;
645 if (PhysicalY
< Buff
->ShowY
)
647 *LogicalY
= Buff
->MaxY
- Buff
->ShowY
+ PhysicalY
;
651 *LogicalY
= PhysicalY
- Buff
->ShowY
;
655 inline BOOLEAN
ConioIsEqualRect(
659 return ((Rect1
->left
== Rect2
->left
) && (Rect1
->right
== Rect2
->right
) &&
660 (Rect1
->top
== Rect2
->top
) && (Rect1
->bottom
== Rect2
->bottom
));
663 inline BOOLEAN
ConioGetIntersection(
668 if (ConioIsRectEmpty(Rect1
) ||
669 (ConioIsRectEmpty(Rect2
)) ||
670 (Rect1
->top
> Rect2
->bottom
) ||
671 (Rect1
->left
> Rect2
->right
) ||
672 (Rect1
->bottom
< Rect2
->top
) ||
673 (Rect1
->right
< Rect2
->left
))
675 /* The rectangles do not intersect */
676 ConioInitRect(Intersection
, 0, -1, 0, -1);
680 ConioInitRect(Intersection
,
681 max(Rect1
->top
, Rect2
->top
),
682 max(Rect1
->left
, Rect2
->left
),
683 min(Rect1
->bottom
, Rect2
->bottom
),
684 min(Rect1
->right
, Rect2
->right
));
689 inline BOOLEAN
ConioGetUnion(
694 if (ConioIsRectEmpty(Rect1
))
696 if (ConioIsRectEmpty(Rect2
))
698 ConioInitRect(Union
, 0, -1, 0, -1);
706 else if (ConioIsRectEmpty(Rect2
))
713 min(Rect1
->top
, Rect2
->top
),
714 min(Rect1
->left
, Rect2
->left
),
715 max(Rect1
->bottom
, Rect2
->bottom
),
716 max(Rect1
->right
, Rect2
->right
));
722 inline BOOLEAN
ConioSubtractRect(
729 if (ConioIsRectEmpty(Rect1
))
731 ConioInitRect(Subtraction
, 0, -1, 0, -1);
734 *Subtraction
= *Rect1
;
735 if (ConioGetIntersection(&tmp
, Rect1
, Rect2
))
737 if (ConioIsEqualRect(&tmp
, Subtraction
))
739 ConioInitRect(Subtraction
, 0, -1, 0, -1);
742 if ((tmp
.top
== Subtraction
->top
) && (tmp
.bottom
== Subtraction
->bottom
))
744 if (tmp
.left
== Subtraction
->left
)
746 Subtraction
->left
= tmp
.right
;
748 else if (tmp
.right
== Subtraction
->right
)
750 Subtraction
->right
= tmp
.left
;
753 else if ((tmp
.left
== Subtraction
->left
) && (tmp
.right
== Subtraction
->right
))
755 if (tmp
.top
== Subtraction
->top
)
757 Subtraction
->top
= tmp
.bottom
;
759 else if (tmp
.bottom
== Subtraction
->bottom
)
761 Subtraction
->bottom
= tmp
.top
;
770 ConioCopyRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer
,
780 DstY
= DstRegion
->top
;
781 BytesPerLine
= ConioRectWidth(DstRegion
) * 2;
783 SrcY
= (SrcRegion
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
784 DstY
= (DstRegion
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
785 SrcOffset
= (SrcY
* ScreenBuffer
->MaxX
+ SrcRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
786 DstOffset
= (DstY
* ScreenBuffer
->MaxX
+ DstRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
788 for (i
= SrcRegion
->top
; i
<= SrcRegion
->bottom
; i
++)
791 &ScreenBuffer
->Buffer
[DstOffset
],
792 &ScreenBuffer
->Buffer
[SrcOffset
],
795 if (++DstY
== ScreenBuffer
->MaxY
)
798 DstOffset
= (DstRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
802 DstOffset
+= ScreenBuffer
->MaxX
* 2;
805 if (++SrcY
== ScreenBuffer
->MaxY
)
808 SrcOffset
= (SrcRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
812 SrcOffset
+= ScreenBuffer
->MaxX
* 2;
818 ConioFillRegion(PCSRSS_CONSOLE Console
,
819 PCSRSS_SCREEN_BUFFER ScreenBuffer
,
831 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &CharInfo
->Char
.UnicodeChar
);
833 Char
= CharInfo
->Char
.AsciiChar
;
835 Y
= (Region
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
836 Offset
= (Y
* ScreenBuffer
->MaxX
+ Region
->left
+ ScreenBuffer
->ShowX
) * 2;
837 Delta
= (ScreenBuffer
->MaxX
- ConioRectWidth(Region
)) * 2;
839 for (i
= Region
->top
; i
<= Region
->bottom
; i
++)
841 for (X
= Region
->left
; X
<= Region
->right
; X
++)
843 SET_CELL_BUFFER(ScreenBuffer
, Offset
, Char
, CharInfo
->Attributes
);
845 if (++Y
== ScreenBuffer
->MaxY
)
848 Offset
= (Region
->left
+ ScreenBuffer
->ShowX
) * 2;
858 ConioInputEventToAnsi(PCSRSS_CONSOLE Console
, PINPUT_RECORD InputEvent
)
860 if (InputEvent
->EventType
== KEY_EVENT
)
862 ConsoleUnicodeCharToAnsiChar(Console
,
863 &InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
,
864 &InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
);
868 CSR_API(CsrWriteConsole
)
871 PCHAR Buffer
= (PCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
;
872 PCSRSS_SCREEN_BUFFER Buff
;
873 PCSRSS_CONSOLE Console
;
874 ULONG CharSize
= (Request
->Data
.WriteConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
876 DPRINT("CsrWriteConsole\n");
878 if (Request
->Header
.DataSize
879 < sizeof(CSRSS_WRITE_CONSOLE
) - 1
880 + (Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
* CharSize
))
882 DPRINT1("Invalid request size\n");
883 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
884 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
885 return Request
->Status
= STATUS_INVALID_PARAMETER
;
887 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
889 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
890 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
892 if (! NT_SUCCESS(Status
))
894 return Request
->Status
= Status
;
897 if(Request
->Data
.WriteConsoleRequest
.Unicode
)
899 ConsoleUnicodeToAnsiN(Console
, Buffer
, (PWCHAR
)Buffer
, Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
);
902 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.WriteConsoleRequest
.ConsoleHandle
, &Buff
);
903 if (! NT_SUCCESS(Status
))
907 ConioUnlockConsole(Console
);
909 return Request
->Status
= Status
;
912 Request
->Status
= ConioWriteConsole(Console
, Buff
, Buffer
,
913 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
, TRUE
);
914 ConioUnlockScreenBuffer(Buff
);
917 ConioUnlockConsole(Console
);
920 if(NT_SUCCESS(Request
->Status
))
922 Request
->Data
.WriteConsoleRequest
.NrCharactersWritten
= Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
;
926 Request
->Data
.WriteConsoleRequest
.NrCharactersWritten
= 0; /* FIXME - return the actual number of characters written! */
929 return Request
->Status
= STATUS_SUCCESS
;
933 ConioDeleteScreenBuffer(Object_t
*Object
)
935 PCSRSS_SCREEN_BUFFER Buffer
= (PCSRSS_SCREEN_BUFFER
) Object
;
936 DeleteCriticalSection(&Buffer
->Header
.Lock
);
937 HeapFree(Win32CsrApiHeap
, 0, Buffer
->Buffer
);
938 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
942 ConioDrawConsole(PCSRSS_CONSOLE Console
)
946 ConioInitRect(&Region
, 0, 0, Console
->Size
.Y
- 1, Console
->Size
.X
- 1);
948 ConioDrawRegion(Console
, &Region
);
953 ConioDeleteConsole(Object_t
*Object
)
955 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Object
;
958 DPRINT("ConioDeleteConsole\n");
960 /* Drain input event queue */
961 while (Console
->InputEvents
.Flink
!= &Console
->InputEvents
)
963 Event
= (ConsoleInput
*) Console
->InputEvents
.Flink
;
964 Console
->InputEvents
.Flink
= Console
->InputEvents
.Flink
->Flink
;
965 Console
->InputEvents
.Flink
->Flink
->Blink
= &Console
->InputEvents
;
966 HeapFree(Win32CsrApiHeap
, 0, Event
);
969 if (0 == --Console
->ActiveBuffer
->Header
.ReferenceCount
)
971 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
974 Console
->ActiveBuffer
= NULL
;
975 ConioCleanupConsole(Console
);
977 CloseHandle(Console
->ActiveEvent
);
978 DeleteCriticalSection(&Console
->Header
.Lock
);
979 RtlFreeUnicodeString(&Console
->Title
);
980 HeapFree(Win32CsrApiHeap
, 0, Console
);
984 CsrInitConsoleSupport(VOID
)
986 DPRINT("CSR: CsrInitConsoleSupport()\n");
988 /* Should call LoadKeyboardLayout */
992 ConioProcessChar(PCSRSS_CONSOLE Console
,
993 ConsoleInput
*KeyEventRecord
)
996 BOOL bClientWake
= FALSE
;
997 ConsoleInput
*TempInput
;
999 /* process Ctrl-C and Ctrl-Break */
1000 if (Console
->Mode
& ENABLE_PROCESSED_INPUT
&&
1001 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
&&
1002 ((KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== VK_PAUSE
) ||
1003 (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== 'C')) &&
1004 (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
)))
1006 PCSRSS_PROCESS_DATA current
;
1007 PLIST_ENTRY current_entry
;
1008 DPRINT1("Console_Api Ctrl-C\n");
1009 current_entry
= Console
->ProcessList
.Flink
;
1010 while (current_entry
!= &Console
->ProcessList
)
1012 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
1013 current_entry
= current_entry
->Flink
;
1014 ConioConsoleCtrlEvent((DWORD
)CTRL_C_EVENT
, current
);
1016 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1020 if (0 != (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
1021 & (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1022 && (VK_UP
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
1023 || VK_DOWN
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
))
1025 if (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1027 /* scroll up or down */
1028 if (NULL
== Console
)
1030 DPRINT1("No Active Console!\n");
1031 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1034 if (VK_UP
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
)
1036 /* only scroll up if there is room to scroll up into */
1037 if (Console
->ActiveBuffer
->ShowY
!= ((Console
->ActiveBuffer
->CurrentY
+ 1) %
1038 Console
->ActiveBuffer
->MaxY
))
1040 Console
->ActiveBuffer
->ShowY
= (Console
->ActiveBuffer
->ShowY
+
1041 Console
->ActiveBuffer
->MaxY
- 1) %
1042 Console
->ActiveBuffer
->MaxY
;
1045 else if (Console
->ActiveBuffer
->ShowY
!= Console
->ActiveBuffer
->CurrentY
)
1046 /* only scroll down if there is room to scroll down into */
1048 if (Console
->ActiveBuffer
->ShowY
% Console
->ActiveBuffer
->MaxY
!=
1049 Console
->ActiveBuffer
->CurrentY
)
1051 if (((Console
->ActiveBuffer
->CurrentY
+ 1) % Console
->ActiveBuffer
->MaxY
) !=
1052 (Console
->ActiveBuffer
->ShowY
+ Console
->ActiveBuffer
->MaxY
) %
1053 Console
->ActiveBuffer
->MaxY
)
1055 Console
->ActiveBuffer
->ShowY
= (Console
->ActiveBuffer
->ShowY
+ 1) %
1056 Console
->ActiveBuffer
->MaxY
;
1060 ConioDrawConsole(Console
);
1062 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1065 if (NULL
== Console
)
1067 DPRINT1("No Active Console!\n");
1068 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1072 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
)))
1074 switch(KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1077 /* first add the \r */
1078 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1079 updown
= KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
;
1080 KeyEventRecord
->Echoed
= FALSE
;
1081 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= VK_RETURN
;
1082 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\r';
1083 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1084 Console
->WaitingChars
++;
1085 KeyEventRecord
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1086 if (NULL
== KeyEventRecord
)
1088 DPRINT1("Failed to allocate KeyEventRecord\n");
1091 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1092 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
= updown
;
1093 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= 0;
1094 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualScanCode
= 0;
1095 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\n';
1096 KeyEventRecord
->Fake
= TRUE
;
1100 /* add event to the queue */
1101 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1102 Console
->WaitingChars
++;
1103 /* if line input mode is enabled, only wake the client on enter key down */
1104 if (0 == (Console
->Mode
& ENABLE_LINE_INPUT
)
1105 || Console
->EarlyReturn
1106 || ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1107 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
))
1109 if ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1111 Console
->WaitingLines
++;
1114 SetEvent(Console
->ActiveEvent
);
1116 KeyEventRecord
->Echoed
= FALSE
;
1117 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
))
1118 && '\b' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1119 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1121 /* walk the input queue looking for a char to backspace */
1122 for (TempInput
= (ConsoleInput
*) Console
->InputEvents
.Blink
;
1123 TempInput
!= (ConsoleInput
*) &Console
->InputEvents
1124 && (KEY_EVENT
== TempInput
->InputEvent
.EventType
1125 || ! TempInput
->InputEvent
.Event
.KeyEvent
.bKeyDown
1126 || '\b' == TempInput
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
);
1127 TempInput
= (ConsoleInput
*) TempInput
->ListEntry
.Blink
)
1131 /* if we found one, delete it, otherwise, wake the client */
1132 if (TempInput
!= (ConsoleInput
*) &Console
->InputEvents
)
1134 /* delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue */
1135 RemoveEntryList(&TempInput
->ListEntry
);
1136 if (TempInput
->Echoed
)
1138 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1139 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1142 HeapFree(Win32CsrApiHeap
, 0, TempInput
);
1143 RemoveEntryList(&KeyEventRecord
->ListEntry
);
1144 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1145 Console
->WaitingChars
-= 2;
1149 SetEvent(Console
->ActiveEvent
);
1154 /* echo chars if we are supposed to and client is waiting for some */
1155 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
) && Console
->EchoCount
1156 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1157 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
1158 && '\r' != KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1160 /* mark the char as already echoed */
1161 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1162 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1164 Console
->EchoCount
--;
1165 KeyEventRecord
->Echoed
= TRUE
;
1169 /* Console->WaitingChars++; */
1170 if (bClientWake
|| 0 == (Console
->Mode
& ENABLE_LINE_INPUT
))
1172 SetEvent(Console
->ActiveEvent
);
1176 STATIC DWORD FASTCALL
1177 ConioGetShiftState(PBYTE KeyState
)
1181 if (KeyState
[VK_CAPITAL
] & 1)
1182 ssOut
|= CAPSLOCK_ON
;
1184 if (KeyState
[VK_NUMLOCK
] & 1)
1185 ssOut
|= NUMLOCK_ON
;
1187 if (KeyState
[VK_SCROLL
] & 1)
1188 ssOut
|= SCROLLLOCK_ON
;
1190 if (KeyState
[VK_SHIFT
] & 0x80)
1191 ssOut
|= SHIFT_PRESSED
;
1193 if (KeyState
[VK_LCONTROL
] & 0x80)
1194 ssOut
|= LEFT_CTRL_PRESSED
;
1195 if (KeyState
[VK_RCONTROL
] & 0x80)
1196 ssOut
|= RIGHT_CTRL_PRESSED
;
1198 if (KeyState
[VK_LMENU
] & 0x80)
1199 ssOut
|= LEFT_ALT_PRESSED
;
1200 if (KeyState
[VK_RMENU
] & 0x80)
1201 ssOut
|= RIGHT_ALT_PRESSED
;
1207 ConioProcessKey(MSG
*msg
, PCSRSS_CONSOLE Console
, BOOL TextMode
)
1209 static BYTE KeyState
[256] = { 0 };
1210 /* MSDN mentions that you should use the last virtual key code received
1211 * when putting a virtual key identity to a WM_CHAR message since multiple
1212 * or translated keys may be involved. */
1213 static UINT LastVirtualKey
= 0;
1215 ConsoleInput
*ConInRec
;
1219 UINT VirtualKeyCode
;
1220 UINT VirtualScanCode
;
1223 ULONG ResultSize
= 0;
1226 VirtualScanCode
= (msg
->lParam
>> 16) & 0xff;
1227 Down
= msg
->message
== WM_KEYDOWN
|| msg
->message
== WM_CHAR
||
1228 msg
->message
== WM_SYSKEYDOWN
|| msg
->message
== WM_SYSCHAR
;
1230 GetKeyboardState(KeyState
);
1231 ShiftState
= ConioGetShiftState(KeyState
);
1233 if (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
)
1235 VirtualKeyCode
= LastVirtualKey
;
1236 UnicodeChar
= msg
->wParam
;
1243 VirtualKeyCode
= msg
->wParam
;
1244 RetChars
= ToUnicodeEx(VirtualKeyCode
,
1251 UnicodeChar
= (1 == RetChars
? Chars
[0] : 0);
1254 if (0 == ResultSize
)
1259 er
.EventType
= KEY_EVENT
;
1260 er
.Event
.KeyEvent
.bKeyDown
= Down
;
1261 er
.Event
.KeyEvent
.wRepeatCount
= RepeatCount
;
1262 er
.Event
.KeyEvent
.uChar
.UnicodeChar
= UnicodeChar
;
1263 er
.Event
.KeyEvent
.dwControlKeyState
= ShiftState
;
1264 er
.Event
.KeyEvent
.wVirtualKeyCode
= VirtualKeyCode
;
1265 er
.Event
.KeyEvent
.wVirtualScanCode
= VirtualScanCode
;
1269 if (0 != (ShiftState
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1270 && VK_TAB
== VirtualKeyCode
)
1274 TuiSwapConsole(ShiftState
& SHIFT_PRESSED
? -1 : 1);
1279 else if (VK_MENU
== VirtualKeyCode
&& ! Down
)
1281 if (TuiSwapConsole(0))
1288 if (NULL
== Console
)
1293 ConInRec
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1295 if (NULL
== ConInRec
)
1300 ConInRec
->InputEvent
= er
;
1301 ConInRec
->Fake
= UnicodeChar
&&
1302 (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
&&
1303 msg
->message
!= WM_KEYUP
&& msg
->message
!= WM_SYSKEYUP
);
1304 ConInRec
->NotChar
= (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
);
1305 ConInRec
->Echoed
= FALSE
;
1306 if (ConInRec
->NotChar
)
1307 LastVirtualKey
= msg
->wParam
;
1309 DPRINT ("csrss: %s %s %s %s %02x %02x '%c' %04x\n",
1310 Down
? "down" : "up ",
1311 (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
) ?
1313 ConInRec
->Fake
? "fake" : "real",
1314 ConInRec
->NotChar
? "notc" : "char",
1317 (AsciiChar
>= ' ') ? AsciiChar
: '.',
1320 if (! ConInRec
->Fake
|| ! ConInRec
->NotChar
)
1322 /* FIXME - convert to ascii */
1323 ConioProcessChar(Console
, ConInRec
);
1327 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1332 Console_Api (PVOID unused
)
1334 /* keep reading events from the keyboard and stuffing them into the current
1335 console's input queue */
1338 /* This call establishes our message queue */
1339 PeekMessageW(&msg
, 0, 0, 0, PM_NOREMOVE
);
1340 /* This call registers our message queue */
1341 PrivateCsrssRegisterPrimitive();
1342 /* This call turns on the input system in win32k */
1343 PrivateCsrssAcquireOrReleaseInputOwnership(FALSE
);
1347 GetMessageW(&msg
, 0, 0, 0);
1348 TranslateMessage(&msg
);
1350 if (msg
.message
== WM_CHAR
|| msg
.message
== WM_SYSCHAR
||
1351 msg
.message
== WM_KEYDOWN
|| msg
.message
== WM_KEYUP
||
1352 msg
.message
== WM_SYSKEYDOWN
|| msg
.message
== WM_SYSKEYUP
)
1354 ConioProcessKey(&msg
, TuiGetFocusConsole(), TRUE
);
1358 PrivateCsrssAcquireOrReleaseInputOwnership(TRUE
);
1362 CSR_API(CsrGetScreenBufferInfo
)
1365 PCSRSS_SCREEN_BUFFER Buff
;
1366 PCONSOLE_SCREEN_BUFFER_INFO pInfo
;
1368 DPRINT("CsrGetScreenBufferInfo\n");
1370 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1371 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1373 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ScreenBufferInfoRequest
.ConsoleHandle
, &Buff
);
1374 if (! NT_SUCCESS(Status
))
1376 return Request
->Status
= Status
;
1378 pInfo
= &Request
->Data
.ScreenBufferInfoRequest
.Info
;
1379 pInfo
->dwSize
.X
= Buff
->MaxX
;
1380 pInfo
->dwSize
.Y
= Buff
->MaxY
;
1381 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1382 pInfo
->dwCursorPosition
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1383 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
1384 pInfo
->srWindow
.Left
= 0;
1385 pInfo
->srWindow
.Right
= Buff
->MaxX
- 1;
1386 pInfo
->srWindow
.Top
= 0;
1387 pInfo
->srWindow
.Bottom
= Buff
->MaxY
- 1;
1388 pInfo
->dwMaximumWindowSize
.X
= Buff
->MaxX
;
1389 pInfo
->dwMaximumWindowSize
.Y
= Buff
->MaxY
;
1390 ConioUnlockScreenBuffer(Buff
);
1392 Request
->Status
= STATUS_SUCCESS
;
1394 return Request
->Status
;
1397 CSR_API(CsrSetCursor
)
1400 PCSRSS_CONSOLE Console
;
1401 PCSRSS_SCREEN_BUFFER Buff
;
1402 LONG OldCursorX
, OldCursorY
;
1403 LONG NewCursorX
, NewCursorY
;
1405 DPRINT("CsrSetCursor\n");
1407 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1408 if (! NT_SUCCESS(Status
))
1410 return Request
->Status
= Status
;
1413 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1414 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1416 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
);
1417 if (! NT_SUCCESS(Status
))
1419 if (NULL
!= Console
)
1421 ConioUnlockConsole(Console
);
1423 return Request
->Status
= Status
;
1426 NewCursorX
= Request
->Data
.SetCursorRequest
.Position
.X
;
1427 NewCursorY
= Request
->Data
.SetCursorRequest
.Position
.Y
;
1428 if (NewCursorX
< 0 || NewCursorX
>= Buff
->MaxX
||
1429 NewCursorY
< 0 || NewCursorY
>= Buff
->MaxY
)
1431 ConioUnlockScreenBuffer(Buff
);
1432 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1434 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &OldCursorX
, &OldCursorY
);
1435 Buff
->CurrentX
= NewCursorX
+ Buff
->ShowX
;
1436 Buff
->CurrentY
= (NewCursorY
+ Buff
->ShowY
) % Buff
->MaxY
;
1437 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1439 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
1441 ConioUnlockScreenBuffer(Buff
);
1442 return Request
->Status
= STATUS_UNSUCCESSFUL
;
1446 ConioUnlockScreenBuffer(Buff
);
1447 if (NULL
!= Console
)
1449 ConioUnlockConsole(Console
);
1452 return Request
->Status
= STATUS_SUCCESS
;
1455 STATIC FASTCALL VOID
1456 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, COORD
*Start
, UINT Length
)
1458 if (Buff
->MaxX
<= Start
->X
+ Length
)
1460 UpdateRect
->left
= 0;
1464 UpdateRect
->left
= Start
->X
;
1466 if (Buff
->MaxX
<= Start
->X
+ Length
)
1468 UpdateRect
->right
= Buff
->MaxX
- 1;
1472 UpdateRect
->right
= Start
->X
+ Length
- 1;
1474 UpdateRect
->top
= Start
->Y
;
1475 UpdateRect
->bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->MaxX
;
1476 if (Buff
->MaxY
<= UpdateRect
->bottom
)
1478 UpdateRect
->bottom
= Buff
->MaxY
- 1;
1482 CSR_API(CsrWriteConsoleOutputChar
)
1485 PCHAR String
= (PCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
;
1487 PCSRSS_CONSOLE Console
;
1488 PCSRSS_SCREEN_BUFFER Buff
;
1489 DWORD X
, Y
, Length
, CharSize
, Written
= 0;
1492 DPRINT("CsrWriteConsoleOutputChar\n");
1494 CharSize
= (Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
1496 if (Request
->Header
.DataSize
1497 < sizeof(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR
) - 1
1498 + (Request
->Data
.WriteConsoleOutputCharRequest
.Length
* CharSize
))
1500 DPRINT1("Invalid request size\n");
1501 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1502 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1503 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1506 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1507 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1508 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1509 if (! NT_SUCCESS(Status
))
1511 return Request
->Status
= Status
;
1514 if(Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
)
1516 ConsoleUnicodeToAnsiN(Console
, String
, (PWCHAR
)String
, Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
1519 Status
= ConioLockScreenBuffer(ProcessData
,
1520 Request
->Data
.WriteConsoleOutputCharRequest
.ConsoleHandle
,
1522 if (! NT_SUCCESS(Status
))
1524 if (NULL
!= Console
)
1526 ConioUnlockConsole(Console
);
1528 return Request
->Status
= Status
;
1531 X
= Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.X
+ Buff
->ShowX
;
1532 Y
= (Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1533 Length
= Request
->Data
.WriteConsoleOutputCharRequest
.Length
;
1534 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1537 *Buffer
= *String
++;
1540 if (++X
== Buff
->MaxX
)
1542 if (++Y
== Buff
->MaxY
)
1545 Buffer
= Buff
->Buffer
;
1551 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1553 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputCharRequest
.Coord
,
1554 Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
1555 ConioDrawRegion(Console
, &UpdateRect
);
1558 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.X
= X
- Buff
->ShowX
;
1559 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1561 ConioUnlockScreenBuffer(Buff
);
1562 if (NULL
!= Console
)
1564 ConioUnlockConsole(Console
);
1567 Request
->Data
.WriteConsoleOutputCharRequest
.NrCharactersWritten
= Written
;
1568 return Request
->Status
= STATUS_SUCCESS
;
1571 CSR_API(CsrFillOutputChar
)
1574 PCSRSS_CONSOLE Console
;
1575 PCSRSS_SCREEN_BUFFER Buff
;
1576 DWORD X
, Y
, Length
, Written
= 0;
1581 DPRINT("CsrFillOutputChar\n");
1583 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1584 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1586 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1587 if (! NT_SUCCESS(Status
))
1589 return Request
->Status
= Status
;
1592 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputRequest
.ConsoleHandle
, &Buff
);
1593 if (! NT_SUCCESS(Status
))
1595 if (NULL
!= Console
)
1597 ConioUnlockConsole(Console
);
1599 return Request
->Status
= Status
;
1602 X
= Request
->Data
.FillOutputRequest
.Position
.X
+ Buff
->ShowX
;
1603 Y
= (Request
->Data
.FillOutputRequest
.Position
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1604 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1605 if(Request
->Data
.FillOutputRequest
.Unicode
)
1606 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &Request
->Data
.FillOutputRequest
.Char
.UnicodeChar
);
1608 Char
= Request
->Data
.FillOutputRequest
.Char
.AsciiChar
;
1609 Length
= Request
->Data
.FillOutputRequest
.Length
;
1615 if (++X
== Buff
->MaxX
)
1617 if (++Y
== Buff
->MaxY
)
1620 Buffer
= Buff
->Buffer
;
1626 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1628 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputRequest
.Position
,
1629 Request
->Data
.FillOutputRequest
.Length
);
1630 ConioDrawRegion(Console
, &UpdateRect
);
1633 ConioUnlockScreenBuffer(Buff
);
1634 if (NULL
!= Console
)
1636 ConioUnlockConsole(Console
);
1639 return Request
->Status
;
1642 CSR_API(CsrReadInputEvent
)
1644 PLIST_ENTRY CurrentEntry
;
1645 PCSRSS_CONSOLE Console
;
1647 BOOLEAN Done
= FALSE
;
1648 ConsoleInput
*Input
;
1650 DPRINT("CsrReadInputEvent\n");
1652 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1653 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1654 Request
->Data
.ReadInputRequest
.Event
= ProcessData
->ConsoleEvent
;
1656 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadInputRequest
.ConsoleHandle
, &Console
);
1657 if (! NT_SUCCESS(Status
))
1659 return Request
->Status
= Status
;
1662 /* only get input if there is any */
1663 CurrentEntry
= Console
->InputEvents
.Flink
;
1664 while (CurrentEntry
!= &Console
->InputEvents
)
1666 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
1667 CurrentEntry
= CurrentEntry
->Flink
;
1669 if (Done
&& !Input
->Fake
)
1671 Request
->Data
.ReadInputRequest
.MoreEvents
= TRUE
;
1675 RemoveEntryList(&Input
->ListEntry
);
1677 if (!Done
&& !Input
->Fake
)
1679 Request
->Data
.ReadInputRequest
.Input
= Input
->InputEvent
;
1680 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
1682 ConioInputEventToAnsi(Console
, &Request
->Data
.ReadInputRequest
.Input
);
1687 if (Input
->InputEvent
.EventType
== KEY_EVENT
)
1689 if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
)
1690 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
1691 && '\r' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1693 Console
->WaitingLines
--;
1695 Console
->WaitingChars
--;
1697 HeapFree(Win32CsrApiHeap
, 0, Input
);
1702 Status
= STATUS_SUCCESS
;
1703 Console
->EarlyReturn
= FALSE
;
1707 Status
= STATUS_PENDING
;
1708 Console
->EarlyReturn
= TRUE
; /* mark for early return */
1711 if (IsListEmpty(&Console
->InputEvents
))
1713 ResetEvent(Console
->ActiveEvent
);
1716 ConioUnlockConsole(Console
);
1718 return Request
->Status
= Status
;
1721 CSR_API(CsrWriteConsoleOutputAttrib
)
1723 PCSRSS_CONSOLE Console
;
1724 PCSRSS_SCREEN_BUFFER Buff
;
1725 PUCHAR Buffer
, Attribute
;
1730 DPRINT("CsrWriteConsoleOutputAttrib\n");
1732 if (Request
->Header
.DataSize
1733 < sizeof(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB
) - 1
1734 + Request
->Data
.WriteConsoleOutputAttribRequest
.Length
)
1736 DPRINT1("Invalid request size\n");
1737 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1738 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1739 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1742 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1743 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1744 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1745 if (! NT_SUCCESS(Status
))
1747 return Request
->Status
= Status
;
1750 Status
= ConioLockScreenBuffer(ProcessData
,
1751 Request
->Data
.WriteConsoleOutputAttribRequest
.ConsoleHandle
,
1753 if (! NT_SUCCESS(Status
))
1755 if (NULL
!= Console
)
1757 ConioUnlockConsole(Console
);
1759 return Request
->Status
= Status
;
1762 X
= Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1763 Y
= (Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1764 Length
= Request
->Data
.WriteConsoleOutputAttribRequest
.Length
;
1765 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + 1];
1766 Attribute
= (PUCHAR
)Request
->Data
.WriteConsoleOutputAttribRequest
.String
;
1769 *Buffer
= *Attribute
++;
1771 if (++X
== Buff
->MaxX
)
1773 if (++Y
== Buff
->MaxY
)
1776 Buffer
= Buff
->Buffer
+ 1;
1782 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1784 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
,
1785 Request
->Data
.WriteConsoleOutputAttribRequest
.Length
);
1786 ConioDrawRegion(Console
, &UpdateRect
);
1789 if (NULL
!= Console
)
1791 ConioUnlockConsole(Console
);
1794 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1795 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1797 ConioUnlockScreenBuffer(Buff
);
1799 return Request
->Status
= STATUS_SUCCESS
;
1802 CSR_API(CsrFillOutputAttrib
)
1804 PCSRSS_SCREEN_BUFFER Buff
;
1810 PCSRSS_CONSOLE Console
;
1812 DPRINT("CsrFillOutputAttrib\n");
1814 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1815 if (! NT_SUCCESS(Status
))
1817 return Request
->Status
= Status
;
1820 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1821 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1822 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputAttribRequest
.ConsoleHandle
, &Buff
);
1823 if (! NT_SUCCESS(Status
))
1825 if (NULL
!= Console
)
1827 ConioUnlockConsole(Console
);
1829 return Request
->Status
= Status
;
1832 X
= Request
->Data
.FillOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1833 Y
= (Request
->Data
.FillOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1834 Length
= Request
->Data
.FillOutputAttribRequest
.Length
;
1835 Attr
= Request
->Data
.FillOutputAttribRequest
.Attribute
;
1836 Buffer
= &Buff
->Buffer
[(Y
* Buff
->MaxX
* 2) + (X
* 2) + 1];
1841 if (++X
== Buff
->MaxX
)
1843 if (++Y
== Buff
->MaxY
)
1846 Buffer
= Buff
->Buffer
+ 1;
1852 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1854 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputAttribRequest
.Coord
,
1855 Request
->Data
.FillOutputAttribRequest
.Length
);
1856 ConioDrawRegion(Console
, &UpdateRect
);
1859 ConioUnlockScreenBuffer(Buff
);
1860 if (NULL
!= Console
)
1862 ConioUnlockConsole(Console
);
1865 return Request
->Status
= STATUS_SUCCESS
;
1869 CSR_API(CsrGetCursorInfo
)
1871 PCSRSS_SCREEN_BUFFER Buff
;
1874 DPRINT("CsrGetCursorInfo\n");
1876 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1877 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1879 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.GetCursorInfoRequest
.ConsoleHandle
, &Buff
);
1880 if (! NT_SUCCESS(Status
))
1882 return Request
->Status
= Status
;
1884 Request
->Data
.GetCursorInfoRequest
.Info
= Buff
->CursorInfo
;
1885 ConioUnlockScreenBuffer(Buff
);
1887 return Request
->Status
= STATUS_SUCCESS
;
1890 CSR_API(CsrSetCursorInfo
)
1892 PCSRSS_CONSOLE Console
;
1893 PCSRSS_SCREEN_BUFFER Buff
;
1898 DPRINT("CsrSetCursorInfo\n");
1900 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1901 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1903 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1904 if (! NT_SUCCESS(Status
))
1906 return Request
->Status
= Status
;
1909 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorInfoRequest
.ConsoleHandle
, &Buff
);
1910 if (! NT_SUCCESS(Status
))
1912 if (NULL
!= Console
)
1914 ConioUnlockConsole(Console
);
1916 return Request
->Status
= Status
;
1919 Size
= Request
->Data
.SetCursorInfoRequest
.Info
.dwSize
;
1920 Visible
= Request
->Data
.SetCursorInfoRequest
.Info
.bVisible
;
1930 if (Size
!= Buff
->CursorInfo
.dwSize
1931 || (Visible
&& ! Buff
->CursorInfo
.bVisible
) || (! Visible
&& Buff
->CursorInfo
.bVisible
))
1933 Buff
->CursorInfo
.dwSize
= Size
;
1934 Buff
->CursorInfo
.bVisible
= Visible
;
1936 if (NULL
!= Console
&& ! ConioSetCursorInfo(Console
, Buff
))
1938 ConioUnlockScreenBuffer(Buff
);
1939 ConioUnlockConsole(Console
);
1940 return Request
->Status
= STATUS_UNSUCCESSFUL
;
1944 ConioUnlockScreenBuffer(Buff
);
1945 if (NULL
!= Console
)
1947 ConioUnlockConsole(Console
);
1950 return Request
->Status
= STATUS_SUCCESS
;
1953 CSR_API(CsrSetTextAttrib
)
1956 PCSRSS_CONSOLE Console
;
1957 PCSRSS_SCREEN_BUFFER Buff
;
1958 LONG OldCursorX
, OldCursorY
;
1960 DPRINT("CsrSetTextAttrib\n");
1962 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1963 if (! NT_SUCCESS(Status
))
1965 return Request
->Status
= Status
;
1968 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
);
1969 if (! NT_SUCCESS(Status
))
1971 if (NULL
!= Console
)
1973 ConioUnlockConsole(Console
);
1975 return Request
->Status
= Status
;
1978 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &OldCursorX
, &OldCursorY
);
1980 Buff
->DefaultAttrib
= Request
->Data
.SetAttribRequest
.Attrib
;
1981 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1983 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
1985 ConioUnlockScreenBuffer(Buff
);
1986 ConioUnlockConsole(Console
);
1987 return Request
->Status
= STATUS_UNSUCCESSFUL
;
1991 ConioUnlockScreenBuffer(Buff
);
1992 if (NULL
!= Console
)
1994 ConioUnlockConsole(Console
);
1997 return Request
->Status
= STATUS_SUCCESS
;
2000 CSR_API(CsrSetConsoleMode
)
2003 PCSRSS_CONSOLE Console
;
2004 PCSRSS_SCREEN_BUFFER Buff
;
2006 DPRINT("CsrSetConsoleMode\n");
2008 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2009 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2010 Status
= Win32CsrGetObject(ProcessData
,
2011 Request
->Data
.SetConsoleModeRequest
.ConsoleHandle
,
2012 (Object_t
**) &Console
);
2013 if (! NT_SUCCESS(Status
))
2015 return Request
->Status
= Status
;
2018 Buff
= (PCSRSS_SCREEN_BUFFER
)Console
;
2019 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
2021 Console
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_INPUT_MODE_VALID
;
2023 else if (CONIO_SCREEN_BUFFER_MAGIC
== Console
->Header
.Type
)
2025 Buff
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_OUTPUT_MODE_VALID
;
2029 return Request
->Status
= STATUS_INVALID_HANDLE
;
2032 Request
->Status
= STATUS_SUCCESS
;
2034 return Request
->Status
;
2037 CSR_API(CsrGetConsoleMode
)
2040 PCSRSS_CONSOLE Console
;
2041 PCSRSS_SCREEN_BUFFER Buff
; /* gee, I really wish I could use an anonymous union here */
2043 DPRINT("CsrGetConsoleMode\n");
2045 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2046 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2047 Status
= Win32CsrGetObject(ProcessData
, Request
->Data
.GetConsoleModeRequest
.ConsoleHandle
,
2048 (Object_t
**) &Console
);
2049 if (! NT_SUCCESS(Status
))
2051 return Request
->Status
= Status
;
2053 Request
->Status
= STATUS_SUCCESS
;
2054 Buff
= (PCSRSS_SCREEN_BUFFER
) Console
;
2055 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
2057 Request
->Data
.GetConsoleModeRequest
.ConsoleMode
= Console
->Mode
;
2059 else if (CONIO_SCREEN_BUFFER_MAGIC
== Buff
->Header
.Type
)
2061 Request
->Data
.GetConsoleModeRequest
.ConsoleMode
= Buff
->Mode
;
2065 Request
->Status
= STATUS_INVALID_HANDLE
;
2068 return Request
->Status
;
2071 CSR_API(CsrCreateScreenBuffer
)
2073 PCSRSS_CONSOLE Console
;
2074 PCSRSS_SCREEN_BUFFER Buff
;
2077 DPRINT("CsrCreateScreenBuffer\n");
2079 if (ProcessData
== NULL
)
2081 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2084 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2085 if (! NT_SUCCESS(Status
))
2087 return Request
->Status
= Status
;
2089 if (NULL
== Console
)
2091 return Request
->Status
= STATUS_INVALID_HANDLE
;
2094 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2095 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2097 Buff
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(CSRSS_SCREEN_BUFFER
));
2100 Request
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2103 Status
= CsrInitConsoleScreenBuffer(Console
, Buff
);
2104 if(! NT_SUCCESS(Status
))
2106 Request
->Status
= Status
;
2110 Request
->Status
= Win32CsrInsertObject(ProcessData
, &Request
->Data
.CreateScreenBufferRequest
.OutputHandle
, &Buff
->Header
);
2113 ConioUnlockConsole(Console
);
2115 return Request
->Status
;
2118 CSR_API(CsrSetScreenBuffer
)
2121 PCSRSS_CONSOLE Console
;
2122 PCSRSS_SCREEN_BUFFER Buff
;
2124 DPRINT("CsrSetScreenBuffer\n");
2126 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2127 if (! NT_SUCCESS(Status
))
2129 return Request
->Status
= Status
;
2131 if (NULL
== Console
)
2133 DPRINT1("Trying to set screen buffer for app without console\n");
2134 return Request
->Status
= STATUS_INVALID_HANDLE
;
2137 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2138 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2140 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetScreenBufferRequest
.OutputHandle
, &Buff
);
2141 if (! NT_SUCCESS(Status
))
2143 ConioUnlockConsole(Console
);
2144 return Request
->Status
;
2147 if (Buff
== Console
->ActiveBuffer
)
2149 ConioUnlockScreenBuffer(Buff
);
2150 ConioUnlockConsole(Console
);
2151 return STATUS_SUCCESS
;
2154 /* drop reference to old buffer, maybe delete */
2155 if (! InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
2157 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
2159 /* tie console to new buffer */
2160 Console
->ActiveBuffer
= Buff
;
2161 /* inc ref count on new buffer */
2162 InterlockedIncrement(&Buff
->Header
.ReferenceCount
);
2163 /* Redraw the console */
2164 ConioDrawConsole(Console
);
2166 ConioUnlockScreenBuffer(Buff
);
2167 ConioUnlockConsole(Console
);
2169 return Request
->Status
= STATUS_SUCCESS
;
2172 CSR_API(CsrSetTitle
)
2175 PCSRSS_CONSOLE Console
;
2177 DPRINT("CsrSetTitle\n");
2179 if (Request
->Header
.DataSize
2180 < sizeof(CSRSS_SET_TITLE
) - 1
2181 + Request
->Data
.SetTitleRequest
.Length
)
2183 DPRINT1("Invalid request size\n");
2184 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2185 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2186 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2189 Status
= ConioLockConsole(ProcessData
, Request
->Data
.SetTitleRequest
.Console
, &Console
);
2190 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2191 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2192 if(! NT_SUCCESS(Status
))
2194 Request
->Status
= Status
;
2198 /* copy title to console */
2199 RtlFreeUnicodeString(&Console
->Title
);
2200 RtlCreateUnicodeString(&Console
->Title
, Request
->Data
.SetTitleRequest
.Title
);
2201 if (! ConioChangeTitle(Console
))
2203 Request
->Status
= STATUS_UNSUCCESSFUL
;
2207 Request
->Status
= STATUS_SUCCESS
;
2210 ConioUnlockConsole(Console
);
2212 return Request
->Status
;
2215 CSR_API(CsrGetTitle
)
2218 PCSRSS_CONSOLE Console
;
2220 DPRINT("CsrGetTitle\n");
2222 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2223 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2224 Status
= ConioLockConsole(ProcessData
,
2225 Request
->Data
.GetTitleRequest
.ConsoleHandle
,
2227 if (! NT_SUCCESS(Status
))
2229 DPRINT1("Can't get console\n");
2230 return Request
->Status
= Status
;
2233 /* Copy title of the console to the user title buffer */
2234 RtlZeroMemory(&Request
->Data
.GetTitleRequest
, sizeof(CSRSS_GET_TITLE
));
2235 Request
->Data
.GetTitleRequest
.ConsoleHandle
= Request
->Data
.GetTitleRequest
.ConsoleHandle
;
2236 Request
->Data
.GetTitleRequest
.Length
= Console
->Title
.Length
;
2237 wcscpy (Request
->Data
.GetTitleRequest
.Title
, Console
->Title
.Buffer
);
2238 Request
->Header
.MessageSize
+= Console
->Title
.Length
;
2239 Request
->Header
.DataSize
+= Console
->Title
.Length
;
2240 Request
->Status
= STATUS_SUCCESS
;
2242 ConioUnlockConsole(Console
);
2244 return Request
->Status
;
2247 CSR_API(CsrWriteConsoleOutput
)
2249 SHORT i
, X
, Y
, SizeX
, SizeY
;
2250 PCSRSS_CONSOLE Console
;
2251 PCSRSS_SCREEN_BUFFER Buff
;
2253 CHAR_INFO
* CurCharInfo
;
2255 CHAR_INFO
* CharInfo
;
2262 DPRINT("CsrWriteConsoleOutput\n");
2264 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2265 if (! NT_SUCCESS(Status
))
2267 return Request
->Status
= Status
;
2270 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2271 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2272 Status
= ConioLockScreenBuffer(ProcessData
,
2273 Request
->Data
.WriteConsoleOutputRequest
.ConsoleHandle
,
2275 if (! NT_SUCCESS(Status
))
2277 if (NULL
!= Console
)
2279 ConioUnlockConsole(Console
);
2281 return Request
->Status
= Status
;
2284 BufferSize
= Request
->Data
.WriteConsoleOutputRequest
.BufferSize
;
2285 PSize
= BufferSize
.X
* BufferSize
.Y
* sizeof(CHAR_INFO
);
2286 BufferCoord
= Request
->Data
.WriteConsoleOutputRequest
.BufferCoord
;
2287 CharInfo
= Request
->Data
.WriteConsoleOutputRequest
.CharInfo
;
2288 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
) ||
2289 (((PVOID
)CharInfo
+ PSize
) >
2290 (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2292 ConioUnlockScreenBuffer(Buff
);
2293 ConioUnlockConsole(Console
);
2294 return Request
->Status
= STATUS_ACCESS_VIOLATION
;
2296 WriteRegion
.left
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
;
2297 WriteRegion
.top
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
;
2298 WriteRegion
.right
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
;
2299 WriteRegion
.bottom
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
;
2301 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&WriteRegion
));
2302 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&WriteRegion
));
2303 WriteRegion
.bottom
= WriteRegion
.top
+ SizeY
- 1;
2304 WriteRegion
.right
= WriteRegion
.left
+ SizeX
- 1;
2306 /* Make sure WriteRegion is inside the screen buffer */
2307 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2308 if (! ConioGetIntersection(&WriteRegion
, &ScreenBuffer
, &WriteRegion
))
2310 ConioUnlockScreenBuffer(Buff
);
2311 ConioUnlockConsole(Console
);
2313 /* It is okay to have a WriteRegion completely outside the screen buffer.
2314 No data is written then. */
2315 return Request
->Status
= STATUS_SUCCESS
;
2318 for (i
= 0, Y
= WriteRegion
.top
; Y
<= WriteRegion
.bottom
; i
++, Y
++)
2320 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
2321 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ WriteRegion
.left
) * 2;
2322 for (X
= WriteRegion
.left
; X
<= WriteRegion
.right
; X
++)
2324 if (Request
->Data
.WriteConsoleOutputRequest
.Unicode
)
2327 ConsoleUnicodeCharToAnsiChar(Console
, &AsciiChar
, &CurCharInfo
->Char
.UnicodeChar
);
2328 SET_CELL_BUFFER(Buff
, Offset
, AsciiChar
, CurCharInfo
->Attributes
);
2332 SET_CELL_BUFFER(Buff
, Offset
, CurCharInfo
->Char
.AsciiChar
, CurCharInfo
->Attributes
);
2338 if (NULL
!= Console
)
2340 ConioDrawRegion(Console
, &WriteRegion
);
2343 ConioUnlockScreenBuffer(Buff
);
2344 ConioUnlockConsole(Console
);
2346 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
= WriteRegion
.left
+ SizeX
- 1;
2347 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
= WriteRegion
.top
+ SizeY
- 1;
2348 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
= WriteRegion
.left
;
2349 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
= WriteRegion
.top
;
2351 return Request
->Status
= STATUS_SUCCESS
;
2354 CSR_API(CsrFlushInputBuffer
)
2356 PLIST_ENTRY CurrentEntry
;
2357 PCSRSS_CONSOLE Console
;
2358 ConsoleInput
* Input
;
2361 DPRINT("CsrFlushInputBuffer\n");
2363 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2364 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2365 Status
= ConioLockConsole(ProcessData
,
2366 Request
->Data
.FlushInputBufferRequest
.ConsoleInput
,
2368 if(! NT_SUCCESS(Status
))
2370 return Request
->Status
= Status
;
2373 /* Discard all entries in the input event queue */
2374 while (!IsListEmpty(&Console
->InputEvents
))
2376 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
2377 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
2378 /* Destroy the event */
2379 HeapFree(Win32CsrApiHeap
, 0, Input
);
2381 ResetEvent(Console
->ActiveEvent
);
2382 Console
->WaitingChars
=0;
2384 ConioUnlockConsole(Console
);
2386 return Request
->Status
= STATUS_SUCCESS
;
2389 CSR_API(CsrScrollConsoleScreenBuffer
)
2391 PCSRSS_CONSOLE Console
;
2392 PCSRSS_SCREEN_BUFFER Buff
;
2397 RECT ScrollRectangle
;
2402 DPRINT("CsrScrollConsoleScreenBuffer\n");
2404 ALIAS(ConsoleHandle
,Request
->Data
.ScrollConsoleScreenBufferRequest
.ConsoleHandle
);
2405 ALIAS(UseClipRectangle
,Request
->Data
.ScrollConsoleScreenBufferRequest
.UseClipRectangle
);
2406 ALIAS(DestinationOrigin
,Request
->Data
.ScrollConsoleScreenBufferRequest
.DestinationOrigin
);
2407 ALIAS(Fill
,Request
->Data
.ScrollConsoleScreenBufferRequest
.Fill
);
2409 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2410 if (! NT_SUCCESS(Status
))
2412 return Request
->Status
= Status
;
2415 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2416 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2417 Status
= ConioLockScreenBuffer(ProcessData
, ConsoleHandle
, &Buff
);
2418 if (! NT_SUCCESS(Status
))
2420 if (NULL
!= Console
)
2422 ConioUnlockConsole(Console
);
2424 return Request
->Status
= Status
;
2427 ScrollRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Left
;
2428 ScrollRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Top
;
2429 ScrollRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Right
;
2430 ScrollRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Bottom
;
2431 ClipRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Left
;
2432 ClipRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Top
;
2433 ClipRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Right
;
2434 ClipRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Bottom
;
2436 /* Make sure source rectangle is inside the screen buffer */
2437 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2438 if (! ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, &ScrollRectangle
))
2440 ConioUnlockScreenBuffer(Buff
);
2441 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2444 if (UseClipRectangle
&& ! ConioGetIntersection(&SrcRegion
, &SrcRegion
, &ClipRectangle
))
2446 ConioUnlockScreenBuffer(Buff
);
2447 return Request
->Status
= STATUS_SUCCESS
;
2451 ConioInitRect(&DstRegion
,
2452 DestinationOrigin
.Y
,
2453 DestinationOrigin
.X
,
2454 DestinationOrigin
.Y
+ ConioRectHeight(&ScrollRectangle
) - 1,
2455 DestinationOrigin
.X
+ ConioRectWidth(&ScrollRectangle
) - 1);
2457 /* Make sure destination rectangle is inside the screen buffer */
2458 if (! ConioGetIntersection(&DstRegion
, &DstRegion
, &ScreenBuffer
))
2460 ConioUnlockScreenBuffer(Buff
);
2461 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2464 ConioCopyRegion(Buff
, &SrcRegion
, &DstRegion
);
2466 /* Get the region that should be filled with the specified character and attributes */
2470 ConioGetUnion(&FillRegion
, &SrcRegion
, &DstRegion
);
2472 if (ConioSubtractRect(&FillRegion
, &FillRegion
, &DstRegion
))
2474 /* FIXME: The subtracted rectangle is off by one line */
2475 FillRegion
.top
+= 1;
2477 ConioFillRegion(Console
, Buff
, &FillRegion
, &Fill
, Request
->Data
.ScrollConsoleScreenBufferRequest
.Unicode
);
2481 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
2483 /* Draw destination region */
2484 ConioDrawRegion(Console
, &DstRegion
);
2488 /* Draw filled region */
2489 ConioDrawRegion(Console
, &FillRegion
);
2493 ConioUnlockScreenBuffer(Buff
);
2494 if (NULL
!= Console
)
2496 ConioUnlockConsole(Console
);
2499 return Request
->Status
= STATUS_SUCCESS
;
2502 CSR_API(CsrReadConsoleOutputChar
)
2505 PCSRSS_CONSOLE Console
;
2506 PCSRSS_SCREEN_BUFFER Buff
;
2513 DPRINT("CsrReadConsoleOutputChar\n");
2515 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2516 Request
->Header
.DataSize
= Request
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
2517 ReadBuffer
= Request
->Data
.ReadConsoleOutputCharRequest
.String
;
2519 CharSize
= (Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
2521 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2522 if (! NT_SUCCESS(Status
))
2524 return Request
->Status
= Status
;
2527 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputCharRequest
.ConsoleHandle
, &Buff
);
2528 if (! NT_SUCCESS(Status
))
2530 return Request
->Status
= Status
;
2533 Xpos
= Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.X
+ Buff
->ShowX
;
2534 Ypos
= (Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
2536 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
; ++i
)
2538 Char
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
)];
2540 if(Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
)
2542 ConsoleAnsiCharToUnicodeChar(Console
, (WCHAR
*)ReadBuffer
, &Char
);
2543 ReadBuffer
+= sizeof(WCHAR
);
2546 *(ReadBuffer
++) = Char
;
2550 if (Xpos
== Buff
->MaxX
)
2555 if (Ypos
== Buff
->MaxY
)
2563 Request
->Status
= STATUS_SUCCESS
;
2564 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.X
= Xpos
- Buff
->ShowX
;
2565 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.Y
= (Ypos
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
;
2566 Request
->Header
.MessageSize
+= Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
;
2567 Request
->Header
.DataSize
+= Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
;
2569 ConioUnlockScreenBuffer(Buff
);
2570 if (NULL
!= Console
)
2572 ConioUnlockConsole(Console
);
2575 Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
= (DWORD
)((ULONG_PTR
)ReadBuffer
- (ULONG_PTR
)Request
->Data
.ReadConsoleOutputCharRequest
.String
) / CharSize
;
2577 return Request
->Status
;
2581 CSR_API(CsrReadConsoleOutputAttrib
)
2584 PCSRSS_SCREEN_BUFFER Buff
;
2589 DPRINT("CsrReadConsoleOutputAttrib\n");
2591 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2592 Request
->Header
.DataSize
= Request
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
2593 ReadBuffer
= Request
->Data
.ReadConsoleOutputAttribRequest
.String
;
2595 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputAttribRequest
.ConsoleHandle
, &Buff
);
2596 if (! NT_SUCCESS(Status
))
2598 return Request
->Status
= Status
;
2601 Xpos
= Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.X
+ Buff
->ShowX
;
2602 Ypos
= (Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
2604 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
; ++i
)
2606 *ReadBuffer
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
) + 1];
2611 if (Xpos
== Buff
->MaxX
)
2616 if (Ypos
== Buff
->MaxY
)
2625 Request
->Status
= STATUS_SUCCESS
;
2626 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.X
= Xpos
- Buff
->ShowX
;
2627 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.Y
= (Ypos
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
;
2628 Request
->Header
.MessageSize
+= Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
;
2629 Request
->Header
.DataSize
+= Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
;
2631 ConioUnlockScreenBuffer(Buff
);
2633 return Request
->Status
;
2637 CSR_API(CsrGetNumberOfConsoleInputEvents
)
2640 PCSRSS_CONSOLE Console
;
2641 PLIST_ENTRY CurrentItem
;
2643 ConsoleInput
*Input
;
2645 DPRINT("CsrGetNumberOfConsoleInputEvents\n");
2647 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2648 Request
->Header
.DataSize
= Request
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
2650 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
);
2651 if (! NT_SUCCESS(Status
))
2653 return Request
->Status
= Status
;
2656 CurrentItem
= Console
->InputEvents
.Flink
;
2659 /* If there are any events ... */
2660 while (CurrentItem
!= &Console
->InputEvents
)
2662 Input
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2663 CurrentItem
= CurrentItem
->Flink
;
2670 ConioUnlockConsole(Console
);
2672 Request
->Status
= STATUS_SUCCESS
;
2673 Request
->Data
.GetNumInputEventsRequest
.NumInputEvents
= NumEvents
;
2675 return Request
->Status
;
2679 CSR_API(CsrPeekConsoleInput
)
2682 PCSRSS_CONSOLE Console
;
2685 PLIST_ENTRY CurrentItem
;
2686 PINPUT_RECORD InputRecord
;
2690 DPRINT("CsrPeekConsoleInput\n");
2692 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2693 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2695 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
);
2696 if(! NT_SUCCESS(Status
))
2698 return Request
->Status
= Status
;
2701 InputRecord
= Request
->Data
.PeekConsoleInputRequest
.InputRecord
;
2702 Length
= Request
->Data
.PeekConsoleInputRequest
.Length
;
2703 Size
= Length
* sizeof(INPUT_RECORD
);
2705 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2706 || (((PVOID
)InputRecord
+ Size
) > (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2708 ConioUnlockConsole(Console
);
2709 Request
->Status
= STATUS_ACCESS_VIOLATION
;
2710 return Request
->Status
;
2715 if (! IsListEmpty(&Console
->InputEvents
))
2717 CurrentItem
= Console
->InputEvents
.Flink
;
2719 while (CurrentItem
!= &Console
->InputEvents
&& NumItems
< Length
)
2721 Item
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2725 CurrentItem
= CurrentItem
->Flink
;
2730 *InputRecord
= Item
->InputEvent
;
2732 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
2734 ConioInputEventToAnsi(Console
, InputRecord
);
2738 CurrentItem
= CurrentItem
->Flink
;
2742 ConioUnlockConsole(Console
);
2744 Request
->Status
= STATUS_SUCCESS
;
2745 Request
->Data
.PeekConsoleInputRequest
.Length
= NumItems
;
2747 return Request
->Status
;
2751 CSR_API(CsrReadConsoleOutput
)
2753 PCHAR_INFO CharInfo
;
2754 PCHAR_INFO CurCharInfo
;
2755 PCSRSS_SCREEN_BUFFER Buff
;
2764 DWORD i
, Y
, X
, Offset
;
2767 DPRINT("CsrReadConsoleOutput\n");
2769 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2770 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2772 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputRequest
.ConsoleHandle
, &Buff
);
2773 if (! NT_SUCCESS(Status
))
2775 return Request
->Status
= Status
;
2778 CharInfo
= Request
->Data
.ReadConsoleOutputRequest
.CharInfo
;
2779 ReadRegion
.left
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
;
2780 ReadRegion
.top
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
;
2781 ReadRegion
.right
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
;
2782 ReadRegion
.bottom
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
;
2783 BufferSize
= Request
->Data
.ReadConsoleOutputRequest
.BufferSize
;
2784 BufferCoord
= Request
->Data
.ReadConsoleOutputRequest
.BufferCoord
;
2785 Length
= BufferSize
.X
* BufferSize
.Y
;
2786 Size
= Length
* sizeof(CHAR_INFO
);
2788 /* FIXME: Is this correct? */
2789 CodePage
= ProcessData
->Console
->OutputCodePage
;
2791 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
)
2792 || (((PVOID
)CharInfo
+ Size
) > (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2794 ConioUnlockScreenBuffer(Buff
);
2795 Request
->Status
= STATUS_ACCESS_VIOLATION
;
2796 return Request
->Status
;
2799 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&ReadRegion
));
2800 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&ReadRegion
));
2801 ReadRegion
.bottom
= ReadRegion
.top
+ SizeY
;
2802 ReadRegion
.right
= ReadRegion
.left
+ SizeX
;
2804 ConioInitRect(&ScreenRect
, 0, 0, Buff
->MaxY
, Buff
->MaxX
);
2805 if (! ConioGetIntersection(&ReadRegion
, &ScreenRect
, &ReadRegion
))
2807 ConioUnlockScreenBuffer(Buff
);
2808 Request
->Status
= STATUS_SUCCESS
;
2809 return Request
->Status
;
2812 for (i
= 0, Y
= ReadRegion
.top
; Y
< ReadRegion
.bottom
; ++i
, ++Y
)
2814 CurCharInfo
= CharInfo
+ (i
* BufferSize
.X
);
2816 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ ReadRegion
.left
) * 2;
2817 for (X
= ReadRegion
.left
; X
< ReadRegion
.right
; ++X
)
2819 if (Request
->Data
.ReadConsoleOutputRequest
.Unicode
)
2821 MultiByteToWideChar(CodePage
, 0,
2822 (PCHAR
)&GET_CELL_BUFFER(Buff
, Offset
), 1,
2823 &CurCharInfo
->Char
.UnicodeChar
, 1);
2827 CurCharInfo
->Char
.AsciiChar
= GET_CELL_BUFFER(Buff
, Offset
);
2829 CurCharInfo
->Attributes
= GET_CELL_BUFFER(Buff
, Offset
);
2834 ConioUnlockScreenBuffer(Buff
);
2836 Request
->Status
= STATUS_SUCCESS
;
2837 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
= ReadRegion
.left
+ SizeX
- 1;
2838 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
= ReadRegion
.top
+ SizeY
- 1;
2839 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
= ReadRegion
.left
;
2840 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
= ReadRegion
.top
;
2842 return Request
->Status
;
2846 CSR_API(CsrWriteConsoleInput
)
2848 PINPUT_RECORD InputRecord
;
2849 PCSRSS_CONSOLE Console
;
2854 ConsoleInput
* Record
;
2856 DPRINT("CsrWriteConsoleInput\n");
2858 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2859 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2861 Status
= ConioLockConsole(ProcessData
, Request
->Data
.WriteConsoleInputRequest
.ConsoleHandle
, &Console
);
2862 if (! NT_SUCCESS(Status
))
2864 return Request
->Status
= Status
;
2867 InputRecord
= Request
->Data
.WriteConsoleInputRequest
.InputRecord
;
2868 Length
= Request
->Data
.WriteConsoleInputRequest
.Length
;
2869 Size
= Length
* sizeof(INPUT_RECORD
);
2871 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2872 || (((PVOID
)InputRecord
+ Size
) > (ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2874 ConioUnlockConsole(Console
);
2875 Request
->Status
= STATUS_ACCESS_VIOLATION
;
2876 return Request
->Status
;
2879 for (i
= 0; i
< Length
; i
++)
2881 Record
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
2884 ConioUnlockConsole(Console
);
2885 Request
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2886 return Request
->Status
;
2889 Record
->Echoed
= FALSE
;
2890 Record
->Fake
= FALSE
;
2891 Record
->InputEvent
= *InputRecord
++;
2892 if (KEY_EVENT
== Record
->InputEvent
.EventType
)
2894 /* FIXME - convert from unicode to ascii!! */
2895 ConioProcessChar(Console
, Record
);
2899 ConioUnlockConsole(Console
);
2901 Request
->Status
= STATUS_SUCCESS
;
2902 Request
->Data
.WriteConsoleInputRequest
.Length
= i
;
2904 return Request
->Status
;
2907 /**********************************************************************
2908 * HardwareStateProperty
2911 * Set/Get the value of the HardwareState and switch
2912 * between direct video buffer ouput and GDI windowed
2915 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
2916 * object. We use the same object to Request.
2918 * ConsoleHwState has the correct size to be compatible
2919 * with NT's, but values are not.
2921 STATIC NTSTATUS FASTCALL
2922 SetConsoleHardwareState (PCSRSS_CONSOLE Console
, DWORD ConsoleHwState
)
2924 DPRINT1("Console Hardware State: %d\n", ConsoleHwState
);
2926 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED
== ConsoleHwState
)
2927 ||(CONSOLE_HARDWARE_STATE_DIRECT
== ConsoleHwState
))
2929 if (Console
->HardwareState
!= ConsoleHwState
)
2931 /* TODO: implement switching from full screen to windowed mode */
2932 /* TODO: or back; now simply store the hardware state */
2933 Console
->HardwareState
= ConsoleHwState
;
2936 return STATUS_SUCCESS
;
2939 return STATUS_INVALID_PARAMETER_3
; /* Client: (handle, set_get, [mode]) */
2942 CSR_API(CsrHardwareStateProperty
)
2944 PCSRSS_CONSOLE Console
;
2947 DPRINT("CsrHardwareStateProperty\n");
2949 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2950 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2952 Status
= ConioLockConsole(ProcessData
,
2953 Request
->Data
.ConsoleHardwareStateRequest
.ConsoleHandle
,
2955 if (! NT_SUCCESS(Status
))
2957 DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
2958 return Request
->Status
= Status
;
2961 switch (Request
->Data
.ConsoleHardwareStateRequest
.SetGet
)
2963 case CONSOLE_HARDWARE_STATE_GET
:
2964 Request
->Data
.ConsoleHardwareStateRequest
.State
= Console
->HardwareState
;
2967 case CONSOLE_HARDWARE_STATE_SET
:
2968 DPRINT("Setting console hardware state.\n");
2969 Request
->Status
= SetConsoleHardwareState(Console
, Request
->Data
.ConsoleHardwareStateRequest
.State
);
2973 Request
->Status
= STATUS_INVALID_PARAMETER_2
; /* Client: (handle, [set_get], mode) */
2977 ConioUnlockConsole(Console
);
2979 return Request
->Status
;
2982 CSR_API(CsrGetConsoleWindow
)
2984 PCSRSS_CONSOLE Console
;
2987 DPRINT("CsrGetConsoleWindow\n");
2989 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2990 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2992 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2993 if (! NT_SUCCESS(Status
))
2995 return Request
->Status
= Status
;
2998 Request
->Data
.GetConsoleWindowRequest
.WindowHandle
= Console
->hWindow
;
2999 ConioUnlockConsole(Console
);
3001 return Request
->Status
= STATUS_SUCCESS
;
3004 CSR_API(CsrSetConsoleIcon
)
3006 PCSRSS_CONSOLE Console
;
3009 DPRINT("CsrSetConsoleIcon\n");
3011 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
3012 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
3014 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3015 if (! NT_SUCCESS(Status
))
3017 return Request
->Status
= Status
;
3020 Console
->hWindowIcon
= Request
->Data
.SetConsoleIconRequest
.WindowIcon
;
3021 Request
->Status
= (ConioChangeIcon(Console
) ? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
3022 ConioUnlockConsole(Console
);
3024 return Request
->Status
;
3027 CSR_API(CsrGetConsoleCodePage
)
3029 PCSRSS_CONSOLE Console
;
3032 DPRINT("CsrGetConsoleCodePage\n");
3034 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3035 if (! NT_SUCCESS(Status
))
3037 return Request
->Status
= Status
;
3040 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
3041 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
3042 Request
->Data
.GetConsoleCodePage
.CodePage
= Console
->CodePage
;
3043 ConioUnlockConsole(Console
);
3044 return Request
->Status
= STATUS_SUCCESS
;
3047 CSR_API(CsrSetConsoleCodePage
)
3049 PCSRSS_CONSOLE Console
;
3052 DPRINT("CsrSetConsoleCodePage\n");
3054 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3055 if (! NT_SUCCESS(Status
))
3057 return Request
->Status
= Status
;
3060 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
3061 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
3062 if (IsValidCodePage(Request
->Data
.SetConsoleCodePage
.CodePage
))
3064 Console
->CodePage
= Request
->Data
.SetConsoleCodePage
.CodePage
;
3065 ConioUnlockConsole(Console
);
3066 return Request
->Status
= STATUS_SUCCESS
;
3068 ConioUnlockConsole(Console
);
3069 return Request
->Status
= STATUS_UNSUCCESSFUL
;
3072 CSR_API(CsrGetConsoleOutputCodePage
)
3074 PCSRSS_CONSOLE Console
;
3077 DPRINT("CsrGetConsoleOutputCodePage\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
.GetConsoleOutputCodePage
.CodePage
= Console
->OutputCodePage
;
3088 ConioUnlockConsole(Console
);
3089 return Request
->Status
= STATUS_SUCCESS
;
3092 CSR_API(CsrSetConsoleOutputCodePage
)
3094 PCSRSS_CONSOLE Console
;
3097 DPRINT("CsrSetConsoleOutputCodePage\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
.SetConsoleOutputCodePage
.CodePage
))
3109 Console
->OutputCodePage
= Request
->Data
.SetConsoleOutputCodePage
.CodePage
;
3110 ConioUnlockConsole(Console
);
3111 return Request
->Status
= STATUS_SUCCESS
;
3113 ConioUnlockConsole(Console
);
3114 return Request
->Status
= STATUS_UNSUCCESSFUL
;
3117 CSR_API(CsrGetProcessList
)
3120 PCSRSS_CONSOLE Console
;
3121 PCSRSS_PROCESS_DATA current
;
3122 PLIST_ENTRY current_entry
;
3123 ULONG nItems
, nCopied
;
3126 DPRINT("CsrGetProcessList\n");
3128 Buffer
= Request
->Data
.GetProcessListRequest
.ProcessId
;
3129 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
3130 Request
->Header
.DataSize
= Request
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
3132 nItems
= nCopied
= 0;
3133 Request
->Data
.GetProcessListRequest
.nProcessIdsCopied
= 0;
3134 Request
->Data
.GetProcessListRequest
.nProcessIdsTotal
= 0;
3136 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3137 if (! NT_SUCCESS(Status
))
3139 return Request
->Status
= Status
;
3142 DPRINT1("Console_Api Ctrl-C\n");
3144 for(current_entry
= Console
->ProcessList
.Flink
;
3145 current_entry
!= &Console
->ProcessList
;
3146 current_entry
= current_entry
->Flink
)
3148 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
3149 if(nItems
++ < Request
->Data
.GetProcessListRequest
.nMaxIds
)
3151 *(Buffer
++) = current
->ProcessId
;
3156 ConioUnlockConsole(Console
);
3158 Request
->Data
.GetProcessListRequest
.nProcessIdsCopied
= nCopied
;
3159 Request
->Data
.GetProcessListRequest
.nProcessIdsTotal
= nItems
;
3161 return Request
->Status
= STATUS_SUCCESS
;