1 /* $Id: conio.c,v 1.12 2000/10/09 00:12:01 ekohl Exp $
3 * reactos/subsys/csrss/api/conio.c
5 * Console I/O functions
7 * ReactOS Operating System
10 /* INCLUDES ******************************************************************/
12 #include <ddk/ntddk.h>
14 #include <csrss/csrss.h>
16 #include <ntdll/rtl.h>
17 #include <ddk/ntddblue.h>
20 /* GLOBALS *******************************************************************/
22 static HANDLE ConsoleDeviceHandle
;
23 static HANDLE KeyboardDeviceHandle
;
24 static PCSRSS_CONSOLE ActiveConsole
;
25 CRITICAL_SECTION ActiveConsoleLock
;
26 static COORD PhysicalConsoleSize
;
28 /* FUNCTIONS *****************************************************************/
30 NTSTATUS
CsrAllocConsole(PCSRSS_PROCESS_DATA ProcessData
,
31 PCSRSS_API_REQUEST LpcMessage
,
32 PCSRSS_API_REPLY LpcReply
)
34 PCSRSS_CONSOLE Console
;
39 LpcReply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
40 LpcReply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
41 sizeof(LPC_MESSAGE_HEADER
);
42 if( ProcessData
->Console
)
44 LpcReply
->Status
= STATUS_INVALID_PARAMETER
;
45 return STATUS_INVALID_PARAMETER
;
47 LpcReply
->Status
= STATUS_SUCCESS
;
48 Console
= RtlAllocateHeap( CsrssApiHeap
, 0, sizeof( CSRSS_CONSOLE
) );
51 LpcReply
->Status
= STATUS_INSUFFICIENT_RESOURCES
;
52 return STATUS_INSUFFICIENT_RESOURCES
;
54 LpcReply
->Status
= CsrInitConsole( ProcessData
, Console
);
55 if( !NT_SUCCESS( LpcReply
->Status
) )
57 RtlFreeHeap( CsrssApiHeap
, 0, Console
);
58 return LpcReply
->Status
;
60 ProcessData
->Console
= Console
;
61 Console
->ReferenceCount
++;
62 CsrInsertObject( ProcessData
, &LpcReply
->Data
.AllocConsoleReply
.ConsoleHandle
, (Object_t
*)Console
);
63 ClientId
.UniqueProcess
= (HANDLE
)ProcessData
->ProcessId
;
64 Status
= NtOpenProcess( &Process
, PROCESS_DUP_HANDLE
, 0, &ClientId
);
65 if( !NT_SUCCESS( Status
) )
67 DbgPrint( "CSR: NtOpenProcess() failed for handle duplication\n" );
68 Console
->ReferenceCount
--;
69 ProcessData
->Console
= 0;
70 CsrReleaseObject( ProcessData
, LpcReply
->Data
.AllocConsoleReply
.ConsoleHandle
);
71 LpcReply
->Status
= Status
;
74 Status
= NtDuplicateObject( NtCurrentProcess(), &ProcessData
->Console
->ActiveEvent
, Process
, &ProcessData
->ConsoleEvent
, SYNCHRONIZE
, FALSE
, 0 );
75 if( !NT_SUCCESS( Status
) )
77 DbgPrint( "CSR: NtDuplicateObject() failed: %x\n", Status
);
79 Console
->ReferenceCount
--;
80 CsrReleaseObject( ProcessData
, LpcReply
->Data
.AllocConsoleReply
.ConsoleHandle
);
81 ProcessData
->Console
= 0;
82 LpcReply
->Status
= Status
;
86 return STATUS_SUCCESS
;
89 NTSTATUS
CsrFreeConsole(PCSRSS_PROCESS_DATA ProcessData
,
90 PCSRSS_API_REQUEST LpcMessage
,
91 PCSRSS_API_REPLY LpcReply
)
93 LpcReply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
94 LpcReply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
95 sizeof(LPC_MESSAGE_HEADER
);
97 LpcReply
->Status
= STATUS_NOT_IMPLEMENTED
;
99 return(STATUS_NOT_IMPLEMENTED
);
102 NTSTATUS
CsrReadConsole(PCSRSS_PROCESS_DATA ProcessData
,
103 PCSRSS_API_REQUEST LpcMessage
,
104 PCSRSS_API_REPLY LpcReply
)
109 ULONG nNumberOfCharsToRead
;
110 PCSRSS_CONSOLE Console
;
113 nNumberOfCharsToRead
= LpcMessage
->Data
.ReadConsoleRequest
.NrCharactersToRead
> CSRSS_MAX_READ_CONSOLE_REQUEST
? CSRSS_MAX_READ_CONSOLE_REQUEST
: LpcMessage
->Data
.ReadConsoleRequest
.NrCharactersToRead
;
115 // DbgPrint("CSR: NrCharactersToRead %d\n", nNumberOfCharsToRead);
117 LpcReply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
) +
118 nNumberOfCharsToRead
;
119 LpcReply
->Header
.DataSize
= LpcReply
->Header
.MessageSize
-
120 sizeof(LPC_MESSAGE_HEADER
);
121 Buffer
= LpcReply
->Data
.ReadConsoleReply
.Buffer
;
122 LpcReply
->Data
.ReadConsoleReply
.EventHandle
= ProcessData
->ConsoleEvent
;
124 Status
= CsrGetObject( ProcessData
, LpcMessage
->Data
.ReadConsoleRequest
.ConsoleHandle
, (Object_t
**)&Console
);
125 if( !NT_SUCCESS( Status
) )
127 LpcReply
->Status
= Status
;
130 RtlEnterCriticalSection( &ActiveConsoleLock
);
131 if( !(Console
->ConsoleMode
& ENABLE_LINE_INPUT
) || Console
->WaitingLines
)
132 for (; i
<nNumberOfCharsToRead
&& Console
->InputEvents
.Flink
!= &Console
->InputEvents
; i
++ )
134 // remove input event from queue
135 Input
= (ConsoleInput
*)Console
->InputEvents
.Flink
;
136 Input
->ListEntry
.Blink
->Flink
= Input
->ListEntry
.Flink
;
137 Input
->ListEntry
.Flink
->Blink
= Input
->ListEntry
.Blink
;
138 // only pay attention to valid ascii chars, on key down
139 if( Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
== TRUE
&&
140 Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
142 Buffer
[i
] = Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
;
143 // process newline on line buffered mode
144 if( Console
->ConsoleMode
& ENABLE_LINE_INPUT
&&
145 Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
== '\n' )
147 Console
->WaitingChars
--;
148 Console
->WaitingLines
--;
149 RtlFreeHeap( CsrssApiHeap
, 0, Input
);
155 Console
->WaitingChars
--;
156 RtlFreeHeap( CsrssApiHeap
, 0, Input
);
159 RtlLeaveCriticalSection( &ActiveConsoleLock
);
160 LpcReply
->Data
.ReadConsoleReply
.NrCharactersRead
= i
;
161 LpcReply
->Status
= i
? STATUS_SUCCESS
: STATUS_PENDING
;
167 NTSTATUS
CsrpWriteConsole( PCSRSS_CONSOLE Console
, CHAR
*Buffer
, DWORD Length
, BOOL Attrib
)
169 IO_STATUS_BLOCK Iosb
;
173 for( i
= 0; i
< Length
; i
++ )
175 switch( Buffer
[ i
] )
179 Console
->CurrentX
= 0;
180 /* slide the viewable screen */
181 if( ((PhysicalConsoleSize
.Y
+ Console
->ShowY
) % Console
->MaxY
) == (Console
->CurrentY
+ 1) % Console
->MaxY
)
182 if( ++Console
->ShowY
== (Console
->MaxY
- 1) )
184 if( ++Console
->CurrentY
== Console
->MaxY
)
186 Console
->CurrentY
= 0;
187 for( c
= 0; c
< Console
->MaxX
; c
++ )
190 Console
->Buffer
[ c
* 2 ] = ' ';
191 Console
->Buffer
[ (c
* 2) + 1 ] = Console
->DefaultAttrib
;
194 else for( c
= 0; c
< Console
->MaxX
; c
++ )
197 Console
->Buffer
[ 2 * ((Console
->CurrentY
* Console
->MaxX
) + c
) ] = ' ';
198 Console
->Buffer
[ (2 * ((Console
->CurrentY
* Console
->MaxX
) + c
)) + 1 ] = Console
->DefaultAttrib
;
203 if( Console
->CurrentX
== 0 )
205 /* slide viewable screen up */
206 if( Console
->ShowY
== Console
->CurrentY
)
208 if( Console
->ShowY
== 0 )
209 Console
->ShowY
= Console
->MaxY
;
213 /* slide virtual position up */
214 Console
->CurrentX
= Console
->MaxX
;
215 if( Console
->CurrentY
== 0 )
216 Console
->CurrentY
= Console
->MaxY
;
222 Console
->Buffer
[ 2 * ((Console
->CurrentY
* Console
->MaxX
) + Console
->CurrentX
) ] = ' ';
223 Console
->Buffer
[ (2 * ((Console
->CurrentY
* Console
->MaxX
) + Console
->CurrentX
)) + 1 ] = Console
->DefaultAttrib
;
228 Console
->Buffer
[ 2 * (((Console
->CurrentY
* Console
->MaxX
)) + Console
->CurrentX
) ] = Buffer
[ i
];
230 Console
->Buffer
[ (2 * ((Console
->CurrentY
* Console
->MaxX
) + Console
->CurrentX
)) + 1 ] = Console
->DefaultAttrib
;
232 if( Console
->CurrentX
== Console
->MaxX
)
234 /* if end of line, go to next */
235 Console
->CurrentX
= 0;
236 if( ++Console
->CurrentY
== Console
->MaxY
)
238 /* if end of buffer, wrap back to beginning */
239 Console
->CurrentY
= 0;
241 for( c
= 0; c
< Console
->MaxX
; c
++ )
243 Console
->Buffer
[ 2 * ((Console
->CurrentY
* Console
->MaxX
) + c
) ] = ' ';
244 Console
->Buffer
[ (2 * ((Console
->CurrentY
* Console
->MaxX
) + c
)) + 1 ] = Console
->DefaultAttrib
;
249 for( c
= 0; c
< Console
->MaxX
; c
+= 2 )
251 Console
->Buffer
[ 2 * ((Console
->CurrentY
* Console
->MaxX
) + c
) ] = ' ';
252 Console
->Buffer
[ (2 * ((Console
->CurrentY
* Console
->MaxX
) + c
)) + 1 ] = Console
->DefaultAttrib
;
255 /* slide the viewable screen */
256 if( (Console
->CurrentY
- Console
->ShowY
) == PhysicalConsoleSize
.Y
)
257 if( ++Console
->ShowY
== Console
->MaxY
)
263 if( Console
== ActiveConsole
)
264 { /* only write to screen if Console is Active, and not scrolled up */
267 Status
= NtWriteFile( ConsoleDeviceHandle
, NULL
, NULL
, NULL
, &Iosb
, Buffer
, Length
, NULL
, 0);
268 if (!NT_SUCCESS(Status
))
269 DbgPrint("CSR: Write failed\n");
271 else CsrDrawConsole( Console
);
273 return(STATUS_SUCCESS
);
276 NTSTATUS
CsrWriteConsole(PCSRSS_PROCESS_DATA ProcessData
,
277 PCSRSS_API_REQUEST LpcMessage
,
278 PCSRSS_API_REPLY Reply
)
280 BYTE
*Buffer
= LpcMessage
->Data
.WriteConsoleRequest
.Buffer
;
281 PCSRSS_CONSOLE Console
;
283 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
284 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
285 sizeof(LPC_MESSAGE_HEADER
);
287 if( !NT_SUCCESS( CsrGetObject( ProcessData
, LpcMessage
->Data
.WriteConsoleRequest
.ConsoleHandle
, (Object_t
**)&Console
) ) )
288 return Reply
->Status
= STATUS_INVALID_HANDLE
;
289 RtlEnterCriticalSection( &ActiveConsoleLock
);
290 CsrpWriteConsole( Console
, Buffer
, LpcMessage
->Data
.WriteConsoleRequest
.NrCharactersToWrite
, TRUE
);
291 RtlLeaveCriticalSection( &ActiveConsoleLock
);
292 return Reply
->Status
= STATUS_SUCCESS
;
296 NTSTATUS
CsrInitConsole(PCSRSS_PROCESS_DATA ProcessData
,
297 PCSRSS_CONSOLE Console
)
301 Console
->MaxX
= PhysicalConsoleSize
.X
;
302 Console
->MaxY
= PhysicalConsoleSize
.Y
* 2;
305 Console
->CurrentX
= 0;
306 Console
->CurrentY
= 0;
307 Console
->ReferenceCount
= 0;
308 Console
->WaitingChars
= 0;
309 Console
->WaitingLines
= 0;
310 Console
->Type
= CSRSS_CONSOLE_MAGIC
;
311 Console
->ConsoleMode
= ENABLE_LINE_INPUT
| ENABLE_ECHO_INPUT
| ENABLE_PROCESSED_INPUT
| ENABLE_MOUSE_INPUT
;
312 Console
->Buffer
= RtlAllocateHeap( CsrssApiHeap
, 0, Console
->MaxX
* Console
->MaxY
* 2 );
313 if( Console
->Buffer
== 0 )
314 return STATUS_INSUFFICIENT_RESOURCES
;
315 Console
->InputEvents
.Flink
= Console
->InputEvents
.Blink
= &Console
->InputEvents
;
316 Status
= NtCreateEvent( &Console
->ActiveEvent
, STANDARD_RIGHTS_ALL
, 0, FALSE
, FALSE
);
317 if( !NT_SUCCESS( Status
) )
319 RtlFreeHeap( CsrssApiHeap
, 0, Console
->Buffer
);
322 Console
->DefaultAttrib
= 0x17;
323 /* initialize buffer to be empty with default attributes */
324 for( ; Console
->CurrentY
< Console
->MaxY
; Console
->CurrentY
++ )
326 for( ; Console
->CurrentX
< Console
->MaxX
; Console
->CurrentX
++ )
328 Console
->Buffer
[ (Console
->CurrentX
* 2) + (Console
->CurrentY
* Console
->MaxX
* 2) ] = ' ';
329 Console
->Buffer
[ (Console
->CurrentX
* 2) + (Console
->CurrentY
* Console
->MaxX
* 2)+ 1 ] = Console
->DefaultAttrib
;
331 Console
->CurrentX
= 0;
333 Console
->CursorInfo
.bVisible
= TRUE
;
334 Console
->CursorInfo
.dwSize
= 5;
335 /* make console active, and insert into console list */
336 RtlEnterCriticalSection( &ActiveConsoleLock
);
339 Console
->Prev
= ActiveConsole
;
340 Console
->Next
= ActiveConsole
->Next
;
341 ActiveConsole
->Next
->Prev
= Console
;
342 ActiveConsole
->Next
= Console
;
345 Console
->Prev
= Console
;
346 Console
->Next
= Console
;
348 Console
->CurrentX
= 0;
349 Console
->CurrentY
= 0;
350 ActiveConsole
= Console
;
351 /* copy buffer contents to screen */
352 CsrDrawConsole( Console
);
353 RtlLeaveCriticalSection( &ActiveConsoleLock
);
354 return STATUS_SUCCESS
;
357 /***************************************************************
358 * CsrDrawConsole blasts the console buffer onto the screen *
359 * must be called while holding the active console lock *
360 **************************************************************/
361 VOID
CsrDrawConsole( PCSRSS_CONSOLE Console
)
363 IO_STATUS_BLOCK Iosb
;
365 CONSOLE_SCREEN_BUFFER_INFO ScrInfo
;
369 /* first set position to 0,0 */
370 ScrInfo
.dwCursorPosition
.X
= 0;
371 ScrInfo
.dwCursorPosition
.Y
= 0;
372 ScrInfo
.wAttributes
= Console
->DefaultAttrib
;
373 Status
= NtDeviceIoControlFile( ConsoleDeviceHandle
, NULL
, NULL
, NULL
, &Iosb
, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO
, &ScrInfo
, sizeof( ScrInfo
), 0, 0 );
374 if( !NT_SUCCESS( Status
) )
376 DbgPrint( "CSR: Failed to set console info\n" );
379 Mode
.dwMode
= 0; /* clear ENABLE_PROCESSED_OUTPUT mode */
380 Status
= NtDeviceIoControlFile( ConsoleDeviceHandle
, NULL
, NULL
, NULL
, &Iosb
, IOCTL_CONSOLE_SET_MODE
, &Mode
, sizeof( Mode
), 0, 0 );
381 if( !NT_SUCCESS( Status
) )
383 DbgPrint( "CSR: Failed to set console mode\n" );
386 /* blast out buffer */
387 for( i
= 0, y
= Console
->ShowY
; i
< PhysicalConsoleSize
.Y
; i
++ )
389 Status
= NtWriteFile( ConsoleDeviceHandle
, NULL
, NULL
, NULL
, &Iosb
, &Console
->Buffer
[ (Console
->ShowX
* 2) + (y
* Console
->MaxX
* 2) ], PhysicalConsoleSize
.X
* 2, 0, 0 );
390 if( !NT_SUCCESS( Status
) )
392 DbgPrint( "CSR: Write to console failed\n" );
395 /* wrap back around the end of the buffer */
396 if( ++y
== Console
->MaxY
)
399 Mode
.dwMode
= ENABLE_PROCESSED_OUTPUT
;
400 Status
= NtDeviceIoControlFile( ConsoleDeviceHandle
, NULL
, NULL
, NULL
, &Iosb
, IOCTL_CONSOLE_SET_MODE
, &Mode
, sizeof( Mode
), 0, 0 );
401 if( !NT_SUCCESS( Status
) )
403 DbgPrint( "CSR: Failed to set console mode\n" );
406 ScrInfo
.dwCursorPosition
.X
= Console
->CurrentX
- Console
->ShowX
;
407 ScrInfo
.dwCursorPosition
.Y
= ((Console
->CurrentY
+ Console
->MaxY
) - Console
->ShowY
) % Console
->MaxY
;
408 Status
= NtDeviceIoControlFile( ConsoleDeviceHandle
, NULL
, NULL
, NULL
, &Iosb
, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO
, &ScrInfo
, sizeof( ScrInfo
), 0, 0 );
409 if( !NT_SUCCESS( Status
) )
411 DbgPrint( "CSR: Failed to set console info\n" );
414 Status
= NtDeviceIoControlFile( ConsoleDeviceHandle
, NULL
, NULL
, NULL
, &Iosb
, IOCTL_CONSOLE_SET_CURSOR_INFO
, &Console
->CursorInfo
, sizeof( Console
->CursorInfo
), 0, 0 );
415 if( !NT_SUCCESS( Status
) )
417 DbgPrint( "CSR: Failed to set cursor info\n" );
423 VOID
CsrDeleteConsole( PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_CONSOLE Console
)
426 RtlEnterCriticalSection( &ActiveConsoleLock
);
427 RtlFreeHeap( CsrssApiHeap
, 0, Console
->Buffer
);
428 while( Console
->InputEvents
.Flink
!= &Console
->InputEvents
)
430 Event
= (ConsoleInput
*)Console
->InputEvents
.Flink
;
431 Console
->InputEvents
.Flink
= Console
->InputEvents
.Flink
->Flink
;
432 Console
->InputEvents
.Flink
->Flink
->Blink
= &Console
->InputEvents
;
433 RtlFreeHeap( CsrssApiHeap
, 0, Event
);
435 if( ActiveConsole
== Console
)
437 if( Console
->Next
!= Console
)
439 ActiveConsole
= Console
->Next
;
440 Console
->Prev
->Next
= Console
->Next
;
441 Console
->Next
->Prev
= Console
->Prev
;
443 else ActiveConsole
= 0;
446 CsrDrawConsole( ActiveConsole
);
447 RtlLeaveCriticalSection( &ActiveConsoleLock
);
448 NtClose( Console
->ActiveEvent
);
451 VOID
CsrInitConsoleSupport(VOID
)
453 OBJECT_ATTRIBUTES ObjectAttributes
;
454 UNICODE_STRING DeviceName
;
456 IO_STATUS_BLOCK Iosb
;
457 CONSOLE_SCREEN_BUFFER_INFO ScrInfo
;
459 DbgPrint("CSR: CsrInitConsoleSupport()\n");
461 RtlInitUnicodeString(&DeviceName
, L
"\\??\\BlueScreen");
462 InitializeObjectAttributes(&ObjectAttributes
,
467 Status
= NtOpenFile(&ConsoleDeviceHandle
,
472 FILE_SYNCHRONOUS_IO_ALERT
);
473 if (!NT_SUCCESS(Status
))
475 DbgPrint("CSR: Failed to open console. Expect problems.\n");
477 // DbgPrint("CSR: ConsoleDeviceHandle %x\n", ConsoleDeviceHandle);
479 RtlInitUnicodeString(&DeviceName
, L
"\\??\\Keyboard");
480 InitializeObjectAttributes(&ObjectAttributes
,
485 Status
= NtOpenFile(&KeyboardDeviceHandle
,
491 if (!NT_SUCCESS(Status
))
493 DbgPrint("CSR: Failed to open keyboard. Expect problems.\n");
497 RtlInitializeCriticalSection( &ActiveConsoleLock
);
498 Status
= NtDeviceIoControlFile( ConsoleDeviceHandle
, NULL
, NULL
, NULL
, &Iosb
, IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO
, 0, 0, &ScrInfo
, sizeof( ScrInfo
) );
499 if( !NT_SUCCESS( Status
) )
501 DbgPrint( "CSR: Failed to get console info, expect trouble\n" );
504 PhysicalConsoleSize
= ScrInfo
.dwSize
;
507 VOID
Console_Api( DWORD RefreshEvent
)
509 /* keep reading events from the keyboard and stuffing them into the current
510 console's input queue */
511 ConsoleInput
*KeyEventRecord
;
512 IO_STATUS_BLOCK Iosb
;
514 HANDLE Events
[2]; // 0 = keyboard, 1 = refresh
518 Status
= NtCreateEvent( &Events
[0], STANDARD_RIGHTS_ALL
, NULL
, FALSE
, FALSE
);
519 if( !NT_SUCCESS( Status
) )
521 DbgPrint( "CSR: NtCreateEvent failed: %x\n", Status
);
524 Events
[1] = (HANDLE
)RefreshEvent
;
527 KeyEventRecord
= RtlAllocateHeap(CsrssApiHeap
,
529 sizeof(ConsoleInput
));
530 if ( KeyEventRecord
== 0 )
532 DbgPrint( "CSR: Memory allocation failure!" );
535 KeyEventRecord
->InputEvent
.EventType
= KEY_EVENT
;
536 Status
= NtReadFile( KeyboardDeviceHandle
, Events
[0], NULL
, NULL
, &Iosb
, &KeyEventRecord
->InputEvent
.Event
.KeyEvent
, sizeof( KEY_EVENT_RECORD
), NULL
, 0 );
537 if( !NT_SUCCESS( Status
) )
539 DbgPrint( "CSR: ReadFile on keyboard device failed\n" );
540 RtlFreeHeap( CsrssApiHeap
, 0, KeyEventRecord
);
543 if( Status
== STATUS_PENDING
)
547 Status
= NtWaitForMultipleObjects( 2, Events
, WaitAny
, FALSE
, NULL
);
548 if( Status
== STATUS_WAIT_0
+ 1 )
550 RtlEnterCriticalSection( &ActiveConsoleLock
);
551 CsrDrawConsole( ActiveConsole
);
552 RtlLeaveCriticalSection( &ActiveConsoleLock
);
555 else if( Status
!= STATUS_WAIT_0
)
557 DbgPrint( "CSR: NtWaitForMultipleObjects failed: %x, exiting\n", Status
);
563 // DbgPrint( "Char: %c\n", KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar );
564 if( KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
& ( RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
)&& KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
== 'q' )
565 if( KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
== TRUE
)
567 /* alt-tab, swap consoles */
568 RtlEnterCriticalSection( &ActiveConsoleLock
);
569 if( ActiveConsole
->Next
!= ActiveConsole
)
570 ActiveConsole
= ActiveConsole
->Next
;
571 CsrDrawConsole( ActiveConsole
);
572 RtlLeaveCriticalSection( &ActiveConsoleLock
);
573 RtlFreeHeap( CsrssApiHeap
, 0, KeyEventRecord
);
577 RtlFreeHeap( CsrssApiHeap
, 0, KeyEventRecord
);
580 else if( KeyEventRecord
->InputEvent
.Event
.KeyEvent
.dwControlKeyState
& ( RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
) && (KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
|| KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== VK_DOWN
) )
582 if( KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
== TRUE
)
584 /* scroll up or down */
585 RtlEnterCriticalSection( &ActiveConsoleLock
);
586 if( ActiveConsole
== 0 )
588 DbgPrint( "CSR: No Active Console!\n" );
589 RtlFreeHeap( CsrssApiHeap
, 0, KeyEventRecord
);
592 if( KeyEventRecord
->InputEvent
.Event
.KeyEvent
.wVirtualKeyCode
== VK_UP
)
594 /* only scroll up if there is room to scroll up into */
595 if( ActiveConsole
->ShowY
!= ((ActiveConsole
->CurrentY
+ 1) % ActiveConsole
->MaxY
) )
596 ActiveConsole
->ShowY
= (ActiveConsole
->ShowY
+ ActiveConsole
->MaxY
- 1) % ActiveConsole
->MaxY
;
598 else if( ActiveConsole
->ShowY
!= ActiveConsole
->CurrentY
)
599 /* only scroll down if there is room to scroll down into */
600 if( ActiveConsole
->ShowY
% ActiveConsole
->MaxY
!= ActiveConsole
->CurrentY
)
601 if( ((ActiveConsole
->CurrentY
+ 1) % ActiveConsole
->MaxY
) != (ActiveConsole
->ShowY
+ PhysicalConsoleSize
.Y
) % ActiveConsole
->MaxY
)
602 ActiveConsole
->ShowY
= (ActiveConsole
->ShowY
+ 1) % ActiveConsole
->MaxY
;
603 CsrDrawConsole( ActiveConsole
);
604 RtlLeaveCriticalSection( &ActiveConsoleLock
);
606 RtlFreeHeap( CsrssApiHeap
, 0, KeyEventRecord
);
609 RtlEnterCriticalSection( &ActiveConsoleLock
);
610 if( ActiveConsole
== 0 )
612 DbgPrint( "CSR: No Active Console!\n" );
613 RtlFreeHeap( CsrssApiHeap
, 0, KeyEventRecord
);
616 // echo to screen if enabled, but do not echo '\b' if there are no keys in buffer to delete
617 if( ActiveConsole
->ConsoleMode
& ENABLE_ECHO_INPUT
&&
618 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
== TRUE
&&
619 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
&&
620 ( KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
!= '\b' ||
621 ActiveConsole
->InputEvents
.Flink
!= &ActiveConsole
->InputEvents
) )
623 CsrpWriteConsole( ActiveConsole
, &KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
, 1, TRUE
);
625 // process special keys if enabled
626 if( ActiveConsole
->ConsoleMode
& ENABLE_PROCESSED_INPUT
)
627 switch( KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
)
630 if( KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
== TRUE
)
631 for( c
= 0; c
< 2; c
++ )
633 ConsoleInput
*Input
= ActiveConsole
->InputEvents
.Blink
;
636 ActiveConsole
->InputEvents
.Blink
->Blink
->Flink
= &ActiveConsole
->InputEvents
;
637 ActiveConsole
->InputEvents
.Blink
= ActiveConsole
->InputEvents
.Blink
->Blink
;
638 RtlFreeHeap( CsrssApiHeap
, 0, Input
);
640 RtlFreeHeap( CsrssApiHeap
, 0, KeyEventRecord
);
641 RtlLeaveCriticalSection( &ActiveConsoleLock
);
644 // add event to the queue
645 KeyEventRecord
->ListEntry
.Flink
= &ActiveConsole
->InputEvents
;
646 KeyEventRecord
->ListEntry
.Blink
= ActiveConsole
->InputEvents
.Blink
;
647 ActiveConsole
->InputEvents
.Blink
->Flink
= &KeyEventRecord
->ListEntry
;
648 ActiveConsole
->InputEvents
.Blink
= &KeyEventRecord
->ListEntry
;
649 // if line input mode is enabled, only wake the client on enter key up
650 if( !(ActiveConsole
->ConsoleMode
& ENABLE_LINE_INPUT
) ||
651 ( KeyEventRecord
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
== '\n' &&
652 KeyEventRecord
->InputEvent
.Event
.KeyEvent
.bKeyDown
== FALSE
) )
654 NtSetEvent( ActiveConsole
->ActiveEvent
, 0 );
655 ActiveConsole
->WaitingLines
++;
657 ActiveConsole
->WaitingChars
++;
658 RtlLeaveCriticalSection( &ActiveConsoleLock
);
662 NTSTATUS
CsrGetScreenBufferInfo( PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_API_REQUEST Request
, PCSRSS_API_REPLY Reply
)
665 PCSRSS_CONSOLE Console
;
666 PCONSOLE_SCREEN_BUFFER_INFO pInfo
;
667 IO_STATUS_BLOCK Iosb
;
669 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
670 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
671 sizeof(LPC_MESSAGE_HEADER
);
673 if( !NT_SUCCESS( CsrGetObject( ProcessData
, Request
->Data
.ScreenBufferInfoRequest
.ConsoleHandle
, (Object_t
**)&Console
) ) )
674 return Reply
->Status
= STATUS_INVALID_HANDLE
;
675 pInfo
= &Reply
->Data
.ScreenBufferInfoReply
.Info
;
676 RtlEnterCriticalSection( &ActiveConsoleLock
);
677 if( Console
== ActiveConsole
)
679 Status
= NtDeviceIoControlFile( ConsoleDeviceHandle
, NULL
, NULL
, NULL
, &Iosb
, IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO
, 0, 0, pInfo
, sizeof( *pInfo
) );
680 if( !NT_SUCCESS( Status
) )
681 DbgPrint( "CSR: Failed to get console info, expect trouble\n" );
682 Reply
->Status
= STATUS_SUCCESS
;
685 pInfo
->dwSize
.X
= PhysicalConsoleSize
.X
;
686 pInfo
->dwSize
.Y
= PhysicalConsoleSize
.Y
;
687 pInfo
->dwCursorPosition
.X
= Console
->CurrentX
- Console
->ShowX
;
688 pInfo
->dwCursorPosition
.Y
= (Console
->CurrentY
+ Console
->MaxY
- Console
->ShowY
) % Console
->MaxY
;
689 pInfo
->wAttributes
= Console
->DefaultAttrib
;
690 pInfo
->srWindow
.Left
= 0;
691 pInfo
->srWindow
.Right
= PhysicalConsoleSize
.X
- 1;
692 pInfo
->srWindow
.Top
= 0;
693 pInfo
->srWindow
.Bottom
= PhysicalConsoleSize
.Y
- 1;
694 Reply
->Status
= STATUS_SUCCESS
;
696 RtlLeaveCriticalSection( &ActiveConsoleLock
);
697 return Reply
->Status
;
700 NTSTATUS
CsrSetCursor( PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_API_REQUEST Request
, PCSRSS_API_REPLY Reply
)
703 PCSRSS_CONSOLE Console
;
704 CONSOLE_SCREEN_BUFFER_INFO Info
;
705 IO_STATUS_BLOCK Iosb
;
707 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
708 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
709 sizeof(LPC_MESSAGE_HEADER
);
711 if( !NT_SUCCESS( CsrGetObject( ProcessData
, Request
->Data
.SetCursorRequest
.ConsoleHandle
, (Object_t
**)&Console
) ) )
712 return Reply
->Status
= STATUS_INVALID_HANDLE
;
713 RtlEnterCriticalSection( &ActiveConsoleLock
);
714 Info
.dwCursorPosition
= Request
->Data
.SetCursorRequest
.Position
;
715 Info
.wAttributes
= Console
->DefaultAttrib
;
716 if( Console
== ActiveConsole
)
718 Status
= NtDeviceIoControlFile( ConsoleDeviceHandle
, NULL
, NULL
, NULL
, &Iosb
, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO
, &Info
, sizeof( Info
), 0, 0 );
719 if( !NT_SUCCESS( Status
) )
720 DbgPrint( "CSR: Failed to set console info, expect trouble\n" );
722 Console
->CurrentX
= Info
.dwCursorPosition
.X
+ Console
->ShowX
;
723 Console
->CurrentY
= (Info
.dwCursorPosition
.Y
+ Console
->ShowY
) % Console
->MaxY
;
724 RtlLeaveCriticalSection( &ActiveConsoleLock
);
725 return Reply
->Status
= Status
;
728 NTSTATUS
CsrWriteConsoleOutputChar( PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_API_REQUEST Request
, PCSRSS_API_REPLY Reply
)
730 BYTE
*Buffer
= Request
->Data
.WriteConsoleOutputCharRequest
.String
;
731 PCSRSS_CONSOLE Console
;
734 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
735 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
736 sizeof(LPC_MESSAGE_HEADER
);
738 if( !NT_SUCCESS( CsrGetObject( ProcessData
, Request
->Data
.WriteConsoleOutputCharRequest
.ConsoleHandle
, (Object_t
**)&Console
) ) )
739 return Reply
->Status
= STATUS_INVALID_HANDLE
;
740 RtlEnterCriticalSection( &ActiveConsoleLock
);
741 X
= Console
->CurrentX
;
742 Y
= Console
->CurrentY
;
743 CsrpWriteConsole( Console
, Buffer
, Request
->Data
.WriteConsoleOutputCharRequest
.Length
, TRUE
);
744 Reply
->Data
.WriteConsoleOutputCharReply
.EndCoord
.X
= Console
->CurrentX
- Console
->ShowX
;
745 Reply
->Data
.WriteConsoleOutputCharReply
.EndCoord
.Y
= (Console
->CurrentY
+ Console
->MaxY
- Console
->ShowY
) % Console
->MaxY
;
746 Console
->CurrentY
= Y
;
747 Console
->CurrentX
= X
;
748 RtlLeaveCriticalSection( &ActiveConsoleLock
);
749 return Reply
->Status
= STATUS_SUCCESS
;
752 NTSTATUS
CsrFillOutputChar( PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_API_REQUEST Request
, PCSRSS_API_REPLY Reply
)
754 PCSRSS_CONSOLE Console
;
757 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
758 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
759 sizeof(LPC_MESSAGE_HEADER
);
761 if( !NT_SUCCESS( CsrGetObject( ProcessData
, Request
->Data
.FillOutputRequest
.ConsoleHandle
, (Object_t
**)&Console
) ) )
762 return Reply
->Status
= STATUS_INVALID_HANDLE
;
763 RtlEnterCriticalSection( &ActiveConsoleLock
);
764 X
= Request
->Data
.FillOutputRequest
.Position
.X
+ Console
->ShowX
;
765 Y
= Request
->Data
.FillOutputRequest
.Position
.Y
+ Console
->ShowY
;
766 for( i
= 0; i
< 20000; i
++ );
767 for( i
= 0; i
< Request
->Data
.FillOutputRequest
.Length
; i
++ )
769 Console
->Buffer
[ (Y
* 2 * Console
->MaxX
) + (X
* 2) ] = Request
->Data
.FillOutputRequest
.Char
;
770 if( ++X
== Console
->MaxX
)
772 if( ++Y
== Console
->MaxY
)
777 if( Console
== ActiveConsole
)
778 CsrDrawConsole( Console
);
779 RtlLeaveCriticalSection( &ActiveConsoleLock
);
780 return Reply
->Status
;
783 NTSTATUS
CsrReadInputEvent( PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_API_REQUEST Request
, PCSRSS_API_REPLY Reply
)
785 PCSRSS_CONSOLE Console
;
789 // DbgPrint("CSR: NrCharactersToRead %d\n", nNumberOfCharsToRead);
791 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
792 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
793 sizeof(LPC_MESSAGE_HEADER
);
794 Reply
->Data
.ReadInputReply
.Event
= ProcessData
->ConsoleEvent
;
796 Status
= CsrGetObject( ProcessData
, Request
->Data
.ReadInputRequest
.ConsoleHandle
, (Object_t
**)&Console
);
797 if( !NT_SUCCESS( Status
) )
799 Reply
->Status
= Status
;
802 RtlEnterCriticalSection( &ActiveConsoleLock
);
803 // only get input if there is input, and we are not in line input mode, or if we are, if we have a whole line
804 if( Console
->InputEvents
.Flink
!= &Console
->InputEvents
&&
805 ( !Console
->ConsoleMode
& ENABLE_LINE_INPUT
|| Console
->WaitingLines
) )
807 Input
= (ConsoleInput
*)Console
->InputEvents
.Flink
;
808 Input
->ListEntry
.Blink
->Flink
= Input
->ListEntry
.Flink
;
809 Input
->ListEntry
.Flink
->Blink
= Input
->ListEntry
.Blink
;
810 Reply
->Data
.ReadInputReply
.Input
= Input
->InputEvent
;
811 if( Console
->ConsoleMode
& ENABLE_LINE_INPUT
&&
812 Input
->InputEvent
.Event
.KeyEvent
.bKeyDown
== FALSE
&&
813 Input
->InputEvent
.Event
.KeyEvent
.uChar
.AsciiChar
== '\n' )
814 Console
->WaitingLines
--;
815 Console
->WaitingChars
--;
816 RtlFreeHeap( CsrssApiHeap
, 0, Input
);
817 Reply
->Data
.ReadInputReply
.MoreEvents
= (Console
->InputEvents
.Flink
!= &Console
->InputEvents
) ? TRUE
: FALSE
;
818 Status
= STATUS_SUCCESS
;
820 else Status
= STATUS_PENDING
;
821 RtlLeaveCriticalSection( &ActiveConsoleLock
);
822 return Reply
->Status
= Status
;
825 NTSTATUS
CsrWriteConsoleOutputAttrib( PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_API_REQUEST Request
, PCSRSS_API_REPLY Reply
)
828 PCSRSS_CONSOLE Console
;
832 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
833 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
834 sizeof(LPC_MESSAGE_HEADER
);
835 Status
= CsrGetObject( ProcessData
, Request
->Data
.WriteConsoleOutputAttribRequest
.ConsoleHandle
, (Object_t
**)&Console
);
836 if( !NT_SUCCESS( Status
) )
838 Reply
->Status
= Status
;
841 RtlEnterCriticalSection( &ActiveConsoleLock
);
842 X
= Console
->CurrentX
;
843 Y
= Console
->CurrentY
;
844 Console
->CurrentX
= Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.X
+ Console
->ShowX
;
845 Console
->CurrentY
= (Request
->Data
.WriteConsoleOutputAttribRequest
.Coord
.Y
+ Console
->ShowY
) % Console
->MaxY
;
846 for( c
= 0; c
< Request
->Data
.WriteConsoleOutputAttribRequest
.Length
; c
++ )
848 Console
->Buffer
[(Console
->CurrentY
* Console
->MaxX
* 2) + (Console
->CurrentX
* 2) + 1] = Request
->Data
.WriteConsoleOutputAttribRequest
.String
[c
];
849 if( ++Console
->CurrentX
== Console
->MaxX
)
851 Console
->CurrentX
= 0;
852 if( ++Console
->CurrentY
== Console
->MaxY
)
853 Console
->CurrentY
= 0;
856 if( Console
== ActiveConsole
)
857 CsrDrawConsole( Console
);
858 Reply
->Data
.WriteConsoleOutputAttribReply
.EndCoord
.X
= Console
->CurrentX
- Console
->ShowX
;
859 Reply
->Data
.WriteConsoleOutputAttribReply
.EndCoord
.Y
= ( Console
->CurrentY
+ Console
->MaxY
- Console
->ShowY
) % Console
->MaxY
;
860 Console
->CurrentX
= X
;
861 Console
->CurrentY
= Y
;
862 RtlLeaveCriticalSection( &ActiveConsoleLock
);
863 return Reply
->Status
= STATUS_SUCCESS
;
866 NTSTATUS
CsrFillOutputAttrib( PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_API_REQUEST Request
, PCSRSS_API_REPLY Reply
)
869 PCSRSS_CONSOLE Console
;
873 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
874 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
875 sizeof(LPC_MESSAGE_HEADER
);
876 Status
= CsrGetObject( ProcessData
, Request
->Data
.FillOutputAttribRequest
.ConsoleHandle
, (Object_t
**)&Console
);
877 if( !NT_SUCCESS( Status
) )
879 Reply
->Status
= Status
;
882 RtlEnterCriticalSection( &ActiveConsoleLock
);
883 X
= Console
->CurrentX
;
884 Y
= Console
->CurrentY
;
885 Console
->CurrentX
= Request
->Data
.FillOutputAttribRequest
.Coord
.X
+ Console
->ShowX
;
886 Console
->CurrentY
= Request
->Data
.FillOutputAttribRequest
.Coord
.Y
+ Console
->ShowY
;
887 for( c
= 0; c
< Request
->Data
.FillOutputAttribRequest
.Length
; c
++ )
889 Console
->Buffer
[(Console
->CurrentY
* Console
->MaxX
* 2) + (Console
->CurrentX
* 2) + 1] = Request
->Data
.FillOutputAttribRequest
.Attribute
;
890 if( ++Console
->CurrentX
== Console
->MaxX
)
892 Console
->CurrentX
= 0;
893 if( ++Console
->CurrentY
== Console
->MaxY
)
894 Console
->CurrentY
= 0;
897 if( Console
== ActiveConsole
)
898 CsrDrawConsole( Console
);
899 Console
->CurrentX
= X
;
900 Console
->CurrentY
= Y
;
901 RtlLeaveCriticalSection( &ActiveConsoleLock
);
902 return Reply
->Status
= STATUS_SUCCESS
;
906 NTSTATUS
CsrGetCursorInfo( PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_API_REQUEST Request
, PCSRSS_API_REPLY Reply
)
908 PCSRSS_CONSOLE Console
;
911 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
912 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
913 sizeof(LPC_MESSAGE_HEADER
);
914 Status
= CsrGetObject( ProcessData
, Request
->Data
.GetCursorInfoRequest
.ConsoleHandle
, (Object_t
**)&Console
);
915 if( !NT_SUCCESS( Status
) )
917 Reply
->Status
= Status
;
920 RtlEnterCriticalSection( &ActiveConsoleLock
);
921 Reply
->Data
.GetCursorInfoReply
.Info
= Console
->CursorInfo
;
922 RtlLeaveCriticalSection( &ActiveConsoleLock
);
923 return Reply
->Status
= STATUS_SUCCESS
;
926 NTSTATUS
CsrSetCursorInfo( PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_API_REQUEST Request
, PCSRSS_API_REPLY Reply
)
928 PCSRSS_CONSOLE Console
;
930 IO_STATUS_BLOCK Iosb
;
932 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
933 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
934 sizeof(LPC_MESSAGE_HEADER
);
935 Status
= CsrGetObject( ProcessData
, Request
->Data
.SetCursorInfoRequest
.ConsoleHandle
, (Object_t
**)&Console
);
936 if( !NT_SUCCESS( Status
) )
938 Reply
->Status
= Status
;
941 RtlEnterCriticalSection( &ActiveConsoleLock
);
942 Console
->CursorInfo
= Request
->Data
.SetCursorInfoRequest
.Info
;
943 if( Console
== ActiveConsole
)
945 Status
= NtDeviceIoControlFile( ConsoleDeviceHandle
, NULL
, NULL
, NULL
, &Iosb
, IOCTL_CONSOLE_SET_CURSOR_INFO
, &Console
->CursorInfo
, sizeof( Console
->CursorInfo
), 0, 0 );
946 if( !NT_SUCCESS( Status
) )
948 DbgPrint( "CSR: Failed to set cursor info\n" );
949 return Reply
->Status
= Status
;
952 RtlLeaveCriticalSection( &ActiveConsoleLock
);
953 return Reply
->Status
= STATUS_SUCCESS
;
956 NTSTATUS
CsrSetTextAttrib( PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_API_REQUEST Request
, PCSRSS_API_REPLY Reply
)
959 CONSOLE_SCREEN_BUFFER_INFO ScrInfo
;
960 IO_STATUS_BLOCK Iosb
;
961 PCSRSS_CONSOLE Console
;
963 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
964 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) -
965 sizeof(LPC_MESSAGE_HEADER
);
966 Status
= CsrGetObject( ProcessData
, Request
->Data
.SetAttribRequest
.ConsoleHandle
, (Object_t
**)&Console
);
967 if( !NT_SUCCESS( Status
) )
969 Reply
->Status
= Status
;
972 RtlEnterCriticalSection( &ActiveConsoleLock
);
973 Console
->DefaultAttrib
= Request
->Data
.SetAttribRequest
.Attrib
;
974 if( Console
== ActiveConsole
)
976 ScrInfo
.wAttributes
= Console
->DefaultAttrib
;
977 ScrInfo
.dwCursorPosition
.X
= Console
->CurrentX
- Console
->ShowX
;
978 ScrInfo
.dwCursorPosition
.Y
= ((Console
->CurrentY
+ Console
->MaxY
) - Console
->ShowY
) % Console
->MaxY
;
979 Status
= NtDeviceIoControlFile( ConsoleDeviceHandle
, NULL
, NULL
, NULL
, &Iosb
, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO
, &ScrInfo
, sizeof( ScrInfo
), 0, 0 );
980 if( !NT_SUCCESS( Status
) )
982 DbgPrint( "CSR: Failed to set console info\n" );
983 return Reply
->Status
= Status
;
986 return Reply
->Status
= STATUS_SUCCESS
;
989 NTSTATUS
CsrSetConsoleMode( PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_API_REQUEST Request
, PCSRSS_API_REPLY Reply
)
992 PCSRSS_CONSOLE Console
;
994 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
995 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE_HEADER
);
996 if( Request
->Data
.SetConsoleModeRequest
.Mode
& (~CONSOLE_MODE_VALID
) ||
997 ( Request
->Data
.SetConsoleModeRequest
.Mode
& (ENABLE_ECHO_INPUT
| ENABLE_PROCESSED_INPUT
) &&
998 !( Request
->Data
.SetConsoleModeRequest
.Mode
& ENABLE_LINE_INPUT
) ) )
1000 Reply
->Status
= STATUS_INVALID_PARAMETER
;
1001 return Reply
->Status
;
1003 Status
= CsrGetObject( ProcessData
, Request
->Data
.SetConsoleModeRequest
.ConsoleHandle
, (Object_t
**)&Console
);
1004 if( !NT_SUCCESS( Status
) )
1006 Reply
->Status
= Status
;
1009 RtlEnterCriticalSection( &ActiveConsoleLock
);
1010 Console
->ConsoleMode
= Request
->Data
.SetConsoleModeRequest
.Mode
;
1011 RtlLeaveCriticalSection( &ActiveConsoleLock
);
1012 Reply
->Status
= STATUS_SUCCESS
;
1013 return Reply
->Status
;
1016 NTSTATUS
CsrGetConsoleMode( PCSRSS_PROCESS_DATA ProcessData
, PCSRSS_API_REQUEST Request
, PCSRSS_API_REPLY Reply
)
1019 PCSRSS_CONSOLE Console
;
1021 Reply
->Header
.MessageSize
= sizeof(CSRSS_API_REPLY
);
1022 Reply
->Header
.DataSize
= sizeof(CSRSS_API_REPLY
) - sizeof(LPC_MESSAGE_HEADER
);
1023 Status
= CsrGetObject( ProcessData
, Request
->Data
.GetConsoleModeRequest
.ConsoleHandle
, (Object_t
**)&Console
);
1024 if( !NT_SUCCESS( Status
) )
1026 Reply
->Status
= Status
;
1029 RtlEnterCriticalSection( &ActiveConsoleLock
);
1030 Reply
->Data
.GetConsoleModeReply
.ConsoleMode
= Console
->ConsoleMode
;
1031 RtlLeaveCriticalSection( &ActiveConsoleLock
);
1032 Reply
->Status
= STATUS_SUCCESS
;
1033 return Reply
->Status
;