2 * reactos/subsys/csrss/win32csr/conio.c
4 * Console I/O functions
6 * ReactOS Operating System
9 /* INCLUDES ******************************************************************/
16 /* GLOBALS *******************************************************************/
18 #define ConioInitRect(Rect, Top, Left, Bottom, Right) \
19 ((Rect)->top) = Top; \
20 ((Rect)->left) = Left; \
21 ((Rect)->bottom) = Bottom; \
22 ((Rect)->right) = Right
24 #define ConioIsRectEmpty(Rect) \
25 (((Rect)->left > (Rect)->right) || ((Rect)->top > (Rect)->bottom))
27 #define ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar) \
28 WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
30 #define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
31 WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
33 #define ConsoleAnsiCharToUnicodeChar(Console, sWChar, dChar) \
34 MultiByteToWideChar((Console)->OutputCodePage, 0, (dChar), 1, (sWChar), 1)
37 /* FUNCTIONS *****************************************************************/
40 ConioConsoleFromProcessData(PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_CONSOLE
*Console
)
42 PCSRSS_CONSOLE ProcessConsole
= ProcessData
->Console
;
47 return STATUS_INVALID_HANDLE
;
50 InterlockedIncrement(&ProcessConsole
->Header
.ReferenceCount
);
51 EnterCriticalSection(&(ProcessConsole
->Header
.Lock
));
52 *Console
= ProcessConsole
;
54 return STATUS_SUCCESS
;
58 ConioConsoleCtrlEventTimeout(DWORD Event
, PCSRSS_PROCESS_DATA ProcessData
, DWORD Timeout
)
62 DPRINT("ConioConsoleCtrlEvent Parent ProcessId = %x\n", ProcessData
->ProcessId
);
64 if (ProcessData
->CtrlDispatcher
)
67 Thread
= CreateRemoteThread(ProcessData
->Process
, NULL
, 0,
68 (LPTHREAD_START_ROUTINE
) ProcessData
->CtrlDispatcher
,
69 (PVOID
) Event
, 0, NULL
);
72 DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
75 WaitForSingleObject(Thread
, Timeout
);
81 ConioConsoleCtrlEvent(DWORD Event
, PCSRSS_PROCESS_DATA ProcessData
)
83 ConioConsoleCtrlEventTimeout(Event
, ProcessData
, 0);
87 ConioCoordToPointer(PCSRSS_SCREEN_BUFFER Buff
, ULONG X
, ULONG Y
)
89 return &Buff
->Buffer
[2 * (((Y
+ Buff
->VirtualY
) % Buff
->MaxY
) * Buff
->MaxX
+ X
)];
93 ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff
)
95 PBYTE Ptr
= ConioCoordToPointer(Buff
, 0, Buff
->CurrentY
);
98 for (Pos
= 0; Pos
< Buff
->MaxX
; Pos
++)
102 *Ptr
++ = Buff
->DefaultAttrib
;
106 static NTSTATUS FASTCALL
107 CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console
,
108 PCSRSS_SCREEN_BUFFER Buffer
)
110 DPRINT("CsrInitConsoleScreenBuffer Size X %d Size Y %d\n", Buffer
->MaxX
, Buffer
->MaxY
);
112 Buffer
->Header
.Type
= CONIO_SCREEN_BUFFER_MAGIC
;
113 Buffer
->Header
.ReferenceCount
= 0;
116 Buffer
->VirtualY
= 0;
117 Buffer
->Buffer
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, Buffer
->MaxX
* Buffer
->MaxY
* 2);
118 if (NULL
== Buffer
->Buffer
)
120 return STATUS_INSUFFICIENT_RESOURCES
;
122 InitializeCriticalSection(&Buffer
->Header
.Lock
);
123 ConioInitScreenBuffer(Console
, Buffer
);
124 /* initialize buffer to be empty with default attributes */
125 for (Buffer
->CurrentY
= 0 ; Buffer
->CurrentY
< Buffer
->MaxY
; Buffer
->CurrentY
++)
127 ClearLineBuffer(Buffer
);
129 Buffer
->Mode
= ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
;
130 Buffer
->CurrentX
= 0;
131 Buffer
->CurrentY
= 0;
133 return STATUS_SUCCESS
;
136 static NTSTATUS STDCALL
137 CsrInitConsole(PCSRSS_CONSOLE Console
)
140 SECURITY_ATTRIBUTES SecurityAttributes
;
141 PCSRSS_SCREEN_BUFFER NewBuffer
;
144 Console
->Title
.MaximumLength
= Console
->Title
.Length
= 0;
145 Console
->Title
.Buffer
= NULL
;
148 RtlCreateUnicodeString(&Console
->Title
, L
"Command Prompt");
150 Console
->Header
.ReferenceCount
= 0;
151 Console
->WaitingChars
= 0;
152 Console
->WaitingLines
= 0;
153 Console
->EchoCount
= 0;
154 Console
->Header
.Type
= CONIO_CONSOLE_MAGIC
;
155 Console
->Mode
= ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_PROCESSED_INPUT
| ENABLE_MOUSE_INPUT
;
156 Console
->EarlyReturn
= FALSE
;
157 Console
->ActiveBuffer
= NULL
;
158 InitializeListHead(&Console
->InputEvents
);
159 Console
->CodePage
= GetOEMCP();
160 Console
->OutputCodePage
= GetOEMCP();
162 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
163 SecurityAttributes
.lpSecurityDescriptor
= NULL
;
164 SecurityAttributes
.bInheritHandle
= TRUE
;
166 Console
->ActiveEvent
= CreateEventW(&SecurityAttributes
, TRUE
, FALSE
, NULL
);
167 if (NULL
== Console
->ActiveEvent
)
169 RtlFreeUnicodeString(&Console
->Title
);
170 return STATUS_UNSUCCESSFUL
;
172 Console
->PrivateData
= NULL
;
173 InitializeCriticalSection(&Console
->Header
.Lock
);
175 GuiMode
= DtbgIsDesktopVisible();
177 /* allocate console screen buffer */
178 NewBuffer
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
179 if (NULL
== NewBuffer
)
181 RtlFreeUnicodeString(&Console
->Title
);
182 DeleteCriticalSection(&Console
->Header
.Lock
);
183 CloseHandle(Console
->ActiveEvent
);
184 return STATUS_INSUFFICIENT_RESOURCES
;
186 /* init screen buffer with defaults */
187 NewBuffer
->CursorInfo
.bVisible
= TRUE
;
188 NewBuffer
->CursorInfo
.dwSize
= 5;
189 /* make console active, and insert into console list */
190 Console
->ActiveBuffer
= (PCSRSS_SCREEN_BUFFER
) NewBuffer
;
194 Status
= TuiInitConsole(Console
);
195 if (! NT_SUCCESS(Status
))
197 DPRINT1("Failed to open text-mode console, switching to gui-mode\n");
203 Status
= GuiInitConsole(Console
);
204 if (! NT_SUCCESS(Status
))
206 HeapFree(Win32CsrApiHeap
,0, NewBuffer
);
207 RtlFreeUnicodeString(&Console
->Title
);
208 DeleteCriticalSection(&Console
->Header
.Lock
);
209 CloseHandle(Console
->ActiveEvent
);
210 DPRINT1("GuiInitConsole: failed\n");
215 Status
= CsrInitConsoleScreenBuffer(Console
, NewBuffer
);
216 if (! NT_SUCCESS(Status
))
218 ConioCleanupConsole(Console
);
219 RtlFreeUnicodeString(&Console
->Title
);
220 DeleteCriticalSection(&Console
->Header
.Lock
);
221 CloseHandle(Console
->ActiveEvent
);
222 HeapFree(Win32CsrApiHeap
, 0, NewBuffer
);
223 DPRINT1("CsrInitConsoleScreenBuffer: failed\n");
227 /* add a reference count because the buffer is tied to the console */
228 InterlockedIncrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
);
230 /* copy buffer contents to screen */
231 ConioDrawConsole(Console
);
233 return STATUS_SUCCESS
;
237 CSR_API(CsrAllocConsole
)
239 PCSRSS_CONSOLE Console
;
240 NTSTATUS Status
= STATUS_SUCCESS
;
241 BOOLEAN NewConsole
= FALSE
;
243 DPRINT("CsrAllocConsole\n");
245 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
246 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
248 if (ProcessData
->Console
)
250 DPRINT1("Process already has a console\n");
251 return STATUS_INVALID_PARAMETER
;
254 /* If we don't need a console, then get out of here */
255 if (!Request
->Data
.AllocConsoleRequest
.ConsoleNeeded
)
257 DPRINT("No console needed\n");
258 return STATUS_SUCCESS
;
261 /* If we already have one, then don't create a new one... */
262 if (!Request
->Data
.AllocConsoleRequest
.Console
||
263 Request
->Data
.AllocConsoleRequest
.Console
!= ProcessData
->ParentConsole
)
265 /* Allocate a console structure */
267 Console
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_CONSOLE
));
270 DPRINT1("Not enough memory for console\n");
271 return STATUS_NO_MEMORY
;
273 /* initialize list head */
274 InitializeListHead(&Console
->ProcessList
);
275 /* insert process data required for GUI initialization */
276 InsertHeadList(&Console
->ProcessList
, &ProcessData
->ProcessEntry
);
277 /* Initialize the Console */
278 Status
= CsrInitConsole(Console
);
279 if (!NT_SUCCESS(Status
))
281 DPRINT1("Console init failed\n");
282 HeapFree(Win32CsrApiHeap
, 0, Console
);
288 /* Reuse our current console */
289 Console
= Request
->Data
.AllocConsoleRequest
.Console
;
292 /* Set the Process Console */
293 ProcessData
->Console
= Console
;
295 /* Return it to the caller */
296 Request
->Data
.AllocConsoleRequest
.Console
= Console
;
298 /* Add a reference count because the process is tied to the console */
299 Console
->Header
.ReferenceCount
++;
301 if (NewConsole
|| !ProcessData
->bInheritHandles
)
303 /* Insert the Objects */
304 Status
= Win32CsrInsertObject(ProcessData
,
305 &Request
->Data
.AllocConsoleRequest
.InputHandle
,
307 GENERIC_READ
| GENERIC_WRITE
,
309 if (! NT_SUCCESS(Status
))
311 DPRINT1("Failed to insert object\n");
312 ConioDeleteConsole((Object_t
*) Console
);
313 ProcessData
->Console
= 0;
317 Status
= Win32CsrInsertObject(ProcessData
,
318 &Request
->Data
.AllocConsoleRequest
.OutputHandle
,
319 &Console
->ActiveBuffer
->Header
,
320 GENERIC_READ
| GENERIC_WRITE
,
322 if (!NT_SUCCESS(Status
))
324 DPRINT1("Failed to insert object\n");
325 ConioDeleteConsole((Object_t
*) Console
);
326 Win32CsrReleaseObject(ProcessData
,
327 Request
->Data
.AllocConsoleRequest
.InputHandle
);
328 ProcessData
->Console
= 0;
333 /* Duplicate the Event */
334 if (!DuplicateHandle(GetCurrentProcess(),
335 ProcessData
->Console
->ActiveEvent
,
336 ProcessData
->Process
,
337 &ProcessData
->ConsoleEvent
,
342 DPRINT1("DuplicateHandle() failed: %d\n", GetLastError
);
343 ConioDeleteConsole((Object_t
*) Console
);
344 if (NewConsole
|| !ProcessData
->bInheritHandles
)
346 Win32CsrReleaseObject(ProcessData
,
347 Request
->Data
.AllocConsoleRequest
.OutputHandle
);
348 Win32CsrReleaseObject(ProcessData
,
349 Request
->Data
.AllocConsoleRequest
.InputHandle
);
351 ProcessData
->Console
= 0;
355 /* Set the Ctrl Dispatcher */
356 ProcessData
->CtrlDispatcher
= Request
->Data
.AllocConsoleRequest
.CtrlDispatcher
;
357 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
361 /* Insert into the list if it has not been added */
362 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ProcessEntry
);
365 return STATUS_SUCCESS
;
368 CSR_API(CsrFreeConsole
)
370 PCSRSS_CONSOLE Console
;
373 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
374 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
376 if (ProcessData
->Console
== NULL
)
378 return STATUS_INVALID_PARAMETER
;
381 Console
= ProcessData
->Console
;
382 ProcessData
->Console
= NULL
;
383 RemoveEntryList(&ProcessData
->ProcessEntry
);
384 if (0 == InterlockedDecrement(&Console
->Header
.ReferenceCount
))
386 ConioDeleteConsole((Object_t
*) Console
);
388 return STATUS_SUCCESS
;
392 ConioNextLine(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, UINT
*ScrolledLines
)
394 /* If we hit bottom, slide the viewable screen */
395 if (++Buff
->CurrentY
== Buff
->MaxY
)
398 if (++Buff
->VirtualY
== Buff
->MaxY
)
403 ClearLineBuffer(Buff
);
404 if (UpdateRect
->top
!= 0)
409 UpdateRect
->left
= 0;
410 UpdateRect
->right
= Buff
->MaxX
- 1;
411 UpdateRect
->bottom
= Buff
->CurrentY
;
414 static NTSTATUS FASTCALL
415 ConioWriteConsole(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
,
416 CHAR
*Buffer
, DWORD Length
, BOOL Attrib
)
421 LONG CursorStartX
, CursorStartY
;
424 CursorStartX
= Buff
->CurrentX
;
425 CursorStartY
= Buff
->CurrentY
;
426 UpdateRect
.left
= Buff
->MaxX
;
427 UpdateRect
.top
= Buff
->CurrentY
;
428 UpdateRect
.right
= -1;
429 UpdateRect
.bottom
= Buff
->CurrentY
;
432 for (i
= 0; i
< Length
; i
++)
434 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
437 if (Buffer
[i
] == '\n')
440 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
444 else if (Buffer
[i
] == '\b')
446 /* Only handle BS if we're not on the first pos of the first line */
447 if (0 != Buff
->CurrentX
|| 0 != Buff
->CurrentY
)
449 if (0 == Buff
->CurrentX
)
451 /* slide virtual position up */
452 Buff
->CurrentX
= Buff
->MaxX
- 1;
454 UpdateRect
.top
= min(UpdateRect
.top
, (LONG
)Buff
->CurrentY
);
460 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
462 Ptr
[1] = Buff
->DefaultAttrib
;
463 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
) Buff
->CurrentX
);
464 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
469 else if (Buffer
[i
] == '\r')
472 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
) Buff
->CurrentX
);
473 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
477 else if (Buffer
[i
] == '\t')
481 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
)Buff
->CurrentX
);
482 EndX
= (Buff
->CurrentX
+ 8) & ~7;
483 if (EndX
> Buff
->MaxX
)
487 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
488 while (Buff
->CurrentX
< EndX
)
491 *Ptr
++ = Buff
->DefaultAttrib
;
494 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
- 1);
495 if (Buff
->CurrentX
== Buff
->MaxX
)
497 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
500 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
510 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
)Buff
->CurrentX
);
511 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
512 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
516 Ptr
[1] = Buff
->DefaultAttrib
;
519 if (Buff
->CurrentX
== Buff
->MaxX
)
521 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
524 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
528 Buff
->CurrentX
= CursorStartX
;
533 if (! ConioIsRectEmpty(&UpdateRect
) && Buff
== Console
->ActiveBuffer
)
535 ConioWriteStream(Console
, &UpdateRect
, CursorStartX
, CursorStartY
, ScrolledLines
,
539 return STATUS_SUCCESS
;
542 CSR_API(CsrReadConsole
)
544 PLIST_ENTRY CurrentEntry
;
547 PWCHAR UnicodeBuffer
;
549 ULONG nNumberOfCharsToRead
, CharSize
;
550 PCSRSS_CONSOLE Console
;
553 DPRINT("CsrReadConsole\n");
555 CharSize
= (Request
->Data
.ReadConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
557 /* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */
558 nNumberOfCharsToRead
= min(Request
->Data
.ReadConsoleRequest
.NrCharactersToRead
, CSRSS_MAX_READ_CONSOLE
/ CharSize
);
559 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
560 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
562 Buffer
= Request
->Data
.ReadConsoleRequest
.Buffer
;
563 UnicodeBuffer
= (PWCHAR
)Buffer
;
564 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadConsoleRequest
.ConsoleHandle
,
565 &Console
, GENERIC_READ
);
566 if (! NT_SUCCESS(Status
))
570 Request
->Data
.ReadConsoleRequest
.EventHandle
= ProcessData
->ConsoleEvent
;
571 for (i
= 0; i
< nNumberOfCharsToRead
&& Console
->InputEvents
.Flink
!= &Console
->InputEvents
; i
++)
573 /* remove input event from queue */
574 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
575 if (IsListEmpty(&Console
->InputEvents
))
578 ResetEvent(Console
->ActiveEvent
);
580 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
582 /* only pay attention to valid ascii chars, on key down */
583 if (KEY_EVENT
== Input
->InputEvent
.EventType
584 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
585 && Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
!= '\0')
588 * backspace handling - if we are in charge of echoing it then we handle it here
589 * otherwise we treat it like a normal char.
591 if ('\b' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
&& 0
592 != (Console
->Mode
& ENABLE_ECHO_INPUT
))
594 /* echo if it has not already been done, and either we or the client has chars to be deleted */
596 && (0 != i
|| Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
))
598 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
599 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
603 i
-= 2; /* if we already have something to return, just back it up by 2 */
606 { /* otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer */
607 Console
->WaitingChars
--;
608 ConioUnlockConsole(Console
);
609 HeapFree(Win32CsrApiHeap
, 0, Input
);
610 Request
->Data
.ReadConsoleRequest
.NrCharactersRead
= 0;
611 return STATUS_NOTIFY_CLEANUP
;
614 Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
--;
615 Input
->Echoed
= TRUE
; /* mark as echoed so we don't echo it below */
617 /* do not copy backspace to buffer */
620 if(Request
->Data
.ReadConsoleRequest
.Unicode
)
621 UnicodeBuffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
; /* FIXME */
623 Buffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
;
625 /* echo to screen if enabled and we did not already echo the char */
626 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
)
628 && '\r' != Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
630 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
631 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
638 Console
->WaitingChars
--;
639 HeapFree(Win32CsrApiHeap
, 0, Input
);
641 Request
->Data
.ReadConsoleRequest
.NrCharactersRead
= i
;
644 Status
= STATUS_PENDING
; /* we didn't read anything */
646 else if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
))
648 if (0 == Console
->WaitingLines
||
649 (Request
->Data
.ReadConsoleRequest
.Unicode
? (L
'\n' != UnicodeBuffer
[i
- 1]) : ('\n' != Buffer
[i
- 1])))
651 Status
= STATUS_PENDING
; /* line buffered, didn't get a complete line */
655 Console
->WaitingLines
--;
656 Status
= STATUS_SUCCESS
; /* line buffered, did get a complete line */
661 Status
= STATUS_SUCCESS
; /* not line buffered, did read something */
664 if (Status
== STATUS_PENDING
)
666 Console
->EchoCount
= nNumberOfCharsToRead
- i
;
670 Console
->EchoCount
= 0; /* if the client is no longer waiting on input, do not echo */
673 ConioUnlockConsole(Console
);
675 if (CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE
) + i
* CharSize
> sizeof(CSR_API_MESSAGE
))
677 Request
->Header
.u1
.s1
.TotalLength
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE
) + i
* CharSize
;
678 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
684 BOOLEAN __inline
ConioGetIntersection(
689 if (ConioIsRectEmpty(Rect1
) ||
690 (ConioIsRectEmpty(Rect2
)) ||
691 (Rect1
->top
> Rect2
->bottom
) ||
692 (Rect1
->left
> Rect2
->right
) ||
693 (Rect1
->bottom
< Rect2
->top
) ||
694 (Rect1
->right
< Rect2
->left
))
696 /* The rectangles do not intersect */
697 ConioInitRect(Intersection
, 0, -1, 0, -1);
701 ConioInitRect(Intersection
,
702 max(Rect1
->top
, Rect2
->top
),
703 max(Rect1
->left
, Rect2
->left
),
704 min(Rect1
->bottom
, Rect2
->bottom
),
705 min(Rect1
->right
, Rect2
->right
));
710 BOOLEAN __inline
ConioGetUnion(
715 if (ConioIsRectEmpty(Rect1
))
717 if (ConioIsRectEmpty(Rect2
))
719 ConioInitRect(Union
, 0, -1, 0, -1);
727 else if (ConioIsRectEmpty(Rect2
))
734 min(Rect1
->top
, Rect2
->top
),
735 min(Rect1
->left
, Rect2
->left
),
736 max(Rect1
->bottom
, Rect2
->bottom
),
737 max(Rect1
->right
, Rect2
->right
));
743 /* Move from one rectangle to another. We must be careful about the order that
744 * this is done, to avoid overwriting parts of the source before they are moved. */
746 ConioMoveRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer
,
752 int Width
= ConioRectWidth(SrcRegion
);
753 int Height
= ConioRectHeight(SrcRegion
);
764 /* Moving down: work from bottom up */
765 SY
= SrcRegion
->bottom
;
766 DY
= DstRegion
->bottom
;
769 for (i
= 0; i
< Height
; i
++)
771 PWORD SRow
= (PWORD
)ConioCoordToPointer(ScreenBuffer
, 0, SY
);
772 PWORD DRow
= (PWORD
)ConioCoordToPointer(ScreenBuffer
, 0, DY
);
774 SX
= SrcRegion
->left
;
775 DX
= DstRegion
->left
;
779 /* Moving right: work from right to left */
780 SX
= SrcRegion
->right
;
781 DX
= DstRegion
->right
;
784 for (j
= 0; j
< Width
; j
++)
786 WORD Cell
= SRow
[SX
];
787 if (SX
>= ClipRegion
->left
&& SX
<= ClipRegion
->right
788 && SY
>= ClipRegion
->top
&& SY
<= ClipRegion
->bottom
)
792 if (DX
>= ClipRegion
->left
&& DX
<= ClipRegion
->right
793 && DY
>= ClipRegion
->top
&& DY
<= ClipRegion
->bottom
)
806 ConioInputEventToAnsi(PCSRSS_CONSOLE Console
, PINPUT_RECORD InputEvent
)
808 if (InputEvent
->EventType
== KEY_EVENT
)
810 WCHAR UnicodeChar
= InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
;
811 InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
= 0;
812 ConsoleInputUnicodeCharToAnsiChar(Console
,
813 &InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
,
818 CSR_API(CsrWriteConsole
)
822 PCSRSS_SCREEN_BUFFER Buff
;
823 PCSRSS_CONSOLE Console
;
826 ULONG CharSize
= (Request
->Data
.WriteConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
828 DPRINT("CsrWriteConsole\n");
830 if (Request
->Header
.u1
.s1
.TotalLength
831 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE
)
832 + (Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
* CharSize
))
834 DPRINT1("Invalid request size\n");
835 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
836 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
837 return STATUS_INVALID_PARAMETER
;
839 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
841 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
842 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
844 if (! NT_SUCCESS(Status
))
849 if(Request
->Data
.WriteConsoleRequest
.Unicode
)
851 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
852 (PWCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
,
853 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
,
854 NULL
, 0, NULL
, NULL
);
855 Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
858 WideCharToMultiByte(Console
->OutputCodePage
, 0,
859 (PWCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
,
860 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
,
861 Buffer
, Length
, NULL
, NULL
);
865 Status
= STATUS_NO_MEMORY
;
870 Buffer
= (PCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
;
875 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.WriteConsoleRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
876 if (NT_SUCCESS(Status
))
878 Status
= ConioWriteConsole(Console
, Buff
, Buffer
,
879 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
, TRUE
);
880 if (NT_SUCCESS(Status
))
882 Written
= Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
;
884 ConioUnlockScreenBuffer(Buff
);
886 if (Request
->Data
.WriteConsoleRequest
.Unicode
)
888 RtlFreeHeap(GetProcessHeap(), 0, Buffer
);
891 ConioUnlockConsole(Console
);
893 Request
->Data
.WriteConsoleRequest
.NrCharactersWritten
= Written
;
899 ConioDeleteScreenBuffer(Object_t
*Object
)
901 PCSRSS_SCREEN_BUFFER Buffer
= (PCSRSS_SCREEN_BUFFER
) Object
;
902 DeleteCriticalSection(&Buffer
->Header
.Lock
);
903 HeapFree(Win32CsrApiHeap
, 0, Buffer
->Buffer
);
904 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
908 ConioDrawConsole(PCSRSS_CONSOLE Console
)
912 ConioInitRect(&Region
, 0, 0, Console
->Size
.Y
- 1, Console
->Size
.X
- 1);
914 ConioDrawRegion(Console
, &Region
);
919 ConioDeleteConsole(Object_t
*Object
)
921 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Object
;
924 DPRINT("ConioDeleteConsole\n");
926 /* Drain input event queue */
927 while (Console
->InputEvents
.Flink
!= &Console
->InputEvents
)
929 Event
= (ConsoleInput
*) Console
->InputEvents
.Flink
;
930 Console
->InputEvents
.Flink
= Console
->InputEvents
.Flink
->Flink
;
931 Console
->InputEvents
.Flink
->Flink
->Blink
= &Console
->InputEvents
;
932 HeapFree(Win32CsrApiHeap
, 0, Event
);
935 ConioCleanupConsole(Console
);
936 if (0 == InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
938 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
941 Console
->ActiveBuffer
= NULL
;
943 CloseHandle(Console
->ActiveEvent
);
944 DeleteCriticalSection(&Console
->Header
.Lock
);
945 RtlFreeUnicodeString(&Console
->Title
);
946 IntDeleteAllAliases(Console
->Aliases
);
947 HeapFree(Win32CsrApiHeap
, 0, Console
);
951 CsrInitConsoleSupport(VOID
)
953 DPRINT("CSR: CsrInitConsoleSupport()\n");
955 /* Should call LoadKeyboardLayout */
959 ConioProcessChar(PCSRSS_CONSOLE Console
,
960 ConsoleInput
*KeyEventRecord
)
963 BOOL bClientWake
= FALSE
;
964 ConsoleInput
*TempInput
;
966 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
)))
968 switch(KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
971 /* first add the \r */
972 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
973 updown
= KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
;
974 KeyEventRecord
->Echoed
= FALSE
;
975 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= VK_RETURN
;
976 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\r';
977 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
978 Console
->WaitingChars
++;
979 KeyEventRecord
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
980 if (NULL
== KeyEventRecord
)
982 DPRINT1("Failed to allocate KeyEventRecord\n");
985 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
986 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
= updown
;
987 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= 0;
988 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualScanCode
= 0;
989 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\n';
990 KeyEventRecord
->Fake
= TRUE
;
994 /* add event to the queue */
995 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
996 Console
->WaitingChars
++;
997 /* if line input mode is enabled, only wake the client on enter key down */
998 if (0 == (Console
->Mode
& ENABLE_LINE_INPUT
)
999 || Console
->EarlyReturn
1000 || ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1001 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
))
1003 if ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1005 Console
->WaitingLines
++;
1008 SetEvent(Console
->ActiveEvent
);
1010 KeyEventRecord
->Echoed
= FALSE
;
1011 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
))
1012 && '\b' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1013 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1015 /* walk the input queue looking for a char to backspace */
1016 for (TempInput
= (ConsoleInput
*) Console
->InputEvents
.Blink
;
1017 TempInput
!= (ConsoleInput
*) &Console
->InputEvents
1018 && (KEY_EVENT
== TempInput
->InputEvent
.EventType
1019 || ! TempInput
->InputEvent
.Event
.KeyEvent
.bKeyDown
1020 || '\b' == TempInput
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
);
1021 TempInput
= (ConsoleInput
*) TempInput
->ListEntry
.Blink
)
1025 /* if we found one, delete it, otherwise, wake the client */
1026 if (TempInput
!= (ConsoleInput
*) &Console
->InputEvents
)
1028 /* delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue */
1029 RemoveEntryList(&TempInput
->ListEntry
);
1030 if (TempInput
->Echoed
)
1032 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1033 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1036 HeapFree(Win32CsrApiHeap
, 0, TempInput
);
1037 RemoveEntryList(&KeyEventRecord
->ListEntry
);
1038 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1039 Console
->WaitingChars
-= 2;
1043 SetEvent(Console
->ActiveEvent
);
1048 /* echo chars if we are supposed to and client is waiting for some */
1049 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
) && Console
->EchoCount
1050 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1051 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
1052 && '\r' != KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1054 /* mark the char as already echoed */
1055 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1056 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1058 Console
->EchoCount
--;
1059 KeyEventRecord
->Echoed
= TRUE
;
1063 /* Console->WaitingChars++; */
1064 if (bClientWake
|| 0 == (Console
->Mode
& ENABLE_LINE_INPUT
))
1066 SetEvent(Console
->ActiveEvent
);
1070 static DWORD FASTCALL
1071 ConioGetShiftState(PBYTE KeyState
)
1075 if (KeyState
[VK_CAPITAL
] & 1)
1076 ssOut
|= CAPSLOCK_ON
;
1078 if (KeyState
[VK_NUMLOCK
] & 1)
1079 ssOut
|= NUMLOCK_ON
;
1081 if (KeyState
[VK_SCROLL
] & 1)
1082 ssOut
|= SCROLLLOCK_ON
;
1084 if (KeyState
[VK_SHIFT
] & 0x80)
1085 ssOut
|= SHIFT_PRESSED
;
1087 if (KeyState
[VK_LCONTROL
] & 0x80)
1088 ssOut
|= LEFT_CTRL_PRESSED
;
1089 if (KeyState
[VK_RCONTROL
] & 0x80)
1090 ssOut
|= RIGHT_CTRL_PRESSED
;
1092 if (KeyState
[VK_LMENU
] & 0x80)
1093 ssOut
|= LEFT_ALT_PRESSED
;
1094 if (KeyState
[VK_RMENU
] & 0x80)
1095 ssOut
|= RIGHT_ALT_PRESSED
;
1101 ConioProcessKey(MSG
*msg
, PCSRSS_CONSOLE Console
, BOOL TextMode
)
1103 static BYTE KeyState
[256] = { 0 };
1104 /* MSDN mentions that you should use the last virtual key code received
1105 * when putting a virtual key identity to a WM_CHAR message since multiple
1106 * or translated keys may be involved. */
1107 static UINT LastVirtualKey
= 0;
1109 ConsoleInput
*ConInRec
;
1113 UINT VirtualKeyCode
;
1114 UINT VirtualScanCode
;
1117 ULONG ResultSize
= 0;
1120 VirtualScanCode
= (msg
->lParam
>> 16) & 0xff;
1121 Down
= msg
->message
== WM_KEYDOWN
|| msg
->message
== WM_CHAR
||
1122 msg
->message
== WM_SYSKEYDOWN
|| msg
->message
== WM_SYSCHAR
;
1124 GetKeyboardState(KeyState
);
1125 ShiftState
= ConioGetShiftState(KeyState
);
1127 if (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
)
1129 VirtualKeyCode
= LastVirtualKey
;
1130 UnicodeChar
= msg
->wParam
;
1137 VirtualKeyCode
= msg
->wParam
;
1138 RetChars
= ToUnicodeEx(VirtualKeyCode
,
1145 UnicodeChar
= (1 == RetChars
? Chars
[0] : 0);
1148 if (0 == ResultSize
)
1153 er
.EventType
= KEY_EVENT
;
1154 er
.Event
.KeyEvent
.bKeyDown
= Down
;
1155 er
.Event
.KeyEvent
.wRepeatCount
= RepeatCount
;
1156 er
.Event
.KeyEvent
.uChar
.UnicodeChar
= UnicodeChar
;
1157 er
.Event
.KeyEvent
.dwControlKeyState
= ShiftState
;
1158 er
.Event
.KeyEvent
.wVirtualKeyCode
= VirtualKeyCode
;
1159 er
.Event
.KeyEvent
.wVirtualScanCode
= VirtualScanCode
;
1163 if (0 != (ShiftState
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1164 && VK_TAB
== VirtualKeyCode
)
1168 TuiSwapConsole(ShiftState
& SHIFT_PRESSED
? -1 : 1);
1173 else if (VK_MENU
== VirtualKeyCode
&& ! Down
)
1175 if (TuiSwapConsole(0))
1182 if (NULL
== Console
)
1184 DPRINT1("No Active Console!\n");
1188 ConInRec
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1190 if (NULL
== ConInRec
)
1195 ConInRec
->InputEvent
= er
;
1196 ConInRec
->Fake
= UnicodeChar
&&
1197 (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
&&
1198 msg
->message
!= WM_KEYUP
&& msg
->message
!= WM_SYSKEYUP
);
1199 ConInRec
->NotChar
= (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
);
1200 ConInRec
->Echoed
= FALSE
;
1201 if (ConInRec
->NotChar
)
1202 LastVirtualKey
= msg
->wParam
;
1204 DPRINT ("csrss: %s %s %s %s %02x %02x '%c' %04x\n",
1205 Down
? "down" : "up ",
1206 (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
) ?
1208 ConInRec
->Fake
? "fake" : "real",
1209 ConInRec
->NotChar
? "notc" : "char",
1212 (AsciiChar
>= ' ') ? AsciiChar
: '.',
1215 if (ConInRec
->Fake
&& ConInRec
->NotChar
)
1217 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1221 /* process Ctrl-C and Ctrl-Break */
1222 if (Console
->Mode
& ENABLE_PROCESSED_INPUT
&&
1223 er
.Event
.KeyEvent
.bKeyDown
&&
1224 ((er
.Event
.KeyEvent
.wVirtualKeyCode
== VK_PAUSE
) ||
1225 (er
.Event
.KeyEvent
.wVirtualKeyCode
== 'C')) &&
1226 (er
.Event
.KeyEvent
.dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
)))
1228 PCSRSS_PROCESS_DATA current
;
1229 PLIST_ENTRY current_entry
;
1230 DPRINT1("Console_Api Ctrl-C\n");
1231 current_entry
= Console
->ProcessList
.Flink
;
1232 while (current_entry
!= &Console
->ProcessList
)
1234 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
1235 current_entry
= current_entry
->Flink
;
1236 ConioConsoleCtrlEvent((DWORD
)CTRL_C_EVENT
, current
);
1238 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1242 if (0 != (er
.Event
.KeyEvent
.dwControlKeyState
1243 & (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1244 && (VK_UP
== er
.Event
.KeyEvent
.wVirtualKeyCode
1245 || VK_DOWN
== er
.Event
.KeyEvent
.wVirtualKeyCode
))
1247 if (er
.Event
.KeyEvent
.bKeyDown
)
1249 /* scroll up or down */
1250 if (VK_UP
== er
.Event
.KeyEvent
.wVirtualKeyCode
)
1252 /* only scroll up if there is room to scroll up into */
1253 if (Console
->ActiveBuffer
->CurrentY
!= Console
->ActiveBuffer
->MaxY
- 1)
1255 Console
->ActiveBuffer
->VirtualY
= (Console
->ActiveBuffer
->VirtualY
+
1256 Console
->ActiveBuffer
->MaxY
- 1) %
1257 Console
->ActiveBuffer
->MaxY
;
1258 Console
->ActiveBuffer
->CurrentY
++;
1263 /* only scroll down if there is room to scroll down into */
1264 if (Console
->ActiveBuffer
->CurrentY
!= 0)
1266 Console
->ActiveBuffer
->VirtualY
= (Console
->ActiveBuffer
->VirtualY
+ 1) %
1267 Console
->ActiveBuffer
->MaxY
;
1268 Console
->ActiveBuffer
->CurrentY
--;
1271 ConioDrawConsole(Console
);
1273 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1276 /* FIXME - convert to ascii */
1277 ConioProcessChar(Console
, ConInRec
);
1280 CSR_API(CsrGetScreenBufferInfo
)
1283 PCSRSS_CONSOLE Console
;
1284 PCSRSS_SCREEN_BUFFER Buff
;
1285 PCONSOLE_SCREEN_BUFFER_INFO pInfo
;
1287 DPRINT("CsrGetScreenBufferInfo\n");
1289 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1290 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1292 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1293 if (! NT_SUCCESS(Status
))
1297 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ScreenBufferInfoRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
1298 if (! NT_SUCCESS(Status
))
1300 ConioUnlockConsole(Console
);
1303 pInfo
= &Request
->Data
.ScreenBufferInfoRequest
.Info
;
1304 pInfo
->dwSize
.X
= Buff
->MaxX
;
1305 pInfo
->dwSize
.Y
= Buff
->MaxY
;
1306 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
;
1307 pInfo
->dwCursorPosition
.Y
= Buff
->CurrentY
;
1308 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
1309 pInfo
->srWindow
.Left
= Buff
->ShowX
;
1310 pInfo
->srWindow
.Right
= Buff
->ShowX
+ Console
->Size
.X
- 1;
1311 pInfo
->srWindow
.Top
= Buff
->ShowY
;
1312 pInfo
->srWindow
.Bottom
= Buff
->ShowY
+ Console
->Size
.Y
- 1;
1313 pInfo
->dwMaximumWindowSize
.X
= Buff
->MaxX
;
1314 pInfo
->dwMaximumWindowSize
.Y
= Buff
->MaxY
;
1315 ConioUnlockScreenBuffer(Buff
);
1316 ConioUnlockConsole(Console
);
1318 return STATUS_SUCCESS
;
1321 CSR_API(CsrSetCursor
)
1324 PCSRSS_CONSOLE Console
;
1325 PCSRSS_SCREEN_BUFFER Buff
;
1326 LONG OldCursorX
, OldCursorY
;
1327 LONG NewCursorX
, NewCursorY
;
1329 DPRINT("CsrSetCursor\n");
1331 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1332 if (! NT_SUCCESS(Status
))
1337 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1338 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1340 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1341 if (! NT_SUCCESS(Status
))
1343 ConioUnlockConsole(Console
);
1347 NewCursorX
= Request
->Data
.SetCursorRequest
.Position
.X
;
1348 NewCursorY
= Request
->Data
.SetCursorRequest
.Position
.Y
;
1349 if (NewCursorX
< 0 || NewCursorX
>= Buff
->MaxX
||
1350 NewCursorY
< 0 || NewCursorY
>= Buff
->MaxY
)
1352 ConioUnlockScreenBuffer(Buff
);
1353 ConioUnlockConsole(Console
);
1354 return STATUS_INVALID_PARAMETER
;
1356 OldCursorX
= Buff
->CurrentX
;
1357 OldCursorY
= Buff
->CurrentY
;
1358 Buff
->CurrentX
= NewCursorX
;
1359 Buff
->CurrentY
= NewCursorY
;
1360 if (Buff
== Console
->ActiveBuffer
)
1362 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
1364 ConioUnlockScreenBuffer(Buff
);
1365 ConioUnlockConsole(Console
);
1366 return STATUS_UNSUCCESSFUL
;
1370 ConioUnlockScreenBuffer(Buff
);
1371 ConioUnlockConsole(Console
);
1373 return STATUS_SUCCESS
;
1376 static VOID FASTCALL
1377 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, COORD
*Start
, UINT Length
)
1379 if (Buff
->MaxX
<= Start
->X
+ Length
)
1381 UpdateRect
->left
= 0;
1385 UpdateRect
->left
= Start
->X
;
1387 if (Buff
->MaxX
<= Start
->X
+ Length
)
1389 UpdateRect
->right
= Buff
->MaxX
- 1;
1393 UpdateRect
->right
= Start
->X
+ Length
- 1;
1395 UpdateRect
->top
= Start
->Y
;
1396 UpdateRect
->bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->MaxX
;
1397 if (Buff
->MaxY
<= UpdateRect
->bottom
)
1399 UpdateRect
->bottom
= Buff
->MaxY
- 1;
1403 CSR_API(CsrWriteConsoleOutputChar
)
1406 PCHAR String
, tmpString
= NULL
;
1408 PCSRSS_CONSOLE Console
;
1409 PCSRSS_SCREEN_BUFFER Buff
;
1410 DWORD X
, Y
, Length
, CharSize
, Written
= 0;
1413 DPRINT("CsrWriteConsoleOutputChar\n");
1415 CharSize
= (Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
1417 if (Request
->Header
.u1
.s1
.TotalLength
1418 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR
)
1419 + (Request
->Data
.WriteConsoleOutputCharRequest
.Length
* CharSize
))
1421 DPRINT1("Invalid request size\n");
1422 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1423 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1424 return STATUS_INVALID_PARAMETER
;
1427 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1428 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1429 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1430 if (NT_SUCCESS(Status
))
1432 if(Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
)
1434 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
1435 (PWCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
,
1436 Request
->Data
.WriteConsoleOutputCharRequest
.Length
,
1437 NULL
, 0, NULL
, NULL
);
1438 tmpString
= String
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
1441 WideCharToMultiByte(Console
->OutputCodePage
, 0,
1442 (PWCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
,
1443 Request
->Data
.WriteConsoleOutputCharRequest
.Length
,
1444 String
, Length
, NULL
, NULL
);
1448 Status
= STATUS_NO_MEMORY
;
1453 String
= (PCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
;
1458 Status
= ConioLockScreenBuffer(ProcessData
,
1459 Request
->Data
.WriteConsoleOutputCharRequest
.ConsoleHandle
,
1462 if (NT_SUCCESS(Status
))
1464 X
= Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.X
;
1465 Y
= (Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1466 Length
= Request
->Data
.WriteConsoleOutputCharRequest
.Length
;
1467 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1470 *Buffer
= *String
++;
1473 if (++X
== Buff
->MaxX
)
1475 if (++Y
== Buff
->MaxY
)
1478 Buffer
= Buff
->Buffer
;
1483 if (Buff
== Console
->ActiveBuffer
)
1485 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputCharRequest
.Coord
,
1486 Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
1487 ConioDrawRegion(Console
, &UpdateRect
);
1490 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.X
= X
;
1491 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->VirtualY
) % Buff
->MaxY
;
1493 ConioUnlockScreenBuffer(Buff
);
1495 if (Request
->Data
.WriteConsoleRequest
.Unicode
)
1497 RtlFreeHeap(GetProcessHeap(), 0, tmpString
);
1500 ConioUnlockConsole(Console
);
1502 Request
->Data
.WriteConsoleOutputCharRequest
.NrCharactersWritten
= Written
;
1506 CSR_API(CsrFillOutputChar
)
1509 PCSRSS_CONSOLE Console
;
1510 PCSRSS_SCREEN_BUFFER Buff
;
1511 DWORD X
, Y
, Length
, Written
= 0;
1516 DPRINT("CsrFillOutputChar\n");
1518 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1519 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1521 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1522 if (! NT_SUCCESS(Status
))
1527 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1528 if (! NT_SUCCESS(Status
))
1530 ConioUnlockConsole(Console
);
1534 X
= Request
->Data
.FillOutputRequest
.Position
.X
;
1535 Y
= (Request
->Data
.FillOutputRequest
.Position
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1536 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1537 if(Request
->Data
.FillOutputRequest
.Unicode
)
1538 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &Request
->Data
.FillOutputRequest
.Char
.UnicodeChar
);
1540 Char
= Request
->Data
.FillOutputRequest
.Char
.AsciiChar
;
1541 Length
= Request
->Data
.FillOutputRequest
.Length
;
1547 if (++X
== Buff
->MaxX
)
1549 if (++Y
== Buff
->MaxY
)
1552 Buffer
= Buff
->Buffer
;
1558 if (Buff
== Console
->ActiveBuffer
)
1560 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputRequest
.Position
,
1561 Request
->Data
.FillOutputRequest
.Length
);
1562 ConioDrawRegion(Console
, &UpdateRect
);
1565 ConioUnlockScreenBuffer(Buff
);
1566 ConioUnlockConsole(Console
);
1567 Length
= Request
->Data
.FillOutputRequest
.Length
;
1568 Request
->Data
.FillOutputRequest
.NrCharactersWritten
= Length
;
1569 return STATUS_SUCCESS
;
1572 CSR_API(CsrReadInputEvent
)
1574 PLIST_ENTRY CurrentEntry
;
1575 PCSRSS_CONSOLE Console
;
1577 BOOLEAN Done
= FALSE
;
1578 ConsoleInput
*Input
;
1580 DPRINT("CsrReadInputEvent\n");
1582 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1583 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1584 Request
->Data
.ReadInputRequest
.Event
= ProcessData
->ConsoleEvent
;
1586 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadInputRequest
.ConsoleHandle
, &Console
, GENERIC_READ
);
1587 if (! NT_SUCCESS(Status
))
1592 /* only get input if there is any */
1593 CurrentEntry
= Console
->InputEvents
.Flink
;
1594 while (CurrentEntry
!= &Console
->InputEvents
)
1596 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
1597 CurrentEntry
= CurrentEntry
->Flink
;
1599 if (Done
&& !Input
->Fake
)
1601 Request
->Data
.ReadInputRequest
.MoreEvents
= TRUE
;
1605 RemoveEntryList(&Input
->ListEntry
);
1607 if (!Done
&& !Input
->Fake
)
1609 Request
->Data
.ReadInputRequest
.Input
= Input
->InputEvent
;
1610 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
1612 ConioInputEventToAnsi(Console
, &Request
->Data
.ReadInputRequest
.Input
);
1617 if (Input
->InputEvent
.EventType
== KEY_EVENT
)
1619 if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
)
1620 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
1621 && '\r' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1623 Console
->WaitingLines
--;
1625 Console
->WaitingChars
--;
1627 HeapFree(Win32CsrApiHeap
, 0, Input
);
1632 Status
= STATUS_SUCCESS
;
1633 Console
->EarlyReturn
= FALSE
;
1637 Status
= STATUS_PENDING
;
1638 Console
->EarlyReturn
= TRUE
; /* mark for early return */
1641 if (IsListEmpty(&Console
->InputEvents
))
1643 ResetEvent(Console
->ActiveEvent
);
1646 ConioUnlockConsole(Console
);
1651 CSR_API(CsrWriteConsoleOutputAttrib
)
1653 PCSRSS_CONSOLE Console
;
1654 PCSRSS_SCREEN_BUFFER Buff
;
1661 DPRINT("CsrWriteConsoleOutputAttrib\n");
1663 if (Request
->Header
.u1
.s1
.TotalLength
1664 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB
)
1665 + Request
->Data
.WriteConsoleOutputAttribRequest
.Length
* sizeof(WORD
))
1667 DPRINT1("Invalid request size\n");
1668 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1669 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1670 return STATUS_INVALID_PARAMETER
;
1673 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1674 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1675 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1676 if (! NT_SUCCESS(Status
))
1681 Status
= ConioLockScreenBuffer(ProcessData
,
1682 Request
->Data
.WriteConsoleOutputAttribRequest
.ConsoleHandle
,
1685 if (! NT_SUCCESS(Status
))
1687 ConioUnlockConsole(Console
);
1691 X
= Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.X
;
1692 Y
= (Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1693 Length
= Request
->Data
.WriteConsoleOutputAttribRequest
.Length
;
1694 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + 1];
1695 Attribute
= Request
->Data
.WriteConsoleOutputAttribRequest
.Attribute
;
1698 *Buffer
= (UCHAR
)(*Attribute
++);
1700 if (++X
== Buff
->MaxX
)
1702 if (++Y
== Buff
->MaxY
)
1705 Buffer
= Buff
->Buffer
+ 1;
1711 if (Buff
== Console
->ActiveBuffer
)
1713 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
,
1714 Request
->Data
.WriteConsoleOutputAttribRequest
.Length
);
1715 ConioDrawRegion(Console
, &UpdateRect
);
1718 ConioUnlockConsole(Console
);
1720 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.X
= X
;
1721 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->VirtualY
) % Buff
->MaxY
;
1723 ConioUnlockScreenBuffer(Buff
);
1725 return STATUS_SUCCESS
;
1728 CSR_API(CsrFillOutputAttrib
)
1730 PCSRSS_SCREEN_BUFFER Buff
;
1736 PCSRSS_CONSOLE Console
;
1738 DPRINT("CsrFillOutputAttrib\n");
1740 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1741 if (! NT_SUCCESS(Status
))
1746 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1747 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1748 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputAttribRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1749 if (! NT_SUCCESS(Status
))
1751 ConioUnlockConsole(Console
);
1755 X
= Request
->Data
.FillOutputAttribRequest
.Coord
.X
;
1756 Y
= (Request
->Data
.FillOutputAttribRequest
.Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1757 Length
= Request
->Data
.FillOutputAttribRequest
.Length
;
1758 Attr
= Request
->Data
.FillOutputAttribRequest
.Attribute
;
1759 Buffer
= &Buff
->Buffer
[(Y
* Buff
->MaxX
* 2) + (X
* 2) + 1];
1764 if (++X
== Buff
->MaxX
)
1766 if (++Y
== Buff
->MaxY
)
1769 Buffer
= Buff
->Buffer
+ 1;
1775 if (Buff
== Console
->ActiveBuffer
)
1777 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputAttribRequest
.Coord
,
1778 Request
->Data
.FillOutputAttribRequest
.Length
);
1779 ConioDrawRegion(Console
, &UpdateRect
);
1782 ConioUnlockScreenBuffer(Buff
);
1783 ConioUnlockConsole(Console
);
1785 return STATUS_SUCCESS
;
1789 CSR_API(CsrGetCursorInfo
)
1791 PCSRSS_SCREEN_BUFFER Buff
;
1794 DPRINT("CsrGetCursorInfo\n");
1796 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1797 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1799 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.GetCursorInfoRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
1800 if (! NT_SUCCESS(Status
))
1804 Request
->Data
.GetCursorInfoRequest
.Info
.bVisible
= Buff
->CursorInfo
.bVisible
;
1805 Request
->Data
.GetCursorInfoRequest
.Info
.dwSize
= Buff
->CursorInfo
.dwSize
;
1806 ConioUnlockScreenBuffer(Buff
);
1808 return STATUS_SUCCESS
;
1811 CSR_API(CsrSetCursorInfo
)
1813 PCSRSS_CONSOLE Console
;
1814 PCSRSS_SCREEN_BUFFER Buff
;
1819 DPRINT("CsrSetCursorInfo\n");
1821 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1822 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1824 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1825 if (! NT_SUCCESS(Status
))
1830 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorInfoRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1831 if (! NT_SUCCESS(Status
))
1833 ConioUnlockConsole(Console
);
1837 Size
= Request
->Data
.SetCursorInfoRequest
.Info
.dwSize
;
1838 Visible
= Request
->Data
.SetCursorInfoRequest
.Info
.bVisible
;
1848 if (Size
!= Buff
->CursorInfo
.dwSize
1849 || (Visible
&& ! Buff
->CursorInfo
.bVisible
) || (! Visible
&& Buff
->CursorInfo
.bVisible
))
1851 Buff
->CursorInfo
.dwSize
= Size
;
1852 Buff
->CursorInfo
.bVisible
= Visible
;
1854 if (! ConioSetCursorInfo(Console
, Buff
))
1856 ConioUnlockScreenBuffer(Buff
);
1857 ConioUnlockConsole(Console
);
1858 return STATUS_UNSUCCESSFUL
;
1862 ConioUnlockScreenBuffer(Buff
);
1863 ConioUnlockConsole(Console
);
1865 return STATUS_SUCCESS
;
1868 CSR_API(CsrSetTextAttrib
)
1871 PCSRSS_CONSOLE Console
;
1872 PCSRSS_SCREEN_BUFFER Buff
;
1874 DPRINT("CsrSetTextAttrib\n");
1876 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1877 if (! NT_SUCCESS(Status
))
1882 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1883 if (! NT_SUCCESS(Status
))
1885 ConioUnlockConsole(Console
);
1889 Buff
->DefaultAttrib
= Request
->Data
.SetAttribRequest
.Attrib
;
1890 if (Buff
== Console
->ActiveBuffer
)
1892 if (! ConioUpdateScreenInfo(Console
, Buff
))
1894 ConioUnlockScreenBuffer(Buff
);
1895 ConioUnlockConsole(Console
);
1896 return STATUS_UNSUCCESSFUL
;
1900 ConioUnlockScreenBuffer(Buff
);
1901 ConioUnlockConsole(Console
);
1903 return STATUS_SUCCESS
;
1906 CSR_API(CsrSetConsoleMode
)
1909 PCSRSS_CONSOLE Console
;
1910 PCSRSS_SCREEN_BUFFER Buff
;
1912 DPRINT("CsrSetConsoleMode\n");
1914 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1915 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1916 Status
= Win32CsrGetObject(ProcessData
,
1917 Request
->Data
.SetConsoleModeRequest
.ConsoleHandle
,
1918 (Object_t
**) &Console
, GENERIC_WRITE
);
1919 if (! NT_SUCCESS(Status
))
1924 Buff
= (PCSRSS_SCREEN_BUFFER
)Console
;
1925 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
1927 Console
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_INPUT_MODE_VALID
;
1929 else if (CONIO_SCREEN_BUFFER_MAGIC
== Console
->Header
.Type
)
1931 Buff
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_OUTPUT_MODE_VALID
;
1935 Status
= STATUS_INVALID_HANDLE
;
1938 Win32CsrReleaseObjectByPointer((Object_t
*)Console
);
1943 CSR_API(CsrGetConsoleMode
)
1946 PCSRSS_CONSOLE Console
;
1947 PCSRSS_SCREEN_BUFFER Buff
; /* gee, I really wish I could use an anonymous union here */
1949 DPRINT("CsrGetConsoleMode\n");
1951 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1952 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1953 Status
= Win32CsrGetObject(ProcessData
, Request
->Data
.GetConsoleModeRequest
.ConsoleHandle
,
1954 (Object_t
**) &Console
, GENERIC_READ
);
1955 if (! NT_SUCCESS(Status
))
1959 Status
= STATUS_SUCCESS
;
1960 Buff
= (PCSRSS_SCREEN_BUFFER
) Console
;
1961 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
1963 Request
->Data
.GetConsoleModeRequest
.ConsoleMode
= Console
->Mode
;
1965 else if (CONIO_SCREEN_BUFFER_MAGIC
== Buff
->Header
.Type
)
1967 Request
->Data
.GetConsoleModeRequest
.ConsoleMode
= Buff
->Mode
;
1971 Status
= STATUS_INVALID_HANDLE
;
1974 Win32CsrReleaseObjectByPointer((Object_t
*)Console
);
1978 CSR_API(CsrCreateScreenBuffer
)
1980 PCSRSS_CONSOLE Console
;
1981 PCSRSS_SCREEN_BUFFER Buff
;
1984 DPRINT("CsrCreateScreenBuffer\n");
1986 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1987 if (! NT_SUCCESS(Status
))
1992 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1993 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1995 Buff
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
1999 if (Console
->ActiveBuffer
)
2001 Buff
->MaxX
= Console
->ActiveBuffer
->MaxX
;
2002 Buff
->MaxY
= Console
->ActiveBuffer
->MaxY
;
2003 Buff
->CursorInfo
.bVisible
= Console
->ActiveBuffer
->CursorInfo
.bVisible
;
2004 Buff
->CursorInfo
.dwSize
= Console
->ActiveBuffer
->CursorInfo
.dwSize
;
2008 Buff
->CursorInfo
.bVisible
= TRUE
;
2009 Buff
->CursorInfo
.dwSize
= 5;
2012 if (Buff
->MaxX
== 0)
2017 if (Buff
->MaxY
== 0)
2022 Status
= CsrInitConsoleScreenBuffer(Console
, Buff
);
2023 if(NT_SUCCESS(Status
))
2025 Status
= Win32CsrInsertObject(ProcessData
,
2026 &Request
->Data
.CreateScreenBufferRequest
.OutputHandle
,
2028 Request
->Data
.CreateScreenBufferRequest
.Access
,
2029 Request
->Data
.CreateScreenBufferRequest
.Inheritable
);
2034 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2037 ConioUnlockConsole(Console
);
2041 CSR_API(CsrSetScreenBuffer
)
2044 PCSRSS_CONSOLE Console
;
2045 PCSRSS_SCREEN_BUFFER Buff
;
2047 DPRINT("CsrSetScreenBuffer\n");
2049 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2050 if (! NT_SUCCESS(Status
))
2055 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2056 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2058 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetScreenBufferRequest
.OutputHandle
, &Buff
, GENERIC_WRITE
);
2059 if (! NT_SUCCESS(Status
))
2061 ConioUnlockConsole(Console
);
2065 if (Buff
== Console
->ActiveBuffer
)
2067 ConioUnlockScreenBuffer(Buff
);
2068 ConioUnlockConsole(Console
);
2069 return STATUS_SUCCESS
;
2072 /* drop reference to old buffer, maybe delete */
2073 if (! InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
2075 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
2077 /* tie console to new buffer */
2078 Console
->ActiveBuffer
= Buff
;
2079 /* inc ref count on new buffer */
2080 InterlockedIncrement(&Buff
->Header
.ReferenceCount
);
2081 /* Redraw the console */
2082 ConioDrawConsole(Console
);
2084 ConioUnlockScreenBuffer(Buff
);
2085 ConioUnlockConsole(Console
);
2087 return STATUS_SUCCESS
;
2090 CSR_API(CsrSetTitle
)
2093 PCSRSS_CONSOLE Console
;
2096 DPRINT("CsrSetTitle\n");
2098 if (Request
->Header
.u1
.s1
.TotalLength
2099 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_SET_TITLE
)
2100 + Request
->Data
.SetTitleRequest
.Length
)
2102 DPRINT1("Invalid request size\n");
2103 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2104 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2105 return STATUS_INVALID_PARAMETER
;
2108 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2109 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2110 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2111 if(NT_SUCCESS(Status
))
2113 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, Request
->Data
.SetTitleRequest
.Length
);
2116 /* copy title to console */
2117 RtlFreeUnicodeString(&Console
->Title
);
2118 Console
->Title
.Buffer
= Buffer
;
2119 Console
->Title
.Length
= Console
->Title
.MaximumLength
= Request
->Data
.SetTitleRequest
.Length
;
2120 memcpy(Console
->Title
.Buffer
, Request
->Data
.SetTitleRequest
.Title
, Console
->Title
.Length
);
2121 if (! ConioChangeTitle(Console
))
2123 Status
= STATUS_UNSUCCESSFUL
;
2127 Status
= STATUS_SUCCESS
;
2132 Status
= STATUS_NO_MEMORY
;
2134 ConioUnlockConsole(Console
);
2140 CSR_API(CsrGetTitle
)
2143 PCSRSS_CONSOLE Console
;
2146 DPRINT("CsrGetTitle\n");
2148 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2149 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2150 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2151 if (! NT_SUCCESS(Status
))
2153 DPRINT1("Can't get console\n");
2157 /* Copy title of the console to the user title buffer */
2158 RtlZeroMemory(&Request
->Data
.GetTitleRequest
, sizeof(CSRSS_GET_TITLE
));
2159 Request
->Data
.GetTitleRequest
.Length
= Console
->Title
.Length
;
2160 memcpy (Request
->Data
.GetTitleRequest
.Title
, Console
->Title
.Buffer
,
2161 Console
->Title
.Length
);
2162 Length
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_SET_TITLE
) + Console
->Title
.Length
;
2164 ConioUnlockConsole(Console
);
2166 if (Length
> sizeof(CSR_API_MESSAGE
))
2168 Request
->Header
.u1
.s1
.TotalLength
= Length
;
2169 Request
->Header
.u1
.s1
.DataLength
= Length
- sizeof(PORT_MESSAGE
);
2171 return STATUS_SUCCESS
;
2174 CSR_API(CsrWriteConsoleOutput
)
2176 SHORT i
, X
, Y
, SizeX
, SizeY
;
2177 PCSRSS_CONSOLE Console
;
2178 PCSRSS_SCREEN_BUFFER Buff
;
2180 CHAR_INFO
* CurCharInfo
;
2182 CHAR_INFO
* CharInfo
;
2189 DPRINT("CsrWriteConsoleOutput\n");
2191 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2192 if (! NT_SUCCESS(Status
))
2197 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2198 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2199 Status
= ConioLockScreenBuffer(ProcessData
,
2200 Request
->Data
.WriteConsoleOutputRequest
.ConsoleHandle
,
2203 if (! NT_SUCCESS(Status
))
2205 ConioUnlockConsole(Console
);
2209 BufferSize
= Request
->Data
.WriteConsoleOutputRequest
.BufferSize
;
2210 PSize
= BufferSize
.X
* BufferSize
.Y
* sizeof(CHAR_INFO
);
2211 BufferCoord
= Request
->Data
.WriteConsoleOutputRequest
.BufferCoord
;
2212 CharInfo
= Request
->Data
.WriteConsoleOutputRequest
.CharInfo
;
2213 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
) ||
2214 (((ULONG_PTR
)CharInfo
+ PSize
) >
2215 ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2217 ConioUnlockScreenBuffer(Buff
);
2218 ConioUnlockConsole(Console
);
2219 return STATUS_ACCESS_VIOLATION
;
2221 WriteRegion
.left
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
;
2222 WriteRegion
.top
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
;
2223 WriteRegion
.right
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
;
2224 WriteRegion
.bottom
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
;
2226 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&WriteRegion
));
2227 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&WriteRegion
));
2228 WriteRegion
.bottom
= WriteRegion
.top
+ SizeY
- 1;
2229 WriteRegion
.right
= WriteRegion
.left
+ SizeX
- 1;
2231 /* Make sure WriteRegion is inside the screen buffer */
2232 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2233 if (! ConioGetIntersection(&WriteRegion
, &ScreenBuffer
, &WriteRegion
))
2235 ConioUnlockScreenBuffer(Buff
);
2236 ConioUnlockConsole(Console
);
2238 /* It is okay to have a WriteRegion completely outside the screen buffer.
2239 No data is written then. */
2240 return STATUS_SUCCESS
;
2243 for (i
= 0, Y
= WriteRegion
.top
; Y
<= WriteRegion
.bottom
; i
++, Y
++)
2245 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
2246 Ptr
= ConioCoordToPointer(Buff
, WriteRegion
.left
, Y
);
2247 for (X
= WriteRegion
.left
; X
<= WriteRegion
.right
; X
++)
2250 if (Request
->Data
.WriteConsoleOutputRequest
.Unicode
)
2252 ConsoleUnicodeCharToAnsiChar(Console
, &AsciiChar
, &CurCharInfo
->Char
.UnicodeChar
);
2256 AsciiChar
= CurCharInfo
->Char
.AsciiChar
;
2259 *Ptr
++ = CurCharInfo
->Attributes
;
2264 ConioDrawRegion(Console
, &WriteRegion
);
2266 ConioUnlockScreenBuffer(Buff
);
2267 ConioUnlockConsole(Console
);
2269 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
= WriteRegion
.left
+ SizeX
- 1;
2270 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
= WriteRegion
.top
+ SizeY
- 1;
2271 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
= WriteRegion
.left
;
2272 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
= WriteRegion
.top
;
2274 return STATUS_SUCCESS
;
2277 CSR_API(CsrFlushInputBuffer
)
2279 PLIST_ENTRY CurrentEntry
;
2280 PCSRSS_CONSOLE Console
;
2281 ConsoleInput
* Input
;
2284 DPRINT("CsrFlushInputBuffer\n");
2286 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2287 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2288 Status
= ConioLockConsole(ProcessData
,
2289 Request
->Data
.FlushInputBufferRequest
.ConsoleInput
,
2292 if(! NT_SUCCESS(Status
))
2297 /* Discard all entries in the input event queue */
2298 while (!IsListEmpty(&Console
->InputEvents
))
2300 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
2301 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
2302 /* Destroy the event */
2303 HeapFree(Win32CsrApiHeap
, 0, Input
);
2305 ResetEvent(Console
->ActiveEvent
);
2306 Console
->WaitingChars
=0;
2308 ConioUnlockConsole(Console
);
2310 return STATUS_SUCCESS
;
2313 CSR_API(CsrScrollConsoleScreenBuffer
)
2315 PCSRSS_CONSOLE Console
;
2316 PCSRSS_SCREEN_BUFFER Buff
;
2321 RECT ScrollRectangle
;
2324 HANDLE ConsoleHandle
;
2325 BOOLEAN UseClipRectangle
;
2326 COORD DestinationOrigin
;
2330 DPRINT("CsrScrollConsoleScreenBuffer\n");
2332 ConsoleHandle
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ConsoleHandle
;
2333 UseClipRectangle
= Request
->Data
.ScrollConsoleScreenBufferRequest
.UseClipRectangle
;
2334 DestinationOrigin
= Request
->Data
.ScrollConsoleScreenBufferRequest
.DestinationOrigin
;
2335 Fill
= Request
->Data
.ScrollConsoleScreenBufferRequest
.Fill
;
2337 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2338 if (! NT_SUCCESS(Status
))
2343 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2344 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2345 Status
= ConioLockScreenBuffer(ProcessData
, ConsoleHandle
, &Buff
, GENERIC_WRITE
);
2346 if (! NT_SUCCESS(Status
))
2348 ConioUnlockConsole(Console
);
2352 ScrollRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Left
;
2353 ScrollRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Top
;
2354 ScrollRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Right
;
2355 ScrollRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Bottom
;
2357 /* Make sure source rectangle is inside the screen buffer */
2358 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2359 if (! ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, &ScrollRectangle
))
2361 ConioUnlockScreenBuffer(Buff
);
2362 ConioUnlockConsole(Console
);
2363 return STATUS_SUCCESS
;
2366 /* If the source was clipped on the left or top, adjust the destination accordingly */
2367 if (ScrollRectangle
.left
< 0)
2369 DestinationOrigin
.X
-= ScrollRectangle
.left
;
2371 if (ScrollRectangle
.top
< 0)
2373 DestinationOrigin
.Y
-= ScrollRectangle
.top
;
2376 if (UseClipRectangle
)
2378 ClipRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Left
;
2379 ClipRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Top
;
2380 ClipRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Right
;
2381 ClipRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Bottom
;
2382 if (!ConioGetIntersection(&ClipRectangle
, &ClipRectangle
, &ScreenBuffer
))
2384 ConioUnlockConsole(Console
);
2385 ConioUnlockScreenBuffer(Buff
);
2386 return STATUS_SUCCESS
;
2391 ClipRectangle
= ScreenBuffer
;
2394 ConioInitRect(&DstRegion
,
2395 DestinationOrigin
.Y
,
2396 DestinationOrigin
.X
,
2397 DestinationOrigin
.Y
+ ConioRectHeight(&SrcRegion
) - 1,
2398 DestinationOrigin
.X
+ ConioRectWidth(&SrcRegion
) - 1);
2400 if (Request
->Data
.ScrollConsoleScreenBufferRequest
.Unicode
)
2401 ConsoleUnicodeCharToAnsiChar(Console
, &FillChar
, &Fill
.Char
.UnicodeChar
);
2403 FillChar
= Fill
.Char
.AsciiChar
;
2405 ConioMoveRegion(Buff
, &SrcRegion
, &DstRegion
, &ClipRectangle
, Fill
.Attributes
<< 8 | (BYTE
)FillChar
);
2407 if (Buff
== Console
->ActiveBuffer
)
2409 ConioGetUnion(&UpdateRegion
, &SrcRegion
, &DstRegion
);
2410 if (ConioGetIntersection(&UpdateRegion
, &UpdateRegion
, &ClipRectangle
))
2412 /* Draw update region */
2413 ConioDrawRegion(Console
, &UpdateRegion
);
2417 ConioUnlockScreenBuffer(Buff
);
2418 ConioUnlockConsole(Console
);
2420 return STATUS_SUCCESS
;
2423 CSR_API(CsrReadConsoleOutputChar
)
2426 PCSRSS_CONSOLE Console
;
2427 PCSRSS_SCREEN_BUFFER Buff
;
2434 DPRINT("CsrReadConsoleOutputChar\n");
2436 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2437 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2438 ReadBuffer
= Request
->Data
.ReadConsoleOutputCharRequest
.String
;
2440 CharSize
= (Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
2442 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2443 if (! NT_SUCCESS(Status
))
2448 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputCharRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
2449 if (! NT_SUCCESS(Status
))
2451 ConioUnlockConsole(Console
);
2455 Xpos
= Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.X
;
2456 Ypos
= (Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
2458 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
; ++i
)
2460 Char
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
)];
2462 if(Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
)
2464 ConsoleAnsiCharToUnicodeChar(Console
, (WCHAR
*)ReadBuffer
, &Char
);
2465 ReadBuffer
+= sizeof(WCHAR
);
2468 *(ReadBuffer
++) = Char
;
2472 if (Xpos
== Buff
->MaxX
)
2477 if (Ypos
== Buff
->MaxY
)
2485 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.X
= Xpos
;
2486 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.Y
= (Ypos
- Buff
->VirtualY
+ Buff
->MaxY
) % Buff
->MaxY
;
2488 ConioUnlockScreenBuffer(Buff
);
2489 ConioUnlockConsole(Console
);
2491 Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
= (DWORD
)((ULONG_PTR
)ReadBuffer
- (ULONG_PTR
)Request
->Data
.ReadConsoleOutputCharRequest
.String
) / CharSize
;
2492 if (Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
* CharSize
+ CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR
) > sizeof(CSR_API_MESSAGE
))
2494 Request
->Header
.u1
.s1
.TotalLength
= Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
* CharSize
+ CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR
);
2495 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2498 return STATUS_SUCCESS
;
2502 CSR_API(CsrReadConsoleOutputAttrib
)
2505 PCSRSS_SCREEN_BUFFER Buff
;
2509 DWORD CurrentLength
;
2511 DPRINT("CsrReadConsoleOutputAttrib\n");
2513 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2514 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2515 ReadBuffer
= Request
->Data
.ReadConsoleOutputAttribRequest
.Attribute
;
2517 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputAttribRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
2518 if (! NT_SUCCESS(Status
))
2523 Xpos
= Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.X
;
2524 Ypos
= (Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
2526 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
; ++i
)
2528 *ReadBuffer
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
) + 1];
2533 if (Xpos
== Buff
->MaxX
)
2538 if (Ypos
== Buff
->MaxY
)
2547 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.X
= Xpos
;
2548 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.Y
= (Ypos
- Buff
->VirtualY
+ Buff
->MaxY
) % Buff
->MaxY
;
2550 ConioUnlockScreenBuffer(Buff
);
2552 CurrentLength
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_ATTRIB
)
2553 + Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
* sizeof(WORD
);
2554 if (CurrentLength
> sizeof(CSR_API_MESSAGE
))
2556 Request
->Header
.u1
.s1
.TotalLength
= CurrentLength
;
2557 Request
->Header
.u1
.s1
.DataLength
= CurrentLength
- sizeof(PORT_MESSAGE
);
2560 return STATUS_SUCCESS
;
2564 CSR_API(CsrGetNumberOfConsoleInputEvents
)
2567 PCSRSS_CONSOLE Console
;
2568 PLIST_ENTRY CurrentItem
;
2570 ConsoleInput
*Input
;
2572 DPRINT("CsrGetNumberOfConsoleInputEvents\n");
2574 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2575 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2577 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
, GENERIC_READ
);
2578 if (! NT_SUCCESS(Status
))
2583 CurrentItem
= Console
->InputEvents
.Flink
;
2586 /* If there are any events ... */
2587 while (CurrentItem
!= &Console
->InputEvents
)
2589 Input
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2590 CurrentItem
= CurrentItem
->Flink
;
2597 ConioUnlockConsole(Console
);
2599 Request
->Data
.GetNumInputEventsRequest
.NumInputEvents
= NumEvents
;
2601 return STATUS_SUCCESS
;
2605 CSR_API(CsrPeekConsoleInput
)
2608 PCSRSS_CONSOLE Console
;
2611 PLIST_ENTRY CurrentItem
;
2612 PINPUT_RECORD InputRecord
;
2616 DPRINT("CsrPeekConsoleInput\n");
2618 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2619 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2621 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
, GENERIC_READ
);
2622 if(! NT_SUCCESS(Status
))
2627 InputRecord
= Request
->Data
.PeekConsoleInputRequest
.InputRecord
;
2628 Length
= Request
->Data
.PeekConsoleInputRequest
.Length
;
2629 Size
= Length
* sizeof(INPUT_RECORD
);
2631 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2632 || (((ULONG_PTR
)InputRecord
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2634 ConioUnlockConsole(Console
);
2635 return STATUS_ACCESS_VIOLATION
;
2640 if (! IsListEmpty(&Console
->InputEvents
))
2642 CurrentItem
= Console
->InputEvents
.Flink
;
2644 while (CurrentItem
!= &Console
->InputEvents
&& NumItems
< Length
)
2646 Item
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2650 CurrentItem
= CurrentItem
->Flink
;
2655 *InputRecord
= Item
->InputEvent
;
2657 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
2659 ConioInputEventToAnsi(Console
, InputRecord
);
2663 CurrentItem
= CurrentItem
->Flink
;
2667 ConioUnlockConsole(Console
);
2669 Request
->Data
.PeekConsoleInputRequest
.Length
= NumItems
;
2671 return STATUS_SUCCESS
;
2675 CSR_API(CsrReadConsoleOutput
)
2677 PCHAR_INFO CharInfo
;
2678 PCHAR_INFO CurCharInfo
;
2679 PCSRSS_SCREEN_BUFFER Buff
;
2693 DPRINT("CsrReadConsoleOutput\n");
2695 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2696 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2698 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
2699 if (! NT_SUCCESS(Status
))
2704 CharInfo
= Request
->Data
.ReadConsoleOutputRequest
.CharInfo
;
2705 ReadRegion
.left
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
;
2706 ReadRegion
.top
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
;
2707 ReadRegion
.right
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
;
2708 ReadRegion
.bottom
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
;
2709 BufferSize
= Request
->Data
.ReadConsoleOutputRequest
.BufferSize
;
2710 BufferCoord
= Request
->Data
.ReadConsoleOutputRequest
.BufferCoord
;
2711 Length
= BufferSize
.X
* BufferSize
.Y
;
2712 Size
= Length
* sizeof(CHAR_INFO
);
2714 /* FIXME: Is this correct? */
2715 CodePage
= ProcessData
->Console
->OutputCodePage
;
2717 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
)
2718 || (((ULONG_PTR
)CharInfo
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2720 ConioUnlockScreenBuffer(Buff
);
2721 return STATUS_ACCESS_VIOLATION
;
2724 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&ReadRegion
));
2725 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&ReadRegion
));
2726 ReadRegion
.bottom
= ReadRegion
.top
+ SizeY
;
2727 ReadRegion
.right
= ReadRegion
.left
+ SizeX
;
2729 ConioInitRect(&ScreenRect
, 0, 0, Buff
->MaxY
, Buff
->MaxX
);
2730 if (! ConioGetIntersection(&ReadRegion
, &ScreenRect
, &ReadRegion
))
2732 ConioUnlockScreenBuffer(Buff
);
2733 return STATUS_SUCCESS
;
2736 for (i
= 0, Y
= ReadRegion
.top
; Y
< ReadRegion
.bottom
; ++i
, ++Y
)
2738 CurCharInfo
= CharInfo
+ (i
* BufferSize
.X
);
2740 Ptr
= ConioCoordToPointer(Buff
, ReadRegion
.left
, Y
);
2741 for (X
= ReadRegion
.left
; X
< ReadRegion
.right
; ++X
)
2743 if (Request
->Data
.ReadConsoleOutputRequest
.Unicode
)
2745 MultiByteToWideChar(CodePage
, 0,
2747 &CurCharInfo
->Char
.UnicodeChar
, 1);
2751 CurCharInfo
->Char
.AsciiChar
= *Ptr
++;
2753 CurCharInfo
->Attributes
= *Ptr
++;
2758 ConioUnlockScreenBuffer(Buff
);
2760 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
= ReadRegion
.left
+ SizeX
- 1;
2761 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
= ReadRegion
.top
+ SizeY
- 1;
2762 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
= ReadRegion
.left
;
2763 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
= ReadRegion
.top
;
2765 return STATUS_SUCCESS
;
2769 CSR_API(CsrWriteConsoleInput
)
2771 PINPUT_RECORD InputRecord
;
2772 PCSRSS_CONSOLE Console
;
2777 ConsoleInput
* Record
;
2779 DPRINT("CsrWriteConsoleInput\n");
2781 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2782 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2784 Status
= ConioLockConsole(ProcessData
, Request
->Data
.WriteConsoleInputRequest
.ConsoleHandle
, &Console
, GENERIC_WRITE
);
2785 if (! NT_SUCCESS(Status
))
2790 InputRecord
= Request
->Data
.WriteConsoleInputRequest
.InputRecord
;
2791 Length
= Request
->Data
.WriteConsoleInputRequest
.Length
;
2792 Size
= Length
* sizeof(INPUT_RECORD
);
2794 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2795 || (((ULONG_PTR
)InputRecord
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2797 ConioUnlockConsole(Console
);
2798 return STATUS_ACCESS_VIOLATION
;
2801 for (i
= 0; i
< Length
; i
++)
2803 Record
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
2806 ConioUnlockConsole(Console
);
2807 return STATUS_INSUFFICIENT_RESOURCES
;
2810 Record
->Echoed
= FALSE
;
2811 Record
->Fake
= FALSE
;
2812 //Record->InputEvent = *InputRecord++;
2813 memcpy(&Record
->InputEvent
, &InputRecord
[i
], sizeof(INPUT_RECORD
));
2814 if (KEY_EVENT
== Record
->InputEvent
.EventType
)
2816 /* FIXME - convert from unicode to ascii!! */
2817 ConioProcessChar(Console
, Record
);
2821 ConioUnlockConsole(Console
);
2823 Request
->Data
.WriteConsoleInputRequest
.Length
= i
;
2825 return STATUS_SUCCESS
;
2828 /**********************************************************************
2829 * HardwareStateProperty
2832 * Set/Get the value of the HardwareState and switch
2833 * between direct video buffer ouput and GDI windowed
2836 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
2837 * object. We use the same object to Request.
2839 * ConsoleHwState has the correct size to be compatible
2840 * with NT's, but values are not.
2842 static NTSTATUS FASTCALL
2843 SetConsoleHardwareState (PCSRSS_CONSOLE Console
, DWORD ConsoleHwState
)
2845 DPRINT1("Console Hardware State: %d\n", ConsoleHwState
);
2847 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED
== ConsoleHwState
)
2848 ||(CONSOLE_HARDWARE_STATE_DIRECT
== ConsoleHwState
))
2850 if (Console
->HardwareState
!= ConsoleHwState
)
2852 /* TODO: implement switching from full screen to windowed mode */
2853 /* TODO: or back; now simply store the hardware state */
2854 Console
->HardwareState
= ConsoleHwState
;
2857 return STATUS_SUCCESS
;
2860 return STATUS_INVALID_PARAMETER_3
; /* Client: (handle, set_get, [mode]) */
2863 CSR_API(CsrHardwareStateProperty
)
2865 PCSRSS_CONSOLE Console
;
2868 DPRINT("CsrHardwareStateProperty\n");
2870 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2871 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2873 Status
= ConioLockConsole(ProcessData
,
2874 Request
->Data
.ConsoleHardwareStateRequest
.ConsoleHandle
,
2877 if (! NT_SUCCESS(Status
))
2879 DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
2883 switch (Request
->Data
.ConsoleHardwareStateRequest
.SetGet
)
2885 case CONSOLE_HARDWARE_STATE_GET
:
2886 Request
->Data
.ConsoleHardwareStateRequest
.State
= Console
->HardwareState
;
2889 case CONSOLE_HARDWARE_STATE_SET
:
2890 DPRINT("Setting console hardware state.\n");
2891 Status
= SetConsoleHardwareState(Console
, Request
->Data
.ConsoleHardwareStateRequest
.State
);
2895 Status
= STATUS_INVALID_PARAMETER_2
; /* Client: (handle, [set_get], mode) */
2899 ConioUnlockConsole(Console
);
2904 CSR_API(CsrGetConsoleWindow
)
2906 PCSRSS_CONSOLE Console
;
2909 DPRINT("CsrGetConsoleWindow\n");
2911 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2912 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2914 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2915 if (! NT_SUCCESS(Status
))
2920 Request
->Data
.GetConsoleWindowRequest
.WindowHandle
= Console
->hWindow
;
2921 ConioUnlockConsole(Console
);
2923 return STATUS_SUCCESS
;
2926 CSR_API(CsrSetConsoleIcon
)
2928 PCSRSS_CONSOLE Console
;
2931 DPRINT("CsrSetConsoleIcon\n");
2933 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2934 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2936 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2937 if (! NT_SUCCESS(Status
))
2942 Status
= (ConioChangeIcon(Console
, Request
->Data
.SetConsoleIconRequest
.WindowIcon
)
2943 ? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
2944 ConioUnlockConsole(Console
);
2949 CSR_API(CsrGetConsoleCodePage
)
2951 PCSRSS_CONSOLE Console
;
2954 DPRINT("CsrGetConsoleCodePage\n");
2956 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2957 if (! NT_SUCCESS(Status
))
2962 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2963 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2964 Request
->Data
.GetConsoleCodePage
.CodePage
= Console
->CodePage
;
2965 ConioUnlockConsole(Console
);
2966 return STATUS_SUCCESS
;
2969 CSR_API(CsrSetConsoleCodePage
)
2971 PCSRSS_CONSOLE Console
;
2974 DPRINT("CsrSetConsoleCodePage\n");
2976 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2977 if (! NT_SUCCESS(Status
))
2982 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2983 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2984 if (IsValidCodePage(Request
->Data
.SetConsoleCodePage
.CodePage
))
2986 Console
->CodePage
= Request
->Data
.SetConsoleCodePage
.CodePage
;
2987 ConioUnlockConsole(Console
);
2988 return STATUS_SUCCESS
;
2990 ConioUnlockConsole(Console
);
2991 return STATUS_UNSUCCESSFUL
;
2994 CSR_API(CsrGetConsoleOutputCodePage
)
2996 PCSRSS_CONSOLE Console
;
2999 DPRINT("CsrGetConsoleOutputCodePage\n");
3001 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3002 if (! NT_SUCCESS(Status
))
3007 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3008 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3009 Request
->Data
.GetConsoleOutputCodePage
.CodePage
= Console
->OutputCodePage
;
3010 ConioUnlockConsole(Console
);
3011 return STATUS_SUCCESS
;
3014 CSR_API(CsrSetConsoleOutputCodePage
)
3016 PCSRSS_CONSOLE Console
;
3019 DPRINT("CsrSetConsoleOutputCodePage\n");
3021 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3022 if (! NT_SUCCESS(Status
))
3027 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3028 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3029 if (IsValidCodePage(Request
->Data
.SetConsoleOutputCodePage
.CodePage
))
3031 Console
->OutputCodePage
= Request
->Data
.SetConsoleOutputCodePage
.CodePage
;
3032 ConioUnlockConsole(Console
);
3033 return STATUS_SUCCESS
;
3035 ConioUnlockConsole(Console
);
3036 return STATUS_UNSUCCESSFUL
;
3039 CSR_API(CsrGetProcessList
)
3042 PCSRSS_CONSOLE Console
;
3043 PCSRSS_PROCESS_DATA current
;
3044 PLIST_ENTRY current_entry
;
3045 ULONG nItems
, nCopied
, Length
;
3048 DPRINT("CsrGetProcessList\n");
3050 Buffer
= Request
->Data
.GetProcessListRequest
.ProcessId
;
3051 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3052 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3054 nItems
= nCopied
= 0;
3055 Request
->Data
.GetProcessListRequest
.nProcessIdsCopied
= 0;
3056 Request
->Data
.GetProcessListRequest
.nProcessIdsTotal
= 0;
3058 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3059 if (! NT_SUCCESS(Status
))
3064 DPRINT1("Console_Api Ctrl-C\n");
3066 for(current_entry
= Console
->ProcessList
.Flink
;
3067 current_entry
!= &Console
->ProcessList
;
3068 current_entry
= current_entry
->Flink
)
3070 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
3071 if(++nItems
< Request
->Data
.GetProcessListRequest
.nMaxIds
)
3073 *(Buffer
++) = current
->ProcessId
;
3078 ConioUnlockConsole(Console
);
3080 Request
->Data
.GetProcessListRequest
.nProcessIdsCopied
= nCopied
;
3081 Request
->Data
.GetProcessListRequest
.nProcessIdsTotal
= nItems
;
3083 Length
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_GET_PROCESS_LIST
) + nCopied
* sizeof(HANDLE
);
3084 if (Length
> sizeof(CSR_API_MESSAGE
))
3086 Request
->Header
.u1
.s1
.TotalLength
= Length
;
3087 Request
->Header
.u1
.s1
.DataLength
= Length
- sizeof(PORT_MESSAGE
);
3089 return STATUS_SUCCESS
;
3092 CSR_API(CsrGenerateCtrlEvent
)
3094 PCSRSS_CONSOLE Console
;
3095 PCSRSS_PROCESS_DATA current
;
3096 PLIST_ENTRY current_entry
;
3100 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3101 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3103 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3104 if (! NT_SUCCESS(Status
))
3109 Group
= Request
->Data
.GenerateCtrlEvent
.ProcessGroup
;
3110 Status
= STATUS_INVALID_PARAMETER
;
3111 for (current_entry
= Console
->ProcessList
.Flink
;
3112 current_entry
!= &Console
->ProcessList
;
3113 current_entry
= current_entry
->Flink
)
3115 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
3116 if (Group
== 0 || current
->ProcessGroup
== Group
)
3118 ConioConsoleCtrlEvent(Request
->Data
.GenerateCtrlEvent
.Event
, current
);
3119 Status
= STATUS_SUCCESS
;
3123 ConioUnlockConsole(Console
);