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 ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar) \
31 WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
33 #define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
34 WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
36 #define ConsoleAnsiCharToUnicodeChar(Console, sWChar, dChar) \
37 MultiByteToWideChar((Console)->OutputCodePage, 0, (dChar), 1, (sWChar), 1)
40 /* FUNCTIONS *****************************************************************/
42 static NTSTATUS FASTCALL
43 ConioConsoleFromProcessData(PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_CONSOLE
*Console
)
45 PCSRSS_CONSOLE ProcessConsole
= ProcessData
->Console
;
50 return STATUS_SUCCESS
;
53 EnterCriticalSection(&(ProcessConsole
->Header
.Lock
));
54 *Console
= ProcessConsole
;
56 return STATUS_SUCCESS
;
60 ConioConsoleCtrlEventTimeout(DWORD Event
, PCSRSS_PROCESS_DATA ProcessData
, DWORD Timeout
)
64 DPRINT("ConioConsoleCtrlEvent Parent ProcessId = %x\n", ProcessData
->ProcessId
);
66 if (ProcessData
->CtrlDispatcher
)
69 Thread
= CreateRemoteThread(ProcessData
->Process
, NULL
, 0,
70 (LPTHREAD_START_ROUTINE
) ProcessData
->CtrlDispatcher
,
71 (PVOID
) Event
, 0, NULL
);
74 DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
77 WaitForSingleObject(Thread
, Timeout
);
83 ConioConsoleCtrlEvent(DWORD Event
, PCSRSS_PROCESS_DATA ProcessData
)
85 ConioConsoleCtrlEventTimeout(Event
, ProcessData
, INFINITE
);
88 #define GET_CELL_BUFFER(b,o)\
91 #define SET_CELL_BUFFER(b,o,c,a)\
92 (b)->Buffer[(o)++]=(c),\
93 (b)->Buffer[(o)++]=(a)
96 ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff
)
98 DWORD Offset
= 2 * (Buff
->CurrentY
* Buff
->MaxX
);
101 for (Pos
= 0; Pos
< Buff
->MaxX
; Pos
++)
103 /* Fill the cell: Offset is incremented by the macro */
104 SET_CELL_BUFFER(Buff
, Offset
, ' ', Buff
->DefaultAttrib
);
108 static NTSTATUS FASTCALL
109 CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console
,
110 PCSRSS_SCREEN_BUFFER Buffer
)
112 DPRINT("CsrInitConsoleScreenBuffer Size X %d Size Y %d\n", Buffer
->MaxX
, Buffer
->MaxY
);
114 Buffer
->Header
.Type
= CONIO_SCREEN_BUFFER_MAGIC
;
115 Buffer
->Header
.ReferenceCount
= 0;
118 Buffer
->Buffer
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, Buffer
->MaxX
* Buffer
->MaxY
* 2);
119 if (NULL
== Buffer
->Buffer
)
121 return STATUS_INSUFFICIENT_RESOURCES
;
123 InitializeCriticalSection(&Buffer
->Header
.Lock
);
124 ConioInitScreenBuffer(Console
, Buffer
);
125 /* initialize buffer to be empty with default attributes */
126 for (Buffer
->CurrentY
= 0 ; Buffer
->CurrentY
< Buffer
->MaxY
; Buffer
->CurrentY
++)
128 ClearLineBuffer(Buffer
);
130 Buffer
->Mode
= ENABLE_PROCESSED_OUTPUT
| ENABLE_WRAP_AT_EOL_OUTPUT
;
131 Buffer
->CurrentX
= 0;
132 Buffer
->CurrentY
= 0;
134 return STATUS_SUCCESS
;
137 static NTSTATUS STDCALL
138 CsrInitConsole(PCSRSS_CONSOLE Console
)
141 SECURITY_ATTRIBUTES SecurityAttributes
;
142 PCSRSS_SCREEN_BUFFER NewBuffer
;
145 Console
->Title
.MaximumLength
= Console
->Title
.Length
= 0;
146 Console
->Title
.Buffer
= NULL
;
149 RtlCreateUnicodeString(&Console
->Title
, L
"Command Prompt");
151 Console
->Header
.ReferenceCount
= 0;
152 Console
->WaitingChars
= 0;
153 Console
->WaitingLines
= 0;
154 Console
->EchoCount
= 0;
155 Console
->Header
.Type
= CONIO_CONSOLE_MAGIC
;
156 Console
->Mode
= ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_PROCESSED_INPUT
| ENABLE_MOUSE_INPUT
;
157 Console
->EarlyReturn
= FALSE
;
158 Console
->ActiveBuffer
= NULL
;
159 Console
->hActiveBuffer
= INVALID_HANDLE_VALUE
;
160 InitializeListHead(&Console
->InputEvents
);
161 Console
->CodePage
= GetOEMCP();
162 Console
->OutputCodePage
= GetOEMCP();
164 SecurityAttributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
165 SecurityAttributes
.lpSecurityDescriptor
= NULL
;
166 SecurityAttributes
.bInheritHandle
= TRUE
;
168 Console
->ActiveEvent
= CreateEventW(&SecurityAttributes
, TRUE
, FALSE
, NULL
);
169 if (NULL
== Console
->ActiveEvent
)
171 RtlFreeUnicodeString(&Console
->Title
);
172 return STATUS_UNSUCCESSFUL
;
174 Console
->PrivateData
= NULL
;
175 InitializeCriticalSection(&Console
->Header
.Lock
);
177 GuiMode
= DtbgIsDesktopVisible();
179 /* allocate console screen buffer */
180 NewBuffer
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
181 if (NULL
== NewBuffer
)
183 RtlFreeUnicodeString(&Console
->Title
);
184 DeleteCriticalSection(&Console
->Header
.Lock
);
185 CloseHandle(Console
->ActiveEvent
);
186 return STATUS_INSUFFICIENT_RESOURCES
;
188 /* init screen buffer with defaults */
189 NewBuffer
->CursorInfo
.bVisible
= TRUE
;
190 NewBuffer
->CursorInfo
.dwSize
= 5;
191 /* make console active, and insert into console list */
192 Console
->ActiveBuffer
= (PCSRSS_SCREEN_BUFFER
) NewBuffer
;
193 Console
->hActiveBuffer
= INVALID_HANDLE_VALUE
;
197 Status
= TuiInitConsole(Console
);
198 if (! NT_SUCCESS(Status
))
200 DPRINT1("Failed to open text-mode console, switching to gui-mode\n");
206 Status
= GuiInitConsole(Console
);
207 if (! NT_SUCCESS(Status
))
209 HeapFree(Win32CsrApiHeap
,0, NewBuffer
);
210 RtlFreeUnicodeString(&Console
->Title
);
211 DeleteCriticalSection(&Console
->Header
.Lock
);
212 CloseHandle(Console
->ActiveEvent
);
213 DPRINT1("GuiInitConsole: failed\n");
218 Status
= CsrInitConsoleScreenBuffer(Console
, NewBuffer
);
219 if (! NT_SUCCESS(Status
))
221 ConioCleanupConsole(Console
);
222 RtlFreeUnicodeString(&Console
->Title
);
223 DeleteCriticalSection(&Console
->Header
.Lock
);
224 CloseHandle(Console
->ActiveEvent
);
225 HeapFree(Win32CsrApiHeap
, 0, NewBuffer
);
226 DPRINT1("CsrInitConsoleScreenBuffer: failed\n");
230 /* add a reference count because the buffer is tied to the console */
231 InterlockedIncrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
);
233 /* copy buffer contents to screen */
234 ConioDrawConsole(Console
);
236 return STATUS_SUCCESS
;
240 CSR_API(CsrAllocConsole
)
242 PCSRSS_CONSOLE Console
;
243 NTSTATUS Status
= STATUS_SUCCESS
;
244 BOOLEAN NewConsole
= FALSE
;
246 DPRINT("CsrAllocConsole\n");
248 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
249 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
251 if (ProcessData
== NULL
)
253 DPRINT1("No process data\n");
254 return Request
->Status
= STATUS_INVALID_PARAMETER
;
257 if (ProcessData
->Console
)
259 DPRINT1("Process already has a console\n");
260 Request
->Status
= STATUS_INVALID_PARAMETER
;
261 return STATUS_INVALID_PARAMETER
;
265 Request
->Status
= STATUS_SUCCESS
;
267 /* If we don't need a console, then get out of here */
268 if (!Request
->Data
.AllocConsoleRequest
.ConsoleNeeded
)
270 DPRINT("No console needed\n");
271 return STATUS_SUCCESS
;
274 /* If we already have one, then don't create a new one... */
275 if (!Request
->Data
.AllocConsoleRequest
.Console
||
276 Request
->Data
.AllocConsoleRequest
.Console
!= ProcessData
->ParentConsole
)
278 /* Allocate a console structure */
280 Console
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_CONSOLE
));
283 DPRINT1("Not enough memory for console\n");
284 Request
->Status
= STATUS_NO_MEMORY
;
285 return STATUS_NO_MEMORY
;
287 /* initialize list head */
288 InitializeListHead(&Console
->ProcessList
);
289 /* insert process data required for GUI initialization */
290 InsertHeadList(&Console
->ProcessList
, &ProcessData
->ProcessEntry
);
291 /* Initialize the Console */
292 Request
->Status
= CsrInitConsole(Console
);
293 if (!NT_SUCCESS(Request
->Status
))
295 DPRINT1("Console init failed\n");
296 HeapFree(Win32CsrApiHeap
, 0, Console
);
297 return Request
->Status
;
302 /* Reuse our current console */
303 Console
= Request
->Data
.AllocConsoleRequest
.Console
;
306 /* Set the Process Console */
307 ProcessData
->Console
= Console
;
309 /* Return it to the caller */
310 Request
->Data
.AllocConsoleRequest
.Console
= Console
;
312 /* Add a reference count because the process is tied to the console */
313 Console
->Header
.ReferenceCount
++;
315 if (NewConsole
|| !ProcessData
->bInheritHandles
)
317 /* Insert the Objects */
318 Status
= Win32CsrInsertObject2(ProcessData
,
319 &Request
->Data
.AllocConsoleRequest
.InputHandle
,
321 if (! NT_SUCCESS(Status
))
323 DPRINT1("Failed to insert object\n");
324 ConioDeleteConsole((Object_t
*) Console
);
325 ProcessData
->Console
= 0;
326 return Request
->Status
= Status
;
329 Status
= Win32CsrInsertObject2(ProcessData
,
330 &Request
->Data
.AllocConsoleRequest
.OutputHandle
,
331 &Console
->ActiveBuffer
->Header
);
332 if (!NT_SUCCESS(Status
))
334 DPRINT1("Failed to insert object\n");
335 ConioDeleteConsole((Object_t
*) Console
);
336 Win32CsrReleaseObject(ProcessData
,
337 Request
->Data
.AllocConsoleRequest
.InputHandle
);
338 ProcessData
->Console
= 0;
339 return Request
->Status
= Status
;
341 Console
->hActiveBuffer
= Request
->Data
.AllocConsoleRequest
.OutputHandle
;
344 /* Duplicate the Event */
345 if (!DuplicateHandle(GetCurrentProcess(),
346 ProcessData
->Console
->ActiveEvent
,
347 ProcessData
->Process
,
348 &ProcessData
->ConsoleEvent
,
353 DPRINT1("DuplicateHandle() failed: %d\n", GetLastError
);
354 ConioDeleteConsole((Object_t
*) Console
);
355 if (NewConsole
|| !ProcessData
->bInheritHandles
)
357 Win32CsrReleaseObject(ProcessData
,
358 Request
->Data
.AllocConsoleRequest
.OutputHandle
);
359 Win32CsrReleaseObject(ProcessData
,
360 Request
->Data
.AllocConsoleRequest
.InputHandle
);
362 ProcessData
->Console
= 0;
363 return Request
->Status
= Status
;
366 /* Set the Ctrl Dispatcher */
367 ProcessData
->CtrlDispatcher
= Request
->Data
.AllocConsoleRequest
.CtrlDispatcher
;
368 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
372 /* Insert into the list if it has not been added */
373 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ProcessEntry
);
376 return STATUS_SUCCESS
;
379 CSR_API(CsrFreeConsole
)
381 PCSRSS_CONSOLE Console
;
384 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
385 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
387 if (ProcessData
== NULL
|| ProcessData
->Console
== NULL
)
389 return Request
->Status
= STATUS_INVALID_PARAMETER
;
392 Console
= ProcessData
->Console
;
393 ProcessData
->Console
= NULL
;
394 if (0 == InterlockedDecrement(&Console
->Header
.ReferenceCount
))
396 ConioDeleteConsole((Object_t
*) Console
);
398 return STATUS_SUCCESS
;
402 ConioNextLine(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, UINT
*ScrolledLines
)
404 if (++Buff
->CurrentY
== Buff
->MaxY
)
408 /* If we hit bottom, slide the viewable screen */
409 if (Buff
->CurrentY
== Buff
->ShowY
)
411 if (++Buff
->ShowY
== Buff
->MaxY
)
416 ClearLineBuffer(Buff
);
418 UpdateRect
->left
= 0;
419 UpdateRect
->right
= Buff
->MaxX
- 1;
420 if (UpdateRect
->top
== (LONG
)Buff
->CurrentY
)
422 if (++UpdateRect
->top
== Buff
->MaxY
)
427 UpdateRect
->bottom
= Buff
->CurrentY
;
430 static NTSTATUS FASTCALL
431 ConioWriteConsole(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
,
432 CHAR
*Buffer
, DWORD Length
, BOOL Attrib
)
437 LONG CursorStartX
, CursorStartY
;
440 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &CursorStartX
, &CursorStartY
);
441 UpdateRect
.left
= Buff
->MaxX
;
442 UpdateRect
.top
= Buff
->CurrentY
;
443 UpdateRect
.right
= -1;
444 UpdateRect
.bottom
= Buff
->CurrentY
;
447 for (i
= 0; i
< Length
; i
++)
449 if (Buff
->Mode
& ENABLE_PROCESSED_OUTPUT
)
452 if (Buffer
[i
] == '\n')
455 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
459 else if (Buffer
[i
] == '\b')
461 /* Only handle BS if we're not on the first pos of the first line */
462 if (0 != Buff
->CurrentX
|| Buff
->ShowY
!= Buff
->CurrentY
)
464 if (0 == Buff
->CurrentX
)
466 /* slide virtual position up */
467 Buff
->CurrentX
= Buff
->MaxX
- 1;
468 if (0 == Buff
->CurrentY
)
470 Buff
->CurrentY
= Buff
->MaxY
;
476 if ((0 == UpdateRect
.top
&& UpdateRect
.bottom
< (LONG
)Buff
->CurrentY
)
477 || (0 != UpdateRect
.top
&& (LONG
)Buff
->CurrentY
< UpdateRect
.top
))
479 UpdateRect
.top
= Buff
->CurrentY
;
486 Offset
= 2 * ((Buff
->CurrentY
* Buff
->MaxX
) + Buff
->CurrentX
);
487 SET_CELL_BUFFER(Buff
, Offset
, ' ', Buff
->DefaultAttrib
);
488 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
) Buff
->CurrentX
);
489 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
494 else if (Buffer
[i
] == '\r')
497 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
) Buff
->CurrentX
);
498 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
502 else if (Buffer
[i
] == '\t')
506 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
)Buff
->CurrentX
);
507 EndX
= (Buff
->CurrentX
+ 8) & ~7;
508 if (EndX
> Buff
->MaxX
)
512 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
513 while (Buff
->CurrentX
< EndX
)
515 Buff
->Buffer
[Offset
] = ' ';
516 Buff
->Buffer
[Offset
+ 1] = Buff
->DefaultAttrib
;
520 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
- 1);
521 if (Buff
->CurrentX
== Buff
->MaxX
)
523 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
526 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
536 UpdateRect
.left
= min(UpdateRect
.left
, (LONG
)Buff
->CurrentX
);
537 UpdateRect
.right
= max(UpdateRect
.right
, (LONG
) Buff
->CurrentX
);
538 Offset
= 2 * (((Buff
->CurrentY
* Buff
->MaxX
)) + Buff
->CurrentX
);
539 Buff
->Buffer
[Offset
++] = Buffer
[i
];
542 Buff
->Buffer
[Offset
] = Buff
->DefaultAttrib
;
545 if (Buff
->CurrentX
== Buff
->MaxX
)
547 if (Buff
->Mode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
550 ConioNextLine(Buff
, &UpdateRect
, &ScrolledLines
);
554 Buff
->CurrentX
= CursorStartX
;
559 ConioPhysicalToLogical(Buff
, UpdateRect
.left
, UpdateRect
.top
, &(UpdateRect
.left
),
561 ConioPhysicalToLogical(Buff
, UpdateRect
.right
, UpdateRect
.bottom
, &(UpdateRect
.right
),
562 &(UpdateRect
.bottom
));
563 if (! ConioIsRectEmpty(&UpdateRect
) && NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
565 ConioWriteStream(Console
, &UpdateRect
, CursorStartX
, CursorStartY
, ScrolledLines
,
569 return STATUS_SUCCESS
;
572 CSR_API(CsrReadConsole
)
574 PLIST_ENTRY CurrentEntry
;
577 PWCHAR UnicodeBuffer
;
579 ULONG nNumberOfCharsToRead
, CharSize
;
580 PCSRSS_CONSOLE Console
;
583 DPRINT("CsrReadConsole\n");
585 CharSize
= (Request
->Data
.ReadConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
587 /* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */
588 nNumberOfCharsToRead
= min(Request
->Data
.ReadConsoleRequest
.NrCharactersToRead
, CSRSS_MAX_READ_CONSOLE
/ CharSize
);
589 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
590 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
592 Buffer
= Request
->Data
.ReadConsoleRequest
.Buffer
;
593 UnicodeBuffer
= (PWCHAR
)Buffer
;
594 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadConsoleRequest
.ConsoleHandle
,
596 if (! NT_SUCCESS(Status
))
598 return Request
->Status
= Status
;
600 Request
->Data
.ReadConsoleRequest
.EventHandle
= ProcessData
->ConsoleEvent
;
601 for (i
= 0; i
< nNumberOfCharsToRead
&& Console
->InputEvents
.Flink
!= &Console
->InputEvents
; i
++)
603 /* remove input event from queue */
604 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
605 if (IsListEmpty(&Console
->InputEvents
))
608 ResetEvent(Console
->ActiveEvent
);
610 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
612 /* only pay attention to valid ascii chars, on key down */
613 if (KEY_EVENT
== Input
->InputEvent
.EventType
614 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
615 && Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
!= '\0')
618 * backspace handling - if we are in charge of echoing it then we handle it here
619 * otherwise we treat it like a normal char.
621 if ('\b' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
&& 0
622 != (Console
->Mode
& ENABLE_ECHO_INPUT
))
624 /* echo if it has not already been done, and either we or the client has chars to be deleted */
626 && (0 != i
|| Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
))
628 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
629 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
633 i
-= 2; /* if we already have something to return, just back it up by 2 */
636 { /* otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer */
637 Console
->WaitingChars
--;
638 ConioUnlockConsole(Console
);
639 HeapFree(Win32CsrApiHeap
, 0, Input
);
640 Request
->Data
.ReadConsoleRequest
.NrCharactersRead
= 0;
641 Request
->Status
= STATUS_NOTIFY_CLEANUP
;
642 return STATUS_NOTIFY_CLEANUP
;
645 Request
->Data
.ReadConsoleRequest
.nCharsCanBeDeleted
--;
646 Input
->Echoed
= TRUE
; /* mark as echoed so we don't echo it below */
648 /* do not copy backspace to buffer */
651 if(Request
->Data
.ReadConsoleRequest
.Unicode
)
652 UnicodeBuffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
; /* FIXME */
654 Buffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
;
656 /* echo to screen if enabled and we did not already echo the char */
657 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
)
659 && '\r' != Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
661 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
662 &Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
669 Console
->WaitingChars
--;
670 HeapFree(Win32CsrApiHeap
, 0, Input
);
672 Request
->Data
.ReadConsoleRequest
.NrCharactersRead
= i
;
675 Request
->Status
= STATUS_PENDING
; /* we didn't read anything */
677 else if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
))
679 if (0 == Console
->WaitingLines
||
680 (Request
->Data
.ReadConsoleRequest
.Unicode
? (L
'\n' != UnicodeBuffer
[i
- 1]) : ('\n' != Buffer
[i
- 1])))
682 Request
->Status
= STATUS_PENDING
; /* line buffered, didn't get a complete line */
686 Console
->WaitingLines
--;
687 Request
->Status
= STATUS_SUCCESS
; /* line buffered, did get a complete line */
692 Request
->Status
= STATUS_SUCCESS
; /* not line buffered, did read something */
695 if (Request
->Status
== STATUS_PENDING
)
697 Console
->EchoCount
= nNumberOfCharsToRead
- i
;
701 Console
->EchoCount
= 0; /* if the client is no longer waiting on input, do not echo */
704 ConioUnlockConsole(Console
);
706 if (CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE
) + i
* CharSize
> sizeof(CSR_API_MESSAGE
))
708 Request
->Header
.u1
.s1
.TotalLength
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE
) + i
* CharSize
;
709 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
712 return Request
->Status
;
716 ConioPhysicalToLogical(PCSRSS_SCREEN_BUFFER Buff
,
722 *LogicalX
= PhysicalX
;
723 if (PhysicalY
< Buff
->ShowY
)
725 *LogicalY
= Buff
->MaxY
- Buff
->ShowY
+ PhysicalY
;
729 *LogicalY
= PhysicalY
- Buff
->ShowY
;
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 /* Move from one rectangle to another. We must be careful about the order that
793 * this is done, to avoid overwriting parts of the source before they are moved. */
795 ConioMoveRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer
,
801 int Width
= ConioRectWidth(SrcRegion
);
802 int Height
= ConioRectHeight(SrcRegion
);
813 /* Moving down: work from bottom up */
814 SY
= SrcRegion
->bottom
;
815 DY
= DstRegion
->bottom
;
818 for (i
= 0; i
< Height
; i
++)
820 PWORD SRow
= (PWORD
)&ScreenBuffer
->Buffer
[((SY
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
) * ScreenBuffer
->MaxX
* 2];
821 PWORD DRow
= (PWORD
)&ScreenBuffer
->Buffer
[((DY
+ ScreenBuffer
->ShowY
) % ScreenBuffer
->MaxY
) * ScreenBuffer
->MaxX
* 2];
823 SX
= SrcRegion
->left
;
824 DX
= DstRegion
->left
;
828 /* Moving right: work from right to left */
829 SX
= SrcRegion
->right
;
830 DX
= DstRegion
->right
;
833 for (j
= 0; j
< Width
; j
++)
835 WORD Cell
= SRow
[SX
];
836 if (SX
>= ClipRegion
->left
&& SX
<= ClipRegion
->right
837 && SY
>= ClipRegion
->top
&& SY
<= ClipRegion
->bottom
)
841 if (DX
>= ClipRegion
->left
&& DX
<= ClipRegion
->right
842 && DY
>= ClipRegion
->top
&& DY
<= ClipRegion
->bottom
)
855 ConioInputEventToAnsi(PCSRSS_CONSOLE Console
, PINPUT_RECORD InputEvent
)
857 if (InputEvent
->EventType
== KEY_EVENT
)
859 WCHAR UnicodeChar
= InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
;
860 InputEvent
->Event
.KeyEvent
.uChar
.UnicodeChar
= 0;
861 ConsoleInputUnicodeCharToAnsiChar(Console
,
862 &InputEvent
->Event
.KeyEvent
.uChar
.AsciiChar
,
867 CSR_API(CsrWriteConsole
)
871 PCSRSS_SCREEN_BUFFER Buff
;
872 PCSRSS_CONSOLE Console
;
875 ULONG CharSize
= (Request
->Data
.WriteConsoleRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
877 DPRINT("CsrWriteConsole\n");
879 if (Request
->Header
.u1
.s1
.TotalLength
880 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE
)
881 + (Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
* CharSize
))
883 DPRINT1("Invalid request size\n");
884 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
885 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
886 return Request
->Status
= STATUS_INVALID_PARAMETER
;
888 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
890 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
891 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
893 if (! NT_SUCCESS(Status
))
895 return Request
->Status
= Status
;
898 if(Request
->Data
.WriteConsoleRequest
.Unicode
)
900 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
901 (PWCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
,
902 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
,
903 NULL
, 0, NULL
, NULL
);
904 Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
907 WideCharToMultiByte(Console
->OutputCodePage
, 0,
908 (PWCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
,
909 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
,
910 Buffer
, Length
, NULL
, NULL
);
914 Status
= STATUS_NO_MEMORY
;
919 Buffer
= (PCHAR
)Request
->Data
.WriteConsoleRequest
.Buffer
;
924 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.WriteConsoleRequest
.ConsoleHandle
, &Buff
);
925 if (NT_SUCCESS(Status
))
927 Request
->Status
= ConioWriteConsole(Console
, Buff
, Buffer
,
928 Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
, TRUE
);
929 if (NT_SUCCESS(Status
))
931 Written
= Request
->Data
.WriteConsoleRequest
.NrCharactersToWrite
;
933 ConioUnlockScreenBuffer(Buff
);
935 if (Request
->Data
.WriteConsoleRequest
.Unicode
)
937 RtlFreeHeap(GetProcessHeap(), 0, Buffer
);
942 ConioUnlockConsole(Console
);
945 Request
->Data
.WriteConsoleRequest
.NrCharactersWritten
= Written
;
947 return Request
->Status
= Status
;
951 ConioDeleteScreenBuffer(Object_t
*Object
)
953 PCSRSS_SCREEN_BUFFER Buffer
= (PCSRSS_SCREEN_BUFFER
) Object
;
954 DeleteCriticalSection(&Buffer
->Header
.Lock
);
955 HeapFree(Win32CsrApiHeap
, 0, Buffer
->Buffer
);
956 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
960 ConioDrawConsole(PCSRSS_CONSOLE Console
)
964 ConioInitRect(&Region
, 0, 0, Console
->Size
.Y
- 1, Console
->Size
.X
- 1);
966 ConioDrawRegion(Console
, &Region
);
971 ConioDeleteConsole(Object_t
*Object
)
973 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Object
;
976 DPRINT("ConioDeleteConsole\n");
978 /* Drain input event queue */
979 while (Console
->InputEvents
.Flink
!= &Console
->InputEvents
)
981 Event
= (ConsoleInput
*) Console
->InputEvents
.Flink
;
982 Console
->InputEvents
.Flink
= Console
->InputEvents
.Flink
->Flink
;
983 Console
->InputEvents
.Flink
->Flink
->Blink
= &Console
->InputEvents
;
984 HeapFree(Win32CsrApiHeap
, 0, Event
);
988 if (0 == InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
990 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
994 Console
->ActiveBuffer
= NULL
;
995 Console
->hActiveBuffer
= INVALID_HANDLE_VALUE
;
996 ConioCleanupConsole(Console
);
998 CloseHandle(Console
->ActiveEvent
);
999 DeleteCriticalSection(&Console
->Header
.Lock
);
1000 RtlFreeUnicodeString(&Console
->Title
);
1001 HeapFree(Win32CsrApiHeap
, 0, Console
);
1005 CsrInitConsoleSupport(VOID
)
1007 DPRINT("CSR: CsrInitConsoleSupport()\n");
1009 /* Should call LoadKeyboardLayout */
1012 static VOID FASTCALL
1013 ConioProcessChar(PCSRSS_CONSOLE Console
,
1014 ConsoleInput
*KeyEventRecord
)
1017 BOOL bClientWake
= FALSE
;
1018 ConsoleInput
*TempInput
;
1020 /* process Ctrl-C and Ctrl-Break */
1021 if (Console
->Mode
& ENABLE_PROCESSED_INPUT
&&
1022 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
&&
1023 ((KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== VK_PAUSE
) ||
1024 (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== 'C')) &&
1025 (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
)))
1027 PCSRSS_PROCESS_DATA current
;
1028 PLIST_ENTRY current_entry
;
1029 DPRINT1("Console_Api Ctrl-C\n");
1030 current_entry
= Console
->ProcessList
.Flink
;
1031 while (current_entry
!= &Console
->ProcessList
)
1033 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
1034 current_entry
= current_entry
->Flink
;
1035 ConioConsoleCtrlEvent((DWORD
)CTRL_C_EVENT
, current
);
1037 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1041 if (0 != (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
1042 & (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1043 && (VK_UP
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
1044 || VK_DOWN
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
))
1046 if (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1048 /* scroll up or down */
1049 if (NULL
== Console
)
1051 DPRINT1("No Active Console!\n");
1052 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1055 if (VK_UP
== KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
)
1057 /* only scroll up if there is room to scroll up into */
1058 if (Console
->ActiveBuffer
->ShowY
!= ((Console
->ActiveBuffer
->CurrentY
+ 1) %
1059 Console
->ActiveBuffer
->MaxY
))
1061 Console
->ActiveBuffer
->ShowY
= (Console
->ActiveBuffer
->ShowY
+
1062 Console
->ActiveBuffer
->MaxY
- 1) %
1063 Console
->ActiveBuffer
->MaxY
;
1066 else if (Console
->ActiveBuffer
->ShowY
!= Console
->ActiveBuffer
->CurrentY
)
1067 /* only scroll down if there is room to scroll down into */
1069 if (Console
->ActiveBuffer
->ShowY
% Console
->ActiveBuffer
->MaxY
!=
1070 Console
->ActiveBuffer
->CurrentY
)
1072 if (((Console
->ActiveBuffer
->CurrentY
+ 1) % Console
->ActiveBuffer
->MaxY
) !=
1073 (Console
->ActiveBuffer
->ShowY
+ Console
->ActiveBuffer
->MaxY
) %
1074 Console
->ActiveBuffer
->MaxY
)
1076 Console
->ActiveBuffer
->ShowY
= (Console
->ActiveBuffer
->ShowY
+ 1) %
1077 Console
->ActiveBuffer
->MaxY
;
1081 ConioDrawConsole(Console
);
1083 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1086 if (NULL
== Console
)
1088 DPRINT1("No Active Console!\n");
1089 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1093 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
)))
1095 switch(KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1098 /* first add the \r */
1099 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1100 updown
= KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
;
1101 KeyEventRecord
->Echoed
= FALSE
;
1102 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= VK_RETURN
;
1103 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\r';
1104 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1105 Console
->WaitingChars
++;
1106 KeyEventRecord
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1107 if (NULL
== KeyEventRecord
)
1109 DPRINT1("Failed to allocate KeyEventRecord\n");
1112 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
1113 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
= updown
;
1114 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
= 0;
1115 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualScanCode
= 0;
1116 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
= '\n';
1117 KeyEventRecord
->Fake
= TRUE
;
1121 /* add event to the queue */
1122 InsertTailList(&Console
->InputEvents
, &KeyEventRecord
->ListEntry
);
1123 Console
->WaitingChars
++;
1124 /* if line input mode is enabled, only wake the client on enter key down */
1125 if (0 == (Console
->Mode
& ENABLE_LINE_INPUT
)
1126 || Console
->EarlyReturn
1127 || ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1128 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
))
1130 if ('\n' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1132 Console
->WaitingLines
++;
1135 SetEvent(Console
->ActiveEvent
);
1137 KeyEventRecord
->Echoed
= FALSE
;
1138 if (0 != (Console
->Mode
& (ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
))
1139 && '\b' == KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1140 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
)
1142 /* walk the input queue looking for a char to backspace */
1143 for (TempInput
= (ConsoleInput
*) Console
->InputEvents
.Blink
;
1144 TempInput
!= (ConsoleInput
*) &Console
->InputEvents
1145 && (KEY_EVENT
== TempInput
->InputEvent
.EventType
1146 || ! TempInput
->InputEvent
.Event
.KeyEvent
.bKeyDown
1147 || '\b' == TempInput
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
);
1148 TempInput
= (ConsoleInput
*) TempInput
->ListEntry
.Blink
)
1152 /* if we found one, delete it, otherwise, wake the client */
1153 if (TempInput
!= (ConsoleInput
*) &Console
->InputEvents
)
1155 /* delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue */
1156 RemoveEntryList(&TempInput
->ListEntry
);
1157 if (TempInput
->Echoed
)
1159 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1160 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1163 HeapFree(Win32CsrApiHeap
, 0, TempInput
);
1164 RemoveEntryList(&KeyEventRecord
->ListEntry
);
1165 HeapFree(Win32CsrApiHeap
, 0, KeyEventRecord
);
1166 Console
->WaitingChars
-= 2;
1170 SetEvent(Console
->ActiveEvent
);
1175 /* echo chars if we are supposed to and client is waiting for some */
1176 if (0 != (Console
->Mode
& ENABLE_ECHO_INPUT
) && Console
->EchoCount
1177 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
1178 && KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
1179 && '\r' != KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1181 /* mark the char as already echoed */
1182 ConioWriteConsole(Console
, Console
->ActiveBuffer
,
1183 &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
,
1185 Console
->EchoCount
--;
1186 KeyEventRecord
->Echoed
= TRUE
;
1190 /* Console->WaitingChars++; */
1191 if (bClientWake
|| 0 == (Console
->Mode
& ENABLE_LINE_INPUT
))
1193 SetEvent(Console
->ActiveEvent
);
1197 static DWORD FASTCALL
1198 ConioGetShiftState(PBYTE KeyState
)
1202 if (KeyState
[VK_CAPITAL
] & 1)
1203 ssOut
|= CAPSLOCK_ON
;
1205 if (KeyState
[VK_NUMLOCK
] & 1)
1206 ssOut
|= NUMLOCK_ON
;
1208 if (KeyState
[VK_SCROLL
] & 1)
1209 ssOut
|= SCROLLLOCK_ON
;
1211 if (KeyState
[VK_SHIFT
] & 0x80)
1212 ssOut
|= SHIFT_PRESSED
;
1214 if (KeyState
[VK_LCONTROL
] & 0x80)
1215 ssOut
|= LEFT_CTRL_PRESSED
;
1216 if (KeyState
[VK_RCONTROL
] & 0x80)
1217 ssOut
|= RIGHT_CTRL_PRESSED
;
1219 if (KeyState
[VK_LMENU
] & 0x80)
1220 ssOut
|= LEFT_ALT_PRESSED
;
1221 if (KeyState
[VK_RMENU
] & 0x80)
1222 ssOut
|= RIGHT_ALT_PRESSED
;
1228 ConioProcessKey(MSG
*msg
, PCSRSS_CONSOLE Console
, BOOL TextMode
)
1230 static BYTE KeyState
[256] = { 0 };
1231 /* MSDN mentions that you should use the last virtual key code received
1232 * when putting a virtual key identity to a WM_CHAR message since multiple
1233 * or translated keys may be involved. */
1234 static UINT LastVirtualKey
= 0;
1236 ConsoleInput
*ConInRec
;
1240 UINT VirtualKeyCode
;
1241 UINT VirtualScanCode
;
1244 ULONG ResultSize
= 0;
1247 VirtualScanCode
= (msg
->lParam
>> 16) & 0xff;
1248 Down
= msg
->message
== WM_KEYDOWN
|| msg
->message
== WM_CHAR
||
1249 msg
->message
== WM_SYSKEYDOWN
|| msg
->message
== WM_SYSCHAR
;
1251 GetKeyboardState(KeyState
);
1252 ShiftState
= ConioGetShiftState(KeyState
);
1254 if (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
)
1256 VirtualKeyCode
= LastVirtualKey
;
1257 UnicodeChar
= msg
->wParam
;
1264 VirtualKeyCode
= msg
->wParam
;
1265 RetChars
= ToUnicodeEx(VirtualKeyCode
,
1272 UnicodeChar
= (1 == RetChars
? Chars
[0] : 0);
1275 if (0 == ResultSize
)
1280 er
.EventType
= KEY_EVENT
;
1281 er
.Event
.KeyEvent
.bKeyDown
= Down
;
1282 er
.Event
.KeyEvent
.wRepeatCount
= RepeatCount
;
1283 er
.Event
.KeyEvent
.uChar
.UnicodeChar
= UnicodeChar
;
1284 er
.Event
.KeyEvent
.dwControlKeyState
= ShiftState
;
1285 er
.Event
.KeyEvent
.wVirtualKeyCode
= VirtualKeyCode
;
1286 er
.Event
.KeyEvent
.wVirtualScanCode
= VirtualScanCode
;
1290 if (0 != (ShiftState
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
1291 && VK_TAB
== VirtualKeyCode
)
1295 TuiSwapConsole(ShiftState
& SHIFT_PRESSED
? -1 : 1);
1300 else if (VK_MENU
== VirtualKeyCode
&& ! Down
)
1302 if (TuiSwapConsole(0))
1309 if (NULL
== Console
)
1314 ConInRec
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
1316 if (NULL
== ConInRec
)
1321 ConInRec
->InputEvent
= er
;
1322 ConInRec
->Fake
= UnicodeChar
&&
1323 (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
&&
1324 msg
->message
!= WM_KEYUP
&& msg
->message
!= WM_SYSKEYUP
);
1325 ConInRec
->NotChar
= (msg
->message
!= WM_CHAR
&& msg
->message
!= WM_SYSCHAR
);
1326 ConInRec
->Echoed
= FALSE
;
1327 if (ConInRec
->NotChar
)
1328 LastVirtualKey
= msg
->wParam
;
1330 DPRINT ("csrss: %s %s %s %s %02x %02x '%c' %04x\n",
1331 Down
? "down" : "up ",
1332 (msg
->message
== WM_CHAR
|| msg
->message
== WM_SYSCHAR
) ?
1334 ConInRec
->Fake
? "fake" : "real",
1335 ConInRec
->NotChar
? "notc" : "char",
1338 (AsciiChar
>= ' ') ? AsciiChar
: '.',
1341 if (! ConInRec
->Fake
|| ! ConInRec
->NotChar
)
1343 /* FIXME - convert to ascii */
1344 ConioProcessChar(Console
, ConInRec
);
1348 HeapFree(Win32CsrApiHeap
, 0, ConInRec
);
1352 CSR_API(CsrGetScreenBufferInfo
)
1355 PCSRSS_SCREEN_BUFFER Buff
;
1356 PCONSOLE_SCREEN_BUFFER_INFO pInfo
;
1358 DPRINT("CsrGetScreenBufferInfo\n");
1360 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1361 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1363 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ScreenBufferInfoRequest
.ConsoleHandle
, &Buff
);
1364 if (! NT_SUCCESS(Status
))
1366 return Request
->Status
= Status
;
1368 pInfo
= &Request
->Data
.ScreenBufferInfoRequest
.Info
;
1369 pInfo
->dwSize
.X
= Buff
->MaxX
;
1370 pInfo
->dwSize
.Y
= Buff
->MaxY
;
1371 pInfo
->dwCursorPosition
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1372 pInfo
->dwCursorPosition
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1373 pInfo
->wAttributes
= Buff
->DefaultAttrib
;
1374 pInfo
->srWindow
.Left
= 0;
1375 pInfo
->srWindow
.Right
= Buff
->MaxX
- 1;
1376 pInfo
->srWindow
.Top
= 0;
1377 pInfo
->srWindow
.Bottom
= Buff
->MaxY
- 1;
1378 pInfo
->dwMaximumWindowSize
.X
= Buff
->MaxX
;
1379 pInfo
->dwMaximumWindowSize
.Y
= Buff
->MaxY
;
1380 ConioUnlockScreenBuffer(Buff
);
1382 Request
->Status
= STATUS_SUCCESS
;
1384 return Request
->Status
;
1387 CSR_API(CsrSetCursor
)
1390 PCSRSS_CONSOLE Console
;
1391 PCSRSS_SCREEN_BUFFER Buff
;
1392 LONG OldCursorX
, OldCursorY
;
1393 LONG NewCursorX
, NewCursorY
;
1395 DPRINT("CsrSetCursor\n");
1397 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1398 if (! NT_SUCCESS(Status
))
1400 return Request
->Status
= Status
;
1403 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1404 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1406 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
);
1407 if (! NT_SUCCESS(Status
))
1409 if (NULL
!= Console
)
1411 ConioUnlockConsole(Console
);
1413 return Request
->Status
= Status
;
1416 NewCursorX
= Request
->Data
.SetCursorRequest
.Position
.X
;
1417 NewCursorY
= Request
->Data
.SetCursorRequest
.Position
.Y
;
1418 if (NewCursorX
< 0 || NewCursorX
>= Buff
->MaxX
||
1419 NewCursorY
< 0 || NewCursorY
>= Buff
->MaxY
)
1421 ConioUnlockScreenBuffer(Buff
);
1422 if (NULL
!= Console
)
1424 ConioUnlockConsole(Console
);
1426 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1428 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &OldCursorX
, &OldCursorY
);
1429 Buff
->CurrentX
= NewCursorX
+ Buff
->ShowX
;
1430 Buff
->CurrentY
= (NewCursorY
+ Buff
->ShowY
) % Buff
->MaxY
;
1431 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1433 if (! ConioSetScreenInfo(Console
, Buff
, OldCursorX
, OldCursorY
))
1435 ConioUnlockScreenBuffer(Buff
);
1436 if (NULL
!= Console
)
1438 ConioUnlockConsole(Console
);
1440 return Request
->Status
= STATUS_UNSUCCESSFUL
;
1444 ConioUnlockScreenBuffer(Buff
);
1445 if (NULL
!= Console
)
1447 ConioUnlockConsole(Console
);
1450 return Request
->Status
= STATUS_SUCCESS
;
1453 static VOID FASTCALL
1454 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff
, RECT
*UpdateRect
, COORD
*Start
, UINT Length
)
1456 if (Buff
->MaxX
<= Start
->X
+ Length
)
1458 UpdateRect
->left
= 0;
1462 UpdateRect
->left
= Start
->X
;
1464 if (Buff
->MaxX
<= Start
->X
+ Length
)
1466 UpdateRect
->right
= Buff
->MaxX
- 1;
1470 UpdateRect
->right
= Start
->X
+ Length
- 1;
1472 UpdateRect
->top
= Start
->Y
;
1473 UpdateRect
->bottom
= Start
->Y
+ (Start
->X
+ Length
- 1) / Buff
->MaxX
;
1474 if (Buff
->MaxY
<= UpdateRect
->bottom
)
1476 UpdateRect
->bottom
= Buff
->MaxY
- 1;
1480 CSR_API(CsrWriteConsoleOutputChar
)
1483 PCHAR String
, tmpString
= NULL
;
1485 PCSRSS_CONSOLE Console
;
1486 PCSRSS_SCREEN_BUFFER Buff
;
1487 DWORD X
, Y
, Length
, CharSize
, Written
= 0;
1490 DPRINT("CsrWriteConsoleOutputChar\n");
1492 CharSize
= (Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
1494 if (Request
->Header
.u1
.s1
.TotalLength
1495 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR
)
1496 + (Request
->Data
.WriteConsoleOutputCharRequest
.Length
* CharSize
))
1498 DPRINT1("Invalid request size\n");
1499 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1500 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1501 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1504 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1505 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1506 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1507 if (NT_SUCCESS(Status
))
1509 if(Request
->Data
.WriteConsoleOutputCharRequest
.Unicode
)
1511 Length
= WideCharToMultiByte(Console
->OutputCodePage
, 0,
1512 (PWCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
,
1513 Request
->Data
.WriteConsoleOutputCharRequest
.Length
,
1514 NULL
, 0, NULL
, NULL
);
1515 tmpString
= String
= RtlAllocateHeap(GetProcessHeap(), 0, Length
);
1518 WideCharToMultiByte(Console
->OutputCodePage
, 0,
1519 (PWCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
,
1520 Request
->Data
.WriteConsoleOutputCharRequest
.Length
,
1521 String
, Length
, NULL
, NULL
);
1525 Status
= STATUS_NO_MEMORY
;
1530 String
= (PCHAR
)Request
->Data
.WriteConsoleOutputCharRequest
.String
;
1535 Status
= ConioLockScreenBuffer(ProcessData
,
1536 Request
->Data
.WriteConsoleOutputCharRequest
.ConsoleHandle
,
1538 if (NT_SUCCESS(Status
))
1540 X
= Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.X
+ Buff
->ShowX
;
1541 Y
= (Request
->Data
.WriteConsoleOutputCharRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1542 Length
= Request
->Data
.WriteConsoleOutputCharRequest
.Length
;
1543 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1546 *Buffer
= *String
++;
1549 if (++X
== Buff
->MaxX
)
1551 if (++Y
== Buff
->MaxY
)
1554 Buffer
= Buff
->Buffer
;
1559 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1561 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputCharRequest
.Coord
,
1562 Request
->Data
.WriteConsoleOutputCharRequest
.Length
);
1563 ConioDrawRegion(Console
, &UpdateRect
);
1566 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.X
= X
- Buff
->ShowX
;
1567 Request
->Data
.WriteConsoleOutputCharRequest
.EndCoord
.Y
= (Y
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1569 ConioUnlockScreenBuffer(Buff
);
1571 if (Request
->Data
.WriteConsoleRequest
.Unicode
)
1573 RtlFreeHeap(GetProcessHeap(), 0, tmpString
);
1576 if (NULL
!= Console
)
1578 ConioUnlockConsole(Console
);
1581 Request
->Data
.WriteConsoleOutputCharRequest
.NrCharactersWritten
= Written
;
1582 return Request
->Status
= Status
;
1585 CSR_API(CsrFillOutputChar
)
1588 PCSRSS_CONSOLE Console
;
1589 PCSRSS_SCREEN_BUFFER Buff
;
1590 DWORD X
, Y
, Length
, Written
= 0;
1595 DPRINT("CsrFillOutputChar\n");
1597 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1598 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1600 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1601 if (! NT_SUCCESS(Status
))
1603 return Request
->Status
= Status
;
1606 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputRequest
.ConsoleHandle
, &Buff
);
1607 if (! NT_SUCCESS(Status
))
1609 if (NULL
!= Console
)
1611 ConioUnlockConsole(Console
);
1613 return Request
->Status
= Status
;
1616 X
= Request
->Data
.FillOutputRequest
.Position
.X
+ Buff
->ShowX
;
1617 Y
= (Request
->Data
.FillOutputRequest
.Position
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1618 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
)];
1619 if(Request
->Data
.FillOutputRequest
.Unicode
)
1620 ConsoleUnicodeCharToAnsiChar(Console
, &Char
, &Request
->Data
.FillOutputRequest
.Char
.UnicodeChar
);
1622 Char
= Request
->Data
.FillOutputRequest
.Char
.AsciiChar
;
1623 Length
= Request
->Data
.FillOutputRequest
.Length
;
1629 if (++X
== Buff
->MaxX
)
1631 if (++Y
== Buff
->MaxY
)
1634 Buffer
= Buff
->Buffer
;
1640 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1642 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputRequest
.Position
,
1643 Request
->Data
.FillOutputRequest
.Length
);
1644 ConioDrawRegion(Console
, &UpdateRect
);
1647 ConioUnlockScreenBuffer(Buff
);
1648 if (NULL
!= Console
)
1650 ConioUnlockConsole(Console
);
1652 Length
= Request
->Data
.FillOutputRequest
.Length
;
1653 Request
->Data
.FillOutputRequest
.NrCharactersWritten
= Length
;
1654 return Request
->Status
;
1657 CSR_API(CsrReadInputEvent
)
1659 PLIST_ENTRY CurrentEntry
;
1660 PCSRSS_CONSOLE Console
;
1662 BOOLEAN Done
= FALSE
;
1663 ConsoleInput
*Input
;
1665 DPRINT("CsrReadInputEvent\n");
1667 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1668 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1669 Request
->Data
.ReadInputRequest
.Event
= ProcessData
->ConsoleEvent
;
1671 Status
= ConioLockConsole(ProcessData
, Request
->Data
.ReadInputRequest
.ConsoleHandle
, &Console
);
1672 if (! NT_SUCCESS(Status
))
1674 return Request
->Status
= Status
;
1677 /* only get input if there is any */
1678 CurrentEntry
= Console
->InputEvents
.Flink
;
1679 while (CurrentEntry
!= &Console
->InputEvents
)
1681 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
1682 CurrentEntry
= CurrentEntry
->Flink
;
1684 if (Done
&& !Input
->Fake
)
1686 Request
->Data
.ReadInputRequest
.MoreEvents
= TRUE
;
1690 RemoveEntryList(&Input
->ListEntry
);
1692 if (!Done
&& !Input
->Fake
)
1694 Request
->Data
.ReadInputRequest
.Input
= Input
->InputEvent
;
1695 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
1697 ConioInputEventToAnsi(Console
, &Request
->Data
.ReadInputRequest
.Input
);
1702 if (Input
->InputEvent
.EventType
== KEY_EVENT
)
1704 if (0 != (Console
->Mode
& ENABLE_LINE_INPUT
)
1705 && Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
1706 && '\r' == Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
1708 Console
->WaitingLines
--;
1710 Console
->WaitingChars
--;
1712 HeapFree(Win32CsrApiHeap
, 0, Input
);
1717 Status
= STATUS_SUCCESS
;
1718 Console
->EarlyReturn
= FALSE
;
1722 Status
= STATUS_PENDING
;
1723 Console
->EarlyReturn
= TRUE
; /* mark for early return */
1726 if (IsListEmpty(&Console
->InputEvents
))
1728 ResetEvent(Console
->ActiveEvent
);
1731 ConioUnlockConsole(Console
);
1733 return Request
->Status
= Status
;
1736 CSR_API(CsrWriteConsoleOutputAttrib
)
1738 PCSRSS_CONSOLE Console
;
1739 PCSRSS_SCREEN_BUFFER Buff
;
1746 DPRINT("CsrWriteConsoleOutputAttrib\n");
1748 if (Request
->Header
.u1
.s1
.TotalLength
1749 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB
)
1750 + Request
->Data
.WriteConsoleOutputAttribRequest
.Length
* sizeof(WORD
))
1752 DPRINT1("Invalid request size\n");
1753 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1754 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1755 return Request
->Status
= STATUS_INVALID_PARAMETER
;
1758 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1759 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1760 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1761 if (! NT_SUCCESS(Status
))
1763 return Request
->Status
= Status
;
1766 Status
= ConioLockScreenBuffer(ProcessData
,
1767 Request
->Data
.WriteConsoleOutputAttribRequest
.ConsoleHandle
,
1769 if (! NT_SUCCESS(Status
))
1771 if (NULL
!= Console
)
1773 ConioUnlockConsole(Console
);
1775 return Request
->Status
= Status
;
1778 X
= Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1779 Y
= (Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1780 Length
= Request
->Data
.WriteConsoleOutputAttribRequest
.Length
;
1781 Buffer
= &Buff
->Buffer
[2 * (Y
* Buff
->MaxX
+ X
) + 1];
1782 Attribute
= Request
->Data
.WriteConsoleOutputAttribRequest
.Attribute
;
1785 *Buffer
= (UCHAR
)(*Attribute
++);
1787 if (++X
== Buff
->MaxX
)
1789 if (++Y
== Buff
->MaxY
)
1792 Buffer
= Buff
->Buffer
+ 1;
1798 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1800 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
,
1801 Request
->Data
.WriteConsoleOutputAttribRequest
.Length
);
1802 ConioDrawRegion(Console
, &UpdateRect
);
1805 if (NULL
!= Console
)
1807 ConioUnlockConsole(Console
);
1810 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.X
= Buff
->CurrentX
- Buff
->ShowX
;
1811 Request
->Data
.WriteConsoleOutputAttribRequest
.EndCoord
.Y
= (Buff
->CurrentY
+ Buff
->MaxY
- Buff
->ShowY
) % Buff
->MaxY
;
1813 ConioUnlockScreenBuffer(Buff
);
1815 return Request
->Status
= STATUS_SUCCESS
;
1818 CSR_API(CsrFillOutputAttrib
)
1820 PCSRSS_SCREEN_BUFFER Buff
;
1826 PCSRSS_CONSOLE Console
;
1828 DPRINT("CsrFillOutputAttrib\n");
1830 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1831 if (! NT_SUCCESS(Status
))
1833 return Request
->Status
= Status
;
1836 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1837 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1838 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.FillOutputAttribRequest
.ConsoleHandle
, &Buff
);
1839 if (! NT_SUCCESS(Status
))
1841 if (NULL
!= Console
)
1843 ConioUnlockConsole(Console
);
1845 return Request
->Status
= Status
;
1848 X
= Request
->Data
.FillOutputAttribRequest
.Coord
.X
+ Buff
->ShowX
;
1849 Y
= (Request
->Data
.FillOutputAttribRequest
.Coord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
1850 Length
= Request
->Data
.FillOutputAttribRequest
.Length
;
1851 Attr
= Request
->Data
.FillOutputAttribRequest
.Attribute
;
1852 Buffer
= &Buff
->Buffer
[(Y
* Buff
->MaxX
* 2) + (X
* 2) + 1];
1857 if (++X
== Buff
->MaxX
)
1859 if (++Y
== Buff
->MaxY
)
1862 Buffer
= Buff
->Buffer
+ 1;
1868 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1870 ConioComputeUpdateRect(Buff
, &UpdateRect
, &Request
->Data
.FillOutputAttribRequest
.Coord
,
1871 Request
->Data
.FillOutputAttribRequest
.Length
);
1872 ConioDrawRegion(Console
, &UpdateRect
);
1875 ConioUnlockScreenBuffer(Buff
);
1876 if (NULL
!= Console
)
1878 ConioUnlockConsole(Console
);
1881 return Request
->Status
= STATUS_SUCCESS
;
1885 CSR_API(CsrGetCursorInfo
)
1887 PCSRSS_SCREEN_BUFFER Buff
;
1890 DPRINT("CsrGetCursorInfo\n");
1892 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1893 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1895 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.GetCursorInfoRequest
.ConsoleHandle
, &Buff
);
1896 if (! NT_SUCCESS(Status
))
1898 return Request
->Status
= Status
;
1900 Request
->Data
.GetCursorInfoRequest
.Info
.bVisible
= Buff
->CursorInfo
.bVisible
;
1901 Request
->Data
.GetCursorInfoRequest
.Info
.dwSize
= Buff
->CursorInfo
.dwSize
;
1902 ConioUnlockScreenBuffer(Buff
);
1904 return Request
->Status
= STATUS_SUCCESS
;
1907 CSR_API(CsrSetCursorInfo
)
1909 PCSRSS_CONSOLE Console
;
1910 PCSRSS_SCREEN_BUFFER Buff
;
1915 DPRINT("CsrSetCursorInfo\n");
1917 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
1918 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
1920 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1921 if (! NT_SUCCESS(Status
))
1923 return Request
->Status
= Status
;
1926 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorInfoRequest
.ConsoleHandle
, &Buff
);
1927 if (! NT_SUCCESS(Status
))
1929 if (NULL
!= Console
)
1931 ConioUnlockConsole(Console
);
1933 return Request
->Status
= Status
;
1936 Size
= Request
->Data
.SetCursorInfoRequest
.Info
.dwSize
;
1937 Visible
= Request
->Data
.SetCursorInfoRequest
.Info
.bVisible
;
1947 if (Size
!= Buff
->CursorInfo
.dwSize
1948 || (Visible
&& ! Buff
->CursorInfo
.bVisible
) || (! Visible
&& Buff
->CursorInfo
.bVisible
))
1950 Buff
->CursorInfo
.dwSize
= Size
;
1951 Buff
->CursorInfo
.bVisible
= Visible
;
1953 if (NULL
!= Console
&& ! ConioSetCursorInfo(Console
, Buff
))
1955 ConioUnlockScreenBuffer(Buff
);
1956 ConioUnlockConsole(Console
);
1957 return Request
->Status
= STATUS_UNSUCCESSFUL
;
1961 ConioUnlockScreenBuffer(Buff
);
1962 if (NULL
!= Console
)
1964 ConioUnlockConsole(Console
);
1967 return Request
->Status
= STATUS_SUCCESS
;
1970 CSR_API(CsrSetTextAttrib
)
1973 PCSRSS_CONSOLE Console
;
1974 PCSRSS_SCREEN_BUFFER Buff
;
1976 DPRINT("CsrSetTextAttrib\n");
1978 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
1979 if (! NT_SUCCESS(Status
))
1981 return Request
->Status
= Status
;
1984 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, &Buff
);
1985 if (! NT_SUCCESS(Status
))
1987 if (NULL
!= Console
)
1989 ConioUnlockConsole(Console
);
1991 return Request
->Status
= Status
;
1994 Buff
->DefaultAttrib
= Request
->Data
.SetAttribRequest
.Attrib
;
1995 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
1997 if (! ConioUpdateScreenInfo(Console
, Buff
))
1999 ConioUnlockScreenBuffer(Buff
);
2000 ConioUnlockConsole(Console
);
2001 return Request
->Status
= STATUS_UNSUCCESSFUL
;
2005 ConioUnlockScreenBuffer(Buff
);
2006 if (NULL
!= Console
)
2008 ConioUnlockConsole(Console
);
2011 return Request
->Status
= STATUS_SUCCESS
;
2014 CSR_API(CsrSetConsoleMode
)
2017 PCSRSS_CONSOLE Console
;
2018 PCSRSS_SCREEN_BUFFER Buff
;
2020 DPRINT("CsrSetConsoleMode\n");
2022 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2023 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2024 Status
= Win32CsrGetObject(ProcessData
,
2025 Request
->Data
.SetConsoleModeRequest
.ConsoleHandle
,
2026 (Object_t
**) &Console
);
2027 if (! NT_SUCCESS(Status
))
2029 return Request
->Status
= Status
;
2032 Buff
= (PCSRSS_SCREEN_BUFFER
)Console
;
2033 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
2035 Console
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_INPUT_MODE_VALID
;
2037 else if (CONIO_SCREEN_BUFFER_MAGIC
== Console
->Header
.Type
)
2039 Buff
->Mode
= Request
->Data
.SetConsoleModeRequest
.Mode
& CONSOLE_OUTPUT_MODE_VALID
;
2043 return Request
->Status
= STATUS_INVALID_HANDLE
;
2046 Request
->Status
= STATUS_SUCCESS
;
2048 return Request
->Status
;
2051 CSR_API(CsrGetConsoleMode
)
2054 PCSRSS_CONSOLE Console
;
2055 PCSRSS_SCREEN_BUFFER Buff
; /* gee, I really wish I could use an anonymous union here */
2057 DPRINT("CsrGetConsoleMode\n");
2059 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2060 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2061 Status
= Win32CsrGetObject(ProcessData
, Request
->Data
.GetConsoleModeRequest
.ConsoleHandle
,
2062 (Object_t
**) &Console
);
2063 if (! NT_SUCCESS(Status
))
2065 return Request
->Status
= Status
;
2067 Request
->Status
= STATUS_SUCCESS
;
2068 Buff
= (PCSRSS_SCREEN_BUFFER
) Console
;
2069 if (CONIO_CONSOLE_MAGIC
== Console
->Header
.Type
)
2071 Request
->Data
.GetConsoleModeRequest
.ConsoleMode
= Console
->Mode
;
2073 else if (CONIO_SCREEN_BUFFER_MAGIC
== Buff
->Header
.Type
)
2075 Request
->Data
.GetConsoleModeRequest
.ConsoleMode
= Buff
->Mode
;
2079 Request
->Status
= STATUS_INVALID_HANDLE
;
2082 return Request
->Status
;
2085 CSR_API(CsrCreateScreenBuffer
)
2087 PCSRSS_CONSOLE Console
;
2088 PCSRSS_SCREEN_BUFFER Buff
;
2091 DPRINT("CsrCreateScreenBuffer\n");
2093 if (ProcessData
== NULL
)
2095 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2098 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2099 if (! NT_SUCCESS(Status
))
2101 return Request
->Status
= Status
;
2103 if (NULL
== Console
)
2105 return Request
->Status
= STATUS_INVALID_HANDLE
;
2108 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2109 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2111 Buff
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
, sizeof(CSRSS_SCREEN_BUFFER
));
2115 if (Console
->ActiveBuffer
)
2117 Buff
->MaxX
= Console
->ActiveBuffer
->MaxX
;
2118 Buff
->MaxY
= Console
->ActiveBuffer
->MaxY
;
2119 Buff
->CursorInfo
.bVisible
= Console
->ActiveBuffer
->CursorInfo
.bVisible
;
2120 Buff
->CursorInfo
.dwSize
= Console
->ActiveBuffer
->CursorInfo
.dwSize
;
2124 Buff
->CursorInfo
.bVisible
= TRUE
;
2125 Buff
->CursorInfo
.dwSize
= 5;
2128 if (Buff
->MaxX
== 0)
2133 if (Buff
->MaxY
== 0)
2138 Status
= CsrInitConsoleScreenBuffer(Console
, Buff
);
2139 if(! NT_SUCCESS(Status
))
2141 Request
->Status
= Status
;
2145 Request
->Status
= Win32CsrInsertObject(ProcessData
, &Request
->Data
.CreateScreenBufferRequest
.OutputHandle
, &Buff
->Header
);
2150 Request
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2153 ConioUnlockConsole(Console
);
2154 return Request
->Status
;
2157 CSR_API(CsrSetScreenBuffer
)
2160 PCSRSS_CONSOLE Console
;
2161 PCSRSS_SCREEN_BUFFER Buff
;
2163 DPRINT("CsrSetScreenBuffer\n");
2165 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2166 if (! NT_SUCCESS(Status
))
2168 return Request
->Status
= Status
;
2170 if (NULL
== Console
)
2172 DPRINT1("Trying to set screen buffer for app without console\n");
2173 return Request
->Status
= STATUS_INVALID_HANDLE
;
2176 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2177 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2179 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.SetScreenBufferRequest
.OutputHandle
, &Buff
);
2180 if (! NT_SUCCESS(Status
))
2182 ConioUnlockConsole(Console
);
2183 return Request
->Status
= Status
;
2186 if (Buff
== Console
->ActiveBuffer
)
2188 ConioUnlockScreenBuffer(Buff
);
2189 ConioUnlockConsole(Console
);
2190 return Request
->Status
= STATUS_SUCCESS
;
2193 /* drop reference to old buffer, maybe delete */
2194 if (! InterlockedDecrement(&Console
->ActiveBuffer
->Header
.ReferenceCount
))
2196 ConioDeleteScreenBuffer((Object_t
*) Console
->ActiveBuffer
);
2198 /* tie console to new buffer */
2199 Console
->ActiveBuffer
= Buff
;
2200 Console
->hActiveBuffer
= Request
->Data
.SetScreenBufferRequest
.OutputHandle
;
2201 /* inc ref count on new buffer */
2202 InterlockedIncrement(&Buff
->Header
.ReferenceCount
);
2203 /* Redraw the console */
2204 ConioDrawConsole(Console
);
2206 ConioUnlockScreenBuffer(Buff
);
2207 ConioUnlockConsole(Console
);
2209 return Request
->Status
= STATUS_SUCCESS
;
2212 CSR_API(CsrSetTitle
)
2215 PCSRSS_CONSOLE Console
;
2218 DPRINT("CsrSetTitle\n");
2220 if (Request
->Header
.u1
.s1
.TotalLength
2221 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_SET_TITLE
)
2222 + Request
->Data
.SetTitleRequest
.Length
)
2224 DPRINT1("Invalid request size\n");
2225 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2226 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2227 return Request
->Status
= STATUS_INVALID_PARAMETER
;
2230 Status
= ConioLockConsole(ProcessData
, Request
->Data
.SetTitleRequest
.Console
, &Console
);
2231 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2232 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2233 if(! NT_SUCCESS(Status
))
2235 Request
->Status
= Status
;
2239 Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, Request
->Data
.SetTitleRequest
.Length
);
2242 /* copy title to console */
2243 RtlFreeUnicodeString(&Console
->Title
);
2244 Console
->Title
.Buffer
= Buffer
;
2245 Console
->Title
.Length
= Console
->Title
.MaximumLength
= Request
->Data
.SetTitleRequest
.Length
;
2246 memcpy(Console
->Title
.Buffer
, Request
->Data
.SetTitleRequest
.Title
, Console
->Title
.Length
);
2247 if (! ConioChangeTitle(Console
))
2249 Request
->Status
= STATUS_UNSUCCESSFUL
;
2253 Request
->Status
= STATUS_SUCCESS
;
2258 Request
->Status
= STATUS_NO_MEMORY
;
2261 ConioUnlockConsole(Console
);
2263 return Request
->Status
;
2266 CSR_API(CsrGetTitle
)
2269 PCSRSS_CONSOLE Console
;
2272 DPRINT("CsrGetTitle\n");
2274 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2275 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2276 Status
= ConioLockConsole(ProcessData
,
2277 Request
->Data
.GetTitleRequest
.ConsoleHandle
,
2279 if (! NT_SUCCESS(Status
))
2281 DPRINT1("Can't get console\n");
2282 return Request
->Status
= Status
;
2285 /* Copy title of the console to the user title buffer */
2286 RtlZeroMemory(&Request
->Data
.GetTitleRequest
, sizeof(CSRSS_GET_TITLE
));
2287 Request
->Data
.GetTitleRequest
.ConsoleHandle
= Request
->Data
.GetTitleRequest
.ConsoleHandle
;
2288 Request
->Data
.GetTitleRequest
.Length
= Console
->Title
.Length
;
2289 memcpy (Request
->Data
.GetTitleRequest
.Title
, Console
->Title
.Buffer
,
2290 Console
->Title
.Length
);
2291 Length
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_SET_TITLE
) + Console
->Title
.Length
;
2293 ConioUnlockConsole(Console
);
2295 if (Length
> sizeof(CSR_API_MESSAGE
))
2297 Request
->Header
.u1
.s1
.TotalLength
= Length
;
2298 Request
->Header
.u1
.s1
.DataLength
= Length
- sizeof(PORT_MESSAGE
);
2300 Request
->Status
= STATUS_SUCCESS
;
2302 return Request
->Status
;
2305 CSR_API(CsrWriteConsoleOutput
)
2307 SHORT i
, X
, Y
, SizeX
, SizeY
;
2308 PCSRSS_CONSOLE Console
;
2309 PCSRSS_SCREEN_BUFFER Buff
;
2311 CHAR_INFO
* CurCharInfo
;
2313 CHAR_INFO
* CharInfo
;
2320 DPRINT("CsrWriteConsoleOutput\n");
2322 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2323 if (! NT_SUCCESS(Status
))
2325 return Request
->Status
= Status
;
2328 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2329 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2330 Status
= ConioLockScreenBuffer(ProcessData
,
2331 Request
->Data
.WriteConsoleOutputRequest
.ConsoleHandle
,
2333 if (! NT_SUCCESS(Status
))
2335 if (NULL
!= Console
)
2337 ConioUnlockConsole(Console
);
2339 return Request
->Status
= Status
;
2342 BufferSize
= Request
->Data
.WriteConsoleOutputRequest
.BufferSize
;
2343 PSize
= BufferSize
.X
* BufferSize
.Y
* sizeof(CHAR_INFO
);
2344 BufferCoord
= Request
->Data
.WriteConsoleOutputRequest
.BufferCoord
;
2345 CharInfo
= Request
->Data
.WriteConsoleOutputRequest
.CharInfo
;
2346 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
) ||
2347 (((ULONG_PTR
)CharInfo
+ PSize
) >
2348 ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2350 ConioUnlockScreenBuffer(Buff
);
2351 ConioUnlockConsole(Console
);
2352 return Request
->Status
= STATUS_ACCESS_VIOLATION
;
2354 WriteRegion
.left
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
;
2355 WriteRegion
.top
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
;
2356 WriteRegion
.right
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
;
2357 WriteRegion
.bottom
= Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
;
2359 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&WriteRegion
));
2360 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&WriteRegion
));
2361 WriteRegion
.bottom
= WriteRegion
.top
+ SizeY
- 1;
2362 WriteRegion
.right
= WriteRegion
.left
+ SizeX
- 1;
2364 /* Make sure WriteRegion is inside the screen buffer */
2365 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2366 if (! ConioGetIntersection(&WriteRegion
, &ScreenBuffer
, &WriteRegion
))
2368 ConioUnlockScreenBuffer(Buff
);
2369 ConioUnlockConsole(Console
);
2371 /* It is okay to have a WriteRegion completely outside the screen buffer.
2372 No data is written then. */
2373 return Request
->Status
= STATUS_SUCCESS
;
2376 for (i
= 0, Y
= WriteRegion
.top
; Y
<= WriteRegion
.bottom
; i
++, Y
++)
2378 CurCharInfo
= CharInfo
+ (i
+ BufferCoord
.Y
) * BufferSize
.X
+ BufferCoord
.X
;
2379 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ WriteRegion
.left
) * 2;
2380 for (X
= WriteRegion
.left
; X
<= WriteRegion
.right
; X
++)
2382 if (Request
->Data
.WriteConsoleOutputRequest
.Unicode
)
2385 ConsoleUnicodeCharToAnsiChar(Console
, &AsciiChar
, &CurCharInfo
->Char
.UnicodeChar
);
2386 SET_CELL_BUFFER(Buff
, Offset
, AsciiChar
, CurCharInfo
->Attributes
);
2390 SET_CELL_BUFFER(Buff
, Offset
, CurCharInfo
->Char
.AsciiChar
, CurCharInfo
->Attributes
);
2396 if (NULL
!= Console
)
2398 ConioDrawRegion(Console
, &WriteRegion
);
2401 ConioUnlockScreenBuffer(Buff
);
2402 ConioUnlockConsole(Console
);
2404 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Right
= WriteRegion
.left
+ SizeX
- 1;
2405 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Bottom
= WriteRegion
.top
+ SizeY
- 1;
2406 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Left
= WriteRegion
.left
;
2407 Request
->Data
.WriteConsoleOutputRequest
.WriteRegion
.Top
= WriteRegion
.top
;
2409 return Request
->Status
= STATUS_SUCCESS
;
2412 CSR_API(CsrFlushInputBuffer
)
2414 PLIST_ENTRY CurrentEntry
;
2415 PCSRSS_CONSOLE Console
;
2416 ConsoleInput
* Input
;
2419 DPRINT("CsrFlushInputBuffer\n");
2421 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2422 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2423 Status
= ConioLockConsole(ProcessData
,
2424 Request
->Data
.FlushInputBufferRequest
.ConsoleInput
,
2426 if(! NT_SUCCESS(Status
))
2428 return Request
->Status
= Status
;
2431 /* Discard all entries in the input event queue */
2432 while (!IsListEmpty(&Console
->InputEvents
))
2434 CurrentEntry
= RemoveHeadList(&Console
->InputEvents
);
2435 Input
= CONTAINING_RECORD(CurrentEntry
, ConsoleInput
, ListEntry
);
2436 /* Destroy the event */
2437 HeapFree(Win32CsrApiHeap
, 0, Input
);
2439 ResetEvent(Console
->ActiveEvent
);
2440 Console
->WaitingChars
=0;
2442 ConioUnlockConsole(Console
);
2444 return Request
->Status
= STATUS_SUCCESS
;
2447 CSR_API(CsrScrollConsoleScreenBuffer
)
2449 PCSRSS_CONSOLE Console
;
2450 PCSRSS_SCREEN_BUFFER Buff
;
2455 RECT ScrollRectangle
;
2458 HANDLE ConsoleHandle
;
2459 BOOLEAN UseClipRectangle
;
2460 COORD DestinationOrigin
;
2464 DPRINT("CsrScrollConsoleScreenBuffer\n");
2466 ConsoleHandle
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ConsoleHandle
;
2467 UseClipRectangle
= Request
->Data
.ScrollConsoleScreenBufferRequest
.UseClipRectangle
;
2468 DestinationOrigin
= Request
->Data
.ScrollConsoleScreenBufferRequest
.DestinationOrigin
;
2469 Fill
= Request
->Data
.ScrollConsoleScreenBufferRequest
.Fill
;
2471 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2472 if (! NT_SUCCESS(Status
))
2474 return Request
->Status
= Status
;
2477 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2478 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2479 Status
= ConioLockScreenBuffer(ProcessData
, ConsoleHandle
, &Buff
);
2480 if (! NT_SUCCESS(Status
))
2482 if (NULL
!= Console
)
2484 ConioUnlockConsole(Console
);
2486 return Request
->Status
= Status
;
2489 ScrollRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Left
;
2490 ScrollRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Top
;
2491 ScrollRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Right
;
2492 ScrollRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ScrollRectangle
.Bottom
;
2494 /* Make sure source rectangle is inside the screen buffer */
2495 ConioInitRect(&ScreenBuffer
, 0, 0, Buff
->MaxY
- 1, Buff
->MaxX
- 1);
2496 if (! ConioGetIntersection(&SrcRegion
, &ScreenBuffer
, &ScrollRectangle
))
2498 ConioUnlockScreenBuffer(Buff
);
2499 if (NULL
!= Console
)
2501 ConioUnlockConsole(Console
);
2503 return Request
->Status
= STATUS_SUCCESS
;
2506 /* If the source was clipped on the left or top, adjust the destination accordingly */
2507 if (ScrollRectangle
.left
< 0)
2509 DestinationOrigin
.X
-= ScrollRectangle
.left
;
2511 if (ScrollRectangle
.top
< 0)
2513 DestinationOrigin
.Y
-= ScrollRectangle
.top
;
2516 if (UseClipRectangle
)
2518 ClipRectangle
.left
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Left
;
2519 ClipRectangle
.top
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Top
;
2520 ClipRectangle
.right
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Right
;
2521 ClipRectangle
.bottom
= Request
->Data
.ScrollConsoleScreenBufferRequest
.ClipRectangle
.Bottom
;
2522 if (!ConioGetIntersection(&ClipRectangle
, &ClipRectangle
, &ScreenBuffer
))
2524 if (NULL
!= Console
)
2526 ConioUnlockConsole(Console
);
2528 ConioUnlockScreenBuffer(Buff
);
2529 return Request
->Status
= STATUS_SUCCESS
;
2534 ClipRectangle
= ScreenBuffer
;
2537 ConioInitRect(&DstRegion
,
2538 DestinationOrigin
.Y
,
2539 DestinationOrigin
.X
,
2540 DestinationOrigin
.Y
+ ConioRectHeight(&SrcRegion
) - 1,
2541 DestinationOrigin
.X
+ ConioRectWidth(&SrcRegion
) - 1);
2543 if (Request
->Data
.ScrollConsoleScreenBufferRequest
.Unicode
)
2544 ConsoleUnicodeCharToAnsiChar(Console
, &FillChar
, &Fill
.Char
.UnicodeChar
);
2546 FillChar
= Fill
.Char
.AsciiChar
;
2548 ConioMoveRegion(Buff
, &SrcRegion
, &DstRegion
, &ClipRectangle
, Fill
.Attributes
<< 8 | (BYTE
)FillChar
);
2550 if (NULL
!= Console
&& Buff
== Console
->ActiveBuffer
)
2552 ConioGetUnion(&UpdateRegion
, &SrcRegion
, &DstRegion
);
2553 if (ConioGetIntersection(&UpdateRegion
, &UpdateRegion
, &ClipRectangle
))
2555 /* Draw update region */
2556 ConioDrawRegion(Console
, &UpdateRegion
);
2560 ConioUnlockScreenBuffer(Buff
);
2561 if (NULL
!= Console
)
2563 ConioUnlockConsole(Console
);
2566 return Request
->Status
= STATUS_SUCCESS
;
2569 CSR_API(CsrReadConsoleOutputChar
)
2572 PCSRSS_CONSOLE Console
;
2573 PCSRSS_SCREEN_BUFFER Buff
;
2580 DPRINT("CsrReadConsoleOutputChar\n");
2582 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2583 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2584 ReadBuffer
= Request
->Data
.ReadConsoleOutputCharRequest
.String
;
2586 CharSize
= (Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
? sizeof(WCHAR
) : sizeof(CHAR
));
2588 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
2589 if (! NT_SUCCESS(Status
))
2591 return Request
->Status
= Status
;
2594 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputCharRequest
.ConsoleHandle
, &Buff
);
2595 if (! NT_SUCCESS(Status
))
2597 if (NULL
!= Console
)
2599 ConioUnlockConsole(Console
);
2601 return Request
->Status
= Status
;
2604 Xpos
= Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.X
+ Buff
->ShowX
;
2605 Ypos
= (Request
->Data
.ReadConsoleOutputCharRequest
.ReadCoord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
2607 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputCharRequest
.NumCharsToRead
; ++i
)
2609 Char
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
)];
2611 if(Request
->Data
.ReadConsoleOutputCharRequest
.Unicode
)
2613 ConsoleAnsiCharToUnicodeChar(Console
, (WCHAR
*)ReadBuffer
, &Char
);
2614 ReadBuffer
+= sizeof(WCHAR
);
2617 *(ReadBuffer
++) = Char
;
2621 if (Xpos
== Buff
->MaxX
)
2626 if (Ypos
== Buff
->MaxY
)
2634 Request
->Status
= STATUS_SUCCESS
;
2635 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.X
= Xpos
- Buff
->ShowX
;
2636 Request
->Data
.ReadConsoleOutputCharRequest
.EndCoord
.Y
= (Ypos
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
;
2638 ConioUnlockScreenBuffer(Buff
);
2639 if (NULL
!= Console
)
2641 ConioUnlockConsole(Console
);
2644 Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
= (DWORD
)((ULONG_PTR
)ReadBuffer
- (ULONG_PTR
)Request
->Data
.ReadConsoleOutputCharRequest
.String
) / CharSize
;
2645 if (Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
* CharSize
+ CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR
) > sizeof(CSR_API_MESSAGE
))
2647 Request
->Header
.u1
.s1
.TotalLength
= Request
->Data
.ReadConsoleOutputCharRequest
.CharsRead
* CharSize
+ CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR
);
2648 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2651 return Request
->Status
;
2655 CSR_API(CsrReadConsoleOutputAttrib
)
2658 PCSRSS_SCREEN_BUFFER Buff
;
2662 DWORD CurrentLength
;
2664 DPRINT("CsrReadConsoleOutputAttrib\n");
2666 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2667 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2668 ReadBuffer
= Request
->Data
.ReadConsoleOutputAttribRequest
.Attribute
;
2670 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputAttribRequest
.ConsoleHandle
, &Buff
);
2671 if (! NT_SUCCESS(Status
))
2673 return Request
->Status
= Status
;
2676 Xpos
= Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.X
+ Buff
->ShowX
;
2677 Ypos
= (Request
->Data
.ReadConsoleOutputAttribRequest
.ReadCoord
.Y
+ Buff
->ShowY
) % Buff
->MaxY
;
2679 for (i
= 0; i
< Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
; ++i
)
2681 *ReadBuffer
= Buff
->Buffer
[(Xpos
* 2) + (Ypos
* 2 * Buff
->MaxX
) + 1];
2686 if (Xpos
== Buff
->MaxX
)
2691 if (Ypos
== Buff
->MaxY
)
2700 Request
->Status
= STATUS_SUCCESS
;
2701 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.X
= Xpos
- Buff
->ShowX
;
2702 Request
->Data
.ReadConsoleOutputAttribRequest
.EndCoord
.Y
= (Ypos
- Buff
->ShowY
+ Buff
->MaxY
) % Buff
->MaxY
;
2704 ConioUnlockScreenBuffer(Buff
);
2706 CurrentLength
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_ATTRIB
)
2707 + Request
->Data
.ReadConsoleOutputAttribRequest
.NumAttrsToRead
* sizeof(WORD
);
2708 if (CurrentLength
> sizeof(CSR_API_MESSAGE
))
2710 Request
->Header
.u1
.s1
.TotalLength
= CurrentLength
;
2711 Request
->Header
.u1
.s1
.DataLength
= CurrentLength
- sizeof(PORT_MESSAGE
);
2714 return Request
->Status
;
2718 CSR_API(CsrGetNumberOfConsoleInputEvents
)
2721 PCSRSS_CONSOLE Console
;
2722 PLIST_ENTRY CurrentItem
;
2724 ConsoleInput
*Input
;
2726 DPRINT("CsrGetNumberOfConsoleInputEvents\n");
2728 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2729 Request
->Header
.u1
.s1
.DataLength
= Request
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
2731 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
);
2732 if (! NT_SUCCESS(Status
))
2734 return Request
->Status
= Status
;
2737 CurrentItem
= Console
->InputEvents
.Flink
;
2740 /* If there are any events ... */
2741 while (CurrentItem
!= &Console
->InputEvents
)
2743 Input
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2744 CurrentItem
= CurrentItem
->Flink
;
2751 ConioUnlockConsole(Console
);
2753 Request
->Status
= STATUS_SUCCESS
;
2754 Request
->Data
.GetNumInputEventsRequest
.NumInputEvents
= NumEvents
;
2756 return Request
->Status
;
2760 CSR_API(CsrPeekConsoleInput
)
2763 PCSRSS_CONSOLE Console
;
2766 PLIST_ENTRY CurrentItem
;
2767 PINPUT_RECORD InputRecord
;
2771 DPRINT("CsrPeekConsoleInput\n");
2773 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2774 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2776 Status
= ConioLockConsole(ProcessData
, Request
->Data
.GetNumInputEventsRequest
.ConsoleHandle
, &Console
);
2777 if(! NT_SUCCESS(Status
))
2779 return Request
->Status
= Status
;
2782 InputRecord
= Request
->Data
.PeekConsoleInputRequest
.InputRecord
;
2783 Length
= Request
->Data
.PeekConsoleInputRequest
.Length
;
2784 Size
= Length
* sizeof(INPUT_RECORD
);
2786 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2787 || (((ULONG_PTR
)InputRecord
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2789 ConioUnlockConsole(Console
);
2790 Request
->Status
= STATUS_ACCESS_VIOLATION
;
2791 return Request
->Status
;
2796 if (! IsListEmpty(&Console
->InputEvents
))
2798 CurrentItem
= Console
->InputEvents
.Flink
;
2800 while (CurrentItem
!= &Console
->InputEvents
&& NumItems
< Length
)
2802 Item
= CONTAINING_RECORD(CurrentItem
, ConsoleInput
, ListEntry
);
2806 CurrentItem
= CurrentItem
->Flink
;
2811 *InputRecord
= Item
->InputEvent
;
2813 if (Request
->Data
.ReadInputRequest
.Unicode
== FALSE
)
2815 ConioInputEventToAnsi(Console
, InputRecord
);
2819 CurrentItem
= CurrentItem
->Flink
;
2823 ConioUnlockConsole(Console
);
2825 Request
->Status
= STATUS_SUCCESS
;
2826 Request
->Data
.PeekConsoleInputRequest
.Length
= NumItems
;
2828 return Request
->Status
;
2832 CSR_API(CsrReadConsoleOutput
)
2834 PCHAR_INFO CharInfo
;
2835 PCHAR_INFO CurCharInfo
;
2836 PCSRSS_SCREEN_BUFFER Buff
;
2849 DPRINT("CsrReadConsoleOutput\n");
2851 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2852 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2854 Status
= ConioLockScreenBuffer(ProcessData
, Request
->Data
.ReadConsoleOutputRequest
.ConsoleHandle
, &Buff
);
2855 if (! NT_SUCCESS(Status
))
2857 return Request
->Status
= Status
;
2860 CharInfo
= Request
->Data
.ReadConsoleOutputRequest
.CharInfo
;
2861 ReadRegion
.left
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
;
2862 ReadRegion
.top
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
;
2863 ReadRegion
.right
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
;
2864 ReadRegion
.bottom
= Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
;
2865 BufferSize
= Request
->Data
.ReadConsoleOutputRequest
.BufferSize
;
2866 BufferCoord
= Request
->Data
.ReadConsoleOutputRequest
.BufferCoord
;
2867 Length
= BufferSize
.X
* BufferSize
.Y
;
2868 Size
= Length
* sizeof(CHAR_INFO
);
2870 /* FIXME: Is this correct? */
2871 CodePage
= ProcessData
->Console
->OutputCodePage
;
2873 if (((PVOID
)CharInfo
< ProcessData
->CsrSectionViewBase
)
2874 || (((ULONG_PTR
)CharInfo
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2876 ConioUnlockScreenBuffer(Buff
);
2877 Request
->Status
= STATUS_ACCESS_VIOLATION
;
2878 return Request
->Status
;
2881 SizeY
= min(BufferSize
.Y
- BufferCoord
.Y
, ConioRectHeight(&ReadRegion
));
2882 SizeX
= min(BufferSize
.X
- BufferCoord
.X
, ConioRectWidth(&ReadRegion
));
2883 ReadRegion
.bottom
= ReadRegion
.top
+ SizeY
;
2884 ReadRegion
.right
= ReadRegion
.left
+ SizeX
;
2886 ConioInitRect(&ScreenRect
, 0, 0, Buff
->MaxY
, Buff
->MaxX
);
2887 if (! ConioGetIntersection(&ReadRegion
, &ScreenRect
, &ReadRegion
))
2889 ConioUnlockScreenBuffer(Buff
);
2890 Request
->Status
= STATUS_SUCCESS
;
2891 return Request
->Status
;
2894 for (i
= 0, Y
= ReadRegion
.top
; Y
< ReadRegion
.bottom
; ++i
, ++Y
)
2896 CurCharInfo
= CharInfo
+ (i
* BufferSize
.X
);
2898 Offset
= (((Y
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
+ ReadRegion
.left
) * 2;
2899 for (X
= ReadRegion
.left
; X
< ReadRegion
.right
; ++X
)
2901 if (Request
->Data
.ReadConsoleOutputRequest
.Unicode
)
2903 MultiByteToWideChar(CodePage
, 0,
2904 (PCHAR
)&GET_CELL_BUFFER(Buff
, Offset
), 1,
2905 &CurCharInfo
->Char
.UnicodeChar
, 1);
2909 CurCharInfo
->Char
.AsciiChar
= GET_CELL_BUFFER(Buff
, Offset
);
2911 CurCharInfo
->Attributes
= GET_CELL_BUFFER(Buff
, Offset
);
2916 ConioUnlockScreenBuffer(Buff
);
2918 Request
->Status
= STATUS_SUCCESS
;
2919 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Right
= ReadRegion
.left
+ SizeX
- 1;
2920 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Bottom
= ReadRegion
.top
+ SizeY
- 1;
2921 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Left
= ReadRegion
.left
;
2922 Request
->Data
.ReadConsoleOutputRequest
.ReadRegion
.Top
= ReadRegion
.top
;
2924 return Request
->Status
;
2928 CSR_API(CsrWriteConsoleInput
)
2930 PINPUT_RECORD InputRecord
;
2931 PCSRSS_CONSOLE Console
;
2936 ConsoleInput
* Record
;
2938 DPRINT("CsrWriteConsoleInput\n");
2940 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
2941 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
2943 Status
= ConioLockConsole(ProcessData
, Request
->Data
.WriteConsoleInputRequest
.ConsoleHandle
, &Console
);
2944 if (! NT_SUCCESS(Status
))
2946 return Request
->Status
= Status
;
2949 InputRecord
= Request
->Data
.WriteConsoleInputRequest
.InputRecord
;
2950 Length
= Request
->Data
.WriteConsoleInputRequest
.Length
;
2951 Size
= Length
* sizeof(INPUT_RECORD
);
2953 if (((PVOID
)InputRecord
< ProcessData
->CsrSectionViewBase
)
2954 || (((ULONG_PTR
)InputRecord
+ Size
) > ((ULONG_PTR
)ProcessData
->CsrSectionViewBase
+ ProcessData
->CsrSectionViewSize
)))
2956 ConioUnlockConsole(Console
);
2957 Request
->Status
= STATUS_ACCESS_VIOLATION
;
2958 return Request
->Status
;
2961 for (i
= 0; i
< Length
; i
++)
2963 Record
= HeapAlloc(Win32CsrApiHeap
, 0, sizeof(ConsoleInput
));
2966 ConioUnlockConsole(Console
);
2967 Request
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
2968 return Request
->Status
;
2971 Record
->Echoed
= FALSE
;
2972 Record
->Fake
= FALSE
;
2973 //Record->InputEvent = *InputRecord++;
2974 memcpy(&Record
->InputEvent
, &InputRecord
[i
], sizeof(INPUT_RECORD
));
2975 if (KEY_EVENT
== Record
->InputEvent
.EventType
)
2977 /* FIXME - convert from unicode to ascii!! */
2978 ConioProcessChar(Console
, Record
);
2982 ConioUnlockConsole(Console
);
2984 Request
->Status
= STATUS_SUCCESS
;
2985 Request
->Data
.WriteConsoleInputRequest
.Length
= i
;
2987 return Request
->Status
;
2990 /**********************************************************************
2991 * HardwareStateProperty
2994 * Set/Get the value of the HardwareState and switch
2995 * between direct video buffer ouput and GDI windowed
2998 * Client hands us a CSRSS_CONSOLE_HARDWARE_STATE
2999 * object. We use the same object to Request.
3001 * ConsoleHwState has the correct size to be compatible
3002 * with NT's, but values are not.
3004 static NTSTATUS FASTCALL
3005 SetConsoleHardwareState (PCSRSS_CONSOLE Console
, DWORD ConsoleHwState
)
3007 DPRINT1("Console Hardware State: %d\n", ConsoleHwState
);
3009 if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED
== ConsoleHwState
)
3010 ||(CONSOLE_HARDWARE_STATE_DIRECT
== ConsoleHwState
))
3012 if (Console
->HardwareState
!= ConsoleHwState
)
3014 /* TODO: implement switching from full screen to windowed mode */
3015 /* TODO: or back; now simply store the hardware state */
3016 Console
->HardwareState
= ConsoleHwState
;
3019 return STATUS_SUCCESS
;
3022 return STATUS_INVALID_PARAMETER_3
; /* Client: (handle, set_get, [mode]) */
3025 CSR_API(CsrHardwareStateProperty
)
3027 PCSRSS_CONSOLE Console
;
3030 DPRINT("CsrHardwareStateProperty\n");
3032 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3033 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3035 Status
= ConioLockConsole(ProcessData
,
3036 Request
->Data
.ConsoleHardwareStateRequest
.ConsoleHandle
,
3038 if (! NT_SUCCESS(Status
))
3040 DPRINT1("Failed to get console handle in SetConsoleHardwareState\n");
3041 return Request
->Status
= Status
;
3044 switch (Request
->Data
.ConsoleHardwareStateRequest
.SetGet
)
3046 case CONSOLE_HARDWARE_STATE_GET
:
3047 Request
->Data
.ConsoleHardwareStateRequest
.State
= Console
->HardwareState
;
3050 case CONSOLE_HARDWARE_STATE_SET
:
3051 DPRINT("Setting console hardware state.\n");
3052 Request
->Status
= SetConsoleHardwareState(Console
, Request
->Data
.ConsoleHardwareStateRequest
.State
);
3056 Request
->Status
= STATUS_INVALID_PARAMETER_2
; /* Client: (handle, [set_get], mode) */
3060 ConioUnlockConsole(Console
);
3062 return Request
->Status
;
3065 CSR_API(CsrGetConsoleWindow
)
3067 PCSRSS_CONSOLE Console
;
3070 DPRINT("CsrGetConsoleWindow\n");
3072 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3073 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3075 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3076 if (! NT_SUCCESS(Status
))
3078 return Request
->Status
= Status
;
3081 Request
->Data
.GetConsoleWindowRequest
.WindowHandle
= Console
->hWindow
;
3082 ConioUnlockConsole(Console
);
3084 return Request
->Status
= STATUS_SUCCESS
;
3087 CSR_API(CsrSetConsoleIcon
)
3089 PCSRSS_CONSOLE Console
;
3092 DPRINT("CsrSetConsoleIcon\n");
3094 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3095 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3097 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3098 if (! NT_SUCCESS(Status
))
3100 return Request
->Status
= Status
;
3103 Console
->hWindowIcon
= Request
->Data
.SetConsoleIconRequest
.WindowIcon
;
3104 Request
->Status
= (ConioChangeIcon(Console
) ? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
3105 ConioUnlockConsole(Console
);
3107 return Request
->Status
;
3110 CSR_API(CsrGetConsoleCodePage
)
3112 PCSRSS_CONSOLE Console
;
3115 DPRINT("CsrGetConsoleCodePage\n");
3117 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3118 if (! NT_SUCCESS(Status
))
3120 return Request
->Status
= Status
;
3123 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3124 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3125 Request
->Data
.GetConsoleCodePage
.CodePage
= Console
->CodePage
;
3126 ConioUnlockConsole(Console
);
3127 return Request
->Status
= STATUS_SUCCESS
;
3130 CSR_API(CsrSetConsoleCodePage
)
3132 PCSRSS_CONSOLE Console
;
3135 DPRINT("CsrSetConsoleCodePage\n");
3137 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3138 if (! NT_SUCCESS(Status
))
3140 return Request
->Status
= Status
;
3143 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3144 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3145 if (IsValidCodePage(Request
->Data
.SetConsoleCodePage
.CodePage
))
3147 Console
->CodePage
= Request
->Data
.SetConsoleCodePage
.CodePage
;
3148 ConioUnlockConsole(Console
);
3149 return Request
->Status
= STATUS_SUCCESS
;
3151 ConioUnlockConsole(Console
);
3152 return Request
->Status
= STATUS_UNSUCCESSFUL
;
3155 CSR_API(CsrGetConsoleOutputCodePage
)
3157 PCSRSS_CONSOLE Console
;
3160 DPRINT("CsrGetConsoleOutputCodePage\n");
3162 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3163 if (! NT_SUCCESS(Status
))
3165 return Request
->Status
= Status
;
3168 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3169 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3170 Request
->Data
.GetConsoleOutputCodePage
.CodePage
= Console
->OutputCodePage
;
3171 ConioUnlockConsole(Console
);
3172 return Request
->Status
= STATUS_SUCCESS
;
3175 CSR_API(CsrSetConsoleOutputCodePage
)
3177 PCSRSS_CONSOLE Console
;
3180 DPRINT("CsrSetConsoleOutputCodePage\n");
3182 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3183 if (! NT_SUCCESS(Status
))
3185 return Request
->Status
= Status
;
3188 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3189 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3190 if (IsValidCodePage(Request
->Data
.SetConsoleOutputCodePage
.CodePage
))
3192 Console
->OutputCodePage
= Request
->Data
.SetConsoleOutputCodePage
.CodePage
;
3193 ConioUnlockConsole(Console
);
3194 return Request
->Status
= STATUS_SUCCESS
;
3196 ConioUnlockConsole(Console
);
3197 return Request
->Status
= STATUS_UNSUCCESSFUL
;
3200 CSR_API(CsrGetProcessList
)
3203 PCSRSS_CONSOLE Console
;
3204 PCSRSS_PROCESS_DATA current
;
3205 PLIST_ENTRY current_entry
;
3206 ULONG nItems
, nCopied
, Length
;
3209 DPRINT("CsrGetProcessList\n");
3211 Buffer
= Request
->Data
.GetProcessListRequest
.ProcessId
;
3212 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
3213 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
3215 nItems
= nCopied
= 0;
3216 Request
->Data
.GetProcessListRequest
.nProcessIdsCopied
= 0;
3217 Request
->Data
.GetProcessListRequest
.nProcessIdsTotal
= 0;
3219 Status
= ConioConsoleFromProcessData(ProcessData
, &Console
);
3220 if (! NT_SUCCESS(Status
))
3222 return Request
->Status
= Status
;
3225 DPRINT1("Console_Api Ctrl-C\n");
3227 for(current_entry
= Console
->ProcessList
.Flink
;
3228 current_entry
!= &Console
->ProcessList
;
3229 current_entry
= current_entry
->Flink
)
3231 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
3232 if(++nItems
< Request
->Data
.GetProcessListRequest
.nMaxIds
)
3234 *(Buffer
++) = current
->ProcessId
;
3239 ConioUnlockConsole(Console
);
3241 Request
->Data
.GetProcessListRequest
.nProcessIdsCopied
= nCopied
;
3242 Request
->Data
.GetProcessListRequest
.nProcessIdsTotal
= nItems
;
3244 Length
= CSR_API_MESSAGE_HEADER_SIZE(CSRSS_GET_PROCESS_LIST
) + nCopied
* sizeof(HANDLE
);
3245 if (Length
> sizeof(CSR_API_MESSAGE
))
3247 Request
->Header
.u1
.s1
.TotalLength
= Length
;
3248 Request
->Header
.u1
.s1
.DataLength
= Length
- sizeof(PORT_MESSAGE
);
3250 return Request
->Status
= STATUS_SUCCESS
;