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 ConsoleInputAnsiCharToUnicodeChar(Console, dWChar, sChar) \
30 MultiByteToWideChar((Console)->CodePage, 0, (sChar), 1, (dWChar), 1)
32 #define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
33 WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
35 #define ConsoleAnsiCharToUnicodeChar(Console, dWChar, sChar) \
36 MultiByteToWideChar((Console)->OutputCodePage, 0, (sChar), 1, (dWChar), 1)
39 /* FUNCTIONS *****************************************************************/
42 ConioConsoleFromProcessData(PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_CONSOLE
*Console
)
44 PCSRSS_CONSOLE ProcessConsole
= ProcessData
->Console
;
49 return STATUS_INVALID_HANDLE
;
52 InterlockedIncrement(&ProcessConsole
->Header
.ReferenceCount
);
53 EnterCriticalSection(&(ProcessConsole
->Header
.Lock
));
54 *Console
= ProcessConsole
;
56 return STATUS_SUCCESS
;
60 ConioConsoleCtrlEventTimeout(DWORD Event
, PCSRSS_PROCESS_DATA ProcessData
, DWORD Timeout
)
64 DPRINT("ConioConsoleCtrlEvent Parent ProcessId = %x\n", ProcessData
->ProcessId
);
66 if (ProcessData
->CtrlDispatcher
)
69 Thread
= CreateRemoteThread(ProcessData
->Process
, NULL
, 0,
70 (LPTHREAD_START_ROUTINE
) ProcessData
->CtrlDispatcher
,
71 UlongToPtr(Event
), 0, NULL
);
74 DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
77 WaitForSingleObject(Thread
, Timeout
);
83 ConioConsoleCtrlEvent(DWORD Event
, PCSRSS_PROCESS_DATA ProcessData
)
85 ConioConsoleCtrlEventTimeout(Event
, ProcessData
, 0);
89 ConioCoordToPointer(PCSRSS_SCREEN_BUFFER Buff
, ULONG X
, ULONG Y
)
91 return &Buff
->Buffer
[2 * (((Y
+ Buff
->VirtualY
) % Buff
->MaxY
) * Buff
->MaxX
+ X
)];
95 ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff
)
97 PBYTE Ptr
= ConioCoordToPointer(Buff
, 0, Buff
->CurrentY
);
100 for (Pos
= 0; Pos
< Buff
->MaxX
; Pos
++)
104 *Ptr
++ = Buff
->DefaultAttrib
;
108 static NTSTATUS FASTCALL
109 CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console
,
110 PCSRSS_SCREEN_BUFFER Buffer
)
112 DPRINT("CsrInitConsoleScreenBuffer Size X %d Size Y %d\n", Buffer
->MaxX
, Buffer
->MaxY
);
114 Buffer
->Header
.Type
= CONIO_SCREEN_BUFFER_MAGIC
;
115 Buffer
->Header
.ReferenceCount
= 0;
118 Buffer
->VirtualY
= 0;
119 Buffer
->Buffer
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, Buffer
->MaxX
* Buffer
->MaxY
* 2);
120 if (NULL
== Buffer
->Buffer
)
122 return STATUS_INSUFFICIENT_RESOURCES
;
124 InitializeCriticalSection(&Buffer
->Header
.Lock
);
125 ConioInitScreenBuffer(Console
, Buffer
);
126 /* initialize buffer to be empty with default attributes */
127 for (Buffer
->CurrentY
= 0 ; Buffer
->CurrentY
< Buffer
->MaxY
; Buffer
->CurrentY
++)
129 ClearLineBuffer(Buffer
);
131 Buffer
->Mode
= ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
;
132 Buffer
->CurrentX
= 0;
133 Buffer
->CurrentY
= 0;
135 return STATUS_SUCCESS
;
138 static NTSTATUS WINAPI
139 CsrInitConsole(PCSRSS_CONSOLE Console
)
142 SECURITY_ATTRIBUTES SecurityAttributes
;
143 PCSRSS_SCREEN_BUFFER NewBuffer
;
146 Console
->Title
.MaximumLength
= Console
->Title
.Length
= 0;
147 Console
->Title
.Buffer
= NULL
;
150 RtlCreateUnicodeString(&Console
->Title
, L
"Command Prompt");
152 Console
->Header
.ReferenceCount
= 0;
153 Console
->WaitingChars
= 0;
154 Console
->WaitingLines
= 0;
155 Console
->EchoCount
= 0;
156 Console
->Header
.Type
= CONIO_CONSOLE_MAGIC
;
157 Console
->Mode
= ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_PROCESSED_INPUT
| ENABLE_MOUSE_INPUT
;
158 Console
->EarlyReturn
= FALSE
;
159 Console
->ActiveBuffer
= NULL
;
160 InitializeListHead(&Console
->InputEvents
);
161 Console
->CodePage
= GetOEMCP();
162 Console
->OutputCodePage
= GetOEMCP();
164 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
165 SecurityAttributes
.lpSecurityDescriptor
= NULL
;
166 SecurityAttributes
.bInheritHandle
= TRUE
;
168 Console
->ActiveEvent
= CreateEventW(&SecurityAttributes
, TRUE
, FALSE
, NULL
);
169 if (NULL
== Console
->ActiveEvent
)
171 RtlFreeUnicodeString(&Console
->Title
);
172 return STATUS_UNSUCCESSFUL
;
174 Console
->PrivateData
= NULL
;
175 InitializeCriticalSection(&Console
->Header
.Lock
);
177 GuiMode
= DtbgIsDesktopVisible();
179 /* allocate console screen buffer */
180 NewBuffer
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
181 if (NULL
== NewBuffer
)
183 RtlFreeUnicodeString(&Console
->Title
);
184 DeleteCriticalSection(&Console
->Header
.Lock
);
185 CloseHandle(Console
->ActiveEvent
);
186 return STATUS_INSUFFICIENT_RESOURCES
;
188 /* init screen buffer with defaults */
189 NewBuffer
->CursorInfo
.bVisible
= TRUE
;
190 NewBuffer
->CursorInfo
.dwSize
= CSR_DEFAULT_CURSOR_SIZE
;
191 /* make console active, and insert into console list */
192 Console
->ActiveBuffer
= (PCSRSS_SCREEN_BUFFER
) NewBuffer
;
196 Status
= TuiInitConsole(Console
);
197 if (! NT_SUCCESS(Status
))
199 DPRINT1("Failed to open text-mode console, switching to gui-mode\n");
205 Status
= GuiInitConsole(Console
);
206 if (! NT_SUCCESS(Status
))
208 HeapFree(Win32CsrApiHeap
,0, NewBuffer
);
209 RtlFreeUnicodeString(&Console
->Title
);
210 DeleteCriticalSection(&Console
->Header
.Lock
);
211 CloseHandle(Console
->ActiveEvent
);
212 DPRINT1("GuiInitConsole: failed\n");
217 Status
= CsrInitConsoleScreenBuffer(Console
, NewBuffer
);
218 if (! NT_SUCCESS(Status
))
220 ConioCleanupConsole(Console
);
221 RtlFreeUnicodeString(&Console
->Title
);
222 DeleteCriticalSection(&Console
->Header
.Lock
);
223 CloseHandle(Console
->ActiveEvent
);
224 HeapFree(Win32CsrApiHeap
, 0, NewBuffer
);
225 DPRINT1("CsrInitConsoleScreenBuffer: failed\n");
229 /* add a reference count because the buffer is tied to the console */
230 InterlockedIncrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
);
232 /* copy buffer contents to screen */
233 ConioDrawConsole(Console
);
235 return STATUS_SUCCESS
;
239 CSR_API(CsrAllocConsole
)
241 PCSRSS_CONSOLE Console
;
242 NTSTATUS Status
= STATUS_SUCCESS
;
243 BOOLEAN NewConsole
= FALSE
;
245 DPRINT("CsrAllocConsole\n");
247 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
248 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
250 if (ProcessData
->Console
)
252 DPRINT1("Process already has a console\n");
253 return STATUS_INVALID_PARAMETER
;
256 /* If we don't need a console, then get out of here */
257 if (!Request
->Data
.AllocConsoleRequest
.ConsoleNeeded
)
259 DPRINT("No console needed\n");
260 return STATUS_SUCCESS
;
263 /* If we already have one, then don't create a new one... */
264 if (!Request
->Data
.AllocConsoleRequest
.Console
||
265 Request
->Data
.AllocConsoleRequest
.Console
!= ProcessData
->ParentConsole
)
267 /* Allocate a console structure */
269 Console
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_CONSOLE
));
272 DPRINT1("Not enough memory for console\n");
273 return STATUS_NO_MEMORY
;
275 /* initialize list head */
276 InitializeListHead(&Console
->ProcessList
);
277 /* insert process data required for GUI initialization */
278 InsertHeadList(&Console
->ProcessList
, &ProcessData
->ProcessEntry
);
279 /* Initialize the Console */
280 Status
= CsrInitConsole(Console
);
281 if (!NT_SUCCESS(Status
))
283 DPRINT1("Console init failed\n");
284 HeapFree(Win32CsrApiHeap
, 0, Console
);
290 /* Reuse our current console */
291 Console
= Request
->Data
.AllocConsoleRequest
.Console
;
294 /* Set the Process Console */
295 ProcessData
->Console
= Console
;
297 /* Return it to the caller */
298 Request
->Data
.AllocConsoleRequest
.Console
= Console
;
300 /* Add a reference count because the process is tied to the console */
301 Console
->Header
.ReferenceCount
++;
303 if (NewConsole
|| !ProcessData
->bInheritHandles
)
305 /* Insert the Objects */
306 Status
= Win32CsrInsertObject(ProcessData
,
307 &Request
->Data
.AllocConsoleRequest
.InputHandle
,
309 GENERIC_READ
| GENERIC_WRITE
,
311 if (! NT_SUCCESS(Status
))
313 DPRINT1("Failed to insert object\n");
314 ConioDeleteConsole((Object_t
*) Console
);
315 ProcessData
->Console
= 0;
319 Status
= Win32CsrInsertObject(ProcessData
,
320 &Request
->Data
.AllocConsoleRequest
.OutputHandle
,
321 &Console
->ActiveBuffer
->Header
,
322 GENERIC_READ
| GENERIC_WRITE
,
324 if (!NT_SUCCESS(Status
))
326 DPRINT1("Failed to insert object\n");
327 ConioDeleteConsole((Object_t
*) Console
);
328 Win32CsrReleaseObject(ProcessData
,
329 Request
->Data
.AllocConsoleRequest
.InputHandle
);
330 ProcessData
->Console
= 0;
335 /* Duplicate the Event */
336 if (!DuplicateHandle(GetCurrentProcess(),
337 ProcessData
->Console
->ActiveEvent
,
338 ProcessData
->Process
,
339 &ProcessData
->ConsoleEvent
,
344 DPRINT1("DuplicateHandle() failed: %d\n", GetLastError
);
345 ConioDeleteConsole((Object_t
*) Console
);
346 if (NewConsole
|| !ProcessData
->bInheritHandles
)
348 Win32CsrReleaseObject(ProcessData
,
349 Request
->Data
.AllocConsoleRequest
.OutputHandle
);
350 Win32CsrReleaseObject(ProcessData
,
351 Request
->Data
.AllocConsoleRequest
.InputHandle
);
353 ProcessData
->Console
= 0;
357 /* Set the Ctrl Dispatcher */
358 ProcessData
->CtrlDispatcher
= Request
->Data
.AllocConsoleRequest
.CtrlDispatcher
;
359 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
363 /* Insert into the list if it has not been added */
364 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ProcessEntry
);
367 return STATUS_SUCCESS
;
370 CSR_API(CsrFreeConsole
)
372 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
373 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
375 return Win32CsrReleaseConsole(ProcessData
);
379 ConioNextLine(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, UINT
*ScrolledLines
)
381 /* If we hit bottom, slide the viewable screen */
382 if (++Buff
->CurrentY
== Buff
->MaxY
)
385 if (++Buff
->VirtualY
== Buff
->MaxY
)
390 ClearLineBuffer(Buff
);
391 if (UpdateRect
->top
!= 0)
396 UpdateRect
->left
= 0;
397 UpdateRect
->right
= Buff
->MaxX
- 1;
398 UpdateRect
->bottom
= Buff
->CurrentY
;
401 static NTSTATUS FASTCALL
402 ConioWriteConsole(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
,
403 CHAR
*Buffer
, DWORD Length
, BOOL Attrib
)
408 LONG CursorStartX
, CursorStartY
;
411 CursorStartX
= Buff
->CurrentX
;
412 CursorStartY
= Buff
->CurrentY
;
413 UpdateRect
.left
= Buff
->MaxX
;
414 UpdateRect
.top
= Buff
->CurrentY
;
415 UpdateRect
.right
= -1;
416 UpdateRect
.bottom
= Buff
->CurrentY
;
419 for (i
= 0; i
< Length
; i
++)
421 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
424 if (Buffer
[i
] == '\n')
427 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
431 else if (Buffer
[i
] == '\b')
433 /* Only handle BS if we're not on the first pos of the first line */
434 if (0 != Buff
->CurrentX
|| 0 != Buff
->CurrentY
)
436 if (0 == Buff
->CurrentX
)
438 /* slide virtual position up */
439 Buff
->CurrentX
= Buff
->MaxX
- 1;
441 UpdateRect
.top
= min(UpdateRect
.top
, (LONG
)Buff
->CurrentY
);
447 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
449 Ptr
[1] = Buff
->DefaultAttrib
;
450 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
) Buff
->CurrentX
);
451 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
456 else if (Buffer
[i
] == '\r')
459 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
) Buff
->CurrentX
);
460 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
464 else if (Buffer
[i
] == '\t')
468 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
)Buff
->CurrentX
);
469 EndX
= (Buff
->CurrentX
+ 8) & ~7;
470 if (EndX
> Buff
->MaxX
)
474 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
475 while (Buff
->CurrentX
< EndX
)
478 *Ptr
++ = Buff
->DefaultAttrib
;
481 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
- 1);
482 if (Buff
->CurrentX
== Buff
->MaxX
)
484 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
487 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
497 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
)Buff
->CurrentX
);
498 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
499 Ptr
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
);
503 Ptr
[1] = Buff
->DefaultAttrib
;
506 if (Buff
->CurrentX
== Buff
->MaxX
)
508 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
511 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
515 Buff
->CurrentX
= CursorStartX
;
520 if (! ConioIsRectEmpty(&UpdateRect
) && Buff
== Console
->ActiveBuffer
)
522 ConioWriteStream(Console
, &UpdateRect
, CursorStartX
, CursorStartY
, ScrolledLines
,
526 return STATUS_SUCCESS
;
529 CSR_API(CsrReadConsole
)
531 PLIST_ENTRY CurrentEntry
;
534 PWCHAR UnicodeBuffer
;
536 ULONG nNumberOfCharsToRead
, CharSize
;
537 PCSRSS_CONSOLE Console
;
540 DPRINT("CsrReadConsole\n");
542 CharSize
= (Request
->Data
.ReadConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
544 /* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */
545 nNumberOfCharsToRead
= min(Request
->Data
.ReadConsoleRequest
.NrCharactersToRead
, CSRSS_MAX_READ_CONSOLE
/ CharSize
);
546 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
547 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
549 Buffer
= Request
->Data
.ReadConsoleRequest
.Buffer
;
550 UnicodeBuffer
= (PWCHAR
)Buffer
;
551 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadConsoleRequest
.ConsoleHandle
,
552 &Console
, GENERIC_READ
);
553 if (! NT_SUCCESS(Status
))
557 Request
->Data
.ReadConsoleRequest
.EventHandle
= ProcessData
->ConsoleEvent
;
558 for (i
= 0; i
< nNumberOfCharsToRead
&& Console
->InputEvents
.Flink
!= &Console
->InputEvents
; i
++)
560 /* remove input event from queue */
561 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
562 if (IsListEmpty(&Console
->InputEvents
))
564 ResetEvent(Console
->ActiveEvent
);
566 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
568 /* only pay attention to valid ascii chars, on key down */
569 if (KEY_EVENT
== Input
->InputEvent
.EventType
570 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
571 && Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
!= '\0')
574 * backspace handling - if we are in charge of echoing it then we handle it here
575 * otherwise we treat it like a normal char.
577 if ('\b' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
&& 0
578 != (Console
->Mode
& ENABLE_ECHO_INPUT
))
580 /* echo if it has not already been done, and either we or the client has chars to be deleted */
582 && (0 != i
|| Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
))
584 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
585 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
589 i
-= 2; /* if we already have something to return, just back it up by 2 */
592 { /* otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer */
593 Console
->WaitingChars
--;
594 ConioUnlockConsole(Console
);
595 HeapFree(Win32CsrApiHeap
, 0, Input
);
596 Request
->Data
.ReadConsoleRequest
.NrCharactersRead
= 0;
597 return STATUS_NOTIFY_CLEANUP
;
600 Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
--;
601 Input
->Echoed
= TRUE
; /* mark as echoed so we don't echo it below */
603 /* do not copy backspace to buffer */
606 if(Request
->Data
.ReadConsoleRequest
.Unicode
)
607 ConsoleInputAnsiCharToUnicodeChar(Console
, &UnicodeBuffer
[i
], &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
);
609 Buffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
;
611 /* echo to screen if enabled and we did not already echo the char */
612 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
)
614 && '\r' != Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
616 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
617 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
624 Console
->WaitingChars
--;
625 HeapFree(Win32CsrApiHeap
, 0, Input
);
627 Request
->Data
.ReadConsoleRequest
.NrCharactersRead
= i
;
630 Status
= STATUS_PENDING
; /* we didn't read anything */
632 else if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
))
634 if (0 == Console
->WaitingLines
||
635 (Request
->Data
.ReadConsoleRequest
.Unicode
? (L
'\n' != UnicodeBuffer
[i
- 1]) : ('\n' != Buffer
[i
- 1])))
637 Status
= STATUS_PENDING
; /* line buffered, didn't get a complete line */
641 Console
->WaitingLines
--;
642 Status
= STATUS_SUCCESS
; /* line buffered, did get a complete line */
647 Status
= STATUS_SUCCESS
; /* not line buffered, did read something */
650 if (Status
== STATUS_PENDING
)
652 Console
->EchoCount
= nNumberOfCharsToRead
- i
;
656 Console
->EchoCount
= 0; /* if the client is no longer waiting on input, do not echo */
659 ConioUnlockConsole(Console
);
661 if (CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE
) + i
* CharSize
> sizeof(CSR_API_MESSAGE
))
663 Request
->Header
.u1
.s1
.TotalLength
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE
) + i
* CharSize
;
664 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
670 __inline BOOLEAN
ConioGetIntersection(
675 if (ConioIsRectEmpty(Rect1
) ||
676 (ConioIsRectEmpty(Rect2
)) ||
677 (Rect1
->top
> Rect2
->bottom
) ||
678 (Rect1
->left
> Rect2
->right
) ||
679 (Rect1
->bottom
< Rect2
->top
) ||
680 (Rect1
->right
< Rect2
->left
))
682 /* The rectangles do not intersect */
683 ConioInitRect(Intersection
, 0, -1, 0, -1);
687 ConioInitRect(Intersection
,
688 max(Rect1
->top
, Rect2
->top
),
689 max(Rect1
->left
, Rect2
->left
),
690 min(Rect1
->bottom
, Rect2
->bottom
),
691 min(Rect1
->right
, Rect2
->right
));
696 __inline BOOLEAN
ConioGetUnion(
701 if (ConioIsRectEmpty(Rect1
))
703 if (ConioIsRectEmpty(Rect2
))
705 ConioInitRect(Union
, 0, -1, 0, -1);
713 else if (ConioIsRectEmpty(Rect2
))
720 min(Rect1
->top
, Rect2
->top
),
721 min(Rect1
->left
, Rect2
->left
),
722 max(Rect1
->bottom
, Rect2
->bottom
),
723 max(Rect1
->right
, Rect2
->right
));
729 /* Move from one rectangle to another. We must be careful about the order that
730 * this is done, to avoid overwriting parts of the source before they are moved. */
732 ConioMoveRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer
,
738 int Width
= ConioRectWidth(SrcRegion
);
739 int Height
= ConioRectHeight(SrcRegion
);
750 /* Moving down: work from bottom up */
751 SY
= SrcRegion
->bottom
;
752 DY
= DstRegion
->bottom
;
755 for (i
= 0; i
< Height
; i
++)
757 PWORD SRow
= (PWORD
)ConioCoordToPointer(ScreenBuffer
, 0, SY
);
758 PWORD DRow
= (PWORD
)ConioCoordToPointer(ScreenBuffer
, 0, DY
);
760 SX
= SrcRegion
->left
;
761 DX
= DstRegion
->left
;
765 /* Moving right: work from right to left */
766 SX
= SrcRegion
->right
;
767 DX
= DstRegion
->right
;
770 for (j
= 0; j
< Width
; j
++)
772 WORD Cell
= SRow
[SX
];
773 if (SX
>= ClipRegion
->left
&& SX
<= ClipRegion
->right
774 && SY
>= ClipRegion
->top
&& SY
<= ClipRegion
->bottom
)
778 if (DX
>= ClipRegion
->left
&& DX
<= ClipRegion
->right
779 && DY
>= ClipRegion
->top
&& DY
<= ClipRegion
->bottom
)
792 ConioInputEventToAnsi(PCSRSS_CONSOLE Console
, PINPUT_RECORD InputEvent
)
794 if (InputEvent
->EventType
== KEY_EVENT
)
796 WCHAR UnicodeChar
= InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
;
797 InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
= 0;
798 ConsoleInputUnicodeCharToAnsiChar(Console
,
799 &InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
,
804 CSR_API(CsrWriteConsole
)
808 PCSRSS_SCREEN_BUFFER Buff
;
809 PCSRSS_CONSOLE Console
;
812 ULONG CharSize
= (Request
->Data
.WriteConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
814 DPRINT("CsrWriteConsole\n");
816 if (Request
->Header
.u1
.s1
.TotalLength
817 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE
)
818 + (Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
* CharSize
))
820 DPRINT1("Invalid request size\n");
821 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
822 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
823 return STATUS_INVALID_PARAMETER
;
825 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
827 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
828 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
830 if (! NT_SUCCESS(Status
))
835 if(Request
->Data
.WriteConsoleRequest
.Unicode
)
837 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
838 (PWCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
,
839 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
,
840 NULL
, 0, NULL
, NULL
);
841 Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
844 WideCharToMultiByte(Console
->OutputCodePage
, 0,
845 (PWCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
,
846 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
,
847 Buffer
, Length
, NULL
, NULL
);
851 Status
= STATUS_NO_MEMORY
;
856 Buffer
= (PCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
;
861 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.WriteConsoleRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
862 if (NT_SUCCESS(Status
))
864 Status
= ConioWriteConsole(Console
, Buff
, Buffer
,
865 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
, TRUE
);
866 if (NT_SUCCESS(Status
))
868 Written
= Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
;
870 ConioUnlockScreenBuffer(Buff
);
872 if (Request
->Data
.WriteConsoleRequest
.Unicode
)
874 RtlFreeHeap(GetProcessHeap(), 0, Buffer
);
877 ConioUnlockConsole(Console
);
879 Request
->Data
.WriteConsoleRequest
.NrCharactersWritten
= Written
;
885 ConioDeleteScreenBuffer(Object_t
*Object
)
887 PCSRSS_SCREEN_BUFFER Buffer
= (PCSRSS_SCREEN_BUFFER
) Object
;
888 DeleteCriticalSection(&Buffer
->Header
.Lock
);
889 HeapFree(Win32CsrApiHeap
, 0, Buffer
->Buffer
);
890 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
894 ConioDrawConsole(PCSRSS_CONSOLE Console
)
898 ConioInitRect(&Region
, 0, 0, Console
->Size
.Y
- 1, Console
->Size
.X
- 1);
900 ConioDrawRegion(Console
, &Region
);
905 ConioDeleteConsole(Object_t
*Object
)
907 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Object
;
910 DPRINT("ConioDeleteConsole\n");
912 /* Drain input event queue */
913 while (Console
->InputEvents
.Flink
!= &Console
->InputEvents
)
915 Event
= (ConsoleInput
*) Console
->InputEvents
.Flink
;
916 Console
->InputEvents
.Flink
= Console
->InputEvents
.Flink
->Flink
;
917 Console
->InputEvents
.Flink
->Flink
->Blink
= &Console
->InputEvents
;
918 HeapFree(Win32CsrApiHeap
, 0, Event
);
921 ConioCleanupConsole(Console
);
922 if (0 == InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
924 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
927 Console
->ActiveBuffer
= NULL
;
929 CloseHandle(Console
->ActiveEvent
);
930 DeleteCriticalSection(&Console
->Header
.Lock
);
931 RtlFreeUnicodeString(&Console
->Title
);
932 IntDeleteAllAliases(Console
->Aliases
);
933 HeapFree(Win32CsrApiHeap
, 0, Console
);
937 CsrInitConsoleSupport(VOID
)
939 DPRINT("CSR: CsrInitConsoleSupport()\n");
941 /* Should call LoadKeyboardLayout */
945 ConioProcessChar(PCSRSS_CONSOLE Console
,
946 ConsoleInput
*KeyEventRecord
)
949 ConsoleInput
*TempInput
;
951 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
)))
953 switch(KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
956 /* first add the \r */
957 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
958 updown
= KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
;
959 KeyEventRecord
->Echoed
= FALSE
;
960 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= VK_RETURN
;
961 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\r';
962 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
963 Console
->WaitingChars
++;
964 KeyEventRecord
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
965 if (NULL
== KeyEventRecord
)
967 DPRINT1("Failed to allocate KeyEventRecord\n");
970 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
971 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
= updown
;
972 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= 0;
973 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualScanCode
= 0;
974 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\n';
975 KeyEventRecord
->Fake
= TRUE
;
979 /* add event to the queue */
980 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
981 Console
->WaitingChars
++;
982 /* if line input mode is enabled, only wake the client on enter key down */
983 if (0 == (Console
->Mode
& ENABLE_LINE_INPUT
)
984 || Console
->EarlyReturn
985 || ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
986 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
))
988 if ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
990 Console
->WaitingLines
++;
993 KeyEventRecord
->Echoed
= FALSE
;
994 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
))
995 && '\b' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
996 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
998 /* walk the input queue looking for a char to backspace */
999 for (TempInput
= (ConsoleInput
*) Console
->InputEvents
.Blink
;
1000 TempInput
!= (ConsoleInput
*) &Console
->InputEvents
1001 && (KEY_EVENT
== TempInput
->InputEvent
.EventType
1002 || ! TempInput
->InputEvent
.Event
.KeyEvent
.bKeyDown
1003 || '\b' == TempInput
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
);
1004 TempInput
= (ConsoleInput
*) TempInput
->ListEntry
.Blink
)
1008 /* if we found one, delete it, otherwise, wake the client */
1009 if (TempInput
!= (ConsoleInput
*) &Console
->InputEvents
)
1011 /* delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue */
1012 RemoveEntryList(&TempInput
->ListEntry
);
1013 if (TempInput
->Echoed
)
1015 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1016 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1019 HeapFree(Win32CsrApiHeap
, 0, TempInput
);
1020 RemoveEntryList(&KeyEventRecord
->ListEntry
);
1021 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1022 Console
->WaitingChars
-= 2;
1028 /* echo chars if we are supposed to and client is waiting for some */
1029 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
) && Console
->EchoCount
1030 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1031 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
1032 && '\r' != KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1034 /* mark the char as already echoed */
1035 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1036 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1038 Console
->EchoCount
--;
1039 KeyEventRecord
->Echoed
= TRUE
;
1043 /* Console->WaitingChars++; */
1044 SetEvent(Console
->ActiveEvent
);
1047 static DWORD FASTCALL
1048 ConioGetShiftState(PBYTE KeyState
)
1052 if (KeyState
[VK_CAPITAL
] & 1)
1053 ssOut
|= CAPSLOCK_ON
;
1055 if (KeyState
[VK_NUMLOCK
] & 1)
1056 ssOut
|= NUMLOCK_ON
;
1058 if (KeyState
[VK_SCROLL
] & 1)
1059 ssOut
|= SCROLLLOCK_ON
;
1061 if (KeyState
[VK_SHIFT
] & 0x80)
1062 ssOut
|= SHIFT_PRESSED
;
1064 if (KeyState
[VK_LCONTROL
] & 0x80)
1065 ssOut
|= LEFT_CTRL_PRESSED
;
1066 if (KeyState
[VK_RCONTROL
] & 0x80)
1067 ssOut
|= RIGHT_CTRL_PRESSED
;
1069 if (KeyState
[VK_LMENU
] & 0x80)
1070 ssOut
|= LEFT_ALT_PRESSED
;
1071 if (KeyState
[VK_RMENU
] & 0x80)
1072 ssOut
|= RIGHT_ALT_PRESSED
;
1078 ConioProcessKey(MSG
*msg
, PCSRSS_CONSOLE Console
, BOOL TextMode
)
1080 static BYTE KeyState
[256] = { 0 };
1081 /* MSDN mentions that you should use the last virtual key code received
1082 * when putting a virtual key identity to a WM_CHAR message since multiple
1083 * or translated keys may be involved. */
1084 static UINT LastVirtualKey
= 0;
1086 ConsoleInput
*ConInRec
;
1090 UINT VirtualKeyCode
;
1091 UINT VirtualScanCode
;
1094 ULONG ResultSize
= 0;
1097 VirtualScanCode
= (msg
->lParam
>> 16) & 0xff;
1098 Down
= msg
->message
== WM_KEYDOWN
|| msg
->message
== WM_CHAR
||
1099 msg
->message
== WM_SYSKEYDOWN
|| msg
->message
== WM_SYSCHAR
;
1101 GetKeyboardState(KeyState
);
1102 ShiftState
= ConioGetShiftState(KeyState
);
1104 if (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
)
1106 VirtualKeyCode
= LastVirtualKey
;
1107 UnicodeChar
= msg
->wParam
;
1114 VirtualKeyCode
= msg
->wParam
;
1115 RetChars
= ToUnicodeEx(VirtualKeyCode
,
1122 UnicodeChar
= (1 == RetChars
? Chars
[0] : 0);
1125 if (0 == ResultSize
)
1130 er
.EventType
= KEY_EVENT
;
1131 er
.Event
.KeyEvent
.bKeyDown
= Down
;
1132 er
.Event
.KeyEvent
.wRepeatCount
= RepeatCount
;
1133 er
.Event
.KeyEvent
.uChar
.UnicodeChar
= UnicodeChar
;
1134 er
.Event
.KeyEvent
.dwControlKeyState
= ShiftState
;
1135 er
.Event
.KeyEvent
.wVirtualKeyCode
= VirtualKeyCode
;
1136 er
.Event
.KeyEvent
.wVirtualScanCode
= VirtualScanCode
;
1140 if (0 != (ShiftState
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1141 && VK_TAB
== VirtualKeyCode
)
1145 TuiSwapConsole(ShiftState
& SHIFT_PRESSED
? -1 : 1);
1150 else if (VK_MENU
== VirtualKeyCode
&& ! Down
)
1152 if (TuiSwapConsole(0))
1159 if (NULL
== Console
)
1161 DPRINT1("No Active Console!\n");
1165 ConInRec
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1167 if (NULL
== ConInRec
)
1172 ConInRec
->InputEvent
= er
;
1173 ConInRec
->Fake
= UnicodeChar
&&
1174 (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
&&
1175 msg
->message
!= WM_KEYUP
&& msg
->message
!= WM_SYSKEYUP
);
1176 ConInRec
->NotChar
= (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
);
1177 ConInRec
->Echoed
= FALSE
;
1178 if (ConInRec
->NotChar
)
1179 LastVirtualKey
= msg
->wParam
;
1181 DPRINT ("csrss: %s %s %s %s %02x %02x '%c' %04x\n",
1182 Down
? "down" : "up ",
1183 (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
) ?
1185 ConInRec
->Fake
? "fake" : "real",
1186 ConInRec
->NotChar
? "notc" : "char",
1189 (AsciiChar
>= ' ') ? AsciiChar
: '.',
1192 if (ConInRec
->Fake
&& ConInRec
->NotChar
)
1194 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1198 /* process Ctrl-C and Ctrl-Break */
1199 if (Console
->Mode
& ENABLE_PROCESSED_INPUT
&&
1200 er
.Event
.KeyEvent
.bKeyDown
&&
1201 ((er
.Event
.KeyEvent
.wVirtualKeyCode
== VK_PAUSE
) ||
1202 (er
.Event
.KeyEvent
.wVirtualKeyCode
== 'C')) &&
1203 (er
.Event
.KeyEvent
.dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
)))
1205 PCSRSS_PROCESS_DATA current
;
1206 PLIST_ENTRY current_entry
;
1207 DPRINT1("Console_Api Ctrl-C\n");
1208 current_entry
= Console
->ProcessList
.Flink
;
1209 while (current_entry
!= &Console
->ProcessList
)
1211 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
1212 current_entry
= current_entry
->Flink
;
1213 ConioConsoleCtrlEvent((DWORD
)CTRL_C_EVENT
, current
);
1215 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1219 if (0 != (er
.Event
.KeyEvent
.dwControlKeyState
1220 & (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1221 && (VK_UP
== er
.Event
.KeyEvent
.wVirtualKeyCode
1222 || VK_DOWN
== er
.Event
.KeyEvent
.wVirtualKeyCode
))
1224 if (er
.Event
.KeyEvent
.bKeyDown
)
1226 /* scroll up or down */
1227 if (VK_UP
== er
.Event
.KeyEvent
.wVirtualKeyCode
)
1229 /* only scroll up if there is room to scroll up into */
1230 if (Console
->ActiveBuffer
->CurrentY
!= Console
->ActiveBuffer
->MaxY
- 1)
1232 Console
->ActiveBuffer
->VirtualY
= (Console
->ActiveBuffer
->VirtualY
+
1233 Console
->ActiveBuffer
->MaxY
- 1) %
1234 Console
->ActiveBuffer
->MaxY
;
1235 Console
->ActiveBuffer
->CurrentY
++;
1240 /* only scroll down if there is room to scroll down into */
1241 if (Console
->ActiveBuffer
->CurrentY
!= 0)
1243 Console
->ActiveBuffer
->VirtualY
= (Console
->ActiveBuffer
->VirtualY
+ 1) %
1244 Console
->ActiveBuffer
->MaxY
;
1245 Console
->ActiveBuffer
->CurrentY
--;
1248 ConioDrawConsole(Console
);
1250 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1253 /* FIXME - convert to ascii */
1254 ConioProcessChar(Console
, ConInRec
);
1257 CSR_API(CsrGetScreenBufferInfo
)
1260 PCSRSS_CONSOLE Console
;
1261 PCSRSS_SCREEN_BUFFER Buff
;
1262 PCONSOLE_SCREEN_BUFFER_INFO pInfo
;
1264 DPRINT("CsrGetScreenBufferInfo\n");
1266 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1267 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1269 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1270 if (! NT_SUCCESS(Status
))
1274 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ScreenBufferInfoRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
1275 if (! NT_SUCCESS(Status
))
1277 ConioUnlockConsole(Console
);
1280 pInfo
= &Request
->Data
.ScreenBufferInfoRequest
.Info
;
1281 pInfo
->dwSize
.X
= Buff
->MaxX
;
1282 pInfo
->dwSize
.Y
= Buff
->MaxY
;
1283 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
;
1284 pInfo
->dwCursorPosition
.Y
= Buff
->CurrentY
;
1285 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
1286 pInfo
->srWindow
.Left
= Buff
->ShowX
;
1287 pInfo
->srWindow
.Right
= Buff
->ShowX
+ Console
->Size
.X
- 1;
1288 pInfo
->srWindow
.Top
= Buff
->ShowY
;
1289 pInfo
->srWindow
.Bottom
= Buff
->ShowY
+ Console
->Size
.Y
- 1;
1290 pInfo
->dwMaximumWindowSize
.X
= Buff
->MaxX
;
1291 pInfo
->dwMaximumWindowSize
.Y
= Buff
->MaxY
;
1292 ConioUnlockScreenBuffer(Buff
);
1293 ConioUnlockConsole(Console
);
1295 return STATUS_SUCCESS
;
1298 CSR_API(CsrSetCursor
)
1301 PCSRSS_CONSOLE Console
;
1302 PCSRSS_SCREEN_BUFFER Buff
;
1303 LONG OldCursorX
, OldCursorY
;
1304 LONG NewCursorX
, NewCursorY
;
1306 DPRINT("CsrSetCursor\n");
1308 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1309 if (! NT_SUCCESS(Status
))
1314 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1315 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1317 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1318 if (! NT_SUCCESS(Status
))
1320 ConioUnlockConsole(Console
);
1324 NewCursorX
= Request
->Data
.SetCursorRequest
.Position
.X
;
1325 NewCursorY
= Request
->Data
.SetCursorRequest
.Position
.Y
;
1326 if (NewCursorX
< 0 || NewCursorX
>= Buff
->MaxX
||
1327 NewCursorY
< 0 || NewCursorY
>= Buff
->MaxY
)
1329 ConioUnlockScreenBuffer(Buff
);
1330 ConioUnlockConsole(Console
);
1331 return STATUS_INVALID_PARAMETER
;
1333 OldCursorX
= Buff
->CurrentX
;
1334 OldCursorY
= Buff
->CurrentY
;
1335 Buff
->CurrentX
= NewCursorX
;
1336 Buff
->CurrentY
= NewCursorY
;
1337 if (Buff
== Console
->ActiveBuffer
)
1339 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
1341 ConioUnlockScreenBuffer(Buff
);
1342 ConioUnlockConsole(Console
);
1343 return STATUS_UNSUCCESSFUL
;
1347 ConioUnlockScreenBuffer(Buff
);
1348 ConioUnlockConsole(Console
);
1350 return STATUS_SUCCESS
;
1353 static VOID FASTCALL
1354 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, COORD
*Start
, UINT Length
)
1356 if (Buff
->MaxX
<= Start
->X
+ Length
)
1358 UpdateRect
->left
= 0;
1362 UpdateRect
->left
= Start
->X
;
1364 if (Buff
->MaxX
<= Start
->X
+ Length
)
1366 UpdateRect
->right
= Buff
->MaxX
- 1;
1370 UpdateRect
->right
= Start
->X
+ Length
- 1;
1372 UpdateRect
->top
= Start
->Y
;
1373 UpdateRect
->bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->MaxX
;
1374 if (Buff
->MaxY
<= UpdateRect
->bottom
)
1376 UpdateRect
->bottom
= Buff
->MaxY
- 1;
1380 CSR_API(CsrWriteConsoleOutputChar
)
1383 PCHAR String
, tmpString
= NULL
;
1385 PCSRSS_CONSOLE Console
;
1386 PCSRSS_SCREEN_BUFFER Buff
;
1387 DWORD X
, Y
, Length
, CharSize
, Written
= 0;
1390 DPRINT("CsrWriteConsoleOutputChar\n");
1392 CharSize
= (Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
1394 if (Request
->Header
.u1
.s1
.TotalLength
1395 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR
)
1396 + (Request
->Data
.WriteConsoleOutputCharRequest
.Length
* CharSize
))
1398 DPRINT1("Invalid request size\n");
1399 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1400 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1401 return STATUS_INVALID_PARAMETER
;
1404 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1405 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1406 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1407 if (NT_SUCCESS(Status
))
1409 if(Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
)
1411 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
1412 (PWCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
,
1413 Request
->Data
.WriteConsoleOutputCharRequest
.Length
,
1414 NULL
, 0, NULL
, NULL
);
1415 tmpString
= String
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
1418 WideCharToMultiByte(Console
->OutputCodePage
, 0,
1419 (PWCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
,
1420 Request
->Data
.WriteConsoleOutputCharRequest
.Length
,
1421 String
, Length
, NULL
, NULL
);
1425 Status
= STATUS_NO_MEMORY
;
1430 String
= (PCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
;
1435 Status
= ConioLockScreenBuffer(ProcessData
,
1436 Request
->Data
.WriteConsoleOutputCharRequest
.ConsoleHandle
,
1439 if (NT_SUCCESS(Status
))
1441 X
= Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.X
;
1442 Y
= (Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1443 Length
= Request
->Data
.WriteConsoleOutputCharRequest
.Length
;
1444 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1447 *Buffer
= *String
++;
1450 if (++X
== Buff
->MaxX
)
1452 if (++Y
== Buff
->MaxY
)
1455 Buffer
= Buff
->Buffer
;
1460 if (Buff
== Console
->ActiveBuffer
)
1462 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputCharRequest
.Coord
,
1463 Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
1464 ConioDrawRegion(Console
, &UpdateRect
);
1467 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.X
= X
;
1468 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->VirtualY
) % Buff
->MaxY
;
1470 ConioUnlockScreenBuffer(Buff
);
1472 if (Request
->Data
.WriteConsoleRequest
.Unicode
)
1474 RtlFreeHeap(GetProcessHeap(), 0, tmpString
);
1477 ConioUnlockConsole(Console
);
1479 Request
->Data
.WriteConsoleOutputCharRequest
.NrCharactersWritten
= Written
;
1483 CSR_API(CsrFillOutputChar
)
1486 PCSRSS_CONSOLE Console
;
1487 PCSRSS_SCREEN_BUFFER Buff
;
1488 DWORD X
, Y
, Length
, Written
= 0;
1493 DPRINT("CsrFillOutputChar\n");
1495 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1496 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1498 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1499 if (! NT_SUCCESS(Status
))
1504 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1505 if (! NT_SUCCESS(Status
))
1507 ConioUnlockConsole(Console
);
1511 X
= Request
->Data
.FillOutputRequest
.Position
.X
;
1512 Y
= (Request
->Data
.FillOutputRequest
.Position
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1513 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1514 if(Request
->Data
.FillOutputRequest
.Unicode
)
1515 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &Request
->Data
.FillOutputRequest
.Char
.UnicodeChar
);
1517 Char
= Request
->Data
.FillOutputRequest
.Char
.AsciiChar
;
1518 Length
= Request
->Data
.FillOutputRequest
.Length
;
1524 if (++X
== Buff
->MaxX
)
1526 if (++Y
== Buff
->MaxY
)
1529 Buffer
= Buff
->Buffer
;
1535 if (Buff
== Console
->ActiveBuffer
)
1537 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputRequest
.Position
,
1538 Request
->Data
.FillOutputRequest
.Length
);
1539 ConioDrawRegion(Console
, &UpdateRect
);
1542 ConioUnlockScreenBuffer(Buff
);
1543 ConioUnlockConsole(Console
);
1544 Length
= Request
->Data
.FillOutputRequest
.Length
;
1545 Request
->Data
.FillOutputRequest
.NrCharactersWritten
= Length
;
1546 return STATUS_SUCCESS
;
1549 CSR_API(CsrReadInputEvent
)
1551 PLIST_ENTRY CurrentEntry
;
1552 PCSRSS_CONSOLE Console
;
1554 BOOLEAN Done
= FALSE
;
1555 ConsoleInput
*Input
;
1557 DPRINT("CsrReadInputEvent\n");
1559 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1560 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1561 Request
->Data
.ReadInputRequest
.Event
= ProcessData
->ConsoleEvent
;
1563 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadInputRequest
.ConsoleHandle
, &Console
, GENERIC_READ
);
1564 if (! NT_SUCCESS(Status
))
1569 /* only get input if there is any */
1570 CurrentEntry
= Console
->InputEvents
.Flink
;
1571 while (CurrentEntry
!= &Console
->InputEvents
)
1573 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
1574 CurrentEntry
= CurrentEntry
->Flink
;
1576 if (Done
&& !Input
->Fake
)
1578 Request
->Data
.ReadInputRequest
.MoreEvents
= TRUE
;
1582 RemoveEntryList(&Input
->ListEntry
);
1584 if (!Done
&& !Input
->Fake
)
1586 Request
->Data
.ReadInputRequest
.Input
= Input
->InputEvent
;
1587 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
1589 ConioInputEventToAnsi(Console
, &Request
->Data
.ReadInputRequest
.Input
);
1594 if (Input
->InputEvent
.EventType
== KEY_EVENT
)
1596 if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
)
1597 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
1598 && '\r' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1600 Console
->WaitingLines
--;
1602 Console
->WaitingChars
--;
1604 HeapFree(Win32CsrApiHeap
, 0, Input
);
1609 Status
= STATUS_SUCCESS
;
1610 Console
->EarlyReturn
= FALSE
;
1614 Status
= STATUS_PENDING
;
1615 Console
->EarlyReturn
= TRUE
; /* mark for early return */
1618 if (IsListEmpty(&Console
->InputEvents
))
1620 ResetEvent(Console
->ActiveEvent
);
1623 ConioUnlockConsole(Console
);
1628 CSR_API(CsrWriteConsoleOutputAttrib
)
1630 PCSRSS_CONSOLE Console
;
1631 PCSRSS_SCREEN_BUFFER Buff
;
1638 DPRINT("CsrWriteConsoleOutputAttrib\n");
1640 if (Request
->Header
.u1
.s1
.TotalLength
1641 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB
)
1642 + Request
->Data
.WriteConsoleOutputAttribRequest
.Length
* sizeof(WORD
))
1644 DPRINT1("Invalid request size\n");
1645 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1646 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1647 return STATUS_INVALID_PARAMETER
;
1650 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1651 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1652 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1653 if (! NT_SUCCESS(Status
))
1658 Status
= ConioLockScreenBuffer(ProcessData
,
1659 Request
->Data
.WriteConsoleOutputAttribRequest
.ConsoleHandle
,
1662 if (! NT_SUCCESS(Status
))
1664 ConioUnlockConsole(Console
);
1668 X
= Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.X
;
1669 Y
= (Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1670 Length
= Request
->Data
.WriteConsoleOutputAttribRequest
.Length
;
1671 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + 1];
1672 Attribute
= Request
->Data
.WriteConsoleOutputAttribRequest
.Attribute
;
1675 *Buffer
= (UCHAR
)(*Attribute
++);
1677 if (++X
== Buff
->MaxX
)
1679 if (++Y
== Buff
->MaxY
)
1682 Buffer
= Buff
->Buffer
+ 1;
1688 if (Buff
== Console
->ActiveBuffer
)
1690 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
,
1691 Request
->Data
.WriteConsoleOutputAttribRequest
.Length
);
1692 ConioDrawRegion(Console
, &UpdateRect
);
1695 ConioUnlockConsole(Console
);
1697 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.X
= X
;
1698 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->VirtualY
) % Buff
->MaxY
;
1700 ConioUnlockScreenBuffer(Buff
);
1702 return STATUS_SUCCESS
;
1705 CSR_API(CsrFillOutputAttrib
)
1707 PCSRSS_SCREEN_BUFFER Buff
;
1713 PCSRSS_CONSOLE Console
;
1715 DPRINT("CsrFillOutputAttrib\n");
1717 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1718 if (! NT_SUCCESS(Status
))
1723 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1724 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1725 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputAttribRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1726 if (! NT_SUCCESS(Status
))
1728 ConioUnlockConsole(Console
);
1732 X
= Request
->Data
.FillOutputAttribRequest
.Coord
.X
;
1733 Y
= (Request
->Data
.FillOutputAttribRequest
.Coord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
1734 Length
= Request
->Data
.FillOutputAttribRequest
.Length
;
1735 Attr
= Request
->Data
.FillOutputAttribRequest
.Attribute
;
1736 Buffer
= &Buff
->Buffer
[(Y
* Buff
->MaxX
* 2) + (X
* 2) + 1];
1741 if (++X
== Buff
->MaxX
)
1743 if (++Y
== Buff
->MaxY
)
1746 Buffer
= Buff
->Buffer
+ 1;
1752 if (Buff
== Console
->ActiveBuffer
)
1754 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputAttribRequest
.Coord
,
1755 Request
->Data
.FillOutputAttribRequest
.Length
);
1756 ConioDrawRegion(Console
, &UpdateRect
);
1759 ConioUnlockScreenBuffer(Buff
);
1760 ConioUnlockConsole(Console
);
1762 return STATUS_SUCCESS
;
1766 CSR_API(CsrGetCursorInfo
)
1768 PCSRSS_SCREEN_BUFFER Buff
;
1771 DPRINT("CsrGetCursorInfo\n");
1773 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1774 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1776 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.GetCursorInfoRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
1777 if (! NT_SUCCESS(Status
))
1781 Request
->Data
.GetCursorInfoRequest
.Info
.bVisible
= Buff
->CursorInfo
.bVisible
;
1782 Request
->Data
.GetCursorInfoRequest
.Info
.dwSize
= Buff
->CursorInfo
.dwSize
;
1783 ConioUnlockScreenBuffer(Buff
);
1785 return STATUS_SUCCESS
;
1788 CSR_API(CsrSetCursorInfo
)
1790 PCSRSS_CONSOLE Console
;
1791 PCSRSS_SCREEN_BUFFER Buff
;
1796 DPRINT("CsrSetCursorInfo\n");
1798 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1799 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1801 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1802 if (! NT_SUCCESS(Status
))
1807 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorInfoRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1808 if (! NT_SUCCESS(Status
))
1810 ConioUnlockConsole(Console
);
1814 Size
= Request
->Data
.SetCursorInfoRequest
.Info
.dwSize
;
1815 Visible
= Request
->Data
.SetCursorInfoRequest
.Info
.bVisible
;
1825 if (Size
!= Buff
->CursorInfo
.dwSize
1826 || (Visible
&& ! Buff
->CursorInfo
.bVisible
) || (! Visible
&& Buff
->CursorInfo
.bVisible
))
1828 Buff
->CursorInfo
.dwSize
= Size
;
1829 Buff
->CursorInfo
.bVisible
= Visible
;
1831 if (! ConioSetCursorInfo(Console
, Buff
))
1833 ConioUnlockScreenBuffer(Buff
);
1834 ConioUnlockConsole(Console
);
1835 return STATUS_UNSUCCESSFUL
;
1839 ConioUnlockScreenBuffer(Buff
);
1840 ConioUnlockConsole(Console
);
1842 return STATUS_SUCCESS
;
1845 CSR_API(CsrSetTextAttrib
)
1848 PCSRSS_CONSOLE Console
;
1849 PCSRSS_SCREEN_BUFFER Buff
;
1851 DPRINT("CsrSetTextAttrib\n");
1853 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1854 if (! NT_SUCCESS(Status
))
1859 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
, GENERIC_WRITE
);
1860 if (! NT_SUCCESS(Status
))
1862 ConioUnlockConsole(Console
);
1866 Buff
->DefaultAttrib
= Request
->Data
.SetAttribRequest
.Attrib
;
1867 if (Buff
== Console
->ActiveBuffer
)
1869 if (! ConioUpdateScreenInfo(Console
, Buff
))
1871 ConioUnlockScreenBuffer(Buff
);
1872 ConioUnlockConsole(Console
);
1873 return STATUS_UNSUCCESSFUL
;
1877 ConioUnlockScreenBuffer(Buff
);
1878 ConioUnlockConsole(Console
);
1880 return STATUS_SUCCESS
;
1883 CSR_API(CsrSetConsoleMode
)
1886 PCSRSS_CONSOLE Console
;
1887 PCSRSS_SCREEN_BUFFER Buff
;
1889 DPRINT("CsrSetConsoleMode\n");
1891 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1892 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1893 Status
= Win32CsrGetObject(ProcessData
,
1894 Request
->Data
.SetConsoleModeRequest
.ConsoleHandle
,
1895 (Object_t
**) &Console
, GENERIC_WRITE
);
1896 if (! NT_SUCCESS(Status
))
1901 Buff
= (PCSRSS_SCREEN_BUFFER
)Console
;
1902 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
1904 Console
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_INPUT_MODE_VALID
;
1906 else if (CONIO_SCREEN_BUFFER_MAGIC
== Console
->Header
.Type
)
1908 Buff
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_OUTPUT_MODE_VALID
;
1912 Status
= STATUS_INVALID_HANDLE
;
1915 Win32CsrReleaseObjectByPointer((Object_t
*)Console
);
1920 CSR_API(CsrGetConsoleMode
)
1923 PCSRSS_CONSOLE Console
;
1924 PCSRSS_SCREEN_BUFFER Buff
; /* gee, I really wish I could use an anonymous union here */
1926 DPRINT("CsrGetConsoleMode\n");
1928 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1929 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1930 Status
= Win32CsrGetObject(ProcessData
, Request
->Data
.GetConsoleModeRequest
.ConsoleHandle
,
1931 (Object_t
**) &Console
, GENERIC_READ
);
1932 if (! NT_SUCCESS(Status
))
1936 Status
= STATUS_SUCCESS
;
1937 Buff
= (PCSRSS_SCREEN_BUFFER
) Console
;
1938 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
1940 Request
->Data
.GetConsoleModeRequest
.ConsoleMode
= Console
->Mode
;
1942 else if (CONIO_SCREEN_BUFFER_MAGIC
== Buff
->Header
.Type
)
1944 Request
->Data
.GetConsoleModeRequest
.ConsoleMode
= Buff
->Mode
;
1948 Status
= STATUS_INVALID_HANDLE
;
1951 Win32CsrReleaseObjectByPointer((Object_t
*)Console
);
1955 CSR_API(CsrCreateScreenBuffer
)
1957 PCSRSS_CONSOLE Console
;
1958 PCSRSS_SCREEN_BUFFER Buff
;
1961 DPRINT("CsrCreateScreenBuffer\n");
1963 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1964 if (! NT_SUCCESS(Status
))
1969 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1970 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1972 Buff
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
1976 if (Console
->ActiveBuffer
)
1978 Buff
->MaxX
= Console
->ActiveBuffer
->MaxX
;
1979 Buff
->MaxY
= Console
->ActiveBuffer
->MaxY
;
1980 Buff
->CursorInfo
.bVisible
= Console
->ActiveBuffer
->CursorInfo
.bVisible
;
1981 Buff
->CursorInfo
.dwSize
= Console
->ActiveBuffer
->CursorInfo
.dwSize
;
1985 Buff
->CursorInfo
.bVisible
= TRUE
;
1986 Buff
->CursorInfo
.dwSize
= CSR_DEFAULT_CURSOR_SIZE
;
1989 if (Buff
->MaxX
== 0)
1994 if (Buff
->MaxY
== 0)
1999 Status
= CsrInitConsoleScreenBuffer(Console
, Buff
);
2000 if(NT_SUCCESS(Status
))
2002 Status
= Win32CsrInsertObject(ProcessData
,
2003 &Request
->Data
.CreateScreenBufferRequest
.OutputHandle
,
2005 Request
->Data
.CreateScreenBufferRequest
.Access
,
2006 Request
->Data
.CreateScreenBufferRequest
.Inheritable
);
2011 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2014 ConioUnlockConsole(Console
);
2018 CSR_API(CsrSetScreenBuffer
)
2021 PCSRSS_CONSOLE Console
;
2022 PCSRSS_SCREEN_BUFFER Buff
;
2024 DPRINT("CsrSetScreenBuffer\n");
2026 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2027 if (! NT_SUCCESS(Status
))
2032 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2033 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2035 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetScreenBufferRequest
.OutputHandle
, &Buff
, GENERIC_WRITE
);
2036 if (! NT_SUCCESS(Status
))
2038 ConioUnlockConsole(Console
);
2042 if (Buff
== Console
->ActiveBuffer
)
2044 ConioUnlockScreenBuffer(Buff
);
2045 ConioUnlockConsole(Console
);
2046 return STATUS_SUCCESS
;
2049 /* drop reference to old buffer, maybe delete */
2050 if (! InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
2052 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
2054 /* tie console to new buffer */
2055 Console
->ActiveBuffer
= Buff
;
2056 /* inc ref count on new buffer */
2057 InterlockedIncrement(&Buff
->Header
.ReferenceCount
);
2058 /* Redraw the console */
2059 ConioDrawConsole(Console
);
2061 ConioUnlockScreenBuffer(Buff
);
2062 ConioUnlockConsole(Console
);
2064 return STATUS_SUCCESS
;
2067 CSR_API(CsrSetTitle
)
2070 PCSRSS_CONSOLE Console
;
2073 DPRINT("CsrSetTitle\n");
2075 if (Request
->Header
.u1
.s1
.TotalLength
2076 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_SET_TITLE
)
2077 + Request
->Data
.SetTitleRequest
.Length
)
2079 DPRINT1("Invalid request size\n");
2080 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2081 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2082 return STATUS_INVALID_PARAMETER
;
2085 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2086 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2087 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2088 if(NT_SUCCESS(Status
))
2090 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, Request
->Data
.SetTitleRequest
.Length
);
2093 /* copy title to console */
2094 RtlFreeUnicodeString(&Console
->Title
);
2095 Console
->Title
.Buffer
= Buffer
;
2096 Console
->Title
.Length
= Console
->Title
.MaximumLength
= Request
->Data
.SetTitleRequest
.Length
;
2097 memcpy(Console
->Title
.Buffer
, Request
->Data
.SetTitleRequest
.Title
, Console
->Title
.Length
);
2098 if (! ConioChangeTitle(Console
))
2100 Status
= STATUS_UNSUCCESSFUL
;
2104 Status
= STATUS_SUCCESS
;
2109 Status
= STATUS_NO_MEMORY
;
2111 ConioUnlockConsole(Console
);
2117 CSR_API(CsrGetTitle
)
2120 PCSRSS_CONSOLE Console
;
2123 DPRINT("CsrGetTitle\n");
2125 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2126 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2127 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2128 if (! NT_SUCCESS(Status
))
2130 DPRINT1("Can't get console\n");
2134 /* Copy title of the console to the user title buffer */
2135 RtlZeroMemory(&Request
->Data
.GetTitleRequest
, sizeof(CSRSS_GET_TITLE
));
2136 Request
->Data
.GetTitleRequest
.Length
= Console
->Title
.Length
;
2137 memcpy (Request
->Data
.GetTitleRequest
.Title
, Console
->Title
.Buffer
,
2138 Console
->Title
.Length
);
2139 Length
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_SET_TITLE
) + Console
->Title
.Length
;
2141 ConioUnlockConsole(Console
);
2143 if (Length
> sizeof(CSR_API_MESSAGE
))
2145 Request
->Header
.u1
.s1
.TotalLength
= Length
;
2146 Request
->Header
.u1
.s1
.DataLength
= Length
- sizeof(PORT_MESSAGE
);
2148 return STATUS_SUCCESS
;
2151 CSR_API(CsrWriteConsoleOutput
)
2153 SHORT i
, X
, Y
, SizeX
, SizeY
;
2154 PCSRSS_CONSOLE Console
;
2155 PCSRSS_SCREEN_BUFFER Buff
;
2157 CHAR_INFO
* CurCharInfo
;
2159 CHAR_INFO
* CharInfo
;
2166 DPRINT("CsrWriteConsoleOutput\n");
2168 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2169 if (! NT_SUCCESS(Status
))
2174 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2175 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2176 Status
= ConioLockScreenBuffer(ProcessData
,
2177 Request
->Data
.WriteConsoleOutputRequest
.ConsoleHandle
,
2180 if (! NT_SUCCESS(Status
))
2182 ConioUnlockConsole(Console
);
2186 BufferSize
= Request
->Data
.WriteConsoleOutputRequest
.BufferSize
;
2187 PSize
= BufferSize
.X
* BufferSize
.Y
* sizeof(CHAR_INFO
);
2188 BufferCoord
= Request
->Data
.WriteConsoleOutputRequest
.BufferCoord
;
2189 CharInfo
= Request
->Data
.WriteConsoleOutputRequest
.CharInfo
;
2190 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
) ||
2191 (((ULONG_PTR
)CharInfo
+ PSize
) >
2192 ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2194 ConioUnlockScreenBuffer(Buff
);
2195 ConioUnlockConsole(Console
);
2196 return STATUS_ACCESS_VIOLATION
;
2198 WriteRegion
.left
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
;
2199 WriteRegion
.top
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
;
2200 WriteRegion
.right
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
;
2201 WriteRegion
.bottom
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
;
2203 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&WriteRegion
));
2204 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&WriteRegion
));
2205 WriteRegion
.bottom
= WriteRegion
.top
+ SizeY
- 1;
2206 WriteRegion
.right
= WriteRegion
.left
+ SizeX
- 1;
2208 /* Make sure WriteRegion is inside the screen buffer */
2209 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2210 if (! ConioGetIntersection(&WriteRegion
, &ScreenBuffer
, &WriteRegion
))
2212 ConioUnlockScreenBuffer(Buff
);
2213 ConioUnlockConsole(Console
);
2215 /* It is okay to have a WriteRegion completely outside the screen buffer.
2216 No data is written then. */
2217 return STATUS_SUCCESS
;
2220 for (i
= 0, Y
= WriteRegion
.top
; Y
<= WriteRegion
.bottom
; i
++, Y
++)
2222 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
2223 Ptr
= ConioCoordToPointer(Buff
, WriteRegion
.left
, Y
);
2224 for (X
= WriteRegion
.left
; X
<= WriteRegion
.right
; X
++)
2227 if (Request
->Data
.WriteConsoleOutputRequest
.Unicode
)
2229 ConsoleUnicodeCharToAnsiChar(Console
, &AsciiChar
, &CurCharInfo
->Char
.UnicodeChar
);
2233 AsciiChar
= CurCharInfo
->Char
.AsciiChar
;
2236 *Ptr
++ = CurCharInfo
->Attributes
;
2241 ConioDrawRegion(Console
, &WriteRegion
);
2243 ConioUnlockScreenBuffer(Buff
);
2244 ConioUnlockConsole(Console
);
2246 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
= WriteRegion
.left
+ SizeX
- 1;
2247 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
= WriteRegion
.top
+ SizeY
- 1;
2248 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
= WriteRegion
.left
;
2249 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
= WriteRegion
.top
;
2251 return STATUS_SUCCESS
;
2254 CSR_API(CsrFlushInputBuffer
)
2256 PLIST_ENTRY CurrentEntry
;
2257 PCSRSS_CONSOLE Console
;
2258 ConsoleInput
* Input
;
2261 DPRINT("CsrFlushInputBuffer\n");
2263 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2264 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2265 Status
= ConioLockConsole(ProcessData
,
2266 Request
->Data
.FlushInputBufferRequest
.ConsoleInput
,
2269 if(! NT_SUCCESS(Status
))
2274 /* Discard all entries in the input event queue */
2275 while (!IsListEmpty(&Console
->InputEvents
))
2277 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
2278 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
2279 /* Destroy the event */
2280 HeapFree(Win32CsrApiHeap
, 0, Input
);
2282 ResetEvent(Console
->ActiveEvent
);
2283 Console
->WaitingChars
=0;
2285 ConioUnlockConsole(Console
);
2287 return STATUS_SUCCESS
;
2290 CSR_API(CsrScrollConsoleScreenBuffer
)
2292 PCSRSS_CONSOLE Console
;
2293 PCSRSS_SCREEN_BUFFER Buff
;
2298 RECT ScrollRectangle
;
2301 HANDLE ConsoleHandle
;
2302 BOOLEAN UseClipRectangle
;
2303 COORD DestinationOrigin
;
2307 DPRINT("CsrScrollConsoleScreenBuffer\n");
2309 ConsoleHandle
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ConsoleHandle
;
2310 UseClipRectangle
= Request
->Data
.ScrollConsoleScreenBufferRequest
.UseClipRectangle
;
2311 DestinationOrigin
= Request
->Data
.ScrollConsoleScreenBufferRequest
.DestinationOrigin
;
2312 Fill
= Request
->Data
.ScrollConsoleScreenBufferRequest
.Fill
;
2314 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2315 if (! NT_SUCCESS(Status
))
2320 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2321 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2322 Status
= ConioLockScreenBuffer(ProcessData
, ConsoleHandle
, &Buff
, GENERIC_WRITE
);
2323 if (! NT_SUCCESS(Status
))
2325 ConioUnlockConsole(Console
);
2329 ScrollRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Left
;
2330 ScrollRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Top
;
2331 ScrollRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Right
;
2332 ScrollRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Bottom
;
2334 /* Make sure source rectangle is inside the screen buffer */
2335 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2336 if (! ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, &ScrollRectangle
))
2338 ConioUnlockScreenBuffer(Buff
);
2339 ConioUnlockConsole(Console
);
2340 return STATUS_SUCCESS
;
2343 /* If the source was clipped on the left or top, adjust the destination accordingly */
2344 if (ScrollRectangle
.left
< 0)
2346 DestinationOrigin
.X
-= ScrollRectangle
.left
;
2348 if (ScrollRectangle
.top
< 0)
2350 DestinationOrigin
.Y
-= ScrollRectangle
.top
;
2353 if (UseClipRectangle
)
2355 ClipRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Left
;
2356 ClipRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Top
;
2357 ClipRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Right
;
2358 ClipRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Bottom
;
2359 if (!ConioGetIntersection(&ClipRectangle
, &ClipRectangle
, &ScreenBuffer
))
2361 ConioUnlockConsole(Console
);
2362 ConioUnlockScreenBuffer(Buff
);
2363 return STATUS_SUCCESS
;
2368 ClipRectangle
= ScreenBuffer
;
2371 ConioInitRect(&DstRegion
,
2372 DestinationOrigin
.Y
,
2373 DestinationOrigin
.X
,
2374 DestinationOrigin
.Y
+ ConioRectHeight(&SrcRegion
) - 1,
2375 DestinationOrigin
.X
+ ConioRectWidth(&SrcRegion
) - 1);
2377 if (Request
->Data
.ScrollConsoleScreenBufferRequest
.Unicode
)
2378 ConsoleUnicodeCharToAnsiChar(Console
, &FillChar
, &Fill
.Char
.UnicodeChar
);
2380 FillChar
= Fill
.Char
.AsciiChar
;
2382 ConioMoveRegion(Buff
, &SrcRegion
, &DstRegion
, &ClipRectangle
, Fill
.Attributes
<< 8 | (BYTE
)FillChar
);
2384 if (Buff
== Console
->ActiveBuffer
)
2386 ConioGetUnion(&UpdateRegion
, &SrcRegion
, &DstRegion
);
2387 if (ConioGetIntersection(&UpdateRegion
, &UpdateRegion
, &ClipRectangle
))
2389 /* Draw update region */
2390 ConioDrawRegion(Console
, &UpdateRegion
);
2394 ConioUnlockScreenBuffer(Buff
);
2395 ConioUnlockConsole(Console
);
2397 return STATUS_SUCCESS
;
2400 CSR_API(CsrReadConsoleOutputChar
)
2403 PCSRSS_CONSOLE Console
;
2404 PCSRSS_SCREEN_BUFFER Buff
;
2411 DPRINT("CsrReadConsoleOutputChar\n");
2413 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2414 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2415 ReadBuffer
= Request
->Data
.ReadConsoleOutputCharRequest
.String
;
2417 CharSize
= (Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
2419 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2420 if (! NT_SUCCESS(Status
))
2425 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputCharRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
2426 if (! NT_SUCCESS(Status
))
2428 ConioUnlockConsole(Console
);
2432 Xpos
= Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.X
;
2433 Ypos
= (Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
2435 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
; ++i
)
2437 Char
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
)];
2439 if(Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
)
2441 ConsoleAnsiCharToUnicodeChar(Console
, (WCHAR
*)ReadBuffer
, &Char
);
2442 ReadBuffer
+= sizeof(WCHAR
);
2445 *(ReadBuffer
++) = Char
;
2449 if (Xpos
== Buff
->MaxX
)
2454 if (Ypos
== Buff
->MaxY
)
2462 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.X
= Xpos
;
2463 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.Y
= (Ypos
- Buff
->VirtualY
+ Buff
->MaxY
) % Buff
->MaxY
;
2465 ConioUnlockScreenBuffer(Buff
);
2466 ConioUnlockConsole(Console
);
2468 Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
= (DWORD
)((ULONG_PTR
)ReadBuffer
- (ULONG_PTR
)Request
->Data
.ReadConsoleOutputCharRequest
.String
) / CharSize
;
2469 if (Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
* CharSize
+ CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR
) > sizeof(CSR_API_MESSAGE
))
2471 Request
->Header
.u1
.s1
.TotalLength
= Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
* CharSize
+ CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR
);
2472 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2475 return STATUS_SUCCESS
;
2479 CSR_API(CsrReadConsoleOutputAttrib
)
2482 PCSRSS_SCREEN_BUFFER Buff
;
2486 DWORD CurrentLength
;
2488 DPRINT("CsrReadConsoleOutputAttrib\n");
2490 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2491 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2492 ReadBuffer
= Request
->Data
.ReadConsoleOutputAttribRequest
.Attribute
;
2494 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputAttribRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
2495 if (! NT_SUCCESS(Status
))
2500 Xpos
= Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.X
;
2501 Ypos
= (Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.Y
+ Buff
->VirtualY
) % Buff
->MaxY
;
2503 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
; ++i
)
2505 *ReadBuffer
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
) + 1];
2510 if (Xpos
== Buff
->MaxX
)
2515 if (Ypos
== Buff
->MaxY
)
2524 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.X
= Xpos
;
2525 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.Y
= (Ypos
- Buff
->VirtualY
+ Buff
->MaxY
) % Buff
->MaxY
;
2527 ConioUnlockScreenBuffer(Buff
);
2529 CurrentLength
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_ATTRIB
)
2530 + Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
* sizeof(WORD
);
2531 if (CurrentLength
> sizeof(CSR_API_MESSAGE
))
2533 Request
->Header
.u1
.s1
.TotalLength
= CurrentLength
;
2534 Request
->Header
.u1
.s1
.DataLength
= CurrentLength
- sizeof(PORT_MESSAGE
);
2537 return STATUS_SUCCESS
;
2541 CSR_API(CsrGetNumberOfConsoleInputEvents
)
2544 PCSRSS_CONSOLE Console
;
2545 PLIST_ENTRY CurrentItem
;
2547 ConsoleInput
*Input
;
2549 DPRINT("CsrGetNumberOfConsoleInputEvents\n");
2551 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2552 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2554 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
, GENERIC_READ
);
2555 if (! NT_SUCCESS(Status
))
2560 CurrentItem
= Console
->InputEvents
.Flink
;
2563 /* If there are any events ... */
2564 while (CurrentItem
!= &Console
->InputEvents
)
2566 Input
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2567 CurrentItem
= CurrentItem
->Flink
;
2574 ConioUnlockConsole(Console
);
2576 Request
->Data
.GetNumInputEventsRequest
.NumInputEvents
= NumEvents
;
2578 return STATUS_SUCCESS
;
2582 CSR_API(CsrPeekConsoleInput
)
2585 PCSRSS_CONSOLE Console
;
2588 PLIST_ENTRY CurrentItem
;
2589 PINPUT_RECORD InputRecord
;
2593 DPRINT("CsrPeekConsoleInput\n");
2595 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2596 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2598 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
, GENERIC_READ
);
2599 if(! NT_SUCCESS(Status
))
2604 InputRecord
= Request
->Data
.PeekConsoleInputRequest
.InputRecord
;
2605 Length
= Request
->Data
.PeekConsoleInputRequest
.Length
;
2606 Size
= Length
* sizeof(INPUT_RECORD
);
2608 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2609 || (((ULONG_PTR
)InputRecord
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2611 ConioUnlockConsole(Console
);
2612 return STATUS_ACCESS_VIOLATION
;
2617 if (! IsListEmpty(&Console
->InputEvents
))
2619 CurrentItem
= Console
->InputEvents
.Flink
;
2621 while (CurrentItem
!= &Console
->InputEvents
&& NumItems
< Length
)
2623 Item
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2627 CurrentItem
= CurrentItem
->Flink
;
2632 *InputRecord
= Item
->InputEvent
;
2634 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
2636 ConioInputEventToAnsi(Console
, InputRecord
);
2640 CurrentItem
= CurrentItem
->Flink
;
2644 ConioUnlockConsole(Console
);
2646 Request
->Data
.PeekConsoleInputRequest
.Length
= NumItems
;
2648 return STATUS_SUCCESS
;
2652 CSR_API(CsrReadConsoleOutput
)
2654 PCHAR_INFO CharInfo
;
2655 PCHAR_INFO CurCharInfo
;
2656 PCSRSS_SCREEN_BUFFER Buff
;
2670 DPRINT("CsrReadConsoleOutput\n");
2672 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2673 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2675 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputRequest
.ConsoleHandle
, &Buff
, GENERIC_READ
);
2676 if (! NT_SUCCESS(Status
))
2681 CharInfo
= Request
->Data
.ReadConsoleOutputRequest
.CharInfo
;
2682 ReadRegion
.left
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
;
2683 ReadRegion
.top
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
;
2684 ReadRegion
.right
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
;
2685 ReadRegion
.bottom
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
;
2686 BufferSize
= Request
->Data
.ReadConsoleOutputRequest
.BufferSize
;
2687 BufferCoord
= Request
->Data
.ReadConsoleOutputRequest
.BufferCoord
;
2688 Length
= BufferSize
.X
* BufferSize
.Y
;
2689 Size
= Length
* sizeof(CHAR_INFO
);
2691 /* FIXME: Is this correct? */
2692 CodePage
= ProcessData
->Console
->OutputCodePage
;
2694 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
)
2695 || (((ULONG_PTR
)CharInfo
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2697 ConioUnlockScreenBuffer(Buff
);
2698 return STATUS_ACCESS_VIOLATION
;
2701 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&ReadRegion
));
2702 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&ReadRegion
));
2703 ReadRegion
.bottom
= ReadRegion
.top
+ SizeY
;
2704 ReadRegion
.right
= ReadRegion
.left
+ SizeX
;
2706 ConioInitRect(&ScreenRect
, 0, 0, Buff
->MaxY
, Buff
->MaxX
);
2707 if (! ConioGetIntersection(&ReadRegion
, &ScreenRect
, &ReadRegion
))
2709 ConioUnlockScreenBuffer(Buff
);
2710 return STATUS_SUCCESS
;
2713 for (i
= 0, Y
= ReadRegion
.top
; Y
< ReadRegion
.bottom
; ++i
, ++Y
)
2715 CurCharInfo
= CharInfo
+ (i
* BufferSize
.X
);
2717 Ptr
= ConioCoordToPointer(Buff
, ReadRegion
.left
, Y
);
2718 for (X
= ReadRegion
.left
; X
< ReadRegion
.right
; ++X
)
2720 if (Request
->Data
.ReadConsoleOutputRequest
.Unicode
)
2722 MultiByteToWideChar(CodePage
, 0,
2724 &CurCharInfo
->Char
.UnicodeChar
, 1);
2728 CurCharInfo
->Char
.AsciiChar
= *Ptr
++;
2730 CurCharInfo
->Attributes
= *Ptr
++;
2735 ConioUnlockScreenBuffer(Buff
);
2737 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
= ReadRegion
.left
+ SizeX
- 1;
2738 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
= ReadRegion
.top
+ SizeY
- 1;
2739 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
= ReadRegion
.left
;
2740 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
= ReadRegion
.top
;
2742 return STATUS_SUCCESS
;
2746 CSR_API(CsrWriteConsoleInput
)
2748 PINPUT_RECORD InputRecord
;
2749 PCSRSS_CONSOLE Console
;
2754 ConsoleInput
* Record
;
2756 DPRINT("CsrWriteConsoleInput\n");
2758 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2759 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2761 Status
= ConioLockConsole(ProcessData
, Request
->Data
.WriteConsoleInputRequest
.ConsoleHandle
, &Console
, GENERIC_WRITE
);
2762 if (! NT_SUCCESS(Status
))
2767 InputRecord
= Request
->Data
.WriteConsoleInputRequest
.InputRecord
;
2768 Length
= Request
->Data
.WriteConsoleInputRequest
.Length
;
2769 Size
= Length
* sizeof(INPUT_RECORD
);
2771 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2772 || (((ULONG_PTR
)InputRecord
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2774 ConioUnlockConsole(Console
);
2775 return STATUS_ACCESS_VIOLATION
;
2778 for (i
= 0; i
< Length
; i
++)
2780 Record
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
2783 ConioUnlockConsole(Console
);
2784 return STATUS_INSUFFICIENT_RESOURCES
;
2787 Record
->Echoed
= FALSE
;
2788 Record
->Fake
= FALSE
;
2789 //Record->InputEvent = *InputRecord++;
2790 memcpy(&Record
->InputEvent
, &InputRecord
[i
], sizeof(INPUT_RECORD
));
2791 if (KEY_EVENT
== Record
->InputEvent
.EventType
)
2793 /* FIXME - convert from unicode to ascii!! */
2794 ConioProcessChar(Console
, Record
);
2798 ConioUnlockConsole(Console
);
2800 Request
->Data
.WriteConsoleInputRequest
.Length
= i
;
2802 return STATUS_SUCCESS
;
2805 /**********************************************************************
2806 * HardwareStateProperty
2809 * Set/Get the value of the HardwareState and switch
2810 * between direct video buffer ouput and GDI windowed
2813 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
2814 * object. We use the same object to Request.
2816 * ConsoleHwState has the correct size to be compatible
2817 * with NT's, but values are not.
2819 static NTSTATUS FASTCALL
2820 SetConsoleHardwareState (PCSRSS_CONSOLE Console
, DWORD ConsoleHwState
)
2822 DPRINT1("Console Hardware State: %d\n", ConsoleHwState
);
2824 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED
== ConsoleHwState
)
2825 ||(CONSOLE_HARDWARE_STATE_DIRECT
== ConsoleHwState
))
2827 if (Console
->HardwareState
!= ConsoleHwState
)
2829 /* TODO: implement switching from full screen to windowed mode */
2830 /* TODO: or back; now simply store the hardware state */
2831 Console
->HardwareState
= ConsoleHwState
;
2834 return STATUS_SUCCESS
;
2837 return STATUS_INVALID_PARAMETER_3
; /* Client: (handle, set_get, [mode]) */
2840 CSR_API(CsrHardwareStateProperty
)
2842 PCSRSS_CONSOLE Console
;
2845 DPRINT("CsrHardwareStateProperty\n");
2847 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2848 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2850 Status
= ConioLockConsole(ProcessData
,
2851 Request
->Data
.ConsoleHardwareStateRequest
.ConsoleHandle
,
2854 if (! NT_SUCCESS(Status
))
2856 DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
2860 switch (Request
->Data
.ConsoleHardwareStateRequest
.SetGet
)
2862 case CONSOLE_HARDWARE_STATE_GET
:
2863 Request
->Data
.ConsoleHardwareStateRequest
.State
= Console
->HardwareState
;
2866 case CONSOLE_HARDWARE_STATE_SET
:
2867 DPRINT("Setting console hardware state.\n");
2868 Status
= SetConsoleHardwareState(Console
, Request
->Data
.ConsoleHardwareStateRequest
.State
);
2872 Status
= STATUS_INVALID_PARAMETER_2
; /* Client: (handle, [set_get], mode) */
2876 ConioUnlockConsole(Console
);
2881 CSR_API(CsrGetConsoleWindow
)
2883 PCSRSS_CONSOLE Console
;
2886 DPRINT("CsrGetConsoleWindow\n");
2888 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2889 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2891 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2892 if (! NT_SUCCESS(Status
))
2897 Request
->Data
.GetConsoleWindowRequest
.WindowHandle
= Console
->hWindow
;
2898 ConioUnlockConsole(Console
);
2900 return STATUS_SUCCESS
;
2903 CSR_API(CsrSetConsoleIcon
)
2905 PCSRSS_CONSOLE Console
;
2908 DPRINT("CsrSetConsoleIcon\n");
2910 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2911 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2913 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2914 if (! NT_SUCCESS(Status
))
2919 Status
= (ConioChangeIcon(Console
, Request
->Data
.SetConsoleIconRequest
.WindowIcon
)
2920 ? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
2921 ConioUnlockConsole(Console
);
2926 CSR_API(CsrGetConsoleCodePage
)
2928 PCSRSS_CONSOLE Console
;
2931 DPRINT("CsrGetConsoleCodePage\n");
2933 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2934 if (! NT_SUCCESS(Status
))
2939 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2940 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2941 Request
->Data
.GetConsoleCodePage
.CodePage
= Console
->CodePage
;
2942 ConioUnlockConsole(Console
);
2943 return STATUS_SUCCESS
;
2946 CSR_API(CsrSetConsoleCodePage
)
2948 PCSRSS_CONSOLE Console
;
2951 DPRINT("CsrSetConsoleCodePage\n");
2953 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2954 if (! NT_SUCCESS(Status
))
2959 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2960 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2962 if (IsValidCodePage(Request
->Data
.SetConsoleCodePage
.CodePage
))
2964 Console
->CodePage
= Request
->Data
.SetConsoleCodePage
.CodePage
;
2965 ConioUnlockConsole(Console
);
2966 return STATUS_SUCCESS
;
2969 ConioUnlockConsole(Console
);
2970 return STATUS_INVALID_PARAMETER
;
2973 CSR_API(CsrGetConsoleOutputCodePage
)
2975 PCSRSS_CONSOLE Console
;
2978 DPRINT("CsrGetConsoleOutputCodePage\n");
2980 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2981 if (! NT_SUCCESS(Status
))
2986 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2987 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2988 Request
->Data
.GetConsoleOutputCodePage
.CodePage
= Console
->OutputCodePage
;
2989 ConioUnlockConsole(Console
);
2990 return STATUS_SUCCESS
;
2993 CSR_API(CsrSetConsoleOutputCodePage
)
2995 PCSRSS_CONSOLE Console
;
2998 DPRINT("CsrSetConsoleOutputCodePage\n");
3000 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3001 if (! NT_SUCCESS(Status
))
3006 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3007 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3009 if (IsValidCodePage(Request
->Data
.SetConsoleOutputCodePage
.CodePage
))
3011 Console
->OutputCodePage
= Request
->Data
.SetConsoleOutputCodePage
.CodePage
;
3012 ConioUnlockConsole(Console
);
3013 return STATUS_SUCCESS
;
3016 ConioUnlockConsole(Console
);
3017 return STATUS_INVALID_PARAMETER
;
3020 CSR_API(CsrGetProcessList
)
3023 PCSRSS_CONSOLE Console
;
3024 PCSRSS_PROCESS_DATA current
;
3025 PLIST_ENTRY current_entry
;
3026 ULONG nItems
, nCopied
, Length
;
3029 DPRINT("CsrGetProcessList\n");
3031 Buffer
= Request
->Data
.GetProcessListRequest
.ProcessId
;
3032 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3033 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3035 nItems
= nCopied
= 0;
3036 Request
->Data
.GetProcessListRequest
.nProcessIdsCopied
= 0;
3037 Request
->Data
.GetProcessListRequest
.nProcessIdsTotal
= 0;
3039 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3040 if (! NT_SUCCESS(Status
))
3045 DPRINT1("Console_Api Ctrl-C\n");
3047 for(current_entry
= Console
->ProcessList
.Flink
;
3048 current_entry
!= &Console
->ProcessList
;
3049 current_entry
= current_entry
->Flink
)
3051 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
3052 if(++nItems
< Request
->Data
.GetProcessListRequest
.nMaxIds
)
3054 *(Buffer
++) = current
->ProcessId
;
3059 ConioUnlockConsole(Console
);
3061 Request
->Data
.GetProcessListRequest
.nProcessIdsCopied
= nCopied
;
3062 Request
->Data
.GetProcessListRequest
.nProcessIdsTotal
= nItems
;
3064 Length
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_GET_PROCESS_LIST
) + nCopied
* sizeof(HANDLE
);
3065 if (Length
> sizeof(CSR_API_MESSAGE
))
3067 Request
->Header
.u1
.s1
.TotalLength
= Length
;
3068 Request
->Header
.u1
.s1
.DataLength
= Length
- sizeof(PORT_MESSAGE
);
3070 return STATUS_SUCCESS
;
3073 CSR_API(CsrGenerateCtrlEvent
)
3075 PCSRSS_CONSOLE Console
;
3076 PCSRSS_PROCESS_DATA current
;
3077 PLIST_ENTRY current_entry
;
3081 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3082 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3084 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3085 if (! NT_SUCCESS(Status
))
3090 Group
= Request
->Data
.GenerateCtrlEvent
.ProcessGroup
;
3091 Status
= STATUS_INVALID_PARAMETER
;
3092 for (current_entry
= Console
->ProcessList
.Flink
;
3093 current_entry
!= &Console
->ProcessList
;
3094 current_entry
= current_entry
->Flink
)
3096 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
3097 if (Group
== 0 || current
->ProcessGroup
== Group
)
3099 ConioConsoleCtrlEvent(Request
->Data
.GenerateCtrlEvent
.Event
, current
);
3100 Status
= STATUS_SUCCESS
;
3104 ConioUnlockConsole(Console
);
3109 CSR_API(CsrSetScreenBufferSize
)
3112 PCSRSS_CONSOLE Console
;
3113 PCSRSS_SCREEN_BUFFER Buff
;
3115 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3116 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3118 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3119 if (!NT_SUCCESS(Status
))
3124 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetScreenBufferSize
.OutputHandle
, &Buff
, GENERIC_WRITE
);
3125 if (!NT_SUCCESS(Status
))
3127 ConioUnlockConsole(Console
);
3131 Status
= ConioResizeBuffer(Console
, Buff
, Request
->Data
.SetScreenBufferSize
.Size
);
3132 ConioUnlockScreenBuffer(Buff
);
3133 ConioUnlockConsole(Console
);