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 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
;
229 DPRINT1("CsrAllocConsole\n");
231 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
232 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
234 if (ProcessData
== NULL
)
236 DPRINT1("No process data\n");
237 return Request
->Status
= STATUS_INVALID_PARAMETER
;
240 if (ProcessData
->Console
)
242 DPRINT1("Process already has a console\n");
243 Request
->Status
= STATUS_INVALID_PARAMETER
;
244 return STATUS_INVALID_PARAMETER
;
248 Request
->Status
= STATUS_SUCCESS
;
250 /* If we don't need a console, then get out of here */
251 if (!Request
->Data
.AllocConsoleRequest
.ConsoleNeeded
)
253 DPRINT1("No console needed\n");
254 return STATUS_SUCCESS
;
257 /* If we already have one, then don't create a new one... */
258 if (!Request
->Data
.AllocConsoleRequest
.Console
)
260 /* Allocate a console structure */
261 Console
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(CSRSS_CONSOLE
));
264 DPRINT1("Not enough memory for console\n");
265 Request
->Status
= STATUS_NO_MEMORY
;
266 return STATUS_NO_MEMORY
;
269 /* Initialize the Console */
270 Request
->Status
= CsrInitConsole(Console
);
271 if (!NT_SUCCESS(Request
->Status
))
273 DPRINT1("Console init failed\n");
274 HeapFree(Win32CsrApiHeap
, 0, Console
);
275 return Request
->Status
;
280 /* Reuse our current console */
281 Console
= Request
->Data
.AllocConsoleRequest
.Console
;
284 /* Set the Process Console */
285 ProcessData
->Console
= Console
;
287 /* Return it to the caller */
288 Request
->Data
.AllocConsoleRequest
.Console
= Console
;
290 /* Add a reference count because the process is tied to the console */
291 Console
->Header
.ReferenceCount
++;
293 /* Insert the Objects */
294 Status
= Win32CsrInsertObject(ProcessData
,
295 &Request
->Data
.AllocConsoleRequest
.InputHandle
,
297 if (! NT_SUCCESS(Status
))
299 DPRINT1("Failed to insert object\n");
300 ConioDeleteConsole((Object_t
*) Console
);
301 ProcessData
->Console
= 0;
302 return Request
->Status
= Status
;
304 Status
= Win32CsrInsertObject(ProcessData
,
305 &Request
->Data
.AllocConsoleRequest
.OutputHandle
,
306 &Console
->ActiveBuffer
->Header
);
307 if (!NT_SUCCESS(Status
))
309 DPRINT1("Failed to insert object\n");
310 Console
->Header
.ReferenceCount
--;
311 Win32CsrReleaseObject(ProcessData
,
312 Request
->Data
.AllocConsoleRequest
.InputHandle
);
313 ProcessData
->Console
= 0;
314 return Request
->Status
= Status
;
317 /* Duplicate the Event */
318 if (!DuplicateHandle(GetCurrentProcess(),
319 ProcessData
->Console
->ActiveEvent
,
320 ProcessData
->Process
,
321 &ProcessData
->ConsoleEvent
,
326 DPRINT1("DuplicateHandle() failed: %d\n", GetLastError
);
327 Console
->Header
.ReferenceCount
--;
328 Win32CsrReleaseObject(ProcessData
,
329 Request
->Data
.AllocConsoleRequest
.OutputHandle
);
330 Win32CsrReleaseObject(ProcessData
,
331 Request
->Data
.AllocConsoleRequest
.InputHandle
);
332 ProcessData
->Console
= 0;
333 Request
->Status
= Status
;
337 /* Set the Ctrl Dispatcher */
338 ProcessData
->CtrlDispatcher
= Request
->Data
.AllocConsoleRequest
.CtrlDispatcher
;
339 DPRINT1("CSRSS:CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
341 /* Insert into the list */
342 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ProcessEntry
);
343 return STATUS_SUCCESS
;
346 CSR_API(CsrFreeConsole
)
348 PCSRSS_CONSOLE Console
;
350 DPRINT("CsrFreeConsole\n");
352 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
353 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
355 if (ProcessData
== NULL
|| ProcessData
->Console
== NULL
)
357 return Request
->Status
= STATUS_INVALID_PARAMETER
;
360 Console
= ProcessData
->Console
;
361 Console
->Header
.ReferenceCount
--;
362 ProcessData
->Console
= NULL
;
363 if (0 == Console
->Header
.ReferenceCount
)
365 ConioDeleteConsole((Object_t
*) Console
);
368 return STATUS_SUCCESS
;
372 ConioNextLine(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, UINT
*ScrolledLines
)
374 /* slide the viewable screen */
375 if (((Buff
->CurrentY
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
) == (ULONG
)Buff
->MaxY
- 1)
377 if (++Buff
->ShowY
== Buff
->MaxY
)
383 if (++Buff
->CurrentY
== Buff
->MaxY
)
387 ClearLineBuffer(Buff
);
388 UpdateRect
->left
= 0;
389 UpdateRect
->right
= Buff
->MaxX
- 1;
390 if (UpdateRect
->top
== (LONG
)Buff
->CurrentY
)
392 if (++UpdateRect
->top
== Buff
->MaxY
)
397 UpdateRect
->bottom
= Buff
->CurrentY
;
400 STATIC NTSTATUS FASTCALL
401 ConioWriteConsole(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
,
402 CHAR
*Buffer
, DWORD Length
, BOOL Attrib
)
407 LONG CursorStartX
, CursorStartY
;
410 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &CursorStartX
, &CursorStartY
);
411 UpdateRect
.left
= Buff
->MaxX
;
412 UpdateRect
.top
= Buff
->CurrentY
;
413 UpdateRect
.right
= -1;
414 UpdateRect
.bottom
= Buff
->CurrentY
;
417 for (i
= 0; i
< Length
; i
++)
419 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
422 if (Buffer
[i
] == '\n')
425 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
429 else if (Buffer
[i
] == '\b')
431 /* Only handle BS if we're not on the first pos of the first line */
432 if (0 != Buff
->CurrentX
|| Buff
->ShowY
!= Buff
->CurrentY
)
434 if (0 == Buff
->CurrentX
)
436 /* slide virtual position up */
437 Buff
->CurrentX
= Buff
->MaxX
- 1;
438 if (0 == Buff
->CurrentY
)
440 Buff
->CurrentY
= Buff
->MaxY
;
446 if ((0 == UpdateRect
.top
&& UpdateRect
.bottom
< (LONG
)Buff
->CurrentY
)
447 || (0 != UpdateRect
.top
&& (LONG
)Buff
->CurrentY
< UpdateRect
.top
))
449 UpdateRect
.top
= Buff
->CurrentY
;
456 Offset
= 2 * ((Buff
->CurrentY
* Buff
->MaxX
) + Buff
->CurrentX
);
457 SET_CELL_BUFFER(Buff
, Offset
, ' ', Buff
->DefaultAttrib
);
458 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
) Buff
->CurrentX
);
459 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
464 else if (Buffer
[i
] == '\r')
467 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
) Buff
->CurrentX
);
468 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
472 else if (Buffer
[i
] == '\t')
476 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
)Buff
->CurrentX
);
477 EndX
= (Buff
->CurrentX
+ 8) & ~7;
478 if (EndX
> Buff
->MaxX
)
482 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
483 while (Buff
->CurrentX
< EndX
)
485 Buff
->Buffer
[Offset
] = ' ';
489 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
- 1);
490 if (Buff
->CurrentX
== Buff
->MaxX
)
492 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
495 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
505 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
)Buff
->CurrentX
);
506 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
507 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
508 Buff
->Buffer
[Offset
++] = Buffer
[i
];
511 Buff
->Buffer
[Offset
] = Buff
->DefaultAttrib
;
514 if (Buff
->CurrentX
== Buff
->MaxX
)
516 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
519 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
523 Buff
->CurrentX
= CursorStartX
;
528 ConioPhysicalToLogical(Buff
, UpdateRect
.left
, UpdateRect
.top
, &(UpdateRect
.left
),
530 ConioPhysicalToLogical(Buff
, UpdateRect
.right
, UpdateRect
.bottom
, &(UpdateRect
.right
),
531 &(UpdateRect
.bottom
));
532 if (! ConioIsRectEmpty(&UpdateRect
) && NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
534 ConioWriteStream(Console
, &UpdateRect
, CursorStartX
, CursorStartY
, ScrolledLines
,
538 return STATUS_SUCCESS
;
541 CSR_API(CsrReadConsole
)
543 PLIST_ENTRY CurrentEntry
;
546 PWCHAR UnicodeBuffer
;
548 ULONG nNumberOfCharsToRead
, CharSize
;
549 PCSRSS_CONSOLE Console
;
552 DPRINT("CsrReadConsole\n");
554 CharSize
= (Request
->Data
.ReadConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
556 /* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */
557 nNumberOfCharsToRead
= min(Request
->Data
.ReadConsoleRequest
.NrCharactersToRead
, CSRSS_MAX_READ_CONSOLE
/ CharSize
);
558 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
559 Request
->Header
.DataSize
= Request
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
561 Buffer
= Request
->Data
.ReadConsoleRequest
.Buffer
;
562 UnicodeBuffer
= (PWCHAR
)Buffer
;
563 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadConsoleRequest
.ConsoleHandle
,
565 if (! NT_SUCCESS(Status
))
567 return Request
->Status
= Status
;
569 Request
->Data
.ReadConsoleRequest
.EventHandle
= ProcessData
->ConsoleEvent
;
570 for (i
= 0; i
< nNumberOfCharsToRead
&& Console
->InputEvents
.Flink
!= &Console
->InputEvents
; i
++)
572 /* remove input event from queue */
573 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
574 if (IsListEmpty(&Console
->InputEvents
))
577 ResetEvent(Console
->ActiveEvent
);
579 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
581 /* only pay attention to valid ascii chars, on key down */
582 if (KEY_EVENT
== Input
->InputEvent
.EventType
583 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
584 && Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
!= '\0')
586 /* backspace handling */
587 if ('\b' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
589 /* echo if it has not already been done, and either we or the client has chars to be deleted */
591 && (0 != i
|| Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
))
593 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
594 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
598 i
-= 2; /* if we already have something to return, just back it up by 2 */
601 { /* otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer */
602 Console
->WaitingChars
--;
603 ConioUnlockConsole(Console
);
604 HeapFree(Win32CsrApiHeap
, 0, Input
);
605 Request
->Data
.ReadConsoleRequest
.NrCharactersRead
= 0;
606 Request
->Status
= STATUS_NOTIFY_CLEANUP
;
607 return STATUS_NOTIFY_CLEANUP
;
609 Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
--;
610 Input
->Echoed
= TRUE
; /* mark as echoed so we don't echo it below */
612 /* do not copy backspace to buffer */
615 if(Request
->Data
.ReadConsoleRequest
.Unicode
)
616 UnicodeBuffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
; /* FIXME */
618 Buffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
;
620 /* echo to screen if enabled and we did not already echo the char */
621 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
)
623 && '\r' != Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
625 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
626 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
633 Console
->WaitingChars
--;
634 HeapFree(Win32CsrApiHeap
, 0, Input
);
636 Request
->Data
.ReadConsoleRequest
.NrCharactersRead
= i
;
639 Request
->Status
= STATUS_PENDING
; /* we didn't read anything */
641 else if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
))
643 if (0 == Console
->WaitingLines
||
644 (Request
->Data
.ReadConsoleRequest
.Unicode
? (L
'\n' != UnicodeBuffer
[i
- 1]) : ('\n' != Buffer
[i
- 1])))
646 Request
->Status
= STATUS_PENDING
; /* line buffered, didn't get a complete line */
650 Console
->WaitingLines
--;
651 Request
->Status
= STATUS_SUCCESS
; /* line buffered, did get a complete line */
656 Request
->Status
= STATUS_SUCCESS
; /* not line buffered, did read something */
659 if (Request
->Status
== STATUS_PENDING
)
661 Console
->EchoCount
= nNumberOfCharsToRead
- i
;
665 Console
->EchoCount
= 0; /* if the client is no longer waiting on input, do not echo */
667 Request
->Header
.MessageSize
+= i
* CharSize
;
669 ConioUnlockConsole(Console
);
670 return Request
->Status
;
674 ConioPhysicalToLogical(PCSRSS_SCREEN_BUFFER Buff
,
680 *LogicalX
= PhysicalX
;
681 if (PhysicalY
< Buff
->ShowY
)
683 *LogicalY
= Buff
->MaxY
- Buff
->ShowY
+ PhysicalY
;
687 *LogicalY
= PhysicalY
- Buff
->ShowY
;
691 inline BOOLEAN
ConioIsEqualRect(
695 return ((Rect1
->left
== Rect2
->left
) && (Rect1
->right
== Rect2
->right
) &&
696 (Rect1
->top
== Rect2
->top
) && (Rect1
->bottom
== Rect2
->bottom
));
699 inline BOOLEAN
ConioGetIntersection(
704 if (ConioIsRectEmpty(Rect1
) ||
705 (ConioIsRectEmpty(Rect2
)) ||
706 (Rect1
->top
> Rect2
->bottom
) ||
707 (Rect1
->left
> Rect2
->right
) ||
708 (Rect1
->bottom
< Rect2
->top
) ||
709 (Rect1
->right
< Rect2
->left
))
711 /* The rectangles do not intersect */
712 ConioInitRect(Intersection
, 0, -1, 0, -1);
716 ConioInitRect(Intersection
,
717 max(Rect1
->top
, Rect2
->top
),
718 max(Rect1
->left
, Rect2
->left
),
719 min(Rect1
->bottom
, Rect2
->bottom
),
720 min(Rect1
->right
, Rect2
->right
));
725 inline BOOLEAN
ConioGetUnion(
730 if (ConioIsRectEmpty(Rect1
))
732 if (ConioIsRectEmpty(Rect2
))
734 ConioInitRect(Union
, 0, -1, 0, -1);
742 else if (ConioIsRectEmpty(Rect2
))
749 min(Rect1
->top
, Rect2
->top
),
750 min(Rect1
->left
, Rect2
->left
),
751 max(Rect1
->bottom
, Rect2
->bottom
),
752 max(Rect1
->right
, Rect2
->right
));
758 inline BOOLEAN
ConioSubtractRect(
765 if (ConioIsRectEmpty(Rect1
))
767 ConioInitRect(Subtraction
, 0, -1, 0, -1);
770 *Subtraction
= *Rect1
;
771 if (ConioGetIntersection(&tmp
, Rect1
, Rect2
))
773 if (ConioIsEqualRect(&tmp
, Subtraction
))
775 ConioInitRect(Subtraction
, 0, -1, 0, -1);
778 if ((tmp
.top
== Subtraction
->top
) && (tmp
.bottom
== Subtraction
->bottom
))
780 if (tmp
.left
== Subtraction
->left
)
782 Subtraction
->left
= tmp
.right
;
784 else if (tmp
.right
== Subtraction
->right
)
786 Subtraction
->right
= tmp
.left
;
789 else if ((tmp
.left
== Subtraction
->left
) && (tmp
.right
== Subtraction
->right
))
791 if (tmp
.top
== Subtraction
->top
)
793 Subtraction
->top
= tmp
.bottom
;
795 else if (tmp
.bottom
== Subtraction
->bottom
)
797 Subtraction
->bottom
= tmp
.top
;
806 ConioCopyRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer
,
816 DstY
= DstRegion
->top
;
817 BytesPerLine
= ConioRectWidth(DstRegion
) * 2;
819 SrcY
= (SrcRegion
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
820 DstY
= (DstRegion
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
821 SrcOffset
= (SrcY
* ScreenBuffer
->MaxX
+ SrcRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
822 DstOffset
= (DstY
* ScreenBuffer
->MaxX
+ DstRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
824 for (i
= SrcRegion
->top
; i
<= SrcRegion
->bottom
; i
++)
827 &ScreenBuffer
->Buffer
[DstOffset
],
828 &ScreenBuffer
->Buffer
[SrcOffset
],
831 if (++DstY
== ScreenBuffer
->MaxY
)
834 DstOffset
= (DstRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
838 DstOffset
+= ScreenBuffer
->MaxX
* 2;
841 if (++SrcY
== ScreenBuffer
->MaxY
)
844 SrcOffset
= (SrcRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
848 SrcOffset
+= ScreenBuffer
->MaxX
* 2;
854 ConioFillRegion(PCSRSS_CONSOLE Console
,
855 PCSRSS_SCREEN_BUFFER ScreenBuffer
,
867 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &CharInfo
->Char
.UnicodeChar
);
869 Char
= CharInfo
->Char
.AsciiChar
;
871 Y
= (Region
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
872 Offset
= (Y
* ScreenBuffer
->MaxX
+ Region
->left
+ ScreenBuffer
->ShowX
) * 2;
873 Delta
= (ScreenBuffer
->MaxX
- ConioRectWidth(Region
)) * 2;
875 for (i
= Region
->top
; i
<= Region
->bottom
; i
++)
877 for (X
= Region
->left
; X
<= Region
->right
; X
++)
879 SET_CELL_BUFFER(ScreenBuffer
, Offset
, Char
, CharInfo
->Attributes
);
881 if (++Y
== ScreenBuffer
->MaxY
)
884 Offset
= (Region
->left
+ ScreenBuffer
->ShowX
) * 2;
894 ConioInputEventToAnsi(PCSRSS_CONSOLE Console
, PINPUT_RECORD InputEvent
)
896 if (InputEvent
->EventType
== KEY_EVENT
)
898 ConsoleUnicodeCharToAnsiChar(Console
,
899 &InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
,
900 &InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
);
904 CSR_API(CsrWriteConsole
)
907 PCHAR Buffer
= (PCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
;
908 PCSRSS_SCREEN_BUFFER Buff
;
909 PCSRSS_CONSOLE Console
;
910 ULONG CharSize
= (Request
->Data
.WriteConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
912 DPRINT("CsrWriteConsole\n");
914 if (Request
->Header
.DataSize
915 < sizeof(CSRSS_WRITE_CONSOLE
) - 1
916 + (Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
* CharSize
))
918 DPRINT1("Invalid request size\n");
919 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
920 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
921 return Request
->Status
= STATUS_INVALID_PARAMETER
;
923 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
925 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
926 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
928 if (! NT_SUCCESS(Status
))
930 return Request
->Status
= Status
;
933 if(Request
->Data
.WriteConsoleRequest
.Unicode
)
935 ConsoleUnicodeToAnsiN(Console
, Buffer
, (PWCHAR
)Buffer
, Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
);
938 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.WriteConsoleRequest
.ConsoleHandle
, &Buff
);
939 if (! NT_SUCCESS(Status
))
943 ConioUnlockConsole(Console
);
945 return Request
->Status
= Status
;
948 Request
->Status
= ConioWriteConsole(Console
, Buff
, Buffer
,
949 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
, TRUE
);
950 ConioUnlockScreenBuffer(Buff
);
953 ConioUnlockConsole(Console
);
956 if(NT_SUCCESS(Request
->Status
))
958 Request
->Data
.WriteConsoleRequest
.NrCharactersWritten
= Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
;
962 Request
->Data
.WriteConsoleRequest
.NrCharactersWritten
= 0; /* FIXME - return the actual number of characters written! */
965 return Request
->Status
= STATUS_SUCCESS
;
969 ConioDeleteScreenBuffer(Object_t
*Object
)
971 PCSRSS_SCREEN_BUFFER Buffer
= (PCSRSS_SCREEN_BUFFER
) Object
;
972 DeleteCriticalSection(&Buffer
->Header
.Lock
);
973 HeapFree(Win32CsrApiHeap
, 0, Buffer
->Buffer
);
974 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
978 ConioDrawConsole(PCSRSS_CONSOLE Console
)
982 ConioInitRect(&Region
, 0, 0, Console
->Size
.Y
- 1, Console
->Size
.X
- 1);
984 ConioDrawRegion(Console
, &Region
);
989 ConioDeleteConsole(Object_t
*Object
)
991 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Object
;
994 DPRINT("ConioDeleteConsole\n");
996 /* Drain input event queue */
997 while (Console
->InputEvents
.Flink
!= &Console
->InputEvents
)
999 Event
= (ConsoleInput
*) Console
->InputEvents
.Flink
;
1000 Console
->InputEvents
.Flink
= Console
->InputEvents
.Flink
->Flink
;
1001 Console
->InputEvents
.Flink
->Flink
->Blink
= &Console
->InputEvents
;
1002 HeapFree(Win32CsrApiHeap
, 0, Event
);
1005 if (0 == --Console
->ActiveBuffer
->Header
.ReferenceCount
)
1007 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
1010 Console
->ActiveBuffer
= NULL
;
1011 ConioCleanupConsole(Console
);
1013 CloseHandle(Console
->ActiveEvent
);
1014 DeleteCriticalSection(&Console
->Header
.Lock
);
1015 RtlFreeUnicodeString(&Console
->Title
);
1016 HeapFree(Win32CsrApiHeap
, 0, Console
);
1020 CsrInitConsoleSupport(VOID
)
1022 DPRINT("CSR: CsrInitConsoleSupport()\n");
1024 /* Should call LoadKeyboardLayout */
1027 STATIC VOID FASTCALL
1028 ConioProcessChar(PCSRSS_CONSOLE Console
,
1029 ConsoleInput
*KeyEventRecord
)
1032 BOOL bClientWake
= FALSE
;
1033 ConsoleInput
*TempInput
;
1035 /* process Ctrl-C and Ctrl-Break */
1036 if (Console
->Mode
& ENABLE_PROCESSED_INPUT
&&
1037 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
&&
1038 ((KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== VK_PAUSE
) ||
1039 (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== 'C')) &&
1040 (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
)))
1042 PCSRSS_PROCESS_DATA current
;
1043 PLIST_ENTRY current_entry
;
1044 DPRINT1("Console_Api Ctrl-C\n");
1045 current_entry
= Console
->ProcessList
.Flink
;
1046 while (current_entry
!= &Console
->ProcessList
)
1048 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
1049 current_entry
= current_entry
->Flink
;
1050 ConioConsoleCtrlEvent((DWORD
)CTRL_C_EVENT
, current
);
1052 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1056 if (0 != (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
1057 & (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1058 && (VK_UP
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
1059 || VK_DOWN
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
))
1061 if (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1063 /* scroll up or down */
1064 if (NULL
== Console
)
1066 DPRINT1("No Active Console!\n");
1067 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1070 if (VK_UP
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
)
1072 /* only scroll up if there is room to scroll up into */
1073 if (Console
->ActiveBuffer
->ShowY
!= ((Console
->ActiveBuffer
->CurrentY
+ 1) %
1074 Console
->ActiveBuffer
->MaxY
))
1076 Console
->ActiveBuffer
->ShowY
= (Console
->ActiveBuffer
->ShowY
+
1077 Console
->ActiveBuffer
->MaxY
- 1) %
1078 Console
->ActiveBuffer
->MaxY
;
1081 else if (Console
->ActiveBuffer
->ShowY
!= Console
->ActiveBuffer
->CurrentY
)
1082 /* only scroll down if there is room to scroll down into */
1084 if (Console
->ActiveBuffer
->ShowY
% Console
->ActiveBuffer
->MaxY
!=
1085 Console
->ActiveBuffer
->CurrentY
)
1087 if (((Console
->ActiveBuffer
->CurrentY
+ 1) % Console
->ActiveBuffer
->MaxY
) !=
1088 (Console
->ActiveBuffer
->ShowY
+ Console
->ActiveBuffer
->MaxY
) %
1089 Console
->ActiveBuffer
->MaxY
)
1091 Console
->ActiveBuffer
->ShowY
= (Console
->ActiveBuffer
->ShowY
+ 1) %
1092 Console
->ActiveBuffer
->MaxY
;
1096 ConioDrawConsole(Console
);
1098 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1101 if (NULL
== Console
)
1103 DPRINT1("No Active Console!\n");
1104 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1108 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
)))
1110 switch(KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1113 /* first add the \r */
1114 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1115 updown
= KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
;
1116 KeyEventRecord
->Echoed
= FALSE
;
1117 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= VK_RETURN
;
1118 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\r';
1119 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1120 Console
->WaitingChars
++;
1121 KeyEventRecord
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1122 if (NULL
== KeyEventRecord
)
1124 DPRINT1("Failed to allocate KeyEventRecord\n");
1127 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1128 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
= updown
;
1129 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= 0;
1130 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualScanCode
= 0;
1131 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\n';
1132 KeyEventRecord
->Fake
= TRUE
;
1136 /* add event to the queue */
1137 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1138 Console
->WaitingChars
++;
1139 /* if line input mode is enabled, only wake the client on enter key down */
1140 if (0 == (Console
->Mode
& ENABLE_LINE_INPUT
)
1141 || Console
->EarlyReturn
1142 || ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1143 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
))
1145 if ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1147 Console
->WaitingLines
++;
1150 SetEvent(Console
->ActiveEvent
);
1152 KeyEventRecord
->Echoed
= FALSE
;
1153 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
))
1154 && '\b' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1155 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1157 /* walk the input queue looking for a char to backspace */
1158 for (TempInput
= (ConsoleInput
*) Console
->InputEvents
.Blink
;
1159 TempInput
!= (ConsoleInput
*) &Console
->InputEvents
1160 && (KEY_EVENT
== TempInput
->InputEvent
.EventType
1161 || ! TempInput
->InputEvent
.Event
.KeyEvent
.bKeyDown
1162 || '\b' == TempInput
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
);
1163 TempInput
= (ConsoleInput
*) TempInput
->ListEntry
.Blink
)
1167 /* if we found one, delete it, otherwise, wake the client */
1168 if (TempInput
!= (ConsoleInput
*) &Console
->InputEvents
)
1170 /* delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue */
1171 RemoveEntryList(&TempInput
->ListEntry
);
1172 if (TempInput
->Echoed
)
1174 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1175 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1178 HeapFree(Win32CsrApiHeap
, 0, TempInput
);
1179 RemoveEntryList(&KeyEventRecord
->ListEntry
);
1180 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1181 Console
->WaitingChars
-= 2;
1185 SetEvent(Console
->ActiveEvent
);
1190 /* echo chars if we are supposed to and client is waiting for some */
1191 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
) && Console
->EchoCount
1192 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1193 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
1194 && '\r' != KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1196 /* mark the char as already echoed */
1197 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1198 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1200 Console
->EchoCount
--;
1201 KeyEventRecord
->Echoed
= TRUE
;
1205 /* Console->WaitingChars++; */
1206 if (bClientWake
|| 0 == (Console
->Mode
& ENABLE_LINE_INPUT
))
1208 SetEvent(Console
->ActiveEvent
);
1212 STATIC DWORD FASTCALL
1213 ConioGetShiftState(PBYTE KeyState
)
1217 if (KeyState
[VK_CAPITAL
] & 1)
1218 ssOut
|= CAPSLOCK_ON
;
1220 if (KeyState
[VK_NUMLOCK
] & 1)
1221 ssOut
|= NUMLOCK_ON
;
1223 if (KeyState
[VK_SCROLL
] & 1)
1224 ssOut
|= SCROLLLOCK_ON
;
1226 if (KeyState
[VK_SHIFT
] & 0x80)
1227 ssOut
|= SHIFT_PRESSED
;
1229 if (KeyState
[VK_LCONTROL
] & 0x80)
1230 ssOut
|= LEFT_CTRL_PRESSED
;
1231 if (KeyState
[VK_RCONTROL
] & 0x80)
1232 ssOut
|= RIGHT_CTRL_PRESSED
;
1234 if (KeyState
[VK_LMENU
] & 0x80)
1235 ssOut
|= LEFT_ALT_PRESSED
;
1236 if (KeyState
[VK_RMENU
] & 0x80)
1237 ssOut
|= RIGHT_ALT_PRESSED
;
1243 ConioProcessKey(MSG
*msg
, PCSRSS_CONSOLE Console
, BOOL TextMode
)
1245 static BYTE KeyState
[256] = { 0 };
1246 /* MSDN mentions that you should use the last virtual key code received
1247 * when putting a virtual key identity to a WM_CHAR message since multiple
1248 * or translated keys may be involved. */
1249 static UINT LastVirtualKey
= 0;
1251 ConsoleInput
*ConInRec
;
1255 UINT VirtualKeyCode
;
1256 UINT VirtualScanCode
;
1259 ULONG ResultSize
= 0;
1262 VirtualScanCode
= (msg
->lParam
>> 16) & 0xff;
1263 Down
= msg
->message
== WM_KEYDOWN
|| msg
->message
== WM_CHAR
||
1264 msg
->message
== WM_SYSKEYDOWN
|| msg
->message
== WM_SYSCHAR
;
1266 GetKeyboardState(KeyState
);
1267 ShiftState
= ConioGetShiftState(KeyState
);
1269 if (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
)
1271 VirtualKeyCode
= LastVirtualKey
;
1272 UnicodeChar
= msg
->wParam
;
1279 VirtualKeyCode
= msg
->wParam
;
1280 RetChars
= ToUnicodeEx(VirtualKeyCode
,
1287 UnicodeChar
= (1 == RetChars
? Chars
[0] : 0);
1290 if (0 == ResultSize
)
1295 er
.EventType
= KEY_EVENT
;
1296 er
.Event
.KeyEvent
.bKeyDown
= Down
;
1297 er
.Event
.KeyEvent
.wRepeatCount
= RepeatCount
;
1298 er
.Event
.KeyEvent
.uChar
.UnicodeChar
= UnicodeChar
;
1299 er
.Event
.KeyEvent
.dwControlKeyState
= ShiftState
;
1300 er
.Event
.KeyEvent
.wVirtualKeyCode
= VirtualKeyCode
;
1301 er
.Event
.KeyEvent
.wVirtualScanCode
= VirtualScanCode
;
1305 if (0 != (ShiftState
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1306 && VK_TAB
== VirtualKeyCode
)
1310 TuiSwapConsole(ShiftState
& SHIFT_PRESSED
? -1 : 1);
1315 else if (VK_MENU
== VirtualKeyCode
&& ! Down
)
1317 if (TuiSwapConsole(0))
1324 if (NULL
== Console
)
1329 ConInRec
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1331 if (NULL
== ConInRec
)
1336 ConInRec
->InputEvent
= er
;
1337 ConInRec
->Fake
= UnicodeChar
&&
1338 (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
&&
1339 msg
->message
!= WM_KEYUP
&& msg
->message
!= WM_SYSKEYUP
);
1340 ConInRec
->NotChar
= (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
);
1341 ConInRec
->Echoed
= FALSE
;
1342 if (ConInRec
->NotChar
)
1343 LastVirtualKey
= msg
->wParam
;
1345 DPRINT ("csrss: %s %s %s %s %02x %02x '%c' %04x\n",
1346 Down
? "down" : "up ",
1347 (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
) ?
1349 ConInRec
->Fake
? "fake" : "real",
1350 ConInRec
->NotChar
? "notc" : "char",
1353 (AsciiChar
>= ' ') ? AsciiChar
: '.',
1356 if (! ConInRec
->Fake
|| ! ConInRec
->NotChar
)
1358 /* FIXME - convert to ascii */
1359 ConioProcessChar(Console
, ConInRec
);
1363 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1368 Console_Api (PVOID unused
)
1370 /* keep reading events from the keyboard and stuffing them into the current
1371 console's input queue */
1374 /* This call establishes our message queue */
1375 PeekMessageW(&msg
, 0, 0, 0, PM_NOREMOVE
);
1376 /* This call registers our message queue */
1377 PrivateCsrssRegisterPrimitive();
1378 /* This call turns on the input system in win32k */
1379 PrivateCsrssAcquireOrReleaseInputOwnership(FALSE
);
1383 GetMessageW(&msg
, 0, 0, 0);
1384 TranslateMessage(&msg
);
1386 if (msg
.message
== WM_CHAR
|| msg
.message
== WM_SYSCHAR
||
1387 msg
.message
== WM_KEYDOWN
|| msg
.message
== WM_KEYUP
||
1388 msg
.message
== WM_SYSKEYDOWN
|| msg
.message
== WM_SYSKEYUP
)
1390 ConioProcessKey(&msg
, TuiGetFocusConsole(), TRUE
);
1394 PrivateCsrssAcquireOrReleaseInputOwnership(TRUE
);
1398 CSR_API(CsrGetScreenBufferInfo
)
1401 PCSRSS_SCREEN_BUFFER Buff
;
1402 PCONSOLE_SCREEN_BUFFER_INFO pInfo
;
1404 DPRINT("CsrGetScreenBufferInfo\n");
1406 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1407 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1409 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ScreenBufferInfoRequest
.ConsoleHandle
, &Buff
);
1410 if (! NT_SUCCESS(Status
))
1412 return Request
->Status
= Status
;
1414 pInfo
= &Request
->Data
.ScreenBufferInfoRequest
.Info
;
1415 pInfo
->dwSize
.X
= Buff
->MaxX
;
1416 pInfo
->dwSize
.Y
= Buff
->MaxY
;
1417 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1418 pInfo
->dwCursorPosition
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1419 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
1420 pInfo
->srWindow
.Left
= 0;
1421 pInfo
->srWindow
.Right
= Buff
->MaxX
- 1;
1422 pInfo
->srWindow
.Top
= 0;
1423 pInfo
->srWindow
.Bottom
= Buff
->MaxY
- 1;
1424 pInfo
->dwMaximumWindowSize
.X
= Buff
->MaxX
;
1425 pInfo
->dwMaximumWindowSize
.Y
= Buff
->MaxY
;
1426 ConioUnlockScreenBuffer(Buff
);
1428 Request
->Status
= STATUS_SUCCESS
;
1430 return Request
->Status
;
1433 CSR_API(CsrSetCursor
)
1436 PCSRSS_CONSOLE Console
;
1437 PCSRSS_SCREEN_BUFFER Buff
;
1438 LONG OldCursorX
, OldCursorY
;
1439 LONG NewCursorX
, NewCursorY
;
1441 DPRINT("CsrSetCursor\n");
1443 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1444 if (! NT_SUCCESS(Status
))
1446 return Request
->Status
= Status
;
1449 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1450 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1452 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
);
1453 if (! NT_SUCCESS(Status
))
1455 if (NULL
!= Console
)
1457 ConioUnlockConsole(Console
);
1459 return Request
->Status
= Status
;
1462 NewCursorX
= Request
->Data
.SetCursorRequest
.Position
.X
;
1463 NewCursorY
= Request
->Data
.SetCursorRequest
.Position
.Y
;
1464 if (NewCursorX
< 0 || NewCursorX
>= Buff
->MaxX
||
1465 NewCursorY
< 0 || NewCursorY
>= Buff
->MaxY
)
1467 ConioUnlockScreenBuffer(Buff
);
1468 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1470 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &OldCursorX
, &OldCursorY
);
1471 Buff
->CurrentX
= NewCursorX
+ Buff
->ShowX
;
1472 Buff
->CurrentY
= (NewCursorY
+ Buff
->ShowY
) % Buff
->MaxY
;
1473 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1475 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
1477 ConioUnlockScreenBuffer(Buff
);
1478 return Request
->Status
= STATUS_UNSUCCESSFUL
;
1482 ConioUnlockScreenBuffer(Buff
);
1483 if (NULL
!= Console
)
1485 ConioUnlockConsole(Console
);
1488 return Request
->Status
= STATUS_SUCCESS
;
1491 STATIC FASTCALL VOID
1492 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, COORD
*Start
, UINT Length
)
1494 if (Buff
->MaxX
<= Start
->X
+ Length
)
1496 UpdateRect
->left
= 0;
1500 UpdateRect
->left
= Start
->X
;
1502 if (Buff
->MaxX
<= Start
->X
+ Length
)
1504 UpdateRect
->right
= Buff
->MaxX
- 1;
1508 UpdateRect
->right
= Start
->X
+ Length
- 1;
1510 UpdateRect
->top
= Start
->Y
;
1511 UpdateRect
->bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->MaxX
;
1512 if (Buff
->MaxY
<= UpdateRect
->bottom
)
1514 UpdateRect
->bottom
= Buff
->MaxY
- 1;
1518 CSR_API(CsrWriteConsoleOutputChar
)
1521 PCHAR String
= (PCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
;
1523 PCSRSS_CONSOLE Console
;
1524 PCSRSS_SCREEN_BUFFER Buff
;
1525 DWORD X
, Y
, Length
, CharSize
, Written
= 0;
1528 DPRINT("CsrWriteConsoleOutputChar\n");
1530 CharSize
= (Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
1532 if (Request
->Header
.DataSize
1533 < sizeof(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR
) - 1
1534 + (Request
->Data
.WriteConsoleOutputCharRequest
.Length
* CharSize
))
1536 DPRINT1("Invalid request size\n");
1537 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1538 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1539 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1542 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1543 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1544 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1545 if (! NT_SUCCESS(Status
))
1547 return Request
->Status
= Status
;
1550 if(Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
)
1552 ConsoleUnicodeToAnsiN(Console
, String
, (PWCHAR
)String
, Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
1555 Status
= ConioLockScreenBuffer(ProcessData
,
1556 Request
->Data
.WriteConsoleOutputCharRequest
.ConsoleHandle
,
1558 if (! NT_SUCCESS(Status
))
1560 if (NULL
!= Console
)
1562 ConioUnlockConsole(Console
);
1564 return Request
->Status
= Status
;
1567 X
= Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.X
+ Buff
->ShowX
;
1568 Y
= (Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1569 Length
= Request
->Data
.WriteConsoleOutputCharRequest
.Length
;
1570 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1573 *Buffer
= *String
++;
1576 if (++X
== Buff
->MaxX
)
1578 if (++Y
== Buff
->MaxY
)
1581 Buffer
= Buff
->Buffer
;
1587 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1589 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputCharRequest
.Coord
,
1590 Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
1591 ConioDrawRegion(Console
, &UpdateRect
);
1594 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.X
= X
- Buff
->ShowX
;
1595 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1597 ConioUnlockScreenBuffer(Buff
);
1598 if (NULL
!= Console
)
1600 ConioUnlockConsole(Console
);
1603 Request
->Data
.WriteConsoleOutputCharRequest
.NrCharactersWritten
= Written
;
1604 return Request
->Status
= STATUS_SUCCESS
;
1607 CSR_API(CsrFillOutputChar
)
1610 PCSRSS_CONSOLE Console
;
1611 PCSRSS_SCREEN_BUFFER Buff
;
1612 DWORD X
, Y
, Length
, Written
= 0;
1617 DPRINT("CsrFillOutputChar\n");
1619 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1620 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1622 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1623 if (! NT_SUCCESS(Status
))
1625 return Request
->Status
= Status
;
1628 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputRequest
.ConsoleHandle
, &Buff
);
1629 if (! NT_SUCCESS(Status
))
1631 if (NULL
!= Console
)
1633 ConioUnlockConsole(Console
);
1635 return Request
->Status
= Status
;
1638 X
= Request
->Data
.FillOutputRequest
.Position
.X
+ Buff
->ShowX
;
1639 Y
= (Request
->Data
.FillOutputRequest
.Position
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1640 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1641 if(Request
->Data
.FillOutputRequest
.Unicode
)
1642 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &Request
->Data
.FillOutputRequest
.Char
.UnicodeChar
);
1644 Char
= Request
->Data
.FillOutputRequest
.Char
.AsciiChar
;
1645 Length
= Request
->Data
.FillOutputRequest
.Length
;
1651 if (++X
== Buff
->MaxX
)
1653 if (++Y
== Buff
->MaxY
)
1656 Buffer
= Buff
->Buffer
;
1662 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1664 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputRequest
.Position
,
1665 Request
->Data
.FillOutputRequest
.Length
);
1666 ConioDrawRegion(Console
, &UpdateRect
);
1669 ConioUnlockScreenBuffer(Buff
);
1670 if (NULL
!= Console
)
1672 ConioUnlockConsole(Console
);
1675 return Request
->Status
;
1678 CSR_API(CsrReadInputEvent
)
1680 PLIST_ENTRY CurrentEntry
;
1681 PCSRSS_CONSOLE Console
;
1683 BOOLEAN Done
= FALSE
;
1684 ConsoleInput
*Input
;
1686 DPRINT("CsrReadInputEvent\n");
1688 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1689 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1690 Request
->Data
.ReadInputRequest
.Event
= ProcessData
->ConsoleEvent
;
1692 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadInputRequest
.ConsoleHandle
, &Console
);
1693 if (! NT_SUCCESS(Status
))
1695 return Request
->Status
= Status
;
1698 /* only get input if there is any */
1699 CurrentEntry
= Console
->InputEvents
.Flink
;
1700 while (CurrentEntry
!= &Console
->InputEvents
)
1702 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
1703 CurrentEntry
= CurrentEntry
->Flink
;
1705 if (Done
&& !Input
->Fake
)
1707 Request
->Data
.ReadInputRequest
.MoreEvents
= TRUE
;
1711 RemoveEntryList(&Input
->ListEntry
);
1713 if (!Done
&& !Input
->Fake
)
1715 Request
->Data
.ReadInputRequest
.Input
= Input
->InputEvent
;
1716 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
1718 ConioInputEventToAnsi(Console
, &Request
->Data
.ReadInputRequest
.Input
);
1723 if (Input
->InputEvent
.EventType
== KEY_EVENT
)
1725 if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
)
1726 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
1727 && '\r' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1729 Console
->WaitingLines
--;
1731 Console
->WaitingChars
--;
1733 HeapFree(Win32CsrApiHeap
, 0, Input
);
1738 Status
= STATUS_SUCCESS
;
1739 Console
->EarlyReturn
= FALSE
;
1743 Status
= STATUS_PENDING
;
1744 Console
->EarlyReturn
= TRUE
; /* mark for early return */
1747 if (IsListEmpty(&Console
->InputEvents
))
1749 ResetEvent(Console
->ActiveEvent
);
1752 ConioUnlockConsole(Console
);
1754 return Request
->Status
= Status
;
1757 CSR_API(CsrWriteConsoleOutputAttrib
)
1759 PCSRSS_CONSOLE Console
;
1760 PCSRSS_SCREEN_BUFFER Buff
;
1761 PUCHAR Buffer
, Attribute
;
1766 DPRINT("CsrWriteConsoleOutputAttrib\n");
1768 if (Request
->Header
.DataSize
1769 < sizeof(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB
) - 1
1770 + Request
->Data
.WriteConsoleOutputAttribRequest
.Length
)
1772 DPRINT1("Invalid request size\n");
1773 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1774 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1775 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1778 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1779 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1780 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1781 if (! NT_SUCCESS(Status
))
1783 return Request
->Status
= Status
;
1786 Status
= ConioLockScreenBuffer(ProcessData
,
1787 Request
->Data
.WriteConsoleOutputAttribRequest
.ConsoleHandle
,
1789 if (! NT_SUCCESS(Status
))
1791 if (NULL
!= Console
)
1793 ConioUnlockConsole(Console
);
1795 return Request
->Status
= Status
;
1798 X
= Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1799 Y
= (Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1800 Length
= Request
->Data
.WriteConsoleOutputAttribRequest
.Length
;
1801 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + 1];
1802 Attribute
= (PUCHAR
)Request
->Data
.WriteConsoleOutputAttribRequest
.String
;
1805 *Buffer
= *Attribute
++;
1807 if (++X
== Buff
->MaxX
)
1809 if (++Y
== Buff
->MaxY
)
1812 Buffer
= Buff
->Buffer
+ 1;
1818 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1820 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
,
1821 Request
->Data
.WriteConsoleOutputAttribRequest
.Length
);
1822 ConioDrawRegion(Console
, &UpdateRect
);
1825 if (NULL
!= Console
)
1827 ConioUnlockConsole(Console
);
1830 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1831 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1833 ConioUnlockScreenBuffer(Buff
);
1835 return Request
->Status
= STATUS_SUCCESS
;
1838 CSR_API(CsrFillOutputAttrib
)
1840 PCSRSS_SCREEN_BUFFER Buff
;
1846 PCSRSS_CONSOLE Console
;
1848 DPRINT("CsrFillOutputAttrib\n");
1850 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1851 if (! NT_SUCCESS(Status
))
1853 return Request
->Status
= Status
;
1856 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1857 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1858 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputAttribRequest
.ConsoleHandle
, &Buff
);
1859 if (! NT_SUCCESS(Status
))
1861 if (NULL
!= Console
)
1863 ConioUnlockConsole(Console
);
1865 return Request
->Status
= Status
;
1868 X
= Request
->Data
.FillOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1869 Y
= (Request
->Data
.FillOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1870 Length
= Request
->Data
.FillOutputAttribRequest
.Length
;
1871 Attr
= Request
->Data
.FillOutputAttribRequest
.Attribute
;
1872 Buffer
= &Buff
->Buffer
[(Y
* Buff
->MaxX
* 2) + (X
* 2) + 1];
1877 if (++X
== Buff
->MaxX
)
1879 if (++Y
== Buff
->MaxY
)
1882 Buffer
= Buff
->Buffer
+ 1;
1888 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1890 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputAttribRequest
.Coord
,
1891 Request
->Data
.FillOutputAttribRequest
.Length
);
1892 ConioDrawRegion(Console
, &UpdateRect
);
1895 ConioUnlockScreenBuffer(Buff
);
1896 if (NULL
!= Console
)
1898 ConioUnlockConsole(Console
);
1901 return Request
->Status
= STATUS_SUCCESS
;
1905 CSR_API(CsrGetCursorInfo
)
1907 PCSRSS_SCREEN_BUFFER Buff
;
1910 DPRINT("CsrGetCursorInfo\n");
1912 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1913 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1915 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.GetCursorInfoRequest
.ConsoleHandle
, &Buff
);
1916 if (! NT_SUCCESS(Status
))
1918 return Request
->Status
= Status
;
1920 Request
->Data
.GetCursorInfoRequest
.Info
= Buff
->CursorInfo
;
1921 ConioUnlockScreenBuffer(Buff
);
1923 return Request
->Status
= STATUS_SUCCESS
;
1926 CSR_API(CsrSetCursorInfo
)
1928 PCSRSS_CONSOLE Console
;
1929 PCSRSS_SCREEN_BUFFER Buff
;
1934 DPRINT("CsrSetCursorInfo\n");
1936 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
1937 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
1939 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1940 if (! NT_SUCCESS(Status
))
1942 return Request
->Status
= Status
;
1945 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorInfoRequest
.ConsoleHandle
, &Buff
);
1946 if (! NT_SUCCESS(Status
))
1948 if (NULL
!= Console
)
1950 ConioUnlockConsole(Console
);
1952 return Request
->Status
= Status
;
1955 Size
= Request
->Data
.SetCursorInfoRequest
.Info
.dwSize
;
1956 Visible
= Request
->Data
.SetCursorInfoRequest
.Info
.bVisible
;
1966 if (Size
!= Buff
->CursorInfo
.dwSize
1967 || (Visible
&& ! Buff
->CursorInfo
.bVisible
) || (! Visible
&& Buff
->CursorInfo
.bVisible
))
1969 Buff
->CursorInfo
.dwSize
= Size
;
1970 Buff
->CursorInfo
.bVisible
= Visible
;
1972 if (NULL
!= Console
&& ! ConioSetCursorInfo(Console
, Buff
))
1974 ConioUnlockScreenBuffer(Buff
);
1975 ConioUnlockConsole(Console
);
1976 return Request
->Status
= STATUS_UNSUCCESSFUL
;
1980 ConioUnlockScreenBuffer(Buff
);
1981 if (NULL
!= Console
)
1983 ConioUnlockConsole(Console
);
1986 return Request
->Status
= STATUS_SUCCESS
;
1989 CSR_API(CsrSetTextAttrib
)
1992 PCSRSS_CONSOLE Console
;
1993 PCSRSS_SCREEN_BUFFER Buff
;
1994 LONG OldCursorX
, OldCursorY
;
1996 DPRINT("CsrSetTextAttrib\n");
1998 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1999 if (! NT_SUCCESS(Status
))
2001 return Request
->Status
= Status
;
2004 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
);
2005 if (! NT_SUCCESS(Status
))
2007 if (NULL
!= Console
)
2009 ConioUnlockConsole(Console
);
2011 return Request
->Status
= Status
;
2014 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &OldCursorX
, &OldCursorY
);
2016 Buff
->DefaultAttrib
= Request
->Data
.SetAttribRequest
.Attrib
;
2017 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
2019 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
2021 ConioUnlockScreenBuffer(Buff
);
2022 ConioUnlockConsole(Console
);
2023 return Request
->Status
= STATUS_UNSUCCESSFUL
;
2027 ConioUnlockScreenBuffer(Buff
);
2028 if (NULL
!= Console
)
2030 ConioUnlockConsole(Console
);
2033 return Request
->Status
= STATUS_SUCCESS
;
2036 CSR_API(CsrSetConsoleMode
)
2039 PCSRSS_CONSOLE Console
;
2040 PCSRSS_SCREEN_BUFFER Buff
;
2042 DPRINT("CsrSetConsoleMode\n");
2044 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2045 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2046 Status
= Win32CsrGetObject(ProcessData
,
2047 Request
->Data
.SetConsoleModeRequest
.ConsoleHandle
,
2048 (Object_t
**) &Console
);
2049 if (! NT_SUCCESS(Status
))
2051 return Request
->Status
= Status
;
2054 Buff
= (PCSRSS_SCREEN_BUFFER
)Console
;
2055 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
2057 Console
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_INPUT_MODE_VALID
;
2059 else if (CONIO_SCREEN_BUFFER_MAGIC
== Console
->Header
.Type
)
2061 Buff
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_OUTPUT_MODE_VALID
;
2065 return Request
->Status
= STATUS_INVALID_HANDLE
;
2068 Request
->Status
= STATUS_SUCCESS
;
2070 return Request
->Status
;
2073 CSR_API(CsrGetConsoleMode
)
2076 PCSRSS_CONSOLE Console
;
2077 PCSRSS_SCREEN_BUFFER Buff
; /* gee, I really wish I could use an anonymous union here */
2079 DPRINT("CsrGetConsoleMode\n");
2081 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2082 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2083 Status
= Win32CsrGetObject(ProcessData
, Request
->Data
.GetConsoleModeRequest
.ConsoleHandle
,
2084 (Object_t
**) &Console
);
2085 if (! NT_SUCCESS(Status
))
2087 return Request
->Status
= Status
;
2089 Request
->Status
= STATUS_SUCCESS
;
2090 Buff
= (PCSRSS_SCREEN_BUFFER
) Console
;
2091 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
2093 Request
->Data
.GetConsoleModeRequest
.ConsoleMode
= Console
->Mode
;
2095 else if (CONIO_SCREEN_BUFFER_MAGIC
== Buff
->Header
.Type
)
2097 Request
->Data
.GetConsoleModeRequest
.ConsoleMode
= Buff
->Mode
;
2101 Request
->Status
= STATUS_INVALID_HANDLE
;
2104 return Request
->Status
;
2107 CSR_API(CsrCreateScreenBuffer
)
2109 PCSRSS_CONSOLE Console
;
2110 PCSRSS_SCREEN_BUFFER Buff
;
2113 DPRINT("CsrCreateScreenBuffer\n");
2115 if (ProcessData
== NULL
)
2117 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2120 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2121 if (! NT_SUCCESS(Status
))
2123 return Request
->Status
= Status
;
2125 if (NULL
== Console
)
2127 return Request
->Status
= STATUS_INVALID_HANDLE
;
2130 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2131 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2133 Buff
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(CSRSS_SCREEN_BUFFER
));
2136 Request
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2139 Status
= CsrInitConsoleScreenBuffer(Console
, Buff
);
2140 if(! NT_SUCCESS(Status
))
2142 Request
->Status
= Status
;
2146 Request
->Status
= Win32CsrInsertObject(ProcessData
, &Request
->Data
.CreateScreenBufferRequest
.OutputHandle
, &Buff
->Header
);
2149 ConioUnlockConsole(Console
);
2151 return Request
->Status
;
2154 CSR_API(CsrSetScreenBuffer
)
2157 PCSRSS_CONSOLE Console
;
2158 PCSRSS_SCREEN_BUFFER Buff
;
2160 DPRINT("CsrSetScreenBuffer\n");
2162 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2163 if (! NT_SUCCESS(Status
))
2165 return Request
->Status
= Status
;
2167 if (NULL
== Console
)
2169 DPRINT1("Trying to set screen buffer for app without console\n");
2170 return Request
->Status
= STATUS_INVALID_HANDLE
;
2173 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2174 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2176 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetScreenBufferRequest
.OutputHandle
, &Buff
);
2177 if (! NT_SUCCESS(Status
))
2179 ConioUnlockConsole(Console
);
2180 return Request
->Status
;
2183 if (Buff
== Console
->ActiveBuffer
)
2185 ConioUnlockScreenBuffer(Buff
);
2186 ConioUnlockConsole(Console
);
2187 return STATUS_SUCCESS
;
2190 /* drop reference to old buffer, maybe delete */
2191 if (! InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
2193 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
2195 /* tie console to new buffer */
2196 Console
->ActiveBuffer
= Buff
;
2197 /* inc ref count on new buffer */
2198 InterlockedIncrement(&Buff
->Header
.ReferenceCount
);
2199 /* Redraw the console */
2200 ConioDrawConsole(Console
);
2202 ConioUnlockScreenBuffer(Buff
);
2203 ConioUnlockConsole(Console
);
2205 return Request
->Status
= STATUS_SUCCESS
;
2208 CSR_API(CsrSetTitle
)
2211 PCSRSS_CONSOLE Console
;
2213 DPRINT("CsrSetTitle\n");
2215 if (Request
->Header
.DataSize
2216 < sizeof(CSRSS_SET_TITLE
) - 1
2217 + Request
->Data
.SetTitleRequest
.Length
)
2219 DPRINT1("Invalid request size\n");
2220 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2221 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2222 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2225 Status
= ConioLockConsole(ProcessData
, Request
->Data
.SetTitleRequest
.Console
, &Console
);
2226 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2227 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2228 if(! NT_SUCCESS(Status
))
2230 Request
->Status
= Status
;
2234 /* copy title to console */
2235 RtlFreeUnicodeString(&Console
->Title
);
2236 RtlCreateUnicodeString(&Console
->Title
, Request
->Data
.SetTitleRequest
.Title
);
2237 if (! ConioChangeTitle(Console
))
2239 Request
->Status
= STATUS_UNSUCCESSFUL
;
2243 Request
->Status
= STATUS_SUCCESS
;
2246 ConioUnlockConsole(Console
);
2248 return Request
->Status
;
2251 CSR_API(CsrGetTitle
)
2254 PCSRSS_CONSOLE Console
;
2256 DPRINT("CsrGetTitle\n");
2258 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2259 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2260 Status
= ConioLockConsole(ProcessData
,
2261 Request
->Data
.GetTitleRequest
.ConsoleHandle
,
2263 if (! NT_SUCCESS(Status
))
2265 DPRINT1("Can't get console\n");
2266 return Request
->Status
= Status
;
2269 /* Copy title of the console to the user title buffer */
2270 RtlZeroMemory(&Request
->Data
.GetTitleRequest
, sizeof(CSRSS_GET_TITLE
));
2271 Request
->Data
.GetTitleRequest
.ConsoleHandle
= Request
->Data
.GetTitleRequest
.ConsoleHandle
;
2272 Request
->Data
.GetTitleRequest
.Length
= Console
->Title
.Length
;
2273 wcscpy (Request
->Data
.GetTitleRequest
.Title
, Console
->Title
.Buffer
);
2274 Request
->Header
.MessageSize
+= Console
->Title
.Length
;
2275 Request
->Header
.DataSize
+= Console
->Title
.Length
;
2276 Request
->Status
= STATUS_SUCCESS
;
2278 ConioUnlockConsole(Console
);
2280 return Request
->Status
;
2283 CSR_API(CsrWriteConsoleOutput
)
2285 SHORT i
, X
, Y
, SizeX
, SizeY
;
2286 PCSRSS_CONSOLE Console
;
2287 PCSRSS_SCREEN_BUFFER Buff
;
2289 CHAR_INFO
* CurCharInfo
;
2291 CHAR_INFO
* CharInfo
;
2298 DPRINT("CsrWriteConsoleOutput\n");
2300 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2301 if (! NT_SUCCESS(Status
))
2303 return Request
->Status
= Status
;
2306 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2307 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2308 Status
= ConioLockScreenBuffer(ProcessData
,
2309 Request
->Data
.WriteConsoleOutputRequest
.ConsoleHandle
,
2311 if (! NT_SUCCESS(Status
))
2313 if (NULL
!= Console
)
2315 ConioUnlockConsole(Console
);
2317 return Request
->Status
= Status
;
2320 BufferSize
= Request
->Data
.WriteConsoleOutputRequest
.BufferSize
;
2321 PSize
= BufferSize
.X
* BufferSize
.Y
* sizeof(CHAR_INFO
);
2322 BufferCoord
= Request
->Data
.WriteConsoleOutputRequest
.BufferCoord
;
2323 CharInfo
= Request
->Data
.WriteConsoleOutputRequest
.CharInfo
;
2324 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
) ||
2325 (((ULONG_PTR
)CharInfo
+ PSize
) >
2326 ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2328 ConioUnlockScreenBuffer(Buff
);
2329 ConioUnlockConsole(Console
);
2330 return Request
->Status
= STATUS_ACCESS_VIOLATION
;
2332 WriteRegion
.left
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
;
2333 WriteRegion
.top
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
;
2334 WriteRegion
.right
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
;
2335 WriteRegion
.bottom
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
;
2337 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&WriteRegion
));
2338 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&WriteRegion
));
2339 WriteRegion
.bottom
= WriteRegion
.top
+ SizeY
- 1;
2340 WriteRegion
.right
= WriteRegion
.left
+ SizeX
- 1;
2342 /* Make sure WriteRegion is inside the screen buffer */
2343 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2344 if (! ConioGetIntersection(&WriteRegion
, &ScreenBuffer
, &WriteRegion
))
2346 ConioUnlockScreenBuffer(Buff
);
2347 ConioUnlockConsole(Console
);
2349 /* It is okay to have a WriteRegion completely outside the screen buffer.
2350 No data is written then. */
2351 return Request
->Status
= STATUS_SUCCESS
;
2354 for (i
= 0, Y
= WriteRegion
.top
; Y
<= WriteRegion
.bottom
; i
++, Y
++)
2356 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
2357 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ WriteRegion
.left
) * 2;
2358 for (X
= WriteRegion
.left
; X
<= WriteRegion
.right
; X
++)
2360 if (Request
->Data
.WriteConsoleOutputRequest
.Unicode
)
2363 ConsoleUnicodeCharToAnsiChar(Console
, &AsciiChar
, &CurCharInfo
->Char
.UnicodeChar
);
2364 SET_CELL_BUFFER(Buff
, Offset
, AsciiChar
, CurCharInfo
->Attributes
);
2368 SET_CELL_BUFFER(Buff
, Offset
, CurCharInfo
->Char
.AsciiChar
, CurCharInfo
->Attributes
);
2374 if (NULL
!= Console
)
2376 ConioDrawRegion(Console
, &WriteRegion
);
2379 ConioUnlockScreenBuffer(Buff
);
2380 ConioUnlockConsole(Console
);
2382 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
= WriteRegion
.left
+ SizeX
- 1;
2383 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
= WriteRegion
.top
+ SizeY
- 1;
2384 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
= WriteRegion
.left
;
2385 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
= WriteRegion
.top
;
2387 return Request
->Status
= STATUS_SUCCESS
;
2390 CSR_API(CsrFlushInputBuffer
)
2392 PLIST_ENTRY CurrentEntry
;
2393 PCSRSS_CONSOLE Console
;
2394 ConsoleInput
* Input
;
2397 DPRINT("CsrFlushInputBuffer\n");
2399 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2400 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2401 Status
= ConioLockConsole(ProcessData
,
2402 Request
->Data
.FlushInputBufferRequest
.ConsoleInput
,
2404 if(! NT_SUCCESS(Status
))
2406 return Request
->Status
= Status
;
2409 /* Discard all entries in the input event queue */
2410 while (!IsListEmpty(&Console
->InputEvents
))
2412 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
2413 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
2414 /* Destroy the event */
2415 HeapFree(Win32CsrApiHeap
, 0, Input
);
2417 ResetEvent(Console
->ActiveEvent
);
2418 Console
->WaitingChars
=0;
2420 ConioUnlockConsole(Console
);
2422 return Request
->Status
= STATUS_SUCCESS
;
2425 CSR_API(CsrScrollConsoleScreenBuffer
)
2427 PCSRSS_CONSOLE Console
;
2428 PCSRSS_SCREEN_BUFFER Buff
;
2433 RECT ScrollRectangle
;
2438 DPRINT("CsrScrollConsoleScreenBuffer\n");
2440 ALIAS(ConsoleHandle
,Request
->Data
.ScrollConsoleScreenBufferRequest
.ConsoleHandle
);
2441 ALIAS(UseClipRectangle
,Request
->Data
.ScrollConsoleScreenBufferRequest
.UseClipRectangle
);
2442 ALIAS(DestinationOrigin
,Request
->Data
.ScrollConsoleScreenBufferRequest
.DestinationOrigin
);
2443 ALIAS(Fill
,Request
->Data
.ScrollConsoleScreenBufferRequest
.Fill
);
2445 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2446 if (! NT_SUCCESS(Status
))
2448 return Request
->Status
= Status
;
2451 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2452 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2453 Status
= ConioLockScreenBuffer(ProcessData
, ConsoleHandle
, &Buff
);
2454 if (! NT_SUCCESS(Status
))
2456 if (NULL
!= Console
)
2458 ConioUnlockConsole(Console
);
2460 return Request
->Status
= Status
;
2463 ScrollRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Left
;
2464 ScrollRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Top
;
2465 ScrollRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Right
;
2466 ScrollRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Bottom
;
2467 ClipRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Left
;
2468 ClipRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Top
;
2469 ClipRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Right
;
2470 ClipRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Bottom
;
2472 /* Make sure source rectangle is inside the screen buffer */
2473 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2474 if (! ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, &ScrollRectangle
))
2476 ConioUnlockScreenBuffer(Buff
);
2477 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2480 if (UseClipRectangle
&& ! ConioGetIntersection(&SrcRegion
, &SrcRegion
, &ClipRectangle
))
2482 ConioUnlockScreenBuffer(Buff
);
2483 return Request
->Status
= STATUS_SUCCESS
;
2487 ConioInitRect(&DstRegion
,
2488 DestinationOrigin
.Y
,
2489 DestinationOrigin
.X
,
2490 DestinationOrigin
.Y
+ ConioRectHeight(&ScrollRectangle
) - 1,
2491 DestinationOrigin
.X
+ ConioRectWidth(&ScrollRectangle
) - 1);
2493 /* Make sure destination rectangle is inside the screen buffer */
2494 if (! ConioGetIntersection(&DstRegion
, &DstRegion
, &ScreenBuffer
))
2496 ConioUnlockScreenBuffer(Buff
);
2497 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2500 ConioCopyRegion(Buff
, &SrcRegion
, &DstRegion
);
2502 /* Get the region that should be filled with the specified character and attributes */
2506 ConioGetUnion(&FillRegion
, &SrcRegion
, &DstRegion
);
2508 if (ConioSubtractRect(&FillRegion
, &FillRegion
, &DstRegion
))
2510 /* FIXME: The subtracted rectangle is off by one line */
2511 FillRegion
.top
+= 1;
2513 ConioFillRegion(Console
, Buff
, &FillRegion
, &Fill
, Request
->Data
.ScrollConsoleScreenBufferRequest
.Unicode
);
2517 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
2519 /* Draw destination region */
2520 ConioDrawRegion(Console
, &DstRegion
);
2524 /* Draw filled region */
2525 ConioDrawRegion(Console
, &FillRegion
);
2529 ConioUnlockScreenBuffer(Buff
);
2530 if (NULL
!= Console
)
2532 ConioUnlockConsole(Console
);
2535 return Request
->Status
= STATUS_SUCCESS
;
2538 CSR_API(CsrReadConsoleOutputChar
)
2541 PCSRSS_CONSOLE Console
;
2542 PCSRSS_SCREEN_BUFFER Buff
;
2549 DPRINT("CsrReadConsoleOutputChar\n");
2551 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2552 Request
->Header
.DataSize
= Request
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
2553 ReadBuffer
= Request
->Data
.ReadConsoleOutputCharRequest
.String
;
2555 CharSize
= (Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
2557 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2558 if (! NT_SUCCESS(Status
))
2560 return Request
->Status
= Status
;
2563 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputCharRequest
.ConsoleHandle
, &Buff
);
2564 if (! NT_SUCCESS(Status
))
2566 return Request
->Status
= Status
;
2569 Xpos
= Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.X
+ Buff
->ShowX
;
2570 Ypos
= (Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
2572 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
; ++i
)
2574 Char
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
)];
2576 if(Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
)
2578 ConsoleAnsiCharToUnicodeChar(Console
, (WCHAR
*)ReadBuffer
, &Char
);
2579 ReadBuffer
+= sizeof(WCHAR
);
2582 *(ReadBuffer
++) = Char
;
2586 if (Xpos
== Buff
->MaxX
)
2591 if (Ypos
== Buff
->MaxY
)
2599 Request
->Status
= STATUS_SUCCESS
;
2600 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.X
= Xpos
- Buff
->ShowX
;
2601 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.Y
= (Ypos
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
;
2602 Request
->Header
.MessageSize
+= Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
;
2603 Request
->Header
.DataSize
+= Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
;
2605 ConioUnlockScreenBuffer(Buff
);
2606 if (NULL
!= Console
)
2608 ConioUnlockConsole(Console
);
2611 Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
= (DWORD
)((ULONG_PTR
)ReadBuffer
- (ULONG_PTR
)Request
->Data
.ReadConsoleOutputCharRequest
.String
) / CharSize
;
2613 return Request
->Status
;
2617 CSR_API(CsrReadConsoleOutputAttrib
)
2620 PCSRSS_SCREEN_BUFFER Buff
;
2625 DPRINT("CsrReadConsoleOutputAttrib\n");
2627 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2628 Request
->Header
.DataSize
= Request
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
2629 ReadBuffer
= Request
->Data
.ReadConsoleOutputAttribRequest
.String
;
2631 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputAttribRequest
.ConsoleHandle
, &Buff
);
2632 if (! NT_SUCCESS(Status
))
2634 return Request
->Status
= Status
;
2637 Xpos
= Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.X
+ Buff
->ShowX
;
2638 Ypos
= (Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
2640 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
; ++i
)
2642 *ReadBuffer
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
) + 1];
2647 if (Xpos
== Buff
->MaxX
)
2652 if (Ypos
== Buff
->MaxY
)
2661 Request
->Status
= STATUS_SUCCESS
;
2662 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.X
= Xpos
- Buff
->ShowX
;
2663 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.Y
= (Ypos
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
;
2664 Request
->Header
.MessageSize
+= Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
;
2665 Request
->Header
.DataSize
+= Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
;
2667 ConioUnlockScreenBuffer(Buff
);
2669 return Request
->Status
;
2673 CSR_API(CsrGetNumberOfConsoleInputEvents
)
2676 PCSRSS_CONSOLE Console
;
2677 PLIST_ENTRY CurrentItem
;
2679 ConsoleInput
*Input
;
2681 DPRINT("CsrGetNumberOfConsoleInputEvents\n");
2683 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2684 Request
->Header
.DataSize
= Request
->Header
.MessageSize
- LPC_MESSAGE_BASE_SIZE
;
2686 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
);
2687 if (! NT_SUCCESS(Status
))
2689 return Request
->Status
= Status
;
2692 CurrentItem
= Console
->InputEvents
.Flink
;
2695 /* If there are any events ... */
2696 while (CurrentItem
!= &Console
->InputEvents
)
2698 Input
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2699 CurrentItem
= CurrentItem
->Flink
;
2706 ConioUnlockConsole(Console
);
2708 Request
->Status
= STATUS_SUCCESS
;
2709 Request
->Data
.GetNumInputEventsRequest
.NumInputEvents
= NumEvents
;
2711 return Request
->Status
;
2715 CSR_API(CsrPeekConsoleInput
)
2718 PCSRSS_CONSOLE Console
;
2721 PLIST_ENTRY CurrentItem
;
2722 PINPUT_RECORD InputRecord
;
2726 DPRINT("CsrPeekConsoleInput\n");
2728 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2729 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2731 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
);
2732 if(! NT_SUCCESS(Status
))
2734 return Request
->Status
= Status
;
2737 InputRecord
= Request
->Data
.PeekConsoleInputRequest
.InputRecord
;
2738 Length
= Request
->Data
.PeekConsoleInputRequest
.Length
;
2739 Size
= Length
* sizeof(INPUT_RECORD
);
2741 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2742 || (((ULONG_PTR
)InputRecord
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2744 ConioUnlockConsole(Console
);
2745 Request
->Status
= STATUS_ACCESS_VIOLATION
;
2746 return Request
->Status
;
2751 if (! IsListEmpty(&Console
->InputEvents
))
2753 CurrentItem
= Console
->InputEvents
.Flink
;
2755 while (CurrentItem
!= &Console
->InputEvents
&& NumItems
< Length
)
2757 Item
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2761 CurrentItem
= CurrentItem
->Flink
;
2766 *InputRecord
= Item
->InputEvent
;
2768 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
2770 ConioInputEventToAnsi(Console
, InputRecord
);
2774 CurrentItem
= CurrentItem
->Flink
;
2778 ConioUnlockConsole(Console
);
2780 Request
->Status
= STATUS_SUCCESS
;
2781 Request
->Data
.PeekConsoleInputRequest
.Length
= NumItems
;
2783 return Request
->Status
;
2787 CSR_API(CsrReadConsoleOutput
)
2789 PCHAR_INFO CharInfo
;
2790 PCHAR_INFO CurCharInfo
;
2791 PCSRSS_SCREEN_BUFFER Buff
;
2804 DPRINT("CsrReadConsoleOutput\n");
2806 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2807 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2809 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputRequest
.ConsoleHandle
, &Buff
);
2810 if (! NT_SUCCESS(Status
))
2812 return Request
->Status
= Status
;
2815 CharInfo
= Request
->Data
.ReadConsoleOutputRequest
.CharInfo
;
2816 ReadRegion
.left
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
;
2817 ReadRegion
.top
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
;
2818 ReadRegion
.right
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
;
2819 ReadRegion
.bottom
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
;
2820 BufferSize
= Request
->Data
.ReadConsoleOutputRequest
.BufferSize
;
2821 BufferCoord
= Request
->Data
.ReadConsoleOutputRequest
.BufferCoord
;
2822 Length
= BufferSize
.X
* BufferSize
.Y
;
2823 Size
= Length
* sizeof(CHAR_INFO
);
2825 /* FIXME: Is this correct? */
2826 CodePage
= ProcessData
->Console
->OutputCodePage
;
2828 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
)
2829 || (((ULONG_PTR
)CharInfo
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2831 ConioUnlockScreenBuffer(Buff
);
2832 Request
->Status
= STATUS_ACCESS_VIOLATION
;
2833 return Request
->Status
;
2836 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&ReadRegion
));
2837 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&ReadRegion
));
2838 ReadRegion
.bottom
= ReadRegion
.top
+ SizeY
;
2839 ReadRegion
.right
= ReadRegion
.left
+ SizeX
;
2841 ConioInitRect(&ScreenRect
, 0, 0, Buff
->MaxY
, Buff
->MaxX
);
2842 if (! ConioGetIntersection(&ReadRegion
, &ScreenRect
, &ReadRegion
))
2844 ConioUnlockScreenBuffer(Buff
);
2845 Request
->Status
= STATUS_SUCCESS
;
2846 return Request
->Status
;
2849 for (i
= 0, Y
= ReadRegion
.top
; Y
< ReadRegion
.bottom
; ++i
, ++Y
)
2851 CurCharInfo
= CharInfo
+ (i
* BufferSize
.X
);
2853 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ ReadRegion
.left
) * 2;
2854 for (X
= ReadRegion
.left
; X
< ReadRegion
.right
; ++X
)
2856 if (Request
->Data
.ReadConsoleOutputRequest
.Unicode
)
2858 MultiByteToWideChar(CodePage
, 0,
2859 (PCHAR
)&GET_CELL_BUFFER(Buff
, Offset
), 1,
2860 &CurCharInfo
->Char
.UnicodeChar
, 1);
2864 CurCharInfo
->Char
.AsciiChar
= GET_CELL_BUFFER(Buff
, Offset
);
2866 CurCharInfo
->Attributes
= GET_CELL_BUFFER(Buff
, Offset
);
2871 ConioUnlockScreenBuffer(Buff
);
2873 Request
->Status
= STATUS_SUCCESS
;
2874 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
= ReadRegion
.left
+ SizeX
- 1;
2875 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
= ReadRegion
.top
+ SizeY
- 1;
2876 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
= ReadRegion
.left
;
2877 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
= ReadRegion
.top
;
2879 return Request
->Status
;
2883 CSR_API(CsrWriteConsoleInput
)
2885 PINPUT_RECORD InputRecord
;
2886 PCSRSS_CONSOLE Console
;
2891 ConsoleInput
* Record
;
2893 DPRINT("CsrWriteConsoleInput\n");
2895 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2896 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2898 Status
= ConioLockConsole(ProcessData
, Request
->Data
.WriteConsoleInputRequest
.ConsoleHandle
, &Console
);
2899 if (! NT_SUCCESS(Status
))
2901 return Request
->Status
= Status
;
2904 InputRecord
= Request
->Data
.WriteConsoleInputRequest
.InputRecord
;
2905 Length
= Request
->Data
.WriteConsoleInputRequest
.Length
;
2906 Size
= Length
* sizeof(INPUT_RECORD
);
2908 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2909 || (((ULONG_PTR
)InputRecord
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2911 ConioUnlockConsole(Console
);
2912 Request
->Status
= STATUS_ACCESS_VIOLATION
;
2913 return Request
->Status
;
2916 for (i
= 0; i
< Length
; i
++)
2918 Record
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
2921 ConioUnlockConsole(Console
);
2922 Request
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2923 return Request
->Status
;
2926 Record
->Echoed
= FALSE
;
2927 Record
->Fake
= FALSE
;
2928 Record
->InputEvent
= *InputRecord
++;
2929 if (KEY_EVENT
== Record
->InputEvent
.EventType
)
2931 /* FIXME - convert from unicode to ascii!! */
2932 ConioProcessChar(Console
, Record
);
2936 ConioUnlockConsole(Console
);
2938 Request
->Status
= STATUS_SUCCESS
;
2939 Request
->Data
.WriteConsoleInputRequest
.Length
= i
;
2941 return Request
->Status
;
2944 /**********************************************************************
2945 * HardwareStateProperty
2948 * Set/Get the value of the HardwareState and switch
2949 * between direct video buffer ouput and GDI windowed
2952 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
2953 * object. We use the same object to Request.
2955 * ConsoleHwState has the correct size to be compatible
2956 * with NT's, but values are not.
2958 STATIC NTSTATUS FASTCALL
2959 SetConsoleHardwareState (PCSRSS_CONSOLE Console
, DWORD ConsoleHwState
)
2961 DPRINT1("Console Hardware State: %d\n", ConsoleHwState
);
2963 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED
== ConsoleHwState
)
2964 ||(CONSOLE_HARDWARE_STATE_DIRECT
== ConsoleHwState
))
2966 if (Console
->HardwareState
!= ConsoleHwState
)
2968 /* TODO: implement switching from full screen to windowed mode */
2969 /* TODO: or back; now simply store the hardware state */
2970 Console
->HardwareState
= ConsoleHwState
;
2973 return STATUS_SUCCESS
;
2976 return STATUS_INVALID_PARAMETER_3
; /* Client: (handle, set_get, [mode]) */
2979 CSR_API(CsrHardwareStateProperty
)
2981 PCSRSS_CONSOLE Console
;
2984 DPRINT("CsrHardwareStateProperty\n");
2986 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
2987 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
2989 Status
= ConioLockConsole(ProcessData
,
2990 Request
->Data
.ConsoleHardwareStateRequest
.ConsoleHandle
,
2992 if (! NT_SUCCESS(Status
))
2994 DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
2995 return Request
->Status
= Status
;
2998 switch (Request
->Data
.ConsoleHardwareStateRequest
.SetGet
)
3000 case CONSOLE_HARDWARE_STATE_GET
:
3001 Request
->Data
.ConsoleHardwareStateRequest
.State
= Console
->HardwareState
;
3004 case CONSOLE_HARDWARE_STATE_SET
:
3005 DPRINT("Setting console hardware state.\n");
3006 Request
->Status
= SetConsoleHardwareState(Console
, Request
->Data
.ConsoleHardwareStateRequest
.State
);
3010 Request
->Status
= STATUS_INVALID_PARAMETER_2
; /* Client: (handle, [set_get], mode) */
3014 ConioUnlockConsole(Console
);
3016 return Request
->Status
;
3019 CSR_API(CsrGetConsoleWindow
)
3021 PCSRSS_CONSOLE Console
;
3024 DPRINT("CsrGetConsoleWindow\n");
3026 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
3027 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
3029 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3030 if (! NT_SUCCESS(Status
))
3032 return Request
->Status
= Status
;
3035 Request
->Data
.GetConsoleWindowRequest
.WindowHandle
= Console
->hWindow
;
3036 ConioUnlockConsole(Console
);
3038 return Request
->Status
= STATUS_SUCCESS
;
3041 CSR_API(CsrSetConsoleIcon
)
3043 PCSRSS_CONSOLE Console
;
3046 DPRINT("CsrSetConsoleIcon\n");
3048 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
3049 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
3051 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3052 if (! NT_SUCCESS(Status
))
3054 return Request
->Status
= Status
;
3057 Console
->hWindowIcon
= Request
->Data
.SetConsoleIconRequest
.WindowIcon
;
3058 Request
->Status
= (ConioChangeIcon(Console
) ? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
3059 ConioUnlockConsole(Console
);
3061 return Request
->Status
;
3064 CSR_API(CsrGetConsoleCodePage
)
3066 PCSRSS_CONSOLE Console
;
3069 DPRINT("CsrGetConsoleCodePage\n");
3071 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3072 if (! NT_SUCCESS(Status
))
3074 return Request
->Status
= Status
;
3077 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
3078 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
3079 Request
->Data
.GetConsoleCodePage
.CodePage
= Console
->CodePage
;
3080 ConioUnlockConsole(Console
);
3081 return Request
->Status
= STATUS_SUCCESS
;
3084 CSR_API(CsrSetConsoleCodePage
)
3086 PCSRSS_CONSOLE Console
;
3089 DPRINT("CsrSetConsoleCodePage\n");
3091 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3092 if (! NT_SUCCESS(Status
))
3094 return Request
->Status
= Status
;
3097 Request
->Header
.MessageSize
= sizeof(CSR_API_MESSAGE
);
3098 Request
->Header
.DataSize
= sizeof(CSR_API_MESSAGE
) - LPC_MESSAGE_BASE_SIZE
;
3099 if (IsValidCodePage(Request
->Data
.SetConsoleCodePage
.CodePage
))
3101 Console
->CodePage
= Request
->Data
.SetConsoleCodePage
.CodePage
;
3102 ConioUnlockConsole(Console
);