2 * reactos/subsys/csrss/win32csr/conio.c
4 * Console I/O functions
6 * ReactOS Operating System
9 /* INCLUDES ******************************************************************/
15 /* GLOBALS *******************************************************************/
17 #define ConioInitRect(Rect, Top, Left, Bottom, Right) \
18 ((Rect)->top) = Top; \
19 ((Rect)->left) = Left; \
20 ((Rect)->bottom) = Bottom; \
21 ((Rect)->right) = Right
23 #define ConioIsRectEmpty(Rect) \
24 (((Rect)->left > (Rect)->right) || ((Rect)->top > (Rect)->bottom))
26 #define ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar) \
27 WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
29 #define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
30 WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
32 #define ConsoleAnsiCharToUnicodeChar(Console, sWChar, dChar) \
33 MultiByteToWideChar((Console)->OutputCodePage, 0, (dChar), 1, (sWChar), 1)
36 /* FUNCTIONS *****************************************************************/
39 ConioConsoleFromProcessData(PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_CONSOLE
*Console
)
41 PCSRSS_CONSOLE ProcessConsole
= ProcessData
->Console
;
46 return STATUS_INVALID_HANDLE
;
49 InterlockedIncrement(&ProcessConsole
->Header
.ReferenceCount
);
50 EnterCriticalSection(&(ProcessConsole
->Header
.Lock
));
51 *Console
= ProcessConsole
;
53 return STATUS_SUCCESS
;
57 ConioConsoleCtrlEventTimeout(DWORD Event
, PCSRSS_PROCESS_DATA ProcessData
, DWORD Timeout
)
61 DPRINT("ConioConsoleCtrlEvent Parent ProcessId = %x\n", ProcessData
->ProcessId
);
63 if (ProcessData
->CtrlDispatcher
)
66 Thread
= CreateRemoteThread(ProcessData
->Process
, NULL
, 0,
67 (LPTHREAD_START_ROUTINE
) ProcessData
->CtrlDispatcher
,
68 UlongToPtr(Event
), 0, NULL
);
71 DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
74 WaitForSingleObject(Thread
, Timeout
);
80 ConioConsoleCtrlEvent(DWORD Event
, PCSRSS_PROCESS_DATA ProcessData
)
82 ConioConsoleCtrlEventTimeout(Event
, ProcessData
, 0);
86 ConioCoordToPointer(PCSRSS_SCREEN_BUFFER Buff
, ULONG X
, ULONG Y
)
88 return &Buff
->Buffer
[2 * (((Y
+ Buff
->VirtualY
) % Buff
->MaxY
) * Buff
->MaxX
+ X
)];
92 ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff
)
94 PBYTE Ptr
= ConioCoordToPointer(Buff
, 0, Buff
->CurrentY
);
97 for (Pos
= 0; Pos
< Buff
->MaxX
; Pos
++)
101 *Ptr
++ = Buff
->DefaultAttrib
;
105 static NTSTATUS FASTCALL
106 CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console
,
107 PCSRSS_SCREEN_BUFFER Buffer
)
109 DPRINT("CsrInitConsoleScreenBuffer Size X %d Size Y %d\n", Buffer
->MaxX
, Buffer
->MaxY
);
111 Buffer
->Header
.Type
= CONIO_SCREEN_BUFFER_MAGIC
;
112 Buffer
->Header
.ReferenceCount
= 0;
115 Buffer
->VirtualY
= 0;
116 Buffer
->Buffer
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, Buffer
->MaxX
* Buffer
->MaxY
* 2);
117 if (NULL
== Buffer
->Buffer
)
119 return STATUS_INSUFFICIENT_RESOURCES
;
121 InitializeCriticalSection(&Buffer
->Header
.Lock
);
122 ConioInitScreenBuffer(Console
, Buffer
);
123 /* initialize buffer to be empty with default attributes */
124 for (Buffer
->CurrentY
= 0 ; Buffer
->CurrentY
< Buffer
->MaxY
; Buffer
->CurrentY
++)
126 ClearLineBuffer(Buffer
);
128 Buffer
->Mode
= ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
;
129 Buffer
->CurrentX
= 0;
130 Buffer
->CurrentY
= 0;
132 return STATUS_SUCCESS
;
135 static NTSTATUS WINAPI
136 CsrInitConsole(PCSRSS_CONSOLE Console
)
139 SECURITY_ATTRIBUTES SecurityAttributes
;
140 PCSRSS_SCREEN_BUFFER NewBuffer
;
143 Console
->Title
.MaximumLength
= Console
->Title
.Length
= 0;
144 Console
->Title
.Buffer
= NULL
;
147 RtlCreateUnicodeString(&Console
->Title
, L
"Command Prompt");
149 Console
->Header
.ReferenceCount
= 0;
150 Console
->WaitingChars
= 0;
151 Console
->WaitingLines
= 0;
152 Console
->EchoCount
= 0;
153 Console
->Header
.Type
= CONIO_CONSOLE_MAGIC
;
154 Console
->Mode
= ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_PROCESSED_INPUT
| ENABLE_MOUSE_INPUT
;
155 Console
->EarlyReturn
= FALSE
;
156 Console
->ActiveBuffer
= NULL
;
157 InitializeListHead(&Console
->InputEvents
);
158 Console
->CodePage
= GetOEMCP();
159 Console
->OutputCodePage
= GetOEMCP();
161 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
162 SecurityAttributes
.lpSecurityDescriptor
= NULL
;
163 SecurityAttributes
.bInheritHandle
= TRUE
;
165 Console
->ActiveEvent
= CreateEventW(&SecurityAttributes
, TRUE
, FALSE
, NULL
);
166 if (NULL
== Console
->ActiveEvent
)
168 RtlFreeUnicodeString(&Console
->Title
);
169 return STATUS_UNSUCCESSFUL
;
171 Console
->PrivateData
= NULL
;
172 InitializeCriticalSection(&Console
->Header
.Lock
);
174 GuiMode
= DtbgIsDesktopVisible();
176 /* allocate console screen buffer */
177 NewBuffer
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
178 if (NULL
== NewBuffer
)
180 RtlFreeUnicodeString(&Console
->Title
);
181 DeleteCriticalSection(&Console
->Header
.Lock
);
182 CloseHandle(Console
->ActiveEvent
);
183 return STATUS_INSUFFICIENT_RESOURCES
;
185 /* init screen buffer with defaults */
186 NewBuffer
->CursorInfo
.bVisible
= TRUE
;
187 NewBuffer
->CursorInfo
.dwSize
= CSR_DEFAULT_CURSOR_SIZE
;
188 /* make console active, and insert into console list */
189 Console
->ActiveBuffer
= (PCSRSS_SCREEN_BUFFER
) NewBuffer
;
193 Status
= TuiInitConsole(Console
);
194 if (! NT_SUCCESS(Status
))
196 DPRINT1("Failed to open text-mode console, switching to gui-mode\n");
202 Status
= GuiInitConsole(Console
);
203 if (! NT_SUCCESS(Status
))
205 HeapFree(Win32CsrApiHeap
,0, NewBuffer
);
206 RtlFreeUnicodeString(&Console
->Title
);
207 DeleteCriticalSection(&Console
->Header
.Lock
);
208 CloseHandle(Console
->ActiveEvent
);
209 DPRINT1("GuiInitConsole: failed\n");
214 Status
= CsrInitConsoleScreenBuffer(Console
, NewBuffer
);
215 if (! NT_SUCCESS(Status
))
217 ConioCleanupConsole(Console
);
218 RtlFreeUnicodeString(&Console
->Title
);
219 DeleteCriticalSection(&Console
->Header
.Lock
);
220 CloseHandle(Console
->ActiveEvent
);
221 HeapFree(Win32CsrApiHeap
, 0, NewBuffer
);
222 DPRINT1("CsrInitConsoleScreenBuffer: failed\n");
226 /* add a reference count because the buffer is tied to the console */
227 InterlockedIncrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
);
229 /* copy buffer contents to screen */
230 ConioDrawConsole(Console
);
232 return STATUS_SUCCESS
;
236 CSR_API(CsrAllocConsole
)
238 PCSRSS_CONSOLE Console
;
239 NTSTATUS Status
= STATUS_SUCCESS
;
240 BOOLEAN NewConsole
= FALSE
;
242 DPRINT("CsrAllocConsole\n");
244 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
245 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
247 if (ProcessData
->Console
)
249 DPRINT1("Process already has a console\n");
250 return STATUS_INVALID_PARAMETER
;
253 /* If we don't need a console, then get out of here */
254 if (!Request
->Data
.AllocConsoleRequest
.ConsoleNeeded
)
256 DPRINT("No console needed\n");
257 return STATUS_SUCCESS
;
260 /* If we already have one, then don't create a new one... */
261 if (!Request
->Data
.AllocConsoleRequest
.Console
||
262 Request
->Data
.AllocConsoleRequest
.Console
!= ProcessData
->ParentConsole
)
264 /* Allocate a console structure */
266 Console
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_CONSOLE
));
269 DPRINT1("Not enough memory for console\n");
270 return STATUS_NO_MEMORY
;
272 /* initialize list head */
273 InitializeListHead(&Console
->ProcessList
);
274 /* insert process data required for GUI initialization */
275 InsertHeadList(&Console
->ProcessList
, &ProcessData
->ProcessEntry
);
276 /* Initialize the Console */
277 Status
= CsrInitConsole(Console
);
278 if (!NT_SUCCESS(Status
))
280 DPRINT1("Console init failed\n");
281 HeapFree(Win32CsrApiHeap
, 0, Console
);
287 /* Reuse our current console */
288 Console
= Request
->Data
.AllocConsoleRequest
.Console
;
291 /* Set the Process Console */
292 ProcessData
->Console
= Console
;
294 /* Return it to the caller */
295 Request
->Data
.AllocConsoleRequest
.Console
= Console
;
297 /* Add a reference count because the process is tied to the console */
298 Console
->Header
.ReferenceCount
++;
300 if (NewConsole
|| !ProcessData
->bInheritHandles
)
302 /* Insert the Objects */
303 Status
= Win32CsrInsertObject(ProcessData
,
304 &Request
->Data
.AllocConsoleRequest
.InputHandle
,
306 GENERIC_READ
| GENERIC_WRITE
,
308 if (! NT_SUCCESS(Status
))
310 DPRINT1("Failed to insert object\n");
311 ConioDeleteConsole((Object_t
*) Console
);
312 ProcessData
->Console
= 0;
316 Status
= Win32CsrInsertObject(ProcessData
,
317 &Request
->Data
.AllocConsoleRequest
.OutputHandle
,
318 &Console
->ActiveBuffer
->Header
,
319 GENERIC_READ
| GENERIC_WRITE
,
321 if (!NT_SUCCESS(Status
))
323 DPRINT1("Failed to insert object\n");
324 ConioDeleteConsole((Object_t
*) Console
);
325 Win32CsrReleaseObject(ProcessData
,
326 Request
->Data
.AllocConsoleRequest
.InputHandle
);
327 ProcessData
->Console
= 0;
332 /* Duplicate the Event */
333 if (!DuplicateHandle(GetCurrentProcess(),
334 ProcessData
->Console
->ActiveEvent
,
335 ProcessData
->Process
,
336 &ProcessData
->ConsoleEvent
,
341 DPRINT1("DuplicateHandle() failed: %d\n", GetLastError
);
342 ConioDeleteConsole((Object_t
*) Console
);
343 if (NewConsole
|| !ProcessData
->bInheritHandles
)
345 Win32CsrReleaseObject(ProcessData
,
346 Request
->Data
.AllocConsoleRequest
.OutputHandle
);
347 Win32CsrReleaseObject(ProcessData
,
348 Request
->Data
.AllocConsoleRequest
.InputHandle
);
350 ProcessData
->Console
= 0;
354 /* Set the Ctrl Dispatcher */
355 ProcessData
->CtrlDispatcher
= Request
->Data
.AllocConsoleRequest
.CtrlDispatcher
;
356 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
360 /* Insert into the list if it has not been added */
361 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ProcessEntry
);
364 return STATUS_SUCCESS
;
367 CSR_API(CsrFreeConsole
)
369 PCSRSS_CONSOLE Console
;
372 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
373 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
375 if (ProcessData
->Console
== NULL
)
377 return STATUS_INVALID_PARAMETER
;
380 Console
= ProcessData
->Console
;
381 ProcessData
->Console
= NULL
;
382 RemoveEntryList(&ProcessData
->ProcessEntry
);
383 if (0 == InterlockedDecrement(&Console
->Header
.ReferenceCount
))
385 ConioDeleteConsole((Object_t
*) Console
);
387 return STATUS_SUCCESS
;
391 ConioNextLine(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, UINT
*ScrolledLines
)
393 /* If we hit bottom, slide the viewable screen */
394 if (++Buff
->CurrentY
== Buff
->MaxY
)
397 if (++Buff
->VirtualY
== Buff
->MaxY
)
402 ClearLineBuffer(Buff
);
403 if (UpdateRect
->top
!= 0)
408 UpdateRect
->left
= 0;
409 UpdateRect
->right
= Buff
->MaxX
- 1;
410 UpdateRect
->bottom
= Buff
->CurrentY
;
413 static NTSTATUS FASTCALL
414 ConioWriteConsole(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
,
415 CHAR
*Buffer
, DWORD Length
, BOOL Attrib
)
420 LONG CursorStartX
, CursorStartY
;
423 CursorStartX
= Buff
->CurrentX
;
424 CursorStartY
= Buff
->CurrentY
;
425 UpdateRect
.left
= Buff
->MaxX
;
426 UpdateRect
.top
= Buff
->CurrentY
;
427 UpdateRect
.right
= -1;
428 UpdateRect
.bottom
= Buff
->CurrentY
;
431 for (i
= 0; i
< Length
; i
++)
433 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
436 if (Buffer
[i
] == '\n')
439 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
443 else if (Buffer
[i
] == '\b')
445 /* Only handle BS if we're not on the first pos of the first line */
446 if (0 != Buff
->CurrentX
|| 0 != Buff
->CurrentY
)
448 if (0 == Buff
->CurrentX
)
450 /* slide virtual position up */
451 Buff
->CurrentX
= Buff
->MaxX
- 1;
453 UpdateRect
.top
= min(UpdateRect
.top
, (LONG
)Buff
->CurrentY
);
459 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
461 Ptr
[1] = Buff
->DefaultAttrib
;
462 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
) Buff
->CurrentX
);
463 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
468 else if (Buffer
[i
] == '\r')
471 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
) Buff
->CurrentX
);
472 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
476 else if (Buffer
[i
] == '\t')
480 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
)Buff
->CurrentX
);
481 EndX
= (Buff
->CurrentX
+ 8) & ~7;
482 if (EndX
> Buff
->MaxX
)
486 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
487 while (Buff
->CurrentX
< EndX
)
490 *Ptr
++ = Buff
->DefaultAttrib
;
493 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
- 1);
494 if (Buff
->CurrentX
== Buff
->MaxX
)
496 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
499 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
509 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
)Buff
->CurrentX
);
510 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
511 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
515 Ptr
[1] = Buff
->DefaultAttrib
;
518 if (Buff
->CurrentX
== Buff
->MaxX
)
520 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
523 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
527 Buff
->CurrentX
= CursorStartX
;
532 if (! ConioIsRectEmpty(&UpdateRect
) && 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
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
559 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
561 Buffer
= Request
->Data
.ReadConsoleRequest
.Buffer
;
562 UnicodeBuffer
= (PWCHAR
)Buffer
;
563 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadConsoleRequest
.ConsoleHandle
,
564 &Console
, GENERIC_READ
);
565 if (! NT_SUCCESS(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
))
576 ResetEvent(Console
->ActiveEvent
);
578 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
580 /* only pay attention to valid ascii chars, on key down */
581 if (KEY_EVENT
== Input
->InputEvent
.EventType
582 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
583 && Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
!= '\0')
586 * backspace handling - if we are in charge of echoing it then we handle it here
587 * otherwise we treat it like a normal char.
589 if ('\b' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
&& 0
590 != (Console
->Mode
& ENABLE_ECHO_INPUT
))
592 /* echo if it has not already been done, and either we or the client has chars to be deleted */
594 && (0 != i
|| Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
))
596 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
597 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
601 i
-= 2; /* if we already have something to return, just back it up by 2 */
604 { /* otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer */
605 Console
->WaitingChars
--;
606 ConioUnlockConsole(Console
);
607 HeapFree(Win32CsrApiHeap
, 0, Input
);
608 Request
->Data
.ReadConsoleRequest
.NrCharactersRead
= 0;
609 return STATUS_NOTIFY_CLEANUP
;
612 Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
--;
613 Input
->Echoed
= TRUE
; /* mark as echoed so we don't echo it below */
615 /* do not copy backspace to buffer */
618 if(Request
->Data
.ReadConsoleRequest
.Unicode
)
619 UnicodeBuffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
; /* FIXME */
621 Buffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
;
623 /* echo to screen if enabled and we did not already echo the char */
624 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
)
626 && '\r' != Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
628 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
629 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
636 Console
->WaitingChars
--;
637 HeapFree(Win32CsrApiHeap
, 0, Input
);
639 Request
->Data
.ReadConsoleRequest
.NrCharactersRead
= i
;
642 Status
= STATUS_PENDING
; /* we didn't read anything */
644 else if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
))
646 if (0 == Console
->WaitingLines
||
647 (Request
->Data
.ReadConsoleRequest
.Unicode
? (L
'\n' != UnicodeBuffer
[i
- 1]) : ('\n' != Buffer
[i
- 1])))
649 Status
= STATUS_PENDING
; /* line buffered, didn't get a complete line */
653 Console
->WaitingLines
--;
654 Status
= STATUS_SUCCESS
; /* line buffered, did get a complete line */
659 Status
= STATUS_SUCCESS
; /* not line buffered, did read something */
662 if (Status
== STATUS_PENDING
)
664 Console
->EchoCount
= nNumberOfCharsToRead
- i
;
668 Console
->EchoCount
= 0; /* if the client is no longer waiting on input, do not echo */
671 ConioUnlockConsole(Console
);
673 if (CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE
) + i
* CharSize
> sizeof(CSR_API_MESSAGE
))
675 Request
->Header
.u1
.s1
.TotalLength
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE
) + i
* CharSize
;
676 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
682 __inline BOOLEAN
ConioGetIntersection(
687 if (ConioIsRectEmpty(Rect1
) ||
688 (ConioIsRectEmpty(Rect2
)) ||
689 (Rect1
->top
> Rect2
->bottom
) ||
690 (Rect1
->left
> Rect2
->right
) ||
691 (Rect1
->bottom
< Rect2
->top
) ||
692 (Rect1
->right
< Rect2
->left
))
694 /* The rectangles do not intersect */
695 ConioInitRect(Intersection
, 0, -1, 0, -1);
699 ConioInitRect(Intersection
,
700 max(Rect1
->top
, Rect2
->top
),
701 max(Rect1
->left
, Rect2
->left
),
702 min(Rect1
->bottom
, Rect2
->bottom
),
703 min(Rect1
->right
, Rect2
->right
));
708 __inline BOOLEAN
ConioGetUnion(
713 if (ConioIsRectEmpty(Rect1
))
715 if (ConioIsRectEmpty(Rect2
))
717 ConioInitRect(Union
, 0, -1, 0, -1);
725 else if (ConioIsRectEmpty(Rect2
))
732 min(Rect1
->top
, Rect2
->top
),
733 min(Rect1
->left
, Rect2
->left
),
734 max(Rect1
->bottom
, Rect2
->bottom
),
735 max(Rect1
->right
, Rect2
->right
));
741 /* Move from one rectangle to another. We must be careful about the order that
742 * this is done, to avoid overwriting parts of the source before they are moved. */
744 ConioMoveRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer
,
750 int Width
= ConioRectWidth(SrcRegion
);
751 int Height
= ConioRectHeight(SrcRegion
);
762 /* Moving down: work from bottom up */
763 SY
= SrcRegion
->bottom
;
764 DY
= DstRegion
->bottom
;
767 for (i
= 0; i
< Height
; i
++)
769 PWORD SRow
= (PWORD
)ConioCoordToPointer(ScreenBuffer
, 0, SY
);
770 PWORD DRow
= (PWORD
)ConioCoordToPointer(ScreenBuffer
, 0, DY
);
772 SX
= SrcRegion
->left
;
773 DX
= DstRegion
->left
;
777 /* Moving right: work from right to left */
778 SX
= SrcRegion
->right
;
779 DX
= DstRegion
->right
;
782 for (j
= 0; j
< Width
; j
++)
784 WORD Cell
= SRow
[SX
];
785 if (SX
>= ClipRegion
->left
&& SX
<= ClipRegion
->right
786 && SY
>= ClipRegion
->top
&& SY
<= ClipRegion
->bottom
)
790 if (DX
>= ClipRegion
->left
&& DX
<= ClipRegion
->right
791 && DY
>= ClipRegion
->top
&& DY
<= ClipRegion
->bottom
)
804 ConioInputEventToAnsi(PCSRSS_CONSOLE Console
, PINPUT_RECORD InputEvent
)
806 if (InputEvent
->EventType
== KEY_EVENT
)
808 WCHAR UnicodeChar
= InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
;
809 InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
= 0;
810 ConsoleInputUnicodeCharToAnsiChar(Console
,
811 &InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
,
816 CSR_API(CsrWriteConsole
)
820 PCSRSS_SCREEN_BUFFER Buff
;
821 PCSRSS_CONSOLE Console
;
824 ULONG CharSize
= (Request
->Data
.WriteConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
826 DPRINT("CsrWriteConsole\n");
828 if (Request
->Header
.u1
.s1
.TotalLength
829 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE
)
830 + (Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
* CharSize
))
832 DPRINT1("Invalid request size\n");
833 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
834 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
835 return STATUS_INVALID_PARAMETER
;
837 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
839 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
840 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
842 if (! NT_SUCCESS(Status
))
847 if(Request
->Data
.WriteConsoleRequest
.Unicode
)
849 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
850 (PWCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
,
851 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
,
852 NULL
, 0, NULL
, NULL
);
853 Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
856 WideCharToMultiByte(Console
->OutputCodePage
, 0,
857 (PWCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
,
858 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
,
859 Buffer
, Length
, NULL
, NULL
);
863 Status
= STATUS_NO_MEMORY
;
868 Buffer
= (PCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
;
873 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.WriteConsoleRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
874 if (NT_SUCCESS(Status
))
876 Status
= ConioWriteConsole(Console
, Buff
, Buffer
,
877 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
, TRUE
);
878 if (NT_SUCCESS(Status
))
880 Written
= Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
;
882 ConioUnlockScreenBuffer(Buff
);
884 if (Request
->Data
.WriteConsoleRequest
.Unicode
)
886 RtlFreeHeap(GetProcessHeap(), 0, Buffer
);
889 ConioUnlockConsole(Console
);
891 Request
->Data
.WriteConsoleRequest
.NrCharactersWritten
= Written
;
897 ConioDeleteScreenBuffer(Object_t
*Object
)
899 PCSRSS_SCREEN_BUFFER Buffer
= (PCSRSS_SCREEN_BUFFER
) Object
;
900 DeleteCriticalSection(&Buffer
->Header
.Lock
);
901 HeapFree(Win32CsrApiHeap
, 0, Buffer
->Buffer
);
902 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
906 ConioDrawConsole(PCSRSS_CONSOLE Console
)
910 ConioInitRect(&Region
, 0, 0, Console
->Size
.Y
- 1, Console
->Size
.X
- 1);
912 ConioDrawRegion(Console
, &Region
);
917 ConioDeleteConsole(Object_t
*Object
)
919 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Object
;
922 DPRINT("ConioDeleteConsole\n");
924 /* Drain input event queue */
925 while (Console
->InputEvents
.Flink
!= &Console
->InputEvents
)
927 Event
= (ConsoleInput
*) Console
->InputEvents
.Flink
;
928 Console
->InputEvents
.Flink
= Console
->InputEvents
.Flink
->Flink
;
929 Console
->InputEvents
.Flink
->Flink
->Blink
= &Console
->InputEvents
;
930 HeapFree(Win32CsrApiHeap
, 0, Event
);
933 ConioCleanupConsole(Console
);
934 if (0 == InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
936 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
939 Console
->ActiveBuffer
= NULL
;
941 CloseHandle(Console
->ActiveEvent
);
942 DeleteCriticalSection(&Console
->Header
.Lock
);
943 RtlFreeUnicodeString(&Console
->Title
);
944 IntDeleteAllAliases(Console
->Aliases
);
945 HeapFree(Win32CsrApiHeap
, 0, Console
);
949 CsrInitConsoleSupport(VOID
)
951 DPRINT("CSR: CsrInitConsoleSupport()\n");
953 /* Should call LoadKeyboardLayout */
957 ConioProcessChar(PCSRSS_CONSOLE Console
,
958 ConsoleInput
*KeyEventRecord
)
961 ConsoleInput
*TempInput
;
963 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
)))
965 switch(KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
968 /* first add the \r */
969 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
970 updown
= KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
;
971 KeyEventRecord
->Echoed
= FALSE
;
972 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= VK_RETURN
;
973 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\r';
974 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
975 Console
->WaitingChars
++;
976 KeyEventRecord
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
977 if (NULL
== KeyEventRecord
)
979 DPRINT1("Failed to allocate KeyEventRecord\n");
982 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
983 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
= updown
;
984 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= 0;
985 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualScanCode
= 0;
986 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\n';
987 KeyEventRecord
->Fake
= TRUE
;
991 /* add event to the queue */
992 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
993 Console
->WaitingChars
++;
994 /* if line input mode is enabled, only wake the client on enter key down */
995 if (0 == (Console
->Mode
& ENABLE_LINE_INPUT
)
996 || Console
->EarlyReturn
997 || ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
998 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
))
1000 if ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1002 Console
->WaitingLines
++;
1005 KeyEventRecord
->Echoed
= FALSE
;
1006 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
))
1007 && '\b' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1008 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1010 /* walk the input queue looking for a char to backspace */
1011 for (TempInput
= (ConsoleInput
*) Console
->InputEvents
.Blink
;
1012 TempInput
!= (ConsoleInput
*) &Console
->InputEvents
1013 && (KEY_EVENT
== TempInput
->InputEvent
.EventType
1014 || ! TempInput
->InputEvent
.Event
.KeyEvent
.bKeyDown
1015 || '\b' == TempInput
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
);
1016 TempInput
= (ConsoleInput
*) TempInput
->ListEntry
.Blink
)
1020 /* if we found one, delete it, otherwise, wake the client */
1021 if (TempInput
!= (ConsoleInput
*) &Console
->InputEvents
)
1023 /* delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue */
1024 RemoveEntryList(&TempInput
->ListEntry
);
1025 if (TempInput
->Echoed
)
1027 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1028 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1031 HeapFree(Win32CsrApiHeap
, 0, TempInput
);
1032 RemoveEntryList(&KeyEventRecord
->ListEntry
);
1033 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1034 Console
->WaitingChars
-= 2;
1040 /* echo chars if we are supposed to and client is waiting for some */
1041 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
) && Console
->EchoCount
1042 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1043 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
1044 && '\r' != KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1046 /* mark the char as already echoed */
1047 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1048 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1050 Console
->EchoCount
--;
1051 KeyEventRecord
->Echoed
= TRUE
;
1055 /* Console->WaitingChars++; */
1056 SetEvent(Console
->ActiveEvent
);
1059 static DWORD FASTCALL
1060 ConioGetShiftState(PBYTE KeyState
)
1064 if (KeyState
[VK_CAPITAL
] & 1)
1065 ssOut
|= CAPSLOCK_ON
;
1067 if (KeyState
[VK_NUMLOCK
] & 1)
1068 ssOut
|= NUMLOCK_ON
;
1070 if (KeyState
[VK_SCROLL
] & 1)
1071 ssOut
|= SCROLLLOCK_ON
;
1073 if (KeyState
[VK_SHIFT
] & 0x80)
1074 ssOut
|= SHIFT_PRESSED
;
1076 if (KeyState
[VK_LCONTROL
] & 0x80)
1077 ssOut
|= LEFT_CTRL_PRESSED
;
1078 if (KeyState
[VK_RCONTROL
] & 0x80)
1079 ssOut
|= RIGHT_CTRL_PRESSED
;
1081 if (KeyState
[VK_LMENU
] & 0x80)
1082 ssOut
|= LEFT_ALT_PRESSED
;
1083 if (KeyState
[VK_RMENU
] & 0x80)
1084 ssOut
|= RIGHT_ALT_PRESSED
;
1090 ConioProcessKey(MSG
*msg
, PCSRSS_CONSOLE Console
, BOOL TextMode
)
1092 static BYTE KeyState
[256] = { 0 };
1093 /* MSDN mentions that you should use the last virtual key code received
1094 * when putting a virtual key identity to a WM_CHAR message since multiple
1095 * or translated keys may be involved. */
1096 static UINT LastVirtualKey
= 0;
1098 ConsoleInput
*ConInRec
;
1102 UINT VirtualKeyCode
;
1103 UINT VirtualScanCode
;
1106 ULONG ResultSize
= 0;
1109 VirtualScanCode
= (msg
->lParam
>> 16) & 0xff;
1110 Down
= msg
->message
== WM_KEYDOWN
|| msg
->message
== WM_CHAR
||
1111 msg
->message
== WM_SYSKEYDOWN
|| msg
->message
== WM_SYSCHAR
;
1113 GetKeyboardState(KeyState
);
1114 ShiftState
= ConioGetShiftState(KeyState
);
1116 if (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
)
1118 VirtualKeyCode
= LastVirtualKey
;
1119 UnicodeChar
= msg
->wParam
;
1126 VirtualKeyCode
= msg
->wParam
;
1127 RetChars
= ToUnicodeEx(VirtualKeyCode
,
1134 UnicodeChar
= (1 == RetChars
? Chars
[0] : 0);
1137 if (0 == ResultSize
)
1142 er
.EventType
= KEY_EVENT
;
1143 er
.Event
.KeyEvent
.bKeyDown
= Down
;
1144 er
.Event
.KeyEvent
.wRepeatCount
= RepeatCount
;
1145 er
.Event
.KeyEvent
.uChar
.UnicodeChar
= UnicodeChar
;
1146 er
.Event
.KeyEvent
.dwControlKeyState
= ShiftState
;
1147 er
.Event
.KeyEvent
.wVirtualKeyCode
= VirtualKeyCode
;
1148 er
.Event
.KeyEvent
.wVirtualScanCode
= VirtualScanCode
;
1152 if (0 != (ShiftState
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1153 && VK_TAB
== VirtualKeyCode
)
1157 TuiSwapConsole(ShiftState
& SHIFT_PRESSED
? -1 : 1);
1162 else if (VK_MENU
== VirtualKeyCode
&& ! Down
)
1164 if (TuiSwapConsole(0))
1171 if (NULL
== Console
)
1173 DPRINT1("No Active Console!\n");
1177 ConInRec
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1179 if (NULL
== ConInRec
)
1184 ConInRec
->InputEvent
= er
;
1185 ConInRec
->Fake
= UnicodeChar
&&
1186 (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
&&
1187 msg
->message
!= WM_KEYUP
&& msg
->message
!= WM_SYSKEYUP
);
1188 ConInRec
->NotChar
= (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
);
1189 ConInRec
->Echoed
= FALSE
;
1190 if (ConInRec
->NotChar
)
1191 LastVirtualKey
= msg
->wParam
;
1193 DPRINT ("csrss: %s %s %s %s %02x %02x '%c' %04x\n",
1194 Down
? "down" : "up ",
1195 (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
) ?
1197 ConInRec
->Fake
? "fake" : "real",
1198 ConInRec
->NotChar
? "notc" : "char",
1201 (AsciiChar
>= ' ') ? AsciiChar
: '.',
1204 if (ConInRec
->Fake
&& ConInRec
->NotChar
)
1206 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1210 /* process Ctrl-C and Ctrl-Break */
1211 if (Console
->Mode
& ENABLE_PROCESSED_INPUT
&&
1212 er
.Event
.KeyEvent
.bKeyDown
&&
1213 ((er
.Event
.KeyEvent
.wVirtualKeyCode
== VK_PAUSE
) ||
1214 (er
.Event
.KeyEvent
.wVirtualKeyCode
== 'C')) &&
1215 (er
.Event
.KeyEvent
.dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
)))
1217 PCSRSS_PROCESS_DATA current
;
1218 PLIST_ENTRY current_entry
;
1219 DPRINT1("Console_Api Ctrl-C\n");
1220 current_entry
= Console
->ProcessList
.Flink
;
1221 while (current_entry
!= &Console
->ProcessList
)
1223 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
1224 current_entry
= current_entry
->Flink
;
1225 ConioConsoleCtrlEvent((DWORD
)CTRL_C_EVENT
, current
);
1227 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1231 if (0 != (er
.Event
.KeyEvent
.dwControlKeyState
1232 & (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1233 && (VK_UP
== er
.Event
.KeyEvent
.wVirtualKeyCode
1234 || VK_DOWN
== er
.Event
.KeyEvent
.wVirtualKeyCode
))
1236 if (er
.Event
.KeyEvent
.bKeyDown
)
1238 /* scroll up or down */
1239 if (VK_UP
== er
.Event
.KeyEvent
.wVirtualKeyCode
)
1241 /* only scroll up if there is room to scroll up into */
1242 if (Console
->ActiveBuffer
->CurrentY
!= Console
->ActiveBuffer
->MaxY
- 1)
1244 Console
->ActiveBuffer
->VirtualY
= (Console
->ActiveBuffer
->VirtualY
+
1245 Console
->ActiveBuffer
->MaxY
- 1) %
1246 Console
->ActiveBuffer
->MaxY
;
1247 Console
->ActiveBuffer
->CurrentY
++;
1252 /* only scroll down if there is room to scroll down into */
1253 if (Console
->ActiveBuffer
->CurrentY
!= 0)
1255 Console
->ActiveBuffer
->VirtualY
= (Console
->ActiveBuffer
->VirtualY
+ 1) %
1256 Console
->ActiveBuffer
->MaxY
;
1257 Console
->ActiveBuffer
->CurrentY
--;
1260 ConioDrawConsole(Console
);
1262 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1265 /* FIXME - convert to ascii */
1266 ConioProcessChar(Console
, ConInRec
);
1269 CSR_API(CsrGetScreenBufferInfo
)
1272 PCSRSS_CONSOLE Console
;
1273 PCSRSS_SCREEN_BUFFER Buff
;
1274 PCONSOLE_SCREEN_BUFFER_INFO pInfo
;
1276 DPRINT("CsrGetScreenBufferInfo\n");
1278 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1279 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1281 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1282 if (! NT_SUCCESS(Status
))
1286 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ScreenBufferInfoRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
1287 if (! NT_SUCCESS(Status
))
1289 ConioUnlockConsole(Console
);
1292 pInfo
= &Request
->Data
.ScreenBufferInfoRequest
.Info
;
1293 pInfo
->dwSize
.X
= Buff
->MaxX
;
1294 pInfo
->dwSize
.Y
= Buff
->MaxY
;
1295 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
;
1296 pInfo
->dwCursorPosition
.Y
= Buff
->CurrentY
;
1297 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
1298 pInfo
->srWindow
.Left
= Buff
->ShowX
;
1299 pInfo
->srWindow
.Right
= Buff
->ShowX
+ Console
->Size
.X
- 1;
1300 pInfo
->srWindow
.Top
= Buff
->ShowY
;
1301 pInfo
->srWindow
.Bottom
= Buff
->ShowY
+ Console
->Size
.Y
- 1;
1302 pInfo
->dwMaximumWindowSize
.X
= Buff
->MaxX
;
1303 pInfo
->dwMaximumWindowSize
.Y
= Buff
->MaxY
;
1304 ConioUnlockScreenBuffer(Buff
);
1305 ConioUnlockConsole(Console
);
1307 return STATUS_SUCCESS
;
1310 CSR_API(CsrSetCursor
)
1313 PCSRSS_CONSOLE Console
;
1314 PCSRSS_SCREEN_BUFFER Buff
;
1315 LONG OldCursorX
, OldCursorY
;
1316 LONG NewCursorX
, NewCursorY
;
1318 DPRINT("CsrSetCursor\n");
1320 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1321 if (! NT_SUCCESS(Status
))
1326 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1327 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1329 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1330 if (! NT_SUCCESS(Status
))
1332 ConioUnlockConsole(Console
);
1336 NewCursorX
= Request
->Data
.SetCursorRequest
.Position
.X
;
1337 NewCursorY
= Request
->Data
.SetCursorRequest
.Position
.Y
;
1338 if (NewCursorX
< 0 || NewCursorX
>= Buff
->MaxX
||
1339 NewCursorY
< 0 || NewCursorY
>= Buff
->MaxY
)
1341 ConioUnlockScreenBuffer(Buff
);
1342 ConioUnlockConsole(Console
);
1343 return STATUS_INVALID_PARAMETER
;
1345 OldCursorX
= Buff
->CurrentX
;
1346 OldCursorY
= Buff
->CurrentY
;
1347 Buff
->CurrentX
= NewCursorX
;
1348 Buff
->CurrentY
= NewCursorY
;
1349 if (Buff
== Console
->ActiveBuffer
)
1351 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
1353 ConioUnlockScreenBuffer(Buff
);
1354 ConioUnlockConsole(Console
);
1355 return STATUS_UNSUCCESSFUL
;
1359 ConioUnlockScreenBuffer(Buff
);
1360 ConioUnlockConsole(Console
);
1362 return STATUS_SUCCESS
;
1365 static VOID FASTCALL
1366 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, COORD
*Start
, UINT Length
)
1368 if (Buff
->MaxX
<= Start
->X
+ Length
)
1370 UpdateRect
->left
= 0;
1374 UpdateRect
->left
= Start
->X
;
1376 if (Buff
->MaxX
<= Start
->X
+ Length
)
1378 UpdateRect
->right
= Buff
->MaxX
- 1;
1382 UpdateRect
->right
= Start
->X
+ Length
- 1;
1384 UpdateRect
->top
= Start
->Y
;
1385 UpdateRect
->bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->MaxX
;
1386 if (Buff
->MaxY
<= UpdateRect
->bottom
)
1388 UpdateRect
->bottom
= Buff
->MaxY
- 1;
1392 CSR_API(CsrWriteConsoleOutputChar
)
1395 PCHAR String
, tmpString
= NULL
;
1397 PCSRSS_CONSOLE Console
;
1398 PCSRSS_SCREEN_BUFFER Buff
;
1399 DWORD X
, Y
, Length
, CharSize
, Written
= 0;
1402 DPRINT("CsrWriteConsoleOutputChar\n");
1404 CharSize
= (Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
1406 if (Request
->Header
.u1
.s1
.TotalLength
1407 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR
)
1408 + (Request
->Data
.WriteConsoleOutputCharRequest
.Length
* CharSize
))
1410 DPRINT1("Invalid request size\n");
1411 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1412 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1413 return STATUS_INVALID_PARAMETER
;
1416 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1417 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1418 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1419 if (NT_SUCCESS(Status
))
1421 if(Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
)
1423 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
1424 (PWCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
,
1425 Request
->Data
.WriteConsoleOutputCharRequest
.Length
,
1426 NULL
, 0, NULL
, NULL
);
1427 tmpString
= String
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
1430 WideCharToMultiByte(Console
->OutputCodePage
, 0,
1431 (PWCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
,
1432 Request
->Data
.WriteConsoleOutputCharRequest
.Length
,
1433 String
, Length
, NULL
, NULL
);
1437 Status
= STATUS_NO_MEMORY
;
1442 String
= (PCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
;
1447 Status
= ConioLockScreenBuffer(ProcessData
,
1448 Request
->Data
.WriteConsoleOutputCharRequest
.ConsoleHandle
,
1451 if (NT_SUCCESS(Status
))
1453 X
= Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.X
;
1454 Y
= (Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1455 Length
= Request
->Data
.WriteConsoleOutputCharRequest
.Length
;
1456 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1459 *Buffer
= *String
++;
1462 if (++X
== Buff
->MaxX
)
1464 if (++Y
== Buff
->MaxY
)
1467 Buffer
= Buff
->Buffer
;
1472 if (Buff
== Console
->ActiveBuffer
)
1474 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputCharRequest
.Coord
,
1475 Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
1476 ConioDrawRegion(Console
, &UpdateRect
);
1479 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.X
= X
;
1480 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->VirtualY
) % Buff
->MaxY
;
1482 ConioUnlockScreenBuffer(Buff
);
1484 if (Request
->Data
.WriteConsoleRequest
.Unicode
)
1486 RtlFreeHeap(GetProcessHeap(), 0, tmpString
);
1489 ConioUnlockConsole(Console
);
1491 Request
->Data
.WriteConsoleOutputCharRequest
.NrCharactersWritten
= Written
;
1495 CSR_API(CsrFillOutputChar
)
1498 PCSRSS_CONSOLE Console
;
1499 PCSRSS_SCREEN_BUFFER Buff
;
1500 DWORD X
, Y
, Length
, Written
= 0;
1505 DPRINT("CsrFillOutputChar\n");
1507 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1508 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1510 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1511 if (! NT_SUCCESS(Status
))
1516 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1517 if (! NT_SUCCESS(Status
))
1519 ConioUnlockConsole(Console
);
1523 X
= Request
->Data
.FillOutputRequest
.Position
.X
;
1524 Y
= (Request
->Data
.FillOutputRequest
.Position
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1525 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1526 if(Request
->Data
.FillOutputRequest
.Unicode
)
1527 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &Request
->Data
.FillOutputRequest
.Char
.UnicodeChar
);
1529 Char
= Request
->Data
.FillOutputRequest
.Char
.AsciiChar
;
1530 Length
= Request
->Data
.FillOutputRequest
.Length
;
1536 if (++X
== Buff
->MaxX
)
1538 if (++Y
== Buff
->MaxY
)
1541 Buffer
= Buff
->Buffer
;
1547 if (Buff
== Console
->ActiveBuffer
)
1549 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputRequest
.Position
,
1550 Request
->Data
.FillOutputRequest
.Length
);
1551 ConioDrawRegion(Console
, &UpdateRect
);
1554 ConioUnlockScreenBuffer(Buff
);
1555 ConioUnlockConsole(Console
);
1556 Length
= Request
->Data
.FillOutputRequest
.Length
;
1557 Request
->Data
.FillOutputRequest
.NrCharactersWritten
= Length
;
1558 return STATUS_SUCCESS
;
1561 CSR_API(CsrReadInputEvent
)
1563 PLIST_ENTRY CurrentEntry
;
1564 PCSRSS_CONSOLE Console
;
1566 BOOLEAN Done
= FALSE
;
1567 ConsoleInput
*Input
;
1569 DPRINT("CsrReadInputEvent\n");
1571 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1572 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1573 Request
->Data
.ReadInputRequest
.Event
= ProcessData
->ConsoleEvent
;
1575 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadInputRequest
.ConsoleHandle
, &Console
, GENERIC_READ
);
1576 if (! NT_SUCCESS(Status
))
1581 /* only get input if there is any */
1582 CurrentEntry
= Console
->InputEvents
.Flink
;
1583 while (CurrentEntry
!= &Console
->InputEvents
)
1585 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
1586 CurrentEntry
= CurrentEntry
->Flink
;
1588 if (Done
&& !Input
->Fake
)
1590 Request
->Data
.ReadInputRequest
.MoreEvents
= TRUE
;
1594 RemoveEntryList(&Input
->ListEntry
);
1596 if (!Done
&& !Input
->Fake
)
1598 Request
->Data
.ReadInputRequest
.Input
= Input
->InputEvent
;
1599 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
1601 ConioInputEventToAnsi(Console
, &Request
->Data
.ReadInputRequest
.Input
);
1606 if (Input
->InputEvent
.EventType
== KEY_EVENT
)
1608 if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
)
1609 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
1610 && '\r' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1612 Console
->WaitingLines
--;
1614 Console
->WaitingChars
--;
1616 HeapFree(Win32CsrApiHeap
, 0, Input
);
1621 Status
= STATUS_SUCCESS
;
1622 Console
->EarlyReturn
= FALSE
;
1626 Status
= STATUS_PENDING
;
1627 Console
->EarlyReturn
= TRUE
; /* mark for early return */
1630 if (IsListEmpty(&Console
->InputEvents
))
1632 ResetEvent(Console
->ActiveEvent
);
1635 ConioUnlockConsole(Console
);
1640 CSR_API(CsrWriteConsoleOutputAttrib
)
1642 PCSRSS_CONSOLE Console
;
1643 PCSRSS_SCREEN_BUFFER Buff
;
1650 DPRINT("CsrWriteConsoleOutputAttrib\n");
1652 if (Request
->Header
.u1
.s1
.TotalLength
1653 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB
)
1654 + Request
->Data
.WriteConsoleOutputAttribRequest
.Length
* sizeof(WORD
))
1656 DPRINT1("Invalid request size\n");
1657 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1658 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1659 return STATUS_INVALID_PARAMETER
;
1662 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1663 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1664 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1665 if (! NT_SUCCESS(Status
))
1670 Status
= ConioLockScreenBuffer(ProcessData
,
1671 Request
->Data
.WriteConsoleOutputAttribRequest
.ConsoleHandle
,
1674 if (! NT_SUCCESS(Status
))
1676 ConioUnlockConsole(Console
);
1680 X
= Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.X
;
1681 Y
= (Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1682 Length
= Request
->Data
.WriteConsoleOutputAttribRequest
.Length
;
1683 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + 1];
1684 Attribute
= Request
->Data
.WriteConsoleOutputAttribRequest
.Attribute
;
1687 *Buffer
= (UCHAR
)(*Attribute
++);
1689 if (++X
== Buff
->MaxX
)
1691 if (++Y
== Buff
->MaxY
)
1694 Buffer
= Buff
->Buffer
+ 1;
1700 if (Buff
== Console
->ActiveBuffer
)
1702 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
,
1703 Request
->Data
.WriteConsoleOutputAttribRequest
.Length
);
1704 ConioDrawRegion(Console
, &UpdateRect
);
1707 ConioUnlockConsole(Console
);
1709 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.X
= X
;
1710 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->VirtualY
) % Buff
->MaxY
;
1712 ConioUnlockScreenBuffer(Buff
);
1714 return STATUS_SUCCESS
;
1717 CSR_API(CsrFillOutputAttrib
)
1719 PCSRSS_SCREEN_BUFFER Buff
;
1725 PCSRSS_CONSOLE Console
;
1727 DPRINT("CsrFillOutputAttrib\n");
1729 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1730 if (! NT_SUCCESS(Status
))
1735 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1736 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1737 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputAttribRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1738 if (! NT_SUCCESS(Status
))
1740 ConioUnlockConsole(Console
);
1744 X
= Request
->Data
.FillOutputAttribRequest
.Coord
.X
;
1745 Y
= (Request
->Data
.FillOutputAttribRequest
.Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1746 Length
= Request
->Data
.FillOutputAttribRequest
.Length
;
1747 Attr
= Request
->Data
.FillOutputAttribRequest
.Attribute
;
1748 Buffer
= &Buff
->Buffer
[(Y
* Buff
->MaxX
* 2) + (X
* 2) + 1];
1753 if (++X
== Buff
->MaxX
)
1755 if (++Y
== Buff
->MaxY
)
1758 Buffer
= Buff
->Buffer
+ 1;
1764 if (Buff
== Console
->ActiveBuffer
)
1766 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputAttribRequest
.Coord
,
1767 Request
->Data
.FillOutputAttribRequest
.Length
);
1768 ConioDrawRegion(Console
, &UpdateRect
);
1771 ConioUnlockScreenBuffer(Buff
);
1772 ConioUnlockConsole(Console
);
1774 return STATUS_SUCCESS
;
1778 CSR_API(CsrGetCursorInfo
)
1780 PCSRSS_SCREEN_BUFFER Buff
;
1783 DPRINT("CsrGetCursorInfo\n");
1785 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1786 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1788 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.GetCursorInfoRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
1789 if (! NT_SUCCESS(Status
))
1793 Request
->Data
.GetCursorInfoRequest
.Info
.bVisible
= Buff
->CursorInfo
.bVisible
;
1794 Request
->Data
.GetCursorInfoRequest
.Info
.dwSize
= Buff
->CursorInfo
.dwSize
;
1795 ConioUnlockScreenBuffer(Buff
);
1797 return STATUS_SUCCESS
;
1800 CSR_API(CsrSetCursorInfo
)
1802 PCSRSS_CONSOLE Console
;
1803 PCSRSS_SCREEN_BUFFER Buff
;
1808 DPRINT("CsrSetCursorInfo\n");
1810 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1811 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1813 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1814 if (! NT_SUCCESS(Status
))
1819 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorInfoRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1820 if (! NT_SUCCESS(Status
))
1822 ConioUnlockConsole(Console
);
1826 Size
= Request
->Data
.SetCursorInfoRequest
.Info
.dwSize
;
1827 Visible
= Request
->Data
.SetCursorInfoRequest
.Info
.bVisible
;
1837 if (Size
!= Buff
->CursorInfo
.dwSize
1838 || (Visible
&& ! Buff
->CursorInfo
.bVisible
) || (! Visible
&& Buff
->CursorInfo
.bVisible
))
1840 Buff
->CursorInfo
.dwSize
= Size
;
1841 Buff
->CursorInfo
.bVisible
= Visible
;
1843 if (! ConioSetCursorInfo(Console
, Buff
))
1845 ConioUnlockScreenBuffer(Buff
);
1846 ConioUnlockConsole(Console
);
1847 return STATUS_UNSUCCESSFUL
;
1851 ConioUnlockScreenBuffer(Buff
);
1852 ConioUnlockConsole(Console
);
1854 return STATUS_SUCCESS
;
1857 CSR_API(CsrSetTextAttrib
)
1860 PCSRSS_CONSOLE Console
;
1861 PCSRSS_SCREEN_BUFFER Buff
;
1863 DPRINT("CsrSetTextAttrib\n");
1865 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1866 if (! NT_SUCCESS(Status
))
1871 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1872 if (! NT_SUCCESS(Status
))
1874 ConioUnlockConsole(Console
);
1878 Buff
->DefaultAttrib
= Request
->Data
.SetAttribRequest
.Attrib
;
1879 if (Buff
== Console
->ActiveBuffer
)
1881 if (! ConioUpdateScreenInfo(Console
, Buff
))
1883 ConioUnlockScreenBuffer(Buff
);
1884 ConioUnlockConsole(Console
);
1885 return STATUS_UNSUCCESSFUL
;
1889 ConioUnlockScreenBuffer(Buff
);
1890 ConioUnlockConsole(Console
);
1892 return STATUS_SUCCESS
;
1895 CSR_API(CsrSetConsoleMode
)
1898 PCSRSS_CONSOLE Console
;
1899 PCSRSS_SCREEN_BUFFER Buff
;
1901 DPRINT("CsrSetConsoleMode\n");
1903 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1904 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1905 Status
= Win32CsrGetObject(ProcessData
,
1906 Request
->Data
.SetConsoleModeRequest
.ConsoleHandle
,
1907 (Object_t
**) &Console
, GENERIC_WRITE
);
1908 if (! NT_SUCCESS(Status
))
1913 Buff
= (PCSRSS_SCREEN_BUFFER
)Console
;
1914 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
1916 Console
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_INPUT_MODE_VALID
;
1918 else if (CONIO_SCREEN_BUFFER_MAGIC
== Console
->Header
.Type
)
1920 Buff
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_OUTPUT_MODE_VALID
;
1924 Status
= STATUS_INVALID_HANDLE
;
1927 Win32CsrReleaseObjectByPointer((Object_t
*)Console
);
1932 CSR_API(CsrGetConsoleMode
)
1935 PCSRSS_CONSOLE Console
;
1936 PCSRSS_SCREEN_BUFFER Buff
; /* gee, I really wish I could use an anonymous union here */
1938 DPRINT("CsrGetConsoleMode\n");
1940 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1941 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1942 Status
= Win32CsrGetObject(ProcessData
, Request
->Data
.GetConsoleModeRequest
.ConsoleHandle
,
1943 (Object_t
**) &Console
, GENERIC_READ
);
1944 if (! NT_SUCCESS(Status
))
1948 Status
= STATUS_SUCCESS
;
1949 Buff
= (PCSRSS_SCREEN_BUFFER
) Console
;
1950 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
1952 Request
->Data
.GetConsoleModeRequest
.ConsoleMode
= Console
->Mode
;
1954 else if (CONIO_SCREEN_BUFFER_MAGIC
== Buff
->Header
.Type
)
1956 Request
->Data
.GetConsoleModeRequest
.ConsoleMode
= Buff
->Mode
;
1960 Status
= STATUS_INVALID_HANDLE
;
1963 Win32CsrReleaseObjectByPointer((Object_t
*)Console
);
1967 CSR_API(CsrCreateScreenBuffer
)
1969 PCSRSS_CONSOLE Console
;
1970 PCSRSS_SCREEN_BUFFER Buff
;
1973 DPRINT("CsrCreateScreenBuffer\n");
1975 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1976 if (! NT_SUCCESS(Status
))
1981 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1982 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1984 Buff
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
1988 if (Console
->ActiveBuffer
)
1990 Buff
->MaxX
= Console
->ActiveBuffer
->MaxX
;
1991 Buff
->MaxY
= Console
->ActiveBuffer
->MaxY
;
1992 Buff
->CursorInfo
.bVisible
= Console
->ActiveBuffer
->CursorInfo
.bVisible
;
1993 Buff
->CursorInfo
.dwSize
= Console
->ActiveBuffer
->CursorInfo
.dwSize
;
1997 Buff
->CursorInfo
.bVisible
= TRUE
;
1998 Buff
->CursorInfo
.dwSize
= CSR_DEFAULT_CURSOR_SIZE
;
2001 if (Buff
->MaxX
== 0)
2006 if (Buff
->MaxY
== 0)
2011 Status
= CsrInitConsoleScreenBuffer(Console
, Buff
);
2012 if(NT_SUCCESS(Status
))
2014 Status
= Win32CsrInsertObject(ProcessData
,
2015 &Request
->Data
.CreateScreenBufferRequest
.OutputHandle
,
2017 Request
->Data
.CreateScreenBufferRequest
.Access
,
2018 Request
->Data
.CreateScreenBufferRequest
.Inheritable
);
2023 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2026 ConioUnlockConsole(Console
);
2030 CSR_API(CsrSetScreenBuffer
)
2033 PCSRSS_CONSOLE Console
;
2034 PCSRSS_SCREEN_BUFFER Buff
;
2036 DPRINT("CsrSetScreenBuffer\n");
2038 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2039 if (! NT_SUCCESS(Status
))
2044 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2045 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2047 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetScreenBufferRequest
.OutputHandle
, &Buff
, GENERIC_WRITE
);
2048 if (! NT_SUCCESS(Status
))
2050 ConioUnlockConsole(Console
);
2054 if (Buff
== Console
->ActiveBuffer
)
2056 ConioUnlockScreenBuffer(Buff
);
2057 ConioUnlockConsole(Console
);
2058 return STATUS_SUCCESS
;
2061 /* drop reference to old buffer, maybe delete */
2062 if (! InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
2064 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
2066 /* tie console to new buffer */
2067 Console
->ActiveBuffer
= Buff
;
2068 /* inc ref count on new buffer */
2069 InterlockedIncrement(&Buff
->Header
.ReferenceCount
);
2070 /* Redraw the console */
2071 ConioDrawConsole(Console
);
2073 ConioUnlockScreenBuffer(Buff
);
2074 ConioUnlockConsole(Console
);
2076 return STATUS_SUCCESS
;
2079 CSR_API(CsrSetTitle
)
2082 PCSRSS_CONSOLE Console
;
2085 DPRINT("CsrSetTitle\n");
2087 if (Request
->Header
.u1
.s1
.TotalLength
2088 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_SET_TITLE
)
2089 + Request
->Data
.SetTitleRequest
.Length
)
2091 DPRINT1("Invalid request size\n");
2092 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2093 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2094 return STATUS_INVALID_PARAMETER
;
2097 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2098 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2099 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2100 if(NT_SUCCESS(Status
))
2102 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, Request
->Data
.SetTitleRequest
.Length
);
2105 /* copy title to console */
2106 RtlFreeUnicodeString(&Console
->Title
);
2107 Console
->Title
.Buffer
= Buffer
;
2108 Console
->Title
.Length
= Console
->Title
.MaximumLength
= Request
->Data
.SetTitleRequest
.Length
;
2109 memcpy(Console
->Title
.Buffer
, Request
->Data
.SetTitleRequest
.Title
, Console
->Title
.Length
);
2110 if (! ConioChangeTitle(Console
))
2112 Status
= STATUS_UNSUCCESSFUL
;
2116 Status
= STATUS_SUCCESS
;
2121 Status
= STATUS_NO_MEMORY
;
2123 ConioUnlockConsole(Console
);
2129 CSR_API(CsrGetTitle
)
2132 PCSRSS_CONSOLE Console
;
2135 DPRINT("CsrGetTitle\n");
2137 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2138 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2139 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2140 if (! NT_SUCCESS(Status
))
2142 DPRINT1("Can't get console\n");
2146 /* Copy title of the console to the user title buffer */
2147 RtlZeroMemory(&Request
->Data
.GetTitleRequest
, sizeof(CSRSS_GET_TITLE
));
2148 Request
->Data
.GetTitleRequest
.Length
= Console
->Title
.Length
;
2149 memcpy (Request
->Data
.GetTitleRequest
.Title
, Console
->Title
.Buffer
,
2150 Console
->Title
.Length
);
2151 Length
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_SET_TITLE
) + Console
->Title
.Length
;
2153 ConioUnlockConsole(Console
);
2155 if (Length
> sizeof(CSR_API_MESSAGE
))
2157 Request
->Header
.u1
.s1
.TotalLength
= Length
;
2158 Request
->Header
.u1
.s1
.DataLength
= Length
- sizeof(PORT_MESSAGE
);
2160 return STATUS_SUCCESS
;
2163 CSR_API(CsrWriteConsoleOutput
)
2165 SHORT i
, X
, Y
, SizeX
, SizeY
;
2166 PCSRSS_CONSOLE Console
;
2167 PCSRSS_SCREEN_BUFFER Buff
;
2169 CHAR_INFO
* CurCharInfo
;
2171 CHAR_INFO
* CharInfo
;
2178 DPRINT("CsrWriteConsoleOutput\n");
2180 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2181 if (! NT_SUCCESS(Status
))
2186 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2187 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2188 Status
= ConioLockScreenBuffer(ProcessData
,
2189 Request
->Data
.WriteConsoleOutputRequest
.ConsoleHandle
,
2192 if (! NT_SUCCESS(Status
))
2194 ConioUnlockConsole(Console
);
2198 BufferSize
= Request
->Data
.WriteConsoleOutputRequest
.BufferSize
;
2199 PSize
= BufferSize
.X
* BufferSize
.Y
* sizeof(CHAR_INFO
);
2200 BufferCoord
= Request
->Data
.WriteConsoleOutputRequest
.BufferCoord
;
2201 CharInfo
= Request
->Data
.WriteConsoleOutputRequest
.CharInfo
;
2202 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
) ||
2203 (((ULONG_PTR
)CharInfo
+ PSize
) >
2204 ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2206 ConioUnlockScreenBuffer(Buff
);
2207 ConioUnlockConsole(Console
);
2208 return STATUS_ACCESS_VIOLATION
;
2210 WriteRegion
.left
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
;
2211 WriteRegion
.top
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
;
2212 WriteRegion
.right
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
;
2213 WriteRegion
.bottom
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
;
2215 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&WriteRegion
));
2216 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&WriteRegion
));
2217 WriteRegion
.bottom
= WriteRegion
.top
+ SizeY
- 1;
2218 WriteRegion
.right
= WriteRegion
.left
+ SizeX
- 1;
2220 /* Make sure WriteRegion is inside the screen buffer */
2221 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2222 if (! ConioGetIntersection(&WriteRegion
, &ScreenBuffer
, &WriteRegion
))
2224 ConioUnlockScreenBuffer(Buff
);
2225 ConioUnlockConsole(Console
);
2227 /* It is okay to have a WriteRegion completely outside the screen buffer.
2228 No data is written then. */
2229 return STATUS_SUCCESS
;
2232 for (i
= 0, Y
= WriteRegion
.top
; Y
<= WriteRegion
.bottom
; i
++, Y
++)
2234 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
2235 Ptr
= ConioCoordToPointer(Buff
, WriteRegion
.left
, Y
);
2236 for (X
= WriteRegion
.left
; X
<= WriteRegion
.right
; X
++)
2239 if (Request
->Data
.WriteConsoleOutputRequest
.Unicode
)
2241 ConsoleUnicodeCharToAnsiChar(Console
, &AsciiChar
, &CurCharInfo
->Char
.UnicodeChar
);
2245 AsciiChar
= CurCharInfo
->Char
.AsciiChar
;
2248 *Ptr
++ = CurCharInfo
->Attributes
;
2253 ConioDrawRegion(Console
, &WriteRegion
);
2255 ConioUnlockScreenBuffer(Buff
);
2256 ConioUnlockConsole(Console
);
2258 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
= WriteRegion
.left
+ SizeX
- 1;
2259 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
= WriteRegion
.top
+ SizeY
- 1;
2260 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
= WriteRegion
.left
;
2261 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
= WriteRegion
.top
;
2263 return STATUS_SUCCESS
;
2266 CSR_API(CsrFlushInputBuffer
)
2268 PLIST_ENTRY CurrentEntry
;
2269 PCSRSS_CONSOLE Console
;
2270 ConsoleInput
* Input
;
2273 DPRINT("CsrFlushInputBuffer\n");
2275 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2276 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2277 Status
= ConioLockConsole(ProcessData
,
2278 Request
->Data
.FlushInputBufferRequest
.ConsoleInput
,
2281 if(! NT_SUCCESS(Status
))
2286 /* Discard all entries in the input event queue */
2287 while (!IsListEmpty(&Console
->InputEvents
))
2289 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
2290 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
2291 /* Destroy the event */
2292 HeapFree(Win32CsrApiHeap
, 0, Input
);
2294 ResetEvent(Console
->ActiveEvent
);
2295 Console
->WaitingChars
=0;
2297 ConioUnlockConsole(Console
);
2299 return STATUS_SUCCESS
;
2302 CSR_API(CsrScrollConsoleScreenBuffer
)
2304 PCSRSS_CONSOLE Console
;
2305 PCSRSS_SCREEN_BUFFER Buff
;
2310 RECT ScrollRectangle
;
2313 HANDLE ConsoleHandle
;
2314 BOOLEAN UseClipRectangle
;
2315 COORD DestinationOrigin
;
2319 DPRINT("CsrScrollConsoleScreenBuffer\n");
2321 ConsoleHandle
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ConsoleHandle
;
2322 UseClipRectangle
= Request
->Data
.ScrollConsoleScreenBufferRequest
.UseClipRectangle
;
2323 DestinationOrigin
= Request
->Data
.ScrollConsoleScreenBufferRequest
.DestinationOrigin
;
2324 Fill
= Request
->Data
.ScrollConsoleScreenBufferRequest
.Fill
;
2326 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2327 if (! NT_SUCCESS(Status
))
2332 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2333 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2334 Status
= ConioLockScreenBuffer(ProcessData
, ConsoleHandle
, &Buff
, GENERIC_WRITE
);
2335 if (! NT_SUCCESS(Status
))
2337 ConioUnlockConsole(Console
);
2341 ScrollRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Left
;
2342 ScrollRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Top
;
2343 ScrollRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Right
;
2344 ScrollRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Bottom
;
2346 /* Make sure source rectangle is inside the screen buffer */
2347 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2348 if (! ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, &ScrollRectangle
))
2350 ConioUnlockScreenBuffer(Buff
);
2351 ConioUnlockConsole(Console
);
2352 return STATUS_SUCCESS
;
2355 /* If the source was clipped on the left or top, adjust the destination accordingly */
2356 if (ScrollRectangle
.left
< 0)
2358 DestinationOrigin
.X
-= ScrollRectangle
.left
;
2360 if (ScrollRectangle
.top
< 0)
2362 DestinationOrigin
.Y
-= ScrollRectangle
.top
;
2365 if (UseClipRectangle
)
2367 ClipRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Left
;
2368 ClipRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Top
;
2369 ClipRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Right
;
2370 ClipRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Bottom
;
2371 if (!ConioGetIntersection(&ClipRectangle
, &ClipRectangle
, &ScreenBuffer
))
2373 ConioUnlockConsole(Console
);
2374 ConioUnlockScreenBuffer(Buff
);
2375 return STATUS_SUCCESS
;
2380 ClipRectangle
= ScreenBuffer
;
2383 ConioInitRect(&DstRegion
,
2384 DestinationOrigin
.Y
,
2385 DestinationOrigin
.X
,
2386 DestinationOrigin
.Y
+ ConioRectHeight(&SrcRegion
) - 1,
2387 DestinationOrigin
.X
+ ConioRectWidth(&SrcRegion
) - 1);
2389 if (Request
->Data
.ScrollConsoleScreenBufferRequest
.Unicode
)
2390 ConsoleUnicodeCharToAnsiChar(Console
, &FillChar
, &Fill
.Char
.UnicodeChar
);
2392 FillChar
= Fill
.Char
.AsciiChar
;
2394 ConioMoveRegion(Buff
, &SrcRegion
, &DstRegion
, &ClipRectangle
, Fill
.Attributes
<< 8 | (BYTE
)FillChar
);
2396 if (Buff
== Console
->ActiveBuffer
)
2398 ConioGetUnion(&UpdateRegion
, &SrcRegion
, &DstRegion
);
2399 if (ConioGetIntersection(&UpdateRegion
, &UpdateRegion
, &ClipRectangle
))
2401 /* Draw update region */
2402 ConioDrawRegion(Console
, &UpdateRegion
);
2406 ConioUnlockScreenBuffer(Buff
);
2407 ConioUnlockConsole(Console
);
2409 return STATUS_SUCCESS
;
2412 CSR_API(CsrReadConsoleOutputChar
)
2415 PCSRSS_CONSOLE Console
;
2416 PCSRSS_SCREEN_BUFFER Buff
;
2423 DPRINT("CsrReadConsoleOutputChar\n");
2425 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2426 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2427 ReadBuffer
= Request
->Data
.ReadConsoleOutputCharRequest
.String
;
2429 CharSize
= (Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
2431 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2432 if (! NT_SUCCESS(Status
))
2437 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputCharRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
2438 if (! NT_SUCCESS(Status
))
2440 ConioUnlockConsole(Console
);
2444 Xpos
= Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.X
;
2445 Ypos
= (Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
2447 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
; ++i
)
2449 Char
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
)];
2451 if(Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
)
2453 ConsoleAnsiCharToUnicodeChar(Console
, (WCHAR
*)ReadBuffer
, &Char
);
2454 ReadBuffer
+= sizeof(WCHAR
);
2457 *(ReadBuffer
++) = Char
;
2461 if (Xpos
== Buff
->MaxX
)
2466 if (Ypos
== Buff
->MaxY
)
2474 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.X
= Xpos
;
2475 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.Y
= (Ypos
- Buff
->VirtualY
+ Buff
->MaxY
) % Buff
->MaxY
;
2477 ConioUnlockScreenBuffer(Buff
);
2478 ConioUnlockConsole(Console
);
2480 Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
= (DWORD
)((ULONG_PTR
)ReadBuffer
- (ULONG_PTR
)Request
->Data
.ReadConsoleOutputCharRequest
.String
) / CharSize
;
2481 if (Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
* CharSize
+ CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR
) > sizeof(CSR_API_MESSAGE
))
2483 Request
->Header
.u1
.s1
.TotalLength
= Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
* CharSize
+ CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR
);
2484 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2487 return STATUS_SUCCESS
;
2491 CSR_API(CsrReadConsoleOutputAttrib
)
2494 PCSRSS_SCREEN_BUFFER Buff
;
2498 DWORD CurrentLength
;
2500 DPRINT("CsrReadConsoleOutputAttrib\n");
2502 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2503 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2504 ReadBuffer
= Request
->Data
.ReadConsoleOutputAttribRequest
.Attribute
;
2506 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputAttribRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
2507 if (! NT_SUCCESS(Status
))
2512 Xpos
= Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.X
;
2513 Ypos
= (Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
2515 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
; ++i
)
2517 *ReadBuffer
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
) + 1];
2522 if (Xpos
== Buff
->MaxX
)
2527 if (Ypos
== Buff
->MaxY
)
2536 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.X
= Xpos
;
2537 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.Y
= (Ypos
- Buff
->VirtualY
+ Buff
->MaxY
) % Buff
->MaxY
;
2539 ConioUnlockScreenBuffer(Buff
);
2541 CurrentLength
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_ATTRIB
)
2542 + Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
* sizeof(WORD
);
2543 if (CurrentLength
> sizeof(CSR_API_MESSAGE
))
2545 Request
->Header
.u1
.s1
.TotalLength
= CurrentLength
;
2546 Request
->Header
.u1
.s1
.DataLength
= CurrentLength
- sizeof(PORT_MESSAGE
);
2549 return STATUS_SUCCESS
;
2553 CSR_API(CsrGetNumberOfConsoleInputEvents
)
2556 PCSRSS_CONSOLE Console
;
2557 PLIST_ENTRY CurrentItem
;
2559 ConsoleInput
*Input
;
2561 DPRINT("CsrGetNumberOfConsoleInputEvents\n");
2563 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2564 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2566 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
, GENERIC_READ
);
2567 if (! NT_SUCCESS(Status
))
2572 CurrentItem
= Console
->InputEvents
.Flink
;
2575 /* If there are any events ... */
2576 while (CurrentItem
!= &Console
->InputEvents
)
2578 Input
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2579 CurrentItem
= CurrentItem
->Flink
;
2586 ConioUnlockConsole(Console
);
2588 Request
->Data
.GetNumInputEventsRequest
.NumInputEvents
= NumEvents
;
2590 return STATUS_SUCCESS
;
2594 CSR_API(CsrPeekConsoleInput
)
2597 PCSRSS_CONSOLE Console
;
2600 PLIST_ENTRY CurrentItem
;
2601 PINPUT_RECORD InputRecord
;
2605 DPRINT("CsrPeekConsoleInput\n");
2607 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2608 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2610 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
, GENERIC_READ
);
2611 if(! NT_SUCCESS(Status
))
2616 InputRecord
= Request
->Data
.PeekConsoleInputRequest
.InputRecord
;
2617 Length
= Request
->Data
.PeekConsoleInputRequest
.Length
;
2618 Size
= Length
* sizeof(INPUT_RECORD
);
2620 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2621 || (((ULONG_PTR
)InputRecord
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2623 ConioUnlockConsole(Console
);
2624 return STATUS_ACCESS_VIOLATION
;
2629 if (! IsListEmpty(&Console
->InputEvents
))
2631 CurrentItem
= Console
->InputEvents
.Flink
;
2633 while (CurrentItem
!= &Console
->InputEvents
&& NumItems
< Length
)
2635 Item
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2639 CurrentItem
= CurrentItem
->Flink
;
2644 *InputRecord
= Item
->InputEvent
;
2646 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
2648 ConioInputEventToAnsi(Console
, InputRecord
);
2652 CurrentItem
= CurrentItem
->Flink
;
2656 ConioUnlockConsole(Console
);
2658 Request
->Data
.PeekConsoleInputRequest
.Length
= NumItems
;
2660 return STATUS_SUCCESS
;
2664 CSR_API(CsrReadConsoleOutput
)
2666 PCHAR_INFO CharInfo
;
2667 PCHAR_INFO CurCharInfo
;
2668 PCSRSS_SCREEN_BUFFER Buff
;
2682 DPRINT("CsrReadConsoleOutput\n");
2684 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2685 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2687 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
2688 if (! NT_SUCCESS(Status
))
2693 CharInfo
= Request
->Data
.ReadConsoleOutputRequest
.CharInfo
;
2694 ReadRegion
.left
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
;
2695 ReadRegion
.top
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
;
2696 ReadRegion
.right
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
;
2697 ReadRegion
.bottom
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
;
2698 BufferSize
= Request
->Data
.ReadConsoleOutputRequest
.BufferSize
;
2699 BufferCoord
= Request
->Data
.ReadConsoleOutputRequest
.BufferCoord
;
2700 Length
= BufferSize
.X
* BufferSize
.Y
;
2701 Size
= Length
* sizeof(CHAR_INFO
);
2703 /* FIXME: Is this correct? */
2704 CodePage
= ProcessData
->Console
->OutputCodePage
;
2706 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
)
2707 || (((ULONG_PTR
)CharInfo
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2709 ConioUnlockScreenBuffer(Buff
);
2710 return STATUS_ACCESS_VIOLATION
;
2713 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&ReadRegion
));
2714 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&ReadRegion
));
2715 ReadRegion
.bottom
= ReadRegion
.top
+ SizeY
;
2716 ReadRegion
.right
= ReadRegion
.left
+ SizeX
;
2718 ConioInitRect(&ScreenRect
, 0, 0, Buff
->MaxY
, Buff
->MaxX
);
2719 if (! ConioGetIntersection(&ReadRegion
, &ScreenRect
, &ReadRegion
))
2721 ConioUnlockScreenBuffer(Buff
);
2722 return STATUS_SUCCESS
;
2725 for (i
= 0, Y
= ReadRegion
.top
; Y
< ReadRegion
.bottom
; ++i
, ++Y
)
2727 CurCharInfo
= CharInfo
+ (i
* BufferSize
.X
);
2729 Ptr
= ConioCoordToPointer(Buff
, ReadRegion
.left
, Y
);
2730 for (X
= ReadRegion
.left
; X
< ReadRegion
.right
; ++X
)
2732 if (Request
->Data
.ReadConsoleOutputRequest
.Unicode
)
2734 MultiByteToWideChar(CodePage
, 0,
2736 &CurCharInfo
->Char
.UnicodeChar
, 1);
2740 CurCharInfo
->Char
.AsciiChar
= *Ptr
++;
2742 CurCharInfo
->Attributes
= *Ptr
++;
2747 ConioUnlockScreenBuffer(Buff
);
2749 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
= ReadRegion
.left
+ SizeX
- 1;
2750 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
= ReadRegion
.top
+ SizeY
- 1;
2751 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
= ReadRegion
.left
;
2752 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
= ReadRegion
.top
;
2754 return STATUS_SUCCESS
;
2758 CSR_API(CsrWriteConsoleInput
)
2760 PINPUT_RECORD InputRecord
;
2761 PCSRSS_CONSOLE Console
;
2766 ConsoleInput
* Record
;
2768 DPRINT("CsrWriteConsoleInput\n");
2770 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2771 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2773 Status
= ConioLockConsole(ProcessData
, Request
->Data
.WriteConsoleInputRequest
.ConsoleHandle
, &Console
, GENERIC_WRITE
);
2774 if (! NT_SUCCESS(Status
))
2779 InputRecord
= Request
->Data
.WriteConsoleInputRequest
.InputRecord
;
2780 Length
= Request
->Data
.WriteConsoleInputRequest
.Length
;
2781 Size
= Length
* sizeof(INPUT_RECORD
);
2783 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2784 || (((ULONG_PTR
)InputRecord
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2786 ConioUnlockConsole(Console
);
2787 return STATUS_ACCESS_VIOLATION
;
2790 for (i
= 0; i
< Length
; i
++)
2792 Record
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
2795 ConioUnlockConsole(Console
);
2796 return STATUS_INSUFFICIENT_RESOURCES
;
2799 Record
->Echoed
= FALSE
;
2800 Record
->Fake
= FALSE
;
2801 //Record->InputEvent = *InputRecord++;
2802 memcpy(&Record
->InputEvent
, &InputRecord
[i
], sizeof(INPUT_RECORD
));
2803 if (KEY_EVENT
== Record
->InputEvent
.EventType
)
2805 /* FIXME - convert from unicode to ascii!! */
2806 ConioProcessChar(Console
, Record
);
2810 ConioUnlockConsole(Console
);
2812 Request
->Data
.WriteConsoleInputRequest
.Length
= i
;
2814 return STATUS_SUCCESS
;
2817 /**********************************************************************
2818 * HardwareStateProperty
2821 * Set/Get the value of the HardwareState and switch
2822 * between direct video buffer ouput and GDI windowed
2825 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
2826 * object. We use the same object to Request.
2828 * ConsoleHwState has the correct size to be compatible
2829 * with NT's, but values are not.
2831 static NTSTATUS FASTCALL
2832 SetConsoleHardwareState (PCSRSS_CONSOLE Console
, DWORD ConsoleHwState
)
2834 DPRINT1("Console Hardware State: %d\n", ConsoleHwState
);
2836 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED
== ConsoleHwState
)
2837 ||(CONSOLE_HARDWARE_STATE_DIRECT
== ConsoleHwState
))
2839 if (Console
->HardwareState
!= ConsoleHwState
)
2841 /* TODO: implement switching from full screen to windowed mode */
2842 /* TODO: or back; now simply store the hardware state */
2843 Console
->HardwareState
= ConsoleHwState
;
2846 return STATUS_SUCCESS
;
2849 return STATUS_INVALID_PARAMETER_3
; /* Client: (handle, set_get, [mode]) */
2852 CSR_API(CsrHardwareStateProperty
)
2854 PCSRSS_CONSOLE Console
;
2857 DPRINT("CsrHardwareStateProperty\n");
2859 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2860 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2862 Status
= ConioLockConsole(ProcessData
,
2863 Request
->Data
.ConsoleHardwareStateRequest
.ConsoleHandle
,
2866 if (! NT_SUCCESS(Status
))
2868 DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
2872 switch (Request
->Data
.ConsoleHardwareStateRequest
.SetGet
)
2874 case CONSOLE_HARDWARE_STATE_GET
:
2875 Request
->Data
.ConsoleHardwareStateRequest
.State
= Console
->HardwareState
;
2878 case CONSOLE_HARDWARE_STATE_SET
:
2879 DPRINT("Setting console hardware state.\n");
2880 Status
= SetConsoleHardwareState(Console
, Request
->Data
.ConsoleHardwareStateRequest
.State
);
2884 Status
= STATUS_INVALID_PARAMETER_2
; /* Client: (handle, [set_get], mode) */
2888 ConioUnlockConsole(Console
);
2893 CSR_API(CsrGetConsoleWindow
)
2895 PCSRSS_CONSOLE Console
;
2898 DPRINT("CsrGetConsoleWindow\n");
2900 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2901 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2903 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2904 if (! NT_SUCCESS(Status
))
2909 Request
->Data
.GetConsoleWindowRequest
.WindowHandle
= Console
->hWindow
;
2910 ConioUnlockConsole(Console
);
2912 return STATUS_SUCCESS
;
2915 CSR_API(CsrSetConsoleIcon
)
2917 PCSRSS_CONSOLE Console
;
2920 DPRINT("CsrSetConsoleIcon\n");
2922 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2923 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2925 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2926 if (! NT_SUCCESS(Status
))
2931 Status
= (ConioChangeIcon(Console
, Request
->Data
.SetConsoleIconRequest
.WindowIcon
)
2932 ? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
2933 ConioUnlockConsole(Console
);
2938 CSR_API(CsrGetConsoleCodePage
)
2940 PCSRSS_CONSOLE Console
;
2943 DPRINT("CsrGetConsoleCodePage\n");
2945 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2946 if (! NT_SUCCESS(Status
))
2951 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2952 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2953 Request
->Data
.GetConsoleCodePage
.CodePage
= Console
->CodePage
;
2954 ConioUnlockConsole(Console
);
2955 return STATUS_SUCCESS
;
2958 CSR_API(CsrSetConsoleCodePage
)
2960 PCSRSS_CONSOLE Console
;
2963 DPRINT("CsrSetConsoleCodePage\n");
2965 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2966 if (! NT_SUCCESS(Status
))
2971 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2972 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2974 if (IsValidCodePage(Request
->Data
.SetConsoleCodePage
.CodePage
))
2976 Console
->CodePage
= Request
->Data
.SetConsoleCodePage
.CodePage
;
2977 ConioUnlockConsole(Console
);
2978 return STATUS_SUCCESS
;
2981 ConioUnlockConsole(Console
);
2982 return STATUS_INVALID_PARAMETER
;
2985 CSR_API(CsrGetConsoleOutputCodePage
)
2987 PCSRSS_CONSOLE Console
;
2990 DPRINT("CsrGetConsoleOutputCodePage\n");
2992 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2993 if (! NT_SUCCESS(Status
))
2998 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2999 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3000 Request
->Data
.GetConsoleOutputCodePage
.CodePage
= Console
->OutputCodePage
;
3001 ConioUnlockConsole(Console
);
3002 return STATUS_SUCCESS
;
3005 CSR_API(CsrSetConsoleOutputCodePage
)
3007 PCSRSS_CONSOLE Console
;
3010 DPRINT("CsrSetConsoleOutputCodePage\n");
3012 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3013 if (! NT_SUCCESS(Status
))
3018 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3019 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3021 if (IsValidCodePage(Request
->Data
.SetConsoleOutputCodePage
.CodePage
))
3023 Console
->OutputCodePage
= Request
->Data
.SetConsoleOutputCodePage
.CodePage
;
3024 ConioUnlockConsole(Console
);
3025 return STATUS_SUCCESS
;
3028 ConioUnlockConsole(Console
);
3029 return STATUS_INVALID_PARAMETER
;
3032 CSR_API(CsrGetProcessList
)
3035 PCSRSS_CONSOLE Console
;
3036 PCSRSS_PROCESS_DATA current
;
3037 PLIST_ENTRY current_entry
;
3038 ULONG nItems
, nCopied
, Length
;
3041 DPRINT("CsrGetProcessList\n");
3043 Buffer
= Request
->Data
.GetProcessListRequest
.ProcessId
;
3044 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3045 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3047 nItems
= nCopied
= 0;
3048 Request
->Data
.GetProcessListRequest
.nProcessIdsCopied
= 0;
3049 Request
->Data
.GetProcessListRequest
.nProcessIdsTotal
= 0;
3051 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3052 if (! NT_SUCCESS(Status
))
3057 DPRINT1("Console_Api Ctrl-C\n");
3059 for(current_entry
= Console
->ProcessList
.Flink
;
3060 current_entry
!= &Console
->ProcessList
;
3061 current_entry
= current_entry
->Flink
)
3063 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
3064 if(++nItems
< Request
->Data
.GetProcessListRequest
.nMaxIds
)
3066 *(Buffer
++) = current
->ProcessId
;
3071 ConioUnlockConsole(Console
);
3073 Request
->Data
.GetProcessListRequest
.nProcessIdsCopied
= nCopied
;
3074 Request
->Data
.GetProcessListRequest
.nProcessIdsTotal
= nItems
;
3076 Length
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_GET_PROCESS_LIST
) + nCopied
* sizeof(HANDLE
);
3077 if (Length
> sizeof(CSR_API_MESSAGE
))
3079 Request
->Header
.u1
.s1
.TotalLength
= Length
;
3080 Request
->Header
.u1
.s1
.DataLength
= Length
- sizeof(PORT_MESSAGE
);
3082 return STATUS_SUCCESS
;
3085 CSR_API(CsrGenerateCtrlEvent
)
3087 PCSRSS_CONSOLE Console
;
3088 PCSRSS_PROCESS_DATA current
;
3089 PLIST_ENTRY current_entry
;
3093 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3094 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3096 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3097 if (! NT_SUCCESS(Status
))
3102 Group
= Request
->Data
.GenerateCtrlEvent
.ProcessGroup
;
3103 Status
= STATUS_INVALID_PARAMETER
;
3104 for (current_entry
= Console
->ProcessList
.Flink
;
3105 current_entry
!= &Console
->ProcessList
;
3106 current_entry
= current_entry
->Flink
)
3108 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
3109 if (Group
== 0 || current
->ProcessGroup
== Group
)
3111 ConioConsoleCtrlEvent(Request
->Data
.GenerateCtrlEvent
.Event
, current
);
3112 Status
= STATUS_SUCCESS
;
3116 ConioUnlockConsole(Console
);