2 * reactos/subsys/csrss/win32csr/conio.c
4 * Console I/O functions
6 * ReactOS Operating System
9 /* INCLUDES ******************************************************************/
16 extern NTSTATUS FASTCALL
17 Win32CsrInsertObject2(PCSRSS_PROCESS_DATA
, PHANDLE
, Object_t
*);
19 /* GLOBALS *******************************************************************/
21 #define ConioInitRect(Rect, Top, Left, Bottom, Right) \
22 ((Rect)->top) = Top; \
23 ((Rect)->left) = Left; \
24 ((Rect)->bottom) = Bottom; \
25 ((Rect)->right) = Right
27 #define ConioIsRectEmpty(Rect) \
28 (((Rect)->left > (Rect)->right) || ((Rect)->top > (Rect)->bottom))
30 #define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
31 WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
33 #define ConsoleAnsiCharToUnicodeChar(Console, sWChar, dChar) \
34 MultiByteToWideChar((Console)->CodePage, 0, (dChar), 1, (sWChar), 1)
37 /* FUNCTIONS *****************************************************************/
39 static NTSTATUS FASTCALL
40 ConioConsoleFromProcessData(PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_CONSOLE
*Console
)
42 PCSRSS_CONSOLE ProcessConsole
= ProcessData
->Console
;
47 return STATUS_SUCCESS
;
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 (PVOID
) 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
, INFINITE
);
85 #define GET_CELL_BUFFER(b,o)\
88 #define SET_CELL_BUFFER(b,o,c,a)\
89 (b)->Buffer[(o)++]=(c),\
90 (b)->Buffer[(o)++]=(a)
93 ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff
)
95 DWORD Offset
= 2 * (Buff
->CurrentY
* Buff
->MaxX
);
98 for (Pos
= 0; Pos
< Buff
->MaxX
; Pos
++)
100 /* Fill the cell: Offset is incremented by the macro */
101 SET_CELL_BUFFER(Buff
, Offset
, ' ', 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
->Buffer
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, Buffer
->MaxX
* Buffer
->MaxY
* 2);
116 if (NULL
== Buffer
->Buffer
)
118 return STATUS_INSUFFICIENT_RESOURCES
;
120 InitializeCriticalSection(&Buffer
->Header
.Lock
);
121 ConioInitScreenBuffer(Console
, Buffer
);
122 /* initialize buffer to be empty with default attributes */
123 for (Buffer
->CurrentY
= 0 ; Buffer
->CurrentY
< Buffer
->MaxY
; Buffer
->CurrentY
++)
125 ClearLineBuffer(Buffer
);
127 Buffer
->Mode
= ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
;
128 Buffer
->CurrentX
= 0;
129 Buffer
->CurrentY
= 0;
131 return STATUS_SUCCESS
;
134 static NTSTATUS STDCALL
135 CsrInitConsole(PCSRSS_CONSOLE Console
)
138 SECURITY_ATTRIBUTES SecurityAttributes
;
139 PCSRSS_SCREEN_BUFFER NewBuffer
;
142 Console
->Title
.MaximumLength
= Console
->Title
.Length
= 0;
143 Console
->Title
.Buffer
= NULL
;
146 RtlCreateUnicodeString(&Console
->Title
, L
"Command Prompt");
148 Console
->Header
.ReferenceCount
= 0;
149 Console
->WaitingChars
= 0;
150 Console
->WaitingLines
= 0;
151 Console
->EchoCount
= 0;
152 Console
->Header
.Type
= CONIO_CONSOLE_MAGIC
;
153 Console
->Mode
= ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_PROCESSED_INPUT
| ENABLE_MOUSE_INPUT
;
154 Console
->EarlyReturn
= FALSE
;
155 Console
->ActiveBuffer
= NULL
;
156 InitializeListHead(&Console
->InputEvents
);
157 Console
->CodePage
= GetOEMCP();
158 Console
->OutputCodePage
= GetOEMCP();
160 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
161 SecurityAttributes
.lpSecurityDescriptor
= NULL
;
162 SecurityAttributes
.bInheritHandle
= TRUE
;
164 Console
->ActiveEvent
= CreateEventW(&SecurityAttributes
, TRUE
, FALSE
, NULL
);
165 if (NULL
== Console
->ActiveEvent
)
167 RtlFreeUnicodeString(&Console
->Title
);
168 return STATUS_UNSUCCESSFUL
;
170 Console
->PrivateData
= NULL
;
171 InitializeCriticalSection(&Console
->Header
.Lock
);
173 GuiMode
= DtbgIsDesktopVisible();
175 /* allocate console screen buffer */
176 NewBuffer
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
177 /* init screen buffer with defaults */
178 NewBuffer
->CursorInfo
.bVisible
= TRUE
;
179 NewBuffer
->CursorInfo
.dwSize
= 5;
180 /* make console active, and insert into console list */
181 Console
->ActiveBuffer
= (PCSRSS_SCREEN_BUFFER
) NewBuffer
;
182 /* add a reference count because the buffer is tied to the console */
183 InterlockedIncrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
);
184 if (NULL
== NewBuffer
)
186 RtlFreeUnicodeString(&Console
->Title
);
187 DeleteCriticalSection(&Console
->Header
.Lock
);
188 CloseHandle(Console
->ActiveEvent
);
189 return STATUS_INSUFFICIENT_RESOURCES
;
194 Status
= TuiInitConsole(Console
);
195 if (! NT_SUCCESS(Status
))
197 DPRINT1("Failed to open text-mode console, switching to gui-mode\n");
203 Status
= GuiInitConsole(Console
);
204 if (! NT_SUCCESS(Status
))
206 HeapFree(Win32CsrApiHeap
,0, NewBuffer
);
207 RtlFreeUnicodeString(&Console
->Title
);
208 DeleteCriticalSection(&Console
->Header
.Lock
);
209 CloseHandle(Console
->ActiveEvent
);
210 DPRINT1("GuiInitConsole: failed\n");
215 Status
= CsrInitConsoleScreenBuffer(Console
, NewBuffer
);
216 if (! NT_SUCCESS(Status
))
218 ConioCleanupConsole(Console
);
219 RtlFreeUnicodeString(&Console
->Title
);
220 DeleteCriticalSection(&Console
->Header
.Lock
);
221 CloseHandle(Console
->ActiveEvent
);
222 HeapFree(Win32CsrApiHeap
, 0, NewBuffer
);
223 DPRINT1("CsrInitConsoleScreenBuffer: failed\n");
227 /* copy buffer contents to screen */
228 ConioDrawConsole(Console
);
230 return STATUS_SUCCESS
;
234 CSR_API(CsrAllocConsole
)
236 PCSRSS_CONSOLE Console
;
237 NTSTATUS Status
= STATUS_SUCCESS
;
238 BOOLEAN NewConsole
= FALSE
;
240 DPRINT("CsrAllocConsole\n");
242 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
243 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
245 if (ProcessData
== NULL
)
247 DPRINT1("No process data\n");
248 return Request
->Status
= STATUS_INVALID_PARAMETER
;
251 if (ProcessData
->Console
)
253 DPRINT1("Process already has a console\n");
254 Request
->Status
= STATUS_INVALID_PARAMETER
;
255 return STATUS_INVALID_PARAMETER
;
259 Request
->Status
= STATUS_SUCCESS
;
261 /* If we don't need a console, then get out of here */
262 if (!Request
->Data
.AllocConsoleRequest
.ConsoleNeeded
)
264 DPRINT("No console needed\n");
265 return STATUS_SUCCESS
;
268 /* If we already have one, then don't create a new one... */
269 if (!Request
->Data
.AllocConsoleRequest
.Console
||
270 Request
->Data
.AllocConsoleRequest
.Console
!= ProcessData
->ParentConsole
)
272 /* Allocate a console structure */
274 Console
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_CONSOLE
));
277 DPRINT1("Not enough memory for console\n");
278 Request
->Status
= STATUS_NO_MEMORY
;
279 return STATUS_NO_MEMORY
;
281 /* initialize list head */
282 InitializeListHead(&Console
->ProcessList
);
283 /* insert process data required for GUI initialization */
284 InsertHeadList(&Console
->ProcessList
, &ProcessData
->ProcessEntry
);
285 /* Initialize the Console */
286 Request
->Status
= CsrInitConsole(Console
);
287 if (!NT_SUCCESS(Request
->Status
))
289 DPRINT1("Console init failed\n");
290 HeapFree(Win32CsrApiHeap
, 0, Console
);
291 return Request
->Status
;
296 /* Reuse our current console */
297 Console
= Request
->Data
.AllocConsoleRequest
.Console
;
300 /* Set the Process Console */
301 ProcessData
->Console
= Console
;
303 /* Return it to the caller */
304 Request
->Data
.AllocConsoleRequest
.Console
= Console
;
306 /* Add a reference count because the process is tied to the console */
307 Console
->Header
.ReferenceCount
++;
309 if (NewConsole
|| !ProcessData
->bInheritHandles
)
311 /* Insert the Objects */
312 Status
= Win32CsrInsertObject2(ProcessData
,
313 &Request
->Data
.AllocConsoleRequest
.InputHandle
,
315 if (! NT_SUCCESS(Status
))
317 DPRINT1("Failed to insert object\n");
318 ConioDeleteConsole((Object_t
*) Console
);
319 ProcessData
->Console
= 0;
320 return Request
->Status
= Status
;
323 Status
= Win32CsrInsertObject2(ProcessData
,
324 &Request
->Data
.AllocConsoleRequest
.OutputHandle
,
325 &Console
->ActiveBuffer
->Header
);
326 if (!NT_SUCCESS(Status
))
328 DPRINT1("Failed to insert object\n");
329 ConioDeleteConsole((Object_t
*) Console
);
330 Win32CsrReleaseObject(ProcessData
,
331 Request
->Data
.AllocConsoleRequest
.InputHandle
);
332 ProcessData
->Console
= 0;
333 return Request
->Status
= Status
;
337 /* Duplicate the Event */
338 if (!DuplicateHandle(GetCurrentProcess(),
339 ProcessData
->Console
->ActiveEvent
,
340 ProcessData
->Process
,
341 &ProcessData
->ConsoleEvent
,
346 DPRINT1("DuplicateHandle() failed: %d\n", GetLastError
);
347 ConioDeleteConsole((Object_t
*) Console
);
348 if (NewConsole
|| !ProcessData
->bInheritHandles
)
350 Win32CsrReleaseObject(ProcessData
,
351 Request
->Data
.AllocConsoleRequest
.OutputHandle
);
352 Win32CsrReleaseObject(ProcessData
,
353 Request
->Data
.AllocConsoleRequest
.InputHandle
);
355 ProcessData
->Console
= 0;
356 return Request
->Status
= Status
;
359 /* Set the Ctrl Dispatcher */
360 ProcessData
->CtrlDispatcher
= Request
->Data
.AllocConsoleRequest
.CtrlDispatcher
;
361 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
365 /* Insert into the list if it has not been added */
366 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ProcessEntry
);
369 return STATUS_SUCCESS
;
372 CSR_API(CsrFreeConsole
)
374 PCSRSS_CONSOLE Console
;
377 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
378 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
380 if (ProcessData
== NULL
|| ProcessData
->Console
== NULL
)
382 return Request
->Status
= STATUS_INVALID_PARAMETER
;
385 Console
= ProcessData
->Console
;
386 ProcessData
->Console
= NULL
;
387 if (0 == InterlockedDecrement(&Console
->Header
.ReferenceCount
))
389 ConioDeleteConsole((Object_t
*) Console
);
391 return STATUS_SUCCESS
;
395 ConioNextLine(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, UINT
*ScrolledLines
)
397 /* slide the viewable screen */
398 if (((Buff
->CurrentY
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
) == (ULONG
)Buff
->MaxY
- 1)
400 if (++Buff
->ShowY
== Buff
->MaxY
)
406 if (++Buff
->CurrentY
== Buff
->MaxY
)
410 ClearLineBuffer(Buff
);
411 UpdateRect
->left
= 0;
412 UpdateRect
->right
= Buff
->MaxX
- 1;
413 if (UpdateRect
->top
== (LONG
)Buff
->CurrentY
)
415 if (++UpdateRect
->top
== Buff
->MaxY
)
420 UpdateRect
->bottom
= Buff
->CurrentY
;
423 static NTSTATUS FASTCALL
424 ConioWriteConsole(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
,
425 CHAR
*Buffer
, DWORD Length
, BOOL Attrib
)
430 LONG CursorStartX
, CursorStartY
;
433 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &CursorStartX
, &CursorStartY
);
434 UpdateRect
.left
= Buff
->MaxX
;
435 UpdateRect
.top
= Buff
->CurrentY
;
436 UpdateRect
.right
= -1;
437 UpdateRect
.bottom
= Buff
->CurrentY
;
440 for (i
= 0; i
< Length
; i
++)
442 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
445 if (Buffer
[i
] == '\n')
448 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
452 else if (Buffer
[i
] == '\b')
454 /* Only handle BS if we're not on the first pos of the first line */
455 if (0 != Buff
->CurrentX
|| Buff
->ShowY
!= Buff
->CurrentY
)
457 if (0 == Buff
->CurrentX
)
459 /* slide virtual position up */
460 Buff
->CurrentX
= Buff
->MaxX
- 1;
461 if (0 == Buff
->CurrentY
)
463 Buff
->CurrentY
= Buff
->MaxY
;
469 if ((0 == UpdateRect
.top
&& UpdateRect
.bottom
< (LONG
)Buff
->CurrentY
)
470 || (0 != UpdateRect
.top
&& (LONG
)Buff
->CurrentY
< UpdateRect
.top
))
472 UpdateRect
.top
= Buff
->CurrentY
;
479 Offset
= 2 * ((Buff
->CurrentY
* Buff
->MaxX
) + Buff
->CurrentX
);
480 SET_CELL_BUFFER(Buff
, Offset
, ' ', Buff
->DefaultAttrib
);
481 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
) Buff
->CurrentX
);
482 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
487 else if (Buffer
[i
] == '\r')
490 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
) Buff
->CurrentX
);
491 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
495 else if (Buffer
[i
] == '\t')
499 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
)Buff
->CurrentX
);
500 EndX
= (Buff
->CurrentX
+ 8) & ~7;
501 if (EndX
> Buff
->MaxX
)
505 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
506 while (Buff
->CurrentX
< EndX
)
508 Buff
->Buffer
[Offset
] = ' ';
512 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
- 1);
513 if (Buff
->CurrentX
== Buff
->MaxX
)
515 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
518 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
528 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
)Buff
->CurrentX
);
529 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
530 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
531 Buff
->Buffer
[Offset
++] = Buffer
[i
];
534 Buff
->Buffer
[Offset
] = Buff
->DefaultAttrib
;
537 if (Buff
->CurrentX
== Buff
->MaxX
)
539 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
542 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
546 Buff
->CurrentX
= CursorStartX
;
551 ConioPhysicalToLogical(Buff
, UpdateRect
.left
, UpdateRect
.top
, &(UpdateRect
.left
),
553 ConioPhysicalToLogical(Buff
, UpdateRect
.right
, UpdateRect
.bottom
, &(UpdateRect
.right
),
554 &(UpdateRect
.bottom
));
555 if (! ConioIsRectEmpty(&UpdateRect
) && NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
557 ConioWriteStream(Console
, &UpdateRect
, CursorStartX
, CursorStartY
, ScrolledLines
,
561 return STATUS_SUCCESS
;
564 CSR_API(CsrReadConsole
)
566 PLIST_ENTRY CurrentEntry
;
569 PWCHAR UnicodeBuffer
;
571 ULONG nNumberOfCharsToRead
, CharSize
;
572 PCSRSS_CONSOLE Console
;
575 DPRINT("CsrReadConsole\n");
577 CharSize
= (Request
->Data
.ReadConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
579 /* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */
580 nNumberOfCharsToRead
= min(Request
->Data
.ReadConsoleRequest
.NrCharactersToRead
, CSRSS_MAX_READ_CONSOLE
/ CharSize
);
581 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
582 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
584 Buffer
= Request
->Data
.ReadConsoleRequest
.Buffer
;
585 UnicodeBuffer
= (PWCHAR
)Buffer
;
586 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadConsoleRequest
.ConsoleHandle
,
588 if (! NT_SUCCESS(Status
))
590 return Request
->Status
= Status
;
592 Request
->Data
.ReadConsoleRequest
.EventHandle
= ProcessData
->ConsoleEvent
;
593 for (i
= 0; i
< nNumberOfCharsToRead
&& Console
->InputEvents
.Flink
!= &Console
->InputEvents
; i
++)
595 /* remove input event from queue */
596 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
597 if (IsListEmpty(&Console
->InputEvents
))
600 ResetEvent(Console
->ActiveEvent
);
602 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
604 /* only pay attention to valid ascii chars, on key down */
605 if (KEY_EVENT
== Input
->InputEvent
.EventType
606 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
607 && Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
!= '\0')
610 * backspace handling - if we are in charge of echoing it then we handle it here
611 * otherwise we treat it like a normal char.
613 if ('\b' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
&& 0
614 != (Console
->Mode
& ENABLE_ECHO_INPUT
))
616 /* echo if it has not already been done, and either we or the client has chars to be deleted */
618 && (0 != i
|| Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
))
620 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
621 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
625 i
-= 2; /* if we already have something to return, just back it up by 2 */
628 { /* otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer */
629 Console
->WaitingChars
--;
630 ConioUnlockConsole(Console
);
631 HeapFree(Win32CsrApiHeap
, 0, Input
);
632 Request
->Data
.ReadConsoleRequest
.NrCharactersRead
= 0;
633 Request
->Status
= STATUS_NOTIFY_CLEANUP
;
634 return STATUS_NOTIFY_CLEANUP
;
637 Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
--;
638 Input
->Echoed
= TRUE
; /* mark as echoed so we don't echo it below */
640 /* do not copy backspace to buffer */
643 if(Request
->Data
.ReadConsoleRequest
.Unicode
)
644 UnicodeBuffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
; /* FIXME */
646 Buffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
;
648 /* echo to screen if enabled and we did not already echo the char */
649 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
)
651 && '\r' != Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
653 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
654 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
661 Console
->WaitingChars
--;
662 HeapFree(Win32CsrApiHeap
, 0, Input
);
664 Request
->Data
.ReadConsoleRequest
.NrCharactersRead
= i
;
667 Request
->Status
= STATUS_PENDING
; /* we didn't read anything */
669 else if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
))
671 if (0 == Console
->WaitingLines
||
672 (Request
->Data
.ReadConsoleRequest
.Unicode
? (L
'\n' != UnicodeBuffer
[i
- 1]) : ('\n' != Buffer
[i
- 1])))
674 Request
->Status
= STATUS_PENDING
; /* line buffered, didn't get a complete line */
678 Console
->WaitingLines
--;
679 Request
->Status
= STATUS_SUCCESS
; /* line buffered, did get a complete line */
684 Request
->Status
= STATUS_SUCCESS
; /* not line buffered, did read something */
687 if (Request
->Status
== STATUS_PENDING
)
689 Console
->EchoCount
= nNumberOfCharsToRead
- i
;
693 Console
->EchoCount
= 0; /* if the client is no longer waiting on input, do not echo */
696 ConioUnlockConsole(Console
);
698 if (CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE
) + i
* CharSize
> sizeof(CSR_API_MESSAGE
))
700 Request
->Header
.u1
.s1
.TotalLength
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE
) + i
* CharSize
;
701 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
704 return Request
->Status
;
708 ConioPhysicalToLogical(PCSRSS_SCREEN_BUFFER Buff
,
714 *LogicalX
= PhysicalX
;
715 if (PhysicalY
< Buff
->ShowY
)
717 *LogicalY
= Buff
->MaxY
- Buff
->ShowY
+ PhysicalY
;
721 *LogicalY
= PhysicalY
- Buff
->ShowY
;
725 BOOLEAN __inline
ConioIsEqualRect(
729 return ((Rect1
->left
== Rect2
->left
) && (Rect1
->right
== Rect2
->right
) &&
730 (Rect1
->top
== Rect2
->top
) && (Rect1
->bottom
== Rect2
->bottom
));
733 BOOLEAN __inline
ConioGetIntersection(
738 if (ConioIsRectEmpty(Rect1
) ||
739 (ConioIsRectEmpty(Rect2
)) ||
740 (Rect1
->top
> Rect2
->bottom
) ||
741 (Rect1
->left
> Rect2
->right
) ||
742 (Rect1
->bottom
< Rect2
->top
) ||
743 (Rect1
->right
< Rect2
->left
))
745 /* The rectangles do not intersect */
746 ConioInitRect(Intersection
, 0, -1, 0, -1);
750 ConioInitRect(Intersection
,
751 max(Rect1
->top
, Rect2
->top
),
752 max(Rect1
->left
, Rect2
->left
),
753 min(Rect1
->bottom
, Rect2
->bottom
),
754 min(Rect1
->right
, Rect2
->right
));
759 BOOLEAN __inline
ConioGetUnion(
764 if (ConioIsRectEmpty(Rect1
))
766 if (ConioIsRectEmpty(Rect2
))
768 ConioInitRect(Union
, 0, -1, 0, -1);
776 else if (ConioIsRectEmpty(Rect2
))
783 min(Rect1
->top
, Rect2
->top
),
784 min(Rect1
->left
, Rect2
->left
),
785 max(Rect1
->bottom
, Rect2
->bottom
),
786 max(Rect1
->right
, Rect2
->right
));
792 BOOLEAN __inline
ConioSubtractRect(
799 if (ConioIsRectEmpty(Rect1
))
801 ConioInitRect(Subtraction
, 0, -1, 0, -1);
804 *Subtraction
= *Rect1
;
805 if (ConioGetIntersection(&tmp
, Rect1
, Rect2
))
807 if (ConioIsEqualRect(&tmp
, Subtraction
))
809 ConioInitRect(Subtraction
, 0, -1, 0, -1);
812 if ((tmp
.top
== Subtraction
->top
) && (tmp
.bottom
== Subtraction
->bottom
))
814 if (tmp
.left
== Subtraction
->left
)
816 Subtraction
->left
= tmp
.right
;
818 else if (tmp
.right
== Subtraction
->right
)
820 Subtraction
->right
= tmp
.left
;
823 else if ((tmp
.left
== Subtraction
->left
) && (tmp
.right
== Subtraction
->right
))
825 if (tmp
.top
== Subtraction
->top
)
827 Subtraction
->top
= tmp
.bottom
;
829 else if (tmp
.bottom
== Subtraction
->bottom
)
831 Subtraction
->bottom
= tmp
.top
;
840 ConioCopyRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer
,
850 DstY
= DstRegion
->top
;
851 BytesPerLine
= ConioRectWidth(DstRegion
) * 2;
853 SrcY
= (SrcRegion
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
854 DstY
= (DstRegion
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
855 SrcOffset
= (SrcY
* ScreenBuffer
->MaxX
+ SrcRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
856 DstOffset
= (DstY
* ScreenBuffer
->MaxX
+ DstRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
858 for (i
= SrcRegion
->top
; i
<= SrcRegion
->bottom
; i
++)
861 &ScreenBuffer
->Buffer
[DstOffset
],
862 &ScreenBuffer
->Buffer
[SrcOffset
],
865 if (++DstY
== ScreenBuffer
->MaxY
)
868 DstOffset
= (DstRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
872 DstOffset
+= ScreenBuffer
->MaxX
* 2;
875 if (++SrcY
== ScreenBuffer
->MaxY
)
878 SrcOffset
= (SrcRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
882 SrcOffset
+= ScreenBuffer
->MaxX
* 2;
888 ConioFillRegion(PCSRSS_CONSOLE Console
,
889 PCSRSS_SCREEN_BUFFER ScreenBuffer
,
901 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &CharInfo
->Char
.UnicodeChar
);
903 Char
= CharInfo
->Char
.AsciiChar
;
905 Y
= (Region
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
906 Offset
= (Y
* ScreenBuffer
->MaxX
+ Region
->left
+ ScreenBuffer
->ShowX
) * 2;
907 Delta
= (ScreenBuffer
->MaxX
- ConioRectWidth(Region
)) * 2;
909 for (i
= Region
->top
; i
<= Region
->bottom
; i
++)
911 for (X
= Region
->left
; X
<= Region
->right
; X
++)
913 SET_CELL_BUFFER(ScreenBuffer
, Offset
, Char
, CharInfo
->Attributes
);
915 if (++Y
== ScreenBuffer
->MaxY
)
918 Offset
= (Region
->left
+ ScreenBuffer
->ShowX
) * 2;
928 ConioInputEventToAnsi(PCSRSS_CONSOLE Console
, PINPUT_RECORD InputEvent
)
930 if (InputEvent
->EventType
== KEY_EVENT
)
932 WCHAR UnicodeChar
= InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
;
933 InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
= 0;
934 ConsoleUnicodeCharToAnsiChar(Console
,
935 &InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
,
940 CSR_API(CsrWriteConsole
)
944 PCSRSS_SCREEN_BUFFER Buff
;
945 PCSRSS_CONSOLE Console
;
948 ULONG CharSize
= (Request
->Data
.WriteConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
950 DPRINT("CsrWriteConsole\n");
952 if (Request
->Header
.u1
.s1
.TotalLength
953 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE
)
954 + (Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
* CharSize
))
956 DPRINT1("Invalid request size\n");
957 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
958 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
959 return Request
->Status
= STATUS_INVALID_PARAMETER
;
961 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
963 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
964 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
966 if (! NT_SUCCESS(Status
))
968 return Request
->Status
= Status
;
971 if(Request
->Data
.WriteConsoleRequest
.Unicode
)
973 Length
= WideCharToMultiByte(Console
->CodePage
, 0,
974 (PWCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
,
975 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
,
976 NULL
, 0, NULL
, NULL
);
977 Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
980 WideCharToMultiByte(Console
->CodePage
, 0,
981 (PWCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
,
982 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
,
983 Buffer
, Length
, NULL
, NULL
);
987 Status
= STATUS_NO_MEMORY
;
992 Buffer
= (PCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
;
997 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.WriteConsoleRequest
.ConsoleHandle
, &Buff
);
998 if (NT_SUCCESS(Status
))
1000 Request
->Status
= ConioWriteConsole(Console
, Buff
, Buffer
,
1001 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
, TRUE
);
1002 if (NT_SUCCESS(Status
))
1004 Written
= Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
;
1006 ConioUnlockScreenBuffer(Buff
);
1008 if (Request
->Data
.WriteConsoleRequest
.Unicode
)
1010 RtlFreeHeap(GetProcessHeap(), 0, Buffer
);
1013 if (NULL
!= Console
)
1015 ConioUnlockConsole(Console
);
1018 Request
->Data
.WriteConsoleRequest
.NrCharactersWritten
= Written
;
1020 return Request
->Status
= Status
;
1024 ConioDeleteScreenBuffer(Object_t
*Object
)
1026 PCSRSS_SCREEN_BUFFER Buffer
= (PCSRSS_SCREEN_BUFFER
) Object
;
1027 DeleteCriticalSection(&Buffer
->Header
.Lock
);
1028 HeapFree(Win32CsrApiHeap
, 0, Buffer
->Buffer
);
1029 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
1033 ConioDrawConsole(PCSRSS_CONSOLE Console
)
1037 ConioInitRect(&Region
, 0, 0, Console
->Size
.Y
- 1, Console
->Size
.X
- 1);
1039 ConioDrawRegion(Console
, &Region
);
1044 ConioDeleteConsole(Object_t
*Object
)
1046 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Object
;
1047 ConsoleInput
*Event
;
1049 DPRINT("ConioDeleteConsole\n");
1051 /* Drain input event queue */
1052 while (Console
->InputEvents
.Flink
!= &Console
->InputEvents
)
1054 Event
= (ConsoleInput
*) Console
->InputEvents
.Flink
;
1055 Console
->InputEvents
.Flink
= Console
->InputEvents
.Flink
->Flink
;
1056 Console
->InputEvents
.Flink
->Flink
->Blink
= &Console
->InputEvents
;
1057 HeapFree(Win32CsrApiHeap
, 0, Event
);
1061 if (0 == InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
1063 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
1067 Console
->ActiveBuffer
= NULL
;
1068 ConioCleanupConsole(Console
);
1070 CloseHandle(Console
->ActiveEvent
);
1071 DeleteCriticalSection(&Console
->Header
.Lock
);
1072 RtlFreeUnicodeString(&Console
->Title
);
1073 HeapFree(Win32CsrApiHeap
, 0, Console
);
1077 CsrInitConsoleSupport(VOID
)
1079 DPRINT("CSR: CsrInitConsoleSupport()\n");
1081 /* Should call LoadKeyboardLayout */
1084 static VOID FASTCALL
1085 ConioProcessChar(PCSRSS_CONSOLE Console
,
1086 ConsoleInput
*KeyEventRecord
)
1089 BOOL bClientWake
= FALSE
;
1090 ConsoleInput
*TempInput
;
1092 /* process Ctrl-C and Ctrl-Break */
1093 if (Console
->Mode
& ENABLE_PROCESSED_INPUT
&&
1094 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
&&
1095 ((KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== VK_PAUSE
) ||
1096 (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== 'C')) &&
1097 (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
)))
1099 PCSRSS_PROCESS_DATA current
;
1100 PLIST_ENTRY current_entry
;
1101 DPRINT1("Console_Api Ctrl-C\n");
1102 current_entry
= Console
->ProcessList
.Flink
;
1103 while (current_entry
!= &Console
->ProcessList
)
1105 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
1106 current_entry
= current_entry
->Flink
;
1107 ConioConsoleCtrlEvent((DWORD
)CTRL_C_EVENT
, current
);
1109 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1113 if (0 != (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
1114 & (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1115 && (VK_UP
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
1116 || VK_DOWN
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
))
1118 if (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1120 /* scroll up or down */
1121 if (NULL
== Console
)
1123 DPRINT1("No Active Console!\n");
1124 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1127 if (VK_UP
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
)
1129 /* only scroll up if there is room to scroll up into */
1130 if (Console
->ActiveBuffer
->ShowY
!= ((Console
->ActiveBuffer
->CurrentY
+ 1) %
1131 Console
->ActiveBuffer
->MaxY
))
1133 Console
->ActiveBuffer
->ShowY
= (Console
->ActiveBuffer
->ShowY
+
1134 Console
->ActiveBuffer
->MaxY
- 1) %
1135 Console
->ActiveBuffer
->MaxY
;
1138 else if (Console
->ActiveBuffer
->ShowY
!= Console
->ActiveBuffer
->CurrentY
)
1139 /* only scroll down if there is room to scroll down into */
1141 if (Console
->ActiveBuffer
->ShowY
% Console
->ActiveBuffer
->MaxY
!=
1142 Console
->ActiveBuffer
->CurrentY
)
1144 if (((Console
->ActiveBuffer
->CurrentY
+ 1) % Console
->ActiveBuffer
->MaxY
) !=
1145 (Console
->ActiveBuffer
->ShowY
+ Console
->ActiveBuffer
->MaxY
) %
1146 Console
->ActiveBuffer
->MaxY
)
1148 Console
->ActiveBuffer
->ShowY
= (Console
->ActiveBuffer
->ShowY
+ 1) %
1149 Console
->ActiveBuffer
->MaxY
;
1153 ConioDrawConsole(Console
);
1155 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1158 if (NULL
== Console
)
1160 DPRINT1("No Active Console!\n");
1161 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1165 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
)))
1167 switch(KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1170 /* first add the \r */
1171 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1172 updown
= KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
;
1173 KeyEventRecord
->Echoed
= FALSE
;
1174 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= VK_RETURN
;
1175 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\r';
1176 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1177 Console
->WaitingChars
++;
1178 KeyEventRecord
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1179 if (NULL
== KeyEventRecord
)
1181 DPRINT1("Failed to allocate KeyEventRecord\n");
1184 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1185 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
= updown
;
1186 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= 0;
1187 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualScanCode
= 0;
1188 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\n';
1189 KeyEventRecord
->Fake
= TRUE
;
1193 /* add event to the queue */
1194 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1195 Console
->WaitingChars
++;
1196 /* if line input mode is enabled, only wake the client on enter key down */
1197 if (0 == (Console
->Mode
& ENABLE_LINE_INPUT
)
1198 || Console
->EarlyReturn
1199 || ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1200 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
))
1202 if ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1204 Console
->WaitingLines
++;
1207 SetEvent(Console
->ActiveEvent
);
1209 KeyEventRecord
->Echoed
= FALSE
;
1210 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
))
1211 && '\b' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1212 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1214 /* walk the input queue looking for a char to backspace */
1215 for (TempInput
= (ConsoleInput
*) Console
->InputEvents
.Blink
;
1216 TempInput
!= (ConsoleInput
*) &Console
->InputEvents
1217 && (KEY_EVENT
== TempInput
->InputEvent
.EventType
1218 || ! TempInput
->InputEvent
.Event
.KeyEvent
.bKeyDown
1219 || '\b' == TempInput
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
);
1220 TempInput
= (ConsoleInput
*) TempInput
->ListEntry
.Blink
)
1224 /* if we found one, delete it, otherwise, wake the client */
1225 if (TempInput
!= (ConsoleInput
*) &Console
->InputEvents
)
1227 /* delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue */
1228 RemoveEntryList(&TempInput
->ListEntry
);
1229 if (TempInput
->Echoed
)
1231 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1232 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1235 HeapFree(Win32CsrApiHeap
, 0, TempInput
);
1236 RemoveEntryList(&KeyEventRecord
->ListEntry
);
1237 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1238 Console
->WaitingChars
-= 2;
1242 SetEvent(Console
->ActiveEvent
);
1247 /* echo chars if we are supposed to and client is waiting for some */
1248 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
) && Console
->EchoCount
1249 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1250 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
1251 && '\r' != KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1253 /* mark the char as already echoed */
1254 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1255 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1257 Console
->EchoCount
--;
1258 KeyEventRecord
->Echoed
= TRUE
;
1262 /* Console->WaitingChars++; */
1263 if (bClientWake
|| 0 == (Console
->Mode
& ENABLE_LINE_INPUT
))
1265 SetEvent(Console
->ActiveEvent
);
1269 static DWORD FASTCALL
1270 ConioGetShiftState(PBYTE KeyState
)
1274 if (KeyState
[VK_CAPITAL
] & 1)
1275 ssOut
|= CAPSLOCK_ON
;
1277 if (KeyState
[VK_NUMLOCK
] & 1)
1278 ssOut
|= NUMLOCK_ON
;
1280 if (KeyState
[VK_SCROLL
] & 1)
1281 ssOut
|= SCROLLLOCK_ON
;
1283 if (KeyState
[VK_SHIFT
] & 0x80)
1284 ssOut
|= SHIFT_PRESSED
;
1286 if (KeyState
[VK_LCONTROL
] & 0x80)
1287 ssOut
|= LEFT_CTRL_PRESSED
;
1288 if (KeyState
[VK_RCONTROL
] & 0x80)
1289 ssOut
|= RIGHT_CTRL_PRESSED
;
1291 if (KeyState
[VK_LMENU
] & 0x80)
1292 ssOut
|= LEFT_ALT_PRESSED
;
1293 if (KeyState
[VK_RMENU
] & 0x80)
1294 ssOut
|= RIGHT_ALT_PRESSED
;
1300 ConioProcessKey(MSG
*msg
, PCSRSS_CONSOLE Console
, BOOL TextMode
)
1302 static BYTE KeyState
[256] = { 0 };
1303 /* MSDN mentions that you should use the last virtual key code received
1304 * when putting a virtual key identity to a WM_CHAR message since multiple
1305 * or translated keys may be involved. */
1306 static UINT LastVirtualKey
= 0;
1308 ConsoleInput
*ConInRec
;
1312 UINT VirtualKeyCode
;
1313 UINT VirtualScanCode
;
1316 ULONG ResultSize
= 0;
1319 VirtualScanCode
= (msg
->lParam
>> 16) & 0xff;
1320 Down
= msg
->message
== WM_KEYDOWN
|| msg
->message
== WM_CHAR
||
1321 msg
->message
== WM_SYSKEYDOWN
|| msg
->message
== WM_SYSCHAR
;
1323 GetKeyboardState(KeyState
);
1324 ShiftState
= ConioGetShiftState(KeyState
);
1326 if (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
)
1328 VirtualKeyCode
= LastVirtualKey
;
1329 UnicodeChar
= msg
->wParam
;
1336 VirtualKeyCode
= msg
->wParam
;
1337 RetChars
= ToUnicodeEx(VirtualKeyCode
,
1344 UnicodeChar
= (1 == RetChars
? Chars
[0] : 0);
1347 if (0 == ResultSize
)
1352 er
.EventType
= KEY_EVENT
;
1353 er
.Event
.KeyEvent
.bKeyDown
= Down
;
1354 er
.Event
.KeyEvent
.wRepeatCount
= RepeatCount
;
1355 er
.Event
.KeyEvent
.uChar
.UnicodeChar
= UnicodeChar
;
1356 er
.Event
.KeyEvent
.dwControlKeyState
= ShiftState
;
1357 er
.Event
.KeyEvent
.wVirtualKeyCode
= VirtualKeyCode
;
1358 er
.Event
.KeyEvent
.wVirtualScanCode
= VirtualScanCode
;
1362 if (0 != (ShiftState
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1363 && VK_TAB
== VirtualKeyCode
)
1367 TuiSwapConsole(ShiftState
& SHIFT_PRESSED
? -1 : 1);
1372 else if (VK_MENU
== VirtualKeyCode
&& ! Down
)
1374 if (TuiSwapConsole(0))
1381 if (NULL
== Console
)
1386 ConInRec
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1388 if (NULL
== ConInRec
)
1393 ConInRec
->InputEvent
= er
;
1394 ConInRec
->Fake
= UnicodeChar
&&
1395 (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
&&
1396 msg
->message
!= WM_KEYUP
&& msg
->message
!= WM_SYSKEYUP
);
1397 ConInRec
->NotChar
= (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
);
1398 ConInRec
->Echoed
= FALSE
;
1399 if (ConInRec
->NotChar
)
1400 LastVirtualKey
= msg
->wParam
;
1402 DPRINT ("csrss: %s %s %s %s %02x %02x '%c' %04x\n",
1403 Down
? "down" : "up ",
1404 (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
) ?
1406 ConInRec
->Fake
? "fake" : "real",
1407 ConInRec
->NotChar
? "notc" : "char",
1410 (AsciiChar
>= ' ') ? AsciiChar
: '.',
1413 if (! ConInRec
->Fake
|| ! ConInRec
->NotChar
)
1415 /* FIXME - convert to ascii */
1416 ConioProcessChar(Console
, ConInRec
);
1420 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1424 CSR_API(CsrGetScreenBufferInfo
)
1427 PCSRSS_SCREEN_BUFFER Buff
;
1428 PCONSOLE_SCREEN_BUFFER_INFO pInfo
;
1430 DPRINT("CsrGetScreenBufferInfo\n");
1432 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1433 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1435 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ScreenBufferInfoRequest
.ConsoleHandle
, &Buff
);
1436 if (! NT_SUCCESS(Status
))
1438 return Request
->Status
= Status
;
1440 pInfo
= &Request
->Data
.ScreenBufferInfoRequest
.Info
;
1441 pInfo
->dwSize
.X
= Buff
->MaxX
;
1442 pInfo
->dwSize
.Y
= Buff
->MaxY
;
1443 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1444 pInfo
->dwCursorPosition
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1445 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
1446 pInfo
->srWindow
.Left
= 0;
1447 pInfo
->srWindow
.Right
= Buff
->MaxX
- 1;
1448 pInfo
->srWindow
.Top
= 0;
1449 pInfo
->srWindow
.Bottom
= Buff
->MaxY
- 1;
1450 pInfo
->dwMaximumWindowSize
.X
= Buff
->MaxX
;
1451 pInfo
->dwMaximumWindowSize
.Y
= Buff
->MaxY
;
1452 ConioUnlockScreenBuffer(Buff
);
1454 Request
->Status
= STATUS_SUCCESS
;
1456 return Request
->Status
;
1459 CSR_API(CsrSetCursor
)
1462 PCSRSS_CONSOLE Console
;
1463 PCSRSS_SCREEN_BUFFER Buff
;
1464 LONG OldCursorX
, OldCursorY
;
1465 LONG NewCursorX
, NewCursorY
;
1467 DPRINT("CsrSetCursor\n");
1469 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1470 if (! NT_SUCCESS(Status
))
1472 return Request
->Status
= Status
;
1475 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1476 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1478 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
);
1479 if (! NT_SUCCESS(Status
))
1481 if (NULL
!= Console
)
1483 ConioUnlockConsole(Console
);
1485 return Request
->Status
= Status
;
1488 NewCursorX
= Request
->Data
.SetCursorRequest
.Position
.X
;
1489 NewCursorY
= Request
->Data
.SetCursorRequest
.Position
.Y
;
1490 if (NewCursorX
< 0 || NewCursorX
>= Buff
->MaxX
||
1491 NewCursorY
< 0 || NewCursorY
>= Buff
->MaxY
)
1493 ConioUnlockScreenBuffer(Buff
);
1494 if (NULL
!= Console
)
1496 ConioUnlockConsole(Console
);
1498 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1500 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &OldCursorX
, &OldCursorY
);
1501 Buff
->CurrentX
= NewCursorX
+ Buff
->ShowX
;
1502 Buff
->CurrentY
= (NewCursorY
+ Buff
->ShowY
) % Buff
->MaxY
;
1503 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1505 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
1507 ConioUnlockScreenBuffer(Buff
);
1508 if (NULL
!= Console
)
1510 ConioUnlockConsole(Console
);
1512 return Request
->Status
= STATUS_UNSUCCESSFUL
;
1516 ConioUnlockScreenBuffer(Buff
);
1517 if (NULL
!= Console
)
1519 ConioUnlockConsole(Console
);
1522 return Request
->Status
= STATUS_SUCCESS
;
1525 static VOID FASTCALL
1526 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, COORD
*Start
, UINT Length
)
1528 if (Buff
->MaxX
<= Start
->X
+ Length
)
1530 UpdateRect
->left
= 0;
1534 UpdateRect
->left
= Start
->X
;
1536 if (Buff
->MaxX
<= Start
->X
+ Length
)
1538 UpdateRect
->right
= Buff
->MaxX
- 1;
1542 UpdateRect
->right
= Start
->X
+ Length
- 1;
1544 UpdateRect
->top
= Start
->Y
;
1545 UpdateRect
->bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->MaxX
;
1546 if (Buff
->MaxY
<= UpdateRect
->bottom
)
1548 UpdateRect
->bottom
= Buff
->MaxY
- 1;
1552 CSR_API(CsrWriteConsoleOutputChar
)
1555 PCHAR String
, tmpString
= NULL
;
1557 PCSRSS_CONSOLE Console
;
1558 PCSRSS_SCREEN_BUFFER Buff
;
1559 DWORD X
, Y
, Length
, CharSize
, Written
= 0;
1562 DPRINT("CsrWriteConsoleOutputChar\n");
1564 CharSize
= (Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
1566 if (Request
->Header
.u1
.s1
.TotalLength
1567 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR
)
1568 + (Request
->Data
.WriteConsoleOutputCharRequest
.Length
* CharSize
))
1570 DPRINT1("Invalid request size\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 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1576 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1577 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1578 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1579 if (NT_SUCCESS(Status
))
1581 if(Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
)
1583 Length
= WideCharToMultiByte(Console
->CodePage
, 0,
1584 (PWCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
,
1585 Request
->Data
.WriteConsoleOutputCharRequest
.Length
,
1586 NULL
, 0, NULL
, NULL
);
1587 tmpString
= String
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
1590 WideCharToMultiByte(Console
->CodePage
, 0,
1591 (PWCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
,
1592 Request
->Data
.WriteConsoleOutputCharRequest
.Length
,
1593 String
, Length
, NULL
, NULL
);
1597 Status
= STATUS_NO_MEMORY
;
1602 String
= (PCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
;
1607 Status
= ConioLockScreenBuffer(ProcessData
,
1608 Request
->Data
.WriteConsoleOutputCharRequest
.ConsoleHandle
,
1610 if (NT_SUCCESS(Status
))
1612 X
= Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.X
+ Buff
->ShowX
;
1613 Y
= (Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1614 Length
= Request
->Data
.WriteConsoleOutputCharRequest
.Length
;
1615 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1618 *Buffer
= *String
++;
1621 if (++X
== Buff
->MaxX
)
1623 if (++Y
== Buff
->MaxY
)
1626 Buffer
= Buff
->Buffer
;
1631 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1633 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputCharRequest
.Coord
,
1634 Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
1635 ConioDrawRegion(Console
, &UpdateRect
);
1638 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.X
= X
- Buff
->ShowX
;
1639 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1641 ConioUnlockScreenBuffer(Buff
);
1643 if (Request
->Data
.WriteConsoleRequest
.Unicode
)
1645 RtlFreeHeap(GetProcessHeap(), 0, tmpString
);
1648 if (NULL
!= Console
)
1650 ConioUnlockConsole(Console
);
1653 Request
->Data
.WriteConsoleOutputCharRequest
.NrCharactersWritten
= Written
;
1654 return Request
->Status
= Status
;
1657 CSR_API(CsrFillOutputChar
)
1660 PCSRSS_CONSOLE Console
;
1661 PCSRSS_SCREEN_BUFFER Buff
;
1662 DWORD X
, Y
, Length
, Written
= 0;
1667 DPRINT("CsrFillOutputChar\n");
1669 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1670 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1672 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1673 if (! NT_SUCCESS(Status
))
1675 return Request
->Status
= Status
;
1678 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputRequest
.ConsoleHandle
, &Buff
);
1679 if (! NT_SUCCESS(Status
))
1681 if (NULL
!= Console
)
1683 ConioUnlockConsole(Console
);
1685 return Request
->Status
= Status
;
1688 X
= Request
->Data
.FillOutputRequest
.Position
.X
+ Buff
->ShowX
;
1689 Y
= (Request
->Data
.FillOutputRequest
.Position
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1690 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1691 if(Request
->Data
.FillOutputRequest
.Unicode
)
1692 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &Request
->Data
.FillOutputRequest
.Char
.UnicodeChar
);
1694 Char
= Request
->Data
.FillOutputRequest
.Char
.AsciiChar
;
1695 Length
= Request
->Data
.FillOutputRequest
.Length
;
1701 if (++X
== Buff
->MaxX
)
1703 if (++Y
== Buff
->MaxY
)
1706 Buffer
= Buff
->Buffer
;
1712 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1714 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputRequest
.Position
,
1715 Request
->Data
.FillOutputRequest
.Length
);
1716 ConioDrawRegion(Console
, &UpdateRect
);
1719 ConioUnlockScreenBuffer(Buff
);
1720 if (NULL
!= Console
)
1722 ConioUnlockConsole(Console
);
1724 Length
= Request
->Data
.FillOutputRequest
.Length
;
1725 Request
->Data
.FillOutputRequest
.NrCharactersWritten
= Length
;
1726 return Request
->Status
;
1729 CSR_API(CsrReadInputEvent
)
1731 PLIST_ENTRY CurrentEntry
;
1732 PCSRSS_CONSOLE Console
;
1734 BOOLEAN Done
= FALSE
;
1735 ConsoleInput
*Input
;
1737 DPRINT("CsrReadInputEvent\n");
1739 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1740 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1741 Request
->Data
.ReadInputRequest
.Event
= ProcessData
->ConsoleEvent
;
1743 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadInputRequest
.ConsoleHandle
, &Console
);
1744 if (! NT_SUCCESS(Status
))
1746 return Request
->Status
= Status
;
1749 /* only get input if there is any */
1750 CurrentEntry
= Console
->InputEvents
.Flink
;
1751 while (CurrentEntry
!= &Console
->InputEvents
)
1753 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
1754 CurrentEntry
= CurrentEntry
->Flink
;
1756 if (Done
&& !Input
->Fake
)
1758 Request
->Data
.ReadInputRequest
.MoreEvents
= TRUE
;
1762 RemoveEntryList(&Input
->ListEntry
);
1764 if (!Done
&& !Input
->Fake
)
1766 Request
->Data
.ReadInputRequest
.Input
= Input
->InputEvent
;
1767 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
1769 ConioInputEventToAnsi(Console
, &Request
->Data
.ReadInputRequest
.Input
);
1774 if (Input
->InputEvent
.EventType
== KEY_EVENT
)
1776 if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
)
1777 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
1778 && '\r' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1780 Console
->WaitingLines
--;
1782 Console
->WaitingChars
--;
1784 HeapFree(Win32CsrApiHeap
, 0, Input
);
1789 Status
= STATUS_SUCCESS
;
1790 Console
->EarlyReturn
= FALSE
;
1794 Status
= STATUS_PENDING
;
1795 Console
->EarlyReturn
= TRUE
; /* mark for early return */
1798 if (IsListEmpty(&Console
->InputEvents
))
1800 ResetEvent(Console
->ActiveEvent
);
1803 ConioUnlockConsole(Console
);
1805 return Request
->Status
= Status
;
1808 CSR_API(CsrWriteConsoleOutputAttrib
)
1810 PCSRSS_CONSOLE Console
;
1811 PCSRSS_SCREEN_BUFFER Buff
;
1818 DPRINT("CsrWriteConsoleOutputAttrib\n");
1820 if (Request
->Header
.u1
.s1
.TotalLength
1821 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB
)
1822 + Request
->Data
.WriteConsoleOutputAttribRequest
.Length
* sizeof(WORD
))
1824 DPRINT1("Invalid request size\n");
1825 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1826 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1827 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1830 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1831 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1832 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1833 if (! NT_SUCCESS(Status
))
1835 return Request
->Status
= Status
;
1838 Status
= ConioLockScreenBuffer(ProcessData
,
1839 Request
->Data
.WriteConsoleOutputAttribRequest
.ConsoleHandle
,
1841 if (! NT_SUCCESS(Status
))
1843 if (NULL
!= Console
)
1845 ConioUnlockConsole(Console
);
1847 return Request
->Status
= Status
;
1850 X
= Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1851 Y
= (Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1852 Length
= Request
->Data
.WriteConsoleOutputAttribRequest
.Length
;
1853 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + 1];
1854 Attribute
= Request
->Data
.WriteConsoleOutputAttribRequest
.Attribute
;
1857 *Buffer
= (UCHAR
)(*Attribute
++);
1859 if (++X
== Buff
->MaxX
)
1861 if (++Y
== Buff
->MaxY
)
1864 Buffer
= Buff
->Buffer
+ 1;
1870 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1872 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
,
1873 Request
->Data
.WriteConsoleOutputAttribRequest
.Length
);
1874 ConioDrawRegion(Console
, &UpdateRect
);
1877 if (NULL
!= Console
)
1879 ConioUnlockConsole(Console
);
1882 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1883 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1885 ConioUnlockScreenBuffer(Buff
);
1887 return Request
->Status
= STATUS_SUCCESS
;
1890 CSR_API(CsrFillOutputAttrib
)
1892 PCSRSS_SCREEN_BUFFER Buff
;
1898 PCSRSS_CONSOLE Console
;
1900 DPRINT("CsrFillOutputAttrib\n");
1902 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1903 if (! NT_SUCCESS(Status
))
1905 return Request
->Status
= Status
;
1908 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1909 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1910 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputAttribRequest
.ConsoleHandle
, &Buff
);
1911 if (! NT_SUCCESS(Status
))
1913 if (NULL
!= Console
)
1915 ConioUnlockConsole(Console
);
1917 return Request
->Status
= Status
;
1920 X
= Request
->Data
.FillOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1921 Y
= (Request
->Data
.FillOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1922 Length
= Request
->Data
.FillOutputAttribRequest
.Length
;
1923 Attr
= Request
->Data
.FillOutputAttribRequest
.Attribute
;
1924 Buffer
= &Buff
->Buffer
[(Y
* Buff
->MaxX
* 2) + (X
* 2) + 1];
1929 if (++X
== Buff
->MaxX
)
1931 if (++Y
== Buff
->MaxY
)
1934 Buffer
= Buff
->Buffer
+ 1;
1940 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1942 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputAttribRequest
.Coord
,
1943 Request
->Data
.FillOutputAttribRequest
.Length
);
1944 ConioDrawRegion(Console
, &UpdateRect
);
1947 ConioUnlockScreenBuffer(Buff
);
1948 if (NULL
!= Console
)
1950 ConioUnlockConsole(Console
);
1953 return Request
->Status
= STATUS_SUCCESS
;
1957 CSR_API(CsrGetCursorInfo
)
1959 PCSRSS_SCREEN_BUFFER Buff
;
1962 DPRINT("CsrGetCursorInfo\n");
1964 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1965 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1967 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.GetCursorInfoRequest
.ConsoleHandle
, &Buff
);
1968 if (! NT_SUCCESS(Status
))
1970 return Request
->Status
= Status
;
1972 Request
->Data
.GetCursorInfoRequest
.Info
.bVisible
= Buff
->CursorInfo
.bVisible
;
1973 Request
->Data
.GetCursorInfoRequest
.Info
.dwSize
= Buff
->CursorInfo
.dwSize
;
1974 ConioUnlockScreenBuffer(Buff
);
1976 return Request
->Status
= STATUS_SUCCESS
;
1979 CSR_API(CsrSetCursorInfo
)
1981 PCSRSS_CONSOLE Console
;
1982 PCSRSS_SCREEN_BUFFER Buff
;
1987 DPRINT("CsrSetCursorInfo\n");
1989 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1990 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1992 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1993 if (! NT_SUCCESS(Status
))
1995 return Request
->Status
= Status
;
1998 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorInfoRequest
.ConsoleHandle
, &Buff
);
1999 if (! NT_SUCCESS(Status
))
2001 if (NULL
!= Console
)
2003 ConioUnlockConsole(Console
);
2005 return Request
->Status
= Status
;
2008 Size
= Request
->Data
.SetCursorInfoRequest
.Info
.dwSize
;
2009 Visible
= Request
->Data
.SetCursorInfoRequest
.Info
.bVisible
;
2019 if (Size
!= Buff
->CursorInfo
.dwSize
2020 || (Visible
&& ! Buff
->CursorInfo
.bVisible
) || (! Visible
&& Buff
->CursorInfo
.bVisible
))
2022 Buff
->CursorInfo
.dwSize
= Size
;
2023 Buff
->CursorInfo
.bVisible
= Visible
;
2025 if (NULL
!= Console
&& ! ConioSetCursorInfo(Console
, Buff
))
2027 ConioUnlockScreenBuffer(Buff
);
2028 ConioUnlockConsole(Console
);
2029 return Request
->Status
= STATUS_UNSUCCESSFUL
;
2033 ConioUnlockScreenBuffer(Buff
);
2034 if (NULL
!= Console
)
2036 ConioUnlockConsole(Console
);
2039 return Request
->Status
= STATUS_SUCCESS
;
2042 CSR_API(CsrSetTextAttrib
)
2045 PCSRSS_CONSOLE Console
;
2046 PCSRSS_SCREEN_BUFFER Buff
;
2047 LONG OldCursorX
, OldCursorY
;
2049 DPRINT("CsrSetTextAttrib\n");
2051 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2052 if (! NT_SUCCESS(Status
))
2054 return Request
->Status
= Status
;
2057 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
);
2058 if (! NT_SUCCESS(Status
))
2060 if (NULL
!= Console
)
2062 ConioUnlockConsole(Console
);
2064 return Request
->Status
= Status
;
2067 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &OldCursorX
, &OldCursorY
);
2069 Buff
->DefaultAttrib
= Request
->Data
.SetAttribRequest
.Attrib
;
2070 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
2072 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
2074 ConioUnlockScreenBuffer(Buff
);
2075 ConioUnlockConsole(Console
);
2076 return Request
->Status
= STATUS_UNSUCCESSFUL
;
2080 ConioUnlockScreenBuffer(Buff
);
2081 if (NULL
!= Console
)
2083 ConioUnlockConsole(Console
);
2086 return Request
->Status
= STATUS_SUCCESS
;
2089 CSR_API(CsrSetConsoleMode
)
2092 PCSRSS_CONSOLE Console
;
2093 PCSRSS_SCREEN_BUFFER Buff
;
2095 DPRINT("CsrSetConsoleMode\n");
2097 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2098 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2099 Status
= Win32CsrGetObject(ProcessData
,
2100 Request
->Data
.SetConsoleModeRequest
.ConsoleHandle
,
2101 (Object_t
**) &Console
);
2102 if (! NT_SUCCESS(Status
))
2104 return Request
->Status
= Status
;
2107 Buff
= (PCSRSS_SCREEN_BUFFER
)Console
;
2108 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
2110 Console
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_INPUT_MODE_VALID
;
2112 else if (CONIO_SCREEN_BUFFER_MAGIC
== Console
->Header
.Type
)
2114 Buff
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_OUTPUT_MODE_VALID
;
2118 return Request
->Status
= STATUS_INVALID_HANDLE
;
2121 Request
->Status
= STATUS_SUCCESS
;
2123 return Request
->Status
;
2126 CSR_API(CsrGetConsoleMode
)
2129 PCSRSS_CONSOLE Console
;
2130 PCSRSS_SCREEN_BUFFER Buff
; /* gee, I really wish I could use an anonymous union here */
2132 DPRINT("CsrGetConsoleMode\n");
2134 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2135 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2136 Status
= Win32CsrGetObject(ProcessData
, Request
->Data
.GetConsoleModeRequest
.ConsoleHandle
,
2137 (Object_t
**) &Console
);
2138 if (! NT_SUCCESS(Status
))
2140 return Request
->Status
= Status
;
2142 Request
->Status
= STATUS_SUCCESS
;
2143 Buff
= (PCSRSS_SCREEN_BUFFER
) Console
;
2144 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
2146 Request
->Data
.GetConsoleModeRequest
.ConsoleMode
= Console
->Mode
;
2148 else if (CONIO_SCREEN_BUFFER_MAGIC
== Buff
->Header
.Type
)
2150 Request
->Data
.GetConsoleModeRequest
.ConsoleMode
= Buff
->Mode
;
2154 Request
->Status
= STATUS_INVALID_HANDLE
;
2157 return Request
->Status
;
2160 CSR_API(CsrCreateScreenBuffer
)
2162 PCSRSS_CONSOLE Console
;
2163 PCSRSS_SCREEN_BUFFER Buff
;
2166 DPRINT("CsrCreateScreenBuffer\n");
2168 if (ProcessData
== NULL
)
2170 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2173 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2174 if (! NT_SUCCESS(Status
))
2176 return Request
->Status
= Status
;
2178 if (NULL
== Console
)
2180 return Request
->Status
= STATUS_INVALID_HANDLE
;
2183 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2184 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2186 Buff
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
2190 if (Console
->ActiveBuffer
)
2192 Buff
->MaxX
= Console
->ActiveBuffer
->MaxX
;
2193 Buff
->MaxY
= Console
->ActiveBuffer
->MaxY
;
2194 Buff
->CursorInfo
.bVisible
= Console
->ActiveBuffer
->CursorInfo
.bVisible
;
2195 Buff
->CursorInfo
.dwSize
= Console
->ActiveBuffer
->CursorInfo
.dwSize
;
2199 Buff
->CursorInfo
.bVisible
= TRUE
;
2200 Buff
->CursorInfo
.dwSize
= 5;
2203 if (Buff
->MaxX
== 0)
2208 if (Buff
->MaxY
== 0)
2213 Status
= CsrInitConsoleScreenBuffer(Console
, Buff
);
2214 if(! NT_SUCCESS(Status
))
2216 Request
->Status
= Status
;
2220 Request
->Status
= Win32CsrInsertObject(ProcessData
, &Request
->Data
.CreateScreenBufferRequest
.OutputHandle
, &Buff
->Header
);
2225 Request
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2228 ConioUnlockConsole(Console
);
2229 return Request
->Status
;
2232 CSR_API(CsrSetScreenBuffer
)
2235 PCSRSS_CONSOLE Console
;
2236 PCSRSS_SCREEN_BUFFER Buff
;
2238 DPRINT("CsrSetScreenBuffer\n");
2240 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2241 if (! NT_SUCCESS(Status
))
2243 return Request
->Status
= Status
;
2245 if (NULL
== Console
)
2247 DPRINT1("Trying to set screen buffer for app without console\n");
2248 return Request
->Status
= STATUS_INVALID_HANDLE
;
2251 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2252 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2254 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetScreenBufferRequest
.OutputHandle
, &Buff
);
2255 if (! NT_SUCCESS(Status
))
2257 ConioUnlockConsole(Console
);
2258 return Request
->Status
;
2261 if (Buff
== Console
->ActiveBuffer
)
2263 ConioUnlockScreenBuffer(Buff
);
2264 ConioUnlockConsole(Console
);
2265 return STATUS_SUCCESS
;
2268 /* drop reference to old buffer, maybe delete */
2269 if (! InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
2271 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
2273 /* tie console to new buffer */
2274 Console
->ActiveBuffer
= Buff
;
2275 /* inc ref count on new buffer */
2276 InterlockedIncrement(&Buff
->Header
.ReferenceCount
);
2277 /* Redraw the console */
2278 ConioDrawConsole(Console
);
2280 ConioUnlockScreenBuffer(Buff
);
2281 ConioUnlockConsole(Console
);
2283 return Request
->Status
= STATUS_SUCCESS
;
2286 CSR_API(CsrSetTitle
)
2289 PCSRSS_CONSOLE Console
;
2292 DPRINT("CsrSetTitle\n");
2294 if (Request
->Header
.u1
.s1
.TotalLength
2295 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_SET_TITLE
)
2296 + Request
->Data
.SetTitleRequest
.Length
)
2298 DPRINT1("Invalid request size\n");
2299 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2300 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2301 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2304 Status
= ConioLockConsole(ProcessData
, Request
->Data
.SetTitleRequest
.Console
, &Console
);
2305 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2306 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2307 if(! NT_SUCCESS(Status
))
2309 Request
->Status
= Status
;
2313 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, Request
->Data
.SetTitleRequest
.Length
);
2316 /* copy title to console */
2317 RtlFreeUnicodeString(&Console
->Title
);
2318 Console
->Title
.Buffer
= Buffer
;
2319 Console
->Title
.Length
= Console
->Title
.MaximumLength
= Request
->Data
.SetTitleRequest
.Length
;
2320 memcpy(Console
->Title
.Buffer
, Request
->Data
.SetTitleRequest
.Title
, Console
->Title
.Length
);
2321 if (! ConioChangeTitle(Console
))
2323 Request
->Status
= STATUS_UNSUCCESSFUL
;
2327 Request
->Status
= STATUS_SUCCESS
;
2332 Request
->Status
= STATUS_NO_MEMORY
;
2335 ConioUnlockConsole(Console
);
2337 return Request
->Status
;
2340 CSR_API(CsrGetTitle
)
2343 PCSRSS_CONSOLE Console
;
2346 DPRINT("CsrGetTitle\n");
2348 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2349 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2350 Status
= ConioLockConsole(ProcessData
,
2351 Request
->Data
.GetTitleRequest
.ConsoleHandle
,
2353 if (! NT_SUCCESS(Status
))
2355 DPRINT1("Can't get console\n");
2356 return Request
->Status
= Status
;
2359 /* Copy title of the console to the user title buffer */
2360 RtlZeroMemory(&Request
->Data
.GetTitleRequest
, sizeof(CSRSS_GET_TITLE
));
2361 Request
->Data
.GetTitleRequest
.ConsoleHandle
= Request
->Data
.GetTitleRequest
.ConsoleHandle
;
2362 Request
->Data
.GetTitleRequest
.Length
= Console
->Title
.Length
;
2363 memcpy (Request
->Data
.GetTitleRequest
.Title
, Console
->Title
.Buffer
,
2364 Console
->Title
.Length
);
2365 Length
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_SET_TITLE
) + Console
->Title
.Length
;
2367 ConioUnlockConsole(Console
);
2369 if (Length
> sizeof(CSR_API_MESSAGE
))
2371 Request
->Header
.u1
.s1
.TotalLength
= Length
;
2372 Request
->Header
.u1
.s1
.DataLength
= Length
- sizeof(PORT_MESSAGE
);
2374 Request
->Status
= STATUS_SUCCESS
;
2376 return Request
->Status
;
2379 CSR_API(CsrWriteConsoleOutput
)
2381 SHORT i
, X
, Y
, SizeX
, SizeY
;
2382 PCSRSS_CONSOLE Console
;
2383 PCSRSS_SCREEN_BUFFER Buff
;
2385 CHAR_INFO
* CurCharInfo
;
2387 CHAR_INFO
* CharInfo
;
2394 DPRINT("CsrWriteConsoleOutput\n");
2396 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2397 if (! NT_SUCCESS(Status
))
2399 return Request
->Status
= Status
;
2402 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2403 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2404 Status
= ConioLockScreenBuffer(ProcessData
,
2405 Request
->Data
.WriteConsoleOutputRequest
.ConsoleHandle
,
2407 if (! NT_SUCCESS(Status
))
2409 if (NULL
!= Console
)
2411 ConioUnlockConsole(Console
);
2413 return Request
->Status
= Status
;
2416 BufferSize
= Request
->Data
.WriteConsoleOutputRequest
.BufferSize
;
2417 PSize
= BufferSize
.X
* BufferSize
.Y
* sizeof(CHAR_INFO
);
2418 BufferCoord
= Request
->Data
.WriteConsoleOutputRequest
.BufferCoord
;
2419 CharInfo
= Request
->Data
.WriteConsoleOutputRequest
.CharInfo
;
2420 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
) ||
2421 (((ULONG_PTR
)CharInfo
+ PSize
) >
2422 ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2424 ConioUnlockScreenBuffer(Buff
);
2425 ConioUnlockConsole(Console
);
2426 return Request
->Status
= STATUS_ACCESS_VIOLATION
;
2428 WriteRegion
.left
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
;
2429 WriteRegion
.top
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
;
2430 WriteRegion
.right
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
;
2431 WriteRegion
.bottom
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
;
2433 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&WriteRegion
));
2434 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&WriteRegion
));
2435 WriteRegion
.bottom
= WriteRegion
.top
+ SizeY
- 1;
2436 WriteRegion
.right
= WriteRegion
.left
+ SizeX
- 1;
2438 /* Make sure WriteRegion is inside the screen buffer */
2439 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2440 if (! ConioGetIntersection(&WriteRegion
, &ScreenBuffer
, &WriteRegion
))
2442 ConioUnlockScreenBuffer(Buff
);
2443 ConioUnlockConsole(Console
);
2445 /* It is okay to have a WriteRegion completely outside the screen buffer.
2446 No data is written then. */
2447 return Request
->Status
= STATUS_SUCCESS
;
2450 for (i
= 0, Y
= WriteRegion
.top
; Y
<= WriteRegion
.bottom
; i
++, Y
++)
2452 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
2453 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ WriteRegion
.left
) * 2;
2454 for (X
= WriteRegion
.left
; X
<= WriteRegion
.right
; X
++)
2456 if (Request
->Data
.WriteConsoleOutputRequest
.Unicode
)
2459 ConsoleUnicodeCharToAnsiChar(Console
, &AsciiChar
, &CurCharInfo
->Char
.UnicodeChar
);
2460 SET_CELL_BUFFER(Buff
, Offset
, AsciiChar
, CurCharInfo
->Attributes
);
2464 SET_CELL_BUFFER(Buff
, Offset
, CurCharInfo
->Char
.AsciiChar
, CurCharInfo
->Attributes
);
2470 if (NULL
!= Console
)
2472 ConioDrawRegion(Console
, &WriteRegion
);
2475 ConioUnlockScreenBuffer(Buff
);
2476 ConioUnlockConsole(Console
);
2478 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
= WriteRegion
.left
+ SizeX
- 1;
2479 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
= WriteRegion
.top
+ SizeY
- 1;
2480 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
= WriteRegion
.left
;
2481 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
= WriteRegion
.top
;
2483 return Request
->Status
= STATUS_SUCCESS
;
2486 CSR_API(CsrFlushInputBuffer
)
2488 PLIST_ENTRY CurrentEntry
;
2489 PCSRSS_CONSOLE Console
;
2490 ConsoleInput
* Input
;
2493 DPRINT("CsrFlushInputBuffer\n");
2495 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2496 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2497 Status
= ConioLockConsole(ProcessData
,
2498 Request
->Data
.FlushInputBufferRequest
.ConsoleInput
,
2500 if(! NT_SUCCESS(Status
))
2502 return Request
->Status
= Status
;
2505 /* Discard all entries in the input event queue */
2506 while (!IsListEmpty(&Console
->InputEvents
))
2508 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
2509 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
2510 /* Destroy the event */
2511 HeapFree(Win32CsrApiHeap
, 0, Input
);
2513 ResetEvent(Console
->ActiveEvent
);
2514 Console
->WaitingChars
=0;
2516 ConioUnlockConsole(Console
);
2518 return Request
->Status
= STATUS_SUCCESS
;
2521 CSR_API(CsrScrollConsoleScreenBuffer
)
2523 PCSRSS_CONSOLE Console
;
2524 PCSRSS_SCREEN_BUFFER Buff
;
2529 RECT ScrollRectangle
;
2533 HANDLE ConsoleHandle
;
2534 BOOLEAN UseClipRectangle
;
2535 COORD DestinationOrigin
;
2538 DPRINT("CsrScrollConsoleScreenBuffer\n");
2540 ConsoleHandle
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ConsoleHandle
;
2541 UseClipRectangle
= Request
->Data
.ScrollConsoleScreenBufferRequest
.UseClipRectangle
;
2542 DestinationOrigin
= Request
->Data
.ScrollConsoleScreenBufferRequest
.DestinationOrigin
;
2543 Fill
= Request
->Data
.ScrollConsoleScreenBufferRequest
.Fill
;
2545 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2546 if (! NT_SUCCESS(Status
))
2548 return Request
->Status
= Status
;
2551 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2552 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2553 Status
= ConioLockScreenBuffer(ProcessData
, ConsoleHandle
, &Buff
);
2554 if (! NT_SUCCESS(Status
))
2556 if (NULL
!= Console
)
2558 ConioUnlockConsole(Console
);
2560 return Request
->Status
= Status
;
2563 ScrollRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Left
;
2564 ScrollRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Top
;
2565 ScrollRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Right
;
2566 ScrollRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Bottom
;
2567 ClipRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Left
;
2568 ClipRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Top
;
2569 ClipRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Right
;
2570 ClipRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Bottom
;
2572 /* Make sure source rectangle is inside the screen buffer */
2573 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2574 if (! ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, &ScrollRectangle
))
2576 ConioUnlockScreenBuffer(Buff
);
2577 if (NULL
!= Console
)
2579 ConioUnlockConsole(Console
);
2581 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2584 if (UseClipRectangle
&& ! ConioGetIntersection(&SrcRegion
, &SrcRegion
, &ClipRectangle
))
2586 if (NULL
!= Console
)
2588 ConioUnlockConsole(Console
);
2590 ConioUnlockScreenBuffer(Buff
);
2591 return Request
->Status
= STATUS_SUCCESS
;
2595 ConioInitRect(&DstRegion
,
2596 DestinationOrigin
.Y
,
2597 DestinationOrigin
.X
,
2598 DestinationOrigin
.Y
+ ConioRectHeight(&ScrollRectangle
) - 1,
2599 DestinationOrigin
.X
+ ConioRectWidth(&ScrollRectangle
) - 1);
2601 /* Make sure destination rectangle is inside the screen buffer */
2602 if (! ConioGetIntersection(&DstRegion
, &DstRegion
, &ScreenBuffer
))
2604 if (NULL
!= Console
)
2606 ConioUnlockConsole(Console
);
2608 ConioUnlockScreenBuffer(Buff
);
2609 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2612 ConioCopyRegion(Buff
, &SrcRegion
, &DstRegion
);
2614 /* Get the region that should be filled with the specified character and attributes */
2618 ConioGetUnion(&FillRegion
, &SrcRegion
, &DstRegion
);
2620 if (ConioSubtractRect(&FillRegion
, &FillRegion
, &DstRegion
))
2622 /* FIXME: The subtracted rectangle is off by one line */
2623 FillRegion
.top
+= 1;
2625 ConioFillRegion(Console
, Buff
, &FillRegion
, &Fill
, Request
->Data
.ScrollConsoleScreenBufferRequest
.Unicode
);
2629 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
2631 /* Draw destination region */
2632 ConioDrawRegion(Console
, &DstRegion
);
2636 /* Draw filled region */
2637 ConioDrawRegion(Console
, &FillRegion
);
2641 ConioUnlockScreenBuffer(Buff
);
2642 if (NULL
!= Console
)
2644 ConioUnlockConsole(Console
);
2647 return Request
->Status
= STATUS_SUCCESS
;
2650 CSR_API(CsrReadConsoleOutputChar
)
2653 PCSRSS_CONSOLE Console
;
2654 PCSRSS_SCREEN_BUFFER Buff
;
2661 DPRINT("CsrReadConsoleOutputChar\n");
2663 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2664 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2665 ReadBuffer
= Request
->Data
.ReadConsoleOutputCharRequest
.String
;
2667 CharSize
= (Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
2669 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2670 if (! NT_SUCCESS(Status
))
2672 return Request
->Status
= Status
;
2675 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputCharRequest
.ConsoleHandle
, &Buff
);
2676 if (! NT_SUCCESS(Status
))
2678 if (NULL
!= Console
)
2680 ConioUnlockConsole(Console
);
2682 return Request
->Status
= Status
;
2685 Xpos
= Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.X
+ Buff
->ShowX
;
2686 Ypos
= (Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
2688 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
; ++i
)
2690 Char
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
)];
2692 if(Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
)
2694 ConsoleAnsiCharToUnicodeChar(Console
, (WCHAR
*)ReadBuffer
, &Char
);
2695 ReadBuffer
+= sizeof(WCHAR
);
2698 *(ReadBuffer
++) = Char
;
2702 if (Xpos
== Buff
->MaxX
)
2707 if (Ypos
== Buff
->MaxY
)
2715 Request
->Status
= STATUS_SUCCESS
;
2716 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.X
= Xpos
- Buff
->ShowX
;
2717 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.Y
= (Ypos
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
;
2719 ConioUnlockScreenBuffer(Buff
);
2720 if (NULL
!= Console
)
2722 ConioUnlockConsole(Console
);
2725 Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
= (DWORD
)((ULONG_PTR
)ReadBuffer
- (ULONG_PTR
)Request
->Data
.ReadConsoleOutputCharRequest
.String
) / CharSize
;
2726 if (Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
* CharSize
+ CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR
) > sizeof(CSR_API_MESSAGE
))
2728 Request
->Header
.u1
.s1
.TotalLength
= Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
* CharSize
+ CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR
);
2729 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2732 return Request
->Status
;
2736 CSR_API(CsrReadConsoleOutputAttrib
)
2739 PCSRSS_SCREEN_BUFFER Buff
;
2743 DWORD CurrentLength
;
2745 DPRINT("CsrReadConsoleOutputAttrib\n");
2747 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2748 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2749 ReadBuffer
= Request
->Data
.ReadConsoleOutputAttribRequest
.Attribute
;
2751 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputAttribRequest
.ConsoleHandle
, &Buff
);
2752 if (! NT_SUCCESS(Status
))
2754 return Request
->Status
= Status
;
2757 Xpos
= Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.X
+ Buff
->ShowX
;
2758 Ypos
= (Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
2760 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
; ++i
)
2762 *ReadBuffer
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
) + 1];
2767 if (Xpos
== Buff
->MaxX
)
2772 if (Ypos
== Buff
->MaxY
)
2781 Request
->Status
= STATUS_SUCCESS
;
2782 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.X
= Xpos
- Buff
->ShowX
;
2783 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.Y
= (Ypos
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
;
2785 ConioUnlockScreenBuffer(Buff
);
2787 CurrentLength
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_ATTRIB
)
2788 + Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
* sizeof(WORD
);
2789 if (CurrentLength
> sizeof(CSR_API_MESSAGE
))
2791 Request
->Header
.u1
.s1
.TotalLength
= CurrentLength
;
2792 Request
->Header
.u1
.s1
.DataLength
= CurrentLength
- sizeof(PORT_MESSAGE
);
2795 return Request
->Status
;
2799 CSR_API(CsrGetNumberOfConsoleInputEvents
)
2802 PCSRSS_CONSOLE Console
;
2803 PLIST_ENTRY CurrentItem
;
2805 ConsoleInput
*Input
;
2807 DPRINT("CsrGetNumberOfConsoleInputEvents\n");
2809 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2810 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2812 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
);
2813 if (! NT_SUCCESS(Status
))
2815 return Request
->Status
= Status
;
2818 CurrentItem
= Console
->InputEvents
.Flink
;
2821 /* If there are any events ... */
2822 while (CurrentItem
!= &Console
->InputEvents
)
2824 Input
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2825 CurrentItem
= CurrentItem
->Flink
;
2832 ConioUnlockConsole(Console
);
2834 Request
->Status
= STATUS_SUCCESS
;
2835 Request
->Data
.GetNumInputEventsRequest
.NumInputEvents
= NumEvents
;
2837 return Request
->Status
;
2841 CSR_API(CsrPeekConsoleInput
)
2844 PCSRSS_CONSOLE Console
;
2847 PLIST_ENTRY CurrentItem
;
2848 PINPUT_RECORD InputRecord
;
2852 DPRINT("CsrPeekConsoleInput\n");
2854 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2855 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2857 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
);
2858 if(! NT_SUCCESS(Status
))
2860 return Request
->Status
= Status
;
2863 InputRecord
= Request
->Data
.PeekConsoleInputRequest
.InputRecord
;
2864 Length
= Request
->Data
.PeekConsoleInputRequest
.Length
;
2865 Size
= Length
* sizeof(INPUT_RECORD
);
2867 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2868 || (((ULONG_PTR
)InputRecord
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2870 ConioUnlockConsole(Console
);
2871 Request
->Status
= STATUS_ACCESS_VIOLATION
;
2872 return Request
->Status
;
2877 if (! IsListEmpty(&Console
->InputEvents
))
2879 CurrentItem
= Console
->InputEvents
.Flink
;
2881 while (CurrentItem
!= &Console
->InputEvents
&& NumItems
< Length
)
2883 Item
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2887 CurrentItem
= CurrentItem
->Flink
;
2892 *InputRecord
= Item
->InputEvent
;
2894 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
2896 ConioInputEventToAnsi(Console
, InputRecord
);
2900 CurrentItem
= CurrentItem
->Flink
;
2904 ConioUnlockConsole(Console
);
2906 Request
->Status
= STATUS_SUCCESS
;
2907 Request
->Data
.PeekConsoleInputRequest
.Length
= NumItems
;
2909 return Request
->Status
;
2913 CSR_API(CsrReadConsoleOutput
)
2915 PCHAR_INFO CharInfo
;
2916 PCHAR_INFO CurCharInfo
;
2917 PCSRSS_SCREEN_BUFFER Buff
;
2930 DPRINT("CsrReadConsoleOutput\n");
2932 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2933 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2935 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputRequest
.ConsoleHandle
, &Buff
);
2936 if (! NT_SUCCESS(Status
))
2938 return Request
->Status
= Status
;
2941 CharInfo
= Request
->Data
.ReadConsoleOutputRequest
.CharInfo
;
2942 ReadRegion
.left
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
;
2943 ReadRegion
.top
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
;
2944 ReadRegion
.right
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
;
2945 ReadRegion
.bottom
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
;
2946 BufferSize
= Request
->Data
.ReadConsoleOutputRequest
.BufferSize
;
2947 BufferCoord
= Request
->Data
.ReadConsoleOutputRequest
.BufferCoord
;
2948 Length
= BufferSize
.X
* BufferSize
.Y
;
2949 Size
= Length
* sizeof(CHAR_INFO
);
2951 /* FIXME: Is this correct? */
2952 CodePage
= ProcessData
->Console
->OutputCodePage
;
2954 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
)
2955 || (((ULONG_PTR
)CharInfo
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2957 ConioUnlockScreenBuffer(Buff
);
2958 Request
->Status
= STATUS_ACCESS_VIOLATION
;
2959 return Request
->Status
;
2962 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&ReadRegion
));
2963 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&ReadRegion
));
2964 ReadRegion
.bottom
= ReadRegion
.top
+ SizeY
;
2965 ReadRegion
.right
= ReadRegion
.left
+ SizeX
;
2967 ConioInitRect(&ScreenRect
, 0, 0, Buff
->MaxY
, Buff
->MaxX
);
2968 if (! ConioGetIntersection(&ReadRegion
, &ScreenRect
, &ReadRegion
))
2970 ConioUnlockScreenBuffer(Buff
);
2971 Request
->Status
= STATUS_SUCCESS
;
2972 return Request
->Status
;
2975 for (i
= 0, Y
= ReadRegion
.top
; Y
< ReadRegion
.bottom
; ++i
, ++Y
)
2977 CurCharInfo
= CharInfo
+ (i
* BufferSize
.X
);
2979 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ ReadRegion
.left
) * 2;
2980 for (X
= ReadRegion
.left
; X
< ReadRegion
.right
; ++X
)
2982 if (Request
->Data
.ReadConsoleOutputRequest
.Unicode
)
2984 MultiByteToWideChar(CodePage
, 0,
2985 (PCHAR
)&GET_CELL_BUFFER(Buff
, Offset
), 1,
2986 &CurCharInfo
->Char
.UnicodeChar
, 1);
2990 CurCharInfo
->Char
.AsciiChar
= GET_CELL_BUFFER(Buff
, Offset
);
2992 CurCharInfo
->Attributes
= GET_CELL_BUFFER(Buff
, Offset
);
2997 ConioUnlockScreenBuffer(Buff
);
2999 Request
->Status
= STATUS_SUCCESS
;
3000 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
= ReadRegion
.left
+ SizeX
- 1;
3001 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
= ReadRegion
.top
+ SizeY
- 1;
3002 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
= ReadRegion
.left
;
3003 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
= ReadRegion
.top
;
3005 return Request
->Status
;
3009 CSR_API(CsrWriteConsoleInput
)
3011 PINPUT_RECORD InputRecord
;
3012 PCSRSS_CONSOLE Console
;
3017 ConsoleInput
* Record
;
3019 DPRINT("CsrWriteConsoleInput\n");
3021 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3022 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3024 Status
= ConioLockConsole(ProcessData
, Request
->Data
.WriteConsoleInputRequest
.ConsoleHandle
, &Console
);
3025 if (! NT_SUCCESS(Status
))
3027 return Request
->Status
= Status
;
3030 InputRecord
= Request
->Data
.WriteConsoleInputRequest
.InputRecord
;
3031 Length
= Request
->Data
.WriteConsoleInputRequest
.Length
;
3032 Size
= Length
* sizeof(INPUT_RECORD
);
3034 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
3035 || (((ULONG_PTR
)InputRecord
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
3037 ConioUnlockConsole(Console
);
3038 Request
->Status
= STATUS_ACCESS_VIOLATION
;
3039 return Request
->Status
;
3042 for (i
= 0; i
< Length
; i
++)
3044 Record
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
3047 ConioUnlockConsole(Console
);
3048 Request
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
3049 return Request
->Status
;
3052 Record
->Echoed
= FALSE
;
3053 Record
->Fake
= FALSE
;
3054 //Record->InputEvent = *InputRecord++;
3055 memcpy(&Record
->InputEvent
, &InputRecord
[i
], sizeof(INPUT_RECORD
));
3056 if (KEY_EVENT
== Record
->InputEvent
.EventType
)
3058 /* FIXME - convert from unicode to ascii!! */
3059 ConioProcessChar(Console
, Record
);
3063 ConioUnlockConsole(Console
);
3065 Request
->Status
= STATUS_SUCCESS
;
3066 Request
->Data
.WriteConsoleInputRequest
.Length
= i
;
3068 return Request
->Status
;
3071 /**********************************************************************
3072 * HardwareStateProperty
3075 * Set/Get the value of the HardwareState and switch
3076 * between direct video buffer ouput and GDI windowed
3079 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
3080 * object. We use the same object to Request.
3082 * ConsoleHwState has the correct size to be compatible
3083 * with NT's, but values are not.
3085 static NTSTATUS FASTCALL
3086 SetConsoleHardwareState (PCSRSS_CONSOLE Console
, DWORD ConsoleHwState
)
3088 DPRINT1("Console Hardware State: %d\n", ConsoleHwState
);
3090 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED
== ConsoleHwState
)
3091 ||(CONSOLE_HARDWARE_STATE_DIRECT
== ConsoleHwState
))
3093 if (Console
->HardwareState
!= ConsoleHwState
)
3095 /* TODO: implement switching from full screen to windowed mode */
3096 /* TODO: or back; now simply store the hardware state */
3097 Console
->HardwareState
= ConsoleHwState
;
3100 return STATUS_SUCCESS
;
3103 return STATUS_INVALID_PARAMETER_3
; /* Client: (handle, set_get, [mode]) */
3106 CSR_API(CsrHardwareStateProperty
)
3108 PCSRSS_CONSOLE Console
;
3111 DPRINT("CsrHardwareStateProperty\n");
3113 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3114 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3116 Status
= ConioLockConsole(ProcessData
,
3117 Request
->Data
.ConsoleHardwareStateRequest
.ConsoleHandle
,
3119 if (! NT_SUCCESS(Status
))
3121 DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
3122 return Request
->Status
= Status
;
3125 switch (Request
->Data
.ConsoleHardwareStateRequest
.SetGet
)
3127 case CONSOLE_HARDWARE_STATE_GET
:
3128 Request
->Data
.ConsoleHardwareStateRequest
.State
= Console
->HardwareState
;
3131 case CONSOLE_HARDWARE_STATE_SET
:
3132 DPRINT("Setting console hardware state.\n");
3133 Request
->Status
= SetConsoleHardwareState(Console
, Request
->Data
.ConsoleHardwareStateRequest
.State
);
3137 Request
->Status
= STATUS_INVALID_PARAMETER_2
; /* Client: (handle, [set_get], mode) */
3141 ConioUnlockConsole(Console
);
3143 return Request
->Status
;
3146 CSR_API(CsrGetConsoleWindow
)
3148 PCSRSS_CONSOLE Console
;
3151 DPRINT("CsrGetConsoleWindow\n");
3153 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3154 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3156 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3157 if (! NT_SUCCESS(Status
))
3159 return Request
->Status
= Status
;
3162 Request
->Data
.GetConsoleWindowRequest
.WindowHandle
= Console
->hWindow
;
3163 ConioUnlockConsole(Console
);
3165 return Request
->Status
= STATUS_SUCCESS
;
3168 CSR_API(CsrSetConsoleIcon
)
3170 PCSRSS_CONSOLE Console
;
3173 DPRINT("CsrSetConsoleIcon\n");
3175 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3176 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3178 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3179 if (! NT_SUCCESS(Status
))
3181 return Request
->Status
= Status
;
3184 Console
->hWindowIcon
= Request
->Data
.SetConsoleIconRequest
.WindowIcon
;
3185 Request
->Status
= (ConioChangeIcon(Console
) ? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
3186 ConioUnlockConsole(Console
);
3188 return Request
->Status
;
3191 CSR_API(CsrGetConsoleCodePage
)
3193 PCSRSS_CONSOLE Console
;
3196 DPRINT("CsrGetConsoleCodePage\n");
3198 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3199 if (! NT_SUCCESS(Status
))
3201 return Request
->Status
= Status
;
3204 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3205 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3206 Request
->Data
.GetConsoleCodePage
.CodePage
= Console
->CodePage
;
3207 ConioUnlockConsole(Console
);
3208 return Request
->Status
= STATUS_SUCCESS
;
3211 CSR_API(CsrSetConsoleCodePage
)
3213 PCSRSS_CONSOLE Console
;
3216 DPRINT("CsrSetConsoleCodePage\n");
3218 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3219 if (! NT_SUCCESS(Status
))
3221 return Request
->Status
= Status
;
3224 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3225 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3226 if (IsValidCodePage(Request
->Data
.SetConsoleCodePage
.CodePage
))
3228 Console
->CodePage
= Request
->Data
.SetConsoleCodePage
.CodePage
;
3229 ConioUnlockConsole(Console
);
3230 return Request
->Status
= STATUS_SUCCESS
;
3232 ConioUnlockConsole(Console
);
3233 return Request
->Status
= STATUS_UNSUCCESSFUL
;
3236 CSR_API(CsrGetConsoleOutputCodePage
)
3238 PCSRSS_CONSOLE Console
;
3241 DPRINT("CsrGetConsoleOutputCodePage\n");
3243 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3244 if (! NT_SUCCESS(Status
))
3246 return Request
->Status
= Status
;
3249 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3250 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3251 Request
->Data
.GetConsoleOutputCodePage
.CodePage
= Console
->OutputCodePage
;
3252 ConioUnlockConsole(Console
);
3253 return Request
->Status
= STATUS_SUCCESS
;
3256 CSR_API(CsrSetConsoleOutputCodePage
)
3258 PCSRSS_CONSOLE Console
;
3261 DPRINT("CsrSetConsoleOutputCodePage\n");
3263 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3264 if (! NT_SUCCESS(Status
))
3266 return Request
->Status
= Status
;
3269 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3270 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3271 if (IsValidCodePage(Request
->Data
.SetConsoleOutputCodePage
.CodePage
))
3273 Console
->OutputCodePage
= Request
->Data
.SetConsoleOutputCodePage
.CodePage
;
3274 ConioUnlockConsole(Console
);
3275 return Request
->Status
= STATUS_SUCCESS
;
3277 ConioUnlockConsole(Console
);
3278 return Request
->Status
= STATUS_UNSUCCESSFUL
;
3281 CSR_API(CsrGetProcessList
)
3284 PCSRSS_CONSOLE Console
;
3285 PCSRSS_PROCESS_DATA current
;
3286 PLIST_ENTRY current_entry
;
3287 ULONG nItems
, nCopied
, Length
;
3290 DPRINT("CsrGetProcessList\n");
3292 Buffer
= Request
->Data
.GetProcessListRequest
.ProcessId
;
3293 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3294 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3296 nItems
= nCopied
= 0;
3297 Request
->Data
.GetProcessListRequest
.nProcessIdsCopied
= 0;
3298 Request
->Data
.GetProcessListRequest
.nProcessIdsTotal
= 0;
3300 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3301 if (! NT_SUCCESS(Status
))
3303 return Request
->Status
= Status
;
3306 DPRINT1("Console_Api Ctrl-C\n");
3308 for(current_entry
= Console
->ProcessList
.Flink
;
3309 current_entry
!= &Console
->ProcessList
;
3310 current_entry
= current_entry
->Flink
)
3312 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
3313 if(++nItems
< Request
->Data
.GetProcessListRequest
.nMaxIds
)
3315 *(Buffer
++) = current
->ProcessId
;
3320 ConioUnlockConsole(Console
);
3322 Request
->Data
.GetProcessListRequest
.nProcessIdsCopied
= nCopied
;
3323 Request
->Data
.GetProcessListRequest
.nProcessIdsTotal
= nItems
;
3325 Length
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_GET_PROCESS_LIST
) + nCopied
* sizeof(HANDLE
);
3326 if (Length
> sizeof(CSR_API_MESSAGE
))
3328 Request
->Header
.u1
.s1
.TotalLength
= Length
;
3329 Request
->Header
.u1
.s1
.DataLength
= Length
- sizeof(PORT_MESSAGE
);
3331 return Request
->Status
= STATUS_SUCCESS
;