2 * reactos/subsys/csrss/win32csr/conio.c
4 * Console I/O functions
6 * ReactOS Operating System
9 /* INCLUDES ******************************************************************/
16 /* GLOBALS *******************************************************************/
18 #define ConioInitRect(Rect, Top, Left, Bottom, Right) \
19 ((Rect)->top) = Top; \
20 ((Rect)->left) = Left; \
21 ((Rect)->bottom) = Bottom; \
22 ((Rect)->right) = Right
24 #define ConioIsRectEmpty(Rect) \
25 (((Rect)->left > (Rect)->right) || ((Rect)->top > (Rect)->bottom))
27 #define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
28 WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
30 #define ConsoleAnsiCharToUnicodeChar(Console, sWChar, dChar) \
31 MultiByteToWideChar((Console)->CodePage, 0, (dChar), 1, (sWChar), 1)
34 /* FUNCTIONS *****************************************************************/
36 static NTSTATUS FASTCALL
37 ConioConsoleFromProcessData(PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_CONSOLE
*Console
)
39 if (NULL
== ProcessData
->Console
)
42 return STATUS_SUCCESS
;
45 EnterCriticalSection(&(ProcessData
->Console
->Header
.Lock
));
46 *Console
= ProcessData
->Console
;
48 return STATUS_SUCCESS
;
52 ConioConsoleCtrlEventTimeout(DWORD Event
, PCSRSS_PROCESS_DATA ProcessData
, DWORD Timeout
)
56 DPRINT("ConioConsoleCtrlEvent Parent ProcessId = %x\n", ProcessData
->ProcessId
);
58 if (ProcessData
->CtrlDispatcher
)
61 Thread
= CreateRemoteThread(ProcessData
->Process
, NULL
, 0,
62 (LPTHREAD_START_ROUTINE
) ProcessData
->CtrlDispatcher
,
63 (PVOID
) Event
, 0, NULL
);
66 DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
69 WaitForSingleObject(Thread
, Timeout
);
75 ConioConsoleCtrlEvent(DWORD Event
, PCSRSS_PROCESS_DATA ProcessData
)
77 ConioConsoleCtrlEventTimeout(Event
, ProcessData
, INFINITE
);
80 #define GET_CELL_BUFFER(b,o)\
83 #define SET_CELL_BUFFER(b,o,c,a)\
84 (b)->Buffer[(o)++]=(c),\
85 (b)->Buffer[(o)++]=(a)
88 ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff
)
90 DWORD Offset
= 2 * (Buff
->CurrentY
* Buff
->MaxX
);
93 for (Pos
= 0; Pos
< Buff
->MaxX
; Pos
++)
95 /* Fill the cell: Offset is incremented by the macro */
96 SET_CELL_BUFFER(Buff
, Offset
, ' ', Buff
->DefaultAttrib
);
100 static NTSTATUS FASTCALL
101 CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console
,
102 PCSRSS_SCREEN_BUFFER Buffer
)
104 DPRINT("CsrInitConsoleScreenBuffer Size X %d Size Y %d\n", Buffer
->MaxX
, Buffer
->MaxY
);
106 Buffer
->Header
.Type
= CONIO_SCREEN_BUFFER_MAGIC
;
107 Buffer
->Header
.ReferenceCount
= 0;
110 Buffer
->Buffer
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, Buffer
->MaxX
* Buffer
->MaxY
* 2);
111 if (NULL
== Buffer
->Buffer
)
113 return STATUS_INSUFFICIENT_RESOURCES
;
115 InitializeCriticalSection(&Buffer
->Header
.Lock
);
116 ConioInitScreenBuffer(Console
, Buffer
);
117 /* initialize buffer to be empty with default attributes */
118 for (Buffer
->CurrentY
= 0 ; Buffer
->CurrentY
< Buffer
->MaxY
; Buffer
->CurrentY
++)
120 ClearLineBuffer(Buffer
);
122 Buffer
->Mode
= ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
;
123 Buffer
->CurrentX
= 0;
124 Buffer
->CurrentY
= 0;
126 return STATUS_SUCCESS
;
129 static NTSTATUS STDCALL
130 CsrInitConsole(PCSRSS_CONSOLE Console
)
133 SECURITY_ATTRIBUTES SecurityAttributes
;
134 PCSRSS_SCREEN_BUFFER NewBuffer
;
137 Console
->Title
.MaximumLength
= Console
->Title
.Length
= 0;
138 Console
->Title
.Buffer
= NULL
;
141 RtlCreateUnicodeString(&Console
->Title
, L
"Command Prompt");
143 Console
->Header
.ReferenceCount
= 0;
144 Console
->WaitingChars
= 0;
145 Console
->WaitingLines
= 0;
146 Console
->EchoCount
= 0;
147 Console
->Header
.Type
= CONIO_CONSOLE_MAGIC
;
148 Console
->Mode
= ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_PROCESSED_INPUT
| ENABLE_MOUSE_INPUT
;
149 Console
->EarlyReturn
= FALSE
;
150 Console
->ActiveBuffer
= NULL
;
151 InitializeListHead(&Console
->InputEvents
);
152 Console
->CodePage
= GetOEMCP();
153 Console
->OutputCodePage
= GetOEMCP();
155 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
156 SecurityAttributes
.lpSecurityDescriptor
= NULL
;
157 SecurityAttributes
.bInheritHandle
= TRUE
;
159 Console
->ActiveEvent
= CreateEventW(&SecurityAttributes
, TRUE
, FALSE
, NULL
);
160 if (NULL
== Console
->ActiveEvent
)
162 RtlFreeUnicodeString(&Console
->Title
);
163 return STATUS_UNSUCCESSFUL
;
165 Console
->PrivateData
= NULL
;
166 InitializeCriticalSection(&Console
->Header
.Lock
);
168 GuiMode
= DtbgIsDesktopVisible();
170 /* allocate console screen buffer */
171 NewBuffer
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
172 /* init screen buffer with defaults */
173 NewBuffer
->CursorInfo
.bVisible
= TRUE
;
174 NewBuffer
->CursorInfo
.dwSize
= 5;
175 /* make console active, and insert into console list */
176 Console
->ActiveBuffer
= (PCSRSS_SCREEN_BUFFER
) NewBuffer
;
177 /* add a reference count because the buffer is tied to the console */
178 InterlockedIncrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
);
179 if (NULL
== NewBuffer
)
181 RtlFreeUnicodeString(&Console
->Title
);
182 DeleteCriticalSection(&Console
->Header
.Lock
);
183 CloseHandle(Console
->ActiveEvent
);
184 return STATUS_INSUFFICIENT_RESOURCES
;
189 Status
= TuiInitConsole(Console
);
190 if (! NT_SUCCESS(Status
))
192 DPRINT1("Failed to open text-mode console, switching to gui-mode\n");
198 Status
= GuiInitConsole(Console
);
199 if (! NT_SUCCESS(Status
))
201 HeapFree(Win32CsrApiHeap
,0, NewBuffer
);
202 RtlFreeUnicodeString(&Console
->Title
);
203 DeleteCriticalSection(&Console
->Header
.Lock
);
204 CloseHandle(Console
->ActiveEvent
);
205 DPRINT1("GuiInitConsole: failed\n");
210 Status
= CsrInitConsoleScreenBuffer(Console
, NewBuffer
);
211 if (! NT_SUCCESS(Status
))
213 ConioCleanupConsole(Console
);
214 RtlFreeUnicodeString(&Console
->Title
);
215 DeleteCriticalSection(&Console
->Header
.Lock
);
216 CloseHandle(Console
->ActiveEvent
);
217 HeapFree(Win32CsrApiHeap
, 0, NewBuffer
);
218 DPRINT1("CsrInitConsoleScreenBuffer: failed\n");
223 /* copy buffer contents to screen */
224 ConioDrawConsole(Console
);
226 return STATUS_SUCCESS
;
230 CSR_API(CsrAllocConsole
)
232 PCSRSS_CONSOLE Console
;
233 NTSTATUS Status
= STATUS_SUCCESS
;
234 BOOLEAN NewConsole
= FALSE
;
236 DPRINT("CsrAllocConsole\n");
238 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
239 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
241 if (ProcessData
== NULL
)
243 DPRINT1("No process data\n");
244 return Request
->Status
= STATUS_INVALID_PARAMETER
;
247 if (ProcessData
->Console
)
249 DPRINT1("Process already has a console\n");
250 Request
->Status
= STATUS_INVALID_PARAMETER
;
251 return STATUS_INVALID_PARAMETER
;
255 Request
->Status
= STATUS_SUCCESS
;
257 /* If we don't need a console, then get out of here */
258 if (!Request
->Data
.AllocConsoleRequest
.ConsoleNeeded
)
260 DPRINT("No console needed\n");
261 return STATUS_SUCCESS
;
264 /* If we already have one, then don't create a new one... */
265 if (!Request
->Data
.AllocConsoleRequest
.Console
||
266 Request
->Data
.AllocConsoleRequest
.Console
!= ProcessData
->ParentConsole
)
268 /* Allocate a console structure */
270 Console
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_CONSOLE
));
273 DPRINT1("Not enough memory for console\n");
274 Request
->Status
= STATUS_NO_MEMORY
;
275 return STATUS_NO_MEMORY
;
277 /* initialize list head */
278 InitializeListHead(&Console
->ProcessList
);
279 /* insert process data required for GUI initialization */
280 InsertHeadList(&Console
->ProcessList
, &ProcessData
->ProcessEntry
);
281 /* Initialize the Console */
282 Request
->Status
= CsrInitConsole(Console
);
283 if (!NT_SUCCESS(Request
->Status
))
285 DPRINT1("Console init failed\n");
286 HeapFree(Win32CsrApiHeap
, 0, Console
);
287 return Request
->Status
;
292 /* Reuse our current console */
293 Console
= Request
->Data
.AllocConsoleRequest
.Console
;
296 /* Set the Process Console */
297 ProcessData
->Console
= Console
;
299 /* Return it to the caller */
300 Request
->Data
.AllocConsoleRequest
.Console
= Console
;
302 /* Add a reference count because the process is tied to the console */
303 Console
->Header
.ReferenceCount
++;
305 if (NewConsole
|| !ProcessData
->bInheritHandles
)
307 /* Insert the Objects */
308 Status
= Win32CsrInsertObject(ProcessData
,
309 &Request
->Data
.AllocConsoleRequest
.InputHandle
,
311 if (! NT_SUCCESS(Status
))
313 DPRINT1("Failed to insert object\n");
314 ConioDeleteConsole((Object_t
*) Console
);
315 ProcessData
->Console
= 0;
316 return Request
->Status
= Status
;
319 Status
= Win32CsrInsertObject(ProcessData
,
320 &Request
->Data
.AllocConsoleRequest
.OutputHandle
,
321 &Console
->ActiveBuffer
->Header
);
322 if (!NT_SUCCESS(Status
))
324 DPRINT1("Failed to insert object\n");
325 ConioDeleteConsole((Object_t
*) Console
);
326 Win32CsrReleaseObject(ProcessData
,
327 Request
->Data
.AllocConsoleRequest
.InputHandle
);
328 ProcessData
->Console
= 0;
329 return Request
->Status
= Status
;
333 /* Duplicate the Event */
334 if (!DuplicateHandle(GetCurrentProcess(),
335 ProcessData
->Console
->ActiveEvent
,
336 ProcessData
->Process
,
337 &ProcessData
->ConsoleEvent
,
342 DPRINT1("DuplicateHandle() failed: %d\n", GetLastError
);
343 ConioDeleteConsole((Object_t
*) Console
);
344 if (NewConsole
|| !ProcessData
->bInheritHandles
)
346 Win32CsrReleaseObject(ProcessData
,
347 Request
->Data
.AllocConsoleRequest
.OutputHandle
);
348 Win32CsrReleaseObject(ProcessData
,
349 Request
->Data
.AllocConsoleRequest
.InputHandle
);
351 ProcessData
->Console
= 0;
352 return Request
->Status
= Status
;
355 /* Set the Ctrl Dispatcher */
356 ProcessData
->CtrlDispatcher
= Request
->Data
.AllocConsoleRequest
.CtrlDispatcher
;
357 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
361 /* Insert into the list if it has not been added */
362 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ProcessEntry
);
365 return STATUS_SUCCESS
;
368 CSR_API(CsrFreeConsole
)
370 PCSRSS_CONSOLE Console
;
373 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
374 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
376 if (ProcessData
== NULL
|| ProcessData
->Console
== NULL
)
378 return Request
->Status
= STATUS_INVALID_PARAMETER
;
381 Console
= ProcessData
->Console
;
382 ProcessData
->Console
= NULL
;
383 if (0 == InterlockedDecrement(&Console
->Header
.ReferenceCount
))
385 ConioDeleteConsole((Object_t
*) Console
);
387 return STATUS_SUCCESS
;
391 ConioNextLine(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, UINT
*ScrolledLines
)
393 /* slide the viewable screen */
394 if (((Buff
->CurrentY
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
) == (ULONG
)Buff
->MaxY
- 1)
396 if (++Buff
->ShowY
== Buff
->MaxY
)
402 if (++Buff
->CurrentY
== Buff
->MaxY
)
406 ClearLineBuffer(Buff
);
407 UpdateRect
->left
= 0;
408 UpdateRect
->right
= Buff
->MaxX
- 1;
409 if (UpdateRect
->top
== (LONG
)Buff
->CurrentY
)
411 if (++UpdateRect
->top
== Buff
->MaxY
)
416 UpdateRect
->bottom
= Buff
->CurrentY
;
419 static NTSTATUS FASTCALL
420 ConioWriteConsole(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
,
421 CHAR
*Buffer
, DWORD Length
, BOOL Attrib
)
426 LONG CursorStartX
, CursorStartY
;
429 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &CursorStartX
, &CursorStartY
);
430 UpdateRect
.left
= Buff
->MaxX
;
431 UpdateRect
.top
= Buff
->CurrentY
;
432 UpdateRect
.right
= -1;
433 UpdateRect
.bottom
= Buff
->CurrentY
;
436 for (i
= 0; i
< Length
; i
++)
438 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
441 if (Buffer
[i
] == '\n')
444 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
448 else if (Buffer
[i
] == '\b')
450 /* Only handle BS if we're not on the first pos of the first line */
451 if (0 != Buff
->CurrentX
|| Buff
->ShowY
!= Buff
->CurrentY
)
453 if (0 == Buff
->CurrentX
)
455 /* slide virtual position up */
456 Buff
->CurrentX
= Buff
->MaxX
- 1;
457 if (0 == Buff
->CurrentY
)
459 Buff
->CurrentY
= Buff
->MaxY
;
465 if ((0 == UpdateRect
.top
&& UpdateRect
.bottom
< (LONG
)Buff
->CurrentY
)
466 || (0 != UpdateRect
.top
&& (LONG
)Buff
->CurrentY
< UpdateRect
.top
))
468 UpdateRect
.top
= Buff
->CurrentY
;
475 Offset
= 2 * ((Buff
->CurrentY
* Buff
->MaxX
) + Buff
->CurrentX
);
476 SET_CELL_BUFFER(Buff
, Offset
, ' ', Buff
->DefaultAttrib
);
477 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
) Buff
->CurrentX
);
478 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
483 else if (Buffer
[i
] == '\r')
486 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
) Buff
->CurrentX
);
487 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
491 else if (Buffer
[i
] == '\t')
495 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
)Buff
->CurrentX
);
496 EndX
= (Buff
->CurrentX
+ 8) & ~7;
497 if (EndX
> Buff
->MaxX
)
501 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
502 while (Buff
->CurrentX
< EndX
)
504 Buff
->Buffer
[Offset
] = ' ';
508 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
- 1);
509 if (Buff
->CurrentX
== Buff
->MaxX
)
511 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
514 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
524 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
)Buff
->CurrentX
);
525 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
526 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
527 Buff
->Buffer
[Offset
++] = Buffer
[i
];
530 Buff
->Buffer
[Offset
] = Buff
->DefaultAttrib
;
533 if (Buff
->CurrentX
== Buff
->MaxX
)
535 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
538 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
542 Buff
->CurrentX
= CursorStartX
;
547 ConioPhysicalToLogical(Buff
, UpdateRect
.left
, UpdateRect
.top
, &(UpdateRect
.left
),
549 ConioPhysicalToLogical(Buff
, UpdateRect
.right
, UpdateRect
.bottom
, &(UpdateRect
.right
),
550 &(UpdateRect
.bottom
));
551 if (! ConioIsRectEmpty(&UpdateRect
) && NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
553 ConioWriteStream(Console
, &UpdateRect
, CursorStartX
, CursorStartY
, ScrolledLines
,
557 return STATUS_SUCCESS
;
560 CSR_API(CsrReadConsole
)
562 PLIST_ENTRY CurrentEntry
;
565 PWCHAR UnicodeBuffer
;
567 ULONG nNumberOfCharsToRead
, CharSize
;
568 PCSRSS_CONSOLE Console
;
571 DPRINT("CsrReadConsole\n");
573 CharSize
= (Request
->Data
.ReadConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
575 /* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */
576 nNumberOfCharsToRead
= min(Request
->Data
.ReadConsoleRequest
.NrCharactersToRead
, CSRSS_MAX_READ_CONSOLE
/ CharSize
);
577 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
578 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
580 Buffer
= Request
->Data
.ReadConsoleRequest
.Buffer
;
581 UnicodeBuffer
= (PWCHAR
)Buffer
;
582 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadConsoleRequest
.ConsoleHandle
,
584 if (! NT_SUCCESS(Status
))
586 return Request
->Status
= Status
;
588 Request
->Data
.ReadConsoleRequest
.EventHandle
= ProcessData
->ConsoleEvent
;
589 for (i
= 0; i
< nNumberOfCharsToRead
&& Console
->InputEvents
.Flink
!= &Console
->InputEvents
; i
++)
591 /* remove input event from queue */
592 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
593 if (IsListEmpty(&Console
->InputEvents
))
596 ResetEvent(Console
->ActiveEvent
);
598 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
600 /* only pay attention to valid ascii chars, on key down */
601 if (KEY_EVENT
== Input
->InputEvent
.EventType
602 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
603 && Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
!= '\0')
606 * backspace handling - if we are in charge of echoing it then we handle it here
607 * otherwise we treat it like a normal char.
609 if ('\b' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
&& 0
610 != (Console
->Mode
& ENABLE_ECHO_INPUT
))
612 /* echo if it has not already been done, and either we or the client has chars to be deleted */
614 && (0 != i
|| Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
))
616 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
617 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
621 i
-= 2; /* if we already have something to return, just back it up by 2 */
624 { /* otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer */
625 Console
->WaitingChars
--;
626 ConioUnlockConsole(Console
);
627 HeapFree(Win32CsrApiHeap
, 0, Input
);
628 Request
->Data
.ReadConsoleRequest
.NrCharactersRead
= 0;
629 Request
->Status
= STATUS_NOTIFY_CLEANUP
;
630 return STATUS_NOTIFY_CLEANUP
;
633 Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
--;
634 Input
->Echoed
= TRUE
; /* mark as echoed so we don't echo it below */
636 /* do not copy backspace to buffer */
639 if(Request
->Data
.ReadConsoleRequest
.Unicode
)
640 UnicodeBuffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
; /* FIXME */
642 Buffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
;
644 /* echo to screen if enabled and we did not already echo the char */
645 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
)
647 && '\r' != Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
649 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
650 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
657 Console
->WaitingChars
--;
658 HeapFree(Win32CsrApiHeap
, 0, Input
);
660 Request
->Data
.ReadConsoleRequest
.NrCharactersRead
= i
;
663 Request
->Status
= STATUS_PENDING
; /* we didn't read anything */
665 else if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
))
667 if (0 == Console
->WaitingLines
||
668 (Request
->Data
.ReadConsoleRequest
.Unicode
? (L
'\n' != UnicodeBuffer
[i
- 1]) : ('\n' != Buffer
[i
- 1])))
670 Request
->Status
= STATUS_PENDING
; /* line buffered, didn't get a complete line */
674 Console
->WaitingLines
--;
675 Request
->Status
= STATUS_SUCCESS
; /* line buffered, did get a complete line */
680 Request
->Status
= STATUS_SUCCESS
; /* not line buffered, did read something */
683 if (Request
->Status
== STATUS_PENDING
)
685 Console
->EchoCount
= nNumberOfCharsToRead
- i
;
689 Console
->EchoCount
= 0; /* if the client is no longer waiting on input, do not echo */
692 ConioUnlockConsole(Console
);
694 if (CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE
) + i
* CharSize
> sizeof(CSR_API_MESSAGE
))
696 Request
->Header
.u1
.s1
.TotalLength
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE
) + i
* CharSize
;
697 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
700 return Request
->Status
;
704 ConioPhysicalToLogical(PCSRSS_SCREEN_BUFFER Buff
,
710 *LogicalX
= PhysicalX
;
711 if (PhysicalY
< Buff
->ShowY
)
713 *LogicalY
= Buff
->MaxY
- Buff
->ShowY
+ PhysicalY
;
717 *LogicalY
= PhysicalY
- Buff
->ShowY
;
721 BOOLEAN __inline
ConioIsEqualRect(
725 return ((Rect1
->left
== Rect2
->left
) && (Rect1
->right
== Rect2
->right
) &&
726 (Rect1
->top
== Rect2
->top
) && (Rect1
->bottom
== Rect2
->bottom
));
729 BOOLEAN __inline
ConioGetIntersection(
734 if (ConioIsRectEmpty(Rect1
) ||
735 (ConioIsRectEmpty(Rect2
)) ||
736 (Rect1
->top
> Rect2
->bottom
) ||
737 (Rect1
->left
> Rect2
->right
) ||
738 (Rect1
->bottom
< Rect2
->top
) ||
739 (Rect1
->right
< Rect2
->left
))
741 /* The rectangles do not intersect */
742 ConioInitRect(Intersection
, 0, -1, 0, -1);
746 ConioInitRect(Intersection
,
747 max(Rect1
->top
, Rect2
->top
),
748 max(Rect1
->left
, Rect2
->left
),
749 min(Rect1
->bottom
, Rect2
->bottom
),
750 min(Rect1
->right
, Rect2
->right
));
755 BOOLEAN __inline
ConioGetUnion(
760 if (ConioIsRectEmpty(Rect1
))
762 if (ConioIsRectEmpty(Rect2
))
764 ConioInitRect(Union
, 0, -1, 0, -1);
772 else if (ConioIsRectEmpty(Rect2
))
779 min(Rect1
->top
, Rect2
->top
),
780 min(Rect1
->left
, Rect2
->left
),
781 max(Rect1
->bottom
, Rect2
->bottom
),
782 max(Rect1
->right
, Rect2
->right
));
788 BOOLEAN __inline
ConioSubtractRect(
795 if (ConioIsRectEmpty(Rect1
))
797 ConioInitRect(Subtraction
, 0, -1, 0, -1);
800 *Subtraction
= *Rect1
;
801 if (ConioGetIntersection(&tmp
, Rect1
, Rect2
))
803 if (ConioIsEqualRect(&tmp
, Subtraction
))
805 ConioInitRect(Subtraction
, 0, -1, 0, -1);
808 if ((tmp
.top
== Subtraction
->top
) && (tmp
.bottom
== Subtraction
->bottom
))
810 if (tmp
.left
== Subtraction
->left
)
812 Subtraction
->left
= tmp
.right
;
814 else if (tmp
.right
== Subtraction
->right
)
816 Subtraction
->right
= tmp
.left
;
819 else if ((tmp
.left
== Subtraction
->left
) && (tmp
.right
== Subtraction
->right
))
821 if (tmp
.top
== Subtraction
->top
)
823 Subtraction
->top
= tmp
.bottom
;
825 else if (tmp
.bottom
== Subtraction
->bottom
)
827 Subtraction
->bottom
= tmp
.top
;
836 ConioCopyRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer
,
846 DstY
= DstRegion
->top
;
847 BytesPerLine
= ConioRectWidth(DstRegion
) * 2;
849 SrcY
= (SrcRegion
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
850 DstY
= (DstRegion
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
851 SrcOffset
= (SrcY
* ScreenBuffer
->MaxX
+ SrcRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
852 DstOffset
= (DstY
* ScreenBuffer
->MaxX
+ DstRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
854 for (i
= SrcRegion
->top
; i
<= SrcRegion
->bottom
; i
++)
857 &ScreenBuffer
->Buffer
[DstOffset
],
858 &ScreenBuffer
->Buffer
[SrcOffset
],
861 if (++DstY
== ScreenBuffer
->MaxY
)
864 DstOffset
= (DstRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
868 DstOffset
+= ScreenBuffer
->MaxX
* 2;
871 if (++SrcY
== ScreenBuffer
->MaxY
)
874 SrcOffset
= (SrcRegion
->left
+ ScreenBuffer
->ShowX
) * 2;
878 SrcOffset
+= ScreenBuffer
->MaxX
* 2;
884 ConioFillRegion(PCSRSS_CONSOLE Console
,
885 PCSRSS_SCREEN_BUFFER ScreenBuffer
,
897 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &CharInfo
->Char
.UnicodeChar
);
899 Char
= CharInfo
->Char
.AsciiChar
;
901 Y
= (Region
->top
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
;
902 Offset
= (Y
* ScreenBuffer
->MaxX
+ Region
->left
+ ScreenBuffer
->ShowX
) * 2;
903 Delta
= (ScreenBuffer
->MaxX
- ConioRectWidth(Region
)) * 2;
905 for (i
= Region
->top
; i
<= Region
->bottom
; i
++)
907 for (X
= Region
->left
; X
<= Region
->right
; X
++)
909 SET_CELL_BUFFER(ScreenBuffer
, Offset
, Char
, CharInfo
->Attributes
);
911 if (++Y
== ScreenBuffer
->MaxY
)
914 Offset
= (Region
->left
+ ScreenBuffer
->ShowX
) * 2;
924 ConioInputEventToAnsi(PCSRSS_CONSOLE Console
, PINPUT_RECORD InputEvent
)
926 if (InputEvent
->EventType
== KEY_EVENT
)
928 WCHAR UnicodeChar
= InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
;
929 InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
= 0;
930 ConsoleUnicodeCharToAnsiChar(Console
,
931 &InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
,
936 CSR_API(CsrWriteConsole
)
940 PCSRSS_SCREEN_BUFFER Buff
;
941 PCSRSS_CONSOLE Console
;
944 ULONG CharSize
= (Request
->Data
.WriteConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
946 DPRINT("CsrWriteConsole\n");
948 if (Request
->Header
.u1
.s1
.TotalLength
949 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE
)
950 + (Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
* CharSize
))
952 DPRINT1("Invalid request size\n");
953 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
954 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
955 return Request
->Status
= STATUS_INVALID_PARAMETER
;
957 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
959 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
960 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
962 if (! NT_SUCCESS(Status
))
964 return Request
->Status
= Status
;
967 if(Request
->Data
.WriteConsoleRequest
.Unicode
)
969 Length
= WideCharToMultiByte(Console
->CodePage
, 0,
970 (PWCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
,
971 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
,
972 NULL
, 0, NULL
, NULL
);
973 Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
976 WideCharToMultiByte(Console
->CodePage
, 0,
977 (PWCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
,
978 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
,
979 Buffer
, Length
, NULL
, NULL
);
983 Status
= STATUS_NO_MEMORY
;
988 Buffer
= (PCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
;
993 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.WriteConsoleRequest
.ConsoleHandle
, &Buff
);
994 if (NT_SUCCESS(Status
))
996 Request
->Status
= ConioWriteConsole(Console
, Buff
, Buffer
,
997 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
, TRUE
);
998 if (NT_SUCCESS(Status
))
1000 Written
= Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
;
1002 ConioUnlockScreenBuffer(Buff
);
1004 if (Request
->Data
.WriteConsoleRequest
.Unicode
)
1006 RtlFreeHeap(GetProcessHeap(), 0, Buffer
);
1009 if (NULL
!= Console
)
1011 ConioUnlockConsole(Console
);
1014 Request
->Data
.WriteConsoleRequest
.NrCharactersWritten
= Written
;
1016 return Request
->Status
= Status
;
1020 ConioDeleteScreenBuffer(Object_t
*Object
)
1022 PCSRSS_SCREEN_BUFFER Buffer
= (PCSRSS_SCREEN_BUFFER
) Object
;
1023 DeleteCriticalSection(&Buffer
->Header
.Lock
);
1024 HeapFree(Win32CsrApiHeap
, 0, Buffer
->Buffer
);
1025 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
1029 ConioDrawConsole(PCSRSS_CONSOLE Console
)
1033 ConioInitRect(&Region
, 0, 0, Console
->Size
.Y
- 1, Console
->Size
.X
- 1);
1035 ConioDrawRegion(Console
, &Region
);
1040 ConioDeleteConsole(Object_t
*Object
)
1042 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Object
;
1043 ConsoleInput
*Event
;
1045 DPRINT("ConioDeleteConsole\n");
1047 /* Drain input event queue */
1048 while (Console
->InputEvents
.Flink
!= &Console
->InputEvents
)
1050 Event
= (ConsoleInput
*) Console
->InputEvents
.Flink
;
1051 Console
->InputEvents
.Flink
= Console
->InputEvents
.Flink
->Flink
;
1052 Console
->InputEvents
.Flink
->Flink
->Blink
= &Console
->InputEvents
;
1053 HeapFree(Win32CsrApiHeap
, 0, Event
);
1056 if (0 == InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
1058 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
1061 Console
->ActiveBuffer
= NULL
;
1062 ConioCleanupConsole(Console
);
1064 CloseHandle(Console
->ActiveEvent
);
1065 DeleteCriticalSection(&Console
->Header
.Lock
);
1066 RtlFreeUnicodeString(&Console
->Title
);
1067 HeapFree(Win32CsrApiHeap
, 0, Console
);
1071 CsrInitConsoleSupport(VOID
)
1073 DPRINT("CSR: CsrInitConsoleSupport()\n");
1075 /* Should call LoadKeyboardLayout */
1078 static VOID FASTCALL
1079 ConioProcessChar(PCSRSS_CONSOLE Console
,
1080 ConsoleInput
*KeyEventRecord
)
1083 BOOL bClientWake
= FALSE
;
1084 ConsoleInput
*TempInput
;
1086 /* process Ctrl-C and Ctrl-Break */
1087 if (Console
->Mode
& ENABLE_PROCESSED_INPUT
&&
1088 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
&&
1089 ((KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== VK_PAUSE
) ||
1090 (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== 'C')) &&
1091 (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
)))
1093 PCSRSS_PROCESS_DATA current
;
1094 PLIST_ENTRY current_entry
;
1095 DPRINT1("Console_Api Ctrl-C\n");
1096 current_entry
= Console
->ProcessList
.Flink
;
1097 while (current_entry
!= &Console
->ProcessList
)
1099 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
1100 current_entry
= current_entry
->Flink
;
1101 ConioConsoleCtrlEvent((DWORD
)CTRL_C_EVENT
, current
);
1103 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1107 if (0 != (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
1108 & (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1109 && (VK_UP
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
1110 || VK_DOWN
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
))
1112 if (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1114 /* scroll up or down */
1115 if (NULL
== Console
)
1117 DPRINT1("No Active Console!\n");
1118 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1121 if (VK_UP
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
)
1123 /* only scroll up if there is room to scroll up into */
1124 if (Console
->ActiveBuffer
->ShowY
!= ((Console
->ActiveBuffer
->CurrentY
+ 1) %
1125 Console
->ActiveBuffer
->MaxY
))
1127 Console
->ActiveBuffer
->ShowY
= (Console
->ActiveBuffer
->ShowY
+
1128 Console
->ActiveBuffer
->MaxY
- 1) %
1129 Console
->ActiveBuffer
->MaxY
;
1132 else if (Console
->ActiveBuffer
->ShowY
!= Console
->ActiveBuffer
->CurrentY
)
1133 /* only scroll down if there is room to scroll down into */
1135 if (Console
->ActiveBuffer
->ShowY
% Console
->ActiveBuffer
->MaxY
!=
1136 Console
->ActiveBuffer
->CurrentY
)
1138 if (((Console
->ActiveBuffer
->CurrentY
+ 1) % Console
->ActiveBuffer
->MaxY
) !=
1139 (Console
->ActiveBuffer
->ShowY
+ Console
->ActiveBuffer
->MaxY
) %
1140 Console
->ActiveBuffer
->MaxY
)
1142 Console
->ActiveBuffer
->ShowY
= (Console
->ActiveBuffer
->ShowY
+ 1) %
1143 Console
->ActiveBuffer
->MaxY
;
1147 ConioDrawConsole(Console
);
1149 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1152 if (NULL
== Console
)
1154 DPRINT1("No Active Console!\n");
1155 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1159 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
)))
1161 switch(KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1164 /* first add the \r */
1165 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1166 updown
= KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
;
1167 KeyEventRecord
->Echoed
= FALSE
;
1168 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= VK_RETURN
;
1169 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\r';
1170 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1171 Console
->WaitingChars
++;
1172 KeyEventRecord
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1173 if (NULL
== KeyEventRecord
)
1175 DPRINT1("Failed to allocate KeyEventRecord\n");
1178 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1179 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
= updown
;
1180 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= 0;
1181 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualScanCode
= 0;
1182 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\n';
1183 KeyEventRecord
->Fake
= TRUE
;
1187 /* add event to the queue */
1188 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1189 Console
->WaitingChars
++;
1190 /* if line input mode is enabled, only wake the client on enter key down */
1191 if (0 == (Console
->Mode
& ENABLE_LINE_INPUT
)
1192 || Console
->EarlyReturn
1193 || ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1194 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
))
1196 if ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1198 Console
->WaitingLines
++;
1201 SetEvent(Console
->ActiveEvent
);
1203 KeyEventRecord
->Echoed
= FALSE
;
1204 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
))
1205 && '\b' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1206 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1208 /* walk the input queue looking for a char to backspace */
1209 for (TempInput
= (ConsoleInput
*) Console
->InputEvents
.Blink
;
1210 TempInput
!= (ConsoleInput
*) &Console
->InputEvents
1211 && (KEY_EVENT
== TempInput
->InputEvent
.EventType
1212 || ! TempInput
->InputEvent
.Event
.KeyEvent
.bKeyDown
1213 || '\b' == TempInput
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
);
1214 TempInput
= (ConsoleInput
*) TempInput
->ListEntry
.Blink
)
1218 /* if we found one, delete it, otherwise, wake the client */
1219 if (TempInput
!= (ConsoleInput
*) &Console
->InputEvents
)
1221 /* delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue */
1222 RemoveEntryList(&TempInput
->ListEntry
);
1223 if (TempInput
->Echoed
)
1225 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1226 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1229 HeapFree(Win32CsrApiHeap
, 0, TempInput
);
1230 RemoveEntryList(&KeyEventRecord
->ListEntry
);
1231 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1232 Console
->WaitingChars
-= 2;
1236 SetEvent(Console
->ActiveEvent
);
1241 /* echo chars if we are supposed to and client is waiting for some */
1242 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
) && Console
->EchoCount
1243 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1244 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
1245 && '\r' != KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1247 /* mark the char as already echoed */
1248 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1249 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1251 Console
->EchoCount
--;
1252 KeyEventRecord
->Echoed
= TRUE
;
1256 /* Console->WaitingChars++; */
1257 if (bClientWake
|| 0 == (Console
->Mode
& ENABLE_LINE_INPUT
))
1259 SetEvent(Console
->ActiveEvent
);
1263 static DWORD FASTCALL
1264 ConioGetShiftState(PBYTE KeyState
)
1268 if (KeyState
[VK_CAPITAL
] & 1)
1269 ssOut
|= CAPSLOCK_ON
;
1271 if (KeyState
[VK_NUMLOCK
] & 1)
1272 ssOut
|= NUMLOCK_ON
;
1274 if (KeyState
[VK_SCROLL
] & 1)
1275 ssOut
|= SCROLLLOCK_ON
;
1277 if (KeyState
[VK_SHIFT
] & 0x80)
1278 ssOut
|= SHIFT_PRESSED
;
1280 if (KeyState
[VK_LCONTROL
] & 0x80)
1281 ssOut
|= LEFT_CTRL_PRESSED
;
1282 if (KeyState
[VK_RCONTROL
] & 0x80)
1283 ssOut
|= RIGHT_CTRL_PRESSED
;
1285 if (KeyState
[VK_LMENU
] & 0x80)
1286 ssOut
|= LEFT_ALT_PRESSED
;
1287 if (KeyState
[VK_RMENU
] & 0x80)
1288 ssOut
|= RIGHT_ALT_PRESSED
;
1294 ConioProcessKey(MSG
*msg
, PCSRSS_CONSOLE Console
, BOOL TextMode
)
1296 static BYTE KeyState
[256] = { 0 };
1297 /* MSDN mentions that you should use the last virtual key code received
1298 * when putting a virtual key identity to a WM_CHAR message since multiple
1299 * or translated keys may be involved. */
1300 static UINT LastVirtualKey
= 0;
1302 ConsoleInput
*ConInRec
;
1306 UINT VirtualKeyCode
;
1307 UINT VirtualScanCode
;
1310 ULONG ResultSize
= 0;
1313 VirtualScanCode
= (msg
->lParam
>> 16) & 0xff;
1314 Down
= msg
->message
== WM_KEYDOWN
|| msg
->message
== WM_CHAR
||
1315 msg
->message
== WM_SYSKEYDOWN
|| msg
->message
== WM_SYSCHAR
;
1317 GetKeyboardState(KeyState
);
1318 ShiftState
= ConioGetShiftState(KeyState
);
1320 if (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
)
1322 VirtualKeyCode
= LastVirtualKey
;
1323 UnicodeChar
= msg
->wParam
;
1330 VirtualKeyCode
= msg
->wParam
;
1331 RetChars
= ToUnicodeEx(VirtualKeyCode
,
1338 UnicodeChar
= (1 == RetChars
? Chars
[0] : 0);
1341 if (0 == ResultSize
)
1346 er
.EventType
= KEY_EVENT
;
1347 er
.Event
.KeyEvent
.bKeyDown
= Down
;
1348 er
.Event
.KeyEvent
.wRepeatCount
= RepeatCount
;
1349 er
.Event
.KeyEvent
.uChar
.UnicodeChar
= UnicodeChar
;
1350 er
.Event
.KeyEvent
.dwControlKeyState
= ShiftState
;
1351 er
.Event
.KeyEvent
.wVirtualKeyCode
= VirtualKeyCode
;
1352 er
.Event
.KeyEvent
.wVirtualScanCode
= VirtualScanCode
;
1356 if (0 != (ShiftState
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1357 && VK_TAB
== VirtualKeyCode
)
1361 TuiSwapConsole(ShiftState
& SHIFT_PRESSED
? -1 : 1);
1366 else if (VK_MENU
== VirtualKeyCode
&& ! Down
)
1368 if (TuiSwapConsole(0))
1375 if (NULL
== Console
)
1380 ConInRec
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1382 if (NULL
== ConInRec
)
1387 ConInRec
->InputEvent
= er
;
1388 ConInRec
->Fake
= UnicodeChar
&&
1389 (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
&&
1390 msg
->message
!= WM_KEYUP
&& msg
->message
!= WM_SYSKEYUP
);
1391 ConInRec
->NotChar
= (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
);
1392 ConInRec
->Echoed
= FALSE
;
1393 if (ConInRec
->NotChar
)
1394 LastVirtualKey
= msg
->wParam
;
1396 DPRINT ("csrss: %s %s %s %s %02x %02x '%c' %04x\n",
1397 Down
? "down" : "up ",
1398 (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
) ?
1400 ConInRec
->Fake
? "fake" : "real",
1401 ConInRec
->NotChar
? "notc" : "char",
1404 (AsciiChar
>= ' ') ? AsciiChar
: '.',
1407 if (! ConInRec
->Fake
|| ! ConInRec
->NotChar
)
1409 /* FIXME - convert to ascii */
1410 ConioProcessChar(Console
, ConInRec
);
1414 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1418 CSR_API(CsrGetScreenBufferInfo
)
1421 PCSRSS_SCREEN_BUFFER Buff
;
1422 PCONSOLE_SCREEN_BUFFER_INFO pInfo
;
1424 DPRINT("CsrGetScreenBufferInfo\n");
1426 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1427 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1429 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ScreenBufferInfoRequest
.ConsoleHandle
, &Buff
);
1430 if (! NT_SUCCESS(Status
))
1432 return Request
->Status
= Status
;
1434 pInfo
= &Request
->Data
.ScreenBufferInfoRequest
.Info
;
1435 pInfo
->dwSize
.X
= Buff
->MaxX
;
1436 pInfo
->dwSize
.Y
= Buff
->MaxY
;
1437 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1438 pInfo
->dwCursorPosition
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1439 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
1440 pInfo
->srWindow
.Left
= 0;
1441 pInfo
->srWindow
.Right
= Buff
->MaxX
- 1;
1442 pInfo
->srWindow
.Top
= 0;
1443 pInfo
->srWindow
.Bottom
= Buff
->MaxY
- 1;
1444 pInfo
->dwMaximumWindowSize
.X
= Buff
->MaxX
;
1445 pInfo
->dwMaximumWindowSize
.Y
= Buff
->MaxY
;
1446 ConioUnlockScreenBuffer(Buff
);
1448 Request
->Status
= STATUS_SUCCESS
;
1450 return Request
->Status
;
1453 CSR_API(CsrSetCursor
)
1456 PCSRSS_CONSOLE Console
;
1457 PCSRSS_SCREEN_BUFFER Buff
;
1458 LONG OldCursorX
, OldCursorY
;
1459 LONG NewCursorX
, NewCursorY
;
1461 DPRINT("CsrSetCursor\n");
1463 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1464 if (! NT_SUCCESS(Status
))
1466 return Request
->Status
= Status
;
1469 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1470 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1472 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
);
1473 if (! NT_SUCCESS(Status
))
1475 if (NULL
!= Console
)
1477 ConioUnlockConsole(Console
);
1479 return Request
->Status
= Status
;
1482 NewCursorX
= Request
->Data
.SetCursorRequest
.Position
.X
;
1483 NewCursorY
= Request
->Data
.SetCursorRequest
.Position
.Y
;
1484 if (NewCursorX
< 0 || NewCursorX
>= Buff
->MaxX
||
1485 NewCursorY
< 0 || NewCursorY
>= Buff
->MaxY
)
1487 ConioUnlockScreenBuffer(Buff
);
1488 if (NULL
!= Console
)
1490 ConioUnlockConsole(Console
);
1492 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1494 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &OldCursorX
, &OldCursorY
);
1495 Buff
->CurrentX
= NewCursorX
+ Buff
->ShowX
;
1496 Buff
->CurrentY
= (NewCursorY
+ Buff
->ShowY
) % Buff
->MaxY
;
1497 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1499 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
1501 ConioUnlockScreenBuffer(Buff
);
1502 if (NULL
!= Console
)
1504 ConioUnlockConsole(Console
);
1506 return Request
->Status
= STATUS_UNSUCCESSFUL
;
1510 ConioUnlockScreenBuffer(Buff
);
1511 if (NULL
!= Console
)
1513 ConioUnlockConsole(Console
);
1516 return Request
->Status
= STATUS_SUCCESS
;
1519 static VOID FASTCALL
1520 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, COORD
*Start
, UINT Length
)
1522 if (Buff
->MaxX
<= Start
->X
+ Length
)
1524 UpdateRect
->left
= 0;
1528 UpdateRect
->left
= Start
->X
;
1530 if (Buff
->MaxX
<= Start
->X
+ Length
)
1532 UpdateRect
->right
= Buff
->MaxX
- 1;
1536 UpdateRect
->right
= Start
->X
+ Length
- 1;
1538 UpdateRect
->top
= Start
->Y
;
1539 UpdateRect
->bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->MaxX
;
1540 if (Buff
->MaxY
<= UpdateRect
->bottom
)
1542 UpdateRect
->bottom
= Buff
->MaxY
- 1;
1546 CSR_API(CsrWriteConsoleOutputChar
)
1549 PCHAR String
, tmpString
= NULL
;
1551 PCSRSS_CONSOLE Console
;
1552 PCSRSS_SCREEN_BUFFER Buff
;
1553 DWORD X
, Y
, Length
, CharSize
, Written
= 0;
1556 DPRINT("CsrWriteConsoleOutputChar\n");
1558 CharSize
= (Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
1560 if (Request
->Header
.u1
.s1
.TotalLength
1561 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR
)
1562 + (Request
->Data
.WriteConsoleOutputCharRequest
.Length
* CharSize
))
1564 DPRINT1("Invalid request size\n");
1565 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1566 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1567 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1570 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1571 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1572 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1573 if (NT_SUCCESS(Status
))
1575 if(Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
)
1577 Length
= WideCharToMultiByte(Console
->CodePage
, 0,
1578 (PWCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
,
1579 Request
->Data
.WriteConsoleOutputCharRequest
.Length
,
1580 NULL
, 0, NULL
, NULL
);
1581 tmpString
= String
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
1584 WideCharToMultiByte(Console
->CodePage
, 0,
1585 (PWCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
,
1586 Request
->Data
.WriteConsoleOutputCharRequest
.Length
,
1587 String
, Length
, NULL
, NULL
);
1591 Status
= STATUS_NO_MEMORY
;
1596 String
= (PCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
;
1601 Status
= ConioLockScreenBuffer(ProcessData
,
1602 Request
->Data
.WriteConsoleOutputCharRequest
.ConsoleHandle
,
1604 if (NT_SUCCESS(Status
))
1606 X
= Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.X
+ Buff
->ShowX
;
1607 Y
= (Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1608 Length
= Request
->Data
.WriteConsoleOutputCharRequest
.Length
;
1609 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1612 *Buffer
= *String
++;
1615 if (++X
== Buff
->MaxX
)
1617 if (++Y
== Buff
->MaxY
)
1620 Buffer
= Buff
->Buffer
;
1625 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1627 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputCharRequest
.Coord
,
1628 Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
1629 ConioDrawRegion(Console
, &UpdateRect
);
1632 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.X
= X
- Buff
->ShowX
;
1633 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1635 ConioUnlockScreenBuffer(Buff
);
1637 if (Request
->Data
.WriteConsoleRequest
.Unicode
)
1639 RtlFreeHeap(GetProcessHeap(), 0, tmpString
);
1642 if (NULL
!= Console
)
1644 ConioUnlockConsole(Console
);
1647 Request
->Data
.WriteConsoleOutputCharRequest
.NrCharactersWritten
= Written
;
1648 return Request
->Status
= Status
;
1651 CSR_API(CsrFillOutputChar
)
1654 PCSRSS_CONSOLE Console
;
1655 PCSRSS_SCREEN_BUFFER Buff
;
1656 DWORD X
, Y
, Length
, Written
= 0;
1661 DPRINT("CsrFillOutputChar\n");
1663 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1664 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1666 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1667 if (! NT_SUCCESS(Status
))
1669 return Request
->Status
= Status
;
1672 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputRequest
.ConsoleHandle
, &Buff
);
1673 if (! NT_SUCCESS(Status
))
1675 if (NULL
!= Console
)
1677 ConioUnlockConsole(Console
);
1679 return Request
->Status
= Status
;
1682 X
= Request
->Data
.FillOutputRequest
.Position
.X
+ Buff
->ShowX
;
1683 Y
= (Request
->Data
.FillOutputRequest
.Position
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1684 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1685 if(Request
->Data
.FillOutputRequest
.Unicode
)
1686 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &Request
->Data
.FillOutputRequest
.Char
.UnicodeChar
);
1688 Char
= Request
->Data
.FillOutputRequest
.Char
.AsciiChar
;
1689 Length
= Request
->Data
.FillOutputRequest
.Length
;
1695 if (++X
== Buff
->MaxX
)
1697 if (++Y
== Buff
->MaxY
)
1700 Buffer
= Buff
->Buffer
;
1706 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1708 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputRequest
.Position
,
1709 Request
->Data
.FillOutputRequest
.Length
);
1710 ConioDrawRegion(Console
, &UpdateRect
);
1713 ConioUnlockScreenBuffer(Buff
);
1714 if (NULL
!= Console
)
1716 ConioUnlockConsole(Console
);
1718 Length
= Request
->Data
.FillOutputRequest
.Length
;
1719 Request
->Data
.FillOutputRequest
.NrCharactersWritten
= Length
;
1720 return Request
->Status
;
1723 CSR_API(CsrReadInputEvent
)
1725 PLIST_ENTRY CurrentEntry
;
1726 PCSRSS_CONSOLE Console
;
1728 BOOLEAN Done
= FALSE
;
1729 ConsoleInput
*Input
;
1731 DPRINT("CsrReadInputEvent\n");
1733 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1734 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1735 Request
->Data
.ReadInputRequest
.Event
= ProcessData
->ConsoleEvent
;
1737 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadInputRequest
.ConsoleHandle
, &Console
);
1738 if (! NT_SUCCESS(Status
))
1740 return Request
->Status
= Status
;
1743 /* only get input if there is any */
1744 CurrentEntry
= Console
->InputEvents
.Flink
;
1745 while (CurrentEntry
!= &Console
->InputEvents
)
1747 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
1748 CurrentEntry
= CurrentEntry
->Flink
;
1750 if (Done
&& !Input
->Fake
)
1752 Request
->Data
.ReadInputRequest
.MoreEvents
= TRUE
;
1756 RemoveEntryList(&Input
->ListEntry
);
1758 if (!Done
&& !Input
->Fake
)
1760 Request
->Data
.ReadInputRequest
.Input
= Input
->InputEvent
;
1761 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
1763 ConioInputEventToAnsi(Console
, &Request
->Data
.ReadInputRequest
.Input
);
1768 if (Input
->InputEvent
.EventType
== KEY_EVENT
)
1770 if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
)
1771 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
1772 && '\r' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1774 Console
->WaitingLines
--;
1776 Console
->WaitingChars
--;
1778 HeapFree(Win32CsrApiHeap
, 0, Input
);
1783 Status
= STATUS_SUCCESS
;
1784 Console
->EarlyReturn
= FALSE
;
1788 Status
= STATUS_PENDING
;
1789 Console
->EarlyReturn
= TRUE
; /* mark for early return */
1792 if (IsListEmpty(&Console
->InputEvents
))
1794 ResetEvent(Console
->ActiveEvent
);
1797 ConioUnlockConsole(Console
);
1799 return Request
->Status
= Status
;
1802 CSR_API(CsrWriteConsoleOutputAttrib
)
1804 PCSRSS_CONSOLE Console
;
1805 PCSRSS_SCREEN_BUFFER Buff
;
1812 DPRINT("CsrWriteConsoleOutputAttrib\n");
1814 if (Request
->Header
.u1
.s1
.TotalLength
1815 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB
)
1816 + Request
->Data
.WriteConsoleOutputAttribRequest
.Length
* sizeof(WORD
))
1818 DPRINT1("Invalid request size\n");
1819 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1820 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1821 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1824 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1825 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1826 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1827 if (! NT_SUCCESS(Status
))
1829 return Request
->Status
= Status
;
1832 Status
= ConioLockScreenBuffer(ProcessData
,
1833 Request
->Data
.WriteConsoleOutputAttribRequest
.ConsoleHandle
,
1835 if (! NT_SUCCESS(Status
))
1837 if (NULL
!= Console
)
1839 ConioUnlockConsole(Console
);
1841 return Request
->Status
= Status
;
1844 X
= Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1845 Y
= (Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1846 Length
= Request
->Data
.WriteConsoleOutputAttribRequest
.Length
;
1847 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + 1];
1848 Attribute
= Request
->Data
.WriteConsoleOutputAttribRequest
.Attribute
;
1851 *Buffer
= (UCHAR
)(*Attribute
++);
1853 if (++X
== Buff
->MaxX
)
1855 if (++Y
== Buff
->MaxY
)
1858 Buffer
= Buff
->Buffer
+ 1;
1864 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1866 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
,
1867 Request
->Data
.WriteConsoleOutputAttribRequest
.Length
);
1868 ConioDrawRegion(Console
, &UpdateRect
);
1871 if (NULL
!= Console
)
1873 ConioUnlockConsole(Console
);
1876 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1877 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1879 ConioUnlockScreenBuffer(Buff
);
1881 return Request
->Status
= STATUS_SUCCESS
;
1884 CSR_API(CsrFillOutputAttrib
)
1886 PCSRSS_SCREEN_BUFFER Buff
;
1892 PCSRSS_CONSOLE Console
;
1894 DPRINT("CsrFillOutputAttrib\n");
1896 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1897 if (! NT_SUCCESS(Status
))
1899 return Request
->Status
= Status
;
1902 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1903 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1904 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputAttribRequest
.ConsoleHandle
, &Buff
);
1905 if (! NT_SUCCESS(Status
))
1907 if (NULL
!= Console
)
1909 ConioUnlockConsole(Console
);
1911 return Request
->Status
= Status
;
1914 X
= Request
->Data
.FillOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1915 Y
= (Request
->Data
.FillOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1916 Length
= Request
->Data
.FillOutputAttribRequest
.Length
;
1917 Attr
= Request
->Data
.FillOutputAttribRequest
.Attribute
;
1918 Buffer
= &Buff
->Buffer
[(Y
* Buff
->MaxX
* 2) + (X
* 2) + 1];
1923 if (++X
== Buff
->MaxX
)
1925 if (++Y
== Buff
->MaxY
)
1928 Buffer
= Buff
->Buffer
+ 1;
1934 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1936 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputAttribRequest
.Coord
,
1937 Request
->Data
.FillOutputAttribRequest
.Length
);
1938 ConioDrawRegion(Console
, &UpdateRect
);
1941 ConioUnlockScreenBuffer(Buff
);
1942 if (NULL
!= Console
)
1944 ConioUnlockConsole(Console
);
1947 return Request
->Status
= STATUS_SUCCESS
;
1951 CSR_API(CsrGetCursorInfo
)
1953 PCSRSS_SCREEN_BUFFER Buff
;
1956 DPRINT("CsrGetCursorInfo\n");
1958 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1959 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1961 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.GetCursorInfoRequest
.ConsoleHandle
, &Buff
);
1962 if (! NT_SUCCESS(Status
))
1964 return Request
->Status
= Status
;
1966 Request
->Data
.GetCursorInfoRequest
.Info
.bVisible
= Buff
->CursorInfo
.bVisible
;
1967 Request
->Data
.GetCursorInfoRequest
.Info
.dwSize
= Buff
->CursorInfo
.dwSize
;
1968 ConioUnlockScreenBuffer(Buff
);
1970 return Request
->Status
= STATUS_SUCCESS
;
1973 CSR_API(CsrSetCursorInfo
)
1975 PCSRSS_CONSOLE Console
;
1976 PCSRSS_SCREEN_BUFFER Buff
;
1981 DPRINT("CsrSetCursorInfo\n");
1983 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1984 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1986 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1987 if (! NT_SUCCESS(Status
))
1989 return Request
->Status
= Status
;
1992 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorInfoRequest
.ConsoleHandle
, &Buff
);
1993 if (! NT_SUCCESS(Status
))
1995 if (NULL
!= Console
)
1997 ConioUnlockConsole(Console
);
1999 return Request
->Status
= Status
;
2002 Size
= Request
->Data
.SetCursorInfoRequest
.Info
.dwSize
;
2003 Visible
= Request
->Data
.SetCursorInfoRequest
.Info
.bVisible
;
2013 if (Size
!= Buff
->CursorInfo
.dwSize
2014 || (Visible
&& ! Buff
->CursorInfo
.bVisible
) || (! Visible
&& Buff
->CursorInfo
.bVisible
))
2016 Buff
->CursorInfo
.dwSize
= Size
;
2017 Buff
->CursorInfo
.bVisible
= Visible
;
2019 if (NULL
!= Console
&& ! ConioSetCursorInfo(Console
, Buff
))
2021 ConioUnlockScreenBuffer(Buff
);
2022 ConioUnlockConsole(Console
);
2023 return Request
->Status
= STATUS_UNSUCCESSFUL
;
2027 ConioUnlockScreenBuffer(Buff
);
2028 if (NULL
!= Console
)
2030 ConioUnlockConsole(Console
);
2033 return Request
->Status
= STATUS_SUCCESS
;
2036 CSR_API(CsrSetTextAttrib
)
2039 PCSRSS_CONSOLE Console
;
2040 PCSRSS_SCREEN_BUFFER Buff
;
2041 LONG OldCursorX
, OldCursorY
;
2043 DPRINT("CsrSetTextAttrib\n");
2045 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2046 if (! NT_SUCCESS(Status
))
2048 return Request
->Status
= Status
;
2051 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
);
2052 if (! NT_SUCCESS(Status
))
2054 if (NULL
!= Console
)
2056 ConioUnlockConsole(Console
);
2058 return Request
->Status
= Status
;
2061 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &OldCursorX
, &OldCursorY
);
2063 Buff
->DefaultAttrib
= Request
->Data
.SetAttribRequest
.Attrib
;
2064 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
2066 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
2068 ConioUnlockScreenBuffer(Buff
);
2069 ConioUnlockConsole(Console
);
2070 return Request
->Status
= STATUS_UNSUCCESSFUL
;
2074 ConioUnlockScreenBuffer(Buff
);
2075 if (NULL
!= Console
)
2077 ConioUnlockConsole(Console
);
2080 return Request
->Status
= STATUS_SUCCESS
;
2083 CSR_API(CsrSetConsoleMode
)
2086 PCSRSS_CONSOLE Console
;
2087 PCSRSS_SCREEN_BUFFER Buff
;
2089 DPRINT("CsrSetConsoleMode\n");
2091 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2092 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2093 Status
= Win32CsrGetObject(ProcessData
,
2094 Request
->Data
.SetConsoleModeRequest
.ConsoleHandle
,
2095 (Object_t
**) &Console
);
2096 if (! NT_SUCCESS(Status
))
2098 return Request
->Status
= Status
;
2101 Buff
= (PCSRSS_SCREEN_BUFFER
)Console
;
2102 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
2104 Console
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_INPUT_MODE_VALID
;
2106 else if (CONIO_SCREEN_BUFFER_MAGIC
== Console
->Header
.Type
)
2108 Buff
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_OUTPUT_MODE_VALID
;
2112 return Request
->Status
= STATUS_INVALID_HANDLE
;
2115 Request
->Status
= STATUS_SUCCESS
;
2117 return Request
->Status
;
2120 CSR_API(CsrGetConsoleMode
)
2123 PCSRSS_CONSOLE Console
;
2124 PCSRSS_SCREEN_BUFFER Buff
; /* gee, I really wish I could use an anonymous union here */
2126 DPRINT("CsrGetConsoleMode\n");
2128 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2129 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2130 Status
= Win32CsrGetObject(ProcessData
, Request
->Data
.GetConsoleModeRequest
.ConsoleHandle
,
2131 (Object_t
**) &Console
);
2132 if (! NT_SUCCESS(Status
))
2134 return Request
->Status
= Status
;
2136 Request
->Status
= STATUS_SUCCESS
;
2137 Buff
= (PCSRSS_SCREEN_BUFFER
) Console
;
2138 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
2140 Request
->Data
.GetConsoleModeRequest
.ConsoleMode
= Console
->Mode
;
2142 else if (CONIO_SCREEN_BUFFER_MAGIC
== Buff
->Header
.Type
)
2144 Request
->Data
.GetConsoleModeRequest
.ConsoleMode
= Buff
->Mode
;
2148 Request
->Status
= STATUS_INVALID_HANDLE
;
2151 return Request
->Status
;
2154 CSR_API(CsrCreateScreenBuffer
)
2156 PCSRSS_CONSOLE Console
;
2157 PCSRSS_SCREEN_BUFFER Buff
;
2160 DPRINT("CsrCreateScreenBuffer\n");
2162 if (ProcessData
== NULL
)
2164 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2167 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2168 if (! NT_SUCCESS(Status
))
2170 return Request
->Status
= Status
;
2172 if (NULL
== Console
)
2174 return Request
->Status
= STATUS_INVALID_HANDLE
;
2177 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2178 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2180 Buff
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
2184 if (Console
->ActiveBuffer
)
2186 Buff
->MaxX
= Console
->ActiveBuffer
->MaxX
;
2187 Buff
->MaxY
= Console
->ActiveBuffer
->MaxY
;
2188 Buff
->CursorInfo
.bVisible
= Console
->ActiveBuffer
->CursorInfo
.bVisible
;
2189 Buff
->CursorInfo
.dwSize
= Console
->ActiveBuffer
->CursorInfo
.dwSize
;
2193 Buff
->CursorInfo
.bVisible
= TRUE
;
2194 Buff
->CursorInfo
.dwSize
= 5;
2197 if (Buff
->MaxX
== 0)
2202 if (Buff
->MaxY
== 0)
2207 Status
= CsrInitConsoleScreenBuffer(Console
, Buff
);
2208 if(! NT_SUCCESS(Status
))
2210 Request
->Status
= Status
;
2214 Request
->Status
= Win32CsrInsertObject(ProcessData
, &Request
->Data
.CreateScreenBufferRequest
.OutputHandle
, &Buff
->Header
);
2219 Request
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2222 ConioUnlockConsole(Console
);
2223 return Request
->Status
;
2226 CSR_API(CsrSetScreenBuffer
)
2229 PCSRSS_CONSOLE Console
;
2230 PCSRSS_SCREEN_BUFFER Buff
;
2232 DPRINT("CsrSetScreenBuffer\n");
2234 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2235 if (! NT_SUCCESS(Status
))
2237 return Request
->Status
= Status
;
2239 if (NULL
== Console
)
2241 DPRINT1("Trying to set screen buffer for app without console\n");
2242 return Request
->Status
= STATUS_INVALID_HANDLE
;
2245 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2246 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2248 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetScreenBufferRequest
.OutputHandle
, &Buff
);
2249 if (! NT_SUCCESS(Status
))
2251 ConioUnlockConsole(Console
);
2252 return Request
->Status
;
2255 if (Buff
== Console
->ActiveBuffer
)
2257 ConioUnlockScreenBuffer(Buff
);
2258 ConioUnlockConsole(Console
);
2259 return STATUS_SUCCESS
;
2262 /* drop reference to old buffer, maybe delete */
2263 if (! InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
2265 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
2267 /* tie console to new buffer */
2268 Console
->ActiveBuffer
= Buff
;
2269 /* inc ref count on new buffer */
2270 InterlockedIncrement(&Buff
->Header
.ReferenceCount
);
2271 /* Redraw the console */
2272 ConioDrawConsole(Console
);
2274 ConioUnlockScreenBuffer(Buff
);
2275 ConioUnlockConsole(Console
);
2277 return Request
->Status
= STATUS_SUCCESS
;
2280 CSR_API(CsrSetTitle
)
2283 PCSRSS_CONSOLE Console
;
2286 DPRINT("CsrSetTitle\n");
2288 if (Request
->Header
.u1
.s1
.TotalLength
2289 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_SET_TITLE
)
2290 + Request
->Data
.SetTitleRequest
.Length
)
2292 DPRINT1("Invalid request size\n");
2293 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2294 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2295 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2298 Status
= ConioLockConsole(ProcessData
, Request
->Data
.SetTitleRequest
.Console
, &Console
);
2299 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2300 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2301 if(! NT_SUCCESS(Status
))
2303 Request
->Status
= Status
;
2307 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, Request
->Data
.SetTitleRequest
.Length
);
2310 /* copy title to console */
2311 RtlFreeUnicodeString(&Console
->Title
);
2312 Console
->Title
.Buffer
= Buffer
;
2313 Console
->Title
.Length
= Console
->Title
.MaximumLength
= Request
->Data
.SetTitleRequest
.Length
;
2314 memcpy(Console
->Title
.Buffer
, Request
->Data
.SetTitleRequest
.Title
, Console
->Title
.Length
);
2315 if (! ConioChangeTitle(Console
))
2317 Request
->Status
= STATUS_UNSUCCESSFUL
;
2321 Request
->Status
= STATUS_SUCCESS
;
2326 Request
->Status
= STATUS_NO_MEMORY
;
2329 ConioUnlockConsole(Console
);
2331 return Request
->Status
;
2334 CSR_API(CsrGetTitle
)
2337 PCSRSS_CONSOLE Console
;
2340 DPRINT("CsrGetTitle\n");
2342 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2343 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2344 Status
= ConioLockConsole(ProcessData
,
2345 Request
->Data
.GetTitleRequest
.ConsoleHandle
,
2347 if (! NT_SUCCESS(Status
))
2349 DPRINT1("Can't get console\n");
2350 return Request
->Status
= Status
;
2353 /* Copy title of the console to the user title buffer */
2354 RtlZeroMemory(&Request
->Data
.GetTitleRequest
, sizeof(CSRSS_GET_TITLE
));
2355 Request
->Data
.GetTitleRequest
.ConsoleHandle
= Request
->Data
.GetTitleRequest
.ConsoleHandle
;
2356 Request
->Data
.GetTitleRequest
.Length
= Console
->Title
.Length
;
2357 memcpy (Request
->Data
.GetTitleRequest
.Title
, Console
->Title
.Buffer
,
2358 Console
->Title
.Length
);
2359 Length
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_SET_TITLE
) + Console
->Title
.Length
;
2361 ConioUnlockConsole(Console
);
2363 if (Length
> sizeof(CSR_API_MESSAGE
))
2365 Request
->Header
.u1
.s1
.TotalLength
= Length
;
2366 Request
->Header
.u1
.s1
.DataLength
= Length
- sizeof(PORT_MESSAGE
);
2368 Request
->Status
= STATUS_SUCCESS
;
2370 return Request
->Status
;
2373 CSR_API(CsrWriteConsoleOutput
)
2375 SHORT i
, X
, Y
, SizeX
, SizeY
;
2376 PCSRSS_CONSOLE Console
;
2377 PCSRSS_SCREEN_BUFFER Buff
;
2379 CHAR_INFO
* CurCharInfo
;
2381 CHAR_INFO
* CharInfo
;
2388 DPRINT("CsrWriteConsoleOutput\n");
2390 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2391 if (! NT_SUCCESS(Status
))
2393 return Request
->Status
= Status
;
2396 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2397 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2398 Status
= ConioLockScreenBuffer(ProcessData
,
2399 Request
->Data
.WriteConsoleOutputRequest
.ConsoleHandle
,
2401 if (! NT_SUCCESS(Status
))
2403 if (NULL
!= Console
)
2405 ConioUnlockConsole(Console
);
2407 return Request
->Status
= Status
;
2410 BufferSize
= Request
->Data
.WriteConsoleOutputRequest
.BufferSize
;
2411 PSize
= BufferSize
.X
* BufferSize
.Y
* sizeof(CHAR_INFO
);
2412 BufferCoord
= Request
->Data
.WriteConsoleOutputRequest
.BufferCoord
;
2413 CharInfo
= Request
->Data
.WriteConsoleOutputRequest
.CharInfo
;
2414 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
) ||
2415 (((ULONG_PTR
)CharInfo
+ PSize
) >
2416 ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2418 ConioUnlockScreenBuffer(Buff
);
2419 ConioUnlockConsole(Console
);
2420 return Request
->Status
= STATUS_ACCESS_VIOLATION
;
2422 WriteRegion
.left
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
;
2423 WriteRegion
.top
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
;
2424 WriteRegion
.right
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
;
2425 WriteRegion
.bottom
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
;
2427 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&WriteRegion
));
2428 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&WriteRegion
));
2429 WriteRegion
.bottom
= WriteRegion
.top
+ SizeY
- 1;
2430 WriteRegion
.right
= WriteRegion
.left
+ SizeX
- 1;
2432 /* Make sure WriteRegion is inside the screen buffer */
2433 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2434 if (! ConioGetIntersection(&WriteRegion
, &ScreenBuffer
, &WriteRegion
))
2436 ConioUnlockScreenBuffer(Buff
);
2437 ConioUnlockConsole(Console
);
2439 /* It is okay to have a WriteRegion completely outside the screen buffer.
2440 No data is written then. */
2441 return Request
->Status
= STATUS_SUCCESS
;
2444 for (i
= 0, Y
= WriteRegion
.top
; Y
<= WriteRegion
.bottom
; i
++, Y
++)
2446 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
2447 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ WriteRegion
.left
) * 2;
2448 for (X
= WriteRegion
.left
; X
<= WriteRegion
.right
; X
++)
2450 if (Request
->Data
.WriteConsoleOutputRequest
.Unicode
)
2453 ConsoleUnicodeCharToAnsiChar(Console
, &AsciiChar
, &CurCharInfo
->Char
.UnicodeChar
);
2454 SET_CELL_BUFFER(Buff
, Offset
, AsciiChar
, CurCharInfo
->Attributes
);
2458 SET_CELL_BUFFER(Buff
, Offset
, CurCharInfo
->Char
.AsciiChar
, CurCharInfo
->Attributes
);
2464 if (NULL
!= Console
)
2466 ConioDrawRegion(Console
, &WriteRegion
);
2469 ConioUnlockScreenBuffer(Buff
);
2470 ConioUnlockConsole(Console
);
2472 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
= WriteRegion
.left
+ SizeX
- 1;
2473 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
= WriteRegion
.top
+ SizeY
- 1;
2474 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
= WriteRegion
.left
;
2475 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
= WriteRegion
.top
;
2477 return Request
->Status
= STATUS_SUCCESS
;
2480 CSR_API(CsrFlushInputBuffer
)
2482 PLIST_ENTRY CurrentEntry
;
2483 PCSRSS_CONSOLE Console
;
2484 ConsoleInput
* Input
;
2487 DPRINT("CsrFlushInputBuffer\n");
2489 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2490 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2491 Status
= ConioLockConsole(ProcessData
,
2492 Request
->Data
.FlushInputBufferRequest
.ConsoleInput
,
2494 if(! NT_SUCCESS(Status
))
2496 return Request
->Status
= Status
;
2499 /* Discard all entries in the input event queue */
2500 while (!IsListEmpty(&Console
->InputEvents
))
2502 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
2503 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
2504 /* Destroy the event */
2505 HeapFree(Win32CsrApiHeap
, 0, Input
);
2507 ResetEvent(Console
->ActiveEvent
);
2508 Console
->WaitingChars
=0;
2510 ConioUnlockConsole(Console
);
2512 return Request
->Status
= STATUS_SUCCESS
;
2515 CSR_API(CsrScrollConsoleScreenBuffer
)
2517 PCSRSS_CONSOLE Console
;
2518 PCSRSS_SCREEN_BUFFER Buff
;
2523 RECT ScrollRectangle
;
2527 HANDLE ConsoleHandle
;
2528 BOOLEAN UseClipRectangle
;
2529 COORD DestinationOrigin
;
2532 DPRINT("CsrScrollConsoleScreenBuffer\n");
2534 ConsoleHandle
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ConsoleHandle
;
2535 UseClipRectangle
= Request
->Data
.ScrollConsoleScreenBufferRequest
.UseClipRectangle
;
2536 DestinationOrigin
= Request
->Data
.ScrollConsoleScreenBufferRequest
.DestinationOrigin
;
2537 Fill
= Request
->Data
.ScrollConsoleScreenBufferRequest
.Fill
;
2539 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2540 if (! NT_SUCCESS(Status
))
2542 return Request
->Status
= Status
;
2545 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2546 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2547 Status
= ConioLockScreenBuffer(ProcessData
, ConsoleHandle
, &Buff
);
2548 if (! NT_SUCCESS(Status
))
2550 if (NULL
!= Console
)
2552 ConioUnlockConsole(Console
);
2554 return Request
->Status
= Status
;
2557 ScrollRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Left
;
2558 ScrollRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Top
;
2559 ScrollRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Right
;
2560 ScrollRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Bottom
;
2561 ClipRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Left
;
2562 ClipRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Top
;
2563 ClipRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Right
;
2564 ClipRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Bottom
;
2566 /* Make sure source rectangle is inside the screen buffer */
2567 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2568 if (! ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, &ScrollRectangle
))
2570 ConioUnlockScreenBuffer(Buff
);
2571 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2574 if (UseClipRectangle
&& ! ConioGetIntersection(&SrcRegion
, &SrcRegion
, &ClipRectangle
))
2576 ConioUnlockScreenBuffer(Buff
);
2577 return Request
->Status
= STATUS_SUCCESS
;
2581 ConioInitRect(&DstRegion
,
2582 DestinationOrigin
.Y
,
2583 DestinationOrigin
.X
,
2584 DestinationOrigin
.Y
+ ConioRectHeight(&ScrollRectangle
) - 1,
2585 DestinationOrigin
.X
+ ConioRectWidth(&ScrollRectangle
) - 1);
2587 /* Make sure destination rectangle is inside the screen buffer */
2588 if (! ConioGetIntersection(&DstRegion
, &DstRegion
, &ScreenBuffer
))
2590 ConioUnlockScreenBuffer(Buff
);
2591 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2594 ConioCopyRegion(Buff
, &SrcRegion
, &DstRegion
);
2596 /* Get the region that should be filled with the specified character and attributes */
2600 ConioGetUnion(&FillRegion
, &SrcRegion
, &DstRegion
);
2602 if (ConioSubtractRect(&FillRegion
, &FillRegion
, &DstRegion
))
2604 /* FIXME: The subtracted rectangle is off by one line */
2605 FillRegion
.top
+= 1;
2607 ConioFillRegion(Console
, Buff
, &FillRegion
, &Fill
, Request
->Data
.ScrollConsoleScreenBufferRequest
.Unicode
);
2611 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
2613 /* Draw destination region */
2614 ConioDrawRegion(Console
, &DstRegion
);
2618 /* Draw filled region */
2619 ConioDrawRegion(Console
, &FillRegion
);
2623 ConioUnlockScreenBuffer(Buff
);
2624 if (NULL
!= Console
)
2626 ConioUnlockConsole(Console
);
2629 return Request
->Status
= STATUS_SUCCESS
;
2632 CSR_API(CsrReadConsoleOutputChar
)
2635 PCSRSS_CONSOLE Console
;
2636 PCSRSS_SCREEN_BUFFER Buff
;
2643 DPRINT("CsrReadConsoleOutputChar\n");
2645 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2646 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2647 ReadBuffer
= Request
->Data
.ReadConsoleOutputCharRequest
.String
;
2649 CharSize
= (Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
2651 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2652 if (! NT_SUCCESS(Status
))
2654 return Request
->Status
= Status
;
2657 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputCharRequest
.ConsoleHandle
, &Buff
);
2658 if (! NT_SUCCESS(Status
))
2660 return Request
->Status
= Status
;
2663 Xpos
= Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.X
+ Buff
->ShowX
;
2664 Ypos
= (Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
2666 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
; ++i
)
2668 Char
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
)];
2670 if(Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
)
2672 ConsoleAnsiCharToUnicodeChar(Console
, (WCHAR
*)ReadBuffer
, &Char
);
2673 ReadBuffer
+= sizeof(WCHAR
);
2676 *(ReadBuffer
++) = Char
;
2680 if (Xpos
== Buff
->MaxX
)
2685 if (Ypos
== Buff
->MaxY
)
2693 Request
->Status
= STATUS_SUCCESS
;
2694 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.X
= Xpos
- Buff
->ShowX
;
2695 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.Y
= (Ypos
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
;
2697 ConioUnlockScreenBuffer(Buff
);
2698 if (NULL
!= Console
)
2700 ConioUnlockConsole(Console
);
2703 Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
= (DWORD
)((ULONG_PTR
)ReadBuffer
- (ULONG_PTR
)Request
->Data
.ReadConsoleOutputCharRequest
.String
) / CharSize
;
2704 if (Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
* CharSize
+ CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR
) > sizeof(CSR_API_MESSAGE
))
2706 Request
->Header
.u1
.s1
.TotalLength
= Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
* CharSize
+ CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR
);
2707 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2710 return Request
->Status
;
2714 CSR_API(CsrReadConsoleOutputAttrib
)
2717 PCSRSS_SCREEN_BUFFER Buff
;
2721 DWORD CurrentLength
;
2723 DPRINT("CsrReadConsoleOutputAttrib\n");
2725 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2726 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2727 ReadBuffer
= Request
->Data
.ReadConsoleOutputAttribRequest
.Attribute
;
2729 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputAttribRequest
.ConsoleHandle
, &Buff
);
2730 if (! NT_SUCCESS(Status
))
2732 return Request
->Status
= Status
;
2735 Xpos
= Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.X
+ Buff
->ShowX
;
2736 Ypos
= (Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
2738 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
; ++i
)
2740 *ReadBuffer
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
) + 1];
2745 if (Xpos
== Buff
->MaxX
)
2750 if (Ypos
== Buff
->MaxY
)
2759 Request
->Status
= STATUS_SUCCESS
;
2760 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.X
= Xpos
- Buff
->ShowX
;
2761 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.Y
= (Ypos
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
;
2763 ConioUnlockScreenBuffer(Buff
);
2765 CurrentLength
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_ATTRIB
)
2766 + Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
* sizeof(WORD
);
2767 if (CurrentLength
> sizeof(CSR_API_MESSAGE
))
2769 Request
->Header
.u1
.s1
.TotalLength
= CurrentLength
;
2770 Request
->Header
.u1
.s1
.DataLength
= CurrentLength
- sizeof(PORT_MESSAGE
);
2773 return Request
->Status
;
2777 CSR_API(CsrGetNumberOfConsoleInputEvents
)
2780 PCSRSS_CONSOLE Console
;
2781 PLIST_ENTRY CurrentItem
;
2783 ConsoleInput
*Input
;
2785 DPRINT("CsrGetNumberOfConsoleInputEvents\n");
2787 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2788 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2790 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
);
2791 if (! NT_SUCCESS(Status
))
2793 return Request
->Status
= Status
;
2796 CurrentItem
= Console
->InputEvents
.Flink
;
2799 /* If there are any events ... */
2800 while (CurrentItem
!= &Console
->InputEvents
)
2802 Input
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2803 CurrentItem
= CurrentItem
->Flink
;
2810 ConioUnlockConsole(Console
);
2812 Request
->Status
= STATUS_SUCCESS
;
2813 Request
->Data
.GetNumInputEventsRequest
.NumInputEvents
= NumEvents
;
2815 return Request
->Status
;
2819 CSR_API(CsrPeekConsoleInput
)
2822 PCSRSS_CONSOLE Console
;
2825 PLIST_ENTRY CurrentItem
;
2826 PINPUT_RECORD InputRecord
;
2830 DPRINT("CsrPeekConsoleInput\n");
2832 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2833 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2835 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
);
2836 if(! NT_SUCCESS(Status
))
2838 return Request
->Status
= Status
;
2841 InputRecord
= Request
->Data
.PeekConsoleInputRequest
.InputRecord
;
2842 Length
= Request
->Data
.PeekConsoleInputRequest
.Length
;
2843 Size
= Length
* sizeof(INPUT_RECORD
);
2845 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2846 || (((ULONG_PTR
)InputRecord
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2848 ConioUnlockConsole(Console
);
2849 Request
->Status
= STATUS_ACCESS_VIOLATION
;
2850 return Request
->Status
;
2855 if (! IsListEmpty(&Console
->InputEvents
))
2857 CurrentItem
= Console
->InputEvents
.Flink
;
2859 while (CurrentItem
!= &Console
->InputEvents
&& NumItems
< Length
)
2861 Item
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2865 CurrentItem
= CurrentItem
->Flink
;
2870 *InputRecord
= Item
->InputEvent
;
2872 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
2874 ConioInputEventToAnsi(Console
, InputRecord
);
2878 CurrentItem
= CurrentItem
->Flink
;
2882 ConioUnlockConsole(Console
);
2884 Request
->Status
= STATUS_SUCCESS
;
2885 Request
->Data
.PeekConsoleInputRequest
.Length
= NumItems
;
2887 return Request
->Status
;
2891 CSR_API(CsrReadConsoleOutput
)
2893 PCHAR_INFO CharInfo
;
2894 PCHAR_INFO CurCharInfo
;
2895 PCSRSS_SCREEN_BUFFER Buff
;
2908 DPRINT("CsrReadConsoleOutput\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
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputRequest
.ConsoleHandle
, &Buff
);
2914 if (! NT_SUCCESS(Status
))
2916 return Request
->Status
= Status
;
2919 CharInfo
= Request
->Data
.ReadConsoleOutputRequest
.CharInfo
;
2920 ReadRegion
.left
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
;
2921 ReadRegion
.top
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
;
2922 ReadRegion
.right
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
;
2923 ReadRegion
.bottom
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
;
2924 BufferSize
= Request
->Data
.ReadConsoleOutputRequest
.BufferSize
;
2925 BufferCoord
= Request
->Data
.ReadConsoleOutputRequest
.BufferCoord
;
2926 Length
= BufferSize
.X
* BufferSize
.Y
;
2927 Size
= Length
* sizeof(CHAR_INFO
);
2929 /* FIXME: Is this correct? */
2930 CodePage
= ProcessData
->Console
->OutputCodePage
;
2932 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
)
2933 || (((ULONG_PTR
)CharInfo
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2935 ConioUnlockScreenBuffer(Buff
);
2936 Request
->Status
= STATUS_ACCESS_VIOLATION
;
2937 return Request
->Status
;
2940 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&ReadRegion
));
2941 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&ReadRegion
));
2942 ReadRegion
.bottom
= ReadRegion
.top
+ SizeY
;
2943 ReadRegion
.right
= ReadRegion
.left
+ SizeX
;
2945 ConioInitRect(&ScreenRect
, 0, 0, Buff
->MaxY
, Buff
->MaxX
);
2946 if (! ConioGetIntersection(&ReadRegion
, &ScreenRect
, &ReadRegion
))
2948 ConioUnlockScreenBuffer(Buff
);
2949 Request
->Status
= STATUS_SUCCESS
;
2950 return Request
->Status
;
2953 for (i
= 0, Y
= ReadRegion
.top
; Y
< ReadRegion
.bottom
; ++i
, ++Y
)
2955 CurCharInfo
= CharInfo
+ (i
* BufferSize
.X
);
2957 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ ReadRegion
.left
) * 2;
2958 for (X
= ReadRegion
.left
; X
< ReadRegion
.right
; ++X
)
2960 if (Request
->Data
.ReadConsoleOutputRequest
.Unicode
)
2962 MultiByteToWideChar(CodePage
, 0,
2963 (PCHAR
)&GET_CELL_BUFFER(Buff
, Offset
), 1,
2964 &CurCharInfo
->Char
.UnicodeChar
, 1);
2968 CurCharInfo
->Char
.AsciiChar
= GET_CELL_BUFFER(Buff
, Offset
);
2970 CurCharInfo
->Attributes
= GET_CELL_BUFFER(Buff
, Offset
);
2975 ConioUnlockScreenBuffer(Buff
);
2977 Request
->Status
= STATUS_SUCCESS
;
2978 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
= ReadRegion
.left
+ SizeX
- 1;
2979 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
= ReadRegion
.top
+ SizeY
- 1;
2980 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
= ReadRegion
.left
;
2981 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
= ReadRegion
.top
;
2983 return Request
->Status
;
2987 CSR_API(CsrWriteConsoleInput
)
2989 PINPUT_RECORD InputRecord
;
2990 PCSRSS_CONSOLE Console
;
2995 ConsoleInput
* Record
;
2997 DPRINT("CsrWriteConsoleInput\n");
2999 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3000 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3002 Status
= ConioLockConsole(ProcessData
, Request
->Data
.WriteConsoleInputRequest
.ConsoleHandle
, &Console
);
3003 if (! NT_SUCCESS(Status
))
3005 return Request
->Status
= Status
;
3008 InputRecord
= Request
->Data
.WriteConsoleInputRequest
.InputRecord
;
3009 Length
= Request
->Data
.WriteConsoleInputRequest
.Length
;
3010 Size
= Length
* sizeof(INPUT_RECORD
);
3012 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
3013 || (((ULONG_PTR
)InputRecord
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
3015 ConioUnlockConsole(Console
);
3016 Request
->Status
= STATUS_ACCESS_VIOLATION
;
3017 return Request
->Status
;
3020 for (i
= 0; i
< Length
; i
++)
3022 Record
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
3025 ConioUnlockConsole(Console
);
3026 Request
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
3027 return Request
->Status
;
3030 Record
->Echoed
= FALSE
;
3031 Record
->Fake
= FALSE
;
3032 //Record->InputEvent = *InputRecord++;
3033 memcpy(&Record
->InputEvent
, &InputRecord
[i
], sizeof(INPUT_RECORD
));
3034 if (KEY_EVENT
== Record
->InputEvent
.EventType
)
3036 /* FIXME - convert from unicode to ascii!! */
3037 ConioProcessChar(Console
, Record
);
3041 ConioUnlockConsole(Console
);
3043 Request
->Status
= STATUS_SUCCESS
;
3044 Request
->Data
.WriteConsoleInputRequest
.Length
= i
;
3046 return Request
->Status
;
3049 /**********************************************************************
3050 * HardwareStateProperty
3053 * Set/Get the value of the HardwareState and switch
3054 * between direct video buffer ouput and GDI windowed
3057 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
3058 * object. We use the same object to Request.
3060 * ConsoleHwState has the correct size to be compatible
3061 * with NT's, but values are not.
3063 static NTSTATUS FASTCALL
3064 SetConsoleHardwareState (PCSRSS_CONSOLE Console
, DWORD ConsoleHwState
)
3066 DPRINT1("Console Hardware State: %d\n", ConsoleHwState
);
3068 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED
== ConsoleHwState
)
3069 ||(CONSOLE_HARDWARE_STATE_DIRECT
== ConsoleHwState
))
3071 if (Console
->HardwareState
!= ConsoleHwState
)
3073 /* TODO: implement switching from full screen to windowed mode */
3074 /* TODO: or back; now simply store the hardware state */
3075 Console
->HardwareState
= ConsoleHwState
;
3078 return STATUS_SUCCESS
;
3081 return STATUS_INVALID_PARAMETER_3
; /* Client: (handle, set_get, [mode]) */
3084 CSR_API(CsrHardwareStateProperty
)
3086 PCSRSS_CONSOLE Console
;
3089 DPRINT("CsrHardwareStateProperty\n");
3091 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3092 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3094 Status
= ConioLockConsole(ProcessData
,
3095 Request
->Data
.ConsoleHardwareStateRequest
.ConsoleHandle
,
3097 if (! NT_SUCCESS(Status
))
3099 DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
3100 return Request
->Status
= Status
;
3103 switch (Request
->Data
.ConsoleHardwareStateRequest
.SetGet
)
3105 case CONSOLE_HARDWARE_STATE_GET
:
3106 Request
->Data
.ConsoleHardwareStateRequest
.State
= Console
->HardwareState
;
3109 case CONSOLE_HARDWARE_STATE_SET
:
3110 DPRINT("Setting console hardware state.\n");
3111 Request
->Status
= SetConsoleHardwareState(Console
, Request
->Data
.ConsoleHardwareStateRequest
.State
);
3115 Request
->Status
= STATUS_INVALID_PARAMETER_2
; /* Client: (handle, [set_get], mode) */
3119 ConioUnlockConsole(Console
);
3121 return Request
->Status
;
3124 CSR_API(CsrGetConsoleWindow
)
3126 PCSRSS_CONSOLE Console
;
3129 DPRINT("CsrGetConsoleWindow\n");
3131 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3132 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3134 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3135 if (! NT_SUCCESS(Status
))
3137 return Request
->Status
= Status
;
3140 Request
->Data
.GetConsoleWindowRequest
.WindowHandle
= Console
->hWindow
;
3141 ConioUnlockConsole(Console
);
3143 return Request
->Status
= STATUS_SUCCESS
;
3146 CSR_API(CsrSetConsoleIcon
)
3148 PCSRSS_CONSOLE Console
;
3151 DPRINT("CsrSetConsoleIcon\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 Console
->hWindowIcon
= Request
->Data
.SetConsoleIconRequest
.WindowIcon
;
3163 Request
->Status
= (ConioChangeIcon(Console
) ? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
3164 ConioUnlockConsole(Console
);
3166 return Request
->Status
;
3169 CSR_API(CsrGetConsoleCodePage
)
3171 PCSRSS_CONSOLE Console
;
3174 DPRINT("CsrGetConsoleCodePage\n");
3176 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3177 if (! NT_SUCCESS(Status
))
3179 return Request
->Status
= Status
;
3182 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3183 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3184 Request
->Data
.GetConsoleCodePage
.CodePage
= Console
->CodePage
;
3185 ConioUnlockConsole(Console
);
3186 return Request
->Status
= STATUS_SUCCESS
;
3189 CSR_API(CsrSetConsoleCodePage
)
3191 PCSRSS_CONSOLE Console
;
3194 DPRINT("CsrSetConsoleCodePage\n");
3196 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3197 if (! NT_SUCCESS(Status
))
3199 return Request
->Status
= Status
;
3202 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3203 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3204 if (IsValidCodePage(Request
->Data
.SetConsoleCodePage
.CodePage
))
3206 Console
->CodePage
= Request
->Data
.SetConsoleCodePage
.CodePage
;
3207 ConioUnlockConsole(Console
);
3208 return Request
->Status
= STATUS_SUCCESS
;
3210 ConioUnlockConsole(Console
);
3211 return Request
->Status
= STATUS_UNSUCCESSFUL
;
3214 CSR_API(CsrGetConsoleOutputCodePage
)
3216 PCSRSS_CONSOLE Console
;
3219 DPRINT("CsrGetConsoleOutputCodePage\n");
3221 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3222 if (! NT_SUCCESS(Status
))
3224 return Request
->Status
= Status
;
3227 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3228 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3229 Request
->Data
.GetConsoleOutputCodePage
.CodePage
= Console
->OutputCodePage
;
3230 ConioUnlockConsole(Console
);
3231 return Request
->Status
= STATUS_SUCCESS
;
3234 CSR_API(CsrSetConsoleOutputCodePage
)
3236 PCSRSS_CONSOLE Console
;
3239 DPRINT("CsrSetConsoleOutputCodePage\n");
3241 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3242 if (! NT_SUCCESS(Status
))
3244 return Request
->Status
= Status
;
3247 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3248 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3249 if (IsValidCodePage(Request
->Data
.SetConsoleOutputCodePage
.CodePage
))
3251 Console
->OutputCodePage
= Request
->Data
.SetConsoleOutputCodePage
.CodePage
;
3252 ConioUnlockConsole(Console
);
3253 return Request
->Status
= STATUS_SUCCESS
;
3255 ConioUnlockConsole(Console
);
3256 return Request
->Status
= STATUS_UNSUCCESSFUL
;
3259 CSR_API(CsrGetProcessList
)
3262 PCSRSS_CONSOLE Console
;
3263 PCSRSS_PROCESS_DATA current
;
3264 PLIST_ENTRY current_entry
;
3265 ULONG nItems
, nCopied
, Length
;
3268 DPRINT("CsrGetProcessList\n");
3270 Buffer
= Request
->Data
.GetProcessListRequest
.ProcessId
;
3271 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3272 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3274 nItems
= nCopied
= 0;
3275 Request
->Data
.GetProcessListRequest
.nProcessIdsCopied
= 0;
3276 Request
->Data
.GetProcessListRequest
.nProcessIdsTotal
= 0;
3278 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3279 if (! NT_SUCCESS(Status
))
3281 return Request
->Status
= Status
;
3284 DPRINT1("Console_Api Ctrl-C\n");
3286 for(current_entry
= Console
->ProcessList
.Flink
;
3287 current_entry
!= &Console
->ProcessList
;
3288 current_entry
= current_entry
->Flink
)
3290 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
3291 if(++nItems
< Request
->Data
.GetProcessListRequest
.nMaxIds
)
3293 *(Buffer
++) = current
->ProcessId
;
3298 ConioUnlockConsole(Console
);
3300 Request
->Data
.GetProcessListRequest
.nProcessIdsCopied
= nCopied
;
3301 Request
->Data
.GetProcessListRequest
.nProcessIdsTotal
= nItems
;
3303 Length
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_GET_PROCESS_LIST
) + nCopied
* sizeof(HANDLE
);
3304 if (Length
> sizeof(CSR_API_MESSAGE
))
3306 Request
->Header
.u1
.s1
.TotalLength
= Length
;
3307 Request
->Header
.u1
.s1
.DataLength
= Length
- sizeof(PORT_MESSAGE
);
3309 return Request
->Status
= STATUS_SUCCESS
;